diff --git a/ReadMe.md b/ReadMe.md
new file mode 100644
index 0000000..6e182a4
--- /dev/null
+++ b/ReadMe.md
@@ -0,0 +1,35 @@
+# GoodGarden
+
+Welkom bij ons project genaamd "GoodGarden". Wij hebben besloten om er een monolitische project van te maken. Alles is te vinden binnen deze repository.
+
+### Vereisten
+
+ * Python
+ * Node.Js
+ * XAMPP (of andere naar keuze)
+
+### Installeren
+
+Zorg dat je in de hoofdmap "GoodGarden" zit. Kijk in je path: "/GoodGarden". Als je in de correcte map zit moet je de volgende items installeren:
+
+ - npm install electron
+ - npm install express
+ - npm install body-parser
+ - npm install python-shell
+
+ - pip install mysql-connector-python
+ - pip install requests
+
+## Gebruik
+
+Een paar voorbeelden van nuttig gebruik van dit project of hoe het gebruikt kan worden.
+
+## Versiebeheer
+
+We gebruiken [SemVer](http://semver.org/) voor versiebeheer. Voor de beschikbare versies, zie de [tags op deze repository](https://example.com/tags).
+
+## Auteurs
+
+* **Jouw Naam** - *Initieel werk* - [Gebruikersnaam](https://example.com/)
+
+Zie ook de lijst van [bijdragers](https://example.com/contributors) die hebben bijgedragen aan dit project.
diff --git a/app.js b/app.js
new file mode 100644
index 0000000..7c74b7f
--- /dev/null
+++ b/app.js
@@ -0,0 +1,101 @@
+const { app, BrowserWindow,ipcMain } = require('electron'); /* TYPE IN TERMINAL: "npm install electron" */
+const express = require('express'); /* TYPE IN TERMINAL: "npm install express" */
+const bodyParser = require('body-parser'); /* TYPE IN TERMINAL: "npm install body-parser" */
+const { PythonShell } = require('python-shell'); /* TYPE IN TERMINAL: "npm install python-shell" */
+const path = require('path');
+const urlElectron = path.join(__dirname, "src/index.html");
+
+// Maak een Express-app
+const server = express();
+server.use(bodyParser.urlencoded({ extended: true }));
+
+// Definieer een route voor form POST verzoeken
+server.post('/submit-form', (req, res) => {
+ const { plant_naam, plantensoort } = req.body; // Verkrijg de plant_naam uit het formulier
+ const plant_geteelt = req.body.plant_geteelt == 'true' ? 'true' : 'false'; // Zorgt dat de string "true" herkent wordt
+
+ let options = {
+ mode: 'text',
+ args: [plant_naam, plantensoort, plant_geteelt], // Zet hier een variable bij om de data toe te voegen aan de databas
+ };
+
+/*Om python te gebruiken*/
+// ipcMain.on('request-update-temp', (event, args) => {
+// let options = {
+// mode: 'text',
+// scriptPath: 'path/to/your/python/script',
+// args: args
+// };
+
+// PythonShell.run('calculate.py', options, (err, results) => {
+// if (err) {
+// console.error('Error running python script', err);
+// event.reply('update-temp-result', 'error');
+// } else {
+// console.log('Python script results:', results);
+// event.reply('update-temp-result', results[0]); // Verstuur het resultaat terug naar de renderer proces
+// }
+// });
+// });
+
+// En dan in je renderer proces, stuur je een bericht om de update te verzoeken
+ipcRenderer.send('request-update-temp', [/* hier kunnen argumenten komen die je Python script nodig heeft */]);
+
+});
+
+// Start de server voor verbinding met de database
+const PORT = 3000;
+server.listen(PORT, () => {
+ console.log(`Server luistert op port ${PORT}`);
+});
+
+// Maak de Electron applicatie aan met bijbehorende waardes
+function createWindow() {
+ const mainWindow = new BrowserWindow({
+ width: 1280,
+ height: 800,
+ frame: false,
+ webPreferences: {
+ nodeIntegration: true,
+ contextIsolation: false
+ }
+ });
+
+ mainWindow.loadURL(urlElectron);
+
+ /*Is om het Python script te kunnen gebruiken*/
+ ipcMain.on('run-python-script', (event, args) => {
+ let options = {
+ mode: 'text',
+ args: args
+ };
+
+ PythonShell.run('../src/py/calculate.py', options, (err, results) => {
+ if (err)
+ {
+ console.error('Error running python script', err);
+ event.reply('python-script-response', 'error');
+ }
+ else
+ {
+ console.log('Python script results:', results);
+ event.reply('python-script-response', results);
+ }
+ });
+});
+}
+
+app.whenReady().then(createWindow);
+
+// Functionaliteit voor het openen en sluiten van de app
+app.on('window-all-closed', () => {
+ if (process.platform !== 'darwin') {
+ app.quit();
+ }
+});
+
+app.on('activate', () => {
+ if (BrowserWindow.getAllWindows().length === 0) {
+ createWindow();
+ }
+});
\ No newline at end of file
diff --git a/goodGarden.sql b/goodGarden.sql
deleted file mode 100644
index de6d9d1..0000000
--- a/goodGarden.sql
+++ /dev/null
@@ -1,16 +0,0 @@
-DROP DATABASE IF EXISTS goodgarden;
-CREATE DATABASE goodgarden;
-
-CREATE TABLE goodgarden.sensor_data (
- id INT UNSIGNED NOT NULL AUTO_INCREMENT,
- timestamp INT,
- gateway_receive_time VARCHAR(50),
- device INT,
- value DECIMAL(10, 5),
- PRIMARY KEY (id)
-);
-
-Invoegen van gegevens in de 'sensor_data'-tabel
-INSERT INTO goodgarden.sensor_data (timestamp, gateway_receive_time, device, value)
-VALUES (1707295162, '2024-02-07T08:39:22Z', 256, 4.107448101043701),
- (1707261284, '2024-02-06T23:14:44Z', 322, 4.111111164093018);
diff --git a/main.js b/main.js
deleted file mode 100644
index 724c226..0000000
--- a/main.js
+++ /dev/null
@@ -1,39 +0,0 @@
-const { app, BrowserWindow, nativeImage, shell } = require("electron");
-// const screen = require("electron").screen;
-const path = require("path");
-
-let mainWindow;
-
-function createWindow()
-{
- // const iconPath = path.join(__dirname, "images/logo.png");
- // const icon = nativeImage.createFromPath(iconPath);
- const urlElectron = path.join(__dirname, "src/main.html");
-
- mainWindow = new BrowserWindow(
- {
- width: 1000,
- height: 650,
- webPreferences:
- {
- nodeIntegration: true,
- },
- resizable: false,
- frame: true,
- // icon: icon,
- alwaysOnTop: true,
- // backgroundColor: "green"
- });
-
- // const { width, height } = screen.getPrimaryDisplay().workAreaSize;
- // mainWindow.setPosition(width - 450, height - 500);
-
- mainWindow.loadURL(urlElectron);
-
- // mainWindow.on("closed", function ()
- // {
- // mainWindow = null;
- // });
-}
-
-app.on("ready", createWindow);
\ No newline at end of file
diff --git a/package-lock.json b/package-lock.json
index 6071e6d..1b052bb 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,14 +1,18 @@
{
- "name": "app",
+ "name": "goodgarden",
"version": "1.0.0",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
- "name": "app",
+ "name": "goodgarden",
"license": "ISC",
"dependencies": {
- "elctron": "^0.0.1-security"
+ "body-parser": "^1.20.2",
+ "elctron": "^0.0.1-security",
+ "express": "^4.18.2",
+ "mysql2": "^3.9.1",
+ "python-shell": "^5.0.0"
},
"devDependencies": {
"electron": "^23.3.13"
@@ -264,28 +268,6 @@
"node": ">=6 <7 || >=8"
}
},
- "node_modules/@electron/get/node_modules/function-bind": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
- "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==",
- "dev": true,
- "optional": true
- },
- "node_modules/@electron/get/node_modules/get-intrinsic": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.0.tgz",
- "integrity": "sha512-L049y6nFOuom5wGyRc3/gdTLO94dySVKRACj1RmJZBQXlbTMhtNIgkWkUHq+jYmZvKf14EW1EoJnnjbmoHij0Q==",
- "dev": true,
- "optional": true,
- "dependencies": {
- "function-bind": "^1.1.1",
- "has": "^1.0.3",
- "has-symbols": "^1.0.3"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
"node_modules/@electron/get/node_modules/get-stream": {
"version": "5.2.0",
"resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz",
@@ -382,45 +364,6 @@
"integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==",
"dev": true
},
- "node_modules/@electron/get/node_modules/has": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
- "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
- "dev": true,
- "optional": true,
- "dependencies": {
- "function-bind": "^1.1.1"
- },
- "engines": {
- "node": ">= 0.4.0"
- }
- },
- "node_modules/@electron/get/node_modules/has-property-descriptors": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz",
- "integrity": "sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==",
- "dev": true,
- "optional": true,
- "dependencies": {
- "get-intrinsic": "^1.1.1"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/@electron/get/node_modules/has-symbols": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz",
- "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==",
- "dev": true,
- "optional": true,
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
"node_modules/@electron/get/node_modules/http-cache-semantics": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz",
@@ -726,6 +669,169 @@
"integrity": "sha512-l0/3XZ153UTlNOnZK8xSNoJlQda9/WnYgiTdcKKPJSZjdjI9MU+A9oMXOesAWLSnqAaaJhj3qfQsU07Dr8OUwg==",
"dev": true
},
+ "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==",
+ "dependencies": {
+ "mime-types": "~2.1.34",
+ "negotiator": "0.6.3"
+ },
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "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=="
+ },
+ "node_modules/body-parser": {
+ "version": "1.20.2",
+ "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.2.tgz",
+ "integrity": "sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==",
+ "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.0",
+ "iconv-lite": "0.4.24",
+ "on-finished": "2.4.1",
+ "qs": "6.11.0",
+ "raw-body": "2.5.2",
+ "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/iconv-lite": {
+ "version": "0.4.24",
+ "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
+ "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
+ "dependencies": {
+ "safer-buffer": ">= 2.1.2 < 3"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/bytes": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz",
+ "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==",
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/call-bind": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz",
+ "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==",
+ "dependencies": {
+ "es-define-property": "^1.0.0",
+ "es-errors": "^1.3.0",
+ "function-bind": "^1.1.2",
+ "get-intrinsic": "^1.2.4",
+ "set-function-length": "^1.2.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "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==",
+ "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==",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/cookie": {
+ "version": "0.5.0",
+ "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz",
+ "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/cookie-signature": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
+ "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ=="
+ },
+ "node_modules/debug": {
+ "version": "2.6.9",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+ "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+ "dependencies": {
+ "ms": "2.0.0"
+ }
+ },
+ "node_modules/define-data-property": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz",
+ "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==",
+ "dependencies": {
+ "es-define-property": "^1.0.0",
+ "es-errors": "^1.3.0",
+ "gopd": "^1.0.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/denque": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/denque/-/denque-2.1.0.tgz",
+ "integrity": "sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==",
+ "engines": {
+ "node": ">=0.10"
+ }
+ },
+ "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==",
+ "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==",
+ "engines": {
+ "node": ">= 0.8",
+ "npm": "1.2.8000 || >= 1.4.16"
+ }
+ },
+ "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=="
+ },
"node_modules/elctron": {
"version": "0.0.1-security",
"resolved": "https://registry.npmjs.org/elctron/-/elctron-0.0.1-security.tgz",
@@ -749,6 +855,135 @@
"node": ">= 12.20.55"
}
},
+ "node_modules/encodeurl": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
+ "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==",
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/es-define-property": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz",
+ "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==",
+ "dependencies": {
+ "get-intrinsic": "^1.2.4"
+ },
+ "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==",
+ "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=="
+ },
+ "node_modules/etag": {
+ "version": "1.8.1",
+ "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",
+ "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/express": {
+ "version": "4.18.2",
+ "resolved": "https://registry.npmjs.org/express/-/express-4.18.2.tgz",
+ "integrity": "sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ==",
+ "dependencies": {
+ "accepts": "~1.3.8",
+ "array-flatten": "1.1.1",
+ "body-parser": "1.20.1",
+ "content-disposition": "0.5.4",
+ "content-type": "~1.0.4",
+ "cookie": "0.5.0",
+ "cookie-signature": "1.0.6",
+ "debug": "2.6.9",
+ "depd": "2.0.0",
+ "encodeurl": "~1.0.2",
+ "escape-html": "~1.0.3",
+ "etag": "~1.8.1",
+ "finalhandler": "1.2.0",
+ "fresh": "0.5.2",
+ "http-errors": "2.0.0",
+ "merge-descriptors": "1.0.1",
+ "methods": "~1.1.2",
+ "on-finished": "2.4.1",
+ "parseurl": "~1.3.3",
+ "path-to-regexp": "0.1.7",
+ "proxy-addr": "~2.0.7",
+ "qs": "6.11.0",
+ "range-parser": "~1.2.1",
+ "safe-buffer": "5.2.1",
+ "send": "0.18.0",
+ "serve-static": "1.15.0",
+ "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"
+ }
+ },
+ "node_modules/express/node_modules/body-parser": {
+ "version": "1.20.1",
+ "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.1.tgz",
+ "integrity": "sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==",
+ "dependencies": {
+ "bytes": "3.1.2",
+ "content-type": "~1.0.4",
+ "debug": "2.6.9",
+ "depd": "2.0.0",
+ "destroy": "1.2.0",
+ "http-errors": "2.0.0",
+ "iconv-lite": "0.4.24",
+ "on-finished": "2.4.1",
+ "qs": "6.11.0",
+ "raw-body": "2.5.1",
+ "type-is": "~1.6.18",
+ "unpipe": "1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.8",
+ "npm": "1.2.8000 || >= 1.4.16"
+ }
+ },
+ "node_modules/express/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==",
+ "dependencies": {
+ "safer-buffer": ">= 2.1.2 < 3"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/express/node_modules/raw-body": {
+ "version": "2.5.1",
+ "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz",
+ "integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==",
+ "dependencies": {
+ "bytes": "3.1.2",
+ "http-errors": "2.0.0",
+ "iconv-lite": "0.4.24",
+ "unpipe": "1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
"node_modules/extract-zip": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz",
@@ -884,6 +1119,554 @@
"buffer-crc32": "~0.2.3",
"fd-slicer": "~1.1.0"
}
+ },
+ "node_modules/finalhandler": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz",
+ "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==",
+ "dependencies": {
+ "debug": "2.6.9",
+ "encodeurl": "~1.0.2",
+ "escape-html": "~1.0.3",
+ "on-finished": "2.4.1",
+ "parseurl": "~1.3.3",
+ "statuses": "2.0.1",
+ "unpipe": "~1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/forwarded": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz",
+ "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==",
+ "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==",
+ "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==",
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/generate-function": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.3.1.tgz",
+ "integrity": "sha512-eeB5GfMNeevm/GRYq20ShmsaGcmI81kIX2K9XQx5miC8KdHaC6Jm0qQ8ZNeGOi7wYB8OsdxKs+Y2oVuTFuVwKQ==",
+ "dependencies": {
+ "is-property": "^1.0.2"
+ }
+ },
+ "node_modules/get-intrinsic": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz",
+ "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==",
+ "dependencies": {
+ "es-errors": "^1.3.0",
+ "function-bind": "^1.1.2",
+ "has-proto": "^1.0.1",
+ "has-symbols": "^1.0.3",
+ "hasown": "^2.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/gopd": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz",
+ "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==",
+ "dependencies": {
+ "get-intrinsic": "^1.1.3"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/has-property-descriptors": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz",
+ "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==",
+ "dependencies": {
+ "es-define-property": "^1.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/has-proto": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz",
+ "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==",
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/has-symbols": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz",
+ "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==",
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/hasown": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.1.tgz",
+ "integrity": "sha512-1/th4MHjnwncwXsIW6QMzlvYL9kG5e/CpVvLRZe4XPa8TOUNbCELqmvhDmnkNsAjwaG4+I8gJJL0JBvTTLO9qA==",
+ "dependencies": {
+ "function-bind": "^1.1.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/http-errors": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz",
+ "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==",
+ "dependencies": {
+ "depd": "2.0.0",
+ "inherits": "2.0.4",
+ "setprototypeof": "1.2.0",
+ "statuses": "2.0.1",
+ "toidentifier": "1.0.1"
+ },
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/iconv-lite": {
+ "version": "0.6.3",
+ "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz",
+ "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==",
+ "dependencies": {
+ "safer-buffer": ">= 2.1.2 < 3.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/inherits": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
+ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
+ },
+ "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==",
+ "engines": {
+ "node": ">= 0.10"
+ }
+ },
+ "node_modules/is-property": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz",
+ "integrity": "sha512-Ks/IoX00TtClbGQr4TWXemAnktAQvYB7HzcCxDGqEZU6oCmb2INHuOoKxbtR+HFkmYWBKv/dOZtGRiAjDhj92g=="
+ },
+ "node_modules/long": {
+ "version": "5.2.3",
+ "resolved": "https://registry.npmjs.org/long/-/long-5.2.3.tgz",
+ "integrity": "sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q=="
+ },
+ "node_modules/lru-cache": {
+ "version": "8.0.5",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-8.0.5.tgz",
+ "integrity": "sha512-MhWWlVnuab1RG5/zMRRcVGXZLCXrZTgfwMikgzCegsPnG62yDQo5JnqKkrK4jO5iKqDAZGItAqN5CtKBCBWRUA==",
+ "engines": {
+ "node": ">=16.14"
+ }
+ },
+ "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==",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/merge-descriptors": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz",
+ "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w=="
+ },
+ "node_modules/methods": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz",
+ "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==",
+ "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==",
+ "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==",
+ "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==",
+ "dependencies": {
+ "mime-db": "1.52.0"
+ },
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/ms": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+ "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="
+ },
+ "node_modules/mysql2": {
+ "version": "3.9.1",
+ "resolved": "https://registry.npmjs.org/mysql2/-/mysql2-3.9.1.tgz",
+ "integrity": "sha512-3njoWAAhGBYy0tWBabqUQcLtczZUxrmmtc2vszQUekg3kTJyZ5/IeLC3Fo04u6y6Iy5Sba7pIIa2P/gs8D3ZeQ==",
+ "dependencies": {
+ "denque": "^2.1.0",
+ "generate-function": "^2.3.1",
+ "iconv-lite": "^0.6.3",
+ "long": "^5.2.1",
+ "lru-cache": "^8.0.0",
+ "named-placeholders": "^1.1.3",
+ "seq-queue": "^0.0.5",
+ "sqlstring": "^2.3.2"
+ },
+ "engines": {
+ "node": ">= 8.0"
+ }
+ },
+ "node_modules/named-placeholders": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/named-placeholders/-/named-placeholders-1.1.3.tgz",
+ "integrity": "sha512-eLoBxg6wE/rZkJPhU/xRX1WTpkFEwDJEN96oxFrTsqBdbT5ec295Q+CoHrL9IT0DipqKhmGcaZmwOt8OON5x1w==",
+ "dependencies": {
+ "lru-cache": "^7.14.1"
+ },
+ "engines": {
+ "node": ">=12.0.0"
+ }
+ },
+ "node_modules/named-placeholders/node_modules/lru-cache": {
+ "version": "7.18.3",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz",
+ "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==",
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "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==",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/object-inspect": {
+ "version": "1.13.1",
+ "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz",
+ "integrity": "sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==",
+ "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==",
+ "dependencies": {
+ "ee-first": "1.1.1"
+ },
+ "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==",
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/path-to-regexp": {
+ "version": "0.1.7",
+ "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz",
+ "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ=="
+ },
+ "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==",
+ "dependencies": {
+ "forwarded": "0.2.0",
+ "ipaddr.js": "1.9.1"
+ },
+ "engines": {
+ "node": ">= 0.10"
+ }
+ },
+ "node_modules/python-shell": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/python-shell/-/python-shell-5.0.0.tgz",
+ "integrity": "sha512-RUOOOjHLhgR1MIQrCtnEqz/HJ1RMZBIN+REnpSUrfft2bXqXy69fwJASVziWExfFXsR1bCY0TznnHooNsCo0/w==",
+ "engines": {
+ "node": ">=0.10"
+ }
+ },
+ "node_modules/qs": {
+ "version": "6.11.0",
+ "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz",
+ "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==",
+ "dependencies": {
+ "side-channel": "^1.0.4"
+ },
+ "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==",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/raw-body": {
+ "version": "2.5.2",
+ "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz",
+ "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==",
+ "dependencies": {
+ "bytes": "3.1.2",
+ "http-errors": "2.0.0",
+ "iconv-lite": "0.4.24",
+ "unpipe": "1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/raw-body/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==",
+ "dependencies": {
+ "safer-buffer": ">= 2.1.2 < 3"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "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"
+ }
+ ]
+ },
+ "node_modules/safer-buffer": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
+ "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
+ },
+ "node_modules/send": {
+ "version": "0.18.0",
+ "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz",
+ "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==",
+ "dependencies": {
+ "debug": "2.6.9",
+ "depd": "2.0.0",
+ "destroy": "1.2.0",
+ "encodeurl": "~1.0.2",
+ "escape-html": "~1.0.3",
+ "etag": "~1.8.1",
+ "fresh": "0.5.2",
+ "http-errors": "2.0.0",
+ "mime": "1.6.0",
+ "ms": "2.1.3",
+ "on-finished": "2.4.1",
+ "range-parser": "~1.2.1",
+ "statuses": "2.0.1"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "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=="
+ },
+ "node_modules/seq-queue": {
+ "version": "0.0.5",
+ "resolved": "https://registry.npmjs.org/seq-queue/-/seq-queue-0.0.5.tgz",
+ "integrity": "sha512-hr3Wtp/GZIc/6DAGPDcV4/9WoZhjrkXsi5B/07QgX8tsdc6ilr7BFM6PM6rbdAX1kFSDYeZGLipIZZKyQP0O5Q=="
+ },
+ "node_modules/serve-static": {
+ "version": "1.15.0",
+ "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz",
+ "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==",
+ "dependencies": {
+ "encodeurl": "~1.0.2",
+ "escape-html": "~1.0.3",
+ "parseurl": "~1.3.3",
+ "send": "0.18.0"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/set-function-length": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.1.tgz",
+ "integrity": "sha512-j4t6ccc+VsKwYHso+kElc5neZpjtq9EnRICFZtWyBsLojhmeF/ZBd/elqm22WJh/BziDe/SBiOeAt0m2mfLD0g==",
+ "dependencies": {
+ "define-data-property": "^1.1.2",
+ "es-errors": "^1.3.0",
+ "function-bind": "^1.1.2",
+ "get-intrinsic": "^1.2.3",
+ "gopd": "^1.0.1",
+ "has-property-descriptors": "^1.0.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/setprototypeof": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz",
+ "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw=="
+ },
+ "node_modules/side-channel": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.5.tgz",
+ "integrity": "sha512-QcgiIWV4WV7qWExbN5llt6frQB/lBven9pqliLXfGPB+K9ZYXxDozp0wLkHS24kWCm+6YXH/f0HhnObZnZOBnQ==",
+ "dependencies": {
+ "call-bind": "^1.0.6",
+ "es-errors": "^1.3.0",
+ "get-intrinsic": "^1.2.4",
+ "object-inspect": "^1.13.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/sqlstring": {
+ "version": "2.3.3",
+ "resolved": "https://registry.npmjs.org/sqlstring/-/sqlstring-2.3.3.tgz",
+ "integrity": "sha512-qC9iz2FlN7DQl3+wjwn3802RTyjCx7sDvfQEXchwa6CWOx07/WVfh91gBmQ9fahw8snwGEWU3xGzOt4tFyHLxg==",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/statuses": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz",
+ "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==",
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "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==",
+ "engines": {
+ "node": ">=0.6"
+ }
+ },
+ "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==",
+ "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==",
+ "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==",
+ "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==",
+ "engines": {
+ "node": ">= 0.8"
+ }
}
},
"dependencies": {
@@ -1075,25 +1858,6 @@
"universalify": "^0.1.0"
}
},
- "function-bind": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
- "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==",
- "dev": true,
- "optional": true
- },
- "get-intrinsic": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.0.tgz",
- "integrity": "sha512-L049y6nFOuom5wGyRc3/gdTLO94dySVKRACj1RmJZBQXlbTMhtNIgkWkUHq+jYmZvKf14EW1EoJnnjbmoHij0Q==",
- "dev": true,
- "optional": true,
- "requires": {
- "function-bind": "^1.1.1",
- "has": "^1.0.3",
- "has-symbols": "^1.0.3"
- }
- },
"get-stream": {
"version": "5.2.0",
"resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz",
@@ -1165,33 +1929,6 @@
"integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==",
"dev": true
},
- "has": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
- "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
- "dev": true,
- "optional": true,
- "requires": {
- "function-bind": "^1.1.1"
- }
- },
- "has-property-descriptors": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz",
- "integrity": "sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==",
- "dev": true,
- "optional": true,
- "requires": {
- "get-intrinsic": "^1.1.1"
- }
- },
- "has-symbols": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz",
- "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==",
- "dev": true,
- "optional": true
- },
"http-cache-semantics": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz",
@@ -1436,6 +2173,127 @@
"integrity": "sha512-l0/3XZ153UTlNOnZK8xSNoJlQda9/WnYgiTdcKKPJSZjdjI9MU+A9oMXOesAWLSnqAaaJhj3qfQsU07Dr8OUwg==",
"dev": true
},
+ "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==",
+ "requires": {
+ "mime-types": "~2.1.34",
+ "negotiator": "0.6.3"
+ }
+ },
+ "array-flatten": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
+ "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg=="
+ },
+ "body-parser": {
+ "version": "1.20.2",
+ "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.2.tgz",
+ "integrity": "sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==",
+ "requires": {
+ "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.0",
+ "iconv-lite": "0.4.24",
+ "on-finished": "2.4.1",
+ "qs": "6.11.0",
+ "raw-body": "2.5.2",
+ "type-is": "~1.6.18",
+ "unpipe": "1.0.0"
+ },
+ "dependencies": {
+ "iconv-lite": {
+ "version": "0.4.24",
+ "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
+ "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
+ "requires": {
+ "safer-buffer": ">= 2.1.2 < 3"
+ }
+ }
+ }
+ },
+ "bytes": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz",
+ "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg=="
+ },
+ "call-bind": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz",
+ "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==",
+ "requires": {
+ "es-define-property": "^1.0.0",
+ "es-errors": "^1.3.0",
+ "function-bind": "^1.1.2",
+ "get-intrinsic": "^1.2.4",
+ "set-function-length": "^1.2.1"
+ }
+ },
+ "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==",
+ "requires": {
+ "safe-buffer": "5.2.1"
+ }
+ },
+ "content-type": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz",
+ "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA=="
+ },
+ "cookie": {
+ "version": "0.5.0",
+ "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz",
+ "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw=="
+ },
+ "cookie-signature": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
+ "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ=="
+ },
+ "debug": {
+ "version": "2.6.9",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+ "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+ "requires": {
+ "ms": "2.0.0"
+ }
+ },
+ "define-data-property": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz",
+ "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==",
+ "requires": {
+ "es-define-property": "^1.0.0",
+ "es-errors": "^1.3.0",
+ "gopd": "^1.0.1"
+ }
+ },
+ "denque": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/denque/-/denque-2.1.0.tgz",
+ "integrity": "sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw=="
+ },
+ "depd": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
+ "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw=="
+ },
+ "destroy": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz",
+ "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg=="
+ },
+ "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=="
+ },
"elctron": {
"version": "0.0.1-security",
"resolved": "https://registry.npmjs.org/elctron/-/elctron-0.0.1-security.tgz",
@@ -1452,6 +2310,112 @@
"extract-zip": "^2.0.1"
}
},
+ "encodeurl": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
+ "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w=="
+ },
+ "es-define-property": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz",
+ "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==",
+ "requires": {
+ "get-intrinsic": "^1.2.4"
+ }
+ },
+ "es-errors": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz",
+ "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw=="
+ },
+ "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=="
+ },
+ "etag": {
+ "version": "1.8.1",
+ "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",
+ "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg=="
+ },
+ "express": {
+ "version": "4.18.2",
+ "resolved": "https://registry.npmjs.org/express/-/express-4.18.2.tgz",
+ "integrity": "sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ==",
+ "requires": {
+ "accepts": "~1.3.8",
+ "array-flatten": "1.1.1",
+ "body-parser": "1.20.1",
+ "content-disposition": "0.5.4",
+ "content-type": "~1.0.4",
+ "cookie": "0.5.0",
+ "cookie-signature": "1.0.6",
+ "debug": "2.6.9",
+ "depd": "2.0.0",
+ "encodeurl": "~1.0.2",
+ "escape-html": "~1.0.3",
+ "etag": "~1.8.1",
+ "finalhandler": "1.2.0",
+ "fresh": "0.5.2",
+ "http-errors": "2.0.0",
+ "merge-descriptors": "1.0.1",
+ "methods": "~1.1.2",
+ "on-finished": "2.4.1",
+ "parseurl": "~1.3.3",
+ "path-to-regexp": "0.1.7",
+ "proxy-addr": "~2.0.7",
+ "qs": "6.11.0",
+ "range-parser": "~1.2.1",
+ "safe-buffer": "5.2.1",
+ "send": "0.18.0",
+ "serve-static": "1.15.0",
+ "setprototypeof": "1.2.0",
+ "statuses": "2.0.1",
+ "type-is": "~1.6.18",
+ "utils-merge": "1.0.1",
+ "vary": "~1.1.2"
+ },
+ "dependencies": {
+ "body-parser": {
+ "version": "1.20.1",
+ "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.1.tgz",
+ "integrity": "sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==",
+ "requires": {
+ "bytes": "3.1.2",
+ "content-type": "~1.0.4",
+ "debug": "2.6.9",
+ "depd": "2.0.0",
+ "destroy": "1.2.0",
+ "http-errors": "2.0.0",
+ "iconv-lite": "0.4.24",
+ "on-finished": "2.4.1",
+ "qs": "6.11.0",
+ "raw-body": "2.5.1",
+ "type-is": "~1.6.18",
+ "unpipe": "1.0.0"
+ }
+ },
+ "iconv-lite": {
+ "version": "0.4.24",
+ "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
+ "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
+ "requires": {
+ "safer-buffer": ">= 2.1.2 < 3"
+ }
+ },
+ "raw-body": {
+ "version": "2.5.1",
+ "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz",
+ "integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==",
+ "requires": {
+ "bytes": "3.1.2",
+ "http-errors": "2.0.0",
+ "iconv-lite": "0.4.24",
+ "unpipe": "1.0.0"
+ }
+ }
+ }
+ },
"extract-zip": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz",
@@ -1564,6 +2528,399 @@
}
}
}
+ },
+ "finalhandler": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz",
+ "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==",
+ "requires": {
+ "debug": "2.6.9",
+ "encodeurl": "~1.0.2",
+ "escape-html": "~1.0.3",
+ "on-finished": "2.4.1",
+ "parseurl": "~1.3.3",
+ "statuses": "2.0.1",
+ "unpipe": "~1.0.0"
+ }
+ },
+ "forwarded": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz",
+ "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow=="
+ },
+ "fresh": {
+ "version": "0.5.2",
+ "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz",
+ "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q=="
+ },
+ "function-bind": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
+ "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA=="
+ },
+ "generate-function": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.3.1.tgz",
+ "integrity": "sha512-eeB5GfMNeevm/GRYq20ShmsaGcmI81kIX2K9XQx5miC8KdHaC6Jm0qQ8ZNeGOi7wYB8OsdxKs+Y2oVuTFuVwKQ==",
+ "requires": {
+ "is-property": "^1.0.2"
+ }
+ },
+ "get-intrinsic": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz",
+ "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==",
+ "requires": {
+ "es-errors": "^1.3.0",
+ "function-bind": "^1.1.2",
+ "has-proto": "^1.0.1",
+ "has-symbols": "^1.0.3",
+ "hasown": "^2.0.0"
+ }
+ },
+ "gopd": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz",
+ "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==",
+ "requires": {
+ "get-intrinsic": "^1.1.3"
+ }
+ },
+ "has-property-descriptors": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz",
+ "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==",
+ "requires": {
+ "es-define-property": "^1.0.0"
+ }
+ },
+ "has-proto": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz",
+ "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg=="
+ },
+ "has-symbols": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz",
+ "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A=="
+ },
+ "hasown": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.1.tgz",
+ "integrity": "sha512-1/th4MHjnwncwXsIW6QMzlvYL9kG5e/CpVvLRZe4XPa8TOUNbCELqmvhDmnkNsAjwaG4+I8gJJL0JBvTTLO9qA==",
+ "requires": {
+ "function-bind": "^1.1.2"
+ }
+ },
+ "http-errors": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz",
+ "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==",
+ "requires": {
+ "depd": "2.0.0",
+ "inherits": "2.0.4",
+ "setprototypeof": "1.2.0",
+ "statuses": "2.0.1",
+ "toidentifier": "1.0.1"
+ }
+ },
+ "iconv-lite": {
+ "version": "0.6.3",
+ "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz",
+ "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==",
+ "requires": {
+ "safer-buffer": ">= 2.1.2 < 3.0.0"
+ }
+ },
+ "inherits": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
+ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
+ },
+ "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=="
+ },
+ "is-property": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz",
+ "integrity": "sha512-Ks/IoX00TtClbGQr4TWXemAnktAQvYB7HzcCxDGqEZU6oCmb2INHuOoKxbtR+HFkmYWBKv/dOZtGRiAjDhj92g=="
+ },
+ "long": {
+ "version": "5.2.3",
+ "resolved": "https://registry.npmjs.org/long/-/long-5.2.3.tgz",
+ "integrity": "sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q=="
+ },
+ "lru-cache": {
+ "version": "8.0.5",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-8.0.5.tgz",
+ "integrity": "sha512-MhWWlVnuab1RG5/zMRRcVGXZLCXrZTgfwMikgzCegsPnG62yDQo5JnqKkrK4jO5iKqDAZGItAqN5CtKBCBWRUA=="
+ },
+ "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=="
+ },
+ "merge-descriptors": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz",
+ "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w=="
+ },
+ "methods": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz",
+ "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w=="
+ },
+ "mime": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz",
+ "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg=="
+ },
+ "mime-db": {
+ "version": "1.52.0",
+ "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
+ "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg=="
+ },
+ "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==",
+ "requires": {
+ "mime-db": "1.52.0"
+ }
+ },
+ "ms": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+ "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="
+ },
+ "mysql2": {
+ "version": "3.9.1",
+ "resolved": "https://registry.npmjs.org/mysql2/-/mysql2-3.9.1.tgz",
+ "integrity": "sha512-3njoWAAhGBYy0tWBabqUQcLtczZUxrmmtc2vszQUekg3kTJyZ5/IeLC3Fo04u6y6Iy5Sba7pIIa2P/gs8D3ZeQ==",
+ "requires": {
+ "denque": "^2.1.0",
+ "generate-function": "^2.3.1",
+ "iconv-lite": "^0.6.3",
+ "long": "^5.2.1",
+ "lru-cache": "^8.0.0",
+ "named-placeholders": "^1.1.3",
+ "seq-queue": "^0.0.5",
+ "sqlstring": "^2.3.2"
+ }
+ },
+ "named-placeholders": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/named-placeholders/-/named-placeholders-1.1.3.tgz",
+ "integrity": "sha512-eLoBxg6wE/rZkJPhU/xRX1WTpkFEwDJEN96oxFrTsqBdbT5ec295Q+CoHrL9IT0DipqKhmGcaZmwOt8OON5x1w==",
+ "requires": {
+ "lru-cache": "^7.14.1"
+ },
+ "dependencies": {
+ "lru-cache": {
+ "version": "7.18.3",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz",
+ "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA=="
+ }
+ }
+ },
+ "negotiator": {
+ "version": "0.6.3",
+ "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz",
+ "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg=="
+ },
+ "object-inspect": {
+ "version": "1.13.1",
+ "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz",
+ "integrity": "sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ=="
+ },
+ "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==",
+ "requires": {
+ "ee-first": "1.1.1"
+ }
+ },
+ "parseurl": {
+ "version": "1.3.3",
+ "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz",
+ "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ=="
+ },
+ "path-to-regexp": {
+ "version": "0.1.7",
+ "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz",
+ "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ=="
+ },
+ "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==",
+ "requires": {
+ "forwarded": "0.2.0",
+ "ipaddr.js": "1.9.1"
+ }
+ },
+ "python-shell": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/python-shell/-/python-shell-5.0.0.tgz",
+ "integrity": "sha512-RUOOOjHLhgR1MIQrCtnEqz/HJ1RMZBIN+REnpSUrfft2bXqXy69fwJASVziWExfFXsR1bCY0TznnHooNsCo0/w=="
+ },
+ "qs": {
+ "version": "6.11.0",
+ "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz",
+ "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==",
+ "requires": {
+ "side-channel": "^1.0.4"
+ }
+ },
+ "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=="
+ },
+ "raw-body": {
+ "version": "2.5.2",
+ "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz",
+ "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==",
+ "requires": {
+ "bytes": "3.1.2",
+ "http-errors": "2.0.0",
+ "iconv-lite": "0.4.24",
+ "unpipe": "1.0.0"
+ },
+ "dependencies": {
+ "iconv-lite": {
+ "version": "0.4.24",
+ "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
+ "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
+ "requires": {
+ "safer-buffer": ">= 2.1.2 < 3"
+ }
+ }
+ }
+ },
+ "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=="
+ },
+ "safer-buffer": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
+ "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
+ },
+ "send": {
+ "version": "0.18.0",
+ "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz",
+ "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==",
+ "requires": {
+ "debug": "2.6.9",
+ "depd": "2.0.0",
+ "destroy": "1.2.0",
+ "encodeurl": "~1.0.2",
+ "escape-html": "~1.0.3",
+ "etag": "~1.8.1",
+ "fresh": "0.5.2",
+ "http-errors": "2.0.0",
+ "mime": "1.6.0",
+ "ms": "2.1.3",
+ "on-finished": "2.4.1",
+ "range-parser": "~1.2.1",
+ "statuses": "2.0.1"
+ },
+ "dependencies": {
+ "ms": {
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
+ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="
+ }
+ }
+ },
+ "seq-queue": {
+ "version": "0.0.5",
+ "resolved": "https://registry.npmjs.org/seq-queue/-/seq-queue-0.0.5.tgz",
+ "integrity": "sha512-hr3Wtp/GZIc/6DAGPDcV4/9WoZhjrkXsi5B/07QgX8tsdc6ilr7BFM6PM6rbdAX1kFSDYeZGLipIZZKyQP0O5Q=="
+ },
+ "serve-static": {
+ "version": "1.15.0",
+ "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz",
+ "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==",
+ "requires": {
+ "encodeurl": "~1.0.2",
+ "escape-html": "~1.0.3",
+ "parseurl": "~1.3.3",
+ "send": "0.18.0"
+ }
+ },
+ "set-function-length": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.1.tgz",
+ "integrity": "sha512-j4t6ccc+VsKwYHso+kElc5neZpjtq9EnRICFZtWyBsLojhmeF/ZBd/elqm22WJh/BziDe/SBiOeAt0m2mfLD0g==",
+ "requires": {
+ "define-data-property": "^1.1.2",
+ "es-errors": "^1.3.0",
+ "function-bind": "^1.1.2",
+ "get-intrinsic": "^1.2.3",
+ "gopd": "^1.0.1",
+ "has-property-descriptors": "^1.0.1"
+ }
+ },
+ "setprototypeof": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz",
+ "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw=="
+ },
+ "side-channel": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.5.tgz",
+ "integrity": "sha512-QcgiIWV4WV7qWExbN5llt6frQB/lBven9pqliLXfGPB+K9ZYXxDozp0wLkHS24kWCm+6YXH/f0HhnObZnZOBnQ==",
+ "requires": {
+ "call-bind": "^1.0.6",
+ "es-errors": "^1.3.0",
+ "get-intrinsic": "^1.2.4",
+ "object-inspect": "^1.13.1"
+ }
+ },
+ "sqlstring": {
+ "version": "2.3.3",
+ "resolved": "https://registry.npmjs.org/sqlstring/-/sqlstring-2.3.3.tgz",
+ "integrity": "sha512-qC9iz2FlN7DQl3+wjwn3802RTyjCx7sDvfQEXchwa6CWOx07/WVfh91gBmQ9fahw8snwGEWU3xGzOt4tFyHLxg=="
+ },
+ "statuses": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz",
+ "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ=="
+ },
+ "toidentifier": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz",
+ "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA=="
+ },
+ "type-is": {
+ "version": "1.6.18",
+ "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz",
+ "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==",
+ "requires": {
+ "media-typer": "0.3.0",
+ "mime-types": "~2.1.24"
+ }
+ },
+ "unpipe": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
+ "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ=="
+ },
+ "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=="
+ },
+ "vary": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
+ "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg=="
}
}
}
diff --git a/package.json b/package.json
index b3664ac..9ad6306 100644
--- a/package.json
+++ b/package.json
@@ -1,10 +1,10 @@
{
"name": "goodgarden",
"description": "",
- "main": "main.js",
+ "main": "app.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
- "start": "electron main.js"
+ "start": "electron app.js"
},
"author": "",
"license": "ISC",
@@ -12,6 +12,10 @@
"electron": "^23.3.13"
},
"dependencies": {
- "elctron": "^0.0.1-security"
+ "body-parser": "^1.20.2",
+ "elctron": "^0.0.1-security",
+ "express": "^4.18.2",
+ "mysql2": "^3.9.1",
+ "python-shell": "^5.0.0"
}
}
diff --git a/script/DUMMY.json b/script/DUMMY.json
new file mode 100644
index 0000000..98acdaf
--- /dev/null
+++ b/script/DUMMY.json
@@ -0,0 +1,123 @@
+
+ // Deze spanningswaarden zijn relatief hoog, wat suggereert dat de batterijen van de sensoren goed opgeladen zijn. De meeste sensorapparaten gebruiken batterijen die een nominale spanning van ongeveer 3,7 volt hebben (typisch voor lithium-ion batterijen) en kunnen worden beschouwd als "volledig opgeladen" wanneer ze een spanning dicht bij of iets boven 4,1 volt bereiken
+ "battery_voltage_events": [
+ {
+ "timestamp": 1707825721,
+ "gateway_receive_time": "2024-02-13T12:02:01Z",
+ "device": 256,
+ "value": 4.098901271820068
+ // Volledig opgeladen: Rond 4.2 volt.
+ // Nominale spanning: Ongeveer 3.7 volt.
+ // Kritiek laag: Minder dan 3.0 volt.
+ },
+ {
+ "timestamp": 1707837460,
+ "gateway_receive_time": "2024-02-13T15:17:40Z",
+ "device": 322,
+ "value": 4.105006217956543
+ }
+ ],
+
+
+
+
+ "devices": [
+ {
+ "id": 256,
+ "serial_number": "0033889B1BAB1169",
+ "name": "firefly2_0051",
+ "label": "The Field",
+ "last_seen": 1707765066,
+ "last_battery_voltage": 4.09768009185791
+ },
+ {
+ "id": 322,
+ "serial_number": "006FE1FC316ED7D8",
+ "name": "firefly2_0111",
+ "label": "The Field",
+ "last_seen": 1707764966,
+ "last_battery_voltage": 4.107448101043701
+ }
+ ],
+
+
+
+
+
+ // Fotosyntese??? (zonlicht)
+ "par_events": [
+ {
+ "timestamp": 1707844638,
+ "gateway_receive_time": "2024-02-13T17:17:18Z",
+ "device": 322,
+ "value": 0.0
+ },
+ {
+ "timestamp": 1707851099,
+ "gateway_receive_time": "2024-02-13T19:04:59Z",
+ "device": 256,
+ "value": 0.0
+ }
+ ],
+
+
+
+
+ // Luchtvochtigheid
+ "relative_humidity_events": [
+ {
+ "timestamp": 1707844638,
+ "gateway_receive_time": "2024-02-13T17:17:18Z",
+ "device": 322,
+ "value": 71.08984375
+ },
+ {
+ "timestamp": 1707851099,
+ "gateway_receive_time": "2024-02-13T19:04:59Z",
+ "device": 256,
+ "value": 66.7294921875
+ }
+ ],
+
+
+
+
+
+ // De "soil_electric_conductivity_events" gegevens wijzen op metingen van de elektrische geleidbaarheid (EC) van de bodem, een indicator van de hoeveelheid oplosbare zouten of voedingsstoffen in de bodem. EC wordt gemeten in Siemens per meter (S/m) of, voor bodemmetingen, vaak in milliSiemens per centimeter (mS/cm). Een hogere EC-waarde duidt op een hogere concentratie van opgeloste zouten, wat belangrijk is voor het bepalen van de voedingsstatus van de bodem en het beheren van de bemesting voor optimale plantengroei.
+ "soil_electric_conductivity_events": [
+ {
+ "timestamp": 1707851215,
+ "gateway_receive_time": "2024-02-13T19:06:55Z",
+ "device": 322,
+ "value": 0.0
+ }
+ ],
+
+
+
+
+
+ // In de context van bodemmetingen, geeft deze waarde inzicht in het vochtgehalte van de bodem, omdat water een relatief hoge diëlektrische constante heeft in vergelijking met droge bodem of lucht.
+ "soil_relative_permittivity_events": [
+ {
+ "timestamp": 1707851215,
+ "gateway_receive_time": "2024-02-13T19:06:55Z",
+ "device": 322,
+ "value": 1.52
+ // Een waarde van 1.52 is relatief laag en suggereert dat de bodem droog kan zijn op het moment van meting. Ter referentie, de diëlektrische constante van lucht is ongeveer 1, terwijl water een diëlektrische constante heeft van ongeveer 80 bij kamertemperatuur.
+ }
+ ],
+
+
+
+ //De "soil_temperature_events" gegevens bevatten informatie over de temperatuur van de bodem op een specifiek tijdstip. De waarde geeft de temperatuur van de bodem aan in graden Celsius (°C).
+ "soil_temperature_events": [
+ {
+ "timestamp": 1707851215,
+ "gateway_receive_time": "2024-02-13T19:06:55Z",
+ "device": 322,
+ "value": 12.06
+ }
+ ]
+ }
+
\ No newline at end of file
diff --git a/script/battery_voltage_events.py b/script/battery_voltage_events.py
new file mode 100644
index 0000000..28b84f1
--- /dev/null
+++ b/script/battery_voltage_events.py
@@ -0,0 +1,418 @@
+# import requests #** TYPE IN TERMINAL: "pip install requests"
+# import time
+# import mysql.connector #** TYPE IN TERMINAL: "pip install mysql-connector-python"
+
+# # Import python db_connect.py script
+# from db_connect import database_connect
+
+# # Functie voor het aanmaken van gegevens in de database
+# def create_data(url, access_token, repeat_count=5):
+# for _ in range(repeat_count):
+# try:
+# headers = {
+# "Authorization": f"Token {access_token}"
+# }
+# response = requests.get(url, headers=headers)
+# response.raise_for_status()
+
+# data = response.json()
+
+# # print(f"Data from {url}:")
+# print(data)
+# insert_data(data)
+
+# except requests.exceptions.RequestException as e:
+# print(f"Error fetching data from {url}: {e}")
+
+# print("Waiting for the next create action...")
+# time.sleep(10)
+# # time.sleep(300)
+
+# # Functie voor het invoegen van gegevens in de database
+# def insert_data(data):
+# mydb = database_connect()
+# if mydb.is_connected():
+# mycursor = mydb.cursor()
+
+# insert_query = """
+# INSERT INTO goodgarden.battery_voltage_events (timestamp, gateway_receive_time, device, value)
+# VALUES (%s, %s, %s, %s)
+# """
+
+# for record in data['results']: # Pas dit aan op basis van de werkelijke structuur van de JSON
+
+# timestamp = record.get('timestamp', '')
+# gateway_receive_time = record.get('gateway_receive_time', '')
+# device = record.get('device', '')
+# value = record.get('value', '')
+
+# print(f"Inserting data: timestamp={timestamp}, gateway_receive_time={gateway_receive_time}, device={device}, value={value}")
+
+# # Voer de query uit
+# mycursor.execute(insert_query, (timestamp, gateway_receive_time, device, value))
+
+# # Bevestig de wijzigingen
+# mydb.commit()
+
+# # Sluit cursor en verbinding
+# mycursor.close()
+# mydb.close()
+
+# # Functie voor het lezen van gegevens uit de database
+# def read_data(url, access_token, repeat_count=5):
+# for _ in range(repeat_count):
+# try:
+# headers = {
+# "Authorization": f"Token {access_token}"
+# }
+# response = requests.get(url, headers=headers)
+# response.raise_for_status()
+
+# data = response.json()
+# print(f"Data from {url}:")
+# print(data)
+
+# except requests.exceptions.RequestException as e:
+# print(f"Error fetching data from {url}: {e}")
+
+# # Wacht een bepaalde tijd in secondes
+# print("Waiting for the next read action...")
+# time.sleep(300)
+
+# # Functie voor het bijwerken van gegevens in de database
+# def update_data(record_id, new_value):
+# try:
+# mydb = database_connect()
+
+# if mydb.is_connected():
+# mycursor = mydb.cursor()
+
+# # Controleer of het record bestaat voordat je het bijwerkt
+# mycursor.execute("SELECT * FROM goodgarden.battery_voltage_events WHERE id = %s", (record_id,))
+# existing_record = mycursor.fetchone()
+
+# if not existing_record:
+# print(f"Record with ID {record_id} not found. Update operation aborted.")
+# return
+
+# # Hier moet je de juiste kolomnamen aanpassen op basis van de structuur van je database
+# update_query = """
+# UPDATE goodgarden.battery_voltage_events
+# SET value = %s
+# WHERE id = %s
+# """
+
+# # Voer de query uit
+# print(f"Executing update query: {update_query}")
+# print(f"Updating record with ID {record_id} to new value: {new_value}")
+
+# mycursor.execute(update_query, (new_value, record_id)) # Provide the tuple with values here
+
+# # Bevestig de wijzigingen
+# mydb.commit()
+
+# print(f"Update executed. Rowcount: {mycursor.rowcount}")
+
+# except mysql.connector.Error as update_err:
+# print(f"Error updating data: {update_err}")
+# finally:
+# # Zorg ervoor dat je altijd de cursor en de databaseverbinding sluit
+# if 'mycursor' in locals() and mycursor is not None:
+# mycursor.close()
+# if 'mydb' in locals() and mydb.is_connected():
+# mydb.close()
+
+
+# # Functie voor het verwijderen van gegevens uit de database
+# def delete_data(record_id):
+# mydb = database_connect()
+# if mydb.is_connected():
+# mycursor = mydb.cursor()
+
+# # Hier moet je de juiste kolomnamen aanpassen op basis van de structuur van je database
+# delete_query = """
+# DELETE FROM goodgarden.battery_voltage_events
+# WHERE id = %s
+# """
+
+# # Voer de query uit
+# mycursor.execute(delete_query, (record_id,))
+
+# # Bevestig de wijzigingen
+# mydb.commit()
+
+# # Sluit cursor en verbinding
+# mycursor.close()
+# mydb.close()
+
+# print(f"Data with ID {record_id} deleted.")
+
+# if __name__ == "__main__":
+# url = "https://garden.inajar.nl/api/battery_voltage_events/?format=json"
+# access_token = "33bb3b42452306c58ecedc3c86cfae28ba22329c"
+
+# repeat_count = 10
+
+# operation_choice = input("Choose operation (C for Create, R for Read, U for Update, D for Delete): ").upper()
+
+# # Maak gegevens aan
+# if operation_choice == "C":
+# create_data(url, access_token, repeat_count)
+
+# # Lees gegevens
+# elif operation_choice == "R":
+# read_data(url, access_token, repeat_count)
+
+# # Update gegevens
+# elif operation_choice == "U":
+# record_id = int(input("Enter record ID to update: "))
+# new_value = input("Enter new value: ")
+# update_data(record_id, new_value)
+
+# # Verwijder gegevens
+# elif operation_choice == "D":
+# record_id = int(input("Enter record ID to delete: "))
+# delete_data(record_id)
+
+# else:
+# print("Invalid operation choice. Please choose C, R, U, or D.")
+
+import mysql.connector
+import requests
+from datetime import datetime, timezone, timedelta
+import time
+import os
+import paho.mqtt.client as mqtt
+from dotenv import load_dotenv
+
+# Functie om verbinding te maken met de database
+def database_connect():
+ return mysql.connector.connect(
+ host="localhost",
+ user="root",
+ password="",
+ database="goodgarden"
+ )
+
+def calculate_timestamp(gateway_receive_time):
+ # Converteer de stringrepresentatie naar een datetime-object in UTC
+ datetime_obj_utc = datetime.strptime(gateway_receive_time, "%Y-%m-%dT%H:%M:%SZ").replace(tzinfo=timezone.utc)
+
+ # Voeg het tijdsverschil van 1 uur toe voor de Nederlandse tijdzone (UTC+1)
+ datetime_obj_nl = datetime_obj_utc + timedelta(hours=0)
+
+ # Formateer het datetime-object als een leesbare datumstring
+ formatted_date = datetime_obj_nl.strftime("%Y-%m-%d %H:%M:%S")
+ return formatted_date
+
+# Functie voor het aanmaken van gegevens in de database
+def create_data(url, access_token, repeat_count=5):
+ for _ in range(repeat_count):
+ try:
+ headers = {"Authorization": f"Token {access_token}"}
+ response = requests.get(url, headers=headers)
+ response.raise_for_status()
+
+ data = response.json()
+ print(f"Data from {url}:\n")
+
+ # Check if data is a list (records directly under the root)
+ if isinstance(data, list):
+ records = data
+ elif isinstance(data, dict) and 'results' in data:
+ records = data['results']
+ else:
+ print(f"Unexpected data format received: {data}")
+ continue
+
+ for record in records:
+ # Now, record is assumed to be a dictionary
+ timestamp = record.get('timestamp', '')
+ gateway_receive_time = record.get('gateway_receive_time', '')
+ device = record.get('device', '')
+ value = record.get('value', '')
+
+ # Voeg de timestamp-berekening toe
+ calculated_timestamp = calculate_timestamp(gateway_receive_time)
+
+ print(f"\nInserted data: Timestamp: {calculated_timestamp}, Device: {device}, Battery Voltage: {value}V")
+ if float(value) < 3.0:
+ print("Waarschuwing: Batterijspanning is lager dan 3.0 volt. Opladen aanbevolen.\n")
+ # Controleer of de batterijspanning hoger is dan 4.2 volt en geef een melding
+ elif float(value) > 4.2:
+ print("Melding: Batterijspanning is hoger dan 4.2 volt. Batterij is vol.\n")
+ else:
+ print("Melding: Batterijspanning is binnen het gewenste bereik.\n\n")
+
+ # Insert data into the database
+ insert_data(record)
+
+ except requests.exceptions.RequestException as e:
+ print(f"Error fetching data from {url}: {e}")
+
+ print("Waiting for the next create action...\n")
+ time.sleep(2)
+
+# Functie voor het invoegen van gegevens in de database
+def insert_data(record):
+ mydb = database_connect()
+ if mydb.is_connected():
+ mycursor = mydb.cursor()
+
+ # Hier moet je de juiste kolomnamen en gegevensindeling aanpassen op basis van de API-respons
+ insert_query = """
+ INSERT INTO goodgarden.battery_voltage_events (timestamp, gateway_receive_time, device, value)
+ VALUES (%s, %s, %s, %s)
+ """
+ # Pas dit aan op basis van de werkelijke structuur van de JSON
+ timestamp = calculate_timestamp(record.get('gateway_receive_time', ''))
+ gateway_receive_time = record.get('gateway_receive_time', '')
+ device = record.get('device', '')
+ value = record.get('value', '')
+
+ print(f"Inserting data: timestamp={timestamp}, gateway_receive_time={gateway_receive_time}, device={device}, value={value}\n\n") # Print de ingevoerde gegevens
+
+ # Voer de query uit
+ mycursor.execute(insert_query, (timestamp, gateway_receive_time, device, value))
+
+ # Bevestig de wijzigingen
+ mydb.commit()
+
+ # Sluit cursor en verbinding
+ mycursor.close()
+ mydb.close()
+
+ print("Data inserted into the database.")
+
+# Functie voor het lezen van gegevens uit de database
+def read_data(url, access_token, repeat_count=5):
+ for _ in range(repeat_count):
+ try:
+ headers = {"Authorization": f"Token {access_token}"}
+ response = requests.get(url, headers=headers)
+ response.raise_for_status()
+
+ data = response.json()
+ print(f"Data from {url}:\n")
+
+ for record in data['results']:
+ timestamp = record.get('timestamp', '')
+ device = record.get('device', '')
+ value = record.get('value', '')
+ print(f"Timestamp: {timestamp}, Device: {device}, Battery Voltage: {value}V\n")
+
+ if float(value) < 3.0:
+ print("Waarschuwing: Batterijspanning is lager dan 3.0 volt. Opladen aanbevolen.\n")
+ # Controleer of de batterijspanning hoger is dan 4.2 volt en geef een melding
+ elif float(value) > 4.2:
+ print("Melding: Batterijspanning is hoger dan 4.2 volt. Batterij is vol.\n")
+ else:
+ print("Melding: Batterijspanning is binnen het gewenste bereik.\n\n")
+
+ except requests.exceptions.RequestException as e:
+ print(f"Error fetching data from {url}: {e}")
+
+ print("Waiting for the next read action...\n")
+ time.sleep(300)
+
+# Functie voor het bijwerken van gegevens in de database
+def update_data(record_id):
+ try:
+ mydb = database_connect()
+
+ if mydb.is_connected():
+ mycursor = mydb.cursor()
+
+ # Controleer of het record bestaat voordat je het bijwerkt
+ mycursor.execute("SELECT * FROM goodgarden.battery_voltage_events WHERE id = %s", (record_id,))
+ existing_record = mycursor.fetchone()
+
+ if not existing_record:
+ print(f"Record with ID {record_id} not found. Update operation aborted.")
+ return
+
+ # Vraag de gebruiker om nieuwe waarden voor de andere velden
+ new_timestamp = input("Enter new timestamp: ")
+ new_gateway_receive_time = input("Enter new gateway_receive_time: ")
+ new_device = input("Enter new device: ")
+ new_value = input("Enter new value: ")
+
+ # Hier moet je de juiste kolomnamen aanpassen op basis van de structuur van je database
+ update_query = """
+ UPDATE goodgarden.battery_voltage_events
+ SET timestamp = %s, gateway_receive_time = %s, device = %s, value = %s
+ WHERE id = %s
+ """
+
+ # Voer de query uit
+ print(f"Executing update query: {update_query}")
+ print(f"Updating record with ID {record_id} to new values - timestamp: {new_timestamp}, gateway_receive_time: {new_gateway_receive_time}, device: {new_device}, value: {new_value}")
+
+ mycursor.execute(update_query, (new_timestamp, new_gateway_receive_time, new_device, new_value, record_id))
+
+ # Bevestig de wijzigingen
+ mydb.commit()
+
+ print(f"Update executed. Rowcount: {mycursor.rowcount}")
+
+ except mysql.connector.Error as update_err:
+ print(f"Error updating data: {update_err}")
+ finally:
+ # Zorg ervoor dat je altijd de cursor en de databaseverbinding sluit
+ if 'mycursor' in locals() and mycursor is not None:
+ mycursor.close()
+ if 'mydb' in locals() and mydb.is_connected():
+ mydb.close()
+
+# Functie voor het verwijderen van gegevens uit de database
+def delete_data(record_id):
+ mydb = database_connect()
+ if mydb.is_connected():
+ mycursor = mydb.cursor()
+
+ # Hier moet je de juiste kolomnamen aanpassen op basis van de structuur van je database
+ delete_query = """
+ DELETE FROM goodgarden.battery_voltage_events
+ WHERE id = %s
+ """
+
+ # Voer de query uit
+ mycursor.execute(delete_query, (record_id,))
+
+ # Bevestig de wijzigingen
+ mydb.commit()
+
+ # Sluit cursor en verbinding
+ mycursor.close()
+ mydb.close()
+
+ print(f"Data with ID {record_id} deleted.")
+
+# Functie voor het aanmaken van gegevens in de database op basis van batterijspanningsinformatie
+if __name__ == "__main__":
+ url = "https://garden.inajar.nl/api/battery_voltage_events/?format=json"
+ access_token = "33bb3b42452306c58ecedc3c86cfae28ba22329c" # Vervang dit door je werkelijke toegangstoken
+
+ # Je kunt repeat_count wijzigen om te bepalen hoe vaak je de bewerking wilt herhalen
+ repeat_count = 10
+
+ # Keuze voor de bewerking
+ operation_choice = input("Choose operation (C for Create, R for Read, U for Update, D for Delete): ").upper()
+
+ if operation_choice == "C":
+ # Maak gegevens aan
+ create_data(url, access_token, repeat_count)
+ elif operation_choice == "R":
+ # Lees gegevens
+ read_data(url, access_token, repeat_count)
+ elif operation_choice == "U":
+ # Update gegevens
+ record_id = int(input("Enter record ID to update: "))
+ # Call the update_data function without additional arguments
+ update_data(record_id)
+ elif operation_choice == "D":
+ # Verwijder gegevens
+ record_id = int(input("Enter record ID to delete: "))
+ delete_data(record_id)
+ else:
+ print("Invalid operation choice. Please choose C, R, U, or D.")
\ No newline at end of file
diff --git a/script/db_connect.py b/script/db_connect.py
new file mode 100644
index 0000000..fbed212
--- /dev/null
+++ b/script/db_connect.py
@@ -0,0 +1,19 @@
+import mysql.connector #** TYPE IN TERMINAL: "pip install mysql-connector-python"
+from mysql.connector import Error
+
+def database_connect():
+ try:
+ connection = mysql.connector.connect(
+ host="localhost",
+ user="root",
+ password="",
+ database="goodgarden"
+ )
+ if connection.is_connected():
+ # print("Connection gelukt!")
+ return connection
+ except Error as e:
+ print(f"Connection NIET gelukt! ${e}")
+ return None
+
+# database_connect()
\ No newline at end of file
diff --git a/script/db_connect_form.py b/script/db_connect_form.py
new file mode 100644
index 0000000..eb78cce
--- /dev/null
+++ b/script/db_connect_form.py
@@ -0,0 +1,50 @@
+import sys
+import json
+import mysql.connector #** TYPE IN TERMINAL: "pip install mysql-connector-python"
+from mysql.connector import Error
+
+
+# Voeg de data uit het formulier toe aan de database
+def insert_plant_name(plant_naam, plantensoort, plant_geteelt):
+
+ # Als er "true" is meegeven als waarde dan komt in de database 1 anders 0 (false)
+ plant_geteelt_value = 1 if plant_geteelt.lower() == "true" else 0
+
+ try:
+ connection = mysql.connector.connect(
+ host='localhost',
+ database='goodgarden',
+ user='root',
+ password=''
+ )
+
+ # Als er verbinding gemaakt kan worden voer dan onderstaande query uit
+ if connection.is_connected():
+
+ # De crusor() zorgt ervoor dat er een verbinding met de database gelegt kan worden en de data gemanipuleerd
+ cursor = connection.cursor()
+ query = "INSERT INTO goodgarden.planten (plant_naam, plantensoort, plant_geteelt) VALUES (%s, %s, %s)"
+ cursor.execute(query, (plant_naam, plantensoort, plant_geteelt_value)) # "%s" wordt hier ingevuld doormiddel van de variable (parameter)
+ connection.commit()
+ print(json.dumps({"success": True}))
+
+ else:
+ print(json.dumps({"success": False, "error": "Database connection failed"}))
+
+ except Error as e:
+ print(json.dumps({"success": False, "error": str(e)}))
+
+ finally:
+ if connection and connection.is_connected():
+ cursor.close()
+ connection.close()
+
+# Wordt alleen uitgevoerd als het een standalone script is (geen import!!!)
+if __name__ == "__main__":
+ # Dit zijn de variables die door het JavaScript bestand (app.js) worden meegegeven --- NOTE: sys.argv[0] is altijd de naam van het script!
+ plant_naam = sys.argv[1]
+ plantensoort = sys.argv[2]
+ plant_geteelt = sys.argv[3]
+
+ # Call de function met de variables
+ insert_plant_name(plant_naam, plantensoort, plant_geteelt)
\ No newline at end of file
diff --git a/script/devices.py b/script/devices.py
new file mode 100644
index 0000000..3825589
--- /dev/null
+++ b/script/devices.py
@@ -0,0 +1,71 @@
+import requests
+import time
+
+from db_connect import database_connect
+
+def fetch_and_display_all(url, access_token, repeat_count=5):
+ for _ in range(repeat_count):
+ try:
+ headers = {
+ "Authorization": f"Token {access_token}"
+ }
+ response = requests.get(url, headers=headers)
+ response.raise_for_status()
+
+ data = response.json()
+ print(f"Data from {url}:")
+ print(data)
+ load_data(data)
+
+ except requests.exceptions.RequestException as e:
+ print(f"Error fetching data from {url}: {e}")
+
+ print("Waiting for the next retrieval action...")
+
+ # time.sleep(300) # Time here is in seconds.
+
+ time.sleep(1) # Time here is in seconds.
+
+def load_data(data):
+ mydb = database_connect()
+ if mydb.is_connected():
+ mycursor = mydb.cursor()
+
+ # Here you need to adjust the correct column names and data formats based on the API response
+ insert_query = """
+ INSERT INTO goodgarden.devices (serial_number, name, label, last_seen, last_battery_voltage)
+ VALUES (%s, %s, %s, %s, %s )
+ """
+ for record in data['results']:
+ serial_number = record.get('serial_number', '')
+ name = record.get('name', '')
+ label = record.get('label', '')
+ last_seen = record.get('last_seen', '')
+ last_battery_voltage = record.get('last_battery_voltage', '')
+
+ print(f"Inserting data: serial_number={serial_number}, name={name}, label={label}, last_seen={last_seen}, last_battery_voltage={last_battery_voltage}")
+
+ # Execute the query
+ mycursor.execute(insert_query, (serial_number, name, label, last_seen, last_battery_voltage))
+
+ # Commit the changes
+ mydb.commit()
+
+ # Close cursor and connection
+ mycursor.close()
+ mydb.close()
+
+ print("Data inserted into the database.")
+
+if __name__ == "__main__":
+ url = "https://garden.inajar.nl/api/devices/?format=json"
+ access_token = "33bb3b42452306c58ecedc3c86cfae28ba22329c" # Replace this with your actual access token
+
+
+ # access_token = "33bb3b42452306c58ecedc3c86cfae28ba22329c"
+
+ # You can change the repeat_count to control how many times you want to repeat the process
+ repeat_count = 10
+
+
+ fetch_and_display_all(url, access_token, repeat_count)
diff --git a/script/fetch.py b/script/fetch.py
new file mode 100644
index 0000000..f7f707f
--- /dev/null
+++ b/script/fetch.py
@@ -0,0 +1,73 @@
+import requests
+import time
+
+from db_connect import database_connect
+
+# Establish a database connection
+connection = database_connect()
+
+def fetch_and_display_all(urls, access_token):
+ for url in urls:
+ try:
+ headers = {
+ "Authorization": f"Token {access_token}"
+ }
+ response = requests.get(url, headers=headers)
+ response.raise_for_status()
+
+ data = response.json()
+ print(f"Data from {url}:")
+ print(data)
+ load_data(data)
+
+ except requests.exceptions.RequestException as e:
+ print(f"Error fetching data from {url}: {e}")
+
+ # Wait for a certain time (e.g., 60 seconds) before making the next call
+ print("Waiting for the next retrieval action...")
+ time.sleep(10) # Time here is in seconds.
+
+def load_data(data):
+ mydb = database_connect()
+ if mydb.is_connected():
+ mycursor = mydb.cursor()
+
+ # Here you need to adjust the correct column names and data formats based on the API response
+ insert_query = """
+ INSERT INTO goodgarden.fetch (timestamp, gateway_receive_time, device, value)
+ VALUES (%s, %s, %s, %s)
+ """
+ for record in data['results']: # Adjust this based on the actual structure of the JSON
+ timestamp = record.get('timestamp', '')
+ gateway_receive_time = record.get('gateway_receive_time', '')
+ device = record.get('device', '')
+ value = record.get('value', '')
+
+ print(f"Inserting data: timestamp={timestamp}, gateway_receive_time={gateway_receive_time}, device={device}, value={value}") # Print the data being inserted
+
+ # Execute the query
+ mycursor.execute(insert_query, (timestamp, gateway_receive_time, device, value))
+
+ # Commit the changes
+ mydb.commit()
+
+ # Close cursor and connection
+ mycursor.close()
+ mydb.close()
+
+ print("Data inserted into the database.")
+
+if __name__ == "__main__":
+ urls = [
+ "https://garden.inajar.nl/api/battery_voltage_events/?format=json",
+ "https://garden.inajar.nl/api/devices/?format=json",
+ "https://garden.inajar.nl/api/par_events/?format=json",
+ "https://garden.inajar.nl/api/relative_humidity_events/?format=json",
+ "https://garden.inajar.nl/api/soil_electric_conductivity_events/?format=json",
+ "https://garden.inajar.nl/api/soil_relative_permittivity_events/?format=json",
+ "https://garden.inajar.nl/api/soil_temperature_events/?format=json"
+ ]
+
+ access_token = "33bb3b42452306c58ecedc3c86cfae28ba22329c" # Vervang dit met jouw echte toegangstoken
+
+ fetch_and_display_all(urls, access_token)
diff --git a/index.py b/script/fetch_data.py
similarity index 60%
rename from index.py
rename to script/fetch_data.py
index 0bc2059..72964ce 100644
--- a/index.py
+++ b/script/fetch_data.py
@@ -1,16 +1,9 @@
-import mysql.connector
import requests
import time
-def database_connect():
- return mysql.connector.connect(
- host="localhost",
- user="root",
- password="",
- database="goodgarden"
- )
+from db_connect import database_connect
-def fetch_data():
+def fetch_battery_voltage_events():
url = "https://garden.inajar.nl/api/battery_voltage_events/?format=json"
headers = {
"Authorization": "Token 33bb3b42452306c58ecedc3c86cfae28ba22329c"
@@ -24,9 +17,8 @@ def fetch_data():
data = response.json()
load_data(data)
- # Wacht voor een bepaalde tijd (bijvoorbeeld 60 seconden) voordat je de volgende oproep doet
print("Wachten voor de volgende ophaalactie...")
- time.sleep(60) # De tijd hier is in seconden.
+ time.sleep(300) # De tijd hier is in seconden.
except requests.exceptions.RequestException as e:
print(f"Error fetching data: {e}")
@@ -40,19 +32,17 @@ def load_data(data):
# Hier moet je de juiste kolomnamen en dataformaten aanpassen op basis van de API-respons
insert_query = """
- INSERT INTO goodgarden.sensor_data (timestamp, gateway_receive_time, device, value)
+ INSERT INTO goodgarden.battery_voltage_events (timestamp, gateway_receive_time, device, value)
VALUES (%s, %s, %s, %s)
"""
- for record in data['results']: # Pas dit aan op basis van de werkelijke structuur van de JSON
+ for record in data['results']:
timestamp = record['timestamp']
gateway_receive_time = record['gateway_receive_time']
device = record['device']
value = record['value']
- print(f"Inserting data: timestamp={timestamp}, gateway_receive_time={gateway_receive_time}, device={device}, value={value}") # Print de data die wordt ingevoegd
-
- # Voer de query uit
- mycursor.execute(insert_query, (timestamp, gateway_receive_time, device, value))
+ # print(f"Inserting data: timestamp={timestamp}, gateway_receive_time={gateway_receive_time}, device={device}, value={value}")
+ mycursor.execute(insert_query, (timestamp, gateway_receive_time, device, value))
# Commit de wijzigingen
mydb.commit()
@@ -64,4 +54,4 @@ def load_data(data):
print("Data ingevoegd in de database.")
if __name__ == "__main__":
- fetch_data()
\ No newline at end of file
+ fetch_battery_voltage_events()
\ No newline at end of file
diff --git a/script/main.py b/script/main.py
new file mode 100644
index 0000000..e69de29
diff --git a/script/par_events.py b/script/par_events.py
new file mode 100644
index 0000000..8246737
--- /dev/null
+++ b/script/par_events.py
@@ -0,0 +1,64 @@
+import requests
+import time
+
+from db_connect import database_connect
+
+def fetch_and_display_all(url, access_token, repeat_count=5):
+ for _ in range(repeat_count):
+ try:
+ headers = {
+ "Authorization": f"Token {access_token}"
+ }
+ response = requests.get(url, headers=headers)
+ response.raise_for_status()
+
+ data = response.json()
+ print(f"Data from {url}:")
+ print(data)
+ load_data(data)
+
+ except requests.exceptions.RequestException as e:
+ print(f"Error fetching data from {url}: {e}")
+
+ print("Waiting for the next retrieval action...")
+
+ time.sleep(1) # Time here is in seconds.
+
+
+def load_data(data):
+ mydb = database_connect()
+ if mydb.is_connected():
+ mycursor = mydb.cursor()
+
+ # Here you need to adjust the correct column names and data formats based on the API response
+ insert_query = """
+ INSERT INTO goodgarden.par_events (timestamp, gateway_receive_time, device, value)
+ VALUES (%s, %s, %s, %s)
+ """
+ for record in data['results']:
+ timestamp = record.get('timestamp', '')
+ gateway_receive_time = record.get('gateway_receive_time', '')
+ device = record.get('device', '')
+ value = record.get('value', '')
+
+ print(f"Inserting data: timestamp={timestamp}, gateway_receive_time={gateway_receive_time}, device={device}, value={value}")
+
+ # Execute the query
+ mycursor.execute(insert_query, (timestamp, gateway_receive_time, device, value))
+
+ # Commit the changes
+ mydb.commit()
+
+ # Close cursor and connection
+ mycursor.close()
+ mydb.close()
+
+ print("Data inserted into the database.")
+
+if __name__ == "__main__":
+ url = "https://garden.inajar.nl/api/par_events/?format=json"
+ access_token = "33bb3b42452306c58ecedc3c86cfae28ba22329c"
+ # You can change the repeat_count to control how many times you want to repeat the process
+ repeat_count = 10
+
+ fetch_and_display_all(url, access_token, repeat_count)
\ No newline at end of file
diff --git a/script/relative_humidity_events.py b/script/relative_humidity_events.py
new file mode 100644
index 0000000..6961094
--- /dev/null
+++ b/script/relative_humidity_events.py
@@ -0,0 +1,64 @@
+import requests
+import time
+
+from db_connect import database_connect
+
+def fetch_and_display_all(url, access_token, repeat_count=5):
+ for _ in range(repeat_count):
+ try:
+ headers = {
+ "Authorization": f"Token {access_token}"
+ }
+ response = requests.get(url, headers=headers)
+ response.raise_for_status()
+
+ data = response.json()
+ print(f"Data from {url}:")
+ print(data)
+ load_data(data)
+
+ except requests.exceptions.RequestException as e:
+ print(f"Error fetching data from {url}: {e}")
+
+ print("Waiting for the next retrieval action...")
+
+ time.sleep(1) # Time here is in seconds.
+
+def load_data(data):
+ mydb = database_connect()
+ if mydb.is_connected():
+ mycursor = mydb.cursor()
+
+ # Here you need to adjust the correct column names and data formats based on the API response
+ insert_query = """
+ INSERT INTO goodgarden.relative_humidity_events (timestamp, gateway_receive_time, device, value)
+ VALUES (%s, %s, %s, %s)
+ """
+ for record in data['results']:
+ timestamp = record.get('timestamp', '')
+ gateway_receive_time = record.get('gateway_receive_time', '')
+ device = record.get('device', '')
+ value = record.get('value', '')
+
+ print(f"Inserting data: timestamp={timestamp}, gateway_receive_time={gateway_receive_time}, device={device}, value={value}")
+
+ # Execute the query
+ mycursor.execute(insert_query, (timestamp, gateway_receive_time, device, value))
+
+ # Commit the changes
+ mydb.commit()
+
+ # Close cursor and connection
+ mycursor.close()
+ mydb.close()
+
+ print("Data inserted into the database.")
+
+if __name__ == "__main__":
+ url = "https://garden.inajar.nl/api/relative_humidity_events/?format=json"
+ access_token = "33bb3b42452306c58ecedc3c86cfae28ba22329c"
+
+ # You can change the repeat_count to control how many times you want to repeat the process
+ repeat_count = 10
+
+ fetch_and_display_all(url, access_token, repeat_count)
\ No newline at end of file
diff --git a/script/soil_electric_conductivity_events.py b/script/soil_electric_conductivity_events.py
new file mode 100644
index 0000000..d9a598a
--- /dev/null
+++ b/script/soil_electric_conductivity_events.py
@@ -0,0 +1,63 @@
+import requests
+import time
+
+from db_connect import database_connect
+
+def fetch_and_display_all(url, access_token, repeat_count=5):
+ for _ in range(repeat_count):
+ try:
+ headers = {
+ "Authorization": f"Token {access_token}"
+ }
+ response = requests.get(url, headers=headers)
+ response.raise_for_status()
+
+ data = response.json()
+ print(f"Data from {url}:")
+ print(data)
+ load_data(data)
+
+ except requests.exceptions.RequestException as e:
+ print(f"Error fetching data from {url}: {e}")
+
+ print("Waiting for the next retrieval action...")
+
+ time.sleep(1) # Time here is in seconds.
+
+def load_data(data):
+ mydb = database_connect()
+ if mydb.is_connected():
+ mycursor = mydb.cursor()
+
+ # Here you need to adjust the correct column names and data formats based on the API response
+ insert_query = """
+ INSERT INTO goodgarden.soil_electric_conductivity_events (timestamp, gateway_receive_time, device, value)
+ VALUES (%s, %s, %s, %s)
+ """
+ for record in data['results']:
+ timestamp = record.get('timestamp', '')
+ gateway_receive_time = record.get('gateway_receive_time', '')
+ device = record.get('device', '')
+ value = record.get('value', '')
+
+ print(f"Inserting data: timestamp={timestamp}, gateway_receive_time={gateway_receive_time}, device={device}, value={value}")
+
+ # Execute the query
+ mycursor.execute(insert_query, (timestamp, gateway_receive_time, device, value))
+
+ # Commit the changes
+ mydb.commit()
+
+ # Close cursor and connection
+ mycursor.close()
+ mydb.close()
+
+ print("Data inserted into the database.")
+if __name__ == "__main__":
+ url = "https://garden.inajar.nl/api/soil_electric_conductivity_events/?format=json"
+ access_token = "33bb3b42452306c58ecedc3c86cfae28ba22329c" # Replace this with your actual access token
+
+ # You can change the repeat_count to control how many times you want to repeat the process
+ repeat_count = 10
+
+ fetch_and_display_all(url, access_token, repeat_count)
\ No newline at end of file
diff --git a/script/soil_relative_permittivity_events.py b/script/soil_relative_permittivity_events.py
new file mode 100644
index 0000000..62b3483
--- /dev/null
+++ b/script/soil_relative_permittivity_events.py
@@ -0,0 +1,66 @@
+import requests
+import time
+
+from db_connect import database_connect
+
+def fetch_and_display_all(url, access_token, repeat_count=5):
+ for _ in range(repeat_count):
+ try:
+ headers = {
+ "Authorization": f"Token {access_token}"
+ }
+ response = requests.get(url, headers=headers)
+ response.raise_for_status()
+
+ data = response.json()
+ print(f"Data from {url}:")
+ print(data)
+ load_data(data)
+
+ except requests.exceptions.RequestException as e:
+ print(f"Error fetching data from {url}: {e}")
+
+ print("Waiting for the next retrieval action...")
+
+ time.sleep(1) # Time here is in seconds.
+
+
+def load_data(data):
+ mydb = database_connect()
+ if mydb.is_connected():
+ mycursor = mydb.cursor()
+
+ # Here you need to adjust the correct column names and data formats based on the API response
+ insert_query = """
+ INSERT INTO goodgarden.soil_temperature_events (timestamp, gateway_receive_time, device, value)
+ VALUES (%s, %s, %s, %s)
+ """
+ for record in data['results']:
+ timestamp = record.get('timestamp', '')
+ gateway_receive_time = record.get('gateway_receive_time', '')
+ device = record.get('device', '')
+ value = record.get('value', '')
+
+ print(f"Inserting data: timestamp={timestamp}, gateway_receive_time={gateway_receive_time}, device={device}, value={value}")
+
+ # Execute the query
+ mycursor.execute(insert_query, (timestamp, gateway_receive_time, device, value))
+
+ # Commit the changes
+ mydb.commit()
+
+ # Close cursor and connection
+ mycursor.close()
+ mydb.close()
+
+ print("Data inserted into the database.")
+
+if __name__ == "__main__":
+ url = "https://garden.inajar.nl/api/soil_relative_permittivity_events/?format=json"
+ access_token = "33bb3b42452306c58ecedc3c86cfae28ba22329c"
+ # You can change the repeat_count to control how many times you want to repeat the process
+ repeat_count = 10
+
+ # fetch_and_display_all(urls, access_token)
+
+ fetch_and_display_all(url, access_token, repeat_count)
\ No newline at end of file
diff --git a/script/soil_temperature_events.py b/script/soil_temperature_events.py
new file mode 100644
index 0000000..2cd9750
--- /dev/null
+++ b/script/soil_temperature_events.py
@@ -0,0 +1,65 @@
+import requests
+import time
+
+
+from db_connect import database_connect
+
+def fetch_and_display_all(url, access_token, repeat_count=5):
+ for _ in range(repeat_count):
+
+ try:
+ headers = {
+ "Authorization": f"Token {access_token}"
+ }
+ response = requests.get(url, headers=headers)
+ response.raise_for_status()
+
+ data = response.json()
+ print(f"Data from {url}:")
+ print(data)
+ load_data(data)
+
+ except requests.exceptions.RequestException as e:
+ print(f"Error fetching data from {url}: {e}")
+
+ print("Waiting for the next retrieval action...")
+
+ time.sleep(1) # Time here is in seconds.
+
+def load_data(data):
+ mydb = database_connect()
+ if mydb.is_connected():
+ mycursor = mydb.cursor()
+
+ # Here you need to adjust the correct column names and data formats based on the API response
+ insert_query = """
+ INSERT INTO goodgarden.soil_temperature_events (timestamp, gateway_receive_time, device, value)
+ VALUES (%s, %s, %s, %s)
+ """
+ for record in data['results']:
+ timestamp = record.get('timestamp', '')
+ gateway_receive_time = record.get('gateway_receive_time', '')
+ device = record.get('device', '')
+ value = record.get('value', '')
+
+ print(f"Inserting data: timestamp={timestamp}, gateway_receive_time={gateway_receive_time}, device={device}, value={value}")
+
+ # Execute the query
+ mycursor.execute(insert_query, (timestamp, gateway_receive_time, device, value))
+
+ # Commit the changes
+ mydb.commit()
+
+ # Close cursor and connection
+ mycursor.close()
+ mydb.close()
+
+ print("Data inserted into the database.")
+if __name__ == "__main__":
+ url = "https://garden.inajar.nl/api/soil_temperature_events/?format=json"
+ access_token = "33bb3b42452306c58ecedc3c86cfae28ba22329c" # Replace this with your actual access token
+
+ # You can change the repeat_count to control how many times you want to repeat the process
+ repeat_count = 10
+
+ fetch_and_display_all(url, access_token, repeat_count)
\ No newline at end of file
diff --git a/src/css/style.css b/src/css/style.css
new file mode 100644
index 0000000..8e26c88
--- /dev/null
+++ b/src/css/style.css
@@ -0,0 +1,236 @@
+/*default colors*/
+@import url("https://fonts.googleapis.com/css2?family=Akaya+Kanadaka&display=swap");
+@import url("https://fonts.googleapis.com/css2?family=Afacad:ital,wght@0,400..700;1,400..700&display=swap");
+h1, h2, h3, h4, h5 {
+ font-family: "Akaya Kanadaka", system-ui;
+ margin: 0;
+}
+
+p, td {
+ font-family: "Afacad", sans-serif;
+}
+
+body {
+ background-image: url("../images/achtergrond.png");
+ background-repeat: no-repeat;
+ background-size: cover;
+ background-position: center;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ height: 100vh;
+ margin: 0;
+}
+body .mainContainer {
+ width: 85vw;
+ height: 38rem;
+ background-color: rgba(255, 255, 255, 0.95);
+ border-radius: 40px;
+ padding: 2rem;
+}
+body .mainContainer .goodgarden-logo {
+ position: absolute;
+ width: 10vw;
+ left: 50%;
+ top: 2.5rem;
+ transform: translateX(-50%);
+}
+body .mainContainer .informatie-kas-main-container {
+ display: grid;
+ grid-template-columns: 5fr 7fr;
+}
+body .mainContainer .mainBorder {
+ padding: 1.25rem 1.5rem;
+ height: 35rem;
+ border: solid 5px rgb(171, 211, 174);
+ border-radius: 40px;
+}
+body .mainContainer .mainBorder .pagina-titel {
+ font-size: 2rem;
+ margin-left: 1.5rem;
+}
+body .mainContainer .mainBorder #sectie-1 {
+ display: flex;
+ flex-direction: column;
+ gap: 1rem;
+ padding: 0 2.5rem 0 1rem;
+ position: relative;
+}
+body .mainContainer .mainBorder #sectie-1 .parent-algemeen-overzicht {
+ box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.5);
+ border-radius: 40px;
+ padding: 1rem;
+ margin-top: 1rem;
+}
+body .mainContainer .mainBorder #sectie-1 .parent-algemeen-overzicht .algemeen-overzicht {
+ border: solid 2px rgb(171, 211, 174);
+ border-radius: 35px;
+ font-size: 1.25rem;
+ padding: 0.5rem 1rem;
+}
+body .mainContainer .mainBorder #sectie-1 .parent-algemeen-overzicht .algemeen-overzicht .table-informatie-kas {
+ width: 100%;
+}
+body .mainContainer .mainBorder #sectie-1 .parent-algemeen-overzicht .algemeen-overzicht .table-informatie-kas .tr-informatie-kas {
+ display: flex;
+ justify-content: space-between;
+ text-align: left;
+}
+body .mainContainer .mainBorder #sectie-1 .grafiek {
+ box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.5);
+ border-radius: 40px;
+ padding: 1rem;
+ position: relative;
+}
+body .mainContainer .mainBorder #sectie-1 .grafiek .grafiek-innerbox {
+ border: solid 2px rgb(171, 211, 174);
+ border-radius: 35px;
+ font-size: 1.25rem;
+ padding: 0 1rem 2.5rem;
+ height: 225px;
+}
+body .mainContainer .mainBorder #sectie-1 .grafiek .grafiek-innerbox h2 {
+ position: absolute;
+ left: 50%;
+ transform: translateX(-50%);
+}
+body .mainContainer .mainBorder #sectie-1 .grafiek .grafiek-innerbox canvas {
+ position: absolute;
+ top: 50%;
+ left: 50%;
+ transform: translate(-50%, -50%);
+}
+body .mainContainer .mainBorder #sectie-1 .content {
+ display: grid;
+ grid-template-columns: 3fr 1fr 3fr;
+ height: 100%;
+}
+body .mainContainer .mainBorder #sectie-1 .content .kant-links {
+ grid-column: 1;
+}
+body .mainContainer .mainBorder #sectie-1 .content .kant-links #planten {
+ width: 100%;
+ border-collapse: collapse;
+}
+body .mainContainer .mainBorder #sectie-1 .content .kant-links #planten td article {
+ height: 7rem;
+ width: 10rem;
+ padding: 0.6rem;
+ margin: 0.1rem;
+ margin-left: 2rem;
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+ align-items: center;
+ border: solid 3px rgb(171, 211, 174);
+ border-radius: 40px;
+ box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
+}
+body .mainContainer .mainBorder #sectie-1 .content .kant-links #planten td article #toevoegen {
+ height: 5rem;
+ width: 5rem;
+}
+body .mainContainer .mainBorder #sectie-1 .content .kant-links #planten td article h2 {
+ color: gray;
+}
+body .mainContainer .mainBorder #sectie-1 .content .kant-links #planten td article:hover {
+ background-color: lightgray;
+}
+body .mainContainer .mainBorder #sectie-1 .content .kant-rechts {
+ grid-column: 3;
+}
+body .mainContainer .mainBorder #sectie-1 .content .kant-rechts #metingen {
+ border: solid 3px rgb(171, 211, 174);
+ border-radius: 40px;
+}
+body .mainContainer .mainBorder #sectie-1 .content .kant-rechts #metingen #main-waardes {
+ display: flex;
+ justify-content: space-evenly;
+ padding: 0.5rem;
+ padding-bottom: 0;
+ width: 100%;
+}
+body .mainContainer .mainBorder #sectie-1 .content .kant-rechts #metingen #main-waardes table {
+ display: flex;
+ justify-content: space-around;
+}
+body .mainContainer .mainBorder .grid-column-2 {
+ box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.5);
+ border-radius: 40px;
+ padding: 1rem;
+ margin: 3.25rem 1rem 1.25rem 1rem;
+}
+body .mainContainer .mainBorder .grid-column-2 .grid-2-child {
+ border: solid 2px rgb(171, 211, 174);
+ border-radius: 35px;
+ height: 100%;
+}
+body .mainContainer .mainBorder .grid-column-2 .grid-2-child .parent-table {
+ padding: 1.5rem 2rem;
+ display: flex;
+ flex-direction: column;
+ justify-content: space-around;
+ height: 90%;
+}
+body .mainContainer .mainBorder .grid-column-2 .grid-2-child .parent-table table tr td {
+ font-size: 1.05rem;
+}
+body .mainContainer .mainBorder .grid-column-2 .grid-2-child .parent-table .kas-table-1 tr td {
+ font-size: 1.25rem;
+}
+body .mainContainer .mainBorder .grid-column-2 .grid-2-child .parent-table .kas-table-2 {
+ position: relative;
+}
+body .mainContainer .mainBorder .grid-column-2 .grid-2-child .parent-table .kas-table-2::after, body .mainContainer .mainBorder .grid-column-2 .grid-2-child .parent-table .kas-table-2::before {
+ content: "";
+ position: absolute;
+ left: 0;
+ right: 0;
+ height: 1px;
+ width: 90%;
+ background: black;
+}
+body .mainContainer .mainBorder .grid-column-2 .grid-2-child .parent-table .kas-table-2::after {
+ bottom: -20px;
+}
+body .mainContainer .mainBorder .grid-column-2 .grid-2-child .parent-table .kas-table-2::before {
+ top: -20px;
+}
+
+/* Divider */
+.divider {
+ display: flex;
+ justify-content: center;
+ border: solid 1px rgb(171, 211, 174);
+ border-radius: 5px;
+ width: 80%;
+ margin: 0 auto;
+}
+
+/* The Modal (background) */
+.modal {
+ display: none;
+ position: fixed;
+ z-index: 999;
+ left: 50%;
+ top: 50%;
+ transform: translate(-50%, -50%);
+ background: white;
+ padding: 1.25rem;
+ box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
+ width: 30vw;
+ height: auto;
+ border: solid 2px black;
+ border-radius: 10px;
+}
+.modal .close {
+ color: #aaa;
+ float: right;
+ font-size: 1.75rem;
+ font-weight: bold;
+}
+.modal .close:hover, .modal .close:active {
+ color: black;
+ text-decoration: none;
+ cursor: pointer;
+}/*# sourceMappingURL=style.css.map */
\ No newline at end of file
diff --git a/src/css/style.css.map b/src/css/style.css.map
new file mode 100644
index 0000000..d300b9e
--- /dev/null
+++ b/src/css/style.css.map
@@ -0,0 +1 @@
+{"version":3,"sources":["style.scss","style.css"],"names":[],"mappings":"AAAA,iBAAA;AAKQ,mFAAA;AACA,2GAAA;AAgCR;EAEI,wCAhCU;EAiCV,SAAA;ACnCJ;;ADsCA;EAEI,iCApCQ;ACAZ;;ADuCA;EAEI,kDAAA;EACA,4BAAA;EACA,sBAAA;EACA,2BAAA;EAEA,aAAA;EACA,uBAAA;EACA,mBAAA;EACA,aAAA;EACA,SAAA;ACtCJ;ADwCI;EAEI,WAAA;EACA,aAAA;EACA,2CAAA;EACA,mBAAA;EACA,aAAA;ACvCR;ADyCQ;EAGI,kBAAA;EACA,WAAA;EACA,SAAA;EACA,WAAA;EACA,2BAAA;ACzCZ;AD4CQ;EAEI,aAAA;EACA,8BAAA;AC3CZ;AD8CQ;EAEI,uBAAA;EACA,aAAA;EACA,oCAAA;EACA,mBAAA;AC7CZ;AD+CY;EAEI,eAAA;EACA,mBAAA;AC9ChB;ADiDY;EAEI,aAAA;EACA,sBAAA;EACA,SAAA;EACA,wBAAA;EACA,kBAAA;AChDhB;ADkDgB;EAlFZ,2CAAA;EAKA,mBAAA;EAiFgB,aAAA;EACA,gBAAA;ACjDpB;ADoDoB;EA/FhB,oCAAA;EAeA,mBAAA;EAoFoB,kBAAA;EACA,oBAAA;ACnDxB;ADsDwB;EAEI,WAAA;ACrD5B;ADuD4B;EAEI,aAAA;EACA,8BAAA;EACA,gBAAA;ACtDhC;AD8DgB;EAlHZ,2CAAA;EAKA,mBAAA;EAiHgB,aAAA;EACA,kBAAA;AC7DpB;AD+DoB;EA9HhB,oCAAA;EAeA,mBAAA;EAmHoB,kBAAA;EACA,sBAAA;EACA,aAAA;AC9DxB;ADiEwB;EAEI,kBAAA;EACA,SAAA;EACA,2BAAA;AChE5B;ADmEwB;EAGI,kBAAA;EACA,QAAA;EACA,SAAA;EACA,gCAAA;ACnE5B;ADwEgB;EAEI,aAAA;EACA,kCAAA;EACA,YAAA;ACvEpB;AD2EwB;EAEI,cAAA;AC1E5B;AD4E4B;EAEI,WAAA;EACA,yBAAA;AC3EhC;AD+EoC;EAEI,YAAA;EACA,YAAA;EACA,eAAA;EACA,cAAA;EACA,iBAAA;EACA,aAAA;EACA,sBAAA;EACA,uBAAA;EACA,mBAAA;EACA,oCAAA;EACA,mBAAA;EACA,wCAAA;AC9ExC;ADgFwC;EAEI,YAAA;EACA,WAAA;AC/E5C;ADkFwC;EAEI,WAAA;ACjF5C;ADoFwC;EAEI,2BAAA;ACnF5C;AD4FwB;EAEI,cAAA;AC3F5B;AD8F4B;EAGI,oCAAA;EACA,mBAAA;AC9FhC;ADgGgC;EAEA,aAAA;EACA,6BAAA;EACA,eAAA;EACA,iBAAA;EACA,WAAA;AC/FhC;ADiGoC;EAEI,aAAA;EACA,6BAAA;AChGxC;AD0GY;EA5OR,2CAAA;EAKA,mBAAA;EA2OY,aAAA;EACA,iCAAA;ACzGhB;AD2GgB;EAxPZ,oCAAA;EAeA,mBAAA;EA6OgB,YAAA;AC1GpB;AD6GoB;EAEI,oBAAA;EACA,aAAA;EACA,sBAAA;EAGA,6BAAA;EACA,WAAA;AC9GxB;ADoHgC;EAEI,kBAAA;ACnHpC;AD4HgC;EAEI,kBAAA;AC3HpC;ADgIwB;EAEI,kBAAA;AC/H5B;ADiI4B;EAGI,WAAA;EACA,kBAAA;EACA,OAAA;EACA,QAAA;EACA,WAAA;EACA,UAAA;EACA,iBAAA;ACjIhC;ADoI4B;EAEI,aAAA;ACnIhC;ADsI4B;EAEI,UAAA;ACrIhC;;ADiJI,YAAA;AACJ;EACI,aAAA;EACA,uBAAA;EACA,oCAAA;EACA,kBAAA;EACA,UAAA;EACA,cAAA;AC9IJ;;ADiJA,2BAAA;AAEA;EAEI,aAAA;EACA,eAAA;EACA,YAAA;EACA,SAAA;EACA,QAAA;EACA,gCAAA;EACA,iBAAA;EACA,gBAAA;EACA,wCAAA;EACA,WAAA;EACA,YAAA;EACA,uBAAA;EACA,mBAAA;AChJJ;ADkJI;EAEI,WAAA;EACA,YAAA;EACA,kBAAA;EACA,iBAAA;ACjJR;ADmJQ;EAGI,YAAA;EACA,qBAAA;EACA,eAAA;ACnJZ","file":"style.css"}
\ No newline at end of file
diff --git a/src/css/style.scss b/src/css/style.scss
new file mode 100644
index 0000000..24bade7
--- /dev/null
+++ b/src/css/style.scss
@@ -0,0 +1,386 @@
+/*default colors*/
+
+$primary-color: rgb(171, 211, 174);
+$secondary-color: rgb(143, 188, 143);
+
+@import url('https://fonts.googleapis.com/css2?family=Akaya+Kanadaka&display=swap');
+@import url('https://fonts.googleapis.com/css2?family=Afacad:ital,wght@0,400..700;1,400..700&display=swap');
+
+$font-titels: "Akaya Kanadaka", system-ui;
+
+$font-text: "Afacad", sans-serif;
+
+@mixin flexbox
+{
+ display: flex;
+ justify-content: space-around;
+}
+
+@mixin groene-border
+{
+ border: solid 2px $primary-color;
+}
+
+@mixin box-shadow
+{
+ box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.5);
+}
+
+@mixin border-radius
+{
+ border-radius: 40px;
+}
+
+@mixin inner-border-radius
+{
+ border-radius: 35px;
+}
+
+h1, h2, h3, h4, h5
+{
+ font-family: $font-titels;
+ margin: 0;
+}
+
+p, td
+{
+ font-family: $font-text;
+}
+
+body
+{
+ background-image: url("../images/achtergrond.png");
+ background-repeat: no-repeat;
+ background-size: cover;
+ background-position: center;
+ // font-family: $font-text;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ height: 100vh;
+ margin: 0;
+
+ .mainContainer
+ {
+ width: 85vw;
+ height: 38rem;
+ background-color: rgb(255, 255, 255, 95%);
+ border-radius: 40px;
+ padding: 2rem;
+
+ .goodgarden-logo
+ {
+ // z-index: inherit;
+ position: absolute;
+ width: 10vw;
+ left: 50%;
+ top: 2.5rem;
+ transform: translateX(-50%);
+ }
+
+ .informatie-kas-main-container
+ {
+ display: grid;
+ grid-template-columns: 5fr 7fr;
+ }
+
+ .mainBorder
+ {
+ padding: 1.25rem 1.5rem;
+ height: 35rem;
+ border: solid 5px $primary-color;
+ border-radius: 40px;
+
+ .pagina-titel
+ {
+ font-size: 2rem;
+ margin-left: 1.5rem;
+ }
+
+ #sectie-1
+ {
+ display: flex;
+ flex-direction: column;
+ gap: 1rem;
+ padding: 0 2.5rem 0 1rem;
+ position: relative;
+
+ .parent-algemeen-overzicht
+ {
+ @include box-shadow;
+ @include border-radius;
+ padding: 1rem;
+ margin-top: 1rem;
+
+
+ .algemeen-overzicht
+ {
+ @include groene-border;
+ @include inner-border-radius;
+ font-size: 1.25rem;
+ padding: .5rem 1rem;
+ // background-color: red;
+
+ .table-informatie-kas
+ {
+ width: 100%;
+
+ .tr-informatie-kas
+ {
+ display: flex;
+ justify-content: space-between;
+ text-align: left;
+ }
+
+
+ }
+ }
+ }
+
+ .grafiek
+ {
+ @include box-shadow;
+ @include border-radius;
+ padding: 1rem;
+ position: relative;
+
+ .grafiek-innerbox
+ {
+ @include groene-border;
+ @include inner-border-radius;
+ font-size: 1.25rem;
+ padding: 0 1rem 2.5rem;
+ height: 225px;
+ // position: relative;
+
+ h2
+ {
+ position: absolute;
+ left: 50%;
+ transform: translateX(-50%);
+ }
+
+ canvas
+ {
+ // Zorgt ervoor dat de grafiek precies in eht midden komt
+ position: absolute;
+ top: 50%;
+ left: 50%;
+ transform: translate(-50%, -50%);
+ }
+ }
+ }
+
+ .content
+ {
+ display: grid;
+ grid-template-columns: 3fr 1fr 3fr;
+ height: 100%;
+
+ .kant
+ {
+ &-links
+ {
+ grid-column: 1;
+
+ #planten
+ {
+ width: 100%;
+ border-collapse: collapse;
+
+ td
+ {
+ article
+ {
+ height: 7rem;
+ width: 10rem;
+ padding: .6rem;
+ margin: .1rem;
+ margin-left: 2rem;
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+ align-items: center;
+ border: solid 3px $primary-color;
+ border-radius: 40px;
+ box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
+
+ #toevoegen
+ {
+ height: 5rem;
+ width: 5rem;
+ }
+
+ h2
+ {
+ color: gray;
+ }
+
+ &:hover
+ {
+ background-color: lightgray;
+ }
+
+
+ }
+ }
+ }
+ }
+
+ &-rechts
+ {
+ grid-column: 3;
+ // margin-right: 2rem;
+
+ #metingen
+ {
+
+ border: solid 3px $primary-color;
+ border-radius: 40px;
+
+ #main-waardes
+ {
+ display: flex;
+ justify-content: space-evenly;
+ padding: .5rem;
+ padding-bottom: 0;
+ width: 100%;
+
+ table
+ {
+ display: flex;
+ justify-content: space-around;
+ // width: 100%;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ .grid-column-2
+ {
+ @include box-shadow;
+ @include border-radius;
+ padding: 1rem;
+ margin: 3.25rem 1rem 1.25rem 1rem;
+
+ .grid-2-child
+ {
+ @include groene-border;
+ @include inner-border-radius;
+ height: 100%;
+
+
+ .parent-table
+ {
+ padding: 1.5rem 2rem;
+ display: flex;
+ flex-direction: column;
+ // align-items: stretch;
+ // gap: 2.5rem;
+ justify-content: space-around;
+ height: 90%;
+
+ table
+ {
+ tr
+ {
+ td
+ {
+ font-size: 1.05rem;
+ }
+ }
+ }
+
+ .kas-table-1
+ {
+ tr
+ {
+ td
+ {
+ font-size: 1.25rem;
+ }
+ }
+ }
+
+ .kas-table-2
+ {
+ position: relative;
+
+ &::after,
+ &::before
+ {
+ content: "";
+ position: absolute;
+ left: 0;
+ right: 0;
+ height: 1px;
+ width: 90%;
+ background: black;
+ }
+
+ &::after
+ {
+ bottom: -20px;
+ }
+
+ &::before
+ {
+ top: -20px;
+ }
+ }
+
+ }
+ }
+ }
+
+ }
+ }
+}
+
+ /* Divider */
+.divider {
+ display: flex;
+ justify-content: center;
+ border: solid 1px $primary-color;
+ border-radius: 5px;
+ width: 80%;
+ margin: 0 auto;
+}
+
+/* The Modal (background) */
+
+.modal
+{
+ display: none;
+ position: fixed;
+ z-index: 999;
+ left: 50%;
+ top: 50%;
+ transform: translate(-50%, -50%);
+ background: white;
+ padding: 1.25rem;
+ box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
+ width: 30vw;
+ height: auto;
+ border: solid 2px black;
+ border-radius: 10px;
+
+ .close
+ {
+ color: #aaa;
+ float: right;
+ font-size: 1.75rem;
+ font-weight: bold;
+
+ &:hover,
+ &:active
+ {
+ color: black;
+ text-decoration: none;
+ cursor: pointer;
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/images/Icon awesome-apple-alt.png b/src/images/Icon awesome-apple-alt.png
new file mode 100644
index 0000000..6fbb70b
Binary files /dev/null and b/src/images/Icon awesome-apple-alt.png differ
diff --git a/src/images/Toevoegen.png b/src/images/Toevoegen.png
new file mode 100644
index 0000000..3878c7e
Binary files /dev/null and b/src/images/Toevoegen.png differ
diff --git a/src/images/achtergrond.png b/src/images/achtergrond.png
new file mode 100644
index 0000000..aea4958
Binary files /dev/null and b/src/images/achtergrond.png differ
diff --git a/src/images/logo.png b/src/images/logo.png
new file mode 100644
index 0000000..b46eaa6
Binary files /dev/null and b/src/images/logo.png differ
diff --git a/src/index.html b/src/index.html
new file mode 100644
index 0000000..9de297b
--- /dev/null
+++ b/src/index.html
@@ -0,0 +1,119 @@
+
+
+
+
+
+ Document
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Waardes
+
+
+ Huidig
+
+
+ 24u gemiddelde
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/js/main.js b/src/js/main.js
new file mode 100644
index 0000000..4ce0a61
--- /dev/null
+++ b/src/js/main.js
@@ -0,0 +1,124 @@
+const { ipcRenderer } = require("electron");
+
+document.addEventListener('DOMContentLoaded', () =>
+{
+ // Stuur een bericht naar de main process om het Python script uit te voeren
+// In je renderer.js (geladen met defer in je HTML)
+ ipcRenderer.send('request-update-temp', ['some', 'arguments']);
+
+ ipcRenderer.on('update-temp-result', (event, newTemperature) => {
+ if (newTemperature === 'error') {
+ console.error('Er is een fout opgetreden bij het ophalen van de nieuwe temperatuur');
+ } else {
+ document.getElementById('bodem-temperatuur').textContent = newTemperature;
+ }
+ });
+
+});
+
+// function dataTablePython()
+// {
+// document.getElementById("")
+// }
+
+function openModal()
+{
+ const modal = document.getElementById("myModal");
+ const button = document.getElementById("modalButton");
+ const close = document.getElementsByClassName("close")[0];
+
+ // Toon de modal wanneer op de knop wordt geklikt
+ button.onclick = function()
+ {
+ modal.style.display = "block";
+ }
+
+ // Sluit de modal wanneer op het 'sluiten' icoon wordt geklikt
+ close.onclick = function()
+ {
+ modal.style.display = "none";
+ }
+
+ // Sluit de modal wanneer buiten de modal wordt geklikt
+ window.onclick = function(event)
+ {
+ if (event.target == modal)
+ {
+ modal.style.display = "none";
+ }
+ }
+}
+
+/**
+ * --- Functie om de grafiek te tekenen. Enigste belangrijke is de eerste 2 "const" arrays "data" & "xLabels".
+ */
+function drawLineChart()
+{
+ /*Dit is de data die getoond wordt als "punt" op de grafiek. 20 = y20 / x20, 50 = y50 / x50 enzovoort... De array "data" & "xLabels" moeten beide evenveel array items hebben!!*/
+ const data = [20, 50, 60, 45, 50, 100, 70, 60, 65, 0, 85, 0];
+ const xLabels = ["", "", "", "", "", 6, "", "", "", "", "", 12];
+
+ // Define Y-axis labels here. The number of labels should match your scale.
+ const yLabels = ["", 20, "", 40, "", 60, "", 80, "", 100]; /*NIET VERANDEREN!!!*/
+
+ const canvas = document.getElementById("myCanvas");
+ const ctx = canvas.getContext("2d");
+
+ ctx.clearRect(0, 0, canvas.width, canvas.height); // Clear the canvas
+
+ const padding = 35; // Increased padding for Y labels
+ const graphWidth = canvas.width - padding * 2;
+ const graphHeight = canvas.height - padding * 2;
+
+ // Draw the axes
+ ctx.beginPath();
+ ctx.moveTo(padding, padding);
+ ctx.lineTo(padding, canvas.height - padding);
+ ctx.lineTo(canvas.width - padding, canvas.height - padding);
+ ctx.stroke();
+
+ // Set the color of the line
+ ctx.strokeStyle = "#008000"; // This sets the line color to green
+
+ const xIncrement = graphWidth / (xLabels.length - 1);
+ const yIncrement = graphHeight / (yLabels.length - 1); // Assuming you have labels for each increment
+
+ // Plot the data
+ ctx.beginPath();
+ ctx.moveTo(padding, canvas.height - padding - (data[0] / 100) * graphHeight);
+
+ for (let i = 1; i < data.length; i++)
+ {
+ const xPos = padding + i * xIncrement;
+ const yPos = canvas.height - padding - (data[i] / 100) * graphHeight;
+ ctx.lineTo(xPos, yPos);
+ }
+ ctx.stroke(); // Apply the stroke to the line
+
+ // Draw Y labels
+ ctx.fillStyle = "black";
+ ctx.textAlign = "right"; // Align text to the right
+ ctx.textBaseline = "middle"; // Center vertically
+
+ for (let i = 0; i < yLabels.length; i++)
+ {
+ if (yLabels[i] !== "")
+ {
+ const yPos = canvas.height - padding - i * yIncrement;
+ ctx.fillText(yLabels[i], padding - 10, yPos);
+ }
+ }
+
+ // Draw X labels
+ ctx.textAlign = "center"; // Center horizontally for X labels
+ for (let i = 0; i < xLabels.length; i++)
+ {
+ if (xLabels[i] !== "")
+ {
+ const xPos = padding + i * xIncrement;
+ ctx.fillText(xLabels[i], xPos, canvas.height - padding + 20);
+ }
+ }
+}
+
+drawLineChart();
\ No newline at end of file
diff --git a/src/kas_informatie.html b/src/kas_informatie.html
new file mode 100644
index 0000000..c8d24e1
--- /dev/null
+++ b/src/kas_informatie.html
@@ -0,0 +1,111 @@
+
+
+
+
+
+
+
+
+ Informatie Kas
+
+
+
+
+
+
+
+
+ Informatie Kas
+
+
+
+
+
+
+
+
+ Zonlicht
+
+
+
+
+
+
+
+
+
+
+
+ Aantal geplant:
+ 2
+
+
+ Succesvolle Oogst:
+ 2
+
+
+ Gefaalde Oogst:
+ 2
+
+
+
+
+ Warmste Maand:
+ n.v.t.
+
+
+ koudste Maand:
+ December
+
+
+ Gemiddelde Bodemtemp.:
+ 2˚C
+
+
+ Gemiddelde Uren Zonlicht:
+ 2u
+
+
+
+
+ Laatste Irrigatie:
+ 2u
+
+
+ Aankomende Irrigatie:
+ 2u
+
+
+ Laatste Bemesting
+ 2d
+
+
+ Aankomende Bemesting:
+ 2w
+
+
+
+
+
+
+
+
+
diff --git a/src/main.html b/src/main.html
deleted file mode 100644
index 6297477..0000000
--- a/src/main.html
+++ /dev/null
@@ -1,11 +0,0 @@
-
-
-
-
-
- Document
-
-
- sdgdfsgjindgfvadsiuuiadsiuhdgnhaewgiadsnugaeuigndfogjdfsgdff
-
-
\ No newline at end of file
diff --git a/src/py/calculate.py b/src/py/calculate.py
new file mode 100644
index 0000000..5a4f5f5
--- /dev/null
+++ b/src/py/calculate.py
@@ -0,0 +1,7 @@
+# In calculate.py
+
+# Doe je berekeningen hier, vervang 42 door je berekende waarde
+calculated_value = 42
+
+# Print het resultaat, dat zal worden gelezen door de PythonShell.run callback
+print(calculated_value)