Merge branch 'main' of https://github.com/Newtbot/MP
This commit is contained in:
commit
b3e2533ec0
@ -9,13 +9,13 @@ const sequelize = new Sequelize(
|
|||||||
process.env.DB_USER,
|
process.env.DB_USER,
|
||||||
process.env.DB_PASS,
|
process.env.DB_PASS,
|
||||||
{
|
{
|
||||||
host: "mpsqldatabase.mysql.database.azure.com",
|
host: "mpsqldatabasean.mysql.database.azure.com",
|
||||||
dialect: 'mysql',
|
dialect: 'mysql',
|
||||||
// attributeBehavior?: 'escape' | 'throw' | 'unsafe-legacy';
|
// attributeBehavior?: 'escape' | 'throw' | 'unsafe-legacy';
|
||||||
attributeBehavior: 'escape',
|
attributeBehavior: 'escape',
|
||||||
dialectOptions: {
|
dialectOptions: {
|
||||||
ssl: {
|
ssl: {
|
||||||
ca: fs.readFileSync(path.resolve(__dirname, '../cert/DigiCertGlobalRootCA.crt.pem')),
|
ca: fs.readFileSync(path.resolve(__dirname, '../cert/DigiCertGlobalRootCA.crt_3.pem')),
|
||||||
},
|
},
|
||||||
|
|
||||||
},
|
},
|
||||||
|
11
README.md
11
README.md
@ -7,16 +7,15 @@ i repeat DO NOT USE CREDS IN CODE! Please use .env files (https://www.npmjs.com/
|
|||||||
|
|
||||||
## Workload
|
## Workload
|
||||||
1) Ti Seng
|
1) Ti Seng
|
||||||
* Webserver Microservices
|
|
||||||
* IoT sensor
|
* IoT sensor
|
||||||
* Most Database / Backend Functions of this repo
|
* Most Database / Backend Functions of this repo
|
||||||
* consumer website api and user function
|
* consumer website api and user function
|
||||||
|
|
||||||
2) Sean
|
2) Sean
|
||||||
* Admin Website Microservice
|
* Admin Website Microservice
|
||||||
|
|
||||||
Micro Service
|
Micro Service
|
||||||
1) api.blah handle api
|
1) admin.blah admin website
|
||||||
2) admin.blah admin website
|
2) consumer.blah comsumer
|
||||||
3) consumer.blah comsumer
|
3) proxy.blah reverproxy
|
||||||
4) proxy.blah reverproxy
|
4) mqtt.blah mqtt service
|
||||||
5) mqtt.blah mqtt service
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
const { body } = require('express-validator');
|
const { validationResult, body } = require('express-validator');
|
||||||
|
|
||||||
const locationValidation = [
|
const locationValidation = [
|
||||||
body('name').trim().isLength({ min: 1 }).withMessage('Name must not be empty').escape(),
|
body('name').trim().isLength({ min: 1 }).withMessage('Name must not be empty').escape(),
|
||||||
@ -69,7 +69,34 @@ const createValidation = [
|
|||||||
body('jobTitle').trim().isLength({ min: 1 }).withMessage('Job title must not be empty').escape(),
|
body('jobTitle').trim().isLength({ min: 1 }).withMessage('Job title must not be empty').escape(),
|
||||||
];
|
];
|
||||||
|
|
||||||
|
function isStrongPassword(password) {
|
||||||
|
// Password must be at least 10 characters long
|
||||||
|
if (password.length < 10) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Password must contain at least one uppercase letter
|
||||||
|
if (!/[A-Z]/.test(password)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Password must contain at least one lowercase letter
|
||||||
|
if (!/[a-z]/.test(password)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Password must contain at least one digit
|
||||||
|
if (!/\d/.test(password)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Password must contain at least one symbol
|
||||||
|
if (!/[!@#$%^&*(),.?":{}|<>]/.test(password)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
module.exports = {
|
module.exports = {
|
||||||
locationValidation,locationValidationUpdate,locationdeleteValidation
|
locationValidation,locationValidationUpdate,locationdeleteValidation
|
||||||
,sensorValidation,sensorupdateValidation,sensordeleteValidation,loginValidation,otpValidation
|
,sensorValidation,sensorupdateValidation,sensordeleteValidation,loginValidation,otpValidation
|
||||||
|
@ -7,10 +7,10 @@ const crypto = require("crypto");
|
|||||||
const validator = require('validator');
|
const validator = require('validator');
|
||||||
const axios = require('axios');
|
const axios = require('axios');
|
||||||
|
|
||||||
const {validationResult } = require('express-validator');
|
const { validationResult } = require('express-validator');
|
||||||
const {locationValidation, locationValidationUpdate, locationdeleteValidation
|
const { locationValidation, locationValidationUpdate, locationdeleteValidation
|
||||||
,sensorValidation, sensorupdateValidation, sensordeleteValidation, loginValidation
|
,sensorValidation, sensorupdateValidation, sensordeleteValidation, loginValidation
|
||||||
,otpValidation, createValidation} = require('./modules/validationMiddleware');
|
,otpValidation, createValidation } = require('./modules/validationMiddleware');
|
||||||
const rateLimit = require('./modules/rateLimitMiddleware');
|
const rateLimit = require('./modules/rateLimitMiddleware');
|
||||||
const { generateOTP, sendOTPByEmail } = require('./modules/otpUtils');
|
const { generateOTP, sendOTPByEmail } = require('./modules/otpUtils');
|
||||||
const { format } = require('date-fns');
|
const { format } = require('date-fns');
|
||||||
@ -255,15 +255,15 @@ function isStrongPassword(password) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
app.post(
|
app.post
|
||||||
'/createUser', createValidation, async (req, res) => {
|
('/createUser', createValidation,
|
||||||
|
async (req, res) => {
|
||||||
try {
|
try {
|
||||||
const errors = validationResult(req);
|
const errors = validationResult(req);
|
||||||
|
|
||||||
if (!errors.isEmpty()) {
|
if (!errors.isEmpty()) {
|
||||||
return res.status(400).json({ errors: errors.array() });
|
return res.status(400).json({ errors: errors.array() });
|
||||||
}
|
}
|
||||||
|
|
||||||
const sessionTokencookie = req.cookies['sessionToken'];
|
const sessionTokencookie = req.cookies['sessionToken'];
|
||||||
|
|
||||||
// Verify sessionToken with the one stored in the database
|
// Verify sessionToken with the one stored in the database
|
||||||
@ -286,10 +286,6 @@ app.post(
|
|||||||
// Extract the username of the user creating a new user
|
// Extract the username of the user creating a new user
|
||||||
const creatorUsername = req.session.username; // Adjust this based on how you store the creator's username in your session
|
const creatorUsername = req.session.username; // Adjust this based on how you store the creator's username in your session
|
||||||
|
|
||||||
// Additional password complexity check
|
|
||||||
if (!isStrongPassword(password)) {
|
|
||||||
return res.status(400).json({ error: "Password does not meet complexity requirements" });
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if the username is already taken
|
// Check if the username is already taken
|
||||||
const existingUser = await User.findOne({ where: { username } });
|
const existingUser = await User.findOne({ where: { username } });
|
||||||
|
@ -57,7 +57,7 @@
|
|||||||
<a class="nav-link link text-black display-4" href="index.html#contacts02-9">Contacts</a>
|
<a class="nav-link link text-black display-4" href="index.html#contacts02-9">Contacts</a>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
<div class="navbar-buttons mbr-section-btn"><a class="btn btn-primary display-4" href="https://mobiri.se">Login</a></div>
|
<div class="navbar-buttons mbr-section-btn"><a class="btn btn-primary display-4" href="http://localhost:3000/login">Login</a></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
|
2
api.MD
2
api.MD
@ -172,4 +172,4 @@ http://localhost/api/v0/sensor-data/data?week=1&sensorid=1&locationid=1&page=2&p
|
|||||||
curl localhost/api/v0/user/register -H "Content-Type: application/json" -X POST -d '{"username": "testuser123", "password": "thisisthesystemuserpasswordnoob", "email": "testuser123@ecosaver.com", "address": "Nanyang Polytechnic 180 Ang Mo Kio Avenue 8 Singapore 569830", "phone": "12345678"}'
|
curl localhost/api/v0/user/register -H "Content-Type: application/json" -X POST -d '{"username": "testuser123", "password": "thisisthesystemuserpasswordnoob", "email": "testuser123@ecosaver.com", "address": "Nanyang Polytechnic 180 Ang Mo Kio Avenue 8 Singapore 569830", "phone": "12345678"}'
|
||||||
|
|
||||||
|
|
||||||
curl localhost:3000/api/v0/token/new -H "Content-Type: application/json" -X POST -d '{"userid": "5", "permission": "canRead"}'
|
curl localhost/api/v0/token/new -H "Content-Type: application/json" -X POST -d '{"userid": "5", "permission": "canRead"}'
|
||||||
|
@ -50,49 +50,48 @@ app.use("/", require("./routes/render"));
|
|||||||
// Catch 404 and forward to error handler. If none of the above routes are
|
// Catch 404 and forward to error handler. If none of the above routes are
|
||||||
// used, this is what will be called.
|
// used, this is what will be called.
|
||||||
app.use(function (req, res, next) {
|
app.use(function (req, res, next) {
|
||||||
//application/json; charset=utf-8
|
//application/json; charset=utf-8
|
||||||
if (req.is("application/json" || "application/json; charset=utf-8")) {
|
var err = new Error("Not Found");
|
||||||
var err = new Error("Not Found");
|
err.message = "Page not found";
|
||||||
err.message = "Page not found";
|
err.status = 404;
|
||||||
err.status = 404;
|
next(err);
|
||||||
next(err);
|
|
||||||
} else {
|
|
||||||
res.status(404).render("404");
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// Error handler. This is where `next()` will go on error
|
// Error handler. This is where `next()` will go on error
|
||||||
app.use(function (err, req, res, next) {
|
app.use(function (err, req, res, next) {
|
||||||
console.error(err.status || res.status, err.name, req.method, req.url);
|
console.error(err.status || res.status, err.name, req.method, req.url);
|
||||||
if (![404].includes(err.status || res.status)) {
|
|
||||||
console.error(err.message);
|
|
||||||
console.error(err.stack);
|
|
||||||
console.error("=========================================");
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log(err.name + " validation error");
|
// Parse key error for Sequilzw
|
||||||
// Parse key error for Sequilzw
|
let keyErrors = {};
|
||||||
let keyErrors = {};
|
if (["SequelizeValidationError"].includes(err.name) && err.errors) {
|
||||||
if (["SequelizeValidationError"].includes(err.name) && err.errors) {
|
for (let item of err.errors) {
|
||||||
for (let item of err.errors) {
|
if (item.path) {
|
||||||
if (item.path) {
|
keyErrors[item.path] = item.message;
|
||||||
keyErrors[item.path] = item.message;
|
}
|
||||||
}
|
}
|
||||||
}
|
res.status = 422;
|
||||||
res.status = 422;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (![404, 422].includes(err.status || res.status)) {
|
if (![404, 401, 422].includes(err.status || res.status)) {
|
||||||
console.error(err.message);
|
console.error(err.message);
|
||||||
console.error(err.stack);
|
console.error(err.stack);
|
||||||
console.error("=========================================");
|
console.error("=========================================");
|
||||||
}
|
}
|
||||||
|
res.status(err.status || 500);
|
||||||
|
// res.status(err.status || 500);
|
||||||
|
|
||||||
|
if (req.get('Content-Type') && req.get('Content-Type').includes("json")) {
|
||||||
res.status(err.status || 500);
|
res.json({
|
||||||
res.json({
|
name: err.name || "Unknown error",
|
||||||
name: err.name || "Unknown error",
|
message: err.message,
|
||||||
message: err.message,
|
keyErrors,
|
||||||
keyErrors,
|
});
|
||||||
});
|
}
|
||||||
|
else {
|
||||||
|
res.json({
|
||||||
|
name: err.name || "Unknown error",
|
||||||
|
message: err.message,
|
||||||
|
keyErrors,
|
||||||
|
});
|
||||||
|
}
|
||||||
});
|
});
|
@ -107,4 +107,6 @@ const sensorModel = sequelize.define(
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
sensorModel.belongsTo(locationModel);
|
||||||
|
|
||||||
module.exports = { sensorModel };
|
module.exports = { sensorModel };
|
||||||
|
@ -3,7 +3,7 @@ const { Sequelize, DataTypes } = require("sequelize");
|
|||||||
const { sequelize } = require("../mySQL");
|
const { sequelize } = require("../mySQL");
|
||||||
const { userModel } = require("./userModel");
|
const { userModel } = require("./userModel");
|
||||||
|
|
||||||
//sequelize.sync();
|
sequelize.sync();
|
||||||
const tokenModel = sequelize.define(
|
const tokenModel = sequelize.define(
|
||||||
"token",
|
"token",
|
||||||
{
|
{
|
||||||
|
@ -9,13 +9,13 @@ const sequelize = new Sequelize(
|
|||||||
process.env.DB_USER,
|
process.env.DB_USER,
|
||||||
process.env.DB_PASS,
|
process.env.DB_PASS,
|
||||||
{
|
{
|
||||||
host: "mpsqldatabase.mysql.database.azure.com",
|
host: "mpsqldatabasean.mysql.database.azure.com",
|
||||||
dialect: 'mysql',
|
dialect: 'mysql',
|
||||||
// attributeBehavior?: 'escape' | 'throw' | 'unsafe-legacy';
|
// attributeBehavior?: 'escape' | 'throw' | 'unsafe-legacy';
|
||||||
attributeBehavior: 'escape',
|
attributeBehavior: 'escape',
|
||||||
dialectOptions: {
|
dialectOptions: {
|
||||||
ssl: {
|
ssl: {
|
||||||
ca: fs.readFileSync(path.resolve(__dirname, '../cert/DigiCertGlobalRootCA.crt.pem')),
|
ca: fs.readFileSync(path.resolve(__dirname, '../cert/DigiCertGlobalRootCA.crt_3.pem')),
|
||||||
},
|
},
|
||||||
|
|
||||||
},
|
},
|
||||||
|
@ -1,19 +1,41 @@
|
|||||||
const { hash, compareHash } = require("./bcrypt.js");
|
|
||||||
const { tokenModel } = require("../database/model/tokenModel.js");
|
const { tokenModel } = require("../database/model/tokenModel.js");
|
||||||
|
const { userModel } = require("../database/model/userModel");
|
||||||
|
const { hash, compareHash } = require("./bcrypt.js");
|
||||||
const { generateUUID } = require("./generateUUID.js");
|
const { generateUUID } = require("./generateUUID.js");
|
||||||
|
const { isValid } = require("./isValid");
|
||||||
|
|
||||||
/*
|
async function getTokenByToken(token) {
|
||||||
1) take userid
|
const splitAuthToken = token.split("-");
|
||||||
2) generate random api key
|
const rowid = splitAuthToken[0];
|
||||||
3) hash the api key
|
const suppliedToken = splitAuthToken.slice(1).join("-");
|
||||||
4) append userid with - and api key
|
|
||||||
5) you give the user rowid-uuidv4
|
token = await tokenModel.findByPk(rowid, { include: userModel });
|
||||||
6) store in database
|
|
||||||
*/
|
token.isValid = await compareHash(suppliedToken, token.token); //true
|
||||||
//can be used for api key or token. Both are the same logic
|
console.log("function api getTokenByToken token", token.isValid);
|
||||||
async function addToken(userId, permission , expiry) {
|
token.isValid = token.isValid && isValid(token.expiration);
|
||||||
|
console.log("function api getTokenByToken token", token.isValid);
|
||||||
|
if (!token.isValid) {
|
||||||
|
//add boolean to token table
|
||||||
|
token.destroy();
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
console.log(
|
||||||
|
"function api getTokenByToken token",
|
||||||
|
await compareHash(suppliedToken, token.token),
|
||||||
|
isValid("token" , token.expiration)
|
||||||
|
);
|
||||||
|
*/
|
||||||
|
console.log(token.isValid);
|
||||||
|
return token;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function addToken(userId, permission, expiry) {
|
||||||
let uuid = await generateUUID();
|
let uuid = await generateUUID();
|
||||||
let hashtoken = await hash(uuid);
|
let hashtoken = await hash(uuid);
|
||||||
|
//console.log("user id", userId);
|
||||||
|
// return { token: token, userid: userRes.id, username: userRes.username };
|
||||||
|
// let token = await addToken(userRes.id , "canRead" , tokenToLive);
|
||||||
|
|
||||||
let token = await tokenModel.create({
|
let token = await tokenModel.create({
|
||||||
userid: userId,
|
userid: userId,
|
||||||
@ -26,23 +48,4 @@ async function addToken(userId, permission , expiry) {
|
|||||||
return token.id + "-" + uuid;
|
return token.id + "-" + uuid;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function checkToken(Supplied, rowid) {
|
module.exports = { addToken, getTokenByToken };
|
||||||
try {
|
|
||||||
const retrivedToken = await tokenModel.findOne({
|
|
||||||
raw: true,
|
|
||||||
attributes: ["token", "permission"],
|
|
||||||
where: {
|
|
||||||
id: rowid,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
//console.log(retrivedKey.apikey);
|
|
||||||
if (compareHash(Supplied, retrivedToken.token)) {
|
|
||||||
//return true;
|
|
||||||
return retrivedToken.permission;
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.error(error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = { addToken , checkToken };
|
|
||||||
|
@ -1,20 +1,14 @@
|
|||||||
const moment = require("moment");
|
|
||||||
const currentTime = moment().format("YYYY-MM-DD HH:mm:ss");
|
|
||||||
|
|
||||||
//time is taken from the token
|
//time is taken from the token
|
||||||
function isValid(time){
|
function isValid(time) {
|
||||||
const timeDiff = moment(currentTime).diff(time, "minutes");
|
|
||||||
|
|
||||||
if (timeDiff > 1) {
|
if (
|
||||||
console.log(timeDiff);
|
Math.floor(new Date(time).getTime() / 1000) <
|
||||||
return false;
|
Math.floor(new Date().getTime() / 1000)
|
||||||
}
|
) {
|
||||||
|
return false;
|
||||||
return true;
|
}
|
||||||
|
return true;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
module.exports = { isValid };
|
module.exports = { isValid };
|
82
consumerWebsite/functions/nodeMail.js
Normal file
82
consumerWebsite/functions/nodeMail.js
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
const { transporter } = require("../modules/nodemailer");
|
||||||
|
const path = require("path");
|
||||||
|
require("dotenv").config({ path: path.resolve(__dirname, "../.env") });
|
||||||
|
|
||||||
|
/*
|
||||||
|
var message = {
|
||||||
|
from: "sender@server.com",
|
||||||
|
to: "receiver@sender.com",
|
||||||
|
subject: "Message title",
|
||||||
|
text: "Plaintext version of the message",
|
||||||
|
html: "<p>HTML version of the message</p>",
|
||||||
|
};
|
||||||
|
//send mail with defined transport object
|
||||||
|
transporter.sendMail(data[, callback])
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
async function sendContactEmail(email, name, message) {
|
||||||
|
console.log(email, name, message);
|
||||||
|
|
||||||
|
try {
|
||||||
|
let contactMessage = await transporter.sendMail({
|
||||||
|
to: process.env.euser,
|
||||||
|
subject: "Contact us Message",
|
||||||
|
html: `
|
||||||
|
<h1>Contact us Message</h1>
|
||||||
|
<p><strong>From:</strong> ${name}</p>
|
||||||
|
<p><strong>User Email:</strong> ${email}</p>
|
||||||
|
<p><strong>Message:</strong> ${message}</p>
|
||||||
|
<p>Thank you for contacting us. We will get back to you as soon as possible.</p>
|
||||||
|
<p>Regards,</p>
|
||||||
|
<p>EcoSaver Team</p>
|
||||||
|
<p><a href="https://ecosaver.teeseng.uk/">EcoSaver Website</a></p>
|
||||||
|
<p>Please do not reply to this email.</p>
|
||||||
|
`,
|
||||||
|
});
|
||||||
|
transporter.sendMail({ contactMessage }, function (error, info) {
|
||||||
|
if (error) {
|
||||||
|
console.log(error);
|
||||||
|
} else {
|
||||||
|
console.log("Email sent: " + info.response);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function sendTokenEmail(email, token) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
let tokenMessage = await transporter.sendMail({
|
||||||
|
to: email,
|
||||||
|
from: process.env.euser,
|
||||||
|
subject: "API Token",
|
||||||
|
html: `
|
||||||
|
<h1>API Token</h1>
|
||||||
|
<p><strong>Token:</strong> ${token}</p>
|
||||||
|
<p>Please do not lose this token and do not share your token with anyone!</p>
|
||||||
|
<p>Thank you for using EcoSaver.</p>
|
||||||
|
<p>Regards,</p>
|
||||||
|
<p>EcoSaver Team</p>
|
||||||
|
<p><a href="https://ecosaver.teeseng.uk/">EcoSaver Website</a></p>
|
||||||
|
<p>Please do not reply to this email.</p>
|
||||||
|
|
||||||
|
`,
|
||||||
|
});
|
||||||
|
transporter.sendMail({ tokenMessage }, function (error, info) {
|
||||||
|
if (error) {
|
||||||
|
console.log(error);
|
||||||
|
} else {
|
||||||
|
console.log("Email sent: " + info.response);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
module.exports = { sendContactEmail , sendTokenEmail };
|
@ -18,15 +18,17 @@ async function getSensorData() {
|
|||||||
const sensorData = await sensorDataModel.findAll();
|
const sensorData = await sensorDataModel.findAll();
|
||||||
return sensorData;
|
return sensorData;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function addSensorData(id_sensor, id_location, sensordata) {
|
async function addSensorData(id_sensor, id_location, sensordata) {
|
||||||
const sensorData = await sensorDataModel.create({
|
const sensorData = await sensorDataModel.create({
|
||||||
sensorid: id_sensor,
|
sensorid: id_sensor,
|
||||||
locationid: id_location,
|
locationid: id_location ,
|
||||||
measurement: sensordata,
|
measurement: sensordata.measurement,
|
||||||
});
|
});
|
||||||
io().emit('sensorData:new', sensorData)
|
//console.log("sensorData", sensorData);
|
||||||
|
//console.log("sensorData", sensordata.measurement);
|
||||||
|
|
||||||
|
|
||||||
|
io().emit('sensorData:new', sensordata)
|
||||||
return sensorData;
|
return sensorData;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -61,6 +63,14 @@ async function getSensorDataById(id) {
|
|||||||
});
|
});
|
||||||
return sensorData;
|
return sensorData;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function getLatestData() {
|
||||||
|
const sensorData = await sensorDataModel.findAll({
|
||||||
|
limit: 6,
|
||||||
|
order: [["createdAt", "DESC"]],
|
||||||
|
});
|
||||||
|
return sensorData;
|
||||||
|
}
|
||||||
var ormQuery = {};
|
var ormQuery = {};
|
||||||
var whereClause = {};
|
var whereClause = {};
|
||||||
var whereDate = {};
|
var whereDate = {};
|
||||||
@ -724,5 +734,6 @@ module.exports = {
|
|||||||
getSensorDataById,
|
getSensorDataById,
|
||||||
getData,
|
getData,
|
||||||
getDatabyRange,
|
getDatabyRange,
|
||||||
|
getLatestData,
|
||||||
|
|
||||||
};
|
};
|
@ -2,7 +2,6 @@ const { Op } = require('sequelize')
|
|||||||
const { hash, compareHash } = require("./bcrypt.js");
|
const { hash, compareHash } = require("./bcrypt.js");
|
||||||
const { addToken } = require("./api");
|
const { addToken } = require("./api");
|
||||||
const { userModel } = require("../database/model/userModel");
|
const { userModel } = require("../database/model/userModel");
|
||||||
moment = require('moment')
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -21,6 +20,16 @@ async function getUserByID(userid) {
|
|||||||
return userRes;
|
return userRes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function getUserByEmail(email) {
|
||||||
|
let userRes = await userModel.findOne({
|
||||||
|
where: {
|
||||||
|
email: email,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
if (!userRes) return false;
|
||||||
|
return userRes;
|
||||||
|
}
|
||||||
|
|
||||||
//api/v0/auth/register
|
//api/v0/auth/register
|
||||||
/* Registering new user
|
/* Registering new user
|
||||||
1) req.body is taken from html form or wtv
|
1) req.body is taken from html form or wtv
|
||||||
@ -71,9 +80,11 @@ async function loginUser(user) {
|
|||||||
if (!match) return false;
|
if (!match) return false;
|
||||||
//console.log('loginUser', userRes.id, userRes.username);
|
//console.log('loginUser', userRes.id, userRes.username);
|
||||||
|
|
||||||
//generate token and permission and experiation time
|
//generate token and permission and experiation time + 30 mins
|
||||||
const currentTime = moment().format('YYYY-MM-DD HH:mm:ss');
|
//let tokenToLive = moment().add(30, 'minutes').format();
|
||||||
let token = await addToken(userRes.id , "canRead" , currentTime);
|
let currentDate = new Date();
|
||||||
|
let tokenToLive = new Date(currentDate.getTime() + 30 * 60000);
|
||||||
|
let token = await addToken(userRes.id , "canRead" , tokenToLive);
|
||||||
return { token: token, userid: userRes.id, username: userRes.username };
|
return { token: token, userid: userRes.id, username: userRes.username };
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -130,9 +141,23 @@ async function updateProfile(user, body) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function checkEmail(email) {
|
||||||
|
let emailRes = await userModel.findOne({
|
||||||
|
where: {
|
||||||
|
email: email,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
if (!emailRes) return false;
|
||||||
|
return true;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
getUserByID,
|
getUserByID,
|
||||||
|
getUserByEmail,
|
||||||
addUser,
|
addUser,
|
||||||
loginUser,
|
loginUser,
|
||||||
updateProfile,
|
updateProfile,
|
||||||
|
checkEmail
|
||||||
};
|
};
|
@ -1,68 +1,48 @@
|
|||||||
const { tokenModel } = require("../database/model/tokenModel");
|
const { getTokenByToken } = require("../functions/api");
|
||||||
const { userModel } = require("../database/model/userModel");
|
|
||||||
const { compareHash } = require("../functions/bcrypt");
|
|
||||||
const { checkToken } = require("../functions/api");
|
|
||||||
const { isValid } = require("../functions/isValid");
|
|
||||||
|
|
||||||
|
const permissionError = new Error('PermissionError')
|
||||||
|
permissionError.name = "Inadequate Permission Error"
|
||||||
|
permissionError.status = 401
|
||||||
|
permissionError.message = "Inadequate permission to complete this response"
|
||||||
|
|
||||||
async function auth(req, res, next) {
|
async function auth(req, res, next) {
|
||||||
try {
|
try {
|
||||||
const authToken = req.header("auth-token");
|
const token = await getTokenByToken(req.header("auth-token"));
|
||||||
if (!authToken) {
|
|
||||||
const error = new Error("No Token key was supplied. Invalid request");
|
if (!token || !token.isValid){
|
||||||
throw error;
|
throw permissionError;
|
||||||
}
|
}
|
||||||
|
|
||||||
const splitAuthToken = authToken.split("-");
|
|
||||||
const rowid = splitAuthToken[0];
|
|
||||||
const suppliedToken = splitAuthToken.slice(1).join("-");
|
|
||||||
|
|
||||||
const token = await tokenModel.findByPk(rowid, { include: userModel });
|
|
||||||
|
|
||||||
if (!token) {
|
|
||||||
const error = new Error("Token key not found. Invalid request");
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
|
|
||||||
const isMatch = await compareHash(suppliedToken, token.token);
|
|
||||||
|
|
||||||
console.log(isMatch);
|
|
||||||
if (!isMatch) {
|
|
||||||
const error = new Error("Token key not found. Invalid request");
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
//if token is a match
|
//if token is a match
|
||||||
req.token = token;
|
req.token = token;
|
||||||
req.user = await token.getUser();
|
req.user = await token.getUser();
|
||||||
const permission = await checkToken(suppliedToken, rowid);
|
|
||||||
|
|
||||||
const route = req.originalUrl.split("?")[0]; // Removing query parameters
|
const route = req.originalUrl.split("?")[0]; // Removing query parameters
|
||||||
//if route is from user/ and permission is canRead allow it to do CRUD
|
//if route is from user/ and permission is canRead allow it to do CRUD
|
||||||
if (route.includes("/user/") && permission === "canRead") {
|
if (route.includes("/user/") || route.includes("/token/") && token.permission === "canRead") {
|
||||||
next();
|
console.log("user route");
|
||||||
|
return next();
|
||||||
}
|
}
|
||||||
if ((req.method === "GET" && permission === "canRead") || (["GET", "POST", "PUT", "DELETE"].includes(req.method) && permission === "canWrite")) {
|
if ((req.method === "GET" && token.permission === "canRead")){
|
||||||
next();
|
console.log("wtf you shldnt be here");
|
||||||
}
|
return next();
|
||||||
|
|
||||||
if (!isValid(token.expiration)){
|
|
||||||
req.token.destroy();
|
|
||||||
throw new Error("Token expired");
|
|
||||||
}
|
}
|
||||||
|
if (["GET", "POST", "PUT", "DELETE"].includes(req.method) && token.permission === "canWrite") {
|
||||||
|
console.log("wtf you shldnt be here");
|
||||||
|
return next();
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
if ((req.method === "GET" && token.permission === "canRead") ||
|
||||||
|
(["GET", "POST", "PUT", "DELETE"].includes(req.method) && token.permission === "canWrite")) {
|
||||||
|
return next();
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
throw permissionError
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
next(error);
|
next(error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = { auth };
|
module.exports = { auth };
|
||||||
|
|
||||||
/*
|
|
||||||
else {
|
|
||||||
const error = new Error("Insufficient permission");
|
|
||||||
error.status = 401;
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
|
|
||||||
*/
|
|
@ -2,6 +2,7 @@ const nodemailer = require("nodemailer");
|
|||||||
const dotenv = require("dotenv");
|
const dotenv = require("dotenv");
|
||||||
const path = require('path')
|
const path = require('path')
|
||||||
require('dotenv').config({ path: path.resolve(__dirname, '../.env') })
|
require('dotenv').config({ path: path.resolve(__dirname, '../.env') })
|
||||||
|
//.env
|
||||||
|
|
||||||
let transporter = nodemailer.createTransport({
|
let transporter = nodemailer.createTransport({
|
||||||
service: 'gmail',
|
service: 'gmail',
|
||||||
|
@ -3812,6 +3812,7 @@
|
|||||||
|
|
||||||
.card-text {
|
.card-text {
|
||||||
color: #000000;
|
color: #000000;
|
||||||
|
font-size: 16px;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* edit profile */
|
/* edit profile */
|
||||||
|
@ -528,23 +528,22 @@ body.one-content-column-version .content thead {
|
|||||||
|
|
||||||
|
|
||||||
.generate-key-button {
|
.generate-key-button {
|
||||||
float: right; /* Align the button to the right */
|
margin-top: -40px;
|
||||||
margin-right: 85%;
|
margin-left: 25px;
|
||||||
margin-top: -40px; /* Adjust the margin-top value based on your layout */
|
|
||||||
/* Add any additional styling you want for the button */
|
|
||||||
}
|
|
||||||
|
|
||||||
#content-get-api .generate-key-button {
|
|
||||||
background-color: #4caf50; /* Green background color */
|
background-color: #4caf50; /* Green background color */
|
||||||
color: white; /* White text color */
|
color: #ffffff;
|
||||||
padding: 5px 11px; /* Padding for the button */
|
padding: 5px 11px; /* Padding for the button */
|
||||||
border: none; /* Remove button border */
|
border: none; /* Remove button border */
|
||||||
border-radius: 5px; /* Add border-radius for rounded corners */
|
border-radius: 5px; /* Add border-radius for rounded corners */
|
||||||
cursor: pointer; /* Add pointer cursor on hover */
|
cursor: pointer; /* Add pointer cursor on hover */
|
||||||
font-size: 14px; /* Font size */
|
font-size: 14px; /* Font size */
|
||||||
}
|
}
|
||||||
|
.api-form {
|
||||||
|
margin-top: 20px;
|
||||||
|
margin-left: 25px;
|
||||||
|
}
|
||||||
|
|
||||||
#content-get-api .generate-key-button:hover {
|
.generate-key-button:hover {
|
||||||
background-color: #45a049; /* Darker green on hover */
|
background-color: #45a049; /* Darker green on hover */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -186,9 +186,7 @@ app.auth = (function (app) {
|
|||||||
function isLoggedIn(callback) {
|
function isLoggedIn(callback) {
|
||||||
|
|
||||||
if (getToken()) {
|
if (getToken()) {
|
||||||
console.log("you shldnt appear at all");
|
|
||||||
return app.api.get("user/me", function (error, data) {
|
return app.api.get("user/me", function (error, data) {
|
||||||
console.log(error, data);
|
|
||||||
if (!error) app.auth.user = data;
|
if (!error) app.auth.user = data;
|
||||||
return callback(error, data);
|
return callback(error, data);
|
||||||
});
|
});
|
||||||
@ -287,7 +285,7 @@ function formAJAX(btn, del) {
|
|||||||
//console.log('Data being sent to', $form.attr('action'), formData)
|
//console.log('Data being sent to', $form.attr('action'), formData)
|
||||||
|
|
||||||
app.api[method]($form.attr("action"), formData, function (error, data) {
|
app.api[method]($form.attr("action"), formData, function (error, data) {
|
||||||
//console.log('Data back from the server', error, data)
|
console.log('Data back from the server', error, data)
|
||||||
app.util.actionMessage(data.message, $form, error ? "danger" : "success"); //re-populate table
|
app.util.actionMessage(data.message, $form, error ? "danger" : "success"); //re-populate table
|
||||||
if (!error) {
|
if (!error) {
|
||||||
$form.trigger("reset");
|
$form.trigger("reset");
|
||||||
|
@ -18,5 +18,8 @@ router.use('/sensor', [auth, APIlogger], require('./sensor.js'));
|
|||||||
//sensor data route
|
//sensor data route
|
||||||
router.use('/sensor-data', [auth, APIlogger], require('./sensorData.js'));
|
router.use('/sensor-data', [auth, APIlogger], require('./sensorData.js'));
|
||||||
|
|
||||||
|
//latest sensor data to display on dashboard
|
||||||
|
router.use('/latest-sensor-data', [APIlogger], require('./latestsensorData.js'));
|
||||||
|
|
||||||
module.exports = router;
|
module.exports = router;
|
||||||
|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
const { addUser, loginUser } = require("../functions/user");
|
const { addUser, loginUser, checkEmail } = require("../functions/user");
|
||||||
|
const { sendContactEmail } = require("../functions/nodeMail");
|
||||||
|
|
||||||
const express = require("express");
|
const express = require("express");
|
||||||
const router = express.Router();
|
const router = express.Router();
|
||||||
@ -12,12 +13,11 @@ router.post("/register", async (req, res, next) => {
|
|||||||
error.message = "The user failed to be craated";
|
error.message = "The user failed to be craated";
|
||||||
error.status = 400;
|
error.status = 400;
|
||||||
return next(error);
|
return next(error);
|
||||||
|
} else {
|
||||||
|
return res.json({
|
||||||
|
message: "User created successfully",
|
||||||
|
});
|
||||||
}
|
}
|
||||||
else{
|
|
||||||
return res.json({
|
|
||||||
message: "User created successfully",
|
|
||||||
});
|
|
||||||
}
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(error);
|
console.error(error);
|
||||||
next(error);
|
next(error);
|
||||||
@ -29,20 +29,18 @@ router.post("/login", async (req, res, next) => {
|
|||||||
try {
|
try {
|
||||||
let Res = await loginUser(req.body);
|
let Res = await loginUser(req.body);
|
||||||
if (Res == false) {
|
if (Res == false) {
|
||||||
let error = new Error("User Login Failed");
|
let error = new Error("User Login Failed");
|
||||||
error.status = 400;
|
error.status = 400;
|
||||||
return next(error);
|
return next(error);
|
||||||
|
} else {
|
||||||
|
//pass res back to form to be set in local storage
|
||||||
|
return res.json({
|
||||||
|
message: "User login successfully",
|
||||||
|
token: Res.token,
|
||||||
|
userid: Res.userid,
|
||||||
|
username: Res.username,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
else{
|
|
||||||
//pass res back to form to be set in local storage
|
|
||||||
return res.json({
|
|
||||||
message: "User login successfully",
|
|
||||||
token: Res.token,
|
|
||||||
userid: Res.userid,
|
|
||||||
username: Res.username,
|
|
||||||
});
|
|
||||||
|
|
||||||
}
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(error);
|
console.error(error);
|
||||||
next(error);
|
next(error);
|
||||||
@ -52,8 +50,26 @@ router.post("/login", async (req, res, next) => {
|
|||||||
//contact
|
//contact
|
||||||
//auth/contact
|
//auth/contact
|
||||||
router.post("/contact", async (req, res, next) => {
|
router.post("/contact", async (req, res, next) => {
|
||||||
|
try {
|
||||||
|
//console.log(req.body);
|
||||||
|
let Res = await checkEmail(req.body.email);
|
||||||
|
if (!Res) {
|
||||||
|
let error = new Error("Email not found");
|
||||||
|
error.status = 400;
|
||||||
|
return next(error);
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
//console.log(Res);
|
||||||
|
sendContactEmail(req.body.email, req.body.name, req.body.message);
|
||||||
|
return res.json({
|
||||||
|
message: "Email sent successfully",
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error);
|
||||||
|
next(error);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
module.exports = router;
|
module.exports = router;
|
||||||
|
|
||||||
|
21
consumerWebsite/routes/latestsensorData.js
Normal file
21
consumerWebsite/routes/latestsensorData.js
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
const {
|
||||||
|
getLatestData,
|
||||||
|
|
||||||
|
} = require("../functions/sensorData");
|
||||||
|
|
||||||
|
const express = require("express");
|
||||||
|
const router = express.Router();
|
||||||
|
|
||||||
|
router.get("/data", async (req, res, next) => {
|
||||||
|
try {
|
||||||
|
console.log(req.query);
|
||||||
|
const data = await getLatestData();
|
||||||
|
res.status(200).json(data);
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error);
|
||||||
|
next(error);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
module.exports = router;
|
@ -1,4 +1,7 @@
|
|||||||
const { addToken } = require("../functions/api");
|
const { addToken } = require("../functions/api");
|
||||||
|
const { checkEmail , getUserByEmail } = require("../functions/user");
|
||||||
|
const { sendTokenEmail } = require("../functions/nodeMail");
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const express = require("express");
|
const express = require("express");
|
||||||
@ -15,8 +18,29 @@ const router = express.Router();
|
|||||||
//'{"userid": "5", "permission": "canRead" ,}'
|
//'{"userid": "5", "permission": "canRead" ,}'
|
||||||
router.post("/new", async (req, res, next) => {
|
router.post("/new", async (req, res, next) => {
|
||||||
try {
|
try {
|
||||||
const token = await addToken(req.body.userid, req.body.permission , "2204-01-24 07:34:36" );
|
//console.log(req.body);
|
||||||
res.json({token: token});
|
const Res = await checkEmail(req.body.email);
|
||||||
|
if (!Res) {
|
||||||
|
let error = new Error("Email not found");
|
||||||
|
error.status = 400;
|
||||||
|
return next(error);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//console.log("email found");
|
||||||
|
let userid = await getUserByEmail(req.body.email);
|
||||||
|
if (!userid) return false;
|
||||||
|
|
||||||
|
const token = await addToken(userid.id, "canRead" , "2204-01-24 07:34:36" );
|
||||||
|
if (!token) return false;
|
||||||
|
sendTokenEmail(req.body.email, token);
|
||||||
|
res.json({
|
||||||
|
message: "Token generated successfully and sent to email",
|
||||||
|
})
|
||||||
|
|
||||||
|
}
|
||||||
|
//const token = await addToken(req.body.userid, "canRead" , "2204-01-24 07:34:36" );
|
||||||
|
//res.json({token: token});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(error);
|
console.error(error);
|
||||||
next(error);
|
next(error);
|
||||||
|
@ -8,7 +8,7 @@ const router = express.Router();
|
|||||||
router.get("/me", async function (req, res, next) {
|
router.get("/me", async function (req, res, next) {
|
||||||
try {
|
try {
|
||||||
let user = await getUserByID(req.user);
|
let user = await getUserByID(req.user);
|
||||||
console.log(user);
|
//console.log(user);
|
||||||
res.json({
|
res.json({
|
||||||
user: user,
|
user: user,
|
||||||
});
|
});
|
||||||
|
@ -5,8 +5,12 @@
|
|||||||
https://github.com/ticlekiwi/API-Documentation-HTML-Template
|
https://github.com/ticlekiwi/API-Documentation-HTML-Template
|
||||||
!-->
|
!-->
|
||||||
|
|
||||||
<%- include('top') %>
|
<%- include('top') %>
|
||||||
<link rel="stylesheet" href="css/api.css" media="all">
|
<script type="text/javascript">
|
||||||
|
// Require login to see this page.
|
||||||
|
app.auth.forceLogin()
|
||||||
|
</script>
|
||||||
|
<link rel="stylesheet" href="css/api.css" media="all">
|
||||||
|
|
||||||
<body class="one-content-column-version">
|
<body class="one-content-column-version">
|
||||||
<div class="left-menu">
|
<div class="left-menu">
|
||||||
@ -50,353 +54,633 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
<div class="content-page">
|
<div class="content-page">
|
||||||
<div class="content">
|
<div class="content">
|
||||||
<div class="overflow-hidden content-section" id="content-get-started">
|
<div class="overflow-hidden content-section" id="content-get-started">
|
||||||
<h1>Get started</h1>
|
<h1>Get started</h1>
|
||||||
<p>
|
|
||||||
The following API is provided by the Eco saver developer team. It allows you to get Location and
|
|
||||||
Sensor and Sensor Data from the Eco saver database.
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
To use this API, you need an <strong>API key</strong>.
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
<div class="overflow-hidden content-section" id="content-get-location">
|
|
||||||
<h2>Get all location</h2>
|
|
||||||
<p>
|
|
||||||
To get Location of sensors you need to make a GET call to the following url :<br>
|
|
||||||
<code class="higlighted break-word">https://api.teeseng.uk/api/v0/location</code>
|
|
||||||
<br>
|
|
||||||
<br>
|
|
||||||
Return Response :<br>
|
|
||||||
<code class="higlighted break-word">{"status":"200"}</code>
|
|
||||||
</p>
|
|
||||||
<br>
|
|
||||||
<h4>QUERY PARAMETERS</h4>
|
|
||||||
<table>
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th>Field</th>
|
|
||||||
<th>Type</th>
|
|
||||||
<th>Description</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
<tr>
|
|
||||||
<td>Authorization</td>
|
|
||||||
<td>JSON</td>
|
|
||||||
<td>Your API key.</td>
|
|
||||||
<td>(Required) Example: curl https://api.teeseng.uk/api/v0/location -H "Authorization:
|
|
||||||
{provide your
|
|
||||||
API key here}"</td>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
<div class="overflow-hidden content-section" id="content-get-location-by-id">
|
|
||||||
<h2>Get location by ID</h2>
|
|
||||||
<p>
|
|
||||||
To get Location you need to make a GET call to the following url :<br>
|
|
||||||
<code class="higlighted break-word">https://api.teeseng.uk/api/v0/location/{id}</code>
|
|
||||||
<br>
|
|
||||||
<br>
|
|
||||||
Return Response :<br>
|
|
||||||
<code class="higlighted break-word">{"status":"200"}</code>
|
|
||||||
</p>
|
|
||||||
<br>
|
|
||||||
<h4>QUERY PARAMETERS</h4>
|
|
||||||
<table>
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th>Field</th>
|
|
||||||
<th>Type</th>
|
|
||||||
<th>Description</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
<tr>
|
|
||||||
<td>Authorization</td>
|
|
||||||
<td>JSON</td>
|
|
||||||
<td>(Required) Your API key.</td>
|
|
||||||
<td>Example: curl https://api.teeseng.uk/api/v0/location -H "Authorization: {provide
|
|
||||||
your
|
|
||||||
API key here}"</td>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
<div class="overflow-hidden content-section" id="content-add-location">
|
|
||||||
<h2>Add Location (Only for system or admin API key)</h2>
|
|
||||||
<p>
|
|
||||||
To add an Location you need to make a POST call to the following url :<br>
|
|
||||||
<code class="higlighted break-word">https://api.teeseng.uk/api/v0/location/new</code>
|
|
||||||
<br>
|
|
||||||
<br>
|
|
||||||
Example :<br>
|
|
||||||
<code
|
|
||||||
class="higlighted break-word">curl https://api.teeseng.uk/api/v0/location/new -H "Content-Type: application/json" -X POST -d '{"name": "SAMPLE", "added_by": "system" , "description": "test"}'</code>
|
|
||||||
<br>
|
|
||||||
<br>
|
|
||||||
Return Response :<br>
|
|
||||||
<code class="higlighted break-word">{"status":"200"}</code>
|
|
||||||
</p>
|
|
||||||
<br>
|
|
||||||
<h4>QUERY PARAMETERS</h4>
|
|
||||||
<table>
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th>Field</th>
|
|
||||||
<th>Type</th>
|
|
||||||
<th>Description</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
<tr>
|
|
||||||
<td>Authorization</td>
|
|
||||||
<td>JSON</td>
|
|
||||||
<td>Your API key.</td>
|
|
||||||
<td>(Required) Example: curl https://api.teeseng.uk/api/v0/location/new -H
|
|
||||||
"Authorization: {provide your
|
|
||||||
API key here}"</td>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>Location name</td>
|
|
||||||
<td>JSON</td>
|
|
||||||
<td>Location name.</td>
|
|
||||||
<td>(Required) Location name. Example: curl https://api.teeseng.uk/api/v0/location/new
|
|
||||||
-H "Authorization: provide
|
|
||||||
your API key here" -d '{"name":"Location name"}'</td>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>Added by </td>
|
|
||||||
<td>JSON</td>
|
|
||||||
<td>System or Admin</td>
|
|
||||||
<td>(Required) System or Admin Example: curl https://api.teeseng.uk/api/v0/location/new
|
|
||||||
-H "Authorization: provide
|
|
||||||
your API key here" -d '{"added_by":"system"}'</td>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>Description</td>
|
|
||||||
<td>JSON</td>
|
|
||||||
<td>Description of Location</td>
|
|
||||||
<td>(Required) System or Admin Example: curl https://api.teeseng.uk/api/v0/location/new
|
|
||||||
-H "Authorization: provide
|
|
||||||
your API key here" -d '{"description":"test"}'</td>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
<!-- update -->
|
|
||||||
<div class="overflow-hidden content-section" id="content-update-location-by-id">
|
|
||||||
<h2>Update Location (Only for system or admin API key)</h2>
|
|
||||||
<p>
|
|
||||||
To update an Location you need to make a PUT call to the following url :<br>
|
|
||||||
<code class="higlighted break-word">https://api.teeseng.uk/api/v0/location/update</code>
|
|
||||||
<br>
|
|
||||||
<br>
|
|
||||||
Example :<br>
|
|
||||||
<code
|
|
||||||
class="higlighted break-word">curl https://api.teeseng.uk/api/v0/location/update -H "Content-Type: application/json" -X POST -d '{"id": "7" , "name": "SAMPLE", "added_by": "system" , "description": "test"}'</code>
|
|
||||||
<br>
|
|
||||||
<br>
|
|
||||||
Return Response :<br>
|
|
||||||
<code class="higlighted break-word">{"status":"200","message":"Location 7 updated"}</code>
|
|
||||||
</p>
|
|
||||||
<br>
|
|
||||||
<h4>QUERY PARAMETERS</h4>
|
|
||||||
<table>
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th>Field</th>
|
|
||||||
<th>Type</th>
|
|
||||||
<th>Description</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
<tr>
|
|
||||||
<td>Authorization</td>
|
|
||||||
<td>JSON</td>
|
|
||||||
<td>Your API key.</td>
|
|
||||||
<td>(Required) example: curl https://api.teeseng.uk/api/v0/location/update -H
|
|
||||||
"Authorization: {provide your
|
|
||||||
API key here}"</td>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>ID</td>
|
|
||||||
<td>JSON</td>
|
|
||||||
<td>Location ID</td>
|
|
||||||
<td>(Required) Location ID Example: curl https://api.teeseng.uk/api/v0/location/update
|
|
||||||
-H "Authorization: provide
|
|
||||||
your API key here" -d '{"id": "7"}'</td>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>Location name</td>
|
|
||||||
<td>JSON</td>
|
|
||||||
<td>Location name.</td>
|
|
||||||
<td>(Optional) Location name. Example: curl https://api.teeseng.uk/api/v0/location/new
|
|
||||||
-H "Authorization: provide
|
|
||||||
your API key here" -d '{"name":"Location name"}'</td>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>Added by </td>
|
|
||||||
<td>JSON</td>
|
|
||||||
<td>System or Admin</td>
|
|
||||||
<td>(Optional) System or Admin Example: curl https://api.teeseng.uk/api/v0/location/new
|
|
||||||
-H "Authorization: provide
|
|
||||||
your API key here" -d '{"added_by":"system"}'</td>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>Description</td>
|
|
||||||
<td>JSON</td>
|
|
||||||
<td>Description of Location</td>
|
|
||||||
<td>(Optional) System or Admin Example: curl https://api.teeseng.uk/api/v0/location/new
|
|
||||||
-H "Authorization: provide
|
|
||||||
your API key here" -d '{"description":"test"}'</td>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
<!-- delete location -->
|
|
||||||
<div class="overflow-hidden content-section" id="content-update-location-by-id">
|
|
||||||
<h2>Delete Location (Only for system or admin API key)</h2>
|
|
||||||
<p>
|
|
||||||
To delete an Location you need to make a DELETE call to the following url :<br>
|
|
||||||
<code class="higlighted break-word">https://api.teeseng.uk/api/v0/location/delete</code>
|
|
||||||
<br>
|
|
||||||
<br>
|
|
||||||
Example :<br>
|
|
||||||
<code
|
|
||||||
class="higlighted break-word">curl https://api.teeseng.uk/api/v0/location/delete -H "Content-Type: application/json" -X POST -d '{"id": "7"}'</code>
|
|
||||||
</p>
|
|
||||||
<br>
|
|
||||||
<h4>QUERY PARAMETERS</h4>
|
|
||||||
<table>
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th>Field</th>
|
|
||||||
<th>Type</th>
|
|
||||||
<th>Description</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
<tr>
|
|
||||||
<td>Authorization</td>
|
|
||||||
<td>JSON</td>
|
|
||||||
<td>Your API key.</td>
|
|
||||||
<td>(Required) example: curl https://api.teeseng.uk/api/v0/location/delete -H
|
|
||||||
"Authorization: {provide your
|
|
||||||
API key here}"</td>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>ID</td>
|
|
||||||
<td>JSON</td>
|
|
||||||
<td>Location ID</td>
|
|
||||||
<td>(Required) Location ID Example: curl https://api.teeseng.uk/api/v0/location/delete
|
|
||||||
-H "Authorization: provide
|
|
||||||
your API key here" -d '{"id": "7"}'</td>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="overflow-hidden content-section" id="content-errors">
|
|
||||||
<h2>Errors</h2>
|
|
||||||
<p>
|
|
||||||
The Westeros API uses the following error codes:
|
|
||||||
</p>
|
|
||||||
<table>
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th>Error Code</th>
|
|
||||||
<th>Meaning</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
<tr>
|
|
||||||
<td>X000</td>
|
|
||||||
<td>
|
|
||||||
Some parameters are missing. This error appears when you don't pass every mandatory
|
|
||||||
parameters.
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>403</td>
|
|
||||||
<td>
|
|
||||||
Unknown or unvalid <code class="higlighted">secret_key</code>. This error appears if
|
|
||||||
you use an unknow API key or if your API key expired.
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>500</td>
|
|
||||||
<td>
|
|
||||||
Unvalid <code class="higlighted">secret_key</code> No API key was supplied. Invalid
|
|
||||||
request.
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>X003</td>
|
|
||||||
<td>
|
|
||||||
Unknown or unvalid user <code class="higlighted">token</code>. This error appears if
|
|
||||||
you use an unknow user <code class="higlighted">token</code> or if the user <code
|
|
||||||
class="higlighted">token</code> expired.
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
<div class="overflow-hidden content-section" id="content-get-api">
|
|
||||||
<div class="api-keys-header">
|
|
||||||
<h2>API Keys</h2>
|
|
||||||
<div class="button-container">
|
|
||||||
<button class="generate-key-button" onclick="generateKey()">Generate Key</button>
|
|
||||||
<button class="delete-key-button" onclick="deleteKeys()">Delete Keys</button>
|
|
||||||
</div>
|
|
||||||
<p>
|
<p>
|
||||||
You can generate API Keys here:
|
The following API is provided by the Eco saver developer team. It allows you to get Location and
|
||||||
|
Sensor and Sensor Data from the Eco saver database.
|
||||||
</p>
|
</p>
|
||||||
|
<p>
|
||||||
|
To use this API, you need an <strong>API key</strong>.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div class="overflow-hidden content-section" id="content-get-location">
|
||||||
|
<h2>Get all location</h2>
|
||||||
|
<p>
|
||||||
|
To get Location of sensors you need to make a GET call to the following url :<br>
|
||||||
|
<code class="higlighted break-word">https://api.teeseng.uk/api/v0/location</code>
|
||||||
|
<br>
|
||||||
|
<br>
|
||||||
|
Return Response :<br>
|
||||||
|
<code class="higlighted break-word">{"status":"200"}</code>
|
||||||
|
</p>
|
||||||
|
<br>
|
||||||
|
<h4>QUERY PARAMETERS</h4>
|
||||||
<table>
|
<table>
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th>Name</th>
|
<th>Field</th>
|
||||||
<th>Public Key</th>
|
<th>Type</th>
|
||||||
<th>Private Key</th>
|
<th>Description</th>
|
||||||
<th>Created</th>
|
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr>
|
<tr>
|
||||||
<td>API Key</td>
|
<td>Authorization</td>
|
||||||
<td>GR234-We34</td>
|
<td>JSON</td>
|
||||||
<td>greR-234-fEG</td>
|
<td>Your API key.</td>
|
||||||
<td>2024-01-22</td>
|
<td>(Required) Example: curl https://api.teeseng.uk/api/v0/location -H "Authorization:
|
||||||
|
{provide your
|
||||||
|
API key here}"</td>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
<div class="overflow-hidden content-section" id="content-get-location-by-id">
|
||||||
|
<h2>Get location by ID</h2>
|
||||||
|
<p>
|
||||||
|
To get Location you need to make a GET call to the following url :<br>
|
||||||
|
<code class="higlighted break-word">https://api.teeseng.uk/api/v0/location/{id}</code>
|
||||||
|
<br>
|
||||||
|
<br>
|
||||||
|
Return Response :<br>
|
||||||
|
<code class="higlighted break-word">{"status":"200"}</code>
|
||||||
|
</p>
|
||||||
|
<br>
|
||||||
|
<h4>QUERY PARAMETERS</h4>
|
||||||
|
<table>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Field</th>
|
||||||
|
<th>Type</th>
|
||||||
|
<th>Description</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td>Authorization</td>
|
||||||
|
<td>JSON</td>
|
||||||
|
<td>(Required) Your API key.</td>
|
||||||
|
<td>Example: curl https://api.teeseng.uk/api/v0/location -H "Authorization: {provide
|
||||||
|
your
|
||||||
|
API key here}"</td>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
<div class="overflow-hidden content-section" id="content-add-location">
|
||||||
|
<h2>Add Location (Only for system or admin API key)</h2>
|
||||||
|
<p>
|
||||||
|
To add an Location you need to make a POST call to the following url :<br>
|
||||||
|
<code class="higlighted break-word">https://api.teeseng.uk/api/v0/location/new</code>
|
||||||
|
<br>
|
||||||
|
<br>
|
||||||
|
Example :<br>
|
||||||
|
<code
|
||||||
|
class="higlighted break-word">curl https://api.teeseng.uk/api/v0/location/new -H "Content-Type: application/json" -X POST -d '{"name": "SAMPLE", "added_by": "system" , "description": "test"}'</code>
|
||||||
|
<br>
|
||||||
|
<br>
|
||||||
|
Return Response :<br>
|
||||||
|
<code class="higlighted break-word">{"status":"200"}</code>
|
||||||
|
</p>
|
||||||
|
<br>
|
||||||
|
<h4>QUERY PARAMETERS</h4>
|
||||||
|
<table>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Field</th>
|
||||||
|
<th>Type</th>
|
||||||
|
<th>Description</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td>Authorization</td>
|
||||||
|
<td>JSON</td>
|
||||||
|
<td>Your API key.</td>
|
||||||
|
<td>(Required) Example: curl https://api.teeseng.uk/api/v0/location/new -H
|
||||||
|
"Authorization: {provide your
|
||||||
|
API key here}"</td>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Location name</td>
|
||||||
|
<td>JSON</td>
|
||||||
|
<td>Location name.</td>
|
||||||
|
<td>(Required) Location name. Example: curl https://api.teeseng.uk/api/v0/location/new
|
||||||
|
-H "Authorization: provide
|
||||||
|
your API key here" -d '{"name":"Location name"}'</td>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Added by </td>
|
||||||
|
<td>JSON</td>
|
||||||
|
<td>System or Admin</td>
|
||||||
|
<td>(Required) System or Admin Example: curl https://api.teeseng.uk/api/v0/location/new
|
||||||
|
-H "Authorization: provide
|
||||||
|
your API key here" -d '{"added_by":"system"}'</td>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Description</td>
|
||||||
|
<td>JSON</td>
|
||||||
|
<td>Description of Location</td>
|
||||||
|
<td>(Required) System or Admin Example: curl https://api.teeseng.uk/api/v0/location/new
|
||||||
|
-H "Authorization: provide
|
||||||
|
your API key here" -d '{"description":"test"}'</td>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
<!-- update -->
|
||||||
|
<div class="overflow-hidden content-section" id="content-update-location-by-id">
|
||||||
|
<h2>Update Location (Only for system or admin API key)</h2>
|
||||||
|
<p>
|
||||||
|
To update an Location you need to make a PUT call to the following url :<br>
|
||||||
|
<code class="higlighted break-word">https://api.teeseng.uk/api/v0/location/update</code>
|
||||||
|
<br>
|
||||||
|
<br>
|
||||||
|
Example :<br>
|
||||||
|
<code
|
||||||
|
class="higlighted break-word">curl https://api.teeseng.uk/api/v0/location/update -H "Content-Type: application/json" -X POST -d '{"id": "7" , "name": "SAMPLE", "added_by": "system" , "description": "test"}'</code>
|
||||||
|
<br>
|
||||||
|
<br>
|
||||||
|
Return Response :<br>
|
||||||
|
<code class="higlighted break-word">{"status":"200","message":"Location 7 updated"}</code>
|
||||||
|
</p>
|
||||||
|
<br>
|
||||||
|
<h4>QUERY PARAMETERS</h4>
|
||||||
|
<table>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Field</th>
|
||||||
|
<th>Type</th>
|
||||||
|
<th>Description</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td>Authorization</td>
|
||||||
|
<td>JSON</td>
|
||||||
|
<td>Your API key.</td>
|
||||||
|
<td>(Required) example: curl https://api.teeseng.uk/api/v0/location/update -H
|
||||||
|
"Authorization: {provide your
|
||||||
|
API key here}"</td>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>ID</td>
|
||||||
|
<td>JSON</td>
|
||||||
|
<td>Location ID</td>
|
||||||
|
<td>(Required) Location ID Example: curl https://api.teeseng.uk/api/v0/location/update
|
||||||
|
-H "Authorization: provide
|
||||||
|
your API key here" -d '{"id": "7"}'</td>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Location name</td>
|
||||||
|
<td>JSON</td>
|
||||||
|
<td>Location name.</td>
|
||||||
|
<td>(Optional) Location name. Example: curl https://api.teeseng.uk/api/v0/location/new
|
||||||
|
-H "Authorization: provide
|
||||||
|
your API key here" -d '{"name":"Location name"}'</td>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Added by </td>
|
||||||
|
<td>JSON</td>
|
||||||
|
<td>System or Admin</td>
|
||||||
|
<td>(Optional) System or Admin Example: curl https://api.teeseng.uk/api/v0/location/new
|
||||||
|
-H "Authorization: provide
|
||||||
|
your API key here" -d '{"added_by":"system"}'</td>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Description</td>
|
||||||
|
<td>JSON</td>
|
||||||
|
<td>Description of Location</td>
|
||||||
|
<td>(Optional) System or Admin Example: curl https://api.teeseng.uk/api/v0/location/new
|
||||||
|
-H "Authorization: provide
|
||||||
|
your API key here" -d '{"description":"test"}'</td>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
<!-- delete location -->
|
||||||
|
<div class="overflow-hidden content-section" id="content-update-location-by-id">
|
||||||
|
<h2>Delete Location (Only for system or admin API key)</h2>
|
||||||
|
<p>
|
||||||
|
To delete an Location you need to make a DELETE call to the following url :<br>
|
||||||
|
<code class="higlighted break-word">https://api.teeseng.uk/api/v0/location/delete</code>
|
||||||
|
<br>
|
||||||
|
<br>
|
||||||
|
Example :<br>
|
||||||
|
<code
|
||||||
|
class="higlighted break-word">curl https://api.teeseng.uk/api/v0/location/delete -H "Content-Type: application/json" -X POST -d '{"id": "7"}'</code>
|
||||||
|
</p>
|
||||||
|
<br>
|
||||||
|
<h4>QUERY PARAMETERS</h4>
|
||||||
|
<table>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Field</th>
|
||||||
|
<th>Type</th>
|
||||||
|
<th>Description</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td>Authorization</td>
|
||||||
|
<td>JSON</td>
|
||||||
|
<td>Your API key.</td>
|
||||||
|
<td>(Required) example: curl https://api.teeseng.uk/api/v0/location/delete -H
|
||||||
|
"Authorization: {provide your
|
||||||
|
API key here}"</td>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>ID</td>
|
||||||
|
<td>JSON</td>
|
||||||
|
<td>Location ID</td>
|
||||||
|
<td>(Required) Location ID Example: curl https://api.teeseng.uk/api/v0/location/delete
|
||||||
|
-H "Authorization: provide
|
||||||
|
your API key here" -d '{"id": "7"}'</td>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
<div class="overflow-hidden content-section" id="content-get-sensor">
|
||||||
|
<h2>Get all sensor</h2>
|
||||||
|
<p>
|
||||||
|
To get sensors you need to make a GET call to the following url :<br>
|
||||||
|
<code class="higlighted break-word">https://api.teeseng.uk/api/v0/sensor</code>
|
||||||
|
<br>
|
||||||
|
<br>
|
||||||
|
Return Response :<br>
|
||||||
|
<code class="higlighted break-word">{"status":"200"}</code>
|
||||||
|
</p>
|
||||||
|
<br>
|
||||||
|
<h4>QUERY PARAMETERS</h4>
|
||||||
|
<table>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Field</th>
|
||||||
|
<th>Type</th>
|
||||||
|
<th>Description</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td>Authorization</td>
|
||||||
|
<td>JSON</td>
|
||||||
|
<td>Your API key.</td>
|
||||||
|
<td>(Required) Example: curl https://api.teeseng.uk/api/v0/sensor -H "Authorization:
|
||||||
|
{provide your
|
||||||
|
API key here}"</td>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
<div class="overflow-hidden content-section" id="content-get-sensor-by-id">
|
||||||
|
<h2>Get sensor by ID</h2>
|
||||||
|
<p>
|
||||||
|
To get Sensor you need to make a GET call to the following url :<br>
|
||||||
|
<code class="higlighted break-word">https://api.teeseng.uk/api/v0/sensor/{id}</code>
|
||||||
|
<br>
|
||||||
|
<br>
|
||||||
|
Return Response :<br>
|
||||||
|
<code class="higlighted break-word">{"status":"200"}</code>
|
||||||
|
</p>
|
||||||
|
<br>
|
||||||
|
<h4>QUERY PARAMETERS</h4>
|
||||||
|
<table>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Field</th>
|
||||||
|
<th>Type</th>
|
||||||
|
<th>Description</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td>Authorization</td>
|
||||||
|
<td>JSON</td>
|
||||||
|
<td>(Required) Your API key.</td>
|
||||||
|
<td>Example: curl https://api.teeseng.uk/api/v0/sensor/{id} -H "Authorization: {provide
|
||||||
|
your
|
||||||
|
API key here}"</td>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
<div class="overflow-hidden content-section" id="content-add-sensor">
|
||||||
|
<h2>Add Sensor (Only for system or admin API key)</h2>
|
||||||
|
<p>
|
||||||
|
To add a Sensor you need to make a POST call to the following url :<br>
|
||||||
|
<code class="higlighted break-word">https://api.teeseng.uk/api/v0/sensor/new</code>
|
||||||
|
<br>
|
||||||
|
<br>
|
||||||
|
Example :<br>
|
||||||
|
<code
|
||||||
|
class="higlighted break-word">curl https://api.teeseng.uk/api/v0/sensor/new -H "Content-Type: application/json" -X POST -d '{"sensorname": "test", "added_by": "system" , "mac_address": "99-6A-F8-7D-B4-94", "description": "test" , "location": "11"}'</code>
|
||||||
|
<br>
|
||||||
|
<br>
|
||||||
|
Return Response :<br>
|
||||||
|
<code class="higlighted break-word">{"status":"200"}</code>
|
||||||
|
</p>
|
||||||
|
<br>
|
||||||
|
<h4>QUERY PARAMETERS</h4>
|
||||||
|
<table>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Field</th>
|
||||||
|
<th>Type</th>
|
||||||
|
<th>Description</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td>Authorization</td>
|
||||||
|
<td>JSON</td>
|
||||||
|
<td>Your API key.</td>
|
||||||
|
<td>(Required) Example: curl https://api.teeseng.uk/api/v0/sensor/new
|
||||||
|
-H "Authorization: {provide your
|
||||||
|
API key here}"</td>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Sensor name</td>
|
||||||
|
<td>JSON</td>
|
||||||
|
<td>Sesnsor name.</td>
|
||||||
|
<td>(Required) Location name. Example: curl https://api.teeseng.uk/api/v0/sensor/new
|
||||||
|
-H "Authorization: provide
|
||||||
|
your API key here" -d '{"sensorname": "test"}'</td>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Added by </td>
|
||||||
|
<td>JSON</td>
|
||||||
|
<td>System or Admin</td>
|
||||||
|
<td>(Required) System or Admin Example: curl https://api.teeseng.uk/api/v0/sensor/new
|
||||||
|
-H "Authorization: provide
|
||||||
|
your API key here" -d '{"added_by":"system"}'</td>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Mac Address</td>
|
||||||
|
<td>JSON</td>
|
||||||
|
<td>Mac Address</td>
|
||||||
|
<td>(Required) Mac Address Example: curl https://api.teeseng.uk/api/v0/sensor/new
|
||||||
|
-H "Authorization: provide
|
||||||
|
your API key here" -d '{"mac_address": "99-6A-F8-7D-B4-94"}'</td>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Description</td>
|
||||||
|
<td>JSON</td>
|
||||||
|
<td>Description of Sensor</td>
|
||||||
|
<td>(Required) System or Admin Example: curl https://api.teeseng.uk/api/v0/sensor/new
|
||||||
|
-H "Authorization: provide
|
||||||
|
your API key here" -d '{"description":"test"}'</td>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Mac Address</td>
|
||||||
|
<td>JSON</td>
|
||||||
|
<td>Mac Address</td>
|
||||||
|
<td>(Required) Mac Address Example: curl https://api.teeseng.uk/api/v0/sensor/new
|
||||||
|
-H "Authorization: provide
|
||||||
|
your API key here" -d '{"mac_address": "99-6A-F8-7D-B4-94"}'</td>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Location</td>
|
||||||
|
<td>JSON</td>
|
||||||
|
<td>Location</td>
|
||||||
|
<td>(Required) Location Example: curl https://api.teeseng.uk/api/v0/sensor/new
|
||||||
|
-H "Authorization: provide
|
||||||
|
your API key here" -d '{"location": "11"}'</td>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
<div class="overflow-hidden content-section" id="content-update-sensor-by-id">
|
||||||
|
<h2>Update Sensor (Only for system or admin API key)</h2>
|
||||||
|
<p>
|
||||||
|
To update a Sensor you need to make a PUT call to the following url :<br>
|
||||||
|
<code class="higlighted break-word">https://api.teeseng.uk/api/v0/sensor/update</code>
|
||||||
|
<br>
|
||||||
|
<br>
|
||||||
|
Example :<br>
|
||||||
|
<code
|
||||||
|
class="higlighted break-word">curl https://api.teeseng.uk/api/v0/sensor/update -H "Content-Type: application/json" -X POST -d '{"id": "2" ,"sensorname": "test", "added_by": "system" , "mac_address": "99-6A-F8-7D-B4-94" , "description": "test123" , "location": "11" }'</code>
|
||||||
|
<br>
|
||||||
|
<br>
|
||||||
|
Return Response :<br>
|
||||||
|
<code class="higlighted break-word">{"status":"200","message":"Sensor 2 updated"}</code>
|
||||||
|
</p>
|
||||||
|
<br>
|
||||||
|
<h4>QUERY PARAMETERS</h4>
|
||||||
|
<table>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Field</th>
|
||||||
|
<th>Type</th>
|
||||||
|
<th>Description</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td>Authorization</td>
|
||||||
|
<td>JSON</td>
|
||||||
|
<td>Your API key.</td>
|
||||||
|
<td>(Required) example: curl https://api.teeseng.uk/api/v0/sensor/update -H
|
||||||
|
"Authorization: {provide your
|
||||||
|
API key here}"</td>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>ID</td>
|
||||||
|
<td>JSON</td>
|
||||||
|
<td>Sensor ID</td>
|
||||||
|
<td>(Required) Sensor ID Example: curl https://api.teeseng.uk/api/v0/sensor/update
|
||||||
|
-H "Authorization: provide
|
||||||
|
your API key here" -d '{"id": "7"}'</td>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Sensor name</td>
|
||||||
|
<td>JSON</td>
|
||||||
|
<td>Sensor name.</td>
|
||||||
|
<td>(Optional) Sensor name. Example: curl https://api.teeseng.uk/api/v0/sensor/update
|
||||||
|
-H "Authorization: provide
|
||||||
|
your API key here" -d '{"sensorname": "test"}'</td>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Added by </td>
|
||||||
|
<td>JSON</td>
|
||||||
|
<td>System or Admin</td>
|
||||||
|
<td>(Optional) System or Admin Example: curl https://api.teeseng.uk/api/v0/sensor/update
|
||||||
|
-H "Authorization: provide
|
||||||
|
your API key here" -d '{"added_by":"system"}'</td>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Mac Address </td>
|
||||||
|
<td>JSON</td>
|
||||||
|
<td>Mac Address</td>
|
||||||
|
<td>(Optional) Mac Address Example: curl https://api.teeseng.uk/api/v0/sensor/update
|
||||||
|
-H "Authorization: provide
|
||||||
|
your API key here" -d '{"mac_address": "99-6A-F8-7D-B4-94"}'</td>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Description</td>
|
||||||
|
<td>JSON</td>
|
||||||
|
<td>Description of Sensor</td>
|
||||||
|
<td>(Optional) Description of Sensor Example: curl
|
||||||
|
https://api.teeseng.uk/api/v0/sensor/update
|
||||||
|
-H "Authorization: provide
|
||||||
|
your API key here" -d '{"description":"test"}'</td>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Location</td>
|
||||||
|
<td>JSON</td>
|
||||||
|
<td>Location of Sensor</td>
|
||||||
|
<td>(Optional) Location of Sensor Example: curl
|
||||||
|
https://api.teeseng.uk/api/v0/sensor/update
|
||||||
|
-H "Authorization: provide
|
||||||
|
your API key here" -d '{"location": "11"}'</td>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
<div class="overflow-hidden content-section" id="content-delete-sensor-by-id">
|
||||||
|
<h2>Delete Sensor (Only for system or admin API key)</h2>
|
||||||
|
<p>
|
||||||
|
To delete a sensor you need to make a DELETE call to the following url :<br>
|
||||||
|
<code class="higlighted break-word">https://api.teeseng.uk/api/v0/sensor/delete</code>
|
||||||
|
<br>
|
||||||
|
<br>
|
||||||
|
Example :<br>
|
||||||
|
<code
|
||||||
|
class="higlighted break-word">curl https://api.teeseng.uk/api/v0/sensor/delete -H "Content-Type: application/json" -X POST -d '{"id": "7"}'</code>
|
||||||
|
</p>
|
||||||
|
<br>
|
||||||
|
<h4>QUERY PARAMETERS</h4>
|
||||||
|
<table>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Field</th>
|
||||||
|
<th>Type</th>
|
||||||
|
<th>Description</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td>Authorization</td>
|
||||||
|
<td>JSON</td>
|
||||||
|
<td>Your API key.</td>
|
||||||
|
<td>(Required) example: curl https://api.teeseng.uk/api/v0/sensor/delete -H
|
||||||
|
"Authorization: {provide your
|
||||||
|
API key here}"</td>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>ID</td>
|
||||||
|
<td>JSON</td>
|
||||||
|
<td>Sensor ID</td>
|
||||||
|
<td>(Required) Sensor ID Example: curl https://api.teeseng.uk/api/v0/sensor/delete
|
||||||
|
-H "Authorization: provide
|
||||||
|
your API key here" -d '{"id": "7"}'</td>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<div class="api-keys-header iot-card" id="content-get-api">
|
||||||
|
<h2>API Keys</h2>
|
||||||
|
<p>
|
||||||
|
You can generate API Keys here:
|
||||||
|
</p>
|
||||||
|
<form action="token/new" onsubmit="formAJAX(this)" class="api-form">
|
||||||
|
<div class="card-header shadow actionMessage" style="display:none;"></div>
|
||||||
|
<input type="email" name="email" id="email" placeholder="Email address"
|
||||||
|
pattern="\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*">
|
||||||
|
<div style="margin-top: 10px;"></div>
|
||||||
|
<button class="generate-key-button">Generate Key</button>
|
||||||
|
|
||||||
|
</form>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="overflow-hidden content-section" id="content-errors">
|
||||||
|
<h2>Errors</h2>
|
||||||
|
<p>
|
||||||
|
The EcoSaver API uses the following error codes:
|
||||||
|
</p>
|
||||||
|
<table>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Error Code</th>
|
||||||
|
<th>Meaning</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td>X000</td>
|
||||||
|
<td>
|
||||||
|
Some parameters are missing. This error appears when you don't pass every
|
||||||
|
mandatory
|
||||||
|
parameters.
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>403</td>
|
||||||
|
<td>
|
||||||
|
Unknown or unvalid <code class="higlighted">secret_key</code>. This error
|
||||||
|
appears if
|
||||||
|
you use an unknow API key or if your API key expired.
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>500</td>
|
||||||
|
<td>
|
||||||
|
Unvalid <code class="higlighted">secret_key</code> No API key was supplied.
|
||||||
|
Invalid
|
||||||
|
request.
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>X003</td>
|
||||||
|
<td>
|
||||||
|
Unknown or unvalid user <code class="higlighted">token</code>. This error
|
||||||
|
appears if
|
||||||
|
you use an unknow user <code class="higlighted">token</code> or if the user
|
||||||
|
<code class="higlighted">token</code> expired.
|
||||||
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
<script src="js/api.js"></script>
|
||||||
|
|
||||||
|
</html>
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</body>
|
|
||||||
<script src="js/api.js"></script>
|
|
||||||
<script src="js/apikey.js"></script>
|
|
||||||
|
|
||||||
</html>
|
|
||||||
|
@ -42,7 +42,8 @@
|
|||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
<abbr title="Email">E</abbr>:
|
<abbr title="Email">E</abbr>:
|
||||||
<a href="mailto:name@example.com">leongdingxuan@gmail.com
|
<a href="mailto:name@example.com">ecosaverx@gmail.com
|
||||||
|
|
||||||
</a>
|
</a>
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
@ -55,17 +56,18 @@
|
|||||||
<!-- Contact Form -->
|
<!-- Contact Form -->
|
||||||
<!-- In order to set the email address and subject line for the contact form go to the bin/contact_me.php file. -->
|
<!-- In order to set the email address and subject line for the contact form go to the bin/contact_me.php file. -->
|
||||||
<div class="row">
|
<div class="row">
|
||||||
|
<div class="form contact iot-card">
|
||||||
<div class="col-lg-8 mb-4 contact-left">
|
<div class="col-lg-8 mb-4 contact-left">
|
||||||
<h3>Send us a Message</h3>
|
<h3>Send us a Message</h3>
|
||||||
<form id="form">
|
<form action="auth/contact" onsubmit="formAJAX(this)">
|
||||||
<input type="hidden" name="access_key" value="">
|
<div class="card-header shadow actionMessage" style="display:none"></div>
|
||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
<label for="name">Full Name</label>
|
<label for="name">Full Name</label>
|
||||||
<input type="text" name="name" id="name" required>
|
<input type="text" name="name" id="name" required pattern="^[a-zA-Z]{3,}( {1,2}[a-zA-Z]{3,}){0,}$">
|
||||||
</div>
|
</div>
|
||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
<label for="email">Email address</label>
|
<label for="email">Email address</label>
|
||||||
<input type="email" name="email" id="email" required>
|
<input type="email" name="email" id="email" required pattern="\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*">
|
||||||
</div>
|
</div>
|
||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
<label for="message">Message</label>
|
<label for="message">Message</label>
|
||||||
@ -75,6 +77,8 @@
|
|||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<!-- /.row -->
|
<!-- /.row -->
|
||||||
|
@ -1,11 +1,60 @@
|
|||||||
<%- include('top') %>
|
<%- include('top') %>
|
||||||
<script>
|
<script type="text/javascript">
|
||||||
//call socket.io
|
function extractNumbers(str) {
|
||||||
app.socket.on("sensorData:new", function (data) {
|
if (typeof str === 'number') return str;
|
||||||
console.log("new data!!")
|
return str.match(/\d+/)[0];
|
||||||
console.log(data);
|
}
|
||||||
|
|
||||||
|
function calculateAverage(numbers) {
|
||||||
|
if (numbers.length === 0) return 0
|
||||||
|
const sum = numbers.reduce((acc, num) => acc + num, 0);
|
||||||
|
return sum / numbers.length;
|
||||||
|
}
|
||||||
|
const values = {
|
||||||
|
psi: [],
|
||||||
|
humidity: [],
|
||||||
|
temperature: [],
|
||||||
|
windspeed: [],
|
||||||
|
};
|
||||||
|
|
||||||
|
function parseRowToTemplace(row) {
|
||||||
|
values.psi.unshift(extractNumbers(row.measurement.psi))
|
||||||
|
values.humidity.unshift(extractNumbers(row.measurement.humidity))
|
||||||
|
values.temperature.unshift(extractNumbers(row.measurement.temperature))
|
||||||
|
values.windspeed.unshift(extractNumbers(row.measurement.windspeed))
|
||||||
|
|
||||||
|
return {
|
||||||
|
average: {
|
||||||
|
psi: parseInt(calculateAverage(values.psi)),
|
||||||
|
humidity: parseInt(calculateAverage(values.humidity)),
|
||||||
|
temperature: parseInt(calculateAverage(values.temperature)),
|
||||||
|
windspeed: parseInt(calculateAverage(values.windspeed)),
|
||||||
|
},
|
||||||
|
latest: {
|
||||||
|
psi: values.psi[0],
|
||||||
|
humidity: values.humidity[0],
|
||||||
|
temperature: values.temperature[0],
|
||||||
|
windspeed: values.windspeed[0],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$(document).ready(async function () {
|
||||||
|
|
||||||
|
app.api.get('latest-sensor-data/data', function (error, data) {
|
||||||
|
for (let row of data) {
|
||||||
|
//console.log(row);
|
||||||
|
$.scope.LatestSensorData.update(parseRowToTemplace(row));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
//call socket.io to get live data
|
||||||
|
app.socket.on("sensorData:new", function (data) {
|
||||||
|
$.scope.LatestSensorData.update(parseRowToTemplace(data));
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
||||||
@ -53,55 +102,59 @@
|
|||||||
</header>
|
</header>
|
||||||
<!-- Page Content -->
|
<!-- Page Content -->
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<div class="services-bar">
|
<div class="services-bar" jq-repeat="LatestSensorData">
|
||||||
<h1 class="my-4">Services</h1>
|
<h1 class="my-4">Services</h1>
|
||||||
<!-- Services Section -->
|
<!-- Services Section -->
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-lg-3 mb-4">
|
<div class="col-lg-3 mb-4">
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<h4 class="card-header">Air Quality Index</h4>
|
<h4 class="card-header">Air Quality Index</h4>
|
||||||
<div class="card-body text-center">
|
<div class="card-body text-center">
|
||||||
<p class="card-text display-4">15 - 18 PSI</p>
|
<p class="card-text display-4"> Average: {{average.psi}} PSI</p>
|
||||||
</div>
|
<p class="card-text display-4"> Latest: {{latest.psi}} PSI</p>
|
||||||
<div class="card-footer">
|
|
||||||
<a href="/learnmore" class="btn btn-primary">Learn More</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<div class="card-footer">
|
||||||
<div class="col-lg-3 mb-4">
|
<a href="/learnmore" class="btn btn-primary">Learn More</a>
|
||||||
<div class="card">
|
|
||||||
<h4 class="card-header">Humidity</h4>
|
|
||||||
<div class="card-body text-center">
|
|
||||||
<p class="card-text display-4">70% - 75%</p>
|
|
||||||
</div>
|
|
||||||
<div class="card-footer">
|
|
||||||
<a href="/learnmore" class="btn btn-primary">Learn More</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-lg-3 mb-4">
|
</div>
|
||||||
<div class="card">
|
<div class="col-lg-3 mb-4">
|
||||||
<h4 class="card-header">Temperature</h4>
|
<div class="card">
|
||||||
<div class="card-body text-center">
|
<h4 class="card-header">Humidity</h4>
|
||||||
<p class="card-text display-4">30° - 37°</p>
|
<div class="card-body text-center">
|
||||||
</div>
|
<p class="card-text display-4"> Average: {{average.humidity}} %</p>
|
||||||
<div class="card-footer">
|
<p class="card-text display-4"> Latest: {{latest.humidity}} %</p>
|
||||||
<a href="/learnmore" class="btn btn-primary">Learn More</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<div class="card-footer">
|
||||||
<div class="col-lg-3 mb-4">
|
<a href="/learnmore" class="btn btn-primary">Learn More</a>
|
||||||
<div class="card">
|
|
||||||
<h4 class="card-header">Another Category</h4>
|
|
||||||
<div class="card-body text-center">
|
|
||||||
<p class="card-text display-4">values</p>
|
|
||||||
</div>
|
|
||||||
<div class="card-footer">
|
|
||||||
<a href="/learnmore" class="btn btn-primary">Learn More</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="col-lg-3 mb-4">
|
||||||
|
<div class="card">
|
||||||
|
<h4 class="card-header">Temperature</h4>
|
||||||
|
<div class="card-body text-center">
|
||||||
|
<p class="card-text display-4"> Average: {{average.temperature}}°</p>
|
||||||
|
<p class="card-text display-4"> Latest: {{latest.temperature}}°</p>
|
||||||
|
</div>
|
||||||
|
<div class="card-footer">
|
||||||
|
<a href="/learnmore" class="btn btn-primary">Learn More</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-lg-3 mb-4">
|
||||||
|
<div class="card">
|
||||||
|
<h4 class="card-header">Wind Speed</h4>
|
||||||
|
<div class="card-body text-center">
|
||||||
|
<p class="card-text display-4"> Average: {{average.windspeed}} Km/h</p>
|
||||||
|
<p class="card-text display-4"> Latest: {{latest.windspeed}} Km/h</p>
|
||||||
|
</div>
|
||||||
|
<div class="card-footer">
|
||||||
|
<a href="/learnmore" class="btn btn-primary">Learn More</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<!-- /.row -->
|
<!-- /.row -->
|
||||||
</div>
|
</div>
|
||||||
|
@ -27,7 +27,7 @@
|
|||||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/mustache.js/0.1/mustache.min.js"></script>
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/mustache.js/0.1/mustache.min.js"></script>
|
||||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/mustache.js/0.1/mustache.js"></script>
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/mustache.js/0.1/mustache.js"></script>
|
||||||
<!-- socket.io scriot -->
|
<!-- socket.io scriot -->
|
||||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/4.2.0/socket.io.min.js"></script>
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/4.2.0/socket.io.min.js"></script>
|
||||||
|
|
||||||
<!-- jquery app.js -->
|
<!-- jquery app.js -->
|
||||||
<script src="js/app.js"></script>
|
<script src="js/app.js"></script>
|
||||||
@ -44,19 +44,22 @@
|
|||||||
$(document).ready(function () {
|
$(document).ready(function () {
|
||||||
//check if user is logged in
|
//check if user is logged in
|
||||||
app.auth.isLoggedIn(function (error, data) {
|
app.auth.isLoggedIn(function (error, data) {
|
||||||
if (data) {
|
if (!error) {
|
||||||
$('#cl-logout-button').show('fast');
|
$("#cl-logout-button").show("fast");
|
||||||
$('#cl-profile-button').show('fast');
|
$("#cl-api-button").show("fast");
|
||||||
$('#cl-login-button').hide('fast');
|
$("#cl-profile-button").show("fast");
|
||||||
|
$("#cl-login-button").hide("fast");
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
$('#cl-login-button').show('fast');
|
$('#cl-login-button').show('fast');
|
||||||
|
|
||||||
}
|
}
|
||||||
$('body').show('fast')
|
$('body').show('fast')
|
||||||
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
||||||
<nav class="navbar fixed-top navbar-expand-lg navbar-dark bg-light top-nav fixed-top">
|
<nav class="navbar fixed-top navbar-expand-lg navbar-dark bg-light top-nav fixed-top">
|
||||||
@ -79,11 +82,12 @@
|
|||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<a class="nav-link" href="/contact">Contact</a>
|
<a class="nav-link" href="/contact">Contact</a>
|
||||||
</li>
|
</li>
|
||||||
<li class="nav-item">
|
|
||||||
<a class="nav-link" href="/api">API Doc</a>
|
|
||||||
</li>
|
|
||||||
<!-- profile button -->
|
<!-- profile button -->
|
||||||
<div class="form-inline mt-2 mt-md-0">
|
<div class="form-inline mt-2 mt-md-0">
|
||||||
|
<a id="cl-api-button" class="btn btn-outline-info btn-sm my-2 my-sm-0" href="/api"
|
||||||
|
style="display: none">
|
||||||
|
<i class="fas fa-sign-out"></i> API
|
||||||
|
</a>
|
||||||
<a id="cl-profile-button" class="btn btn-outline-info my-2 my-sm-0" href="/profile"
|
<a id="cl-profile-button" class="btn btn-outline-info my-2 my-sm-0" href="/profile"
|
||||||
style="display: none;">
|
style="display: none;">
|
||||||
<i class="fas fa-sign-out"></i>
|
<i class="fas fa-sign-out"></i>
|
||||||
@ -104,4 +108,3 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
|
|
||||||
|
@ -1,4 +1,8 @@
|
|||||||
<%- include('top') %>
|
<%- include('top') %>
|
||||||
|
<script type="text/javascript">
|
||||||
|
// Require login to see this page.
|
||||||
|
app.auth.forceLogin()
|
||||||
|
</script>
|
||||||
|
|
||||||
<br>
|
<br>
|
||||||
<br>
|
<br>
|
||||||
@ -6,9 +10,9 @@
|
|||||||
<div class="profile">
|
<div class="profile">
|
||||||
<!-- <li jq-repeat="getUsername" class="nav-item"> -->
|
<!-- <li jq-repeat="getUsername" class="nav-item"> -->
|
||||||
<div class="edit_information" jq-repeat="getUserDetails">
|
<div class="edit_information" jq-repeat="getUserDetails">
|
||||||
<div class="card-header shadow actionMessage" style="display:none"></div>
|
|
||||||
<form id="profileForm" action="user/update" method="put" onsubmit="formAJAX(this)"
|
<form id="profileForm" action="user/update" method="put" onsubmit="formAJAX(this)"
|
||||||
evalAJAX="app.auth.profileRedirect();">
|
evalAJAX="app.auth.profileRedirect();">
|
||||||
|
<div class="card-header shadow actionMessage" style="display:none"></div>
|
||||||
<h3 class="text-center">Edit Personal Information</h3>
|
<h3 class="text-center">Edit Personal Information</h3>
|
||||||
<br>
|
<br>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
|
@ -8,10 +8,9 @@
|
|||||||
|
|
||||||
<ul id="sensorDataList">
|
<ul id="sensorDataList">
|
||||||
<li jq-repeat='sensorData'>
|
<li jq-repeat='sensorData'>
|
||||||
rowid: {{ id }}
|
|
||||||
sensorId: {{ sensorid }}
|
sensorId: {{ sensorid }}
|
||||||
created: {{ createdAt }}
|
|
||||||
location: {{ locationid }}
|
location: {{ locationid }}
|
||||||
|
created: {{ createdAt }}
|
||||||
<br />
|
<br />
|
||||||
co: {{ measurement.co }}
|
co: {{ measurement.co }}
|
||||||
humidity: {{ measurement.humidity }}
|
humidity: {{ measurement.humidity }}
|
||||||
@ -30,7 +29,7 @@
|
|||||||
|
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
$(document).ready(async function () {
|
$(document).ready(async function () {
|
||||||
app.api.get('sensor-data/data?order=DESC&limit=40', function(error, data){
|
app.api.get('sensor-data/data?order=DESC&limit=6', function(error, data){
|
||||||
$.scope.sensorData.push(...data);
|
$.scope.sensorData.push(...data);
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
@ -57,9 +57,7 @@
|
|||||||
//check if user is logged in
|
//check if user is logged in
|
||||||
app.auth.isLoggedIn(function (error, data) {
|
app.auth.isLoggedIn(function (error, data) {
|
||||||
if (!error) {
|
if (!error) {
|
||||||
console.log(error);
|
|
||||||
$.scope.getUsername.update(data);
|
$.scope.getUsername.update(data);
|
||||||
|
|
||||||
if (location.pathname == "/profile") {
|
if (location.pathname == "/profile") {
|
||||||
$.scope.getUserDetails.update(data);
|
$.scope.getUserDetails.update(data);
|
||||||
}
|
}
|
||||||
|
277
example.html
Normal file
277
example.html
Normal file
@ -0,0 +1,277 @@
|
|||||||
|
<%- include('top') %>
|
||||||
|
<style>
|
||||||
|
#sensorDataAverage {
|
||||||
|
padding-top: 2.5em;
|
||||||
|
padding-bottom: 2.5em;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<div class="container">
|
||||||
|
|
||||||
|
<div class="row" id="sensorDataAverage" jq-repeat='sensorDataAverage'>
|
||||||
|
|
||||||
|
<div class="col-md-3">
|
||||||
|
<div id="workerStatusCard" class="card shadow-lg">
|
||||||
|
<h5 class="card-header">
|
||||||
|
Air Quality Index
|
||||||
|
</h5>
|
||||||
|
<div class="card-body">
|
||||||
|
Average: {{average.aqi}}
|
||||||
|
<br />
|
||||||
|
latest: {{latest.aqi}}
|
||||||
|
</div>
|
||||||
|
<div class="card-footer">
|
||||||
|
<button type="button" class="btn btn-success">
|
||||||
|
Learn More
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-md-3">
|
||||||
|
<div id="workerStatusCard" class="card shadow-lg">
|
||||||
|
<h5 class="card-header">
|
||||||
|
Humidity
|
||||||
|
</h5>
|
||||||
|
<div class="card-body">
|
||||||
|
Average: {{average.humidity}}
|
||||||
|
<br />
|
||||||
|
latest: {{latest.humidity}}
|
||||||
|
</div>
|
||||||
|
<div class="card-footer">
|
||||||
|
<button type="button" class="btn btn-success">
|
||||||
|
Learn More
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-md-3">
|
||||||
|
<div id="workerStatusCard" class="card shadow-lg">
|
||||||
|
<h5 class="card-header">
|
||||||
|
Temperature
|
||||||
|
</h5>
|
||||||
|
<div class="card-body">
|
||||||
|
Average: {{average.temperature}}
|
||||||
|
<br />
|
||||||
|
latest: {{latest.temperature}}
|
||||||
|
</div>
|
||||||
|
<div class="card-footer">
|
||||||
|
<button type="button" class="btn btn-success">
|
||||||
|
Learn More
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-md-3">
|
||||||
|
<div id="workerStatusCard" class="card shadow-lg">
|
||||||
|
<h5 class="card-header">
|
||||||
|
Wind Speed
|
||||||
|
</h5>
|
||||||
|
<div class="card-body">
|
||||||
|
Average: {{average.windspeed}}
|
||||||
|
<br />
|
||||||
|
latest: {{latest.windspeed}}
|
||||||
|
</div>
|
||||||
|
<div class="card-footer">
|
||||||
|
<button type="button" class="btn btn-success">
|
||||||
|
Learn More
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row" jq-repeat-defualt='sensorDataAverage'>
|
||||||
|
Loading...
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script type="text/javascript">
|
||||||
|
function extractNumbers(str) {
|
||||||
|
if(typeof str === 'number') return str;
|
||||||
|
return str.match(/\d+/)[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
function calculateAverage(numbers) {
|
||||||
|
if (numbers.length === 0) return 0
|
||||||
|
const sum = numbers.reduce((acc, num) => acc + num, 0);
|
||||||
|
return sum / numbers.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
const values = {
|
||||||
|
aqi: [],
|
||||||
|
humidity: [],
|
||||||
|
temperature: [],
|
||||||
|
windspeed: [],
|
||||||
|
};
|
||||||
|
|
||||||
|
function parseRowToTemplace(row){
|
||||||
|
|
||||||
|
values.aqi.unshift(extractNumbers(row.measurement.o3))
|
||||||
|
values.humidity.unshift(extractNumbers(row.measurement.humidity))
|
||||||
|
values.temperature.unshift(extractNumbers(row.measurement.temperature))
|
||||||
|
values.windspeed.unshift(extractNumbers(row.measurement.windspeed))
|
||||||
|
|
||||||
|
return {
|
||||||
|
average: {
|
||||||
|
aqi: parseInt(calculateAverage(values.aqi)),
|
||||||
|
humidity: parseInt(calculateAverage(values.humidity)),
|
||||||
|
temperature: parseInt(calculateAverage(values.temperature)),
|
||||||
|
windspeed: parseInt(calculateAverage(values.windspeed)),
|
||||||
|
},
|
||||||
|
latest: {
|
||||||
|
aqi: values.humidity[0],
|
||||||
|
humidity: values.humidity[0],
|
||||||
|
temperature: values.humidity[0],
|
||||||
|
windspeed: values.windspeed[0],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$(document).ready(async function () {
|
||||||
|
app.api.get('sensor-data/data?order=DESC&limit=40', function(error, data){
|
||||||
|
for(let row of data){
|
||||||
|
$.scope.sensorDataAverage.update(parseRowToTemplace(row));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
app.socket.on('sensorData:new', function(row){
|
||||||
|
$.scope.sensorDataAverage.update(parseRowToTemplace(row));
|
||||||
|
})
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
<%- include('bot') %>
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<td>Location</td>
|
||||||
|
<td>JSON</td>
|
||||||
|
<td>Location</td>
|
||||||
|
<td>(Required) Location Example: curl https://api.teeseng.uk/api/v0/sensor/new
|
||||||
|
-H "Authorization: provide
|
||||||
|
your API key here" -d '{"location": "11"}'</td>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
|
||||||
|
<div class="overflow-hidden content-section" id="content-get-api">
|
||||||
|
<div class="api-keys-header">
|
||||||
|
<h2>API Keys</h2>
|
||||||
|
<button class="generate-key-button">Generate Key</button>
|
||||||
|
<p>
|
||||||
|
You can generate API Keys here:
|
||||||
|
</p>
|
||||||
|
<table>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Name</th>
|
||||||
|
<th>Public Key</th>
|
||||||
|
<th>Private Key</th>
|
||||||
|
<th>Key Type</th>
|
||||||
|
<th>Created</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td>API Key</td>
|
||||||
|
<td>GR234-We34</td>
|
||||||
|
<td>greR-234-fEG</td>
|
||||||
|
<td>Type</td>
|
||||||
|
<td>2024-01-22</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<div class="overflow-hidden content-section" id="content-errors">
|
||||||
|
<h2>Errors</h2>
|
||||||
|
<p>
|
||||||
|
The Westeros API uses the following error codes:
|
||||||
|
</p>
|
||||||
|
<table>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Error Code</th>
|
||||||
|
<th>Meaning</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td>X000</td>
|
||||||
|
<td>
|
||||||
|
Some parameters are missing. This error appears when you don't pass every mandatory
|
||||||
|
parameters.
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>403</td>
|
||||||
|
<td>
|
||||||
|
Unknown or unvalid <code class="higlighted">secret_key</code>. This error appears if
|
||||||
|
you use an unknow API key or if your API key expired.
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>500</td>
|
||||||
|
<td>
|
||||||
|
Unvalid <code class="higlighted">secret_key</code> No API key was supplied. Invalid
|
||||||
|
request.
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>X003</td>
|
||||||
|
<td>
|
||||||
|
Unknown or unvalid user <code class="higlighted">token</code>. This error appears if
|
||||||
|
you use an unknow user <code class="higlighted">token</code> or if the user <code
|
||||||
|
class="higlighted">token</code> expired.
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<div class="overflow-hidden content-section" id="content-get-api">
|
||||||
|
<div class="api-keys-header">
|
||||||
|
<h2>API Keys</h2>
|
||||||
|
<button class="generate-key-button">Generate Key</button>
|
||||||
|
<p>
|
||||||
|
You can generate API Keys here:
|
||||||
|
</p>
|
||||||
|
<table>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Name</th>
|
||||||
|
<th>Public Key</th>
|
||||||
|
<th>Private Key</th>
|
||||||
|
<th>Key Type</th>
|
||||||
|
<th>Created</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td>API Key</td>
|
||||||
|
<td>GR234-We34</td>
|
||||||
|
<td>greR-234-fEG</td>
|
||||||
|
<td>Type</td>
|
||||||
|
<td>2024-01-22</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<div class="api-keys-header">
|
||||||
|
<h2>API Keys</h2>
|
||||||
|
<p>
|
||||||
|
You can generate API Keys here:
|
||||||
|
</p>
|
||||||
|
<form action="token/new" onsubmit="formAJAX(this)" class="api-form">
|
||||||
|
<div class="card-header shadow actionMessage" style="display:none"></div>
|
||||||
|
<input type="email" name="email" id="email" required pattern="\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*">
|
||||||
|
<div style="margin-top: 10px;"></div> <!-- Adjust margin-top value as needed -->
|
||||||
|
<input type="submit" value="Generate Key">
|
||||||
|
</form>
|
||||||
|
</div>
|
626
package-lock.json
generated
626
package-lock.json
generated
@ -4,6 +4,14 @@
|
|||||||
"lockfileVersion": 1,
|
"lockfileVersion": 1,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@babel/runtime": {
|
||||||
|
"version": "7.23.8",
|
||||||
|
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.23.8.tgz",
|
||||||
|
"integrity": "sha512-Y7KbAP984rn1VGMbGqKmBLio9V7y5Je9GvU4rQPCPinCyNfUcToxIXl06d59URp/F3LwinvODxab5N/G6qggkw==",
|
||||||
|
"requires": {
|
||||||
|
"regenerator-runtime": "^0.14.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"@isaacs/cliui": {
|
"@isaacs/cliui": {
|
||||||
"version": "8.0.2",
|
"version": "8.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz",
|
||||||
@ -141,6 +149,24 @@
|
|||||||
"integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==",
|
"integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==",
|
||||||
"optional": true
|
"optional": true
|
||||||
},
|
},
|
||||||
|
"@socket.io/component-emitter": {
|
||||||
|
"version": "3.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.0.tgz",
|
||||||
|
"integrity": "sha512-+9jVqKhRSpsc591z5vX+X5Yyw+he/HCB4iQ/RYxw35CEPaY1gnsNE43nf9n9AaYjAQrTiI/mOwKUKdUs9vf7Xg=="
|
||||||
|
},
|
||||||
|
"@types/cookie": {
|
||||||
|
"version": "0.4.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.4.1.tgz",
|
||||||
|
"integrity": "sha512-XW/Aa8APYr6jSVVA1y/DEIZX0/GMKLEVekNG727R8cs56ahETkRAy/3DR7+fJyh7oUgGwNQaRfXCun0+KbWY7Q=="
|
||||||
|
},
|
||||||
|
"@types/cors": {
|
||||||
|
"version": "2.8.17",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.17.tgz",
|
||||||
|
"integrity": "sha512-8CGDvrBj1zgo2qE+oS3pOCyYNqCPryMWY2bGfwA0dcfopWGgxs+78df0Rs3rc9THP4JkOhLsAa+15VdpAqkcUA==",
|
||||||
|
"requires": {
|
||||||
|
"@types/node": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
"@types/debug": {
|
"@types/debug": {
|
||||||
"version": "4.1.12",
|
"version": "4.1.12",
|
||||||
"resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.12.tgz",
|
"resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.12.tgz",
|
||||||
@ -162,16 +188,48 @@
|
|||||||
"undici-types": "~5.26.4"
|
"undici-types": "~5.26.4"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"@types/readable-stream": {
|
||||||
|
"version": "4.0.10",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/readable-stream/-/readable-stream-4.0.10.tgz",
|
||||||
|
"integrity": "sha512-AbUKBjcC8SHmImNi4yK2bbjogQlkFSg7shZCcicxPQapniOlajG8GCc39lvXzCWX4lLRRs7DM3VAeSlqmEVZUA==",
|
||||||
|
"requires": {
|
||||||
|
"@types/node": "*",
|
||||||
|
"safe-buffer": "~5.1.1"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"safe-buffer": {
|
||||||
|
"version": "5.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
|
||||||
|
"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"@types/validator": {
|
"@types/validator": {
|
||||||
"version": "13.11.8",
|
"version": "13.11.8",
|
||||||
"resolved": "https://registry.npmjs.org/@types/validator/-/validator-13.11.8.tgz",
|
"resolved": "https://registry.npmjs.org/@types/validator/-/validator-13.11.8.tgz",
|
||||||
"integrity": "sha512-c/hzNDBh7eRF+KbCf+OoZxKbnkpaK/cKp9iLQWqB7muXtM+MtL9SUUH8vCFcLn6dH1Qm05jiexK0ofWY7TfOhQ=="
|
"integrity": "sha512-c/hzNDBh7eRF+KbCf+OoZxKbnkpaK/cKp9iLQWqB7muXtM+MtL9SUUH8vCFcLn6dH1Qm05jiexK0ofWY7TfOhQ=="
|
||||||
},
|
},
|
||||||
|
"@types/ws": {
|
||||||
|
"version": "8.5.10",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.10.tgz",
|
||||||
|
"integrity": "sha512-vmQSUcfalpIq0R9q7uTo2lXs6eGIpt9wtnLdMv9LVpIjCA/+ufZRozlVoVelIYixx1ugCBKDhn89vnsEGOCx9A==",
|
||||||
|
"requires": {
|
||||||
|
"@types/node": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
"abbrev": {
|
"abbrev": {
|
||||||
"version": "1.1.1",
|
"version": "1.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz",
|
||||||
"integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q=="
|
"integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q=="
|
||||||
},
|
},
|
||||||
|
"abort-controller": {
|
||||||
|
"version": "3.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz",
|
||||||
|
"integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==",
|
||||||
|
"requires": {
|
||||||
|
"event-target-shim": "^5.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"accepts": {
|
"accepts": {
|
||||||
"version": "1.3.8",
|
"version": "1.3.8",
|
||||||
"resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz",
|
"resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz",
|
||||||
@ -202,6 +260,16 @@
|
|||||||
"color-convert": "^2.0.1"
|
"color-convert": "^2.0.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"anymatch": {
|
||||||
|
"version": "3.1.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz",
|
||||||
|
"integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"normalize-path": "^3.0.0",
|
||||||
|
"picomatch": "^2.0.4"
|
||||||
|
}
|
||||||
|
},
|
||||||
"aproba": {
|
"aproba": {
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz",
|
||||||
@ -263,6 +331,16 @@
|
|||||||
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
|
||||||
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="
|
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="
|
||||||
},
|
},
|
||||||
|
"base64-js": {
|
||||||
|
"version": "1.5.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
|
||||||
|
"integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA=="
|
||||||
|
},
|
||||||
|
"base64id": {
|
||||||
|
"version": "2.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/base64id/-/base64id-2.0.0.tgz",
|
||||||
|
"integrity": "sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog=="
|
||||||
|
},
|
||||||
"bcrypt": {
|
"bcrypt": {
|
||||||
"version": "5.1.1",
|
"version": "5.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/bcrypt/-/bcrypt-5.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/bcrypt/-/bcrypt-5.1.1.tgz",
|
||||||
@ -272,6 +350,22 @@
|
|||||||
"node-addon-api": "^5.0.0"
|
"node-addon-api": "^5.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"binary-extensions": {
|
||||||
|
"version": "2.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz",
|
||||||
|
"integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"bl": {
|
||||||
|
"version": "6.0.10",
|
||||||
|
"resolved": "https://registry.npmjs.org/bl/-/bl-6.0.10.tgz",
|
||||||
|
"integrity": "sha512-F14DFhDZfxtVm2FY0k9kG2lWAwzZkO9+jX3Ytuoy/V0E1/5LBuBzzQHXAjqpxXEDIpmTPZZf5GVIGPQcLxFpaA==",
|
||||||
|
"requires": {
|
||||||
|
"buffer": "^6.0.3",
|
||||||
|
"inherits": "^2.0.4",
|
||||||
|
"readable-stream": "^4.2.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"bluebird": {
|
"bluebird": {
|
||||||
"version": "3.7.2",
|
"version": "3.7.2",
|
||||||
"resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz",
|
"resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz",
|
||||||
@ -319,6 +413,29 @@
|
|||||||
"balanced-match": "^1.0.0"
|
"balanced-match": "^1.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"braces": {
|
||||||
|
"version": "3.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
|
||||||
|
"integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"fill-range": "^7.0.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"buffer": {
|
||||||
|
"version": "6.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz",
|
||||||
|
"integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==",
|
||||||
|
"requires": {
|
||||||
|
"base64-js": "^1.3.1",
|
||||||
|
"ieee754": "^1.2.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"buffer-from": {
|
||||||
|
"version": "1.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz",
|
||||||
|
"integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ=="
|
||||||
|
},
|
||||||
"bytes": {
|
"bytes": {
|
||||||
"version": "3.1.2",
|
"version": "3.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz",
|
||||||
@ -348,6 +465,22 @@
|
|||||||
"supports-color": "^7.1.0"
|
"supports-color": "^7.1.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"chokidar": {
|
||||||
|
"version": "3.5.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz",
|
||||||
|
"integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"anymatch": "~3.1.2",
|
||||||
|
"braces": "~3.0.2",
|
||||||
|
"fsevents": "~2.3.2",
|
||||||
|
"glob-parent": "~5.1.2",
|
||||||
|
"is-binary-path": "~2.1.0",
|
||||||
|
"is-glob": "~4.0.1",
|
||||||
|
"normalize-path": "~3.0.0",
|
||||||
|
"readdirp": "~3.6.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"chownr": {
|
"chownr": {
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz",
|
||||||
@ -406,11 +539,39 @@
|
|||||||
"resolved": "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz",
|
||||||
"integrity": "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug=="
|
"integrity": "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug=="
|
||||||
},
|
},
|
||||||
|
"commist": {
|
||||||
|
"version": "3.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/commist/-/commist-3.2.0.tgz",
|
||||||
|
"integrity": "sha512-4PIMoPniho+LqXmpS5d3NuGYncG6XWlkBSVGiWycL22dd42OYdUGil2CWuzklaJoNxyxUSpO4MKIBU94viWNAw=="
|
||||||
|
},
|
||||||
"concat-map": {
|
"concat-map": {
|
||||||
"version": "0.0.1",
|
"version": "0.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
|
||||||
"integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="
|
"integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="
|
||||||
},
|
},
|
||||||
|
"concat-stream": {
|
||||||
|
"version": "2.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-2.0.0.tgz",
|
||||||
|
"integrity": "sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A==",
|
||||||
|
"requires": {
|
||||||
|
"buffer-from": "^1.0.0",
|
||||||
|
"inherits": "^2.0.3",
|
||||||
|
"readable-stream": "^3.0.2",
|
||||||
|
"typedarray": "^0.0.6"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"readable-stream": {
|
||||||
|
"version": "3.6.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz",
|
||||||
|
"integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==",
|
||||||
|
"requires": {
|
||||||
|
"inherits": "^2.0.3",
|
||||||
|
"string_decoder": "^1.1.1",
|
||||||
|
"util-deprecate": "^1.0.1"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"config-chain": {
|
"config-chain": {
|
||||||
"version": "1.1.13",
|
"version": "1.1.13",
|
||||||
"resolved": "https://registry.npmjs.org/config-chain/-/config-chain-1.1.13.tgz",
|
"resolved": "https://registry.npmjs.org/config-chain/-/config-chain-1.1.13.tgz",
|
||||||
@ -464,6 +625,15 @@
|
|||||||
"resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
|
"resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
|
||||||
"integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ=="
|
"integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ=="
|
||||||
},
|
},
|
||||||
|
"cors": {
|
||||||
|
"version": "2.8.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz",
|
||||||
|
"integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==",
|
||||||
|
"requires": {
|
||||||
|
"object-assign": "^4",
|
||||||
|
"vary": "^1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"cross-spawn": {
|
"cross-spawn": {
|
||||||
"version": "7.0.3",
|
"version": "7.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
|
||||||
@ -718,6 +888,59 @@
|
|||||||
"resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
|
||||||
"integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w=="
|
"integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w=="
|
||||||
},
|
},
|
||||||
|
"engine.io": {
|
||||||
|
"version": "6.5.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.5.4.tgz",
|
||||||
|
"integrity": "sha512-KdVSDKhVKyOi+r5uEabrDLZw2qXStVvCsEB/LN3mw4WFi6Gx50jTyuxYVCwAAC0U46FdnzP/ScKRBTXb/NiEOg==",
|
||||||
|
"requires": {
|
||||||
|
"@types/cookie": "^0.4.1",
|
||||||
|
"@types/cors": "^2.8.12",
|
||||||
|
"@types/node": ">=10.0.0",
|
||||||
|
"accepts": "~1.3.4",
|
||||||
|
"base64id": "2.0.0",
|
||||||
|
"cookie": "~0.4.1",
|
||||||
|
"cors": "~2.8.5",
|
||||||
|
"debug": "~4.3.1",
|
||||||
|
"engine.io-parser": "~5.2.1",
|
||||||
|
"ws": "~8.11.0"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"cookie": {
|
||||||
|
"version": "0.4.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz",
|
||||||
|
"integrity": "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA=="
|
||||||
|
},
|
||||||
|
"ws": {
|
||||||
|
"version": "8.11.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/ws/-/ws-8.11.0.tgz",
|
||||||
|
"integrity": "sha512-HPG3wQd9sNQoT9xHyNCXoDUa+Xw/VevmY9FoHyQ+g+rrMn4j6FB4np7Z0OhdTgjx6MgQLK7jwSy1YecU1+4Asg=="
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"engine.io-client": {
|
||||||
|
"version": "6.5.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-6.5.3.tgz",
|
||||||
|
"integrity": "sha512-9Z0qLB0NIisTRt1DZ/8U2k12RJn8yls/nXMZLn+/N8hANT3TcYjKFKcwbw5zFQiN4NTde3TSY9zb79e1ij6j9Q==",
|
||||||
|
"requires": {
|
||||||
|
"@socket.io/component-emitter": "~3.1.0",
|
||||||
|
"debug": "~4.3.1",
|
||||||
|
"engine.io-parser": "~5.2.1",
|
||||||
|
"ws": "~8.11.0",
|
||||||
|
"xmlhttprequest-ssl": "~2.0.0"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"ws": {
|
||||||
|
"version": "8.11.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/ws/-/ws-8.11.0.tgz",
|
||||||
|
"integrity": "sha512-HPG3wQd9sNQoT9xHyNCXoDUa+Xw/VevmY9FoHyQ+g+rrMn4j6FB4np7Z0OhdTgjx6MgQLK7jwSy1YecU1+4Asg=="
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"engine.io-parser": {
|
||||||
|
"version": "5.2.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.2.1.tgz",
|
||||||
|
"integrity": "sha512-9JktcM3u18nU9N2Lz3bWeBgxVgOKpw7yhRaoxQA3FUDZzzw+9WlA6p4G4u0RixNkg14fH7EfEc/RhpurtiROTQ=="
|
||||||
|
},
|
||||||
"entities": {
|
"entities": {
|
||||||
"version": "4.5.0",
|
"version": "4.5.0",
|
||||||
"resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz",
|
"resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz",
|
||||||
@ -797,6 +1020,16 @@
|
|||||||
"es5-ext": "~0.10.14"
|
"es5-ext": "~0.10.14"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"event-target-shim": {
|
||||||
|
"version": "5.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz",
|
||||||
|
"integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ=="
|
||||||
|
},
|
||||||
|
"events": {
|
||||||
|
"version": "3.3.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz",
|
||||||
|
"integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q=="
|
||||||
|
},
|
||||||
"express": {
|
"express": {
|
||||||
"version": "4.18.2",
|
"version": "4.18.2",
|
||||||
"resolved": "https://registry.npmjs.org/express/-/express-4.18.2.tgz",
|
"resolved": "https://registry.npmjs.org/express/-/express-4.18.2.tgz",
|
||||||
@ -944,6 +1177,15 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"fast-unique-numbers": {
|
||||||
|
"version": "8.0.13",
|
||||||
|
"resolved": "https://registry.npmjs.org/fast-unique-numbers/-/fast-unique-numbers-8.0.13.tgz",
|
||||||
|
"integrity": "sha512-7OnTFAVPefgw2eBJ1xj2PGGR9FwYzSUso9decayHgCDX4sJkHLdcsYTytTg+tYv+wKF3U8gJuSBz2jJpQV4u/g==",
|
||||||
|
"requires": {
|
||||||
|
"@babel/runtime": "^7.23.8",
|
||||||
|
"tslib": "^2.6.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
"fetch-blob": {
|
"fetch-blob": {
|
||||||
"version": "3.2.0",
|
"version": "3.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.2.0.tgz",
|
||||||
@ -971,6 +1213,15 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"fill-range": {
|
||||||
|
"version": "7.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
|
||||||
|
"integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"to-regex-range": "^5.0.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"finalhandler": {
|
"finalhandler": {
|
||||||
"version": "1.2.0",
|
"version": "1.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz",
|
||||||
@ -1092,6 +1343,13 @@
|
|||||||
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
|
||||||
"integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw=="
|
"integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw=="
|
||||||
},
|
},
|
||||||
|
"fsevents": {
|
||||||
|
"version": "2.3.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
|
||||||
|
"integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
|
||||||
|
"dev": true,
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
"function-bind": {
|
"function-bind": {
|
||||||
"version": "1.1.2",
|
"version": "1.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
|
||||||
@ -1150,6 +1408,15 @@
|
|||||||
"path-is-absolute": "^1.0.0"
|
"path-is-absolute": "^1.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"glob-parent": {
|
||||||
|
"version": "5.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
|
||||||
|
"integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"is-glob": "^4.0.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"gopd": {
|
"gopd": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz",
|
||||||
@ -1204,6 +1471,11 @@
|
|||||||
"resolved": "https://registry.npmjs.org/helmet/-/helmet-7.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/helmet/-/helmet-7.1.0.tgz",
|
||||||
"integrity": "sha512-g+HZqgfbpXdCkme/Cd/mZkV0aV3BZZZSugecH03kl38m/Kmdx8jKjBikpDj2cr+Iynv4KpYEviojNdTJActJAg=="
|
"integrity": "sha512-g+HZqgfbpXdCkme/Cd/mZkV0aV3BZZZSugecH03kl38m/Kmdx8jKjBikpDj2cr+Iynv4KpYEviojNdTJActJAg=="
|
||||||
},
|
},
|
||||||
|
"help-me": {
|
||||||
|
"version": "5.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/help-me/-/help-me-5.0.0.tgz",
|
||||||
|
"integrity": "sha512-7xgomUX6ADmcYzFik0HzAxh/73YlKR9bmFzf51CZwR+b6YtzU2m0u49hQCqV6SvlqIqsaxovfwdvbnsw3b/zpg=="
|
||||||
|
},
|
||||||
"htmlparser2": {
|
"htmlparser2": {
|
||||||
"version": "8.0.2",
|
"version": "8.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-8.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-8.0.2.tgz",
|
||||||
@ -1244,6 +1516,17 @@
|
|||||||
"safer-buffer": ">= 2.1.2 < 3"
|
"safer-buffer": ">= 2.1.2 < 3"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"ieee754": {
|
||||||
|
"version": "1.2.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz",
|
||||||
|
"integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA=="
|
||||||
|
},
|
||||||
|
"ignore-by-default": {
|
||||||
|
"version": "1.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz",
|
||||||
|
"integrity": "sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"inflection": {
|
"inflection": {
|
||||||
"version": "1.13.4",
|
"version": "1.13.4",
|
||||||
"resolved": "https://registry.npmjs.org/inflection/-/inflection-1.13.4.tgz",
|
"resolved": "https://registry.npmjs.org/inflection/-/inflection-1.13.4.tgz",
|
||||||
@ -1273,6 +1556,15 @@
|
|||||||
"resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz",
|
"resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz",
|
||||||
"integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g=="
|
"integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g=="
|
||||||
},
|
},
|
||||||
|
"is-binary-path": {
|
||||||
|
"version": "2.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
|
||||||
|
"integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"binary-extensions": "^2.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"is-core-module": {
|
"is-core-module": {
|
||||||
"version": "2.13.1",
|
"version": "2.13.1",
|
||||||
"resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz",
|
"resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz",
|
||||||
@ -1281,11 +1573,32 @@
|
|||||||
"hasown": "^2.0.0"
|
"hasown": "^2.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"is-extglob": {
|
||||||
|
"version": "2.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
|
||||||
|
"integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"is-fullwidth-code-point": {
|
"is-fullwidth-code-point": {
|
||||||
"version": "3.0.0",
|
"version": "3.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
|
||||||
"integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg=="
|
"integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg=="
|
||||||
},
|
},
|
||||||
|
"is-glob": {
|
||||||
|
"version": "4.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
|
||||||
|
"integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"is-extglob": "^2.1.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"is-number": {
|
||||||
|
"version": "7.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
|
||||||
|
"integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"is-plain-object": {
|
"is-plain-object": {
|
||||||
"version": "5.0.0",
|
"version": "5.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz",
|
||||||
@ -1372,6 +1685,11 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"js-sdsl": {
|
||||||
|
"version": "4.3.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.3.0.tgz",
|
||||||
|
"integrity": "sha512-mifzlm2+5nZ+lEcLJMoBK0/IH/bDg8XnJfd/Wq6IP+xoCjLZsTOnV2QpxlVbX9bMnkl5PdEjNtBJ9Cj1NjifhQ=="
|
||||||
|
},
|
||||||
"jsonfile": {
|
"jsonfile": {
|
||||||
"version": "6.1.0",
|
"version": "6.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz",
|
||||||
@ -1497,6 +1815,11 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"minimist": {
|
||||||
|
"version": "1.2.8",
|
||||||
|
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz",
|
||||||
|
"integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA=="
|
||||||
|
},
|
||||||
"minipass": {
|
"minipass": {
|
||||||
"version": "5.0.0",
|
"version": "5.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz",
|
||||||
@ -1526,6 +1849,11 @@
|
|||||||
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz",
|
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz",
|
||||||
"integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw=="
|
"integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw=="
|
||||||
},
|
},
|
||||||
|
"moment": {
|
||||||
|
"version": "2.30.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/moment/-/moment-2.30.1.tgz",
|
||||||
|
"integrity": "sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how=="
|
||||||
|
},
|
||||||
"moment-timezone": {
|
"moment-timezone": {
|
||||||
"version": "0.5.44",
|
"version": "0.5.44",
|
||||||
"resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.44.tgz",
|
"resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.44.tgz",
|
||||||
@ -1541,6 +1869,47 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"mqtt": {
|
||||||
|
"version": "5.3.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/mqtt/-/mqtt-5.3.5.tgz",
|
||||||
|
"integrity": "sha512-xd7qt/LEM721U6yHQcqjlaAKXL1Fsqf/MXq6C2WPi/6OXK2jdSzL1eZ7ZUgjea7IY2yFLRWD5LNdT1mL0arPoA==",
|
||||||
|
"requires": {
|
||||||
|
"@types/readable-stream": "^4.0.5",
|
||||||
|
"@types/ws": "^8.5.9",
|
||||||
|
"commist": "^3.2.0",
|
||||||
|
"concat-stream": "^2.0.0",
|
||||||
|
"debug": "^4.3.4",
|
||||||
|
"help-me": "^5.0.0",
|
||||||
|
"lru-cache": "^10.0.1",
|
||||||
|
"minimist": "^1.2.8",
|
||||||
|
"mqtt": "^5.2.0",
|
||||||
|
"mqtt-packet": "^9.0.0",
|
||||||
|
"number-allocator": "^1.0.14",
|
||||||
|
"readable-stream": "^4.4.2",
|
||||||
|
"reinterval": "^1.1.0",
|
||||||
|
"rfdc": "^1.3.0",
|
||||||
|
"split2": "^4.2.0",
|
||||||
|
"worker-timers": "^7.0.78",
|
||||||
|
"ws": "^8.14.2"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"lru-cache": {
|
||||||
|
"version": "10.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.1.0.tgz",
|
||||||
|
"integrity": "sha512-/1clY/ui8CzjKFyjdvwPWJUYKiFVXG2I2cY0ssG7h4+hwk+XOIX7ZSG9Q7TW8TW3Kp3BUSqgFWBLgL4PJ+Blag=="
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"mqtt-packet": {
|
||||||
|
"version": "9.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/mqtt-packet/-/mqtt-packet-9.0.0.tgz",
|
||||||
|
"integrity": "sha512-8v+HkX+fwbodsWAZIZTI074XIoxVBOmPeggQuDFCGg1SqNcC+uoRMWu7J6QlJPqIUIJXmjNYYHxBBLr1Y/Df4w==",
|
||||||
|
"requires": {
|
||||||
|
"bl": "^6.0.8",
|
||||||
|
"debug": "^4.3.4",
|
||||||
|
"process-nextick-args": "^2.0.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"ms": {
|
"ms": {
|
||||||
"version": "2.1.2",
|
"version": "2.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
|
||||||
@ -1631,6 +2000,41 @@
|
|||||||
"resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.9.8.tgz",
|
"resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.9.8.tgz",
|
||||||
"integrity": "sha512-cfrYUk16e67Ks051i4CntM9kshRYei1/o/Gi8K1d+R34OIs21xdFnW7Pt7EucmVKA0LKtqUGNcjMZ7ehjl49mQ=="
|
"integrity": "sha512-cfrYUk16e67Ks051i4CntM9kshRYei1/o/Gi8K1d+R34OIs21xdFnW7Pt7EucmVKA0LKtqUGNcjMZ7ehjl49mQ=="
|
||||||
},
|
},
|
||||||
|
"nodemon": {
|
||||||
|
"version": "3.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/nodemon/-/nodemon-3.0.3.tgz",
|
||||||
|
"integrity": "sha512-7jH/NXbFPxVaMwmBCC2B9F/V6X1VkEdNgx3iu9jji8WxWcvhMWkmhNWhI5077zknOnZnBzba9hZP6bCPJLSReQ==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"chokidar": "^3.5.2",
|
||||||
|
"debug": "^4",
|
||||||
|
"ignore-by-default": "^1.0.1",
|
||||||
|
"minimatch": "^3.1.2",
|
||||||
|
"pstree.remy": "^1.1.8",
|
||||||
|
"semver": "^7.5.3",
|
||||||
|
"simple-update-notifier": "^2.0.0",
|
||||||
|
"supports-color": "^5.5.0",
|
||||||
|
"touch": "^3.1.0",
|
||||||
|
"undefsafe": "^2.0.5"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"has-flag": {
|
||||||
|
"version": "3.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
|
||||||
|
"integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"supports-color": {
|
||||||
|
"version": "5.5.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
|
||||||
|
"integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"has-flag": "^3.0.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"nopt": {
|
"nopt": {
|
||||||
"version": "5.0.0",
|
"version": "5.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz",
|
||||||
@ -1639,6 +2043,12 @@
|
|||||||
"abbrev": "1"
|
"abbrev": "1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"normalize-path": {
|
||||||
|
"version": "3.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
|
||||||
|
"integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"npmlog": {
|
"npmlog": {
|
||||||
"version": "5.0.1",
|
"version": "5.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/npmlog/-/npmlog-5.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/npmlog/-/npmlog-5.0.1.tgz",
|
||||||
@ -1650,6 +2060,15 @@
|
|||||||
"set-blocking": "^2.0.0"
|
"set-blocking": "^2.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"number-allocator": {
|
||||||
|
"version": "1.0.14",
|
||||||
|
"resolved": "https://registry.npmjs.org/number-allocator/-/number-allocator-1.0.14.tgz",
|
||||||
|
"integrity": "sha512-OrL44UTVAvkKdOdRQZIJpLkAdjXGTRda052sN4sO77bKEzYYqWKMBjQvrJFzqygI99gL6Z4u2xctPW1tB8ErvA==",
|
||||||
|
"requires": {
|
||||||
|
"debug": "^4.3.1",
|
||||||
|
"js-sdsl": "4.3.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"object-assign": {
|
"object-assign": {
|
||||||
"version": "4.1.1",
|
"version": "4.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
|
||||||
@ -1778,6 +2197,12 @@
|
|||||||
"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz",
|
||||||
"integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ=="
|
"integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ=="
|
||||||
},
|
},
|
||||||
|
"picomatch": {
|
||||||
|
"version": "2.3.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
|
||||||
|
"integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"pngjs": {
|
"pngjs": {
|
||||||
"version": "5.0.0",
|
"version": "5.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/pngjs/-/pngjs-5.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/pngjs/-/pngjs-5.0.0.tgz",
|
||||||
@ -1793,6 +2218,16 @@
|
|||||||
"source-map-js": "^1.0.2"
|
"source-map-js": "^1.0.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"process": {
|
||||||
|
"version": "0.11.10",
|
||||||
|
"resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz",
|
||||||
|
"integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A=="
|
||||||
|
},
|
||||||
|
"process-nextick-args": {
|
||||||
|
"version": "2.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
|
||||||
|
"integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag=="
|
||||||
|
},
|
||||||
"proto-list": {
|
"proto-list": {
|
||||||
"version": "1.2.4",
|
"version": "1.2.4",
|
||||||
"resolved": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz",
|
"resolved": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz",
|
||||||
@ -1812,6 +2247,12 @@
|
|||||||
"resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
|
||||||
"integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg=="
|
"integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg=="
|
||||||
},
|
},
|
||||||
|
"pstree.remy": {
|
||||||
|
"version": "1.1.8",
|
||||||
|
"resolved": "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.8.tgz",
|
||||||
|
"integrity": "sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"qrcode": {
|
"qrcode": {
|
||||||
"version": "1.5.3",
|
"version": "1.5.3",
|
||||||
"resolved": "https://registry.npmjs.org/qrcode/-/qrcode-1.5.3.tgz",
|
"resolved": "https://registry.npmjs.org/qrcode/-/qrcode-1.5.3.tgz",
|
||||||
@ -1852,6 +2293,37 @@
|
|||||||
"unpipe": "1.0.0"
|
"unpipe": "1.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"readable-stream": {
|
||||||
|
"version": "4.5.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.5.2.tgz",
|
||||||
|
"integrity": "sha512-yjavECdqeZ3GLXNgRXgeQEdz9fvDDkNKyHnbHRFtOr7/LcfgBcmct7t/ET+HaCTqfh06OzoAxrkN/IfjJBVe+g==",
|
||||||
|
"requires": {
|
||||||
|
"abort-controller": "^3.0.0",
|
||||||
|
"buffer": "^6.0.3",
|
||||||
|
"events": "^3.3.0",
|
||||||
|
"process": "^0.11.10",
|
||||||
|
"string_decoder": "^1.3.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"readdirp": {
|
||||||
|
"version": "3.6.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
|
||||||
|
"integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"picomatch": "^2.2.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"regenerator-runtime": {
|
||||||
|
"version": "0.14.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz",
|
||||||
|
"integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw=="
|
||||||
|
},
|
||||||
|
"reinterval": {
|
||||||
|
"version": "1.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/reinterval/-/reinterval-1.1.0.tgz",
|
||||||
|
"integrity": "sha512-QIRet3SYrGp0HUHO88jVskiG6seqUGC5iAG7AwI/BV4ypGcuqk9Du6YQBUOUqm9c8pw1eyLoIaONifRua1lsEQ=="
|
||||||
|
},
|
||||||
"require-directory": {
|
"require-directory": {
|
||||||
"version": "2.1.1",
|
"version": "2.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
|
||||||
@ -1877,6 +2349,11 @@
|
|||||||
"resolved": "https://registry.npmjs.org/retry-as-promised/-/retry-as-promised-7.0.4.tgz",
|
"resolved": "https://registry.npmjs.org/retry-as-promised/-/retry-as-promised-7.0.4.tgz",
|
||||||
"integrity": "sha512-XgmCoxKWkDofwH8WddD0w85ZfqYz+ZHlr5yo+3YUCfycWawU56T5ckWXsScsj5B8tqUcIG67DxXByo3VUgiAdA=="
|
"integrity": "sha512-XgmCoxKWkDofwH8WddD0w85ZfqYz+ZHlr5yo+3YUCfycWawU56T5ckWXsScsj5B8tqUcIG67DxXByo3VUgiAdA=="
|
||||||
},
|
},
|
||||||
|
"rfdc": {
|
||||||
|
"version": "1.3.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.1.tgz",
|
||||||
|
"integrity": "sha512-r5a3l5HzYlIC68TpmYKlxWjmOP6wiPJ1vWv2HeLhNsRZMrCkxeqxiHlQ21oXmQ4F3SiryXBHhAD7JZqvOJjFmg=="
|
||||||
|
},
|
||||||
"rimraf": {
|
"rimraf": {
|
||||||
"version": "3.0.2",
|
"version": "3.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
|
||||||
@ -2123,11 +2600,74 @@
|
|||||||
"resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz",
|
"resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz",
|
||||||
"integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ=="
|
"integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ=="
|
||||||
},
|
},
|
||||||
|
"simple-update-notifier": {
|
||||||
|
"version": "2.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/simple-update-notifier/-/simple-update-notifier-2.0.0.tgz",
|
||||||
|
"integrity": "sha512-a2B9Y0KlNXl9u/vsW6sTIu9vGEpfKu2wRV6l1H3XEas/0gUIzGzBoP/IouTcUQbm9JWZLH3COxyn03TYlFax6w==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"semver": "^7.5.3"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"socket.io": {
|
||||||
|
"version": "4.7.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.7.4.tgz",
|
||||||
|
"integrity": "sha512-DcotgfP1Zg9iP/dH9zvAQcWrE0TtbMVwXmlV4T4mqsvY+gw+LqUGPfx2AoVyRk0FLME+GQhufDMyacFmw7ksqw==",
|
||||||
|
"requires": {
|
||||||
|
"accepts": "~1.3.4",
|
||||||
|
"base64id": "~2.0.0",
|
||||||
|
"cors": "~2.8.5",
|
||||||
|
"debug": "~4.3.2",
|
||||||
|
"engine.io": "~6.5.2",
|
||||||
|
"socket.io-adapter": "~2.5.2",
|
||||||
|
"socket.io-parser": "~4.2.4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"socket.io-adapter": {
|
||||||
|
"version": "2.5.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-2.5.2.tgz",
|
||||||
|
"integrity": "sha512-87C3LO/NOMc+eMcpcxUBebGjkpMDkNBS9tf7KJqcDsmL936EChtVva71Dw2q4tQcuVC+hAUy4an2NO/sYXmwRA==",
|
||||||
|
"requires": {
|
||||||
|
"ws": "~8.11.0"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"ws": {
|
||||||
|
"version": "8.11.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/ws/-/ws-8.11.0.tgz",
|
||||||
|
"integrity": "sha512-HPG3wQd9sNQoT9xHyNCXoDUa+Xw/VevmY9FoHyQ+g+rrMn4j6FB4np7Z0OhdTgjx6MgQLK7jwSy1YecU1+4Asg=="
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"socket.io-client": {
|
||||||
|
"version": "4.7.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-4.7.4.tgz",
|
||||||
|
"integrity": "sha512-wh+OkeF0rAVCrABWQBaEjLfb7DVPotMbu0cgWgyR0v6eA4EoVnAwcIeIbcdTE3GT/H3kbdLl7OoH2+asoDRIIg==",
|
||||||
|
"requires": {
|
||||||
|
"@socket.io/component-emitter": "~3.1.0",
|
||||||
|
"debug": "~4.3.2",
|
||||||
|
"engine.io-client": "~6.5.2",
|
||||||
|
"socket.io-parser": "~4.2.4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"socket.io-parser": {
|
||||||
|
"version": "4.2.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.4.tgz",
|
||||||
|
"integrity": "sha512-/GbIKmo8ioc+NIWIhwdecY0ge+qVBSMdgxGygevmdHj24bsfgtCmcUUcQ5ZzcylGFHsN3k4HB4Cgkl96KVnuew==",
|
||||||
|
"requires": {
|
||||||
|
"@socket.io/component-emitter": "~3.1.0",
|
||||||
|
"debug": "~4.3.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"source-map-js": {
|
"source-map-js": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz",
|
||||||
"integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw=="
|
"integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw=="
|
||||||
},
|
},
|
||||||
|
"split2": {
|
||||||
|
"version": "4.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz",
|
||||||
|
"integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg=="
|
||||||
|
},
|
||||||
"sqlstring": {
|
"sqlstring": {
|
||||||
"version": "2.3.3",
|
"version": "2.3.3",
|
||||||
"resolved": "https://registry.npmjs.org/sqlstring/-/sqlstring-2.3.3.tgz",
|
"resolved": "https://registry.npmjs.org/sqlstring/-/sqlstring-2.3.3.tgz",
|
||||||
@ -2229,6 +2769,15 @@
|
|||||||
"next-tick": "1"
|
"next-tick": "1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"to-regex-range": {
|
||||||
|
"version": "5.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
|
||||||
|
"integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"is-number": "^7.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"toidentifier": {
|
"toidentifier": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz",
|
||||||
@ -2239,11 +2788,36 @@
|
|||||||
"resolved": "https://registry.npmjs.org/toposort-class/-/toposort-class-1.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/toposort-class/-/toposort-class-1.0.1.tgz",
|
||||||
"integrity": "sha512-OsLcGGbYF3rMjPUf8oKktyvCiUxSbqMMS39m33MAjLTC1DVIH6x3WSt63/M77ihI09+Sdfk1AXvfhCEeUmC7mg=="
|
"integrity": "sha512-OsLcGGbYF3rMjPUf8oKktyvCiUxSbqMMS39m33MAjLTC1DVIH6x3WSt63/M77ihI09+Sdfk1AXvfhCEeUmC7mg=="
|
||||||
},
|
},
|
||||||
|
"touch": {
|
||||||
|
"version": "3.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/touch/-/touch-3.1.0.tgz",
|
||||||
|
"integrity": "sha512-WBx8Uy5TLtOSRtIq+M03/sKDrXCLHxwDcquSP2c43Le03/9serjQBIztjRz6FkJez9D/hleyAXTBGLwwZUw9lA==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"nopt": "~1.0.10"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"nopt": {
|
||||||
|
"version": "1.0.10",
|
||||||
|
"resolved": "https://registry.npmjs.org/nopt/-/nopt-1.0.10.tgz",
|
||||||
|
"integrity": "sha512-NWmpvLSqUrgrAC9HCuxEvb+PSloHpqVu+FqcO4eeF2h5qYRhA7ev6KvelyQAKtegUbC6RypJnlEOhd8vloNKYg==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"abbrev": "1"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"tr46": {
|
"tr46": {
|
||||||
"version": "0.0.3",
|
"version": "0.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",
|
||||||
"integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw=="
|
"integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw=="
|
||||||
},
|
},
|
||||||
|
"tslib": {
|
||||||
|
"version": "2.6.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz",
|
||||||
|
"integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q=="
|
||||||
|
},
|
||||||
"tsscmp": {
|
"tsscmp": {
|
||||||
"version": "1.0.6",
|
"version": "1.0.6",
|
||||||
"resolved": "https://registry.npmjs.org/tsscmp/-/tsscmp-1.0.6.tgz",
|
"resolved": "https://registry.npmjs.org/tsscmp/-/tsscmp-1.0.6.tgz",
|
||||||
@ -2263,6 +2837,11 @@
|
|||||||
"mime-types": "~2.1.24"
|
"mime-types": "~2.1.24"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"typedarray": {
|
||||||
|
"version": "0.0.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz",
|
||||||
|
"integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA=="
|
||||||
|
},
|
||||||
"uid-safe": {
|
"uid-safe": {
|
||||||
"version": "2.1.5",
|
"version": "2.1.5",
|
||||||
"resolved": "https://registry.npmjs.org/uid-safe/-/uid-safe-2.1.5.tgz",
|
"resolved": "https://registry.npmjs.org/uid-safe/-/uid-safe-2.1.5.tgz",
|
||||||
@ -2279,6 +2858,12 @@
|
|||||||
"bluebird": "^3.7.2"
|
"bluebird": "^3.7.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"undefsafe": {
|
||||||
|
"version": "2.0.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.5.tgz",
|
||||||
|
"integrity": "sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"undici-types": {
|
"undici-types": {
|
||||||
"version": "5.26.5",
|
"version": "5.26.5",
|
||||||
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz",
|
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz",
|
||||||
@ -2367,6 +2952,37 @@
|
|||||||
"@types/node": "*"
|
"@types/node": "*"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"worker-timers": {
|
||||||
|
"version": "7.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/worker-timers/-/worker-timers-7.1.1.tgz",
|
||||||
|
"integrity": "sha512-axtq83GwPqYwkQmQmei2abQ9cT7oSwmLw4lQCZ9VmMH9g4t4kuEF1Gw+tdnIJGHCiZ2QPDnr/+307bYx6tynLA==",
|
||||||
|
"requires": {
|
||||||
|
"@babel/runtime": "^7.23.8",
|
||||||
|
"tslib": "^2.6.2",
|
||||||
|
"worker-timers-broker": "^6.1.1",
|
||||||
|
"worker-timers-worker": "^7.0.65"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"worker-timers-broker": {
|
||||||
|
"version": "6.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/worker-timers-broker/-/worker-timers-broker-6.1.1.tgz",
|
||||||
|
"integrity": "sha512-CTlDnkXAewtYvw5gOwVIc6UuIPcNHJrqWxBMhZbCWOmadvl20nPs9beAsXlaTEwW3G2KBpuKiSgkhBkhl3mxDA==",
|
||||||
|
"requires": {
|
||||||
|
"@babel/runtime": "^7.23.8",
|
||||||
|
"fast-unique-numbers": "^8.0.13",
|
||||||
|
"tslib": "^2.6.2",
|
||||||
|
"worker-timers-worker": "^7.0.65"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"worker-timers-worker": {
|
||||||
|
"version": "7.0.65",
|
||||||
|
"resolved": "https://registry.npmjs.org/worker-timers-worker/-/worker-timers-worker-7.0.65.tgz",
|
||||||
|
"integrity": "sha512-Dl4nGONr8A8Fr+vQnH7Ee+o2iB480S1fBcyJYqnMyMwGRVyQZLZU+o91vbMvU1vHqiryRQmjXzzMYlh86wx+YQ==",
|
||||||
|
"requires": {
|
||||||
|
"@babel/runtime": "^7.23.8",
|
||||||
|
"tslib": "^2.6.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
"wrap-ansi": {
|
"wrap-ansi": {
|
||||||
"version": "6.2.0",
|
"version": "6.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz",
|
||||||
@ -2392,6 +3008,16 @@
|
|||||||
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
|
||||||
"integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="
|
"integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="
|
||||||
},
|
},
|
||||||
|
"ws": {
|
||||||
|
"version": "8.16.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/ws/-/ws-8.16.0.tgz",
|
||||||
|
"integrity": "sha512-HS0c//TP7Ina87TfiPUz1rQzMhHrl/SG2guqRcTOIUYD2q8uhUdNHZYJUaQ8aTGPzCh+c6oawMKW35nFl1dxyQ=="
|
||||||
|
},
|
||||||
|
"xmlhttprequest-ssl": {
|
||||||
|
"version": "2.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-2.0.0.tgz",
|
||||||
|
"integrity": "sha512-QKxVRxiRACQcVuQEYFsI1hhkrMlrXHPegbbd1yn9UHOmRxY+si12nQYzri3vbzt8VdTTRviqcKxcyllFas5z2A=="
|
||||||
|
},
|
||||||
"y18n": {
|
"y18n": {
|
||||||
"version": "4.0.3",
|
"version": "4.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz",
|
||||||
|
Loading…
x
Reference in New Issue
Block a user