mirror of
https://github.com/nuxt/nuxt.git
synced 2024-11-26 07:32:01 +00:00
Merge branch 'main' into patch-21
This commit is contained in:
commit
b9b25a6e41
4
.github/workflows/autofix-docs.yml
vendored
4
.github/workflows/autofix-docs.yml
vendored
@ -19,7 +19,7 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
|
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
|
||||||
- run: corepack enable
|
- run: corepack enable
|
||||||
- uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2
|
- uses: actions/setup-node@1e60f620b9541d16bece96c5465dc8ee9832be0b # v4.0.3
|
||||||
with:
|
with:
|
||||||
node-version: 20
|
node-version: 20
|
||||||
cache: "pnpm"
|
cache: "pnpm"
|
||||||
@ -33,4 +33,4 @@ jobs:
|
|||||||
- name: Lint (docs)
|
- name: Lint (docs)
|
||||||
run: pnpm lint:docs:fix
|
run: pnpm lint:docs:fix
|
||||||
|
|
||||||
- uses: autofix-ci/action@2891949f3779a1cafafae1523058501de3d4e944
|
- uses: autofix-ci/action@ff86a557419858bb967097bfc916833f5647fa8c
|
||||||
|
4
.github/workflows/autofix.yml
vendored
4
.github/workflows/autofix.yml
vendored
@ -15,7 +15,7 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
|
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
|
||||||
- run: corepack enable
|
- run: corepack enable
|
||||||
- uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2
|
- uses: actions/setup-node@1e60f620b9541d16bece96c5465dc8ee9832be0b # v4.0.3
|
||||||
with:
|
with:
|
||||||
node-version: 20
|
node-version: 20
|
||||||
cache: "pnpm"
|
cache: "pnpm"
|
||||||
@ -52,4 +52,4 @@ jobs:
|
|||||||
- name: Lint (code)
|
- name: Lint (code)
|
||||||
run: pnpm lint:fix
|
run: pnpm lint:fix
|
||||||
|
|
||||||
- uses: autofix-ci/action@2891949f3779a1cafafae1523058501de3d4e944
|
- uses: autofix-ci/action@ff86a557419858bb967097bfc916833f5647fa8c
|
||||||
|
4
.github/workflows/benchmark.yml
vendored
4
.github/workflows/benchmark.yml
vendored
@ -31,7 +31,7 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
|
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
|
||||||
- run: corepack enable
|
- run: corepack enable
|
||||||
- uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2
|
- uses: actions/setup-node@1e60f620b9541d16bece96c5465dc8ee9832be0b # v4.0.3
|
||||||
with:
|
with:
|
||||||
node-version: 20
|
node-version: 20
|
||||||
cache: "pnpm"
|
cache: "pnpm"
|
||||||
@ -46,7 +46,7 @@ jobs:
|
|||||||
run: pnpm build
|
run: pnpm build
|
||||||
|
|
||||||
- name: Run benchmarks
|
- name: Run benchmarks
|
||||||
uses: CodSpeedHQ/action@f11c406b8c87cda176ff341ed4925bc98086f6d1 # v2.4.2
|
uses: CodSpeedHQ/action@ab07afd34cbbb7a1306e8d14b7cc44e029eee37a # v3.0.0
|
||||||
with:
|
with:
|
||||||
run: pnpm vitest bench
|
run: pnpm vitest bench
|
||||||
token: ${{ secrets.CODSPEED_TOKEN }}
|
token: ${{ secrets.CODSPEED_TOKEN }}
|
||||||
|
2
.github/workflows/changelog.yml
vendored
2
.github/workflows/changelog.yml
vendored
@ -24,7 +24,7 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
- run: corepack enable
|
- run: corepack enable
|
||||||
- uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2
|
- uses: actions/setup-node@1e60f620b9541d16bece96c5465dc8ee9832be0b # v4.0.3
|
||||||
with:
|
with:
|
||||||
node-version: 20
|
node-version: 20
|
||||||
cache: "pnpm"
|
cache: "pnpm"
|
||||||
|
22
.github/workflows/ci.yml
vendored
22
.github/workflows/ci.yml
vendored
@ -39,7 +39,7 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
|
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
|
||||||
- run: corepack enable
|
- run: corepack enable
|
||||||
- uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2
|
- uses: actions/setup-node@1e60f620b9541d16bece96c5465dc8ee9832be0b # v4.0.3
|
||||||
with:
|
with:
|
||||||
node-version: 20
|
node-version: 20
|
||||||
cache: "pnpm"
|
cache: "pnpm"
|
||||||
@ -57,7 +57,7 @@ jobs:
|
|||||||
run: pnpm build
|
run: pnpm build
|
||||||
|
|
||||||
- name: Cache dist
|
- name: Cache dist
|
||||||
uses: actions/upload-artifact@0b2256b8c012f0828dc542b3febcab082c67f72b # v4.3.4
|
uses: actions/upload-artifact@89ef406dd8d7e03cfd12d9e0a4a378f454709029 # v4.3.5
|
||||||
with:
|
with:
|
||||||
retention-days: 3
|
retention-days: 3
|
||||||
name: dist
|
name: dist
|
||||||
@ -76,7 +76,7 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
|
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
|
||||||
- run: corepack enable
|
- run: corepack enable
|
||||||
- uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2
|
- uses: actions/setup-node@1e60f620b9541d16bece96c5465dc8ee9832be0b # v4.0.3
|
||||||
with:
|
with:
|
||||||
node-version: 20
|
node-version: 20
|
||||||
cache: "pnpm"
|
cache: "pnpm"
|
||||||
@ -85,7 +85,7 @@ jobs:
|
|||||||
run: pnpm install
|
run: pnpm install
|
||||||
|
|
||||||
- name: Initialize CodeQL
|
- name: Initialize CodeQL
|
||||||
uses: github/codeql-action/init@b611370bb5703a7efb587f9d136a52ea24c5c38c # v3.25.11
|
uses: github/codeql-action/init@afb54ba388a7dca6ecae48f608c4ff05ff4cc77a # v3.25.15
|
||||||
with:
|
with:
|
||||||
languages: javascript
|
languages: javascript
|
||||||
queries: +security-and-quality
|
queries: +security-and-quality
|
||||||
@ -97,7 +97,7 @@ jobs:
|
|||||||
path: packages
|
path: packages
|
||||||
|
|
||||||
- name: Perform CodeQL Analysis
|
- name: Perform CodeQL Analysis
|
||||||
uses: github/codeql-action/analyze@b611370bb5703a7efb587f9d136a52ea24c5c38c # v3.25.11
|
uses: github/codeql-action/analyze@afb54ba388a7dca6ecae48f608c4ff05ff4cc77a # v3.25.15
|
||||||
with:
|
with:
|
||||||
category: "/language:javascript"
|
category: "/language:javascript"
|
||||||
|
|
||||||
@ -115,7 +115,7 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
|
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
|
||||||
- run: corepack enable
|
- run: corepack enable
|
||||||
- uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2
|
- uses: actions/setup-node@1e60f620b9541d16bece96c5465dc8ee9832be0b # v4.0.3
|
||||||
with:
|
with:
|
||||||
node-version: 20
|
node-version: 20
|
||||||
cache: "pnpm"
|
cache: "pnpm"
|
||||||
@ -146,7 +146,7 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
|
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
|
||||||
- run: corepack enable
|
- run: corepack enable
|
||||||
- uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2
|
- uses: actions/setup-node@1e60f620b9541d16bece96c5465dc8ee9832be0b # v4.0.3
|
||||||
with:
|
with:
|
||||||
node-version: 20
|
node-version: 20
|
||||||
cache: "pnpm"
|
cache: "pnpm"
|
||||||
@ -170,7 +170,7 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
|
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
|
||||||
- run: corepack enable
|
- run: corepack enable
|
||||||
- uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2
|
- uses: actions/setup-node@1e60f620b9541d16bece96c5465dc8ee9832be0b # v4.0.3
|
||||||
with:
|
with:
|
||||||
node-version: 20
|
node-version: 20
|
||||||
cache: "pnpm"
|
cache: "pnpm"
|
||||||
@ -221,7 +221,7 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
|
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
|
||||||
- run: corepack enable
|
- run: corepack enable
|
||||||
- uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2
|
- uses: actions/setup-node@1e60f620b9541d16bece96c5465dc8ee9832be0b # v4.0.3
|
||||||
with:
|
with:
|
||||||
node-version: ${{ matrix.node }}
|
node-version: ${{ matrix.node }}
|
||||||
cache: "pnpm"
|
cache: "pnpm"
|
||||||
@ -276,7 +276,7 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
- run: corepack enable
|
- run: corepack enable
|
||||||
- uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2
|
- uses: actions/setup-node@1e60f620b9541d16bece96c5465dc8ee9832be0b # v4.0.3
|
||||||
with:
|
with:
|
||||||
node-version: 20
|
node-version: 20
|
||||||
cache: "pnpm"
|
cache: "pnpm"
|
||||||
@ -317,7 +317,7 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
- run: corepack enable
|
- run: corepack enable
|
||||||
- uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2
|
- uses: actions/setup-node@1e60f620b9541d16bece96c5465dc8ee9832be0b # v4.0.3
|
||||||
with:
|
with:
|
||||||
node-version: 20
|
node-version: 20
|
||||||
cache: "pnpm"
|
cache: "pnpm"
|
||||||
|
2
.github/workflows/dependency-review.yml
vendored
2
.github/workflows/dependency-review.yml
vendored
@ -19,4 +19,4 @@ jobs:
|
|||||||
- name: 'Checkout Repository'
|
- name: 'Checkout Repository'
|
||||||
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
|
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
|
||||||
- name: 'Dependency Review'
|
- name: 'Dependency Review'
|
||||||
uses: actions/dependency-review-action@72eb03d02c7872a771aacd928f3123ac62ad6d3a # v4.3.3
|
uses: actions/dependency-review-action@5a2ce3f5b92ee19cbb1541a4984c76d921601d7c # v4.3.4
|
||||||
|
2
.github/workflows/docs.yml
vendored
2
.github/workflows/docs.yml
vendored
@ -23,7 +23,7 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
|
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
|
||||||
- run: corepack enable
|
- run: corepack enable
|
||||||
- uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2
|
- uses: actions/setup-node@1e60f620b9541d16bece96c5465dc8ee9832be0b # v4.0.3
|
||||||
with:
|
with:
|
||||||
node-version: 20
|
node-version: 20
|
||||||
cache: "pnpm"
|
cache: "pnpm"
|
||||||
|
2
.github/workflows/release-pr.yml
vendored
2
.github/workflows/release-pr.yml
vendored
@ -54,7 +54,7 @@ jobs:
|
|||||||
fetch-depth: 1
|
fetch-depth: 1
|
||||||
|
|
||||||
- run: corepack enable
|
- run: corepack enable
|
||||||
- uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2
|
- uses: actions/setup-node@1e60f620b9541d16bece96c5465dc8ee9832be0b # v4.0.3
|
||||||
with:
|
with:
|
||||||
node-version: 20
|
node-version: 20
|
||||||
cache: "pnpm"
|
cache: "pnpm"
|
||||||
|
2
.github/workflows/release.yml
vendored
2
.github/workflows/release.yml
vendored
@ -23,7 +23,7 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
- run: corepack enable
|
- run: corepack enable
|
||||||
- uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2
|
- uses: actions/setup-node@1e60f620b9541d16bece96c5465dc8ee9832be0b # v4.0.3
|
||||||
with:
|
with:
|
||||||
node-version: 20
|
node-version: 20
|
||||||
registry-url: "https://registry.npmjs.org/"
|
registry-url: "https://registry.npmjs.org/"
|
||||||
|
6
.github/workflows/scorecards.yml
vendored
6
.github/workflows/scorecards.yml
vendored
@ -37,7 +37,7 @@ jobs:
|
|||||||
persist-credentials: false
|
persist-credentials: false
|
||||||
|
|
||||||
- name: "Run analysis"
|
- name: "Run analysis"
|
||||||
uses: ossf/scorecard-action@dc50aa9510b46c811795eb24b2f1ba02a914e534 # v2.3.3
|
uses: ossf/scorecard-action@62b2cac7ed8198b15735ed49ab1e5cf35480ba46 # v2.4.0
|
||||||
with:
|
with:
|
||||||
results_file: results.sarif
|
results_file: results.sarif
|
||||||
results_format: sarif
|
results_format: sarif
|
||||||
@ -59,7 +59,7 @@ jobs:
|
|||||||
# Upload the results as artifacts (optional). Commenting out will disable uploads of run results in SARIF
|
# Upload the results as artifacts (optional). Commenting out will disable uploads of run results in SARIF
|
||||||
# format to the repository Actions tab.
|
# format to the repository Actions tab.
|
||||||
- name: "Upload artifact"
|
- name: "Upload artifact"
|
||||||
uses: actions/upload-artifact@0b2256b8c012f0828dc542b3febcab082c67f72b # v4.3.4
|
uses: actions/upload-artifact@89ef406dd8d7e03cfd12d9e0a4a378f454709029 # v4.3.5
|
||||||
if: github.repository == 'nuxt/nuxt' && success()
|
if: github.repository == 'nuxt/nuxt' && success()
|
||||||
with:
|
with:
|
||||||
name: SARIF file
|
name: SARIF file
|
||||||
@ -68,7 +68,7 @@ jobs:
|
|||||||
|
|
||||||
# Upload the results to GitHub's code scanning dashboard.
|
# Upload the results to GitHub's code scanning dashboard.
|
||||||
- name: "Upload to code-scanning"
|
- name: "Upload to code-scanning"
|
||||||
uses: github/codeql-action/upload-sarif@b611370bb5703a7efb587f9d136a52ea24c5c38c # v3.25.11
|
uses: github/codeql-action/upload-sarif@afb54ba388a7dca6ecae48f608c4ff05ff4cc77a # v3.25.15
|
||||||
if: github.repository == 'nuxt/nuxt' && success()
|
if: github.repository == 'nuxt/nuxt' && success()
|
||||||
with:
|
with:
|
||||||
sarif_file: results.sarif
|
sarif_file: results.sarif
|
||||||
|
@ -109,7 +109,7 @@ Follow the docs to [Set Up Your Local Development Environment](https://nuxt.com/
|
|||||||
## <a name="follow-us">🔗 Follow Us</a>
|
## <a name="follow-us">🔗 Follow Us</a>
|
||||||
|
|
||||||
<p valign="center">
|
<p valign="center">
|
||||||
<a href="https://chat.nuxt.dev"><img width="20px" src="./.github/assets/discord.svg" alt="Discord"></a> <a href="https://twitter.nuxt.dev"><img width="20px" src="./.github/assets/twitter.svg" alt="Twitter"></a> <a href="https://github.nuxt.dev"><img width="20px" src="./.github/assets/github.svg" alt="GitHub"></a>
|
<a href="https://go.nuxt.com/discord"><img width="20px" src="./.github/assets/discord.svg" alt="Discord"></a> <a href="https://go.nuxt.com/x"><img width="20px" src="./.github/assets/twitter.svg" alt="Twitter"></a> <a href="https://go.nuxt.com/github"><img width="20px" src="./.github/assets/github.svg" alt="GitHub"></a>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
## <a name="license">⚖️ License</a>
|
## <a name="license">⚖️ License</a>
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
---
|
---
|
||||||
title: 'Introduction'
|
title: Introduction
|
||||||
description: Nuxt's goal is to make web development intuitive and performant with a great Developer Experience in mind.
|
description: Nuxt's goal is to make web development intuitive and performant with a great Developer Experience in mind.
|
||||||
navigation.icon: i-ph-info-duotone
|
navigation:
|
||||||
|
icon: i-ph-info-duotone
|
||||||
---
|
---
|
||||||
|
|
||||||
Nuxt is a free and [open-source framework](https://github.com/nuxt/nuxt) with an intuitive and extendable way to create type-safe, performant and production-grade full-stack web applications and websites with [Vue.js](https://vuejs.org).
|
Nuxt is a free and [open-source framework](https://github.com/nuxt/nuxt) with an intuitive and extendable way to create type-safe, performant and production-grade full-stack web applications and websites with [Vue.js](https://vuejs.org).
|
||||||
@ -78,4 +79,3 @@ Nuxt is composed of different [core packages](https://github.com/nuxt/nuxt/tree/
|
|||||||
- Development kit: [@nuxt/kit](https://github.com/nuxt/nuxt/tree/main/packages/kit)
|
- Development kit: [@nuxt/kit](https://github.com/nuxt/nuxt/tree/main/packages/kit)
|
||||||
|
|
||||||
We recommend reading each concept to have a full vision of Nuxt capabilities and the scope of each package.
|
We recommend reading each concept to have a full vision of Nuxt capabilities and the scope of each package.
|
||||||
|
|
||||||
|
@ -544,17 +544,22 @@ Please use the options below for the `setup` method.
|
|||||||
|
|
||||||
#### Features
|
#### Features
|
||||||
|
|
||||||
|
- `build`: Whether to run a separate build step.
|
||||||
|
- Type: `boolean`
|
||||||
|
- Default: `true` (`false` if `browser` or `server` is disabled, or if a `host` is provided)
|
||||||
|
|
||||||
- `server`: Whether to launch a server to respond to requests in the test suite.
|
- `server`: Whether to launch a server to respond to requests in the test suite.
|
||||||
- Type: `boolean`
|
- Type: `boolean`
|
||||||
- Default: `true`
|
- Default: `true` (`false` if a `host` is provided)
|
||||||
|
|
||||||
- `port`: If provided, set the launched test server port to the value.
|
- `port`: If provided, set the launched test server port to the value.
|
||||||
- Type: `number | undefined`
|
- Type: `number | undefined`
|
||||||
- Default: `undefined`
|
- Default: `undefined`
|
||||||
|
|
||||||
- `build`: Whether to run a separate build step.
|
- `host`: If provided, a URL to use as the test target instead of building and running a new server. Useful for running "real" end-to-end tests against a deployed version of your application, or against an already running local server (which may provide a significant reduction in test execution timings). See the [target host end-to-end example below](#target-host-end-to-end-example).
|
||||||
- Type: `boolean`
|
- Type: `string`
|
||||||
- Default: `true` (`false` if `browser` or `server` is disabled)
|
- Default: `undefined`
|
||||||
|
|
||||||
- `browser`: Under the hood, Nuxt test utils uses [`playwright`](https://playwright.dev) to carry out browser testing. If this option is set, a browser will be launched and can be controlled in the subsequent test suite.
|
- `browser`: Under the hood, Nuxt test utils uses [`playwright`](https://playwright.dev) to carry out browser testing. If this option is set, a browser will be launched and can be controlled in the subsequent test suite.
|
||||||
- Type: `boolean`
|
- Type: `boolean`
|
||||||
- Default: `false`
|
- Default: `false`
|
||||||
@ -566,6 +571,31 @@ Please use the options below for the `setup` method.
|
|||||||
- Type: `'vitest' | 'jest' | 'cucumber'`
|
- Type: `'vitest' | 'jest' | 'cucumber'`
|
||||||
- Default: `'vitest'`
|
- Default: `'vitest'`
|
||||||
|
|
||||||
|
##### Target `host` end-to-end example
|
||||||
|
|
||||||
|
A common use-case for end-to-end testing is running the tests against a deployed application running in the same environment typically used for Production.
|
||||||
|
|
||||||
|
For local development or automated deploy pipelines, testing against a separate local server can be more efficient and is typically faster than allowing the test framework to rebuild between tests.
|
||||||
|
|
||||||
|
To utilize a separate target host for end-to-end tests, simply provide the `host` property of the `setup` function with the desired URL.
|
||||||
|
|
||||||
|
```ts
|
||||||
|
import { setup, createPage } from '@nuxt/test-utils/e2e'
|
||||||
|
import { describe, it, expect } from 'vitest'
|
||||||
|
|
||||||
|
describe('login page', async () => {
|
||||||
|
await setup({
|
||||||
|
host: 'http://localhost:8787',
|
||||||
|
})
|
||||||
|
|
||||||
|
it('displays the email and password fields', async () => {
|
||||||
|
const page = await createPage('/login')
|
||||||
|
expect(await page.getByTestId('email').isVisible()).toBe(true)
|
||||||
|
expect(await page.getByTestId('password').isVisible()).toBe(true)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
### APIs
|
### APIs
|
||||||
|
|
||||||
#### `$fetch(url)`
|
#### `$fetch(url)`
|
||||||
|
@ -26,7 +26,7 @@ pnpm dlx nuxi upgrade
|
|||||||
```
|
```
|
||||||
|
|
||||||
```bash [bun]
|
```bash [bun]
|
||||||
bunx nuxi upgrade
|
bun x nuxi upgrade
|
||||||
```
|
```
|
||||||
|
|
||||||
::
|
::
|
||||||
@ -97,6 +97,24 @@ Breaking or significant changes will be noted here along with migration steps fo
|
|||||||
This section is subject to change until the final release, so please check back here regularly if you are testing Nuxt 4 using `compatibilityVersion: 4`.
|
This section is subject to change until the final release, so please check back here regularly if you are testing Nuxt 4 using `compatibilityVersion: 4`.
|
||||||
::
|
::
|
||||||
|
|
||||||
|
#### Migrating Using Codemods
|
||||||
|
|
||||||
|
To facilitate the upgrade process, we have collaborated with the [Codemod](https://github.com/codemod-com/codemod) team to automate many migration steps with some open-source codemods.
|
||||||
|
|
||||||
|
::note
|
||||||
|
If you encounter any issues, please report them to the Codemod team with `npx codemod feedback` 🙏
|
||||||
|
::
|
||||||
|
|
||||||
|
For a complete list of Nuxt 4 codemods, detailed information on each, their source, and various ways to run them, visit the [Codemod Registry](https://go.codemod.com/codemod-registry).
|
||||||
|
|
||||||
|
You can run all the codemods mentioned in this guide using the following `codemod` recipe:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npx codemod@latest nuxt/4/migration-recipe
|
||||||
|
```
|
||||||
|
|
||||||
|
This command will execute all codemods in sequence, with the option to deselect any that you do not wish to run. Each codemod is also listed below alongside its respective change and can be executed independently.
|
||||||
|
|
||||||
#### New Directory Structure
|
#### New Directory Structure
|
||||||
|
|
||||||
🚦 **Impact Level**: Significant
|
🚦 **Impact Level**: Significant
|
||||||
@ -161,6 +179,10 @@ nuxt.config.ts
|
|||||||
1. Move your `assets/`, `components/`, `composables/`, `layouts/`, `middleware/`, `pages/`, `plugins/` and `utils/` folders under it, as well as `app.vue`, `error.vue`, `app.config.ts`. If you have an `app/router-options.ts` or `app/spa-loading-template.html`, these paths remain the same.
|
1. Move your `assets/`, `components/`, `composables/`, `layouts/`, `middleware/`, `pages/`, `plugins/` and `utils/` folders under it, as well as `app.vue`, `error.vue`, `app.config.ts`. If you have an `app/router-options.ts` or `app/spa-loading-template.html`, these paths remain the same.
|
||||||
1. Make sure your `nuxt.config.ts`, `content/`, `layers/`, `modules/`, `public/` and `server/` folders remain outside the `app/` folder, in the root of your project.
|
1. Make sure your `nuxt.config.ts`, `content/`, `layers/`, `modules/`, `public/` and `server/` folders remain outside the `app/` folder, in the root of your project.
|
||||||
|
|
||||||
|
::tip
|
||||||
|
You can automate this migration by running `npx codemod@latest nuxt/4/file-structure`
|
||||||
|
::
|
||||||
|
|
||||||
However, migration is _not required_. If you wish to keep your current folder structure, Nuxt should auto-detect it. (If it does not, please raise an issue.) The one exception is that if you _already_ have a custom `srcDir`. In this case, you should be aware that your `modules/`, `public/` and `server/` folders will be resolved from your `rootDir` rather than from your custom `srcDir`. You can override this by configuring `dir.modules`, `dir.public` and `serverDir` if you need to.
|
However, migration is _not required_. If you wish to keep your current folder structure, Nuxt should auto-detect it. (If it does not, please raise an issue.) The one exception is that if you _already_ have a custom `srcDir`. In this case, you should be aware that your `modules/`, `public/` and `server/` folders will be resolved from your `rootDir` rather than from your custom `srcDir`. You can override this by configuring `dir.modules`, `dir.public` and `serverDir` if you need to.
|
||||||
|
|
||||||
You can also force a v3 folder structure with the following configuration:
|
You can also force a v3 folder structure with the following configuration:
|
||||||
@ -231,6 +253,12 @@ Previously `data` was initialized to `null` but reset in `clearNuxtData` to `und
|
|||||||
|
|
||||||
##### Migration Steps
|
##### Migration Steps
|
||||||
|
|
||||||
|
If you were checking if `data.value` or `error.value` were `null`, you can update these checks to check for `undefined` instead.
|
||||||
|
|
||||||
|
::tip
|
||||||
|
You can automate this step by running `npx codemod@latest nuxt/4/default-data-error-value`
|
||||||
|
::
|
||||||
|
|
||||||
If you encounter any issues you can revert back to the previous behavior with:
|
If you encounter any issues you can revert back to the previous behavior with:
|
||||||
|
|
||||||
```ts twoslash [nuxt.config.ts]
|
```ts twoslash [nuxt.config.ts]
|
||||||
@ -290,6 +318,10 @@ The migration should be straightforward:
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
::tip
|
||||||
|
You can automate this step by running `npx codemod@latest nuxt/4/deprecated-dedupe-value`
|
||||||
|
::
|
||||||
|
|
||||||
#### Respect defaults when clearing `data` in `useAsyncData` and `useFetch`
|
#### Respect defaults when clearing `data` in `useAsyncData` and `useFetch`
|
||||||
|
|
||||||
🚦 **Impact Level**: Minimal
|
🚦 **Impact Level**: Minimal
|
||||||
@ -353,6 +385,10 @@ In most cases, no migration steps are required, but if you rely on the reactivit
|
|||||||
})
|
})
|
||||||
```
|
```
|
||||||
|
|
||||||
|
::tip
|
||||||
|
If you need to, you can automate this step by running `npx codemod@latest nuxt/4/shallow-function-reactivity`
|
||||||
|
::
|
||||||
|
|
||||||
#### Absolute Watch Paths in `builder:watch`
|
#### Absolute Watch Paths in `builder:watch`
|
||||||
|
|
||||||
🚦 **Impact Level**: Minimal
|
🚦 **Impact Level**: Minimal
|
||||||
@ -380,6 +416,10 @@ However, if you are a module author using the `builder:watch` hook and wishing t
|
|||||||
})
|
})
|
||||||
```
|
```
|
||||||
|
|
||||||
|
::tip
|
||||||
|
You can automate this step by running `npx codemod@latest nuxt/4/absolute-watch-path`
|
||||||
|
::
|
||||||
|
|
||||||
#### Removal of `window.__NUXT__` object
|
#### Removal of `window.__NUXT__` object
|
||||||
|
|
||||||
##### What Changed
|
##### What Changed
|
||||||
@ -487,6 +527,10 @@ const importSources = (sources: string | string[], { lazy = false } = {}) => {
|
|||||||
const importName = genSafeVariableName
|
const importName = genSafeVariableName
|
||||||
```
|
```
|
||||||
|
|
||||||
|
::tip
|
||||||
|
You can automate this step by running `npx codemod@latest nuxt/4/template-compilation-changes`
|
||||||
|
::
|
||||||
|
|
||||||
#### Removal of Experimental Features
|
#### Removal of Experimental Features
|
||||||
|
|
||||||
🚦 **Impact Level**: Minimal
|
🚦 **Impact Level**: Minimal
|
||||||
|
@ -50,7 +50,7 @@ pnpm dlx nuxi@latest init <project-name>
|
|||||||
```
|
```
|
||||||
|
|
||||||
```bash [bun]
|
```bash [bun]
|
||||||
bunx nuxi@latest init <project-name>
|
bun x nuxi@latest init <project-name>
|
||||||
```
|
```
|
||||||
|
|
||||||
::
|
::
|
||||||
|
@ -466,13 +466,14 @@ Be very careful before proxying headers to an external API and just include head
|
|||||||
If you want to pass on/proxy cookies in the other direction, from an internal request back to the client, you will need to handle this yourself.
|
If you want to pass on/proxy cookies in the other direction, from an internal request back to the client, you will need to handle this yourself.
|
||||||
|
|
||||||
```ts [composables/fetch.ts]
|
```ts [composables/fetch.ts]
|
||||||
import { appendResponseHeader, H3Event } from 'h3'
|
import { appendResponseHeader } from 'h3'
|
||||||
|
import type { H3Event } from 'h3'
|
||||||
|
|
||||||
export const fetchWithCookie = async (event: H3Event, url: string) => {
|
export const fetchWithCookie = async (event: H3Event, url: string) => {
|
||||||
/* Get the response from the server endpoint */
|
/* Get the response from the server endpoint */
|
||||||
const res = await $fetch.raw(url)
|
const res = await $fetch.raw(url)
|
||||||
/* Get the cookies from the response */
|
/* Get the cookies from the response */
|
||||||
const cookies = (res.headers.get('set-cookie') || '').split(',')
|
const cookies = res.headers.getSetCookie()
|
||||||
/* Attach each cookie to our incoming Request */
|
/* Attach each cookie to our incoming Request */
|
||||||
for (const cookie of cookies) {
|
for (const cookie of cookies) {
|
||||||
appendResponseHeader(event, 'set-cookie', cookie)
|
appendResponseHeader(event, 'set-cookie', cookie)
|
||||||
|
@ -18,7 +18,13 @@ One of the core features of Nuxt is the layers and extending support. You can ex
|
|||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
You can extend a layer by adding the [extends](/docs/api/nuxt-config#extends) property to the [`nuxt.config.ts`](/docs/guide/directory-structure/nuxt-config) file.
|
By default, any layers within your project in the `~/layers` directory will be automatically registered as layers in your project
|
||||||
|
|
||||||
|
::note
|
||||||
|
Layer auto-registration was introduced in Nuxt v3.12.0
|
||||||
|
::
|
||||||
|
|
||||||
|
In addition, you can extend from a layer by adding the [extends](/docs/api/nuxt-config#extends) property to your [`nuxt.config`](/docs/guide/directory-structure/nuxt-config) file.
|
||||||
|
|
||||||
```ts [nuxt.config.ts]
|
```ts [nuxt.config.ts]
|
||||||
export default defineNuxtConfig({
|
export default defineNuxtConfig({
|
||||||
|
@ -29,7 +29,7 @@ pnpm dlx nuxi generate
|
|||||||
```
|
```
|
||||||
|
|
||||||
```bash [bun]
|
```bash [bun]
|
||||||
bunx nuxi generate
|
bun x nuxi generate
|
||||||
```
|
```
|
||||||
|
|
||||||
::
|
::
|
||||||
|
@ -28,7 +28,7 @@ pnpm dlx nuxi init -t module my-module
|
|||||||
```
|
```
|
||||||
|
|
||||||
```bash [bun]
|
```bash [bun]
|
||||||
bunx nuxi init -t module my-module
|
bun x nuxi init -t module my-module
|
||||||
```
|
```
|
||||||
::
|
::
|
||||||
|
|
||||||
|
@ -39,6 +39,8 @@ You can add, change or remove pages from the scanned routes with the `pages:exte
|
|||||||
For example, to prevent creating routes for any `.ts` files:
|
For example, to prevent creating routes for any `.ts` files:
|
||||||
|
|
||||||
```ts [nuxt.config.ts]
|
```ts [nuxt.config.ts]
|
||||||
|
import type { NuxtPage } from '@nuxt/schema'
|
||||||
|
|
||||||
export default defineNuxtConfig({
|
export default defineNuxtConfig({
|
||||||
hooks: {
|
hooks: {
|
||||||
'pages:extend' (pages) {
|
'pages:extend' (pages) {
|
||||||
@ -51,9 +53,9 @@ export default defineNuxtConfig({
|
|||||||
|
|
||||||
// remove routes
|
// remove routes
|
||||||
function removePagesMatching (pattern: RegExp, pages: NuxtPage[] = []) {
|
function removePagesMatching (pattern: RegExp, pages: NuxtPage[] = []) {
|
||||||
const pagesToRemove = []
|
const pagesToRemove: NuxtPage[] = []
|
||||||
for (const page of pages) {
|
for (const page of pages) {
|
||||||
if (pattern.test(page.file)) {
|
if (page.file && pattern.test(page.file)) {
|
||||||
pagesToRemove.push(page)
|
pagesToRemove.push(page)
|
||||||
} else {
|
} else {
|
||||||
removePagesMatching(pattern, page.children)
|
removePagesMatching(pattern, page.children)
|
||||||
@ -85,7 +87,7 @@ On top of customizing options for [`vue-router`](https://router.vuejs.org/api/in
|
|||||||
|
|
||||||
This is the recommended way to specify [router options](/docs/api/nuxt-config#router).
|
This is the recommended way to specify [router options](/docs/api/nuxt-config#router).
|
||||||
|
|
||||||
```js [app/router.options.ts]
|
```ts [app/router.options.ts]
|
||||||
import type { RouterConfig } from '@nuxt/schema'
|
import type { RouterConfig } from '@nuxt/schema'
|
||||||
|
|
||||||
export default <RouterConfig> {
|
export default <RouterConfig> {
|
||||||
@ -99,6 +101,8 @@ Adding a router options file in this hook will switch on page-based routing, unl
|
|||||||
::
|
::
|
||||||
|
|
||||||
```ts [nuxt.config.ts]
|
```ts [nuxt.config.ts]
|
||||||
|
import { createResolver } from '@nuxt/kit'
|
||||||
|
|
||||||
export default defineNuxtConfig({
|
export default defineNuxtConfig({
|
||||||
hooks: {
|
hooks: {
|
||||||
'pages:routerOptions' ({ files }) {
|
'pages:routerOptions' ({ files }) {
|
||||||
@ -166,7 +170,7 @@ export default defineNuxtConfig({
|
|||||||
|
|
||||||
You can optionally override history mode using a function that accepts the base URL and returns the history mode. If it returns `null` or `undefined`, Nuxt will fallback to the default history.
|
You can optionally override history mode using a function that accepts the base URL and returns the history mode. If it returns `null` or `undefined`, Nuxt will fallback to the default history.
|
||||||
|
|
||||||
```js [app/router.options.ts]
|
```ts [app/router.options.ts]
|
||||||
import type { RouterConfig } from '@nuxt/schema'
|
import type { RouterConfig } from '@nuxt/schema'
|
||||||
import { createMemoryHistory } from 'vue-router'
|
import { createMemoryHistory } from 'vue-router'
|
||||||
|
|
||||||
|
@ -51,7 +51,7 @@ Sets the message with `politeness = "assertive"`
|
|||||||
|
|
||||||
## Example
|
## Example
|
||||||
|
|
||||||
```ts
|
```vue [pages/index.vue]
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
const { message, politeness, set, polite, assertive } = useRouteAnnouncer({
|
const { message, politeness, set, polite, assertive } = useRouteAnnouncer({
|
||||||
politeness: 'assertive'
|
politeness: 'assertive'
|
||||||
|
@ -41,7 +41,7 @@ Use `createError` to trigger error handling in server API routes.
|
|||||||
|
|
||||||
### Example
|
### Example
|
||||||
|
|
||||||
```js
|
```ts [server/api/error.ts]
|
||||||
export default eventHandler(() => {
|
export default eventHandler(() => {
|
||||||
throw createError({
|
throw createError({
|
||||||
statusCode: 404,
|
statusCode: 404,
|
||||||
|
@ -7,7 +7,7 @@ description: Nuxt provides a powerful hooking system to expand almost every aspe
|
|||||||
|
|
||||||
## App Hooks (runtime)
|
## App Hooks (runtime)
|
||||||
|
|
||||||
Check the [app source code](https://github.com/nuxt/nuxt/blob/main/packages/nuxt/src/app/nuxt.ts#L27) for all available hooks.
|
Check the [app source code](https://github.com/nuxt/nuxt/blob/main/packages/nuxt/src/app/nuxt.ts#L37) for all available hooks.
|
||||||
|
|
||||||
Hook | Arguments | Environment | Description
|
Hook | Arguments | Environment | Description
|
||||||
-----------------------|---------------------|-----------------|-------------
|
-----------------------|---------------------|-----------------|-------------
|
||||||
|
@ -10,7 +10,9 @@ This is done through `import.meta`, which is an object that provides your code w
|
|||||||
Throughout the Nuxt documentation you may see snippets that use this already to figure out whether the
|
Throughout the Nuxt documentation you may see snippets that use this already to figure out whether the
|
||||||
code is currently running on the client or server side.
|
code is currently running on the client or server side.
|
||||||
|
|
||||||
:read-more{to="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/import.meta"}
|
::read-more{to="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/import.meta"}
|
||||||
|
Read more about `import.meta`.
|
||||||
|
::
|
||||||
|
|
||||||
## Runtime (App) Properties
|
## Runtime (App) Properties
|
||||||
|
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
---
|
---
|
||||||
title: 'Getting Help'
|
title: Getting Help
|
||||||
description: "We're a friendly community of developers and we'd love to help."
|
description: We're a friendly community of developers and we'd love to help.
|
||||||
navigation.icon: i-ph-lifebuoy-duotone
|
navigation:
|
||||||
|
icon: i-ph-lifebuoy-duotone
|
||||||
---
|
---
|
||||||
|
|
||||||
At some point, you may find that there's an issue you need some help with.
|
At some point, you may find that there's an issue you need some help with.
|
||||||
@ -16,13 +17,10 @@ Please don't feel embarrassed about asking a question that you think is easy - w
|
|||||||
|
|
||||||
Everyone you'll encounter is helping out because they care, not because they are paid to do so. The kindest thing to do is make it easy for them to help you. Here are some ideas:
|
Everyone you'll encounter is helping out because they care, not because they are paid to do so. The kindest thing to do is make it easy for them to help you. Here are some ideas:
|
||||||
|
|
||||||
* _Explain what your objective is, not just the problem you're facing._ "I need to ensure my form inputs are accessible, so I'm trying to get the ids to match between server and client."
|
- _Explain what your objective is, not just the problem you're facing._ "I need to ensure my form inputs are accessible, so I'm trying to get the ids to match between server and client."
|
||||||
|
- _Make sure you've first read the docs and used your favorite search engine_. Let people know by saying something like "I've Googled for 'nuxt script setup' but I couldn't find code examples anywhere."
|
||||||
* _Make sure you've first read the docs and used your favorite search engine_. Let people know by saying something like "I've Googled for 'nuxt script setup' but I couldn't find code examples anywhere."
|
- _Explain what you've tried._ Tell people the kind of solutions you've experimented with, and why. Often this can make people's advice more relevant to your situation.
|
||||||
|
- _Share your code._ People probably won't be able to help if they just see an error message or a screenshot - but that all changes if you share your code in a copy/pasteable format - preferably in the form of a minimal reproduction like a CodeSandbox.
|
||||||
* _Explain what you've tried._ Tell people the kind of solutions you've experimented with, and why. Often this can make people's advice more relevant to your situation.
|
|
||||||
|
|
||||||
* _Share your code._ People probably won't be able to help if they just see an error message or a screenshot - but that all changes if you share your code in a copy/pasteable format - preferably in the form of a minimal reproduction like a CodeSandbox.
|
|
||||||
|
|
||||||
And finally, just ask the question! There's no need to [ask permission to ask a question](https://dontasktoask.com) or [wait for someone to reply to your 'hello'](https://www.nohello.com). If you do, you might not get a response because people are waiting for the whole question before engaging.
|
And finally, just ask the question! There's no need to [ask permission to ask a question](https://dontasktoask.com) or [wait for someone to reply to your 'hello'](https://www.nohello.com). If you do, you might not get a response because people are waiting for the whole question before engaging.
|
||||||
|
|
||||||
@ -31,3 +29,11 @@ And finally, just ask the question! There's no need to [ask permission to ask a
|
|||||||
Something isn't working the way that the docs say that it should. You're not sure if it's a bug. You've searched through the [open issues](https://github.com/nuxt/nuxt/issues) and [discussions](https://github.com/nuxt/nuxt/discussions) but you can't find anything. (if there is a closed issue, please create a new one)
|
Something isn't working the way that the docs say that it should. You're not sure if it's a bug. You've searched through the [open issues](https://github.com/nuxt/nuxt/issues) and [discussions](https://github.com/nuxt/nuxt/discussions) but you can't find anything. (if there is a closed issue, please create a new one)
|
||||||
|
|
||||||
We recommend taking a look at [how to report bugs](/docs/community/reporting-bugs). Nuxt is still in active development, and every issue helps make it better.
|
We recommend taking a look at [how to report bugs](/docs/community/reporting-bugs). Nuxt is still in active development, and every issue helps make it better.
|
||||||
|
|
||||||
|
## "I need professional help"
|
||||||
|
|
||||||
|
If the community couldn't provide the help you need in the time-frame you have, NuxtLabs offers professional support with the [Nuxt Experts](https://nuxt.com/enterprise/support).
|
||||||
|
|
||||||
|
The objective of the Nuxt Expert is to provide support to the Vue ecosystem, while also creating freelance opportunities for those contributing to open-source solutions, thus helping to maintain the sustainability of the ecosystem.
|
||||||
|
|
||||||
|
The Nuxt experts are Vue, Nuxt and Vite chosen contributors providing professional support and consulting services.
|
||||||
|
@ -3,7 +3,6 @@ import { createConfigForNuxt } from '@nuxt/eslint-config/flat'
|
|||||||
// @ts-expect-error missing types
|
// @ts-expect-error missing types
|
||||||
import noOnlyTests from 'eslint-plugin-no-only-tests'
|
import noOnlyTests from 'eslint-plugin-no-only-tests'
|
||||||
import typegen from 'eslint-typegen'
|
import typegen from 'eslint-typegen'
|
||||||
// @ts-expect-error missing types
|
|
||||||
import perfectionist from 'eslint-plugin-perfectionist'
|
import perfectionist from 'eslint-plugin-perfectionist'
|
||||||
|
|
||||||
export default createConfigForNuxt({
|
export default createConfigForNuxt({
|
||||||
@ -189,6 +188,7 @@ export default createConfigForNuxt({
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
// Sort rule keys in eslint config
|
// Sort rule keys in eslint config
|
||||||
|
// @ts-expect-error incorrect types 🤔
|
||||||
{
|
{
|
||||||
files: ['**/eslint.config.mjs'],
|
files: ['**/eslint.config.mjs'],
|
||||||
name: 'local/sort-eslint-config',
|
name: 'local/sort-eslint-config',
|
||||||
|
57
package.json
57
package.json
@ -39,42 +39,43 @@
|
|||||||
"@nuxt/ui-templates": "workspace:*",
|
"@nuxt/ui-templates": "workspace:*",
|
||||||
"@nuxt/vite-builder": "workspace:*",
|
"@nuxt/vite-builder": "workspace:*",
|
||||||
"@nuxt/webpack-builder": "workspace:*",
|
"@nuxt/webpack-builder": "workspace:*",
|
||||||
|
"@types/node": "*",
|
||||||
"c12": "2.0.0-beta.1",
|
"c12": "2.0.0-beta.1",
|
||||||
"h3": "npm:h3-nightly@2.0.0-1718872656.6765a6e",
|
"h3": "npm:h3-nightly@2.0.0-1718872656.6765a6e",
|
||||||
"jiti": "2.0.0-beta.3",
|
"jiti": "2.0.0-beta.3",
|
||||||
"magic-string": "^0.30.10",
|
"magic-string": "^0.30.11",
|
||||||
"nitro": "npm:nitro-nightly@3.0.0-beta-28665895.e727afda",
|
"nitro": "npm:nitro-nightly@3.0.0-beta-28665895.e727afda",
|
||||||
"nuxt": "workspace:*",
|
"nuxt": "workspace:*",
|
||||||
"rollup": "^4.18.0",
|
"rollup": "^4.20.0",
|
||||||
"typescript": "5.5.3",
|
"typescript": "5.5.4",
|
||||||
"unbuild": "3.0.0-rc.6",
|
"unbuild": "3.0.0-rc.7",
|
||||||
"vite": "5.3.3",
|
"vite": "5.3.5",
|
||||||
"vue": "3.4.31"
|
"vue": "3.4.34"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@eslint/js": "9.6.0",
|
"@eslint/js": "9.8.0",
|
||||||
"@nuxt/eslint-config": "0.3.13",
|
"@nuxt/eslint-config": "0.5.0",
|
||||||
"@nuxt/kit": "workspace:*",
|
"@nuxt/kit": "workspace:*",
|
||||||
"@nuxt/test-utils": "3.13.1",
|
"@nuxt/test-utils": "3.14.0",
|
||||||
"@nuxt/webpack-builder": "workspace:*",
|
"@nuxt/webpack-builder": "workspace:*",
|
||||||
"@testing-library/vue": "8.1.0",
|
"@testing-library/vue": "8.1.0",
|
||||||
"@types/eslint__js": "8.42.3",
|
"@types/eslint__js": "8.42.3",
|
||||||
"@types/node": "20.14.9",
|
"@types/node": "20.14.14",
|
||||||
"@types/semver": "7.5.8",
|
"@types/semver": "7.5.8",
|
||||||
"@unhead/schema": "1.9.15",
|
"@unhead/schema": "1.9.16",
|
||||||
"@vitejs/plugin-vue": "5.0.5",
|
"@vitejs/plugin-vue": "5.1.2",
|
||||||
"@vitest/coverage-v8": "1.6.0",
|
"@vitest/coverage-v8": "2.0.5",
|
||||||
"@vue/test-utils": "2.4.6",
|
"@vue/test-utils": "2.4.6",
|
||||||
"autoprefixer": "10.4.19",
|
"autoprefixer": "10.4.20",
|
||||||
"case-police": "0.6.1",
|
"case-police": "0.6.1",
|
||||||
"changelogen": "0.5.5",
|
"changelogen": "0.5.5",
|
||||||
"consola": "3.2.3",
|
"consola": "3.2.3",
|
||||||
"cssnano": "7.0.4",
|
"cssnano": "7.0.4",
|
||||||
"devalue": "5.0.0",
|
"devalue": "5.0.0",
|
||||||
"eslint": "9.6.0",
|
"eslint": "9.8.0",
|
||||||
"eslint-plugin-no-only-tests": "3.1.0",
|
"eslint-plugin-no-only-tests": "3.1.0",
|
||||||
"eslint-plugin-perfectionist": "2.11.0",
|
"eslint-plugin-perfectionist": "3.1.2",
|
||||||
"eslint-typegen": "0.2.4",
|
"eslint-typegen": "0.3.0",
|
||||||
"execa": "9.3.0",
|
"execa": "9.3.0",
|
||||||
"globby": "14.0.2",
|
"globby": "14.0.2",
|
||||||
"h3": "npm:h3-nightly@2.0.0-1718872656.6765a6e",
|
"h3": "npm:h3-nightly@2.0.0-1718872656.6765a6e",
|
||||||
@ -84,22 +85,22 @@
|
|||||||
"nitro": "npm:nitro-nightly@3.0.0-beta-28665895.e727afda",
|
"nitro": "npm:nitro-nightly@3.0.0-beta-28665895.e727afda",
|
||||||
"nuxi": "3.12.0",
|
"nuxi": "3.12.0",
|
||||||
"nuxt": "workspace:*",
|
"nuxt": "workspace:*",
|
||||||
"nuxt-content-twoslash": "0.1.0",
|
"nuxt-content-twoslash": "0.1.1",
|
||||||
"ofetch": "1.3.4",
|
"ofetch": "1.3.4",
|
||||||
"pathe": "1.1.2",
|
"pathe": "1.1.2",
|
||||||
"playwright-core": "1.45.1",
|
"playwright-core": "1.45.3",
|
||||||
"rimraf": "6.0.0",
|
"rimraf": "6.0.1",
|
||||||
"semver": "7.6.2",
|
"semver": "7.6.3",
|
||||||
"std-env": "3.7.0",
|
"std-env": "3.7.0",
|
||||||
"typescript": "5.5.3",
|
"typescript": "5.5.4",
|
||||||
"ufo": "1.5.3",
|
"ufo": "1.5.4",
|
||||||
"vitest": "1.6.0",
|
"vitest": "2.0.5",
|
||||||
"vitest-environment-nuxt": "1.0.0",
|
"vitest-environment-nuxt": "1.0.0",
|
||||||
"vue": "3.4.31",
|
"vue": "3.4.34",
|
||||||
"vue-router": "4.4.0",
|
"vue-router": "4.4.2",
|
||||||
"vue-tsc": "2.0.26"
|
"vue-tsc": "2.0.29"
|
||||||
},
|
},
|
||||||
"packageManager": "pnpm@9.4.0",
|
"packageManager": "pnpm@9.6.0",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": "^16.10.0 || >=18.0.0"
|
"node": "^16.10.0 || >=18.0.0"
|
||||||
},
|
},
|
||||||
|
@ -31,6 +31,7 @@
|
|||||||
"consola": "^3.2.3",
|
"consola": "^3.2.3",
|
||||||
"defu": "^6.1.4",
|
"defu": "^6.1.4",
|
||||||
"destr": "^2.0.3",
|
"destr": "^2.0.3",
|
||||||
|
"errx": "^0.1.0",
|
||||||
"globby": "^14.0.2",
|
"globby": "^14.0.2",
|
||||||
"hash-sum": "^2.0.0",
|
"hash-sum": "^2.0.0",
|
||||||
"ignore": "^5.3.1",
|
"ignore": "^5.3.1",
|
||||||
@ -40,20 +41,20 @@
|
|||||||
"pathe": "^1.1.2",
|
"pathe": "^1.1.2",
|
||||||
"pkg-types": "^1.1.3",
|
"pkg-types": "^1.1.3",
|
||||||
"scule": "^1.3.0",
|
"scule": "^1.3.0",
|
||||||
"semver": "^7.6.2",
|
"semver": "^7.6.3",
|
||||||
"ufo": "^1.5.3",
|
"ufo": "^1.5.4",
|
||||||
"unctx": "^2.3.1",
|
"unctx": "^2.3.1",
|
||||||
"unimport": "^3.7.2",
|
"unimport": "^3.10.0",
|
||||||
"untyped": "^1.4.2"
|
"untyped": "^1.4.2"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/hash-sum": "1.0.2",
|
"@types/hash-sum": "1.0.2",
|
||||||
"@types/semver": "7.5.8",
|
"@types/semver": "7.5.8",
|
||||||
"nitro": "npm:nitro-nightly@3.0.0-beta-28665895.e727afda",
|
"nitro": "npm:nitro-nightly@3.0.0-beta-28665895.e727afda",
|
||||||
"unbuild": "3.0.0-rc.6",
|
"unbuild": "3.0.0-rc.7",
|
||||||
"vite": "5.3.3",
|
"vite": "5.3.5",
|
||||||
"vitest": "1.6.0",
|
"vitest": "2.0.5",
|
||||||
"webpack": "5.92.1"
|
"webpack": "5.93.0"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": "^14.18.0 || >=16.10.0"
|
"node": "^14.18.0 || >=16.10.0"
|
||||||
|
@ -30,8 +30,10 @@ export interface ExtendConfigOptions {
|
|||||||
prepend?: boolean
|
prepend?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-empty-object-type
|
||||||
export interface ExtendWebpackConfigOptions extends ExtendConfigOptions {}
|
export interface ExtendWebpackConfigOptions extends ExtendConfigOptions {}
|
||||||
|
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-empty-object-type
|
||||||
export interface ExtendViteConfigOptions extends ExtendConfigOptions {}
|
export interface ExtendViteConfigOptions extends ExtendConfigOptions {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -108,8 +108,8 @@ export function isNuxt3 (nuxt: Nuxt = useNuxt()) {
|
|||||||
*/
|
*/
|
||||||
export function getNuxtVersion (nuxt: Nuxt | any = useNuxt() /* TODO: LegacyNuxt */) {
|
export function getNuxtVersion (nuxt: Nuxt | any = useNuxt() /* TODO: LegacyNuxt */) {
|
||||||
const rawVersion = nuxt?._version || nuxt?.version || nuxt?.constructor?.version
|
const rawVersion = nuxt?._version || nuxt?.version || nuxt?.constructor?.version
|
||||||
if (!rawVersion) {
|
if (typeof rawVersion !== 'string') {
|
||||||
throw new Error('Cannot determine nuxt version! Is current instance passed?')
|
throw new TypeError('Cannot determine nuxt version! Is current instance passed?')
|
||||||
}
|
}
|
||||||
return rawVersion.replace(/^v/g, '')
|
return rawVersion.replace(/^v/g, '')
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import { pathToFileURL } from 'node:url'
|
import { fileURLToPath, pathToFileURL } from 'node:url'
|
||||||
import { interopDefault, resolvePath, resolvePathSync } from 'mlly'
|
import { interopDefault, resolvePath, resolvePathSync } from 'mlly'
|
||||||
import { createJiti } from 'jiti'
|
import { createJiti } from 'jiti'
|
||||||
|
import { captureStackTrace } from 'errx'
|
||||||
|
|
||||||
export interface ResolveModuleOptions {
|
export interface ResolveModuleOptions {
|
||||||
paths?: string | string[]
|
paths?: string | string[]
|
||||||
@ -48,10 +49,12 @@ const warnings = new Set<string>()
|
|||||||
* @deprecated Please use `importModule` instead.
|
* @deprecated Please use `importModule` instead.
|
||||||
*/
|
*/
|
||||||
export function requireModule<T = unknown> (id: string, opts?: ImportModuleOptions) {
|
export function requireModule<T = unknown> (id: string, opts?: ImportModuleOptions) {
|
||||||
if (!warnings.has(id)) {
|
const { source, line, column } = captureStackTrace().find(entry => entry.source !== import.meta.url) ?? {}
|
||||||
// TODO: add more information on stack trace
|
const explanation = source ? ` (used at \`${fileURLToPath(source)}:${line}:${column}\`)` : ''
|
||||||
console.warn('[@nuxt/kit] `requireModule` is deprecated. Please use `importModule` instead.')
|
const warning = `[@nuxt/kit] \`requireModule\` is deprecated${explanation}. Please use \`importModule\` instead.`
|
||||||
warnings.add(id)
|
if (!warnings.has(warning)) {
|
||||||
|
console.warn(warning)
|
||||||
|
warnings.add(warning)
|
||||||
}
|
}
|
||||||
const resolvedPath = resolveModule(id, opts)
|
const resolvedPath = resolveModule(id, opts)
|
||||||
const jiti = createJiti(import.meta.url, {
|
const jiti = createJiti(import.meta.url, {
|
||||||
|
@ -8,10 +8,11 @@ import { globby } from 'globby'
|
|||||||
import defu from 'defu'
|
import defu from 'defu'
|
||||||
|
|
||||||
export interface LoadNuxtConfigOptions extends Omit<LoadConfigOptions<NuxtConfig>, 'overrides'> {
|
export interface LoadNuxtConfigOptions extends Omit<LoadConfigOptions<NuxtConfig>, 'overrides'> {
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-function-type
|
||||||
overrides?: Exclude<LoadConfigOptions<NuxtConfig>['overrides'], Promise<any> | Function>
|
overrides?: Exclude<LoadConfigOptions<NuxtConfig>['overrides'], Promise<any> | Function>
|
||||||
}
|
}
|
||||||
|
|
||||||
const layerSchemaKeys = ['future', 'srcDir', 'rootDir', 'dir']
|
const layerSchemaKeys = ['future', 'srcDir', 'rootDir', 'serverDir', 'dir']
|
||||||
const layerSchema = Object.create(null)
|
const layerSchema = Object.create(null)
|
||||||
for (const key of layerSchemaKeys) {
|
for (const key of layerSchemaKeys) {
|
||||||
if (key in NuxtConfigSchema) {
|
if (key in NuxtConfigSchema) {
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { pathToFileURL } from 'node:url'
|
import { pathToFileURL } from 'node:url'
|
||||||
import { readPackageJSON, resolvePackageJSON } from 'pkg-types'
|
import { readPackageJSON, resolvePackageJSON } from 'pkg-types'
|
||||||
import type { Nuxt } from '@nuxt/schema'
|
import type { Nuxt, NuxtConfig } from '@nuxt/schema'
|
||||||
import { resolve } from 'pathe'
|
import { resolve } from 'pathe'
|
||||||
import { importModule, tryImportModule } from '../internal/esm'
|
import { importModule, tryImportModule } from '../internal/esm'
|
||||||
import type { LoadNuxtConfigOptions } from './config'
|
import type { LoadNuxtConfigOptions } from './config'
|
||||||
@ -16,7 +16,7 @@ export interface LoadNuxtOptions extends LoadNuxtConfigOptions {
|
|||||||
export async function loadNuxt (opts: LoadNuxtOptions): Promise<Nuxt> {
|
export async function loadNuxt (opts: LoadNuxtOptions): Promise<Nuxt> {
|
||||||
// Backward compatibility
|
// Backward compatibility
|
||||||
opts.cwd = resolve(opts.cwd || (opts as any).rootDir /* backwards compat */ || '.')
|
opts.cwd = resolve(opts.cwd || (opts as any).rootDir /* backwards compat */ || '.')
|
||||||
opts.overrides = opts.overrides || (opts as any).config as {} /* backwards compat */ || {}
|
opts.overrides = opts.overrides || (opts as any).config as NuxtConfig /* backwards compat */ || {}
|
||||||
|
|
||||||
// Apply dev as config override
|
// Apply dev as config override
|
||||||
opts.overrides.dev = !!opts.dev
|
opts.overrides.dev = !!opts.dev
|
||||||
|
@ -55,10 +55,10 @@ function _defineNuxtModule<
|
|||||||
inlineOptions?: Partial<TOptions>,
|
inlineOptions?: Partial<TOptions>,
|
||||||
nuxt: Nuxt = useNuxt(),
|
nuxt: Nuxt = useNuxt(),
|
||||||
): Promise<
|
): Promise<
|
||||||
TWith extends true
|
TWith extends true
|
||||||
? ResolvedModuleOptions<TOptions, TOptionsDefaults>
|
? ResolvedModuleOptions<TOptions, TOptionsDefaults>
|
||||||
: TOptions
|
: TOptions
|
||||||
> {
|
> {
|
||||||
const nuxtConfigOptionsKey = module.meta.configKey || module.meta.name
|
const nuxtConfigOptionsKey = module.meta.configKey || module.meta.name
|
||||||
|
|
||||||
const nuxtConfigOptions: Partial<TOptions> = nuxtConfigOptionsKey && nuxtConfigOptionsKey in nuxt.options ? nuxt.options[<keyof NuxtOptions> nuxtConfigOptionsKey] : {}
|
const nuxtConfigOptions: Partial<TOptions> = nuxtConfigOptionsKey && nuxtConfigOptionsKey in nuxt.options ? nuxt.options[<keyof NuxtOptions> nuxtConfigOptionsKey] : {}
|
||||||
|
@ -59,7 +59,7 @@ export function getDirectory (p: string) {
|
|||||||
// we need to target directories instead of module file paths themselves
|
// we need to target directories instead of module file paths themselves
|
||||||
// /home/user/project/node_modules/module/index.js -> /home/user/project/node_modules/module
|
// /home/user/project/node_modules/module/index.js -> /home/user/project/node_modules/module
|
||||||
return isAbsolute(p) && lstatSync(p).isFile() ? dirname(p) : p
|
return isAbsolute(p) && lstatSync(p).isFile() ? dirname(p) : p
|
||||||
} catch (e) {
|
} catch {
|
||||||
// maybe the path is absolute but does not exist, allow this to bubble up
|
// maybe the path is absolute but does not exist, allow this to bubble up
|
||||||
}
|
}
|
||||||
return p
|
return p
|
||||||
|
@ -158,6 +158,8 @@ export async function _generateTypes (nuxt: Nuxt) {
|
|||||||
const relative = relativeWithDot(nuxt.options.buildDir, path)
|
const relative = relativeWithDot(nuxt.options.buildDir, path)
|
||||||
include.add(join(relative, 'runtime'))
|
include.add(join(relative, 'runtime'))
|
||||||
exclude.add(join(relative, 'runtime/server'))
|
exclude.add(join(relative, 'runtime/server'))
|
||||||
|
include.add(join(relative, 'dist/runtime'))
|
||||||
|
exclude.add(join(relative, 'dist/runtime/server'))
|
||||||
}
|
}
|
||||||
|
|
||||||
const isV4 = nuxt.options.future?.compatibilityVersion === 4
|
const isV4 = nuxt.options.future?.compatibilityVersion === 4
|
||||||
|
1
packages/nuxt/config.d.ts
vendored
1
packages/nuxt/config.d.ts
vendored
@ -3,5 +3,6 @@ import type { ConfigLayerMeta, DefineConfig } from 'c12'
|
|||||||
|
|
||||||
export { NuxtConfig } from 'nuxt/schema'
|
export { NuxtConfig } from 'nuxt/schema'
|
||||||
|
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-empty-object-type
|
||||||
export interface DefineNuxtConfig extends DefineConfig<NuxtConfig, ConfigLayerMeta> {}
|
export interface DefineNuxtConfig extends DefineConfig<NuxtConfig, ConfigLayerMeta> {}
|
||||||
export declare const defineNuxtConfig: DefineNuxtConfig
|
export declare const defineNuxtConfig: DefineNuxtConfig
|
||||||
|
3
packages/nuxt/index.d.ts
vendored
3
packages/nuxt/index.d.ts
vendored
@ -12,7 +12,8 @@ declare global {
|
|||||||
|
|
||||||
interface Window {
|
interface Window {
|
||||||
cookieStore?: {
|
cookieStore?: {
|
||||||
onchange: (event: any) => void
|
addEventListener: (type: 'change', listener: (event: any) => void) => void
|
||||||
|
removeEventListener: (type: 'change', listener: (event: any) => void) => void
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -65,19 +65,20 @@
|
|||||||
"@nuxt/schema": "workspace:*",
|
"@nuxt/schema": "workspace:*",
|
||||||
"@nuxt/telemetry": "^2.5.4",
|
"@nuxt/telemetry": "^2.5.4",
|
||||||
"@nuxt/vite-builder": "workspace:*",
|
"@nuxt/vite-builder": "workspace:*",
|
||||||
"@unhead/dom": "^1.9.15",
|
"@unhead/dom": "^1.9.16",
|
||||||
"@unhead/ssr": "^1.9.15",
|
"@unhead/ssr": "^1.9.16",
|
||||||
"@unhead/vue": "^1.9.15",
|
"@unhead/vue": "^1.9.16",
|
||||||
"@vue/shared": "^3.4.31",
|
"@vue/shared": "^3.4.34",
|
||||||
"acorn": "8.12.1",
|
"acorn": "8.12.1",
|
||||||
"c12": "^2.0.0-beta.1",
|
"c12": "^2.0.0-beta.1",
|
||||||
"chokidar": "^3.6.0",
|
"chokidar": "^3.6.0",
|
||||||
"compatx": "^0.1.8",
|
"compatx": "^0.1.8",
|
||||||
"consola": "^3.2.3",
|
"consola": "^3.2.3",
|
||||||
"cookie-es": "^1.1.0",
|
"cookie-es": "^1.2.2",
|
||||||
"defu": "^6.1.4",
|
"defu": "^6.1.4",
|
||||||
"destr": "^2.0.3",
|
"destr": "^2.0.3",
|
||||||
"devalue": "^5.0.0",
|
"devalue": "^5.0.0",
|
||||||
|
"errx": "^0.1.0",
|
||||||
"esbuild": "^0.23.0",
|
"esbuild": "^0.23.0",
|
||||||
"escape-string-regexp": "^5.0.0",
|
"escape-string-regexp": "^5.0.0",
|
||||||
"estree-walker": "^3.0.3",
|
"estree-walker": "^3.0.3",
|
||||||
@ -88,7 +89,7 @@
|
|||||||
"jiti": "^2.0.0-beta.3",
|
"jiti": "^2.0.0-beta.3",
|
||||||
"klona": "^2.0.6",
|
"klona": "^2.0.6",
|
||||||
"knitwork": "^1.1.0",
|
"knitwork": "^1.1.0",
|
||||||
"magic-string": "^0.30.10",
|
"magic-string": "^0.30.11",
|
||||||
"mlly": "^1.7.1",
|
"mlly": "^1.7.1",
|
||||||
"nitro": "npm:nitro-nightly@3.0.0-beta-28665895.e727afda",
|
"nitro": "npm:nitro-nightly@3.0.0-beta-28665895.e727afda",
|
||||||
"nuxi": "^3.12.0",
|
"nuxi": "^3.12.0",
|
||||||
@ -100,34 +101,34 @@
|
|||||||
"pkg-types": "^1.1.3",
|
"pkg-types": "^1.1.3",
|
||||||
"radix3": "^1.1.2",
|
"radix3": "^1.1.2",
|
||||||
"scule": "^1.3.0",
|
"scule": "^1.3.0",
|
||||||
"semver": "^7.6.2",
|
"semver": "^7.6.3",
|
||||||
"std-env": "^3.7.0",
|
"std-env": "^3.7.0",
|
||||||
"strip-literal": "^2.1.0",
|
"strip-literal": "^2.1.0",
|
||||||
"ufo": "^1.5.3",
|
"ufo": "^1.5.4",
|
||||||
"ultrahtml": "^1.5.3",
|
"ultrahtml": "^1.5.3",
|
||||||
"uncrypto": "^0.1.3",
|
"uncrypto": "^0.1.3",
|
||||||
"unctx": "^2.3.1",
|
"unctx": "^2.3.1",
|
||||||
"unenv": "^1.9.0",
|
"unenv": "^1.10.0",
|
||||||
"unimport": "^3.7.2",
|
"unimport": "^3.10.0",
|
||||||
"unplugin": "^1.11.0",
|
"unplugin": "^1.12.0",
|
||||||
"unplugin-vue-router": "^0.10.0",
|
"unplugin-vue-router": "^0.10.2",
|
||||||
"unstorage": "^1.10.2",
|
"unstorage": "^1.10.2",
|
||||||
"untyped": "^1.4.2",
|
"untyped": "^1.4.2",
|
||||||
"vue": "^3.4.31",
|
"vue": "^3.4.34",
|
||||||
"vue-bundle-renderer": "^2.1.0",
|
"vue-bundle-renderer": "^2.1.0",
|
||||||
"vue-devtools-stub": "^0.1.0",
|
"vue-devtools-stub": "^0.1.0",
|
||||||
"vue-router": "^4.4.0"
|
"vue-router": "^4.4.2"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@nuxt/scripts": "0.5.1",
|
"@nuxt/scripts": "0.6.5",
|
||||||
"@nuxt/ui-templates": "1.3.4",
|
"@nuxt/ui-templates": "1.3.4",
|
||||||
"@parcel/watcher": "2.4.1",
|
"@parcel/watcher": "2.4.1",
|
||||||
"@types/estree": "1.0.5",
|
"@types/estree": "1.0.5",
|
||||||
"@vitejs/plugin-vue": "5.0.5",
|
"@vitejs/plugin-vue": "5.1.2",
|
||||||
"@vue/compiler-sfc": "3.4.31",
|
"@vue/compiler-sfc": "3.4.34",
|
||||||
"unbuild": "3.0.0-rc.6",
|
"unbuild": "3.0.0-rc.7",
|
||||||
"vite": "5.3.3",
|
"vite": "5.3.5",
|
||||||
"vitest": "1.6.0"
|
"vitest": "2.0.5"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@parcel/watcher": "^2.1.0",
|
"@parcel/watcher": "^2.1.0",
|
||||||
|
@ -60,10 +60,10 @@ export interface AsyncDataOptions<
|
|||||||
default?: () => DefaultT | Ref<DefaultT>
|
default?: () => DefaultT | Ref<DefaultT>
|
||||||
/**
|
/**
|
||||||
* Provide a function which returns cached data.
|
* Provide a function which returns cached data.
|
||||||
* A `null` or `undefined` return value will trigger a fetch.
|
* An `undefined` return value will trigger a fetch.
|
||||||
* Default is `key => nuxt.isHydrating ? nuxt.payload.data[key] : nuxt.static.data[key]` which only caches data when payloadExtraction is enabled.
|
* Default is `key => nuxt.isHydrating ? nuxt.payload.data[key] : nuxt.static.data[key]` which only caches data when payloadExtraction is enabled.
|
||||||
*/
|
*/
|
||||||
getCachedData?: (key: string, nuxtApp: NuxtApp) => NoInfer<DataT>
|
getCachedData?: (key: string, nuxtApp: NuxtApp) => NoInfer<DataT> | undefined
|
||||||
/**
|
/**
|
||||||
* A function that can be used to alter handler function result after resolving.
|
* A function that can be used to alter handler function result after resolving.
|
||||||
* Do not use it along with the `pick` option.
|
* Do not use it along with the `pick` option.
|
||||||
@ -100,9 +100,6 @@ export interface AsyncDataExecuteOptions {
|
|||||||
* Force a refresh, even if there is already a pending request. Previous requests will
|
* Force a refresh, even if there is already a pending request. Previous requests will
|
||||||
* not be cancelled, but their result will not affect the data/pending state - and any
|
* not be cancelled, but their result will not affect the data/pending state - and any
|
||||||
* previously awaited promises will not resolve until this new request resolves.
|
* previously awaited promises will not resolve until this new request resolves.
|
||||||
*
|
|
||||||
* Instead of using `boolean` values, use `cancel` for `true` and `defer` for `false`.
|
|
||||||
* Boolean values will be removed in a future release.
|
|
||||||
*/
|
*/
|
||||||
dedupe?: 'cancel' | 'defer'
|
dedupe?: 'cancel' | 'defer'
|
||||||
}
|
}
|
||||||
@ -122,9 +119,6 @@ export interface _AsyncData<DataT, ErrorT> {
|
|||||||
|
|
||||||
export type AsyncData<Data, Error> = _AsyncData<Data, Error> & Promise<_AsyncData<Data, Error>>
|
export type AsyncData<Data, Error> = _AsyncData<Data, Error> & Promise<_AsyncData<Data, Error>>
|
||||||
|
|
||||||
// TODO: remove boolean option in Nuxt 4
|
|
||||||
const isDefer = (dedupe?: boolean | 'cancel' | 'defer') => dedupe === 'defer' || dedupe === false
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provides access to data that resolves asynchronously in an SSR-friendly composable.
|
* Provides access to data that resolves asynchronously in an SSR-friendly composable.
|
||||||
* See {@link https://nuxt.com/docs/api/composables/use-async-data}
|
* See {@link https://nuxt.com/docs/api/composables/use-async-data}
|
||||||
@ -180,7 +174,7 @@ export function useAsyncData<
|
|||||||
* Provides access to data that resolves asynchronously in an SSR-friendly composable.
|
* Provides access to data that resolves asynchronously in an SSR-friendly composable.
|
||||||
* See {@link https://nuxt.com/docs/api/composables/use-async-data}
|
* See {@link https://nuxt.com/docs/api/composables/use-async-data}
|
||||||
* @param key A unique key to ensure that data fetching can be properly de-duplicated across requests.
|
* @param key A unique key to ensure that data fetching can be properly de-duplicated across requests.
|
||||||
* @param handler An asynchronous function that must return a truthy value (for example, it should not be `undefined` or `null`) or the request may be duplicated on the client side.
|
* @param handler An asynchronous function that must return a value (it should not be `undefined`) or the request may be duplicated on the client side.
|
||||||
* @param options customize the behavior of useAsyncData
|
* @param options customize the behavior of useAsyncData
|
||||||
*/
|
*/
|
||||||
export function useAsyncData<
|
export function useAsyncData<
|
||||||
@ -245,21 +239,17 @@ export function useAsyncData<
|
|||||||
options.deep = options.deep ?? asyncDataDefaults.deep
|
options.deep = options.deep ?? asyncDataDefaults.deep
|
||||||
options.dedupe = options.dedupe ?? 'cancel'
|
options.dedupe = options.dedupe ?? 'cancel'
|
||||||
|
|
||||||
if (import.meta.dev && typeof options.dedupe === 'boolean') {
|
|
||||||
console.warn('[nuxt] `boolean` values are deprecated for the `dedupe` option of `useAsyncData` and will be removed in the future. Use \'cancel\' or \'defer\' instead.')
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: make more precise when v4 lands
|
// TODO: make more precise when v4 lands
|
||||||
const hasCachedData = () => options.getCachedData!(key, nuxtApp) != null
|
const hasCachedData = () => options.getCachedData!(key, nuxtApp) !== undefined
|
||||||
|
|
||||||
// Create or use a shared asyncData entity
|
// Create or use a shared asyncData entity
|
||||||
if (!nuxtApp._asyncData[key] || !options.immediate) {
|
if (!nuxtApp._asyncData[key] || !options.immediate) {
|
||||||
nuxtApp.payload._errors[key] ??= undefined
|
nuxtApp.payload._errors[key] ??= undefined
|
||||||
|
|
||||||
const _ref = options.deep ? ref : shallowRef
|
const _ref = options.deep ? ref : shallowRef
|
||||||
|
const cachedData = options.getCachedData!(key, nuxtApp)
|
||||||
nuxtApp._asyncData[key] = {
|
nuxtApp._asyncData[key] = {
|
||||||
data: _ref(options.getCachedData!(key, nuxtApp) ?? options.default!()),
|
data: _ref(typeof cachedData !== 'undefined' ? cachedData : options.default!()),
|
||||||
pending: ref(!hasCachedData()),
|
pending: ref(!hasCachedData()),
|
||||||
error: toRef(nuxtApp.payload._errors, key),
|
error: toRef(nuxtApp.payload._errors, key),
|
||||||
status: ref('idle'),
|
status: ref('idle'),
|
||||||
@ -275,7 +265,7 @@ export function useAsyncData<
|
|||||||
|
|
||||||
asyncData.refresh = asyncData.execute = (opts = {}) => {
|
asyncData.refresh = asyncData.execute = (opts = {}) => {
|
||||||
if (nuxtApp._asyncDataPromises[key]) {
|
if (nuxtApp._asyncDataPromises[key]) {
|
||||||
if (isDefer(opts.dedupe ?? options.dedupe)) {
|
if ((opts.dedupe ?? options.dedupe) === 'defer') {
|
||||||
// Avoid fetching same key more than once at a time
|
// Avoid fetching same key more than once at a time
|
||||||
return nuxtApp._asyncDataPromises[key]!
|
return nuxtApp._asyncDataPromises[key]!
|
||||||
}
|
}
|
||||||
@ -308,9 +298,9 @@ export function useAsyncData<
|
|||||||
result = pick(result as any, options.pick) as DataT
|
result = pick(result as any, options.pick) as DataT
|
||||||
}
|
}
|
||||||
|
|
||||||
if (import.meta.dev && import.meta.server && !result) {
|
if (import.meta.dev && import.meta.server && typeof result === 'undefined') {
|
||||||
// @ts-expect-error private property
|
// @ts-expect-error private property
|
||||||
console.warn(`[nuxt] \`${options._functionName || 'useAsyncData'}\` must return a truthy value (for example, it should not be \`undefined\`, \`null\` or empty string) or the request may be duplicated on the client side.`)
|
console.warn(`[nuxt] \`${options._functionName || 'useAsyncData'}\` must return a value (it should not be \`undefined\`) or the request may be duplicated on the client side.`)
|
||||||
}
|
}
|
||||||
|
|
||||||
nuxtApp.payload.data[key] = result
|
nuxtApp.payload.data[key] = result
|
||||||
|
@ -23,6 +23,7 @@ export interface CookieOptions<T = any> extends _CookieOptions {
|
|||||||
readonly?: boolean
|
readonly?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-empty-object-type
|
||||||
export interface CookieRef<T> extends Ref<T> {}
|
export interface CookieRef<T> extends Ref<T> {}
|
||||||
|
|
||||||
const CookieDefaults = {
|
const CookieDefaults = {
|
||||||
@ -83,13 +84,16 @@ export function useCookie<T = string | null | undefined> (name: string, _opts?:
|
|||||||
const handleChange = (data: { value?: any, refresh?: boolean }) => {
|
const handleChange = (data: { value?: any, refresh?: boolean }) => {
|
||||||
const value = data.refresh ? readRawCookies(opts)?.[name] : opts.decode(data.value)
|
const value = data.refresh ? readRawCookies(opts)?.[name] : opts.decode(data.value)
|
||||||
watchPaused = true
|
watchPaused = true
|
||||||
cookies[name] = cookie.value = value
|
cookie.value = value
|
||||||
|
cookies[name] = klona(value)
|
||||||
nextTick(() => { watchPaused = false })
|
nextTick(() => { watchPaused = false })
|
||||||
}
|
}
|
||||||
|
|
||||||
let watchPaused = false
|
let watchPaused = false
|
||||||
|
|
||||||
if (getCurrentScope()) {
|
const hasScope = !!getCurrentScope()
|
||||||
|
|
||||||
|
if (hasScope) {
|
||||||
onScopeDispose(() => {
|
onScopeDispose(() => {
|
||||||
watchPaused = true
|
watchPaused = true
|
||||||
callback()
|
callback()
|
||||||
@ -98,10 +102,14 @@ export function useCookie<T = string | null | undefined> (name: string, _opts?:
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (store) {
|
if (store) {
|
||||||
store.onchange = (event) => {
|
const changeHandler = (event: any) => {
|
||||||
const cookie = event.changed.find((c: any) => c.name === name)
|
const cookie = event.changed.find((c: any) => c.name === name)
|
||||||
if (cookie) { handleChange({ value: cookie.value }) }
|
if (cookie) { handleChange({ value: cookie.value }) }
|
||||||
}
|
}
|
||||||
|
store.addEventListener('change', changeHandler)
|
||||||
|
if (hasScope) {
|
||||||
|
onScopeDispose(() => store.removeEventListener('change', changeHandler))
|
||||||
|
}
|
||||||
} else if (channel) {
|
} else if (channel) {
|
||||||
channel.onmessage = ({ data }) => handleChange(data)
|
channel.onmessage = ({ data }) => handleChange(data)
|
||||||
}
|
}
|
||||||
@ -119,6 +127,16 @@ export function useCookie<T = string | null | undefined> (name: string, _opts?:
|
|||||||
const nuxtApp = useNuxtApp()
|
const nuxtApp = useNuxtApp()
|
||||||
const writeFinalCookieValue = () => {
|
const writeFinalCookieValue = () => {
|
||||||
if (opts.readonly || isEqual(cookie.value, cookies[name])) { return }
|
if (opts.readonly || isEqual(cookie.value, cookies[name])) { return }
|
||||||
|
nuxtApp._cookies ||= {}
|
||||||
|
if (name in nuxtApp._cookies) {
|
||||||
|
// do not append a second `set-cookie` header
|
||||||
|
if (isEqual(cookie.value, nuxtApp._cookies[name])) { return }
|
||||||
|
// warn in dev mode
|
||||||
|
if (import.meta.dev) {
|
||||||
|
console.warn(`[nuxt] cookie \`${name}\` was previously set to \`${opts.encode(nuxtApp._cookies[name] as any)}\` and is being overridden to \`${opts.encode(cookie.value as any)}\`. This may cause unexpected issues.`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
nuxtApp._cookies[name] = cookie.value
|
||||||
writeServerCookie(useRequestEvent(nuxtApp)!, name, cookie.value, opts as CookieOptions<any>)
|
writeServerCookie(useRequestEvent(nuxtApp)!, name, cookie.value, opts as CookieOptions<any>)
|
||||||
}
|
}
|
||||||
const unhook = nuxtApp.hooks.hookOnce('app:rendered', writeFinalCookieValue)
|
const unhook = nuxtApp.hooks.hookOnce('app:rendered', writeFinalCookieValue)
|
||||||
|
@ -9,6 +9,7 @@ export const NUXT_ERROR_SIGNATURE = '__nuxt_error'
|
|||||||
/** @since 3.0.0 */
|
/** @since 3.0.0 */
|
||||||
export const useError = () => toRef(useNuxtApp().payload, 'error')
|
export const useError = () => toRef(useNuxtApp().payload, 'error')
|
||||||
|
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-empty-object-type
|
||||||
export interface NuxtError<DataT = unknown> extends H3Error<DataT> {}
|
export interface NuxtError<DataT = unknown> extends H3Error<DataT> {}
|
||||||
|
|
||||||
/** @since 3.0.0 */
|
/** @since 3.0.0 */
|
||||||
|
@ -17,6 +17,7 @@ type AvailableRouterMethod<R extends NitroFetchRequest> = _AvailableRouterMethod
|
|||||||
export type FetchResult<ReqT extends NitroFetchRequest, M extends AvailableRouterMethod<ReqT>> = TypedInternalResponse<ReqT, unknown, Lowercase<M>>
|
export type FetchResult<ReqT extends NitroFetchRequest, M extends AvailableRouterMethod<ReqT>> = TypedInternalResponse<ReqT, unknown, Lowercase<M>>
|
||||||
|
|
||||||
type ComputedOptions<T extends Record<string, any>> = {
|
type ComputedOptions<T extends Record<string, any>> = {
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-function-type
|
||||||
[K in keyof T]: T[K] extends Function ? T[K] : ComputedOptions<T[K]> | Ref<T[K]> | T[K]
|
[K in keyof T]: T[K] extends Function ? T[K] : ComputedOptions<T[K]> | Ref<T[K]> | T[K]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -38,7 +38,7 @@ function _loadAsyncComponent (component: Component) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** @since 3.0.0 */
|
/** @since 3.0.0 */
|
||||||
export async function preloadRouteComponents (to: RouteLocationRaw, router: Router & { _routePreloaded?: Set<string>, _preloadPromises?: Array<Promise<any>> } = useRouter()): Promise<void> {
|
export async function preloadRouteComponents (to: RouteLocationRaw, router: Router & { _routePreloaded?: Set<string>, _preloadPromises?: Array<Promise<unknown>> } = useRouter()): Promise<void> {
|
||||||
if (import.meta.server) { return }
|
if (import.meta.server) { return }
|
||||||
|
|
||||||
const { path, matched } = router.resolve(to)
|
const { path, matched } = router.resolve(to)
|
||||||
@ -61,7 +61,7 @@ export async function preloadRouteComponents (to: RouteLocationRaw, router: Rout
|
|||||||
.filter(component => typeof component === 'function')
|
.filter(component => typeof component === 'function')
|
||||||
|
|
||||||
for (const component of components) {
|
for (const component of components) {
|
||||||
const promise = Promise.resolve((component as Function)())
|
const promise = Promise.resolve((component as () => unknown)())
|
||||||
.catch(() => {})
|
.catch(() => {})
|
||||||
.finally(() => promises.splice(promises.indexOf(promise)))
|
.finally(() => promises.splice(promises.indexOf(promise)))
|
||||||
promises.push(promise)
|
promises.push(promise)
|
||||||
|
@ -91,7 +91,7 @@ const isProcessingMiddleware = () => {
|
|||||||
|
|
||||||
// Conditional types, either one or other
|
// Conditional types, either one or other
|
||||||
type Without<T, U> = { [P in Exclude<keyof T, keyof U>]?: never }
|
type Without<T, U> = { [P in Exclude<keyof T, keyof U>]?: never }
|
||||||
type XOR<T, U> = (T | U) extends Object ? (Without<T, U> & U) | (Without<U, T> & T) : T | U
|
type XOR<T, U> = (T | U) extends object ? (Without<T, U> & U) | (Without<U, T> & T) : T | U
|
||||||
|
|
||||||
export type OpenWindowFeatures = {
|
export type OpenWindowFeatures = {
|
||||||
popup?: boolean
|
popup?: boolean
|
||||||
|
@ -45,6 +45,10 @@ export function useScriptCloudflareWebAnalytics (...args: unknown[]) {
|
|||||||
renderStubMessage('useScriptCloudflareWebAnalytics')
|
renderStubMessage('useScriptCloudflareWebAnalytics')
|
||||||
}
|
}
|
||||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
|
export function useScriptCrisp (...args: unknown[]) {
|
||||||
|
renderStubMessage('useScriptCrisp')
|
||||||
|
}
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
export function useScriptFathomAnalytics (...args: unknown[]) {
|
export function useScriptFathomAnalytics (...args: unknown[]) {
|
||||||
renderStubMessage('useScriptFathomAnalytics')
|
renderStubMessage('useScriptFathomAnalytics')
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,7 @@ import { useNuxtApp } from './nuxt'
|
|||||||
// @ts-expect-error virtual file
|
// @ts-expect-error virtual file
|
||||||
import __appConfig from '#build/app.config.mjs'
|
import __appConfig from '#build/app.config.mjs'
|
||||||
|
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-function-type
|
||||||
type DeepPartial<T> = T extends Function ? T : T extends Record<string, any> ? { [P in keyof T]?: DeepPartial<T[P]> } : T
|
type DeepPartial<T> = T extends Function ? T : T extends Record<string, any> ? { [P in keyof T]?: DeepPartial<T[P]> } : T
|
||||||
|
|
||||||
// Workaround for vite HMR with virtual modules
|
// Workaround for vite HMR with virtual modules
|
||||||
|
@ -101,7 +101,6 @@ interface _NuxtApp {
|
|||||||
/** @internal */
|
/** @internal */
|
||||||
_name: string
|
_name: string
|
||||||
vueApp: App<Element>
|
vueApp: App<Element>
|
||||||
globalName: string
|
|
||||||
versions: Record<string, string>
|
versions: Record<string, string>
|
||||||
|
|
||||||
hooks: Hookable<RuntimeNuxtHooks>
|
hooks: Hookable<RuntimeNuxtHooks>
|
||||||
@ -112,6 +111,8 @@ interface _NuxtApp {
|
|||||||
|
|
||||||
[key: string]: unknown
|
[key: string]: unknown
|
||||||
|
|
||||||
|
/** @internal */
|
||||||
|
_cookies?: Record<string, unknown>
|
||||||
/** @internal */
|
/** @internal */
|
||||||
_id?: number
|
_id?: number
|
||||||
/** @internal */
|
/** @internal */
|
||||||
@ -183,6 +184,7 @@ interface _NuxtApp {
|
|||||||
provide: (name: string, value: any) => void
|
provide: (name: string, value: any) => void
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-empty-object-type
|
||||||
export interface NuxtApp extends _NuxtApp {}
|
export interface NuxtApp extends _NuxtApp {}
|
||||||
|
|
||||||
export const NuxtPluginIndicator = '__nuxt_plugin'
|
export const NuxtPluginIndicator = '__nuxt_plugin'
|
||||||
@ -242,7 +244,6 @@ export type ObjectPluginInput<Injections extends Record<string, unknown> = Recor
|
|||||||
export interface CreateOptions {
|
export interface CreateOptions {
|
||||||
vueApp: NuxtApp['vueApp']
|
vueApp: NuxtApp['vueApp']
|
||||||
ssrContext?: NuxtApp['ssrContext']
|
ssrContext?: NuxtApp['ssrContext']
|
||||||
globalName?: NuxtApp['globalName']
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @since 3.0.0 */
|
/** @since 3.0.0 */
|
||||||
@ -252,7 +253,6 @@ export function createNuxtApp (options: CreateOptions) {
|
|||||||
_name: appId || 'nuxt-app',
|
_name: appId || 'nuxt-app',
|
||||||
_scope: effectScope(),
|
_scope: effectScope(),
|
||||||
provide: undefined,
|
provide: undefined,
|
||||||
globalName: 'nuxt',
|
|
||||||
versions: {
|
versions: {
|
||||||
get nuxt () { return __NUXT_VERSION__ },
|
get nuxt () { return __NUXT_VERSION__ },
|
||||||
get vue () { return nuxtApp.vueApp.version },
|
get vue () { return nuxtApp.vueApp.version },
|
||||||
|
@ -17,7 +17,11 @@ export default defineNuxtPlugin({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (import.meta.server) {
|
if (import.meta.server) {
|
||||||
nuxtApp.hook('app:rendered', ({ renderResult }) => { renderResult?.html && nextTick(checkIfLayoutUsed) })
|
nuxtApp.hook('app:rendered', ({ renderResult }) => {
|
||||||
|
if (renderResult?.html) {
|
||||||
|
nextTick(checkIfLayoutUsed)
|
||||||
|
}
|
||||||
|
})
|
||||||
} else {
|
} else {
|
||||||
onNuxtReady(checkIfLayoutUsed)
|
onNuxtReady(checkIfLayoutUsed)
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import { createConsola } from 'consola'
|
import { createConsola } from 'consola'
|
||||||
import type { LogObject } from 'consola'
|
import type { LogObject } from 'consola'
|
||||||
import { parse } from 'devalue'
|
import { parse } from 'devalue'
|
||||||
|
import type { ParsedTrace } from 'errx'
|
||||||
|
|
||||||
import { h } from 'vue'
|
import { h } from 'vue'
|
||||||
import { defineNuxtPlugin } from '../nuxt'
|
import { defineNuxtPlugin } from '../nuxt'
|
||||||
@ -45,15 +46,24 @@ export default defineNuxtPlugin(async (nuxtApp) => {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
function normalizeFilenames (stack?: string) {
|
function normalizeFilenames (stack?: ParsedTrace[]) {
|
||||||
stack = stack?.split('\n')[0] || ''
|
if (!stack) {
|
||||||
stack = stack.replace(`${devRootDir}/`, '')
|
return ''
|
||||||
stack = stack.replace(/:\d+:\d+\)?$/, '')
|
}
|
||||||
return stack
|
let message = ''
|
||||||
|
for (const item of stack) {
|
||||||
|
const source = item.source.replace(`${devRootDir}/`, '')
|
||||||
|
if (item.function) {
|
||||||
|
message += ` at ${item.function} (${source})\n`
|
||||||
|
} else {
|
||||||
|
message += ` at ${source}\n`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return message
|
||||||
}
|
}
|
||||||
|
|
||||||
function normalizeServerLog (log: LogObject) {
|
function normalizeServerLog (log: LogObject) {
|
||||||
log.additional = normalizeFilenames(log.stack as string)
|
log.additional = normalizeFilenames(log.stack as ParsedTrace[])
|
||||||
log.tag = 'ssr'
|
log.tag = 'ssr'
|
||||||
delete log.stack
|
delete log.stack
|
||||||
return log
|
return log
|
||||||
|
@ -77,7 +77,7 @@ interface RouterHooks {
|
|||||||
interface Router {
|
interface Router {
|
||||||
currentRoute: Ref<Route>
|
currentRoute: Ref<Route>
|
||||||
isReady: () => Promise<void>
|
isReady: () => Promise<void>
|
||||||
options: {}
|
options: Record<string, unknown>
|
||||||
install: () => Promise<void>
|
install: () => Promise<void>
|
||||||
// Navigation
|
// Navigation
|
||||||
push: (url: string) => Promise<void>
|
push: (url: string) => Promise<void>
|
||||||
|
2
packages/nuxt/src/app/types/augments.d.ts
vendored
2
packages/nuxt/src/app/types/augments.d.ts
vendored
@ -40,7 +40,7 @@ declare module 'vue' {
|
|||||||
$nuxt: NuxtApp
|
$nuxt: NuxtApp
|
||||||
}
|
}
|
||||||
interface ComponentInternalInstance {
|
interface ComponentInternalInstance {
|
||||||
_nuxtOnBeforeMountCbs: Function[]
|
_nuxtOnBeforeMountCbs: Array<() => void | Promise<void>>
|
||||||
_nuxtIdIndex?: Record<string, number>
|
_nuxtIdIndex?: Record<string, number>
|
||||||
}
|
}
|
||||||
interface ComponentCustomOptions {
|
interface ComponentCustomOptions {
|
||||||
|
@ -13,7 +13,7 @@ import { componentsChunkPlugin, islandsTransform } from './islandsTransform'
|
|||||||
import { createTransformPlugin } from './transform'
|
import { createTransformPlugin } from './transform'
|
||||||
|
|
||||||
const isPureObjectOrString = (val: any) => (!Array.isArray(val) && typeof val === 'object') || typeof val === 'string'
|
const isPureObjectOrString = (val: any) => (!Array.isArray(val) && typeof val === 'object') || typeof val === 'string'
|
||||||
const isDirectory = (p: string) => { try { return statSync(p).isDirectory() } catch (_e) { return false } }
|
const isDirectory = (p: string) => { try { return statSync(p).isDirectory() } catch { return false } }
|
||||||
function compareDirByPathLength ({ path: pathA }: { path: string }, { path: pathB }: { path: string }) {
|
function compareDirByPathLength ({ path: pathA }: { path: string }, { path: pathB }: { path: string }) {
|
||||||
return pathB.split(/[\\/]/).filter(Boolean).length - pathA.split(/[\\/]/).filter(Boolean).length
|
return pathB.split(/[\\/]/).filter(Boolean).length - pathA.split(/[\\/]/).filter(Boolean).length
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,13 @@ import ClientOnly from '#app/components/client-only'
|
|||||||
|
|
||||||
/* @__NO_SIDE_EFFECTS__ */
|
/* @__NO_SIDE_EFFECTS__ */
|
||||||
export const createClientPage = (loader: AsyncComponentLoader) => {
|
export const createClientPage = (loader: AsyncComponentLoader) => {
|
||||||
const page = defineAsyncComponent(loader)
|
const page = defineAsyncComponent(import.meta.dev
|
||||||
|
? () => loader().then((m) => {
|
||||||
|
// mark component as client-only for `definePageMeta`
|
||||||
|
(m.default || m).__clientOnlyPage = true
|
||||||
|
return m.default || m
|
||||||
|
})
|
||||||
|
: loader)
|
||||||
|
|
||||||
return defineComponent({
|
return defineComponent({
|
||||||
inheritAttrs: false,
|
inheritAttrs: false,
|
||||||
|
@ -5,6 +5,8 @@ import { stringify } from 'devalue'
|
|||||||
import type { H3Event } from 'h3'
|
import type { H3Event } from 'h3'
|
||||||
import { withTrailingSlash } from 'ufo'
|
import { withTrailingSlash } from 'ufo'
|
||||||
import { getContext } from 'unctx'
|
import { getContext } from 'unctx'
|
||||||
|
import { captureRawStackTrace, parseRawStackTrace } from 'errx'
|
||||||
|
import type { ParsedTrace } from 'errx'
|
||||||
|
|
||||||
import { isVNode } from 'vue'
|
import { isVNode } from 'vue'
|
||||||
import type { NitroApp } from 'nitro/types'
|
import type { NitroApp } from 'nitro/types'
|
||||||
@ -34,15 +36,28 @@ export default (nitroApp: NitroApp) => {
|
|||||||
const ctx = asyncContext.tryUse()
|
const ctx = asyncContext.tryUse()
|
||||||
if (!ctx) { return }
|
if (!ctx) { return }
|
||||||
|
|
||||||
const stack = getStack()
|
const rawStack = captureRawStackTrace()
|
||||||
if (stack.includes('runtime/vite-node.mjs')) { return }
|
if (!rawStack || rawStack.includes('runtime/vite-node.mjs')) { return }
|
||||||
|
|
||||||
|
const trace: ParsedTrace[] = []
|
||||||
|
let filename = ''
|
||||||
|
for (const entry of parseRawStackTrace(rawStack)) {
|
||||||
|
if (entry.source === import.meta.url) { continue }
|
||||||
|
if (EXCLUDE_TRACE_RE.test(entry.source)) { continue }
|
||||||
|
|
||||||
|
filename ||= entry.source.replace(withTrailingSlash(rootDir), '')
|
||||||
|
trace.push({
|
||||||
|
...entry,
|
||||||
|
source: entry.source.startsWith('file://') ? entry.source.replace('file://', '') : entry.source,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
const log = {
|
const log = {
|
||||||
..._log,
|
..._log,
|
||||||
// Pass along filename to allow the client to display more info about where log comes from
|
// Pass along filename to allow the client to display more info about where log comes from
|
||||||
filename: extractFilenameFromStack(stack),
|
filename,
|
||||||
// Clean up file names in stack trace
|
// Clean up file names in stack trace
|
||||||
stack: normalizeFilenames(stack),
|
stack: trace,
|
||||||
}
|
}
|
||||||
|
|
||||||
// retain log to be include in the next render
|
// retain log to be include in the next render
|
||||||
@ -68,24 +83,7 @@ export default (nitroApp: NitroApp) => {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
const EXCLUDE_TRACE_RE = /^.*at.*(\/node_modules\/(.*\/)?(nuxt|nuxt-nightly|nuxt-edge|nuxt3|consola|@vue)\/.*|core\/runtime\/nitro.*)$\n?/gm
|
const EXCLUDE_TRACE_RE = /\/node_modules\/(?:.*\/)?(?:nuxt|nuxt-nightly|nuxt-edge|nuxt3|consola|@vue)\/|core\/runtime\/nitro/
|
||||||
function getStack () {
|
|
||||||
// Pass along stack traces if needed (for error and warns)
|
|
||||||
// eslint-disable-next-line unicorn/error-message
|
|
||||||
const stack = new Error()
|
|
||||||
Error.captureStackTrace(stack)
|
|
||||||
return stack.stack?.replace(EXCLUDE_TRACE_RE, '').replace(/^Error.*\n/, '') || ''
|
|
||||||
}
|
|
||||||
|
|
||||||
const FILENAME_RE = /at[^(]*\(([^:)]+)[):]/
|
|
||||||
const FILENAME_RE_GLOBAL = /at[^(]*\(([^)]+)\)/g
|
|
||||||
function extractFilenameFromStack (stacktrace: string) {
|
|
||||||
return stacktrace.match(FILENAME_RE)?.[1].replace(withTrailingSlash(rootDir), '')
|
|
||||||
}
|
|
||||||
function normalizeFilenames (stacktrace: string) {
|
|
||||||
// remove line numbers and file: protocol - TODO: sourcemap support for line numbers
|
|
||||||
return stacktrace.replace(FILENAME_RE_GLOBAL, (match, filename) => match.replace(filename, filename.replace('file:///', '/').replace(/:.*$/, '')))
|
|
||||||
}
|
|
||||||
|
|
||||||
function onConsoleLog (callback: (log: LogObject) => void) {
|
function onConsoleLog (callback: (log: LogObject) => void) {
|
||||||
consola.addReporter({
|
consola.addReporter({
|
||||||
|
@ -115,29 +115,34 @@ function normalizeError (error: any) {
|
|||||||
// temp fix for https://github.com/unjs/nitro/issues/759
|
// temp fix for https://github.com/unjs/nitro/issues/759
|
||||||
// TODO: investigate vercel-edge not using unenv pollyfill
|
// TODO: investigate vercel-edge not using unenv pollyfill
|
||||||
const cwd = typeof process.cwd === 'function' ? process.cwd() : '/'
|
const cwd = typeof process.cwd === 'function' ? process.cwd() : '/'
|
||||||
const stack = ((error.stack as string) || '')
|
|
||||||
.split('\n')
|
// Hide details of unhandled/fatal errors in production
|
||||||
.splice(1)
|
const hideDetails = !import.meta.dev && error.unhandled
|
||||||
.filter(line => line.includes('at '))
|
|
||||||
.map((line) => {
|
const stack = hideDetails
|
||||||
const text = line
|
? []
|
||||||
.replace(cwd + '/', './')
|
: ((error.stack as string) || '')
|
||||||
.replace('webpack:/', '')
|
.split('\n')
|
||||||
.replace('file://', '')
|
.splice(1)
|
||||||
.trim()
|
.filter(line => line.includes('at '))
|
||||||
return {
|
.map((line) => {
|
||||||
text,
|
const text = line
|
||||||
internal:
|
.replace(cwd + '/', './')
|
||||||
(line.includes('node_modules') && !line.includes('.cache')) ||
|
.replace('webpack:/', '')
|
||||||
line.includes('internal') ||
|
.replace('file://', '')
|
||||||
line.includes('new Promise'),
|
.trim()
|
||||||
}
|
return {
|
||||||
})
|
text,
|
||||||
|
internal:
|
||||||
|
(line.includes('node_modules') && !line.includes('.cache')) ||
|
||||||
|
line.includes('internal') ||
|
||||||
|
line.includes('new Promise'),
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
const statusCode = error.statusCode || 500
|
const statusCode = error.statusCode || 500
|
||||||
const statusMessage =
|
const statusMessage = error.statusMessage ?? (statusCode === 404 ? 'Not Found' : '')
|
||||||
error.statusMessage ?? (statusCode === 404 ? 'Not Found' : '')
|
const message = hideDetails ? 'internal server error' : (error.message || error.toString())
|
||||||
const message = error.message || error.toString()
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
stack,
|
stack,
|
||||||
|
@ -6,6 +6,7 @@ import {
|
|||||||
getRequestDependencies,
|
getRequestDependencies,
|
||||||
renderResourceHeaders,
|
renderResourceHeaders,
|
||||||
} from 'vue-bundle-renderer/runtime'
|
} from 'vue-bundle-renderer/runtime'
|
||||||
|
import type { Manifest as ClientManifest } from 'vue-bundle-renderer'
|
||||||
import type { RenderResponse } from 'nitro/types'
|
import type { RenderResponse } from 'nitro/types'
|
||||||
import type { Manifest } from 'vite'
|
import type { Manifest } from 'vite'
|
||||||
import type { H3Event } from 'h3'
|
import type { H3Event } from 'h3'
|
||||||
@ -94,8 +95,6 @@ export interface NuxtRenderResponse {
|
|||||||
headers: Record<string, string>
|
headers: Record<string, string>
|
||||||
}
|
}
|
||||||
|
|
||||||
interface ClientManifest {}
|
|
||||||
|
|
||||||
// @ts-expect-error file will be produced after app build
|
// @ts-expect-error file will be produced after app build
|
||||||
const getClientManifest: () => Promise<Manifest> = () => import('#build/dist/server/client.manifest.mjs')
|
const getClientManifest: () => Promise<Manifest> = () => import('#build/dist/server/client.manifest.mjs')
|
||||||
.then(r => r.default || r)
|
.then(r => r.default || r)
|
||||||
|
@ -341,9 +341,10 @@ import { defuFn } from 'defu'
|
|||||||
const inlineConfig = ${JSON.stringify(nuxt.options.appConfig, null, 2)}
|
const inlineConfig = ${JSON.stringify(nuxt.options.appConfig, null, 2)}
|
||||||
|
|
||||||
/** client **/
|
/** client **/
|
||||||
|
import { updateAppConfig } from '#app/config'
|
||||||
|
|
||||||
// Vite - webpack is handled directly in #app/config
|
// Vite - webpack is handled directly in #app/config
|
||||||
if (import.meta.dev && !import.meta.nitro && import.meta.hot) {
|
if (import.meta.dev && !import.meta.nitro && import.meta.hot) {
|
||||||
const { updateAppConfig } = await import('#app/config')
|
|
||||||
import.meta.hot.accept((newModule) => {
|
import.meta.hot.accept((newModule) => {
|
||||||
updateAppConfig(newModule.default)
|
updateAppConfig(newModule.default)
|
||||||
})
|
})
|
||||||
|
@ -123,6 +123,7 @@ export const scriptsStubsPreset = {
|
|||||||
'useScript',
|
'useScript',
|
||||||
'useScriptGoogleAnalytics',
|
'useScriptGoogleAnalytics',
|
||||||
'useScriptPlausibleAnalytics',
|
'useScriptPlausibleAnalytics',
|
||||||
|
'useScriptCrisp',
|
||||||
'useScriptClarity',
|
'useScriptClarity',
|
||||||
'useScriptCloudflareWebAnalytics',
|
'useScriptCloudflareWebAnalytics',
|
||||||
'useScriptFathomAnalytics',
|
'useScriptFathomAnalytics',
|
||||||
|
@ -148,6 +148,12 @@ export default defineNuxtModule({
|
|||||||
priority: 10, // built-in that we do not expect the user to override
|
priority: 10, // built-in that we do not expect the user to override
|
||||||
filePath: resolve(distDir, 'pages/runtime/page-placeholder'),
|
filePath: resolve(distDir, 'pages/runtime/page-placeholder'),
|
||||||
})
|
})
|
||||||
|
// Prerender index if pages integration is not enabled
|
||||||
|
nuxt.hook('nitro:init', (nitro) => {
|
||||||
|
if (nuxt.options.dev || !nuxt.options.ssr || !nitro.options.static || !nitro.options.prerender.crawlLinks) { return }
|
||||||
|
|
||||||
|
nitro.options.prerender.routes.push('/')
|
||||||
|
})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -309,28 +315,22 @@ export default defineNuxtModule({
|
|||||||
processPages(pages)
|
processPages(pages)
|
||||||
})
|
})
|
||||||
|
|
||||||
// For static sites with ssr: false with crawl, prerender all routes
|
nuxt.hook('nitro:build:before', (nitro) => {
|
||||||
nuxt.hook('nitro:init', (nitro) => {
|
|
||||||
if (nuxt.options.dev || !nitro.options.static || nuxt.options.router.options.hashMode || !nitro.options.prerender.crawlLinks) { return }
|
if (nuxt.options.dev || !nitro.options.static || nuxt.options.router.options.hashMode || !nitro.options.prerender.crawlLinks) { return }
|
||||||
|
|
||||||
// Only hint the first route when `ssr: true` and no routes are provided
|
// Only hint the first route when `ssr: true` and no routes are provided
|
||||||
|
// as the rest will be injected at runtime when this is prerendered
|
||||||
if (nuxt.options.ssr) {
|
if (nuxt.options.ssr) {
|
||||||
nitro.hooks.hook('prerender:routes', (routes) => {
|
const [firstPage] = [...prerenderRoutes].sort()
|
||||||
if ([...routes].every(r => r.match(/(^\/api|\.\w+)/))) {
|
nitro.options.prerender.routes.push(firstPage || '/')
|
||||||
const [firstPage] = [...prerenderRoutes].sort()
|
|
||||||
routes.add(firstPage || '/')
|
|
||||||
}
|
|
||||||
})
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Prerender all non-dynamic page routes when generating `ssr: false` app
|
// Prerender all non-dynamic page routes when generating `ssr: false` app
|
||||||
nuxt.hook('nitro:build:before', (nitro) => {
|
for (const route of nitro.options.prerender.routes || []) {
|
||||||
for (const route of nitro.options.prerender.routes || []) {
|
prerenderRoutes.add(route)
|
||||||
prerenderRoutes.add(route)
|
}
|
||||||
}
|
nitro.options.prerender.routes = Array.from(prerenderRoutes)
|
||||||
nitro.options.prerender.routes = Array.from(prerenderRoutes)
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
|
|
||||||
nuxt.hook('imports:extend', (imports) => {
|
nuxt.hook('imports:extend', (imports) => {
|
||||||
|
@ -42,6 +42,7 @@ export interface PageMeta {
|
|||||||
}
|
}
|
||||||
|
|
||||||
declare module 'vue-router' {
|
declare module 'vue-router' {
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-empty-object-type
|
||||||
interface RouteMeta extends UnwrapRef<PageMeta> {}
|
interface RouteMeta extends UnwrapRef<PageMeta> {}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -60,7 +61,7 @@ export const definePageMeta = (meta: PageMeta): void => {
|
|||||||
try {
|
try {
|
||||||
const isRouteComponent = component && useRoute().matched.some(p => Object.values(p.components || {}).includes(component))
|
const isRouteComponent = component && useRoute().matched.some(p => Object.values(p.components || {}).includes(component))
|
||||||
const isRenderingServerPage = import.meta.server && useNuxtApp().ssrContext?.islandContext
|
const isRenderingServerPage = import.meta.server && useNuxtApp().ssrContext?.islandContext
|
||||||
if (isRouteComponent || isRenderingServerPage) {
|
if (isRouteComponent || isRenderingServerPage || ((component as any)?.__clientOnlyPage)) {
|
||||||
// don't warn if it's being used in a route component (or server page)
|
// don't warn if it's being used in a route component (or server page)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -19,7 +19,11 @@ export default defineNuxtPlugin({
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (import.meta.server) {
|
if (import.meta.server) {
|
||||||
nuxtApp.hook('app:rendered', ({ renderResult }) => { renderResult?.html && nextTick(checkIfPageUnused) })
|
nuxtApp.hook('app:rendered', ({ renderResult }) => {
|
||||||
|
if (renderResult?.html) {
|
||||||
|
nextTick(checkIfPageUnused)
|
||||||
|
}
|
||||||
|
})
|
||||||
} else {
|
} else {
|
||||||
onNuxtReady(checkIfPageUnused)
|
onNuxtReady(checkIfPageUnused)
|
||||||
}
|
}
|
||||||
|
@ -117,7 +117,7 @@ const plugin: Plugin<{ router: Router }> = defineNuxtPlugin({
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
// https://github.com/vuejs/router/blob/main/packages/router/src/router.ts#L1225-L1233
|
// https://github.com/vuejs/router/blob/8487c3e18882a0883e464a0f25fb28fa50eeda38/packages/router/src/router.ts#L1283-L1289
|
||||||
const route = {} as RouteLocationNormalizedLoaded
|
const route = {} as RouteLocationNormalizedLoaded
|
||||||
for (const key in _route.value) {
|
for (const key in _route.value) {
|
||||||
Object.defineProperty(route, key, {
|
Object.defineProperty(route, key, {
|
||||||
|
@ -58,7 +58,7 @@ function _getHashElementScrollMarginTop (selector: string): number {
|
|||||||
try {
|
try {
|
||||||
const elem = document.querySelector(selector)
|
const elem = document.querySelector(selector)
|
||||||
if (elem) {
|
if (elem) {
|
||||||
return Number.parseFloat(getComputedStyle(elem).scrollMarginTop)
|
return Number.parseFloat(getComputedStyle(elem).scrollMarginTop) + Number.parseFloat(getComputedStyle(document.documentElement).scrollPaddingTop)
|
||||||
}
|
}
|
||||||
} catch {
|
} catch {
|
||||||
// ignore any errors parsing scrollMarginTop
|
// ignore any errors parsing scrollMarginTop
|
||||||
|
@ -58,7 +58,7 @@ export async function resolvePagesRoutes (): Promise<NuxtPage[]> {
|
|||||||
// sort scanned files using en-US locale to make the result consistent across different system locales
|
// sort scanned files using en-US locale to make the result consistent across different system locales
|
||||||
scannedFiles.sort((a, b) => a.relativePath.localeCompare(b.relativePath, 'en-US'))
|
scannedFiles.sort((a, b) => a.relativePath.localeCompare(b.relativePath, 'en-US'))
|
||||||
|
|
||||||
const allRoutes = await generateRoutesFromFiles(uniqueBy(scannedFiles, 'relativePath'), {
|
const allRoutes = generateRoutesFromFiles(uniqueBy(scannedFiles, 'relativePath'), {
|
||||||
shouldUseServerComponents: !!nuxt.options.experimental.componentIslands,
|
shouldUseServerComponents: !!nuxt.options.experimental.componentIslands,
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -144,7 +144,12 @@ export async function augmentPages (routes: NuxtPage[], vfs: Record<string, stri
|
|||||||
for (const route of routes) {
|
for (const route of routes) {
|
||||||
if (route.file && !augmentedPages.has(route.file)) {
|
if (route.file && !augmentedPages.has(route.file)) {
|
||||||
const fileContent = route.file in vfs ? vfs[route.file] : fs.readFileSync(await resolvePath(route.file), 'utf-8')
|
const fileContent = route.file in vfs ? vfs[route.file] : fs.readFileSync(await resolvePath(route.file), 'utf-8')
|
||||||
Object.assign(route, await getRouteMeta(fileContent, route.file))
|
const routeMeta = await getRouteMeta(fileContent, route.file)
|
||||||
|
if (route.meta) {
|
||||||
|
routeMeta.meta = { ...routeMeta.meta, ...route.meta }
|
||||||
|
}
|
||||||
|
|
||||||
|
Object.assign(route, routeMeta)
|
||||||
augmentedPages.add(route.file)
|
augmentedPages.add(route.file)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17,6 +17,16 @@
|
|||||||
"path": ""/"",
|
"path": ""/"",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
"route.meta generated from file": [
|
||||||
|
{
|
||||||
|
"alias": "mockMeta?.alias || []",
|
||||||
|
"component": "() => import("pages/page-with-meta.vue").then(m => m.default || m)",
|
||||||
|
"meta": "{ ...(mockMeta || {}), ...{"test":1} }",
|
||||||
|
"name": "mockMeta?.name ?? "page-with-meta"",
|
||||||
|
"path": "mockMeta?.path ?? "/page-with-meta"",
|
||||||
|
"redirect": "mockMeta?.redirect",
|
||||||
|
},
|
||||||
|
],
|
||||||
"should allow pages with `:` in their path": [
|
"should allow pages with `:` in their path": [
|
||||||
{
|
{
|
||||||
"alias": "mockMeta?.alias || []",
|
"alias": "mockMeta?.alias || []",
|
||||||
@ -349,6 +359,16 @@
|
|||||||
"redirect": "mockMeta?.redirect",
|
"redirect": "mockMeta?.redirect",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
"should merge route.meta with meta from file": [
|
||||||
|
{
|
||||||
|
"alias": "mockMeta?.alias || []",
|
||||||
|
"component": "() => import("pages/page-with-meta.vue").then(m => m.default || m)",
|
||||||
|
"meta": "{ ...(mockMeta || {}), ...{"test":1} }",
|
||||||
|
"name": "mockMeta?.name ?? "page-with-meta"",
|
||||||
|
"path": "mockMeta?.path ?? "/page-with-meta"",
|
||||||
|
"redirect": "mockMeta?.redirect",
|
||||||
|
},
|
||||||
|
],
|
||||||
"should not generate colliding route names when hyphens are in file name": [
|
"should not generate colliding route names when hyphens are in file name": [
|
||||||
{
|
{
|
||||||
"alias": "mockMeta?.alias || []",
|
"alias": "mockMeta?.alias || []",
|
||||||
|
@ -16,6 +16,14 @@
|
|||||||
"path": ""/"",
|
"path": ""/"",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
"route.meta generated from file": [
|
||||||
|
{
|
||||||
|
"component": "() => import("pages/page-with-meta.vue").then(m => m.default || m)",
|
||||||
|
"meta": "{"test":1}",
|
||||||
|
"name": ""page-with-meta"",
|
||||||
|
"path": ""/page-with-meta"",
|
||||||
|
},
|
||||||
|
],
|
||||||
"should allow pages with `:` in their path": [
|
"should allow pages with `:` in their path": [
|
||||||
{
|
{
|
||||||
"component": "() => import("pages/test:name.vue").then(m => m.default || m)",
|
"component": "() => import("pages/test:name.vue").then(m => m.default || m)",
|
||||||
@ -240,6 +248,14 @@
|
|||||||
"path": ""/"",
|
"path": ""/"",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
"should merge route.meta with meta from file": [
|
||||||
|
{
|
||||||
|
"component": "() => import("pages/page-with-meta.vue").then(m => m.default || m)",
|
||||||
|
"meta": "{ ...(mockMeta || {}), ...{"test":1} }",
|
||||||
|
"name": ""page-with-meta"",
|
||||||
|
"path": ""/page-with-meta"",
|
||||||
|
},
|
||||||
|
],
|
||||||
"should not generate colliding route names when hyphens are in file name": [
|
"should not generate colliding route names when hyphens are in file name": [
|
||||||
{
|
{
|
||||||
"component": "() => import("pages/parent/[child].vue").then(m => m.default || m)",
|
"component": "() => import("pages/parent/[child].vue").then(m => m.default || m)",
|
||||||
|
@ -19,7 +19,7 @@ describe('resolveApp', () => {
|
|||||||
{
|
{
|
||||||
"components": [],
|
"components": [],
|
||||||
"configs": [],
|
"configs": [],
|
||||||
"dir": "<rootDir>/app",
|
"dir": "<rootDir>",
|
||||||
"errorComponent": "<repoRoot>/packages/nuxt/src/app/components/nuxt-error-page.vue",
|
"errorComponent": "<repoRoot>/packages/nuxt/src/app/components/nuxt-error-page.vue",
|
||||||
"extensions": [
|
"extensions": [
|
||||||
".js",
|
".js",
|
||||||
|
@ -23,6 +23,7 @@ describe('imports:transform', () => {
|
|||||||
|
|
||||||
const transformPlugin = TransformPlugin.raw({ ctx, options: { transform: { exclude: [/node_modules/] } } }, { framework: 'rollup' }) as Plugin
|
const transformPlugin = TransformPlugin.raw({ ctx, options: { transform: { exclude: [/node_modules/] } } }, { framework: 'rollup' }) as Plugin
|
||||||
const transform = async (source: string) => {
|
const transform = async (source: string) => {
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-function-type
|
||||||
const result = await (transformPlugin.transform! as Function).call({ error: null, warn: null } as any, source, '')
|
const result = await (transformPlugin.transform! as Function).call({ error: null, warn: null } as any, source, '')
|
||||||
return typeof result === 'string' ? result : result?.code
|
return typeof result === 'string' ? result : result?.code
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,7 @@ import { normalizeLineEndings } from './utils'
|
|||||||
const pluginVite = DevOnlyPlugin.raw({}, { framework: 'vite' }) as Plugin
|
const pluginVite = DevOnlyPlugin.raw({}, { framework: 'vite' }) as Plugin
|
||||||
|
|
||||||
const viteTransform = async (source: string, id: string) => {
|
const viteTransform = async (source: string, id: string) => {
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-function-type
|
||||||
const result = await (pluginVite.transform! as Function)(source, id)
|
const result = await (pluginVite.transform! as Function)(source, id)
|
||||||
return typeof result === 'string' ? result : result?.code
|
return typeof result === 'string' ? result : result?.code
|
||||||
}
|
}
|
||||||
|
@ -29,11 +29,13 @@ const viteTransform = async (source: string, id: string, selectiveClient = false
|
|||||||
selectiveClient,
|
selectiveClient,
|
||||||
}, { framework: 'vite' }) as Plugin
|
}, { framework: 'vite' }) as Plugin
|
||||||
|
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-function-type
|
||||||
const result = await (vitePlugin.transform! as Function)(source, id)
|
const result = await (vitePlugin.transform! as Function)(source, id)
|
||||||
return typeof result === 'string' ? result : result?.code
|
return typeof result === 'string' ? result : result?.code
|
||||||
}
|
}
|
||||||
|
|
||||||
const webpackTransform = async (source: string, id: string) => {
|
const webpackTransform = async (source: string, id: string) => {
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-function-type
|
||||||
const result = await ((pluginWebpack as UnpluginOptions).transform! as Function)(source, id)
|
const result = await ((pluginWebpack as UnpluginOptions).transform! as Function)(source, id)
|
||||||
return typeof result === 'string' ? result : result?.code
|
return typeof result === 'string' ? result : result?.code
|
||||||
}
|
}
|
||||||
|
@ -20,7 +20,7 @@ describe('pages:generateRoutesFromFiles', () => {
|
|||||||
|
|
||||||
const tests: Array<{
|
const tests: Array<{
|
||||||
description: string
|
description: string
|
||||||
files?: Array<{ path: string, template?: string }>
|
files?: Array<{ path: string, template?: string, meta?: Record<string, any> }>
|
||||||
output?: NuxtPage[]
|
output?: NuxtPage[]
|
||||||
normalized?: Record<string, any>[]
|
normalized?: Record<string, any>[]
|
||||||
error?: string
|
error?: string
|
||||||
@ -554,6 +554,53 @@ describe('pages:generateRoutesFromFiles', () => {
|
|||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
description: 'route.meta generated from file',
|
||||||
|
files: [
|
||||||
|
{
|
||||||
|
path: `${pagesDir}/page-with-meta.vue`,
|
||||||
|
meta: {
|
||||||
|
test: 1,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
output: [
|
||||||
|
{
|
||||||
|
name: 'page-with-meta',
|
||||||
|
path: '/page-with-meta',
|
||||||
|
file: `${pagesDir}/page-with-meta.vue`,
|
||||||
|
children: [],
|
||||||
|
meta: { test: 1 },
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
description: 'should merge route.meta with meta from file',
|
||||||
|
files: [
|
||||||
|
{
|
||||||
|
path: `${pagesDir}/page-with-meta.vue`,
|
||||||
|
meta: {
|
||||||
|
test: 1,
|
||||||
|
},
|
||||||
|
template: `
|
||||||
|
<script setup lang="ts">
|
||||||
|
definePageMeta({
|
||||||
|
hello: 'world'
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
`,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
output: [
|
||||||
|
{
|
||||||
|
name: 'page-with-meta',
|
||||||
|
path: '/page-with-meta',
|
||||||
|
file: `${pagesDir}/page-with-meta.vue`,
|
||||||
|
children: [],
|
||||||
|
meta: { [DYNAMIC_META_KEY]: new Set(['meta']), test: 1 },
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
]
|
]
|
||||||
|
|
||||||
const normalizedResults: Record<string, any> = {}
|
const normalizedResults: Record<string, any> = {}
|
||||||
@ -572,7 +619,13 @@ describe('pages:generateRoutesFromFiles', () => {
|
|||||||
shouldUseServerComponents: true,
|
shouldUseServerComponents: true,
|
||||||
absolutePath: file.path,
|
absolutePath: file.path,
|
||||||
relativePath: file.path.replace(/^(pages|layer\/pages)\//, ''),
|
relativePath: file.path.replace(/^(pages|layer\/pages)\//, ''),
|
||||||
})))
|
}))).map((route, index) => {
|
||||||
|
return {
|
||||||
|
...route,
|
||||||
|
meta: test.files![index].meta,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
await augmentPages(result, vfs)
|
await augmentPages(result, vfs)
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
expect(error.message).toEqual(test.error)
|
expect(error.message).toEqual(test.error)
|
||||||
|
@ -9,6 +9,7 @@ describe('route-injection:transform', () => {
|
|||||||
const injectionPlugin = RouteInjectionPlugin({ options: { sourcemap: { client: false, server: false } } } as Nuxt).raw({}, { framework: 'rollup' }) as Plugin
|
const injectionPlugin = RouteInjectionPlugin({ options: { sourcemap: { client: false, server: false } } } as Nuxt).raw({}, { framework: 'rollup' }) as Plugin
|
||||||
|
|
||||||
const transform = async (source: string) => {
|
const transform = async (source: string) => {
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-function-type
|
||||||
const result = await (injectionPlugin.transform! as Function).call({ error: null, warn: null } as any, source, 'test.vue')
|
const result = await (injectionPlugin.transform! as Function).call({ error: null, warn: null } as any, source, 'test.vue')
|
||||||
const code: string = typeof result === 'string' ? result : result?.code
|
const code: string = typeof result === 'string' ? result : result?.code
|
||||||
let depth = 0
|
let depth = 0
|
||||||
|
@ -55,6 +55,7 @@ const treeshakeTemplatePlugin = TreeShakeTemplatePlugin.raw({
|
|||||||
}, { framework: 'rollup' }) as Plugin
|
}, { framework: 'rollup' }) as Plugin
|
||||||
|
|
||||||
const treeshake = async (source: string): Promise<string> => {
|
const treeshake = async (source: string): Promise<string> => {
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-function-type
|
||||||
const result = await (treeshakeTemplatePlugin.transform! as Function).call({
|
const result = await (treeshakeTemplatePlugin.transform! as Function).call({
|
||||||
parse: (code: string, opts: any = {}) => Parser.parse(code, {
|
parse: (code: string, opts: any = {}) => Parser.parse(code, {
|
||||||
sourceType: 'module',
|
sourceType: 'module',
|
||||||
@ -79,6 +80,7 @@ async function SFCCompile (name: string, source: string, options: Options, ssr =
|
|||||||
build: { sourcemap: false },
|
build: { sourcemap: false },
|
||||||
define: {},
|
define: {},
|
||||||
})
|
})
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-function-type
|
||||||
const result = await (plugin.transform! as Function).call({
|
const result = await (plugin.transform! as Function).call({
|
||||||
parse: (code: string, opts: any = {}) => Parser.parse(code, {
|
parse: (code: string, opts: any = {}) => Parser.parse(code, {
|
||||||
sourceType: 'module',
|
sourceType: 'module',
|
||||||
|
@ -20,6 +20,7 @@ declare module 'nitro/types' {
|
|||||||
buildAssetsDir: string
|
buildAssetsDir: string
|
||||||
cdnURL: string
|
cdnURL: string
|
||||||
}
|
}
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-empty-object-type
|
||||||
interface NitroRuntimeConfig extends RuntimeConfig {}
|
interface NitroRuntimeConfig extends RuntimeConfig {}
|
||||||
interface NitroRouteConfig {
|
interface NitroRouteConfig {
|
||||||
ssr?: boolean
|
ssr?: boolean
|
||||||
@ -41,6 +42,7 @@ declare module 'nitropack/types' {
|
|||||||
buildAssetsDir: string
|
buildAssetsDir: string
|
||||||
cdnURL: string
|
cdnURL: string
|
||||||
}
|
}
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-empty-object-type
|
||||||
interface NitroRuntimeConfig extends RuntimeConfig {}
|
interface NitroRuntimeConfig extends RuntimeConfig {}
|
||||||
interface NitroRouteConfig {
|
interface NitroRouteConfig {
|
||||||
ssr?: boolean
|
ssr?: boolean
|
||||||
|
2
packages/nuxt/types.d.ts
vendored
2
packages/nuxt/types.d.ts
vendored
@ -20,6 +20,7 @@ declare module 'nitro/types' {
|
|||||||
buildAssetsDir: string
|
buildAssetsDir: string
|
||||||
cdnURL: string
|
cdnURL: string
|
||||||
}
|
}
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-empty-object-type
|
||||||
interface NitroRuntimeConfig extends RuntimeConfig {}
|
interface NitroRuntimeConfig extends RuntimeConfig {}
|
||||||
interface NitroRouteConfig {
|
interface NitroRouteConfig {
|
||||||
ssr?: boolean
|
ssr?: boolean
|
||||||
@ -41,6 +42,7 @@ declare module 'nitropack/types' {
|
|||||||
buildAssetsDir: string
|
buildAssetsDir: string
|
||||||
cdnURL: string
|
cdnURL: string
|
||||||
}
|
}
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-empty-object-type
|
||||||
interface NitroRuntimeConfig extends RuntimeConfig {}
|
interface NitroRuntimeConfig extends RuntimeConfig {}
|
||||||
interface NitroRouteConfig {
|
interface NitroRouteConfig {
|
||||||
ssr?: boolean
|
ssr?: boolean
|
||||||
|
@ -38,29 +38,29 @@
|
|||||||
"@nuxt/ui-templates": "1.3.4",
|
"@nuxt/ui-templates": "1.3.4",
|
||||||
"@types/file-loader": "5.0.4",
|
"@types/file-loader": "5.0.4",
|
||||||
"@types/pug": "2.0.10",
|
"@types/pug": "2.0.10",
|
||||||
"@types/sass-loader": "8.0.8",
|
"@types/sass-loader": "8.0.9",
|
||||||
"@unhead/schema": "1.9.15",
|
"@unhead/schema": "1.9.16",
|
||||||
"@vitejs/plugin-vue": "5.0.5",
|
"@vitejs/plugin-vue": "5.1.2",
|
||||||
"@vitejs/plugin-vue-jsx": "4.0.0",
|
"@vitejs/plugin-vue-jsx": "4.0.0",
|
||||||
"@vue/compiler-core": "3.4.31",
|
"@vue/compiler-core": "3.4.34",
|
||||||
"@vue/compiler-sfc": "3.4.31",
|
"@vue/compiler-sfc": "3.4.34",
|
||||||
"@vue/language-core": "2.0.26",
|
"@vue/language-core": "2.0.29",
|
||||||
"c12": "2.0.0-beta.1",
|
"c12": "2.0.0-beta.1",
|
||||||
"esbuild-loader": "4.2.0",
|
"esbuild-loader": "4.2.2",
|
||||||
"h3": "npm:h3-nightly@2.0.0-1718872656.6765a6e",
|
"h3": "npm:h3-nightly@2.0.0-1718872656.6765a6e",
|
||||||
"ignore": "5.3.1",
|
"ignore": "5.3.1",
|
||||||
"nitro": "npm:nitro-nightly@3.0.0-beta-28665895.e727afda",
|
"nitro": "npm:nitro-nightly@3.0.0-beta-28665895.e727afda",
|
||||||
"ofetch": "1.3.4",
|
"ofetch": "1.3.4",
|
||||||
"unbuild": "3.0.0-rc.6",
|
"unbuild": "3.0.0-rc.7",
|
||||||
"unctx": "2.3.1",
|
"unctx": "2.3.1",
|
||||||
"unenv": "1.9.0",
|
"unenv": "1.10.0",
|
||||||
"vite": "5.3.3",
|
"vite": "5.3.5",
|
||||||
"vue": "3.4.31",
|
"vue": "3.4.34",
|
||||||
"vue-bundle-renderer": "2.1.0",
|
"vue-bundle-renderer": "2.1.0",
|
||||||
"vue-loader": "17.4.2",
|
"vue-loader": "17.4.2",
|
||||||
"vue-router": "4.4.0",
|
"vue-router": "4.4.2",
|
||||||
"webpack": "5.92.1",
|
"webpack": "5.93.0",
|
||||||
"webpack-dev-middleware": "7.2.1"
|
"webpack-dev-middleware": "7.3.0"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"compatx": "^0.1.8",
|
"compatx": "^0.1.8",
|
||||||
@ -71,9 +71,9 @@
|
|||||||
"pkg-types": "^1.1.3",
|
"pkg-types": "^1.1.3",
|
||||||
"scule": "^1.3.0",
|
"scule": "^1.3.0",
|
||||||
"std-env": "^3.7.0",
|
"std-env": "^3.7.0",
|
||||||
"ufo": "^1.5.3",
|
"ufo": "^1.5.4",
|
||||||
"uncrypto": "^0.1.3",
|
"uncrypto": "^0.1.3",
|
||||||
"unimport": "^3.7.2",
|
"unimport": "^3.10.0",
|
||||||
"untyped": "^1.4.2"
|
"untyped": "^1.4.2"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
|
@ -6,7 +6,7 @@ export default defineUntypedSchema({
|
|||||||
*
|
*
|
||||||
* Any components in the directories configured here can be used throughout your
|
* Any components in the directories configured here can be used throughout your
|
||||||
* pages, layouts (and other components) without needing to explicitly import them.
|
* pages, layouts (and other components) without needing to explicitly import them.
|
||||||
* @see https://nuxt.com/docs/guide/directory-structure/components
|
* @see [`components/` directory documentation](https://nuxt.com/docs/guide/directory-structure/components)
|
||||||
* @type {boolean | typeof import('../src/types/components').ComponentsOptions | typeof import('../src/types/components').ComponentsOptions['dirs']}
|
* @type {boolean | typeof import('../src/types/components').ComponentsOptions | typeof import('../src/types/components').ComponentsOptions['dirs']}
|
||||||
*/
|
*/
|
||||||
components: {
|
components: {
|
||||||
|
@ -18,7 +18,7 @@ export default defineUntypedSchema({
|
|||||||
},
|
},
|
||||||
/**
|
/**
|
||||||
* Options for the Vue compiler that will be passed at build time.
|
* Options for the Vue compiler that will be passed at build time.
|
||||||
* @see [documentation](https://vuejs.org/api/application.html#app-config-compileroptions)
|
* @see [Vue documentation](https://vuejs.org/api/application.html#app-config-compileroptions)
|
||||||
* @type {typeof import('@vue/compiler-core').CompilerOptions}
|
* @type {typeof import('@vue/compiler-core').CompilerOptions}
|
||||||
*/
|
*/
|
||||||
compilerOptions: {},
|
compilerOptions: {},
|
||||||
@ -158,7 +158,7 @@ export default defineUntypedSchema({
|
|||||||
*
|
*
|
||||||
* This can be overridden with `definePageMeta` on an individual page.
|
* This can be overridden with `definePageMeta` on an individual page.
|
||||||
* Only JSON-serializable values are allowed.
|
* Only JSON-serializable values are allowed.
|
||||||
* @see https://vuejs.org/api/built-in-components.html#transition
|
* @see [Vue Transition docs](https://vuejs.org/api/built-in-components.html#transition)
|
||||||
* @type {typeof import('../src/types/config').NuxtAppConfig['layoutTransition']}
|
* @type {typeof import('../src/types/config').NuxtAppConfig['layoutTransition']}
|
||||||
*/
|
*/
|
||||||
layoutTransition: false,
|
layoutTransition: false,
|
||||||
@ -168,7 +168,7 @@ export default defineUntypedSchema({
|
|||||||
*
|
*
|
||||||
* This can be overridden with `definePageMeta` on an individual page.
|
* This can be overridden with `definePageMeta` on an individual page.
|
||||||
* Only JSON-serializable values are allowed.
|
* Only JSON-serializable values are allowed.
|
||||||
* @see https://vuejs.org/api/built-in-components.html#transition
|
* @see [Vue Transition docs](https://vuejs.org/api/built-in-components.html#transition)
|
||||||
* @type {typeof import('../src/types/config').NuxtAppConfig['pageTransition']}
|
* @type {typeof import('../src/types/config').NuxtAppConfig['pageTransition']}
|
||||||
*/
|
*/
|
||||||
pageTransition: false,
|
pageTransition: false,
|
||||||
@ -180,7 +180,7 @@ export default defineUntypedSchema({
|
|||||||
* [enabled in your nuxt.config file](/docs/getting-started/transitions#view-transitions-api-experimental).
|
* [enabled in your nuxt.config file](/docs/getting-started/transitions#view-transitions-api-experimental).
|
||||||
*
|
*
|
||||||
* This can be overridden with `definePageMeta` on an individual page.
|
* This can be overridden with `definePageMeta` on an individual page.
|
||||||
* @see https://nuxt.com/docs/getting-started/transitions#view-transitions-api-experimental
|
* @see [Nuxt View Transition API docs](https://nuxt.com/docs/getting-started/transitions#view-transitions-api-experimental)
|
||||||
* @type {typeof import('../src/types/config').NuxtAppConfig['viewTransition']}
|
* @type {typeof import('../src/types/config').NuxtAppConfig['viewTransition']}
|
||||||
*/
|
*/
|
||||||
viewTransition: {
|
viewTransition: {
|
||||||
@ -194,7 +194,7 @@ export default defineUntypedSchema({
|
|||||||
*
|
*
|
||||||
* This can be overridden with `definePageMeta` on an individual page.
|
* This can be overridden with `definePageMeta` on an individual page.
|
||||||
* Only JSON-serializable values are allowed.
|
* Only JSON-serializable values are allowed.
|
||||||
* @see https://vuejs.org/api/built-in-components.html#keepalive
|
* @see [Vue KeepAlive](https://vuejs.org/api/built-in-components.html#keepalive)
|
||||||
* @type {typeof import('../src/types/config').NuxtAppConfig['keepalive']}
|
* @type {typeof import('../src/types/config').NuxtAppConfig['keepalive']}
|
||||||
*/
|
*/
|
||||||
keepalive: false,
|
keepalive: false,
|
||||||
@ -328,7 +328,7 @@ export default defineUntypedSchema({
|
|||||||
* @note Plugins are also auto-registered from the `~/plugins` directory
|
* @note Plugins are also auto-registered from the `~/plugins` directory
|
||||||
* and these plugins do not need to be listed in `nuxt.config` unless you
|
* and these plugins do not need to be listed in `nuxt.config` unless you
|
||||||
* need to customize their order. All plugins are deduplicated by their src path.
|
* need to customize their order. All plugins are deduplicated by their src path.
|
||||||
* @see https://nuxt.com/docs/guide/directory-structure/plugins
|
* @see [`plugins/` directory documentation](https://nuxt.com/docs/guide/directory-structure/plugins)
|
||||||
* @example
|
* @example
|
||||||
* ```js
|
* ```js
|
||||||
* plugins: [
|
* plugins: [
|
||||||
@ -375,8 +375,7 @@ export default defineUntypedSchema({
|
|||||||
/**
|
/**
|
||||||
* An object that will be passed to `renderSSRHead` to customize the output.
|
* An object that will be passed to `renderSSRHead` to customize the output.
|
||||||
*
|
*
|
||||||
* @see https://unhead.unjs.io/setup/ssr/installation#options
|
* @see [`unhead` options documentation](https://unhead.unjs.io/setup/ssr/installation#options)
|
||||||
* @type {typeof import('@unhead/schema').RenderSSRHeadOptions}
|
|
||||||
*
|
*
|
||||||
* @example
|
* @example
|
||||||
* ```ts
|
* ```ts
|
||||||
@ -387,7 +386,7 @@ export default defineUntypedSchema({
|
|||||||
* }
|
* }
|
||||||
* })
|
* })
|
||||||
* ```
|
* ```
|
||||||
*
|
* @type {typeof import('@unhead/schema').RenderSSRHeadOptions}
|
||||||
*/
|
*/
|
||||||
renderSSRHeadOptions: {
|
renderSSRHeadOptions: {
|
||||||
$resolve: async (val: Record<string, unknown> | undefined, get) => {
|
$resolve: async (val: Record<string, unknown> | undefined, get) => {
|
||||||
|
@ -66,7 +66,7 @@ export default defineUntypedSchema({
|
|||||||
* You can also use a function to conditionally transpile. The function will receive an object ({ isDev, isServer, isClient, isModern, isLegacy }).
|
* You can also use a function to conditionally transpile. The function will receive an object ({ isDev, isServer, isClient, isModern, isLegacy }).
|
||||||
* @example
|
* @example
|
||||||
* ```js
|
* ```js
|
||||||
transpile: [({ isLegacy }) => isLegacy && 'ky']
|
* transpile: [({ isLegacy }) => isLegacy && 'ky']
|
||||||
* ```
|
* ```
|
||||||
* @type {Array<string | RegExp | ((ctx: { isClient?: boolean; isServer?: boolean; isDev: boolean }) => string | RegExp | false)>}
|
* @type {Array<string | RegExp | ((ctx: { isClient?: boolean; isServer?: boolean; isDev: boolean }) => string | RegExp | false)>}
|
||||||
*/
|
*/
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { existsSync } from 'node:fs'
|
import { existsSync } from 'node:fs'
|
||||||
import { readdir } from 'node:fs/promises'
|
import { readdir } from 'node:fs/promises'
|
||||||
import { defineUntypedSchema } from 'untyped'
|
import { defineUntypedSchema } from 'untyped'
|
||||||
import { basename, join, relative, resolve } from 'pathe'
|
import { basename, relative, resolve } from 'pathe'
|
||||||
import { isDebug, isDevelopment, isTest } from 'std-env'
|
import { isDebug, isDevelopment, isTest } from 'std-env'
|
||||||
import { defu } from 'defu'
|
import { defu } from 'defu'
|
||||||
import { findWorkspaceDir } from 'pkg-types'
|
import { findWorkspaceDir } from 'pkg-types'
|
||||||
@ -14,9 +14,9 @@ export default defineUntypedSchema({
|
|||||||
*
|
*
|
||||||
* Value should be either a string or array of strings pointing to source directories or config path relative to current config.
|
* Value should be either a string or array of strings pointing to source directories or config path relative to current config.
|
||||||
*
|
*
|
||||||
* You can use `github:`, `gh:` `gitlab:` or `bitbucket:`.
|
* You can use `github:`, `gh:` `gitlab:` or `bitbucket:`
|
||||||
* @see https://github.com/unjs/c12#extending-config-layer-from-remote-sources
|
* @see [`c12` docs on extending config layers](https://github.com/unjs/c12#extending-config-layer-from-remote-sources)
|
||||||
* @see https://github.com/unjs/giget
|
* @see [`giget` documentation](https://github.com/unjs/giget)
|
||||||
* @type {string | [string, typeof import('c12').SourceOptions?] | (string | [string, typeof import('c12').SourceOptions?])[]}
|
* @type {string | [string, typeof import('c12').SourceOptions?] | (string | [string, typeof import('c12').SourceOptions?])[]}
|
||||||
*/
|
*/
|
||||||
extends: null,
|
extends: null,
|
||||||
@ -118,13 +118,15 @@ export default defineUntypedSchema({
|
|||||||
}
|
}
|
||||||
|
|
||||||
const srcDir = resolve(rootDir, 'app')
|
const srcDir = resolve(rootDir, 'app')
|
||||||
|
if (!existsSync(srcDir)) {
|
||||||
|
return rootDir
|
||||||
|
}
|
||||||
|
|
||||||
const srcDirFiles = new Set<string>()
|
const srcDirFiles = new Set<string>()
|
||||||
if (existsSync(srcDir)) {
|
const files = await readdir(srcDir).catch(() => [])
|
||||||
const files = await readdir(srcDir).catch(() => [])
|
for (const file of files) {
|
||||||
for (const file of files) {
|
if (file !== 'spa-loading-template.html' && !file.startsWith('router.options')) {
|
||||||
if (file !== 'spa-loading-template.html' && !file.startsWith('router.options')) {
|
srcDirFiles.add(file)
|
||||||
srcDirFiles.add(file)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (srcDirFiles.size === 0) {
|
if (srcDirFiles.size === 0) {
|
||||||
@ -156,7 +158,7 @@ export default defineUntypedSchema({
|
|||||||
$resolve: async (val: string | undefined, get): Promise<string> => {
|
$resolve: async (val: string | undefined, get): Promise<string> => {
|
||||||
const isV4 = ((await get('future') as Record<string, unknown>).compatibilityVersion === 4)
|
const isV4 = ((await get('future') as Record<string, unknown>).compatibilityVersion === 4)
|
||||||
|
|
||||||
return resolve(await get('rootDir') as string, (val || isV4) ? 'server' : resolve(await get('srcDir') as string, 'server'))
|
return resolve(isV4 ? await get('rootDir') as string : await get('srcDir') as string, val ?? 'server')
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -420,7 +422,7 @@ export default defineUntypedSchema({
|
|||||||
'@': srcDir,
|
'@': srcDir,
|
||||||
'~~': rootDir,
|
'~~': rootDir,
|
||||||
'@@': rootDir,
|
'@@': rootDir,
|
||||||
[basename(assetsDir)]: join(srcDir, assetsDir),
|
[basename(assetsDir)]: resolve(srcDir, assetsDir),
|
||||||
[basename(publicDir)]: resolve(srcDir, publicDir),
|
[basename(publicDir)]: resolve(srcDir, publicDir),
|
||||||
...val,
|
...val,
|
||||||
}
|
}
|
||||||
@ -552,7 +554,7 @@ export default defineUntypedSchema({
|
|||||||
* ```js
|
* ```js
|
||||||
* export default {
|
* export default {
|
||||||
* runtimeConfig: {
|
* runtimeConfig: {
|
||||||
* apiKey: '' // Default to an empty string, automatically set at runtime using process.env.NUXT_API_KEY
|
* apiKey: '', // Default to an empty string, automatically set at runtime using process.env.NUXT_API_KEY
|
||||||
* public: {
|
* public: {
|
||||||
* baseURL: '' // Exposed to the frontend as well.
|
* baseURL: '' // Exposed to the frontend as well.
|
||||||
* }
|
* }
|
||||||
|
@ -6,7 +6,7 @@ export default defineUntypedSchema({
|
|||||||
/**
|
/**
|
||||||
* Whether to enable HTTPS.
|
* Whether to enable HTTPS.
|
||||||
* @example
|
* @example
|
||||||
* ```
|
* ```ts
|
||||||
* export default defineNuxtConfig({
|
* export default defineNuxtConfig({
|
||||||
* devServer: {
|
* devServer: {
|
||||||
* https: {
|
* https: {
|
||||||
|
@ -26,7 +26,7 @@ export default defineUntypedSchema({
|
|||||||
*
|
*
|
||||||
* You can set it to false to use the legacy 'Node' mode, which is the default for TypeScript.
|
* You can set it to false to use the legacy 'Node' mode, which is the default for TypeScript.
|
||||||
*
|
*
|
||||||
* See https://github.com/microsoft/TypeScript/pull/51669
|
* @see [TypeScript PR implementing `bundler` module resolution](https://github.com/microsoft/TypeScript/pull/51669)
|
||||||
*/
|
*/
|
||||||
typescriptBundlerResolution: {
|
typescriptBundlerResolution: {
|
||||||
async $resolve (val, get) {
|
async $resolve (val, get) {
|
||||||
@ -255,7 +255,7 @@ export default defineUntypedSchema({
|
|||||||
*
|
*
|
||||||
* You can also set this to `chokidar` to watch all files in your source directory.
|
* You can also set this to `chokidar` to watch all files in your source directory.
|
||||||
* @see [chokidar](https://github.com/paulmillr/chokidar)
|
* @see [chokidar](https://github.com/paulmillr/chokidar)
|
||||||
* @see [Parcel watcher](https://github.com/parcel-bundler/watcher)
|
* @see [@parcel/watcher](https://github.com/parcel-bundler/watcher)
|
||||||
* @type {'chokidar' | 'parcel' | 'chokidar-granular'}
|
* @type {'chokidar' | 'parcel' | 'chokidar-granular'}
|
||||||
*/
|
*/
|
||||||
watcher: {
|
watcher: {
|
||||||
@ -283,7 +283,7 @@ export default defineUntypedSchema({
|
|||||||
* - Add the capo.js head plugin in order to render tags in of the head in a more performant way.
|
* - Add the capo.js head plugin in order to render tags in of the head in a more performant way.
|
||||||
* - Uses the hash hydration plugin to reduce initial hydration
|
* - Uses the hash hydration plugin to reduce initial hydration
|
||||||
*
|
*
|
||||||
* @see [Nuxt Discussion #22632](https://github.com/nuxt/nuxt/discussions/22632]
|
* @see [Nuxt Discussion #22632](https://github.com/nuxt/nuxt/discussions/22632)
|
||||||
*/
|
*/
|
||||||
headNext: true,
|
headNext: true,
|
||||||
|
|
||||||
@ -304,7 +304,7 @@ export default defineUntypedSchema({
|
|||||||
*
|
*
|
||||||
* This only works with static or strings/arrays rather than variables or conditional assignment.
|
* This only works with static or strings/arrays rather than variables or conditional assignment.
|
||||||
*
|
*
|
||||||
* https://github.com/nuxt/nuxt/issues/24770
|
* @see [Nuxt Issues #24770](https://github.com/nuxt/nuxt/issues/24770)
|
||||||
*/
|
*/
|
||||||
scanPageMeta: true,
|
scanPageMeta: true,
|
||||||
|
|
||||||
@ -366,7 +366,7 @@ export default defineUntypedSchema({
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Automatically polyfill Node.js imports in the client build using `unenv`.
|
* Automatically polyfill Node.js imports in the client build using `unenv`.
|
||||||
* @see https://github.com/unjs/unenv
|
* @see [unenv](https://github.com/unjs/unenv)
|
||||||
*
|
*
|
||||||
* **Note:** To make globals like `Buffer` work in the browser, you need to manually inject them.
|
* **Note:** To make globals like `Buffer` work in the browser, you need to manually inject them.
|
||||||
*
|
*
|
||||||
|
@ -4,7 +4,7 @@ import type { RuntimeConfig } from '../types/config'
|
|||||||
export default defineUntypedSchema({
|
export default defineUntypedSchema({
|
||||||
/**
|
/**
|
||||||
* Configuration for Nitro.
|
* Configuration for Nitro.
|
||||||
* @see https://nitro.unjs.io/config/
|
* @see [Nitro configuration docs](https://nitro.unjs.io/config/)
|
||||||
* @type {typeof import('nitro/types')['NitroConfig']}
|
* @type {typeof import('nitro/types')['NitroConfig']}
|
||||||
*/
|
*/
|
||||||
nitro: {
|
nitro: {
|
||||||
@ -37,7 +37,7 @@ export default defineUntypedSchema({
|
|||||||
/**
|
/**
|
||||||
* Global route options applied to matching server routes.
|
* Global route options applied to matching server routes.
|
||||||
* @experimental This is an experimental feature and API may change in the future.
|
* @experimental This is an experimental feature and API may change in the future.
|
||||||
* @see https://nitro.unjs.io/config/#routerules
|
* @see [Nitro route rules documentation](https://nitro.unjs.io/config/#routerules)
|
||||||
* @type {typeof import('nitro/types')['NitroConfig']['routeRules']}
|
* @type {typeof import('nitro/types')['NitroConfig']['routeRules']}
|
||||||
*/
|
*/
|
||||||
routeRules: {},
|
routeRules: {},
|
||||||
@ -48,12 +48,12 @@ export default defineUntypedSchema({
|
|||||||
* Each handler accepts the following options:
|
* Each handler accepts the following options:
|
||||||
*
|
*
|
||||||
* - handler: The path to the file defining the handler.
|
* - handler: The path to the file defining the handler.
|
||||||
* - route: The route under which the handler is available. This follows the conventions of https://github.com/unjs/radix3.
|
* - route: The route under which the handler is available. This follows the conventions of [radix3](https://github.com/unjs/radix3.)
|
||||||
* - method: The HTTP method of requests that should be handled.
|
* - method: The HTTP method of requests that should be handled.
|
||||||
* - middleware: Specifies whether it is a middleware handler.
|
* - middleware: Specifies whether it is a middleware handler.
|
||||||
* - lazy: Specifies whether to use lazy loading to import the handler.
|
* - lazy: Specifies whether to use lazy loading to import the handler.
|
||||||
*
|
*
|
||||||
* @see https://nuxt.com/docs/guide/directory-structure/server
|
* @see [`server/` directory documentation](https://nuxt.com/docs/guide/directory-structure/server)
|
||||||
* @note Files from `server/api`, `server/middleware` and `server/routes` will be automatically registered by Nuxt.
|
* @note Files from `server/api`, `server/middleware` and `server/routes` will be automatically registered by Nuxt.
|
||||||
* @example
|
* @example
|
||||||
* ```js
|
* ```js
|
||||||
@ -67,7 +67,7 @@ export default defineUntypedSchema({
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Nitro development-only server handlers.
|
* Nitro development-only server handlers.
|
||||||
* @see https://nitro.unjs.io/guide/routing
|
* @see [Nitro server routes documentation](https://nitro.unjs.io/guide/routing)
|
||||||
* @type {typeof import('nitro/types')['NitroDevEventHandler'][]}
|
* @type {typeof import('nitro/types')['NitroDevEventHandler'][]}
|
||||||
*/
|
*/
|
||||||
devServerHandlers: [],
|
devServerHandlers: [],
|
||||||
|
@ -38,17 +38,19 @@ export default defineUntypedSchema({
|
|||||||
/**
|
/**
|
||||||
* Options for configuring PostCSS plugins.
|
* Options for configuring PostCSS plugins.
|
||||||
*
|
*
|
||||||
* https://postcss.org/
|
* @see [PostCSS docs](https://postcss.org/)
|
||||||
* @type {Record<string, unknown> & { autoprefixer?: typeof import('autoprefixer').Options; cssnano?: typeof import('cssnano').Options }}
|
* @type {Record<string, unknown> & { autoprefixer?: typeof import('autoprefixer').Options; cssnano?: typeof import('cssnano').Options }}
|
||||||
*/
|
*/
|
||||||
plugins: {
|
plugins: {
|
||||||
/**
|
/**
|
||||||
* https://github.com/postcss/autoprefixer
|
* Plugin to parse CSS and add vendor prefixes to CSS rules.
|
||||||
|
*
|
||||||
|
* @see [`autoprefixer`](https://github.com/postcss/autoprefixer)
|
||||||
*/
|
*/
|
||||||
autoprefixer: {},
|
autoprefixer: {},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* https://cssnano.github.io/cssnano/docs/config-file/#configuration-options
|
* @see [`cssnano` configuration options](https://cssnano.github.io/cssnano/docs/config-file/#configuration-options)
|
||||||
*/
|
*/
|
||||||
cssnano: {
|
cssnano: {
|
||||||
$resolve: async (val, get) => {
|
$resolve: async (val, get) => {
|
||||||
|
@ -7,7 +7,7 @@ export default defineUntypedSchema({
|
|||||||
* Nuxt offers additional options to customize the router (see below).
|
* Nuxt offers additional options to customize the router (see below).
|
||||||
* @note Only JSON serializable options should be passed by Nuxt config.
|
* @note Only JSON serializable options should be passed by Nuxt config.
|
||||||
* For more control, you can use `app/router.options.ts` file.
|
* For more control, you can use `app/router.options.ts` file.
|
||||||
* @see [documentation](https://router.vuejs.org/api/interfaces/routeroptions.html).
|
* @see [Vue Router documentation](https://router.vuejs.org/api/interfaces/routeroptions.html).
|
||||||
* @type {typeof import('../src/types/router').RouterConfigSerializable}
|
* @type {typeof import('../src/types/router').RouterConfigSerializable}
|
||||||
*/
|
*/
|
||||||
options: {
|
options: {
|
||||||
|
@ -66,7 +66,7 @@ export default defineUntypedSchema({
|
|||||||
*
|
*
|
||||||
* If set to true, this will type check in development. You can restrict this to build-time type checking by setting it to `build`.
|
* If set to true, this will type check in development. You can restrict this to build-time type checking by setting it to `build`.
|
||||||
* Requires to install `typescript` and `vue-tsc` as dev dependencies.
|
* Requires to install `typescript` and `vue-tsc` as dev dependencies.
|
||||||
* @see https://nuxt.com/docs/guide/concepts/typescript
|
* @see [Nuxt TypeScript docs](https://nuxt.com/docs/guide/concepts/typescript)
|
||||||
* @type {boolean | 'build'}
|
* @type {boolean | 'build'}
|
||||||
*/
|
*/
|
||||||
typeCheck: false,
|
typeCheck: false,
|
||||||
|
@ -8,7 +8,7 @@ export default defineUntypedSchema({
|
|||||||
/**
|
/**
|
||||||
* Configuration that will be passed directly to Vite.
|
* Configuration that will be passed directly to Vite.
|
||||||
*
|
*
|
||||||
* See https://vitejs.dev/config for more information.
|
* @see [Vite configuration docs](https://vitejs.dev/config) for more information.
|
||||||
* Please note that not all vite options are supported in Nuxt.
|
* Please note that not all vite options are supported in Nuxt.
|
||||||
* @type {typeof import('../src/types/config').ViteConfig & { $client?: typeof import('../src/types/config').ViteConfig, $server?: typeof import('../src/types/config').ViteConfig }}
|
* @type {typeof import('../src/types/config').ViteConfig & { $client?: typeof import('../src/types/config').ViteConfig, $server?: typeof import('../src/types/config').ViteConfig }}
|
||||||
*/
|
*/
|
||||||
@ -56,13 +56,21 @@ export default defineUntypedSchema({
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
script: {
|
script: {
|
||||||
propsDestructure: {
|
|
||||||
$resolve: async (val, get) => val ?? Boolean((await get('vue') as Record<string, any>).propsDestructure),
|
|
||||||
},
|
|
||||||
hoistStatic: {
|
hoistStatic: {
|
||||||
$resolve: async (val, get) => val ?? (await get('vue') as Record<string, any>).compilerOptions?.hoistStatic,
|
$resolve: async (val, get) => val ?? (await get('vue') as Record<string, any>).compilerOptions?.hoistStatic,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
features: {
|
||||||
|
propsDestructure: {
|
||||||
|
$resolve: async (val, get) => {
|
||||||
|
if (val !== undefined && val !== null) {
|
||||||
|
return val
|
||||||
|
}
|
||||||
|
const vueOptions = await get('vue') as Record<string, any> || {}
|
||||||
|
return Boolean(vueOptions.script?.propsDestructure ?? vueOptions.propsDestructure)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
vueJsx: {
|
vueJsx: {
|
||||||
$resolve: async (val: Record<string, any>, get) => {
|
$resolve: async (val: Record<string, any>, get) => {
|
||||||
|
@ -96,7 +96,7 @@ export default defineUntypedSchema({
|
|||||||
/**
|
/**
|
||||||
* Customize bundle filenames.
|
* Customize bundle filenames.
|
||||||
*
|
*
|
||||||
* To understand a bit more about the use of manifests, take a look at [this webpack documentation](https://webpack.js.org/guides/code-splitting/).
|
* To understand a bit more about the use of manifests, take a look at [webpack documentation](https://webpack.js.org/guides/code-splitting/).
|
||||||
* @note Be careful when using non-hashed based filenames in production
|
* @note Be careful when using non-hashed based filenames in production
|
||||||
* as most browsers will cache the asset and not detect the changes on first load.
|
* as most browsers will cache the asset and not detect the changes on first load.
|
||||||
*
|
*
|
||||||
@ -154,7 +154,7 @@ export default defineUntypedSchema({
|
|||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* See https://github.com/esbuild-kit/esbuild-loader
|
* @see [esbuild loader](https://github.com/esbuild-kit/esbuild-loader)
|
||||||
* @type {Omit<typeof import('esbuild-loader')['LoaderOptions'], 'loader'>}
|
* @type {Omit<typeof import('esbuild-loader')['LoaderOptions'], 'loader'>}
|
||||||
*/
|
*/
|
||||||
esbuild: {
|
esbuild: {
|
||||||
@ -164,7 +164,7 @@ export default defineUntypedSchema({
|
|||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* See: https://github.com/webpack-contrib/file-loader#options
|
* @see [`file-loader` Options](https://github.com/webpack-contrib/file-loader#options)
|
||||||
* @type {Omit<typeof import('file-loader')['Options'], 'name'>}
|
* @type {Omit<typeof import('file-loader')['Options'], 'name'>}
|
||||||
* @default
|
* @default
|
||||||
* ```ts
|
* ```ts
|
||||||
@ -174,7 +174,7 @@ export default defineUntypedSchema({
|
|||||||
file: { esModule: false },
|
file: { esModule: false },
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* See: https://github.com/webpack-contrib/file-loader#options
|
* @see [`file-loader` Options](https://github.com/webpack-contrib/file-loader#options)
|
||||||
* @type {Omit<typeof import('file-loader')['Options'], 'name'>}
|
* @type {Omit<typeof import('file-loader')['Options'], 'name'>}
|
||||||
* @default
|
* @default
|
||||||
* ```ts
|
* ```ts
|
||||||
@ -184,7 +184,7 @@ export default defineUntypedSchema({
|
|||||||
fontUrl: { esModule: false, limit: 1000 },
|
fontUrl: { esModule: false, limit: 1000 },
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* See: https://github.com/webpack-contrib/file-loader#options
|
* @see [`file-loader` Options](https://github.com/webpack-contrib/file-loader#options)
|
||||||
* @type {Omit<typeof import('file-loader')['Options'], 'name'>}
|
* @type {Omit<typeof import('file-loader')['Options'], 'name'>}
|
||||||
* @default
|
* @default
|
||||||
* ```ts
|
* ```ts
|
||||||
@ -194,7 +194,7 @@ export default defineUntypedSchema({
|
|||||||
imgUrl: { esModule: false, limit: 1000 },
|
imgUrl: { esModule: false, limit: 1000 },
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* See: https://pugjs.org/api/reference.html#options
|
* @see [`pug` options](https://pugjs.org/api/reference.html#options)
|
||||||
* @type {typeof import('pug')['Options']}
|
* @type {typeof import('pug')['Options']}
|
||||||
*/
|
*/
|
||||||
pugPlain: {},
|
pugPlain: {},
|
||||||
@ -235,12 +235,12 @@ export default defineUntypedSchema({
|
|||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* See: https://github.com/webpack-contrib/less-loader#options
|
* @see [`less-loader` Options](https://github.com/webpack-contrib/less-loader#options)
|
||||||
*/
|
*/
|
||||||
less: {},
|
less: {},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* See: https://github.com/webpack-contrib/sass-loader#options
|
* @see [`sass-loader` Options](https://github.com/webpack-contrib/sass-loader#options)
|
||||||
* @type {typeof import('sass-loader')['Options']}
|
* @type {typeof import('sass-loader')['Options']}
|
||||||
* @default
|
* @default
|
||||||
* ```ts
|
* ```ts
|
||||||
@ -258,13 +258,13 @@ export default defineUntypedSchema({
|
|||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* See: https://github.com/webpack-contrib/sass-loader#options
|
* @see [`sass-loader` Options](https://github.com/webpack-contrib/sass-loader#options)
|
||||||
* @type {typeof import('sass-loader')['Options']}
|
* @type {typeof import('sass-loader')['Options']}
|
||||||
*/
|
*/
|
||||||
scss: {},
|
scss: {},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* See: https://github.com/webpack-contrib/stylus-loader#options
|
* @see [`stylus-loader` Options](https://github.com/webpack-contrib/stylus-loader#options)
|
||||||
*/
|
*/
|
||||||
stylus: {},
|
stylus: {},
|
||||||
|
|
||||||
@ -322,7 +322,7 @@ export default defineUntypedSchema({
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Customize PostCSS Loader.
|
* Customize PostCSS Loader.
|
||||||
* Same options as https://github.com/webpack-contrib/postcss-loader#options
|
* same options as [`postcss-loader` options](https://github.com/webpack-contrib/postcss-loader#options)
|
||||||
* @type {{ execute?: boolean, postcssOptions: typeof import('postcss').ProcessOptions, sourceMap?: boolean, implementation?: any }}
|
* @type {{ execute?: boolean, postcssOptions: typeof import('postcss').ProcessOptions, sourceMap?: boolean, implementation?: any }}
|
||||||
*/
|
*/
|
||||||
postcss: {
|
postcss: {
|
||||||
|
@ -11,6 +11,7 @@ import type { AppHeadMetaObject } from './head'
|
|||||||
|
|
||||||
export type { SchemaDefinition } from 'untyped'
|
export type { SchemaDefinition } from 'untyped'
|
||||||
|
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-function-type
|
||||||
type DeepPartial<T> = T extends Function ? T : T extends Record<string, any> ? { [P in keyof T]?: DeepPartial<T[P]> } : T
|
type DeepPartial<T> = T extends Function ? T : T extends Record<string, any> ? { [P in keyof T]?: DeepPartial<T[P]> } : T
|
||||||
|
|
||||||
export type UpperSnakeCase<S extends string> = Uppercase<SnakeCase<S>>
|
export type UpperSnakeCase<S extends string> = Uppercase<SnakeCase<S>>
|
||||||
@ -33,6 +34,7 @@ type Overrideable<T extends Record<string, any>, Path extends string = ''> = {
|
|||||||
|
|
||||||
type RuntimeConfigNamespace = Record<string, unknown>
|
type RuntimeConfigNamespace = Record<string, unknown>
|
||||||
|
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-empty-object-type
|
||||||
export interface PublicRuntimeConfig extends RuntimeConfigNamespace { }
|
export interface PublicRuntimeConfig extends RuntimeConfigNamespace { }
|
||||||
|
|
||||||
export interface RuntimeConfig extends RuntimeConfigNamespace {
|
export interface RuntimeConfig extends RuntimeConfigNamespace {
|
||||||
@ -136,6 +138,7 @@ export interface AppConfigInput extends CustomAppConfig {
|
|||||||
server?: never
|
server?: never
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-function-type
|
||||||
type Serializable<T> = T extends Function ? never : T extends Promise<infer U> ? Serializable<U> : T extends string & {} ? T : T extends Record<string, any> ? { [K in keyof T]: Serializable<T[K]> } : T
|
type Serializable<T> = T extends Function ? never : T extends Promise<infer U> ? Serializable<U> : T extends string & {} ? T : T extends Record<string, any> ? { [K in keyof T]: Serializable<T[K]> } : T
|
||||||
|
|
||||||
export interface NuxtAppConfig {
|
export interface NuxtAppConfig {
|
||||||
|
@ -3,13 +3,21 @@ import type { Head, MergeHead } from '@unhead/schema'
|
|||||||
/** @deprecated Extend types from `@unhead/schema` directly. This may be removed in a future minor version. */
|
/** @deprecated Extend types from `@unhead/schema` directly. This may be removed in a future minor version. */
|
||||||
export interface HeadAugmentations extends MergeHead {
|
export interface HeadAugmentations extends MergeHead {
|
||||||
// runtime type modifications
|
// runtime type modifications
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-empty-object-type
|
||||||
base?: {}
|
base?: {}
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-empty-object-type
|
||||||
link?: {}
|
link?: {}
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-empty-object-type
|
||||||
meta?: {}
|
meta?: {}
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-empty-object-type
|
||||||
style?: {}
|
style?: {}
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-empty-object-type
|
||||||
script?: {}
|
script?: {}
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-empty-object-type
|
||||||
noscript?: {}
|
noscript?: {}
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-empty-object-type
|
||||||
htmlAttrs?: {}
|
htmlAttrs?: {}
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-empty-object-type
|
||||||
bodyAttrs?: {}
|
bodyAttrs?: {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -59,6 +59,7 @@ export type NuxtLayout = {
|
|||||||
file: string
|
file: string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-empty-object-type
|
||||||
export interface ImportPresetWithDeprecation extends InlinePreset {
|
export interface ImportPresetWithDeprecation extends InlinePreset {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -54,6 +54,7 @@ export interface NuxtTypeTemplate<Options = TemplateDefaultOptions> extends Omit
|
|||||||
}
|
}
|
||||||
|
|
||||||
type _TemplatePlugin<Options> = Omit<NuxtPlugin, 'src'> & NuxtTemplate<Options>
|
type _TemplatePlugin<Options> = Omit<NuxtPlugin, 'src'> & NuxtTemplate<Options>
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-empty-object-type
|
||||||
export interface NuxtPluginTemplate<Options = TemplateDefaultOptions> extends _TemplatePlugin<Options> { }
|
export interface NuxtPluginTemplate<Options = TemplateDefaultOptions> extends _TemplatePlugin<Options> { }
|
||||||
|
|
||||||
export interface NuxtApp {
|
export interface NuxtApp {
|
||||||
|
@ -1,10 +1,14 @@
|
|||||||
import { describe, expect, it } from 'vitest'
|
import { describe, expect, it, vi } from 'vitest'
|
||||||
import { applyDefaults } from 'untyped'
|
import { applyDefaults } from 'untyped'
|
||||||
|
|
||||||
import { normalize } from 'pathe'
|
import { normalize } from 'pathe'
|
||||||
import { NuxtConfigSchema } from '../src'
|
import { NuxtConfigSchema } from '../src'
|
||||||
import type { NuxtOptions } from '../src'
|
import type { NuxtOptions } from '../src'
|
||||||
|
|
||||||
|
vi.mock('node:fs', () => ({
|
||||||
|
existsSync: (id: string) => id.endsWith('app'),
|
||||||
|
}))
|
||||||
|
|
||||||
describe('nuxt folder structure', () => {
|
describe('nuxt folder structure', () => {
|
||||||
it('should resolve directories for v3 setup correctly', async () => {
|
it('should resolve directories for v3 setup correctly', async () => {
|
||||||
const result = await applyDefaults(NuxtConfigSchema, {})
|
const result = await applyDefaults(NuxtConfigSchema, {})
|
||||||
@ -73,6 +77,23 @@ describe('nuxt folder structure', () => {
|
|||||||
}
|
}
|
||||||
`)
|
`)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('should not override value from user for serverDir', async () => {
|
||||||
|
const result = await applyDefaults(NuxtConfigSchema, { future: { compatibilityVersion: 4 }, serverDir: '/myServer' })
|
||||||
|
expect(getDirs(result as unknown as NuxtOptions)).toMatchInlineSnapshot(`
|
||||||
|
{
|
||||||
|
"dir": {
|
||||||
|
"app": "<cwd>/app",
|
||||||
|
"modules": "<cwd>/modules",
|
||||||
|
"public": "<cwd>/public",
|
||||||
|
},
|
||||||
|
"rootDir": "<cwd>",
|
||||||
|
"serverDir": "/myServer",
|
||||||
|
"srcDir": "<cwd>/app",
|
||||||
|
"workspaceDir": "<cwd>",
|
||||||
|
}
|
||||||
|
`)
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
function getDirs (options: NuxtOptions) {
|
function getDirs (options: NuxtOptions) {
|
||||||
|
@ -19,18 +19,18 @@
|
|||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/html-minifier": "4.0.5",
|
"@types/html-minifier": "4.0.5",
|
||||||
"@unocss/reset": "0.61.2",
|
"@unocss/reset": "0.61.9",
|
||||||
"critters": "0.0.24",
|
"critters": "0.0.24",
|
||||||
"execa": "9.3.0",
|
"execa": "9.3.0",
|
||||||
"globby": "14.0.2",
|
"globby": "14.0.2",
|
||||||
"html-minifier": "4.0.0",
|
"html-minifier": "4.0.0",
|
||||||
"html-validate": "8.20.1",
|
"html-validate": "8.21.0",
|
||||||
"jiti": "2.0.0-beta.3",
|
"jiti": "2.0.0-beta.3",
|
||||||
"knitwork": "1.1.0",
|
"knitwork": "1.1.0",
|
||||||
"pathe": "1.1.2",
|
"pathe": "1.1.2",
|
||||||
"prettier": "3.3.2",
|
"prettier": "3.3.3",
|
||||||
"scule": "1.3.0",
|
"scule": "1.3.0",
|
||||||
"unocss": "0.61.2",
|
"unocss": "0.61.9",
|
||||||
"vite": "5.3.3"
|
"vite": "5.3.5"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -27,16 +27,16 @@
|
|||||||
"@nuxt/schema": "workspace:*",
|
"@nuxt/schema": "workspace:*",
|
||||||
"@types/clear": "0.1.4",
|
"@types/clear": "0.1.4",
|
||||||
"@types/estree": "1.0.5",
|
"@types/estree": "1.0.5",
|
||||||
"rollup": "4.18.0",
|
"rollup": "4.20.0",
|
||||||
"unbuild": "3.0.0-rc.6",
|
"unbuild": "3.0.0-rc.7",
|
||||||
"vue": "3.4.31"
|
"vue": "3.4.34"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@nuxt/kit": "workspace:*",
|
"@nuxt/kit": "workspace:*",
|
||||||
"@rollup/plugin-replace": "^5.0.7",
|
"@rollup/plugin-replace": "^5.0.7",
|
||||||
"@vitejs/plugin-vue": "^5.0.5",
|
"@vitejs/plugin-vue": "^5.1.2",
|
||||||
"@vitejs/plugin-vue-jsx": "^4.0.0",
|
"@vitejs/plugin-vue-jsx": "^4.0.0",
|
||||||
"autoprefixer": "^10.4.19",
|
"autoprefixer": "^10.4.20",
|
||||||
"clear": "^0.1.0",
|
"clear": "^0.1.0",
|
||||||
"consola": "^3.2.3",
|
"consola": "^3.2.3",
|
||||||
"cssnano": "^7.0.4",
|
"cssnano": "^7.0.4",
|
||||||
@ -49,22 +49,22 @@
|
|||||||
"h3": "npm:h3-nightly@2.0.0-1718872656.6765a6e",
|
"h3": "npm:h3-nightly@2.0.0-1718872656.6765a6e",
|
||||||
"jiti": "^2.0.0-beta.3",
|
"jiti": "^2.0.0-beta.3",
|
||||||
"knitwork": "^1.1.0",
|
"knitwork": "^1.1.0",
|
||||||
"magic-string": "^0.30.10",
|
"magic-string": "^0.30.11",
|
||||||
"mlly": "^1.7.1",
|
"mlly": "^1.7.1",
|
||||||
"ohash": "^1.1.3",
|
"ohash": "^1.1.3",
|
||||||
"pathe": "^1.1.2",
|
"pathe": "^1.1.2",
|
||||||
"perfect-debounce": "^1.0.0",
|
"perfect-debounce": "^1.0.0",
|
||||||
"pkg-types": "^1.1.3",
|
"pkg-types": "^1.1.3",
|
||||||
"postcss": "^8.4.39",
|
"postcss": "^8.4.40",
|
||||||
"rollup-plugin-visualizer": "^5.12.0",
|
"rollup-plugin-visualizer": "^5.12.0",
|
||||||
"std-env": "^3.7.0",
|
"std-env": "^3.7.0",
|
||||||
"strip-literal": "^2.1.0",
|
"strip-literal": "^2.1.0",
|
||||||
"ufo": "^1.5.3",
|
"ufo": "^1.5.4",
|
||||||
"unenv": "^1.9.0",
|
"unenv": "^1.10.0",
|
||||||
"unplugin": "^1.11.0",
|
"unplugin": "^1.12.0",
|
||||||
"vite": "^5.3.3",
|
"vite": "^5.3.5",
|
||||||
"vite-node": "^1.6.0",
|
"vite-node": "^2.0.5",
|
||||||
"vite-plugin-checker": "^0.7.0",
|
"vite-plugin-checker": "^0.7.2",
|
||||||
"vue-bundle-renderer": "^2.1.0"
|
"vue-bundle-renderer": "^2.1.0"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
|
@ -72,6 +72,7 @@ export function ssrStylesPlugin (options: SSRStylePluginOptions): Plugin {
|
|||||||
: outputOptions.assetFileNames({
|
: outputOptions.assetFileNames({
|
||||||
type: 'asset',
|
type: 'asset',
|
||||||
name: `${fileName}-styles.mjs`,
|
name: `${fileName}-styles.mjs`,
|
||||||
|
originalFileName: `${fileName}-styles.mjs`,
|
||||||
source: '',
|
source: '',
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -97,6 +98,7 @@ export function ssrStylesPlugin (options: SSRStylePluginOptions): Plugin {
|
|||||||
this.emitFile({
|
this.emitFile({
|
||||||
type: 'asset',
|
type: 'asset',
|
||||||
fileName: 'styles.mjs',
|
fileName: 'styles.mjs',
|
||||||
|
originalFileName: 'styles.mjs',
|
||||||
source:
|
source:
|
||||||
[
|
[
|
||||||
'const interopDefault = r => r.default || r || []',
|
'const interopDefault = r => r.default || r || []',
|
||||||
|
@ -40,7 +40,7 @@ export async function warmupViteServer (
|
|||||||
entries: string[],
|
entries: string[],
|
||||||
isServer: boolean,
|
isServer: boolean,
|
||||||
) {
|
) {
|
||||||
const warmedUrls = new Set<String>()
|
const warmedUrls = new Set<string>()
|
||||||
|
|
||||||
const warmup = async (url: string) => {
|
const warmup = async (url: string) => {
|
||||||
try {
|
try {
|
||||||
|
@ -27,12 +27,12 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@nuxt/friendly-errors-webpack-plugin": "^2.6.0",
|
"@nuxt/friendly-errors-webpack-plugin": "^2.6.0",
|
||||||
"@nuxt/kit": "workspace:*",
|
"@nuxt/kit": "workspace:*",
|
||||||
"autoprefixer": "^10.4.19",
|
"autoprefixer": "^10.4.20",
|
||||||
"css-loader": "^7.1.2",
|
"css-loader": "^7.1.2",
|
||||||
"css-minimizer-webpack-plugin": "^7.0.0",
|
"css-minimizer-webpack-plugin": "^7.0.0",
|
||||||
"cssnano": "^7.0.4",
|
"cssnano": "^7.0.4",
|
||||||
"defu": "^6.1.4",
|
"defu": "^6.1.4",
|
||||||
"esbuild-loader": "^4.2.0",
|
"esbuild-loader": "^4.2.2",
|
||||||
"escape-string-regexp": "^5.0.0",
|
"escape-string-regexp": "^5.0.0",
|
||||||
"estree-walker": "^3.0.3",
|
"estree-walker": "^3.0.3",
|
||||||
"file-loader": "^6.2.0",
|
"file-loader": "^6.2.0",
|
||||||
@ -43,14 +43,14 @@
|
|||||||
"jiti": "^2.0.0-beta.3",
|
"jiti": "^2.0.0-beta.3",
|
||||||
"knitwork": "^1.1.0",
|
"knitwork": "^1.1.0",
|
||||||
"lodash-es": "4.17.21",
|
"lodash-es": "4.17.21",
|
||||||
"magic-string": "^0.30.10",
|
"magic-string": "^0.30.11",
|
||||||
"memfs": "^4.9.3",
|
"memfs": "^4.11.1",
|
||||||
"mini-css-extract-plugin": "^2.9.0",
|
"mini-css-extract-plugin": "^2.9.0",
|
||||||
"mlly": "^1.7.1",
|
"mlly": "^1.7.1",
|
||||||
"ohash": "^1.1.3",
|
"ohash": "^1.1.3",
|
||||||
"pathe": "^1.1.2",
|
"pathe": "^1.1.2",
|
||||||
"pify": "^6.1.0",
|
"pify": "^6.1.0",
|
||||||
"postcss": "^8.4.39",
|
"postcss": "^8.4.40",
|
||||||
"postcss-import": "^16.1.0",
|
"postcss-import": "^16.1.0",
|
||||||
"postcss-import-resolver": "^2.0.0",
|
"postcss-import-resolver": "^2.0.0",
|
||||||
"postcss-loader": "^8.1.1",
|
"postcss-loader": "^8.1.1",
|
||||||
@ -58,15 +58,15 @@
|
|||||||
"pug-plain-loader": "^1.1.0",
|
"pug-plain-loader": "^1.1.0",
|
||||||
"std-env": "^3.7.0",
|
"std-env": "^3.7.0",
|
||||||
"time-fix-plugin": "^2.0.7",
|
"time-fix-plugin": "^2.0.7",
|
||||||
"ufo": "^1.5.3",
|
"ufo": "^1.5.4",
|
||||||
"unenv": "^1.9.0",
|
"unenv": "^1.10.0",
|
||||||
"unplugin": "^1.11.0",
|
"unplugin": "^1.12.0",
|
||||||
"url-loader": "^4.1.1",
|
"url-loader": "^4.1.1",
|
||||||
"vue-bundle-renderer": "^2.1.0",
|
"vue-bundle-renderer": "^2.1.0",
|
||||||
"vue-loader": "^17.4.2",
|
"vue-loader": "^17.4.2",
|
||||||
"webpack": "^5.92.1",
|
"webpack": "^5.93.0",
|
||||||
"webpack-bundle-analyzer": "^4.10.2",
|
"webpack-bundle-analyzer": "^4.10.2",
|
||||||
"webpack-dev-middleware": "^7.2.1",
|
"webpack-dev-middleware": "^7.3.0",
|
||||||
"webpack-hot-middleware": "^2.26.1",
|
"webpack-hot-middleware": "^2.26.1",
|
||||||
"webpack-virtual-modules": "^0.6.2",
|
"webpack-virtual-modules": "^0.6.2",
|
||||||
"webpackbar": "^6.0.1"
|
"webpackbar": "^6.0.1"
|
||||||
@ -78,9 +78,9 @@
|
|||||||
"@types/pify": "5.0.4",
|
"@types/pify": "5.0.4",
|
||||||
"@types/webpack-bundle-analyzer": "4.7.0",
|
"@types/webpack-bundle-analyzer": "4.7.0",
|
||||||
"@types/webpack-hot-middleware": "2.25.9",
|
"@types/webpack-hot-middleware": "2.25.9",
|
||||||
"rollup": "4.18.0",
|
"rollup": "4.20.0",
|
||||||
"unbuild": "3.0.0-rc.6",
|
"unbuild": "3.0.0-rc.7",
|
||||||
"vue": "3.4.31"
|
"vue": "3.4.34"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"vue": "^3.3.4"
|
"vue": "^3.3.4"
|
||||||
|
@ -4,7 +4,7 @@ import { defu } from 'defu'
|
|||||||
import { createJiti } from 'jiti'
|
import { createJiti } from 'jiti'
|
||||||
import type { Plugin } from 'postcss'
|
import type { Plugin } from 'postcss'
|
||||||
|
|
||||||
const isPureObject = (obj: unknown): obj is Object => obj !== null && !Array.isArray(obj) && typeof obj === 'object'
|
const isPureObject = (obj: unknown): obj is object => obj !== null && !Array.isArray(obj) && typeof obj === 'object'
|
||||||
|
|
||||||
function sortPlugins ({ plugins, order }: NuxtOptions['postcss']): string[] {
|
function sortPlugins ({ plugins, order }: NuxtOptions['postcss']): string[] {
|
||||||
const names = Object.keys(plugins)
|
const names = Object.keys(plugins)
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user