diff --git a/Changelog.md b/Changelog.md index 2b396c4..e006a2b 100644 --- a/Changelog.md +++ b/Changelog.md @@ -2,6 +2,7 @@ ## Upcoming Changes +- feat: Route prefix support. You can run this app at a path prefix by setting the `PKMN_TCG_APP_ROUTE_PREFIX` environment variable - feat: Updated cronjobs to use system timezone rather than just EST ## 1.0.0 - (Oct 19, 2024) diff --git a/app.js b/app.js index dcfb563..84cda76 100644 --- a/app.js +++ b/app.js @@ -30,9 +30,29 @@ if (process.env.DISCORD_WEBHOOK_URL == undefined) { pokemon.configure({ apiKey: process.env["POKEMON_TCG_API_TOKEN"] }); const scheduleJobs = require("./lib/scheduleJobs"); -require("roosevelt")({ +const app = require("roosevelt")({ + routePrefix: process.env.PKMN_TCG_APP_ROUTE_PREFIX, onServerInit: (app) => { appDb.db = sqlite("data/data.db"); scheduleJobs(); }, -}).startServer(); +}); + +const routePrefix = app.expressApp.get("routePrefix") || ""; + +// Middleware to re-route any res.redirect() call to proper location if route prefix is used +if (routePrefix !== "") { + app.expressApp.use((req, res, next) => { + const redirect = res.redirect; + + res.redirect = function (url) { + if (url.charAt(0) === "/" && !url.includes(routePrefix)) { + url = routePrefix + url; + } + redirect.call(this, url); + }; + next(); + }); +} + +app.startServer(); diff --git a/mvc/controllers/404.js b/mvc/controllers/404.js index 66c8446..5dc22e0 100644 --- a/mvc/controllers/404.js +++ b/mvc/controllers/404.js @@ -1,12 +1,13 @@ module.exports = (router, app) => { - router.route('*').all((req, res) => { - const model = require('models/global')(req, res) - model.content.pageTitle = 'Not Found' - model.server = require('models/server')(req, res) - model.server.host = req.hostname - model.server.url = req.url - model.server.appVersion = app.get('package').version - res.status(404) - res.render('404', model) - }) -} + router.route("*").all((req, res) => { + const model = require("models/global")(req, res); + model.routePrefix = app.get("routePrefix") || ""; + model.content.pageTitle = "Not Found"; + model.server = require("models/server")(req, res); + model.server.host = req.hostname; + model.server.url = req.url; + model.server.appVersion = app.get("package").version; + res.status(404); + res.render("404", model); + }); +}; diff --git a/mvc/controllers/homepage.js b/mvc/controllers/homepage.js index 089488d..9d19e82 100644 --- a/mvc/controllers/homepage.js +++ b/mvc/controllers/homepage.js @@ -1,8 +1,9 @@ module.exports = (router, app) => { - router.route('/').get((req, res) => { - let model = require('models/global')(req, res) - model = require('models/homepage')(model) - model.content.pageTitle = 'Homepage' - res.render('homepage', model) - }) -} + router.route("/").get((req, res) => { + let model = require("models/global")(req, res); + model.routePrefix = app.get("routePrefix") || ""; + model = require("models/homepage")(model); + model.content.pageTitle = "Homepage"; + res.render("homepage", model); + }); +}; diff --git a/mvc/controllers/setListing.js b/mvc/controllers/setListing.js index e419986..12ed1cc 100644 --- a/mvc/controllers/setListing.js +++ b/mvc/controllers/setListing.js @@ -17,6 +17,7 @@ const usdFormatter = new Intl.NumberFormat("en-us", { module.exports = (router, app) => { router.route("/new/").get(async (req, res) => { let model = require("../models/global")(req, res); + model.routePrefix = app.get("routePrefix") || ""; model.sets = JSON.parse( fs.readFileSync(path.join(__dirname, "..", "..", "data", "sets.json")) @@ -54,6 +55,7 @@ module.exports = (router, app) => { const setId = req.params.id; let model = require("../models/global")(req, res); + model.routePrefix = app.get("routePrefix") || ""; model.setList = JSON.parse( fs.readFileSync( @@ -103,6 +105,7 @@ module.exports = (router, app) => { const card = await pokemon.card.find(cardId); let model = require("../models/global")(req, res); + model.routePrefix = app.get("routePrefix") || ""; model.cardDetails = JSON.stringify(card, null, 2); // console.log(card); diff --git a/mvc/views/card.html b/mvc/views/card.html index 8e9b294..6347589 100644 --- a/mvc/views/card.html +++ b/mvc/views/card.html @@ -1,7 +1,9 @@
- « Back to Set + « Back to Set

