From 44520fc3c55bdba006ebc835b9d034d0aeee983f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tam=C3=A1s=20H=2E?= <36476318+Tamas-hi@users.noreply.github.com> Date: Wed, 27 Nov 2024 15:23:54 +0100 Subject: [PATCH 01/11] docs: mention that type checking can happen in dev (#30012) --- docs/2.guide/1.concepts/8.typescript.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/2.guide/1.concepts/8.typescript.md b/docs/2.guide/1.concepts/8.typescript.md index a06015dc98..6e880fe496 100644 --- a/docs/2.guide/1.concepts/8.typescript.md +++ b/docs/2.guide/1.concepts/8.typescript.md @@ -35,7 +35,7 @@ Then, run [`nuxi typecheck`](/docs/api/commands/typecheck) command to check your npx nuxi typecheck ``` -To enable type-checking at build time, you can also use the [`typescript.typeCheck`](/docs/api/nuxt-config#typecheck) option in your `nuxt.config` file: +To enable type-checking at build or development time, you can also use the [`typescript.typeCheck`](/docs/api/nuxt-config#typecheck) option in your `nuxt.config` file: ```ts twoslash [nuxt.config.ts] export default defineNuxtConfig({ From 03080ad5d941f526a0971fa5d52e565b6fbd4e2d Mon Sep 17 00:00:00 2001 From: Daniel Rentz Date: Wed, 27 Nov 2024 15:24:35 +0100 Subject: [PATCH 02/11] docs: fix typos in punctuation (#30006) --- docs/3.api/2.composables/use-fetch.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/3.api/2.composables/use-fetch.md b/docs/3.api/2.composables/use-fetch.md index 56effdc62c..038082ab65 100644 --- a/docs/3.api/2.composables/use-fetch.md +++ b/docs/3.api/2.composables/use-fetch.md @@ -30,7 +30,7 @@ If you're using a custom useFetch wrapper, do not await it in the composable, as :: ::note -`data`, `status` and `error` are Vue refs and they should be accessed with `.value` when used within the ` +``` + +```ts +export default defineNuxtConfig({ + experimental: { + extraPageMetaExtractionKeys: ['foo'], + }, + hooks: { + 'pages:resolved' (ctx) { + // ✅ foo is available + }, + }, +}) +``` + +This allows modules to access additional metadata from the page metadata in the build context. If you are using this within a module, it's recommended also to [augment the `NuxtPage` types with your keys](/docs/guide/directory-structure/pages#typing-custom-metadata). + ## normalizeComponentNames Ensure that auto-generated Vue component names match the full component name diff --git a/packages/nuxt/src/pages/utils.ts b/packages/nuxt/src/pages/utils.ts index 27aa91c398..0b68904979 100644 --- a/packages/nuxt/src/pages/utils.ts +++ b/packages/nuxt/src/pages/utils.ts @@ -71,13 +71,14 @@ export async function resolvePagesRoutes (): Promise { return pages } + const augmentCtx = { extraExtractionKeys: nuxt.options.experimental.extraPageMetaExtractionKeys } if (shouldAugment === 'after-resolve') { await nuxt.callHook('pages:extend', pages) - await augmentPages(pages, nuxt.vfs) + await augmentPages(pages, nuxt.vfs, augmentCtx) } else { - const augmentedPages = await augmentPages(pages, nuxt.vfs) + const augmentedPages = await augmentPages(pages, nuxt.vfs, augmentCtx) await nuxt.callHook('pages:extend', pages) - await augmentPages(pages, nuxt.vfs, { pagesToSkip: augmentedPages }) + await augmentPages(pages, nuxt.vfs, { pagesToSkip: augmentedPages, ...augmentCtx }) augmentedPages?.clear() } @@ -158,13 +159,15 @@ export function generateRoutesFromFiles (files: ScannedFile[], options: Generate interface AugmentPagesContext { pagesToSkip?: Set augmentedPages?: Set + extraExtractionKeys?: string[] } + export async function augmentPages (routes: NuxtPage[], vfs: Record, ctx: AugmentPagesContext = {}) { ctx.augmentedPages ??= new Set() for (const route of routes) { if (route.file && !ctx.pagesToSkip?.has(route.file)) { const fileContent = route.file in vfs ? vfs[route.file]! : fs.readFileSync(await resolvePath(route.file), 'utf-8') - const routeMeta = await getRouteMeta(fileContent, route.file) + const routeMeta = await getRouteMeta(fileContent, route.file, ctx.extraExtractionKeys) if (route.meta) { routeMeta.meta = { ...routeMeta.meta, ...route.meta } } @@ -196,12 +199,12 @@ export function extractScriptContent (html: string) { } const PAGE_META_RE = /definePageMeta\([\s\S]*?\)/ -const extractionKeys = ['name', 'path', 'props', 'alias', 'redirect'] as const +const defaultExtractionKeys = ['name', 'path', 'props', 'alias', 'redirect'] as const const DYNAMIC_META_KEY = '__nuxt_dynamic_meta_key' as const const pageContentsCache: Record = {} const metaCache: Record>> = {} -export async function getRouteMeta (contents: string, absolutePath: string): Promise>> { +export async function getRouteMeta (contents: string, absolutePath: string, extraExtractionKeys: string[] = []): Promise>> { // set/update pageContentsCache, invalidate metaCache on cache mismatch if (!(absolutePath in pageContentsCache) || pageContentsCache[absolutePath] !== contents) { pageContentsCache[absolutePath] = contents @@ -221,6 +224,8 @@ export async function getRouteMeta (contents: string, absolutePath: string): Pro const extractedMeta = {} as Partial> + const extractionKeys = new Set([...defaultExtractionKeys, ...extraExtractionKeys as Array]) + for (const script of scriptBlocks) { if (!PAGE_META_RE.test(script.code)) { continue @@ -295,7 +300,7 @@ export async function getRouteMeta (contents: string, absolutePath: string): Pro continue } const name = property.key.type === 'Identifier' ? property.key.name : String(property.value) - if (!(extractionKeys as unknown as string[]).includes(name)) { + if (!extractionKeys.has(name as keyof NuxtPage)) { dynamicProperties.add('meta') break } diff --git a/packages/nuxt/test/page-metadata.test.ts b/packages/nuxt/test/page-metadata.test.ts index 6206e07c08..cdd299c415 100644 --- a/packages/nuxt/test/page-metadata.test.ts +++ b/packages/nuxt/test/page-metadata.test.ts @@ -142,6 +142,24 @@ describe('page metadata', () => { } `) }) + + it('should extract configured extra meta', async () => { + const meta = await getRouteMeta(` + + `, filePath, ['bar', 'foo']) + + expect(meta).toMatchInlineSnapshot(` + { + "bar": true, + "foo": "bar", + } + `) + }) }) describe('normalizeRoutes', () => { diff --git a/packages/schema/src/config/experimental.ts b/packages/schema/src/config/experimental.ts index 00ae9e2e0c..506ddb6481 100644 --- a/packages/schema/src/config/experimental.ts +++ b/packages/schema/src/config/experimental.ts @@ -308,6 +308,16 @@ export default defineUntypedSchema({ }, }, + /** + * Configure additional keys to extract from the page metadata when using `scanPageMeta`. + * + * This allows modules to access additional metadata from the page metadata. It's recommended + * to augment the NuxtPage types with your keys. + * + * @type {string[]} + */ + extraPageMetaExtractionKeys: [], + /** * Automatically share payload _data_ between pages that are prerendered. This can result in a significant * performance improvement when prerendering sites that use `useAsyncData` or `useFetch` and fetch the same From 811f57c0a46308b65331955def3b8283cb677736 Mon Sep 17 00:00:00 2001 From: "@beer" <47961062+iiio2@users.noreply.github.com> Date: Thu, 28 Nov 2024 02:12:15 +0600 Subject: [PATCH 06/11] docs: format text case for consistency (#30073) --- docs/1.getting-started/6.data-fetching.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/1.getting-started/6.data-fetching.md b/docs/1.getting-started/6.data-fetching.md index 8a369eaa0c..f8c48b3759 100644 --- a/docs/1.getting-started/6.data-fetching.md +++ b/docs/1.getting-started/6.data-fetching.md @@ -1,5 +1,5 @@ --- -title: 'Data fetching' +title: 'Data Fetching' description: Nuxt provides composables to handle data fetching within your application. navigation.icon: i-ph-plugs-connected --- From d93de6c1dbd78cf2dd8f696ecd26d00245363353 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 28 Nov 2024 09:19:37 +0000 Subject: [PATCH 07/11] chore(deps): update all non-major dependencies (main) (#30076) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- package.json | 8 +- pnpm-lock.yaml | 282 ++++++++++++++++++++++++------------------------- 2 files changed, 145 insertions(+), 145 deletions(-) diff --git a/package.json b/package.json index d92e180e2d..1474c7b40a 100644 --- a/package.json +++ b/package.json @@ -39,7 +39,7 @@ "@nuxt/schema": "workspace:*", "@nuxt/vite-builder": "workspace:*", "@nuxt/webpack-builder": "workspace:*", - "@types/node": "22.10.0", + "@types/node": "22.10.1", "@unhead/dom": "1.11.13", "@unhead/schema": "1.11.13", "@unhead/shared": "1.11.13", @@ -72,7 +72,7 @@ "@nuxt/test-utils": "3.14.4", "@nuxt/webpack-builder": "workspace:*", "@testing-library/vue": "8.1.0", - "@types/node": "22.10.0", + "@types/node": "22.10.1", "@types/semver": "7.5.8", "@unhead/schema": "1.11.13", "@unhead/vue": "1.11.13", @@ -90,9 +90,9 @@ "eslint-plugin-perfectionist": "4.1.2", "eslint-typegen": "0.3.2", "h3": "npm:h3-nightly@2.0.0-1718872656.6765a6e", - "happy-dom": "15.11.6", + "happy-dom": "15.11.7", "jiti": "2.4.0", - "knip": "5.38.1", + "knip": "5.38.2", "markdownlint-cli": "0.43.0", "nitro": "npm:nitro-nightly@3.0.0-beta-28796231.359af68d", "nuxi": "3.15.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index a9edb20ba5..b66b31d96c 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -10,7 +10,7 @@ overrides: '@nuxt/schema': workspace:* '@nuxt/vite-builder': workspace:* '@nuxt/webpack-builder': workspace:* - '@types/node': 22.10.0 + '@types/node': 22.10.1 '@unhead/dom': 1.11.13 '@unhead/schema': 1.11.13 '@unhead/shared': 1.11.13 @@ -51,7 +51,7 @@ importers: version: link:packages/rspack '@nuxt/test-utils': specifier: 3.14.4 - version: 3.14.4(@testing-library/vue@8.1.0(@vue/compiler-sfc@3.5.13)(vue@3.5.13(typescript@5.6.3)))(@vue/test-utils@2.4.6)(h3-nightly@2.0.0-1718872656.6765a6e)(happy-dom@15.11.6)(magicast@0.3.5)(nitropack@2.9.7(magicast@0.3.5))(playwright-core@1.49.0)(vite@6.0.1(@types/node@22.10.0)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1))(vitest@2.1.6(@types/node@22.10.0)(happy-dom@15.11.6)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1))(vue-router@4.5.0(vue@3.5.13(typescript@5.6.3)))(vue@3.5.13(typescript@5.6.3)) + version: 3.14.4(@testing-library/vue@8.1.0(@vue/compiler-sfc@3.5.13)(vue@3.5.13(typescript@5.6.3)))(@vue/test-utils@2.4.6)(h3-nightly@2.0.0-1718872656.6765a6e)(happy-dom@15.11.7)(magicast@0.3.5)(nitropack@2.9.7(magicast@0.3.5))(playwright-core@1.49.0)(vite@6.0.1(@types/node@22.10.1)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1))(vitest@2.1.6(@types/node@22.10.1)(happy-dom@15.11.7)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1))(vue-router@4.5.0(vue@3.5.13(typescript@5.6.3)))(vue@3.5.13(typescript@5.6.3)) '@nuxt/webpack-builder': specifier: workspace:* version: link:packages/webpack @@ -59,8 +59,8 @@ importers: specifier: 8.1.0 version: 8.1.0(@vue/compiler-sfc@3.5.13)(vue@3.5.13(typescript@5.6.3)) '@types/node': - specifier: 22.10.0 - version: 22.10.0 + specifier: 22.10.1 + version: 22.10.1 '@types/semver': specifier: 7.5.8 version: 7.5.8 @@ -72,7 +72,7 @@ importers: version: 1.11.13(vue@3.5.13(typescript@5.6.3)) '@vitest/coverage-v8': specifier: 2.1.6 - version: 2.1.6(vitest@2.1.6(@types/node@22.10.0)(happy-dom@15.11.6)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1)) + version: 2.1.6(vitest@2.1.6(@types/node@22.10.1)(happy-dom@15.11.7)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1)) '@vue/test-utils': specifier: 2.4.6 version: 2.4.6 @@ -113,14 +113,14 @@ importers: specifier: npm:h3-nightly@2.0.0-1718872656.6765a6e version: h3-nightly@2.0.0-1718872656.6765a6e happy-dom: - specifier: 15.11.6 - version: 15.11.6 + specifier: 15.11.7 + version: 15.11.7 jiti: specifier: 2.4.0 version: 2.4.0 knip: - specifier: 5.38.1 - version: 5.38.1(@types/node@22.10.0)(typescript@5.6.3) + specifier: 5.38.2 + version: 5.38.2(@types/node@22.10.1)(typescript@5.6.3) markdownlint-cli: specifier: 0.43.0 version: 0.43.0 @@ -171,10 +171,10 @@ importers: version: 1.5.4 vitest: specifier: 2.1.6 - version: 2.1.6(@types/node@22.10.0)(happy-dom@15.11.6)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1) + version: 2.1.6(@types/node@22.10.1)(happy-dom@15.11.7)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1) vitest-environment-nuxt: specifier: 1.0.1 - version: 1.0.1(@testing-library/vue@8.1.0(@vue/compiler-sfc@3.5.13)(vue@3.5.13(typescript@5.6.3)))(@vue/test-utils@2.4.6)(h3-nightly@2.0.0-1718872656.6765a6e)(happy-dom@15.11.6)(magicast@0.3.5)(nitropack@2.9.7(magicast@0.3.5))(playwright-core@1.49.0)(vite@6.0.1(@types/node@22.10.0)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1))(vitest@2.1.6(@types/node@22.10.0)(happy-dom@15.11.6)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1))(vue-router@4.5.0(vue@3.5.13(typescript@5.6.3)))(vue@3.5.13(typescript@5.6.3)) + version: 1.0.1(@testing-library/vue@8.1.0(@vue/compiler-sfc@3.5.13)(vue@3.5.13(typescript@5.6.3)))(@vue/test-utils@2.4.6)(h3-nightly@2.0.0-1718872656.6765a6e)(happy-dom@15.11.7)(magicast@0.3.5)(nitropack@2.9.7(magicast@0.3.5))(playwright-core@1.49.0)(vite@6.0.1(@types/node@22.10.1)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1))(vitest@2.1.6(@types/node@22.10.1)(happy-dom@15.11.7)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1))(vue-router@4.5.0(vue@3.5.13(typescript@5.6.3)))(vue@3.5.13(typescript@5.6.3)) vue: specifier: 3.5.13 version: 3.5.13(typescript@5.6.3) @@ -259,10 +259,10 @@ importers: version: 3.0.0-rc.11(sass@1.78.0)(typescript@5.6.3)(vue-tsc@2.1.10(typescript@5.6.3)) vite: specifier: 6.0.1 - version: 6.0.1(@types/node@22.10.0)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1) + version: 6.0.1(@types/node@22.10.1)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1) vitest: specifier: 2.1.6 - version: 2.1.6(@types/node@22.10.0)(happy-dom@15.11.6)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1) + version: 2.1.6(@types/node@22.10.1)(happy-dom@15.11.7)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1) webpack: specifier: 5.96.1 version: 5.96.1 @@ -274,7 +274,7 @@ importers: version: 2.0.2 '@nuxt/devtools': specifier: ^1.6.1 - version: 1.6.1(rollup@4.27.4)(vite@6.0.1(@types/node@22.10.0)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1))(vue@3.5.13(typescript@5.6.3)) + version: 1.6.1(rollup@4.27.4)(vite@6.0.1(@types/node@22.10.1)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1))(vue@3.5.13(typescript@5.6.3)) '@nuxt/kit': specifier: workspace:* version: link:../kit @@ -288,8 +288,8 @@ importers: specifier: workspace:* version: link:../vite '@types/node': - specifier: 22.10.0 - version: 22.10.0 + specifier: 22.10.1 + version: 22.10.1 '@unhead/dom': specifier: 1.11.13 version: 1.11.13 @@ -467,7 +467,7 @@ importers: devDependencies: '@nuxt/scripts': specifier: 0.9.5 - version: 0.9.5(@nuxt/devtools@1.6.1(rollup@4.27.4)(vite@6.0.1(@types/node@22.10.0)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1))(vue@3.5.13(typescript@5.6.3)))(@unocss/webpack@0.62.4(rollup@4.27.4)(webpack@5.96.1(esbuild@0.24.0)))(@vue/compiler-core@3.5.13)(change-case@5.4.4)(ioredis@5.4.1)(nuxt@packages+nuxt)(postcss@8.4.49)(rollup@4.27.4)(typescript@5.6.3)(vite@6.0.1(@types/node@22.10.0)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1))(vue@3.5.13(typescript@5.6.3))(webpack@5.96.1(esbuild@0.24.0)) + version: 0.9.5(@nuxt/devtools@1.6.1(rollup@4.27.4)(vite@6.0.1(@types/node@22.10.1)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1))(vue@3.5.13(typescript@5.6.3)))(@unocss/webpack@0.62.4(rollup@4.27.4)(webpack@5.96.1(esbuild@0.24.0)))(@vue/compiler-core@3.5.13)(change-case@5.4.4)(ioredis@5.4.1)(nuxt@packages+nuxt)(postcss@8.4.49)(rollup@4.27.4)(typescript@5.6.3)(vite@6.0.1(@types/node@22.10.1)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1))(vue@3.5.13(typescript@5.6.3))(webpack@5.96.1(esbuild@0.24.0)) '@parcel/watcher': specifier: 2.5.0 version: 2.5.0 @@ -476,7 +476,7 @@ importers: version: 1.0.6 '@vitejs/plugin-vue': specifier: 5.2.1 - version: 5.2.1(vite@6.0.1(@types/node@22.10.0)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1))(vue@3.5.13(typescript@5.6.3)) + version: 5.2.1(vite@6.0.1(@types/node@22.10.1)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1))(vue@3.5.13(typescript@5.6.3)) '@vue/compiler-sfc': specifier: 3.5.13 version: 3.5.13 @@ -485,10 +485,10 @@ importers: version: 3.0.0-rc.11(sass@1.78.0)(typescript@5.6.3)(vue-tsc@2.1.10(typescript@5.6.3)) vite: specifier: 6.0.1 - version: 6.0.1(@types/node@22.10.0)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1) + version: 6.0.1(@types/node@22.10.1)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1) vitest: specifier: 2.1.6 - version: 2.1.6(@types/node@22.10.0)(happy-dom@15.11.6)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1) + version: 2.1.6(@types/node@22.10.1)(happy-dom@15.11.7)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1) packages/rspack: dependencies: @@ -694,10 +694,10 @@ importers: version: 1.11.13 '@vitejs/plugin-vue': specifier: 5.2.1 - version: 5.2.1(vite@6.0.1(@types/node@22.10.0)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1))(vue@3.5.13(typescript@5.6.3)) + version: 5.2.1(vite@6.0.1(@types/node@22.10.1)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1))(vue@3.5.13(typescript@5.6.3)) '@vitejs/plugin-vue-jsx': specifier: 4.1.1 - version: 4.1.1(vite@6.0.1(@types/node@22.10.0)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1))(vue@3.5.13(typescript@5.6.3)) + version: 4.1.1(vite@6.0.1(@types/node@22.10.1)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1))(vue@3.5.13(typescript@5.6.3)) '@vue/compiler-core': specifier: 3.5.13 version: 3.5.13 @@ -730,7 +730,7 @@ importers: version: 2.3.1 vite: specifier: 6.0.1 - version: 6.0.1(@types/node@22.10.0)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1) + version: 6.0.1(@types/node@22.10.1)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1) vue: specifier: 3.5.13 version: 3.5.13(typescript@5.6.3) @@ -760,7 +760,7 @@ importers: version: 0.1.0 html-validate: specifier: 8.26.0 - version: 8.26.0(vitest@2.1.6(@types/node@22.10.0)(happy-dom@15.11.6)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1)) + version: 8.26.0(vitest@2.1.6(@types/node@22.10.1)(happy-dom@15.11.7)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1)) htmlnano: specifier: 2.1.1 version: 2.1.1(cssnano@7.0.6(postcss@8.4.49))(postcss@8.4.49)(relateurl@0.2.7)(svgo@3.3.2)(terser@5.32.0)(typescript@5.6.3) @@ -790,10 +790,10 @@ importers: version: 0.2.10 unocss: specifier: 0.64.1 - version: 0.64.1(postcss@8.4.49)(rollup@4.27.4)(vite@6.0.1(@types/node@22.10.0)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1))(vue@3.5.13(typescript@5.6.3)) + version: 0.64.1(postcss@8.4.49)(rollup@4.27.4)(vite@6.0.1(@types/node@22.10.1)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1))(vue@3.5.13(typescript@5.6.3)) vite: specifier: 6.0.1 - version: 6.0.1(@types/node@22.10.0)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1) + version: 6.0.1(@types/node@22.10.1)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1) packages/vite: dependencies: @@ -805,10 +805,10 @@ importers: version: 6.0.1(rollup@4.27.4) '@vitejs/plugin-vue': specifier: ^5.2.1 - version: 5.2.1(vite@6.0.1(@types/node@22.10.0)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1))(vue@3.5.13(typescript@5.6.3)) + version: 5.2.1(vite@6.0.1(@types/node@22.10.1)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1))(vue@3.5.13(typescript@5.6.3)) '@vitejs/plugin-vue-jsx': specifier: ^4.1.1 - version: 4.1.1(vite@6.0.1(@types/node@22.10.0)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1))(vue@3.5.13(typescript@5.6.3)) + version: 4.1.1(vite@6.0.1(@types/node@22.10.1)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1))(vue@3.5.13(typescript@5.6.3)) autoprefixer: specifier: ^10.4.20 version: 10.4.20(postcss@8.4.49) @@ -877,13 +877,13 @@ importers: version: 1.16.0 vite: specifier: 6.0.1 - version: 6.0.1(@types/node@22.10.0)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1) + version: 6.0.1(@types/node@22.10.1)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1) vite-node: specifier: ^2.1.6 - version: 2.1.6(@types/node@22.10.0)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1) + version: 2.1.6(@types/node@22.10.1)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1) vite-plugin-checker: specifier: ^0.8.0 - version: 0.8.0(eslint@9.15.0(jiti@2.4.0))(optionator@0.9.4)(typescript@5.6.3)(vite@6.0.1(@types/node@22.10.0)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1))(vue-tsc@2.1.10(typescript@5.6.3)) + version: 0.8.0(eslint@9.15.0(jiti@2.4.0))(optionator@0.9.4)(typescript@5.6.3)(vite@6.0.1(@types/node@22.10.1)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1))(vue-tsc@2.1.10(typescript@5.6.3)) vue-bundle-renderer: specifier: ^2.1.1 version: 2.1.1 @@ -1106,7 +1106,7 @@ importers: version: 0.10.8(rollup@4.27.4)(vue-router@4.5.0(vue@3.5.13(typescript@5.6.3)))(vue@3.5.13(typescript@5.6.3)) vitest: specifier: 1.6.0 - version: 1.6.0(@types/node@22.10.0)(happy-dom@15.11.6)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1) + version: 1.6.0(@types/node@22.10.1)(happy-dom@15.11.7)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1) vue: specifier: 3.5.13 version: 3.5.13(typescript@5.6.3) @@ -2712,8 +2712,8 @@ packages: '@types/node-sass@4.11.7': resolution: {integrity: sha512-QY0sXZGPRzJ2obo66f9zB6S0Uo9PRdcoPKPbyftSoKXub90s4ut/JK3fYHOqmhYhRRVEB3P5o5rEnq2/bWBdeg==} - '@types/node@22.10.0': - resolution: {integrity: sha512-XC70cRZVElFHfIUB40FgZOBbgJYFKKMa5nb9lxcwYstFG/Mi+/Y0bGS+rs6Dmhmkpq4pnNiLiuZAbc02YCOnmA==} + '@types/node@22.10.1': + resolution: {integrity: sha512-qKgsUwfHZV2WCWLAnVP1JqnpE6Im6h3Y0+fYgMTasNQ7V++CBX5OT1as0g0f+OyubbFqhf6XVNIsmN4IIhEgGQ==} '@types/normalize-package-data@2.4.4': resolution: {integrity: sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==} @@ -4715,8 +4715,8 @@ packages: h3-nightly@2.0.0-1718872656.6765a6e: resolution: {integrity: sha512-LQ8hHOIzk+agD1p0K7UosByKuzDAKGLTnYsP0syV/XMr9E7pWmoaDSWkGdWjtLR9O3hinNqrXU1NW0kTmhiSag==} - happy-dom@15.11.6: - resolution: {integrity: sha512-elX7iUTu+5+3b2+NGQc0L3eWyq9jKhuJJ4GpOMxxT/c2pg9O3L5H3ty2VECX0XXZgRmmRqXyOK8brA2hDI6LsQ==} + happy-dom@15.11.7: + resolution: {integrity: sha512-KyrFvnl+J9US63TEzwoiJOQzZBJY7KgBushJA8X61DMbNsH+2ONkDuLDnCnwUiPTF42tLoEmrPyoqbenVA5zrg==} engines: {node: '>=18.0.0'} has-bigints@1.0.2: @@ -5288,12 +5288,12 @@ packages: resolution: {integrity: sha512-dhG34DXATL5hSxJbIexCft8FChFXtmskoZYnoPWjXQuebWYCNkVeV3KkGegCK9CP1oswI/vQibS2GY7Em/sJJA==} engines: {node: '>= 8'} - knip@5.38.1: - resolution: {integrity: sha512-qGQpVO9jhHDoJ/4O1paXQ8Y6XyqH3Xm6OTety/z5IouZBEvJuJoWp59iY9E82Dt0pz9BBmKLczliB4sbYMPr2g==} + knip@5.38.2: + resolution: {integrity: sha512-gVduAQa80bar/uKtQDvOCBzTApdjqiz8e9eDIdRkYFyTAQM/DriWLi2vv/2AlzMcPYeSWddLptBdgN4whGzFtg==} engines: {node: '>=18.6.0'} hasBin: true peerDependencies: - '@types/node': 22.10.0 + '@types/node': 22.10.1 typescript: 5.6.3 knitwork@1.1.0: @@ -7448,7 +7448,7 @@ packages: engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} hasBin: true peerDependencies: - '@types/node': 22.10.0 + '@types/node': 22.10.1 jiti: 2.4.0 less: '*' lightningcss: ^1.21.0 @@ -7492,7 +7492,7 @@ packages: hasBin: true peerDependencies: '@edge-runtime/vm': '*' - '@types/node': 22.10.0 + '@types/node': 22.10.1 '@vitest/browser': 1.6.0 '@vitest/ui': 1.6.0 happy-dom: '*' @@ -7517,7 +7517,7 @@ packages: hasBin: true peerDependencies: '@edge-runtime/vm': '*' - '@types/node': 22.10.0 + '@types/node': 22.10.1 '@vitest/browser': 2.1.6 '@vitest/ui': 2.1.6 happy-dom: '*' @@ -8480,7 +8480,7 @@ snapshots: '@jest/schemas': 29.6.3 '@types/istanbul-lib-coverage': 2.0.6 '@types/istanbul-reports': 3.0.4 - '@types/node': 22.10.0 + '@types/node': 22.10.1 '@types/yargs': 17.0.33 chalk: 4.1.2 @@ -8588,31 +8588,31 @@ snapshots: '@nuxt/devalue@2.0.2': {} - '@nuxt/devtools-kit@1.5.1(vite@6.0.1(@types/node@22.10.0)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1))': + '@nuxt/devtools-kit@1.5.1(vite@6.0.1(@types/node@22.10.1)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1))': dependencies: '@nuxt/kit': link:packages/kit '@nuxt/schema': link:packages/schema execa: 7.2.0 - vite: 6.0.1(@types/node@22.10.0)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1) + vite: 6.0.1(@types/node@22.10.1)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1) - '@nuxt/devtools-kit@1.6.1(vite@6.0.1(@types/node@22.10.0)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1))': + '@nuxt/devtools-kit@1.6.1(vite@6.0.1(@types/node@22.10.1)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1))': dependencies: '@nuxt/kit': link:packages/kit '@nuxt/schema': link:packages/schema execa: 7.2.0 - vite: 6.0.1(@types/node@22.10.0)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1) + vite: 6.0.1(@types/node@22.10.1)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1) - '@nuxt/devtools-ui-kit@1.5.1(@nuxt/devtools@1.6.1(rollup@4.27.4)(vite@6.0.1(@types/node@22.10.0)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1))(vue@3.5.13(typescript@5.6.3)))(@unocss/webpack@0.62.4(rollup@4.27.4)(webpack@5.96.1(esbuild@0.24.0)))(@vue/compiler-core@3.5.13)(change-case@5.4.4)(nuxt@packages+nuxt)(postcss@8.4.49)(rollup@4.27.4)(vite@6.0.1(@types/node@22.10.0)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1))(vue@3.5.13(typescript@5.6.3))(webpack@5.96.1(esbuild@0.24.0))': + '@nuxt/devtools-ui-kit@1.5.1(@nuxt/devtools@1.6.1(rollup@4.27.4)(vite@6.0.1(@types/node@22.10.1)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1))(vue@3.5.13(typescript@5.6.3)))(@unocss/webpack@0.62.4(rollup@4.27.4)(webpack@5.96.1(esbuild@0.24.0)))(@vue/compiler-core@3.5.13)(change-case@5.4.4)(nuxt@packages+nuxt)(postcss@8.4.49)(rollup@4.27.4)(vite@6.0.1(@types/node@22.10.1)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1))(vue@3.5.13(typescript@5.6.3))(webpack@5.96.1(esbuild@0.24.0))': dependencies: '@iconify-json/carbon': 1.2.1 '@iconify-json/logos': 1.2.0 '@iconify-json/ri': 1.2.0 '@iconify-json/tabler': 1.2.3 - '@nuxt/devtools': 1.6.1(rollup@4.27.4)(vite@6.0.1(@types/node@22.10.0)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1))(vue@3.5.13(typescript@5.6.3)) - '@nuxt/devtools-kit': 1.5.1(vite@6.0.1(@types/node@22.10.0)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1)) + '@nuxt/devtools': 1.6.1(rollup@4.27.4)(vite@6.0.1(@types/node@22.10.1)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1))(vue@3.5.13(typescript@5.6.3)) + '@nuxt/devtools-kit': 1.5.1(vite@6.0.1(@types/node@22.10.1)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1)) '@nuxt/kit': link:packages/kit '@unocss/core': 0.62.4 - '@unocss/nuxt': 0.62.4(postcss@8.4.49)(rollup@4.27.4)(vite@6.0.1(@types/node@22.10.0)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1))(webpack@5.96.1(esbuild@0.24.0)) + '@unocss/nuxt': 0.62.4(postcss@8.4.49)(rollup@4.27.4)(vite@6.0.1(@types/node@22.10.1)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1))(webpack@5.96.1(esbuild@0.24.0)) '@unocss/preset-attributify': 0.62.4 '@unocss/preset-icons': 0.62.4 '@unocss/preset-mini': 0.62.4 @@ -8623,7 +8623,7 @@ snapshots: defu: 6.1.4 focus-trap: 7.6.0 splitpanes: 3.1.5 - unocss: 0.62.4(@unocss/webpack@0.62.4(rollup@4.27.4)(webpack@5.96.1(esbuild@0.24.0)))(postcss@8.4.49)(rollup@4.27.4)(vite@6.0.1(@types/node@22.10.0)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1)) + unocss: 0.62.4(@unocss/webpack@0.62.4(rollup@4.27.4)(webpack@5.96.1(esbuild@0.24.0)))(postcss@8.4.49)(rollup@4.27.4)(vite@6.0.1(@types/node@22.10.1)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1)) v-lazy-show: 0.2.4(@vue/compiler-core@3.5.13) transitivePeerDependencies: - '@unocss/webpack' @@ -8661,13 +8661,13 @@ snapshots: rc9: 2.1.2 semver: 7.6.3 - '@nuxt/devtools@1.6.1(rollup@4.27.4)(vite@6.0.1(@types/node@22.10.0)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1))(vue@3.5.13(typescript@5.6.3))': + '@nuxt/devtools@1.6.1(rollup@4.27.4)(vite@6.0.1(@types/node@22.10.1)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1))(vue@3.5.13(typescript@5.6.3))': dependencies: '@antfu/utils': 0.7.10 - '@nuxt/devtools-kit': 1.6.1(vite@6.0.1(@types/node@22.10.0)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1)) + '@nuxt/devtools-kit': 1.6.1(vite@6.0.1(@types/node@22.10.1)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1)) '@nuxt/devtools-wizard': 1.6.1 '@nuxt/kit': link:packages/kit - '@vue/devtools-core': 7.6.4(vite@6.0.1(@types/node@22.10.0)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1))(vue@3.5.13(typescript@5.6.3)) + '@vue/devtools-core': 7.6.4(vite@6.0.1(@types/node@22.10.1)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1))(vue@3.5.13(typescript@5.6.3)) '@vue/devtools-kit': 7.6.4 birpc: 0.2.19 consola: 3.2.3 @@ -8696,9 +8696,9 @@ snapshots: sirv: 2.0.4 tinyglobby: 0.2.10 unimport: 3.13.4(rollup@4.27.4) - vite: 6.0.1(@types/node@22.10.0)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1) - vite-plugin-inspect: 0.8.7(@nuxt/kit@packages+kit)(rollup@4.27.4)(vite@6.0.1(@types/node@22.10.0)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1)) - vite-plugin-vue-inspector: 5.1.3(vite@6.0.1(@types/node@22.10.0)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1)) + vite: 6.0.1(@types/node@22.10.1)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1) + vite-plugin-inspect: 0.8.7(@nuxt/kit@packages+kit)(rollup@4.27.4)(vite@6.0.1(@types/node@22.10.1)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1)) + vite-plugin-vue-inspector: 5.1.3(vite@6.0.1(@types/node@22.10.1)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1)) which: 3.0.1 ws: 8.18.0 transitivePeerDependencies: @@ -8753,10 +8753,10 @@ snapshots: string-width: 4.2.3 webpack: 5.96.1 - '@nuxt/scripts@0.9.5(@nuxt/devtools@1.6.1(rollup@4.27.4)(vite@6.0.1(@types/node@22.10.0)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1))(vue@3.5.13(typescript@5.6.3)))(@unocss/webpack@0.62.4(rollup@4.27.4)(webpack@5.96.1(esbuild@0.24.0)))(@vue/compiler-core@3.5.13)(change-case@5.4.4)(ioredis@5.4.1)(nuxt@packages+nuxt)(postcss@8.4.49)(rollup@4.27.4)(typescript@5.6.3)(vite@6.0.1(@types/node@22.10.0)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1))(vue@3.5.13(typescript@5.6.3))(webpack@5.96.1(esbuild@0.24.0))': + '@nuxt/scripts@0.9.5(@nuxt/devtools@1.6.1(rollup@4.27.4)(vite@6.0.1(@types/node@22.10.1)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1))(vue@3.5.13(typescript@5.6.3)))(@unocss/webpack@0.62.4(rollup@4.27.4)(webpack@5.96.1(esbuild@0.24.0)))(@vue/compiler-core@3.5.13)(change-case@5.4.4)(ioredis@5.4.1)(nuxt@packages+nuxt)(postcss@8.4.49)(rollup@4.27.4)(typescript@5.6.3)(vite@6.0.1(@types/node@22.10.1)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1))(vue@3.5.13(typescript@5.6.3))(webpack@5.96.1(esbuild@0.24.0))': dependencies: - '@nuxt/devtools-kit': 1.6.1(vite@6.0.1(@types/node@22.10.0)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1)) - '@nuxt/devtools-ui-kit': 1.5.1(@nuxt/devtools@1.6.1(rollup@4.27.4)(vite@6.0.1(@types/node@22.10.0)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1))(vue@3.5.13(typescript@5.6.3)))(@unocss/webpack@0.62.4(rollup@4.27.4)(webpack@5.96.1(esbuild@0.24.0)))(@vue/compiler-core@3.5.13)(change-case@5.4.4)(nuxt@packages+nuxt)(postcss@8.4.49)(rollup@4.27.4)(vite@6.0.1(@types/node@22.10.0)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1))(vue@3.5.13(typescript@5.6.3))(webpack@5.96.1(esbuild@0.24.0)) + '@nuxt/devtools-kit': 1.6.1(vite@6.0.1(@types/node@22.10.1)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1)) + '@nuxt/devtools-ui-kit': 1.5.1(@nuxt/devtools@1.6.1(rollup@4.27.4)(vite@6.0.1(@types/node@22.10.1)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1))(vue@3.5.13(typescript@5.6.3)))(@unocss/webpack@0.62.4(rollup@4.27.4)(webpack@5.96.1(esbuild@0.24.0)))(@vue/compiler-core@3.5.13)(change-case@5.4.4)(nuxt@packages+nuxt)(postcss@8.4.49)(rollup@4.27.4)(vite@6.0.1(@types/node@22.10.1)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1))(vue@3.5.13(typescript@5.6.3))(webpack@5.96.1(esbuild@0.24.0)) '@nuxt/kit': link:packages/kit '@stripe/stripe-js': 4.8.0 '@types/google.maps': 3.58.1 @@ -8842,7 +8842,7 @@ snapshots: rc9: 2.1.2 std-env: 3.8.0 - '@nuxt/test-utils@3.14.4(@testing-library/vue@8.1.0(@vue/compiler-sfc@3.5.13)(vue@3.5.13(typescript@5.6.3)))(@vue/test-utils@2.4.6)(h3-nightly@2.0.0-1718872656.6765a6e)(happy-dom@15.11.6)(magicast@0.3.5)(nitropack@2.9.7(magicast@0.3.5))(playwright-core@1.49.0)(vite@6.0.1(@types/node@22.10.0)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1))(vitest@2.1.6(@types/node@22.10.0)(happy-dom@15.11.6)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1))(vue-router@4.5.0(vue@3.5.13(typescript@5.6.3)))(vue@3.5.13(typescript@5.6.3))': + '@nuxt/test-utils@3.14.4(@testing-library/vue@8.1.0(@vue/compiler-sfc@3.5.13)(vue@3.5.13(typescript@5.6.3)))(@vue/test-utils@2.4.6)(h3-nightly@2.0.0-1718872656.6765a6e)(happy-dom@15.11.7)(magicast@0.3.5)(nitropack@2.9.7(magicast@0.3.5))(playwright-core@1.49.0)(vite@6.0.1(@types/node@22.10.1)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1))(vitest@2.1.6(@types/node@22.10.1)(happy-dom@15.11.7)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1))(vue-router@4.5.0(vue@3.5.13(typescript@5.6.3)))(vue@3.5.13(typescript@5.6.3))': dependencies: '@nuxt/kit': link:packages/kit '@nuxt/schema': link:packages/schema @@ -8868,16 +8868,16 @@ snapshots: ufo: 1.5.4 unenv: 1.10.0 unplugin: 1.16.0 - vite: 6.0.1(@types/node@22.10.0)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1) - vitest-environment-nuxt: 1.0.1(@testing-library/vue@8.1.0(@vue/compiler-sfc@3.5.13)(vue@3.5.13(typescript@5.6.3)))(@vue/test-utils@2.4.6)(h3-nightly@2.0.0-1718872656.6765a6e)(happy-dom@15.11.6)(magicast@0.3.5)(nitropack@2.9.7(magicast@0.3.5))(playwright-core@1.49.0)(vite@6.0.1(@types/node@22.10.0)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1))(vitest@2.1.6(@types/node@22.10.0)(happy-dom@15.11.6)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1))(vue-router@4.5.0(vue@3.5.13(typescript@5.6.3)))(vue@3.5.13(typescript@5.6.3)) + vite: 6.0.1(@types/node@22.10.1)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1) + vitest-environment-nuxt: 1.0.1(@testing-library/vue@8.1.0(@vue/compiler-sfc@3.5.13)(vue@3.5.13(typescript@5.6.3)))(@vue/test-utils@2.4.6)(h3-nightly@2.0.0-1718872656.6765a6e)(happy-dom@15.11.7)(magicast@0.3.5)(nitropack@2.9.7(magicast@0.3.5))(playwright-core@1.49.0)(vite@6.0.1(@types/node@22.10.1)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1))(vitest@2.1.6(@types/node@22.10.1)(happy-dom@15.11.7)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1))(vue-router@4.5.0(vue@3.5.13(typescript@5.6.3)))(vue@3.5.13(typescript@5.6.3)) vue: 3.5.13(typescript@5.6.3) vue-router: 4.5.0(vue@3.5.13(typescript@5.6.3)) optionalDependencies: '@testing-library/vue': 8.1.0(@vue/compiler-sfc@3.5.13)(vue@3.5.13(typescript@5.6.3)) '@vue/test-utils': 2.4.6 - happy-dom: 15.11.6 + happy-dom: 15.11.7 playwright-core: 1.49.0 - vitest: 2.1.6(@types/node@22.10.0)(happy-dom@15.11.6)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1) + vitest: 2.1.6(@types/node@22.10.1)(happy-dom@15.11.7)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1) transitivePeerDependencies: - magicast @@ -8912,7 +8912,7 @@ snapshots: remark-parse: 11.0.0 remark-rehype: 11.1.1 scule: 1.3.0 - shiki: 1.22.2 + shiki: 1.23.1 ufo: 1.5.4 unified: 11.0.5 unist-builder: 4.0.0 @@ -9385,7 +9385,7 @@ snapshots: '@types/connect@3.4.38': dependencies: - '@types/node': 22.10.0 + '@types/node': 22.10.1 '@types/debug@4.1.12': dependencies: @@ -9415,7 +9415,7 @@ snapshots: '@types/http-proxy@1.17.15': dependencies: - '@types/node': 22.10.0 + '@types/node': 22.10.1 '@types/istanbul-lib-coverage@2.0.6': {} @@ -9443,9 +9443,9 @@ snapshots: '@types/node-sass@4.11.7': dependencies: - '@types/node': 22.10.0 + '@types/node': 22.10.1 - '@types/node@22.10.0': + '@types/node@22.10.1': dependencies: undici-types: 6.20.0 @@ -9459,7 +9459,7 @@ snapshots: '@types/sass-loader@8.0.9': dependencies: - '@types/node': 22.10.0 + '@types/node': 22.10.1 '@types/node-sass': 4.11.7 '@types/webpack': 4.41.39 sass: 1.78.0 @@ -9484,7 +9484,7 @@ snapshots: '@types/webpack-bundle-analyzer@4.7.0': dependencies: - '@types/node': 22.10.0 + '@types/node': 22.10.1 tapable: 2.2.1 webpack: 5.96.1 transitivePeerDependencies: @@ -9506,13 +9506,13 @@ snapshots: '@types/webpack-sources@3.2.3': dependencies: - '@types/node': 22.10.0 + '@types/node': 22.10.1 '@types/source-list-map': 0.1.6 source-map: 0.7.4 '@types/webpack@4.41.39': dependencies: - '@types/node': 22.10.0 + '@types/node': 22.10.1 '@types/tapable': 1.0.12 '@types/uglify-js': 3.17.5 '@types/webpack-sources': 3.2.3 @@ -9646,24 +9646,24 @@ snapshots: unhead: 1.11.13 vue: 3.5.13(typescript@5.6.3) - '@unocss/astro@0.62.4(rollup@4.27.4)(vite@6.0.1(@types/node@22.10.0)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1))': + '@unocss/astro@0.62.4(rollup@4.27.4)(vite@6.0.1(@types/node@22.10.1)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1))': dependencies: '@unocss/core': 0.62.4 '@unocss/reset': 0.62.4 - '@unocss/vite': 0.62.4(rollup@4.27.4)(vite@6.0.1(@types/node@22.10.0)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1)) + '@unocss/vite': 0.62.4(rollup@4.27.4)(vite@6.0.1(@types/node@22.10.1)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1)) optionalDependencies: - vite: 6.0.1(@types/node@22.10.0)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1) + vite: 6.0.1(@types/node@22.10.1)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1) transitivePeerDependencies: - rollup - supports-color - '@unocss/astro@0.64.1(rollup@4.27.4)(vite@6.0.1(@types/node@22.10.0)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1))(vue@3.5.13(typescript@5.6.3))': + '@unocss/astro@0.64.1(rollup@4.27.4)(vite@6.0.1(@types/node@22.10.1)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1))(vue@3.5.13(typescript@5.6.3))': dependencies: '@unocss/core': 0.64.1 '@unocss/reset': 0.64.1 - '@unocss/vite': 0.64.1(rollup@4.27.4)(vite@6.0.1(@types/node@22.10.0)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1))(vue@3.5.13(typescript@5.6.3)) + '@unocss/vite': 0.64.1(rollup@4.27.4)(vite@6.0.1(@types/node@22.10.1)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1))(vue@3.5.13(typescript@5.6.3)) optionalDependencies: - vite: 6.0.1(@types/node@22.10.0)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1) + vite: 6.0.1(@types/node@22.10.1)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1) transitivePeerDependencies: - rollup - supports-color @@ -9750,7 +9750,7 @@ snapshots: transitivePeerDependencies: - vue - '@unocss/nuxt@0.62.4(postcss@8.4.49)(rollup@4.27.4)(vite@6.0.1(@types/node@22.10.0)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1))(webpack@5.96.1(esbuild@0.24.0))': + '@unocss/nuxt@0.62.4(postcss@8.4.49)(rollup@4.27.4)(vite@6.0.1(@types/node@22.10.1)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1))(webpack@5.96.1(esbuild@0.24.0))': dependencies: '@nuxt/kit': link:packages/kit '@unocss/config': 0.62.4 @@ -9763,9 +9763,9 @@ snapshots: '@unocss/preset-web-fonts': 0.62.4 '@unocss/preset-wind': 0.62.4 '@unocss/reset': 0.62.4 - '@unocss/vite': 0.62.4(rollup@4.27.4)(vite@6.0.1(@types/node@22.10.0)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1)) + '@unocss/vite': 0.62.4(rollup@4.27.4)(vite@6.0.1(@types/node@22.10.1)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1)) '@unocss/webpack': 0.62.4(rollup@4.27.4)(webpack@5.96.1(esbuild@0.24.0)) - unocss: 0.62.4(@unocss/webpack@0.62.4(rollup@4.27.4)(webpack@5.96.1(esbuild@0.24.0)))(postcss@8.4.49)(rollup@4.27.4)(vite@6.0.1(@types/node@22.10.0)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1)) + unocss: 0.62.4(@unocss/webpack@0.62.4(rollup@4.27.4)(webpack@5.96.1(esbuild@0.24.0)))(postcss@8.4.49)(rollup@4.27.4)(vite@6.0.1(@types/node@22.10.1)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1)) transitivePeerDependencies: - postcss - rollup @@ -9935,7 +9935,7 @@ snapshots: dependencies: '@unocss/core': 0.64.1 - '@unocss/vite@0.62.4(rollup@4.27.4)(vite@6.0.1(@types/node@22.10.0)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1))': + '@unocss/vite@0.62.4(rollup@4.27.4)(vite@6.0.1(@types/node@22.10.1)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1))': dependencies: '@ampproject/remapping': 2.3.0 '@rollup/pluginutils': 5.1.3(rollup@4.27.4) @@ -9945,12 +9945,12 @@ snapshots: chokidar: 3.6.0 magic-string: 0.30.14 tinyglobby: 0.2.10 - vite: 6.0.1(@types/node@22.10.0)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1) + vite: 6.0.1(@types/node@22.10.1)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1) transitivePeerDependencies: - rollup - supports-color - '@unocss/vite@0.64.1(rollup@4.27.4)(vite@6.0.1(@types/node@22.10.0)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1))(vue@3.5.13(typescript@5.6.3))': + '@unocss/vite@0.64.1(rollup@4.27.4)(vite@6.0.1(@types/node@22.10.1)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1))(vue@3.5.13(typescript@5.6.3))': dependencies: '@ampproject/remapping': 2.3.0 '@rollup/pluginutils': 5.1.3(rollup@4.27.4) @@ -9960,7 +9960,7 @@ snapshots: chokidar: 3.6.0 magic-string: 0.30.14 tinyglobby: 0.2.10 - vite: 6.0.1(@types/node@22.10.0)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1) + vite: 6.0.1(@types/node@22.10.1)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1) transitivePeerDependencies: - rollup - supports-color @@ -10018,22 +10018,22 @@ snapshots: - encoding - supports-color - '@vitejs/plugin-vue-jsx@4.1.1(vite@6.0.1(@types/node@22.10.0)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1))(vue@3.5.13(typescript@5.6.3))': + '@vitejs/plugin-vue-jsx@4.1.1(vite@6.0.1(@types/node@22.10.1)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1))(vue@3.5.13(typescript@5.6.3))': dependencies: '@babel/core': 7.26.0 '@babel/plugin-transform-typescript': 7.25.9(@babel/core@7.26.0) '@vue/babel-plugin-jsx': 1.2.5(@babel/core@7.26.0) - vite: 6.0.1(@types/node@22.10.0)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1) + vite: 6.0.1(@types/node@22.10.1)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1) vue: 3.5.13(typescript@5.6.3) transitivePeerDependencies: - supports-color - '@vitejs/plugin-vue@5.2.1(vite@6.0.1(@types/node@22.10.0)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1))(vue@3.5.13(typescript@5.6.3))': + '@vitejs/plugin-vue@5.2.1(vite@6.0.1(@types/node@22.10.1)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1))(vue@3.5.13(typescript@5.6.3))': dependencies: - vite: 6.0.1(@types/node@22.10.0)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1) + vite: 6.0.1(@types/node@22.10.1)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1) vue: 3.5.13(typescript@5.6.3) - '@vitest/coverage-v8@2.1.6(vitest@2.1.6(@types/node@22.10.0)(happy-dom@15.11.6)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1))': + '@vitest/coverage-v8@2.1.6(vitest@2.1.6(@types/node@22.10.1)(happy-dom@15.11.7)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1))': dependencies: '@ampproject/remapping': 2.3.0 '@bcoe/v8-coverage': 0.2.3 @@ -10047,7 +10047,7 @@ snapshots: std-env: 3.8.0 test-exclude: 7.0.1 tinyrainbow: 1.2.0 - vitest: 2.1.6(@types/node@22.10.0)(happy-dom@15.11.6)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1) + vitest: 2.1.6(@types/node@22.10.1)(happy-dom@15.11.7)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1) transitivePeerDependencies: - supports-color @@ -10064,13 +10064,13 @@ snapshots: chai: 5.1.2 tinyrainbow: 1.2.0 - '@vitest/mocker@2.1.6(vite@6.0.1(@types/node@22.10.0)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1))': + '@vitest/mocker@2.1.6(vite@6.0.1(@types/node@22.10.1)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1))': dependencies: '@vitest/spy': 2.1.6 estree-walker: 3.0.3 magic-string: 0.30.14 optionalDependencies: - vite: 6.0.1(@types/node@22.10.0)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1) + vite: 6.0.1(@types/node@22.10.1)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1) '@vitest/pretty-format@2.1.6': dependencies: @@ -10216,14 +10216,14 @@ snapshots: dependencies: '@vue/devtools-kit': 7.6.5 - '@vue/devtools-core@7.6.4(vite@6.0.1(@types/node@22.10.0)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1))(vue@3.5.13(typescript@5.6.3))': + '@vue/devtools-core@7.6.4(vite@6.0.1(@types/node@22.10.1)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1))(vue@3.5.13(typescript@5.6.3))': dependencies: '@vue/devtools-kit': 7.6.4 '@vue/devtools-shared': 7.6.4 mitt: 3.0.1 nanoid: 3.3.7 pathe: 1.1.2 - vite-hot-client: 0.2.3(vite@6.0.1(@types/node@22.10.0)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1)) + vite-hot-client: 0.2.3(vite@6.0.1(@types/node@22.10.1)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1)) vue: 3.5.13(typescript@5.6.3) transitivePeerDependencies: - vite @@ -12003,7 +12003,7 @@ snapshots: transitivePeerDependencies: - uWebSockets.js - happy-dom@15.11.6: + happy-dom@15.11.7: dependencies: entities: 4.5.0 webidl-conversions: 7.0.0 @@ -12126,7 +12126,7 @@ snapshots: html-tags@3.3.1: {} - html-validate@8.26.0(vitest@2.1.6(@types/node@22.10.0)(happy-dom@15.11.6)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1)): + html-validate@8.26.0(vitest@2.1.6(@types/node@22.10.1)(happy-dom@15.11.7)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1)): dependencies: '@html-validate/stylish': 4.2.0 '@sidvind/better-ajv-errors': 3.0.1(ajv@8.17.1) @@ -12137,7 +12137,7 @@ snapshots: prompts: 2.4.2 semver: 7.6.3 optionalDependencies: - vitest: 2.1.6(@types/node@22.10.0)(happy-dom@15.11.6)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1) + vitest: 2.1.6(@types/node@22.10.1)(happy-dom@15.11.7)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1) html-void-elements@3.0.0: {} @@ -12473,7 +12473,7 @@ snapshots: jest-util@29.7.0: dependencies: '@jest/types': 29.6.3 - '@types/node': 22.10.0 + '@types/node': 22.10.1 chalk: 4.1.2 ci-info: 3.9.0 graceful-fs: 4.2.11 @@ -12481,13 +12481,13 @@ snapshots: jest-worker@27.5.1: dependencies: - '@types/node': 22.10.0 + '@types/node': 22.10.1 merge-stream: 2.0.0 supports-color: 8.1.1 jest-worker@29.7.0: dependencies: - '@types/node': 22.10.0 + '@types/node': 22.10.1 jest-util: 29.7.0 merge-stream: 2.0.0 supports-color: 8.1.1 @@ -12570,11 +12570,11 @@ snapshots: klona@2.0.6: {} - knip@5.38.1(@types/node@22.10.0)(typescript@5.6.3): + knip@5.38.2(@types/node@22.10.1)(typescript@5.6.3): dependencies: '@nodelib/fs.walk': 1.2.8 '@snyk/github-codeowners': 1.1.0 - '@types/node': 22.10.0 + '@types/node': 22.10.1 easy-table: 1.2.0 enhanced-resolve: 5.17.1 fast-glob: 3.3.2 @@ -15035,9 +15035,9 @@ snapshots: universalify@2.0.1: {} - unocss@0.62.4(@unocss/webpack@0.62.4(rollup@4.27.4)(webpack@5.96.1(esbuild@0.24.0)))(postcss@8.4.49)(rollup@4.27.4)(vite@6.0.1(@types/node@22.10.0)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1)): + unocss@0.62.4(@unocss/webpack@0.62.4(rollup@4.27.4)(webpack@5.96.1(esbuild@0.24.0)))(postcss@8.4.49)(rollup@4.27.4)(vite@6.0.1(@types/node@22.10.1)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1)): dependencies: - '@unocss/astro': 0.62.4(rollup@4.27.4)(vite@6.0.1(@types/node@22.10.0)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1)) + '@unocss/astro': 0.62.4(rollup@4.27.4)(vite@6.0.1(@types/node@22.10.1)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1)) '@unocss/cli': 0.62.4(rollup@4.27.4) '@unocss/core': 0.62.4 '@unocss/postcss': 0.62.4(postcss@8.4.49) @@ -15053,18 +15053,18 @@ snapshots: '@unocss/transformer-compile-class': 0.62.4 '@unocss/transformer-directives': 0.62.4 '@unocss/transformer-variant-group': 0.62.4 - '@unocss/vite': 0.62.4(rollup@4.27.4)(vite@6.0.1(@types/node@22.10.0)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1)) + '@unocss/vite': 0.62.4(rollup@4.27.4)(vite@6.0.1(@types/node@22.10.1)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1)) optionalDependencies: '@unocss/webpack': 0.62.4(rollup@4.27.4)(webpack@5.96.1(esbuild@0.24.0)) - vite: 6.0.1(@types/node@22.10.0)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1) + vite: 6.0.1(@types/node@22.10.1)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1) transitivePeerDependencies: - postcss - rollup - supports-color - unocss@0.64.1(postcss@8.4.49)(rollup@4.27.4)(vite@6.0.1(@types/node@22.10.0)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1))(vue@3.5.13(typescript@5.6.3)): + unocss@0.64.1(postcss@8.4.49)(rollup@4.27.4)(vite@6.0.1(@types/node@22.10.1)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1))(vue@3.5.13(typescript@5.6.3)): dependencies: - '@unocss/astro': 0.64.1(rollup@4.27.4)(vite@6.0.1(@types/node@22.10.0)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1))(vue@3.5.13(typescript@5.6.3)) + '@unocss/astro': 0.64.1(rollup@4.27.4)(vite@6.0.1(@types/node@22.10.1)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1))(vue@3.5.13(typescript@5.6.3)) '@unocss/cli': 0.64.1(rollup@4.27.4) '@unocss/core': 0.64.1 '@unocss/postcss': 0.64.1(postcss@8.4.49) @@ -15080,9 +15080,9 @@ snapshots: '@unocss/transformer-compile-class': 0.64.1 '@unocss/transformer-directives': 0.64.1 '@unocss/transformer-variant-group': 0.64.1 - '@unocss/vite': 0.64.1(rollup@4.27.4)(vite@6.0.1(@types/node@22.10.0)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1))(vue@3.5.13(typescript@5.6.3)) + '@unocss/vite': 0.64.1(rollup@4.27.4)(vite@6.0.1(@types/node@22.10.1)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1))(vue@3.5.13(typescript@5.6.3)) optionalDependencies: - vite: 6.0.1(@types/node@22.10.0)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1) + vite: 6.0.1(@types/node@22.10.1)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1) transitivePeerDependencies: - postcss - rollup @@ -15215,17 +15215,17 @@ snapshots: '@types/unist': 3.0.3 vfile-message: 4.0.2 - vite-hot-client@0.2.3(vite@6.0.1(@types/node@22.10.0)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1)): + vite-hot-client@0.2.3(vite@6.0.1(@types/node@22.10.1)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1)): dependencies: - vite: 6.0.1(@types/node@22.10.0)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1) + vite: 6.0.1(@types/node@22.10.1)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1) - vite-node@1.6.0(@types/node@22.10.0)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1): + vite-node@1.6.0(@types/node@22.10.1)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1): dependencies: cac: 6.7.14 debug: 4.3.7(supports-color@9.4.0) pathe: 1.1.2 picocolors: 1.1.1 - vite: 6.0.1(@types/node@22.10.0)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1) + vite: 6.0.1(@types/node@22.10.1)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1) transitivePeerDependencies: - '@types/node' - jiti @@ -15240,13 +15240,13 @@ snapshots: - tsx - yaml - vite-node@2.1.6(@types/node@22.10.0)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1): + vite-node@2.1.6(@types/node@22.10.1)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1): dependencies: cac: 6.7.14 debug: 4.3.7(supports-color@9.4.0) es-module-lexer: 1.5.4 pathe: 1.1.2 - vite: 6.0.1(@types/node@22.10.0)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1) + vite: 6.0.1(@types/node@22.10.1)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1) transitivePeerDependencies: - '@types/node' - jiti @@ -15261,7 +15261,7 @@ snapshots: - tsx - yaml - vite-plugin-checker@0.8.0(eslint@9.15.0(jiti@2.4.0))(optionator@0.9.4)(typescript@5.6.3)(vite@6.0.1(@types/node@22.10.0)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1))(vue-tsc@2.1.10(typescript@5.6.3)): + vite-plugin-checker@0.8.0(eslint@9.15.0(jiti@2.4.0))(optionator@0.9.4)(typescript@5.6.3)(vite@6.0.1(@types/node@22.10.1)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1))(vue-tsc@2.1.10(typescript@5.6.3)): dependencies: '@babel/code-frame': 7.26.2 ansi-escapes: 4.3.2 @@ -15273,7 +15273,7 @@ snapshots: npm-run-path: 4.0.1 strip-ansi: 6.0.1 tiny-invariant: 1.3.3 - vite: 6.0.1(@types/node@22.10.0)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1) + vite: 6.0.1(@types/node@22.10.1)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1) vscode-languageclient: 7.0.0 vscode-languageserver: 7.0.0 vscode-languageserver-textdocument: 1.0.12 @@ -15284,7 +15284,7 @@ snapshots: typescript: 5.6.3 vue-tsc: 2.1.10(typescript@5.6.3) - vite-plugin-inspect@0.8.7(@nuxt/kit@packages+kit)(rollup@4.27.4)(vite@6.0.1(@types/node@22.10.0)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1)): + vite-plugin-inspect@0.8.7(@nuxt/kit@packages+kit)(rollup@4.27.4)(vite@6.0.1(@types/node@22.10.1)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1)): dependencies: '@antfu/utils': 0.7.10 '@rollup/pluginutils': 5.1.3(rollup@4.27.4) @@ -15295,14 +15295,14 @@ snapshots: perfect-debounce: 1.0.0 picocolors: 1.1.1 sirv: 2.0.4 - vite: 6.0.1(@types/node@22.10.0)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1) + vite: 6.0.1(@types/node@22.10.1)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1) optionalDependencies: '@nuxt/kit': link:packages/kit transitivePeerDependencies: - rollup - supports-color - vite-plugin-vue-inspector@5.1.3(vite@6.0.1(@types/node@22.10.0)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1)): + vite-plugin-vue-inspector@5.1.3(vite@6.0.1(@types/node@22.10.1)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1)): dependencies: '@babel/core': 7.26.0 '@babel/plugin-proposal-decorators': 7.24.7(@babel/core@7.26.0) @@ -15313,17 +15313,17 @@ snapshots: '@vue/compiler-dom': 3.5.13 kolorist: 1.8.0 magic-string: 0.30.14 - vite: 6.0.1(@types/node@22.10.0)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1) + vite: 6.0.1(@types/node@22.10.1)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1) transitivePeerDependencies: - supports-color - vite@6.0.1(@types/node@22.10.0)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1): + vite@6.0.1(@types/node@22.10.1)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1): dependencies: esbuild: 0.24.0 postcss: 8.4.49 rollup: 4.27.4 optionalDependencies: - '@types/node': 22.10.0 + '@types/node': 22.10.1 fsevents: 2.3.3 jiti: 2.4.0 sass: 1.78.0 @@ -15331,9 +15331,9 @@ snapshots: tsx: 4.19.1 yaml: 2.5.1 - vitest-environment-nuxt@1.0.1(@testing-library/vue@8.1.0(@vue/compiler-sfc@3.5.13)(vue@3.5.13(typescript@5.6.3)))(@vue/test-utils@2.4.6)(h3-nightly@2.0.0-1718872656.6765a6e)(happy-dom@15.11.6)(magicast@0.3.5)(nitropack@2.9.7(magicast@0.3.5))(playwright-core@1.49.0)(vite@6.0.1(@types/node@22.10.0)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1))(vitest@2.1.6(@types/node@22.10.0)(happy-dom@15.11.6)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1))(vue-router@4.5.0(vue@3.5.13(typescript@5.6.3)))(vue@3.5.13(typescript@5.6.3)): + vitest-environment-nuxt@1.0.1(@testing-library/vue@8.1.0(@vue/compiler-sfc@3.5.13)(vue@3.5.13(typescript@5.6.3)))(@vue/test-utils@2.4.6)(h3-nightly@2.0.0-1718872656.6765a6e)(happy-dom@15.11.7)(magicast@0.3.5)(nitropack@2.9.7(magicast@0.3.5))(playwright-core@1.49.0)(vite@6.0.1(@types/node@22.10.1)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1))(vitest@2.1.6(@types/node@22.10.1)(happy-dom@15.11.7)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1))(vue-router@4.5.0(vue@3.5.13(typescript@5.6.3)))(vue@3.5.13(typescript@5.6.3)): dependencies: - '@nuxt/test-utils': 3.14.4(@testing-library/vue@8.1.0(@vue/compiler-sfc@3.5.13)(vue@3.5.13(typescript@5.6.3)))(@vue/test-utils@2.4.6)(h3-nightly@2.0.0-1718872656.6765a6e)(happy-dom@15.11.6)(magicast@0.3.5)(nitropack@2.9.7(magicast@0.3.5))(playwright-core@1.49.0)(vite@6.0.1(@types/node@22.10.0)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1))(vitest@2.1.6(@types/node@22.10.0)(happy-dom@15.11.6)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1))(vue-router@4.5.0(vue@3.5.13(typescript@5.6.3)))(vue@3.5.13(typescript@5.6.3)) + '@nuxt/test-utils': 3.14.4(@testing-library/vue@8.1.0(@vue/compiler-sfc@3.5.13)(vue@3.5.13(typescript@5.6.3)))(@vue/test-utils@2.4.6)(h3-nightly@2.0.0-1718872656.6765a6e)(happy-dom@15.11.7)(magicast@0.3.5)(nitropack@2.9.7(magicast@0.3.5))(playwright-core@1.49.0)(vite@6.0.1(@types/node@22.10.1)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1))(vitest@2.1.6(@types/node@22.10.1)(happy-dom@15.11.7)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1))(vue-router@4.5.0(vue@3.5.13(typescript@5.6.3)))(vue@3.5.13(typescript@5.6.3)) transitivePeerDependencies: - '@cucumber/cucumber' - '@jest/globals' @@ -15352,7 +15352,7 @@ snapshots: - vue - vue-router - vitest@1.6.0(@types/node@22.10.0)(happy-dom@15.11.6)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1): + vitest@1.6.0(@types/node@22.10.1)(happy-dom@15.11.7)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1): dependencies: '@vitest/expect': 1.6.0 '@vitest/runner': 1.6.0 @@ -15371,12 +15371,12 @@ snapshots: strip-literal: 2.1.1 tinybench: 2.9.0 tinypool: 0.8.4 - vite: 6.0.1(@types/node@22.10.0)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1) - vite-node: 1.6.0(@types/node@22.10.0)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1) + vite: 6.0.1(@types/node@22.10.1)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1) + vite-node: 1.6.0(@types/node@22.10.1)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1) why-is-node-running: 2.3.0 optionalDependencies: - '@types/node': 22.10.0 - happy-dom: 15.11.6 + '@types/node': 22.10.1 + happy-dom: 15.11.7 transitivePeerDependencies: - jiti - less @@ -15390,10 +15390,10 @@ snapshots: - tsx - yaml - vitest@2.1.6(@types/node@22.10.0)(happy-dom@15.11.6)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1): + vitest@2.1.6(@types/node@22.10.1)(happy-dom@15.11.7)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1): dependencies: '@vitest/expect': 2.1.6 - '@vitest/mocker': 2.1.6(vite@6.0.1(@types/node@22.10.0)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1)) + '@vitest/mocker': 2.1.6(vite@6.0.1(@types/node@22.10.1)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1)) '@vitest/pretty-format': 2.1.6 '@vitest/runner': 2.1.6 '@vitest/snapshot': 2.1.6 @@ -15409,12 +15409,12 @@ snapshots: tinyexec: 0.3.1 tinypool: 1.0.1 tinyrainbow: 1.2.0 - vite: 6.0.1(@types/node@22.10.0)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1) - vite-node: 2.1.6(@types/node@22.10.0)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1) + vite: 6.0.1(@types/node@22.10.1)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1) + vite-node: 2.1.6(@types/node@22.10.1)(jiti@2.4.0)(sass@1.78.0)(terser@5.32.0)(tsx@4.19.1)(yaml@2.5.1) why-is-node-running: 2.3.0 optionalDependencies: - '@types/node': 22.10.0 - happy-dom: 15.11.6 + '@types/node': 22.10.1 + happy-dom: 15.11.7 transitivePeerDependencies: - jiti - less From 9e03a4120cc010d874b8b5c55360f475177229db Mon Sep 17 00:00:00 2001 From: Felix Gabler Date: Thu, 28 Nov 2024 10:39:46 +0100 Subject: [PATCH 08/11] fix(nuxt): allow array/object `style` value for head components (#29999) --- packages/nuxt/src/head/runtime/components.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/nuxt/src/head/runtime/components.ts b/packages/nuxt/src/head/runtime/components.ts index 5913471dde..c4bee3cae3 100644 --- a/packages/nuxt/src/head/runtime/components.ts +++ b/packages/nuxt/src/head/runtime/components.ts @@ -67,7 +67,7 @@ const globalProps = { type: Boolean, default: undefined, }, - style: String, + style: [String, Object, Array], tabindex: String, title: String, translate: String, From a60d7fd51c2c2bb77b7165eaff573dd6aa4499e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20=C4=8Cern=C3=BD?= <112722215+cernymatej@users.noreply.github.com> Date: Thu, 28 Nov 2024 11:00:58 +0100 Subject: [PATCH 09/11] docs: add a section about `event.waitUntil` (#29583) --- .../2.guide/2.directory-structure/1.server.md | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/docs/2.guide/2.directory-structure/1.server.md b/docs/2.guide/2.directory-structure/1.server.md index bb4dc8c8a2..3bd95a592c 100644 --- a/docs/2.guide/2.directory-structure/1.server.md +++ b/docs/2.guide/2.directory-structure/1.server.md @@ -363,6 +363,26 @@ Headers that are **not meant to be forwarded** will **not be included** in the r `transfer-encoding`, `connection`, `keep-alive`, `upgrade`, `expect`, `host`, `accept` :: +### Awaiting Promises After Response + +When handling server requests, you might need to perform asynchronous tasks that shouldn't block the response to the client (for example, caching and logging). You can use `event.waitUntil` to await a promise in the background without delaying the response. + +The `event.waitUntil` method accepts a promise that will be awaited before the handler terminates, ensuring the task is completed even if the server would otherwise terminate the handler right after the response is sent. This integrates with runtime providers to leverage their native capabilities for handling asynchronous operations after the response is sent. + +```ts [server/api/background-task.ts] +const timeConsumingBackgroundTask = async () => { + await new Promise((resolve) => setTimeout(resolve, 1000)) +}; + +export default eventHandler((event) => { + // schedule a background task without blocking the response + event.waitUntil(timeConsumingBackgroundTask()) + + // immediately send the response to the client + return 'done' +}); +``` + ## Advanced Usage ### Nitro Config From 3cb8b9fcb06dab358e787e904f82988e30341e58 Mon Sep 17 00:00:00 2001 From: Daniel Roe Date: Thu, 28 Nov 2024 16:34:02 +0000 Subject: [PATCH 10/11] refactor(nuxt): simplify and improve core plugins that parse ast (#30088) --- .../src/components/plugins/component-names.ts | 16 +- .../nuxt/src/components/plugins/tree-shake.ts | 197 +++++++++--------- packages/nuxt/src/core/nuxt.ts | 4 +- .../nuxt/src/core/plugins/composable-keys.ts | 67 +++--- .../nuxt/src/core/plugins/plugin-metadata.ts | 104 ++++----- packages/nuxt/src/core/plugins/prehydrate.ts | 56 ++--- packages/nuxt/src/core/utils/parse.ts | 33 +++ packages/nuxt/src/pages/module.ts | 2 +- packages/nuxt/src/pages/plugins/page-meta.ts | 63 +++--- packages/nuxt/src/pages/route-rules.ts | 40 ++-- packages/nuxt/src/pages/utils.ts | 127 ++++++----- packages/nuxt/test/component-names.test.ts | 50 +++++ packages/nuxt/test/composable-keys.test.ts | 57 ++++- packages/nuxt/test/page-metadata.test.ts | 71 +++++++ packages/nuxt/test/plugin-metadata.test.ts | 20 +- packages/nuxt/test/prehydrate.test.ts | 40 ++++ packages/nuxt/test/route-rules.test.ts | 56 +++++ packages/nuxt/test/treeshake-client.test.ts | 13 +- 18 files changed, 637 insertions(+), 379 deletions(-) create mode 100644 packages/nuxt/src/core/utils/parse.ts create mode 100644 packages/nuxt/test/component-names.test.ts create mode 100644 packages/nuxt/test/prehydrate.test.ts create mode 100644 packages/nuxt/test/route-rules.test.ts diff --git a/packages/nuxt/src/components/plugins/component-names.ts b/packages/nuxt/src/components/plugins/component-names.ts index 47fec70203..d7b6f10c7a 100644 --- a/packages/nuxt/src/components/plugins/component-names.ts +++ b/packages/nuxt/src/components/plugins/component-names.ts @@ -1,7 +1,8 @@ import { createUnplugin } from 'unplugin' import MagicString from 'magic-string' import type { Component } from 'nuxt/schema' -import type { Program } from 'acorn' +import { parseAndWalk, withLocations } from '../../core/utils/parse' + import { SX_RE, isVue } from '../../core/utils' interface NameDevPluginOptions { @@ -37,12 +38,15 @@ export const ComponentNamePlugin = (options: NameDevPluginOptions) => createUnpl // Without setup function, vue compiler does not generate __name if (!s.hasChanged()) { - const ast = this.parse(code) as Program - const exportDefault = ast.body.find(node => node.type === 'ExportDefaultDeclaration') - if (exportDefault) { - const { start, end } = exportDefault.declaration + parseAndWalk(code, id, function (node) { + if (node.type !== 'ExportDefaultDeclaration') { + return + } + + const { start, end } = withLocations(node.declaration) s.overwrite(start, end, `Object.assign(${code.slice(start, end)}, { __name: ${JSON.stringify(component.pascalName)} })`) - } + this.skip() + }) } if (s.hasChanged()) { diff --git a/packages/nuxt/src/components/plugins/tree-shake.ts b/packages/nuxt/src/components/plugins/tree-shake.ts index 2ebb669a03..d24b5f1c00 100644 --- a/packages/nuxt/src/components/plugins/tree-shake.ts +++ b/packages/nuxt/src/components/plugins/tree-shake.ts @@ -1,11 +1,14 @@ import { pathToFileURL } from 'node:url' import { parseURL } from 'ufo' import MagicString from 'magic-string' -import { walk } from 'estree-walker' -import type { AssignmentProperty, CallExpression, Identifier, Literal, MemberExpression, Node, ObjectExpression, Pattern, Program, Property, ReturnStatement, VariableDeclaration } from 'estree' +import type { AssignmentProperty, CallExpression, ObjectExpression, Pattern, Property, ReturnStatement, VariableDeclaration } from 'estree' +import type { Program } from 'acorn' import { createUnplugin } from 'unplugin' import type { Component } from '@nuxt/schema' import { resolve } from 'pathe' + +import { parseAndWalk, walk, withLocations } from '../../core/utils/parse' +import type { Node } from '../../core/utils/parse' import { distDir } from '../../dirs' interface TreeShakeTemplatePluginOptions { @@ -13,12 +16,9 @@ interface TreeShakeTemplatePluginOptions { getComponents (): Component[] } -type AcornNode = N & { start: number, end: number } - const SSR_RENDER_RE = /ssrRenderComponent/ const PLACEHOLDER_EXACT_RE = /^(?:fallback|placeholder)$/ const CLIENT_ONLY_NAME_RE = /^(?:_unref\()?(?:_component_)?(?:Lazy|lazy_)?(?:client_only|ClientOnly\)?)$/ -const PARSER_OPTIONS = { sourceType: 'module', ecmaVersion: 'latest' } export const TreeShakeTemplatePlugin = (options: TreeShakeTemplatePluginOptions) => createUnplugin(() => { const regexpMap = new WeakMap() @@ -29,7 +29,7 @@ export const TreeShakeTemplatePlugin = (options: TreeShakeTemplatePluginOptions) const { pathname } = parseURL(decodeURIComponent(pathToFileURL(id).href)) return pathname.endsWith('.vue') }, - transform (code) { + transform (code, id) { const components = options.getComponents() if (!regexpMap.has(components)) { @@ -47,62 +47,55 @@ export const TreeShakeTemplatePlugin = (options: TreeShakeTemplatePluginOptions) const [COMPONENTS_RE, COMPONENTS_IDENTIFIERS_RE] = regexpMap.get(components)! if (!COMPONENTS_RE.test(code)) { return } - const codeAst = this.parse(code, PARSER_OPTIONS) as AcornNode - const componentsToRemoveSet = new Set() // remove client only components or components called in ClientOnly default slot - walk(codeAst, { - enter: (_node) => { - const node = _node as AcornNode - if (isSsrRender(node)) { - const [componentCall, _, children] = node.arguments - if (!componentCall) { return } + const ast = parseAndWalk(code, id, (node) => { + if (!isSsrRender(node)) { + return + } - if (componentCall.type === 'Identifier' || componentCall.type === 'MemberExpression' || componentCall.type === 'CallExpression') { - const componentName = getComponentName(node) - const isClientComponent = COMPONENTS_IDENTIFIERS_RE.test(componentName) - const isClientOnlyComponent = CLIENT_ONLY_NAME_RE.test(componentName) + const [componentCall, _, children] = node.arguments + if (!componentCall) { return } - if (isClientComponent && children?.type === 'ObjectExpression') { - const slotsToRemove = isClientOnlyComponent ? children.properties.filter(prop => prop.type === 'Property' && prop.key.type === 'Identifier' && !PLACEHOLDER_EXACT_RE.test(prop.key.name)) as AcornNode[] : children.properties as AcornNode[] + if (componentCall.type === 'Identifier' || componentCall.type === 'MemberExpression' || componentCall.type === 'CallExpression') { + const componentName = getComponentName(node) + if (!componentName || !COMPONENTS_IDENTIFIERS_RE.test(componentName) || children?.type !== 'ObjectExpression') { return } - for (const slot of slotsToRemove) { - s.remove(slot.start, slot.end + 1) - const removedCode = `({${code.slice(slot.start, slot.end + 1)}})` - const currentCodeAst = this.parse(s.toString(), PARSER_OPTIONS) as Node + const isClientOnlyComponent = CLIENT_ONLY_NAME_RE.test(componentName) + const slotsToRemove = isClientOnlyComponent ? children.properties.filter(prop => prop.type === 'Property' && prop.key.type === 'Identifier' && !PLACEHOLDER_EXACT_RE.test(prop.key.name)) as Property[] : children.properties as Property[] - walk(this.parse(removedCode, PARSER_OPTIONS) as Node, { - enter: (_node) => { - const node = _node as AcornNode - if (isSsrRender(node)) { - const name = getComponentName(node) + for (const _slot of slotsToRemove) { + const slot = withLocations(_slot) + s.remove(slot.start, slot.end + 1) + const removedCode = `({${code.slice(slot.start, slot.end + 1)}})` + const currentState = s.toString() - // detect if the component is called else where - const nameToRemove = isComponentNotCalledInSetup(currentCodeAst, name) - if (nameToRemove) { - componentsToRemoveSet.add(nameToRemove) - } - } - }, - }) - } + parseAndWalk(removedCode, id, (node) => { + if (!isSsrRender(node)) { return } + const name = getComponentName(node) + if (!name) { return } + + // detect if the component is called else where + const nameToRemove = isComponentNotCalledInSetup(currentState, id, name) + if (nameToRemove) { + componentsToRemoveSet.add(nameToRemove) } - } + }) } - }, + } }) const componentsToRemove = [...componentsToRemoveSet] - const removedNodes = new WeakSet>() + const removedNodes = new WeakSet() for (const componentName of componentsToRemove) { // remove import declaration if it exists - removeImportDeclaration(codeAst, componentName, s) + removeImportDeclaration(ast, componentName, s) // remove variable declaration - removeVariableDeclarator(codeAst, componentName, s, removedNodes) + removeVariableDeclarator(ast, componentName, s, removedNodes) // remove from setup return statement - removeFromSetupReturn(codeAst, componentName, s) + removeFromSetupReturn(ast, componentName, s) } if (s.hasChanged()) { @@ -129,7 +122,7 @@ function removeFromSetupReturn (codeAst: Program, name: string, magicString: Mag } else if (node.type === 'Property' && node.key.type === 'Identifier' && node.key.name === 'setup' && (node.value.type === 'FunctionExpression' || node.value.type === 'ArrowFunctionExpression')) { // walk into the setup function walkedInSetup = true - if (node.value.body.type === 'BlockStatement') { + if (node.value.body?.type === 'BlockStatement') { const returnStatement = node.value.body.body.find(statement => statement.type === 'ReturnStatement') as ReturnStatement if (returnStatement && returnStatement.argument?.type === 'ObjectExpression') { // remove from return statement @@ -157,7 +150,8 @@ function removeFromSetupReturn (codeAst: Program, name: string, magicString: Mag function removePropertyFromObject (node: ObjectExpression, name: string, magicString: MagicString) { for (const property of node.properties) { if (property.type === 'Property' && property.key.type === 'Identifier' && property.key.name === name) { - magicString.remove((property as AcornNode).start, (property as AcornNode).end + 1) + const _property = withLocations(property) + magicString.remove(_property.start, _property.end + 1) return true } } @@ -167,26 +161,26 @@ function removePropertyFromObject (node: ObjectExpression, name: string, magicSt /** * is the node a call expression ssrRenderComponent() */ -function isSsrRender (node: Node): node is AcornNode { +function isSsrRender (node: Node): node is CallExpression { return node.type === 'CallExpression' && node.callee.type === 'Identifier' && SSR_RENDER_RE.test(node.callee.name) } function removeImportDeclaration (ast: Program, importName: string, magicString: MagicString): boolean { for (const node of ast.body) { - if (node.type === 'ImportDeclaration') { - const specifier = node.specifiers.find(s => s.local.name === importName) - if (specifier) { - if (node.specifiers.length > 1) { - const specifierIndex = node.specifiers.findIndex(s => s.local.name === importName) - if (specifierIndex > -1) { - magicString.remove((node.specifiers[specifierIndex] as AcornNode).start, (node.specifiers[specifierIndex] as AcornNode).end + 1) - node.specifiers.splice(specifierIndex, 1) - } - } else { - magicString.remove((node as AcornNode).start, (node as AcornNode).end) - } - return true + if (node.type !== 'ImportDeclaration' || !node.specifiers) { + continue + } + const specifierIndex = node.specifiers.findIndex(s => s.local.name === importName) + if (specifierIndex > -1) { + if (node.specifiers!.length > 1) { + const specifier = withLocations(node.specifiers![specifierIndex]) + magicString.remove(specifier.start, specifier.end + 1) + node.specifiers!.splice(specifierIndex, 1) + } else { + const specifier = withLocations(node) + magicString.remove(specifier.start, specifier.end) } + return true } } return false @@ -197,62 +191,61 @@ function removeImportDeclaration (ast: Program, importName: string, magicString: * ImportDeclarations and VariableDeclarations are ignored * return the name of the component if is not called */ -function isComponentNotCalledInSetup (codeAst: Node, name: string): string | void { - if (name) { - let found = false - walk(codeAst, { - enter (node) { - if ((node.type === 'Property' && node.key.type === 'Identifier' && node.value.type === 'FunctionExpression' && node.key.name === 'setup') || (node.type === 'FunctionDeclaration' && (node.id?.name === '_sfc_ssrRender' || node.id?.name === 'ssrRender'))) { - // walk through the setup function node or the ssrRender function - walk(node, { - enter (node) { - if (found || node.type === 'VariableDeclaration') { - this.skip() - } else if (node.type === 'Identifier' && node.name === name) { - found = true - } else if (node.type === 'MemberExpression') { - // dev only with $setup or _ctx - found = (node.property.type === 'Literal' && node.property.value === name) || (node.property.type === 'Identifier' && node.property.name === name) - } - }, - }) - } - }, - }) - if (!found) { return name } - } +function isComponentNotCalledInSetup (code: string, id: string, name: string): string | void { + if (!name) { return } + let found = false + parseAndWalk(code, id, function (node) { + if ((node.type === 'Property' && node.key.type === 'Identifier' && node.value.type === 'FunctionExpression' && node.key.name === 'setup') || (node.type === 'FunctionDeclaration' && (node.id?.name === '_sfc_ssrRender' || node.id?.name === 'ssrRender'))) { + // walk through the setup function node or the ssrRender function + walk(node, { + enter (node) { + if (found || node.type === 'VariableDeclaration') { + this.skip() + } else if (node.type === 'Identifier' && node.name === name) { + found = true + } else if (node.type === 'MemberExpression') { + // dev only with $setup or _ctx + found = (node.property.type === 'Literal' && node.property.value === name) || (node.property.type === 'Identifier' && node.property.name === name) + } + }, + }) + } + }) + if (!found) { return name } } /** * retrieve the component identifier being used on ssrRender callExpression * @param ssrRenderNode - ssrRender callExpression */ -function getComponentName (ssrRenderNode: AcornNode): string { - const componentCall = ssrRenderNode.arguments[0] as Identifier | MemberExpression | CallExpression +function getComponentName (ssrRenderNode: CallExpression): string | undefined { + const componentCall = ssrRenderNode.arguments[0] + if (!componentCall) { return } if (componentCall.type === 'Identifier') { return componentCall.name } else if (componentCall.type === 'MemberExpression') { - return (componentCall.property as Literal).value as string + if (componentCall.property.type === 'Literal') { + return componentCall.property.value as string + } + } else if (componentCall.type === 'CallExpression') { + return getComponentName(componentCall) } - return (componentCall.arguments[0] as Identifier).name } /** * remove a variable declaration within the code */ -function removeVariableDeclarator (codeAst: Node, name: string, magicString: MagicString, removedNodes: WeakSet): AcornNode | void { +function removeVariableDeclarator (codeAst: Program, name: string, magicString: MagicString, removedNodes: WeakSet): Node | void { // remove variables walk(codeAst, { enter (node) { - if (node.type === 'VariableDeclaration') { - for (const declarator of node.declarations) { - const toRemove = findMatchingPatternToRemove(declarator.id as AcornNode, node as AcornNode, name, removedNodes) - if (toRemove) { - magicString.remove(toRemove.start, toRemove.end + 1) - removedNodes.add(toRemove) - return toRemove - } + if (node.type !== 'VariableDeclaration') { return } + for (const declarator of node.declarations) { + const toRemove = withLocations(findMatchingPatternToRemove(declarator.id, node, name, removedNodes)) + if (toRemove) { + magicString.remove(toRemove.start, toRemove.end + 1) + removedNodes.add(toRemove) } } }, @@ -262,13 +255,13 @@ function removeVariableDeclarator (codeAst: Node, name: string, magicString: Mag /** * find the Pattern to remove which the identifier is equal to the name parameter. */ -function findMatchingPatternToRemove (node: AcornNode, toRemoveIfMatched: AcornNode, name: string, removedNodeSet: WeakSet): AcornNode | undefined { +function findMatchingPatternToRemove (node: Pattern, toRemoveIfMatched: Node, name: string, removedNodeSet: WeakSet): Node | undefined { if (node.type === 'Identifier') { if (node.name === name) { return toRemoveIfMatched } } else if (node.type === 'ArrayPattern') { - const elements = node.elements.filter((e): e is AcornNode => e !== null && !removedNodeSet.has(e)) + const elements = node.elements.filter((e): e is Pattern => e !== null && !removedNodeSet.has(e)) for (const element of elements) { const matched = findMatchingPatternToRemove(element, elements.length > 1 ? element : toRemoveIfMatched, name, removedNodeSet) @@ -278,12 +271,12 @@ function findMatchingPatternToRemove (node: AcornNode, toRemoveIfMatche const properties = node.properties.filter((e): e is AssignmentProperty => e.type === 'Property' && !removedNodeSet.has(e)) for (const [index, property] of properties.entries()) { - let nodeToRemove = property as AcornNode + let nodeToRemove: Node = property if (properties.length < 2) { nodeToRemove = toRemoveIfMatched } - const matched = findMatchingPatternToRemove(property.value as AcornNode, nodeToRemove as AcornNode, name, removedNodeSet) + const matched = findMatchingPatternToRemove(property.value, nodeToRemove, name, removedNodeSet) if (matched) { if (matched === property) { properties.splice(index, 1) @@ -292,7 +285,7 @@ function findMatchingPatternToRemove (node: AcornNode, toRemoveIfMatche } } } else if (node.type === 'AssignmentPattern') { - const matched = findMatchingPatternToRemove(node.left as AcornNode, toRemoveIfMatched, name, removedNodeSet) + const matched = findMatchingPatternToRemove(node.left, toRemoveIfMatched, name, removedNodeSet) if (matched) { return matched } } } diff --git a/packages/nuxt/src/core/nuxt.ts b/packages/nuxt/src/core/nuxt.ts index e2402adf68..12ad094adc 100644 --- a/packages/nuxt/src/core/nuxt.ts +++ b/packages/nuxt/src/core/nuxt.ts @@ -42,7 +42,7 @@ import { RemovePluginMetadataPlugin } from './plugins/plugin-metadata' import { AsyncContextInjectionPlugin } from './plugins/async-context' import { ComposableKeysPlugin } from './plugins/composable-keys' import { resolveDeepImportsPlugin } from './plugins/resolve-deep-imports' -import { prehydrateTransformPlugin } from './plugins/prehydrate' +import { PrehydrateTransformPlugin } from './plugins/prehydrate' import { VirtualFSPlugin } from './plugins/virtual' export function createNuxt (options: NuxtOptions): Nuxt { @@ -283,7 +283,7 @@ async function initNuxt (nuxt: Nuxt) { addVitePlugin(() => resolveDeepImportsPlugin(nuxt), { server: false }) // Add transform for `onPrehydrate` lifecycle hook - addBuildPlugin(prehydrateTransformPlugin(nuxt)) + addBuildPlugin(PrehydrateTransformPlugin({ sourcemap: !!nuxt.options.sourcemap.server || !!nuxt.options.sourcemap.client })) if (nuxt.options.experimental.localLayerAliases) { // Add layer aliasing support for ~, ~~, @ and @@ aliases diff --git a/packages/nuxt/src/core/plugins/composable-keys.ts b/packages/nuxt/src/core/plugins/composable-keys.ts index 01e11159fc..c9ddfc07a5 100644 --- a/packages/nuxt/src/core/plugins/composable-keys.ts +++ b/packages/nuxt/src/core/plugins/composable-keys.ts @@ -1,14 +1,14 @@ import { pathToFileURL } from 'node:url' import { createUnplugin } from 'unplugin' import { isAbsolute, relative } from 'pathe' -import type { Node } from 'estree-walker' -import { walk } from 'estree-walker' import MagicString from 'magic-string' import { hash } from 'ohash' -import type { CallExpression, Pattern } from 'estree' +import type { Pattern } from 'estree' import { parseQuery, parseURL } from 'ufo' import escapeRE from 'escape-string-regexp' import { findStaticImports, parseStaticImport } from 'mlly' +import { parseAndWalk, walk } from '../../core/utils/parse' + import { matchWithStringOrRegex } from '../utils/plugins' interface ComposableKeysOptions { @@ -52,23 +52,18 @@ export const ComposableKeysPlugin = (options: ComposableKeysOptions) => createUn const relativeID = isAbsolute(id) ? relative(options.rootDir, id) : id const { pathname: relativePathname } = parseURL(relativeID) - const ast = this.parse(script, { - sourceType: 'module', - ecmaVersion: 'latest', - }) as Node - // To handle variables hoisting we need a pre-pass to collect variable and function declarations with scope info. let scopeTracker = new ScopeTracker() const varCollector = new ScopedVarsCollector() - walk(ast, { - enter (_node) { - if (_node.type === 'BlockStatement') { + const ast = parseAndWalk(script, id, { + enter (node) { + if (node.type === 'BlockStatement') { scopeTracker.enterScope() varCollector.refresh(scopeTracker.curScopeKey) - } else if (_node.type === 'FunctionDeclaration' && _node.id) { - varCollector.addVar(_node.id.name) - } else if (_node.type === 'VariableDeclarator') { - varCollector.collect(_node.id) + } else if (node.type === 'FunctionDeclaration' && node.id) { + varCollector.addVar(node.id.name) + } else if (node.type === 'VariableDeclarator') { + varCollector.collect(node.id) } }, leave (_node) { @@ -81,13 +76,12 @@ export const ComposableKeysPlugin = (options: ComposableKeysOptions) => createUn scopeTracker = new ScopeTracker() walk(ast, { - enter (_node) { - if (_node.type === 'BlockStatement') { + enter (node) { + if (node.type === 'BlockStatement') { scopeTracker.enterScope() } - if (_node.type !== 'CallExpression' || (_node as CallExpression).callee.type !== 'Identifier') { return } - const node: CallExpression = _node as CallExpression - const name = 'name' in node.callee && node.callee.name + if (node.type !== 'CallExpression' || node.callee.type !== 'Identifier') { return } + const name = node.callee.name if (!name || !keyedFunctions.has(name) || node.arguments.length >= maxLength) { return } imports = imports || detectImportNames(script, composableMeta) @@ -219,24 +213,23 @@ class ScopedVarsCollector { return false } - collect (n: Pattern) { - const t = n.type - if (t === 'Identifier') { - this.addVar(n.name) - } else if (t === 'RestElement') { - this.collect(n.argument) - } else if (t === 'AssignmentPattern') { - this.collect(n.left) - } else if (t === 'ArrayPattern') { - n.elements.forEach(e => e && this.collect(e)) - } else if (t === 'ObjectPattern') { - n.properties.forEach((p) => { - if (p.type === 'RestElement') { - this.collect(p) - } else { - this.collect(p.value) + collect (pattern: Pattern) { + if (pattern.type === 'Identifier') { + this.addVar(pattern.name) + } else if (pattern.type === 'RestElement') { + this.collect(pattern.argument) + } else if (pattern.type === 'AssignmentPattern') { + this.collect(pattern.left) + } else if (pattern.type === 'ArrayPattern') { + for (const element of pattern.elements) { + if (element) { + this.collect(element.type === 'RestElement' ? element.argument : element) } - }) + } + } else if (pattern.type === 'ObjectPattern') { + for (const property of pattern.properties) { + this.collect(property.type === 'RestElement' ? property.argument : property.value) + } } } } diff --git a/packages/nuxt/src/core/plugins/plugin-metadata.ts b/packages/nuxt/src/core/plugins/plugin-metadata.ts index 9ee9d3e557..3b0b080ac4 100644 --- a/packages/nuxt/src/core/plugins/plugin-metadata.ts +++ b/packages/nuxt/src/core/plugins/plugin-metadata.ts @@ -1,8 +1,5 @@ -import type { CallExpression, Literal, Property, SpreadElement } from 'estree' -import type { Node } from 'estree-walker' -import { walk } from 'estree-walker' +import type { Literal, Property, SpreadElement } from 'estree' import { transform } from 'esbuild' -import { parse } from 'acorn' import { defu } from 'defu' import { findExports } from 'mlly' import type { Nuxt } from '@nuxt/schema' @@ -11,6 +8,8 @@ import MagicString from 'magic-string' import { normalize } from 'pathe' import { logger } from '@nuxt/kit' +import { parseAndWalk, withLocations } from '../../core/utils/parse' + import type { ObjectPlugin, PluginMeta } from '#app' const internalOrderMap = { @@ -47,36 +46,31 @@ export async function extractMetadata (code: string, loader = 'ts' as 'ts' | 'ts return metaCache[code] } const js = await transform(code, { loader }) - walk(parse(js.code, { - sourceType: 'module', - ecmaVersion: 'latest', - }) as Node, { - enter (_node) { - if (_node.type !== 'CallExpression' || (_node as CallExpression).callee.type !== 'Identifier') { return } - const node = _node as CallExpression & { start: number, end: number } - const name = 'name' in node.callee && node.callee.name - if (name !== 'defineNuxtPlugin' && name !== 'definePayloadPlugin') { return } + parseAndWalk(js.code, `file.${loader}`, (node) => { + if (node.type !== 'CallExpression' || node.callee.type !== 'Identifier') { return } - if (name === 'definePayloadPlugin') { - meta.order = internalOrderMap['user-revivers'] + const name = 'name' in node.callee && node.callee.name + if (name !== 'defineNuxtPlugin' && name !== 'definePayloadPlugin') { return } + + if (name === 'definePayloadPlugin') { + meta.order = internalOrderMap['user-revivers'] + } + + const metaArg = node.arguments[1] + if (metaArg) { + if (metaArg.type !== 'ObjectExpression') { + throw new Error('Invalid plugin metadata') } + meta = extractMetaFromObject(metaArg.properties) + } - const metaArg = node.arguments[1] - if (metaArg) { - if (metaArg.type !== 'ObjectExpression') { - throw new Error('Invalid plugin metadata') - } - meta = extractMetaFromObject(metaArg.properties) - } + const plugin = node.arguments[0] + if (plugin?.type === 'ObjectExpression') { + meta = defu(extractMetaFromObject(plugin.properties), meta) + } - const plugin = node.arguments[0] - if (plugin?.type === 'ObjectExpression') { - meta = defu(extractMetaFromObject(plugin.properties), meta) - } - - meta.order = meta.order || orderMap[meta.enforce || 'default'] || orderMap.default - delete meta.enforce - }, + meta.order = meta.order || orderMap[meta.enforce || 'default'] || orderMap.default + delete meta.enforce }) metaCache[code] = meta return meta as Omit @@ -149,41 +143,33 @@ export const RemovePluginMetadataPlugin = (nuxt: Nuxt) => createUnplugin(() => { const wrapperNames = new Set(['defineNuxtPlugin', 'definePayloadPlugin']) try { - walk(this.parse(code, { - sourceType: 'module', - ecmaVersion: 'latest', - }) as Node, { - enter (_node) { - if (_node.type === 'ImportSpecifier' && _node.imported.type === 'Identifier' && (_node.imported.name === 'defineNuxtPlugin' || _node.imported.name === 'definePayloadPlugin')) { - wrapperNames.add(_node.local.name) - } - if (_node.type !== 'CallExpression' || (_node as CallExpression).callee.type !== 'Identifier') { return } - const node = _node as CallExpression & { start: number, end: number } - const name = 'name' in node.callee && node.callee.name - if (!name || !wrapperNames.has(name)) { return } - wrapped = true + parseAndWalk(code, id, (node) => { + if (node.type === 'ImportSpecifier' && node.imported.type === 'Identifier' && (node.imported.name === 'defineNuxtPlugin' || node.imported.name === 'definePayloadPlugin')) { + wrapperNames.add(node.local.name) + } + if (node.type !== 'CallExpression' || node.callee.type !== 'Identifier') { return } - // Remove metadata that already has been extracted - if (!('order' in plugin) && !('name' in plugin)) { return } - for (const [argIndex, _arg] of node.arguments.entries()) { - if (_arg.type !== 'ObjectExpression') { continue } + const name = 'name' in node.callee && node.callee.name + if (!name || !wrapperNames.has(name)) { return } + wrapped = true - const arg = _arg as typeof _arg & { start: number, end: number } - for (const [propertyIndex, _property] of arg.properties.entries()) { - if (_property.type === 'SpreadElement' || !('name' in _property.key)) { continue } + // Remove metadata that already has been extracted + if (!('order' in plugin) && !('name' in plugin)) { return } + for (const [argIndex, arg] of node.arguments.entries()) { + if (arg.type !== 'ObjectExpression') { continue } - const property = _property as typeof _property & { start: number, end: number } - const propertyKey = _property.key.name - if (propertyKey === 'order' || propertyKey === 'enforce' || propertyKey === 'name') { - const _nextNode = arg.properties[propertyIndex + 1] || node.arguments[argIndex + 1] - const nextNode = _nextNode as typeof _nextNode & { start: number, end: number } - const nextIndex = nextNode?.start || (arg.end - 1) + for (const [propertyIndex, property] of arg.properties.entries()) { + if (property.type === 'SpreadElement' || !('name' in property.key)) { continue } - s.remove(property.start, nextIndex) - } + const propertyKey = property.key.name + if (propertyKey === 'order' || propertyKey === 'enforce' || propertyKey === 'name') { + const nextNode = arg.properties[propertyIndex + 1] || node.arguments[argIndex + 1] + const nextIndex = withLocations(nextNode)?.start || (withLocations(arg).end - 1) + + s.remove(withLocations(property).start, nextIndex) } } - }, + } }) } catch (e) { logger.error(e) diff --git a/packages/nuxt/src/core/plugins/prehydrate.ts b/packages/nuxt/src/core/plugins/prehydrate.ts index c91e3cb5f7..ce3a8a6e2a 100644 --- a/packages/nuxt/src/core/plugins/prehydrate.ts +++ b/packages/nuxt/src/core/plugins/prehydrate.ts @@ -1,16 +1,12 @@ import { transform } from 'esbuild' -import { parse } from 'acorn' -import { walk } from 'estree-walker' -import type { Node } from 'estree-walker' -import type { Nuxt } from '@nuxt/schema' import { createUnplugin } from 'unplugin' -import type { SimpleCallExpression } from 'estree' import MagicString from 'magic-string' - import { hash } from 'ohash' + +import { parseAndWalk, withLocations } from '../../core/utils/parse' import { isJS, isVue } from '../utils' -export function prehydrateTransformPlugin (nuxt: Nuxt) { +export function PrehydrateTransformPlugin (options: { sourcemap?: boolean } = {}) { return createUnplugin(() => ({ name: 'nuxt:prehydrate-transform', transformInclude (id) { @@ -22,33 +18,27 @@ export function prehydrateTransformPlugin (nuxt: Nuxt) { const s = new MagicString(code) const promises: Array> = [] - walk(parse(code, { - sourceType: 'module', - ecmaVersion: 'latest', - ranges: true, - }) as Node, { - enter (_node) { - if (_node.type !== 'CallExpression' || _node.callee.type !== 'Identifier') { return } - const node = _node as SimpleCallExpression & { start: number, end: number } - const name = 'name' in node.callee && node.callee.name - if (name === 'onPrehydrate') { - if (!node.arguments[0]) { return } - if (node.arguments[0].type !== 'ArrowFunctionExpression' && node.arguments[0].type !== 'FunctionExpression') { return } + parseAndWalk(code, id, (node) => { + if (node.type !== 'CallExpression' || node.callee.type !== 'Identifier') { + return + } + if (node.callee.name === 'onPrehydrate') { + const callback = withLocations(node.arguments[0]) + if (!callback) { return } + if (callback.type !== 'ArrowFunctionExpression' && callback.type !== 'FunctionExpression') { return } - const needsAttr = node.arguments[0].params.length > 0 - const { start, end } = node.arguments[0] as Node & { start: number, end: number } + const needsAttr = callback.params.length > 0 - const p = transform(`forEach(${code.slice(start, end)})`, { loader: 'ts', minify: true }) - promises.push(p.then(({ code: result }) => { - const cleaned = result.slice('forEach'.length).replace(/;\s+$/, '') - const args = [JSON.stringify(cleaned)] - if (needsAttr) { - args.push(JSON.stringify(hash(result))) - } - s.overwrite(start, end, args.join(', ')) - })) - } - }, + const p = transform(`forEach(${code.slice(callback.start, callback.end)})`, { loader: 'ts', minify: true }) + promises.push(p.then(({ code: result }) => { + const cleaned = result.slice('forEach'.length).replace(/;\s+$/, '') + const args = [JSON.stringify(cleaned)] + if (needsAttr) { + args.push(JSON.stringify(hash(result))) + } + s.overwrite(callback.start, callback.end, args.join(', ')) + })) + } }) await Promise.all(promises).catch((e) => { @@ -58,7 +48,7 @@ export function prehydrateTransformPlugin (nuxt: Nuxt) { if (s.hasChanged()) { return { code: s.toString(), - map: nuxt.options.sourcemap.server || nuxt.options.sourcemap.client + map: options.sourcemap ? s.generateMap({ hires: true }) : undefined, } diff --git a/packages/nuxt/src/core/utils/parse.ts b/packages/nuxt/src/core/utils/parse.ts new file mode 100644 index 0000000000..34f7af6d79 --- /dev/null +++ b/packages/nuxt/src/core/utils/parse.ts @@ -0,0 +1,33 @@ +import { walk as _walk } from 'estree-walker' +import type { Node, SyncHandler } from 'estree-walker' +import type { Program as ESTreeProgram } from 'estree' +import { parse } from 'acorn' +import type { Program } from 'acorn' + +export type { Node } + +type WithLocations = T & { start: number, end: number } +type WalkerCallback = (this: ThisParameterType, node: WithLocations, parent: WithLocations | null, ctx: { key: string | number | symbol | null | undefined, index: number | null | undefined, ast: Program | Node }) => void + +export function walk (ast: Program | Node, callback: { enter?: WalkerCallback, leave?: WalkerCallback }) { + return _walk(ast as unknown as ESTreeProgram | Node, { + enter (node, parent, key, index) { + callback.enter?.call(this, node as WithLocations, parent as WithLocations | null, { key, index, ast }) + }, + leave (node, parent, key, index) { + callback.leave?.call(this, node as WithLocations, parent as WithLocations | null, { key, index, ast }) + }, + }) as Program | Node | null +} + +export function parseAndWalk (code: string, sourceFilename: string, callback: WalkerCallback): Program +export function parseAndWalk (code: string, sourceFilename: string, object: { enter?: WalkerCallback, leave?: WalkerCallback }): Program +export function parseAndWalk (code: string, _sourceFilename: string, callback: { enter?: WalkerCallback, leave?: WalkerCallback } | WalkerCallback) { + const ast = parse (code, { sourceType: 'module', ecmaVersion: 'latest', locations: true }) + walk(ast, typeof callback === 'function' ? { enter: callback } : callback) + return ast +} + +export function withLocations (node: T): WithLocations { + return node as WithLocations +} diff --git a/packages/nuxt/src/pages/module.ts b/packages/nuxt/src/pages/module.ts index 050d1c659d..44cda863c3 100644 --- a/packages/nuxt/src/pages/module.ts +++ b/packages/nuxt/src/pages/module.ts @@ -379,7 +379,7 @@ export default defineNuxtModule({ const glob = pageToGlobMap[path] const code = path in nuxt.vfs ? nuxt.vfs[path]! : await readFile(path!, 'utf-8') try { - const extractedRule = await extractRouteRules(code) + const extractedRule = await extractRouteRules(code, path) if (extractedRule) { if (!glob) { const relativePath = relative(nuxt.options.srcDir, path) diff --git a/packages/nuxt/src/pages/plugins/page-meta.ts b/packages/nuxt/src/pages/plugins/page-meta.ts index 76ae4dc59f..fec8bbb54b 100644 --- a/packages/nuxt/src/pages/plugins/page-meta.ts +++ b/packages/nuxt/src/pages/plugins/page-meta.ts @@ -3,13 +3,13 @@ import { createUnplugin } from 'unplugin' import { parseQuery, parseURL } from 'ufo' import type { StaticImport } from 'mlly' import { findExports, findStaticImports, parseStaticImport } from 'mlly' -import type { CallExpression, Expression, Identifier } from 'estree' -import type { Node } from 'estree-walker' import { walk } from 'estree-walker' import MagicString from 'magic-string' import { isAbsolute } from 'pathe' import { logger } from '@nuxt/kit' +import { parseAndWalk, withLocations } from '../../core/utils/parse' + interface PageMetaPluginOptions { dev?: boolean sourcemap?: boolean @@ -36,7 +36,7 @@ if (import.meta.webpackHot) { }) }` -export const PageMetaPlugin = (options: PageMetaPluginOptions) => createUnplugin(() => { +export const PageMetaPlugin = (options: PageMetaPluginOptions = {}) => createUnplugin(() => { return { name: 'nuxt:pages-macros-transform', enforce: 'post', @@ -112,45 +112,38 @@ export const PageMetaPlugin = (options: PageMetaPluginOptions) => createUnplugin } } - walk(this.parse(code, { - sourceType: 'module', - ecmaVersion: 'latest', - }) as Node, { - enter (_node) { - if (_node.type !== 'CallExpression' || (_node as CallExpression).callee.type !== 'Identifier') { return } - const node = _node as CallExpression & { start: number, end: number } - const name = 'name' in node.callee && node.callee.name - if (name !== 'definePageMeta') { return } + parseAndWalk(code, id, (node) => { + if (node.type !== 'CallExpression' || node.callee.type !== 'Identifier') { return } + if (!('name' in node.callee) || node.callee.name !== 'definePageMeta') { return } - const meta = node.arguments[0] as Expression & { start: number, end: number } + const meta = withLocations(node.arguments[0]) - let contents = `const __nuxt_page_meta = ${code!.slice(meta.start, meta.end) || 'null'}\nexport default __nuxt_page_meta` + (options.dev ? CODE_HMR : '') + if (!meta) { return } - function addImport (name: string | false) { - if (name && importMap.has(name)) { - const importValue = importMap.get(name)!.code - if (!addedImports.has(importValue)) { - contents = importMap.get(name)!.code + '\n' + contents - addedImports.add(importValue) - } + let contents = `const __nuxt_page_meta = ${code!.slice(meta.start, meta.end) || 'null'}\nexport default __nuxt_page_meta` + (options.dev ? CODE_HMR : '') + + function addImport (name: string | false) { + if (name && importMap.has(name)) { + const importValue = importMap.get(name)!.code + if (!addedImports.has(importValue)) { + contents = importMap.get(name)!.code + '\n' + contents + addedImports.add(importValue) } } + } - walk(meta, { - enter (_node) { - if (_node.type === 'CallExpression') { - const node = _node as CallExpression & { start: number, end: number } - addImport('name' in node.callee && node.callee.name) - } - if (_node.type === 'Identifier') { - const node = _node as Identifier & { start: number, end: number } - addImport(node.name) - } - }, - }) + walk(meta, { + enter (node) { + if (node.type === 'CallExpression' && 'name' in node.callee) { + addImport(node.callee.name) + } + if (node.type === 'Identifier') { + addImport(node.name) + } + }, + }) - s.overwrite(0, code.length, contents) - }, + s.overwrite(0, code.length, contents) }) if (!s.hasChanged() && !code.includes('__nuxt_page_meta')) { diff --git a/packages/nuxt/src/pages/route-rules.ts b/packages/nuxt/src/pages/route-rules.ts index 1b76a75b52..c9317176b2 100644 --- a/packages/nuxt/src/pages/route-rules.ts +++ b/packages/nuxt/src/pages/route-rules.ts @@ -1,48 +1,44 @@ import { runInNewContext } from 'node:vm' -import type { Node } from 'estree-walker' -import type { CallExpression } from 'estree' -import { walk } from 'estree-walker' import { transform } from 'esbuild' -import { parse } from 'acorn' import type { NuxtPage } from '@nuxt/schema' import type { NitroRouteConfig } from 'nitro/types' import { normalize } from 'pathe' + +import { getLoader } from '../core/utils' +import { parseAndWalk } from '../core/utils/parse' import { extractScriptContent, pathToNitroGlob } from './utils' const ROUTE_RULE_RE = /\bdefineRouteRules\(/ const ruleCache: Record = {} -export async function extractRouteRules (code: string): Promise { +export async function extractRouteRules (code: string, path: string): Promise { if (code in ruleCache) { return ruleCache[code] || null } if (!ROUTE_RULE_RE.test(code)) { return null } let rule: NitroRouteConfig | null = null - const contents = extractScriptContent(code) + const loader = getLoader(path) + if (!loader) { return null } + + const contents = loader === 'vue' ? extractScriptContent(code) : [{ code, loader }] for (const script of contents) { if (rule) { break } code = script?.code || code const js = await transform(code, { loader: script?.loader || 'ts' }) - walk(parse(js.code, { - sourceType: 'module', - ecmaVersion: 'latest', - }) as Node, { - enter (_node) { - if (_node.type !== 'CallExpression' || (_node as CallExpression).callee.type !== 'Identifier') { return } - const node = _node as CallExpression & { start: number, end: number } - const name = 'name' in node.callee && node.callee.name - if (name === 'defineRouteRules') { - const rulesString = js.code.slice(node.start, node.end) - try { - rule = JSON.parse(runInNewContext(rulesString.replace('defineRouteRules', 'JSON.stringify'), {})) - } catch { - throw new Error('[nuxt] Error parsing route rules. They should be JSON-serializable.') - } + + parseAndWalk(js.code, 'file.' + (script?.loader || 'ts'), (node) => { + if (node.type !== 'CallExpression' || node.callee.type !== 'Identifier') { return } + if (node.callee.name === 'defineRouteRules') { + const rulesString = js.code.slice(node.start, node.end) + try { + rule = JSON.parse(runInNewContext(rulesString.replace('defineRouteRules', 'JSON.stringify'), {})) + } catch { + throw new Error('[nuxt] Error parsing route rules. They should be JSON-serializable.') } - }, + } }) } diff --git a/packages/nuxt/src/pages/utils.ts b/packages/nuxt/src/pages/utils.ts index 0b68904979..bd27eb1e97 100644 --- a/packages/nuxt/src/pages/utils.ts +++ b/packages/nuxt/src/pages/utils.ts @@ -8,11 +8,10 @@ import escapeRE from 'escape-string-regexp' import { filename } from 'pathe/utils' import { hash } from 'ohash' import { transform } from 'esbuild' -import { parse } from 'acorn' -import { walk } from 'estree-walker' -import type { CallExpression, ExpressionStatement, ObjectExpression, Program, Property } from 'estree' +import type { Property } from 'estree' import type { NuxtPage } from 'nuxt/schema' +import { parseAndWalk } from '../core/utils/parse' import { getLoader, uniqueBy } from '../core/utils' import { toArray } from '../utils' @@ -184,9 +183,9 @@ export async function augmentPages (routes: NuxtPage[], vfs: Record[^>]*)>(?[\s\S]*?)<\/script[^>]*>/gi -export function extractScriptContent (html: string) { +export function extractScriptContent (sfc: string) { const contents: Array<{ loader: 'tsx' | 'ts', code: string }> = [] - for (const match of html.matchAll(SFC_SCRIPT_RE)) { + for (const match of sfc.matchAll(SFC_SCRIPT_RE)) { if (match?.groups?.content) { contents.push({ loader: match.groups.attrs?.includes('tsx') ? 'tsx' : 'ts', @@ -222,7 +221,7 @@ export async function getRouteMeta (contents: string, absolutePath: string, extr return {} } - const extractedMeta = {} as Partial> + const extractedMeta: Partial> = {} const extractionKeys = new Set([...defaultExtractionKeys, ...extraExtractionKeys as Array]) @@ -232,85 +231,79 @@ export async function getRouteMeta (contents: string, absolutePath: string, extr } const js = await transform(script.code, { loader: script.loader }) - const ast = parse(js.code, { - sourceType: 'module', - ecmaVersion: 'latest', - ranges: true, - }) as unknown as Program const dynamicProperties = new Set() let foundMeta = false - walk(ast, { - enter (node) { - if (foundMeta) { return } + parseAndWalk(js.code, absolutePath.replace(/\.\w+$/, '.' + script.loader), (node) => { + if (foundMeta) { return } - if (node.type !== 'ExpressionStatement' || node.expression.type !== 'CallExpression' || node.expression.callee.type !== 'Identifier' || node.expression.callee.name !== 'definePageMeta') { return } + if (node.type !== 'ExpressionStatement' || node.expression.type !== 'CallExpression' || node.expression.callee.type !== 'Identifier' || node.expression.callee.name !== 'definePageMeta') { return } - foundMeta = true - const pageMetaArgument = ((node as ExpressionStatement).expression as CallExpression).arguments[0] as ObjectExpression + foundMeta = true + const pageMetaArgument = node.expression.arguments[0] + if (pageMetaArgument?.type !== 'ObjectExpression') { return } - for (const key of extractionKeys) { - const property = pageMetaArgument.properties.find(property => property.type === 'Property' && property.key.type === 'Identifier' && property.key.name === key) as Property - if (!property) { continue } + for (const key of extractionKeys) { + const property = pageMetaArgument.properties.find((property): property is Property => property.type === 'Property' && property.key.type === 'Identifier' && property.key.name === key) + if (!property) { continue } - if (property.value.type === 'ObjectExpression') { - const valueString = js.code.slice(property.value.range![0], property.value.range![1]) - try { - extractedMeta[key] = JSON.parse(runInNewContext(`JSON.stringify(${valueString})`, {})) - } catch { - console.debug(`[nuxt] Skipping extraction of \`${key}\` metadata as it is not JSON-serializable (reading \`${absolutePath}\`).`) - dynamicProperties.add(key) - continue - } - } - - if (property.value.type === 'ArrayExpression') { - const values: string[] = [] - for (const element of property.value.elements) { - if (!element) { - continue - } - if (element.type !== 'Literal' || typeof element.value !== 'string') { - console.debug(`[nuxt] Skipping extraction of \`${key}\` metadata as it is not an array of string literals (reading \`${absolutePath}\`).`) - dynamicProperties.add(key) - continue - } - values.push(element.value) - } - extractedMeta[key] = values - continue - } - - if (property.value.type !== 'Literal' || (typeof property.value.value !== 'string' && typeof property.value.value !== 'boolean')) { - console.debug(`[nuxt] Skipping extraction of \`${key}\` metadata as it is not a string literal or array of string literals (reading \`${absolutePath}\`).`) + if (property.value.type === 'ObjectExpression') { + const valueString = js.code.slice(property.value.range![0], property.value.range![1]) + try { + extractedMeta[key] = JSON.parse(runInNewContext(`JSON.stringify(${valueString})`, {})) + } catch { + console.debug(`[nuxt] Skipping extraction of \`${key}\` metadata as it is not JSON-serializable (reading \`${absolutePath}\`).`) dynamicProperties.add(key) continue } - extractedMeta[key] = property.value.value } - for (const property of pageMetaArgument.properties) { - if (property.type !== 'Property') { - continue - } - const isIdentifierOrLiteral = property.key.type === 'Literal' || property.key.type === 'Identifier' - if (!isIdentifierOrLiteral) { - continue - } - const name = property.key.type === 'Identifier' ? property.key.name : String(property.value) - if (!extractionKeys.has(name as keyof NuxtPage)) { - dynamicProperties.add('meta') - break + if (property.value.type === 'ArrayExpression') { + const values: string[] = [] + for (const element of property.value.elements) { + if (!element) { + continue + } + if (element.type !== 'Literal' || typeof element.value !== 'string') { + console.debug(`[nuxt] Skipping extraction of \`${key}\` metadata as it is not an array of string literals (reading \`${absolutePath}\`).`) + dynamicProperties.add(key) + continue + } + values.push(element.value) } + extractedMeta[key] = values + continue } - if (dynamicProperties.size) { - extractedMeta.meta ??= {} - extractedMeta.meta[DYNAMIC_META_KEY] = dynamicProperties + if (property.value.type !== 'Literal' || (typeof property.value.value !== 'string' && typeof property.value.value !== 'boolean')) { + console.debug(`[nuxt] Skipping extraction of \`${key}\` metadata as it is not a string literal or array of string literals (reading \`${absolutePath}\`).`) + dynamicProperties.add(key) + continue } - }, + extractedMeta[key] = property.value.value + } + + for (const property of pageMetaArgument.properties) { + if (property.type !== 'Property') { + continue + } + const isIdentifierOrLiteral = property.key.type === 'Literal' || property.key.type === 'Identifier' + if (!isIdentifierOrLiteral) { + continue + } + const name = property.key.type === 'Identifier' ? property.key.name : String(property.value) + if (!extractionKeys.has(name as keyof NuxtPage)) { + dynamicProperties.add('meta') + break + } + } + + if (dynamicProperties.size) { + extractedMeta.meta ??= {} + extractedMeta.meta[DYNAMIC_META_KEY] = dynamicProperties + } }) } diff --git a/packages/nuxt/test/component-names.test.ts b/packages/nuxt/test/component-names.test.ts new file mode 100644 index 0000000000..fdb585e614 --- /dev/null +++ b/packages/nuxt/test/component-names.test.ts @@ -0,0 +1,50 @@ +import { describe, expect, it } from 'vitest' +import type { Component } from '@nuxt/schema' +import { compileScript, parse } from '@vue/compiler-sfc' +import * as Parser from 'acorn' + +import { ComponentNamePlugin } from '../src/components/plugins/component-names' + +describe('component names', () => { + const components = [{ + filePath: 'test.ts', + pascalName: 'TestMe', + }] as [Component] + + const transformPlugin = ComponentNamePlugin({ sourcemap: false, getComponents: () => components }).raw({}, {} as any) as { transform: (code: string, id: string) => { code: string } | null } + + it('should add correct default component names', () => { + const sfc = ` + + ` + const res = compileScript(parse(sfc).descriptor, { id: 'test.vue' }) + const { code } = transformPlugin.transform.call({ + parse: (code: string, opts: any = {}) => Parser.parse(code, { + sourceType: 'module', + ecmaVersion: 'latest', + locations: true, + ...opts, + }), + }, res.content, components[0].filePath) ?? {} + expect(code?.trim()).toMatchInlineSnapshot(` + "export default Object.assign({ + setup(__props, { expose: __expose }) { + __expose(); + + onMounted(() => { + window.a = 32 + }) + + const __returned__ = { } + Object.defineProperty(__returned__, '__isScriptSetup', { enumerable: false, value: true }) + return __returned__ + } + + }, { __name: "TestMe" })" + `) + }) +}) diff --git a/packages/nuxt/test/composable-keys.test.ts b/packages/nuxt/test/composable-keys.test.ts index e5733d3cc0..38893a0bab 100644 --- a/packages/nuxt/test/composable-keys.test.ts +++ b/packages/nuxt/test/composable-keys.test.ts @@ -1,6 +1,7 @@ import { describe, expect, it } from 'vitest' +import * as Parser from 'acorn' -import { detectImportNames } from '../src/core/plugins/composable-keys' +import { ComposableKeysPlugin, detectImportNames } from '../src/core/plugins/composable-keys' describe('detectImportNames', () => { const keyedComposables = { @@ -25,3 +26,57 @@ describe('detectImportNames', () => { `) }) }) + +describe('composable keys plugin', () => { + const composables = [{ + name: 'useAsyncData', + source: '#app', + argumentLength: 2, + }] + const transformPlugin = ComposableKeysPlugin({ sourcemap: false, rootDir: '/', composables }).raw({}, {} as any) as { transform: (code: string, id: string) => { code: string } | null } + + it('should add keyed hash when there is none already provided', () => { + const code = ` +import { useAsyncData } from '#app' +useAsyncData(() => {}) + ` + expect(transformPlugin.transform.call({ + parse: (code: string, opts: any = {}) => Parser.parse(code, { + sourceType: 'module', + ecmaVersion: 'latest', + locations: true, + ...opts, + }), + }, code, 'plugin.ts')?.code.trim()).toMatchInlineSnapshot(` + "import { useAsyncData } from '#app' + useAsyncData(() => {}, '$yXewDLZblH')" + `) + }) + + it('should not add hash when one exists', () => { + const code = `useAsyncData(() => {}, 'foo')` + expect(transformPlugin.transform.call({ + parse: (code: string, opts: any = {}) => Parser.parse(code, { + sourceType: 'module', + ecmaVersion: 'latest', + locations: true, + ...opts, + }), + }, code, 'plugin.ts')?.code.trim()).toMatchInlineSnapshot(`undefined`) + }) + + it('should not add hash composables is imported from somewhere else', () => { + const code = ` +const useAsyncData = () => {} +useAsyncData(() => {}) + ` + expect(transformPlugin.transform.call({ + parse: (code: string, opts: any = {}) => Parser.parse(code, { + sourceType: 'module', + ecmaVersion: 'latest', + locations: true, + ...opts, + }), + }, code, 'plugin.ts')?.code.trim()).toMatchInlineSnapshot(`undefined`) + }) +}) diff --git a/packages/nuxt/test/page-metadata.test.ts b/packages/nuxt/test/page-metadata.test.ts index cdd299c415..62b8bfe580 100644 --- a/packages/nuxt/test/page-metadata.test.ts +++ b/packages/nuxt/test/page-metadata.test.ts @@ -1,4 +1,8 @@ import { describe, expect, it } from 'vitest' +import { compileScript, parse } from '@vue/compiler-sfc' +import * as Parser from 'acorn' + +import { PageMetaPlugin } from '../src/pages/plugins/page-meta' import { getRouteMeta, normalizeRoutes } from '../src/pages/utils' import type { NuxtPage } from '../schema' @@ -20,6 +24,43 @@ describe('page metadata', () => { } }) + it('should parse JSX files', async () => { + const fileContents = ` +export default { + setup () { + definePageMeta({ name: 'bar' }) + return () =>
+ } +} + ` + const meta = await getRouteMeta(fileContents, `/app/pages/index.jsx`) + expect(meta).toStrictEqual({ + name: 'bar', + }) + }) + + // TODO: https://github.com/nuxt/nuxt/pull/30066 + it.todo('should handle experimental decorators', async () => { + const fileContents = ` + + ` + const meta = await getRouteMeta(fileContents, `/app/pages/index.vue`) + expect(meta).toStrictEqual({ + name: 'bar', + }) + }) + it('should use and invalidate cache', async () => { const fileContents = `` const meta = await getRouteMeta(fileContents, filePath) @@ -240,3 +281,33 @@ describe('normalizeRoutes', () => { `) }) }) + +describe('rewrite page meta', () => { + const transformPlugin = PageMetaPlugin().raw({}, {} as any) as { transform: (code: string, id: string) => { code: string } | null } + + it('should extract metadata from vue components', () => { + const sfc = ` + + ` + const res = compileScript(parse(sfc).descriptor, { id: 'component.vue' }) + expect(transformPlugin.transform.call({ + parse: (code: string, opts: any = {}) => Parser.parse(code, { + sourceType: 'module', + ecmaVersion: 'latest', + locations: true, + ...opts, + }), + }, res.content, 'component.vue?macro=true')?.code).toMatchInlineSnapshot(` + "const __nuxt_page_meta = { + name: 'hi', + other: 'value' + } + export default __nuxt_page_meta" + `) + }) +}) diff --git a/packages/nuxt/test/plugin-metadata.test.ts b/packages/nuxt/test/plugin-metadata.test.ts index f11f3713ed..a53c287eb2 100644 --- a/packages/nuxt/test/plugin-metadata.test.ts +++ b/packages/nuxt/test/plugin-metadata.test.ts @@ -1,5 +1,5 @@ import { describe, expect, it, vi } from 'vitest' -import { parse } from 'acorn' +import * as Parser from 'acorn' import { RemovePluginMetadataPlugin, extractMetadata } from '../src/core/plugins/plugin-metadata' import { checkForCircularDependencies } from '../src/core/app' @@ -40,7 +40,14 @@ describe('plugin-metadata', () => { 'export const plugin = {}', ] for (const plugin of invalidPlugins) { - expect(transformPlugin.transform.call({ parse }, plugin, 'my-plugin.mjs').code).toBe('export default () => {}') + expect(transformPlugin.transform.call({ + parse: (code: string, opts: any = {}) => Parser.parse(code, { + sourceType: 'module', + ecmaVersion: 'latest', + locations: true, + ...opts, + }), + }, plugin, 'my-plugin.mjs').code).toBe('export default () => {}') } }) @@ -52,7 +59,14 @@ describe('plugin-metadata', () => { setup: () => {}, }, { order: 10, name: test }) ` - expect(transformPlugin.transform.call({ parse }, plugin, 'my-plugin.mjs').code).toMatchInlineSnapshot(` + expect(transformPlugin.transform.call({ + parse: (code: string, opts: any = {}) => Parser.parse(code, { + sourceType: 'module', + ecmaVersion: 'latest', + locations: true, + ...opts, + }), + }, plugin, 'my-plugin.mjs').code).toMatchInlineSnapshot(` " export default defineNuxtPlugin({ setup: () => {}, diff --git a/packages/nuxt/test/prehydrate.test.ts b/packages/nuxt/test/prehydrate.test.ts new file mode 100644 index 0000000000..664e988bb6 --- /dev/null +++ b/packages/nuxt/test/prehydrate.test.ts @@ -0,0 +1,40 @@ +import { describe, expect, it } from 'vitest' + +import { PrehydrateTransformPlugin } from '../src/core/plugins/prehydrate' + +describe('prehydrate', () => { + const transformPlugin = PrehydrateTransformPlugin().raw({}, {} as any) as { transform: (code: string, id: string) => Promise<{ code: string } | null> } + + it('should extract and minify code in onPrehydrate', async () => { + const snippet = ` +onPrehydrate(() => { + console.log('hello world') +}) + ` + const snippet2 = ` +export default { + async setup () { + onPrehydrate(() => { + console.log('hello world') + }) + } +} + ` + + for (const item of [snippet, snippet2]) { + const { code } = await transformPlugin.transform(item, 'test.ts') ?? {} + expect(code).toContain(`onPrehydrate("(()=>{console.log(\\"hello world\\")})")`) + } + }) + + it('should add hash if required', async () => { + const snippet = ` +onPrehydrate((attr) => { + console.log('hello world') +}) + ` + + const { code } = await transformPlugin.transform(snippet, 'test.ts') ?? {} + expect(code?.trim()).toMatchInlineSnapshot(`"onPrehydrate("(o=>{console.log(\\"hello world\\")})", "rifMBArY0d")"`) + }) +}) diff --git a/packages/nuxt/test/route-rules.test.ts b/packages/nuxt/test/route-rules.test.ts new file mode 100644 index 0000000000..a5431fab37 --- /dev/null +++ b/packages/nuxt/test/route-rules.test.ts @@ -0,0 +1,56 @@ +import { describe, expect, it } from 'vitest' + +import { extractRouteRules } from '../src/pages/route-rules' + +describe('route-rules', () => { + it('should extract route rules from pages', async () => { + for (const [path, code] of Object.entries(examples)) { + const result = await extractRouteRules(code, path) + + expect(result).toStrictEqual({ + 'prerender': true, + }) + } + }) +}) + +const examples = { + // vue component with two script blocks + 'app.vue': ` + + + + + + `, + // vue component with a normal script block, and defineRouteRules ambiently + 'component.vue': ` + + + `, +// TODO: JS component with defineRouteRules within a setup function +// 'component.ts': ` +// export default { +// setup() { +// defineRouteRules({ +// prerender: true +// }) +// } +// } +// `, +} diff --git a/packages/nuxt/test/treeshake-client.test.ts b/packages/nuxt/test/treeshake-client.test.ts index b0afa0cb19..13a0a21f59 100644 --- a/packages/nuxt/test/treeshake-client.test.ts +++ b/packages/nuxt/test/treeshake-client.test.ts @@ -3,7 +3,7 @@ import path from 'node:path' import { describe, expect, it, vi } from 'vitest' import * as VueCompilerSFC from 'vue/compiler-sfc' import type { Plugin } from 'vite' -import { Parser } from 'acorn' +import * as Parser from 'acorn' import type { Options } from '@vitejs/plugin-vue' import _vuePlugin from '@vitejs/plugin-vue' import { TreeShakeTemplatePlugin } from '../src/components/plugins/tree-shake' @@ -81,16 +81,7 @@ async function SFCCompile (name: string, source: string, options: Options, ssr = define: {}, }) // eslint-disable-next-line @typescript-eslint/no-unsafe-function-type - const result = await (plugin.transform! as Function).call({ - parse: (code: string, opts: any = {}) => Parser.parse(code, { - sourceType: 'module', - ecmaVersion: 'latest', - locations: true, - ...opts, - }), - }, source, name, { - ssr, - }) + const result = await (plugin.transform! as Function)(source, name, { ssr }) return typeof result === 'string' ? result : result?.code } From 1c418d0ea3b046f2f7dedc3f39a87cc5be3e90b2 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 29 Nov 2024 10:05:02 +0000 Subject: [PATCH 11/11] chore(deps): update dependency nuxi to v3.16.0 (main) (#30085) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- package.json | 2 +- packages/nuxt/package.json | 2 +- pnpm-lock.yaml | 14 +++++++------- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/package.json b/package.json index 1474c7b40a..e7a7e9b133 100644 --- a/package.json +++ b/package.json @@ -95,7 +95,7 @@ "knip": "5.38.2", "markdownlint-cli": "0.43.0", "nitro": "npm:nitro-nightly@3.0.0-beta-28796231.359af68d", - "nuxi": "3.15.0", + "nuxi": "3.16.0", "nuxt": "workspace:*", "nuxt-content-twoslash": "0.1.2", "ofetch": "1.4.1", diff --git a/packages/nuxt/package.json b/packages/nuxt/package.json index a282d303ae..70e8e35875 100644 --- a/packages/nuxt/package.json +++ b/packages/nuxt/package.json @@ -95,7 +95,7 @@ "mlly": "^1.7.3", "nanotar": "^0.1.1", "nitro": "npm:nitro-nightly@3.0.0-beta-28796231.359af68d", - "nuxi": "^3.15.0", + "nuxi": "^3.16.0", "nypm": "^0.4.0", "ofetch": "^1.4.1", "ohash": "^1.1.4", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index b66b31d96c..2b1a975171 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -128,8 +128,8 @@ importers: specifier: npm:nitro-nightly@3.0.0-beta-28796231.359af68d version: nitro-nightly@3.0.0-beta-28796231.359af68d(typescript@5.6.3) nuxi: - specifier: 3.15.0 - version: 3.15.0 + specifier: 3.16.0 + version: 3.16.0 nuxt: specifier: workspace:* version: link:packages/nuxt @@ -381,8 +381,8 @@ importers: specifier: npm:nitro-nightly@3.0.0-beta-28796231.359af68d version: nitro-nightly@3.0.0-beta-28796231.359af68d(typescript@5.6.3) nuxi: - specifier: ^3.15.0 - version: 3.15.0 + specifier: ^3.16.0 + version: 3.16.0 nypm: specifier: ^0.4.0 version: 0.4.0 @@ -5825,8 +5825,8 @@ packages: nth-check@2.1.1: resolution: {integrity: sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==} - nuxi@3.15.0: - resolution: {integrity: sha512-ZVu45nuDrdb7nzKW2kLGY/N1vvFYLLbUVX6gUYw4BApKGGu4+GktTR5o48dGVgMYX9A8chaugl7TL9ZYmwC9Mg==} + nuxi@3.16.0: + resolution: {integrity: sha512-t9m4zTq44R0/icuzQXJHEyPRM3YbgTPMpytyb6YW2LOL/3mwZ3Bmte1FIlCoigzDvxBJRbcchZGc689+Syyu8w==} engines: {node: ^16.10.0 || >=18.0.0} hasBin: true @@ -13449,7 +13449,7 @@ snapshots: dependencies: boolbase: 1.0.0 - nuxi@3.15.0: {} + nuxi@3.16.0: {} nuxt-content-twoslash@0.1.2(@nuxtjs/mdc@0.8.3): dependencies: