mirror of
https://github.com/cpvalente/ontime.git
synced 2026-08-04 06:58:02 +00:00
Merge branch 'wip/migratedb' into master
This commit is contained in:
+1
-1
@@ -34,4 +34,4 @@ yarn.lock
|
||||
package.json
|
||||
package-lock.json
|
||||
db.json
|
||||
server/db backup.json
|
||||
db backup.json
|
||||
|
||||
@@ -10,3 +10,4 @@ export const serverURL = calculateServer();
|
||||
export const eventURL = serverURL + EVENT_TABLE;
|
||||
export const eventsURL = serverURL + EVENTS_TABLE;
|
||||
export const playbackURL = serverURL + 'playback';
|
||||
export const ontimeURL = serverURL + 'ontime';
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
import axios from 'axios';
|
||||
import { ontimeURL } from './apiConstants';
|
||||
|
||||
export const downloadEvents = async () => {
|
||||
await axios({
|
||||
url: ontimeURL + '/db',
|
||||
method: 'GET',
|
||||
responseType: 'blob', // important
|
||||
}).then((response) => {
|
||||
let headerLine = response.headers['Content-Disposition'];
|
||||
console.log(response);
|
||||
let filename = 'events.json';
|
||||
|
||||
// try and get the filename from the response
|
||||
if (headerLine != null) {
|
||||
let startFileNameIndex = headerLine.indexOf('"') + 1;
|
||||
let endFileNameIndex = headerLine.lastIndexOf('"');
|
||||
filename = headerLine.substring(startFileNameIndex, endFileNameIndex);
|
||||
}
|
||||
|
||||
const url = window.URL.createObjectURL(new Blob([response.data]));
|
||||
const link = document.createElement('a');
|
||||
link.href = url;
|
||||
link.setAttribute('download', filename);
|
||||
document.body.appendChild(link);
|
||||
link.click();
|
||||
});
|
||||
};
|
||||
|
||||
export const uploadEvents = async (file) => {
|
||||
console.log('uploading', file);
|
||||
const formData = new FormData();
|
||||
formData.append('jsondb', file); // appending file
|
||||
await axios
|
||||
.post(ontimeURL + '/db', formData, {
|
||||
headers: {
|
||||
'Content-Type': 'multipart/form-data',
|
||||
},
|
||||
})
|
||||
.then((res) => console.log(res.data))
|
||||
.catch((err) => console.error(err));
|
||||
};
|
||||
@@ -0,0 +1,18 @@
|
||||
import { IconButton } from '@chakra-ui/button';
|
||||
import { FiDownload } from 'react-icons/fi';
|
||||
|
||||
export default function DownloadIconBtn(props) {
|
||||
const { clickhandler, ...rest } = props;
|
||||
return (
|
||||
<IconButton
|
||||
size={props.size || 'xs'}
|
||||
icon={<FiDownload />}
|
||||
isRound
|
||||
variant='outline'
|
||||
onClick={clickhandler}
|
||||
_focus={{ boxShadow: 'none' }}
|
||||
colorScheme='whiteAlpha'
|
||||
{...rest}
|
||||
/>
|
||||
);
|
||||
}
|
||||
@@ -9,6 +9,8 @@ import { useDisclosure } from '@chakra-ui/hooks';
|
||||
import SettingsModal from '../modals/SettingsModal';
|
||||
import SettingsIconBtn from 'common/components/buttons/SettingsIconBtn';
|
||||
import { useEffect } from 'react';
|
||||
import DownloadIconBtn from 'common/components/buttons/DownloadIconBtn';
|
||||
import { downloadEvents } from 'app/api/ontimeApi';
|
||||
|
||||
export default function Editor() {
|
||||
const { isOpen, onOpen, onClose } = useDisclosure();
|
||||
@@ -18,6 +20,10 @@ export default function Editor() {
|
||||
document.title = 'ontime - Editor';
|
||||
}, []);
|
||||
|
||||
const handleDownload = () => {
|
||||
downloadEvents();
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<SettingsModal isOpen={isOpen} onClose={onClose} />
|
||||
@@ -67,6 +73,7 @@ export default function Editor() {
|
||||
<Box className={styles.settings}>
|
||||
<div className={styles.content}>
|
||||
<SettingsIconBtn size='md' clickhandler={onOpen} />
|
||||
<DownloadIconBtn size='md' clickhandler={handleDownload} />
|
||||
</div>
|
||||
</Box>
|
||||
</div>
|
||||
|
||||
@@ -107,6 +107,12 @@
|
||||
padding-top: 1.5em;
|
||||
}
|
||||
|
||||
.settings > .content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 1em;
|
||||
}
|
||||
|
||||
.cornerButtonContainer {
|
||||
position: relative;
|
||||
top: -4.5em;
|
||||
|
||||
@@ -1,80 +0,0 @@
|
||||
// get config
|
||||
const config = require('./config.json');
|
||||
|
||||
// init database
|
||||
const low = require('lowdb');
|
||||
const FileSync = require('lowdb/adapters/FileSync');
|
||||
|
||||
const adapter = new FileSync(config.database.filename);
|
||||
const db = low(adapter);
|
||||
|
||||
// dependencies
|
||||
const express = require('express');
|
||||
const http = require('http');
|
||||
const cors = require('cors');
|
||||
const { dbModel } = require('./data/dataModel.js');
|
||||
|
||||
db.defaults(dbModel).write();
|
||||
|
||||
// export db
|
||||
module.exports.db = db;
|
||||
|
||||
// Import Routes
|
||||
const eventsRouter = require('./routes/eventsRouter.js');
|
||||
const eventRouter = require('./routes/eventRouter.js');
|
||||
// No settings yet
|
||||
// const settingsRouter = require('./routes/settingsRouter.js');
|
||||
|
||||
// Setup default port
|
||||
const port = process.env.PORT || config.server.port;
|
||||
|
||||
// Global Objects
|
||||
const EventTimer = require('./classes/EventTimer.js');
|
||||
|
||||
// Create express APP
|
||||
const app = express();
|
||||
|
||||
// setup cors for all routes
|
||||
app.use(cors());
|
||||
|
||||
// enable pre-flight cors
|
||||
app.options('*', cors());
|
||||
|
||||
// Implement middleware
|
||||
app.use(express.urlencoded({ extended: true }));
|
||||
app.use(express.json());
|
||||
|
||||
// Implement route endpoints
|
||||
app.use('/events', eventsRouter);
|
||||
app.use('/event', eventRouter);
|
||||
|
||||
// implement general router
|
||||
app.get('/', (req, res) => {
|
||||
res.send('ontime API');
|
||||
});
|
||||
|
||||
// Implement route for errors
|
||||
app.use((err, req, res, next) => {
|
||||
console.error(err.stack);
|
||||
res.status(500).send('Something broke!');
|
||||
});
|
||||
|
||||
// create HTTP server
|
||||
const server = http.createServer(app);
|
||||
|
||||
// get data (if any)
|
||||
const eventlist = db.get('events').value();
|
||||
|
||||
// init timer
|
||||
global.timer = new EventTimer(server, config);
|
||||
global.timer.setupWithEventList(eventlist);
|
||||
|
||||
// Start server
|
||||
server.listen(port, () =>
|
||||
console.log(`HTTP Server is listening on port ${port}`)
|
||||
);
|
||||
|
||||
// Start OSC server
|
||||
const { initiateOSC } = require('./controllers/OscController.js');
|
||||
|
||||
initiateOSC(config.osc);
|
||||
@@ -1,15 +0,0 @@
|
||||
{
|
||||
"timer": {
|
||||
"refresh": 1000
|
||||
},
|
||||
"server": {
|
||||
"port": 4001
|
||||
},
|
||||
"database": {
|
||||
"filename": "db.json",
|
||||
"tablename": "events"
|
||||
},
|
||||
"osc": {
|
||||
"port": 8888
|
||||
}
|
||||
}
|
||||
@@ -1,144 +0,0 @@
|
||||
// get database
|
||||
const { db } = require('../app.js');
|
||||
|
||||
const table = 'event';
|
||||
|
||||
function getSettings() {
|
||||
return db.get(table).value();
|
||||
}
|
||||
|
||||
// Create controller for GET request to 'event'
|
||||
// Returns ACK message
|
||||
exports.getAll = async (req, res) => {
|
||||
const settings = getSettings();
|
||||
if (settings) res.json(settings);
|
||||
else res.sendStatus(400);
|
||||
};
|
||||
|
||||
// Create controller for POST request to 'event'
|
||||
// Returns ACK message
|
||||
exports.post = async (req, res) => {
|
||||
if (!req.body) {
|
||||
res.status(400).send('No object found in request');
|
||||
return;
|
||||
}
|
||||
// TODO: validate data
|
||||
try {
|
||||
db.get(table)
|
||||
.assign({ ...req.body })
|
||||
.write();
|
||||
res.sendStatus(200);
|
||||
} catch (error) {
|
||||
res.status(400).send(error);
|
||||
}
|
||||
};
|
||||
|
||||
// Create controller for GET request to 'event/title'
|
||||
// Returns ACK message
|
||||
exports.titleGet = async (req, res) => {
|
||||
const settings = getSettings();
|
||||
|
||||
if (settings) res.json(settings.title);
|
||||
else res.sendStatus(400);
|
||||
};
|
||||
|
||||
// Create controller for POST request to 'event/title'
|
||||
// Returns ACK message
|
||||
exports.titlePost = async (req, res) => {
|
||||
if (!req.body) {
|
||||
res.status(400).send('No object found in request');
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO: validate data
|
||||
try {
|
||||
db.get(table).assign({ title: req.body.title }).write();
|
||||
res.sendStatus(200);
|
||||
} catch (error) {
|
||||
res.status(400).send(error);
|
||||
}
|
||||
};
|
||||
|
||||
// Create controller for GET request to '/event/url'
|
||||
// Returns ACK message
|
||||
exports.urlGet = async (req, res) => {
|
||||
const event = getSettings();
|
||||
|
||||
if (event) res.json(event.url);
|
||||
else res.sendStatus(400);
|
||||
};
|
||||
|
||||
// Create controller for POST request to '/event/url'
|
||||
// Returns ACK message
|
||||
exports.urlPost = async (req, res) => {
|
||||
if (!req.body) {
|
||||
res.status(400).send('No object found in request');
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO: validate data
|
||||
try {
|
||||
db.get(table).assign({ url: req.body.url }).write();
|
||||
res.sendStatus(200);
|
||||
} catch (error) {
|
||||
res.status(400).send(error);
|
||||
}
|
||||
};
|
||||
|
||||
// Create controller for GET request to 'event/publicInfo'
|
||||
// Returns ACK message
|
||||
exports.publicInfoGet = async (req, res) => {
|
||||
const settings = getSettings();
|
||||
|
||||
if (settings) res.json(settings.publicInfo);
|
||||
else res.sendStatus(400);
|
||||
};
|
||||
|
||||
// Create controller for POST request to '/event/publicInfo'
|
||||
// Returns ACK message
|
||||
exports.publicInfoPost = async (req, res) => {
|
||||
if (!req.body) {
|
||||
res.status(400).send('No object found in request');
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO: validate data
|
||||
try {
|
||||
db.get(table).assign({ publicInfo: req.body.publicInfo }).write();
|
||||
res.sendStatus(200);
|
||||
} catch (error) {
|
||||
res.status(400).send(error);
|
||||
}
|
||||
};
|
||||
|
||||
// Create controller for GET request to 'event/backstageInfo'
|
||||
// Returns ACK message
|
||||
exports.backstageInfoGet = async (req, res) => {
|
||||
const settings = getSettings();
|
||||
|
||||
if (settings) res.json(settings.backstageInfo);
|
||||
else res.sendStatus(400);
|
||||
};
|
||||
|
||||
// Create controller for POST request to '/event/info'
|
||||
// Returns ACK message
|
||||
exports.backstageInfoPost = async (req, res) => {
|
||||
if (!req.body) {
|
||||
res.status(400).send('No object found in request');
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO: validate data
|
||||
try {
|
||||
db.get(table).assign({ backstageInfo: req.body.backstageInfo }).write();
|
||||
res.sendStatus(200);
|
||||
} catch (error) {
|
||||
res.status(400).send(error);
|
||||
}
|
||||
};
|
||||
|
||||
// Create controller for GET request to 'event/osc'
|
||||
// Returns ACK message
|
||||
exports.osc = async (req, res) => {
|
||||
res.send('Not yet implemented').status(500);
|
||||
};
|
||||
@@ -1,57 +0,0 @@
|
||||
[
|
||||
{
|
||||
"id":"xxxxx0",
|
||||
"duration": 300000,
|
||||
"type": "delay"
|
||||
},
|
||||
{
|
||||
"id":"xxxxx1",
|
||||
"title": "Is the internet a fad?",
|
||||
"subtitle": "It is",
|
||||
"presenter": "Carlos Valente",
|
||||
"timeStart": 32400000,
|
||||
"timeEnd": 34200000,
|
||||
"type": "event"
|
||||
},
|
||||
{
|
||||
"id":"xxxxx2",
|
||||
"duration": 1500000,
|
||||
"type": "delay"
|
||||
},
|
||||
{
|
||||
"id":"xxxxx3",
|
||||
"title": "Is reddit a dictatorship?",
|
||||
"subtitle": "It is",
|
||||
"presenter": "Carlos Valente",
|
||||
"timeStart": 34200000,
|
||||
"timeEnd": 36000000,
|
||||
"type": "event"
|
||||
},
|
||||
{
|
||||
"id":"xxxxx4",
|
||||
"title": "Out of words",
|
||||
"subtitle": "",
|
||||
"presenter": "Carlos Valente",
|
||||
"timeStart": 36000000,
|
||||
"timeEnd": 39600000,
|
||||
"type": "event"
|
||||
},
|
||||
{
|
||||
"id":"xxxxx5",
|
||||
"title": "Really",
|
||||
"subtitle": "",
|
||||
"presenter": "Carlos Valente",
|
||||
"timeStart": 39600000,
|
||||
"timeEnd": 41400000,
|
||||
"type": "event"
|
||||
},
|
||||
{
|
||||
"id":"xxxxx6",
|
||||
"title": "...",
|
||||
"subtitle": "",
|
||||
"presenter": "Carlos Valente",
|
||||
"timeStart": null,
|
||||
"timeEnd": null,
|
||||
"type": "event"
|
||||
}
|
||||
]
|
||||
@@ -1,8 +0,0 @@
|
||||
{
|
||||
"current": null,
|
||||
"next": null,
|
||||
"currentTimer": null,
|
||||
"numEvents": 0,
|
||||
"state": "pause",
|
||||
"prevState": "pause"
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"exclude": ["node_modules", "dist"]
|
||||
}
|
||||
+4
-2
@@ -2,11 +2,13 @@
|
||||
"name": "passport-example",
|
||||
"version": "0.0.1",
|
||||
"description": "Example with Passport (http://www.passportjs.org/)",
|
||||
"type": "module",
|
||||
"dependencies": {
|
||||
"body-parser": "~1.19.0",
|
||||
"express": "~4.17.1",
|
||||
"express-session": "~1.17.1",
|
||||
"lowdb": "^1.0.0",
|
||||
"lowdb": "2.1.0",
|
||||
"multer": "^1.4.2",
|
||||
"nanoid": "^3.1.22",
|
||||
"node-osc": "6.0.2",
|
||||
"passport": "~0.4.1",
|
||||
@@ -14,6 +16,6 @@
|
||||
"socket.io": "^4.0.0"
|
||||
},
|
||||
"scripts": {
|
||||
"start": "node app.js"
|
||||
"start": "node src/app.js"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,37 +0,0 @@
|
||||
const express = require('express');
|
||||
const router = express.Router();
|
||||
|
||||
// import event controller
|
||||
const eventController = require('../controllers/eventController');
|
||||
|
||||
// create route between controller and '/settings' endpoint
|
||||
router.get('/', eventController.getAll);
|
||||
|
||||
// create route between controller and '/settings' endpoint
|
||||
router.post('/', eventController.post);
|
||||
|
||||
// create route between controller and '/event/title' endpoint
|
||||
router.get('/title', eventController.titleGet);
|
||||
|
||||
// create route between controller and '/event/title' endpoint
|
||||
router.post('/title', eventController.titlePost);
|
||||
|
||||
// create route between controller and '/event/info' endpoint
|
||||
router.get('/publicInfo', eventController.publicInfoGet);
|
||||
|
||||
// create route between controller and '/event/info' endpoint
|
||||
router.post('/publicInfo', eventController.publicInfoPost);
|
||||
|
||||
// create route between controller and '/event/info' endpoint
|
||||
router.get('/backstageInfo', eventController.backstageInfoGet);
|
||||
|
||||
// create route between controller and '/event/info' endpoint
|
||||
router.post('/backstageInfo', eventController.backstageInfoPost);
|
||||
|
||||
// create route between controller and '/event/url' endpoint
|
||||
router.get('/url', eventController.urlGet);
|
||||
|
||||
// create route between controller and '/event/url' endpoint
|
||||
router.post('/url', eventController.urlPost);
|
||||
|
||||
module.exports = router;
|
||||
@@ -1,34 +0,0 @@
|
||||
const express = require('express');
|
||||
const router = express.Router();
|
||||
|
||||
// import events controller
|
||||
const eventsController = require('../controllers/eventsController');
|
||||
|
||||
// create route between controller and '/events/' endpoint
|
||||
router.get('/', eventsController.eventsGetAll);
|
||||
|
||||
// create route between controller and '/events/:eventId' endpoint
|
||||
router.get('/:eventId', eventsController.eventsGetById);
|
||||
|
||||
// create route between controller and '/events/' endpoint
|
||||
router.post('/', eventsController.eventsPost);
|
||||
|
||||
// create route between controller and '/events/' endpoint
|
||||
router.put('/', eventsController.eventsPut);
|
||||
|
||||
// create route between controller and '/events/' endpoint
|
||||
router.patch('/', eventsController.eventsPatch);
|
||||
|
||||
// create route between controller and '/events/reorder' endpoint
|
||||
router.patch('/reorder/', eventsController.eventsReorder);
|
||||
|
||||
// create route between controller and '/events/applydelay/:eventId' endpoint
|
||||
router.patch('/applydelay/:eventId', eventsController.eventsApplyDelay);
|
||||
|
||||
// create route between controller and '/events/all' endpoint
|
||||
router.delete('/all', eventsController.eventsDeleteAll);
|
||||
|
||||
// create route between controller and '/events/:eventId' endpoint
|
||||
router.delete('/:eventId', eventsController.eventsDelete);
|
||||
|
||||
module.exports = router;
|
||||
@@ -0,0 +1,89 @@
|
||||
// get config
|
||||
import { config } from './config/config.js';
|
||||
|
||||
// init database
|
||||
import { Low, JSONFile } from 'lowdb';
|
||||
import { join } from 'path';
|
||||
|
||||
const file = join('data/', config.database.filename);
|
||||
const adapter = new JSONFile(file);
|
||||
export const db = new Low(adapter);
|
||||
|
||||
// dependencies
|
||||
import express from 'express';
|
||||
import http from 'http';
|
||||
import cors from 'cors';
|
||||
import { dbModel } from './data/dataModel.js';
|
||||
|
||||
// Read data from JSON file, this will set db.data content
|
||||
await db.read();
|
||||
|
||||
// If file.json doesn't exist, db.data will be null
|
||||
// Set default data
|
||||
// db.data ||= { events: [] }; NODE v15 - v16
|
||||
if (db.data == null) {
|
||||
db.data = dbModel;
|
||||
db.write();
|
||||
}
|
||||
|
||||
// get data
|
||||
export const data = db.data;
|
||||
|
||||
// Import Routes
|
||||
import { router as eventsRouter } from './routes/eventsRouter.js';
|
||||
import { router as eventRouter } from './routes/eventRouter.js';
|
||||
import { router as ontimeRouter } from './routes/ontimeRouter.js';
|
||||
|
||||
// Setup default port
|
||||
const port = process.env.PORT || config.server.port;
|
||||
|
||||
// Global Objects
|
||||
import { EventTimer } from './classes/EventTimer.js';
|
||||
|
||||
// Create express APP
|
||||
const app = express();
|
||||
|
||||
// setup cors for all routes
|
||||
app.use(cors());
|
||||
|
||||
// enable pre-flight cors
|
||||
app.options('*', cors());
|
||||
|
||||
// Implement middleware
|
||||
app.use('/uploads', express.static('uploads'));
|
||||
|
||||
app.use(express.urlencoded({ extended: true }));
|
||||
app.use(express.json({ limit: '1mb' }));
|
||||
|
||||
// Implement route endpoints
|
||||
app.use('/events', eventsRouter);
|
||||
app.use('/event', eventRouter);
|
||||
app.use('/ontime', ontimeRouter);
|
||||
|
||||
// implement general router
|
||||
app.get('/', (req, res) => {
|
||||
res.send('ontime API');
|
||||
});
|
||||
|
||||
// Implement route for errors
|
||||
app.use((err, req, res, next) => {
|
||||
console.error(err.stack);
|
||||
res.status(500).send('Something broke!');
|
||||
});
|
||||
|
||||
// create HTTP server
|
||||
const server = http.createServer(app);
|
||||
|
||||
// init timer
|
||||
global.timer = new EventTimer(server, config);
|
||||
global.timer.setupWithEventList(data.events);
|
||||
|
||||
// Start server
|
||||
server.listen(port, () =>
|
||||
console.log(`HTTP Server is listening on port ${port}`)
|
||||
);
|
||||
|
||||
// Start OSC server
|
||||
import { initiateOSC } from './controllers/OscController.js';
|
||||
|
||||
initiateOSC(config.osc);
|
||||
@@ -1,5 +1,5 @@
|
||||
const Timer = require('./Timer');
|
||||
const socketIo = require('socket.io');
|
||||
import { Timer } from './Timer.js';
|
||||
import { Server } from 'socket.io';
|
||||
|
||||
/*
|
||||
* EventTimer adds functions specific to APP
|
||||
@@ -9,7 +9,7 @@ const socketIo = require('socket.io');
|
||||
*
|
||||
*/
|
||||
|
||||
class EventTimer extends Timer {
|
||||
export class EventTimer extends Timer {
|
||||
// AUX
|
||||
DAYMS = 86400000;
|
||||
|
||||
@@ -57,12 +57,12 @@ class EventTimer extends Timer {
|
||||
numEvents = null;
|
||||
_eventlist = null;
|
||||
|
||||
constructor(server, config) {
|
||||
constructor(httpServer, config) {
|
||||
// call super constructor
|
||||
super();
|
||||
|
||||
// initialise socketIO server
|
||||
this.io = socketIo(server, {
|
||||
this.io = new Server(httpServer, {
|
||||
cors: {
|
||||
origin: '*',
|
||||
methods: 'GET,HEAD,PUT,PATCH,POST,DELETE',
|
||||
@@ -936,5 +936,3 @@ class EventTimer extends Timer {
|
||||
this.loadEvent(this.selectedEventIndex);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = EventTimer;
|
||||
@@ -4,7 +4,7 @@
|
||||
*
|
||||
*/
|
||||
|
||||
class Timer {
|
||||
export class Timer {
|
||||
clock = null;
|
||||
duration = null;
|
||||
current = null;
|
||||
@@ -216,6 +216,4 @@ class Timer {
|
||||
this._finishedAt = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Timer;
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
export const config = {
|
||||
timer: {
|
||||
refresh: 1000,
|
||||
},
|
||||
server: {
|
||||
port: 4001,
|
||||
},
|
||||
database: {
|
||||
filename: 'db.json',
|
||||
tablename: 'events',
|
||||
},
|
||||
osc: {
|
||||
port: 8888,
|
||||
},
|
||||
};
|
||||
@@ -1,7 +1,7 @@
|
||||
const osc = require('node-osc');
|
||||
import { Server } from 'node-osc';
|
||||
|
||||
const initiateOSC = (config) => {
|
||||
const oscServer = new osc.Server(config.port, '0.0.0.0', () => {
|
||||
export const initiateOSC = (config) => {
|
||||
const oscServer = new Server(config.port, '0.0.0.0', () => {
|
||||
console.log(`OSC Server is listening on port ${config.port}`);
|
||||
});
|
||||
|
||||
@@ -88,5 +88,3 @@ const initiateOSC = (config) => {
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
module.exports = { initiateOSC };
|
||||
@@ -0,0 +1,26 @@
|
||||
// get database
|
||||
import { db, data } from '../app.js';
|
||||
|
||||
// Create controller for GET request to 'event'
|
||||
// Returns ACK message
|
||||
export const getEvent = async (req, res) => {
|
||||
res.json(data.event);
|
||||
};
|
||||
|
||||
// Create controller for POST request to 'event'
|
||||
// Returns ACK message
|
||||
export const postEvent = async (req, res) => {
|
||||
if (!req.body) {
|
||||
res.status(400).send('No object found in request');
|
||||
return;
|
||||
}
|
||||
// TODO: validate data
|
||||
try {
|
||||
data.event = { ...data.event, ...req.body };
|
||||
await db.write();
|
||||
res.sendStatus(200);
|
||||
} catch (error) {
|
||||
res.status(400).send(error);
|
||||
console.log(error);
|
||||
}
|
||||
};
|
||||
+53
-38
@@ -1,22 +1,26 @@
|
||||
// get database
|
||||
const db = require('../app.js').db;
|
||||
import { db, data } from '../app.js';
|
||||
|
||||
// utils
|
||||
const customAlphabet = require('nanoid').customAlphabet;
|
||||
import { customAlphabet } from 'nanoid';
|
||||
const nanoid = customAlphabet('1234567890abcdef', 4);
|
||||
const eventDefs = require('../data/eventsDefinition.js');
|
||||
import {
|
||||
event as eventDef,
|
||||
delay as delayDef,
|
||||
block as blockDef,
|
||||
} from '../data/eventsDefinition.js';
|
||||
|
||||
function _getEventsCount() {
|
||||
return db.get('events').size().value();
|
||||
return Array.from(data.events).length;
|
||||
}
|
||||
|
||||
function _pushNew(entry) {
|
||||
return db.get('events').push(entry).write();
|
||||
return data.events.push(entry).write();
|
||||
}
|
||||
|
||||
function _insertAt(entry, index) {
|
||||
async function _insertAt(entry, index) {
|
||||
// get events
|
||||
let events = db.get('events').value();
|
||||
let events = data.events;
|
||||
let count = events.length;
|
||||
let order = entry.order;
|
||||
|
||||
@@ -39,15 +43,18 @@ function _insertAt(entry, index) {
|
||||
}
|
||||
|
||||
// save events
|
||||
db.set('events', events).write();
|
||||
data.events = events;
|
||||
await db.write();
|
||||
}
|
||||
|
||||
function _removeById(eventId) {
|
||||
return db.get('events').remove({ id: eventId }).write();
|
||||
async function _removeById(eventId) {
|
||||
data.events = Array.from(data.events).filter((e) => e.id != eventId);
|
||||
await db.write();
|
||||
}
|
||||
|
||||
function getEventEvents() {
|
||||
return db.get('events').chain().filter({ type: 'event' }).value();
|
||||
// return data.events.filter((e) => e.type === 'event');
|
||||
return Array.from(data.events).filter((e) => e.type === 'event');
|
||||
}
|
||||
|
||||
// Updates timer object
|
||||
@@ -68,21 +75,21 @@ function _deleteTimerId(entryId) {
|
||||
|
||||
// Create controller for GET request to '/events'
|
||||
// Returns -
|
||||
exports.eventsGetAll = async (req, res) => {
|
||||
const results = db.get('events').value();
|
||||
res.json(results);
|
||||
export const eventsGetAll = async (req, res) => {
|
||||
res.json(data.events);
|
||||
};
|
||||
|
||||
// Create controller for GET request to '/events/:eventId'
|
||||
// Returns -
|
||||
exports.eventsGetById = async (req, res) => {
|
||||
const e = db.get('events').find({ id: req.params.eventId }).value();
|
||||
export const eventsGetById = async (req, res) => {
|
||||
const e = data.events.find({ id: req.params.eventId }).value();
|
||||
console.log('event by id', e);
|
||||
res.json(e);
|
||||
};
|
||||
|
||||
// Create controller for POST request to '/events/'
|
||||
// Returns -
|
||||
exports.eventsPost = async (req, res) => {
|
||||
export const eventsPost = async (req, res) => {
|
||||
// TODO: Validate event
|
||||
if (!req.body) {
|
||||
res.status(400).send(`No object found in request`);
|
||||
@@ -95,13 +102,13 @@ exports.eventsPost = async (req, res) => {
|
||||
|
||||
switch (req.body.type) {
|
||||
case 'event':
|
||||
newEvent = { ...eventDefs.event, ...req.body };
|
||||
newEvent = { ...eventDef, ...req.body };
|
||||
break;
|
||||
case 'delay':
|
||||
newEvent = { ...eventDefs.delay, ...req.body };
|
||||
newEvent = { ...delayDef, ...req.body };
|
||||
break;
|
||||
case 'block':
|
||||
newEvent = { ...eventDefs.block, ...req.body };
|
||||
newEvent = { ...blockDef, ...req.body };
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -131,7 +138,7 @@ exports.eventsPost = async (req, res) => {
|
||||
|
||||
// Create controller for PUT request to '/events/'
|
||||
// Returns -
|
||||
exports.eventsPut = async (req, res) => {
|
||||
export const eventsPut = async (req, res) => {
|
||||
// no valid params
|
||||
if (!req.body) {
|
||||
res.status(400).send(`No object found`);
|
||||
@@ -145,29 +152,35 @@ exports.eventsPut = async (req, res) => {
|
||||
}
|
||||
|
||||
try {
|
||||
db.get('events')
|
||||
.find({ id: req.body.id })
|
||||
.assign({ ...req.body })
|
||||
.update('revision', (n) => n + 1)
|
||||
.write();
|
||||
const eventIndex = data.events.findIndex((e) => e.id === req.body.id);
|
||||
if (eventIndex === -1) {
|
||||
res.status(400).send(`No Id found found`);
|
||||
return;
|
||||
}
|
||||
|
||||
const e = data.events[eventIndex];
|
||||
data.events[eventIndex] = { ...e, ...req.body };
|
||||
data.events[eventIndex].revision++;
|
||||
db.write();
|
||||
|
||||
// update timer
|
||||
_updateTimersSingle(req.body.id, req.body);
|
||||
|
||||
res.sendStatus(200);
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
res.status(400).send(error);
|
||||
}
|
||||
};
|
||||
|
||||
// Create controller for PATCH request to '/events/'
|
||||
// Returns -
|
||||
exports.eventsPatch = async (req, res) => {
|
||||
export const eventsPatch = async (req, res) => {
|
||||
// Code is the same as put, call that
|
||||
this.eventsPut(req, res);
|
||||
eventsPut(req, res);
|
||||
};
|
||||
|
||||
exports.eventsReorder = async (req, res) => {
|
||||
export const eventsReorder = async (req, res) => {
|
||||
// TODO: Validate event
|
||||
if (!req.body) {
|
||||
res.status(400).send(`No object found in request`);
|
||||
@@ -177,7 +190,7 @@ exports.eventsReorder = async (req, res) => {
|
||||
const { index, from, to } = req.body;
|
||||
|
||||
// get events
|
||||
let events = db.get('events').value();
|
||||
let events = data.events;
|
||||
let idx = events.findIndex((e) => e.id === index, from);
|
||||
|
||||
// Check if item is at given index
|
||||
@@ -194,7 +207,8 @@ exports.eventsReorder = async (req, res) => {
|
||||
events.splice(to, 0, reorderedItem);
|
||||
|
||||
// save events
|
||||
db.set('events', events).write();
|
||||
data.events = events;
|
||||
db.write();
|
||||
|
||||
// TODO: would it be more efficient to reorder at timer?
|
||||
// update timer
|
||||
@@ -209,7 +223,7 @@ exports.eventsReorder = async (req, res) => {
|
||||
|
||||
// Create controller for PATCH request to '/events/applydelay/:eventId'
|
||||
// Returns -
|
||||
exports.eventsApplyDelay = async (req, res) => {
|
||||
export const eventsApplyDelay = async (req, res) => {
|
||||
// no valid params
|
||||
if (!req.params.eventId) {
|
||||
res.status(400).send(`No id found in request`);
|
||||
@@ -218,7 +232,7 @@ exports.eventsApplyDelay = async (req, res) => {
|
||||
|
||||
try {
|
||||
// get events
|
||||
let events = db.get('events').value();
|
||||
let events = data.events;
|
||||
|
||||
// AUX
|
||||
let delayIndex = null;
|
||||
@@ -259,7 +273,8 @@ exports.eventsApplyDelay = async (req, res) => {
|
||||
if (blockIndex) events.splice(blockIndex - 1, 1);
|
||||
|
||||
// update events
|
||||
db.set('events', events).write();
|
||||
data.events = events;
|
||||
db.write();
|
||||
|
||||
// update timer
|
||||
_updateTimers();
|
||||
@@ -274,7 +289,7 @@ exports.eventsApplyDelay = async (req, res) => {
|
||||
|
||||
// Create controller for DELETE request to '/events/:eventId'
|
||||
// Returns -
|
||||
exports.eventsDelete = async (req, res) => {
|
||||
export const eventsDelete = async (req, res) => {
|
||||
// no valid params
|
||||
if (!req.params.eventId) {
|
||||
res.status(400).send(`No id found in request`);
|
||||
@@ -298,17 +313,17 @@ exports.eventsDelete = async (req, res) => {
|
||||
|
||||
// Create controller for DELETE request to '/events/:eventId'
|
||||
// Returns -
|
||||
exports.eventsDeleteAll = async (req, res) => {
|
||||
export const eventsDeleteAll = async (req, res) => {
|
||||
try {
|
||||
// set with nothing
|
||||
db.set('events', []).write();
|
||||
data.events = [];
|
||||
db.write();
|
||||
|
||||
// update timer object
|
||||
_updateTimersSingle();
|
||||
|
||||
res.sendStatus(201);
|
||||
} catch (error) {
|
||||
console.log('debug:', error);
|
||||
res.status(400).send(error);
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,128 @@
|
||||
// get database
|
||||
import { db, data } from '../app.js';
|
||||
import fs from 'fs';
|
||||
import {
|
||||
event as eventDef,
|
||||
delay as delayDef,
|
||||
block as blockDef,
|
||||
} from '../data/eventsDefinition.js';
|
||||
import { dbModel } from '../data/dataModel.js';
|
||||
|
||||
function getEventTitle() {
|
||||
return data.event.title;
|
||||
}
|
||||
|
||||
async function deleteFile(file) {
|
||||
// delete a file
|
||||
fs.unlink(file, (err) => {
|
||||
if (err) {
|
||||
console.log(err);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// parses version 1 of the data system
|
||||
async function parsev1(jsonData) {
|
||||
if ('events' in jsonData) {
|
||||
let events = [];
|
||||
let ids = [];
|
||||
for (const e of jsonData.events) {
|
||||
if (e.type === 'event') {
|
||||
// doublecheck unique ids
|
||||
if (e.id == null || ids.indexOf(e.id) !== -1) continue;
|
||||
ids.push(e.id);
|
||||
|
||||
// make sure all properties exits
|
||||
// dont load any extra properties than the ones known
|
||||
events.push({
|
||||
...eventDef,
|
||||
title: e.title,
|
||||
subtitle: e.subtitle,
|
||||
presenter: e.presenter,
|
||||
note: e.note,
|
||||
timeStart: e.timeStart,
|
||||
timeEnd: e.timeEnd,
|
||||
isPublic: e.isPublic,
|
||||
id: e.id,
|
||||
});
|
||||
} else if (e.type === 'delay') {
|
||||
events.push({ ...delayDef, duration: e.duration });
|
||||
} else if (e.type === 'block') {
|
||||
events.push({ ...blockDef });
|
||||
}
|
||||
}
|
||||
// write to db
|
||||
db.data.events = events;
|
||||
db.write();
|
||||
}
|
||||
|
||||
if ('event' in jsonData) {
|
||||
const e = jsonData.event;
|
||||
// filter known properties
|
||||
const event = {
|
||||
...dbModel.event,
|
||||
title: e.title,
|
||||
url: e.url,
|
||||
publicInfo: e.publicInfo,
|
||||
backstageInfo: e.backstageInfo,
|
||||
};
|
||||
|
||||
// write to db
|
||||
db.data.event = event;
|
||||
db.write();
|
||||
}
|
||||
|
||||
// Not handling settings yet
|
||||
// let settings = {};
|
||||
// if ('settings' in jsonData) {
|
||||
// }
|
||||
}
|
||||
|
||||
// Create controller for GET request to '/ontime/db'
|
||||
// Returns -
|
||||
export const dbDownload = async (req, res) => {
|
||||
const fileTitle = getEventTitle() || 'ontime events';
|
||||
res.download('db.json', `${fileTitle}.json`, (err) => {
|
||||
if (err) {
|
||||
res.status(500).send({
|
||||
message: 'Could not download the file. ' + err,
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
// Create controller for POST request to '/ontime/db'
|
||||
// Returns -
|
||||
export const dbUpload = async (req, res) => {
|
||||
if (!req.file) {
|
||||
res.status(400).send({ message: 'File not found' });
|
||||
return;
|
||||
}
|
||||
|
||||
const file = req.file.path;
|
||||
if (!fs.existsSync(file)) {
|
||||
res.status(500).send({ message: 'Upload failed' });
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
// get file
|
||||
let rawdata = fs.readFileSync(file);
|
||||
let uploadedJson = JSON.parse(rawdata);
|
||||
|
||||
// delete file
|
||||
deleteFile(file);
|
||||
|
||||
// check version
|
||||
if (uploadedJson.settings.version === 1) parsev1(uploadedJson);
|
||||
else {
|
||||
res.status(400).send({ message: 'Error parsing file, version unknown' });
|
||||
return;
|
||||
}
|
||||
|
||||
res.sendStatus(200);
|
||||
} catch (error) {
|
||||
console.log('Error parsing file', error);
|
||||
res.status(400).send({ message: error });
|
||||
}
|
||||
};
|
||||
+11
-11
@@ -1,64 +1,64 @@
|
||||
// Create controller for GET request to '/playback'
|
||||
// Returns ACK message
|
||||
exports.pbGet = async (req, res) => {
|
||||
export const pbGet = async (req, res) => {
|
||||
res.send(global.timer.playState);
|
||||
};
|
||||
|
||||
// Create controller for GET request to '/playback/start'
|
||||
// Starts timer object
|
||||
exports.pbStart = async (req, res) => {
|
||||
export const pbStart = async (req, res) => {
|
||||
global.timer.start();
|
||||
res.sendStatus(200);
|
||||
};
|
||||
|
||||
// Create controller for GET request to '/playback/pause'
|
||||
// Pauses timer object
|
||||
exports.pbPause = async (req, res) => {
|
||||
export const pbPause = async (req, res) => {
|
||||
global.timer.pause();
|
||||
res.sendStatus(200);
|
||||
};
|
||||
|
||||
// Create controller for GET request to '/playback/stop'
|
||||
// Stops timer object
|
||||
exports.pbStop = async (req, res) => {
|
||||
export const pbStop = async (req, res) => {
|
||||
global.timer.stop();
|
||||
res.sendStatus(200);
|
||||
};
|
||||
|
||||
// Create controller for GET request to '/playback/roll'
|
||||
// Sets timer object to roll mode
|
||||
exports.pbRoll = async (req, res) => {
|
||||
export const pbRoll = async (req, res) => {
|
||||
global.timer.roll();
|
||||
res.sendStatus(501);
|
||||
};
|
||||
|
||||
// Create controller for GET request to '/playback/previous'
|
||||
// Sets timer object to roll mode
|
||||
exports.pbPrevious = async (req, res) => {
|
||||
export const pbPrevious = async (req, res) => {
|
||||
global.timer.previous();
|
||||
res.sendStatus(200);
|
||||
};
|
||||
|
||||
// Create controller for GET request to '/playback/next'
|
||||
// Sets timer object to roll mode
|
||||
exports.pbNext = async (req, res) => {
|
||||
export const pbNext = async (req, res) => {
|
||||
global.timer.next();
|
||||
res.sendStatus(200);
|
||||
};
|
||||
|
||||
// Create controller for GET request to '/playback/unload'
|
||||
// Unloads any events
|
||||
exports.pbUnload = async (req, res) => {
|
||||
export const pbUnload = async (req, res) => {
|
||||
global.timer.unload();
|
||||
console.log('debug: unload called')
|
||||
console.log('debug: unload called');
|
||||
|
||||
res.sendStatus(200);
|
||||
};
|
||||
|
||||
// Create controller for GET request to '/playback/reload'
|
||||
// Reloads current event
|
||||
exports.pbReload = async (req, res) => {
|
||||
export const pbReload = async (req, res) => {
|
||||
global.timer.reload();
|
||||
console.log('debug: reload called')
|
||||
console.log('debug: reload called');
|
||||
res.sendStatus(200);
|
||||
};
|
||||
@@ -1,10 +1,10 @@
|
||||
const dbModel = {
|
||||
export const dbModel = {
|
||||
events: [],
|
||||
event: {
|
||||
title: '',
|
||||
url: '',
|
||||
publicInfo: '',
|
||||
backStageInfo: '',
|
||||
backstageInfo: '',
|
||||
},
|
||||
settings: {
|
||||
app: 'ontime',
|
||||
@@ -14,5 +14,3 @@ const dbModel = {
|
||||
lock: false,
|
||||
},
|
||||
};
|
||||
|
||||
module.exports = { dbModel };
|
||||
@@ -1,4 +1,4 @@
|
||||
const event = {
|
||||
export const event = {
|
||||
title: '',
|
||||
subtitle: '',
|
||||
presenter: '',
|
||||
@@ -10,14 +10,12 @@ const event = {
|
||||
revision: 0,
|
||||
};
|
||||
|
||||
const delay = {
|
||||
export const delay = {
|
||||
duration: 0,
|
||||
type: 'delay',
|
||||
revision: 0,
|
||||
};
|
||||
|
||||
const block = {
|
||||
export const block = {
|
||||
type: 'block',
|
||||
};
|
||||
|
||||
module.exports = { event, delay, block };
|
||||
@@ -0,0 +1,11 @@
|
||||
import express from 'express';
|
||||
export const router = express.Router();
|
||||
|
||||
// import event controller
|
||||
import { getEvent, postEvent } from '../controllers/eventController.js';
|
||||
|
||||
// create route between controller and 'GET /event' endpoint
|
||||
router.get('/', getEvent);
|
||||
|
||||
// create route between controller and 'POST /event' endpoint
|
||||
router.post('/', postEvent);
|
||||
@@ -0,0 +1,42 @@
|
||||
import express from 'express';
|
||||
export const router = express.Router();
|
||||
|
||||
// import events controller
|
||||
import {
|
||||
eventsGetAll,
|
||||
eventsGetById,
|
||||
eventsPost,
|
||||
eventsPut,
|
||||
eventsPatch,
|
||||
eventsReorder,
|
||||
eventsApplyDelay,
|
||||
eventsDeleteAll,
|
||||
eventsDelete,
|
||||
} from '../controllers/eventsController.js';
|
||||
|
||||
// create route between controller and '/events/' endpoint
|
||||
router.get('/', eventsGetAll);
|
||||
|
||||
// create route between controller and '/events/:eventId' endpoint
|
||||
router.get('/:eventId', eventsGetById);
|
||||
|
||||
// create route between controller and '/events/' endpoint
|
||||
router.post('/', eventsPost);
|
||||
|
||||
// create route between controller and '/events/' endpoint
|
||||
router.put('/', eventsPut);
|
||||
|
||||
// create route between controller and '/events/' endpoint
|
||||
router.patch('/', eventsPatch);
|
||||
|
||||
// create route between controller and '/events/reorder' endpoint
|
||||
router.patch('/reorder/', eventsReorder);
|
||||
|
||||
// create route between controller and '/events/applydelay/:eventId' endpoint
|
||||
router.patch('/applydelay/:eventId', eventsApplyDelay);
|
||||
|
||||
// create route between controller and '/events/all' endpoint
|
||||
router.delete('/all', eventsDeleteAll);
|
||||
|
||||
// create route between controller and '/events/:eventId' endpoint
|
||||
router.delete('/:eventId', eventsDelete);
|
||||
@@ -0,0 +1,11 @@
|
||||
import express from 'express';
|
||||
import uploadJson from '../utils/upload.js';
|
||||
export const router = express.Router();
|
||||
|
||||
import { dbDownload, dbUpload } from '../controllers/ontimeController.js';
|
||||
|
||||
// create route between controller and '/ontime/db' endpoint
|
||||
router.get('/db', dbDownload);
|
||||
|
||||
// create route between controller and '/ontime/db' endpoint
|
||||
router.post('/db', uploadJson, dbUpload);
|
||||
@@ -1,5 +1,5 @@
|
||||
const express = require('express');
|
||||
const router = express.Router();
|
||||
import express from 'express';
|
||||
export const router = express.Router();
|
||||
|
||||
// import event controller
|
||||
const playbackController = require('../controllers/playbackController');
|
||||
@@ -30,5 +30,3 @@ router.get('/unload', playbackController.pbUnload);
|
||||
|
||||
// create route between controller and '/playback/reload' endpoint
|
||||
router.get('/reload', playbackController.pbReload);
|
||||
|
||||
module.exports = router;
|
||||
@@ -0,0 +1,23 @@
|
||||
import multer from 'multer';
|
||||
|
||||
const storage = multer.diskStorage({
|
||||
destination: function (req, file, cb) {
|
||||
cb(null, 'uploads/');
|
||||
},
|
||||
filename: function (req, file, cb) {
|
||||
cb(null, Date.now() + '--' + file.originalname);
|
||||
},
|
||||
});
|
||||
|
||||
// filter only json
|
||||
const filterJson = (req, file, cb) => {
|
||||
if (file.mimetype.includes('application/json')) {
|
||||
cb(null, true);
|
||||
} else {
|
||||
cb(null, false);
|
||||
}
|
||||
};
|
||||
|
||||
const uploadJson = multer({ storage: storage, fileFilter: filterJson });
|
||||
|
||||
export default uploadJson.single('jsondb');
|
||||
+147
-36
@@ -30,6 +30,11 @@ accepts@~1.3.4, accepts@~1.3.7:
|
||||
mime-types "~2.1.24"
|
||||
negotiator "0.6.2"
|
||||
|
||||
append-field@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/append-field/-/append-field-1.0.0.tgz#1e3440e915f0b1203d23748e78edd7b9b5b43e56"
|
||||
integrity sha1-HjRA6RXwsSA9I3SOeO3XubW0PlY=
|
||||
|
||||
array-flatten@1.1.1:
|
||||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2"
|
||||
@@ -66,6 +71,19 @@ body-parser@1.19.0, body-parser@~1.19.0:
|
||||
raw-body "2.4.0"
|
||||
type-is "~1.6.17"
|
||||
|
||||
buffer-from@^1.0.0:
|
||||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef"
|
||||
integrity sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==
|
||||
|
||||
busboy@^0.2.11:
|
||||
version "0.2.14"
|
||||
resolved "https://registry.yarnpkg.com/busboy/-/busboy-0.2.14.tgz#6c2a622efcf47c57bbbe1e2a9c37ad36c7925453"
|
||||
integrity sha1-bCpiLvz0fFe7vh4qnDetNseSVFM=
|
||||
dependencies:
|
||||
dicer "0.2.5"
|
||||
readable-stream "1.1.x"
|
||||
|
||||
bytes@3.1.0:
|
||||
version "3.1.0"
|
||||
resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.0.tgz#f6cf7933a360e0588fa9fde85651cdc7f805d1f6"
|
||||
@@ -76,6 +94,16 @@ component-emitter@~1.3.0:
|
||||
resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.3.0.tgz#16e4070fba8ae29b679f2215853ee181ab2eabc0"
|
||||
integrity sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==
|
||||
|
||||
concat-stream@^1.5.2:
|
||||
version "1.6.2"
|
||||
resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.2.tgz#904bdf194cd3122fc675c77fc4ac3d4ff0fd1a34"
|
||||
integrity sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==
|
||||
dependencies:
|
||||
buffer-from "^1.0.0"
|
||||
inherits "^2.0.3"
|
||||
readable-stream "^2.2.2"
|
||||
typedarray "^0.0.6"
|
||||
|
||||
content-disposition@0.5.3:
|
||||
version "0.5.3"
|
||||
resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.3.tgz#e130caf7e7279087c5616c2007d0485698984fbd"
|
||||
@@ -103,6 +131,11 @@ cookie@~0.4.1:
|
||||
resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.4.1.tgz#afd713fe26ebd21ba95ceb61f9a8116e50a537d1"
|
||||
integrity sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA==
|
||||
|
||||
core-util-is@~1.0.0:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7"
|
||||
integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=
|
||||
|
||||
cors@~2.8.5:
|
||||
version "2.8.5"
|
||||
resolved "https://registry.yarnpkg.com/cors/-/cors-2.8.5.tgz#eac11da51592dd86b9f06f6e7ac293b3df875d29"
|
||||
@@ -140,6 +173,14 @@ destroy@~1.0.4:
|
||||
resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.0.4.tgz#978857442c44749e4206613e37946205826abd80"
|
||||
integrity sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=
|
||||
|
||||
dicer@0.2.5:
|
||||
version "0.2.5"
|
||||
resolved "https://registry.yarnpkg.com/dicer/-/dicer-0.2.5.tgz#5996c086bb33218c812c090bddc09cd12facb70f"
|
||||
integrity sha1-WZbAhrszIYyBLAkL3cCc0S+stw8=
|
||||
dependencies:
|
||||
readable-stream "1.1.x"
|
||||
streamsearch "0.1.2"
|
||||
|
||||
ee-first@1.1.1:
|
||||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d"
|
||||
@@ -253,11 +294,6 @@ fresh@0.5.2:
|
||||
resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7"
|
||||
integrity sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=
|
||||
|
||||
graceful-fs@^4.1.3:
|
||||
version "4.2.6"
|
||||
resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.6.tgz#ff040b2b0853b23c3d31027523706f1885d76bee"
|
||||
integrity sha512-nTnJ528pbqxYanhpDYsi4Rd8MAeaBA67+RZ10CM1m3bTAVFEDcd5AuA4a6W5YkGZ1iNXHzZz8T6TBKLeBuNriQ==
|
||||
|
||||
http-errors@1.7.2:
|
||||
version "1.7.2"
|
||||
resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.7.2.tgz#4f5029cf13239f31036e5b2e55292bcfbcc85c8f"
|
||||
@@ -292,7 +328,7 @@ inherits@2.0.3:
|
||||
resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de"
|
||||
integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=
|
||||
|
||||
inherits@2.0.4:
|
||||
inherits@2.0.4, inherits@^2.0.3, inherits@~2.0.1, inherits@~2.0.3:
|
||||
version "2.0.4"
|
||||
resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c"
|
||||
integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==
|
||||
@@ -302,26 +338,22 @@ ipaddr.js@1.9.1:
|
||||
resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.9.1.tgz#bff38543eeb8984825079ff3a2a8e6cbd46781b3"
|
||||
integrity sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==
|
||||
|
||||
is-promise@^2.1.0:
|
||||
version "2.2.2"
|
||||
resolved "https://registry.yarnpkg.com/is-promise/-/is-promise-2.2.2.tgz#39ab959ccbf9a774cf079f7b40c7a26f763135f1"
|
||||
integrity sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ==
|
||||
isarray@0.0.1:
|
||||
version "0.0.1"
|
||||
resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf"
|
||||
integrity sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=
|
||||
|
||||
lodash@4:
|
||||
version "4.17.21"
|
||||
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c"
|
||||
integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==
|
||||
|
||||
lowdb@^1.0.0:
|
||||
isarray@~1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/lowdb/-/lowdb-1.0.0.tgz#5243be6b22786ccce30e50c9a33eac36b20c8064"
|
||||
integrity sha512-2+x8esE/Wb9SQ1F9IHaYWfsC9FIecLOPrK4g17FGEayjUWH172H6nwicRovGvSE2CPZouc2MCIqCI7h9d+GftQ==
|
||||
resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11"
|
||||
integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=
|
||||
|
||||
lowdb@2.1.0:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/lowdb/-/lowdb-2.1.0.tgz#c8063e228b5ab3e082ece90e0512537ecb6e1e2a"
|
||||
integrity sha512-F4Go8/V37gAidTR3c5poyjprOpZSDNSLJVOmI0ny4D4q9rC37OkBhlzX0bqj7LZlT3UIj4FchmZrrSw7qY+eGQ==
|
||||
dependencies:
|
||||
graceful-fs "^4.1.3"
|
||||
is-promise "^2.1.0"
|
||||
lodash "4"
|
||||
pify "^3.0.0"
|
||||
steno "^0.4.1"
|
||||
steno "^1.0.0"
|
||||
|
||||
media-typer@0.3.0:
|
||||
version "0.3.0"
|
||||
@@ -355,6 +387,18 @@ mime@1.6.0:
|
||||
resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1"
|
||||
integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==
|
||||
|
||||
minimist@^1.2.5:
|
||||
version "1.2.5"
|
||||
resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602"
|
||||
integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==
|
||||
|
||||
mkdirp@^0.5.1:
|
||||
version "0.5.5"
|
||||
resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.5.tgz#d91cefd62d1436ca0f41620e251288d420099def"
|
||||
integrity sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==
|
||||
dependencies:
|
||||
minimist "^1.2.5"
|
||||
|
||||
ms@2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8"
|
||||
@@ -370,6 +414,20 @@ ms@2.1.2:
|
||||
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009"
|
||||
integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==
|
||||
|
||||
multer@^1.4.2:
|
||||
version "1.4.2"
|
||||
resolved "https://registry.yarnpkg.com/multer/-/multer-1.4.2.tgz#2f1f4d12dbaeeba74cb37e623f234bf4d3d2057a"
|
||||
integrity sha512-xY8pX7V+ybyUpbYMxtjM9KAiD9ixtg5/JkeKUTD6xilfDv0vzzOFcCp4Ljb1UU3tSOM3VTZtKo63OmzOrGi3Cg==
|
||||
dependencies:
|
||||
append-field "^1.0.0"
|
||||
busboy "^0.2.11"
|
||||
concat-stream "^1.5.2"
|
||||
mkdirp "^0.5.1"
|
||||
object-assign "^4.1.1"
|
||||
on-finished "^2.3.0"
|
||||
type-is "^1.6.4"
|
||||
xtend "^4.0.0"
|
||||
|
||||
nanoid@^3.1.22:
|
||||
version "3.1.22"
|
||||
resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.1.22.tgz#b35f8fb7d151990a8aebd5aa5015c03cf726f844"
|
||||
@@ -387,12 +445,12 @@ node-osc@6.0.2:
|
||||
dependencies:
|
||||
osc-min "^1.1.1"
|
||||
|
||||
object-assign@^4:
|
||||
object-assign@^4, object-assign@^4.1.1:
|
||||
version "4.1.1"
|
||||
resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863"
|
||||
integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=
|
||||
|
||||
on-finished@~2.3.0:
|
||||
on-finished@^2.3.0, on-finished@~2.3.0:
|
||||
version "2.3.0"
|
||||
resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.3.0.tgz#20f1336481b083cd75337992a16971aa2d906947"
|
||||
integrity sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=
|
||||
@@ -446,10 +504,10 @@ pause@0.0.1:
|
||||
resolved "https://registry.yarnpkg.com/pause/-/pause-0.0.1.tgz#1d408b3fdb76923b9543d96fb4c9dfd535d9cb5d"
|
||||
integrity sha1-HUCLP9t2kjuVQ9lvtMnf1TXZy10=
|
||||
|
||||
pify@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/pify/-/pify-3.0.0.tgz#e5a4acd2c101fdf3d9a4d07f0dbc4db49dd28176"
|
||||
integrity sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=
|
||||
process-nextick-args@~2.0.0:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2"
|
||||
integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==
|
||||
|
||||
proxy-addr@~2.0.5:
|
||||
version "2.0.6"
|
||||
@@ -484,7 +542,30 @@ raw-body@2.4.0:
|
||||
iconv-lite "0.4.24"
|
||||
unpipe "1.0.0"
|
||||
|
||||
safe-buffer@5.1.2:
|
||||
readable-stream@1.1.x:
|
||||
version "1.1.14"
|
||||
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.1.14.tgz#7cf4c54ef648e3813084c636dd2079e166c081d9"
|
||||
integrity sha1-fPTFTvZI44EwhMY23SB54WbAgdk=
|
||||
dependencies:
|
||||
core-util-is "~1.0.0"
|
||||
inherits "~2.0.1"
|
||||
isarray "0.0.1"
|
||||
string_decoder "~0.10.x"
|
||||
|
||||
readable-stream@^2.2.2:
|
||||
version "2.3.7"
|
||||
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57"
|
||||
integrity sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==
|
||||
dependencies:
|
||||
core-util-is "~1.0.0"
|
||||
inherits "~2.0.3"
|
||||
isarray "~1.0.0"
|
||||
process-nextick-args "~2.0.0"
|
||||
safe-buffer "~5.1.1"
|
||||
string_decoder "~1.1.1"
|
||||
util-deprecate "~1.0.1"
|
||||
|
||||
safe-buffer@5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1:
|
||||
version "5.1.2"
|
||||
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d"
|
||||
integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==
|
||||
@@ -567,19 +648,34 @@ socket.io@^4.0.0:
|
||||
resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c"
|
||||
integrity sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=
|
||||
|
||||
steno@^0.4.1:
|
||||
version "0.4.4"
|
||||
resolved "https://registry.yarnpkg.com/steno/-/steno-0.4.4.tgz#071105bdfc286e6615c0403c27e9d7b5dcb855cb"
|
||||
integrity sha1-BxEFvfwobmYVwEA8J+nXtdy4Vcs=
|
||||
steno@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/steno/-/steno-1.0.0.tgz#475e32c6066ec9760229eaaf1550601764fbecba"
|
||||
integrity sha512-C/KgCvEa1yWnpHmaPjAXrz1yWxh6hs+HvhqqPa71euaQmNi1wr4+WFo57VQxjKKuFl2KqS7gtlrN0oxj2noQLw==
|
||||
|
||||
streamsearch@0.1.2:
|
||||
version "0.1.2"
|
||||
resolved "https://registry.yarnpkg.com/streamsearch/-/streamsearch-0.1.2.tgz#808b9d0e56fc273d809ba57338e929919a1a9f1a"
|
||||
integrity sha1-gIudDlb8Jz2Am6VzOOkpkZoanxo=
|
||||
|
||||
string_decoder@~0.10.x:
|
||||
version "0.10.31"
|
||||
resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94"
|
||||
integrity sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=
|
||||
|
||||
string_decoder@~1.1.1:
|
||||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8"
|
||||
integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==
|
||||
dependencies:
|
||||
graceful-fs "^4.1.3"
|
||||
safe-buffer "~5.1.0"
|
||||
|
||||
toidentifier@1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.0.tgz#7e1be3470f1e77948bc43d94a3c8f4d7752ba553"
|
||||
integrity sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==
|
||||
|
||||
type-is@~1.6.17, type-is@~1.6.18:
|
||||
type-is@^1.6.4, type-is@~1.6.17, type-is@~1.6.18:
|
||||
version "1.6.18"
|
||||
resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.18.tgz#4e552cd05df09467dcbc4ef739de89f2cf37c131"
|
||||
integrity sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==
|
||||
@@ -587,6 +683,11 @@ type-is@~1.6.17, type-is@~1.6.18:
|
||||
media-typer "0.3.0"
|
||||
mime-types "~2.1.24"
|
||||
|
||||
typedarray@^0.0.6:
|
||||
version "0.0.6"
|
||||
resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777"
|
||||
integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=
|
||||
|
||||
uid-safe@~2.1.5:
|
||||
version "2.1.5"
|
||||
resolved "https://registry.yarnpkg.com/uid-safe/-/uid-safe-2.1.5.tgz#2b3d5c7240e8fc2e58f8aa269e5ee49c0857bd3a"
|
||||
@@ -599,6 +700,11 @@ unpipe@1.0.0, unpipe@~1.0.0:
|
||||
resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec"
|
||||
integrity sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=
|
||||
|
||||
util-deprecate@~1.0.1:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf"
|
||||
integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=
|
||||
|
||||
utils-merge@1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713"
|
||||
@@ -613,3 +719,8 @@ ws@~7.4.2:
|
||||
version "7.4.4"
|
||||
resolved "https://registry.yarnpkg.com/ws/-/ws-7.4.4.tgz#383bc9742cb202292c9077ceab6f6047b17f2d59"
|
||||
integrity sha512-Qm8k8ojNQIMx7S+Zp8u/uHOx7Qazv3Yv4q68MiWWWOJhiwG5W3x7iqmRtJo8xxrciZUY4vRxUTJCKuRnF28ZZw==
|
||||
|
||||
xtend@^4.0.0:
|
||||
version "4.0.2"
|
||||
resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54"
|
||||
integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==
|
||||
|
||||
Reference in New Issue
Block a user