Card Art

Card preview for {cardName}

Pricing

diff --git a/mvc/views/homepage.html b/mvc/views/homepage.html index a3db99e..a5f4ff3 100644 --- a/mvc/views/homepage.html +++ b/mvc/views/homepage.html @@ -3,7 +3,7 @@

Tracking prices for {count} cards:

- Browse Cards + Browse Cards
@@ -23,7 +23,11 @@ - + @@ -33,7 +37,7 @@ diff --git a/mvc/views/layouts/main.html b/mvc/views/layouts/main.html index 5839f0d..c353172 100644 --- a/mvc/views/layouts/main.html +++ b/mvc/views/layouts/main.html @@ -4,9 +4,10 @@ + {content.titleTag} - - + +
@@ -14,7 +15,7 @@

{content.appTitle} - {content.pageTitle}

- Home + Home {pageContent|s}
diff --git a/mvc/views/setList.html b/mvc/views/setList.html index 64ce8eb..7589aa9 100644 --- a/mvc/views/setList.html +++ b/mvc/views/setList.html @@ -1,7 +1,9 @@
- « Back to Set Listing + « Back to Set Listing

Set Information

@@ -22,7 +24,7 @@

{group.type}

  • {card.name} - - {card.value} + {card.value}
  • @@ -33,7 +35,7 @@

    {group.type}

  • {card.name} - - {card.value} + {card.value}
  • diff --git a/mvc/views/setListing.html b/mvc/views/setListing.html index 7793bda..56a8f19 100644 --- a/mvc/views/setListing.html +++ b/mvc/views/setListing.html @@ -11,7 +11,7 @@

    Newest Sets

    Logo for {set.name}

    {set.name} - - {set.value} + {set.value}

    @@ -24,7 +24,9 @@

    {yearGroup.0}

  • {set.name} - {set.description} - - {set.value}
  • diff --git a/statics/js/cardDialog.js b/statics/js/cardDialog.js index 255447b..914cd96 100644 --- a/statics/js/cardDialog.js +++ b/statics/js/cardDialog.js @@ -1,4 +1,8 @@ function createSaveCardDialog() { + const routePrefix = document + .querySelector("meta[name='routePrefix']") + .getAttribute("content"); + const data = JSON.parse(document.getElementById("metadata").innerText); const form = document.createElement("form"); @@ -15,7 +19,7 @@ function createSaveCardDialog() { marketPrice = parseFloat(data.prices[0].marketPrice.slice(1)); } - form.action = "/saveCard"; + form.action = `${routePrefix}/saveCard`; form.method = "POST"; form.innerHTML = ` diff --git a/statics/js/main.js b/statics/js/main.js index f57ce4f..47d648c 100644 --- a/statics/js/main.js +++ b/statics/js/main.js @@ -1,5 +1,9 @@ const { createSaveCardDialog } = require("./cardDialog"); +const routePrefix = document + .querySelector("meta[name='routePrefix']") + .getAttribute("content"); + if (window.location.href.includes("/card/")) { const data = JSON.parse(document.getElementById("metadata").innerText); @@ -13,7 +17,7 @@ if (window.location.href.includes("/card/")) { } } -if (window.location.pathname == "/") { +if (window.location.pathname == `${routePrefix}/`) { document.querySelectorAll(".editBtn").forEach((btn) => { btn.addEventListener("click", async (evt) => { let row = evt.target.parentElement.parentElement; @@ -22,8 +26,8 @@ if (window.location.pathname == "/") { .getAttribute("href") .split("/card/")[1]; - const card = await fetch(`/followedCard/${cardId}`).then((resp) => - resp.json() + const card = await fetch(`${routePrefix}/followedCard/${cardId}`).then( + (resp) => resp.json() ); const aside = document.createElement("aside"); @@ -50,7 +54,7 @@ if (window.location.pathname == "/") { let form = document.createElement("form"); form.method = "post"; - form.action = "/updateFollowCard"; + form.action = `${routePrefix}/updateFollowCard`; form.innerHTML = `
    {card.cardName}{card.identifier} + {card.identifier} + {card.rarity} {card.requestedPrice} {card.marketPrice} X