Skip to content

Commit

Permalink
feat: Issue #3336148: Add support for drupal-forms (#247)
Browse files Browse the repository at this point in the history
* feat: Issue #3336148: Add support for forms

* LDP-2492: Remove unnecessary if

* LDP-2492: Improve redirect code

* LDP-2492: Improve internal redirect code

* LDP-2492: Revert redirect code

* LDP-2492: Improve code and use page middleware

* LDP-2492: Add server middleware and error handling

* LDP-2492: Move middleware to module

* LDP-2492: Include error message commit

* LDP-2492: Add imports
  • Loading branch information
vloss3 authored and harrypango committed Aug 29, 2024
1 parent a45ce16 commit 22213f3
Show file tree
Hide file tree
Showing 6 changed files with 89 additions and 28 deletions.
14 changes: 14 additions & 0 deletions playground/components/global/DrupalForm.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<template>
<form :formId="formId" :method="method" v-bind="attributes" :action="useRoute().fullPath" class="drupal-form">
<slot><div v-html="content" /></slot>
</form>
</template>

<script setup lang="ts">
const props = defineProps<{
formId: String,
attributes: Object,
method: String,
content?: String,
}>()
</script>
16 changes: 0 additions & 16 deletions playground/middleware/redirect.global.ts

This file was deleted.

6 changes: 4 additions & 2 deletions src/module.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { fileURLToPath } from 'url'
import { defineNuxtModule, addPlugin, addServerPlugin, createResolver, addImportsDir, addServerHandler } from '@nuxt/kit'
import { defineNuxtModule, addServerPlugin, createResolver, addImportsDir, addServerHandler } from '@nuxt/kit'
import { defu } from 'defu'
import type { NuxtOptionsWithDrupalCe } from './types'

Expand Down Expand Up @@ -59,11 +59,13 @@ export default defineNuxtModule<ModuleOptions>({
const { resolve } = createResolver(import.meta.url)
const runtimeDir = fileURLToPath(new URL('./runtime', import.meta.url))
nuxt.options.build.transpile.push(runtimeDir)
addPlugin(resolve(runtimeDir, 'plugin'))
if (options.serverLogLevel) {
addServerPlugin(resolve(runtimeDir, 'server/plugins/errorLogger'))
}
addImportsDir(resolve(runtimeDir, 'composables/useDrupalCe'))
addServerHandler({
handler: resolve(runtimeDir, 'server/middleware/drupalFormHandler'),
})

const publicOptions = { ...options }
// Server options are not needed in the client bundle.
Expand Down
37 changes: 31 additions & 6 deletions src/runtime/composables/useDrupalCe/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -116,9 +116,36 @@ export const useDrupalCe = () => {
page_layout: 'default',
title: '',
}))
const serverResponse = useState('server-response', () => null)
useFetchOptions.key = `page-${path}`
const page = ref(null)
const pageError = ref(null)

const { data: page, error } = await useCeApi(path, useFetchOptions, true)
if (import.meta.server) {
serverResponse.value = useRequestEvent(nuxtApp).context.drupalCeCustomPageResponse
}

// Check if the page data is already provided, e.g. by a form response.
if (serverResponse.value) {
if (serverResponse.value._data) {
page.value = serverResponse.value._data
passThroughHeaders(nuxtApp, serverResponse.value.headers)
} else if (serverResponse.value.error) {
pageError.value = serverResponse.value.error
}
// Clear the server response state after it was sent to the client.
if (import.meta.client) {
serverResponse.value = null
}
} else {
const { data, error } = await useCeApi(path, useFetchOptions, true)
page.value = data.value
pageError.value = error.value
}

if (page.value?.messages) {
pushMessagesToState(page.value.messages)
}

if (page?.value?.redirect) {
await callWithNuxt(nuxtApp, navigateTo, [
Expand All @@ -128,13 +155,11 @@ export const useDrupalCe = () => {
return pageState
}

if (error.value) {
overrideErrorHandler ? overrideErrorHandler(error) : pageErrorHandler(error, { config, nuxtApp })
page.value = error.value?.data
if (pageError.value) {
overrideErrorHandler ? overrideErrorHandler(pageError) : pageErrorHandler(pageError, { config, nuxtApp })
page.value = pageError.value?.data
}

page.value?.messages && pushMessagesToState(page.value.messages)

pageState.value = page
return page
}
Expand Down
4 changes: 0 additions & 4 deletions src/runtime/plugin.ts

This file was deleted.

40 changes: 40 additions & 0 deletions src/runtime/server/middleware/drupalFormHandler.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { defineEventHandler, readFormData } from 'h3'
import { getDrupalBaseUrl } from '../../composables/useDrupalCe/server'
import { useRuntimeConfig } from '#imports'

export default defineEventHandler(async (event) => {
const { ceApiEndpoint } = useRuntimeConfig().public.drupalCe

if (event.node.req.method === 'POST') {
const formData = await readFormData(event)

if (formData) {
const targetUrl = event.node.req.url
const response = await $fetch.raw(getDrupalBaseUrl() + ceApiEndpoint + targetUrl, {
method: 'POST',
body: formData,
}).catch((error) => {
event.context.drupalCeCustomPageResponse = {
error: {
data: error,
statusCode: error.statusCode || 400,
message: error.message || 'Error when POSTing form data (drupalFormHandler).',
},
}
})

if (response) {
event.context.drupalCeCustomPageResponse = {
_data: response._data,
headers: Object.fromEntries(response.headers.entries()),
}
}
} else {
throw createError({
statusCode: 400,
statusMessage: 'Bad Request',
message: 'POST requests without form data are not supported (drupalFormHandler).',
})
}
}
})

0 comments on commit 22213f3

Please sign in to comment.