Last active
March 27, 2024 09:00
-
-
Save crgeary/eddb08d7203a24c18c8010fd36e98ef0 to your computer and use it in GitHub Desktop.
Inertia adapter for Express
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const lodashPick = (object, keys) => { | |
return keys.reduce((obj, key) => { | |
if (object && object.hasOwnProperty(key)) { | |
obj[key] = object[key]; | |
} | |
return obj; | |
}, {}); | |
}; | |
const setupProps = async (props) => { | |
const _props = { ...props }; | |
for (i in _props) { | |
if (typeof _props[i] === "object") { | |
_props[i] = await setupProps(_props[i]); | |
} else if (typeof _props[i] === "function") { | |
_props[i] = await _props[i].call(); | |
} | |
} | |
return _props; | |
}; | |
const getRequestedProps = (req, component, props) => { | |
const requestedProps = req.header("X-Inertia-Partial-Data"); | |
if (requestedProps) { | |
if (req.header("X-Inertia-Partial-Component") === component) { | |
return lodashPick(props, requestedProps.split(",")); | |
} | |
} | |
return props; | |
}; | |
const shouldSeeOther = (req, res) => { | |
const methods = ["PUT", "PATCH", "DELETE"]; | |
return res.statusCode === 303 && methods.includes(req.method); | |
}; | |
const shouldConflict = (req, version) => { | |
return req.method === `GET` && req.header("X-Inertia-Version") !== version; | |
}; | |
const inertia = (options = {}) => { | |
options = { | |
version: null, | |
view: "app", | |
...options, | |
}; | |
return (req, res, next) => { | |
res.inertia = async (component, inertiaProps, viewProps) => { | |
const url = `${req.protocol}://${req.get("host")}${ | |
req.originalUrl | |
}`; | |
const props = getRequestedProps(req, component, inertiaProps); | |
const inertiaObject = { | |
component: component, | |
props: await setupProps(props), | |
url: url, | |
version: options.version, | |
}; | |
if (!req.header("X-Inertia")) { | |
return res.render(options.view, { | |
layout: false, | |
page: JSON.stringify(inertiaObject), | |
...viewProps, | |
}); | |
} | |
if (shouldConflict(req, options.version)) { | |
if (req.session && typeof req.flash === "function") { | |
const messages = req.flash(); | |
for (message in messages) { | |
req.flash(message, messages[message]); | |
} | |
} | |
res.setHeader("X-Inertia-Location", url); | |
return res.status(409).end(); | |
} | |
res.setHeader("Vary", "Accept"); | |
res.setHeader("X-Inertia", "true"); | |
res.setHeader("X-Inertia-Version", options.version); | |
return res.json(inertiaObject); | |
}; | |
const end = res.end; | |
res.end = function () { | |
if (shouldSeeOther(req, res)) { | |
res.status(303); | |
} | |
return end.apply(this, arguments); | |
}; | |
next(); | |
}; | |
}; | |
exports.inertia = inertia; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const express = require("express"); | |
const session = require("express-session"); | |
const flash = require("connect-flash"); | |
const { inertia } = require("./inertia"); | |
const app = express(); | |
app.engine("hbs", hbs.engine); | |
app.set("view engine", "hbs"); | |
app.use( | |
session({ | |
secret: "@todo assign a secret", | |
resave: false, | |
saveUninitialized: false, | |
cookie: { | |
maxAge: 1000 * 15, | |
}, | |
}) | |
); | |
app.use(flash()); | |
app.use( | |
inertia({ | |
view: "app", | |
version: "@todo webpack manifest hash (for example)", | |
}) | |
); | |
app.get("/", async (req, res) => { | |
res.inertia("Dashboard", { | |
title: "Dashboard!", | |
reports: async () => { | |
return await aTimeConsumingTasksLikeDatabaseAccess(); | |
} | |
}); | |
}); | |
app.listen(3000, () => { | |
console.log("Listening at http://localhost:3000"); | |
}); |
does it work well? have you used it in any personal/production level apps?
@wajeht I wrote it to understand how inertia worked, and to learn about express middleware, it hasn't been used in any project and I would guess doesn't work with the latest version of inertia either. I wouldn't recommend you use it as is, although feel free to build upon it.
thanks man! 👍
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
@wajeht I wrote it to understand how inertia worked, and to learn about express middleware, it hasn't been used in any project and I would guess doesn't work with the latest version of inertia either. I wouldn't recommend you use it as is, although feel free to build upon it.