-
-
Save wajeht/58396a24cd90c113d2d9bad874695f91 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"); | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment