From 654566794321e299a7d938b7ded0b7a977e51322 Mon Sep 17 00:00:00 2001 From: Daniel Roe Date: Fri, 22 Apr 2022 16:21:37 +0100 Subject: [PATCH 01/34] feat(nuxt): support creating errors directly from `throwError` --- packages/nuxt/src/app/composables/error.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/nuxt/src/app/composables/error.ts b/packages/nuxt/src/app/composables/error.ts index cdee4541c7b..68d0395c66a 100644 --- a/packages/nuxt/src/app/composables/error.ts +++ b/packages/nuxt/src/app/composables/error.ts @@ -1,3 +1,4 @@ +import { createError, H3Error } from 'h3' import { useNuxtApp, useState } from '#app' export const useError = () => { @@ -5,10 +6,10 @@ export const useError = () => { return useState('error', () => process.server ? nuxtApp.ssrContext.error : nuxtApp.payload.error) } -export const throwError = (_err: string | Error) => { +export const throwError = (_err: string | Error | Partial) => { const nuxtApp = useNuxtApp() const error = useError() - const err = typeof _err === 'string' ? new Error(_err) : _err + const err = typeof _err === 'string' ? new Error(_err) : _err && typeof _err === 'object' ? createError(_err) : _err nuxtApp.callHook('app:error', err) if (process.server) { nuxtApp.ssrContext.error = nuxtApp.ssrContext.error || err From ab3bca37742f8cca04108de368548e99821ed937 Mon Sep 17 00:00:00 2001 From: Daniel Roe Date: Fri, 22 Apr 2022 16:43:01 +0100 Subject: [PATCH 02/34] fix(nuxt): clear errors _after_ route resolves --- packages/nuxt/src/app/plugins/router.ts | 9 ++++----- packages/nuxt/src/pages/runtime/router.ts | 9 ++++----- 2 files changed, 8 insertions(+), 10 deletions(-) diff --git a/packages/nuxt/src/app/plugins/router.ts b/packages/nuxt/src/app/plugins/router.ts index 3fcbc18d674..f00c743eafe 100644 --- a/packages/nuxt/src/app/plugins/router.ts +++ b/packages/nuxt/src/app/plugins/router.ts @@ -106,11 +106,6 @@ export default defineNuxtPlugin<{ route: Route, router: Router }>((nuxtApp) => { // Resolve route const to = getRouteFromPath(url) - if (process.client && !nuxtApp.isHydrating) { - // Clear any existing errors - await callWithNuxt(nuxtApp, clearError) - } - // Run beforeEach hooks for (const middleware of hooks['navigate:before']) { const result = await middleware(to, route) @@ -127,6 +122,10 @@ export default defineNuxtPlugin<{ route: Route, router: Router }>((nuxtApp) => { Object.assign(route, to) if (process.client) { window.history[replace ? 'replaceState' : 'pushState']({}, '', url) + if (!nuxtApp.isHydrating) { + // Clear any existing errors + await callWithNuxt(nuxtApp, clearError) + } } // Run afterEach hooks for (const middleware of hooks['navigate:after']) { diff --git a/packages/nuxt/src/pages/runtime/router.ts b/packages/nuxt/src/pages/runtime/router.ts index 9b3e6d68542..29b75e29990 100644 --- a/packages/nuxt/src/pages/runtime/router.ts +++ b/packages/nuxt/src/pages/runtime/router.ts @@ -125,11 +125,6 @@ export default defineNuxtPlugin((nuxtApp) => { } } - if (process.client && !nuxtApp.isHydrating) { - // Clear any existing errors - await callWithNuxt(nuxtApp, clearError) - } - for (const entry of middlewareEntries) { const middleware = typeof entry === 'string' ? nuxtApp._middleware.named[entry] || await namedMiddleware[entry]?.().then(r => r.default || r) : entry @@ -152,6 +147,10 @@ export default defineNuxtPlugin((nuxtApp) => { router.afterEach(() => { delete nuxtApp._processingMiddleware + if (process.client && !nuxtApp.isHydrating) { + // Clear any existing errors + callWithNuxt(nuxtApp, clearError) + } }) nuxtApp.hook('app:created', async () => { From 1481e0081860ed2948e8a04a9a252731913443ac Mon Sep 17 00:00:00 2001 From: Daniel Roe Date: Fri, 22 Apr 2022 16:53:48 +0100 Subject: [PATCH 03/34] docs: update documentation --- .../2.guide/2.features/7.error-handling.md | 14 ++++++++++++- docs/content/3.api/3.utils/throw-error.md | 20 ++++++++++++++++++- 2 files changed, 32 insertions(+), 2 deletions(-) diff --git a/docs/content/2.guide/2.features/7.error-handling.md b/docs/content/2.guide/2.features/7.error-handling.md index c65ed759f82..bc511ac5cbf 100644 --- a/docs/content/2.guide/2.features/7.error-handling.md +++ b/docs/content/2.guide/2.features/7.error-handling.md @@ -82,10 +82,22 @@ This function will return the global Nuxt error that is being handled. ### `throwError` -* `function throwError (err: string | Error): Error` +* `function throwError (err: string | Error | Partial): Error` You can call this function at any point on client-side, or (on server side) directly within middleware, plugins or `setup()` functions. It will trigger a full-screen error page (as above) which you can clear with `clearError`. +### Example + +```vue [pages/movies/[slug].vue] + +``` + ::ReadMore{link="/api/utils/throw-error"} :: diff --git a/docs/content/3.api/3.utils/throw-error.md b/docs/content/3.api/3.utils/throw-error.md index 7a9306def28..9a83651b2b7 100644 --- a/docs/content/3.api/3.utils/throw-error.md +++ b/docs/content/3.api/3.utils/throw-error.md @@ -6,10 +6,11 @@ Within your pages, components and plugins you can use `throwError` to throw an e **Parameters:** -- `error`: `string | Error` +- `error`: `string | Error | Partial` ```js throwError("😱 Oh no, an error has been thrown.") +throwError({ statusCode: 404, statusMessage: "Page Not Found" }) ``` The thrown error is set in the state using [`useError()`](/api/composables/use-error) to create a reactive and SSR-friendly shared error state across components. @@ -18,3 +19,20 @@ The thrown error is set in the state using [`useError()`](/api/composables/use-e ::ReadMore{link="/guide/features/error-handling"} :: + +## Throwing errors in API routes + +You can use `createError` from [`h3`](https://github.com/unjs/h3) package to trigger error handling in server API routes. + +**Example:** + +```js +import { createError } from 'h3' + +export default eventHandler(() => { + return createError({ + statusCode: 404, + statusMessage: 'Page Not Found' + }) +} +``` From 4c899c74c0cdc17d32f5d7c499137abb8977061c Mon Sep 17 00:00:00 2001 From: Daniel Roe Date: Fri, 22 Apr 2022 16:54:42 +0100 Subject: [PATCH 04/34] style: spacing --- packages/nuxt/src/app/plugins/router.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/nuxt/src/app/plugins/router.ts b/packages/nuxt/src/app/plugins/router.ts index f00c743eafe..a9dad4d6560 100644 --- a/packages/nuxt/src/app/plugins/router.ts +++ b/packages/nuxt/src/app/plugins/router.ts @@ -123,7 +123,7 @@ export default defineNuxtPlugin<{ route: Route, router: Router }>((nuxtApp) => { if (process.client) { window.history[replace ? 'replaceState' : 'pushState']({}, '', url) if (!nuxtApp.isHydrating) { - // Clear any existing errors + // Clear any existing errors await callWithNuxt(nuxtApp, clearError) } } From 3b205cab6ef0979505938571f4de04c2fdfd9fe9 Mon Sep 17 00:00:00 2001 From: Daniel Roe Date: Fri, 22 Apr 2022 17:07:39 +0100 Subject: [PATCH 05/34] fix: don't re-create errors --- packages/nuxt/src/app/components/nuxt-error-page.vue | 2 +- packages/nuxt/src/app/composables/error.ts | 7 ++++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/packages/nuxt/src/app/components/nuxt-error-page.vue b/packages/nuxt/src/app/components/nuxt-error-page.vue index 9ccb8c1379b..35bcbffbc9d 100644 --- a/packages/nuxt/src/app/components/nuxt-error-page.vue +++ b/packages/nuxt/src/app/components/nuxt-error-page.vue @@ -34,7 +34,7 @@ const stacktrace = (error.stack || '') const statusCode = String(error.statusCode || 500) const is404 = statusCode === '404' -const statusMessage = error.statusMessage ?? is404 ? 'Page Not Found' : 'Internal Server Error' +const statusMessage = error.statusMessage ?? (is404 ? 'Page Not Found' : 'Internal Server Error') const description = error.message || error.toString() const stack = process.dev && !is404 ? error.description || `
${stacktrace}
` : undefined diff --git a/packages/nuxt/src/app/composables/error.ts b/packages/nuxt/src/app/composables/error.ts index 68d0395c66a..956574e3406 100644 --- a/packages/nuxt/src/app/composables/error.ts +++ b/packages/nuxt/src/app/composables/error.ts @@ -9,7 +9,12 @@ export const useError = () => { export const throwError = (_err: string | Error | Partial) => { const nuxtApp = useNuxtApp() const error = useError() - const err = typeof _err === 'string' ? new Error(_err) : _err && typeof _err === 'object' ? createError(_err) : _err + console.log({ _err }) + const err = typeof _err === 'string' + ? new Error(_err) + : _err && typeof _err === 'object' && !(_err instanceof Error) + ? createError(_err) + : _err nuxtApp.callHook('app:error', err) if (process.server) { nuxtApp.ssrContext.error = nuxtApp.ssrContext.error || err From 5a8bcb64abcc3d477aa326e2223a54d678385cbd Mon Sep 17 00:00:00 2001 From: Daniel Roe Date: Fri, 22 Apr 2022 17:20:19 +0100 Subject: [PATCH 06/34] Update docs/content/2.guide/2.features/7.error-handling.md Co-authored-by: pooya parsa --- docs/content/2.guide/2.features/7.error-handling.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/content/2.guide/2.features/7.error-handling.md b/docs/content/2.guide/2.features/7.error-handling.md index bc511ac5cbf..7b10d18e878 100644 --- a/docs/content/2.guide/2.features/7.error-handling.md +++ b/docs/content/2.guide/2.features/7.error-handling.md @@ -93,7 +93,7 @@ You can call this function at any point on client-side, or (on server side) dire const route = useRoute() const { data: movie } = await useFetch(`/api/movies/${route.params.slug}`) if (!movie.value) { - throwError({ statusCode: 404, statusMessage: 'Page Not Found' }) + return throwError({ statusCode: 404, statusMessage: 'Page Not Found' }) } ``` From d224281f9b7990afb7ab41ab16bd2012d82cea2c Mon Sep 17 00:00:00 2001 From: Daniel Roe Date: Fri, 22 Apr 2022 17:26:37 +0100 Subject: [PATCH 07/34] Update docs/content/3.api/3.utils/throw-error.md Co-authored-by: pooya parsa --- docs/content/3.api/3.utils/throw-error.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/content/3.api/3.utils/throw-error.md b/docs/content/3.api/3.utils/throw-error.md index 9a83651b2b7..4875db9ca2e 100644 --- a/docs/content/3.api/3.utils/throw-error.md +++ b/docs/content/3.api/3.utils/throw-error.md @@ -30,7 +30,7 @@ You can use `createError` from [`h3`](https://github.com/unjs/h3) package to tri import { createError } from 'h3' export default eventHandler(() => { - return createError({ + throw createError({ statusCode: 404, statusMessage: 'Page Not Found' }) From 727e58529c754a9bf1de3b4b32db36890990d4f1 Mon Sep 17 00:00:00 2001 From: Daniel Roe Date: Fri, 22 Apr 2022 17:28:07 +0100 Subject: [PATCH 08/34] Update docs/content/2.guide/2.features/7.error-handling.md Co-authored-by: pooya parsa --- docs/content/2.guide/2.features/7.error-handling.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/content/2.guide/2.features/7.error-handling.md b/docs/content/2.guide/2.features/7.error-handling.md index 7b10d18e878..aa20e9fd813 100644 --- a/docs/content/2.guide/2.features/7.error-handling.md +++ b/docs/content/2.guide/2.features/7.error-handling.md @@ -82,7 +82,7 @@ This function will return the global Nuxt error that is being handled. ### `throwError` -* `function throwError (err: string | Error | Partial): Error` +* `function throwError (err: string | Error | { statusCode, statusMessage }>): Error` You can call this function at any point on client-side, or (on server side) directly within middleware, plugins or `setup()` functions. It will trigger a full-screen error page (as above) which you can clear with `clearError`. From 3983e87ec73889e41321ec41699c4e82f42477e6 Mon Sep 17 00:00:00 2001 From: Daniel Roe Date: Fri, 22 Apr 2022 17:29:39 +0100 Subject: [PATCH 09/34] Update packages/nuxt/src/app/composables/error.ts Co-authored-by: pooya parsa --- packages/nuxt/src/app/composables/error.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/nuxt/src/app/composables/error.ts b/packages/nuxt/src/app/composables/error.ts index 956574e3406..e6a3ff1747c 100644 --- a/packages/nuxt/src/app/composables/error.ts +++ b/packages/nuxt/src/app/composables/error.ts @@ -9,7 +9,6 @@ export const useError = () => { export const throwError = (_err: string | Error | Partial) => { const nuxtApp = useNuxtApp() const error = useError() - console.log({ _err }) const err = typeof _err === 'string' ? new Error(_err) : _err && typeof _err === 'object' && !(_err instanceof Error) From 75466e6110c356fc6f35dc79bc6f7fd7d7bea08f Mon Sep 17 00:00:00 2001 From: Daniel Roe Date: Fri, 22 Apr 2022 17:57:41 +0100 Subject: [PATCH 10/34] docs: check error value --- docs/content/2.guide/2.features/7.error-handling.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/content/2.guide/2.features/7.error-handling.md b/docs/content/2.guide/2.features/7.error-handling.md index aa20e9fd813..e04245b849d 100644 --- a/docs/content/2.guide/2.features/7.error-handling.md +++ b/docs/content/2.guide/2.features/7.error-handling.md @@ -91,8 +91,8 @@ You can call this function at any point on client-side, or (on server side) dire ```vue [pages/movies/[slug].vue] From 5f4a112bd2a7fbc80481beef4e59118b429f611e Mon Sep 17 00:00:00 2001 From: Daniel Roe Date: Tue, 3 May 2022 07:55:52 +0100 Subject: [PATCH 11/34] fix: restore code missed in merge --- packages/nuxt/src/pages/runtime/router.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/packages/nuxt/src/pages/runtime/router.ts b/packages/nuxt/src/pages/runtime/router.ts index 1d38023583a..1819e37cb59 100644 --- a/packages/nuxt/src/pages/runtime/router.ts +++ b/packages/nuxt/src/pages/runtime/router.ts @@ -107,7 +107,11 @@ export default defineNuxtPlugin(async (nuxtApp) => { named: {} } - router.afterEach((to) => { + router.afterEach(async (to) => { + if (process.client && !nuxtApp.isHydrating) { + // Clear any existing errors + await callWithNuxt(nuxtApp, clearError) + } if (to.matched.length === 0) { callWithNuxt(nuxtApp, throwError, [createError({ statusCode: 404, From aede51c32395647654651fe228299b719ae17851 Mon Sep 17 00:00:00 2001 From: Daniel Roe Date: Tue, 3 May 2022 09:34:21 +0100 Subject: [PATCH 12/34] fix: support `throw createError()` directly --- .../2.guide/2.features/7.error-handling.md | 20 +++++++++++++------ .../nuxt/src/app/components/nuxt-root.vue | 4 +++- packages/nuxt/src/app/composables/error.ts | 2 +- packages/nuxt/src/auto-imports/presets.ts | 6 ++++++ 4 files changed, 24 insertions(+), 8 deletions(-) diff --git a/docs/content/2.guide/2.features/7.error-handling.md b/docs/content/2.guide/2.features/7.error-handling.md index e04245b849d..59262b2318d 100644 --- a/docs/content/2.guide/2.features/7.error-handling.md +++ b/docs/content/2.guide/2.features/7.error-handling.md @@ -80,24 +80,32 @@ This function will return the global Nuxt error that is being handled. ::ReadMore{link="/api/composables/use-error"} :: -### `throwError` +### `createError` + +* `function createError (err: { cause, data, message, name, stack, statusCode, statusMessage }): Error` -* `function throwError (err: string | Error | { statusCode, statusMessage }>): Error` +You can use this function to create an error object with additional metadata. It is usable in both the Vue and Nitro portions of your app, and is meant to be thrown. -You can call this function at any point on client-side, or (on server side) directly within middleware, plugins or `setup()` functions. It will trigger a full-screen error page (as above) which you can clear with `clearError`. +If you throw an error created with `createError`, it will trigger a full-screen error page which you can clear with `clearError`. ### Example ```vue [pages/movies/[slug].vue] ``` +### `throwError` + +* `function throwError (err: string | Error | { statusCode, statusMessage }): Error` + +You can call this function at any point on client-side, or (on server side) directly within middleware, plugins or `setup()` functions. It will trigger a full-screen error page which you can clear with `clearError`. + ::ReadMore{link="/api/utils/throw-error"} :: diff --git a/packages/nuxt/src/app/components/nuxt-root.vue b/packages/nuxt/src/app/components/nuxt-root.vue index 9279c810129..387b6c5a890 100644 --- a/packages/nuxt/src/app/components/nuxt-root.vue +++ b/packages/nuxt/src/app/components/nuxt-root.vue @@ -7,6 +7,7 @@ ``` -### `throwError` +### `showError` -* `function throwError (err: string | Error | { statusCode, statusMessage }): Error` +* `function showError (err: string | Error | { statusCode, statusMessage }): Error` You can call this function at any point on client-side, or (on server side) directly within middleware, plugins or `setup()` functions. It will trigger a full-screen error page which you can clear with `clearError`. It is recommended instead to use `throw createError()`. -::ReadMore{link="/api/utils/throw-error"} +::ReadMore{link="/api/utils/show-error"} :: ### `clearError` diff --git a/docs/content/3.api/3.utils/create-error.md b/docs/content/3.api/3.utils/create-error.md index 223d966b691..480b1bf7fca 100644 --- a/docs/content/3.api/3.utils/create-error.md +++ b/docs/content/3.api/3.utils/create-error.md @@ -1,7 +1,44 @@ # `createError` -::ReadMore{link="/guide/features/error-handling"} -:: +You can use this function to create an error object with additional metadata. It is usable in both the Vue and Nitro portions of your app, and is meant to be thrown. + +**Parameters:** + +* err: { cause, data, message, name, stack, statusCode, statusMessage, fatal } + +## Throwing errors in your Vue app + +If you throw an error created with `createError`: + +* on server-side, it will trigger a full-screen error page which you can clear with `clearError`. +* on client-side, it will throw a non-fatal error for you to handle. If you need to trigger a full-screen error page, then you can do this by setting `fatal: true`. -::NeedContribution +### Example + +```vue [pages/movies/[slug].vue] + +``` + +## Throwing errors in API routes + +You can use `createError` to trigger error handling in server API routes. + +### Example + +```js +export default eventHandler(() => { + throw createError({ + statusCode: 404, + statusMessage: 'Page Not Found' + }) +} +``` + +::ReadMore{link="/guide/features/error-handling"} :: diff --git a/docs/content/3.api/3.utils/show-error.md b/docs/content/3.api/3.utils/show-error.md new file mode 100644 index 00000000000..ff128c9b0bd --- /dev/null +++ b/docs/content/3.api/3.utils/show-error.md @@ -0,0 +1,21 @@ +# `showError` + +Nuxt provides a quick and simple way to show a full screen error page if needed. + +Within your pages, components and plugins you can use `showError` to show an error error. + +**Parameters:** + +- `error`: `string | Error | Partial<{ cause, data, message, name, stack, statusCode, statusMessage }>` + +```js +showError("😱 Oh no, an error has been thrown.") +showError({ statusCode: 404, statusMessage: "Page Not Found" }) +``` + +The error is set in the state using [`useError()`](/api/composables/use-error) to create a reactive and SSR-friendly shared error state across components. + +`showError` calls the `app:error` hook. + +::ReadMore{link="/guide/features/error-handling"} +:: diff --git a/docs/content/3.api/3.utils/throw-error.md b/docs/content/3.api/3.utils/throw-error.md deleted file mode 100644 index 44607aeea64..00000000000 --- a/docs/content/3.api/3.utils/throw-error.md +++ /dev/null @@ -1,36 +0,0 @@ -# `throwError` - -Nuxt provides a quick and simple way to throw errors. - -Within your pages, components and plugins you can use `throwError` to throw an error. - -**Parameters:** - -- `error`: `string | Error | Partial<{ cause, data, message, name, stack, statusCode, statusMessage }>` - -```js -throwError("😱 Oh no, an error has been thrown.") -throwError({ statusCode: 404, statusMessage: "Page Not Found" }) -``` - -The thrown error is set in the state using [`useError()`](/api/composables/use-error) to create a reactive and SSR-friendly shared error state across components. - -`throwError` calls the `app:error` hook. - -::ReadMore{link="/guide/features/error-handling"} -:: - -## Throwing errors in API routes - -You can use the auto-imported `createError` from [`h3`](https://github.com/unjs/h3) package to trigger error handling in server API routes. - -**Example:** - -```js -export default eventHandler(() => { - throw createError({ - statusCode: 404, - statusMessage: 'Page Not Found' - }) -} -``` diff --git a/examples/app/error-handling/app.vue b/examples/app/error-handling/app.vue index 66f9ee9c715..bbd937d8ded 100644 --- a/examples/app/error-handling/app.vue +++ b/examples/app/error-handling/app.vue @@ -1,5 +1,5 @@ diff --git a/packages/nuxt/src/app/composables/error.ts b/packages/nuxt/src/app/composables/error.ts index df108233715..d5a29a7c5b0 100644 --- a/packages/nuxt/src/app/composables/error.ts +++ b/packages/nuxt/src/app/composables/error.ts @@ -10,7 +10,7 @@ export interface NuxtError extends H3Error { fatal?: boolean } -export const throwError = (_err: string | Error | Partial) => { +export const showError = (_err: string | Error | Partial) => { const err = createError(_err) err.fatal = true @@ -30,6 +30,9 @@ export const throwError = (_err: string | Error | Partial) => { return err } +/** @deprecated Use `throw createError()` or `showError` */ +export const throwError = showError + export const clearError = async (options: { redirect?: string } = {}) => { const nuxtApp = useNuxtApp() const error = useError() diff --git a/packages/nuxt/src/app/composables/index.ts b/packages/nuxt/src/app/composables/index.ts index e60d2dde8de..cb3eb864379 100644 --- a/packages/nuxt/src/app/composables/index.ts +++ b/packages/nuxt/src/app/composables/index.ts @@ -3,7 +3,7 @@ export { useAsyncData, useLazyAsyncData, refreshNuxtData } from './asyncData' export type { AsyncDataOptions, AsyncData } from './asyncData' export { useHydration } from './hydrate' export { useState } from './state' -export { clearError, createError, isNuxtError, throwError, useError } from './error' +export { clearError, createError, isNuxtError, throwError, showError, useError } from './error' export type { NuxtError } from './error' export { useFetch, useLazyFetch } from './fetch' export type { FetchResult, UseFetchOptions } from './fetch' diff --git a/packages/nuxt/src/app/plugins/router.ts b/packages/nuxt/src/app/plugins/router.ts index 50e5d6bae1e..bde980db0c7 100644 --- a/packages/nuxt/src/app/plugins/router.ts +++ b/packages/nuxt/src/app/plugins/router.ts @@ -3,7 +3,7 @@ import { parseURL, parseQuery, withoutBase, isEqual, joinURL } from 'ufo' import { createError } from 'h3' import { defineNuxtPlugin } from '..' import { callWithNuxt } from '../nuxt' -import { clearError, navigateTo, throwError, useRuntimeConfig } from '#app' +import { clearError, navigateTo, showError, useRuntimeConfig } from '#app' // @ts-ignore import { globalMiddleware } from '#build/middleware' @@ -228,7 +228,7 @@ export default defineNuxtPlugin<{ route: Route, router: Router }>((nuxtApp) => { const error = result || createError({ statusMessage: `Route navigation aborted: ${initialURL}` }) - return callWithNuxt(nuxtApp, throwError, [error]) + return callWithNuxt(nuxtApp, showError, [error]) } } if (result || result === false) { return result } diff --git a/packages/nuxt/src/auto-imports/presets.ts b/packages/nuxt/src/auto-imports/presets.ts index 95688f50355..f2640359034 100644 --- a/packages/nuxt/src/auto-imports/presets.ts +++ b/packages/nuxt/src/auto-imports/presets.ts @@ -43,6 +43,7 @@ export const appPreset = defineUnimportPreset({ 'abortNavigation', 'addRouteMiddleware', 'throwError', + 'showError', 'clearError', 'isNuxtError', 'useError', diff --git a/packages/nuxt/src/pages/runtime/router.ts b/packages/nuxt/src/pages/runtime/router.ts index 824dddeeaea..2ab21f2a261 100644 --- a/packages/nuxt/src/pages/runtime/router.ts +++ b/packages/nuxt/src/pages/runtime/router.ts @@ -9,7 +9,7 @@ import { import { createError } from 'h3' import { withoutBase, isEqual } from 'ufo' import NuxtPage from './page' -import { callWithNuxt, defineNuxtPlugin, useRuntimeConfig, throwError, clearError, navigateTo, useError } from '#app' +import { callWithNuxt, defineNuxtPlugin, useRuntimeConfig, showError, clearError, navigateTo, useError } from '#app' // @ts-ignore import routes from '#build/routes' // @ts-ignore @@ -117,7 +117,7 @@ export default defineNuxtPlugin(async (nuxtApp) => { await router.isReady() } catch (error) { // We'll catch 404s here - callWithNuxt(nuxtApp, throwError, [error]) + callWithNuxt(nuxtApp, showError, [error]) } router.beforeEach(async (to, from) => { @@ -154,7 +154,7 @@ export default defineNuxtPlugin(async (nuxtApp) => { const error = result || createError({ statusMessage: `Route navigation aborted: ${initialURL}` }) - return callWithNuxt(nuxtApp, throwError, [error]) + return callWithNuxt(nuxtApp, showError, [error]) } } if (result || result === false) { return result } @@ -169,7 +169,7 @@ export default defineNuxtPlugin(async (nuxtApp) => { await callWithNuxt(nuxtApp, clearError) } if (to.matched.length === 0) { - callWithNuxt(nuxtApp, throwError, [createError({ + callWithNuxt(nuxtApp, showError, [createError({ statusCode: 404, statusMessage: `Page not found: ${to.fullPath}` })]) @@ -192,7 +192,7 @@ export default defineNuxtPlugin(async (nuxtApp) => { }) } catch (error) { // We'll catch middleware errors or deliberate exceptions here - callWithNuxt(nuxtApp, throwError, [error]) + callWithNuxt(nuxtApp, showError, [error]) } }) From f61e13cd5b0c2eb712c97fdbc18cbd814f93d4d5 Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Thu, 21 Jul 2022 14:12:14 +0200 Subject: [PATCH 32/34] upgrade h3 and reuse fatal --- packages/nuxt/package.json | 2 +- packages/nuxt/src/app/components/nuxt-root.vue | 2 +- packages/nuxt/src/app/composables/error.ts | 7 +------ packages/vite/package.json | 2 +- yarn.lock | 16 ++++++++++++++-- 5 files changed, 18 insertions(+), 11 deletions(-) diff --git a/packages/nuxt/package.json b/packages/nuxt/package.json index b3f4af3846e..5b320350f48 100644 --- a/packages/nuxt/package.json +++ b/packages/nuxt/package.json @@ -46,7 +46,7 @@ "escape-string-regexp": "^5.0.0", "fs-extra": "^10.1.0", "globby": "^13.1.2", - "h3": "^0.7.10", + "h3": "^0.7.12", "hash-sum": "^2.0.0", "hookable": "^5.1.1", "knitwork": "^0.1.2", diff --git a/packages/nuxt/src/app/components/nuxt-root.vue b/packages/nuxt/src/app/components/nuxt-root.vue index cab16e7aa9e..da58c152a93 100644 --- a/packages/nuxt/src/app/components/nuxt-root.vue +++ b/packages/nuxt/src/app/components/nuxt-root.vue @@ -24,7 +24,7 @@ if (process.dev && results && results.some(i => i && 'then' in i)) { const error = useError() onErrorCaptured((err, target, info) => { nuxtApp.hooks.callHook('vue:error', err, target, info).catch(hookError => console.error('[nuxt] Error in `vue:error` hook', hookError)) - if (process.server || (isNuxtError(err) && err.fatal)) { + if (process.server || (isNuxtError(err) && (err.fatal || err.unhandled))) { callWithNuxt(nuxtApp, showError, [err]) } }) diff --git a/packages/nuxt/src/app/composables/error.ts b/packages/nuxt/src/app/composables/error.ts index d5a29a7c5b0..e50c8b72500 100644 --- a/packages/nuxt/src/app/composables/error.ts +++ b/packages/nuxt/src/app/composables/error.ts @@ -6,9 +6,7 @@ export const useError = () => { return useState('error', () => process.server ? nuxtApp.ssrContext.error : nuxtApp.payload.error) } -export interface NuxtError extends H3Error { - fatal?: boolean -} +export interface NuxtError extends H3Error {} export const showError = (_err: string | Error | Partial) => { const err = createError(_err) @@ -47,9 +45,6 @@ export const isNuxtError = (err?: string | object): err is NuxtError => err && t export const createError = (err: string | Partial): NuxtError => { const _err: NuxtError = _createError(err) - if (err && typeof err === 'object' && err.fatal) { - _err.fatal = true - } ;(_err as any).__nuxt_error = true return _err } diff --git a/packages/vite/package.json b/packages/vite/package.json index 850d442c002..86095d430a3 100644 --- a/packages/vite/package.json +++ b/packages/vite/package.json @@ -33,7 +33,7 @@ "externality": "^0.2.2", "fs-extra": "^10.1.0", "get-port-please": "^2.5.0", - "h3": "^0.7.10", + "h3": "^0.7.12", "knitwork": "^0.1.2", "magic-string": "^0.26.2", "mlly": "^0.5.5", diff --git a/yarn.lock b/yarn.lock index 715932666f7..b8bb76af15a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1908,7 +1908,7 @@ __metadata: externality: ^0.2.2 fs-extra: ^10.1.0 get-port-please: ^2.5.0 - h3: ^0.7.10 + h3: ^0.7.12 knitwork: ^0.1.2 magic-string: ^0.26.2 mlly: ^0.5.5 @@ -7223,6 +7223,18 @@ __metadata: languageName: node linkType: hard +"h3@npm:^0.7.12": + version: 0.7.12 + resolution: "h3@npm:0.7.12" + dependencies: + cookie-es: ^0.5.0 + destr: ^1.1.1 + radix3: ^0.1.2 + ufo: ^0.8.5 + checksum: cde4a733910a06a36fb9a26222a624bdd51314bd4a82c7f3830405d76f152cbaf59bbf8438207d76ce5e49a8d23807ba14055965bad64f9e11c598002aeafd1a + languageName: node + linkType: hard + "handlebars@npm:^4.7.7": version: 4.7.7 resolution: "handlebars@npm:4.7.7" @@ -9814,7 +9826,7 @@ __metadata: escape-string-regexp: ^5.0.0 fs-extra: ^10.1.0 globby: ^13.1.2 - h3: ^0.7.10 + h3: ^0.7.12 hash-sum: ^2.0.0 hookable: ^5.1.1 knitwork: ^0.1.2 From b04dda0f7bcfd792feccbeab55a3b51bc785fca3 Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Thu, 21 Jul 2022 14:46:05 +0200 Subject: [PATCH 33/34] only log unhandled errors --- packages/nuxt/src/core/runtime/nitro/error.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/nuxt/src/core/runtime/nitro/error.ts b/packages/nuxt/src/core/runtime/nitro/error.ts index 381832fb500..a34db5c670d 100644 --- a/packages/nuxt/src/core/runtime/nitro/error.ts +++ b/packages/nuxt/src/core/runtime/nitro/error.ts @@ -24,8 +24,8 @@ export default async function errorhandler (_error, event) { event.res.statusMessage = errorObject.statusMessage // Console output - if (errorObject.statusCode !== 404) { - console.error('[nuxt] [request error]', errorObject.message + '\n' + stack.map(l => ' ' + l.text).join(' \n')) + if ((_error as any).unhandled) { + console.error('[nuxt] [unhandled request error]', errorObject.message + '\n' + stack.map(l => ' ' + l.text).join(' \n')) } // JSON response From e69bdf86e6a559689c092f301910d5b7940526cc Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Thu, 21 Jul 2022 14:49:19 +0200 Subject: [PATCH 34/34] update ui templates --- packages/nuxt/package.json | 2 +- yarn.lock | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/nuxt/package.json b/packages/nuxt/package.json index 5b320350f48..cab9fe52870 100644 --- a/packages/nuxt/package.json +++ b/packages/nuxt/package.json @@ -34,7 +34,7 @@ "@nuxt/kit": "^3.0.0-rc.6", "@nuxt/schema": "^3.0.0-rc.6", "@nuxt/telemetry": "^2.1.3", - "@nuxt/ui-templates": "^0.2.1", + "@nuxt/ui-templates": "^0.3.0", "@nuxt/vite-builder": "^3.0.0-rc.6", "@vue/reactivity": "^3.2.37", "@vue/shared": "^3.2.37", diff --git a/yarn.lock b/yarn.lock index b8bb76af15a..e3994371681 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1858,10 +1858,10 @@ __metadata: languageName: unknown linkType: soft -"@nuxt/ui-templates@npm:^0.2.1": - version: 0.2.1 - resolution: "@nuxt/ui-templates@npm:0.2.1" - checksum: a79315c2777b175b007106b51c2db0a56c815e6c6c24f276eaf8fa86dbb34cac135b8c03ed59f8adaeacbcefe02deefa182fc9cb5d1ab04222bc0aec1b2e8222 +"@nuxt/ui-templates@npm:^0.3.0": + version: 0.3.0 + resolution: "@nuxt/ui-templates@npm:0.3.0" + checksum: 075ccb9aa6c781b752a81c1866673623e9f8509b587701352b53620e092a54c943e853d984bf6951295f0c9a999098f5fc2f25fc3df72c7f2b17dcc9eb619bc9 languageName: node linkType: hard @@ -9812,7 +9812,7 @@ __metadata: "@nuxt/kit": ^3.0.0-rc.6 "@nuxt/schema": ^3.0.0-rc.6 "@nuxt/telemetry": ^2.1.3 - "@nuxt/ui-templates": ^0.2.1 + "@nuxt/ui-templates": ^0.3.0 "@nuxt/vite-builder": ^3.0.0-rc.6 "@types/fs-extra": ^9.0.13 "@types/hash-sum": ^1.0.0