Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add error composables from nuxt 3 #588

Merged
merged 3 commits into from
Nov 30, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 7 additions & 2 deletions playground/pages/error.vue
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
<template>
<div />
<div>
{{ state.attr }}
{{ data.something }}
</div>
</template>

<script setup>
throw new Error('This is a custom error')
throw createError({ statusCode: 422, fatal: true, statusMessage: 'This is a custom error' })
// eslint-disable-next-line no-unreachable
const state = ref({ attr: 'Hello World' })
</script>
8 changes: 7 additions & 1 deletion src/imports/presets.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,13 @@ export const appPreset = defineUnimportPreset({
'navigateTo',
'abortNavigation',
'addRouteMiddleware',
'useNuxt2Meta'
'useNuxt2Meta',
'clearError',
'createError',
'isNuxtError',
'throwError',
'showError',
'useError'
]
})

Expand Down
4 changes: 3 additions & 1 deletion src/runtime/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,11 @@ export interface VueAppCompat {
}

export interface RuntimeNuxtHooks {
'vue:setup': () => void
'app:error': (err: any) => void | Promise<void>
'app:error:cleared': (options: { redirect?: string }) => void | Promise<void>
'app:mounted': (app: VueAppCompat) => void | Promise<void>
'meta:register': (metaRenderers: any[]) => void | Promise<void>
'vue:setup': () => void
}

export interface NuxtAppCompat {
Expand Down
1 change: 1 addition & 0 deletions src/runtime/composables.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import { useNuxtApp } from './app'
export { useLazyAsyncData, refreshNuxtData } from './asyncData'
export { useLazyFetch } from './fetch'
export { useCookie } from './cookie'
export { clearError, createError, isNuxtError, throwError, showError, useError } from './error'
export { useRequestHeaders, useRequestEvent } from './ssr'

export * from 'vue'
Expand Down
43 changes: 43 additions & 0 deletions src/runtime/error.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import { createError as _createError, H3Error } from 'h3'
import { toRef } from 'vue'
import { useNuxtApp } from './app'

export const useError = () => toRef(useNuxtApp().payload, 'error')

export interface NuxtError extends H3Error {}

export const showError = (_err: string | Error | Partial<NuxtError>) => {
const err = createError(_err)

try {
const nuxtApp = useNuxtApp()
nuxtApp.callHook('app:error', err)
const error = useError()
error.value = error.value || err
} catch {
throw err
}

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()
nuxtApp.callHook('app:error:cleared', options)
if (options.redirect) {
await nuxtApp.$router.replace(options.redirect)
}
error.value = null
}

export const isNuxtError = (err?: string | object): err is NuxtError => !!(err && typeof err === 'object' && ('__nuxt_error' in err))

export const createError = (err: string | Partial<NuxtError>): NuxtError => {
const _err: NuxtError = _createError(err)
; (_err as any).__nuxt_error = true
return _err
}
6 changes: 3 additions & 3 deletions test/bridge.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,14 +43,14 @@ describe('errors', () => {
accept: 'application/json'
}
})
expect(res.status).toBe(500)
expect(res.status).toBe(422)
const error = await res.json()
delete error.stack
expect(error).toMatchObject({
description: process.env.NUXT_TEST_DEV ? expect.stringContaining('<pre>') : '',
message: 'This is a custom error',
statusCode: 500,
statusMessage: '',
statusCode: 422,
statusMessage: 'This is a custom error',
url: '/error'
})
})
Expand Down