From 2df1f79617c14c943b0567110b470e723cb8d37a Mon Sep 17 00:00:00 2001 From: rxf Date: Sat, 25 Jul 2026 11:35:41 +0000 Subject: [PATCH] Initial monorepo: readin, sensorapi, noise (Node22, npm ci, axios1.x, i18next-fs-backend) --- .gitignore | 6 + README.md | 10 + noise/.dockerignore | 9 + noise/.env.example | 10 + noise/.gitignore | 4 + noise/.vscode/launch.json | 26 + noise/Dockerfile_noise | 19 + noise/Readme.md | 28 + noise/app.js | 77 + noise/bin/www.js | 97 + noise/build_and_copy.sh | 63 + noise/charts/preparecharts.js | 565 ++++ noise/charts/utilities.js | 151 + noise/deploy.sh | 58 + noise/docs/Readme.md | 5 + noise/docs/aktchanges | 5 + noise/locales/de/translation.json | 53 + noise/locales/dev/translation.json | 47 + noise/locales/en/translation.json | 53 + noise/package-lock.json | 2117 ++++++++++++ noise/package.json | 31 + noise/public/images/favicon.ico | Bin 0 -> 1150 bytes noise/public/javascripts/chart_utilities.js | 276 ++ noise/public/javascripts/checklang.js | 15 + noise/public/javascripts/datetime.js | 30 + noise/public/javascripts/global.js | 303 ++ .../javascripts/leaflet.markercluster.js | 3 + .../javascripts/leaflet.markercluster.js.map | 1 + noise/public/javascripts/logit.js | 12 + noise/public/javascripts/luxon.min.js | 1 + noise/public/javascripts/map.js | 99 + noise/public/javascripts/map_noise.js | 210 ++ noise/public/javascripts/map_utilities.js | 17 + noise/public/javascripts/showcharts.js | 141 + noise/public/javascripts/spinner.js | 27 + .../stylesheets/MarkerCluster.Default.css | 60 + noise/public/stylesheets/MarkerCluster.css | 14 + noise/public/stylesheets/style.css | 487 +++ noise/public/stylesheets/style.css.map | 1 + noise/public/stylesheets/style.sass | 257 ++ noise/routes/api.js | 72 + noise/routes/index.js | 69 + noise/views/chglang.pug | 13 + noise/views/error.pug | 6 + noise/views/index_noise.pug | 114 + noise/views/layout.pug | 37 + readin/.dockerignore | 10 + readin/.gitignore | 9 + readin/Dockerfile_readin | 28 + readin/Dockerfile_timeseries | 27 + readin/build_and_copy.sh | 63 + readin/crontab.tmp | 2 + readin/deploy.sh | 58 + readin/docker-compose.yml | 55 + readin/fetchnewdata.js | 141 + readin/influx_post.js | 100 + readin/logit.js | 12 + readin/mongo.js | 202 ++ readin/package-lock.json | 1020 ++++++ readin/package.json | 21 + readin/parse.js | 243 ++ readin/readdata.js | 51 + readin/ts_rotate | 9 + sensorapi/.dockerignore | 9 + sensorapi/.gitignore | 5 + sensorapi/.vscode/launch.json | 75 + sensorapi/Dockerfile_sensorapi | 24 + sensorapi/actions/data4map.js | 190 ++ sensorapi/actions/getAKWData.js | 62 + sensorapi/actions/getaddress.js | 80 + sensorapi/actions/getproperties.js | 48 + sensorapi/actions/getsensorData.js | 308 ++ sensorapi/app.js | 66 + sensorapi/bin/www.js | 93 + sensorapi/build_and_copy.sh | 63 + sensorapi/databases/influx.js | 166 + sensorapi/databases/mongo.js | 424 +++ sensorapi/deploy.sh | 58 + sensorapi/doc/Planung.jpg | Bin 0 -> 583372 bytes sensorapi/doc/Planung.md | 23 + sensorapi/doc/Readne.md | 6 + sensorapi/docker-compose.yml | 19 + sensorapi/locales/de/translation.json | 16 + sensorapi/locales/en/translation.json | 16 + sensorapi/mocks/mongo_mock.js | 74 + sensorapi/package-lock.json | 2915 +++++++++++++++++ sensorapi/package.json | 36 + sensorapi/routes/api.js | 54 + sensorapi/routes/index.js | 12 + sensorapi/sensorspecials/geigeract.js | 152 + sensorapi/sensorspecials/noise.js | 499 +++ sensorapi/test/test.js | 29 + sensorapi/utilities/chartoptions.js | 148 + sensorapi/utilities/checkparams.js | 54 + sensorapi/utilities/csv2json.js | 35 + sensorapi/utilities/logit.js | 16 + sensorapi/utilities/reporterror.js | 22 + 97 files changed, 13547 insertions(+) create mode 100644 .gitignore create mode 100644 README.md create mode 100644 noise/.dockerignore create mode 100644 noise/.env.example create mode 100644 noise/.gitignore create mode 100644 noise/.vscode/launch.json create mode 100644 noise/Dockerfile_noise create mode 100644 noise/Readme.md create mode 100644 noise/app.js create mode 100755 noise/bin/www.js create mode 100755 noise/build_and_copy.sh create mode 100644 noise/charts/preparecharts.js create mode 100644 noise/charts/utilities.js create mode 100755 noise/deploy.sh create mode 100644 noise/docs/Readme.md create mode 100644 noise/docs/aktchanges create mode 100644 noise/locales/de/translation.json create mode 100644 noise/locales/dev/translation.json create mode 100644 noise/locales/en/translation.json create mode 100644 noise/package-lock.json create mode 100644 noise/package.json create mode 100644 noise/public/images/favicon.ico create mode 100644 noise/public/javascripts/chart_utilities.js create mode 100644 noise/public/javascripts/checklang.js create mode 100644 noise/public/javascripts/datetime.js create mode 100644 noise/public/javascripts/global.js create mode 100644 noise/public/javascripts/leaflet.markercluster.js create mode 100644 noise/public/javascripts/leaflet.markercluster.js.map create mode 100644 noise/public/javascripts/logit.js create mode 100644 noise/public/javascripts/luxon.min.js create mode 100644 noise/public/javascripts/map.js create mode 100644 noise/public/javascripts/map_noise.js create mode 100644 noise/public/javascripts/map_utilities.js create mode 100644 noise/public/javascripts/showcharts.js create mode 100644 noise/public/javascripts/spinner.js create mode 100644 noise/public/stylesheets/MarkerCluster.Default.css create mode 100644 noise/public/stylesheets/MarkerCluster.css create mode 100644 noise/public/stylesheets/style.css create mode 100644 noise/public/stylesheets/style.css.map create mode 100644 noise/public/stylesheets/style.sass create mode 100644 noise/routes/api.js create mode 100644 noise/routes/index.js create mode 100644 noise/views/chglang.pug create mode 100644 noise/views/error.pug create mode 100644 noise/views/index_noise.pug create mode 100644 noise/views/layout.pug create mode 100644 readin/.dockerignore create mode 100644 readin/.gitignore create mode 100644 readin/Dockerfile_readin create mode 100644 readin/Dockerfile_timeseries create mode 100755 readin/build_and_copy.sh create mode 100644 readin/crontab.tmp create mode 100755 readin/deploy.sh create mode 100644 readin/docker-compose.yml create mode 100644 readin/fetchnewdata.js create mode 100644 readin/influx_post.js create mode 100644 readin/logit.js create mode 100644 readin/mongo.js create mode 100644 readin/package-lock.json create mode 100644 readin/package.json create mode 100644 readin/parse.js create mode 100644 readin/readdata.js create mode 100644 readin/ts_rotate create mode 100644 sensorapi/.dockerignore create mode 100644 sensorapi/.gitignore create mode 100644 sensorapi/.vscode/launch.json create mode 100644 sensorapi/Dockerfile_sensorapi create mode 100644 sensorapi/actions/data4map.js create mode 100644 sensorapi/actions/getAKWData.js create mode 100644 sensorapi/actions/getaddress.js create mode 100644 sensorapi/actions/getproperties.js create mode 100644 sensorapi/actions/getsensorData.js create mode 100644 sensorapi/app.js create mode 100644 sensorapi/bin/www.js create mode 100755 sensorapi/build_and_copy.sh create mode 100644 sensorapi/databases/influx.js create mode 100644 sensorapi/databases/mongo.js create mode 100755 sensorapi/deploy.sh create mode 100644 sensorapi/doc/Planung.jpg create mode 100644 sensorapi/doc/Planung.md create mode 100644 sensorapi/doc/Readne.md create mode 100644 sensorapi/docker-compose.yml create mode 100644 sensorapi/locales/de/translation.json create mode 100644 sensorapi/locales/en/translation.json create mode 100644 sensorapi/mocks/mongo_mock.js create mode 100644 sensorapi/package-lock.json create mode 100644 sensorapi/package.json create mode 100644 sensorapi/routes/api.js create mode 100644 sensorapi/routes/index.js create mode 100644 sensorapi/sensorspecials/geigeract.js create mode 100644 sensorapi/sensorspecials/noise.js create mode 100644 sensorapi/test/test.js create mode 100644 sensorapi/utilities/chartoptions.js create mode 100644 sensorapi/utilities/checkparams.js create mode 100644 sensorapi/utilities/csv2json.js create mode 100644 sensorapi/utilities/logit.js create mode 100644 sensorapi/utilities/reporterror.js diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..5d0e3bc --- /dev/null +++ b/.gitignore @@ -0,0 +1,6 @@ +node_modules/ +log/ +*.bak +*.bak-* +.DS_Store +*.log diff --git a/README.md b/README.md new file mode 100644 index 0000000..1380af0 --- /dev/null +++ b/README.md @@ -0,0 +1,10 @@ +# sensor-stack + +Monorepo fuer den noisesensors-Stack (esprimo, Dockge: /opt/stacks/esprimo/noisesensors). + +- **readin/** – Sensordaten von sensor.community -> InfluxDB/MongoDB (Cron). Image `docker.citysensor.de/readin` +- **sensorapi/** – Backend-API (liest Influx/Mongo). Image `docker.citysensor.de/sensorapi` +- **noise/** – Web-Frontend (laerm_web, nutzt sensorapi). Image `docker.citysensor.de/noise` + +Deploy je Service: `cd && ./deploy.sh` (nativer amd64-Build -> Registry), +dann `cd /opt/stacks/esprimo/noisesensors && docker compose up -d `. diff --git a/noise/.dockerignore b/noise/.dockerignore new file mode 100644 index 0000000..22c134b --- /dev/null +++ b/noise/.dockerignore @@ -0,0 +1,9 @@ +build_and_copy.sh +Dockerfile_noise +.vscode +node_modules +log +.env* +.gitignore +deploy.sh +Readme.* \ No newline at end of file diff --git a/noise/.env.example b/noise/.env.example new file mode 100644 index 0000000..fd86a67 --- /dev/null +++ b/noise/.env.example @@ -0,0 +1,10 @@ +# API Configuration +API_KEY=your_api_key_here +APIHOST=http://localhost:3005 + +# MongoDB Configuration (if needed) +MONGO_ROOT_USERNAME=admin +MONGO_ROOT_PASSWORD=your_password_here +LOCALDIR=/path/to/local/dir +REPO_USER=your_username +REPO_PASSWORD=your_password diff --git a/noise/.gitignore b/noise/.gitignore new file mode 100644 index 0000000..313d17a --- /dev/null +++ b/noise/.gitignore @@ -0,0 +1,4 @@ +node_modules +log +.env +Readme.pdf \ No newline at end of file diff --git a/noise/.vscode/launch.json b/noise/.vscode/launch.json new file mode 100644 index 0000000..58940ee --- /dev/null +++ b/noise/.vscode/launch.json @@ -0,0 +1,26 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "type": "node", + "request": "launch", + "name": "Launch Program", + "skipFiles": [ + "/**" + ], + "program": "${workspaceFolder}/bin/www.js", + "env": { + "PORT": "3003", + "APIHOST": "http://localhost:3005", + // "MONGOHOST": "reception", + // "MONGOUSRP": "admin:mongo4noise", + // "MONGOAUTH": "true", + // "INFLUXHOST": "reception", + // "INFLUXTOKEN": "gHGGgjaK0lmM6keMa01JeuDpqOE_vRq8UimsU4QKb2miI5BDh2PfWynEbwKizdJapXy8jVbTat5mVZLQTNmSdw==", + } + } + ] +} \ No newline at end of file diff --git a/noise/Dockerfile_noise b/noise/Dockerfile_noise new file mode 100644 index 0000000..0e13baa --- /dev/null +++ b/noise/Dockerfile_noise @@ -0,0 +1,19 @@ +FROM node:22-alpine + +ADD package.json /tmp/package.json +ADD package-lock.json /tmp/package-lock.json +RUN cd /tmp && npm ci +RUN mkdir -p /opt/app && cp -a /tmp/node_modules /tmp/package.json /opt/app/ +WORKDIR /opt/app +ADD . /opt/app/ + +RUN apk add --no-cache tzdata +ENV TZ=Europe/Berlin +RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone + +RUN deluser --remove-home node + +EXPOSE 3000 + +CMD ["npm", "start"] + diff --git a/noise/Readme.md b/noise/Readme.md new file mode 100644 index 0000000..87a55da --- /dev/null +++ b/noise/Readme.md @@ -0,0 +1,28 @@ +# Develop und Deploy der Noise-Anwendung +rxf 2025-08-08 +## Develop local ( auf esprimo !) +* via VS die APP **sensorapi** auf dem *esprimo* starten +* als **mongo** direkt die auf *ionos* verwenden +* in VS die app **laerm_web_sensorapi** editieren und starten +* im Browser aufrufen: **esprimo:3000** + +## Deploy auf *ionos* +* überprüfen, ob **portainer** richtig läuft, ggf. neu installieren +* prüfen, ob alle Container richtig laufen, vor Allem der **watchtower**, ggf. das Stack neu starten +* in VS (auf esprimo) das script **deploy.sh** aufrufen +* auf **ionos** sollte nun via **watchtower** die neue Version geladen werden (spätestens nach 1 Minute) +** nun im Browser **https://noise.fuerst-stuttgart.de** aufrufen und testen + +## Deploy auf *rbsensors* +* wenn **deplay.sh** noch nicht gestartet wurde (via VS auf esprimo), diese aufrufen. +* Portainer auf rbsensors aufrufen: **192.168.51.22:9000** +* über **Images** das neueste Image (**noise:latest**) vom Repository *Reinhard* holen +* das Stack **noisesensor** aufrufen +* den Container **noise** löschen +* via *edit* das Stack neu starten +* und nun im Browser mit **laerm.rbsensors.de** testen + +| Datum | Version | Bemerkung | +|-------|---------|---------| +| 2025-08-08 | 1.0.1 | Typos verbessert | +| 2024-12-20| 1.0.0 | erste Version | diff --git a/noise/app.js b/noise/app.js new file mode 100644 index 0000000..3d7e85b --- /dev/null +++ b/noise/app.js @@ -0,0 +1,77 @@ +import 'dotenv/config' +import createError from 'http-errors' +import logger from 'morgan' +import express from 'express' +import cookieParser from 'cookie-parser' +import path from 'path' +import { fileURLToPath } from 'url' +import i18next from 'i18next' +import i18nextMiddleware from 'i18next-http-middleware' +import Backend from 'i18next-fs-backend' + +const app = express() + +export let url2call + +const __filename = fileURLToPath(import.meta.url); +const __dirname = path.dirname(__filename); + +import * as indexRouter from './routes/index.js' +import apiRouter from './routes/api.js' + +i18next + .use(Backend) + .use(i18nextMiddleware.LanguageDetector) + .init({ + backend: { + loadPath: __dirname + '/locales/{{lng}}/{{ns}}.json' + }, + fallbackLng: 'de', + debug: false, + preload: ['de', 'en'] + }); + +app.use(i18nextMiddleware.handle(i18next)); + +// view engine setup +app.set('views', path.join(__dirname, 'views')); +app.set('view engine', 'pug'); + +app.get('*', (req, res, next) => { + const subdom = req.headers.host.split('.') + if (subdom[0] === 'laerm') { + subdom[0] = 'noise' + } +// app.set('category',subdom[0]) + app.set('category','noise') + next() +}) + +app.use(logger('dev')); +app.use(express.json()); +app.use(express.urlencoded({ extended: false })); +app.use(cookieParser()); +app.use(express.static(path.join(__dirname, 'public'))); +app.use(express.static(path.join(__dirname,'node_modules'))); + +app.use('/api', apiRouter) +app.use('/srv', apiRouter) +app.use('/', indexRouter.router); + +// catch 404 and forward to error handler +app.use(function(req, res, next) { + next(createError(404)); +}); + +// error handler +app.use(function(err, req, res, next) { + // set locals, only providing error in development + res.locals.message = err.message; + res.locals.error = req.app.get('env') === 'development' ? err : {}; + + // render the error page + res.status(err.status || 500); + res.render('error'); +}); + +export default app diff --git a/noise/bin/www.js b/noise/bin/www.js new file mode 100755 index 0000000..49ab556 --- /dev/null +++ b/noise/bin/www.js @@ -0,0 +1,97 @@ +#!/usr/bin/env node + +/** + * Module dependencies. + */ + +import app from '../app.js' +import Debug from 'debug' +import http from 'http' +const debug = Debug('laerm-web-sensorapi:server') + + +/* var app = require('../app'); +var debug = require('debug')('laerm-web-sensorapi:server'); +var http = require('http'); +*/ + +/** + * Get port from environment and store in Express. + */ + +var port = normalizePort(process.env.PORT || '3000'); +app.set('port', port); + +/** + * Create HTTP server. + */ + +var server = http.createServer(app); + +/** + * Listen on provided port, on all network interfaces. + */ + +server.listen(port); +server.on('error', onError); +server.on('listening', onListening); + +/** + * Normalize a port into a number, string, or false. + */ + +function normalizePort(val) { + var port = parseInt(val, 10); + + if (isNaN(port)) { + // named pipe + return val; + } + + if (port >= 0) { + // port number + return port; + } + + return false; +} + +/** + * Event listener for HTTP server "error" event. + */ + +function onError(error) { + if (error.syscall !== 'listen') { + throw error; + } + + var bind = typeof port === 'string' + ? 'Pipe ' + port + : 'Port ' + port; + + // handle specific listen errors with friendly messages + switch (error.code) { + case 'EACCES': + console.error(bind + ' requires elevated privileges'); + process.exit(1); + break; + case 'EADDRINUSE': + console.error(bind + ' is already in use'); + process.exit(1); + break; + default: + throw error; + } +} + +/** + * Event listener for HTTP server "listening" event. + */ + +function onListening() { + var addr = server.address(); + var bind = typeof addr === 'string' + ? 'pipe ' + addr + : 'port ' + addr.port; + debug('Listening on ' + bind); +} diff --git a/noise/build_and_copy.sh b/noise/build_and_copy.sh new file mode 100755 index 0000000..ec13d9b --- /dev/null +++ b/noise/build_and_copy.sh @@ -0,0 +1,63 @@ +#!/bin/bash +# Build Docker-Container +# +# Call: buildit.sh name [target] +# +# The Dockerfile must be named like Dockerfile_name +# +# 2018-09-20 rxf +# - before sending docker image to remote, tag actual remote image +# +# 2018-09-14 rxf +# - first Version +# + +set -x +port="" +orgName=noise +name=noise + +usage() +{ + echo "Usage build_and_copy.sh [-p port] [-n name] target" + echo " Build docker container $name and copy to target" + echo "Params:" + echo " target: Where to copy the container to " + echo " -p port: ssh port (default 22)" + echo " -n name: new name for container (default: $orgName)" +} + +while getopts n:p:h? o +do + case "$o" in + n) name="$OPTARG";; + p) port="-p $OPTARG";; + h) usage; exit 0;; + *) usage; exit 1;; + esac +done +shift $((OPTIND-1)) + +while [ $# -gt 0 ]; do + if [[ -z "$target" ]]; then + target=$1 + shift + else + echo "bad option $1" + # exit 1 + shift + fi +done + +docker build -f Dockerfile_$orgName --no-cache -t $name . + +dat=`date +%Y%m%d%H%M` + +if [ "$target" == "localhost" ] +then + docker tag $name $name:V_$dat + exit +fi + +ssh $port $target "docker tag $name $name:V_$dat" +docker save $name | bzip2 | pv | ssh $port $target 'bunzip2 | docker load' diff --git a/noise/charts/preparecharts.js b/noise/charts/preparecharts.js new file mode 100644 index 0000000..ae6c2f6 --- /dev/null +++ b/noise/charts/preparecharts.js @@ -0,0 +1,565 @@ +// Prepare all data to plot the charts +import * as utils from '../charts/utilities.js' +import { translate as trans } from '../routes/index.js' + +/********************************************** + * Live-Data + * * + * @param params + * @param values + * @returns {{options: {plotOptions: {series: {marker: {enabled: boolean}, turboThreshold: number, animation: boolean}}, xAxis: {gridLineWidth: number, type: string, title: {text: string}, labels: {formatter: function(): (string|*)}}, legend: {layout: string, borderWidth: number, align: string, enabled: boolean}, subtitle: {align: string}, tooltip: {backgroundColor: number, valueDecimals: number, borderRadius: number, useHTML: boolean, borderWidth: number}, title: {useHTML: boolean, style: {fontSize: string}, align: string}, chart: {backgroundColor: {linearGradient: number[], stops: [[number,string],[number,string]]}, spacingTop: number, borderWidth: string, spacingLeft: number, type: string, spacingRight: number, events: {selection: function(*): void}, height: number}}, params}} + * + ***********************************************/ +export const liveData = (params, values, req) => { + let series1 = [] + let series2 = [] + let series3 = [] + let infoTafel + + // save the current (actual) values here + let aktVal = {} + + + // Put values into the arrays + let cnt = 0 + values.forEach((x) => { + let dat = new Date(x.datetime).getTime() + series1.push([dat, x.LAeq]) + series2.push([dat, x.LA_max]) + series3.push([dat, x.LA_min]) // put data and value into series array + }) + + if (values.length != 0) { + const lastidx = values.length - 1 + // Aktuelle Werte speichern + aktVal['LAeq'] = values[lastidx].LAeq + aktVal['LAMax'] = values[lastidx].LA_max + aktVal['LAMin'] = values[lastidx].LA_min + + // InfoTafel füllen + infoTafel = + '' + + '' + + '' + + '' + infoTafel += + '' + + '' + infoTafel += + '' + + '' + infoTafel += + '
' + trans("ActualValues") + '
LAeq' + (aktVal.LAeq).toFixed(1) + 'dbA
LAmin' + (aktVal.LAMin).toFixed(0) + 'dbA
LAmax' + (aktVal.LAMax).toFixed(0) + 'dbA
' + + '' + } + let txtMeldung = false + + + // Plot-Options + let options = utils.createGlobObtions('dd.LL HH:mm:ss') + + let series_LAeq = { + name: 'LAeq', + data: series1, + color: utils.colors.eq, + yAxis: 0, + zIndex: 1, + marker: { + enabled: false, + symbol: 'square', + }, + visible: true, + fillColor: { + linearGradient: [0, 600, 0, 0], + stops: [ + [0, 'rgb(238,223,236)'], + [1, 'rgb(238,223,236)'] + ] + }, + } + + let series_LAMax = { + name: 'LAmax', + data: series2, + color: utils.colors.max, + yAxis: 0, + zIndex: 0, + marker: { + enabled: false, + symbol: 'square', + }, + visible: true, + fillColor: { + linearGradient: [0, 600, 0, 0], + stops: [ + [0, 'rgb(255,233,236)'], + [1, 'rgb(255,233,236)'] + ] + }, +// fillOpacity: 0.2, + } + + let series_LAMin = { + name: 'LAmin', + data: series3, + color: utils.colors.min, + yAxis: 0, + zIndex: 6, + marker: { + enabled: false, + symbol: 'square', + }, + visible: true, + fillColor: { + linearGradient: [0, 600, 0, 0], + stops: [ + [0, 'rgb(219,216,217)'], + [1, 'rgb(219,216,217)'] + ] + }, + } + + let yAxis_LAeq = { // 1 + title: { + text: 'dbA', + style: { + color: 'black' + } + }, + max: utils.noise_ymax, +// min: utils.noise_ymin, + min: 10, +// opposite: true, + tickAmount: 11, + useHTML: true, + } + + options.series = [] + options.yAxis = [] + options.series[0] = series_LAeq + options.series[1] = series_LAMin + options.title.text = trans('NoiseLevelsLast24Hours') + options.subtitle.useHTML = true + options.subtitle.text = `${trans("25minlogAverageValues")}
 ` + options.series[2] = series_LAMax +// options.yAxis[2] = yAxis_LAMin + options.yAxis[0] = yAxis_LAeq +// options.yAxis[1] = yAxis_LAMax + options.chart.zoomType = 'x' + options.chart.type = 'area' + options.chart.resetZoomButton= { + position: { + align: 'left', + verticalAlign: 'bottom', + x: 20, + y: -50, + }, + relativeTo: 'chart' + } + + // options.tooltip.formatter = function () { + // let y = Math.round(this.y * 100) / 100 + // return '
' + + // DateTime.fromMillis(this.x, {zone: 'utc'}).toFormat("dd.LL - HH:mm:ss") + '
' + + // '● ' + + // this.series.name + ':  ' + y + '
' + // } + + + let noDataTafel = '
' + + 'Für heute liegen leider keine Daten vor!
Bitte den Sensor überprüfen!\'
' + + '
' + + + let navy = 20 + let navbreit = 55 + let navtxt = ['-24h', '-12h', 'live', '+12h', '+24h'] + let navtime = [-24, -12, 0, 12, 24] + + return { options: options, params: params, info: {class: 'infoTafel', text:infoTafel}} +} + + +/******************************************** + * havg - Data + * + * @param params + * @param values + * @returns {{options: {plotOptions: {series: {marker: {enabled: boolean}, turboThreshold: number, animation: boolean}}, xAxis: {gridLineWidth: number, type: string, title: {text: string}, labels: {formatter: function(): (string|*)}}, legend: {layout: string, borderWidth: number, align: string, enabled: boolean}, subtitle: {align: string}, tooltip: {backgroundColor: number, valueDecimals: number, borderRadius: number, useHTML: boolean, borderWidth: number}, title: {useHTML: boolean, style: {fontSize: string}, align: string}, chart: {backgroundColor: {linearGradient: number[], stops: [[number,string],[number,string]]}, spacingTop: number, borderWidth: string, spacingLeft: number, type: string, spacingRight: number, events: {selection: function(*): void}, height: number}}, params, options2: any}} + * + ********************************************/ +export const havgData = (params, values) => { + let series1 = [] + let series2 = [] + // Put values into the series + let cnt = 0 + values.forEach((x) => { + if (x.n_AVG != -1) { + let dat = new Date(x.datetime).getTime() // retrieve the date + series1.push([dat, x.n_AVG]) + series2.push([dat, x.peakcount]) + } + }) + + // Plot-Options + let options = utils.createGlobObtions() + options.xAxis.tickInterval = 6 * 3600 * 1000 +// options.xAxis.plotBands = utils.calcWeekends(data, true) + options.xAxis.minTickInterval = 3600 * 1000 + + options.yAxis = [ + { + title: { + text: 'dbA', + useHTML: true, + }, + min: utils.noise_ymin, + tickAmount: 10, + gridLineColor: 'lightgray' + }, { + title: { + text: 'Counts', + useHTML: true, + }, + tickAmount: 10, + allowDecimals: false, + gridLineColor: 'lightgray', + opposite: true + } + ] + options.series = [ + { + name: `${trans('MeanValueLAeq')}`, + data: series1, + color: utils.colors.eq, + type: 'column', + zIndex: 2, + yAxis: 0 + }, { + name: `${trans('Peaks')}`, + data: series2, + color: utils.colors.peaks, + type: 'column', + yAxis: 1, + zIndex: 2 + } + ] + // options.plotOptions.column = { + // pointWidth: 8, + // groupPadding: 0.5 + // } + options.plotOptions.column = { + pointWidth: 8, + groupPadding: 0.1 + } + + options.title.text = `${trans('HourlyMeanValues')} / ${trans('PeaksOver')} ${params.peak} dbA` + options.subtitle.text = `${trans('HourlyMeanValuesOfLAeqForEachFullHour')} / ${trans('NumberOfPeaksPerHour')}
 ` + options.subtitle.useHTML = true + options.chart.zoomType = 'x' + options.chart.resetZoomButton= { + position: { + align: 'left', + x: 20, + y: 300, + }, + relativeTo: 'chart' + } + + return { options: options, params: params} + +} + +/******************************************** + * davg - Data + * + * @param params + * @param values + * @returns {{options: {plotOptions: {series: {marker: {enabled: boolean}, turboThreshold: number, animation: boolean}}, xAxis: {gridLineWidth: number, type: string, title: {text: string}, labels: {formatter: function(): (string|*)}}, legend: {layout: string, borderWidth: number, align: string, enabled: boolean}, subtitle: {align: string}, tooltip: {backgroundColor: number, valueDecimals: number, borderRadius: number, useHTML: boolean, borderWidth: number}, title: {useHTML: boolean, style: {fontSize: string}, align: string}, chart: {backgroundColor: {linearGradient: number[], stops: [[number,string],[number,string]]}, spacingTop: number, borderWidth: string, spacingLeft: number, type: string, spacingRight: number, events: {selection: function(*): void}, height: number}}, params, options2: any}} + * + ********************************************/ + +export const davgData = (params, values) => { + let series1 = [] + let series2 = [] + + // Put values into the serieses + let cnt = 0 + values.forEach((x) => { + if (x.n_AVG != -1) { + let dat = new Date(x.datetime).getTime() // retrieve the date + series1.push([dat, x.n_AVG]) + series2.push([dat, x.peakcount]) + } + }) + // Plot-Options + let options = utils.createGlobObtions() + // options.xAxis.plotBands = utils.calcWeekends(values, true) + options.xAxis.tickInterval = 24 * 3600 * 1000 + options.xAxis.title.text = 'Date' + // options.xAxis.labels = { + // formatter: function () { + // return this.axis.defaultLabelFormatter.call(this); + // } + // } + + options.chart.type = 'column' + + options.yAxis = [ + { + title: { + text: 'dbA', + useHTML: true, + }, + min: utils.noise_ymin, + tickAmount: 10, + gridLineColor: 'lightgray', + }, { + title: { + text: 'Counts', + useHTML: true, + }, + tickAmount: 10, + allowDecimals: false, + gridLineColor: 'lightgray', + opposite: true + } + ] + + options.series = [ + { + name: `${trans('MeanValueLAeq')}`, + data: series1, + color: utils.colors.eq, + type: 'column', + zIndex: 2, + yAxis: 0 + },{ + name: `${trans('Peaks')}`, + data: series2, + color: utils.colors.peaks, + type: 'column', + yAxis: 1, + zIndex: 2, + } + ] + options.plotOptions.column = { + pointWidth: 20, + groupPadding: 0.1 + } + options.title.text = `${trans('DailyMeanValues')} / ${trans('PeaksOver')} ${params.peak} dbA` + options.subtitle.text = `${trans('DailyMeanValuesOfLAeqForEachFullDay')} / ${trans('NumberOfPeaksPerDay')}
 ` + options.subtitle.useHTML = true + options.chart.zoomType = 'x' + options.chart.resetZoomButton = { + position: { + align: 'left', +// verticalAlign: 'bottom', + x: 20, + y: 300, + }, + relativeTo: 'chart' + } + + return {options: options, params: params} + +} + +/******************************************** + * dayNight - Data + * + * @param params + * @param values + * @returns {{options: {plotOptions: {series: {marker: {enabled: boolean}, turboThreshold: number, animation: boolean}}, xAxis: {gridLineWidth: number, type: string, title: {text: string}, labels: {formatter: function(): (string|*)}}, legend: {layout: string, borderWidth: number, align: string, enabled: boolean}, subtitle: {align: string}, tooltip: {backgroundColor: number, valueDecimals: number, borderRadius: number, useHTML: boolean, borderWidth: number}, title: {useHTML: boolean, style: {fontSize: string}, align: string}, chart: {backgroundColor: {linearGradient: number[], stops: [[number,string],[number,string]]}, spacingTop: number, borderWidth: string, spacingLeft: number, type: string, spacingRight: number, events: {selection: function(*): void}, height: number}}, params}} + * + ********************************************/ +export const dayNightData = (params, values) => { + + let series1 = [] + let series2 = [] + // Put values into the serieses + let cnt = 0 + values.forEach((x) => { + if (x.n_dayAVG > 0) { + let dat = new Date(x.datetime).getTime() // retrieve the date + series1.push([dat, x.n_dayAVG]) + series2.push([dat, x.n_nightAVG]) + } + }) + // Plot-Options + let options = utils.createGlobObtions() +// options.xAxis.plotBands = utils.calcWeekends(data, true) + options.xAxis.tickInterval = 24 * 3600 * 1000 + options.xAxis.title.text = trans('Date') + // options.xAxis.labels = { + // formatter: function () { + // return this.axis.defaultLabelFormatter.call(this); + // } + // } + + options.chart.type = 'column' + options.yAxis = { + title: { + text: 'dbA', + useHTML: true, + }, + min: utils.noise_ymin, + tickAmount: 10, + gridLineColor: 'lightgray', + } + options.series = [ + { + name: `${trans('Day')}`, + data: series1, + color: utils.colors.eq, + type: 'column', + zIndex: 2, + }, + { + name: `${trans('Night')}`, + data: series2, + color: utils.colors.max, + type: 'column', + zIndex: 2, + }, + ] + options.plotOptions.series = { + animation: false + } + options.plotOptions.column = { + pointWidth: 20, + groupPadding: 0.3 + } + options.title.text = trans('AverageValuesDuringTheDayAndNightHours') + options.subtitle.text = `${trans('DailyMeanValuesOfLAeqFrom6h00To22h00')}
${trans('NightlyMeanValuesOfLAeqFrom22h00To6h00')}
 ` + options.subtitle.useHTML = true + options.chart.zoomType = 'x' + options.chart.resetZoomButton = { + position: { + align: 'left', +// verticalAlign: 'bottom', + x: 20, + y: 300, + }, + relativeTo: 'chart' + } + return {options: options, params: params} +} + +/*********************************** + Lden - Data + * + * @param params + * @param values + * @returns {{options: {plotOptions: {series: {marker: {enabled: boolean}, turboThreshold: number, animation: boolean}}, xAxis: {gridLineWidth: number, type: string, title: {text: string}, labels: {formatter: function(): (string|*)}}, legend: {layout: string, borderWidth: number, align: string, enabled: boolean}, subtitle: {align: string}, tooltip: {backgroundColor: number, valueDecimals: number, borderRadius: number, useHTML: boolean, borderWidth: number}, title: {useHTML: boolean, style: {fontSize: string}, align: string}, chart: {backgroundColor: {linearGradient: number[], stops: [[number,string],[number,string]]}, spacingTop: number, borderWidth: string, spacingLeft: number, type: string, spacingRight: number, events: {selection: function(*): void}, height: number}}, params}} + **********************************/ +export const ldenData = (params, values) => { + + let series1 = [] + + // Put values into the series + let cnt = 0 + values.forEach((x) => { + if (!((x.lden === -1) || (x.datetime === undefined))) { + let dat = new Date(x.datetime).getTime() // retrieve the date + series1.push([dat, x.lden]) + } + }) + // Plot-Options + let options = utils.createGlobObtions() + +// options.xAxis.plotBands = utils.calcWeekends(data, true) + options.xAxis.tickInterval = 24 * 3600 * 1000 + options.xAxis.title.text = trans('Date') + options.xAxis.labels = { + formatter: function () { + let lbl = this.axis.defaultLabelFormatter.call(this); + this.value += 86400000; + let lbl1 = this.axis.defaultLabelFormatter.call(this); + return parseInt(lbl) + '/' + lbl1; + } + } + options.chart.type = 'column' + options.yAxis = { + title: { + text: 'dbA', + useHTML: true, + }, + min: utils.noise_ymin, + tickAmount: 10, + gridLineColor: 'lightgray', + } + options.series = [ + { + name: 'Lden', + data: series1, + color: utils.colors.eq, + type: 'column', + zIndex: 2, + } + ] + options.plotOptions.series = { + animation: false + } + options.plotOptions.column = { + pointWidth: 20, + groupPadding: 0.1 + } + options.title.text = trans('LDEN-Index') + options.subtitle.text = `${trans('DailyMeanValuesOfLDEN-Index')}
 ` + options.subtitle.useHTML = true + options.chart.zoomType = 'x' + options.chart.resetZoomButton = { + position: { + align: 'left', +// verticalAlign: 'bottom', + x: 20, + y: 300, + }, + relativeTo: 'chart' + } + /* options.tooltip.formatter = function () { + let d = DateTime.fromMillis(this.x, {zone: 'utc'}) + let d1 = d.plus({days: 1}) + let txt = d.toFormat('dd') + '/' + d1.toFormat('dd.LL') + return '
' + + '  ' + txt + '
' + + '● ' + + this.series.name + ':  ' + + Highcharts.numberFormat(this.y, 1) + + '
'; + } + + */ + return {options: options, params: params} +} + +/*********************************** + Map - Data + * + * @param params + * @param values + * @returns {{options: {plotOptions: {series: {marker: {enabled: boolean}, turboThreshold: number, animation: boolean}}, xAxis: {gridLineWidth: number, type: string, title: {text: string}, labels: {formatter: function(): (string|*)}}, legend: {layout: string, borderWidth: number, align: string, enabled: boolean}, subtitle: {align: string}, tooltip: {backgroundColor: number, valueDecimals: number, borderRadius: number, useHTML: boolean, borderWidth: number}, title: {useHTML: boolean, style: {fontSize: string}, align: string}, chart: {backgroundColor: {linearGradient: number[], stops: [[number,string],[number,string]]}, spacingTop: number, borderWidth: string, spacingLeft: number, type: string, spacingRight: number, events: {selection: function(*): void}, height: number}}, params}} + **********************************/ +export const mapData = (params, values) => { + let actsensors = 0 + for (let x of values) { + if (x.value >= 0) { + actsensors++ + } + } + return { + ...params, + values: values, + actsensors: `${trans("ActiveSensors")} ${actsensors}`, + registered: `(${trans("registered")} ${params.count})`, + valfromtxt: trans("ValuesFrom"), + popuptxt: { + offline: trans('offline'), + sensor: trans('Sensor'), + lastseen: trans('LastSeen'), + showchart: trans('ShowChart') + } + } +} + diff --git a/noise/charts/utilities.js b/noise/charts/utilities.js new file mode 100644 index 0000000..3e6c114 --- /dev/null +++ b/noise/charts/utilities.js @@ -0,0 +1,151 @@ +// Utility routine for plotting the data + +import { translate as trans } from '../routes/index.js' + +let language = 'en' + +export const colors = {'eq': '#0000FF', 'max': '#FF0000', 'min': '#008000', 'peaks': '#DAA520'}; +export const noise_ymin = 20; +export const noise_ymax = 120; + +export function createGlobObtions() { + // Options, die für alle Plots identisch sind + let globObject = { + chart: { + spacingRight: 20, + spacingLeft: 20, + spacingTop: 25, + backgroundColor: { + linearGradient: [0, 400, 0, 0], + stops: [ + [0, '#eee'],//[0, '#ACD0AA'], //[0, '#A18D99'], // [0, '#886A8B'], // [0, '#F2D0B5'], + [1, '#fff'] + ] + }, + type: 'line', + borderWidth: '2', + // events: { + // selection: function (event) { + // if (event.xAxis) { + // doUpdate = false; + // } else { + // doUpdate = true; + // } + // } + // } + }, + title: { + align: 'left', + style: {'fontSize': '25px'}, + useHTML: true, + }, + subtitle: { + align: 'left', + }, + tooltip: { + valueDecimals: 1, + backgroundColor: '#ffffff', + borderWidth: 0, + borderRadius: 0, + useHTML: true, + }, + xAxis: { + type: 'datetime', + title: { + text: trans('datetime'), + }, + gridLineWidth: 2, + labels: { + formatter: function () { + let v = this.axis.defaultLabelFormatter.call(this); + if (v.indexOf(':') == -1) { + return '' + v + ''; + } else { + return v; + } + } + }, + }, + legend: { + enabled: true, + layout: 'horizontal', +// verticalAlign: 'top', + borderWidth: 1, + align: 'center', + }, + plotOptions: { + series: { + animation: false, + turboThreshold: 0, + marker: { + enabled: false, + }, + }, + } + }; + return globObject; +} + +export function calcWeekends(data, isyear) { +/* let weekend = []; + let oldDay = 8; + for (let i = 0; i < data.length; i++) { + let mom = moment(data[i].date); + if (isyear) { + mom = moment(data[i]._id) + } + let day = mom.day(); + let st = mom.startOf('day'); + if (day != oldDay) { + if (day == 6) { + weekend.push({ + color: 'rgba(169,235,158,0.4)', + from: st.valueOf(), + to: st.add(1, 'days').valueOf(), + zIndex: 0 + }) + } else if (day == 0) { + weekend.push({ + color: 'rgba(169,235,158,0.4)', + from: st.valueOf(), + to: st.add(1, 'days').valueOf(), + zIndex: 0 + }) + } + oldDay = day; + } + } + return weekend; +*/} + +export function calcDays(data, isyear) { + let days = []; + if (data.length == 0) { + return days + } + let oldday = moment(data[0].date).day(); + if (isyear) { + oldday = moment(data[0]._id).day(); + } + for (let i = 0; i < data.length; i++) { + let m = moment(data[i].date); + if (isyear) { + m = moment(data[i]._id); + } + let tag = m.day() + if (tag != oldday) { + m.startOf('day'); + days.push({color: 'lightgray', value: m.valueOf(), width: 1, zIndex: 2}); + oldday = tag; + } + } + return days; +}; + +export const setLanguage = (lng) => { + language = lng +} + +export const getLanguage = () => { + return language +} diff --git a/noise/deploy.sh b/noise/deploy.sh new file mode 100755 index 0000000..a044a5e --- /dev/null +++ b/noise/deploy.sh @@ -0,0 +1,58 @@ +#!/bin/bash + +set -e + +# Angepasst aus dem readin-/sensorapi-deploy.sh (urspr. /Projekte/Logbuch/deploy.sh) +# Nur linux/amd64, nativer Build auf esprimo (amd64) -> kein buildx/qemu, +# eigener Dockerfile-Name (Dockerfile_noise). Image-Name: noise. + +REGISTRY="docker.citysensor.de" +IMAGE_NAME="noise" +TAG="${1:-latest}" +PLATFORM="linux/amd64" +DOCKERFILE="Dockerfile_noise" +FULL_IMAGE="${REGISTRY}/${IMAGE_NAME}:${TAG}" +BUILD_DATE=$(date +%d.%m.%Y) + +echo "==========================================" +echo "noise (laerm_web) Deploy Script (amd64)" +echo "==========================================" +echo "Registry: ${REGISTRY}" +echo "Image: ${IMAGE_NAME}" +echo "Tag: ${TAG}" +echo "Platform: ${PLATFORM}" +echo "Dockerfile: ${DOCKERFILE}" +echo "Build-Datum: ${BUILD_DATE}" +echo "==========================================" +echo "" + +# Hinweis: Login wird uebersprungen, weil die Credentials fuer ${REGISTRY} +# bereits in ~/.docker/config.json liegen. +# Bei Bedarf manuell: docker login ${REGISTRY} + +echo ">>> Baue Image (nur ${PLATFORM}, nativ) ..." +docker build \ + --platform "${PLATFORM}" \ + -f "${DOCKERFILE}" \ + -t "${FULL_IMAGE}" \ + . +echo "" + +echo ">>> Pushe ${FULL_IMAGE} ..." +docker push "${FULL_IMAGE}" +echo "" + +# Falls ein anderer Tag als 'latest' gebaut wurde, zusaetzlich latest setzen+pushen +if [ "${TAG}" != "latest" ]; then + echo ">>> Tagge zusaetzlich als :latest ..." + docker tag "${FULL_IMAGE}" "${REGISTRY}/${IMAGE_NAME}:latest" + docker push "${REGISTRY}/${IMAGE_NAME}:latest" + echo "" +fi + +echo "==========================================" +echo "Build + Push fertig: ${FULL_IMAGE}" +echo "==========================================" +echo "" +echo "Danach Stack aktualisieren:" +echo " cd /opt/stacks/esprimo/noisesensors && docker compose up -d noise" diff --git a/noise/docs/Readme.md b/noise/docs/Readme.md new file mode 100644 index 0000000..29b8609 --- /dev/null +++ b/noise/docs/Readme.md @@ -0,0 +1,5 @@ +####Neues Sensor-API + +* Programm **sensor_web_api**. Läuft auf Port 3000 +* Aufruf über: **laerm.test.me:3000** (oder feinstaub.test... oder multigeiger.test...) +* Zugriff auf die DB mit dem Programm **SensorApi**. Dieses reagiert auf Port 3005 und muss im Hintergrund laufen! diff --git a/noise/docs/aktchanges b/noise/docs/aktchanges new file mode 100644 index 0000000..0a77e88 --- /dev/null +++ b/noise/docs/aktchanges @@ -0,0 +1,5 @@ +Changes ab AUG-23 + +- i18n in /:sid in idex.js rein +- Messung und Anzeige auf Console der Ladezeit der 5 Pages im Hintergrund + diff --git a/noise/locales/de/translation.json b/noise/locales/de/translation.json new file mode 100644 index 0000000..aba3505 --- /dev/null +++ b/noise/locales/de/translation.json @@ -0,0 +1,53 @@ +{ + "NoiseMeasurement": "Lärm-Messung", + "Settings": "Einstellungen", + "Info": "Info", + "StartDate": "Start Datum", + "NumberOfDays": "So viele Tage anzeigen", + "Only_for_live_chart": "Nur bei 'live' Grafik", + "Count_peaks_over": "Zähle Spitzen über", + "Close": "Schließen", + "Save_changes": "Änderungen speichern", + "Language": "Sprache", + "Map": "Karte", + "Live": "Live", + "Hour_AVG": "Stundenmittel", + "Day_AVG": "Tagesmittel", + "Day_Night": "Tag/Nacht-Werte", + "ActualValues": "Aktuelle Werte", + "NoiseLevelsLast24Hours": "Schallpegel der letzten 24 Stunden", + "ValuesFrom": "Werte vom", + "ActiveSensors": "Aktive Sensoren:", + "registered": "registriert:", + "ShowChart": "Grafik anzeigen", + "Sensor": "Sensor", + "offline": "offline", + "LastSeen": "Letzter Kontakt", + "datetime": "Datum/Zeit", + "25minlogAverageValues": "2.5min log. Mittelwerte", + "HourlyMeanValues": "Stündliche Mittelwerte", + "PeaksOver": "Spitzen über", + "HourlyMeanValuesOfLAeqForEachFullHour": "Stunden-Mittelwerte von LAeq jeweils für eine volle Stunde", + "NumberOfPeaksPerHour": "Anzahl der Spitzen pro Stunde", + "DailyMeanValues": "Tages-Mittelwerte", + "DailyMeanValuesOfLAeqForEachFullDay": "Tages-Mittelwerte von LAeq jeweils für einen vollen Tag", + "NumberOfPeaksPerDay": "Anzahl der Spitzen pro Tag", + "AverageValuesDuringTheDayAndNightHours": "Mittelwerte während der Tag- und Nachtstunden", + "DailyMeanValuesOfLAeqFrom6h00To22h00": "Tages-Mittelwerte des LAeq jeweils von 6:00 bis 22:00 Uhr", + "NightlyMeanValuesOfLAeqFrom22h00To6h00": "Nacht-Mittelwerte des LAeq jeweils von 22:00 bis 6:00 Uhr", + "LDEN-Index": "LDEN-Index", + "DailyMeanValuesOfLDEN-Index": "Tages-Mittelwerte des LDEN-Index", + "Date": "Datum", + "Version": "Version", + "from": "vom", + "RemoveFromMap": "Sensoren nicht anzeigen, die nicht gesendet haben seit", + "weeks": "Wochen", + "ESYSCALL": "Fehler vom Serveraufruf: ", + "Error": "Fehler", + "MeanValueLAeq": "Mittelwert LAeq", + "Peaks": "Spitzen", + "Day": "Tag", + "Night": "Nacht", + "CenterMap": "Karte zentrieren auf", + "MyLocation": "Mein Standort" +} \ No newline at end of file diff --git a/noise/locales/dev/translation.json b/noise/locales/dev/translation.json new file mode 100644 index 0000000..45f152c --- /dev/null +++ b/noise/locales/dev/translation.json @@ -0,0 +1,47 @@ +{ + "NoiseMeasurement": "Lärm-Messung", + "Settings": "Einstellungen", + "Info": "Info", + "StartDate": "Start Datum", + "NumberOfDays": "So viele Tage anzeigen", + "Only_for_live_chart": "Nur bei 'live' Grafik", + "Count_peaks_over": "Zähle Spitzen über", + "Close": "Schließen", + "Save_changes": "Änderungen speichern", + "Language": "Sprache", + "Map": "Karte", + "Live": "Live", + "Hour_AVG": "Stundenmittel", + "Day_AVG": "Tagesmittel", + "Day_Night": "Tag/Nacht-Werte", + "ActualValues": "Aktuelle Werte", + "NoiseLevelsLast24Hours": "Schallpegel der letzten 24 Stunden", + "ValuesFrom": "Werte vom", + "ActiveSensors": "Aktive Sensoren:", + "registered": "registriert:", + "ShowChart": "Grafik anzeigen", + "Sensor": "Sensor", + "offline": "offline", + "LastSeen": "Letzter Kontakt", + "datetime": "Datum/Zeit", + "25minlogAverageValues": "2.5min log. Mittelwerte", + "HourlyMeanValues": "Stündliche Mittelwerte", + "PeaksOver": "Spitzen über", + "HourlyMeanValuesOfLAeqForEachFullHour": "Stunden-Mittelwerte von LAeq jeweils für eine volle Stunde", + "NumberOfPeaksPerHour": "Anzahl der Spitzen pro Stunde", + "DailyMeanValues": "Tages-Mittelwerte", + "DailyMeanValuesOfLAeqForEachFullDay": "Tages-Mittelwerte von LAeq jeweils für einen vollen Tag", + "NumberOfPeaksPerDay": "Anzahl der Spitzen pro Tag", + "AverageValuesDuringTheDayAndNightHours": "Mittelwerte während der Tag- und Nachtstunden", + "DailyMeanValuesOfLAeqFrom6h00To22h00": "Tages-Mittelwerte des LAeq jeweils von 6:00 bis 22:00 Uhr", + "NightlyMeanValuesOfLAeqFrom22h00To6h00": "Nacht-Mittelwerte des LAeq jeweils von 22:00 bis 6:00 Uhr", + "LDEN-Index": "LDEN-Index", + "DailyMeanValuesOfLDEN-Index": "Tages-Mittelwerte des LDEN-Index", + "Date": "Datum", + "Version": "Version", + "from": "vom", + "RemoveFromMap": "Sensoren nicht anzeigen, die nicht gesendet haben seit", + "weeks": "Wochen", + "CenterMap": "Center map on" + +} \ No newline at end of file diff --git a/noise/locales/en/translation.json b/noise/locales/en/translation.json new file mode 100644 index 0000000..17ab654 --- /dev/null +++ b/noise/locales/en/translation.json @@ -0,0 +1,53 @@ +{ + "NoiseMeasurement": "Noise Measurement", + "Settings": "Settings", + "Info": "Info", + "StartDate": "Start date", + "NumberOfDays": "Show so many days", + "Only_for_live_chart": "Only for 'live' chart", + "Count_peaks_over": "Count peaks over", + "Close": "Close", + "Save_changes": "Save changes", + "Language": "Language", + "Map": "Map", + "Live": "Live", + "Hour_AVG": "Hour_AVG", + "Day_AVG": "Day_AVG", + "Day_Night": "Day_Night", + "ActualValues": "Actual Values", + "NoiseLevelsLast24Hours": "Noise levels last 24 hours", + "ValuesFrom": "Values from ", + "ActiveSensors": "Active Sensors:", + "registered": "registered:", + "ShowChart": "Show chart", + "Sensor": "Sensor", + "offline": "offline", + "LastSeen": "Last seen", + "datetime": "Date/Time", + "25minlogAverageValues": "2.5min log average values", + "HourlyMeanValues": "Hourly mean values", + "PeaksOver": "Peaks over", + "HourlyMeanValuesOfLAeqForEachFullHour": "Hourly mean values of LAeq for each full hour", + "NumberOfPeaksPerHour": "Number of peaks per hour", + "DailyMeanValues": "Daily mean values", + "DailyMeanValuesOfLAeqForEachFullDay": "Daily mean values of LAeq for each full day", + "NumberOfPeaksPerDay": "Number of peaks per day", + "AverageValuesDuringTheDayAndNightHours": "Average values during the day and night hours", + "DailyMeanValuesOfLAeqFrom6h00To22h00": "Daily mean values of LAeq from 6h00 to 22h00", + "NightlyMeanValuesOfLAeqFrom22h00To6h00": "Nightly mean values of LAeq from 22h00 to 6h00", + "LDEN-Index": "LDEN-Index", + "DailyMeanValuesOfLDEN-Index": "Daily mean values of LDEN-Index", + "Date": "Date", + "Version": "Version", + "from": "from", + "RemoveFromMap": "Don't show sensors that have not sent for", + "weeks": "weeks", + "ESYSCALL": "Error from Syscall: ", + "Error": "Error", + "MeanValueLAeq": "Mean value LAeq", + "Peaks": "Peaks", + "Day": "Day", + "Night": "Night", + "CenterMap": "Center map on", + "MyLocation": "My Location" +} diff --git a/noise/package-lock.json b/noise/package-lock.json new file mode 100644 index 0000000..28e5697 --- /dev/null +++ b/noise/package-lock.json @@ -0,0 +1,2117 @@ +{ + "name": "laerm-web-sensorapi", + "version": "3.3.1", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "laerm-web-sensorapi", + "version": "3.3.1", + "dependencies": { + "axios": "^1.3.4", + "cookie-parser": "~1.4.4", + "cors": "^2.8.5", + "debug": "~2.6.9", + "dotenv": "^17.2.3", + "express": "^4.18.2", + "http-errors": "~1.6.3", + "i18next": "^22.4.14", + "i18next-express-middleware": "^2.0.0", + "i18next-fs-backend": "^2.0.0", + "i18next-http-middleware": "^3.3.0", + "luxon": "^3.3.0", + "morgan": "^1.10.1", + "pug": "^3.0.2", + "sass": "^1.58.3", + "spin.js": "^4.1.2" + }, + "bin": { + "www": "bin/www.js" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.29.7.tgz", + "integrity": "sha512-Pb5ijPrZ89GDH8223L4UP8i6QApWxs04RbPQJTeWDV0/keR2E36MeKnyr6LYmUUvqRRI+Iv87SuF1W6ErINzYw==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.29.7.tgz", + "integrity": "sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.7.tgz", + "integrity": "sha512-hnORnjP/1P/zFEndoeX+n+t1RwWRJiJpM/jO7FW32Kn9r5+sJB2JWOdYo4L6k78j15eCwY3Gm/7364B1EMwtNg==", + "license": "MIT", + "dependencies": { + "@babel/types": "^7.29.7" + }, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/runtime": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.29.7.tgz", + "integrity": "sha512-Nq8OhGWiZIZGV6hLHoyAKLLcJihP/xFeBMGJoUrxTX2psI8dCifzLhZISFb+VWS3wFMRDmCGw5R+dOySCqPLhw==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/types": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.7.tgz", + "integrity": "sha512-4zBIxpPzowiZpusoFkyGVwakdRJUyuH5PxQ/PrqghfdFWWasvnCdPfQXHrenDai+gyLARulZjZowCOj6fjT4pA==", + "license": "MIT", + "dependencies": { + "@babel/helper-string-parser": "^7.29.7", + "@babel/helper-validator-identifier": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@parcel/watcher": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/@parcel/watcher/-/watcher-2.6.0.tgz", + "integrity": "sha512-7FNeNl8NCE7aINx7WXiKQrPYZWC/hvrTsmk6zmxbI7LTXE7hVek/n8AfVgpe2y82zl3w0HvCHN0bVKMBoJcC0w==", + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "dependencies": { + "detect-libc": "^2.0.3", + "is-glob": "^4.0.3", + "node-addon-api": "^7.0.0", + "picomatch": "^4.0.4" + }, + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + }, + "optionalDependencies": { + "@parcel/watcher-android-arm64": "2.6.0", + "@parcel/watcher-darwin-arm64": "2.6.0", + "@parcel/watcher-darwin-x64": "2.6.0", + "@parcel/watcher-freebsd-x64": "2.6.0", + "@parcel/watcher-linux-arm-glibc": "2.6.0", + "@parcel/watcher-linux-arm-musl": "2.6.0", + "@parcel/watcher-linux-arm64-glibc": "2.6.0", + "@parcel/watcher-linux-arm64-musl": "2.6.0", + "@parcel/watcher-linux-x64-glibc": "2.6.0", + "@parcel/watcher-linux-x64-musl": "2.6.0", + "@parcel/watcher-win32-arm64": "2.6.0", + "@parcel/watcher-win32-x64": "2.6.0" + } + }, + "node_modules/@parcel/watcher-android-arm64": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/@parcel/watcher-android-arm64/-/watcher-android-arm64-2.6.0.tgz", + "integrity": "sha512-trgpLSCKRC/huFjXX/Smh+0sWe4+YtKfktIToiMl59ghz7z+qkH6kMvNnUbLyRs9N11t8l4svSCs1+5B3rOAhA==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-darwin-arm64": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/@parcel/watcher-darwin-arm64/-/watcher-darwin-arm64-2.6.0.tgz", + "integrity": "sha512-Y3QV0gl7Q1zbfueunkWIERICbEojQFCgpyG7YqOGNFLsckXyI1xu9mAIUpKY9QBYzBtSkN8dBPwd3yiAO9ovMw==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-darwin-x64": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/@parcel/watcher-darwin-x64/-/watcher-darwin-x64-2.6.0.tgz", + "integrity": "sha512-Ohv6OpzhUfKYD7Beb8kDvG0jbIxORCYY1JRdZnaBtnjjkJxgD7ZVL0nw2sCYd0yTMKTvz3nnTnOF3cDifK+kvw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-freebsd-x64": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/@parcel/watcher-freebsd-x64/-/watcher-freebsd-x64-2.6.0.tgz", + "integrity": "sha512-5HmXvDgs8VK+74jF9y9/2FE3/OnlcKmc56tjmSrEuZjpSZOGL+fvAu+HKJBdPs9uwoP2hE6TlSUpXZ/C5jUFmQ==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-arm-glibc": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm-glibc/-/watcher-linux-arm-glibc-2.6.0.tgz", + "integrity": "sha512-Ps/hui3A+vMbjdqlqAowK2ZL8+BO8dBjxeWXj6npTBs3jx4wWmbPpaLuqwrQrSqIVMCnpWo238bJ1U37GhQOYg==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-arm-musl": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm-musl/-/watcher-linux-arm-musl-2.6.0.tgz", + "integrity": "sha512-9c6AUHgHoG+IY88MRIHupztQiQnrbqHYQjkM2btA+Bf/wQnQMuiD0Wfk1EVv3TlNT3x41uU71rn6E4xh/+zvkw==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-arm64-glibc": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm64-glibc/-/watcher-linux-arm64-glibc-2.6.0.tgz", + "integrity": "sha512-yHRqS2owEXe6Hic9z6Mh1ECsCd+ODVOGvZDyciqRd21+v+o+DnXMOrw50DSpIG2sb8GPEaPPmfeCAWKPJdq46g==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-arm64-musl": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm64-musl/-/watcher-linux-arm64-musl-2.6.0.tgz", + "integrity": "sha512-WhB2e/V7rqdHHWZusBSPuy5Ei8S6lSz6FE5TKKQz5h3a0O+C+mhY7vxU9b/stqvMb8beLnPY82ZrFTLKs+SrKA==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-x64-glibc": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-x64-glibc/-/watcher-linux-x64-glibc-2.6.0.tgz", + "integrity": "sha512-ulGE6x6Oz6iAwg75T8YQSoguBWasniIbX+QWpaYPcCnDOpdWX3k+4xbEYPZVLxOuoJI+svJJPD3sEj8G7lrQ3A==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-x64-musl": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-x64-musl/-/watcher-linux-x64-musl-2.6.0.tgz", + "integrity": "sha512-tkBYKt7YQrjIJWYDnto2YgO8MRkjlMTSNoRHzsXinBqbLdeOM3L32wPZJvIZxqaLMfSlS/4sUjH/6STVP/XDLw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-win32-arm64": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-arm64/-/watcher-win32-arm64-2.6.0.tgz", + "integrity": "sha512-gIZAP23jaHjGWasY/TY6yL7NHFClf0Ga7FN+iINvk+KN94rhm94lYZhFsbYFNcA04/onvGD9kKmiJLJB2HbNwQ==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-win32-x64": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-x64/-/watcher-win32-x64-2.6.0.tgz", + "integrity": "sha512-cA+/pXV2YkfxlIcXOQ5fSWqAzzPyD78/x5qbK/I0vUkrlYHA8TIz+MXjAbGouguKVSI4bOmkTSJ1/poVSsgt+A==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "license": "MIT", + "dependencies": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/acorn": { + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", + "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", + "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "license": "MIT", + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/agent-base/node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/agent-base/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" + }, + "node_modules/array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==", + "license": "MIT" + }, + "node_modules/asap": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", + "integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==", + "license": "MIT" + }, + "node_modules/assert-never": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/assert-never/-/assert-never-1.4.0.tgz", + "integrity": "sha512-5oJg84os6NMQNl27T9LnZkvvqzvAnHu03ShCnoj6bsJwS7L8AO4lf+C/XjK/nvzEqQB744moC6V128RucQd1jA==", + "license": "MIT" + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "license": "MIT" + }, + "node_modules/axios": { + "version": "1.18.1", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.18.1.tgz", + "integrity": "sha512-3nTvFlvpn9Zu/RkHUqtc7/+al4UpRW5az71ap5zccp6e8RAYEzhMTecX8Dz1wWDYrPpUoB1HAQEGEAEvUr7S9g==", + "license": "MIT", + "dependencies": { + "follow-redirects": "^1.16.0", + "form-data": "^4.0.5", + "https-proxy-agent": "^5.0.1", + "proxy-from-env": "^2.1.0" + } + }, + "node_modules/babel-walk": { + "version": "3.0.0-canary-5", + "resolved": "https://registry.npmjs.org/babel-walk/-/babel-walk-3.0.0-canary-5.tgz", + "integrity": "sha512-GAwkz0AihzY5bkwIY5QDR+LvsRQgB/B+1foMPvi0FZPMl5fjD7ICiznUiBdLYMH1QYe6vqu4gWYytZOccLouFw==", + "license": "MIT", + "dependencies": { + "@babel/types": "^7.9.6" + }, + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/basic-auth": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-2.0.1.tgz", + "integrity": "sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg==", + "license": "MIT", + "dependencies": { + "safe-buffer": "5.1.2" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/basic-auth/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "license": "MIT" + }, + "node_modules/body-parser": { + "version": "1.20.6", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.6.tgz", + "integrity": "sha512-p5tAzS57i5MV9fZFDj9LeIiTZEufbSe2eDozP+ElheSUq1m74CRq1jI4mYNDdVs9vQztXFLuk/Gd6BWTdwRJ5g==", + "license": "MIT", + "dependencies": { + "bytes": "~3.1.2", + "content-type": "~1.0.5", + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "~1.2.0", + "http-errors": "~2.0.1", + "iconv-lite": "~0.4.24", + "on-finished": "~2.4.1", + "qs": "~6.15.1", + "raw-body": "~2.5.3", + "type-is": "~1.6.18", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/body-parser/node_modules/http-errors": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.1.tgz", + "integrity": "sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==", + "license": "MIT", + "dependencies": { + "depd": "~2.0.0", + "inherits": "~2.0.4", + "setprototypeof": "~1.2.0", + "statuses": "~2.0.2", + "toidentifier": "~1.0.1" + }, + "engines": { + "node": ">= 0.8" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/body-parser/node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "license": "ISC" + }, + "node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/call-bound": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", + "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "get-intrinsic": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/character-parser": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/character-parser/-/character-parser-2.2.0.tgz", + "integrity": "sha512-+UqJQjFEFaTAs3bNsF2j2kEN1baG/zghZbdqoYEDxGZtJo9LBzl1A+m0D4n3qKx8N2FNv8/Xp6yV9mQmBuptaw==", + "license": "MIT", + "dependencies": { + "is-regex": "^1.0.3" + } + }, + "node_modules/chokidar": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-5.0.0.tgz", + "integrity": "sha512-TQMmc3w+5AxjpL8iIiwebF73dRDF4fBIieAqGn9RGCWaEVwQ6Fb2cGe31Yns0RRIzii5goJ1Y7xbMwo1TxMplw==", + "license": "MIT", + "dependencies": { + "readdirp": "^5.0.0" + }, + "engines": { + "node": ">= 20.19.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "license": "MIT", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/constantinople": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/constantinople/-/constantinople-4.0.1.tgz", + "integrity": "sha512-vCrqcSIq4//Gx74TXXCGnHpulY1dskqLTFGDmhrGxzeXL8lF8kvXv6mpNWlJj1uD4DW23D4ljAqbY4RRaaUZIw==", + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.6.0", + "@babel/types": "^7.6.1" + } + }, + "node_modules/content-disposition": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", + "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", + "license": "MIT", + "dependencies": { + "safe-buffer": "5.2.1" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/content-type": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", + "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie-parser": { + "version": "1.4.7", + "resolved": "https://registry.npmjs.org/cookie-parser/-/cookie-parser-1.4.7.tgz", + "integrity": "sha512-nGUvgXnotP3BsjiLX2ypbQnWoGUPIIfHQNZkkC668ntrzGWEZVW70HDEB1qnNGMicPje6EttlIgzo51YSwNQGw==", + "license": "MIT", + "dependencies": { + "cookie": "0.7.2", + "cookie-signature": "1.0.6" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==", + "license": "MIT" + }, + "node_modules/cookies": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/cookies/-/cookies-0.7.1.tgz", + "integrity": "sha512-VX3KKCWrKjPnCwF78P60rnMfy1piVeObnjuKO4rBUyiSRYDgY/EqXbw3jX/uXmmdAPmayVJqdbLfJ0BRSfRZFg==", + "license": "MIT", + "dependencies": { + "depd": "~1.1.1", + "keygrip": "~1.0.2" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/cookies/node_modules/depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cors": { + "version": "2.8.6", + "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.6.tgz", + "integrity": "sha512-tJtZBBHA6vjIAaF6EnIaq6laBBP9aq/Y3ouVJjEfoHbRBcHBAHYcMh/w8LDrk2PvIMMq8gmopa5D4V8RmbrxGw==", + "license": "MIT", + "dependencies": { + "object-assign": "^4", + "vary": "^1" + }, + "engines": { + "node": ">= 0.10" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/destroy": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", + "license": "MIT", + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/detect-libc": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", + "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", + "license": "Apache-2.0", + "optional": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/doctypes": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/doctypes/-/doctypes-1.1.0.tgz", + "integrity": "sha512-LLBi6pEqS6Do3EKQ3J0NqHWV5hhb78Pi8vvESYwyOy2c31ZEZVdtitdzsQsKb7878PEERhzUk0ftqGhG6Mz+pQ==", + "license": "MIT" + }, + "node_modules/dotenv": { + "version": "17.4.2", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-17.4.2.tgz", + "integrity": "sha512-nI4U3TottKAcAD9LLud4Cb7b2QztQMUEfHbvhTH09bqXTxnSie8WnjPALV/WMCrJZ6UV/qHJ6L03OqO3LcdYZw==", + "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", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", + "license": "MIT" + }, + "node_modules/encodeurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", + "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-object-atoms": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.2.tgz", + "integrity": "sha512-HWcBoN6NileqtSydK2FqHbS/LoDd2pqrnQHLyJzBj4kOp/ky2MWMN694xOfkK8/SnUsW2DH7EfyVlydKCsm1Zw==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-set-tostringtag": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", + "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", + "license": "MIT" + }, + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/express": { + "version": "4.22.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.22.2.tgz", + "integrity": "sha512-IuL+Elrou2ZvCFHs18/CIzy2Nzvo25nZ1/D2eIZlz7c+QUayAcYoiM2BthCjs+EBHVpjYjcuLDAiCWgeIX3X1Q==", + "license": "MIT", + "dependencies": { + "accepts": "~1.3.8", + "array-flatten": "1.1.1", + "body-parser": "~1.20.5", + "content-disposition": "~0.5.4", + "content-type": "~1.0.4", + "cookie": "~0.7.1", + "cookie-signature": "~1.0.6", + "debug": "2.6.9", + "depd": "2.0.0", + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "~1.3.1", + "fresh": "~0.5.2", + "http-errors": "~2.0.0", + "merge-descriptors": "1.0.3", + "methods": "~1.1.2", + "on-finished": "~2.4.1", + "parseurl": "~1.3.3", + "path-to-regexp": "~0.1.12", + "proxy-addr": "~2.0.7", + "qs": "~6.15.1", + "range-parser": "~1.2.1", + "safe-buffer": "5.2.1", + "send": "~0.19.0", + "serve-static": "~1.16.2", + "setprototypeof": "1.2.0", + "statuses": "~2.0.1", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.10.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/express/node_modules/http-errors": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.1.tgz", + "integrity": "sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==", + "license": "MIT", + "dependencies": { + "depd": "~2.0.0", + "inherits": "~2.0.4", + "setprototypeof": "~1.2.0", + "statuses": "~2.0.2", + "toidentifier": "~1.0.1" + }, + "engines": { + "node": ">= 0.8" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/express/node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "license": "ISC" + }, + "node_modules/finalhandler": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.2.tgz", + "integrity": "sha512-aA4RyPcd3badbdABGDuTXCMTtOneUCAYH/gxoYRTZlIJdF0YPWuGqiAsIrhNnnqdXGswYk6dGujem4w80UJFhg==", + "license": "MIT", + "dependencies": { + "debug": "2.6.9", + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "on-finished": "~2.4.1", + "parseurl": "~1.3.3", + "statuses": "~2.0.2", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/follow-redirects": { + "version": "1.16.0", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.16.0.tgz", + "integrity": "sha512-y5rN/uOsadFT/JfYwhxRS5R7Qce+g3zG97+JrtFZlC9klX/W5hD7iiLzScI4nZqUS7DNUdhPgw4xI8W2LuXlUw==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "license": "MIT", + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, + "node_modules/form-data": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.6.tgz", + "integrity": "sha512-vKatAh4SlVfgbv+YtmhiRjhEMJsYpsG1Y2rMQtR+SVSbytsSD1YGzDIcrAJmdFec88u/+VoGmxnl+80gL1tRCQ==", + "license": "MIT", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "es-set-tostringtag": "^2.1.0", + "hasown": "^2.0.4", + "mime-types": "^2.1.35" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-intrinsic": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "license": "MIT", + "dependencies": { + "has-symbols": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.4.tgz", + "integrity": "sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A==", + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/http-errors": { + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", + "integrity": "sha512-lks+lVC8dgGyh97jxvxeYTWQFvh4uw4yC12gVl63Cg30sjPX4wuGcdkICVXDAESr6OJGjqGA8Iz5mkeN6zlD7A==", + "license": "MIT", + "dependencies": { + "depd": "~1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.0", + "statuses": ">= 1.4.0 < 2" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/http-errors/node_modules/depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/http-errors/node_modules/setprototypeof": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", + "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==", + "license": "ISC" + }, + "node_modules/http-errors/node_modules/statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "license": "MIT", + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/https-proxy-agent/node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/https-proxy-agent/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" + }, + "node_modules/i18next": { + "version": "22.5.1", + "resolved": "https://registry.npmjs.org/i18next/-/i18next-22.5.1.tgz", + "integrity": "sha512-8TGPgM3pAD+VRsMtUMNknRz3kzqwp/gPALrWMsDnmC1mKqJwpWyooQRLMcbTwq8z8YwSmuj+ZYvc+xCuEpkssA==", + "funding": [ + { + "type": "individual", + "url": "https://locize.com" + }, + { + "type": "individual", + "url": "https://locize.com/i18next.html" + }, + { + "type": "individual", + "url": "https://www.i18next.com/how-to/faq#i18next-is-awesome.-how-can-i-support-the-project" + } + ], + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.20.6" + } + }, + "node_modules/i18next-express-middleware": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/i18next-express-middleware/-/i18next-express-middleware-2.0.0.tgz", + "integrity": "sha512-TGlSkYsQHikggv4mIp5B+CiXsZzwbpHaZgmOkRNGStLOdKHABH5cHr136g2PC1+p2VPMf3y3UoQZ1TfPfVOrgg==", + "deprecated": "replaced by i18next-http-middleware", + "license": "MIT", + "dependencies": { + "cookies": "0.7.1" + } + }, + "node_modules/i18next-fs-backend": { + "version": "2.6.6", + "resolved": "https://registry.npmjs.org/i18next-fs-backend/-/i18next-fs-backend-2.6.6.tgz", + "integrity": "sha512-mYGu6Nt8RIp3X/U8Y+Gej1wo5xmYWmGKLqBGMCC2OCAou5rW5epeHgHmVcw20mJs9Z9+DAPHIxQPNCgFyPRMeg==", + "license": "MIT" + }, + "node_modules/i18next-http-middleware": { + "version": "3.9.7", + "resolved": "https://registry.npmjs.org/i18next-http-middleware/-/i18next-http-middleware-3.9.7.tgz", + "integrity": "sha512-k4Aa39thnQXGox5ZeKvlOwbDsFz+iGxtPJITWm6xmmErNZOeGMXIoH9XwK3ITUq7lqHaywnIH9gLwOraU4jJvQ==", + "license": "MIT" + }, + "node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/immutable": { + "version": "5.1.9", + "resolved": "https://registry.npmjs.org/immutable/-/immutable-5.1.9.tgz", + "integrity": "sha512-m8nVez3rwrgmWxtLMt1ZYXB2Lv7OKYn/disyxAlSDYAlKSlFoPPfIAmAM/M5xqL4m4C/wAPw7S2/CNaUii1Hxg==", + "license": "MIT" + }, + "node_modules/inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==", + "license": "ISC" + }, + "node_modules/ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "license": "MIT", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/is-core-module": { + "version": "2.16.2", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.2.tgz", + "integrity": "sha512-evOr8xfXKxE6qSR0hSXL2r3sd7ALj8+7jQEUvPYcm5sgZFdJ+AYzT6yNmJenvIYQBgIGwfwz08sL8zoL7yq2BA==", + "license": "MIT", + "dependencies": { + "hasown": "^2.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-expression": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-expression/-/is-expression-4.0.0.tgz", + "integrity": "sha512-zMIXX63sxzG3XrkHkrAPvm/OVZVSCPNkwMHU8oTX7/U3AL78I0QXCEICXUM13BIa8TYGZ68PiTKfQz3yaTNr4A==", + "license": "MIT", + "dependencies": { + "acorn": "^7.1.1", + "object-assign": "^4.1.1" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "license": "MIT", + "optional": true, + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-promise": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.2.2.tgz", + "integrity": "sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ==", + "license": "MIT" + }, + "node_modules/is-regex": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.2.1.tgz", + "integrity": "sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "gopd": "^1.2.0", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/js-stringify": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/js-stringify/-/js-stringify-1.0.2.tgz", + "integrity": "sha512-rtS5ATOo2Q5k1G+DADISilDA6lv79zIiwFd6CcjuIxGKLFm5C+RLImRscVap9k55i+MOZwgliw+NejvkLuGD5g==", + "license": "MIT" + }, + "node_modules/jstransformer": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/jstransformer/-/jstransformer-1.0.0.tgz", + "integrity": "sha512-C9YK3Rf8q6VAPDCCU9fnqo3mAfOH6vUGnMcP4AQAYIEpWtfGLpwOTmZ+igtdK5y+VvI2n3CyYSzy4Qh34eq24A==", + "license": "MIT", + "dependencies": { + "is-promise": "^2.0.0", + "promise": "^7.0.1" + } + }, + "node_modules/keygrip": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/keygrip/-/keygrip-1.0.3.tgz", + "integrity": "sha512-/PpesirAIfaklxUzp4Yb7xBper9MwP6hNRA6BGGUFCgbJ+BM5CKBtsoxinNXkLHAr+GXS1/lSlF2rP7cv5Fl+g==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/luxon": { + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/luxon/-/luxon-3.7.2.tgz", + "integrity": "sha512-vtEhXh/gNjI9Yg1u4jX/0YVPMvxzHuGgCm6tC5kZyb08yjGWGnqAjGJvcXbqQR2P3MyMEFnRbpcdFS6PBcLqew==", + "license": "MIT", + "engines": { + "node": ">=12" + } + }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/merge-descriptors": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz", + "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "license": "MIT", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/morgan": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/morgan/-/morgan-1.11.0.tgz", + "integrity": "sha512-zSkVu3t18r39pw4ixfBKvfZi3y2UOqr7d4WYwcj3m8nXpEQK4rPO6GLzs/CExoRgmX3y9EjmmcXqv6jq0SK46g==", + "license": "MIT", + "dependencies": { + "basic-auth": "~2.0.1", + "debug": "2.6.9", + "depd": "~2.0.0", + "on-finished": "~2.4.1", + "on-headers": "~1.1.0" + }, + "engines": { + "node": ">= 0.8.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "license": "MIT" + }, + "node_modules/negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/node-addon-api": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-7.1.1.tgz", + "integrity": "sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==", + "license": "MIT", + "optional": true + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-inspect": { + "version": "1.13.4", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", + "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "license": "MIT", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/on-headers": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.1.0.tgz", + "integrity": "sha512-737ZY3yNnXy37FHkQxPzt4UZ2UWPWiCZWLvFZ4fu5cueciegX0zGPnrlY6bwRg4FdQOe9YU8MkmJwGhoMybl8A==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "license": "MIT" + }, + "node_modules/path-to-regexp": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.13.tgz", + "integrity": "sha512-A/AGNMFN3c8bOlvV9RreMdrv7jsmF9XIfDeCd87+I8RNg6s78BhJxMu69NEMHBSJFxKidViTEdruRwEk/WIKqA==", + "license": "MIT" + }, + "node_modules/picomatch": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.5.tgz", + "integrity": "sha512-RvwwcruNjI1ncT5xRakeyS9Lf8lcItv34KD+aif+VH9kduAyfYBipGh12274xtenIPZ119/R9BdTBa8gAwSh0A==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/promise": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/promise/-/promise-7.3.1.tgz", + "integrity": "sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==", + "license": "MIT", + "dependencies": { + "asap": "~2.0.3" + } + }, + "node_modules/proxy-addr": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "license": "MIT", + "dependencies": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/proxy-from-env": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-2.1.0.tgz", + "integrity": "sha512-cJ+oHTW1VAEa8cJslgmUZrc+sjRKgAKl3Zyse6+PV38hZe/V6Z14TbCuXcan9F9ghlz4QrFr2c92TNF82UkYHA==", + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "node_modules/pug": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/pug/-/pug-3.0.4.tgz", + "integrity": "sha512-kFfq5mMzrS7+wrl5pLJzZEzemx34OQ0w4SARfhy/3yxTlhbstsudDwJzhf1hP02yHzbjoVMSXUj/Sz6RNfMyXg==", + "license": "MIT", + "dependencies": { + "pug-code-gen": "^3.0.4", + "pug-filters": "^4.0.0", + "pug-lexer": "^5.0.1", + "pug-linker": "^4.0.0", + "pug-load": "^3.0.0", + "pug-parser": "^6.0.0", + "pug-runtime": "^3.0.1", + "pug-strip-comments": "^2.0.0" + } + }, + "node_modules/pug-attrs": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pug-attrs/-/pug-attrs-3.0.0.tgz", + "integrity": "sha512-azINV9dUtzPMFQktvTXciNAfAuVh/L/JCl0vtPCwvOA21uZrC08K/UnmrL+SXGEVc1FwzjW62+xw5S/uaLj6cA==", + "license": "MIT", + "dependencies": { + "constantinople": "^4.0.1", + "js-stringify": "^1.0.2", + "pug-runtime": "^3.0.0" + } + }, + "node_modules/pug-code-gen": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/pug-code-gen/-/pug-code-gen-3.0.4.tgz", + "integrity": "sha512-6okWYIKdasTyXICyEtvobmTZAVX57JkzgzIi4iRJlin8kmhG+Xry2dsus+Mun/nGCn6F2U49haHI5mkELXB14g==", + "license": "MIT", + "dependencies": { + "constantinople": "^4.0.1", + "doctypes": "^1.1.0", + "js-stringify": "^1.0.2", + "pug-attrs": "^3.0.0", + "pug-error": "^2.1.0", + "pug-runtime": "^3.0.1", + "void-elements": "^3.1.0", + "with": "^7.0.0" + } + }, + "node_modules/pug-error": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/pug-error/-/pug-error-2.1.0.tgz", + "integrity": "sha512-lv7sU9e5Jk8IeUheHata6/UThZ7RK2jnaaNztxfPYUY+VxZyk/ePVaNZ/vwmH8WqGvDz3LrNYt/+gA55NDg6Pg==", + "license": "MIT" + }, + "node_modules/pug-filters": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/pug-filters/-/pug-filters-4.0.0.tgz", + "integrity": "sha512-yeNFtq5Yxmfz0f9z2rMXGw/8/4i1cCFecw/Q7+D0V2DdtII5UvqE12VaZ2AY7ri6o5RNXiweGH79OCq+2RQU4A==", + "license": "MIT", + "dependencies": { + "constantinople": "^4.0.1", + "jstransformer": "1.0.0", + "pug-error": "^2.0.0", + "pug-walk": "^2.0.0", + "resolve": "^1.15.1" + } + }, + "node_modules/pug-lexer": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/pug-lexer/-/pug-lexer-5.0.1.tgz", + "integrity": "sha512-0I6C62+keXlZPZkOJeVam9aBLVP2EnbeDw3An+k0/QlqdwH6rv8284nko14Na7c0TtqtogfWXcRoFE4O4Ff20w==", + "license": "MIT", + "dependencies": { + "character-parser": "^2.2.0", + "is-expression": "^4.0.0", + "pug-error": "^2.0.0" + } + }, + "node_modules/pug-linker": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/pug-linker/-/pug-linker-4.0.0.tgz", + "integrity": "sha512-gjD1yzp0yxbQqnzBAdlhbgoJL5qIFJw78juN1NpTLt/mfPJ5VgC4BvkoD3G23qKzJtIIXBbcCt6FioLSFLOHdw==", + "license": "MIT", + "dependencies": { + "pug-error": "^2.0.0", + "pug-walk": "^2.0.0" + } + }, + "node_modules/pug-load": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pug-load/-/pug-load-3.0.0.tgz", + "integrity": "sha512-OCjTEnhLWZBvS4zni/WUMjH2YSUosnsmjGBB1An7CsKQarYSWQ0GCVyd4eQPMFJqZ8w9xgs01QdiZXKVjk92EQ==", + "license": "MIT", + "dependencies": { + "object-assign": "^4.1.1", + "pug-walk": "^2.0.0" + } + }, + "node_modules/pug-parser": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/pug-parser/-/pug-parser-6.0.0.tgz", + "integrity": "sha512-ukiYM/9cH6Cml+AOl5kETtM9NR3WulyVP2y4HOU45DyMim1IeP/OOiyEWRr6qk5I5klpsBnbuHpwKmTx6WURnw==", + "license": "MIT", + "dependencies": { + "pug-error": "^2.0.0", + "token-stream": "1.0.0" + } + }, + "node_modules/pug-runtime": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/pug-runtime/-/pug-runtime-3.0.1.tgz", + "integrity": "sha512-L50zbvrQ35TkpHwv0G6aLSuueDRwc/97XdY8kL3tOT0FmhgG7UypU3VztfV/LATAvmUfYi4wNxSajhSAeNN+Kg==", + "license": "MIT" + }, + "node_modules/pug-strip-comments": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/pug-strip-comments/-/pug-strip-comments-2.0.0.tgz", + "integrity": "sha512-zo8DsDpH7eTkPHCXFeAk1xZXJbyoTfdPlNR0bK7rpOMuhBYb0f5qUVCO1xlsitYd3w5FQTK7zpNVKb3rZoUrrQ==", + "license": "MIT", + "dependencies": { + "pug-error": "^2.0.0" + } + }, + "node_modules/pug-walk": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/pug-walk/-/pug-walk-2.0.0.tgz", + "integrity": "sha512-yYELe9Q5q9IQhuvqsZNwA5hfPkMJ8u92bQLIMcsMxf/VADjNtEYptU+inlufAFYcWdHlwNfZOEnOOQrZrcyJCQ==", + "license": "MIT" + }, + "node_modules/qs": { + "version": "6.15.3", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.15.3.tgz", + "integrity": "sha512-O9gl3zCl5h5blw1KGUzQKhA5oUXSl8rwUIM5o0S3nCXMliSvy5Dzx7/DJcI+SwgICv+IneSZwhBh1oSyEHA71A==", + "license": "BSD-3-Clause", + "dependencies": { + "es-define-property": "^1.0.1", + "side-channel": "^1.1.1" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/raw-body": { + "version": "2.5.3", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.3.tgz", + "integrity": "sha512-s4VSOf6yN0rvbRZGxs8Om5CWj6seneMwK3oDb4lWDH0UPhWcxwOWw5+qk24bxq87szX1ydrwylIOp2uG1ojUpA==", + "license": "MIT", + "dependencies": { + "bytes": "~3.1.2", + "http-errors": "~2.0.1", + "iconv-lite": "~0.4.24", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/raw-body/node_modules/http-errors": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.1.tgz", + "integrity": "sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==", + "license": "MIT", + "dependencies": { + "depd": "~2.0.0", + "inherits": "~2.0.4", + "setprototypeof": "~1.2.0", + "statuses": "~2.0.2", + "toidentifier": "~1.0.1" + }, + "engines": { + "node": ">= 0.8" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/raw-body/node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "license": "ISC" + }, + "node_modules/readdirp": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-5.0.0.tgz", + "integrity": "sha512-9u/XQ1pvrQtYyMpZe7DXKv2p5CNvyVwzUB6uhLAnQwHMSgKMBR62lc7AHljaeteeHXn11XTAaLLUVZYVZyuRBQ==", + "license": "MIT", + "engines": { + "node": ">= 20.19.0" + }, + "funding": { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/resolve": { + "version": "1.22.12", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.12.tgz", + "integrity": "sha512-TyeJ1zif53BPfHootBGwPRYT1RUt6oGWsaQr8UyZW/eAm9bKoijtvruSDEmZHm92CwS9nj7/fWttqPCgzep8CA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "is-core-module": "^2.16.1", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "license": "MIT" + }, + "node_modules/sass": { + "version": "1.102.0", + "resolved": "https://registry.npmjs.org/sass/-/sass-1.102.0.tgz", + "integrity": "sha512-NSOyTnaQF7rTAEOtI2fwb386vL+akyiQLBZu8Na7hXCb+umJy0GAqlcMIaqACZ6Z1VgTBS4K9PG6B3IdjHGJsw==", + "license": "MIT", + "dependencies": { + "chokidar": "^5.0.0", + "immutable": "^5.1.5", + "source-map-js": ">=0.6.2 <2.0.0" + }, + "bin": { + "sass": "sass.js" + }, + "engines": { + "node": ">=20.19.0" + }, + "optionalDependencies": { + "@parcel/watcher": "^2.4.1" + } + }, + "node_modules/send": { + "version": "0.19.2", + "resolved": "https://registry.npmjs.org/send/-/send-0.19.2.tgz", + "integrity": "sha512-VMbMxbDeehAxpOtWJXlcUS5E8iXh6QmN+BkRX1GARS3wRaXEEgzCcB10gTQazO42tpNIya8xIyNx8fll1OFPrg==", + "license": "MIT", + "dependencies": { + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "~0.5.2", + "http-errors": "~2.0.1", + "mime": "1.6.0", + "ms": "2.1.3", + "on-finished": "~2.4.1", + "range-parser": "~1.2.1", + "statuses": "~2.0.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/send/node_modules/http-errors": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.1.tgz", + "integrity": "sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==", + "license": "MIT", + "dependencies": { + "depd": "~2.0.0", + "inherits": "~2.0.4", + "setprototypeof": "~1.2.0", + "statuses": "~2.0.2", + "toidentifier": "~1.0.1" + }, + "engines": { + "node": ">= 0.8" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/send/node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "license": "ISC" + }, + "node_modules/send/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" + }, + "node_modules/serve-static": { + "version": "1.16.3", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.3.tgz", + "integrity": "sha512-x0RTqQel6g5SY7Lg6ZreMmsOzncHFU7nhnRWkKgWuMTu5NN0DR5oruckMqRvacAN9d5w6ARnRBXl9xhDCgfMeA==", + "license": "MIT", + "dependencies": { + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "~0.19.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", + "license": "ISC" + }, + "node_modules/side-channel": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.1.tgz", + "integrity": "sha512-6x6dK6zJdpTzF4sQeNYxwtvBzf6Eg4GtlesS94HOvTudUeyK2WXAaIfmDgsyslYrRBeFIlsi54AYsFGUuhmvrQ==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.4", + "side-channel-list": "^1.0.1", + "side-channel-map": "^1.0.1", + "side-channel-weakmap": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-list": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.1.tgz", + "integrity": "sha512-mjn/0bi/oUURjc5Xl7IaWi/OJJJumuoJFQJfDDyO46+hBWsfaVM65TBHq2eoZBhzl9EchxOijpkbRC8SVBQU0w==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", + "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-weakmap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", + "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3", + "side-channel-map": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/spin.js": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/spin.js/-/spin.js-4.1.2.tgz", + "integrity": "sha512-ua/yEpxEwyEUWs57tMQYdik/KJ12sQRyMXjSlK/Ai927aEUDVY3FXUi4ml4VvlLCTQNIjC6tHyjSLBrJzFAqMA==", + "license": "MIT" + }, + "node_modules/statuses": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz", + "integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "license": "MIT", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/token-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/token-stream/-/token-stream-1.0.0.tgz", + "integrity": "sha512-VSsyNPPW74RpHwR8Fc21uubwHY7wMDeJLys2IX5zJNih+OnAnaifKHo+1LHT7DAdloQ7apeaaWg8l7qnf/TnEg==", + "license": "MIT" + }, + "node_modules/type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "license": "MIT", + "dependencies": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", + "license": "MIT", + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/void-elements": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/void-elements/-/void-elements-3.1.0.tgz", + "integrity": "sha512-Dhxzh5HZuiHQhbvTW9AMetFfBHDMYpo23Uo9btPXgdYP+3T5S+p+jgNy7spra+veYhBP2dCSgxR/i2Y02h5/6w==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/with": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/with/-/with-7.0.2.tgz", + "integrity": "sha512-RNGKj82nUPg3g5ygxkQl0R937xLyho1J24ItRCBTr/m1YnZkzJy1hUiHUJrc/VlsDQzsCnInEGSg3bci0Lmd4w==", + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.9.6", + "@babel/types": "^7.9.6", + "assert-never": "^1.2.1", + "babel-walk": "3.0.0-canary-5" + }, + "engines": { + "node": ">= 10.0.0" + } + } + } +} diff --git a/noise/package.json b/noise/package.json new file mode 100644 index 0000000..fd76aa9 --- /dev/null +++ b/noise/package.json @@ -0,0 +1,31 @@ +{ + "name": "laerm-web-sensorapi", + "version": "3.3.1", + "date": "2026-06-30 18:00 UTC", + "private": true, + "scripts": { + "start": "node bin/www.js >>/var/log/noise.log 2>&1" + }, + "type": "module", + "bin": { + "www": "./bin/www.js" + }, + "dependencies": { + "axios": "^1.3.4", + "cookie-parser": "~1.4.4", + "cors": "^2.8.5", + "debug": "~2.6.9", + "dotenv": "^17.2.3", + "express": "^4.18.2", + "http-errors": "~1.6.3", + "i18next": "^22.4.14", + "i18next-express-middleware": "^2.0.0", + "i18next-http-middleware": "^3.3.0", + "i18next-fs-backend": "^2.0.0", + "luxon": "^3.3.0", + "morgan": "^1.10.1", + "pug": "^3.0.2", + "sass": "^1.58.3", + "spin.js": "^4.1.2" + } +} diff --git a/noise/public/images/favicon.ico b/noise/public/images/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..a5b85b032e9620693528965d6b916ee4a2436c76 GIT binary patch literal 1150 zcmZ`&TS!z<6g_tyjpOu~aURY~9fg>|si^29D8diRX8PzwNgx<~L?|If82v@jL+qnI zB2fJ3E1`#k5RD>9kr{!b&X}W?4w)roX+?2Eht=Nq>To5xmvzp$d+)W+x%;dwgha2^ zDrgLdQwAYiLWmH7Ok`2*GzmezJc|nDTQjuHLjaH>X#|T>IOlkS*s28L3|_O1eH_#F z9U7(($EG0aKEfP+hnjUG7}F<^5kr6$Y-3+|0yTA?U}g?K)gK@l=)2@C8qHm4*>tM| zqW{kdu99ak15Hg&VDbvfnr#iW0}At z)p;B-%auE7Zm)-OFuYiE<{G5FACO-Cgym8zyoH4nqx${%F2(N{Ma(#YIQ!ijw!pn< zoBEHt_QLpZ2)3%zu+v!$kA`879wpyWOn5Wa)?bA&N%u>Tdgq~kl7>D;;JJGmx@TYD z*nI%5?PZEx*E6GunWXxBg^{%3B5f#j;(BW_umD5HC=BfhNPM4KAFrvdPU04muKv*r z`Ascdu3=?}_pzi) z<}g=Wh6s&T?g6 zMK7coK8Ld`LT8u-$8c;`ztjUt|4OvF9MHC(a_br7L5N z%VQj)?H{FyXi)lhk@|NE!9vocGr17U>79$`yqu3al8Z66Mcz~YW~hIu*O#BPNr)c3 R5EmpB%l7}x%W=$M?q7q2I0pa# literal 0 HcmV?d00001 diff --git a/noise/public/javascripts/chart_utilities.js b/noise/public/javascripts/chart_utilities.js new file mode 100644 index 0000000..aa4ce2b --- /dev/null +++ b/noise/public/javascripts/chart_utilities.js @@ -0,0 +1,276 @@ +// Utility routine for plotting the data + +import {DateTime} from './luxon.min.js' +export const colors = {'eq': '#0000FF', 'max': '#FF0000', 'min': '#008000', 'peaks': '#DAA520'}; + +// Defaults für die Mittelwertbildungen +let txtMeldung = false; // falls keine Daten da sind, Text melden +const avgTime = 30; // defaul average time für particulate matter +let doUpdate = true; // update every 5 min +let optSidsArray = []; // Arrray der letzten 5 Einträge +let nbrofdaysforavg = 8; // Stundenmittel Anzahl Tagte (default = 5) +let nbrofdaysfordaynight = 30; // use 30 days or day/night graphic +let stucols = 1; // Anzeige nur Balken (StundenMittel) +let activeTab = 'maptab'; // active TAB ID + +export const noise_ymin = 30; // lowest value on y-axis for noise +export const noise_ymax = 120; // highest value on y-axis for noise +export let peaklim = 70; // threshold for peak count + +export const url = '/srv' + +export function createGlobObtions() { + // Options, die für alle Plots identisch sind + let globObject = { + chart: { + accessibility: { + enabled: false + }, + height: 600, +// width: 1000, + spacingRight: 20, + spacingLeft: 20, + spacingTop: 25, + backgroundColor: { + linearGradient: [0, 400, 0, 0], + stops: [ + [0, '#eee'],//[0, '#ACD0AA'], //[0, '#A18D99'], // [0, '#886A8B'], // [0, '#F2D0B5'], + [1, '#fff'] + ] + }, + type: 'line', + borderWidth: '2', + useHTML: true, + events: { + selection: function (event) { + if (event.xAxis) { + doUpdate = false; + } else { + doUpdate = true; + } + } + } + }, + title: { +// text: 'Feinstaub über 1 Tag', + align: 'left', + style: {'fontSize': '25px'}, + useHTML: true, + }, + subtitle: { +// text: 'Gemessene Werte und ' + avgTime + 'min-gleitende Mittelwerte', + align: 'left', + }, + tooltip: { + valueDecimals: 1, + backgroundColor: 0, + borderWidth: 0, + borderRadius: 0, + useHTML: true, + }, + labels: { + useHTML: true + }, + xAxis: { + type: 'datetime', + title: { + text: 'date/time', + }, + gridLineWidth: 2, + labels: { + formatter: function () { + let v = this.axis.defaultLabelFormatter.call(this); + if (v.indexOf(':') == -1) { + return '' + v + ''; + } else { + return v; + } + } + }, + }, + legend: { + enabled: true, + layout: 'horizontal', +// verticalAlign: 'top', + borderWidth: 1, + align: 'center', + }, + plotOptions: { + series: { + animation: false, + turboThreshold: 0, + marker: { + enabled: false, + }, + }, + } + }; + return globObject; +} + +export function calcWeekends(data, isyear) { + let weekend = []; + let oldDay = 8; + for (let i = 0; i < data.length; i++) { + let mom = moment(data[i].date); + if (isyear) { + mom = moment(data[i]._id) + } + let day = mom.day(); + let st = mom.startOf('day'); + if (day != oldDay) { + if (day == 6) { + weekend.push({ + color: 'rgba(169,235,158,0.4)', + from: st.valueOf(), + to: st.add(1, 'days').valueOf(), + zIndex: 0 + }) + } else if (day == 0) { + weekend.push({ + color: 'rgba(169,235,158,0.4)', + from: st.valueOf(), + to: st.add(1, 'days').valueOf(), + zIndex: 0 + }) + } + oldDay = day; + } + } + return weekend; +} + +export function calcDays(data, isyear) { + let days = []; + if (data.length == 0) { + return days + } + let oldday = moment(data[0].date).day(); + if (isyear) { + oldday = moment(data[0]._id).day(); + } + for (let i = 0; i < data.length; i++) { + let m = moment(data[i].date); + if (isyear) { + m = moment(data[i]._id); + } + let tag = m.day() + if (tag != oldday) { + m.startOf('day'); + days.push({color: 'lightgray', value: m.valueOf(), width: 1, zIndex: 2}); + oldday = tag; + } + } + return days; +}; + +export async function addSensorID2chart(chart, sensor, width) { + let indoor = sensor.indoor || false + let addr = await addAddress(sensor.sid) + chart.renderer.label( + `Sensor:  ${sensor.sid} ${indoor ? ' (indoor)' : ''}

${addr.street}
${addr.plz} ${addr.city}`, + width / 2 - 150, 70) + .css({ + fontSize: '14pt', + 'font-weight': 'bold', + }) + .attr({ + zIndex: 3, + }).add(); +} + +export const showError = (err) => { + const dialog = document.getElementById('dialogError') + const body = dialog.querySelector('.dialog-body') + body.innerHTML = err + dialog.showModal() +} + +export const showReset = () => { + const dialog = document.getElementById('dialogReset') + dialog.showModal() +} + +// Setup dialog close buttons +document.addEventListener('DOMContentLoaded', () => { + const errorClose = document.querySelector('#dialogError .dialog-close') + if (errorClose) { + errorClose.addEventListener('click', () => { + document.getElementById('dialogError').close() + }) + } + + const resetClose = document.querySelector('#dialogReset .dialog-close') + if (resetClose) { + resetClose.addEventListener('click', () => { + document.getElementById('dialogReset').close() + }) + } + + const resetOk = document.querySelector('#btnResetOk') + if (resetOk) { + resetOk.addEventListener('click', () => { + document.getElementById('dialogReset').close() + }) + } +}) + +// remove the taps (if shownig the map) +export const removeTabs = () => { + document.querySelector('#navi').style.display = 'none' +} + +// show thw tabs again +export const showTabs = () => { + if (activeTab !== 'maptab') { + document.querySelector('#navi').style.display = 'block' + } +} + +export const setCurrentTab = (tab) => { + activeTab = tab +} + +export const getCurrentTab = () => { + return activeTab +} + +export const fetchfromserver = async (url) => { + const ret = await fetch(encodeURI(url)) + .catch(e => { + showError(e) + }); +// return await ret.json() + let x = await ret.json() + return x +} + +export const addAddress = async (sid) => { + let url = `/srv/getaddress?sensorid=${sid}` + let erg = await fetchfromserver(url) + if (!erg.err) { + return erg.address + } else { + return "no address" + } +} + +export const cityCoords = async (city) => { + let url = `/srv/getcitycoords?city=${city}` + let erg = await fetchfromserver(url) + if (!erg.err) { + return erg.coords + } else { + return "no coordinates" + } +} + +// table to distribute the different charts +export const ttIndex = Object.freeze({ + map: 0, + live: 1, + havg: 2, + davg: 3, + daynight: 4, + lden: 5 +}) diff --git a/noise/public/javascripts/checklang.js b/noise/public/javascripts/checklang.js new file mode 100644 index 0000000..7dbb47c --- /dev/null +++ b/noise/public/javascripts/checklang.js @@ -0,0 +1,15 @@ +// set correct language (will be called by chglang.pug) +let currentLang +const navLang = navigator.language.slice(0,2) +const selectedLang = localStorage.getItem('curlang') +if (!selectedLang) { + currentLang = navLang +} else { + currentLang = selectedLang +} +if (sensorid !== '') { + window.location.href = `/${sensorid}?lng=${currentLang}` +} else { + window.location.href = `?lng=${currentLang}` +} + diff --git a/noise/public/javascripts/datetime.js b/noise/public/javascripts/datetime.js new file mode 100644 index 0000000..086ef84 --- /dev/null +++ b/noise/public/javascripts/datetime.js @@ -0,0 +1,30 @@ +// all date and time functions +import { DateTime } from './luxon.min.js' +import {loadAll} from './showcharts.js' +import {getCurrentTab} from "./chart_utilities.js"; + + +// Show date and time (every minute) +// Will be called every second +export const showDate = (sofort, params) => { + let d = DateTime.now() + if(sofort || d.second === 0) { + document.querySelector('#h1datum').innerHTML = d.toFormat('yyyy-MM-dd HH:mm') + } + if (((d.minute % params.refreshRate) == 0) && (d.second == 15)) { // alle ganzen refreshRate Minuten, 15sec danach + let start = 1 + console.log(params.refreshRate, 'Minuten um, Grafik wird erneuert'); + let ct = getCurrentTab() + if (ct !== 'maptab') { + loadAll(params, start) + } + } +} + +export const formatJSDate = (d) => { + return DateTime.fromJSDate(d).toFormat('yyyy-LL-dd HH:mm:ss') +} + +export const formatISODate = (d) => { + return DateTime.fromISO(d).toFormat('yyyy-LL-dd HH:mm:ss') +} diff --git a/noise/public/javascripts/global.js b/noise/public/javascripts/global.js new file mode 100644 index 0000000..d7edd60 --- /dev/null +++ b/noise/public/javascripts/global.js @@ -0,0 +1,303 @@ +// Client side javascript +"use strict" + +import * as map from './map.js' +import * as dt from './datetime.js' +import {loadAll, showChart, setNoUTC, tabtable} from './showcharts.js' +import { DateTime } from './luxon.min.js' +import {ttIndex, setCurrentTab, getCurrentTab, showError, fetchfromserver, cityCoords} from "./chart_utilities.js"; +import * as spin from './spinner.js' + + +(async () => { + + // global variables + const params = { // set defaults + center: {name: 'Stuttgart', coords: [48.778, 9.180]}, + zoom: 10, + span: 1, + peak: 70, + weeks: 4, + datetime: '', + seldate: '', + refreshRate: 5, + sid: -1 + } + + let minDate = new Date(2023, 0, 1) + + const setting = [ + { + typ: 'maptab', + show: ['ccity', 'odth'], + val: ['centercity', 'olderthan'], + param: [["center","name"], 'weeks'] + }, + { + typ: 'livetab', + show: ['stday', 'nbday'], + val: ['startday', 'nbrofdays'], + param: ['seldate', 'span'] + },{ + typ: 'houravgtab', + show: ['stday','pklim'], + val: ['startday', 'peaklim'], + param: ['seldate', 'peak'] + },{ + typ: 'dayavgtab', + show: ['stday','pklim'], + val: ['startday', 'peaklim'], + param: ['seldate', 'peak'] + },{ + typ: 'daynighttab', + show: ['stday'], + val: ['startday'], + param: ['seldate'] + },{ + typ: 'ldentab', + show: ['stday'], + val: ['startday'], + param: ['seldate'] + } + ] + // END global variables + + // localStorage.clear() + + + // Check new map center + const checkNewCenter = (oldC, newC) => { + if((oldC[0] !== newC[0]) || (oldC[1] !== newC[1])) { + map.setNewCenter(newC) + } + } + + // Register events + // Button 'My Location' pressed + document.addEventListener('DOMContentLoaded', () => { + const btnMyLocation = document.querySelector('#btnMyLocation'); + if (btnMyLocation) { + btnMyLocation.addEventListener('click', () => { + map.goToMyLocation(); + }); + } + }); + + // Button 'Save' pressed + document.querySelector('#btnSave').addEventListener('click', async () => { + let curtab = getCurrentTab() + for(let i = 0; i < setting.length; i++) { + if(setting[i].typ === getCurrentTab()) { + for(let j = 0; j < setting[i].show.length; j++) { + let elem = document.getElementById(setting[i].val[j]) + let val = elem.value + if(elem.type === 'checkbox') { + val = elem.checked + } + let x = setting[i].param[j] + console.log('x: ', x) + if ( Array.isArray(x)) { + params[setting[i].param[j][0]][setting[i].param[j][1]] = val + } else { + params[setting[i].param[j]] = val + } + } + break + } + } + if (curtab !== 'maptab') { + let starttime + if ((params.seldate === 'today') || (params.seldate === 'heute') || (DateTime.now().toFormat('yyyy-MM-dd') === params.seldate)) { + starttime = '' + } else { + starttime = DateTime.fromFormat(params.seldate, 'yyyy-MM-dd').toUTC().toISO() + } + params.datetime = starttime + } else { + const oldCoords = params.center.coords + params.center.coords = await cityCoords(params.center.name) + checkNewCenter(oldCoords, params.center.coords) + localStorage.setItem('centercity',JSON.stringify(params.center)) + } + let newlng = document.querySelector('#sellan input:checked').id + let oldlng = localStorage.getItem('curlang') + localStorage.setItem('curlang', newlng) + if(newlng !== oldlng) { + location.reload() + } + document.getElementById('dialogSettings').close() + spin.spinner.spin(spin.spindiv) + await loadAll(params,0, curtab) + spin.spinner.stop() + // ToDo: + // Load ALL incl. MAP und LIVE hier, d.h. an loadAll einen zusätzlichen Parameter übergeben + // if(params.sid !== undefined) { + // await loadAll(params) + // } + }) + + // Btn 'Settings' pressed + document.querySelector('#btnSet').addEventListener('click', () => { + const curtab = getCurrentTab() + const dialog = document.getElementById('dialogSettings') + + // Set max and min dates for date input + const today = new Date().toISOString().split('T')[0] + const minDateStr = minDate.toISOString().split('T')[0] + const startdayInput = document.getElementById('startday') + startdayInput.max = today + startdayInput.min = minDateStr + + // Convert seldate format if needed + let seldate = params.seldate + if (seldate === 'today' || seldate === 'heute') { + seldate = today + } + + startdayInput.value = seldate + document.getElementById('nbrofdays').value = params.span + document.getElementById('peaklim').value = params.peak + document.getElementById('olderthan').value = params.weeks + const centercity = JSON.parse(localStorage.getItem('centercity')) + document.getElementById('centercity').value = centercity.name + + // select different infos depending on the selected tab + // first clear all + document.querySelector('#ccity').style.display = 'none' + document.querySelector('#stday').style.display = 'none' + document.querySelector('#nbday').style.display = 'none' + document.querySelector('#pklim').style.display = 'none' + document.querySelector('#odth').style.display = 'none' + for(let i = 0; i < setting.length; i++) { + if(setting[i].typ === curtab) { + for(let j = 0; j < setting[i].show.length; j++) { + document.querySelector(`#${setting[i].show[j]}`).style.display = 'inline' + } + break + } + } + dialog.showModal() + }) + + // Close button for settings dialog + document.querySelector('#dialogSettings .dialog-close').addEventListener('click', () => { + document.getElementById('dialogSettings').close() + }) + + // Close button (secondary button) + document.querySelector('#btnClose').addEventListener('click', () => { + document.getElementById('dialogSettings').close() + }) + + const getSensorType = async (sid) => { + let url = `/srv/getoneproperty?sensorid=${sid}` + const data = await fetchfromserver(url) + return data.props + } + + // main function: + // show the map if called w/o any parameter + // if called with a sensor-ID, show the live chart for this sensor + async function main() { + setNoUTC() // no UTC for HighCharts + // set correct language + let currentLang = localStorage.getItem('curlang') + if ((currentLang === null) || (currentLang === '')) { + currentLang = 'de' + localStorage.setItem('curlang', currentLang) + } + let centercity + try { + centercity = JSON.parse(localStorage.getItem('centercity')) + } catch (e) { + centercity = params.center + } + if((centercity === null) || (centercity.name === '')) { + centercity = params.center + } + localStorage.setItem('centercity', JSON.stringify(centercity)) + params.center = centercity + if(currentLang === 'en') { + document.querySelector('#en').checked = true + params.seldate = 'today' + } else { + document.querySelector('#de').checked = true + params.seldate = 'heute' + } + console.log(currentLang) + if (parseInt(sysparams.csid) !== -1) { + history.pushState({}, '', `/${sysparams.csid}`) + } else { + history.pushState({}, '', '/') + } + + dt.showDate(true, params) + // and show date/time every minute + setInterval(() => dt.showDate(false, params), 1000) + + // initialise tabs + const triggerTabList = [].slice.call(document.querySelectorAll('.tab-button')) + triggerTabList.forEach(function (triggerEl) { + triggerEl.addEventListener('click', function (event) { + event.preventDefault() + + // Remove active from all tabs + triggerTabList.forEach(tab => tab.classList.remove('active')) + document.querySelectorAll('.tab-pane').forEach(pane => pane.classList.remove('active')) + + // Add active to clicked tab + triggerEl.classList.add('active') + const targetId = triggerEl.getAttribute('data-target') + document.getElementById(targetId).classList.add('active') + + let newtab = event.currentTarget.id + setCurrentTab(newtab) + let tab = tabtable.find(tab => tab.id === newtab) + if (document.querySelector(`#${tab.id}err`).innerHTML !== '') { // if there is an error message, clear it + showError(document.querySelector(`#${tab.id}err`).innerHTML) + } + if (newtab === 'maptab') { + map.showMap(params) + } + }) + }) + const csid = parseInt(sysparams.csid) + if(csid !== -1) { + spin.spinner.spin(spin.spindiv) + // check, if sid is of right type (noise) + const props = await getSensorType(csid) + if (props.type !== 'noise') { + // wrong sensor type + spin.spinner.stop() + showError('Sensor ID ' + csid + ' is not of type noise') + return + } + params.center.coords = [props.location[0].loc.coordinates[1], props.location[0].loc.coordinates[0]] + params.sid = csid + let t = triggerTabList[1] + + // Switch to live tab + triggerTabList.forEach(tab => tab.classList.remove('active')) + document.querySelectorAll('.tab-pane').forEach(pane => pane.classList.remove('active')) + t.classList.add('active') + document.getElementById('t_live').classList.add('active') + + setCurrentTab('livetab') + let err = await showChart(params, ttIndex.live) + spin.spinner.stop() + if (err.error) { + let errtxt = document.querySelector(`#${tabtable[ttIndex.live].id}err`).innerHTML + if (errtxt !== '') { + showError(errtxt) + } + } + await loadAll(params) + } else { + // show the map + map.showMap(params) + } + } + + main().catch(console.error) + +})() \ No newline at end of file diff --git a/noise/public/javascripts/leaflet.markercluster.js b/noise/public/javascripts/leaflet.markercluster.js new file mode 100644 index 0000000..67c52dc --- /dev/null +++ b/noise/public/javascripts/leaflet.markercluster.js @@ -0,0 +1,3 @@ +!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t((e.Leaflet=e.Leaflet||{},e.Leaflet.markercluster=e.Leaflet.markercluster||{}))}(this,function(e){"use strict";var t=L.MarkerClusterGroup=L.FeatureGroup.extend({options:{maxClusterRadius:80,iconCreateFunction:null,clusterPane:L.Marker.prototype.options.pane,spiderfyOnMaxZoom:!0,showCoverageOnHover:!0,zoomToBoundsOnClick:!0,singleMarkerMode:!1,disableClusteringAtZoom:null,removeOutsideVisibleBounds:!0,animate:!0,animateAddingMarkers:!1,spiderfyDistanceMultiplier:1,spiderLegPolylineOptions:{weight:1.5,color:"#222",opacity:.5},chunkedLoading:!1,chunkInterval:200,chunkDelay:50,chunkProgress:null,polygonOptions:{}},initialize:function(e){L.Util.setOptions(this,e),this.options.iconCreateFunction||(this.options.iconCreateFunction=this._defaultIconCreateFunction),this._featureGroup=L.featureGroup(),this._featureGroup.addEventParent(this),this._nonPointGroup=L.featureGroup(),this._nonPointGroup.addEventParent(this),this._inZoomAnimation=0,this._needsClustering=[],this._needsRemoving=[],this._currentShownBounds=null,this._queue=[],this._childMarkerEventHandlers={dragstart:this._childMarkerDragStart,move:this._childMarkerMoved,dragend:this._childMarkerDragEnd};var t=L.DomUtil.TRANSITION&&this.options.animate;L.extend(this,t?this._withAnimation:this._noAnimation),this._markerCluster=t?L.MarkerCluster:L.MarkerClusterNonAnimated},addLayer:function(e){if(e instanceof L.LayerGroup)return this.addLayers([e]);if(!e.getLatLng)return this._nonPointGroup.addLayer(e),this.fire("layeradd",{layer:e}),this;if(!this._map)return this._needsClustering.push(e),this.fire("layeradd",{layer:e}),this;if(this.hasLayer(e))return this;this._unspiderfy&&this._unspiderfy(),this._addLayer(e,this._maxZoom),this.fire("layeradd",{layer:e}),this._topClusterLevel._recalculateBounds(),this._refreshClustersIcons();var t=e,i=this._zoom;if(e.__parent)for(;t.__parent._zoom>=i;)t=t.__parent;return this._currentShownBounds.contains(t.getLatLng())&&(this.options.animateAddingMarkers?this._animationAddLayer(e,t):this._animationAddLayerNonAnimated(e,t)),this},removeLayer:function(e){return e instanceof L.LayerGroup?this.removeLayers([e]):e.getLatLng?this._map?e.__parent?(this._unspiderfy&&(this._unspiderfy(),this._unspiderfyLayer(e)),this._removeLayer(e,!0),this.fire("layerremove",{layer:e}),this._topClusterLevel._recalculateBounds(),this._refreshClustersIcons(),e.off(this._childMarkerEventHandlers,this),this._featureGroup.hasLayer(e)&&(this._featureGroup.removeLayer(e),e.clusterShow&&e.clusterShow()),this):this:(!this._arraySplice(this._needsClustering,e)&&this.hasLayer(e)&&this._needsRemoving.push({layer:e,latlng:e._latlng}),this.fire("layerremove",{layer:e}),this):(this._nonPointGroup.removeLayer(e),this.fire("layerremove",{layer:e}),this)},addLayers:function(e,t){if(!L.Util.isArray(e))return this.addLayer(e);var i,n=this._featureGroup,r=this._nonPointGroup,s=this.options.chunkedLoading,o=this.options.chunkInterval,a=this.options.chunkProgress,h=e.length,l=0,u=!0;if(this._map){var _=(new Date).getTime(),d=L.bind(function(){for(var c=(new Date).getTime();h>l;l++){if(s&&0===l%200){var p=(new Date).getTime()-c;if(p>o)break}if(i=e[l],i instanceof L.LayerGroup)u&&(e=e.slice(),u=!1),this._extractNonGroupLayers(i,e),h=e.length;else if(i.getLatLng){if(!this.hasLayer(i)&&(this._addLayer(i,this._maxZoom),t||this.fire("layeradd",{layer:i}),i.__parent&&2===i.__parent.getChildCount())){var f=i.__parent.getAllChildMarkers(),m=f[0]===i?f[1]:f[0];n.removeLayer(m)}}else r.addLayer(i),t||this.fire("layeradd",{layer:i})}a&&a(l,h,(new Date).getTime()-_),l===h?(this._topClusterLevel._recalculateBounds(),this._refreshClustersIcons(),this._topClusterLevel._recursivelyAddChildrenToMap(null,this._zoom,this._currentShownBounds)):setTimeout(d,this.options.chunkDelay)},this);d()}else for(var c=this._needsClustering;h>l;l++)i=e[l],i instanceof L.LayerGroup?(u&&(e=e.slice(),u=!1),this._extractNonGroupLayers(i,e),h=e.length):i.getLatLng?this.hasLayer(i)||c.push(i):r.addLayer(i);return this},removeLayers:function(e){var t,i,n=e.length,r=this._featureGroup,s=this._nonPointGroup,o=!0;if(!this._map){for(t=0;n>t;t++)i=e[t],i instanceof L.LayerGroup?(o&&(e=e.slice(),o=!1),this._extractNonGroupLayers(i,e),n=e.length):(this._arraySplice(this._needsClustering,i),s.removeLayer(i),this.hasLayer(i)&&this._needsRemoving.push({layer:i,latlng:i._latlng}),this.fire("layerremove",{layer:i}));return this}if(this._unspiderfy){this._unspiderfy();var a=e.slice(),h=n;for(t=0;h>t;t++)i=a[t],i instanceof L.LayerGroup?(this._extractNonGroupLayers(i,a),h=a.length):this._unspiderfyLayer(i)}for(t=0;n>t;t++)i=e[t],i instanceof L.LayerGroup?(o&&(e=e.slice(),o=!1),this._extractNonGroupLayers(i,e),n=e.length):i.__parent?(this._removeLayer(i,!0,!0),this.fire("layerremove",{layer:i}),r.hasLayer(i)&&(r.removeLayer(i),i.clusterShow&&i.clusterShow())):(s.removeLayer(i),this.fire("layerremove",{layer:i}));return this._topClusterLevel._recalculateBounds(),this._refreshClustersIcons(),this._topClusterLevel._recursivelyAddChildrenToMap(null,this._zoom,this._currentShownBounds),this},clearLayers:function(){return this._map||(this._needsClustering=[],this._needsRemoving=[],delete this._gridClusters,delete this._gridUnclustered),this._noanimationUnspiderfy&&this._noanimationUnspiderfy(),this._featureGroup.clearLayers(),this._nonPointGroup.clearLayers(),this.eachLayer(function(e){e.off(this._childMarkerEventHandlers,this),delete e.__parent},this),this._map&&this._generateInitialClusters(),this},getBounds:function(){var e=new L.LatLngBounds;this._topClusterLevel&&e.extend(this._topClusterLevel._bounds);for(var t=this._needsClustering.length-1;t>=0;t--)e.extend(this._needsClustering[t].getLatLng());return e.extend(this._nonPointGroup.getBounds()),e},eachLayer:function(e,t){var i,n,r,s=this._needsClustering.slice(),o=this._needsRemoving;for(this._topClusterLevel&&this._topClusterLevel.getAllChildMarkers(s),n=s.length-1;n>=0;n--){for(i=!0,r=o.length-1;r>=0;r--)if(o[r].layer===s[n]){i=!1;break}i&&e.call(t,s[n])}this._nonPointGroup.eachLayer(e,t)},getLayers:function(){var e=[];return this.eachLayer(function(t){e.push(t)}),e},getLayer:function(e){var t=null;return e=parseInt(e,10),this.eachLayer(function(i){L.stamp(i)===e&&(t=i)}),t},hasLayer:function(e){if(!e)return!1;var t,i=this._needsClustering;for(t=i.length-1;t>=0;t--)if(i[t]===e)return!0;for(i=this._needsRemoving,t=i.length-1;t>=0;t--)if(i[t].layer===e)return!1;return!(!e.__parent||e.__parent._group!==this)||this._nonPointGroup.hasLayer(e)},zoomToShowLayer:function(e,t){"function"!=typeof t&&(t=function(){});var i=function(){!e._icon&&!e.__parent._icon||this._inZoomAnimation||(this._map.off("moveend",i,this),this.off("animationend",i,this),e._icon?t():e.__parent._icon&&(this.once("spiderfied",t,this),e.__parent.spiderfy()))};e._icon&&this._map.getBounds().contains(e.getLatLng())?t():e.__parent._zoomt;t++)n=this._needsRemoving[t],n.newlatlng=n.layer._latlng,n.layer._latlng=n.latlng;for(t=0,i=this._needsRemoving.length;i>t;t++)n=this._needsRemoving[t],this._removeLayer(n.layer,!0),n.layer._latlng=n.newlatlng;this._needsRemoving=[],this._zoom=Math.round(this._map._zoom),this._currentShownBounds=this._getExpandedVisibleBounds(),this._map.on("zoomend",this._zoomEnd,this),this._map.on("moveend",this._moveEnd,this),this._spiderfierOnAdd&&this._spiderfierOnAdd(),this._bindEvents(),i=this._needsClustering,this._needsClustering=[],this.addLayers(i,!0)},onRemove:function(e){e.off("zoomend",this._zoomEnd,this),e.off("moveend",this._moveEnd,this),this._unbindEvents(),this._map._mapPane.className=this._map._mapPane.className.replace(" leaflet-cluster-anim",""),this._spiderfierOnRemove&&this._spiderfierOnRemove(),delete this._maxLat,this._hideCoverage(),this._featureGroup.remove(),this._nonPointGroup.remove(),this._featureGroup.clearLayers(),this._map=null},getVisibleParent:function(e){for(var t=e;t&&!t._icon;)t=t.__parent;return t||null},_arraySplice:function(e,t){for(var i=e.length-1;i>=0;i--)if(e[i]===t)return e.splice(i,1),!0},_removeFromGridUnclustered:function(e,t){for(var i=this._map,n=this._gridUnclustered,r=Math.floor(this._map.getMinZoom());t>=r&&n[t].removeObject(e,i.project(e.getLatLng(),t));t--);},_childMarkerDragStart:function(e){e.target.__dragStart=e.target._latlng},_childMarkerMoved:function(e){if(!this._ignoreMove&&!e.target.__dragStart){var t=e.target._popup&&e.target._popup.isOpen();this._moveChild(e.target,e.oldLatLng,e.latlng),t&&e.target.openPopup()}},_moveChild:function(e,t,i){e._latlng=t,this.removeLayer(e),e._latlng=i,this.addLayer(e)},_childMarkerDragEnd:function(e){var t=e.target.__dragStart;delete e.target.__dragStart,t&&this._moveChild(e.target,t,e.target._latlng)},_removeLayer:function(e,t,i){var n=this._gridClusters,r=this._gridUnclustered,s=this._featureGroup,o=this._map,a=Math.floor(this._map.getMinZoom());t&&this._removeFromGridUnclustered(e,this._maxZoom);var h,l=e.__parent,u=l._markers;for(this._arraySplice(u,e);l&&(l._childCount--,l._boundsNeedUpdate=!0,!(l._zoomt?"small":100>t?"medium":"large",new L.DivIcon({html:"
"+t+"
",className:"marker-cluster"+i,iconSize:new L.Point(40,40)})},_bindEvents:function(){var e=this._map,t=this.options.spiderfyOnMaxZoom,i=this.options.showCoverageOnHover,n=this.options.zoomToBoundsOnClick;(t||n)&&this.on("clusterclick",this._zoomOrSpiderfy,this),i&&(this.on("clustermouseover",this._showCoverage,this),this.on("clustermouseout",this._hideCoverage,this),e.on("zoomend",this._hideCoverage,this))},_zoomOrSpiderfy:function(e){for(var t=e.layer,i=t;1===i._childClusters.length;)i=i._childClusters[0];i._zoom===this._maxZoom&&i._childCount===t._childCount&&this.options.spiderfyOnMaxZoom?t.spiderfy():this.options.zoomToBoundsOnClick&&t.zoomToBounds(),e.originalEvent&&13===e.originalEvent.keyCode&&this._map._container.focus()},_showCoverage:function(e){var t=this._map;this._inZoomAnimation||(this._shownPolygon&&t.removeLayer(this._shownPolygon),e.layer.getChildCount()>2&&e.layer!==this._spiderfied&&(this._shownPolygon=new L.Polygon(e.layer.getConvexHull(),this.options.polygonOptions),t.addLayer(this._shownPolygon)))},_hideCoverage:function(){this._shownPolygon&&(this._map.removeLayer(this._shownPolygon),this._shownPolygon=null)},_unbindEvents:function(){var e=this.options.spiderfyOnMaxZoom,t=this.options.showCoverageOnHover,i=this.options.zoomToBoundsOnClick,n=this._map;(e||i)&&this.off("clusterclick",this._zoomOrSpiderfy,this),t&&(this.off("clustermouseover",this._showCoverage,this),this.off("clustermouseout",this._hideCoverage,this),n.off("zoomend",this._hideCoverage,this))},_zoomEnd:function(){this._map&&(this._mergeSplitClusters(),this._zoom=Math.round(this._map._zoom),this._currentShownBounds=this._getExpandedVisibleBounds())},_moveEnd:function(){if(!this._inZoomAnimation){var e=this._getExpandedVisibleBounds();this._topClusterLevel._recursivelyRemoveChildrenFromMap(this._currentShownBounds,Math.floor(this._map.getMinZoom()),this._zoom,e),this._topClusterLevel._recursivelyAddChildrenToMap(null,Math.round(this._map._zoom),e),this._currentShownBounds=e}},_generateInitialClusters:function(){var e=Math.ceil(this._map.getMaxZoom()),t=Math.floor(this._map.getMinZoom()),i=this.options.maxClusterRadius,n=i;"function"!=typeof i&&(n=function(){return i}),null!==this.options.disableClusteringAtZoom&&(e=this.options.disableClusteringAtZoom-1),this._maxZoom=e,this._gridClusters={},this._gridUnclustered={};for(var r=e;r>=t;r--)this._gridClusters[r]=new L.DistanceGrid(n(r)),this._gridUnclustered[r]=new L.DistanceGrid(n(r));this._topClusterLevel=new this._markerCluster(this,t-1)},_addLayer:function(e,t){var i,n,r=this._gridClusters,s=this._gridUnclustered,o=Math.floor(this._map.getMinZoom());for(this.options.singleMarkerMode&&this._overrideMarkerIcon(e),e.on(this._childMarkerEventHandlers,this);t>=o;t--){i=this._map.project(e.getLatLng(),t);var a=r[t].getNearObject(i);if(a)return a._addChild(e),e.__parent=a,void 0;if(a=s[t].getNearObject(i)){var h=a.__parent;h&&this._removeLayer(a,!1);var l=new this._markerCluster(this,t,a,e);r[t].addObject(l,this._map.project(l._cLatLng,t)),a.__parent=l,e.__parent=l;var u=l;for(n=t-1;n>h._zoom;n--)u=new this._markerCluster(this,n,u),r[n].addObject(u,this._map.project(a.getLatLng(),n));return h._addChild(u),this._removeFromGridUnclustered(a,t),void 0}s[t].addObject(e,i)}this._topClusterLevel._addChild(e),e.__parent=this._topClusterLevel},_refreshClustersIcons:function(){this._featureGroup.eachLayer(function(e){e instanceof L.MarkerCluster&&e._iconNeedsUpdate&&e._updateIcon()})},_enqueue:function(e){this._queue.push(e),this._queueTimeout||(this._queueTimeout=setTimeout(L.bind(this._processQueue,this),300))},_processQueue:function(){for(var e=0;ee?(this._animationStart(),this._animationZoomOut(this._zoom,e)):this._moveEnd()},_getExpandedVisibleBounds:function(){return this.options.removeOutsideVisibleBounds?L.Browser.mobile?this._checkBoundsMaxLat(this._map.getBounds()):this._checkBoundsMaxLat(this._map.getBounds().pad(1)):this._mapBoundsInfinite},_checkBoundsMaxLat:function(e){var t=this._maxLat;return void 0!==t&&(e.getNorth()>=t&&(e._northEast.lat=1/0),e.getSouth()<=-t&&(e._southWest.lat=-1/0)),e},_animationAddLayerNonAnimated:function(e,t){if(t===e)this._featureGroup.addLayer(e);else if(2===t._childCount){t._addToMap();var i=t.getAllChildMarkers();this._featureGroup.removeLayer(i[0]),this._featureGroup.removeLayer(i[1])}else t._updateIcon()},_extractNonGroupLayers:function(e,t){var i,n=e.getLayers(),r=0;for(t=t||[];r=0;i--)o=h[i],n.contains(o._latlng)||r.removeLayer(o)}),this._forceLayout(),this._topClusterLevel._recursivelyBecomeVisible(n,t),r.eachLayer(function(e){e instanceof L.MarkerCluster||!e._icon||e.clusterShow()}),this._topClusterLevel._recursively(n,e,t,function(e){e._recursivelyRestoreChildPositions(t)}),this._ignoreMove=!1,this._enqueue(function(){this._topClusterLevel._recursively(n,e,s,function(e){r.removeLayer(e),e.clusterShow()}),this._animationEnd()})},_animationZoomOut:function(e,t){this._animationZoomOutSingle(this._topClusterLevel,e-1,t),this._topClusterLevel._recursivelyAddChildrenToMap(null,t,this._getExpandedVisibleBounds()),this._topClusterLevel._recursivelyRemoveChildrenFromMap(this._currentShownBounds,Math.floor(this._map.getMinZoom()),e,this._getExpandedVisibleBounds())},_animationAddLayer:function(e,t){var i=this,n=this._featureGroup;n.addLayer(e),t!==e&&(t._childCount>2?(t._updateIcon(),this._forceLayout(),this._animationStart(),e._setPos(this._map.latLngToLayerPoint(t.getLatLng())),e.clusterHide(),this._enqueue(function(){n.removeLayer(e),e.clusterShow(),i._animationEnd()})):(this._forceLayout(),i._animationStart(),i._animationZoomOutSingle(t,this._map.getMaxZoom(),this._zoom)))}},_animationZoomOutSingle:function(e,t,i){var n=this._getExpandedVisibleBounds(),r=Math.floor(this._map.getMinZoom());e._recursivelyAnimateChildrenInAndAddSelfToMap(n,r,t+1,i);var s=this;this._forceLayout(),e._recursivelyBecomeVisible(n,i),this._enqueue(function(){if(1===e._childCount){var o=e._markers[0];this._ignoreMove=!0,o.setLatLng(o.getLatLng()),this._ignoreMove=!1,o.clusterShow&&o.clusterShow()}else e._recursively(n,i,r,function(e){e._recursivelyRemoveChildrenFromMap(n,r,t+1)});s._animationEnd()})},_animationEnd:function(){this._map&&(this._map._mapPane.className=this._map._mapPane.className.replace(" leaflet-cluster-anim","")),this._inZoomAnimation--,this.fire("animationend")},_forceLayout:function(){L.Util.falseFn(document.body.offsetWidth)}}),L.markerClusterGroup=function(e){return new L.MarkerClusterGroup(e)};var i=L.MarkerCluster=L.Marker.extend({options:L.Icon.prototype.options,initialize:function(e,t,i,n){L.Marker.prototype.initialize.call(this,i?i._cLatLng||i.getLatLng():new L.LatLng(0,0),{icon:this,pane:e.options.clusterPane}),this._group=e,this._zoom=t,this._markers=[],this._childClusters=[],this._childCount=0,this._iconNeedsUpdate=!0,this._boundsNeedUpdate=!0,this._bounds=new L.LatLngBounds,i&&this._addChild(i),n&&this._addChild(n)},getAllChildMarkers:function(e,t){e=e||[];for(var i=this._childClusters.length-1;i>=0;i--)this._childClusters[i].getAllChildMarkers(e);for(var n=this._markers.length-1;n>=0;n--)t&&this._markers[n].__dragStart||e.push(this._markers[n]);return e},getChildCount:function(){return this._childCount},zoomToBounds:function(e){for(var t,i=this._childClusters.slice(),n=this._group._map,r=n.getBoundsZoom(this._bounds),s=this._zoom+1,o=n.getZoom();i.length>0&&r>s;){s++;var a=[];for(t=0;ts?this._group._map.setView(this._latlng,s):o>=r?this._group._map.setView(this._latlng,o+1):this._group._map.fitBounds(this._bounds,e)},getBounds:function(){var e=new L.LatLngBounds;return e.extend(this._bounds),e},_updateIcon:function(){this._iconNeedsUpdate=!0,this._icon&&this.setIcon(this)},createIcon:function(){return this._iconNeedsUpdate&&(this._iconObj=this._group.options.iconCreateFunction(this),this._iconNeedsUpdate=!1),this._iconObj.createIcon()},createShadow:function(){return this._iconObj.createShadow()},_addChild:function(e,t){this._iconNeedsUpdate=!0,this._boundsNeedUpdate=!0,this._setClusterCenter(e),e instanceof L.MarkerCluster?(t||(this._childClusters.push(e),e.__parent=this),this._childCount+=e._childCount):(t||this._markers.push(e),this._childCount++),this.__parent&&this.__parent._addChild(e,!0)},_setClusterCenter:function(e){this._cLatLng||(this._cLatLng=e._cLatLng||e._latlng)},_resetBounds:function(){var e=this._bounds;e._southWest&&(e._southWest.lat=1/0,e._southWest.lng=1/0),e._northEast&&(e._northEast.lat=-1/0,e._northEast.lng=-1/0)},_recalculateBounds:function(){var e,t,i,n,r=this._markers,s=this._childClusters,o=0,a=0,h=this._childCount;if(0!==h){for(this._resetBounds(),e=0;e=0;i--)n=r[i],n._icon&&(n._setPos(t),n.clusterHide())},function(e){var i,n,r=e._childClusters;for(i=r.length-1;i>=0;i--)n=r[i],n._icon&&(n._setPos(t),n.clusterHide())})},_recursivelyAnimateChildrenInAndAddSelfToMap:function(e,t,i,n){this._recursively(e,n,t,function(r){r._recursivelyAnimateChildrenIn(e,r._group._map.latLngToLayerPoint(r.getLatLng()).round(),i),r._isSingleParent()&&i-1===n?(r.clusterShow(),r._recursivelyRemoveChildrenFromMap(e,t,i)):r.clusterHide(),r._addToMap()})},_recursivelyBecomeVisible:function(e,t){this._recursively(e,this._group._map.getMinZoom(),t,null,function(e){e.clusterShow()})},_recursivelyAddChildrenToMap:function(e,t,i){this._recursively(i,this._group._map.getMinZoom()-1,t,function(n){if(t!==n._zoom)for(var r=n._markers.length-1;r>=0;r--){var s=n._markers[r];i.contains(s._latlng)&&(e&&(s._backupLatlng=s.getLatLng(),s.setLatLng(e),s.clusterHide&&s.clusterHide()),n._group._featureGroup.addLayer(s))}},function(t){t._addToMap(e)})},_recursivelyRestoreChildPositions:function(e){for(var t=this._markers.length-1;t>=0;t--){var i=this._markers[t];i._backupLatlng&&(i.setLatLng(i._backupLatlng),delete i._backupLatlng)}if(e-1===this._zoom)for(var n=this._childClusters.length-1;n>=0;n--)this._childClusters[n]._restorePosition();else for(var r=this._childClusters.length-1;r>=0;r--)this._childClusters[r]._recursivelyRestoreChildPositions(e)},_restorePosition:function(){this._backupLatlng&&(this.setLatLng(this._backupLatlng),delete this._backupLatlng)},_recursivelyRemoveChildrenFromMap:function(e,t,i,n){var r,s;this._recursively(e,t-1,i-1,function(e){for(s=e._markers.length-1;s>=0;s--)r=e._markers[s],n&&n.contains(r._latlng)||(e._group._featureGroup.removeLayer(r),r.clusterShow&&r.clusterShow())},function(e){for(s=e._childClusters.length-1;s>=0;s--)r=e._childClusters[s],n&&n.contains(r._latlng)||(e._group._featureGroup.removeLayer(r),r.clusterShow&&r.clusterShow())})},_recursively:function(e,t,i,n,r){var s,o,a=this._childClusters,h=this._zoom;if(h>=t&&(n&&n(this),r&&h===i&&r(this)),t>h||i>h)for(s=a.length-1;s>=0;s--)o=a[s],o._boundsNeedUpdate&&o._recalculateBounds(),e.intersects(o._bounds)&&o._recursively(e,t,i,n,r)},_isSingleParent:function(){return this._childClusters.length>0&&this._childClusters[0]._childCount===this._childCount}});L.Marker.include({clusterHide:function(){var e=this.options.opacity;return this.setOpacity(0),this.options.opacity=e,this},clusterShow:function(){return this.setOpacity(this.options.opacity)}}),L.DistanceGrid=function(e){this._cellSize=e,this._sqCellSize=e*e,this._grid={},this._objectPoint={}},L.DistanceGrid.prototype={addObject:function(e,t){var i=this._getCoord(t.x),n=this._getCoord(t.y),r=this._grid,s=r[n]=r[n]||{},o=s[i]=s[i]||[],a=L.Util.stamp(e);this._objectPoint[a]=t,o.push(e)},updateObject:function(e,t){this.removeObject(e),this.addObject(e,t)},removeObject:function(e,t){var i,n,r=this._getCoord(t.x),s=this._getCoord(t.y),o=this._grid,a=o[s]=o[s]||{},h=a[r]=a[r]||[];for(delete this._objectPoint[L.Util.stamp(e)],i=0,n=h.length;n>i;i++)if(h[i]===e)return h.splice(i,1),1===n&&delete a[r],!0},eachObject:function(e,t){var i,n,r,s,o,a,h,l=this._grid;for(i in l){o=l[i];for(n in o)for(a=o[n],r=0,s=a.length;s>r;r++)h=e.call(t,a[r]),h&&(r--,s--)}},getNearObject:function(e){var t,i,n,r,s,o,a,h,l=this._getCoord(e.x),u=this._getCoord(e.y),_=this._objectPoint,d=this._sqCellSize,c=null;for(t=u-1;u+1>=t;t++)if(r=this._grid[t])for(i=l-1;l+1>=i;i++)if(s=r[i])for(n=0,o=s.length;o>n;n++)a=s[n],h=this._sqDist(_[L.Util.stamp(a)],e),(d>h||d>=h&&null===c)&&(d=h,c=a);return c},_getCoord:function(e){var t=Math.floor(e/this._cellSize);return isFinite(t)?t:e},_sqDist:function(e,t){var i=t.x-e.x,n=t.y-e.y;return i*i+n*n}},function(){L.QuickHull={getDistant:function(e,t){var i=t[1].lat-t[0].lat,n=t[0].lng-t[1].lng;return n*(e.lat-t[0].lat)+i*(e.lng-t[0].lng)},findMostDistantPointFromBaseLine:function(e,t){var i,n,r,s=0,o=null,a=[];for(i=t.length-1;i>=0;i--)n=t[i],r=this.getDistant(n,e),r>0&&(a.push(n),r>s&&(s=r,o=n));return{maxPoint:o,newPoints:a}},buildConvexHull:function(e,t){var i=[],n=this.findMostDistantPointFromBaseLine(e,t);return n.maxPoint?(i=i.concat(this.buildConvexHull([e[0],n.maxPoint],n.newPoints)),i=i.concat(this.buildConvexHull([n.maxPoint,e[1]],n.newPoints))):[e[0]]},getConvexHull:function(e){var t,i=!1,n=!1,r=!1,s=!1,o=null,a=null,h=null,l=null,u=null,_=null;for(t=e.length-1;t>=0;t--){var d=e[t];(i===!1||d.lat>i)&&(o=d,i=d.lat),(n===!1||d.latr)&&(h=d,r=d.lng),(s===!1||d.lng=0;t--)e=i[t].getLatLng(),n.push(e);return L.QuickHull.getConvexHull(n)}}),L.MarkerCluster.include({_2PI:2*Math.PI,_circleFootSeparation:25,_circleStartAngle:0,_spiralFootSeparation:28,_spiralLengthStart:11,_spiralLengthFactor:5,_circleSpiralSwitchover:9,spiderfy:function(){if(this._group._spiderfied!==this&&!this._group._inZoomAnimation){var e,t=this.getAllChildMarkers(null,!0),i=this._group,n=i._map,r=n.latLngToLayerPoint(this._latlng);this._group._unspiderfy(),this._group._spiderfied=this,t.length>=this._circleSpiralSwitchover?e=this._generatePointsSpiral(t.length,r):(r.y+=10,e=this._generatePointsCircle(t.length,r)),this._animationSpiderfy(t,e)}},unspiderfy:function(e){this._group._inZoomAnimation||(this._animationUnspiderfy(e),this._group._spiderfied=null)},_generatePointsCircle:function(e,t){var i,n,r=this._group.options.spiderfyDistanceMultiplier*this._circleFootSeparation*(2+e),s=r/this._2PI,o=this._2PI/e,a=[];for(s=Math.max(s,35),a.length=e,i=0;e>i;i++)n=this._circleStartAngle+i*o,a[i]=new L.Point(t.x+s*Math.cos(n),t.y+s*Math.sin(n))._round();return a},_generatePointsSpiral:function(e,t){var i,n=this._group.options.spiderfyDistanceMultiplier,r=n*this._spiralLengthStart,s=n*this._spiralFootSeparation,o=n*this._spiralLengthFactor*this._2PI,a=0,h=[];for(h.length=e,i=e;i>=0;i--)e>i&&(h[i]=new L.Point(t.x+r*Math.cos(a),t.y+r*Math.sin(a))._round()),a+=s/r+5e-4*i,r+=o/a;return h},_noanimationUnspiderfy:function(){var e,t,i=this._group,n=i._map,r=i._featureGroup,s=this.getAllChildMarkers(null,!0);for(i._ignoreMove=!0,this.setOpacity(1),t=s.length-1;t>=0;t--)e=s[t],r.removeLayer(e),e._preSpiderfyLatlng&&(e.setLatLng(e._preSpiderfyLatlng),delete e._preSpiderfyLatlng),e.setZIndexOffset&&e.setZIndexOffset(0),e._spiderLeg&&(n.removeLayer(e._spiderLeg),delete e._spiderLeg);i.fire("unspiderfied",{cluster:this,markers:s}),i._ignoreMove=!1,i._spiderfied=null}}),L.MarkerClusterNonAnimated=L.MarkerCluster.extend({_animationSpiderfy:function(e,t){var i,n,r,s,o=this._group,a=o._map,h=o._featureGroup,l=this._group.options.spiderLegPolylineOptions;for(o._ignoreMove=!0,i=0;i=0;i--)a=u.layerPointToLatLng(t[i]),n=e[i],n._preSpiderfyLatlng=n._latlng,n.setLatLng(a),n.clusterShow&&n.clusterShow(),p&&(r=n._spiderLeg,s=r._path,s.style.strokeDashoffset=0,r.setStyle({opacity:m}));this.setOpacity(.3),l._ignoreMove=!1,setTimeout(function(){l._animationEnd(),l.fire("spiderfied",{cluster:h,markers:e})},200)},_animationUnspiderfy:function(e){var t,i,n,r,s,o,a=this,h=this._group,l=h._map,u=h._featureGroup,_=e?l._latLngToNewLayerPoint(this._latlng,e.zoom,e.center):l.latLngToLayerPoint(this._latlng),d=this.getAllChildMarkers(null,!0),c=L.Path.SVG;for(h._ignoreMove=!0,h._animationStart(),this.setOpacity(1),i=d.length-1;i>=0;i--)t=d[i],t._preSpiderfyLatlng&&(t.closePopup(),t.setLatLng(t._preSpiderfyLatlng),delete t._preSpiderfyLatlng,o=!0,t._setPos&&(t._setPos(_),o=!1),t.clusterHide&&(t.clusterHide(),o=!1),o&&u.removeLayer(t),c&&(n=t._spiderLeg,r=n._path,s=r.getTotalLength()+.1,r.style.strokeDashoffset=s,n.setStyle({opacity:0})));h._ignoreMove=!1,setTimeout(function(){var e=0;for(i=d.length-1;i>=0;i--)t=d[i],t._spiderLeg&&e++;for(i=d.length-1;i>=0;i--)t=d[i],t._spiderLeg&&(t.clusterShow&&t.clusterShow(),t.setZIndexOffset&&t.setZIndexOffset(0),e>1&&u.removeLayer(t),l.removeLayer(t._spiderLeg),delete t._spiderLeg);h._animationEnd(),h.fire("unspiderfied",{cluster:a,markers:d})},200)}}),L.MarkerClusterGroup.include({_spiderfied:null,unspiderfy:function(){this._unspiderfy.apply(this,arguments)},_spiderfierOnAdd:function(){this._map.on("click",this._unspiderfyWrapper,this),this._map.options.zoomAnimation&&this._map.on("zoomstart",this._unspiderfyZoomStart,this),this._map.on("zoomend",this._noanimationUnspiderfy,this),L.Browser.touch||this._map.getRenderer(this)},_spiderfierOnRemove:function(){this._map.off("click",this._unspiderfyWrapper,this),this._map.off("zoomstart",this._unspiderfyZoomStart,this),this._map.off("zoomanim",this._unspiderfyZoomAnim,this),this._map.off("zoomend",this._noanimationUnspiderfy,this),this._noanimationUnspiderfy() +},_unspiderfyZoomStart:function(){this._map&&this._map.on("zoomanim",this._unspiderfyZoomAnim,this)},_unspiderfyZoomAnim:function(e){L.DomUtil.hasClass(this._map._mapPane,"leaflet-touching")||(this._map.off("zoomanim",this._unspiderfyZoomAnim,this),this._unspiderfy(e))},_unspiderfyWrapper:function(){this._unspiderfy()},_unspiderfy:function(e){this._spiderfied&&this._spiderfied.unspiderfy(e)},_noanimationUnspiderfy:function(){this._spiderfied&&this._spiderfied._noanimationUnspiderfy()},_unspiderfyLayer:function(e){e._spiderLeg&&(this._featureGroup.removeLayer(e),e.clusterShow&&e.clusterShow(),e.setZIndexOffset&&e.setZIndexOffset(0),this._map.removeLayer(e._spiderLeg),delete e._spiderLeg)}}),L.MarkerClusterGroup.include({refreshClusters:function(e){return e?e instanceof L.MarkerClusterGroup?e=e._topClusterLevel.getAllChildMarkers():e instanceof L.LayerGroup?e=e._layers:e instanceof L.MarkerCluster?e=e.getAllChildMarkers():e instanceof L.Marker&&(e=[e]):e=this._topClusterLevel.getAllChildMarkers(),this._flagParentsIconsNeedUpdate(e),this._refreshClustersIcons(),this.options.singleMarkerMode&&this._refreshSingleMarkerModeMarkers(e),this},_flagParentsIconsNeedUpdate:function(e){var t,i;for(t in e)for(i=e[t].__parent;i;)i._iconNeedsUpdate=!0,i=i.__parent},_refreshSingleMarkerModeMarkers:function(e){var t,i;for(t in e)i=e[t],this.hasLayer(i)&&i.setIcon(this._overrideMarkerIcon(i))}}),L.Marker.include({refreshIconOptions:function(e,t){var i=this.options.icon;return L.setOptions(i,e),this.setIcon(i),t&&this.__parent&&this.__parent._group.refreshClusters(this),this}}),e.MarkerClusterGroup=t,e.MarkerCluster=i}); +//# sourceMappingURL=leaflet.markercluster.js.map \ No newline at end of file diff --git a/noise/public/javascripts/leaflet.markercluster.js.map b/noise/public/javascripts/leaflet.markercluster.js.map new file mode 100644 index 0000000..a4b459c --- /dev/null +++ b/noise/public/javascripts/leaflet.markercluster.js.map @@ -0,0 +1 @@ +{"version":3,"sources":["../src/MarkerClusterGroup.js","../src/MarkerCluster.js","../src/MarkerOpacity.js","../src/DistanceGrid.js","../src/MarkerCluster.QuickHull.js","../src/MarkerCluster.Spiderfier.js","../src/MarkerClusterGroup.Refresh.js"],"names":[],"mappings":"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","file":"dist/leaflet.markercluster.js"} \ No newline at end of file diff --git a/noise/public/javascripts/logit.js b/noise/public/javascripts/logit.js new file mode 100644 index 0000000..2453df0 --- /dev/null +++ b/noise/public/javascripts/logit.js @@ -0,0 +1,12 @@ +import { DateTime } from './luxon.min.js' + +export function logit(str) { + let s = `${DateTime.now().toISO()} => ${str}`; + console.log(s); +} + +export function logerror(str) { + let s = `${DateTime.utc().toISO()} => *** ERROR *** ${str}`; + console.log(s); +} + diff --git a/noise/public/javascripts/luxon.min.js b/noise/public/javascripts/luxon.min.js new file mode 100644 index 0000000..30ced14 --- /dev/null +++ b/noise/public/javascripts/luxon.min.js @@ -0,0 +1 @@ +class e extends Error{}class z extends e{constructor(e){super("Invalid DateTime: "+e.toMessage())}}class q extends e{constructor(e){super("Invalid Interval: "+e.toMessage())}}class A extends e{constructor(e){super("Invalid Duration: "+e.toMessage())}}class j extends e{}class _ extends e{constructor(e){super("Invalid unit "+e)}}class o extends e{}class r extends e{constructor(){super("Zone is an abstract class")}}var t="numeric",n="short",s="long";const U={year:t,month:t,day:t},$={year:t,month:n,day:t},H={year:t,month:n,day:t,weekday:n},W={year:t,month:s,day:t},R={year:t,month:s,day:t,weekday:s},J={hour:t,minute:t},Y={hour:t,minute:t,second:t},P={hour:t,minute:t,second:t,timeZoneName:n},G={hour:t,minute:t,second:t,timeZoneName:s},B={hour:t,minute:t,hourCycle:"h23"},Q={hour:t,minute:t,second:t,hourCycle:"h23"},K={hour:t,minute:t,second:t,hourCycle:"h23",timeZoneName:n},X={hour:t,minute:t,second:t,hourCycle:"h23",timeZoneName:s},ee={year:t,month:t,day:t,hour:t,minute:t},te={year:t,month:t,day:t,hour:t,minute:t,second:t},re={year:t,month:n,day:t,hour:t,minute:t},ne={year:t,month:n,day:t,hour:t,minute:t,second:t},se={year:t,month:n,day:t,weekday:n,hour:t,minute:t},ie={year:t,month:s,day:t,hour:t,minute:t,timeZoneName:n},ae={year:t,month:s,day:t,hour:t,minute:t,second:t,timeZoneName:n},oe={year:t,month:s,day:t,weekday:s,hour:t,minute:t,timeZoneName:s},ue={year:t,month:s,day:t,weekday:s,hour:t,minute:t,second:t,timeZoneName:s};function O(e){return void 0===e}function c(e){return"number"==typeof e}function le(e){return"number"==typeof e&&e%1==0}function ce(e){return"[object Date]"===Object.prototype.toString.call(e)}function he(){try{return"undefined"!=typeof Intl&&!!Intl.RelativeTimeFormat}catch(e){return!1}}function de(e){return Array.isArray(e)?e:[e]}function me(e,r,n){if(0!==e.length)return e.reduce((e,t)=>{t=[r(t),t];return e&&n(e[0],t[0])===e[0]?e:t},null)[1]}function h(e,t){return Object.prototype.hasOwnProperty.call(e,t)}function u(e,t,r){return le(e)&&t<=e&&e<=r}function l(e,t=2){let r;return r=e<0?"-"+(""+-e).padStart(t,"0"):(""+e).padStart(t,"0")}function d(e){if(!O(e)&&null!==e&&""!==e)return parseInt(e,10)}function m(e){if(!O(e)&&null!==e&&""!==e)return parseFloat(e)}function fe(e){if(!O(e)&&null!==e&&""!==e)return e=1e3*parseFloat("0."+e),Math.floor(e)}function ye(e,t,r=!1){const n=10**t,s=r?Math.trunc:Math.round;return s(e*n)/n}function ge(e){return e%4==0&&(e%100!=0||e%400==0)}function we(e){return ge(e)?366:365}function ve(e,t){var r,n=(n=t-1)-(r=12)*Math.floor(n/r)+1;return 2==n?ge(e+(t-n)/12)?29:28:[31,null,31,30,31,30,31,31,30,31,30,31][n-1]}function pe(e){let t=Date.UTC(e.year,e.month-1,e.day,e.hour,e.minute,e.second,e.millisecond);return e.year<100&&0<=e.year&&(t=new Date(t)).setUTCFullYear(t.getUTCFullYear()-1900),+t}function Te(e){var t=(e+Math.floor(e/4)-Math.floor(e/100)+Math.floor(e/400))%7,e=e-1,e=(e+Math.floor(e/4)-Math.floor(e/100)+Math.floor(e/400))%7;return 4==t||3==e?53:52}function Se(e){return 99"timezonename"===e.type.toLowerCase());return n?n.value:null}function be(e,t){let r=parseInt(e,10);Number.isNaN(r)&&(r=0);e=parseInt(t,10)||0,t=r<0||Object.is(r,-0)?-e:e;return 60*r+t}function ke(e){var t=Number(e);if("boolean"==typeof e||""===e||Number.isNaN(t))throw new o("Invalid unit value "+e);return t}function Me(e,t){const r={};for(const s in e){var n;!h(e,s)||null!=(n=e[s])&&(r[t(s)]=ke(n))}return r}function Ne(e,t){var r=Math.trunc(Math.abs(e/60)),n=Math.trunc(Math.abs(e%60)),s=0<=e?"+":"-";switch(t){case"short":return s+l(r,2)+":"+l(n,2);case"narrow":return s+r+(0(e[t]=r[t],e),{});var r}n=/[A-Za-z_+-]{1,256}(?::?\/[A-Za-z0-9_+-]{1,256}(?:\/[A-Za-z0-9_+-]{1,256})?)?/;const Ee=["January","February","March","April","May","June","July","August","September","October","November","December"],Ve=["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],Ie=["J","F","M","A","M","J","J","A","S","O","N","D"];function xe(e){switch(e){case"narrow":return[...Ie];case"short":return[...Ve];case"long":return[...Ee];case"numeric":return["1","2","3","4","5","6","7","8","9","10","11","12"];case"2-digit":return["01","02","03","04","05","06","07","08","09","10","11","12"];default:return null}}const Ce=["Monday","Tuesday","Wednesday","Thursday","Friday","Saturday","Sunday"],Fe=["Mon","Tue","Wed","Thu","Fri","Sat","Sun"],Ze=["M","T","W","T","F","S","S"];function Le(e){switch(e){case"narrow":return[...Ze];case"short":return[...Fe];case"long":return[...Ce];case"numeric":return["1","2","3","4","5","6","7"];default:return null}}const ze=["AM","PM"],qe=["Before Christ","Anno Domini"],Ae=["BC","AD"],je=["B","A"];function _e(e){switch(e){case"narrow":return[...je];case"short":return[...Ae];case"long":return[...qe];default:return null}}function Ue(e){return ze[e.hour<12?0:1]}function $e(e,t){return Le(t)[e.weekday-1]}function He(e,t){return xe(t)[e.month-1]}function We(e,t){return _e(t)[e.year<0?0:1]}function Re(e,t,r="always",n=!1){var s={years:["year","yr."],quarters:["quarter","qtr."],months:["month","mo."],weeks:["week","wk."],days:["day","day","days"],hours:["hour","hr."],minutes:["minute","min."],seconds:["second","sec."]},i=-1===["hours","minutes","seconds"].indexOf(e);if("auto"===r&&i){var a="days"===e;switch(t){case 1:return a?"tomorrow":"next "+s[e][0];case-1:return a?"yesterday":"last "+s[e][0];case 0:return a?"today":"this "+s[e][0]}}var r=Object.is(t,-0)||t<0,i=Math.abs(t),t=1===i,o=s[e],n=n?!t&&o[2]||o[1]:t?s[e][0]:e;return r?i+` ${n} ago`:`in ${i} `+n}function Je(e,t){let r="";for(const n of e)n.literal?r+=n.val:r+=t(n.val);return r}const Ye={D:U,DD:$,DDD:W,DDDD:R,t:J,tt:Y,ttt:P,tttt:G,T:B,TT:Q,TTT:K,TTTT:X,f:ee,ff:re,fff:ie,ffff:oe,F:te,FF:ne,FFF:ae,FFFF:ue};class f{static create(e,t={}){return new f(e,t)}static parseFormat(t){let r=null,n="",s=!1;const i=[];for(let e=0;ethis.loc.extract(r,e,t),i=e=>r.isOffsetFixed&&0===r.offset&&e.allowZ?"Z":r.isValid?r.zone.formatOffset(r.ts,e.format):"",a=()=>n?Ue(r):s({hour:"numeric",hourCycle:"h12"},"dayperiod"),o=(e,t)=>n?He(r,e):s(t?{month:e}:{month:e,day:"numeric"},"month"),u=(e,t)=>n?$e(r,e):s(t?{weekday:e}:{weekday:e,month:"long",day:"numeric"},"weekday"),l=e=>{var t=f.macroTokenToFormatOpts(e);return t?this.formatWithSystemDefault(r,t):e},c=e=>n?We(r,e):s({era:e},"era");return Je(f.parseFormat(e),e=>{switch(e){case"S":return this.num(r.millisecond);case"u":case"SSS":return this.num(r.millisecond,3);case"s":return this.num(r.second);case"ss":return this.num(r.second,2);case"uu":return this.num(Math.floor(r.millisecond/10),2);case"uuu":return this.num(Math.floor(r.millisecond/100));case"m":return this.num(r.minute);case"mm":return this.num(r.minute,2);case"h":return this.num(r.hour%12==0?12:r.hour%12);case"hh":return this.num(r.hour%12==0?12:r.hour%12,2);case"H":return this.num(r.hour);case"HH":return this.num(r.hour,2);case"Z":return i({format:"narrow",allowZ:this.opts.allowZ});case"ZZ":return i({format:"short",allowZ:this.opts.allowZ});case"ZZZ":return i({format:"techie",allowZ:this.opts.allowZ});case"ZZZZ":return r.zone.offsetName(r.ts,{format:"short",locale:this.loc.locale});case"ZZZZZ":return r.zone.offsetName(r.ts,{format:"long",locale:this.loc.locale});case"z":return r.zoneName;case"a":return a();case"d":return t?s({day:"numeric"},"day"):this.num(r.day);case"dd":return t?s({day:"2-digit"},"day"):this.num(r.day,2);case"c":return this.num(r.weekday);case"ccc":return u("short",!0);case"cccc":return u("long",!0);case"ccccc":return u("narrow",!0);case"E":return this.num(r.weekday);case"EEE":return u("short",!1);case"EEEE":return u("long",!1);case"EEEEE":return u("narrow",!1);case"L":return t?s({month:"numeric",day:"numeric"},"month"):this.num(r.month);case"LL":return t?s({month:"2-digit",day:"numeric"},"month"):this.num(r.month,2);case"LLL":return o("short",!0);case"LLLL":return o("long",!0);case"LLLLL":return o("narrow",!0);case"M":return t?s({month:"numeric"},"month"):this.num(r.month);case"MM":return t?s({month:"2-digit"},"month"):this.num(r.month,2);case"MMM":return o("short",!1);case"MMMM":return o("long",!1);case"MMMMM":return o("narrow",!1);case"y":return t?s({year:"numeric"},"year"):this.num(r.year);case"yy":return t?s({year:"2-digit"},"year"):this.num(r.year.toString().slice(-2),2);case"yyyy":return t?s({year:"numeric"},"year"):this.num(r.year,4);case"yyyyyy":return t?s({year:"numeric"},"year"):this.num(r.year,6);case"G":return c("short");case"GG":return c("long");case"GGGGG":return c("narrow");case"kk":return this.num(r.weekYear.toString().slice(-2),2);case"kkkk":return this.num(r.weekYear,4);case"W":return this.num(r.weekNumber);case"WW":return this.num(r.weekNumber,2);case"o":return this.num(r.ordinal);case"ooo":return this.num(r.ordinal,3);case"q":return this.num(r.quarter);case"qq":return this.num(r.quarter,2);case"X":return this.num(Math.floor(r.ts/1e3));case"x":return this.num(r.ts);default:return l(e)}})}formatDurationFromString(e,t){const r=e=>{switch(e[0]){case"S":return"millisecond";case"s":return"second";case"m":return"minute";case"h":return"hour";case"d":return"day";case"w":return"week";case"M":return"month";case"y":return"year";default:return null}},n=f.parseFormat(t),s=n.reduce((e,{literal:t,val:r})=>t?e:e.concat(r),[]),i=e.shiftTo(...s.map(r).filter(e=>e));return Je(n,(a=i,e=>{var t=r(e);return t?this.num(a.get(t),e.length):e}));var a}}class y{constructor(e,t){this.reason=e,this.explanation=t}toMessage(){return this.explanation?this.reason+": "+this.explanation:this.reason}}class i{get type(){throw new r}get name(){throw new r}get ianaName(){return this.name}get isUniversal(){throw new r}offsetName(e,t){throw new r}formatOffset(e,t){throw new r}offset(e){throw new r}equals(e){throw new r}get isValid(){throw new r}}let Pe=null;class Ge extends i{static get instance(){return Pe=null===Pe?new Ge:Pe}get type(){return"system"}get name(){return(new Intl.DateTimeFormat).resolvedOptions().timeZone}get isUniversal(){return!1}offsetName(e,{format:t,locale:r}){return Oe(e,t,r)}formatOffset(e,t){return Ne(this.offset(e),t)}offset(e){return-new Date(e).getTimezoneOffset()}equals(e){return"system"===e.type}get isValid(){return!0}}let Be={};function Qe(e){return Be[e]||(Be[e]=new Intl.DateTimeFormat("en-US",{hour12:!1,timeZone:e,year:"numeric",month:"2-digit",day:"2-digit",hour:"2-digit",minute:"2-digit",second:"2-digit",era:"short"})),Be[e]}const Ke={year:0,month:1,day:2,era:3,hour:4,minute:5,second:6};function Xe(e,t){var e=e.format(t).replace(/\u200E/g,""),[,t,e,r,n,s,i,a]=/(\d+)\/(\d+)\/(\d+) (AD|BC),? (\d+):(\d+):(\d+)/.exec(e);return[r,t,e,n,s,i,a]}function et(e,t){var r=e.formatToParts(t);const n=[];for(let e=0;eDate.now(),it="system",at=null,ot=null,ut=null,lt;class k{static get now(){return st}static set now(e){st=e}static set defaultZone(e){it=e}static get defaultZone(){return b(it,Ge.instance)}static get defaultLocale(){return at}static set defaultLocale(e){at=e}static get defaultNumberingSystem(){return ot}static set defaultNumberingSystem(e){ot=e}static get defaultOutputCalendar(){return ut}static set defaultOutputCalendar(e){ut=e}static get throwOnInvalid(){return lt}static set throwOnInvalid(e){lt=e}static resetCaches(){M.resetCache(),w.resetCache()}}let ct={};function ht(e,t={}){var r=JSON.stringify([e,t]);let n=ct[r];return n||(n=new Intl.ListFormat(e,t),ct[r]=n),n}let dt={};function mt(e,t={}){var r=JSON.stringify([e,t]);let n=dt[r];return n||(n=new Intl.DateTimeFormat(e,t),dt[r]=n),n}let ft={};function yt(e,t={}){var r=JSON.stringify([e,t]);let n=ft[r];return n||(n=new Intl.NumberFormat(e,t),ft[r]=n),n}let gt={};function wt(e,t={}){const{base:r,...n}=t;var s=JSON.stringify([e,n]);let i=gt[s];return i||(i=new Intl.RelativeTimeFormat(e,t),gt[s]=i),i}let vt=null;function pt(){return vt=vt||(new Intl.DateTimeFormat).resolvedOptions().locale}function Tt(e){var r=e.indexOf("-u-");if(-1===r)return[e];{let t;r=e.substring(0,r);try{t=mt(e).resolvedOptions()}catch(e){t=mt(r).resolvedOptions()}var{numberingSystem:e,calendar:n}=t;return[r,e,n]}}function St(e,t,r){return(r||t)&&(e+="-u",r&&(e+="-ca-"+r),t&&(e+="-nu-"+t)),e}function Ot(t){const r=[];for(let e=1;e<=12;e++){var n=L.utc(2016,e,1);r.push(t(n))}return r}function bt(t){const r=[];for(let e=1;e<=7;e++){var n=L.utc(2016,11,13+e);r.push(t(n))}return r}function kt(e,t,r,n,s){e=e.listingMode(r);return"error"===e?null:("en"===e?n:s)(t)}function Mt(e){return(!e.numberingSystem||"latn"===e.numberingSystem)&&("latn"===e.numberingSystem||!e.locale||e.locale.startsWith("en")||"latn"===new Intl.DateTimeFormat(e.intl).resolvedOptions().numberingSystem)}class Nt{constructor(e,t,r){this.padTo=r.padTo||0,this.floor=r.floor||!1;const{padTo:n,floor:s,...i}=r;if(!t||0{const t=n?{month:r,day:"numeric"}:{month:r},e=n?"format":"standalone";return this.monthsCache[e][r]||(this.monthsCache[e][r]=Ot(e=>this.extract(e,t,"month"))),this.monthsCache[e][r]})}weekdays(r,n=!1,e=!0){return kt(this,r,e,Le,()=>{const t=n?{weekday:r,year:"numeric",month:"long",day:"numeric"}:{weekday:r},e=n?"format":"standalone";return this.weekdaysCache[e][r]||(this.weekdaysCache[e][r]=bt(e=>this.extract(e,t,"weekday"))),this.weekdaysCache[e][r]})}meridiems(e=!0){return kt(this,void 0,e,()=>ze,()=>{if(!this.meridiemCache){const t={hour:"numeric",hourCycle:"h12"};this.meridiemCache=[L.utc(2016,11,13,9),L.utc(2016,11,13,19)].map(e=>this.extract(e,t,"dayperiod"))}return this.meridiemCache})}eras(e,t=!0){return kt(this,e,t,_e,()=>{const t={era:e};return this.eraCache[e]||(this.eraCache[e]=[L.utc(-40,1,1),L.utc(2017,1,1)].map(e=>this.extract(e,t,"era"))),this.eraCache[e]})}extract(e,t,r){const n=this.dtFormatter(e,t),s=n.formatToParts(),i=s.find(e=>e.type.toLowerCase()===r);return i?i.value:null}numberFormatter(e={}){return new Nt(this.intl,e.forceSimple||this.fastNumbers,e)}dtFormatter(e,t={}){return new Dt(e,this.intl,t)}relFormatter(e={}){return new Et(this.intl,this.isEnglish(),e)}listFormatter(e={}){return ht(this.intl,e)}isEnglish(){return"en"===this.locale||"dev-us"===this.locale.toLowerCase()||new Intl.DateTimeFormat(this.intl).resolvedOptions().locale.startsWith("dev-us")}equals(e){return this.locale===e.locale&&this.numberingSystem===e.numberingSystem&&this.outputCalendar===e.outputCalendar}}function a(...e){e=e.reduce((e,t)=>e+t.source,"");return RegExp(`^${e}$`)}function g(...e){return i=>e.reduce(([e,t,r],n)=>{var[n,r,s]=n(i,r);return[{...e,...n},r||t,s]},[{},null,1]).slice(0,2)}function p(e,...t){if(null!=e)for(var[r,n]of t){r=r.exec(e);if(r)return n(r)}return[null,null]}function Vt(...s){return(e,t)=>{const r={};let n;for(n=0;nvoid 0!==e&&(t||e&&l)?-e:e;return[{years:c(m(t)),months:c(m(r)),weeks:c(m(n)),days:c(m(s)),hours:c(m(i)),minutes:c(m(a)),seconds:c(m(o),"-0"===o),milliseconds:c(fe(u),e)}]}const jt={GMT:0,EDT:-240,EST:-300,CDT:-300,CST:-360,MDT:-360,MST:-420,PDT:-420,PST:-480};function _t(e,t,r,n,s,i,a){const o={year:2===t.length?Se(d(t)):d(t),month:Ve.indexOf(r)+1,day:d(n),hour:d(s),minute:d(i)};return a&&(o.second=d(a)),e&&(o.weekday=3O(n[t])?e:(e&&wr(r,n,e,n,t),t),null)}class V{constructor(e){var t="longterm"===e.conversionAccuracy||!1;this.values=e.values,this.loc=e.loc||M.create(),this.conversionAccuracy=t?"longterm":"casual",this.invalid=e.invalid||null,this.matrix=t?yr:mr,this.isLuxonDuration=!0}static fromMillis(e,t){return V.fromObject({milliseconds:e},t)}static fromObject(e,t={}){if(null==e||"object"!=typeof e)throw new o("Duration.fromObject: argument expected to be an object, got "+(null===e?"null":typeof e));return new V({values:Me(e,V.normalizeUnit),loc:M.fromObject(t),conversionAccuracy:t.conversionAccuracy})}static fromDurationLike(e){if(c(e))return V.fromMillis(e);if(V.isDuration(e))return e;if("object"==typeof e)return V.fromObject(e);throw new o(`Unknown duration argument ${e} of type `+typeof e)}static fromISO(e,t){var[r]=ir(e);return r?V.fromObject(r,t):V.invalid("unparsable",`the input "${e}" can't be parsed as ISO 8601`)}static fromISOTime(e,t){var[r]=or(e);return r?V.fromObject(r,t):V.invalid("unparsable",`the input "${e}" can't be parsed as ISO 8601`)}static invalid(e,t=null){if(!e)throw new o("need to specify a reason the Duration is invalid");e=e instanceof y?e:new y(e,t);if(k.throwOnInvalid)throw new A(e);return new V({invalid:e})}static normalizeUnit(e){var t={year:"years",years:"years",quarter:"quarters",quarters:"quarters",month:"months",months:"months",week:"weeks",weeks:"weeks",day:"days",days:"days",hour:"hours",hours:"hours",minute:"minutes",minutes:"minutes",second:"seconds",seconds:"seconds",millisecond:"milliseconds",milliseconds:"milliseconds"}[e&&e.toLowerCase()];if(t)return t;throw new _(e)}static isDuration(e){return e&&e.isLuxonDuration||!1}get locale(){return this.isValid?this.loc.locale:null}get numberingSystem(){return this.isValid?this.loc.numberingSystem:null}toFormat(e,t={}){t={...t,floor:!1!==t.round&&!1!==t.floor};return this.isValid?f.create(this.loc,t).formatDurationFromString(this,e):"Invalid Duration"}toHuman(r={}){var e=D.map(e=>{var t=this.values[e];return O(t)?null:this.loc.numberFormatter({style:"unit",unitDisplay:"long",...r,unit:e.slice(0,-1)}).format(t)}).filter(e=>e);return this.loc.listFormatter({type:"conjunction",style:r.listStyle||"narrow",...r}).format(e)}toObject(){return this.isValid?{...this.values}:{}}toISO(){if(!this.isValid)return null;let e="P";return 0!==this.years&&(e+=this.years+"Y"),0===this.months&&0===this.quarters||(e+=this.months+3*this.quarters+"M"),0!==this.weeks&&(e+=this.weeks+"W"),0!==this.days&&(e+=this.days+"D"),0===this.hours&&0===this.minutes&&0===this.seconds&&0===this.milliseconds||(e+="T"),0!==this.hours&&(e+=this.hours+"H"),0!==this.minutes&&(e+=this.minutes+"M"),0===this.seconds&&0===this.milliseconds||(e+=ye(this.seconds+this.milliseconds/1e3,3)+"S"),"P"===e&&(e+="T0S"),e}toISOTime(e={}){if(!this.isValid)return null;var t=this.toMillis();if(t<0||864e5<=t)return null;e={suppressMilliseconds:!1,suppressSeconds:!1,includePrefix:!1,format:"extended",...e};const r=this.shiftTo("hours","minutes","seconds","milliseconds");let n="basic"===e.format?"hhmm":"hh:mm",s=(e.suppressSeconds&&0===r.seconds&&0===r.milliseconds||(n+="basic"===e.format?"ss":":ss",e.suppressMilliseconds&&0===r.milliseconds||(n+=".SSS")),r.toFormat(n));return s=e.includePrefix?"T"+s:s}toJSON(){return this.toISO()}toString(){return this.toISO()}toMillis(){return this.as("milliseconds")}valueOf(){return this.toMillis()}plus(e){if(!this.isValid)return this;const t=V.fromDurationLike(e),r={};for(const n of D)(h(t.values,n)||h(this.values,n))&&(r[n]=t.get(n)+this.get(n));return E(this,{values:r},!0)}minus(e){if(!this.isValid)return this;const t=V.fromDurationLike(e);return this.plus(t.negate())}mapUnits(e){if(!this.isValid)return this;const t={};for(const r of Object.keys(this.values))t[r]=ke(e(this.values[r],r));return E(this,{values:t},!0)}get(e){return this[V.normalizeUnit(e)]}set(e){return this.isValid?E(this,{values:{...this.values,...Me(e,V.normalizeUnit)}}):this}reconfigure({locale:e,numberingSystem:t,conversionAccuracy:r}={}){const n=this.loc.clone({locale:e,numberingSystem:t}),s={loc:n};return r&&(s.conversionAccuracy=r),E(this,s)}as(e){return this.isValid?this.shiftTo(e).get(e):NaN}normalize(){if(!this.isValid)return this;var e=this.toObject();return vr(this.matrix,e),E(this,{values:e},!0)}shiftTo(...e){if(!this.isValid)return this;if(0===e.length)return this;e=e.map(e=>V.normalizeUnit(e));const t={},r={},n=this.toObject();let s;for(const a of D)if(0<=e.indexOf(a)){s=a;let e=0;for(const o in r)e+=this.matrix[o][a]*r[o],r[o]=0;c(n[a])&&(e+=n[a]);var i=Math.trunc(e);t[a]=i,r[a]=(1e3*e-1e3*i)/1e3;for(const u in n)D.indexOf(u)>D.indexOf(a)&&wr(this.matrix,n,u,t,a)}else c(n[a])&&(r[a]=n[a]);for(const l in r)0!==r[l]&&(t[s]+=l===s?r[l]:r[l]/this.matrix[s][l]);return E(this,{values:t},!0).normalize()}negate(){if(!this.isValid)return this;const e={};for(const t of Object.keys(this.values))e[t]=0===this.values[t]?0:-this.values[t];return E(this,{values:e},!0)}get years(){return this.isValid?this.values.years||0:NaN}get quarters(){return this.isValid?this.values.quarters||0:NaN}get months(){return this.isValid?this.values.months||0:NaN}get weeks(){return this.isValid?this.values.weeks||0:NaN}get days(){return this.isValid?this.values.days||0:NaN}get hours(){return this.isValid?this.values.hours||0:NaN}get minutes(){return this.isValid?this.values.minutes||0:NaN}get seconds(){return this.isValid?this.values.seconds||0:NaN}get milliseconds(){return this.isValid?this.values.milliseconds||0:NaN}get isValid(){return null===this.invalid}get invalidReason(){return this.invalid?this.invalid.reason:null}get invalidExplanation(){return this.invalid?this.invalid.explanation:null}equals(e){if(!this.isValid||!e.isValid)return!1;if(!this.loc.equals(e.loc))return!1;for(const n of D)if(t=this.values[n],r=e.values[n],!(void 0===t||0===t?void 0===r||0===r:t===r))return!1;var t,r;return!0}}const pr="Invalid Interval";function Tr(e,t){return e&&e.isValid?t&&t.isValid?te}isBefore(e){return!!this.isValid&&this.e<=e}contains(e){return!!this.isValid&&(this.s<=e&&this.e>e)}set({start:e,end:t}={}){return this.isValid?I.fromDateTimes(e||this.s,t||this.e):this}splitAt(...e){if(!this.isValid)return[];const t=e.map(Sn).filter(e=>this.contains(e)).sort(),r=[];let n=this["s"],s=0;for(;n+this.e?this.e:i;r.push(I.fromDateTimes(n,i)),n=i,s+=1}return r}splitBy(e){const t=V.fromDurationLike(e);if(!this.isValid||!t.isValid||0===t.as("milliseconds"))return[];let r=this["s"],n=1,s;const i=[];for(;re*n));s=+a>+this.e?this.e:a,i.push(I.fromDateTimes(r,s)),r=s,n+=1}return i}divideEqually(e){return this.isValid?this.splitBy(this.length()/e).slice(0,e):[]}overlaps(e){return this.e>e.s&&this.s=e.e)}equals(e){return!(!this.isValid||!e.isValid)&&(this.s.equals(e.s)&&this.e.equals(e.e))}intersection(e){if(!this.isValid)return this;var t=(this.s>e.s?this:e).s,e=(this.ee.e?this:e).e;return I.fromDateTimes(t,e)}static merge(e){const[t,r]=e.sort((e,t)=>e.s-t.s).reduce(([e,t],r)=>t?t.overlaps(r)||t.abutsStart(r)?[e,t.union(r)]:[e.concat([t]),r]:[e,r],[[],null]);return r&&t.push(r),t}static xor(e){let t=null,r=0;const n=[],s=e.map(e=>[{time:e.s,type:"s"},{time:e.e,type:"e"}]),i=Array.prototype.concat(...s),a=i.sort((e,t)=>e.time-t.time);for(const o of a)r+="s"===o.type?1:-1,t=1===r?o.time:(t&&+t!=+o.time&&n.push(I.fromDateTimes(t,o.time)),null);return I.merge(n)}difference(...e){return I.xor([this].concat(e)).map(e=>this.intersection(e)).filter(e=>e&&!e.isEmpty())}toString(){return this.isValid?`[${this.s.toISO()} – ${this.e.toISO()})`:pr}toISO(e){return this.isValid?this.s.toISO(e)+"/"+this.e.toISO(e):pr}toISODate(){return this.isValid?this.s.toISODate()+"/"+this.e.toISODate():pr}toISOTime(e){return this.isValid?this.s.toISOTime(e)+"/"+this.e.toISOTime(e):pr}toFormat(e,{separator:t=" – "}={}){return this.isValid?""+this.s.toFormat(e)+t+this.e.toFormat(e):pr}toDuration(e,t){return this.isValid?this.e.diff(this.s,e,t):V.invalid(this.invalidReason)}mapEndpoints(e){return I.fromDateTimes(e(this.s),e(this.e))}}class Sr{static hasDST(e=k.defaultZone){const t=L.now().setZone(e).set({month:12});return!e.isUniversal&&t.offset!==t.set({month:6}).offset}static isValidIANAZone(e){return w.isValidZone(e)}static normalizeZone(e){return b(e,k.defaultZone)}static months(e="long",{locale:t=null,numberingSystem:r=null,locObj:n=null,outputCalendar:s="gregory"}={}){return(n||M.create(t,r,s)).months(e)}static monthsFormat(e="long",{locale:t=null,numberingSystem:r=null,locObj:n=null,outputCalendar:s="gregory"}={}){return(n||M.create(t,r,s)).months(e,!0)}static weekdays(e="long",{locale:t=null,numberingSystem:r=null,locObj:n=null}={}){return(n||M.create(t,r,null)).weekdays(e)}static weekdaysFormat(e="long",{locale:t=null,numberingSystem:r=null,locObj:n=null}={}){return(n||M.create(t,r,null)).weekdays(e,!0)}static meridiems({locale:e=null}={}){return M.create(e).meridiems()}static eras(e="short",{locale:t=null}={}){return M.create(t,null,"gregory").eras(e)}static features(){return{relative:he()}}}function Or(e,t){var r=e=>e.toUTC(0,{keepLocalTime:!0}).startOf("day").valueOf(),t=r(t)-r(e);return Math.floor(V.fromMillis(t).as("days"))}function br(e,t,r,n){let[s,i,a,o]=function(t,r,e){var n,s;const i={};let a,o;for([n,s]of[["years",(e,t)=>t.year-e.year],["quarters",(e,t)=>t.quarter-e.quarter],["months",(e,t)=>t.month-e.month+12*(t.year-e.year)],["weeks",(e,t)=>{e=Or(e,t);return(e-e%7)/7}],["days",Or]])if(0<=e.indexOf(n)){a=n;let e=s(t,r);(o=t.plus({[n]:e}))>r?(t=t.plus({[n]:e-1}),--e):t=o,i[n]=e}return[t,i,o,a]}(e,t,r);e=t-s,r=r.filter(e=>0<=["hours","minutes","seconds","milliseconds"].indexOf(e)),0===r.length&&(a=ae){return{regex:e,deser:([e])=>t(function(t){let r=parseInt(t,10);if(isNaN(r)){r="";for(let e=0;ee.findIndex(e=>xr(t)===xr(e))+r}}function Cr(e,t){return{regex:e,deser:([,e,t])=>be(e,t),groups:t}}function Fr(e){return{regex:e,deser:([e])=>e}}const Zr={year:{"2-digit":"yy",numeric:"yyyyy"},month:{numeric:"M","2-digit":"MM",short:"MMM",long:"MMMM"},day:{numeric:"d","2-digit":"dd"},weekday:{short:"EEE",long:"EEEE"},dayperiod:"a",dayPeriod:"a",hour:{numeric:"h","2-digit":"hh"},minute:{numeric:"m","2-digit":"mm"},second:{numeric:"s","2-digit":"ss"}};let Lr=null;function zr(e,t){if(e.literal)return e;const s=f.macroTokenToFormatOpts(e.val);if(!s)return e;const r=f.create(t,s),n=r.formatDateTimeParts(Lr=Lr||L.fromMillis(1555555555555)),i=n.map(t=>{{var r=s,{type:t,value:n}=t;if("literal"===t)return{literal:!0,val:n};n=r[t];let e=Zr[t];return(e="object"==typeof e?e[n]:e)?{literal:!1,val:e}:void 0}});return i.includes(void 0)?e:i}function qr(g,e,t){t=f.parseFormat(t),i=g;const r=Array.prototype.concat(...t.map(e=>zr(e,i))),n=r.map(e=>{{var t=e,r=g;const n=x(r),s=x(r,"{2}"),i=x(r,"{3}"),a=x(r,"{4}"),o=x(r,"{6}"),u=x(r,"{1,2}"),l=x(r,"{1,3}"),c=x(r,"{1,6}"),h=x(r,"{1,9}"),d=x(r,"{2,4}"),m=x(r,"{4,6}"),f=e=>({regex:RegExp(e.val.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g,"\\$&")),deser:([e])=>e,literal:!0}),y=(e=>{if(t.literal)return f(e);switch(e.val){case"G":return F(r.eras("short",!1),0);case"GG":return F(r.eras("long",!1),0);case"y":return C(c);case"yy":return C(d,Se);case"yyyy":return C(a);case"yyyyy":return C(m);case"yyyyyy":return C(o);case"M":return C(u);case"MM":return C(s);case"MMM":return F(r.months("short",!0,!1),1);case"MMMM":return F(r.months("long",!0,!1),1);case"L":return C(u);case"LL":return C(s);case"LLL":return F(r.months("short",!1,!1),1);case"LLLL":return F(r.months("long",!1,!1),1);case"d":return C(u);case"dd":return C(s);case"o":return C(l);case"ooo":return C(i);case"HH":return C(s);case"H":return C(u);case"hh":return C(s);case"h":return C(u);case"mm":return C(s);case"m":case"q":return C(u);case"qq":return C(s);case"s":return C(u);case"ss":return C(s);case"S":return C(l);case"SSS":return C(i);case"u":return Fr(h);case"uu":return Fr(u);case"uuu":return C(n);case"a":return F(r.meridiems(),0);case"kkkk":return C(a);case"kk":return C(d,Se);case"W":return C(u);case"WW":return C(s);case"E":case"c":return C(n);case"EEE":return F(r.weekdays("short",!1,!1),1);case"EEEE":return F(r.weekdays("long",!1,!1),1);case"ccc":return F(r.weekdays("short",!0,!1),1);case"cccc":return F(r.weekdays("long",!0,!1),1);case"Z":case"ZZ":return Cr(new RegExp(`([+-]${u.source})(?::(${s.source}))?`),2);case"ZZZ":return Cr(new RegExp(`([+-]${u.source})(${s.source})?`),2);case"z":return Fr(/[a-z_+-/]{1,256}?/i);default:return f(e)}})(t)||{invalidReason:Dr};return y.token=t,y}}),s=n.find(e=>e.invalidReason);var i;if(s)return{input:e,tokens:r,invalidReason:s.invalidReason};var[t,a]=[`^${(t=n).map(e=>e.regex).reduce((e,t)=>`${e}(${t.source})`,"")}$`,t],t=RegExp(t,"i"),[a,o]=function(e,t,r){const n=e.match(t);if(n){const s={};let e=1;for(const i in r)if(h(r,i)){const a=r[i],o=a.groups?a.groups+1:1;!a.literal&&a.token&&(s[a.token.val[0]]=a.deser(n.slice(e,e+o))),e+=o}return[n,s]}return[n,{}]}(e,t,a),[u,l,c]=o?function(n){let e=null,t;return O(n.z)||(e=w.create(n.z)),O(n.Z)||(e=e||new v(n.Z),t=n.Z),O(n.q)||(n.M=3*(n.q-1)+1),O(n.h)||(n.h<12&&1===n.a?n.h+=12:12===n.h&&0===n.a&&(n.h=0)),0===n.G&&n.y&&(n.y=-n.y),O(n.u)||(n.S=fe(n.u)),[Object.keys(n).reduce((e,t)=>{var r=(e=>{switch(e){case"S":return"millisecond";case"s":return"second";case"m":return"minute";case"h":case"H":return"hour";case"d":return"day";case"o":return"ordinal";case"L":case"M":return"month";case"y":return"year";case"E":case"c":return"weekday";case"W":return"weekNumber";case"k":return"weekYear";case"q":return"quarter";default:return null}})(t);return r&&(e[r]=n[t]),e},{}),e,t]}(o):[null,null,void 0];if(h(o,"a")&&h(o,"H"))throw new j("Can't include meridiem when specifying 24-hour format");return{input:e,tokens:r,regex:t,rawMatches:a,matches:o,result:u,zone:l,specificOffset:c}}function Ar(e,t,r){var{result:e,zone:t,specificOffset:r,invalidReason:n}=qr(e,t,r);return[e,t,r,n]}const jr=[0,31,59,90,120,151,181,212,243,273,304,334],_r=[0,31,60,91,121,152,182,213,244,274,305,335];function Z(e,t){return new y("unit out of range",`you specified ${t} (of type ${typeof t}) as a ${e}, which is invalid`)}function Ur(e,t,r){const n=new Date(Date.UTC(e,t-1,r));e<100&&0<=e&&n.setUTCFullYear(n.getUTCFullYear()-1900);t=n.getUTCDay();return 0===t?7:t}function $r(e,t,r){return r+(ge(e)?_r:jr)[t-1]}function Hr(e,t){const r=ge(e)?_r:jr,n=r.findIndex(e=>eTe(t)?(a=t+1,i=1):a=t,{weekYear:a,weekNumber:i,weekday:r,...De(e)}}function Rr(e){var{weekYear:t,weekNumber:r,weekday:n}=e,s=Ur(t,1,4),i=we(t);let a=7*r+n-s-3,o;a<1?(o=t-1,a+=we(o)):a>i?(o=t+1,a-=we(t)):o=t;var{month:r,day:n}=Hr(o,a);return{year:o,month:r,day:n,...De(e)}}function Jr(e){var{year:t,month:r,day:n}=e;return{year:t,ordinal:$r(t,r,n),...De(e)}}function Yr(e){var{year:t,ordinal:r}=e,{month:r,day:n}=Hr(t,r);return{year:t,month:r,day:n,...De(e)}}function Pr(e){var t=le(e.weekYear),r=u(e.weekNumber,1,Te(e.weekYear)),n=u(e.weekday,1,7);return t?r?!n&&Z("weekday",e.weekday):Z("week",e.week):Z("weekYear",e.weekYear)}function Gr(e){var t=le(e.year),r=u(e.ordinal,1,we(e.year));return t?!r&&Z("ordinal",e.ordinal):Z("year",e.year)}function Br(e){var t=le(e.year),r=u(e.month,1,12),n=u(e.day,1,ve(e.year,e.month));return t?r?!n&&Z("day",e.day):Z("month",e.month):Z("year",e.year)}function Qr(e){var{hour:e,minute:t,second:r,millisecond:n}=e,s=u(e,0,23)||24===e&&0===t&&0===r&&0===n,i=u(t,0,59),a=u(r,0,59),o=u(n,0,999);return s?i?a?!o&&Z("millisecond",n):Z("second",r):Z("minute",t):Z("hour",e)}const Kr="Invalid DateTime";function Xr(e){return new y("unsupported zone",`the zone "${e.name}" is not supported`)}function en(e){return null===e.weekData&&(e.weekData=Wr(e.c)),e.weekData}function tn(e,t){e={ts:e.ts,zone:e.zone,c:e.c,o:e.o,loc:e.loc,invalid:e.invalid};return new L({...e,...t,old:e})}function rn(e,t,r){let n=e-60*t*1e3;var s=r.offset(n);if(t===s)return[n,t];n-=60*(s-t)*1e3;t=r.offset(n);return s===t?[n,s]:[e-60*Math.min(s,t)*1e3,Math.max(s,t)]}function nn(e,t){e+=60*t*1e3;const r=new Date(e);return{year:r.getUTCFullYear(),month:r.getUTCMonth()+1,day:r.getUTCDate(),hour:r.getUTCHours(),minute:r.getUTCMinutes(),second:r.getUTCSeconds(),millisecond:r.getUTCMilliseconds()}}function sn(e,t,r){return rn(pe(e),t,r)}function an(e,t){var r=e.o,n=e.c.year+Math.trunc(t.years),s=e.c.month+Math.trunc(t.months)+3*Math.trunc(t.quarters),n={...e.c,year:n,month:s,day:Math.min(e.c.day,ve(n,s))+Math.trunc(t.days)+7*Math.trunc(t.weeks)},s=V.fromObject({years:t.years-Math.trunc(t.years),quarters:t.quarters-Math.trunc(t.quarters),months:t.months-Math.trunc(t.months),weeks:t.weeks-Math.trunc(t.weeks),days:t.days-Math.trunc(t.days),hours:t.hours,minutes:t.minutes,seconds:t.seconds,milliseconds:t.milliseconds}).as("milliseconds");let[i,a]=rn(pe(n),r,e.zone);return 0!==s&&(i+=s,a=e.zone.offset(i)),{ts:i,o:a}}function on(e,t,r,n,s,i){var{setZone:a,zone:o}=r;if(e&&0!==Object.keys(e).length){const u=t||o,l=L.fromObject(e,{...r,zone:u,specificOffset:i});return a?l:l.setZone(o)}return L.invalid(new y("unparsable",`the input "${s}" can't be parsed as `+n))}function un(e,t,r=!0){return e.isValid?f.create(M.create("en-US"),{allowZ:r,forceSimple:!0}).formatDateTimeFromString(e,t):null}function ln(e,t){var r=9999{e=ye(e,i||s.calendary?0:2,!0);const r=n.loc.clone(s).relFormatter(s);return r.format(e,t)},r=e=>s.calendary?n.hasSame(t,e)?0:n.startOf(e).diff(t.startOf(e),e).get(e):n.diff(t,e).get(e);if(s.unit)return e(r(s.unit),s.unit);for(const o of s.units){var a=r(o);if(1<=Math.abs(a))return e(a,o)}return e(nthis.set({month:1,day:1}).offset||this.offset>this.set({month:5}).offset)}get isInLeapYear(){return ge(this.year)}get daysInMonth(){return ve(this.year,this.month)}get daysInYear(){return this.isValid?we(this.year):NaN}get weeksInWeekYear(){return this.isValid?Te(this.weekYear):NaN}resolvedLocaleOptions(e={}){var{locale:e,numberingSystem:t,calendar:r}=f.create(this.loc.clone(e),e).resolvedOptions(this);return{locale:e,numberingSystem:t,outputCalendar:r}}toUTC(e=0,t={}){return this.setZone(v.instance(e),t)}toLocal(){return this.setZone(k.defaultZone)}setZone(t,{keepLocalTime:r=!1,keepCalendarTime:n=!1}={}){if((t=b(t,k.defaultZone)).equals(this.zone))return this;if(t.isValid){let e=this.ts;return(r||n)&&(r=t.offset(this.ts),n=this.toObject(),[e]=sn(n,r,t)),tn(this,{ts:e,zone:t})}return L.invalid(Xr(t))}reconfigure({locale:e,numberingSystem:t,outputCalendar:r}={}){e=this.loc.clone({locale:e,numberingSystem:t,outputCalendar:r});return tn(this,{loc:e})}setLocale(e){return this.reconfigure({locale:e})}set(e){if(!this.isValid)return this;var e=Me(e,wn),t=!O(e.weekYear)||!O(e.weekNumber)||!O(e.weekday),r=!O(e.ordinal),n=!O(e.year),s=!O(e.month)||!O(e.day),i=e.weekYear||e.weekNumber;if((n||s||r)&&i)throw new j("Can't mix weekYear/weekNumber units with year/month/day or ordinals");if(s&&r)throw new j("Can't mix ordinal dates with month/day");let a;t?a=Rr({...Wr(this.c),...e}):O(e.ordinal)?(a={...this.toObject(),...e},O(e.day)&&(a.day=Math.min(ve(a.year,a.month),a.day))):a=Yr({...Jr(this.c),...e});var[n,i]=sn(a,this.o,this.zone);return tn(this,{ts:n,o:i})}plus(e){return this.isValid?tn(this,an(this,V.fromDurationLike(e))):this}minus(e){return this.isValid?tn(this,an(this,V.fromDurationLike(e).negate())):this}startOf(e){if(!this.isValid)return this;const t={},r=V.normalizeUnit(e);switch(r){case"years":t.month=1;case"quarters":case"months":t.day=1;case"weeks":case"days":t.hour=0;case"hours":t.minute=0;case"minutes":t.second=0;case"seconds":t.millisecond=0}return"weeks"===r&&(t.weekday=1),"quarters"===r&&(e=Math.ceil(this.month/3),t.month=3*(e-1)+1),this.set(t)}endOf(e){return this.isValid?this.plus({[e]:1}).startOf(e).minus(1):this}toFormat(e,t={}){return this.isValid?f.create(this.loc.redefaultToEN(t)).formatDateTimeFromString(this,e):Kr}toLocaleString(e=U,t={}){return this.isValid?f.create(this.loc.clone(t),e).formatDateTime(this):Kr}toLocaleParts(e={}){return this.isValid?f.create(this.loc.clone(e),e).formatDateTimeParts(this):[]}toISO({format:e="extended",suppressSeconds:t=!1,suppressMilliseconds:r=!1,includeOffset:n=!0,extendedZone:s=!1}={}){if(!this.isValid)return null;var e="extended"===e,i=ln(this,e);return(i+="T")+cn(this,e,t,r,n,s)}toISODate({format:e="extended"}={}){return this.isValid?ln(this,"extended"===e):null}toISOWeekDate(){return un(this,"kkkk-'W'WW-c")}toISOTime({suppressMilliseconds:e=!1,suppressSeconds:t=!1,includeOffset:r=!0,includePrefix:n=!1,extendedZone:s=!1,format:i="extended"}={}){return this.isValid?(n?"T":"")+cn(this,"extended"===i,t,e,r,s):null}toRFC2822(){return un(this,"EEE, dd LLL yyyy HH:mm:ss ZZZ",!1)}toHTTP(){return un(this.toUTC(),"EEE, dd LLL yyyy HH:mm:ss 'GMT'")}toSQLDate(){return this.isValid?ln(this,!0):null}toSQLTime({includeOffset:e=!0,includeZone:t=!1,includeOffsetSpace:r=!0}={}){let n="HH:mm:ss.SSS";return(t||e)&&(r&&(n+=" "),t?n+="z":e&&(n+="ZZ")),un(this,n,!0)}toSQL(e={}){return this.isValid?this.toSQLDate()+" "+this.toSQLTime(e):null}toString(){return this.isValid?this.toISO():Kr}valueOf(){return this.toMillis()}toMillis(){return this.isValid?this.ts:NaN}toSeconds(){return this.isValid?this.ts/1e3:NaN}toUnixInteger(){return this.isValid?Math.floor(this.ts/1e3):NaN}toJSON(){return this.toISO()}toBSON(){return this.toJSDate()}toObject(e={}){if(!this.isValid)return{};const t={...this.c};return e.includeConfig&&(t.outputCalendar=this.outputCalendar,t.numberingSystem=this.loc.numberingSystem,t.locale=this.loc.locale),t}toJSDate(){return new Date(this.isValid?this.ts:NaN)}diff(e,t="milliseconds",r={}){if(!this.isValid||!e.isValid)return V.invalid("created by diffing an invalid DateTime");r={locale:this.locale,numberingSystem:this.numberingSystem,...r};const n=de(t).map(V.normalizeUnit),s=e.valueOf()>this.valueOf(),i=s?this:e,a=s?e:this,o=br(i,a,n,r);return s?o.negate():o}diffNow(e="milliseconds",t={}){return this.diff(L.now(),e,t)}until(e){return this.isValid?I.fromDateTimes(this,e):this}hasSame(e,t){if(!this.isValid)return!1;var r=e.valueOf();const n=this.setZone(e.zone,{keepLocalTime:!0});return n.startOf(t)<=r&&r<=n.endOf(t)}equals(e){return this.isValid&&e.isValid&&this.valueOf()===e.valueOf()&&this.zone.equals(e.zone)&&this.loc.equals(e.loc)}toRelative(e={}){if(!this.isValid)return null;var t=e.base||L.fromObject({},{zone:this.zone}),r=e.padding?thise.valueOf(),Math.min);throw new o("min requires all arguments be DateTimes")}static max(...e){if(e.every(L.isDateTime))return me(e,e=>e.valueOf(),Math.max);throw new o("max requires all arguments be DateTimes")}static fromFormatExplain(e,t,r={}){var{locale:r=null,numberingSystem:n=null}=r;return qr(M.fromOpts({locale:r,numberingSystem:n,defaultToEN:!0}),e,t)}static fromStringExplain(e,t,r={}){return L.fromFormatExplain(e,t,r)}static get DATE_SHORT(){return U}static get DATE_MED(){return $}static get DATE_MED_WITH_WEEKDAY(){return H}static get DATE_FULL(){return W}static get DATE_HUGE(){return R}static get TIME_SIMPLE(){return J}static get TIME_WITH_SECONDS(){return Y}static get TIME_WITH_SHORT_OFFSET(){return P}static get TIME_WITH_LONG_OFFSET(){return G}static get TIME_24_SIMPLE(){return B}static get TIME_24_WITH_SECONDS(){return Q}static get TIME_24_WITH_SHORT_OFFSET(){return K}static get TIME_24_WITH_LONG_OFFSET(){return X}static get DATETIME_SHORT(){return ee}static get DATETIME_SHORT_WITH_SECONDS(){return te}static get DATETIME_MED(){return re}static get DATETIME_MED_WITH_SECONDS(){return ne}static get DATETIME_MED_WITH_WEEKDAY(){return se}static get DATETIME_FULL(){return ie}static get DATETIME_FULL_WITH_SECONDS(){return ae}static get DATETIME_HUGE(){return oe}static get DATETIME_HUGE_WITH_SECONDS(){return ue}}function Sn(e){if(L.isDateTime(e))return e;if(e&&e.valueOf&&c(e.valueOf()))return L.fromJSDate(e);if(e&&"object"==typeof e)return L.fromObject(e);throw new o(`Unknown datetime argument: ${e}, of type `+typeof e)}s="2.5.2";export{L as DateTime,V as Duration,v as FixedOffsetZone,w as IANAZone,Sr as Info,I as Interval,nt as InvalidZone,k as Settings,Ge as SystemZone,s as VERSION,i as Zone}; \ No newline at end of file diff --git a/noise/public/javascripts/map.js b/noise/public/javascripts/map.js new file mode 100644 index 0000000..d41b0bf --- /dev/null +++ b/noise/public/javascripts/map.js @@ -0,0 +1,99 @@ +// all function related to the map + +import * as utils from "./chart_utilities.js" +import * as mapn from './map_noise.js' +import * as mapu from './map_utilities.js' + +const mapparams = { + map: null, + bounds: null, + popuptext: '', + clickedSensor: 0, + APIURL: '/srv/getmapdata?', + MAXZOOM: 19 +} + +export async function showMap(params) { + if(sysparams.category === 'noise') { + utils.removeTabs() + if(mapparams.map && mapparams.map.remove) { + mapparams.map.off(); + mapparams.map.remove(); + } + } + mapparams.map = L.map('map', {scrollWheelZoom: false}).setView(params.center.coords, parseInt(params.zoom)) + L.tileLayer('https://tile.openstreetmap.org/{z}/{x}/{y}.png', { + maxZoom: mapparams.MAXZOOM, + attribution: '© OpenStreetMap' + }).addTo(mapparams.map) + mapparams.bounds = mapparams.map.getBounds(); + + mapparams.map.on('moveend', async function () { + mapparams.bounds = mapparams.map.getBounds() + await buildMarkers(params, mapparams) + }); + + if(sysparams.category === 'noise'){ + mapn.buildLegend(mapparams) + } + + let lastdate = await buildMarkers(params, mapparams) + mapu.showLastDate(lastdate, mapparams); +} + +const buildMarkers = async (params, mapparams) => { + return mapn.buildMarkers(params, mapparams) +} + +export const setNewCenter = (center) => { + mapparams.map.setView(center) +} + +export const goToMyLocation = () => { + if (!navigator.geolocation) { + alert('Geolocation wird von diesem Browser nicht unterstützt'); + return; + } + + navigator.geolocation.getCurrentPosition( + (position) => { + const lat = position.coords.latitude; + const lon = position.coords.longitude; + const accuracy = position.coords.accuracy; + + // Karte zur aktuellen Position zentrieren + mapparams.map.setView([lat, lon], 15); + + // Optional: Marker an aktueller Position setzen + const myLocationMarker = L.marker([lat, lon], { + icon: L.icon({ + iconUrl: 'data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI0MCIgaGVpZ2h0PSI0MCI+PGNpcmNsZSBjeD0iMjAiIGN5PSIyMCIgcj0iOCIgZmlsbD0iIzQyODVGNCIgc3Ryb2tlPSJ3aGl0ZSIgc3Ryb2tlLXdpZHRoPSIzIi8+PGNpcmNsZSBjeD0iMjAiIGN5PSIyMCIgcj0iMTUiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzQyODVGNCIgc3Ryb2tlLXdpZHRoPSIyIiBvcGFjaXR5PSIwLjMiLz48L3N2Zz4=', + iconSize: [40, 40], + iconAnchor: [20, 20] + }) + }).addTo(mapparams.map); + + myLocationMarker.bindPopup(`📍 Ihr Standort
Genauigkeit: ±${Math.round(accuracy)}m`).openPopup(); + }, + (error) => { + let errorMsg = 'Position konnte nicht ermittelt werden.'; + switch(error.code) { + case error.PERMISSION_DENIED: + errorMsg = 'Bitte erlauben Sie den Zugriff auf Ihren Standort.'; + break; + case error.POSITION_UNAVAILABLE: + errorMsg = 'Standortinformationen sind nicht verfügbar.'; + break; + case error.TIMEOUT: + errorMsg = 'Die Anfrage ist abgelaufen.'; + break; + } + alert(errorMsg); + }, + { + enableHighAccuracy: true, + timeout: 5000, + maximumAge: 0 + } + ); +} diff --git a/noise/public/javascripts/map_noise.js b/noise/public/javascripts/map_noise.js new file mode 100644 index 0000000..8490655 --- /dev/null +++ b/noise/public/javascripts/map_noise.js @@ -0,0 +1,210 @@ + +import * as dt from './datetime.js' +import * as utils from "./chart_utilities.js" +import { showChart, loadAll} from './showcharts.js' +import * as mapu from './map_utilities.js' +import * as spin from './spinner.js' + +export const colorscale = ['#d53e4f', '#fc8d59', '#fee08b', '#e6f598', '#99d594', '#3288bd', '#808080']; +const dba = [100, 80, 60, 40, 20, 0, -999]; + +export function getColor(d) { + let val = parseInt(d); + for (let i = 0; i < dba.length; i++) { + if (val >= dba[i]) { + return (colorscale[i]); + } + } +} + +export const buildLegend = (mpp) => { + let legend = L.control({position: 'bottomright'}) + legend.onAdd = function () { + let div = L.DomUtil.create('div', 'info legend') + let div_color = L.DomUtil.create('div', 'info legend inner', div) + div_color.innerHTML += 'dbA
'; + // loop through our density intervals and generate a label with a colored square for each interval + for (let i = 0; i < dba.length - 1; i++) { + div_color.innerHTML += + '' + + '  ' + dba[i] + (i == 0 ? '+' : '') + '
' + } + div_color.innerHTML += '  offline' + return div + }; + legend.addTo(mpp.map) +} + +export async function buildMarkers(params, mpp) { + const url = mpp.APIURL + `type=noise&box=${mpp.bounds.toBBoxString()}` + let sensors = await utils.fetchfromserver(url) + if (!sensors.err) { + let markers = L.markerClusterGroup({ + spiderfyOnMaxZoom: true, + showCoverageOnHover: false, + zoomToBoundsOnClick: true, + // disableClusteringAtZoom: 14, + iconCreateFunction: function (cluster) { + let mymarkers = cluster.getAllChildMarkers(); + let color = getMedian(mymarkers); + return new L.Icon({ + iconUrl: buildIcon(color, cluster.getChildCount(), 0), + iconSize: [35, 35] + }); + }, + }); + + for (let x of sensors.values) { + if ((params.weeks > 0) && (x.weeks > params.weeks)) { + continue + } + if (x.value <= -5) { + continue + } + let marker = L.marker([x.location[1], x.location[0]], { + icon: new L.Icon({ + iconUrl: buildIcon(getColor(parseInt(x.value)), 0, x.indoor), + iconSize: [35, 35], + }), + name: x.id, + value: x.value, + url: '/graph?sid=' + x.id, + lastseen: dt.formatISODate(x.lastseen), + indoor: x.indoor + }) + .on('click', e => onMarkerClick(e, true, sensors.popuptxt, params, mpp)) // define click- and + markers.addLayer(marker); + } + mpp.map.addLayer(markers); + return sensors.lastdate + } else { + utils.showError(sensors.err) + } +} + + +function buildIcon(color, n, indoor) { + let x = 100; + if (n < 10) { + x = 200; + } else if (n < 100) { + x = 150; + } + let txtColor = "black"; + if (color == colorscale[5]) { + txtColor = "white" + } + let icon = '' + + ''; + if (n !== 0) { + icon += + '' + n + ''; + } + if(indoor) { + icon += '' + } + icon += ''; + return encodeURI("data:image/svg+xml," + icon).replace(new RegExp('#', 'g'), '%23'); +} + + +async function bauPopupText(item, txts) { + let addr = '' + let offlinetext = ` +${txts.offline} +${txts.lastseen}:${item.lastseen}` + + let normaltext = ` +LA_max:${item.value}` + let popuptext = ` +
+

${txts.sensor}: ${item.name}

+
${addr}
+
+ + + ${item.value < 0 ? offlinetext : normaltext} +
${item.indoor==1 ? "indoor" : ""}
+ +
+
` +return popuptext +} + +async function onMarkerClick(e, click, txts, params, mpp) { + let item = e.target.options; + let popuptext = await bauPopupText(item, txts) + e.target.bindPopup(popuptext).openPopup(); // show the popup + let addr = await utils.addAddress(item.name) + document.querySelector('#infoTitle .addr').innerHTML = `${addr.street}
${addr.plz} ${addr.city}` + let link = document.querySelector('.speciallink') + link.addEventListener('click', async function (ev) { + console.log(`Event clicked: ${mpp.clickedSensor}`) + params.sid = item.name + history.pushState({}, '', `/${params.sid}`) + utils.setCurrentTab('livetab') + spin.spinner.spin(spin.spindiv) + let ok = await showChart(params, utils.ttIndex.live) + spin.spinner.stop() + if (ok) { + // Switch to live tab + let triggerEl = document.querySelector(`#livetab`) + document.querySelectorAll('.tab-button').forEach(tab => tab.classList.remove('active')) + document.querySelectorAll('.tab-pane').forEach(pane => pane.classList.remove('active')) + triggerEl.classList.add('active') + document.getElementById('t_live').classList.add('active') + + params.center.coords = [e.latlng.lat, e.latlng.lng] + ev.preventDefault() + await loadAll(params) + } + }) +} + + +// With all Markers in cluster (markers) calculate the median +// of the values. With this median fetch the color and return it. +// If there are 'offline' sensors (value == -1) strip then before +// calculating the median. If there are only offline sensor, return +// color of value==-1 (dark gray). +function getMedian(markers, value) { + markers.sort(function (a, b) { // first sort, the lowest first + let y1 = a.options.value; + let y2 = b.options.value; + if (y1 < y2) { + return -1; + } + if (y2 < y1) { + return 1; + } + return 0; + }); + // console.log(markers); + let i = 0; // now find the 'offlines' (value == -1) + for (i = 0; i < markers.length; i++) { + if (markers[i].options.value > 0) { + break; + } + } + markers.splice(0, i); // remove these from array + let lang = markers.length; + if (lang > 1) { // + if ((lang % 2) == 1) { // uneven -> + return getColor(markers[(Math.floor(lang / 2))].options.value); // median is in the middle + } else { // evaen -> + lang = lang / 2; // median is mean of both middle values + // console.log(lang); + let wert = (markers[lang - 1].options.value + + markers[lang].options.value) / 2; + return getColor(wert); + } + } else if (lang == 1) { // only one marker -> return its color + return getColor(markers[0].options.value); + } + return getColor(-1); // only offlines +} + diff --git a/noise/public/javascripts/map_utilities.js b/noise/public/javascripts/map_utilities.js new file mode 100644 index 0000000..e6d17b3 --- /dev/null +++ b/noise/public/javascripts/map_utilities.js @@ -0,0 +1,17 @@ +import * as utils from "./chart_utilities.js" +import * as dt from './datetime.js' + +// Show the last date below tha map grafics +export async function showLastDate(ld, mpp) { + let url + if(sysparams) { + url = mpp.APIURL + 'type=noise' + } else { + url = mpp.APIURL + 'type=radiactivity' + } + let sensors = await utils.fetchfromserver(url) + document.querySelector('#mapdate').innerText = `${sensors.valfromtxt} ${dt.formatISODate(ld).slice(0,-3)}` + document.querySelector('#actsensors').innerText = `${sensors.actsensors} ${sensors.registered}` +// $('#actsensors').html(`${erg.count} aktive Sensoren (angemeldet ${allsens})`) +} + diff --git a/noise/public/javascripts/showcharts.js b/noise/public/javascripts/showcharts.js new file mode 100644 index 0000000..ea20b99 --- /dev/null +++ b/noise/public/javascripts/showcharts.js @@ -0,0 +1,141 @@ +import * as utils from "./chart_utilities.js"; +import { DateTime } from './luxon.min.js' +import * as map from "./map.js"; +import {fetchfromserver, showError} from "./chart_utilities.js"; +import * as spin from './spinner.js' + +export const tabtable = [ + {id: 'maptab', type: 'map', container: 'map', func: map.showMap, div: null, dformat: null}, + {id: 'livetab', type: 'live', container: 'dlive', func: showChart, div: 2, dformat: "dd.LL - HH:mm:ss"}, + {id: 'houravgtab', type: 'havg', container: 'dhour', func: showChart, div: 1, dformat: "dd.LL - HH'h'"}, + {id: 'dayavgtab', type: 'davg', container: 'dday', func: showChart, div: 1, dformat: "dd.LL"}, + {id: 'daynighttab', type: 'daynight', container: 'ddaynight', func: showChart, div: 1, dformat: "dd.LL"}, + {id: 'ldentab', type: 'lden', container: 'dlden', func: showChart, div: 1, dformat: "dd.LL"}, +] + + +export async function showChart(params, index) { + let container = tabtable[index].container + let typ = tabtable[index].type + let id = tabtable[index].id + function form() { + for (let item of tabtable) { + if (item.type === typ) { + const d = DateTime.fromMillis(this.x) + const d1 = d.plus({days: 1}) + let fmt = d.toFormat(item.dformat) + if (((typ === 'daynight') && (this.series.name.startsWith('N'))) || (typ === 'lden')) { + fmt = `${d.toFormat('dd')}/${d1.toFormat('dd.LL')}` + } + if (this.series.name === 'Peaks') { + item.div = 0 + } + return '
' + + fmt + '
' + + '● ' + + this.series.name + ':  ' + + Highcharts.numberFormat(this.y, item.div) + + '
' + } + } + } + + function xformat() { + if (typ === 'lden') { + let lbl = this.axis.defaultLabelFormatter.call(this); + this.value += 86400000; + let lbl1 = this.axis.defaultLabelFormatter.call(this); + return parseInt(lbl) + '/' + lbl1; + } else if ((typ === 'live') || (typ === 'havg')) { + let v = this.axis.defaultLabelFormatter.call(this); + if (v.indexOf(':') == -1) { + return '' + v + ''; + } else { + return v; + } + } else { + return this.axis.defaultLabelFormatter.call(this); + } + } + let url = `/srv/getsensordata?sensorid=${params.sid}&data=${typ}&datetime=${params.datetime}` + if (typ === 'live') { + url += `&span=${params.span}` + } else if ((typ === 'havg') || (typ === 'davg')) { + url += `&peak=${params.peak}` + } + console.log(`fetch ${typ} from server ${url}`) + + let errdiv = document.querySelector(`#${id}err`) + errdiv.innerHTML = '' + + let erg = await fetchfromserver(url) + if(sysparams.category === 'noise') { + utils.showTabs() + } + if (!erg.err) { + erg.options.xAxis.labels.formatter = xformat + erg.options.tooltip.formatter = form + let chart = Highcharts.chart(container, erg.options, function (chart) { + utils.addSensorID2chart(chart, { + sid: erg.params.sid, + indoor: erg.params.indoor + }, document.getElementById(container).offsetWidth) + if(erg.info) { + let wbreit = window.innerWidth + let cbreit = chart.chartWidth + let infoposx = wbreit - ((wbreit-cbreit)/2) -200 + let infoposy = chart.plotTop - 80 + chart.renderer.label( + erg.info.text, + infoposx, + infoposy, + 'rect', 0, 0, true) + .css({ + fontSize: '10pt', + color: 'green' + }) + .attr({ + zIndex: 5, + }).add(); + } + }) + return {error: false} + } else { + errdiv.innerHTML = erg.err + return {error: true} + } +} + +export const loadAll = async (params, start = 2, curtab = '') => { + console.log('now load all in Background') + let messzeit = DateTime.now() + if (start == 0) { + map.showMap(params) + start++ + } + if (params.sid !== -1) { + for (let i = start; i < tabtable.length; i++) { + let err = await showChart(params, i) + if(tabtable[i].id === curtab) { + spin.spinner.stop() + let errtxt = document.querySelector(`#${tabtable[i].id}err`).innerHTML + if (errtxt !== '') { + showError(errtxt) + } + } + } + let dauer = DateTime.now().diff(messzeit,['seconds']).toObject().seconds + console.log(`now all loaded. Zeitdauer: ${dauer}`) + } +} + +export const setNoUTC = () => { + Highcharts.setOptions({ + time: { + useUTC: false // Don't use UTC on the charts + }, + accessibility: { // supress warning concerning accessability + enabled: false + } + }); +} \ No newline at end of file diff --git a/noise/public/javascripts/spinner.js b/noise/public/javascripts/spinner.js new file mode 100644 index 0000000..9f9e229 --- /dev/null +++ b/noise/public/javascripts/spinner.js @@ -0,0 +1,27 @@ +// Aufbau eine Spinner, der während des Ladens von AJAX-Requests angezeigt wird + +import { Spinner } from '/spin.js/spin.js' + +const spinneropts = { + lines: 13, // The number of lines to draw + length: 38, // The length of each line + width: 17, // The line thickness + radius: 45, // The radius of the inner circle + scale: 1, // Scales overall size of the spinner + corners: 1, // Corner roundness (0..1) + speed: 1, // Rounds per second + rotate: 0, // The rotation offset + animation: 'spinner-line-fade-quick', // The CSS animation name for the lines + direction: 1, // 1: clockwise, -1: counterclockwise + color: '#404040', // CSS color or array of colors + fadeColor: 'transparent', // CSS color or array of colors + top: '50%', // Top position relative to parent + left: '50%', // Left position relative to parent + shadow: '0 0 1px transparent', // Box-shadow for the lines + zIndex: 2000000000, // The z-index (defaults to 2e9) + className: 'spinner', // The CSS class to assign to the spinner + position: 'absolute', // Element positioning + }; + +export const spinner = new Spinner(spinneropts) +export const spindiv = document.getElementById('spinner') \ No newline at end of file diff --git a/noise/public/stylesheets/MarkerCluster.Default.css b/noise/public/stylesheets/MarkerCluster.Default.css new file mode 100644 index 0000000..bbc8c9f --- /dev/null +++ b/noise/public/stylesheets/MarkerCluster.Default.css @@ -0,0 +1,60 @@ +.marker-cluster-small { + background-color: rgba(181, 226, 140, 0.6); + } +.marker-cluster-small div { + background-color: rgba(110, 204, 57, 0.6); + } + +.marker-cluster-medium { + background-color: rgba(241, 211, 87, 0.6); + } +.marker-cluster-medium div { + background-color: rgba(240, 194, 12, 0.6); + } + +.marker-cluster-large { + background-color: rgba(253, 156, 115, 0.6); + } +.marker-cluster-large div { + background-color: rgba(241, 128, 23, 0.6); + } + + /* IE 6-8 fallback colors */ +.leaflet-oldie .marker-cluster-small { + background-color: rgb(181, 226, 140); + } +.leaflet-oldie .marker-cluster-small div { + background-color: rgb(110, 204, 57); + } + +.leaflet-oldie .marker-cluster-medium { + background-color: rgb(241, 211, 87); + } +.leaflet-oldie .marker-cluster-medium div { + background-color: rgb(240, 194, 12); + } + +.leaflet-oldie .marker-cluster-large { + background-color: rgb(253, 156, 115); + } +.leaflet-oldie .marker-cluster-large div { + background-color: rgb(241, 128, 23); +} + +.marker-cluster { + background-clip: padding-box; + border-radius: 20px; + } +.marker-cluster div { + width: 30px; + height: 30px; + margin-left: 5px; + margin-top: 5px; + + text-align: center; + border-radius: 15px; + font: 12px "Helvetica Neue", Arial, Helvetica, sans-serif; + } +.marker-cluster span { + line-height: 30px; + } \ No newline at end of file diff --git a/noise/public/stylesheets/MarkerCluster.css b/noise/public/stylesheets/MarkerCluster.css new file mode 100644 index 0000000..c60d71b --- /dev/null +++ b/noise/public/stylesheets/MarkerCluster.css @@ -0,0 +1,14 @@ +.leaflet-cluster-anim .leaflet-marker-icon, .leaflet-cluster-anim .leaflet-marker-shadow { + -webkit-transition: -webkit-transform 0.3s ease-out, opacity 0.3s ease-in; + -moz-transition: -moz-transform 0.3s ease-out, opacity 0.3s ease-in; + -o-transition: -o-transform 0.3s ease-out, opacity 0.3s ease-in; + transition: transform 0.3s ease-out, opacity 0.3s ease-in; +} + +.leaflet-cluster-spider-leg { + /* stroke-dashoffset (duration and function) should match with leaflet-marker-icon transform in order to track it exactly */ + -webkit-transition: -webkit-stroke-dashoffset 0.3s ease-out, -webkit-stroke-opacity 0.3s ease-in; + -moz-transition: -moz-stroke-dashoffset 0.3s ease-out, -moz-stroke-opacity 0.3s ease-in; + -o-transition: -o-stroke-dashoffset 0.3s ease-out, -o-stroke-opacity 0.3s ease-in; + transition: stroke-dashoffset 0.3s ease-out, stroke-opacity 0.3s ease-in; +} diff --git a/noise/public/stylesheets/style.css b/noise/public/stylesheets/style.css new file mode 100644 index 0000000..47e7e1f --- /dev/null +++ b/noise/public/stylesheets/style.css @@ -0,0 +1,487 @@ +body { + font-family: Verdana, "Lucida Sans Unicode", sans-serif; + font-size: 16px; + width: 100%; + margin-left: auto; + margin-right: auto; + height: 100%; +} + +html { + height: 100%; +} + +#wrapper { + margin: auto; + width: 100%; + text-align: center; + margin-top: 5px; + height: 100%; + position: relative; +} + +a { + color: #0000EE; +} + +header { + background-color: lightgray; +} +header #hline1 { + margin: 0px 1vw 5px 1vw; + padding-top: 10px; + padding-bottom: 10px; + overflow: auto; +} +header #h1name { + font-size: 148%; + clear: both; + float: left; + text-align: left; +} +header #buttonsRight { + float: right; + margin-right: 1%; +} +header #buttonsRight #btnSet { + margin-right: 20px; +} +header #buttonsRight #btnHelp { + margin-right: 20px; +} +header #buttonsRight #h1datum { + float: right; + margin-top: 5px; +} + +#fenster { + margin-left: 0.5vw; + background: white; + padding-top: 5px; + width: 99vw; +} +#fenster #navi { + float: left; + margin-left: 0.5vw; +} + +#map { + margin-left: 0.5vw; + margin-top: -50px; + width: 98vw; + height: 80vh; + border-radius: 10px; + border: solid 1px seagreen; + overflow: hidden; + z-index: 1; + position: relative; +} +#map #infoTable table, #map #infoTable tr, #map #infoTable td { + margin: auto; + text-align: center; + border: none !important; +} +#map #infoBtn { + margin-top: 10px; + text-align: center; +} +#map #btnMyLocation { + position: absolute; + top: 80px; + right: 10px; + z-index: 1000; + width: 40px; + height: 40px; + padding: 0; + border: 2px solid rgba(0,0,0,0.2); + border-radius: 4px; + background-color: white; + box-shadow: 0 1px 5px rgba(0,0,0,0.4); + cursor: pointer; + font-size: 20px; + line-height: 1; +} +#map #btnMyLocation:hover { + background-color: #f4f4f4; +} +#map #btnMyLocation:active { + box-shadow: 0 1px 3px rgba(0,0,0,0.4); +} + +#mapdateactsens { + width: 98vw; + font-size: 70%; + padding: 10px 0 10px 0; + overflow: auto; +} +#mapdateactsens #mapdate, #mapdateactsens #actsensors { + width: 33%; + float: left; +} +#mapdateactsens #actsensors { + text-align: left; + margin-left: 1vw; +} + +footer { + background-color: lightgray; +} +footer #author { + font-size: 80%; + width: 98vw; + margin: auto; + padding-bottom: 30px; + padding-top: 10px; + height: 50px; +} +footer #author #mailadr { + float: left; +} +footer #author #versn { + float: right; +} + +.info { + padding: 6px 8px; + font: 12px Arial, Helvetica, sans-serif; + background: rgba(255, 255, 255, 0.8); + box-shadow: 0 0 15px rgba(0, 0, 0, 0.2); + border-radius: 5px; +} + +.info h4 { + margin: 0 0 5px; + color: #777; +} + +.legend { + line-height: 18px; + color: #555; + font-size: 110%; +} + +.legend i { + width: 18px; + height: 18px; + float: left; + margin-right: 0px; + opacity: 1; +} + +.leglabel { + padding-top: 20px; +} + +.ndmarker { + position: absolute; + font-size: 24px; +} + +.tab-pane { + margin-top: 44px; +} + +#dlive, #dhour, #dday, #ddaynight, #dlden { + width: 100%; + margin: auto; + height: 80vh; +} + +#dialogError { + color: red; +} + +.modal-content { + border: red solid 2px; +} + +.highcharts-tooltip { + zIndex: 5; +} + +.settings { + text-align: left; +} + +.thelabels { + width: 50%; + float: left; +} + +.theInputs { + float: left; +} + +.rows { + width: 100%; + display: block; +} + +.column { + width: 100%; + display: inline-block; + margin-bottom: 15px; +} + +#startday { + width: 40%; +} + +#nbrofdays, #peaklim, #olderthan { + width: 13%; +} + +.addit { + width: 20%; + border: 1px solid blue; +} + +.klein { + font-size: 80%; +} + +.infoTafel th, td { + margin: auto; + text-align: left; + padding: 0 10px; + border: 1px solid black; + background-color: rgba(238, 238, 238, 0.6); +} + +.infoTafel th { + text-align: center; +} + +.infoTafel tr { + height: 20px; +} + +@media only screen and (max-width: 700px) { + .infoTafel, .legend { + display: none; + } +} + +#stday, #nbday, #pklim, #odth { + display: none; +} + +#first { + display: flex; + align-items: center; + justify-content: center; + text-align: center; +} + +.addr { + font-weight: bold; + margin-bottom: 10px; +} + +.bigger { + font-size: 120%; + font-weight: bold; +} + +.highcharts-container { + margin-top: -10px; +} + +.errdiv { + display: none; +} + +/* Button Styles */ +button { + padding: 8px 16px; + border: 1px solid #ccc; + border-radius: 4px; + background-color: #f8f9fa; + color: #333; + cursor: pointer; + font-size: 14px; + font-family: inherit; +} + +button:hover { + background-color: #e9ecef; +} + +button:active { + background-color: #dee2e6; +} + +#btnSet, #btnHelp { + background-color: #2D6AF8; + color: white; + border-color: #2D6AF8; +} + +#btnSet:hover, #btnHelp:hover { + background-color: #1e5ae8; +} + +#btnMyLocation { + background-color: white; +} + +/* Tabs */ +.tabs { + display: flex; + gap: 2px; + background-color: #f1f1f1; + border-bottom: 1px solid #ccc; + padding: 0; + margin: 0 0.5vw; +} + +.tab-button { + background-color: #2D6AF8; + color: white; + border: none; + border-radius: 4px 4px 0 0; + padding: 10px 20px; + cursor: pointer; + font-size: 14px; + transition: background-color 0.3s; +} + +.tab-button:hover { + background-color: #1e5ae8; +} + +.tab-button.active { + background-color: white; + color: #2D6AF8; + border-bottom: 2px solid white; +} + +.tab-content { + display: block; +} + +.tab-pane { + display: none; +} + +.tab-pane.active { + display: block; +} + +/* Dialog Styles */ +dialog { + border: 1px solid #ccc; + border-radius: 8px; + box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); + padding: 0; + max-width: 600px; + width: 90%; +} + +dialog::backdrop { + background-color: rgba(0, 0, 0, 0.5); +} + +.dialog-content { + display: flex; + flex-direction: column; +} + +.dialog-header { + display: flex; + justify-content: space-between; + align-items: center; + padding: 16px 20px; + border-bottom: 1px solid #dee2e6; + background-color: #f8f9fa; +} + +.dialog-title { + margin: 0; + font-size: 1.25rem; + font-weight: 500; +} + +.dialog-close { + background: none; + border: none; + font-size: 24px; + cursor: pointer; + padding: 0; + width: 30px; + height: 30px; + display: flex; + align-items: center; + justify-content: center; + color: #000; + opacity: 0.5; +} + +.dialog-close:hover { + opacity: 1; + background-color: rgba(0, 0, 0, 0.05); + border-radius: 4px; +} + +.dialog-body { + padding: 20px; + overflow-y: auto; + max-height: 60vh; +} + +.dialog-footer { + display: flex; + justify-content: flex-end; + gap: 10px; + padding: 16px 20px; + border-top: 1px solid #dee2e6; + background-color: #f8f9fa; +} + +.dialog-button { + padding: 8px 16px; + border: 1px solid #ccc; + border-radius: 4px; + cursor: pointer; + font-size: 14px; +} + +.dialog-button.primary { + background-color: #2D6AF8; + color: white; + border-color: #2D6AF8; +} + +.dialog-button.primary:hover { + background-color: #1e5ae8; +} + +.dialog-button.secondary { + background-color: #6c757d; + color: white; + border-color: #6c757d; +} + +.dialog-button.secondary:hover { + background-color: #5a6268; +} + +/* Radio buttons */ +.radio-group { + display: flex; + gap: 15px; +} + +.radio-label { + display: flex; + align-items: center; + gap: 5px; + cursor: pointer; +} + +.radio-label input[type="radio"] { + margin: 0; + cursor: pointer; +} + +/*# sourceMappingURL=style.css.map */ \ No newline at end of file diff --git a/noise/public/stylesheets/style.css.map b/noise/public/stylesheets/style.css.map new file mode 100644 index 0000000..901595e --- /dev/null +++ b/noise/public/stylesheets/style.css.map @@ -0,0 +1 @@ +{"version":3,"sources":["style.sass","style.css"],"names":[],"mappings":"AAYA;EACE,uDAAA;EACA,eAAA;EACA,WAAA;EACA,iBAAA;EACA,kBAAA;EACA,YAAA;ACXF;;ADcA;EACE,YAAA;ACXF;;ADaA;EACE,YAAA;EACA,WAAA;EACA,kBAAA;EAEA,eAAA;EACA,YAAA;EACA,kBAAA;ACXF;;ADaA;EACE,cAAA;ACVF;;ADYA;EACE,2BA9BoB;ACqBtB;ADWE;EACE,uBAAA;EACA,iBAAA;EACA,oBAAA;EACA,cAAA;ACTJ;ADWE;EACE,eAAA;EACA,WAAA;EACA,WAAA;EACA,gBAAA;ACTJ;ADWE;EACE,YAAA;EACA,gBAAA;ACTJ;ADUI;EACE,kBAAA;ACRN;ADSI;EACE,kBAAA;ACPN;ADQI;EACE,YAAA;EACA,eAAA;ACNN;;ADQA;EACE,kBAAA;EACA,iBAAA;EACA,gBAAA;EACA,WAAA;ACLF;ADOE;EACE,WAAA;EACA,kBAAA;ACLJ;;ADOA;EACE,kBAAA;EACA,iBAAA;EACA,WAAA;EACA,YAAA;EACA,mBA7Ec;EA8Ed,0BAAA;EACA,gBAAA;EACA,UAAA;ACJF;ADME;EACE,YAAA;EACA,kBAAA;EACA,uBAAA;ACJJ;ADKE;EACE,gBAAA;EACA,kBAAA;ACHJ;;ADMA;EACE,WAAA;EACA,cAAA;EACA,sBAAA;EACA,cAAA;ACHF;ADKE;EACE,UAAA;EACA,WAAA;ACHJ;ADIE;EACE,gBAAA;EACA,gBAAA;ACFJ;;ADIA;EACE,2BAlGoB;ACiGtB;ADGE;EACE,cAAA;EACA,WAAA;EACA,YAAA;EACA,oBAAA;EACA,iBAAA;EACA,YAAA;ACDJ;ADGI;EACE,WAAA;ACDN;ADGI;EACE,YAAA;ACDN;;ADIA;EACE,gBAAA;EACA,uCAAA;EACA,oCAAA;EACA,uCAAA;EACA,kBAAA;ACDF;;ADGA;EACE,eAAA;EACA,WAAA;ACAF;;ADEA;EACE,iBAAA;EACA,WAAA;EACA,eAAA;ACCF;;ADCA;EACE,WAAA;EACA,YAAA;EACA,WAAA;EACA,iBAAA;EACA,UAAA;ACEF;;ADAA;EACE,iBAAA;ACGF;;ADDA;EACE,kBAAA;EACA,eAAA;ACIF;;ADFA;EACE,gBAAA;ACKF;;ADHA;EACE,WAAA;EACA,YAAA;EACA,YAAA;ACMF;;ADJA;EACE,UAAA;ACOF;;ADLA;EACE,qBAAA;ACQF;;ADNA;EACE,SAAA;ACSF;;ADNA;EACE,gBAAA;ACSF;;ADPA;EACE,UAAA;EACA,WAAA;ACUF;;ADPA;EAEE,WAAA;ACSF;;ADNA;EACE,WAAA;EACA,cAAA;ACSF;;ADPA;EACE,WAAA;EACA,qBAAA;EACA,mBAAA;ACUF;;ADRA;EACE,UAAA;ACWF;;ADTA;EACE,UAAA;ACYF;;ADVA;EACE,UAAA;EACA,sBAAA;ACaF;;ADXA;EACE,cAAA;ACcF;;ADZA;EACE,YAAA;EACA,gBAAA;EACA,eAAA;EACA,uBAAA;EACA,0CAAA;ACeF;;ADbA;EACE,kBAAA;ACgBF;;ADdA;EACE,YAAA;ACiBF;;ADfA;EACE;IACE,aAAA;ECkBF;AACF;ADjBA;EACE,yBArNa;EAsNb,WAAA;ACmBF;;ADjBA;EACE,cAzNa;EA0Nb,yBAAA;ACoBF;;ADjBA;EACE,aAAA;ACoBF;;ADfA;EACE,aAAA;EACA,mBAAA;EACA,uBAAA;EACA,kBAAA;ACkBF;;ADhBA;EACE,iBAAA;EACA,mBAAA;ACmBF;;ADjBA;EACE,eAAA;EACA,iBAAA;ACoBF;;ADlBA;EACE,iBAAA;ACqBF;;ADnBA;EACE,aAAA;ACsBF","file":"style.css"} \ No newline at end of file diff --git a/noise/public/stylesheets/style.sass b/noise/public/stylesheets/style.sass new file mode 100644 index 0000000..717ec42 --- /dev/null +++ b/noise/public/stylesheets/style.sass @@ -0,0 +1,257 @@ +$corner-radius: 10px +$border-color: seagreen +$background: rgb(146, 154, 146) +$divcolor: rgb(162, 227, 162) +$table-stripes: rgb(157, 179, 157) +$fieldset-color: rgb(208, 235, 208) +$button-color: darkslategrey +$header_footer_color: lightgray +$checkboxsize: 1.5 +$inboxwidth: 70px +$navtab-color: #2D6AF8 + +body + font-family: Verdana, 'Lucida Sans Unicode', sans-serif + font-size: 16px + width: 100% + margin-left: auto + margin-right: auto + height: 100% + // background-color: rgba(0,0,0,0.9) + +html + height: 100% + +#wrapper + margin: auto + width: 100% + text-align: center + // background-color: #e9e9e9 + margin-top: 5px + height: 100% + position: relative + +a + color: #0000EE + +header + background-color: $header_footer_color + + #hline1 + margin: 0px 1vw 5px 1vw + padding-top: 10px + padding-bottom: 10px + overflow: auto + + #h1name + font-size: 148% + clear: both + float: left + text-align: left + + #buttonsRight + float: right + margin-right: 1% + #btnSet + margin-right: 20px + #btnHelp + margin-right: 20px + #h1datum + float: right + margin-top: 5px + +#fenster + margin-left: 0.5vw + background: white + padding-top: 5px + width: 99vw + + #navi + float: left + margin-left: 0.5vw + +#map + margin-left: 0.5vw + margin-top: -50px + width: 98vw + height: 80vh + border-radius: $corner-radius + border: solid 1px $border-color + overflow: hidden + z-index: 1 + + #infoTable table, #infoTable tr, #infoTable td + margin: auto + text-align: center + border: none !important + #infoBtn + margin-top: 10px + text-align: center + + +#mapdateactsens + width: 98vw + font-size: 70% + padding: 10px 0 10px 0 + overflow: auto + + #mapdate, #actsensors + width: 33% + float: left + #actsensors + text-align: left + margin-left: 1vw + +footer + background-color: $header_footer_color + + #author + font-size: 80% + width: 98vw + margin: auto + padding-bottom: 30px + padding-top: 10px + height: 50px + + #mailadr + float: left + + #versn + float: right + + +.info + padding: 6px 8px + font: 12px Arial, Helvetica, sans-serif + background: rgba(255,255,255,0.8) + box-shadow: 0 0 15px rgba(0,0,0,0.2) + border-radius: 5px + +.info h4 + margin: 0 0 5px + color: #777 + +.legend + line-height: 18px + color: #555 + font-size: 110% + +.legend i + width: 18px + height: 18px + float: left + margin-right: 0px + opacity: 1 + +.leglabel + padding-top: 20px + +.ndmarker + position: absolute + font-size: 24px + +.tab-pane + margin-top: 44px + +#dlive, #dhour, #dday, #ddaynight, #dlden + width: 100% + margin: auto + height: 80vh + +#dialogError + color: red + +.modal-content + border: red solid 2px + +.highcharts-tooltip + zIndex: 5 + + +.settings + text-align: left + +.thelabels + width: 50% + float: left +// border: 1px solid green + +.theInputs + //width: 60% + float: left +// border: 1px red solid + +.rows + width: 100% + display: block + +.column + width: 100% + display: inline-block + margin-bottom: 15px + +#startday + width: 40% + +#nbrofdays, #peaklim, #olderthan + width: 13% + +.addit + width: 20% + border: 1px solid blue + +.klein + font-size: 80% + +.infoTafel th,td + margin: auto + text-align: left + padding: 0 10px + border: 1px solid black + background-color: rgba(238,238,238,0.6) + +.infoTafel th + text-align: center + +.infoTafel tr + height: 20px + +@media only screen and (max-width: 700px) + .infoTafel, .legend + display: none + +.nav-tabs .nav-item .nav-link + background-color: $navtab-color + color: #FFF + +.nav-tabs .nav-item .nav-link.active + color: $navtab-color + background-color: #FFFFFF + +// for settings: set all to 'none' +#stday, #nbday, #pklim, #odth + display: none + + + +// for first page to show 'Loading ...' +#first + display: flex + align-items: center + justify-content: center + text-align: center + +.addr + font-weight: bold + margin-bottom: 10px + +.bigger + font-size: 120% + font-weight: bold + +.highcharts-container + margin-top: -10px + +.errdiv + display: none + diff --git a/noise/routes/api.js b/noise/routes/api.js new file mode 100644 index 0000000..24c9202 --- /dev/null +++ b/noise/routes/api.js @@ -0,0 +1,72 @@ +import express from 'express' +import axios from 'axios' +import * as prep from '../charts/preparecharts.js' +import { getLanguage } from '../charts/utilities.js' +import { translate as trans } from '../routes/index.js' + +const router = express.Router() + +const disttable = [ + {type: 'live', func: prep.liveData }, + {type: 'havg', func: prep.havgData }, + {type: 'davg', func: prep.davgData }, + {type: 'daynight', func: prep.dayNightData }, + {type: 'lden', func: prep.ldenData }, + {type: 'map', func: prep.mapData }, +] + +let APIHOST = process.env.APIHOST || 'http://localhost:3005' +const API_KEY = process.env.API_KEY + + +/* GET home page. */ +router.get('/:cmd', async function(req, res, next) { +// req.i18n.changeLanguage(req.query.lng) + const calledAs = req.baseUrl + const cmd = req.params.cmd + const pretty = (req.query.pretty !== undefined) + const lng = getLanguage() + + let url = APIHOST + '/api' + req.originalUrl.slice(4) + `&lng=${lng}` + try { + const response = await axios.get(encodeURI(url) , { + headers: {'X-API-Key': API_KEY} + }); + if (response.status !== 200) { + res.json({err: `${trans('ESYSCALL')} status=${response.status}`}) + } + if(response.data.err) { + res.json(response.data) + return + } + // if called as '/api' then directly return the data + if ((calledAs === '/api') || (cmd === 'getoneproperty') || (cmd === 'getaddress') || (cmd === 'getcitycoords')) { + if(pretty) { + res.setHeader('Content-Type', 'text/plain; charset=utf-8'); + res.send(JSON.stringify(response.data,null,2)) + } else { + res.setHeader('Content-Type', 'application/json; charset=utf-8'); + res.json(response.data) + } + return + } + const options = response.data.options + for(let x of disttable) { + if (x.type === options.data) { + let ret = x.func(options, response.data.values, req) + res.json(ret) + break; + } + } + } catch (e) { + res.json({err: `${trans('ESYSCALL')} ${e}`}) + } +}) + +export default router + + + +// ToDo +// Hier : getsensordata und getmapdata unterbringen und damit den externen Server aufrufen + diff --git a/noise/routes/index.js b/noise/routes/index.js new file mode 100644 index 0000000..88d4520 --- /dev/null +++ b/noise/routes/index.js @@ -0,0 +1,69 @@ +import express from 'express' +import pkg from '../package.json' with { type: "json" } +import { setLanguage } from '../charts/utilities.js' + +const router = express.Router() +const { name, version, date } = pkg + +const renderOpts = (sid, cat) => { + return { + title: 'Noise', + version: version, + date: date.slice(0, 10), + csensor: sid, + category: cat + } +} + +let i18n; + +const translate = (x) => { + return i18n.t(x) +} + +const getIndex = (cat) => { + return 'index_noise' +} + + +/* GET home page. If there is no parameter 'lng=xx', check stored language and call +te page again with correct language (chglang.js)) +*/ +router.get('/', function (req, res, next) { + // req.i18n.changeLanguage('de') + if (req.query.lng === undefined) { + res.render('chglang', {sensorid: ''}) + } else { + i18n = req.i18n + let opts = renderOpts(-1, req.app.get('category')) + setLanguage(req.query.lng) + res.render(getIndex(opts.category), opts) + } +}) + +// +// router.get('/', function(req, res, next) { +// // req.i18n.changeLanguage('de') +// res.render('index', renderOpts(-1)) +// }) + + +router.get('/:sid', async function (req, res, next) { + const sid = req.params.sid + let opts + if (req.query.lng === undefined) { + res.render('chglang', { sensorid: sid }) + } else { + i18n = req.i18n + if (isNaN(sid)) { + opts = renderOpts(-1, req.app.get('category')) + } else { + opts = renderOpts(sid, req.app.get('category')) + } + res.render(getIndex(opts.category), opts) + } +}) + +//export default router + +export { router, translate } \ No newline at end of file diff --git a/noise/views/chglang.pug b/noise/views/chglang.pug new file mode 100644 index 0000000..0fb43fa --- /dev/null +++ b/noise/views/chglang.pug @@ -0,0 +1,13 @@ +doctype html +html + head + title= title + meta(name="viewport" content="width=device-width, initial-scale=1" charset="utf-8") + link(rel='stylesheet', href='/stylesheets/style.css') + script. + const sensorid = '#{sensorid}'; + + body + #first + h1 Loading... + script(type="module" src="/javascripts/checklang.js") \ No newline at end of file diff --git a/noise/views/error.pug b/noise/views/error.pug new file mode 100644 index 0000000..51ec12c --- /dev/null +++ b/noise/views/error.pug @@ -0,0 +1,6 @@ +extends layout + +block content + h1= message + h2= error.status + pre #{error.stack} diff --git a/noise/views/index_noise.pug b/noise/views/index_noise.pug new file mode 100644 index 0000000..cdb52ec --- /dev/null +++ b/noise/views/index_noise.pug @@ -0,0 +1,114 @@ +extends layout + +block content + header + #hline1 + #h1name #{t("NoiseMeasurement")} + #buttonsRight + button#btnSet(value='set') #{t("Settings")} + // button#btnHelp(value='help') #{t("Info")} + #h1datum + + #fenster + #spinner + #navi + .tabs#tablist + button.tab-button.active#maptab(data-target="t_map" type="button" role="tab" aria-controls="map" aria-selected="true") #{t("Map")} + button.tab-button#livetab(data-target="t_live" type="button" role="tab" aria-controls="live") #{t("Live")} + button.tab-button#houravgtab(data-target="t_houravg" type="button" role="tab" aria-controls="houravg") #{t("Hour_AVG")} + button.tab-button#dayavgtab(data-target="t_dayavg" type="button" role="tab" aria-controls="dayavg") #{t("Day_AVG")} + button.tab-button#daynighttab(data-target="t_daynight" type="button" role="tab" aria-controls="daynight") #{t("Day_Night")} + button.tab-button#ldentab(data-target="t_lden" type="button" role="tab" aria-controls="lden") LDEN-Index + .tab-content#thetabs + .tab-pane.active#t_map(role="tabpanel") + #map + // button#btnMyLocation(type="button" title=t("MyLocation")) + span 📍 + #maptaberr.errdiv + #mapdateactsens + #actsensors + #mapdate + .tab-pane#t_live(role="tabpanel") + #dlive + #livetaberr.errdiv + .tab-pane#t_houravg(role="tabpanel") + #dhour + #houravgtaberr.errdiv + .tab-pane#t_dayavg(role="tabpanel") + #dday + #dayavgtaberr.errdiv + .tab-pane#t_daynight(role="tabpanel") + #ddaynight + #daynighttaberr.errdiv + .tab-pane#t_lden(role="tabpanel") + #dlden + #ldentaberr.errdiv + + + // Error-Dialog + dialog#dialogError + .dialog-content + .dialog-header + h3.dialog-title #{t("Error")} + button.dialog-close(type="button" aria-label="Close") × + .dialog-body + .dialog-footer + + + // Settings-Dialog + dialog#dialogSettings + .dialog-content + .dialog-header + h3.dialog-title #{t("Settings")} + button.dialog-close(type="button" aria-label="Close") × + .dialog-body.settings + .rows + .column#ccity + label.thelabels(for='city') #{t("CenterMap")}: + input.theInputs#centercity(name="centercity") + .column#stday + label.thelabels(for='startday') #{t("StartDate")}: + input.theInputs#startday(type='date' name='startday') + .column + .column#nbday + label.thelabels(for='nbrofdays') + | #{t("NumberOfDays")}:
+ input.theInputs#nbrofdays(type='number' name='nbrofdays' min="1" max="10") + span.klein   (max. 10) + .column#pklim + label.thelabels(for='peaklim') + | #{t("Count_peaks_over")} + input.theInputs#peaklim(type='number' name='peaklim' min="10" max="130") + |   dbA + span.klein   (max. 130) + .column#odth + label.thelabels(for='olderthan') + | #{t("RemoveFromMap")} + input.theInputs#olderthan(type='number' name='olderthan' min="0" max="52") + |   #{t("weeks")} + span.klein   (max. 52) + .column + .column#sellan + label.thelabels + | #{t("Language")}: + .radio-group + label.radio-label + input#de(type="radio" name="lanbut") + span Deutsch + label.radio-label + input#en(type="radio" name="lanbut" checked) + span English + .dialog-footer + button.dialog-button.secondary#btnClose(type="button") #{t("Close")} + button.dialog-button.primary#btnSave(type="button") #{t("Save_changes")} + + + // Reset-Dialog + dialog#dialogReset + .dialog-content + .dialog-header + h3.dialog-title Info + button.dialog-close(type="button" aria-label="Close") × + .dialog-body + .dialog-footer + button.dialog-button.primary#btnResetOk(type="button") OK diff --git a/noise/views/layout.pug b/noise/views/layout.pug new file mode 100644 index 0000000..2332bff --- /dev/null +++ b/noise/views/layout.pug @@ -0,0 +1,37 @@ +doctype html +html + head + title= title + meta(name="viewport" content="width=device-width, initial-scale=1" charset="utf-8") + link(rel="stylesheet" href="https://unpkg.com/leaflet@1.9.3/dist/leaflet.css" + integrity="sha256-kLaT2GOSpHechhsozzB+flnD+zUyjE2LlfWPgU04xyI=" + crossorigin="") + link(rel='stylesheet', href='/stylesheets/MarkerCluster.css') + link(rel='stylesheet', href='/spin.js/spin.css') + + + script. + const sysparams = { + version: '#{version}', + date: '#{date}', + csid: '#{csensor}', + category: '#{category}' + }; + + link(rel='stylesheet', href='/stylesheets/style.css') + + body + #wrapper + block content + footer + #author + #mailadr + a(href="mailto:rexfue@gmail.com") mailto:rexfue@gmail.com + #versn #{t('Version')}: #{version} #{t('from')} #{date} + + script(src="https://unpkg.com/leaflet@1.9.3/dist/leaflet.js" + integrity="sha256-WBkoXOwTeyKclOHuWtc+i2uENFpDZ9YPdf5Hf+D7ewM=" + crossorigin="") + script(src="/javascripts/leaflet.markercluster.js") + script(src="https://code.highcharts.com/highcharts.js") + script(type="module" src="/javascripts/global.js") \ No newline at end of file diff --git a/readin/.dockerignore b/readin/.dockerignore new file mode 100644 index 0000000..4786954 --- /dev/null +++ b/readin/.dockerignore @@ -0,0 +1,10 @@ +node-modules +.gitignore +.dockerignore +build_and_copy.sh +docker-compose.yml +Dockerfile* +INFLUXSERVER +TRANSFERE +data + diff --git a/readin/.gitignore b/readin/.gitignore new file mode 100644 index 0000000..a7dc966 --- /dev/null +++ b/readin/.gitignore @@ -0,0 +1,9 @@ +data/ +node_modules +.idea +.env +log +docs/Readme.md_x +docs/Readme_tmp.html + + diff --git a/readin/Dockerfile_readin b/readin/Dockerfile_readin new file mode 100644 index 0000000..925c5b0 --- /dev/null +++ b/readin/Dockerfile_readin @@ -0,0 +1,28 @@ +FROM node:22-alpine + +ADD package.json /tmp/package.json +ADD package-lock.json /tmp/package-lock.json +RUN cd /tmp && npm ci +RUN mkdir -p /opt/app && cp -a /tmp/node_modules /tmp/package.json /opt/app/ + +WORKDIR /opt/app +ADD . /opt/app +ADD crontab.tmp /opt/app + +RUN mkdir -p data + +#RUN apk add busybox-initscripts +#RUN apk add --no-cache tzdata +#ENV TZ Europe/Berlin +#RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone + +RUN crontab crontab.tmp +RUN deluser --remove-home node + +RUN touch cmds.sh \ + && echo 'crond -f' >>cmds.sh + +CMD sh ./cmds.sh + + + diff --git a/readin/Dockerfile_timeseries b/readin/Dockerfile_timeseries new file mode 100644 index 0000000..6cb39ee --- /dev/null +++ b/readin/Dockerfile_timeseries @@ -0,0 +1,27 @@ +FROM node:alpine + +ADD package.json /tmp/package.json +RUN cd /tmp && npm install +RUN mkdir -p /opt/app && cp -a /tmp/node_modules /opt/app/ + +WORKDIR /opt/app +ADD . /opt/app +ADD crontab.tmp /opt/app + +RUN mkdir -p data + +#RUN apk add busybox-initscripts +#RUN apk add --no-cache tzdata +#ENV TZ Europe/Berlin +#RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone + +RUN crontab crontab.tmp +RUN deluser --remove-home node + +RUN touch cmds.sh \ + && echo 'crond -f' >>cmds.sh + +CMD sh ./cmds.sh + + + diff --git a/readin/build_and_copy.sh b/readin/build_and_copy.sh new file mode 100755 index 0000000..8d4a210 --- /dev/null +++ b/readin/build_and_copy.sh @@ -0,0 +1,63 @@ +#!/bin/bash +# Build Docker-Container +# +# Call: buildit.sh name [target] +# +# The Dockerfile must be named like Dockerfile_name +# +# 2018-09-20 rxf +# - before sending docker image to remote, tag actual remote image +# +# 2018-09-14 rxf +# - first Version +# + +set -x +port="" +orgName=readin +name=readin + +usage() +{ + echo "Usage build_and_copy.sh [-p port] [-n name] target" + echo " Build docker container $name and copy to target" + echo "Params:" + echo " target: Where to copy the container to " + echo " -p port: ssh port (default 22)" + echo " -n name: new name for container (default: $orgName)" +} + +while getopts n:p:h? o +do + case "$o" in + n) name="$OPTARG";; + p) port="-p $OPTARG";; + h) usage; exit 0;; + *) usage; exit 1;; + esac +done +shift $((OPTIND-1)) + +while [ $# -gt 0 ]; do + if [[ -z "$target" ]]; then + target=$1 + shift + else + echo "bad option $1" + # exit 1 + shift + fi +done + +docker build -f Dockerfile_$orgName -t $name . + +dat=`date +%Y%m%d%H%M` + +if [ "$target" == "localhost" ] +then + docker tag $name $name:V_$dat + exit +fi + +ssh $port $target "docker tag $name $name:V_$dat" +docker save $name | bzip2 | pv | ssh $port $target 'bunzip2 | docker load' diff --git a/readin/crontab.tmp b/readin/crontab.tmp new file mode 100644 index 0000000..60f118f --- /dev/null +++ b/readin/crontab.tmp @@ -0,0 +1,2 @@ +3-59/5 * * * * cd /opt/app && npm start + diff --git a/readin/deploy.sh b/readin/deploy.sh new file mode 100755 index 0000000..dbe3a12 --- /dev/null +++ b/readin/deploy.sh @@ -0,0 +1,58 @@ +#!/bin/bash + +set -e + +# Angepasst aus /Projekte/Logbuch/deploy.sh +# Unterschiede: nur linux/amd64, nativer Build auf esprimo (amd64) -> kein buildx/qemu, +# eigener Dockerfile-Name (Dockerfile_readin). + +REGISTRY="docker.citysensor.de" +IMAGE_NAME="readin" +TAG="${1:-latest}" +PLATFORM="linux/amd64" +DOCKERFILE="Dockerfile_readin" +FULL_IMAGE="${REGISTRY}/${IMAGE_NAME}:${TAG}" +BUILD_DATE=$(date +%d.%m.%Y) + +echo "==========================================" +echo "readin Deploy Script (amd64)" +echo "==========================================" +echo "Registry: ${REGISTRY}" +echo "Image: ${IMAGE_NAME}" +echo "Tag: ${TAG}" +echo "Platform: ${PLATFORM}" +echo "Dockerfile: ${DOCKERFILE}" +echo "Build-Datum: ${BUILD_DATE}" +echo "==========================================" +echo "" + +# Hinweis: Login wird uebersprungen, weil die Credentials fuer ${REGISTRY} +# bereits in ~/.docker/config.json liegen (Container laufen bereits aus dieser Registry). +# Bei Bedarf manuell: docker login ${REGISTRY} + +echo ">>> Baue Image (nur ${PLATFORM}, nativ) ..." +docker build \ + --platform "${PLATFORM}" \ + -f "${DOCKERFILE}" \ + -t "${FULL_IMAGE}" \ + . +echo "" + +echo ">>> Pushe ${FULL_IMAGE} ..." +docker push "${FULL_IMAGE}" +echo "" + +# Falls ein anderer Tag als 'latest' gebaut wurde, zusaetzlich latest setzen+pushen +if [ "${TAG}" != "latest" ]; then + echo ">>> Tagge zusaetzlich als :latest ..." + docker tag "${FULL_IMAGE}" "${REGISTRY}/${IMAGE_NAME}:latest" + docker push "${REGISTRY}/${IMAGE_NAME}:latest" + echo "" +fi + +echo "==========================================" +echo "Build + Push fertig: ${FULL_IMAGE}" +echo "==========================================" +echo "" +echo "Danach Stack aktualisieren:" +echo " cd /opt/stacks/esprimo/noisesensors && docker compose up -d readin" diff --git a/readin/docker-compose.yml b/readin/docker-compose.yml new file mode 100644 index 0000000..0c23be2 --- /dev/null +++ b/readin/docker-compose.yml @@ -0,0 +1,55 @@ +version: '3.9' + +volumes: + mongo_vol: + influx_vol: + +services: + timeseries: + image: timeseries + environment: + DEVELOP: "true" + MONGOHOST: mongodb + MONGOUSRP: "rexfue:noise4mongo" + MONGOAUTH: "true" + INFLUXHOST: influxdb + INFLUXTOKEN: "q35XUBaElzcy8dDd9HF2_mpeHvYCampZg_9mJNP5jeBQRopq3EWIzNTZ555QLSIXhZC05RXCoFgjiaT7VzyNkQ==" + TYP: "[\"noise\", \"thp\"]" + STORE: "mongo" + volumes: + - ${PWD}/log:/var/log + container_name: timeseries + restart: unless-stopped + + mongodb: + image: mongo:6 + volumes: + - ${PWD}/entries:/docker-entrypoint-initdb.d + - mongo_vol:/data/db + ports: + - "27017:27017" + container_name: mongodb + environment: + - MONGO_INITDB_DATABASE=sensor_data + - MONGO_INITDB_ROOT_USERNAME=${MONGO_ROOT_USERNAME} + - MONGO_INITDB_ROOT_PASSWORD=${MONGO_ROOT_PASSWORD} + restart: unless-stopped + + influxdb: + image: influxdb:2.0 + ports: + - '8086:8086' + volumes: + - influx_vol:/var/lib/influxdb2 + environment: + DOCKER_INFLUXDB_INIT_MODE: setup + DOCKER_INFLUXDB_INIT_USERNAME: ${DOCKER_INFLUXDB_INIT_USERNAME} + DOCKER_INFLUXDB_INIT_PASSWORD: ${DOCKER_INFLUXDB_INIT_PASSWORD} + DOCKER_INFLUXDB_INIT_ORG: citysensor + DOCKER_INFLUXDB_INIT_BUCKET: sensor_data + DOCKER_INFLUXDB_INIT_ADMIN_TOKEN: ${DOCKER_INFLUXTOKEN} + restart: + unless-stopped + container_name: influxdb + + diff --git a/readin/fetchnewdata.js b/readin/fetchnewdata.js new file mode 100644 index 0000000..d0567ea --- /dev/null +++ b/readin/fetchnewdata.js @@ -0,0 +1,141 @@ +// Einlesen aller Sensordaten von sensor.comunity und abspeicher in einer Inlux- bzw. einer Mongo-DB + +// Ausgehend von Version 1.x.x werden hier nun die Daten nach den Sensortypen getrennt gespeichert +// und zwar einstellbar in einer Mongo-DB oder in einer Influx-DB (oder auch in beide). + +// Version: +// +// V 2.0.0 2023-10-13 rxf +// - Erste Version mit der Trennung nach Typen +// +// V 2.0.1 2023-10-15 rxf +// - Auswahl der Typen via Commandline (-t) oder Environment TYP + +// TYP: Ist ein Array von Strings, wenn nur einzelne Typen gespeichert werden sollen, also z.B.: +// ['pm', 'noise'] +const TYP = process.env.TYP || '' +const STORE = (process.env.STORE || 'both').toLowerCase() // 'mongo' | 'influx' | 'both' + +import { doReadfromAPI as readin, statistics } from './readdata.js' +import { constructDBaseEntries as parse} from './parse.js' + +import * as mongo from './mongo.js' +import * as influx from './influx_post.js' +import { logit, logerror } from './logit.js' +import { DateTime } from 'luxon' +import fs from 'fs' +import mod_getopt from 'posix-getopt' +import pkg from './package.json' with { type: "json" } + + +// import nodeSchedule from 'node-schedule' + +const fetchNewData = async (args) => { + let client + let start = DateTime.now(); + try { + client = await mongo.connectMongo() + } catch(e) { + logerror(`Connect to Mongo ${e}`); + logit(`Programmend - Error in connecting mongo\n`) + process.exit(-1); + } + try { + // read data from API or from disk + let dat = await readin() + if (dat.length !== 0) { + // parse the data + let [props, data, idata] = await parse(client, dat, args) + + // write sensor data to mongoDB + if(args.mongo) { + for (const [k,v] of Object.entries(data)) { + if(v.length !== 0) { + await mongo.writeDataArray(client, k+'_sensors', v) + } + } + } + + // write sensor data to influxDB + if(args.influx) { + await influx.influxWrite(idata) + } + + // write properties to mongoDB + await mongo.bulkWrite(client, mongo.property_coll, props) + } + } catch (e) { + logerror(`Catch in main ${e}`); + } finally { + statistics.totalTime = DateTime.now().diff(start,['seconds']).toObject().seconds + await mongo.writeStatistic(client, statistics) + await mongo.closeMongo(client) + } +} + +// Parse command line options +function parse_cmdline(argv) { + let parser = new mod_getopt.BasicParser('i(influx)m(mongo)t:(typ)h(help)v(version)',argv); + let option; + let ret = {influx: STORE === 'both' || STORE === 'influx', mongo: STORE === 'both' || STORE === 'mongo', typ: TYP} + while((option = parser.getopt()) !== undefined) { + switch(option.option) { + case 'i': + ret.mongo = false + break; + + case 'm': + ret.influx = false + break; + + case 't': + let x = option.optarg.trim() + let y = [] + if(x[0] === '[') { + y = JSON.parse(x) + } else { + y.push(x) + } + ret.typ = y + break; + + case 'v': + console.log(`Version: ${pkg.version} from ${pkg.date}`); + console.log(); + process.exit(); + break; + + case 'h': + console.log("Usage: node fetchnewdata.js [-i] [-m] [-t [typ, typ, ..]] [-v] [-h]"); + console.log("Params:"); + console.log(" -i use only InfluxDB to store the data (default use both, InfluxDB and MongoDB))"); + console.log(" -m use only MongoDB to store the data (default use both, InfluxDB and MongoDB)"); + console.log(" -t [ sensorType, ..]: if given, only those sensors will be used (ex: laerm) default: all"); + console.log(" MUST BE AN ARRAY!; allowed types: 'pm', 'noise', 'radiactivity', 'thp', 'gps'.") + console.log(" -v version: show version"); + console.log(" -h this help text"); + console.log("All parameters are optional."); + console.log(); + process.exit(); + break; + + default: + break; + } + } + logit(JSON.stringify(ret)); + return ret; +} + + + +const main = async () => { + const json = JSON.parse(fs.readFileSync('package.json', 'utf8')) + logit(`Programmstart V ${json.version} vom ${json.date}.`); + let args = parse_cmdline(process.argv); + await fetchNewData(args) + logit(`Program end - running time: ${statistics.totalTime} sec\n\n`) +} + +main().catch(console.error) + diff --git a/readin/influx_post.js b/readin/influx_post.js new file mode 100644 index 0000000..938b22f --- /dev/null +++ b/readin/influx_post.js @@ -0,0 +1,100 @@ +// Access to influxDB vie HTTP + +import axios from 'axios' +import { logit, logerror } from './logit.js' +import { DateTime } from 'luxon' +import { statistics } from'./readdata.js' + +let DEVELOP = process.env.DEVELOP || 'false' + +let INFLUXHOST = process.env.INFLUXHOST || "localhost" +let INFLUXPORT = process.env.INFLUXPORT || 8086 +let INFLUXTOKEN = process.env.INFLUXTOKEN || 'empty' +let INFLUXDATABUCKET = process.env.INFLUXDATABUCKET || "sensor_data" +let INFLUXORG = process.env.INFLUXORG || "citysensor" + +const INFLUXURL_READ = `http://${INFLUXHOST}:${INFLUXPORT}/api/v2/query?org=${INFLUXORG}` +const INFLUXURL_WRITE = `http://${INFLUXHOST}:${INFLUXPORT}/api/v2/write?org=${INFLUXORG}&bucket=${INFLUXDATABUCKET}&precision=ms` + +export const influxRead = async (query) => { + let start = DateTime.now() + let data = [] + try { + let ret = await axios({ + method: 'post', + url: INFLUXURL_READ, + data: query, + headers: { + Authorization: `Token ${INFLUXTOKEN}`, + Accept: 'application/csv', + 'Content-type': 'application/vnd.flux' + }, + timeout: 10000, + }) + if (ret.status != 200) { + logerror(`doReadfromAPI Status: ${ret.status}`) + } + data = ret.data + } catch (e) { + logerror(`doReadfromAPI ${e}`) + } + logit(`ReadIn-Time: ${start.diffNow('seconds').toObject().seconds * -1} sec`) + return data +} + + +export const influxWrite = async (data) => { + let start = DateTime.now() + let ret + logit(INFLUXURL_WRITE) + if (DEVELOP === 'true') { + logit(`Token: ${INFLUXTOKEN}`) + } + try { + ret = await axios({ + method: 'post', + url: INFLUXURL_WRITE, + data: data, + headers: { + Authorization: `Token ${INFLUXTOKEN}`, + Accept: 'application/json', + 'Content-Type': 'text/plain; charset=utf-8' + }, + timeout: 10000, + }) + if (ret.status != 204) { + logerror(`doWrite2API Status: ${ret.status}`) + } + } catch (e) { + logerror(`doWrite2API ${e}`) + } + let statname = `writeInfluxData[sensor_data]Time` + statistics[statname] = DateTime.now().diff(start, ['seconds']).toObject().seconds + logit(`Influx-Write-Time: ${start.diffNow('seconds').toObject().seconds * -1} sec`) + return ret +} + +/* +async function main() { + let data = ` + pm,sid=140 P1=12,P2=13 + pm,sid=142 P1=42,P2=13 + pm,sid=143 P1=43,P2=13 + pm,sid=144 P1=44,P2=13 + thp,sid=141 temperature=23.5,humidity=48,pressure=998 + ` + let ret = await influxWrite(data) + process.exit() + + let query = `from(bucket:"sensor_data") +|> range(start: -1mo) +|> filter(fn: (r) => r._measurement == "pm") +|> filter(fn: (r) => r.sid == "140") +` + let erg = await influxRead(query) + console.log(erg) +} + + +main().catch(console.error) +*/ diff --git a/readin/logit.js b/readin/logit.js new file mode 100644 index 0000000..19d8b28 --- /dev/null +++ b/readin/logit.js @@ -0,0 +1,12 @@ +import { DateTime} from 'luxon' + +export function logit(str) { + let s = `${DateTime.now().toISO()} => ${str}`; + console.log(s); +} + +export function logerror(str) { + let s = `${DateTime.utc().toISO()} => *** ERROR *** ${str}`; + console.log(s); +} + diff --git a/readin/mongo.js b/readin/mongo.js new file mode 100644 index 0000000..f90fa27 --- /dev/null +++ b/readin/mongo.js @@ -0,0 +1,202 @@ +/* Interface for MongoDB +*/ +import { MongoClient } from 'mongodb' +import { logit, logerror } from './logit.js' +import { statistics } from './readdata.js' +import { DateTime } from 'luxon' + +let DEVELOP = process.env.DEVELOP || 'false' + +let MONGOHOST = process.env.MONGOHOST || 'localhost' +let MONGOPORT = process.env.MONGOPORT || 27017 +let MONGOAUTH = process.env.MONGOAUTH || 'false' +let MONGOUSRP = process.env.MONGOUSRP || '' +let MONGOBASE = process.env.MONGOBASE || 'sensor_data' + + +let MONGO_URL = 'mongodb://' + MONGOHOST + ':' + MONGOPORT; // URL to mongo database +if (MONGOAUTH == 'true') { + MONGO_URL = 'mongodb://' + MONGOUSRP + '@' + MONGOHOST + ':' + MONGOPORT + '/?authSource=admin'; // URL to mongo database +} + +export const property_coll = 'properties' + +const addandshowstatistics = (client, text, field, start) => { + statistics[field] = DateTime.now().diff(start, ['seconds']).toObject().seconds + logit(`Write ${text} to mongoDB: Time: ${statistics[field]} sec.`) +} + +export const connectMongo = async () => { + try { + if(DEVELOP === 'true') { + logit(`Try to connect to ${MONGO_URL}`) + } else { + logit(`Try to connect to ${'mongodb://' + MONGOHOST + ':' + MONGOPORT}`) + } + let client = await MongoClient.connect(MONGO_URL, { useNewUrlParser: true, useUnifiedTopology: true }) + if ( DEVELOP === 'true') { + logit(`Mongodbase connected to ${MONGO_URL}`) + } else { + logit('Mongodbase connected') + } + return client + } + catch (error) { + throw (error) + } +} + +export const closeMongo = async (client) => { + client.close() +} + + +export const getallProperties = async (client) => { + return await client.db(MONGOBASE).collection(property_coll) + .find().sort({ _id: 1 }).toArray() + +} + +export const checkOneproperty = async (client, sid) => { + return await client.db(MONGOBASE).collection("properties") + .findOne({ _id: sid }) +} + +export const writeOneproperty = async (client, prop) => { + try { + let result = await client.db(MONGOBASE).collection("properties") + .insertOne(prop) + } catch (e) { + if (e.code == 11000) { + return false + } else { + throw (e) + } + } + return true +} + +export const writeProperties = async (client, props) => { + let result + let startAll = DateTime.now(); + let start + let coll = client.db(MONGOBASE).collection("properties") + if (props.new.length !== 0) { + start = DateTime.now(); + try { + result = await coll.insertMany(props.new) + } catch (e) { + logerror(`Write properties new ${e}`) + } + logit(`Write ${props.new.length} properties NEW to mongoDB: Result: ${result.acknowledged}, Time: ${start.diffNow('seconds').toObject().seconds * -1} sec.`) + } + if (props.loc.length !== 0) { + start = DateTime.now() + try { + for (let item of props.loc) { + result = await coll.updateOne({ _id: item._id }, { + $set: { location_id: item.location_id }, + $push: { location: { $each: [item.location[0]], $position: 0 } } + }) + } + } catch (e) { + logerror(`Write properties location ${e}`) + } + logit(`Write ${props.loc.length} properties LOC to mongoDB: Result: ${result.acknowledged}, Time: ${start.diffNow('seconds').toObject().seconds * -1} sec.`) + } + if (props.sname.length !== 0) { + start = DateTime.now() + try { + for (let item of props.sname) { + result = await coll.updateOne({ _id: item._id }, { + $push: { name: { $each: [item.name[0]], $position: 0 } } + }) + } + } catch (e) { + logerror(`Write properties samename ${e}`) + } + logit(`Write ${props.sname.length} properties NAME to mongoDB: Result: ${result.acknowledged}, Time: ${start.diffNow('seconds').toObject().seconds * -1} sec.`) + } + addandshowstatistics(client, 'properties', 'writePropsTime', startAll) +} + +export const writeDataArray = async (client, coll, data) => { + let result + let start = DateTime.now(); + try { + result = await client.db(MONGOBASE).collection(coll) + .insertMany(data, { ordered: false }) + } catch (e) { + if (e.code !== 11000) { + console.error(e) + } + } + let statname = `writeMongoData[${coll}]Time` + addandshowstatistics(client, `${data.length} entries for ${coll}`, `writeMongoData[${coll}]Time`, start) + +// statistics[statname] = DateTime.now().diff(start, ['seconds']).toObject().seconds +// logit(`Write Data for ${coll} to mongoDB: Time: ${statistics[statname]} sec.`) +} + +export const writeStatistic = async (client, stat) => { + let result + let start = DateTime.now(); + let entry = { timestamp: new Date(), ...stat } + try { + result = await client.db(MONGOBASE).collection("statistics") + .insertOne(entry) + } catch (e) { + console.error(e) + } + addandshowstatistics(client, `statistics`, `writeStatisticTime`, start) +} + +export const dropColl = async (client, coll) => { + let start = DateTime.now() + let result + try { + result = await client.db(MONGOBASE).collection(coll).drop() + } catch (e) { + console.error(e) + } + logit(`Drop collection ${coll}: Result: ${result}, Time: ${start.diffNow('second').toObject().seconds * -1} sec.`) +} + + +export const createIndex = async (client, coll) => { + let result + let start = DateTime.now() + try { + result = await client.db(MONGOBASE).collection(coll).createIndex({ "location.loc": "2dsphere" }) + } catch (e) { + console.error(e) + } + logit(`Create-Index: Result: ${result}, Time: ${start.diffNow('second').toObject().seconds * -1} sec.`) +} + +export const bulkUpdateMapdata = async (client, data) => { + let start = DateTime.now() + let result + try { + result = await client.db(MONGOBASE).collection("mapdata") + .bulkWrite(data, { ordered: false }) + } catch (e) { + console.error(e) + } + logit(`Write MapData: Result: ${result}, Time: ${start.diffNow('second').toObject().seconds * -1} sec.`) + return result +} + + +export const bulkWrite = async (client, coll, data) => { + let start = DateTime.now() + let result + try { + result = await client.db(MONGOBASE).collection(coll) + .bulkWrite(data, { ordered: false }) + } catch (e) { + console.error(e) + } + addandshowstatistics(client, `Data for ${coll}`, `writeMongoProperties[${coll}]Time`, start) + return result +} diff --git a/readin/package-lock.json b/readin/package-lock.json new file mode 100644 index 0000000..5bb4c50 --- /dev/null +++ b/readin/package-lock.json @@ -0,0 +1,1020 @@ +{ + "name": "timeseries_mongo", + "version": "2.0.2", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "timeseries_mongo", + "version": "2.0.2", + "license": "ISC", + "dependencies": { + "axios": "^1.12.0", + "luxon": "^2.3.1", + "mongodb": "^4.4.1", + "posix-getopt": "^1.2.1" + } + }, + "node_modules/@aws-sdk/core": { + "version": "3.977.1", + "resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.977.1.tgz", + "integrity": "sha512-KVtQRtc00ES/y+Sc3vYXeP6pCIcNlBJCZOwvqSy8ZpVGmbM5+IG+AfhuTKQ2oXmIVqZJewaGMMpzPkywC6xg0w==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "@aws-sdk/types": "^3.974.2", + "@aws-sdk/xml-builder": "^3.972.37", + "@aws/lambda-invoke-store": "^0.3.0", + "@smithy/core": "^3.29.8", + "@smithy/signature-v4": "^5.6.9", + "@smithy/types": "^4.16.1", + "bowser": "^2.11.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-cognito-identity": { + "version": "3.972.60", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-cognito-identity/-/credential-provider-cognito-identity-3.972.60.tgz", + "integrity": "sha512-16Fxa3veKIO6nHJr+vN76z3BkSU7725lzruc5S2SQSTUTbK4TXtmi8033WQljZj4k1+383UsMaNOHN6B76fK5A==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "@aws-sdk/nested-clients": "^3.997.35", + "@aws-sdk/types": "^3.974.2", + "@smithy/core": "^3.29.8", + "@smithy/types": "^4.16.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-env": { + "version": "3.972.61", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.972.61.tgz", + "integrity": "sha512-qihs2ekMb89Nxd2JenCgVFhjbkb3EIo7HEBCBzyZACKVJdrLUZBLOmAE3xr0Sayml8n/jZSzwO/IufIiIzO7PQ==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "@aws-sdk/core": "^3.977.0", + "@aws-sdk/types": "^3.974.2", + "@smithy/core": "^3.29.8", + "@smithy/types": "^4.16.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-http": { + "version": "3.972.63", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-http/-/credential-provider-http-3.972.63.tgz", + "integrity": "sha512-yfozsS8wkWZEi/n6IsrodcFKBWZ0iNAezhJbTReMNc0z1Px17qdeAeuL1/wziCAmCZyXiW7QzP75ggJkBQv8jQ==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "@aws-sdk/core": "^3.977.0", + "@aws-sdk/types": "^3.974.2", + "@smithy/core": "^3.29.8", + "@smithy/fetch-http-handler": "^5.6.10", + "@smithy/node-http-handler": "^4.9.10", + "@smithy/types": "^4.16.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-ini": { + "version": "3.973.6", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.973.6.tgz", + "integrity": "sha512-jGLTW1bj148GL/6/IMlfY2fMYS9FtHOG+NahkFD4y0qkzYudNUahelxryY68/HGMslYuHClk1XaS/3b3eJzEkg==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "@aws-sdk/core": "^3.977.0", + "@aws-sdk/credential-provider-env": "^3.972.61", + "@aws-sdk/credential-provider-http": "^3.972.63", + "@aws-sdk/credential-provider-login": "^3.972.68", + "@aws-sdk/credential-provider-process": "^3.972.61", + "@aws-sdk/credential-provider-sso": "^3.973.5", + "@aws-sdk/credential-provider-web-identity": "^3.972.67", + "@aws-sdk/nested-clients": "^3.997.35", + "@aws-sdk/types": "^3.974.2", + "@smithy/core": "^3.29.8", + "@smithy/credential-provider-imds": "^4.4.13", + "@smithy/types": "^4.16.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-login": { + "version": "3.972.68", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-login/-/credential-provider-login-3.972.68.tgz", + "integrity": "sha512-w6tNci6g7RqFpLhj1f5xseBvaNojb4Pkgp5Jp5apl9hrJtaf2AA+rX9+qlhlWUK6kcyAFYPA7emO+55zj+S98Q==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "@aws-sdk/core": "^3.977.0", + "@aws-sdk/nested-clients": "^3.997.35", + "@aws-sdk/types": "^3.974.2", + "@smithy/core": "^3.29.8", + "@smithy/types": "^4.16.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-node": { + "version": "3.972.72", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.972.72.tgz", + "integrity": "sha512-blQ7F5QGzylnzeh5549zQLoCAiMHkXFLjFovEMaVy4b2X8JhUu+u9NXro1hyK95YHdVFNmBHKs2hIHtZchxKlQ==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "@aws-sdk/credential-provider-env": "^3.972.61", + "@aws-sdk/credential-provider-http": "^3.972.63", + "@aws-sdk/credential-provider-ini": "^3.973.6", + "@aws-sdk/credential-provider-process": "^3.972.61", + "@aws-sdk/credential-provider-sso": "^3.973.5", + "@aws-sdk/credential-provider-web-identity": "^3.972.67", + "@aws-sdk/types": "^3.974.2", + "@smithy/core": "^3.29.8", + "@smithy/credential-provider-imds": "^4.4.13", + "@smithy/types": "^4.16.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-process": { + "version": "3.972.61", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-process/-/credential-provider-process-3.972.61.tgz", + "integrity": "sha512-xzRuj+fUVO4nkafKQJVKAF97kGpeQbfjuwmRrtGZNf42/1dkmcz6o7dswBy7alY0htQn5sCL1GWQYEykviWZkA==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "@aws-sdk/core": "^3.977.0", + "@aws-sdk/types": "^3.974.2", + "@smithy/core": "^3.29.8", + "@smithy/types": "^4.16.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-sso": { + "version": "3.973.5", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.973.5.tgz", + "integrity": "sha512-fZRjjWhLFelsDoOYjqShQTrIGYC3Pf9Mx9Czf+1ikfQDgktxjze33dVo1q1/ZQ+T0qbtejVoHNHrfD5aJVpv/w==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "@aws-sdk/core": "^3.977.0", + "@aws-sdk/nested-clients": "^3.997.35", + "@aws-sdk/token-providers": "3.1095.0", + "@aws-sdk/types": "^3.974.2", + "@smithy/core": "^3.29.8", + "@smithy/types": "^4.16.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-web-identity": { + "version": "3.972.67", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.972.67.tgz", + "integrity": "sha512-FTNZ05gkPBA6CKbU3N4zPgybV+stdazwMOya75CmGdcJL7p8Fw/BdHP8WVxJd0mvzyPK2cg/C3gli58Ir4HgCw==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "@aws-sdk/core": "^3.977.0", + "@aws-sdk/nested-clients": "^3.997.35", + "@aws-sdk/types": "^3.974.2", + "@smithy/core": "^3.29.8", + "@smithy/types": "^4.16.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@aws-sdk/credential-providers": { + "version": "3.1095.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-providers/-/credential-providers-3.1095.0.tgz", + "integrity": "sha512-hcL4iILqep+AieTjJ+eYpBoThcirhlr0rzOqyDKSlFeV15qy8FnvwZFlNmVUFFwHnZjvQz5M9MsRe4XbC6eDfw==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "@aws-sdk/core": "^3.977.0", + "@aws-sdk/credential-provider-cognito-identity": "^3.972.60", + "@aws-sdk/credential-provider-env": "^3.972.61", + "@aws-sdk/credential-provider-http": "^3.972.63", + "@aws-sdk/credential-provider-ini": "^3.973.6", + "@aws-sdk/credential-provider-login": "^3.972.68", + "@aws-sdk/credential-provider-node": "^3.972.72", + "@aws-sdk/credential-provider-process": "^3.972.61", + "@aws-sdk/credential-provider-sso": "^3.973.5", + "@aws-sdk/credential-provider-web-identity": "^3.972.67", + "@aws-sdk/nested-clients": "^3.997.35", + "@aws-sdk/types": "^3.974.2", + "@smithy/core": "^3.29.8", + "@smithy/credential-provider-imds": "^4.4.13", + "@smithy/types": "^4.16.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@aws-sdk/nested-clients": { + "version": "3.997.35", + "resolved": "https://registry.npmjs.org/@aws-sdk/nested-clients/-/nested-clients-3.997.35.tgz", + "integrity": "sha512-2MJfseVG/aXvIyOIBlYA/Oaf6qFDdsu4D8RKsEUdOQpVuLaor0BdxIBBtJLBNQQEe6Ku3YMvLljwb1MwVUpzRw==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "@aws-sdk/core": "^3.977.0", + "@aws-sdk/signature-v4-multi-region": "^3.996.42", + "@aws-sdk/types": "^3.974.2", + "@smithy/core": "^3.29.8", + "@smithy/fetch-http-handler": "^5.6.10", + "@smithy/node-http-handler": "^4.9.10", + "@smithy/types": "^4.16.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@aws-sdk/signature-v4-multi-region": { + "version": "3.996.42", + "resolved": "https://registry.npmjs.org/@aws-sdk/signature-v4-multi-region/-/signature-v4-multi-region-3.996.42.tgz", + "integrity": "sha512-DBV4naZP6HYBlAvPpoQzOP12Wvfou/5rN8yJPXjBTBylU5qwCbh/tXr2MddHoIjgoRkEl/eS+IljiUqvmwey1Q==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "@aws-sdk/types": "^3.974.2", + "@smithy/signature-v4": "^5.6.9", + "@smithy/types": "^4.16.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@aws-sdk/token-providers": { + "version": "3.1095.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.1095.0.tgz", + "integrity": "sha512-65SudS6y4nzaYHybtqcpm3sHe5jLhdMn68HRKS1nUx690BtQeaAQOoujQ+dpOjBATIVGVgKKjEP8tR+U06QJQA==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "@aws-sdk/core": "^3.977.0", + "@aws-sdk/nested-clients": "^3.997.35", + "@aws-sdk/types": "^3.974.2", + "@smithy/core": "^3.29.8", + "@smithy/types": "^4.16.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@aws-sdk/types": { + "version": "3.974.2", + "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.974.2.tgz", + "integrity": "sha512-3W6IUtSxFbH6X7Wb7DzGCV5QiFQsd0g8bOfntpmDxQlzBoKWUMBu/JPQR0DwkE+Hpnxd6db1tXbOwdeHddG6cA==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "@smithy/types": "^4.16.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@aws-sdk/xml-builder": { + "version": "3.972.37", + "resolved": "https://registry.npmjs.org/@aws-sdk/xml-builder/-/xml-builder-3.972.37.tgz", + "integrity": "sha512-zKq4HQum8JwDyEuyfuI4bbiAcU0KxP6qy+9PR/IsR92IyE/DaBAikzAS50tjxip4bqIIANpCcG+Yyj6CVhXupg==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "@smithy/types": "^4.16.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@aws/lambda-invoke-store": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@aws/lambda-invoke-store/-/lambda-invoke-store-0.3.0.tgz", + "integrity": "sha512-sl4Bm6yiMNYrZKkqqDFWN0UfnWhlS8ivKxrYl+6t0gCLrqr8y3B2IqZZbFRkfaVVp7C/baApyh71P+LeE1A2sQ==", + "license": "Apache-2.0", + "optional": true, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@mongodb-js/saslprep": { + "version": "1.4.13", + "resolved": "https://registry.npmjs.org/@mongodb-js/saslprep/-/saslprep-1.4.13.tgz", + "integrity": "sha512-E3Sv4eCYAlKYUTx8S3ioQcDUscOif+8zZ5OnW1IzJ+Tt+EO+ke8mn+Y3FX6N1H79picwbdOavVOb1jPi2EOyrg==", + "license": "MIT", + "optional": true, + "dependencies": { + "sparse-bitfield": "^3.0.3" + } + }, + "node_modules/@smithy/core": { + "version": "3.30.0", + "resolved": "https://registry.npmjs.org/@smithy/core/-/core-3.30.0.tgz", + "integrity": "sha512-dl2yRglDxfzH9uJ4fSo4zTaAHa0zH7+V7BZMRWy8hEYIKT1BiqMUK/CN6T3ADQ3kbA5N1tmUulroJ2UtONS7Kw==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "@smithy/types": "^4.16.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/credential-provider-imds": { + "version": "4.4.14", + "resolved": "https://registry.npmjs.org/@smithy/credential-provider-imds/-/credential-provider-imds-4.4.14.tgz", + "integrity": "sha512-QgbuahIb2qxQeZQvNK0sw3aF3JH5zwH8j2lLp5DUasVXexGGMWULAR+7z0omPXFolCP/m5wN9M5lm9EGdSviTQ==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "@smithy/core": "^3.30.0", + "@smithy/types": "^4.16.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/fetch-http-handler": { + "version": "5.6.11", + "resolved": "https://registry.npmjs.org/@smithy/fetch-http-handler/-/fetch-http-handler-5.6.11.tgz", + "integrity": "sha512-o0Zkj1nKqJAoq+a+BrkhU39tRftMNjLwpc/z06Frfl43wpbHrJMaSAVZE4vTqlxtVkNaGaT0bIDxOp7tkFTuQQ==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "@smithy/core": "^3.30.0", + "@smithy/types": "^4.16.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/node-http-handler": { + "version": "4.9.11", + "resolved": "https://registry.npmjs.org/@smithy/node-http-handler/-/node-http-handler-4.9.11.tgz", + "integrity": "sha512-slbzbz8taEOzoXv/9y34YNBoE+ZHmddLykCgjDAjvMAsu2nM5s2Gzwa5OGF721tD8s+CKeFUBds5lSj9lcbuDg==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "@smithy/core": "^3.30.0", + "@smithy/types": "^4.16.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/signature-v4": { + "version": "5.6.10", + "resolved": "https://registry.npmjs.org/@smithy/signature-v4/-/signature-v4-5.6.10.tgz", + "integrity": "sha512-EXhWePm3SXJAX38npIy4TXL2Aex/OVgCClTjelN2QHw/U+8CQUH8C7AaxsVzQcYieYPseywn48s89DmvuGjiAg==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "@smithy/core": "^3.30.0", + "@smithy/types": "^4.16.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/types": { + "version": "4.16.1", + "resolved": "https://registry.npmjs.org/@smithy/types/-/types-4.16.1.tgz", + "integrity": "sha512-0JFs3V2y2M9tKW5na/qxe69Zv+uxLMO7QBbhxF/FHu/Gp2NFZAAL9tWl9PU02xxo07pb3G9FTyjNc6D5uZrJIg==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@types/node": { + "version": "26.1.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-26.1.1.tgz", + "integrity": "sha512-nxAkRSVkN1Y0JC1W8ky/fTfkGsMmcrRsbx+3XoZE+rMOX71kLYTV7fLXpqud1GpbpP5TuffXFqfX7fH2GgZREw==", + "license": "MIT", + "dependencies": { + "undici-types": "~8.3.0" + } + }, + "node_modules/@types/webidl-conversions": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/@types/webidl-conversions/-/webidl-conversions-7.0.3.tgz", + "integrity": "sha512-CiJJvcRtIgzadHCYXw7dqEnMNRjhGZlYK05Mj9OyktqV8uVT8fD2BFOB7S1uwBE3Kj2Z+4UyPmFw/Ixgw/LAlA==", + "license": "MIT" + }, + "node_modules/@types/whatwg-url": { + "version": "8.2.2", + "resolved": "https://registry.npmjs.org/@types/whatwg-url/-/whatwg-url-8.2.2.tgz", + "integrity": "sha512-FtQu10RWgn3D9U4aazdwIE2yzphmTJREDqNdODHrbrZmmMqI0vMheC/6NE/J1Yveaj8H+ela+YwWTjq5PGmuhA==", + "license": "MIT", + "dependencies": { + "@types/node": "*", + "@types/webidl-conversions": "*" + } + }, + "node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "license": "MIT", + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "license": "MIT" + }, + "node_modules/axios": { + "version": "1.18.1", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.18.1.tgz", + "integrity": "sha512-3nTvFlvpn9Zu/RkHUqtc7/+al4UpRW5az71ap5zccp6e8RAYEzhMTecX8Dz1wWDYrPpUoB1HAQEGEAEvUr7S9g==", + "license": "MIT", + "dependencies": { + "follow-redirects": "^1.16.0", + "form-data": "^4.0.5", + "https-proxy-agent": "^5.0.1", + "proxy-from-env": "^2.1.0" + } + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/bowser": { + "version": "2.14.1", + "resolved": "https://registry.npmjs.org/bowser/-/bowser-2.14.1.tgz", + "integrity": "sha512-tzPjzCxygAKWFOJP011oxFHs57HzIhOEracIgAePE4pqB3LikALKnSzUyU4MGs9/iCEUuHlAJTjTc5M+u7YEGg==", + "license": "MIT", + "optional": true + }, + "node_modules/bson": { + "version": "4.7.2", + "resolved": "https://registry.npmjs.org/bson/-/bson-4.7.2.tgz", + "integrity": "sha512-Ry9wCtIZ5kGqkJoi6aD8KjxFZEx78guTQDnpXWiNthsxzrxAK/i8E6pCHAIZTbaEFWcOCvbecMukfK7XUvyLpQ==", + "license": "Apache-2.0", + "dependencies": { + "buffer": "^5.6.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "license": "MIT", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-object-atoms": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.2.tgz", + "integrity": "sha512-HWcBoN6NileqtSydK2FqHbS/LoDd2pqrnQHLyJzBj4kOp/ky2MWMN694xOfkK8/SnUsW2DH7EfyVlydKCsm1Zw==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-set-tostringtag": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", + "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/follow-redirects": { + "version": "1.16.0", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.16.0.tgz", + "integrity": "sha512-y5rN/uOsadFT/JfYwhxRS5R7Qce+g3zG97+JrtFZlC9klX/W5hD7iiLzScI4nZqUS7DNUdhPgw4xI8W2LuXlUw==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "license": "MIT", + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, + "node_modules/form-data": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.6.tgz", + "integrity": "sha512-vKatAh4SlVfgbv+YtmhiRjhEMJsYpsG1Y2rMQtR+SVSbytsSD1YGzDIcrAJmdFec88u/+VoGmxnl+80gL1tRCQ==", + "license": "MIT", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "es-set-tostringtag": "^2.1.0", + "hasown": "^2.0.4", + "mime-types": "^2.1.35" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-intrinsic": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "license": "MIT", + "dependencies": { + "has-symbols": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.4.tgz", + "integrity": "sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A==", + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "license": "MIT", + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "BSD-3-Clause" + }, + "node_modules/ip-address": { + "version": "10.3.1", + "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.3.1.tgz", + "integrity": "sha512-1e9d3kb97NHJTIJDZW9rKqW2h6+dFa50Dy0fpPSMQp2ADje5gvKsXmdiK6dwY5t76TaTt5+P5N1Y/LoToIxP6g==", + "license": "MIT", + "engines": { + "node": ">= 12" + } + }, + "node_modules/luxon": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/luxon/-/luxon-2.5.2.tgz", + "integrity": "sha512-Yg7/RDp4nedqmLgyH0LwgGRvMEKVzKbUdkBYyCosbHgJ+kaOUx0qzSiSatVc3DFygnirTPYnMM2P5dg2uH1WvA==", + "license": "MIT", + "engines": { + "node": ">=12" + } + }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/memory-pager": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/memory-pager/-/memory-pager-1.5.0.tgz", + "integrity": "sha512-ZS4Bp4r/Zoeq6+NLJpP+0Zzm0pR8whtGPf1XExKLJBAczGMnSi3It14OiNCStjQjM6NU1okjQGSxgEZN8eBYKg==", + "license": "MIT", + "optional": true + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mongodb": { + "version": "4.17.2", + "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-4.17.2.tgz", + "integrity": "sha512-mLV7SEiov2LHleRJPMPrK2PMyhXFZt2UQLC4VD4pnth3jMjYKHhtqfwwkkvS/NXuo/Fp3vbhaNcXrIDaLRb9Tg==", + "license": "Apache-2.0", + "dependencies": { + "bson": "^4.7.2", + "mongodb-connection-string-url": "^2.6.0", + "socks": "^2.7.1" + }, + "engines": { + "node": ">=12.9.0" + }, + "optionalDependencies": { + "@aws-sdk/credential-providers": "^3.186.0", + "@mongodb-js/saslprep": "^1.1.0" + } + }, + "node_modules/mongodb-connection-string-url": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/mongodb-connection-string-url/-/mongodb-connection-string-url-2.6.0.tgz", + "integrity": "sha512-WvTZlI9ab0QYtTYnuMLgobULWhokRjtC7db9LtcVfJ+Hsnyr5eo6ZtNAt3Ly24XZScGMelOcGtm7lSn0332tPQ==", + "license": "Apache-2.0", + "dependencies": { + "@types/whatwg-url": "^8.2.1", + "whatwg-url": "^11.0.0" + } + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" + }, + "node_modules/posix-getopt": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/posix-getopt/-/posix-getopt-1.2.1.tgz", + "integrity": "sha512-BbGTiH8MOWAuc6h5yITkSn9k3HP4+QOCV9t6I5F62OrH7zqTHRo08QNsgELRreTBxcvRhbSpMoUnAx77Dz4yUA==", + "license": "MIT", + "engines": { + "node": "*" + } + }, + "node_modules/proxy-from-env": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-2.1.0.tgz", + "integrity": "sha512-cJ+oHTW1VAEa8cJslgmUZrc+sjRKgAKl3Zyse6+PV38hZe/V6Z14TbCuXcan9F9ghlz4QrFr2c92TNF82UkYHA==", + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/smart-buffer": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", + "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", + "license": "MIT", + "engines": { + "node": ">= 6.0.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/socks": { + "version": "2.8.9", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.9.tgz", + "integrity": "sha512-LJhUYUvItdQ0LkJTmPeaEObWXAqFyfmP85x0tch/ez9cahmhlBBLbIqDFnvBnUJGagb0JbIQrkBs1wJ+yRYpEw==", + "license": "MIT", + "dependencies": { + "ip-address": "^10.1.1", + "smart-buffer": "^4.2.0" + }, + "engines": { + "node": ">= 10.0.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/sparse-bitfield": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/sparse-bitfield/-/sparse-bitfield-3.0.3.tgz", + "integrity": "sha512-kvzhi7vqKTfkh0PZU+2D2PIllw2ymqJKujUcyPMd9Y75Nv4nPbGJZXNhxsgdQab2BmlDct1YnfQCguEvHr7VsQ==", + "license": "MIT", + "optional": true, + "dependencies": { + "memory-pager": "^1.0.2" + } + }, + "node_modules/tr46": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-3.0.0.tgz", + "integrity": "sha512-l7FvfAHlcmulp8kr+flpQZmVwtu7nfRV7NZujtN0OqES8EL4O4e0qqzL0DC5gAvx/ZC/9lk6rhcUwYvkBnBnYA==", + "license": "MIT", + "dependencies": { + "punycode": "^2.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD", + "optional": true + }, + "node_modules/undici-types": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-8.3.0.tgz", + "integrity": "sha512-j375ScV60dom+YkPFIfTLcOiPxkN/buHz5GobjLhixFuANaNs3C9l4GmrWqejgXWJ7BbJcFYpTEUkS1Ge8bpZQ==", + "license": "MIT" + }, + "node_modules/webidl-conversions": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", + "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=12" + } + }, + "node_modules/whatwg-url": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-11.0.0.tgz", + "integrity": "sha512-RKT8HExMpoYx4igMiVMY83lN6UeITKJlBQ+vR/8ZJ8OCdSiN3RwCq+9gH0+Xzj0+5IrM6i4j/6LuvzbZIQgEcQ==", + "license": "MIT", + "dependencies": { + "tr46": "^3.0.0", + "webidl-conversions": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + } + } +} diff --git a/readin/package.json b/readin/package.json new file mode 100644 index 0000000..6a84be4 --- /dev/null +++ b/readin/package.json @@ -0,0 +1,21 @@ +{ + "name": "timeseries_mongo", + "version": "2.0.2", + "date": "2023-12-17", + "description": "", + "main": "main.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1", + "start": "node fetchnewdata.js >>/var/log/readin.log 2>&1" + }, + "type": "module", + "keywords": [], + "author": "", + "license": "ISC", + "dependencies": { + "axios": "^1.12.0", + "luxon": "^2.3.1", + "mongodb": "^4.4.1", + "posix-getopt": "^1.2.1" + } +} diff --git a/readin/parse.js b/readin/parse.js new file mode 100644 index 0000000..334d788 --- /dev/null +++ b/readin/parse.js @@ -0,0 +1,243 @@ +// import logit from './logit.js' +import { DateTime } from 'luxon' +import * as mongo from './mongo.js' +import { statistics } from'./readdata.js' +import { logit, logerror } from './logit.js' + +let actualProps = [] +let newProps = [] + +// Check lat/lon and convert to float +function checkLatLon(w) { + let loc = 0.0; + if (!((w === undefined) || (w == null) || (w == ''))) { + try { + loc = parseFloat(w) + } catch (e) { + logerror(`Math error with lat/lon, ${e}`) + } + } + return loc +} + +// Check, if altitude is there. If so, use it, else use 0 +function checkAltitude(alt) { + let altitude = 0; + if(!((alt === undefined) || (alt === ''))) { + try { + altitude = Math.floor(parseFloat(alt)) + } catch (e) { + logerror(`Math error with altitude, ${e}`) + } + } + return altitude +} + +// binary search fir sensor id in property array +const binarySearch = (arr, element, x) => { + let start = 0, end = arr.length - 1 + // Iterate while start not meets end + while (start <= end) { + // Find the mid index + let mid = Math.floor((start + end) / 2) + // If element is present at mid, return True + if (arr[mid][element] === x) return mid + // Else look in left or right half accordingly + else if (arr[mid][element] < x) + start = mid + 1 + else + end = mid - 1 + } + return -1 +} + + +const checkProperties = (item, mapvalues, typ, dt) => { + let now = DateTime.utc().toJSDate() + let entry + // read entry from actualprops + let idx = binarySearch(actualProps, '_id', item.sensor.id) + if (idx === -1) { // not in properties => new sensor + entry = buildNewEntry(item, typ, dt, now) // so build a new entry + } else { + entry = actualProps[idx] // get actual properties + // check for change of location + if (entry.location[0].id !== item.location.id) { // have got a new location + if (newProps.findIndex((obj) => { + return (obj.replaceOne.replacement.location[0].id === item.location.id) + }) === -1) { + const newloc = { + loc: { + type: "Point", + coordinates: [ + checkLatLon(item.location.longitude), + checkLatLon(item.location.latitude) + ] + }, + id: item.location.id, + altitude: checkAltitude(item.location.altitude), + since: now, + exact_loc: item.location.exact_location, + indoor: item.location.indoor, + country: item.location.country + } + entry.location.splice(0, 0, newloc) // insert new location at pos 0 in location array + } + } else { // same location check for change in indoor or exact_location + if (entry.location[0].indoor !== item.location.indoor) { + entry.location[0].indoor = item.location.indoor // update indoor + } + if (entry.location[0].exact_loc !== item.location.exact_location) { + entry.location[0].exact_loc = item.location.exact_location // update exact_location + } + if (entry.location[0].country === '') { + entry.location[0].country = item.location.country // update country + } + } + // Check für new name + if (entry.name[0].name !== item.sensor.sensor_type.name) { // have got a new name + if (newProps.findIndex((obj) => { + return (obj.replaceOne.replacement.name[0].name === item.sensor.sensor_type.name) + }) === -1) { + let newname = { + name: item.sensor.sensor_type.name, + since: now + } + entry.name.splice(0, 0, newname) + } + } + } + // set new mapvalues + entry.values = mapvalues + delete entry.location_id + delete entry.last_seen + delete entry.since + // push this entry to the new proerties array + newProps.push({replaceOne: { filter: {_id: entry._id}, replacement: entry, upsert: true}}) +} + + +const buildNewEntry = (item, typ, dt, now) => { + return { + _id: item.sensor.id, + type: typ, + name: [{ + name: item.sensor.sensor_type.name, + since: now, + }], + location: [{ + loc: { + type: "Point", + coordinates: [ + checkLatLon(item.location.longitude), + checkLatLon(item.location.latitude) + ] + }, + id: item.location.id, + altitude: checkAltitude(item.location.altitude), + since: now, + exact_loc: item.location.exact_location, + indoor: item.location.indoor, + country: item.location.country + }] + } +} + +const types = { + P1: 'pm', P2: 'pm', P0: 'pm', + temperature: 'thp', humidity: 'thp', pressure: 'thp', + noise_LAeq: 'noise', noise_LA_max: 'noise', noise_LA_min: 'noise', + counts_per_minute: 'radioactivity', + lat: 'gps' +}; + + +function getType(typ) { + if(typ in types) { + return types[typ]; + } else { + return 'unknown' + } +} + +export const constructDBaseEntries = async (client, body, args) => { + logit(`Number of entries: ${body.length}`) + logit('Parsing ...') + let start = DateTime.now() + let allLines = { + pm: [], thp: [], noise: [], radioactivity: [], gps: [], unknown: [] + } + let datalines = '' + actualProps = await mongo.getallProperties(client) + try { + for (let item of body) { // check all entries + const dt = item.timestamp.split(' ') + const datetime = new Date(dt[0] + 'T' + dt[1] + 'Z') // extract date of entry as utc + let values = {} + let ival = '' // fetch values + let typ = 'unknown' + let mapvalue = {} + for (let v of item.sensordatavalues) { // for all values + let vtyp = v.value_type; // extract value type + if (typ === 'unknown') { // extract measurement type + typ = getType(vtyp) + } + if(typ === 'noise') { + vtyp = vtyp.slice(6) + } + let val = v.value; // and value + let x + try { + x = parseFloat(val); // convert value to float + if (Number.isNaN(x)) { + x = -9999.9 // default if value is invalid or unknown + } + } catch (err) { + console.log('Math parse float error on value'); + x = -9999.9 // default if value is invalid or unknown + } + values[vtyp] = x + ival += `${vtyp}=${x},` + // if noise sensor precalculate pow10 + if (vtyp == 'LAeq') { + let e10 = Math.pow(10, x / 10) + values.E10tel_eq = e10 + ival += `E10tel_eq=${e10},` + mapvalue.E10tel_eq = e10 + } + mapvalue[vtyp] = x + } + let store = true + if(args.typ) { + if(!args.typ.includes(typ)) { + store = false + } + } + if (store) { + allLines[typ].push({sensorid: item.sensor.id, datetime: datetime, values: values}) + datalines += `${typ},sid=${item.sensor.id} ${ival.slice(0,-1)} ${datetime.getTime()}\n` + mapvalue.timestamp = datetime + checkProperties(item, mapvalue, typ, datetime); // check if new or new location or new sensor + } + } + } catch (e) { + logerror(`constructDBaseEntries ${e}`); + } + // sort allLines on sensorID + + for (const [k,v] of Object.entries(allLines)) { + allLines[k].sort((a, b) => { + if (a.sensorid < b.sensorid) { + return -1 + } else if (a.sensorid > b.sensorid) { + return 1 + } else { + return 0 + } + }) + } + statistics.parseTime = DateTime.now().diff(start, ['seconds']).toObject().seconds + logit(`Parse time: ${statistics.parseTime} sec`) + return [newProps, allLines, datalines] +} + diff --git a/readin/readdata.js b/readin/readdata.js new file mode 100644 index 0000000..878776c --- /dev/null +++ b/readin/readdata.js @@ -0,0 +1,51 @@ +import axios from 'axios' +import * as fs from 'fs' +import { logit, logerror} from'./logit.js' +import { DateTime } from 'luxon' +const API_URL = 'https://api.sensor.community/static/v1/data.json'; // URL to API on 'luftdaten.info' +const SAVE_NAME = './data/aktdata.json'; // filename for actual data + +let LIVE = process.env.LIVE || 'true' +export let statistics = {}; + +export const doReadfromAPI = async () => { + logit(`LIVE = ${LIVE}`) + let start = DateTime.now() + let data = [] + if (LIVE === 'true') { + logit(`Start Reading from API`) + let body + for(let count = 1; count <= 3; count++) { + try { + logit(`Try - ${count}`) + let ret = await axios(API_URL, {timeout: 10000}) + if (ret.status != 200) { + continue + } + data = ret.data + saveDatatoFile(SAVE_NAME, JSON.stringify(data)) + break + } catch (e) { + logerror(`doReadfromAPI ${e}`) + } + } + } else { + logit('Start using data on disk') + data = readDatafromFile(SAVE_NAME) + } + statistics.readInTime = start.diffNow('seconds').toObject().seconds * -1 + statistics.entries = data.length + logit(`ReadIn-Time: ${statistics.readInTime} sec`) + return data +} + + +// die Daten in eimnr Datei zwischenspeichern +function saveDatatoFile(fn, data) { + fs.writeFileSync(fn, data) +} + +// Daten wieder vom File lesen +function readDatafromFile(fn) { + return JSON.parse(fs.readFileSync(fn)) +} diff --git a/readin/ts_rotate b/readin/ts_rotate new file mode 100644 index 0000000..b26c703 --- /dev/null +++ b/readin/ts_rotate @@ -0,0 +1,9 @@ +/var/log/timeseries.log { + daily + rotate 7 + delaycompress + compress + notifempty + missingok +} + diff --git a/sensorapi/.dockerignore b/sensorapi/.dockerignore new file mode 100644 index 0000000..4a9fb4f --- /dev/null +++ b/sensorapi/.dockerignore @@ -0,0 +1,9 @@ +build_and_copy.sh +Dockerfile_sensorapi +docker-compose.yml +.vscode +log +mocks +test +node_modules +doc diff --git a/sensorapi/.gitignore b/sensorapi/.gitignore new file mode 100644 index 0000000..d441c00 --- /dev/null +++ b/sensorapi/.gitignore @@ -0,0 +1,5 @@ +node_modules/ +.idea +.env* +.DS_Store +sensorapi.log diff --git a/sensorapi/.vscode/launch.json b/sensorapi/.vscode/launch.json new file mode 100644 index 0000000..960e366 --- /dev/null +++ b/sensorapi/.vscode/launch.json @@ -0,0 +1,75 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "type": "node", + "request": "launch", + "name": "Launch reception", + "skipFiles": [ + "/**" + ], + "env": { + "DEBUG": "sensorapi:*", + "INFLUXHOST": "192.168.178.190", + "INFLUXTOKEN": "gHGGgjaK0lmM6keMa01JeuDpqOE_vRq8UimsU4QKb2miI5BDh2PfWynEbwKizdJapXy8jVbTat5mVZLQTNmSdw==", + "MONGOHOST": "192.168.178.190", + "MONGOAUTH": "true", + "MONGOUSRP": "admin:mongo4noise", +// "DBASE": "influx", + }, + "program": "${workspaceFolder}/bin/www.js" + }, + { + "type": "node", + "request": "launch", + "name": "Launch esprimo", + "skipFiles": [ + "/**" + ], + "program": "${workspaceFolder}/bin/www.js", + "env": { + "DEBUG": "sensorapi:*", + "MONGOUSRP": "admin:mongo4noise", + "MONGOPORT": "27037", + "MONGOHOST": "217.72.203.152", + //"MONGOUSRP": "rexfue:5g2h4j3XC$$C$§442dcdsvDCx", + "MONGOAUTH": "true", + "INFLUXTOKEN": "q35XUBaElzcy8dDd9HF2_mpeHvYCampZg_9mJNP5jeBQRopq3EWIzNTZ555QLSIXhZC05RXCoFgjiaT7VzyNkQ==", + "DEVELOP": "true", + } + }, + { + "type": "node", + "request": "launch", + "name": "Ralf", + "skipFiles": [ + "/**" + ], + "program": "${workspaceFolder}/bin/www.js", + "env": { + "MONGOHOST": "192.168.51.22", + "MONGOAUTH": "true", + "MONGOUSRP": "rexfue:s25BMmW2gg", + } + }, + { + "type": "node", + "request": "launch", + "name": "Launch localhost", + "skipFiles": [ + "/**" + ], + "program": "${workspaceFolder}/bin/www.js", + "env": { + "INFLUXHOST": "localhost", + "INFLUXTOKEN": "Pt7cDkKS1pAI2a0qsAhfSY97EVsfeNwJxo-ZdiNvfwC4kBiqxmoj7WbR7XkNRr23YELydv_9HXrN2SMofq9vhQ==", + "MONGOHOST": "localhost", + "MONGOPORT": "27017", + "DEBUG": "sensorapi:*" + } + } + ] +} \ No newline at end of file diff --git a/sensorapi/Dockerfile_sensorapi b/sensorapi/Dockerfile_sensorapi new file mode 100644 index 0000000..bc24c99 --- /dev/null +++ b/sensorapi/Dockerfile_sensorapi @@ -0,0 +1,24 @@ +FROM node:22-alpine + +ADD package.json /tmp/package.json +ADD package-lock.json /tmp/package-lock.json +RUN cd /tmp && npm ci +RUN mkdir -p /opt/app && cp -a /tmp/node_modules /opt/app/ + +WORKDIR /opt/app +ADD . /opt/app + +# RUN apk add busybox-initscripts +RUN apk add --no-cache tzdata +ENV TZ Europe/Berlin +RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone + +RUN deluser --remove-home node + +RUN touch cmds.sh \ + && echo 'npm start' >>cmds.sh + +CMD sh ./cmds.sh + + + diff --git a/sensorapi/actions/data4map.js b/sensorapi/actions/data4map.js new file mode 100644 index 0000000..7ce7d64 --- /dev/null +++ b/sensorapi/actions/data4map.js @@ -0,0 +1,190 @@ +// Fetch the actual (= newest) data out of the dbase to show it on the map +import {DateTime} from "luxon" +import * as mongo from "../databases/mongo.js" +import { returnOnError } from "../utilities/reporterror.js" + + +// Default distance for center search ( in km) +const DEFAULT_DISTANCE = 10 + +// Value to use fpr map +const value4map = [ + { typ: 'noise', value: 'LA_max'}, + { typ: 'pm', value: 'P1'}, + { typ: 'thp', value: 'temperature'}, + { typ: 'radioactivity', value: 'counts_per_minute'}, +] + +// get value for map from tabel +const getValue4Map = (t) => { + for(let x of value4map) { + if(x.typ == t) { + return x.value + } + } + return '' +} + +// Relations between types and value type +const vtype2measurement = { + P1: 'pm', P2: 'pm', P0: 'pm', + temperature: 'thp', humidity: 'thp', pressure: 'thp', + LAeq: 'noise', + counts_per_minute: 'radioactivity' +}; + + + +// find first value type from measurement +const getfieldfromtype = (typ) => { + for (const [key, value] of Object.entries(vtype2measurement)) { + if (value === typ) { + return key + } + } + return ' ' +} + + +// read the last entries from the influx database +const readLastDates = async (typ) => { + let ret = {values: [], err: null} + let query = ` + from(bucket: "sensor_data") +|> range(start: -2h) +|> filter(fn: (r) => r._measurement == "${typ}" and r._field == "${getValue4Map(typ)}") +|> last() +|> group() +|> map(fn: (r) => ({r with sid: int(v: r.sid)})) +|> sort(columns: ["sid"]) +|> keep(columns: ["_time","sid","_value"]) +` + return await fetchFromInflux(ret, query) +} + +export var getData4map = async (params) => { + let start = DateTime.now() + let ret = {err: null} + + // ***** This function will (at the moment) only be called by internal routines, so there is no need to check the parameters ! + + const typ = params.type + let poly = [] + let south = null, north = null, east = null, west = null, center = null + let distance = DEFAULT_DISTANCE + if(params.box !== undefined) { + let val = params.box.split(',') + for (let i = 0; i < val.length; i++) { + val[i] = parseFloat(val[i]) + } + south = parseFloat(val[1]) + north = parseFloat(val[3]) + east = parseFloat(val[2]) + west = parseFloat(val[0]) +// logit(`getData4map: S=${south} N=${north} E=${east} W=${west}`) + } + if (!((params.poly === undefined) || (params.poly === ' '))){ + poly = JSON.parse(params.poly) + } + if (params.center !== undefined) { + center = params.center + if ((params.distance !== undefined) && + (params.distance >= 1) && (params.distance <= 1000)) { + distance = params.distance + } + } + const aktData = [] + let lastDate = 0 + let query = {type: typ} + + // if polyline or box were given, set query + if (poly.length !== 0) { // polyline given + query.location = { + $geoWithin: { + $geometry: { + type: "Polygon", + coordinates: [poly], + } + } + } + } else if (south !== null) { // box given + query["location.loc"] = { + $geoWithin: { + $box: [ + [west, south], + [east, north] + ] + } + } + } else if (center !== null) { // center point given + query["location.loc"] = { + $nearSphere: { + $geometry: { + type: "Point", + coordinates: center + }, + $maxDistance: distance * 1000 + } + } + } + try { + // fetch mapdata from mongodb + let { properties, err } = await mongo.getallProperties(mongo.properties_collection, query) + if(err) { + return returnOnError(ret, 'NOPROPSFOUND', getData4map.name) + } + let v4map = getValue4Map(typ) + for (let sensor of properties) { + let oneAktData = {} + if (sensor.values !== undefined) { + oneAktData = { + location: sensor.location[0].loc.coordinates, + id: sensor._id, + name: sensor.name[0].name, + indoor: sensor.location[0].indoor, + lastseen: sensor.values.timestamp + } + let now = new Date().getTime() + if(oneAktData.lastseen !== '') { + let diff = now - oneAktData.lastseen.getTime() + if (diff >= 365 * 24 * 3600 * 1000) { + oneAktData.value = -4 + } else if (diff >= 30 * 24 * 3600 * 1000) { + oneAktData.value = -3 + } else if (diff >= 7 * 24 * 3600 * 1000) { + oneAktData.value = -2 + } else if (diff >= 2 * 3600 * 1000) { + oneAktData.value = -1 + } else { + if (sensor.values !== undefined) { + oneAktData.value = Math.round(sensor.values[v4map] * 100) / 100 + } + } + let weeks = Math.round(diff / (7 * 24 * 3600 * 1000)) + oneAktData.weeks = weeks + } + if (sensor.values.timestamp > lastDate) { + lastDate = sensor.values.timestamp + } + } else { + oneAktData.value = -5 + oneAktData.weeks = 0 + oneAktData.lastseen = '' + } + aktData.push(oneAktData) + } + ret = { + err: null, + options: { + lastdate: lastDate, + count: aktData.length, + data: 'map' + }, + values: aktData + } + return ret + } + catch(e) { + return returnOnError(ret, `catch\n${e}`, getData4map.name) + } +} diff --git a/sensorapi/actions/getAKWData.js b/sensorapi/actions/getAKWData.js new file mode 100644 index 0000000..b7384e5 --- /dev/null +++ b/sensorapi/actions/getAKWData.js @@ -0,0 +1,62 @@ +// get data for one sensor + +import {DateTime} from "luxon" +import { logit, logerror } from '../utilities/logit.js' +import * as mongo from "../databases/mongo.js" +import {reportError, returnOnError} from "../utilities/reporterror.js" +import {csv2Json} from "../utilities/csv2json.js" + + +// Fetch all akw data out of the dbase +// router.get('/getakwdata/', async function (req, res) { +export const getakwdata = async (options) => { + let data = {err: null, ...options, count: 0, values: []} + let erg = [] + try { + let rawAKWs = await mongo.readAKWs(options) + if (rawAKWs.err) { + return returnOnError(date, rawAKWs.err, getakwdata.name) + } + for (let item of rawAKWs.values.akws) { + var oneAktData = {}; + oneAktData['location'] = { + type: 'Point', + coordinates: [item.lon, item.lat] + }; + oneAktData['name'] = item.Name; + oneAktData['active'] = item.Status == 'aktiv'; + oneAktData['start'] = item.Baujahr; + oneAktData['end'] = item.Stillgeleg; + oneAktData['type'] = item.Status === 'aktiv' ? 'akw_a' : 'akw_s'; + oneAktData['link'] = item.Wiki_Link; + erg.push(oneAktData); // dies ganzen Werte nun in das Array + } + for (let item of rawAKWs.values.th1_akws) { + let oneAktData = {}; + let loc = item.geo.substr(6).split(' '); + let lon = parseFloat(loc[0]); + let lat = parseFloat(loc[1]); + oneAktData['location'] = { + type: 'Point', + coordinates: [lon, lat] + }; + oneAktData['name'] = item.name; + oneAktData['typeText'] = item.types; + oneAktData['type'] = item.types == "Nuclear power plant" ? 'akw_a' : 'other'; + oneAktData['link'] = item.item; + if (item.itemServiceretirement != undefined) { + oneAktData['ende'] = item.itemServiceretirement.substr(0, 4); + } + if (item.itemServiceentry != undefined) { + oneAktData['begin'] = item.itemServiceentry.substr(0, 4); + } + erg.push(oneAktData); + } + data.values = erg + data.count = erg.length + } catch (e) { + return returnOnError(data, e, getakwdata.name) + } + return data +} + diff --git a/sensorapi/actions/getaddress.js b/sensorapi/actions/getaddress.js new file mode 100644 index 0000000..eecf128 --- /dev/null +++ b/sensorapi/actions/getaddress.js @@ -0,0 +1,80 @@ +import {returnOnError} from "../utilities/reporterror.js" +import axios from 'axios' +import {logit} from "../utilities/logit.js" +import {getOneProperty} from "./getproperties.js" +import { response } from "express" + +const NOMINATIM_URL = `https://nominatim.openstreetmap.org/reverse?lat=${'xx'}&lon=${'yy'}&format=json` +const NOMINATIM_CITY_URL = `https://nominatim.openstreetmap.org/?q="${'xx'}"&format=json` + +export const getCityCoords = async (params) => { + let ret = {coords: [], city: params.city, err: null} + let url = NOMINATIM_CITY_URL.replace('xx', params.city) +// let url = 'https://nominatim.openstreetmap.org/?q="K%C3%B6ln"&format=json' + try { + const response = await axios(url) + if (response.status !== 200) { + return returnOnError(ret, 'RESPSTATUS', getCityCoord.name, response.status) + } + ret.coords = [response.data[0].lat,response.data[0].lon] + logit(JSON.stringify(ret.coords)) + } catch (e) { + return returnOnError(ret, e, getCityCoords.name) + } + return ret +} + +export const getAddress = async (params) => { + let ret = {address: "", err: null} + let {props, err} = await getOneProperty(params) + if (err) { + return returnOnError(ret, err, getAddress.name) + } + let coord = props.location[0].loc.coordinates + let url = NOMINATIM_URL.replace('xx', coord[1]).replace('yy', coord[0]) + try { + const response = await axios(encodeURI(url),{ + headers: { + 'User-Agent': 'Firefox 132.0.1' + } + }); + if (response.status !== 200) { + return returnOnError(ret, 'RESPSTATUS', getAddress.name, response.status) + } + let akt = response.data.address +// logit(JSON.stringify(akt)) + const CITY = ['city', 'town', 'village', 'suburb', 'county'] + let city = "unknown" + for (let c of CITY) { + if(akt[c] !== undefined) { + city = akt[c] + break + } + } +// ret.address = `${(akt.road ? akt.road : "")} ${(akt.postcode ? akt.postcode : "")} ${city}`; + ret.address = { + street: `${(akt.road ? akt.road : "")}`, + plz: `${(akt.postcode ? akt.postcode : "")}`, + city: `${city}`} + } catch (e) { + return returnOnError(ret, e, getAddress.name) + } + return ret +} +/* + let addr = "Addr"; + try { + let ret = await $.get("api/getprops?sensorid=" + marker.options.name); + if(ret.values[0].address.city == null) { + addr += " unbekannt !" + } else { + let akt = ret.values[0].address; + addr = (akt.street ? akt.street : "") + "  " + (akt.plz ? akt.plz : "") + " " + akt.city; + } + } catch (e) { + console.log("onMarker - getpops", e) + } + console.log("addr:", addr); + return addr; + + */ diff --git a/sensorapi/actions/getproperties.js b/sensorapi/actions/getproperties.js new file mode 100644 index 0000000..e3087eb --- /dev/null +++ b/sensorapi/actions/getproperties.js @@ -0,0 +1,48 @@ +// Fetch the properties for the given sensor + +import * as mongo from "../databases/mongo.js" +import {returnOnError} from "../utilities/reporterror.js" +import checkParams from "../utilities/checkparams.js" + +let readProperties = mongo.readProperties +let readChipData = mongo.readChipData + +// Read properties for sensorid and properties for all other sensors on same location +export const getOneProperty = async (params) => { + let properties = {err: null, props: {}, chip: {}} + let {opts, err} = checkParams(params, {mandatory:[{name:'sensorid', type: 'int'}], optional:[]}) + if (err) { + return returnOnError(properties, err, getOneProperty.name) + } + // read 'chip'-data (special for noise sensors) + const chipdata = await readChipData(opts.sensorid) + if (chipdata.err === null) { + properties.chip = chipdata + } + let sensorEntries = []; + try { + let pp = await readProperties({sid: opts.sensorid}); // read for given sensorID + if ((pp.properties == null) || (pp.error)) { + return returnOnError(properties, 'NOPROPSREAD', getOneProperty.name, opts.sensorid) + } + // now find sensors with same location + let query = {"location.0.id": pp.properties.location[0].id} + let others = await readProperties(query) + if (others.err) { + return returnOnError(properties, 'NOPROPSREAD', getOneProperty.name, others.errortext) + } + if (others.properties.length > 0) { + for (const x of others.properties) { + if(x._id === pp.properties._id) { + continue + } + sensorEntries.push({name: x.name[0].name, sid: x._id}) + } + } + properties.props = pp.properties + properties.props.othersensors = sensorEntries; + } catch (e) { + return returnOnError(properties, e, getOneProperty.name) + } + return properties +} diff --git a/sensorapi/actions/getsensorData.js b/sensorapi/actions/getsensorData.js new file mode 100644 index 0000000..c8e5ece --- /dev/null +++ b/sensorapi/actions/getsensorData.js @@ -0,0 +1,308 @@ +// get data for one sensor + +const DBASE = process.env.DBASE || 'mongo' +import {DateTime} from "luxon" +import * as influx from "../databases/influx.js" +import * as mongo from "../databases/mongo.js" +import {returnOnError} from "../utilities/reporterror.js" +import {csv2Json} from "../utilities/csv2json.js" +import checkParams from "../utilities/checkparams.js" +import {getOneProperty} from "./getproperties.js" +import {getNoiseData} from "../sensorspecials/noise.js" +import {getgeigerData} from "../sensorspecials/geigeract.js" + +// Possible params for the different sensor types +const noiseParams = [ + {name:'data', type: 'string', default: 'live'}, + {name: 'span', type: 'int', default: 1}, + {name: 'daystart', type: 'bool', default: null}, + {name: 'peak', type: 'int', default: 70}, + {name: 'since', type: 'date', default: '1900-01-01T00:00:00Z'}, + {name: 'box', type: 'array', default: null}, + {name: 'out', type: 'string', default: ''}, + {name: 'csv', type: 'bool', default: false}, + {name: 'long', type: 'bool', default: false}, + {name: 'sort', type: 'int', default: 1}, + {name: 'last_seen', type: 'date', default: '1900-01-01T00:00:00Z'}, + {name: 'datetime', type: 'date', default: null} +] +const thpParams = [] +const pmParams = [] +const geigerParams = [ + {name: 'what', type: 'string', default: 'day'}, + {name: 'span', type: 'int', default: 1}, + {name: 'daystart', type: 'bool', default: null}, + {name: 'avg', type: 'int', default: 1}, + {name: 'since', type: 'date', default: '1900-01-01T00:00:00Z'}, + {name: 'box', type: 'array', default: null}, + {name: 'out', type: 'string', default: ''}, + {name: 'csv', type: 'bool', default: false}, + {name: 'long', type: 'bool', default: false}, + {name: 'sort', type: 'int', default: 1}, + {name: 'last_seen', type: 'date', default: '1900-01-01T00:00:00Z'}, + {name: 'datetime', type: 'date', default: null}, + {name: 'moving', type: 'bool', default: false}, +] + +// >>>>>>>>>>>>>>>>>>>>> DUMMIES +async function getPmData(opts) { + +} +async function getThpData(opts) { + +} +// <<<<<<<<<<<<<<<<<<<<< DUMMIES + +// Table for the different sensor types +const sensorTypeTable = [ + { typ: 'thp', possibleParams: thpParams, func: getThpData}, + { typ: 'noise', possibleParams: noiseParams, func: getNoiseData}, + { typ: 'pm', possibleParams: pmParams, func: getPmData}, + { typ: 'radioactivity', possibleParams: geigerParams, func: getgeigerData} +] + +/* Units: +* span -> days +* avg -> minutes +*/ + +// ********************************************* +// calcRange +// +// Calculate the date/time range ro read the data from +// +// If 'datetime' is not given, use 'now()' as end and 'now()' - span as start +// If 'datetime' is given, use it as start and 'datetime'+span as end +// If 'daystart'==true, change start and end so, that they begin at 00:00:00h +// if 'avg' has a value, move start backward ba 'avg' minutes +// +// params: +// opts: Object with different options, specially +// datetime, avg, daystart, span +// +// return: +// Object with start and stop in ISO-Format +// ********************************************* +export const calcRange = (opts) => { + let start, end + let ret = { start: start, stop: end, err: null} + if((opts.datetime === null) || (opts.datetime === undefined) || (opts.datetime === '')) { + start = end = DateTime.local().toUTC() + start = start.minus({days: opts.span}) + } else { + start = end = DateTime.fromISO(opts.datetime).toUTC() + end = end.plus({days: opts.span}) + } + if(opts.daystart) { + start = start.startOf("day") + end = end.startOf("day") + } +// start = start.toUTC() +// end = end.toUTC() + // if(opts.avg !== undefined) { + // start = start.minus({minutes: opts.avg}) + // } + ret.start = `start: ${start.toISO()}` + ret.stop = `stop: ${end.toISO()}` + return ret +} + + +// ********************************************* +// getSensorData +// +// Depending on the parameter 'sensorid', distribute to the special routines for +// the sensors +// +// params: +// params: all parameters from the url +// +// return: +// Returns from the special routines +// ********************************************* +// export const getSensorData = async (params) => { +export async function getSensorData(params) { + let ret = {err: null} + let {opts, err} = checkParams(params, { // check for sensorid + mandatory: [{name: 'sensorid', type: 'int'}], + optional: [] + }) + if (err) { + return returnOnError(ret, err, getSensorData.name) + } + // with the sensorid get the type of this sensor + let erg = await getOneProperty({sensorid: opts.sensorid}) + if (erg.err) { + return returnOnError(ret, erg.err, getSensorData.name) + } + + // distribute to the right routine + for(let item of sensorTypeTable) { + if(item.typ === erg.props.type) { + ret = await item.func(params, item.possibleParams, erg.props) // get the values from database + return ret + } + } + return returnOnError(ret, 'CMNDUNKNOWN', getActData.name) +} + + + + +// export const getActData = async (opts) => { +export async function getActData(opts) { + if (DBASE === 'mongo') { + return await mongo.fetchActData(opts) + } else if (DBASE === 'influx') { + return await influx.fetchActData(opts) + } + return {err: 'DBASEUNKNOWN', values: []} +} + + +// ..../api/getavgdata? +// ToDo: check UTC !!!! +export var getAvgData = async (params) => { + let ret = {data: {count: 0, values: []}, err: null} + let {opts, err} = checkParams(params, + { + mandatory: + [ + {name: 'sensorid', type: 'int'}, + ], + optional: + [ + {name: 'span', type: 'int', default: 1}, + {name: 'datetime', type: 'date', default: null}, + {name: 'avg', type: 'int', default: 10}, + {name: 'moving', type: 'bool', default: true}, + ] + } + ) + if (err) { + return returnOnError(ret, err, getActdata.name) + } + let {start, stop} = calcRange(opts) + if (stop === '') { + ret.data.start = DateTime.now().toUTC().minus({days: `${opts.span}`}).toFormat("yyyy-LL-dd'T'HH:mm:ss'Z'") + } else { + ret.data.start = DateTime.fromISO(opts.datetime, {zone: 'utc'}).toISO() + } + ret.data.span = opts.span + ret.data.moving = opts.moving + ret.data.avg = opts.avg + + let every = opts.moving ? '150s' : `${opts.avg}m` + let period = `${opts.avg}m` + let query = ` + from(bucket: "sensor_data") +|> range(${start}, ${stop}) +|> filter(fn: (r) => r.sid == "${opts.sensorid}") +|> timedMovingAverage(every: ${every}, period: ${period}) +|> keep(columns: ["_time","_field","_value"]) +|> pivot(rowKey:["_time"], columnKey: ["_field"], valueColumn: "_value") + ` + return await fetchFromInflux(ret, query) +} + +// ..../api/getlongavg?sensorid=123&span=2 +export var getLongAvg = async (params) => { + let ret = {data: {count: 0, values: []}, err: null} + let {opts, err} = checkParams(params, + { + mandatory: + [ + {name: 'sensorid', type: 'int'}, + ], + optional: + [ + {name: 'span', type: 'int', default: 2}, + ] + } + ) + if (err) { + return returnOnError(ret, err, getActdata.name) + } + ret.data.span = opts.span + let query = ` + from(bucket: "sensor_data") +|> range(start: -${opts.span}d) +|> filter(fn: (r) => r.sid == "${opts.sensorid}") +|> mean() +|> drop(columns: ["_start","_measurement", "sid"]) +|> pivot(rowKey:["_stop"], columnKey: ["_field"], valueColumn: "_value") + ` + return await fetchFromInflux(ret, query) +} + + + + +// ********************************************* +// function getMAPaktData() { +// +// Get the actual data from the database within the bounds for the given sensor typ +// +// params: +// opt: opt.box => region for which to find sensor data +// opt.typ: type of sensor +// +// return +// JSON +// { avgs: [ +// { location: [ 9.00, 48.80 ], id: 29174, lastSeen: "2019-10-23T12:03:00.000Z", max: "65" } +// { location: [ 9.10, 49.80 ], id: 28194, lastSeen: "2019-10-22T16:03:00.000Z", max: "45" } +// ......... +// ], lastDate: "2019-10-29T15:05:59.000Z" } +// +// ********************************************* +export const getMAPaktData = async (opt) => { + let box = opt.box + if ((box == "") || (box == undefined)) { + return {"avgs": [], "lastDate": null} + } + let south = parseFloat(box[0][1]) + let north = parseFloat(box[1][1]) + let east = parseFloat(box[1][0]) + let west = parseFloat(box[0][0]) + let aktData = [] + let lastDate = 0 + let loc = { + location: { + $geoWithin: { + $box: [ + [west, south], + [east, north] + ] + } + }, + typ: opt.typ, + } + let docs = await mongo.readMapdata(loc,0) +// console.log(docs) + for (let i = 0;i < docs.length; i++) { + let item = docs[i] + let oneAktData = {} + oneAktData['location'] = item.location.coordinates + oneAktData['id'] = item._id // ID des Sensors holen + oneAktData['lastSeen'] = item.values.datetime + oneAktData['indoor'] = item.indoor + let dati = item.values.datetime + let dt = new Date(dati) + if ((now - dt) >= 31 * 24 * 3600 * 1000) { // älter als 1 Monat -> + oneAktData['noise_max'] = -2 // -2 zurückgeben + } else if ((now - dt) >= 3600 * 1000) { // älter als 1 Stunde -> + oneAktData['noise_max'] = -1 // -1 zurückgeben + } else { + oneAktData['noise_max'] = -5 // bedutet -> nicht anzeigen + if (item.values.hasOwnProperty('LA_max')) { + oneAktData['noise_max'] = item.values.LA_max.toFixed(0) // und merken + } + if (dati > lastDate) { + lastDate = dati + } + } + aktData.push(oneAktData) // dies ganzen Werte nun in das Array + } + return {"avgs": aktData, "lastDate": lastDate} // alles bearbeitet _> Array senden +} diff --git a/sensorapi/app.js b/sensorapi/app.js new file mode 100644 index 0000000..aa47566 --- /dev/null +++ b/sensorapi/app.js @@ -0,0 +1,66 @@ +import createError from 'http-errors' +import logger from 'morgan' +import express from 'express' +import cookieParser from 'cookie-parser' +import cors from 'cors' +import i18next from 'i18next' +import i18nextMiddleware from 'i18next-http-middleware' +import Backend from 'i18next-fs-backend' +import {logit} from "./utilities/logit.js" +import pkg from './package.json' with { type: "json" } + + +const app = express() + +const __filename = fileURLToPath(import.meta.url); +const __dirname = path.dirname(__filename); + +import indexRouter from './routes/index.js' +import { apiRouter } from './routes/api.js' +import {fileURLToPath} from "url"; +import path from "path"; + + +i18next + .use(Backend) + .use(i18nextMiddleware.LanguageDetector) + .init({ + backend: { + loadPath: __dirname + '/locales/{{lng}}/{{ns}}.json' + }, + fallbackLng: 'de', + debug: false, + preload: ['de', 'en'] + }); + +app.use(i18nextMiddleware.handle(i18next)); + +app.use(cors()) +app.use(logger('dev')) +app.use(express.json()) +app.use(express.urlencoded({ extended: true })) +app.use(cookieParser()) + +app.use('/', indexRouter) +app.use('/api', apiRouter) + + +// catch 404 and forward to error handler +app.use(function(req, res, next) { + next(createError(404)) +}) + +// error handler +app.use(function(err, req, res, next) { + // set locals, only providing error in development + res.locals.message = err.message + res.locals.error = req.app.get('env') === 'development' ? err : {} + + // render the error page + res.status(err.status || 500) + res.send(`ERROR: ${err.status}, ${err.stack}`) +}) + +logit(`Start of Program Version: ${pkg.version} vom ${pkg.date}`) + +export default app diff --git a/sensorapi/bin/www.js b/sensorapi/bin/www.js new file mode 100644 index 0000000..98160d6 --- /dev/null +++ b/sensorapi/bin/www.js @@ -0,0 +1,93 @@ +#!/usr/bin/env node + +/** + * Module dependencies. + */ + +import app from '../app.js' +import Debug from 'debug' +import http from 'http' + +const debug = Debug('sensorapi:*') + +/** + * Get port from environment and store in Express. + */ + +const port = normalizePort(process.env.PORT || '3005'); +app.set('port', port); + +/** + * Create HTTP server. + */ + +const server = http.createServer(app); + +/** + * Listen on provided port, on all network interfaces. + */ + +server.listen(port); +server.on('error', onError); +server.on('listening', onListening); + +/** + * Normalize a port into a number, string, or false. + */ + +function normalizePort(val) { + const port = parseInt(val, 10); + + if (isNaN(port)) { + // named pipe + return val; + } + + if (port >= 0) { + // port number + return port; + } + + return false; +} + +/** + * Event listener for HTTP server "error" event. + */ + +function onError(error) { + if (error.syscall !== 'listen') { + throw error; + } + + const bind = typeof port === 'string' + ? 'Pipe ' + port + : 'Port ' + port; + + // handle specific listen errors with friendly messages + switch (error.code) { + case 'EACCES': + console.error(bind + ' requires elevated privileges'); + process.exit(1); + break; + case 'EADDRINUSE': + console.error(bind + ' is already in use'); + process.exit(1); + break; + default: + throw error; + } +} + +/** + * Event listener for HTTP server "listening" event. + */ + +function onListening() { + const addr = server.address(); + const bind = typeof addr === 'string' + ? 'pipe ' + addr + : 'port ' + addr.port; + debug('Listening on ' + bind); + console.log('Listening on ' + bind); +} diff --git a/sensorapi/build_and_copy.sh b/sensorapi/build_and_copy.sh new file mode 100755 index 0000000..1f07fb5 --- /dev/null +++ b/sensorapi/build_and_copy.sh @@ -0,0 +1,63 @@ +#!/bin/bash +# Build Docker-Container +# +# Call: buildit.sh name [target] +# +# The Dockerfile must be named like Dockerfile_name +# +# 2018-09-20 rxf +# - before sending docker image to remote, tag actual remote image +# +# 2018-09-14 rxf +# - first Version +# + +set -x +port="" +orgName=sensorapi +name=sensorapi + +usage() +{ + echo "Usage build_and_copy.sh [-p port] [-n name] target" + echo " Build docker container $name and copy to target" + echo "Params:" + echo " target: Where to copy the container to " + echo " -p port: ssh port (default 22)" + echo " -n name: new name for container (default: $orgName)" +} + +while getopts n:p:h? o +do + case "$o" in + n) name="$OPTARG";; + p) port="-p $OPTARG";; + h) usage; exit 0;; + *) usage; exit 1;; + esac +done +shift $((OPTIND-1)) + +while [ $# -gt 0 ]; do + if [[ -z "$target" ]]; then + target=$1 + shift + else + echo "bad option $1" + # exit 1 + shift + fi +done + +docker build -f Dockerfile_$orgName -t $name . + +dat=`date +%Y%m%d%H%M` + +if [ "$target" == "localhost" ] +then + docker tag $name $name:V_$dat + exit +fi + +ssh $port $target "docker tag $name $name:V_$dat" +docker save $name | bzip2 | pv | ssh $port $target 'bunzip2 | docker load' diff --git a/sensorapi/databases/influx.js b/sensorapi/databases/influx.js new file mode 100644 index 0000000..94fa11d --- /dev/null +++ b/sensorapi/databases/influx.js @@ -0,0 +1,166 @@ +// Access to influxDB vie HTTP + +import axios from 'axios' +import { DateTime } from 'luxon' +// import csvParse from 'csv-parser' +import { logit, logerror } from '../utilities/logit.js' +import {returnOnError} from "../utilities/reporterror.js"; +import {csv2Json} from "../utilities/csv2json.js"; + +let INFLUXHOST = process.env.INFLUXHOST || "localhost" +let INFLUXPORT = process.env.INFLUXPORT || 8086 +let INFLUXTOKEN = process.env.INFLUXTOKEN || "" + //"rklEClT22KfdXZhA47eyJhbqcvekb8bcKCqlUG7n72uDSmR2xGvif0CmGJe0WQtXB96y29mmt-9BdsgWA5npfg==" + //"BNR6cGdb006O1T6hQkGcfB8tgH-UPO6QkOPToeAvrP7LATJbCuWi1wYf3HBpVdZQEBxHxNSrNenZsOSMogX-lg==" +let INFLUXDATABUCKET = process.env.INFLUXDATABUCKET || "sensor_data" +let INFLUXORG = process.env.INFLUXORG || "citysensor" + +const INFLUXURL_READ = `http://${INFLUXHOST}:${INFLUXPORT}/api/v2/query?org=${INFLUXORG}` +const INFLUXURL_WRITE = `http://${INFLUXHOST}:${INFLUXPORT}/api/v2/write?org=${INFLUXORG}&bucket=${INFLUXDATABUCKET}` + +const influxRead = async (query) => { + let start = DateTime.now() + logit(`ReadInflux from ${INFLUXURL_READ}`) + let erg = { values: [], err: null} + try { + let ret = await axios({ + method: 'post', + url: INFLUXURL_READ, + data: query, + headers: { + Authorization: `Token ${INFLUXTOKEN}`, + Accept: 'application/csv', + 'Content-type': 'application/vnd.flux' + }, + timeout: 10000, + }) + if (ret.status !== 200) { + return returnOnError(erg, RESPSTATUS, influxRead.name, ret.status) + } + erg.values = ret.data + } catch (e) { + return returnOnError(erg, e, influxRead.name) + } +// logit(`Influx read time: ${start.diffNow('seconds').toObject().seconds * -1} sec`) + return erg +} + + +const influxWrite = async (data) => { + let start = DateTime.now() + let ret + try { + ret = await axios({ + method: 'post', + url: INFLUXURL_WRITE, + data: data, + headers: { + Authorization: `Token ${INFLUXTOKEN}`, + Accept: 'application/json', + 'Content-Type': 'text/plain; charset=utf-8' + }, + timeout: 10000, + }) + if (ret.status !== 204) { + logerror(`doWrite2API Status: ${ret.status}`) + } + } catch (e) { + logerror(`doWrite2API ${e}`) + } + logit(`Influx-Write-Time: ${start.diffNow('seconds').toObject().seconds * -1} sec`) + return ret +} + +const fetchFromInflux = async (ret, query) => { + let { values, err} = await influxRead(query) + if(err) { + if(err.toString().includes('400')) { + return returnOnError(ret, 'SYNTAXURL', fetchFromInflux.name) + } else { + return returnOnError(ret, err, fetchFromInflux.name) + } + } + if (values.length <= 2) { + return returnOnError(ret, 'NODATA', fetchFromInflux.name) + } + ret.values = csv2Json(values) + return ret +} + +export const fetchActData = async (opts) => { + let ret = {err: null, values: []} + let sorting = '' + if(opts.sort) { + if (opts.sort === 1) { + sorting = '|> sort(columns: ["_time"], desc: false)' + } else if (opts.sort === -1) { + sorting = '|> sort(columns: ["_time"], desc: true)' + } + } + // build the flux query + let query = ` + from(bucket: "sensor_data") +|> range(${opts.start}, ${opts.stop}) +|> filter(fn: (r) => r.sid == "${opts.sensorid}") +${sorting} +|> keep(columns: ["_time","_field","_value"]) +|> pivot(rowKey:["_time"], columnKey: ["_field"], valueColumn: "_value") +` + return await fetchFromInflux(ret, query) +} + +export const fetchNoiseAVGData = async (opts) => { + let ret = {err: null, values: []} + let small = '|> keep(columns: ["_time", "peakcount", "n_AVG"])' + if (opts.long) { + small = '' + } + let queryAVG = ` +import "math" +threshold = ${opts.peak} + +data = from(bucket: "sensor_data") + |> range(${opts.start}, ${opts.stop}) + |> filter(fn: (r) => r["sid"] == "${opts.sensorid}") +e10 = data + |> filter(fn: (r) => r._field == "E10tel_eq") + |> aggregateWindow(every: 1h, fn: mean, createEmpty: false) + |> map(fn: (r) => ({r with _value: (10.0 * math.log10(x: r._value))})) + |> keep(columns: ["_time","_field","_value"]) + |> pivot(rowKey:["_time"], columnKey: ["_field"], valueColumn: "_value") + |> rename(columns: {"E10tel_eq" : "n_AVG"}) +ecnt = data + |> filter(fn: (r) => r._field == "E10tel_eq") + |> aggregateWindow(every: 1h, fn: count, createEmpty: false) + |> keep(columns: ["_time","_field","_value"]) + |> pivot(rowKey:["_time"], columnKey: ["_field"], valueColumn: "_value") + |> rename(columns: {"E10tel_eq" : "count"}) +esum = data + |> filter(fn: (r) => r._field == "E10tel_eq") + |> aggregateWindow(every: 1h, fn: sum, createEmpty: false) + |> keep(columns: ["_time","_field","_value"]) + |> pivot(rowKey:["_time"], columnKey: ["_field"], valueColumn: "_value") + |> rename(columns: {"E10tel_eq" : "n_sum"}) +peak = data + |> filter(fn: (r) => r._field == "LA_max") + |> aggregateWindow( + every: 1h, + fn: (column, tables=<-) => tables + |> reduce( + identity: {peakcount: 0.0}, + fn: (r, accumulator) => ({ + peakcount: if r._value >= threshold then + accumulator.peakcount + 1.0 + else + accumulator.peakcount + 0.0, + }), + ), + ) + |> keep(columns: ["_time","peakcount"]) + part1 = join( tables: {e10: e10, ecnt: ecnt}, on: ["_time"]) + part2 = join( tables: {esum: esum, peak: peak}, on: ["_time"]) + join( tables: {P1: part1, P2: part2}, on: ["_time"]) + ${small} +` + return await fetchFromInflux(ret, queryAVG) +} diff --git a/sensorapi/databases/mongo.js b/sensorapi/databases/mongo.js new file mode 100644 index 0000000..d4046b3 --- /dev/null +++ b/sensorapi/databases/mongo.js @@ -0,0 +1,424 @@ +/* Interface for MongoDB +*/ +import { MongoClient } from 'mongodb' +import { logit, logerror } from '../utilities/logit.js' +import { DateTime } from 'luxon' +import {returnOnError} from "../utilities/reporterror.js"; + +// const nodemailer = require('nodemailer'); + +let MONGOHOST = process.env.MONGOHOST; +let MONGOPORT = process.env.MONGOPORT; +let MONGOAUTH = process.env.MONGOAUTH; +let MONGOUSRP = process.env.MONGOUSRP; +let MONGOBASE = process.env.MONGOBASE; + +if (MONGOHOST === undefined) { MONGOHOST = 'localhost';} +if (MONGOPORT === undefined) { MONGOPORT = 27017; } +if (MONGOAUTH === undefined) { MONGOAUTH = 'false'; } +if (MONGOBASE === undefined) { MONGOBASE = 'sensor_data'; } + +let MONGO_URL = 'mongodb://'+MONGOHOST+':'+MONGOPORT; // URL to mongo database +if (MONGOAUTH === 'true') { +// MONGO_URL = 'mongodb://'+MONGOUSRP+'@' + MONGOHOST + ':' + MONGOPORT + '/?authSource=' + MONGOBASE; // URL to mongo database + MONGO_URL = 'mongodb://'+MONGOUSRP+'@' + MONGOHOST + ':' + MONGOPORT + '/?authSource=admin'; // URL to mongo database +} + +export const properties_collection = 'properties' + +export const connectMongo = async () => { + try { +// logit(`Try to connect to ${MONGO_URL}`) + let client = await MongoClient.connect(MONGO_URL) +// logit(`Mongodbase connected to ${MONGO_URL}`) + return client + } + catch(error){ + throw(error) + } +} + +const listDatabases = async (client) => { + let databasesList = await client.db().admin().listDatabases(); + + console.log("Databases:"); + databasesList.databases.forEach(db => console.log(` - ${db.name}`)); +} + +/* *************************************************** +// READ routines +******************************************************/ + +// Read properties from the database +export const readProperties = async (query, limit = 0) => { + let ret = {err: null, properties: null} + let client = await connectMongo() + try { + if ("sid" in query) { // if sid is given, read property for sid + ret.properties = await client.db(MONGOBASE).collection(properties_collection).findOne({_id: query.sid}) + } else { // otherwise read props corresponding to query + ret.properties = await client.db(MONGOBASE).collection(properties_collection).find(query).limit(limit).toArray() + } + } catch (e) { + ret.err = e + } + finally { + client.close() + } + return ret +} + +export const readChipData = async (sid) => { + let ret = { err: null, chipdata: null} + let client = await connectMongo() + try { + ret.chipdata = await client.db(MONGOBASE).collection('prop_flux').findOne({_id: sid},{projection: {chip: 1, _id: 0}}) + } catch (e) { + ret.err = e + } + finally { + client.close() + } + return ret +} + + +// read mapdata from database +export const readMapdata = async (query, limit) => { + let ret = {err: null, mapdata: []} + let client = await connectMongo() + try { + ret.mapdata = await client.db(MONGOBASE).collection("mapdata").find(query).limit(limit).toArray() + } catch (e) { + ret.err = e + } + finally { + client.close() + } + return ret +} + + +export const getallProperties = async (coll, query) => { + let ret = {err: null, properties: []} + let client = await connectMongo() + try { + ret.properties = await client.db(MONGOBASE).collection(coll) + .find(query).toArray() + } catch (e) { + ret.err = e + } + finally { + client.close() + } + return ret +} + + +export const getOneproperty = async (sid) => { + let ret = {error: false} + let client = await connectMongo() + try { + ret.properties = await client.db(MONGOBASE).collection(properties_collection) + .findOne({_id: sid}) + } catch (e) { + ret = {error: true, errortext: e} + } + finally { + client.close() + } + return ret +} + + +export const readAKWs = async (options) => { + let ret = {values: { akws: [], th1_akws: []}, err: null} + let erg = [] + let client = await connectMongo() + try { + let docs = await client.db(MONGOBASE).collection("akws") + .find().toArray() + if(docs == null) { + return returnOnError(ret, 'akws - docs == null', readAKWs.name) + } + logit(`getawkdata: data fetched from akws, length= ${docs.length}`); + ret.values.akws = docs + let docs1 = await client.db(MONGOBASE).collection("th1_akws") + .find().toArray() + if(docs1 == null) { + return returnOnError(ret, 'th1_akws - docs == null', readAKWs.name) + } + logit(`getawkdata: data fetched from th1_akws, length= ${docs1.length}`) + ret.values.th1_akws = docs1 + } catch (e) { + return returnOnError(ret, e, readAKWs.name) + } + finally { + client.close() + } + return ret +} + +export const fetchActData = async (opts) => { + let ret = {err: null, values: []} + let start = opts.start.slice(7) + let end = opts.stop.slice(6) + start = DateTime.fromISO(start).toJSDate() + end = DateTime.fromISO(end).toJSDate() + let query = {sensorid: opts.sensorid, datetime: {$gte: start, $lt: end}} + let options = { projection: {_id: 0, values: 1, datetime: 1}, sort: {datetime: 1}} + let client = await connectMongo() + try { + // ret.values = await client.db(MONGOBASE).collection('noise_sensors') + // .find(query, options).toArray() + ret.values = await client.db(MONGOBASE).collection('noise_sensors').aggregate([ + {$match: query}, + {$sort: { datetime: 1}}, + // {$replaceWith: + // { + // '$values.LA_min': '$values.noise_LA_min' + // } + // }, + {$replaceWith: + { + datetime: {$dateToString: {format: '%Y-%m-%dT%H:%M:%SZ', date: '$datetime'}}, + LA_min: '$values.LA_min', + LA_minx: '$values.noise_LA_min', + LA_max: '$values.LA_max', + LAeq: '$values.LAeq', + E10tel_eq: '$values.E10tel_eq' } + }, + // {$project: { + // datetime: {$dateToString: {format: '%Y-%m-%dT%H:%M:%SZ', date: '$datetime'}}, + // _id: 0, values:1 + // }}, + ]).toArray() + } + catch(e) { + ret.err = e + } + finally { + client.close() + } + return ret +} +/* +Try to connect to mongodb://rexfue:s25BMmW2gg@192.168.51.22:27017 +Try to connect to mongodb://rexfue:s25BMmW2gg@192.168.51.22:27017 +*/ + + + + +/* + let docs = await collection.find( + { datetime: + { $gte: start.toDate(), $lt: end.toDate() } + }, + { projection: + {_id:0, E_eq:0, E_mx:0, E_mi:0, E10tel_mx:0, E10tel_mi:0}, sort: {datetime: sort} + }, + ).toArray(); +*/ + +export const fetchgeigerAVGData = async (opts) => { + let docs = [] + let ret = {err: null, values: []} + let start = opts.start.slice(7) + let end = opts.stop.slice(6) + start = DateTime.fromISO(start).toJSDate() + end = DateTime.fromISO(end).toJSDate() + let datRange = {sensorid: opts.sensorid, datetime: {$gte: start, $lt: end}} + let sorting = {datetime: opts.sort}; + let client = await connectMongo() + try { + if(opts.moving) { + docs = await client.db(MONGOBASE).collection('sensors').aggregate([ + { + $sort: sorting + }, // sort by date + { + $match: {sensorid: opts.sensorid} + }, // select only values for given sensor + { + $match: datRange + }, // select only values in give data range + { + $setWindowFields: { + sortBy: {datetime: 1}, + output: { + cpm_avg: { + $avg: "$values.counts_per_minute", + window: { + range: [-60, 0], + unit: "minute" + } + } + } + } + }, + { + $project: {_id:0, cpm_avg: 1, datetime:1, uSvph_avg: { $multiply: ["$cpm_avg", opts.factor]}} + }, + { + $sort: {datetime: 1} + } + ]).toArray(); + } else { + docs = await client.db(MONGOBASE).collection('sensors').aggregate([ + { + $sort: sorting + }, // sort by date + { + $match: {sensorid: opts.sensorid} + }, // select only values for given sensor + { + $match: datRange + }, // select only values in give data range + { $group: { + _id: {$dateTrunc: { + date: "$datetime", + unit: "minute", + binSize: 60 + }}, + cpm_avg: {$avg: "$values.counts_per_minute"}, // calculate the average + } + }, + { $addFields: { datetime: "$_id"}}, // change '_id' to 'datetime + { + $project: {_id:0, uSvph_avg: { $multiply: ["$cpm_avg", opts.factor]}, datetime: 1, cpm_avg: 1} + }, + { + $sort: {datetime: 1} + } + ]).toArray(); + } + } catch(e) { // if there was an error + ret.err = e // log it to console + } + finally { + client.close() + } + ret.values = docs + return ret +} + +export const fetchNoiseAVGData = async (opts) => { + let docs = [] + let ret = {err: null, values: []} + let start = opts.start.slice(7) + let end = opts.stop.slice(6) + start = DateTime.fromISO(start).toJSDate() + end = DateTime.fromISO(end).toJSDate() + let peak = opts.peak; // threshold for peak count + let datRange = {sensorid: opts.sensorid, datetime: {$gte: start, $lt: end}} + let sorting = {datetime: opts.sort}; + let grpId = {$dateToString: {format: '%Y-%m-%dT%H:00:00Z', date: '$datetime'}} + let client = await connectMongo() + try { + docs = await client.db(MONGOBASE).collection('noise_sensors').aggregate([ + {$sort: sorting}, // sort by date + {$match: datRange}, // select only values in give data range + { + $group: { + _id: grpId, + n_average: {$avg: "$values.E10tel_eq"}, // calculate the average + n_sum: {$sum: "$values.E10tel_eq"}, // calculate the sum + peakcount: {$sum: {$cond: [{$gte: ["$values.LA_max", peak]}, 1, 0]}}, // count peaks + count: {$sum: 1}, // count entries + } + }, + {$sort: {_id: 1}}, // sort by result dates + { $addFields: { datetime: "$_id"}}, // change '_id' to 'date' + {$project: opts.long ? { _id:0, n_AVG: { $multiply: [10, {$log10: "$n_average"}]}, datetime:1, peakcount:1, count:1, n_sum:1} : + {_id:0, n_AVG: { $multiply: [10, {$log10: "$n_average"}]}, datetime:1, peakcount:1}} + ]).toArray(); // return not all fields, depending on 'long' + } catch(e) { // if there was an error + ret.err = e // log it to console + } + finally { + client.close() + } + ret.values = docs + return ret +} + +export const fetchAVGData = async (opts) => { +} +/* +// ********************************************* +// getAverageData +// +// Calculate different values per hour +// average of E10tel_eq ( E10tel_eq => 10 ^(LAeq/10) ) +// sum of E10tel_eq, to calculate day, night and eveniung averages +// count, how many values are used for average/sum +// paeakcount, how many values of LAmax are over defined peak value in every hour +// +// params: +// db: Database +// opt: different options (see further down) +// +// return +// depending an calling parameter 'what', not all values will be sent in 'values' +// JSON +// {[ +// { datetime: "2019-10-23T00:00:00Z" , n_AVG: 67.22, n_sum: 32783, count: 24, peakcount: 6 }. +// { datetime: "2019-10-23T01:00:00Z" , n_AVG: 52.89, n_sum: 23561, count: 26, peakcount: 5 }. +// ......... +// ]} +// +// ********************************************* +async function getAverageData(db,opt) { + let start = opt.start; + let end = opt.end; // start and ent time for aggregation + let docs = []; // collect data here + const collection = db.collection('data_' + opt.sid);; + let span = opt.span // date range in days + let peak = opt.peak; // threshold for peak count + let long = opt.long; // true => give extra output + let nbrOfHours = opt.end.diff(opt.start,'hours') + 24; + let datRange = {datetime: {$gte: opt.start.toDate(), $lt: opt.end.toDate()}}; + let sorting = {datetime: opt.sort}; + let grpId = {$dateToString: {format: '%Y-%m-%dT%H:00:00Z', date: '$datetime'}}; + try { + docs = await collection.aggregate([ + {$sort: sorting}, // sort by date + {$match: datRange}, // select only values in give data range + { + $group: { + _id: grpId, + n_average: {$avg: '$E10tel_eq'}, // calculate the average + n_sum: {$sum: '$E10tel_eq'}, // calculate the sum + peakcount: {$sum: {$cond: [{$gte: ["$LA_max", peak]}, 1, 0]}}, // count peaks + count: {$sum: 1}, // count entries + } + }, + {$sort: {_id: 1}}, // sort by result dates + { $addFields: { datetime: "$_id"}}, // change '_id' to 'date' + {$project: opt.long ? { _id:0, n_AVG: { $multiply: [10, {$log10: "$n_average"}]}, datetime:1, peakcount:1, count:1, n_sum:1} : + {_id:0, n_AVG: { $multiply: [10, {$log10: "$n_average"}]}, datetime:1, peakcount:1}} + ]).toArray(); // return not all fields, depending on 'long' + } catch(e) { // if there was an error + console.log(e); // log it to console + } + // To easily extract the values, we copy the data from docs into a new array, so that the + // hour in an element in docs becomes the index into the new array (for every new day this + // index will be incremented by 24). Missing values are marked by: {n_sum=-1, n_AVG=-1}. + let hoursArr = new Array(nbrOfHours); // generate new array + let emptyValues = opt.long ? {n_sum: -1, n_AVG:-1} : {n_AVG:-1}; + hoursArr.fill(emptyValues); // fill with 'empty' value + let startDay = moment.utc(docs[0].datetime).date(); // calc first day + let k = 0; + for (let i=0; i kein buildx/qemu, +# eigener Dockerfile-Name (Dockerfile_sensorapi). + +REGISTRY="docker.citysensor.de" +IMAGE_NAME="sensorapi" +TAG="${1:-latest}" +PLATFORM="linux/amd64" +DOCKERFILE="Dockerfile_sensorapi" +FULL_IMAGE="${REGISTRY}/${IMAGE_NAME}:${TAG}" +BUILD_DATE=$(date +%d.%m.%Y) + +echo "==========================================" +echo "sensorapi Deploy Script (amd64)" +echo "==========================================" +echo "Registry: ${REGISTRY}" +echo "Image: ${IMAGE_NAME}" +echo "Tag: ${TAG}" +echo "Platform: ${PLATFORM}" +echo "Dockerfile: ${DOCKERFILE}" +echo "Build-Datum: ${BUILD_DATE}" +echo "==========================================" +echo "" + +# Hinweis: Login wird uebersprungen, weil die Credentials fuer ${REGISTRY} +# bereits in ~/.docker/config.json liegen. +# Bei Bedarf manuell: docker login ${REGISTRY} + +echo ">>> Baue Image (nur ${PLATFORM}, nativ) ..." +docker build \ + --platform "${PLATFORM}" \ + -f "${DOCKERFILE}" \ + -t "${FULL_IMAGE}" \ + . +echo "" + +echo ">>> Pushe ${FULL_IMAGE} ..." +docker push "${FULL_IMAGE}" +echo "" + +# Falls ein anderer Tag als 'latest' gebaut wurde, zusaetzlich latest setzen+pushen +if [ "${TAG}" != "latest" ]; then + echo ">>> Tagge zusaetzlich als :latest ..." + docker tag "${FULL_IMAGE}" "${REGISTRY}/${IMAGE_NAME}:latest" + docker push "${REGISTRY}/${IMAGE_NAME}:latest" + echo "" +fi + +echo "==========================================" +echo "Build + Push fertig: ${FULL_IMAGE}" +echo "==========================================" +echo "" +echo "Danach Stack aktualisieren:" +echo " cd /opt/stacks/esprimo/noisesensors && docker compose up -d sensorapi" diff --git a/sensorapi/doc/Planung.jpg b/sensorapi/doc/Planung.jpg new file mode 100644 index 0000000000000000000000000000000000000000..c0787b52130401743d8c6b91befa993c497c3e42 GIT binary patch literal 583372 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®$1oHMh*~s}!@IAG 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 Y_IVkd>t&Go+?GraZ}zuBiWqPDZ=!(o+5i9m literal 0 HcmV?d00001 diff --git a/sensorapi/doc/Planung.md b/sensorapi/doc/Planung.md new file mode 100644 index 0000000..64dbab9 --- /dev/null +++ b/sensorapi/doc/Planung.md @@ -0,0 +1,23 @@ +##Planung, Ideen und Entscheidungen + +###Websocket +Da Websockets nur dann Vorteile bringen, wenn der Server von sich aus was 'zu sagen' hat, wird in diesem Projekt auf +Websockets verzichtet und der Verkher zwischen der API und dem GUI über normale HTTP-Calls ausgeführt. + +###Planung +![Planung](planung.jpg "Text to show on mouseover"). +####Ergänzungen zur Grafik (2022-05-26) + * Für die 3 GUIs je ein extra Container, so wie jetzt auch (Feinstaub, Geiger, Laerm) + * ab sofort (d.h. möglichst bald) die **influx-** und die **mongo-**Databases parallel laufen lassen + * nach ca. 1 Monat **nur noch mongo** verwenden + * + + + + +####Versions-History + +|Version | Datum | Author +|--------|------|------- +|1.0 | 2022-05-27 | rxf + diff --git a/sensorapi/doc/Readne.md b/sensorapi/doc/Readne.md new file mode 100644 index 0000000..0357693 --- /dev/null +++ b/sensorapi/doc/Readne.md @@ -0,0 +1,6 @@ +# Sensor-API + +### Allgemein +* **ALLE** Zeiten werden in UTC ausgegeben. + Wird beim Aufruf die Zeit im ISO-Format **ohne** Zonenbezeichnung eingegeben, wird sie in UTC umgerechnet und auch so ausgegeben. Wenn die Eingabe schon UTC ist (Z ale letztes Zeichen) dann bleibt es so. + diff --git a/sensorapi/docker-compose.yml b/sensorapi/docker-compose.yml new file mode 100644 index 0000000..3d39bda --- /dev/null +++ b/sensorapi/docker-compose.yml @@ -0,0 +1,19 @@ +version: '3.9' + +services: + node: + image: sensorapi + environment: + DEVELOP: "true" + MONGOHOST: ${MONGOHOST} + MONGOPORT: ${MONGOPORT} + INFLUXHOST: ${INFLUXHOST} + INFLUXTOKEN: ${INFLUXTOKEN} + LIVE: "true" + PORT: 3004 + ports: + - "3004:3004" + volumes: + - ${PWD}/log/sensorapi:/var/log + container_name: node_sensorapi + restart: unless-stopped diff --git a/sensorapi/locales/de/translation.json b/sensorapi/locales/de/translation.json new file mode 100644 index 0000000..bd7b225 --- /dev/null +++ b/sensorapi/locales/de/translation.json @@ -0,0 +1,16 @@ +{ + "CMNDUNKNOWN": "Unbekanntes Kommando", + "NOTHING": "Nichts anzuzeigen", + "PARAMNONUM": "Parameter \"xxx\" ist keine Zahl", + "NOTYP": "KeinTyp angegeben", + "NOSENSFOUND": "Kein passender Sensor in den Properties gefunden", + "NOMANDPARAM": "Nitewendiger Parameter xxx nicht angegeben", + "NOPROPSREAD": "Keine properties für Sensor xxx eingelesen", + "NOPARAMETER": "Keine Parameter übergene", + "RESPSTATUS": "Rückgabe-Status: xxx", + "NODATA": "keine Daten gefunden", + "SYNTAXURL": "Syntax Fehler beim Aufruf der URL", + "WRONGTYPE": "Sensor xxx ist kein yyy Sensor", + "NOLASTDATES": "Probleme bein abholen der letzten Daten", + "NOPROPSFOUND": "Properties Collection nicht gefunden" +} diff --git a/sensorapi/locales/en/translation.json b/sensorapi/locales/en/translation.json new file mode 100644 index 0000000..d701d6d --- /dev/null +++ b/sensorapi/locales/en/translation.json @@ -0,0 +1,16 @@ +{ + "CMNDUNKNOWN": "Command not known", + "NOTHING": "Nothing to show", + "PARAMNONUM": "Parameter 'xxx' is not a number", + "NOTYP": "No type given", + "NOSENSFOUND": "No suitable sensors found in properties", + "NOMANDPARAM": "Mandatory parameter xxx not given", + "NOPROPSREAD": "No properties read for sensor xxx", + "NOPARAMETER": "No parameter given", + "RESPSTATUS": "Returned status: xxxx", + "NODATA": "No data found", + "SYNTAXURL": "Syntax error in calling url!", + "WRONGTYPE": "Sensor xxx is not of type yyy", + "NOLASTDATES": "Problems fetching last dates from database", + "NOPROPSFOUND": "Properties collection not found" +} diff --git a/sensorapi/mocks/mongo_mock.js b/sensorapi/mocks/mongo_mock.js new file mode 100644 index 0000000..dc1a2b4 --- /dev/null +++ b/sensorapi/mocks/mongo_mock.js @@ -0,0 +1,74 @@ +// Gibt für eine Property-Anfrage immer den 140er Sensor zurück +// rxf 2022-05-25 + +export const readProperties = async (query, limit = 0) => { + let ret = {error: false} + if ("sid" in query) { // if sid is given, read property for sid + ret.values = { + "_id" : 140, + "location_id" : 65, + "name" : "SDS011", + "since" : "2021-04-21T09:44:12.888Z", + "location" : [ + { + "loc" : + { + "type" : "Point", + "coordinates" : [ 9.16, 48.778 ] + }, + "id" : 65, + "altitude" : 282, + "since" : "2021-04-21T09:44:12.888Z", + "address" : { }, + "exact_loc" : 0, + "indoor" : 0 + } + ] + } + } else { // otherwise read props corresponding to query + ret.values = [ + { + "_id" : 140, + "location_id" : 65, + "name" : "SDS011", + "since" : "2021-04-21T09:44:12.888Z", + "location" : [ + { + "loc" : + { + "type" : "Point", + "coordinates" : [ 9.16, 48.778 ] + }, + "id" : 65, + "altitude" : 282, + "since" : "2021-04-21T09:44:12.888Z", + "address" : { }, + "exact_loc" : 0, + "indoor" : 0 + } + ] + },{ + "_id" : 141, + "location_id" : 65, + "name" : "BME280", + "since" : "2021-04-21T09:44:12.888Z", + "location" : [ + { + "loc" : + { + "type" : "Point", + "coordinates" : [ 9.16, 48.778 ] + }, + "id" : 65, + "altitude" : 282, + "since" : "2021-04-21T09:44:12.888Z", + "address" : { }, + "exact_loc" : 0, + "indoor" : 0 + } + ] + } + ] + } + return ret +} diff --git a/sensorapi/package-lock.json b/sensorapi/package-lock.json new file mode 100644 index 0000000..df48f47 --- /dev/null +++ b/sensorapi/package-lock.json @@ -0,0 +1,2915 @@ +{ + "name": "sensorapi", + "version": "1.4.2", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "sensorapi", + "version": "1.4.2", + "dependencies": { + "@influxdata/influxdb-client": "^1.35.0", + "@influxdata/influxdb-client-apis": "^1.35.0", + "axios": "^1.12.2", + "cookie-parser": "~1.4.7", + "cors": "^2.8.5", + "debug": "~4.4.3", + "express": "^5.1.0", + "http-errors": "~2.0.0", + "i18next": "^25.5.2", + "i18next-fs-backend": "^2.0.0", + "i18next-http-middleware": "^3.8.0", + "luxon": "^3.7.2", + "mongodb": "^6.19.0", + "morgan": "~1.10.1", + "pug": "^3.0.3", + "ws": "^8.18.3" + }, + "bin": { + "www": "bin/www.js" + }, + "devDependencies": { + "mocha": "^11.7.2" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.29.7.tgz", + "integrity": "sha512-Pb5ijPrZ89GDH8223L4UP8i6QApWxs04RbPQJTeWDV0/keR2E36MeKnyr6LYmUUvqRRI+Iv87SuF1W6ErINzYw==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.29.7.tgz", + "integrity": "sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.7.tgz", + "integrity": "sha512-hnORnjP/1P/zFEndoeX+n+t1RwWRJiJpM/jO7FW32Kn9r5+sJB2JWOdYo4L6k78j15eCwY3Gm/7364B1EMwtNg==", + "license": "MIT", + "dependencies": { + "@babel/types": "^7.29.7" + }, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/runtime": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.29.7.tgz", + "integrity": "sha512-Nq8OhGWiZIZGV6hLHoyAKLLcJihP/xFeBMGJoUrxTX2psI8dCifzLhZISFb+VWS3wFMRDmCGw5R+dOySCqPLhw==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/types": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.7.tgz", + "integrity": "sha512-4zBIxpPzowiZpusoFkyGVwakdRJUyuH5PxQ/PrqghfdFWWasvnCdPfQXHrenDai+gyLARulZjZowCOj6fjT4pA==", + "license": "MIT", + "dependencies": { + "@babel/helper-string-parser": "^7.29.7", + "@babel/helper-validator-identifier": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@influxdata/influxdb-client": { + "version": "1.35.0", + "resolved": "https://registry.npmjs.org/@influxdata/influxdb-client/-/influxdb-client-1.35.0.tgz", + "integrity": "sha512-woWMi8PDpPQpvTsRaUw4Ig+nOGS/CWwAwS66Fa1Vr/EkW+NEwxI8YfPBsdBMn33jK2Y86/qMiiuX/ROHIkJLTw==", + "license": "MIT" + }, + "node_modules/@influxdata/influxdb-client-apis": { + "version": "1.35.0", + "resolved": "https://registry.npmjs.org/@influxdata/influxdb-client-apis/-/influxdb-client-apis-1.35.0.tgz", + "integrity": "sha512-+7h6smVPHYBge2rNKgYh/5k+SriYvPMsoJDfbUiQt1vJtpWnElwgBDLDl7Cr6d9XPC+FCI9GP4GQEMv7y8WxdA==", + "license": "MIT", + "peerDependencies": { + "@influxdata/influxdb-client": "*" + } + }, + "node_modules/@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "dev": true, + "license": "ISC", + "dependencies": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@mongodb-js/saslprep": { + "version": "1.4.13", + "resolved": "https://registry.npmjs.org/@mongodb-js/saslprep/-/saslprep-1.4.13.tgz", + "integrity": "sha512-E3Sv4eCYAlKYUTx8S3ioQcDUscOif+8zZ5OnW1IzJ+Tt+EO+ke8mn+Y3FX6N1H79picwbdOavVOb1jPi2EOyrg==", + "license": "MIT", + "dependencies": { + "sparse-bitfield": "^3.0.3" + } + }, + "node_modules/@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">=14" + } + }, + "node_modules/@types/webidl-conversions": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/@types/webidl-conversions/-/webidl-conversions-7.0.3.tgz", + "integrity": "sha512-CiJJvcRtIgzadHCYXw7dqEnMNRjhGZlYK05Mj9OyktqV8uVT8fD2BFOB7S1uwBE3Kj2Z+4UyPmFw/Ixgw/LAlA==", + "license": "MIT" + }, + "node_modules/@types/whatwg-url": { + "version": "11.0.5", + "resolved": "https://registry.npmjs.org/@types/whatwg-url/-/whatwg-url-11.0.5.tgz", + "integrity": "sha512-coYR071JRaHa+xoEvvYqvnIHaVqaYrLPbsufM9BF63HkwI5Lgmy2QR8Q5K/lYDYo5AK82wOvSOS0UsLTpTG7uQ==", + "license": "MIT", + "dependencies": { + "@types/webidl-conversions": "*" + } + }, + "node_modules/accepts": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-2.0.0.tgz", + "integrity": "sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==", + "license": "MIT", + "dependencies": { + "mime-types": "^3.0.0", + "negotiator": "^1.0.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/acorn": { + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", + "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", + "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "license": "MIT", + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/ansi-regex": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", + "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true, + "license": "Python-2.0" + }, + "node_modules/asap": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", + "integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==", + "license": "MIT" + }, + "node_modules/assert-never": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/assert-never/-/assert-never-1.4.0.tgz", + "integrity": "sha512-5oJg84os6NMQNl27T9LnZkvvqzvAnHu03ShCnoj6bsJwS7L8AO4lf+C/XjK/nvzEqQB744moC6V128RucQd1jA==", + "license": "MIT" + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "license": "MIT" + }, + "node_modules/axios": { + "version": "1.18.1", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.18.1.tgz", + "integrity": "sha512-3nTvFlvpn9Zu/RkHUqtc7/+al4UpRW5az71ap5zccp6e8RAYEzhMTecX8Dz1wWDYrPpUoB1HAQEGEAEvUr7S9g==", + "license": "MIT", + "dependencies": { + "follow-redirects": "^1.16.0", + "form-data": "^4.0.5", + "https-proxy-agent": "^5.0.1", + "proxy-from-env": "^2.1.0" + } + }, + "node_modules/babel-walk": { + "version": "3.0.0-canary-5", + "resolved": "https://registry.npmjs.org/babel-walk/-/babel-walk-3.0.0-canary-5.tgz", + "integrity": "sha512-GAwkz0AihzY5bkwIY5QDR+LvsRQgB/B+1foMPvi0FZPMl5fjD7ICiznUiBdLYMH1QYe6vqu4gWYytZOccLouFw==", + "license": "MIT", + "dependencies": { + "@babel/types": "^7.9.6" + }, + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/basic-auth": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-2.0.1.tgz", + "integrity": "sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg==", + "license": "MIT", + "dependencies": { + "safe-buffer": "5.1.2" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/body-parser": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-2.3.0.tgz", + "integrity": "sha512-2cGmJupaNgg+QUwVLAucDuWuoMZ6EX9iHDRswZ5lsNYEmwPaRknMPCLZz07yTzVq/83p4o/wzbDZbBrTvGGTIw==", + "license": "MIT", + "dependencies": { + "bytes": "^3.1.2", + "content-type": "^2.0.0", + "debug": "^4.4.3", + "http-errors": "^2.0.1", + "iconv-lite": "^0.7.2", + "on-finished": "^2.4.1", + "qs": "^6.15.2", + "raw-body": "^3.0.2", + "type-is": "^2.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/body-parser/node_modules/content-type": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-2.0.0.tgz", + "integrity": "sha512-j/O/d7GcZCyNl7/hwZAb606rzqkyvaDctLmckbxLzHvFBzTJHuGEdodATcP3yIRoDrLHkIATJuvzbFlp/ki2cQ==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/brace-expansion": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.1.2.tgz", + "integrity": "sha512-w5JZcKgdhDOgOwm8H+KgbosopHMuGcl6qbulwjtz3SM7I7P3yW1eAjzMPLrIE+NQ9vjgANKHWeMHnrT0OXW1oA==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/browser-stdout": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", + "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", + "dev": true, + "license": "ISC" + }, + "node_modules/bson": { + "version": "6.10.4", + "resolved": "https://registry.npmjs.org/bson/-/bson-6.10.4.tgz", + "integrity": "sha512-WIsKqkSC0ABoBJuT1LEX+2HEvNmNKKgnTAyd0fL8qzK4SH2i9NXg+t08YtdZp/V9IZ33cxe3iV4yM0qg8lMQng==", + "license": "Apache-2.0", + "engines": { + "node": ">=16.20.1" + } + }, + "node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/call-bound": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", + "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "get-intrinsic": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/chalk/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/character-parser": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/character-parser/-/character-parser-2.2.0.tgz", + "integrity": "sha512-+UqJQjFEFaTAs3bNsF2j2kEN1baG/zghZbdqoYEDxGZtJo9LBzl1A+m0D4n3qKx8N2FNv8/Xp6yV9mQmBuptaw==", + "license": "MIT", + "dependencies": { + "is-regex": "^1.0.3" + } + }, + "node_modules/chokidar": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz", + "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==", + "dev": true, + "license": "MIT", + "dependencies": { + "readdirp": "^4.0.1" + }, + "engines": { + "node": ">= 14.16.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/cliui/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/cliui/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true, + "license": "MIT" + }, + "node_modules/cliui/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cliui/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cliui/node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true, + "license": "MIT" + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "license": "MIT", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/constantinople": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/constantinople/-/constantinople-4.0.1.tgz", + "integrity": "sha512-vCrqcSIq4//Gx74TXXCGnHpulY1dskqLTFGDmhrGxzeXL8lF8kvXv6mpNWlJj1uD4DW23D4ljAqbY4RRaaUZIw==", + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.6.0", + "@babel/types": "^7.6.1" + } + }, + "node_modules/content-disposition": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-1.1.0.tgz", + "integrity": "sha512-5jRCH9Z/+DRP7rkvY83B+yGIGX96OYdJmzngqnw2SBSxqCFPd0w2km3s5iawpGX8krnwSGmF0FW5Nhr0Hfai3g==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/content-type": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", + "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie-parser": { + "version": "1.4.7", + "resolved": "https://registry.npmjs.org/cookie-parser/-/cookie-parser-1.4.7.tgz", + "integrity": "sha512-nGUvgXnotP3BsjiLX2ypbQnWoGUPIIfHQNZkkC668ntrzGWEZVW70HDEB1qnNGMicPje6EttlIgzo51YSwNQGw==", + "license": "MIT", + "dependencies": { + "cookie": "0.7.2", + "cookie-signature": "1.0.6" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==", + "license": "MIT" + }, + "node_modules/cors": { + "version": "2.8.6", + "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.6.tgz", + "integrity": "sha512-tJtZBBHA6vjIAaF6EnIaq6laBBP9aq/Y3ouVJjEfoHbRBcHBAHYcMh/w8LDrk2PvIMMq8gmopa5D4V8RmbrxGw==", + "license": "MIT", + "dependencies": { + "object-assign": "^4", + "vary": "^1" + }, + "engines": { + "node": ">= 0.10" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/decamelize": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz", + "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/diff": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-7.0.0.tgz", + "integrity": "sha512-PJWHUb1RFevKCwaFA9RlG5tCd+FO5iRh9A8HEtkmBH2Li03iJriB6m6JIN4rGz3K3JLawI7/veA1xzRKP6ISBw==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/doctypes": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/doctypes/-/doctypes-1.1.0.tgz", + "integrity": "sha512-LLBi6pEqS6Do3EKQ3J0NqHWV5hhb78Pi8vvESYwyOy2c31ZEZVdtitdzsQsKb7878PEERhzUk0ftqGhG6Mz+pQ==", + "license": "MIT" + }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "dev": true, + "license": "MIT" + }, + "node_modules/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", + "license": "MIT" + }, + "node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "dev": true, + "license": "MIT" + }, + "node_modules/encodeurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", + "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-object-atoms": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.2.tgz", + "integrity": "sha512-HWcBoN6NileqtSydK2FqHbS/LoDd2pqrnQHLyJzBj4kOp/ky2MWMN694xOfkK8/SnUsW2DH7EfyVlydKCsm1Zw==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-set-tostringtag": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", + "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", + "license": "MIT" + }, + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/express": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/express/-/express-5.2.1.tgz", + "integrity": "sha512-hIS4idWWai69NezIdRt2xFVofaF4j+6INOpJlVOLDO8zXGpUVEVzIYk12UUi2JzjEzWL3IOAxcTubgz9Po0yXw==", + "license": "MIT", + "dependencies": { + "accepts": "^2.0.0", + "body-parser": "^2.2.1", + "content-disposition": "^1.0.0", + "content-type": "^1.0.5", + "cookie": "^0.7.1", + "cookie-signature": "^1.2.1", + "debug": "^4.4.0", + "depd": "^2.0.0", + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "etag": "^1.8.1", + "finalhandler": "^2.1.0", + "fresh": "^2.0.0", + "http-errors": "^2.0.0", + "merge-descriptors": "^2.0.0", + "mime-types": "^3.0.0", + "on-finished": "^2.4.1", + "once": "^1.4.0", + "parseurl": "^1.3.3", + "proxy-addr": "^2.0.7", + "qs": "^6.14.0", + "range-parser": "^1.2.1", + "router": "^2.2.0", + "send": "^1.1.0", + "serve-static": "^2.2.0", + "statuses": "^2.0.1", + "type-is": "^2.0.1", + "vary": "^1.1.2" + }, + "engines": { + "node": ">= 18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/express/node_modules/cookie-signature": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.2.2.tgz", + "integrity": "sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg==", + "license": "MIT", + "engines": { + "node": ">=6.6.0" + } + }, + "node_modules/finalhandler": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-2.1.1.tgz", + "integrity": "sha512-S8KoZgRZN+a5rNwqTxlZZePjT/4cnm0ROV70LedRHZ0p8u9fRID0hJUZQpkKLzro8LfmC8sx23bY6tVNxv8pQA==", + "license": "MIT", + "dependencies": { + "debug": "^4.4.0", + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "on-finished": "^2.4.1", + "parseurl": "^1.3.3", + "statuses": "^2.0.1" + }, + "engines": { + "node": ">= 18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/flat": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", + "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", + "dev": true, + "license": "BSD-3-Clause", + "bin": { + "flat": "cli.js" + } + }, + "node_modules/follow-redirects": { + "version": "1.16.0", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.16.0.tgz", + "integrity": "sha512-y5rN/uOsadFT/JfYwhxRS5R7Qce+g3zG97+JrtFZlC9klX/W5hD7iiLzScI4nZqUS7DNUdhPgw4xI8W2LuXlUw==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "license": "MIT", + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, + "node_modules/foreground-child": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz", + "integrity": "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==", + "dev": true, + "license": "ISC", + "dependencies": { + "cross-spawn": "^7.0.6", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/form-data": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.6.tgz", + "integrity": "sha512-vKatAh4SlVfgbv+YtmhiRjhEMJsYpsG1Y2rMQtR+SVSbytsSD1YGzDIcrAJmdFec88u/+VoGmxnl+80gL1tRCQ==", + "license": "MIT", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "es-set-tostringtag": "^2.1.0", + "hasown": "^2.0.4", + "mime-types": "^2.1.35" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/form-data/node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/form-data/node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fresh": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-2.0.0.tgz", + "integrity": "sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true, + "license": "ISC", + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/get-intrinsic": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/glob": { + "version": "10.5.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.5.0.tgz", + "integrity": "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==", + "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", + "dev": true, + "license": "ISC", + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/has-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "license": "MIT", + "dependencies": { + "has-symbols": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.4.tgz", + "integrity": "sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A==", + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/he": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", + "dev": true, + "license": "MIT", + "bin": { + "he": "bin/he" + } + }, + "node_modules/http-errors": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.1.tgz", + "integrity": "sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==", + "license": "MIT", + "dependencies": { + "depd": "~2.0.0", + "inherits": "~2.0.4", + "setprototypeof": "~1.2.0", + "statuses": "~2.0.2", + "toidentifier": "~1.0.1" + }, + "engines": { + "node": ">= 0.8" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "license": "MIT", + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/i18next": { + "version": "25.10.10", + "resolved": "https://registry.npmjs.org/i18next/-/i18next-25.10.10.tgz", + "integrity": "sha512-cqUW2Z3EkRx7NqSyywjkgCLK7KLCL6IFVFcONG7nVYIJ3ekZ1/N5jUsihHV6Bq37NfhgtczxJcxduELtjTwkuQ==", + "funding": [ + { + "type": "individual", + "url": "https://www.locize.com/i18next" + }, + { + "type": "individual", + "url": "https://www.i18next.com/how-to/faq#i18next-is-awesome.-how-can-i-support-the-project" + }, + { + "type": "individual", + "url": "https://www.locize.com" + } + ], + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.29.2" + }, + "peerDependencies": { + "typescript": "^5 || ^6" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/i18next-fs-backend": { + "version": "2.6.6", + "resolved": "https://registry.npmjs.org/i18next-fs-backend/-/i18next-fs-backend-2.6.6.tgz", + "integrity": "sha512-mYGu6Nt8RIp3X/U8Y+Gej1wo5xmYWmGKLqBGMCC2OCAou5rW5epeHgHmVcw20mJs9Z9+DAPHIxQPNCgFyPRMeg==", + "license": "MIT" + }, + "node_modules/i18next-http-middleware": { + "version": "3.9.7", + "resolved": "https://registry.npmjs.org/i18next-http-middleware/-/i18next-http-middleware-3.9.7.tgz", + "integrity": "sha512-k4Aa39thnQXGox5ZeKvlOwbDsFz+iGxtPJITWm6xmmErNZOeGMXIoH9XwK3ITUq7lqHaywnIH9gLwOraU4jJvQ==", + "license": "MIT" + }, + "node_modules/iconv-lite": { + "version": "0.7.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.7.3.tgz", + "integrity": "sha512-IKXpvIzjnC9XTAUbVBcMfGS0EPaIXtW6v+zr+RRp+hqULEpo0owZax6wyRwPOJbWbzjYspQwusTsfVr0ifh4uQ==", + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "license": "ISC" + }, + "node_modules/ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "license": "MIT", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/is-core-module": { + "version": "2.16.2", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.2.tgz", + "integrity": "sha512-evOr8xfXKxE6qSR0hSXL2r3sd7ALj8+7jQEUvPYcm5sgZFdJ+AYzT6yNmJenvIYQBgIGwfwz08sL8zoL7yq2BA==", + "license": "MIT", + "dependencies": { + "hasown": "^2.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-expression": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-expression/-/is-expression-4.0.0.tgz", + "integrity": "sha512-zMIXX63sxzG3XrkHkrAPvm/OVZVSCPNkwMHU8oTX7/U3AL78I0QXCEICXUM13BIa8TYGZ68PiTKfQz3yaTNr4A==", + "license": "MIT", + "dependencies": { + "acorn": "^7.1.1", + "object-assign": "^4.1.1" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-plain-obj": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", + "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-promise": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.2.2.tgz", + "integrity": "sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ==", + "license": "MIT" + }, + "node_modules/is-regex": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.2.1.tgz", + "integrity": "sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "gopd": "^1.2.0", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-unicode-supported": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", + "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true, + "license": "ISC" + }, + "node_modules/jackspeak": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", + "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" + } + }, + "node_modules/js-stringify": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/js-stringify/-/js-stringify-1.0.2.tgz", + "integrity": "sha512-rtS5ATOo2Q5k1G+DADISilDA6lv79zIiwFd6CcjuIxGKLFm5C+RLImRscVap9k55i+MOZwgliw+NejvkLuGD5g==", + "license": "MIT" + }, + "node_modules/js-yaml": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.3.0.tgz", + "integrity": "sha512-1td788aAnnZ5qs7V2QIRl1owjtYpbKt749Y3xauqQgwIIGF/xXWz1wMTEBx5O3LK3lXLVuqXPdPxj2BoFHaW9Q==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/puzrin" + }, + { + "type": "github", + "url": "https://github.com/sponsors/nodeca" + } + ], + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/jstransformer": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/jstransformer/-/jstransformer-1.0.0.tgz", + "integrity": "sha512-C9YK3Rf8q6VAPDCCU9fnqo3mAfOH6vUGnMcP4AQAYIEpWtfGLpwOTmZ+igtdK5y+VvI2n3CyYSzy4Qh34eq24A==", + "license": "MIT", + "dependencies": { + "is-promise": "^2.0.0", + "promise": "^7.0.1" + } + }, + "node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/log-symbols": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", + "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", + "dev": true, + "license": "MIT", + "dependencies": { + "chalk": "^4.1.0", + "is-unicode-supported": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/luxon": { + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/luxon/-/luxon-3.7.2.tgz", + "integrity": "sha512-vtEhXh/gNjI9Yg1u4jX/0YVPMvxzHuGgCm6tC5kZyb08yjGWGnqAjGJvcXbqQR2P3MyMEFnRbpcdFS6PBcLqew==", + "license": "MIT", + "engines": { + "node": ">=12" + } + }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/media-typer": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-1.1.1.tgz", + "integrity": "sha512-yz3xRaG20c6/BOzvYoDaGtPmGscs7YivItZEEqe6GbwNfHuxu9YNmvnEkMzKldAGY4/80pRcQRZSEnhquk9XuQ==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/memory-pager": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/memory-pager/-/memory-pager-1.5.0.tgz", + "integrity": "sha512-ZS4Bp4r/Zoeq6+NLJpP+0Zzm0pR8whtGPf1XExKLJBAczGMnSi3It14OiNCStjQjM6NU1okjQGSxgEZN8eBYKg==", + "license": "MIT" + }, + "node_modules/merge-descriptors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-2.0.0.tgz", + "integrity": "sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/mime-db": { + "version": "1.54.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz", + "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.2.tgz", + "integrity": "sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A==", + "license": "MIT", + "dependencies": { + "mime-db": "^1.54.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/minimatch": { + "version": "9.0.9", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.9.tgz", + "integrity": "sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.2" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/minipass": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.3.tgz", + "integrity": "sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A==", + "dev": true, + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/mocha": { + "version": "11.7.6", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-11.7.6.tgz", + "integrity": "sha512-nS9xOGbw2I3cjCpxwZAEJ9xK9lmJ08vEkQvLtz4du9ZrF9UrjRpeJGiIgl2Z+Qs++pmB4ecDe48Fwsh+j+j7xA==", + "dev": true, + "license": "MIT", + "dependencies": { + "browser-stdout": "^1.3.1", + "chokidar": "^4.0.1", + "debug": "^4.3.5", + "diff": "^7.0.0", + "escape-string-regexp": "^4.0.0", + "find-up": "^5.0.0", + "glob": "^10.4.5", + "he": "^1.2.0", + "is-path-inside": "^3.0.3", + "js-yaml": "^4.1.0", + "log-symbols": "^4.1.0", + "minimatch": "^9.0.5", + "ms": "^2.1.3", + "picocolors": "^1.1.1", + "serialize-javascript": "^6.0.2", + "strip-json-comments": "^3.1.1", + "supports-color": "^8.1.1", + "workerpool": "^9.2.0", + "yargs": "^17.7.2", + "yargs-parser": "^21.1.1", + "yargs-unparser": "^2.0.0" + }, + "bin": { + "_mocha": "bin/_mocha", + "mocha": "bin/mocha.js" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/mongodb": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-6.21.0.tgz", + "integrity": "sha512-URyb/VXMjJ4da46OeSXg+puO39XH9DeQpWCslifrRn9JWugy0D+DvvBvkm2WxmHe61O/H19JM66p1z7RHVkZ6A==", + "license": "Apache-2.0", + "dependencies": { + "@mongodb-js/saslprep": "^1.3.0", + "bson": "^6.10.4", + "mongodb-connection-string-url": "^3.0.2" + }, + "engines": { + "node": ">=16.20.1" + }, + "peerDependencies": { + "@aws-sdk/credential-providers": "^3.188.0", + "@mongodb-js/zstd": "^1.1.0 || ^2.0.0", + "gcp-metadata": "^5.2.0", + "kerberos": "^2.0.1", + "mongodb-client-encryption": ">=6.0.0 <7", + "snappy": "^7.3.2", + "socks": "^2.7.1" + }, + "peerDependenciesMeta": { + "@aws-sdk/credential-providers": { + "optional": true + }, + "@mongodb-js/zstd": { + "optional": true + }, + "gcp-metadata": { + "optional": true + }, + "kerberos": { + "optional": true + }, + "mongodb-client-encryption": { + "optional": true + }, + "snappy": { + "optional": true + }, + "socks": { + "optional": true + } + } + }, + "node_modules/mongodb-connection-string-url": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/mongodb-connection-string-url/-/mongodb-connection-string-url-3.0.2.tgz", + "integrity": "sha512-rMO7CGo/9BFwyZABcKAWL8UJwH/Kc2x0g72uhDWzG48URRax5TCIcJ7Rc3RZqffZzO/Gwff/jyKwCU9TN8gehA==", + "license": "Apache-2.0", + "dependencies": { + "@types/whatwg-url": "^11.0.2", + "whatwg-url": "^14.1.0 || ^13.0.0" + } + }, + "node_modules/morgan": { + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/morgan/-/morgan-1.10.1.tgz", + "integrity": "sha512-223dMRJtI/l25dJKWpgij2cMtywuG/WiUKXdvwfbhGKBhy1puASqXwFzmWZ7+K73vUPoR7SS2Qz2cI/g9MKw0A==", + "license": "MIT", + "dependencies": { + "basic-auth": "~2.0.1", + "debug": "2.6.9", + "depd": "~2.0.0", + "on-finished": "~2.3.0", + "on-headers": "~1.1.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/morgan/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/morgan/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "license": "MIT" + }, + "node_modules/morgan/node_modules/on-finished": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "integrity": "sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww==", + "license": "MIT", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" + }, + "node_modules/negotiator": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-1.0.0.tgz", + "integrity": "sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-inspect": { + "version": "1.13.4", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", + "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "license": "MIT", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/on-headers": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.1.0.tgz", + "integrity": "sha512-737ZY3yNnXy37FHkQxPzt4UZ2UWPWiCZWLvFZ4fu5cueciegX0zGPnrlY6bwRg4FdQOe9YU8MkmJwGhoMybl8A==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "license": "ISC", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/package-json-from-dist": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", + "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", + "dev": true, + "license": "BlueOak-1.0.0" + }, + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "license": "MIT" + }, + "node_modules/path-scurry": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", + "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "lru-cache": "^10.2.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + }, + "engines": { + "node": ">=16 || 14 >=14.18" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/path-to-regexp": { + "version": "8.4.2", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-8.4.2.tgz", + "integrity": "sha512-qRcuIdP69NPm4qbACK+aDogI5CBDMi1jKe0ry5rSQJz8JVLsC7jV8XpiJjGRLLol3N+R5ihGYcrPLTno6pAdBA==", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "dev": true, + "license": "ISC" + }, + "node_modules/promise": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/promise/-/promise-7.3.1.tgz", + "integrity": "sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==", + "license": "MIT", + "dependencies": { + "asap": "~2.0.3" + } + }, + "node_modules/proxy-addr": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "license": "MIT", + "dependencies": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/proxy-from-env": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-2.1.0.tgz", + "integrity": "sha512-cJ+oHTW1VAEa8cJslgmUZrc+sjRKgAKl3Zyse6+PV38hZe/V6Z14TbCuXcan9F9ghlz4QrFr2c92TNF82UkYHA==", + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "node_modules/pug": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/pug/-/pug-3.0.4.tgz", + "integrity": "sha512-kFfq5mMzrS7+wrl5pLJzZEzemx34OQ0w4SARfhy/3yxTlhbstsudDwJzhf1hP02yHzbjoVMSXUj/Sz6RNfMyXg==", + "license": "MIT", + "dependencies": { + "pug-code-gen": "^3.0.4", + "pug-filters": "^4.0.0", + "pug-lexer": "^5.0.1", + "pug-linker": "^4.0.0", + "pug-load": "^3.0.0", + "pug-parser": "^6.0.0", + "pug-runtime": "^3.0.1", + "pug-strip-comments": "^2.0.0" + } + }, + "node_modules/pug-attrs": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pug-attrs/-/pug-attrs-3.0.0.tgz", + "integrity": "sha512-azINV9dUtzPMFQktvTXciNAfAuVh/L/JCl0vtPCwvOA21uZrC08K/UnmrL+SXGEVc1FwzjW62+xw5S/uaLj6cA==", + "license": "MIT", + "dependencies": { + "constantinople": "^4.0.1", + "js-stringify": "^1.0.2", + "pug-runtime": "^3.0.0" + } + }, + "node_modules/pug-code-gen": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/pug-code-gen/-/pug-code-gen-3.0.4.tgz", + "integrity": "sha512-6okWYIKdasTyXICyEtvobmTZAVX57JkzgzIi4iRJlin8kmhG+Xry2dsus+Mun/nGCn6F2U49haHI5mkELXB14g==", + "license": "MIT", + "dependencies": { + "constantinople": "^4.0.1", + "doctypes": "^1.1.0", + "js-stringify": "^1.0.2", + "pug-attrs": "^3.0.0", + "pug-error": "^2.1.0", + "pug-runtime": "^3.0.1", + "void-elements": "^3.1.0", + "with": "^7.0.0" + } + }, + "node_modules/pug-error": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/pug-error/-/pug-error-2.1.0.tgz", + "integrity": "sha512-lv7sU9e5Jk8IeUheHata6/UThZ7RK2jnaaNztxfPYUY+VxZyk/ePVaNZ/vwmH8WqGvDz3LrNYt/+gA55NDg6Pg==", + "license": "MIT" + }, + "node_modules/pug-filters": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/pug-filters/-/pug-filters-4.0.0.tgz", + "integrity": "sha512-yeNFtq5Yxmfz0f9z2rMXGw/8/4i1cCFecw/Q7+D0V2DdtII5UvqE12VaZ2AY7ri6o5RNXiweGH79OCq+2RQU4A==", + "license": "MIT", + "dependencies": { + "constantinople": "^4.0.1", + "jstransformer": "1.0.0", + "pug-error": "^2.0.0", + "pug-walk": "^2.0.0", + "resolve": "^1.15.1" + } + }, + "node_modules/pug-lexer": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/pug-lexer/-/pug-lexer-5.0.1.tgz", + "integrity": "sha512-0I6C62+keXlZPZkOJeVam9aBLVP2EnbeDw3An+k0/QlqdwH6rv8284nko14Na7c0TtqtogfWXcRoFE4O4Ff20w==", + "license": "MIT", + "dependencies": { + "character-parser": "^2.2.0", + "is-expression": "^4.0.0", + "pug-error": "^2.0.0" + } + }, + "node_modules/pug-linker": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/pug-linker/-/pug-linker-4.0.0.tgz", + "integrity": "sha512-gjD1yzp0yxbQqnzBAdlhbgoJL5qIFJw78juN1NpTLt/mfPJ5VgC4BvkoD3G23qKzJtIIXBbcCt6FioLSFLOHdw==", + "license": "MIT", + "dependencies": { + "pug-error": "^2.0.0", + "pug-walk": "^2.0.0" + } + }, + "node_modules/pug-load": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pug-load/-/pug-load-3.0.0.tgz", + "integrity": "sha512-OCjTEnhLWZBvS4zni/WUMjH2YSUosnsmjGBB1An7CsKQarYSWQ0GCVyd4eQPMFJqZ8w9xgs01QdiZXKVjk92EQ==", + "license": "MIT", + "dependencies": { + "object-assign": "^4.1.1", + "pug-walk": "^2.0.0" + } + }, + "node_modules/pug-parser": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/pug-parser/-/pug-parser-6.0.0.tgz", + "integrity": "sha512-ukiYM/9cH6Cml+AOl5kETtM9NR3WulyVP2y4HOU45DyMim1IeP/OOiyEWRr6qk5I5klpsBnbuHpwKmTx6WURnw==", + "license": "MIT", + "dependencies": { + "pug-error": "^2.0.0", + "token-stream": "1.0.0" + } + }, + "node_modules/pug-runtime": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/pug-runtime/-/pug-runtime-3.0.1.tgz", + "integrity": "sha512-L50zbvrQ35TkpHwv0G6aLSuueDRwc/97XdY8kL3tOT0FmhgG7UypU3VztfV/LATAvmUfYi4wNxSajhSAeNN+Kg==", + "license": "MIT" + }, + "node_modules/pug-strip-comments": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/pug-strip-comments/-/pug-strip-comments-2.0.0.tgz", + "integrity": "sha512-zo8DsDpH7eTkPHCXFeAk1xZXJbyoTfdPlNR0bK7rpOMuhBYb0f5qUVCO1xlsitYd3w5FQTK7zpNVKb3rZoUrrQ==", + "license": "MIT", + "dependencies": { + "pug-error": "^2.0.0" + } + }, + "node_modules/pug-walk": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/pug-walk/-/pug-walk-2.0.0.tgz", + "integrity": "sha512-yYELe9Q5q9IQhuvqsZNwA5hfPkMJ8u92bQLIMcsMxf/VADjNtEYptU+inlufAFYcWdHlwNfZOEnOOQrZrcyJCQ==", + "license": "MIT" + }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/qs": { + "version": "6.15.3", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.15.3.tgz", + "integrity": "sha512-O9gl3zCl5h5blw1KGUzQKhA5oUXSl8rwUIM5o0S3nCXMliSvy5Dzx7/DJcI+SwgICv+IneSZwhBh1oSyEHA71A==", + "license": "BSD-3-Clause", + "dependencies": { + "es-define-property": "^1.0.1", + "side-channel": "^1.1.1" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "safe-buffer": "^5.1.0" + } + }, + "node_modules/range-parser": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.3.0.tgz", + "integrity": "sha512-hek2mFQpPuI4E1BBKrSto+BU3e3x4xuarsbiwr3+lf7p44juvFMV0XFWQAP3xUyqXA4RrXLIoaSUGbSt056ZMw==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/raw-body": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-3.0.2.tgz", + "integrity": "sha512-K5zQjDllxWkf7Z5xJdV0/B0WTNqx6vxG70zJE4N0kBs4LovmEYWJzQGxC9bS9RAKu3bgM40lrd5zoLJ12MQ5BA==", + "license": "MIT", + "dependencies": { + "bytes": "~3.1.2", + "http-errors": "~2.0.1", + "iconv-lite": "~0.7.0", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/readdirp": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz", + "integrity": "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 14.18.0" + }, + "funding": { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/resolve": { + "version": "1.22.12", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.12.tgz", + "integrity": "sha512-TyeJ1zif53BPfHootBGwPRYT1RUt6oGWsaQr8UyZW/eAm9bKoijtvruSDEmZHm92CwS9nj7/fWttqPCgzep8CA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "is-core-module": "^2.16.1", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/router": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/router/-/router-2.2.0.tgz", + "integrity": "sha512-nLTrUKm2UyiL7rlhapu/Zl45FwNgkZGaCpZbIHajDYgwlJCOzLSk+cIPAnsEqV955GjILJnKbdQC1nVPz+gAYQ==", + "license": "MIT", + "dependencies": { + "debug": "^4.4.0", + "depd": "^2.0.0", + "is-promise": "^4.0.0", + "parseurl": "^1.3.3", + "path-to-regexp": "^8.0.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/router/node_modules/is-promise": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-4.0.0.tgz", + "integrity": "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==", + "license": "MIT" + }, + "node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "license": "MIT" + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "license": "MIT" + }, + "node_modules/send": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/send/-/send-1.2.1.tgz", + "integrity": "sha512-1gnZf7DFcoIcajTjTwjwuDjzuz4PPcY2StKPlsGAQ1+YH20IRVrBaXSWmdjowTJ6u8Rc01PoYOGHXfP1mYcZNQ==", + "license": "MIT", + "dependencies": { + "debug": "^4.4.3", + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "etag": "^1.8.1", + "fresh": "^2.0.0", + "http-errors": "^2.0.1", + "mime-types": "^3.0.2", + "ms": "^2.1.3", + "on-finished": "^2.4.1", + "range-parser": "^1.2.1", + "statuses": "^2.0.2" + }, + "engines": { + "node": ">= 18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/serialize-javascript": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz", + "integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "randombytes": "^2.1.0" + } + }, + "node_modules/serve-static": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-2.2.1.tgz", + "integrity": "sha512-xRXBn0pPqQTVQiC8wyQrKs2MOlX24zQ0POGaj0kultvoOCstBQM5yvOhAVSUwOMjQtTvsPWoNCHfPGwaaQJhTw==", + "license": "MIT", + "dependencies": { + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "parseurl": "^1.3.3", + "send": "^1.2.0" + }, + "engines": { + "node": ">= 18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", + "license": "ISC" + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/side-channel": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.1.tgz", + "integrity": "sha512-6x6dK6zJdpTzF4sQeNYxwtvBzf6Eg4GtlesS94HOvTudUeyK2WXAaIfmDgsyslYrRBeFIlsi54AYsFGUuhmvrQ==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.4", + "side-channel-list": "^1.0.1", + "side-channel-map": "^1.0.1", + "side-channel-weakmap": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-list": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.1.tgz", + "integrity": "sha512-mjn/0bi/oUURjc5Xl7IaWi/OJJJumuoJFQJfDDyO46+hBWsfaVM65TBHq2eoZBhzl9EchxOijpkbRC8SVBQU0w==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", + "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-weakmap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", + "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3", + "side-channel-map": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/sparse-bitfield": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/sparse-bitfield/-/sparse-bitfield-3.0.3.tgz", + "integrity": "sha512-kvzhi7vqKTfkh0PZU+2D2PIllw2ymqJKujUcyPMd9Y75Nv4nPbGJZXNhxsgdQab2BmlDct1YnfQCguEvHr7VsQ==", + "license": "MIT", + "dependencies": { + "memory-pager": "^1.0.2" + } + }, + "node_modules/statuses": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz", + "integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/string-width-cjs": { + "name": "string-width", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true, + "license": "MIT" + }, + "node_modules/string-width-cjs/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.2.0.tgz", + "integrity": "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.2.2" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/strip-ansi-cjs": { + "name": "strip-ansi", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "license": "MIT", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/token-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/token-stream/-/token-stream-1.0.0.tgz", + "integrity": "sha512-VSsyNPPW74RpHwR8Fc21uubwHY7wMDeJLys2IX5zJNih+OnAnaifKHo+1LHT7DAdloQ7apeaaWg8l7qnf/TnEg==", + "license": "MIT" + }, + "node_modules/tr46": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-5.1.1.tgz", + "integrity": "sha512-hdF5ZgjTqgAntKkklYw0R03MG2x/bSzTtkxmIRw/sTNV8YXsCJ1tfLAX23lhxhHJlEf3CRCOCGGWw3vI3GaSPw==", + "license": "MIT", + "dependencies": { + "punycode": "^2.3.1" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/type-is": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-2.1.0.tgz", + "integrity": "sha512-faYHw0anBbc/kWF3zFTEnxSFOAGUX9GFbOBthvDdLsIlEoWOFOtS0zgCiQYwIskL9iGXZL3kAXD8OoZ4GmMATA==", + "license": "MIT", + "dependencies": { + "content-type": "^2.0.0", + "media-typer": "^1.1.0", + "mime-types": "^3.0.0" + }, + "engines": { + "node": ">= 18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/type-is/node_modules/content-type": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-2.0.0.tgz", + "integrity": "sha512-j/O/d7GcZCyNl7/hwZAb606rzqkyvaDctLmckbxLzHvFBzTJHuGEdodATcP3yIRoDrLHkIATJuvzbFlp/ki2cQ==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/void-elements": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/void-elements/-/void-elements-3.1.0.tgz", + "integrity": "sha512-Dhxzh5HZuiHQhbvTW9AMetFfBHDMYpo23Uo9btPXgdYP+3T5S+p+jgNy7spra+veYhBP2dCSgxR/i2Y02h5/6w==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/webidl-conversions": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", + "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=12" + } + }, + "node_modules/whatwg-url": { + "version": "14.2.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-14.2.0.tgz", + "integrity": "sha512-De72GdQZzNTUBBChsXueQUnPKDkg/5A5zp7pFDuQAj5UFoENpiACU0wlCvzpAGnTkj++ihpKwKyYewn/XNUbKw==", + "license": "MIT", + "dependencies": { + "tr46": "^5.1.0", + "webidl-conversions": "^7.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/with": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/with/-/with-7.0.2.tgz", + "integrity": "sha512-RNGKj82nUPg3g5ygxkQl0R937xLyho1J24ItRCBTr/m1YnZkzJy1hUiHUJrc/VlsDQzsCnInEGSg3bci0Lmd4w==", + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.9.6", + "@babel/types": "^7.9.6", + "assert-never": "^1.2.1", + "babel-walk": "3.0.0-canary-5" + }, + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/workerpool": { + "version": "9.3.4", + "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-9.3.4.tgz", + "integrity": "sha512-TmPRQYYSAnnDiEB0P/Ytip7bFGvqnSU6I2BcuSw7Hx+JSg/DsUi5ebYfc8GYaSdpuvOcEs6dXxPurOYpe9QFwg==", + "dev": true, + "license": "Apache-2.0" + }, + "node_modules/wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs": { + "name": "wrap-ansi", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true, + "license": "MIT" + }, + "node_modules/wrap-ansi-cjs/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-styles": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", + "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "license": "ISC" + }, + "node_modules/ws": { + "version": "8.21.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.21.1.tgz", + "integrity": "sha512-+0NTnW77fFN/DjQi6k/Sq/Yvk4Sgajw7urW8V+asjXnRgDs9gyGkdb7EzgfhA4goXsRIZKE28fzIXBHEzhuiWw==", + "license": "MIT", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=10" + } + }, + "node_modules/yargs": { + "version": "17.7.3", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.3.tgz", + "integrity": "sha512-GZtjxm/J/4TSxuL3FNYjCmLktBTnIw/rVmKSIyKeYAZpmJB2ig9VauCC5xsa82GNKVKDAqpOn3KVzNt0zmrU0g==", + "dev": true, + "license": "MIT", + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs-unparser": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz", + "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==", + "dev": true, + "license": "MIT", + "dependencies": { + "camelcase": "^6.0.0", + "decamelize": "^4.0.0", + "flat": "^5.0.2", + "is-plain-obj": "^2.1.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/yargs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/yargs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true, + "license": "MIT" + }, + "node_modules/yargs/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/yargs/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + } + } +} diff --git a/sensorapi/package.json b/sensorapi/package.json new file mode 100644 index 0000000..ac5adbe --- /dev/null +++ b/sensorapi/package.json @@ -0,0 +1,36 @@ +{ + "name": "sensorapi", + "version": "1.4.2", + "date": "2023-11-29 16:00 UTC", + "private": true, + "scripts": { + "start": "node ./bin/www.js >>/var/log/sensorapi.log 2>&1", + "dev": "node ./bin/www.js", + "test": "mocha ./test/test.js" + }, + "type": "module", + "bin": { + "www": "./bin/www.js" + }, + "dependencies": { + "@influxdata/influxdb-client": "^1.35.0", + "@influxdata/influxdb-client-apis": "^1.35.0", + "axios": "^1.12.2", + "cookie-parser": "~1.4.7", + "cors": "^2.8.5", + "debug": "~4.4.3", + "express": "^5.1.0", + "http-errors": "~2.0.0", + "i18next": "^25.5.2", + "i18next-http-middleware": "^3.8.0", + "i18next-fs-backend": "^2.0.0", + "luxon": "^3.7.2", + "mongodb": "^6.19.0", + "morgan": "~1.10.1", + "pug": "^3.0.3", + "ws": "^8.18.3" + }, + "devDependencies": { + "mocha": "^11.7.2" + } +} diff --git a/sensorapi/routes/api.js b/sensorapi/routes/api.js new file mode 100644 index 0000000..4a18f9c --- /dev/null +++ b/sensorapi/routes/api.js @@ -0,0 +1,54 @@ +import express from 'express' + +import {getData4map} from "../actions/data4map.js" +import * as getData from "../actions/getsensorData.js"; +import * as getProps from "../actions/getproperties.js"; +import * as getAKWs from "../actions/getAKWData.js"; +import * as holAddr from "../actions/getaddress.js"; + +export const apiRouter = express.Router(); + +const cmdTable = [ + {cmd: 'getactdata', func: getData.getActData}, + {cmd: 'getlongavg', func: getData.getLongAvg}, + {cmd: 'getavgdata', func: getData.getAvgData}, + {cmd: 'getoneproperty', func: getProps.getOneProperty}, + {cmd: 'getakwdata', func: getAKWs.getakwdata}, + {cmd: 'getaddress', func: holAddr.getAddress}, + {cmd: 'getcitycoords', func: holAddr.getCityCoords}, + {cmd: 'getsensordata', func: getData.getSensorData}, + {cmd: 'getmapdata', func: getData4map} +] + +let i18n; + +export const translate = (x) => { + return i18n.t(x) +} + +export const dispatchCommand = async (cmd, table, params, res) => { + let notfound = true + for (let c of table) { + if (c.cmd === cmd) { + notfound = false + let erg = await c.func(params) + if (typeof erg === 'string') { + res.type('text') + res.send(erg) + } else { + res.json(erg) + } + } + } + if (notfound) { + res.json({err: translate('CMNDUNKNOWN')}) + } +} + +// normal routes called from javascript client +apiRouter.get('/:cmd', async (req, res) => { + const params = req.query + params.chart = false + i18n = req.i18n + await dispatchCommand(req.params.cmd, cmdTable, params, res) +}) diff --git a/sensorapi/routes/index.js b/sensorapi/routes/index.js new file mode 100644 index 0000000..edec9e8 --- /dev/null +++ b/sensorapi/routes/index.js @@ -0,0 +1,12 @@ +import express from 'express' +import { translate as trans } from '../routes/api.js' + +const router = express.Router(); + +/* GET home page. */ + +router.get('/', function(req, res, next) { + res.status(200).json({message: trans('NOTHING')}) +}); + +export default router diff --git a/sensorapi/sensorspecials/geigeract.js b/sensorapi/sensorspecials/geigeract.js new file mode 100644 index 0000000..be04164 --- /dev/null +++ b/sensorapi/sensorspecials/geigeract.js @@ -0,0 +1,152 @@ +// Data preparation for fetching geigeractivity data +// rxf 2022-06-24 + +import {returnOnError} from "../utilities/reporterror.js"; +import { calcRange, getActData, getAvgData, getLongAvg } from "../actions/getsensorData.js" +import checkParams from "../utilities/checkparams.js"; +import { setoptionfromtable } from "../utilities/chartoptions.js" +import {DateTime} from 'luxon' +import { fetchgeigerAVGData } from "../databases/mongo.js"; +import { translate as trans } from '../routes/api.js' + + + +const geigeractFilter = (data, opts, actual) => { + let erg = {} + erg.sid = opts.sensorid + erg.sname = opts.sname + erg.values = [] + for (let x of data.values) { + let entry = {} + entry.datetime = x.datetime + if(actual) { + entry.cpm = x.counts_per_minute, + entry.uSvh = x.counts_per_minute / 60 * opts.factor + } else { + entry.cpmAvg = x.counts_per_minute, + entry.uSvhAvg = x.counts_per_minute / 60 * opts.factor + } + erg.values.push(entry) + } + return erg +} + +const getgeigerDWMData = async (opts) => { + if(opts.avg === 1) { + const erg = await getActData(opts) + return erg + } else { + const erg = await fetchgeigerAVGData(opts) + return erg + } +} + +const factorTable = [ + {name: 'SBM-20', factor: 1 / 2.47}, + {name: 'SBM-19', factor: 1 / 9.81888}, + {name: 'Si22G', factor: 0.081438}, + {name: 'J306', factor: 0.06536} +] + +const getfactor = (name) => { + const typ = name.slice((10)) + for(const x of factorTable) { + if (x.name === typ) { + return 1 / 60 * x.factor + } + } + return 1 +} + + +export const getgeigerData = async (params, possibles, props) => { + let ret = {err: null} + + let {opts, erro} = checkParams(params, { + mandatory:[ + {name:'sensorid', type: 'int'}, + ], + optional: possibles + }) + // To be compatible with old API: + if (opts.out === 'csv') { + opts.csv = true + } + if (erro) { + return returnOnError(ret, erro, getNoiseData.name) + } + + opts.factor = getfactor(props.name[0].name) + opts.span = setoptionfromtable(opts.span, 1) + opts.daystart = setoptionfromtable(opts.daystart, false) + opts.avg = setoptionfromtable(opts.avg, 1) + opts.moving = setoptionfromtable(opts.moving, false) + let {start, stop} = calcRange(opts) // calc time range + opts.start = start + opts.stop = stop + let erg = await getgeigerDWMData(opts) // get the data + ret = { + err: erg.err, + options: { + sid: opts.sensorid, + indoor: props.location[0].indoor, + span: opts.span, + start: DateTime.fromISO(opts.start.slice(7)), + data: opts.data, + count: erg.values.length, + avg: opts.avg, + moving: opts.moving + }, + values: erg.values, + } + if(ret.values.length === 0) { + ret.err = trans('NODATA') + } + return ret +} + +/* + + + let erg = { err: null, data: {}} + + let params = { + sensorid: opts.sensorid, + avg: opts.avg, + datetime: opts.start + } + if (opts.what === 'oneday') { + params.span = 1 + } else if (opts.what === 'oneweek') { + params.span = 7 + } else { + params.span = 31 + params.moving = false + params.avg = 1440 + } + let { data, err } = await getAvgData(params) + if (err != null) { + return returnOnError(erg, err, getgeigerData.name) + } + erg.data.geigermovavg = geigeractFilter(data, opts, false) + if (opts.what === 'oneday') { + const { data, err} = await getActData(params) + if (err != null) { + return returnOnError(erg, err, getgeigerData.name) + } + erg.data.geigeractual = geigeractFilter(data, opts, true) + } + if(opts.climatesid && ((opts.what === 'oneday') || (opts.what === 'oneweek'))) { + params.sensorid = opts.climatesid + params.avg = 10 + const { data, err} = await getAvgData(params) + if (err != null) { + return returnOnError(erg, err, getgeigerData.name) + } + data.sid = opts.climatesid + data.sname = opts.climatesname + erg.data.climate = data + } + return erg +} +*/ diff --git a/sensorapi/sensorspecials/noise.js b/sensorapi/sensorspecials/noise.js new file mode 100644 index 0000000..6d37807 --- /dev/null +++ b/sensorapi/sensorspecials/noise.js @@ -0,0 +1,499 @@ +// Data preparation for fetching noise data +// rxf 2023-03-05 +const DBASE = process.env.DBASE || 'mongo' + +import {returnOnError} from "../utilities/reporterror.js"; +import { getActData, getAvgData, getLongAvg, calcRange} from "../actions/getsensorData.js" +import checkParams from "../utilities/checkparams.js"; +import {DateTime} from 'luxon' +import { translate as trans } from '../routes/api.js' +import * as influx from "../databases/influx.js" +import * as mongo from "../databases/mongo.js" +import { setoptionfromtable } from "../utilities/chartoptions.js" + +export const getNoiseData = async (params, possibles, props) => { + let ret = {err: null} + + let {opts, err} = checkParams(params, { + mandatory:[ + {name:'sensorid', type: 'int'}, + ], + optional: possibles + }) + // To be compatible with old API: + if (opts.out === 'csv') { + opts.csv = true + } + if (err) { + return returnOnError(ret, err, getNoiseData.name) + } + // execute function depending on given 'data' + for(let x of whatTable) { + if (x.what === opts.data) { + opts.span = setoptionfromtable(opts.span, x.span) + opts.daystart = setoptionfromtable(opts.daystart, x.daystart) + let {start, stop} = calcRange(opts) // calc time range + opts.start = start + opts.stop = stop + let erg = await x.func(opts) // get the data + if (opts.csv === true) { + ret = erg + } else { + ret = { + err: erg.err, + options: { + sid: opts.sensorid, + indoor: props.location[0].indoor, + span: opts.span, + start: DateTime.fromISO(opts.start.slice(7)).toUTC().toFormat("yyyy-LL-dd'T'HH:mm:ss'Z'"), + data: opts.data, + peak: opts.peak, + count: erg.values.length, + }, + values: erg.values, + } + if (!x.peak) { + delete ret.options.peak + } + if(ret.values.length === 0) { + ret.err = trans('NODATA') + } + } + return ret + } + } + return returnOnError(ret, 'CMNDUNKNOWN', getNoiseData.name) +} + + +// ********************************************* +// getLiveData +// +// Get all actual data from database. Values are stored every 2.5min +// +// params: +// db: Database +// opt: different options (see further down) +// +// return: +// JSON: +// { sid: 29212, span: 1, start: "2019-10-23T00:00", count: 381, values: [ +// { datetime: "2019-10-22T22:05:34.000Z", LAeq: 42.22, LA_min: 39.91, LA_max: 45.18, E10tel_eq: 16672.47212551061 }, +// { datetime: "2019-10-22T22:07:59.000Z", LAeq: 53.72, LA_min: 39.97, LA_max: 63.54, E10tel_eq: 235504.9283896009 }, +// ......... +// ]} +// CSV +// datetime,LAeq,LAmax,LAmin,"10^(LAeq/10)" +// 2019-10-22T22:05:34.000Z,42.22,45.18,39.91,16672.47212551061 +// 2019-10-22T22:07:59.000Z,53.72,63.54,39.97,235504.9283896009 +// 2019-10-22T22:15:16.000Z,44.02,48.99,42.14,25234.807724805756 +// .... +// +// ********************************************* +const getLiveData = async (opts) => { + const erg = await getActData(opts) + if (opts.csv) { + let csvStr = "datetime,LAeq,LAmax,LAmin,10^(LAeq/10)\n" + if (!erg.err) { + for (let item of erg.values) { + if (item.n_AVG != -1) { + csvStr += item.datetime + ',' + + item.LAeq + ',' + + item.LA_max + ',' + + item.LA_min+ ',' + + item.E10tel_eq + '\n' + } + } + } + return csvStr + } + return erg +} + + +// ********************************************* +// gethavgData +// +// Get average per hour, default: 5 days +// +// params: +// db: Database +// opt: different options (see further down) +// +// return: +// JSON: +// { sid: 29212, span: 5, start: "2019-11-01T23:00:00Z", average: 'hour', peak: 70, count: 120, values: [ +// { datetime: "2019-10-22T23:00:00.000Z", n_AVG: 58.27, peakcount: 3 }, +// { datetime: "2019-10-23T00:00:00.000Z", n_AVG: 45.77, peakcount: 4 }, +// { datetime: "2019-10-23T01:00:00.000Z", n_AVG: 62.34, peakcount: 6 }, +// ......... +// ]} + +// CSV: +// datetime,n_AVG,peakcount +// 2019-10-22T23:00:00.000Z,58.27,3 +// 2019-10-23T00:00:00.000Z,45.77,4 +// 2019-10-23T01:00:00.000Z,62.34,6 +// .... +// +// ********************************************* +const gethavgData = async (opts, props) => { + let erg = await getNoiseAVGData(opts) + if (opts.csv) { + let csvStr = "datetime,n_AVG,peakcount\n" + if (!erg.err) { + for (let item of erg.values) { + if (item.n_AVG != -1) { + csvStr += item.datetime + ',' + item.n_AVG + ',' + item.peakcount + '\n' + } + } + } + return csvStr + } + return {err: erg.err, values: erg.values} +} + + +// ********************************************* +// getdavgData +// +// Get average per day , default: 30 days +// +// params: +// db: Database +// opt: different options (see further down) +// +// return: +// JSON: +// { sid: 29212, span: 30, start: "2019-10-23T00:00", average: 'day', peak: 70, count: 30, values: [ +// { datetime: "2019-10-22T23:00:00.000Z", n_AVG: 58.27, peakcount: 300 }, +// { datetime: "2019-10-23T23:00:00.000Z", n_AVG: 62.34, peakcount: 245 }, +// ......... +// ]} +// +// CSV: +// datetime,n_AVG,peakcount +// 2019-10-22T23:00:00.000Z,58.27,300 +// 2019-10-23T23:00:00.000Z,62.34,245 +// .... +// +// ********************************************* +async function getdavgData(opts) { + opts.long = true; + let erg = await getNoiseAVGData(opts); + let val = []; + let csvStr = 'datetime,n_AVG,peakcount\n'; + if (!erg.err) { + for (let i = 0; i < erg.values.length; i += 24) { + let sum = 0; + let count = 0; + let pk = 0; + let werte = {}; + for (let k = 0; k < 24; k++) { + const item = erg.values[i + k] + if ((item != null) && (item.n_sum != -1)) { + sum += item.n_sum; + count += item.count; + pk += item.peakcount; + if (werte.datetime === undefined) { + let dt = DateTime.fromISO(item.datetime) + werte.datetime = dt.startOf('day').toFormat("yyyy-LL-dd'T'HH:mm:ss'Z'") + } + } + } + if (count === 0) { + werte.n_AVG = -1 + } else { + werte.n_AVG = 10 * Math.log10(sum / count); + } + werte.peakcount = pk; + if (opts.csv) { + csvStr += werte.datetime + ',' + werte.n_AVG + ',' + werte.peakcount + '\n' + } else { + val.push(werte); + } + } + } + if (opts.csv) { + return csvStr; + } + return {err: erg.err, values: val} +} + +// addDatetime +// add the actual date to wert, if werte is undefined +const addDatetime = (werte, item) => { + if (werte.datetime === undefined) { + let dt = DateTime.fromISO(item.datetime) + werte.datetime = dt.startOf('day').toFormat("yyyy-LL-dd'T'HH:mm:ss'Z'") + } +} + + + +// ********************************************* +// getdaynightData +// +// Get average for day (6h00 - 22h00) and night (22h00 - 6h00) separated +// Use the hour average calculation, which brings the sum and the count for every hour +// then add these values up for the desired time range and calculate the average. +// +// The night-value of the last day is always 0, because the night is not complete (day is +// over at 24:00 and the night lasts til 6:00) +// +// params: +// db: Database +// opt: different options (see further down) +// +// return +// JSON +// { sid: 29212, span: 30, start: "2019-09-29", count: 30, values: [ +// { date: "2019-09-29", n_dayAVG: 49.45592437272605, n_nightAVG: 53.744277577490614 }, +// { date: "2019-09-30", n_dayAVG: 51.658169450663465, n_nightAVG: 47.82407695888631 }, +// ......... +// ]} +// CSV +// datetime,n_dayAVG,n_nightAVG +// 2019-09-29,49.45592437272605,53.744277577490614 +// 2019-09-30,51.658169450663465,47.82407695888631 +// .... +// +// ********************************************* +async function getdaynightData(opts) { + opts.long = true; + let erg = await getNoiseAVGData(opts); + let val = []; + let csvStr = 'datetime,n_dayAVG,n_nightAVG\n'; + if (!erg.err) { + let done = false; + let dt; + // The received hourly data array always (!!) starts at 0h00 local (!) time. + // So to calculate day values, we skip the first 6 hour and start from there + // now we add 16 hour for day and following 8 hour for night + const length = erg.values.length + for (let i = 6; i < length;) { + let dsum = 0, dcnt = 0; + let nsum = 0, ncnt = 0; + let werte = {}; + for (let k = 0; k < 16; k++, i++) { + if ( i < length) { + const item = erg.values[i] + if (item.n_sum != -1) { + addDatetime(werte, item) + dsum += item.n_sum; + dcnt += item.count; + } + } + } + if (i < (length - 8)) { + const item = erg.values[i] + for (let k = 0; k < 8; k++, i++) { + if (i < length) { + if (item.n_sum != -1) { + addDatetime(werte, item) + nsum += item.n_sum; + ncnt += item.count; + } + } + } + } else { + done = true; + } + if (dcnt != 0) { + werte.n_dayAVG = 10 * Math.log10(dsum / dcnt); + } else { + werte.n_dayAVG = 0; + } + if (ncnt != 0) { + werte.n_nightAVG = 10 * Math.log10(nsum / ncnt); + } else { + werte.n_nightAVG = 0; + } + if (opts.csv) { + csvStr += werte.datetime + ',' + werte.n_dayAVG + ',' + werte.n_nightAVG + '\n' + } else { + val.push(werte); + } + if (done) { + break; + } + } + } + if (opts.csv) { + return csvStr; + } + return {err: erg.err, values: val} +} + + +// ********************************************* +// getLdenData +// +// Use hour averages to calculate the LDEN. +// Formula: +// LDEN = 10 * log10 ( 1/24 ( (12 * 10^(Lday/10)) + (4*10^((Levn+5)/10) + (8*10^((Lnight+10)/10)) ) +// +// params: +// db: Database +// sid: sensor number +// opt: different options (see further down) +// +// return: +// JSON: +// { sid: 29212, span: 30, start: "2019-09-29", count: 30, values: [ +// { lden: 59.53553743437777, date: "2019-09-29" }, +// { lden: 55.264733497513554, date: "2019-09-30" }, +// ......... +// ]} +// CSV +// datetime,lden +// 2019-09-29,59.53553743437777 +// 2019-09-30,55.264733497513554 +// .... +// +// ********************************************* +async function getLdenData(opts) { + opts.long = true; + let erg = await getNoiseAVGData(opts); + let val = []; + let csvStr = 'datetime,lden\n'; + if (!erg.err) { + let done = false; + const calcAVG = (sum, cnt) => { + if (cnt != 0) { + return (10 * Math.log10(sum / cnt)); + } else { + return 0; + } + } + + // The received hourly data array always (!!) starts at 0h00 local (!) time. + // So to calculate day values, we skip the first 6 hour and start from there + // now we add 12 hour for day and following 4 hour for evening and + // additional 8 hours for night + const length = erg.values.length + for (let i = 6; i < length;) { + let dsum = 0, dcnt = 0; + let nsum = 0, ncnt = 0; + let esum = 0, ecnt = 0; + let werte = {}; + let dayAVG = 0, evnAVG = 0, nightAVG = 0; + for (let k = 0; k < 12; k++, i++) { + if ( i < length) { + const item = erg.values[i] + if (item.n_sum != -1) { + addDatetime(werte, item) + dsum += item.n_sum; + dcnt += item.count; + } + } + } + for (let k = 0; k < 4; k++, i++) { + if ( i < length) { + const item = erg.values[i] + if (item.n_sum != -1) { + addDatetime(werte, item) + esum += item.n_sum; + ecnt += item.count; + } + } + } + if (i < (erg.values.length - 8)) { + for (let k = 0; k < 8; k++, i++) { + if (i < length) { + const item = erg.values[i] + if (item.n_sum != -1) { + addDatetime(werte, item) + nsum += item.n_sum; + ncnt += item.count; + } + } + } + } else { + done = true; + } + dayAVG = calcAVG(dsum, dcnt); + evnAVG = calcAVG(esum, ecnt); + nightAVG = calcAVG(nsum, ncnt); + // Calculate LDEN: + let day = 12 * Math.pow(10, dayAVG / 10); // ... and calculate the LDEN values following ... + let evn = 4 * Math.pow(10, (evnAVG + 5) / 10); // ... the LDEN formaula (see function description) + let night = 8 * Math.pow(10, (nightAVG + 10) / 10); + werte.lden = 10 * Math.log10((day + evn + night) / 24); + if (opts.csv) { + csvStr += werte.datetime + ',' + werte.lden + '\n' + } else { + val.push(werte); + } + if (done) { + break; + } + } + } + if (opts.csv) { + return csvStr; + } + return {err: erg.err, values: val} +} + + +const getAPIprops = (opt) => { + +} + +const getNoiseAVGData = async (opts) => { + let ret + if (DBASE === 'mongo') { + ret = await mongo.fetchNoiseAVGData(opts) + } else if (DBASE === 'influx') { + ret = await influx.fetchNoiseAVGData(opts) + // Influx stores the average from 00:00h to 01:00h as 01:00h, so we have to shift the time 1 hour back + for (let x=0; x < ret.values.length; x++) { + ret.values[x].datetime = DateTime.fromISO(ret.values[x].datetime).toUTC().minus({hours:1}).toFormat("yyyy-LL-dd'T'HH:mm:ss'Z'") + } + } else { + ret.err = 'DBASEUNKNOWN' + } + + if(ret.err) { + return returnOnError(ret, ret.err, getNoiseAVGData.name) + } + if(ret.values.length === 0) { + return returnOnError(ret, 'NODATA', getNoiseAVGData.name) + } + // The times are always the END of the period (so: period from 00:00h to 01:00h -> time is 01:00) + + // To easily extract the values, we copy the data from docs into a new array, so that the + // hour in an element in docs becomes the index into the new array (for every new day this + // index will be incremented by 24). Missing values are marked by: {n_sum=-1, n_AVG=-1}. + // For havg add the missed hours to the arry + let emptyValues = {n_AVG: -1} + if (opts.long) { + emptyValues.n_sum = -1 + } + const misshours = DateTime.fromISO(ret.values[0].datetime).toUTC().get('hour') + let hoursArr = new Array(opts.span * 24 + misshours); // generate new array + hoursArr.fill(emptyValues) // fill array with 'empty' values + let startDay = DateTime.fromISO(ret.values[0].datetime).toUTC().get('day') // calc first day + let k = 0 + for (let d of ret.values) { // loop through docs + let stunde = DateTime.fromISO(d.datetime).toUTC().get('hour') // get current hour + let day = DateTime.fromISO(d.datetime).toUTC().get('day') // get current day + if (day != startDay) { // if date has changed + k += 24 // increment index by 24 + startDay = day + } + hoursArr[k + stunde] = d // copy date into hourArray + } + return { err: ret.err, values: hoursArr} +} + +const whatTable = [ + {'what':'live', 'span': 1, 'daystart': false, peak: false, 'func': getLiveData}, + {'what':'havg', 'span': 7, 'daystart': false, peak: true, 'func': gethavgData}, + {'what':'davg', 'span': 30, 'daystart': true, peak: true, 'func': getdavgData}, + {'what':'daynight', 'span': 30, 'daystart': true, peak: false, 'func': getdaynightData}, + {'what':'lden', 'span': 30, 'daystart': true, peak: false, 'func': getLdenData}, + {'what':'props', 'span': 0, 'daystart': true, peak:false, 'func': getAPIprops}, +]; + diff --git a/sensorapi/test/test.js b/sensorapi/test/test.js new file mode 100644 index 0000000..183f1c0 --- /dev/null +++ b/sensorapi/test/test.js @@ -0,0 +1,29 @@ +import {getData4map} from '../actions/data4map.js' +import assert from 'assert/strict' + +describe("get data for map - test", function() { + const box = { + "east": 9.322391662597672, + "north": 48.86726810417461, + "south": 48.69057640500091, + "west": 8.99760833740236 + } + + it("geigeractivity should return at least 4 elements", async function() { + const erg = await getData4map( + { + "type": "radioactivity", + "box": box, + test: true + }) + assert.ok(erg.count >= 4) + }) + it("pm should return at least 270 elements", async function() { + const erg = await getData4map( + { + "type": "pm", + "box": box + }) + assert.ok(erg.count >= 270) + }) +}) diff --git a/sensorapi/utilities/chartoptions.js b/sensorapi/utilities/chartoptions.js new file mode 100644 index 0000000..01ddc6f --- /dev/null +++ b/sensorapi/utilities/chartoptions.js @@ -0,0 +1,148 @@ +// Utility routine for plotting the data + +export const colors = {'eq': '#0000FF', 'max': '#FF0000', 'min': '#008000', 'peaks': '#DAA520'}; +export const noise_ymin = 30; + +export function createGlobObtions() { + // Options, die für alle Plots identisch sind + let globObject = { + chart: { + spacingRight: 20, + spacingLeft: 20, + spacingTop: 25, + backgroundColor: { + linearGradient: [0, 400, 0, 0], + stops: [ + [0, '#eee'],//[0, '#ACD0AA'], //[0, '#A18D99'], // [0, '#886A8B'], // [0, '#F2D0B5'], + [1, '#fff'] + ] + }, + type: 'line', + borderWidth: '2', + // events: { + // selection: function (event) { + // if (event.xAxis) { + // doUpdate = false; + // } else { + // doUpdate = true; + // } + // } + // } + }, + title: { + align: 'left', + style: {'fontSize': '25px'}, + useHTML: true, + }, + subtitle: { + align: 'left', + }, + tooltip: { + valueDecimals: 1, + backgroundColor: '#ffffff', + borderWidth: 0, + borderRadius: 0, + useHTML: true, + }, + xAxis: { + type: 'datetime', + title: { + text: 'date/time', + }, + gridLineWidth: 2, + labels: { + formatter: function () { + let v = this.axis.defaultLabelFormatter.call(this); + if (v.indexOf(':') == -1) { + return '' + v + ''; + } else { + return v; + } + } + }, + }, + legend: { + enabled: true, + layout: 'horizontal', +// verticalAlign: 'top', + borderWidth: 1, + align: 'center', + }, + plotOptions: { + series: { + animation: false, + turboThreshold: 0, + marker: { + enabled: false, + }, + }, + } + }; + return globObject; +} + +export function calcWeekends(data, isyear) { +/* let weekend = []; + let oldDay = 8; + for (let i = 0; i < data.length; i++) { + let mom = moment(data[i].date); + if (isyear) { + mom = moment(data[i]._id) + } + let day = mom.day(); + let st = mom.startOf('day'); + if (day != oldDay) { + if (day == 6) { + weekend.push({ + color: 'rgba(169,235,158,0.4)', + from: st.valueOf(), + to: st.add(1, 'days').valueOf(), + zIndex: 0 + }) + } else if (day == 0) { + weekend.push({ + color: 'rgba(169,235,158,0.4)', + from: st.valueOf(), + to: st.add(1, 'days').valueOf(), + zIndex: 0 + }) + } + oldDay = day; + } + } + return weekend; +*/} + +export function calcDays(data, isyear) { + let days = []; + if (data.length == 0) { + return days + } + let oldday = moment(data[0].date).day(); + if (isyear) { + oldday = moment(data[0]._id).day(); + } + for (let i = 0; i < data.length; i++) { + let m = moment(data[i].date); + if (isyear) { + m = moment(data[i]._id); + } + let tag = m.day() + if (tag != oldday) { + m.startOf('day'); + days.push({color: 'lightgray', value: m.valueOf(), width: 1, zIndex: 2}); + oldday = tag; + } + } + return days; +}; + +export const setoptionfromtable = (opt,tabval) => { + let ret = opt + if ((opt === null) || (opt === '') || (opt === undefined) || (opt < tabval)){ + ret = tabval + } + return ret +} + + diff --git a/sensorapi/utilities/checkparams.js b/sensorapi/utilities/checkparams.js new file mode 100644 index 0000000..ad4af59 --- /dev/null +++ b/sensorapi/utilities/checkparams.js @@ -0,0 +1,54 @@ +// parse the params from http call + +import {returnOnError} from "./reporterror.js" + +const checkParams = (params, mo) => { + let o = {opts: {}, err: null} + if ((mo.mandatory.length !== 0) && (params === undefined)) { + return returnOnError(o, 'NOPARAMETER', checkParams.name ) + } + for (let p of mo.mandatory) { + if (!(p.name in params)) { + return returnOnError(o, 'NOMANDPARAM', checkParams.name, p.name) + } + if (p.type === 'int') { + let x = parseInt(params[p.name]) + if (isNaN(x)) { + return returnOnError(o, 'PARAMNONUM', checkParams.name, p.name) + } else { + o.opts[p.name] = x + continue + } + } else if (p.type === 'float') { + let x = parseFloat(params[p.name]) + if (isNaN(x)) { + return returnOnError(o, 'PARAMNONUM', checkParams.name, p.name) + } else { + o.opts[p.name] = x + continue + } + } + o.opts[p.name] = params[p.name] + } + for(let p of mo.optional) { + if (!(p.name in params)) { + o.opts[p.name] = p.default + } else { + if (p.type === 'int') { + let x = parseInt(params[p.name]) + if (isNaN(x)) { + o.opts[p.name] = p.default + } else { + o.opts[p.name] = x + } + } else if (p.type === 'bool') { + o.opts[p.name] = params[p.name] === 'true' + } else { + o.opts[p.name] = params[p.name] + } + } + } + return o +} + +export default checkParams diff --git a/sensorapi/utilities/csv2json.js b/sensorapi/utilities/csv2json.js new file mode 100644 index 0000000..4ce9bfe --- /dev/null +++ b/sensorapi/utilities/csv2json.js @@ -0,0 +1,35 @@ +// convert influx csv output to JSON + +export function csv2Json(str, delimiter = ",") { + // slice from start of text to the first \n index + // use split to create an array from string by delimiter + const headers = str.slice(0, str.indexOf("\r\n")).split(delimiter).slice(3); + let x = headers.findIndex((x) => (x === '_time') || (x === '_stop')) + if (x != -1) { + headers[x] = 'datetime' + } + // slice from \n index + 1 to the end of the text + // use split to create an array of each csv value row + const rows = str.slice(str.indexOf("\r\n") + 2).split("\r\n").slice(0,-2) + + // Map the rows + // split values from each row into an array + // use headers.reduce to create an object + // object properties derived from headers:values + // the object passed as an element of the array + const arr = rows.map(function (row) { + const values = row.split(delimiter).slice(3); + const el = headers.reduce(function (object, header, index) { + if(header !== 'datetime') { + object[header] = parseFloat(values[index]); + } else { + object[header] = values[index]; + } + return object; + }, {}); + return el; + }); + + // return the array + return arr; +} diff --git a/sensorapi/utilities/logit.js b/sensorapi/utilities/logit.js new file mode 100644 index 0000000..7a4e0c8 --- /dev/null +++ b/sensorapi/utilities/logit.js @@ -0,0 +1,16 @@ +import { DateTime} from 'luxon' + +const MOCHA_TEST = process.env.MOCHA_TEST || false + +export function logit(str) { + if(MOCHA_TEST) return + let s = `${DateTime.now().toISO()} => ${str}`; + console.log(s); +} + +export function logerror(str) { + if(MOCHA_TEST) return + let s = `${DateTime.toISO()} => *** ERROR *** ${str}`; + console.log(s); +} + diff --git a/sensorapi/utilities/reporterror.js b/sensorapi/utilities/reporterror.js new file mode 100644 index 0000000..c3a34c9 --- /dev/null +++ b/sensorapi/utilities/reporterror.js @@ -0,0 +1,22 @@ +import {logit} from "./logit.js"; +import { translate as trans } from '../routes/api.js' + +export const reportError = (message, errortext) => { + message.error = true + message.errortext = errortext + return message +} + +export const returnOnError = (pr, error, name, p1='', p2='') => { + error = trans(error) + if (error.indexOf('xxx') !== -1) { + error = error.replace('xxx', p1) + } + if (error.indexOf('yyy') !== -1) { + error = error.replace('yyy', p1) + } + pr.err = error + logit(`${name}: ${error}`) + return pr +} +