Skip to content

Commit

Permalink
improve: LDP-2150: Implemented custom page and menu error handlers (#155
Browse files Browse the repository at this point in the history
)

* improve: LDP-2150: Implement custom page and menu error handlers

* LDP-2150: Added README

* LDP-2150: Added override error handler parameters

* LDP-2150: Added error parameter for custom error handlers

* LDP-2150: Added logging for menu errors and improved README
  • Loading branch information
vloss3 authored May 19, 2023
1 parent 27c337e commit 0cdb18f
Show file tree
Hide file tree
Showing 3 changed files with 58 additions and 20 deletions.
3 changes: 2 additions & 1 deletion .eslintrc
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
"rules": {
"@typescript-eslint/no-unused-vars": [
"off"
]
],
"no-console": "off"
}
}
48 changes: 41 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -86,13 +86,47 @@ is added automatically to requests. Defaults to `false`.

- `useLocalizedMenuEndpoint`: If enabled, the menu endpoint will use a language prefix as configured by [nuxtjs/i18n](https://v8.i18n.nuxtjs.org) module. Defaults to `true`.


## TODO - List of 1.x options not yet implemented

- `pageErrorHandler`: The default page error handler can be overridden.

- `menuErrorHandler`: The default menu error handler can be overridden.

## Error handling

The module provides a default error handler for the `fetchPage` and `fetchMenu` methods:

- `fetchPage`: Throws an error with the status code and message provided by Drupal.
- `fetchMenu`: Logs an error message to the console and displays a message in the frontend.

## Customizing error handling

You have the option to override the default error handlers by using a parameter when calling the `fetch` methods.

- `fetchPage`:
```javascript
<script lang="ts" setup>
const { fetchPage } = useDrupalCe()

function customPageError (error: Record<string, any>) {
throw createError({ statusCode: error.value.statusCode, statusMessage: 'No access.', data: {}, fatal: true })
}
const page = await fetchPage(useRoute().path, { query: useRoute().query }, customPageError)
</script>
```

- `fetchMenu`:
```javascript
<script lang="ts" setup>
const { fetchMenu } = useDrupalCe()
const { getMessages } = useDrupalCe()
const messages = getMessages()

function customMenuError (error: Record<string, any>) {
messages.value.push({
type: 'error',
message: `Menu error: Unavailable. ${error.value.statusCode}`
})
}
const mainMenu = await fetchMenu('main', {}, customMenuError)
</script>
```

Note: The `error` parameter is optional and can be omitted.

## Previous options not supported in 2.x version

Expand Down
27 changes: 15 additions & 12 deletions src/runtime/composables/useDrupalCe.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ export const useDrupalCe = () => {
* @param path Path of the Drupal page to fetch
* @param useFetchOptions Optional Nuxt useFetch options
*/
const fetchPage = async (path: string, useFetchOptions:UseFetchOptions<any> = {}) => {
const fetchPage = async (path: string, useFetchOptions: UseFetchOptions<any> = {}, overrideErrorHandler?: (error?: any) => void) => {
const nuxtApp = useNuxtApp()

// Workaround for issue - useState is not available after async call (Nuxt instance unavailable)
Expand Down Expand Up @@ -71,12 +71,8 @@ export const useDrupalCe = () => {
return pageState
}

if (error.value && (!error.value?.data?.content || config.customErrorPages)) {
throw createError({ statusCode: error.value.statusCode, statusMessage: error.value.message, data: error.value.data, fatal: true })
}

if (error.value) {
callWithNuxt(nuxtApp, setResponseStatus, [error.value.statusCode])
overrideErrorHandler ? overrideErrorHandler(error) : pageErrorHandler(error, { config, nuxtApp })
page.value = error.value?.data
}

Expand All @@ -91,7 +87,7 @@ export const useDrupalCe = () => {
* @param name Menu name being fetched
* @param useFetchOptions Optional Nuxt useFetch options
*/
const fetchMenu = async (name: string, useFetchOptions:UseFetchOptions<any> = {}) => {
const fetchMenu = async (name: string, useFetchOptions: UseFetchOptions<any> = {}, overrideErrorHandler?: (error?: any) => void) => {
const nuxtApp = useNuxtApp()
useFetchOptions = processFetchOptions(useFetchOptions)
useFetchOptions.key = `menu-${name}`
Expand All @@ -110,21 +106,20 @@ export const useDrupalCe = () => {
const { data: menu, error } = await useFetch(menuPath, useFetchOptions)

if (error.value) {
errorMenuHandler(error)
return
overrideErrorHandler ? overrideErrorHandler(error) : menuErrorHandler(error)
}
return menu
}

/**
* Use messages state
*/
const getMessages = () => useState('drupal-ce-messages', () => [])
const getMessages = (): Ref => useState('drupal-ce-messages', () => [])

/**
* Use page data
*/
const getPage = () => useState('drupal-ce-page-data', () => ({}))
const getPage = (): Ref => useState('drupal-ce-page-data', () => ({}))

/**
* Render elements from page data returned from fetchPage
Expand Down Expand Up @@ -160,9 +155,17 @@ const pushMessagesToState = (messages) => {
process.client && useDrupalCe().getMessages().value.push(...messagesArray)
}

const errorMenuHandler = (error) => {
const menuErrorHandler = (error: Record<string, any>) => {
console.error({ statusCode: error.value.statusCode, statusMessage: error.value.message, data: error.value.data })
process.client && useDrupalCe().getMessages().value.push({
type: 'error',
message: `Menu error: ${error.value.message}.`
})
}

const pageErrorHandler = (error: Record<string, any>, context: Record<string, any>) => {
if (error.value && (!error.value?.data?.content || context.config.customErrorPages)) {
throw createError({ statusCode: error.value.statusCode, statusMessage: error.value.message, data: error.value.data, fatal: true })
}
callWithNuxt(context.nuxtApp, setResponseStatus, [error.value.statusCode])
}

0 comments on commit 0cdb18f

Please sign in to comment.