forked from adonisjs/inertia
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathinertia_middleware.ts
More file actions
123 lines (105 loc) · 3.43 KB
/
inertia_middleware.ts
File metadata and controls
123 lines (105 loc) · 3.43 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
/*
* @adonisjs/inertia
*
* (c) AdonisJS
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
/// <reference types="@adonisjs/session/session_middleware" />
import type { Vite } from '@adonisjs/vite'
import type { HttpContext } from '@adonisjs/core/http'
import type { NextFn } from '@adonisjs/core/types/http'
import { Inertia } from './inertia.js'
import { InertiaHeaders } from './headers.js'
import type { ResolvedConfig } from './types.js'
/**
* HttpContext augmentations
*/
declare module '@adonisjs/core/http' {
export interface HttpContext {
inertia: Inertia
}
}
/**
* Inertia middleware to handle the Inertia requests and
* set appropriate headers/status
*/
export default class InertiaMiddleware {
constructor(
protected config: ResolvedConfig,
protected vite?: Vite
) {}
/**
* Resolves the validation errors to be shared with Inertia
*/
#resolveValidationErrors(ctx: HttpContext) {
const { session, request } = ctx
// If the session middleware wasn't executed
// (on routes that are not in the router, for instance),
// then the session object will be undefined.
if (!session) {
return {}
}
/**
* If not a Vine Validation error, then return the entire error bag
*/
if (!session.flashMessages.has('errorsBag.E_VALIDATION_ERROR')) {
return session.flashMessages.get('errorsBag', {})
}
/**
* Otherwise, resolve the validation errors. We only keep the first
* error message for each field
*/
const errors = Object.entries(session.flashMessages.get('inputErrorsBag')).reduce(
(acc, [field, messages]) => {
acc[field] = Array.isArray(messages) ? messages[0] : messages
return acc
},
{} as Record<string, string>
)
/**
* Also, nest the errors under the error bag key if asked
* See https://inertiajs.com/validation#error-bags
*/
const errorBag = request.header(InertiaHeaders.ErrorBag)
return errorBag ? { [errorBag]: errors } : errors
}
/**
* Share validation and flashed errors with Inertia
*/
#shareErrors(ctx: HttpContext) {
ctx.inertia.share({ errors: ctx.inertia.always(() => this.#resolveValidationErrors(ctx)) })
}
async handle(ctx: HttpContext, next: NextFn) {
const { response, request } = ctx
ctx.inertia = new Inertia(ctx, this.config, this.vite)
this.#shareErrors(ctx)
await next()
const isInertiaRequest = !!request.header(InertiaHeaders.Inertia)
if (!isInertiaRequest) return
response.header('Vary', InertiaHeaders.Inertia)
/**
* When redirecting a PUT/PATCH/DELETE request, we need to change the
* we must use a 303 status code instead of a 302 to force
* the browser to use a GET request after redirecting.
*
* See https://inertiajs.com/redirects
*/
const method = request.method()
if (response.getStatus() === 302 && ['PUT', 'PATCH', 'DELETE'].includes(method)) {
response.status(303)
}
/**
* Handle version change
*
* See https://inertiajs.com/the-protocol#asset-versioning
*/
const version = this.config.versionCache.getVersion().toString()
if (method === 'GET' && request.header(InertiaHeaders.Version, '') !== version) {
response.removeHeader(InertiaHeaders.Inertia)
response.header(InertiaHeaders.Location, request.url())
response.status(409)
}
}
}