From e952d860dcfda779c9c5e5d898ae7b86b201acba Mon Sep 17 00:00:00 2001 From: Matt Walsh Date: Tue, 13 May 2025 23:04:46 -0500 Subject: [PATCH] add environment variables for default configuration --- .gitignore | 5 ++++- README.md | 7 ++++--- index.mjs | 33 +++++++++++++++++++++++++++++++++ package-lock.json | 13 +++++++++++++ package.json | 1 + ws4kp.code-workspace | 3 ++- 6 files changed, 57 insertions(+), 5 deletions(-) diff --git a/.gitignore b/.gitignore index ae0ce9c..7ed4bca 100644 --- a/.gitignore +++ b/.gitignore @@ -11,4 +11,7 @@ server/music/* #dist folder dist/* -!dist/readme.txt \ No newline at end of file +!dist/readme.txt + +#environment variables +.env \ No newline at end of file diff --git a/README.md b/README.md index d479853..ab54c2a 100644 --- a/README.md +++ b/README.md @@ -92,11 +92,12 @@ Kiosk mode can be activated by a checkbox on the page. Note that there is no way It's also possible to enter kiosk mode using a permalink. First generate a [Permalink](#sharing-a-permalink-bookmarking), then to the end of it add `&kiosk=true`. Opening this link will load all of the selected displays included in the Permalink, enter kiosk mode immediately upon loading and start playing the forecast. -## Wish list +## Default query string paramaters (environment variables) +When serving this via the built-in Express server, it's possible to define environment variables that direct the user to a default set of paramaters (like the [Permalink](#sharing-a-permalink-bookmarking) above). If a user requests the root page at `http://localhost:8080/` the query string provided by environment variables will be appended to the url thus providing a default configuration. -As time allows I will be working on the following enhancements. +Environment variables can be added to the command line as usual, or via a .env file which is parsed with [dotenv](https://github.com/motdotla/dotenv). Both methods have the same effect. -* Better error reporting when api.weather.gov is down (happens more often than you would think) +Environment variables that are to be added to the default query string are prefixed with `WSQS_` and then use the same key/value pairs generated by the [Permalink](#sharing-a-permalink-bookmarking) above, with the `- (dash)` character replaced by an `_ (underscore)`. For example, if you wanted to turn the travel forecast on, you would find `travel-checkbox=true` in the permalink, it's matching environment variable becomes `WSQS_travel_checkbox=true`. ## Serving static files The app can be served as a static set of files on any web server. Run the provided gulp task to create a set of static distribution files: diff --git a/index.mjs b/index.mjs index da377ca..a8e0b10 100644 --- a/index.mjs +++ b/index.mjs @@ -1,3 +1,4 @@ +import 'dotenv/config'; import express from 'express'; import fs from 'fs'; import corsPassThru from './cors/index.mjs'; @@ -20,7 +21,39 @@ app.get('/playlist.json', playlist); // version const { version } = JSON.parse(fs.readFileSync('package.json')); +// read and parse environment variables to append to the query string +// use the permalink (share) button on the web app to generate a starting point for your configuration +// then take each key/value in the querystring and append WSQS_ to the beginning, and then replace any +// hyphens with underscores in the key name +// environment variables are read from the command line and .env file via the dotenv package + +const qsVars = {}; + +Object.entries(process.env).forEach(([key, value]) => { + // test for key matching pattern described above + if (key.match(/^WSQS_[A-Za-z0-9_]+$/)) { + // convert the key to a querystring formatted key + const formattedKey = key.replace(/^WSQS_/, '').replaceAll('_', '-'); + qsVars[formattedKey] = value; + } +}); + +// single flag to determine if environment variables are present +const hasQsVars = Object.entries(qsVars).length > 0; + +// turn the environment query string into search params +const defaultSearchParams = (new URLSearchParams(qsVars)).toString(); + const index = (req, res) => { + // test for no query string in request and if environment query string values were provided + if (hasQsVars && Object.keys(req.query).length === 0) { + // redirect the user to the query-string appended url + const url = new URL(`${req.protocol}://${req.host}${req.url}`); + url.search = defaultSearchParams; + res.redirect(307, url.toString()); + return; + } + // return the standard page res.render('index', { production: false, version, diff --git a/package-lock.json b/package-lock.json index 5a74106..3873abb 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,6 +9,7 @@ "version": "5.17.0", "license": "MIT", "dependencies": { + "dotenv": "^16.5.0", "ejs": "^3.1.5", "express": "^5.1.0" }, @@ -3813,6 +3814,18 @@ "node": ">=6.0.0" } }, + "node_modules/dotenv": { + "version": "16.5.0", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.5.0.tgz", + "integrity": "sha512-m/C+AwOAr9/W1UOIZUo232ejMNnJAJtYQjUbHoNTBNTJSvqzzDh7vnrei3o3r3m9blf6ZoDkvcw0VmozNRFJxg==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://dotenvx.com" + } + }, "node_modules/dunder-proto": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", diff --git a/package.json b/package.json index 9cee0eb..cc964c0 100644 --- a/package.json +++ b/package.json @@ -46,6 +46,7 @@ "webpack-stream": "^7.0.0" }, "dependencies": { + "dotenv": "^16.5.0", "ejs": "^3.1.5", "express": "^5.1.0" } diff --git a/ws4kp.code-workspace b/ws4kp.code-workspace index bbdf588..4614e67 100644 --- a/ws4kp.code-workspace +++ b/ws4kp.code-workspace @@ -33,7 +33,8 @@ "T'storm", "uscomp", "Visib", - "Waukegan" + "Waukegan", + "WSQS" ], "cSpell.ignorePaths": [ "**/package-lock.json",