commit
19baa706fc
12 changed files with 70 additions and 3042 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -33,6 +33,8 @@ node_modules
|
|||
.node_repl_history
|
||||
|
||||
db.sqlite
|
||||
db.json
|
||||
package-lock.json
|
||||
public/client.js
|
||||
public/main.js
|
||||
public/status.js
|
||||
|
|
12
Dockerfile
12
Dockerfile
|
@ -11,10 +11,9 @@ COPY public $HOME/public
|
|||
|
||||
WORKDIR $HOME
|
||||
|
||||
RUN apk add --no-cache make gcc g++ python && \
|
||||
npm install && \
|
||||
apk del make gcc g++ python && \
|
||||
npm run build
|
||||
RUN npm install && \
|
||||
npm run build && \
|
||||
rm -rf node_modules
|
||||
|
||||
###########################
|
||||
# Server
|
||||
|
@ -27,13 +26,10 @@ COPY .babelrc config.js log.js index.js package.json $HOME/
|
|||
|
||||
WORKDIR $HOME
|
||||
|
||||
RUN apk add --no-cache make gcc g++ python && \
|
||||
npm install --production
|
||||
RUN npm install --production
|
||||
|
||||
COPY api $HOME/api
|
||||
COPY migrations $HOME/migrations
|
||||
COPY config $HOME/config
|
||||
COPY script $HOME/script
|
||||
COPY --from=build /app/public $HOME/public
|
||||
|
||||
EXPOSE 3000
|
||||
|
|
|
@ -14,7 +14,7 @@ let casparIsConnected
|
|||
let currentHost
|
||||
|
||||
export function initialise(log, db, socket) {
|
||||
io = socket.socket
|
||||
io = socket
|
||||
logger = log
|
||||
db = db
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import template from 'lodash.template'
|
||||
import _ from 'lodash'
|
||||
|
||||
export const active = { }
|
||||
|
||||
|
@ -13,7 +13,7 @@ function getSocket(ctx, all) {
|
|||
* Display a specific graphic content
|
||||
*/
|
||||
export async function display(ctx, data) {
|
||||
let compiled = template(data.graphic.settings.html)
|
||||
let compiled = _.template(data.graphic.settings.html)
|
||||
let html = compiled(data.data)
|
||||
|
||||
// let old = await Content.getSingle(data.graphic.name)
|
||||
|
@ -68,7 +68,7 @@ function generateDisplayText(item) {
|
|||
// return `${item.data.text} - ${item.data.finished}`
|
||||
// }
|
||||
try {
|
||||
return template(item.graphic.settings.main)(item.data)
|
||||
return _.template(item.graphic.settings.main)(item.data)
|
||||
} catch (e) {
|
||||
return `Error creating display: ${e.message}`
|
||||
}
|
||||
|
|
|
@ -41,9 +41,9 @@ export async function create(ctx, data) {
|
|||
data.settings.main = '<%- text %> - <%- finished %>'
|
||||
}
|
||||
|
||||
let graphics = ctx.db.get('graphics').insert(data)
|
||||
let graphics = ctx.db.get('graphics')
|
||||
await graphics.insert(data).write()
|
||||
let graphic = graphics.last().value()
|
||||
await graphics.write()
|
||||
|
||||
ctx.io.emit('graphic.single', graphic)
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import bunyan from 'bunyan'
|
||||
import bunyan from 'bunyan-lite'
|
||||
import defaults from './defaults.mjs'
|
||||
import config from './config.mjs'
|
||||
|
||||
|
|
|
@ -1,40 +0,0 @@
|
|||
|
||||
export function bunyanLogger(logger) {
|
||||
return async (ctx, next) => {
|
||||
ctx.log = logger.child({
|
||||
})
|
||||
|
||||
const d1 = new Date().getTime()
|
||||
|
||||
await next()
|
||||
|
||||
const d2 = new Date().getTime()
|
||||
|
||||
let level = 'info'
|
||||
if (ctx.status >= 400) {
|
||||
level = 'warn'
|
||||
}
|
||||
if (ctx.status >= 500) {
|
||||
level = 'error'
|
||||
}
|
||||
|
||||
ctx.log[level]({
|
||||
duration: (d2 - d1),
|
||||
status: ctx.res.statusCode,
|
||||
}, `<-- ${ctx.request.method} ${ctx.request.url}`)
|
||||
}
|
||||
}
|
||||
|
||||
export function errorHandler() {
|
||||
return async (ctx, next) => {
|
||||
try {
|
||||
await next()
|
||||
} catch(err) {
|
||||
ctx.log.error(err, 'Unknown error occured')
|
||||
ctx.status = 500
|
||||
ctx.render('error', {
|
||||
error: err,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
|
@ -11,8 +11,8 @@ import * as settings from './settings/routes.mjs'
|
|||
import * as schedule from './schedule/routes.mjs'
|
||||
|
||||
function onConnection(server, db, data) {
|
||||
const io = server.socket
|
||||
const socket = data.socket
|
||||
const io = server
|
||||
const socket = data
|
||||
const log = logger.child({
|
||||
id: socket.id,
|
||||
})
|
||||
|
|
|
@ -1,38 +1,69 @@
|
|||
import Koa from 'koa'
|
||||
import serve from 'koa-better-serve'
|
||||
import socket from 'koa-socket'
|
||||
import socket from 'socket.io-serveronly'
|
||||
import http from 'http'
|
||||
import nStatic from 'node-static'
|
||||
import * as casparcg from './casparcg/client.mjs'
|
||||
|
||||
import lowdb from './db.mjs'
|
||||
import config from './config.mjs'
|
||||
import log from './log.mjs'
|
||||
import onConnection from './routerio.mjs'
|
||||
import { bunyanLogger, errorHandler } from './middlewares.mjs'
|
||||
|
||||
log.info('Server: Opening database db.json')
|
||||
|
||||
lowdb().then(function(db) {
|
||||
const app = new Koa()
|
||||
const io = new socket()
|
||||
const fileServer = new nStatic.Server('./public')
|
||||
const server = http.createServer(function (req, res) {
|
||||
const child = log.child({})
|
||||
|
||||
io.attach(app)
|
||||
const d1 = new Date().getTime()
|
||||
|
||||
var done = function () {
|
||||
var requestTime = new Date().getTime() - d1
|
||||
|
||||
let level = 'info'
|
||||
if (res.status >= 400) {
|
||||
level = 'warn'
|
||||
}
|
||||
if (res.status >= 500) {
|
||||
level = 'error'
|
||||
}
|
||||
|
||||
child[level]({
|
||||
duration: requestTime,
|
||||
status: res.statusCode,
|
||||
}, `<-- ${req.method} ${req.url}`)
|
||||
}
|
||||
|
||||
res.addListener('finish', done);
|
||||
res.addListener('close', done);
|
||||
|
||||
req.addListener('end', function () {
|
||||
if (req.url === '/') {
|
||||
res.writeHead(302, { Location: '/index.html' })
|
||||
return res.end()
|
||||
}
|
||||
|
||||
fileServer.serve(req, res, function (err) {
|
||||
if (err) {
|
||||
log.error(err);
|
||||
|
||||
res.writeHead(err.status, err.headers);
|
||||
res.end(err.message);
|
||||
}
|
||||
});
|
||||
}).resume()
|
||||
})
|
||||
|
||||
const io = new socket(server)
|
||||
io.on('connection', onConnection.bind(this, io, db))
|
||||
|
||||
casparcg.initialise(log, db, io)
|
||||
|
||||
app.use(bunyanLogger(log))
|
||||
app.use(errorHandler())
|
||||
app.use(async (ctx, next) => {
|
||||
if (ctx.url === '/') {
|
||||
return ctx.redirect('/index.html')
|
||||
server.listen(config.get('server:port'), '0.0.0.0', function(err) {
|
||||
if (err) {
|
||||
log.fatal(err)
|
||||
return process.exit(2)
|
||||
}
|
||||
await next()
|
||||
})
|
||||
app.use(serve('./public', ''))
|
||||
|
||||
app.listen(config.get('server:port'), err => {
|
||||
if (err) return log.fatal(err)
|
||||
log.info(`Server is listening on ${config.get('server:port')}`)
|
||||
})
|
||||
}, function(e) {
|
||||
|
|
187
db.json
187
db.json
|
@ -1,187 +0,0 @@
|
|||
{
|
||||
"graphics": [
|
||||
{
|
||||
"name": "Nidurteljari",
|
||||
"engine": "countdown",
|
||||
"settings": {
|
||||
"html": "<%- text %><br><span id=\"Nidurteljari-countdown-timer\">countdown appears here</span>",
|
||||
"main": "text",
|
||||
"text": "Sunnudagssamkoman hefst klukkan 11:00",
|
||||
"countdown": "2018-07-01 11:00",
|
||||
"finished": "Skamma stund",
|
||||
"css": "#Nidurteljari {\n position: absolute;\n font: 2em \"Berthold Akzidenz Grotesk BE\";\n top: 830px;\n left: 230px;\n width: 1450px;\n padding-top: 20px;\n border-top: 1px solid #095376;\n text-align: center;\n color: #095376;\n font-size: 60pt;\n line-height: 70pt;\n font-weight: bold;\n}\n#Nidurteljari-countdown-timer {\n font-size: 80pt;\n}"
|
||||
},
|
||||
"id": 1586112780891
|
||||
},
|
||||
{
|
||||
"name": "Nafn",
|
||||
"engine": "text",
|
||||
"settings": {
|
||||
"properties": [
|
||||
"nafn",
|
||||
"titill"
|
||||
],
|
||||
"main": "<%- nafn %>",
|
||||
"html": "<div class=\"outer\">\n<div class=\"inside\">\n<h2><%- nafn %></h2>\n<h4><%- titill %></h4>\n</div>\n</div>",
|
||||
"css": "#Nafn {\nposition: absolute;\nbottom: 50px;\nleft: 0px;\nwidth: 100%;\nright: 0;\nbackground: transparent;\ncolor: black;\nfont-family: Raleway;\ndisplay: flex;\njustify-content: center;\n}\n\n#Nafn .outer {\nborder: 4px solid white;\npadding: 6px;\n}\n\n#Nafn .inside {\npadding: 8px 24px;\nbackground: white;\ndisplay: flex;\nflex-direction: column;\n}\n\n#Nafn .inside h2 {\nfont-weight: bold;\nfont-size: 40px;\ntext-align: center;\ntext-transform: uppercase;\npadding: 0;\nmargin: 0;\nline-height: 120%;\n}\n\n#Nafn .inside h4 {\nfont-weight: normal;\nfont-size: 18px;\npadding: 0;\nmargin: 0;\ntext-align: center;\nline-height: 125%;\ntext-transform: uppercase;\n}"
|
||||
},
|
||||
"id": 1586112780892
|
||||
},
|
||||
{
|
||||
"name": "Minnisvers",
|
||||
"engine": "text",
|
||||
"settings": {
|
||||
"properties": [
|
||||
"bok",
|
||||
"vers"
|
||||
],
|
||||
"main": "bok",
|
||||
"css": "#Minnisvers {\n position: absolute;\n font: 2em \"Berthold Akzidenz Grotesk BE\";\n top: 850px;\n right: 0px;\n}\n.bok-holder {\n background: rgba(0,68,105,0.6);\n line-height: 60px;\n font-size: 60px;\n color: white;\n padding: 10px 60px 0px 30px;\n}\n.vers-holder {\n background: rgba(33,29,29,0.6);\n font-size: 30px;\n line-height: 30px;\n color: white;\n padding: 10px 60px 0px 40px;\n}",
|
||||
"html": "<div class=\"bok-holder\"><%- bok %></div>\n<div class=\"vers-holder\"><%- vers %></div>"
|
||||
},
|
||||
"id": 1586112780893
|
||||
},
|
||||
{
|
||||
"name": "Forn",
|
||||
"engine": "text",
|
||||
"settings": {
|
||||
"properties": [
|
||||
"Titill",
|
||||
"Text"
|
||||
],
|
||||
"main": "<%- Titill %> - <%- Text %>",
|
||||
"css": "#Forn {\nposition: absolute;\ntop: 50px;\nleft: 95px;\nborder: 4px solid white;\npadding: 6px;\nbackground: transparent;\ncolor: black;\nfont-family: Raleway;\n}\n\n#Forn .inside {\npadding: 6px 24px;\nbackground: white;\ndisplay: flex;\nflex-direction: column;\n}\n\n#Forn .inside h2 {\nfont-weight: bold;\nfont-size: 24px;\ntext-align: center;\ntext-transform: uppercase;\npadding: 0;\nmargin: 0;\n}\n\n#Forn .inside h4 {\nfont-weight: normal;\nfont-size: 18px;\npadding: 0;\nmargin: 0;\ntext-align: center;\nline-height: 125%;\n}",
|
||||
"html": "<div class=\"inside\">\n<h2><%- Titill %></h2>\n<h4><%= Text.replace('\\n', '<br>') %></h4>\n</div>"
|
||||
},
|
||||
"id": 1586112780894
|
||||
},
|
||||
{
|
||||
"name": "Lög",
|
||||
"engine": "text",
|
||||
"settings": {
|
||||
"properties": [
|
||||
"nafn"
|
||||
],
|
||||
"html": "<div class=\"box-before\"></div>\n<div class=\"box-logo\"></div>\n<div class=\"box-after\"></div>\n<div class=\"box-name\">\n <div class=\"holder\">\n <div class=\"name-holder\"><%- nafn %>\n <div class=\"name-triangle\"></div><div class=\"titill-triangle\"></div>\n </div>\n </div>\n</div>",
|
||||
"css": ".box-before {\n margin-bottom: 15px;\n width: 160px;\n height: 112px;\n margin-right: -37px;\n /* ---------- THEME COLOR ---------- */\n background-image: -webkit-radial-gradient(200px 50%, circle, rgba(0, 0, 0, 0) 0, rgba(0, 0, 0, 0) 75px, rgba(0,68,105,1) 77px);\n /* ---------- END THEME COLOR ---------- */\n}\n.box-after {\n /* ---------- THEME COLOR ---------- */\n background-image: -webkit-radial-gradient(-40px 50%, circle, rgba(0, 0, 0, 0) 0, rgba(0, 0, 0, 0) 75px, rgba(0,68,105,1) 77px);\n /* ---------- END THEME COLOR ---------- */\n margin-bottom: 15px;\n width: 100px;\n height: 112px;\n margin-left: -37px;\n}\n\n#Lög {\n position: absolute;\n color: white;\n font: 2em \"Berthold Akzidenz Grotesk BE\";\n top: 100px;\n left: 0px;\n}\n\n#Lög > div { display: inline-block; }\n\n.box-logo {\n width: 141px;\n height: 141px;\n background: url('uploads/logo.png') 0px 0px no-repeat;\n background-size: contain;\n}\n\n.box-name {\n margin-bottom: 15px;\n height: 112px;\n position: relative;\n margin-left: -6px;\n width: 700px;\n}\n.holder { position: absolute; }\n.name-holder {\n position: relative;\n background: linear-gradient(to right, rgba(207,209,210,0.6) 0%,rgba(235,235,237,0.6) 50%,rgba(183,185,185,0.6) 100%);\n line-height: 102px;\n font-size: 60px;\n color: rgba(0,68,105,1);\n padding: 10px 30px 0px 20px;\n}\n.name-triangle {\n position: absolute;\n right: -112px;\n border-width: 0 112px 112px 0px;\n top: 0;\n border-style: solid;\n border-color: transparent transparent rgba(183,185,185,0.6) transparent;\n}",
|
||||
"main": "nafn"
|
||||
},
|
||||
"id": 1586112780895
|
||||
},
|
||||
{
|
||||
"name": "Dagskra",
|
||||
"engine": "schedule",
|
||||
"settings": {
|
||||
"properties": [
|
||||
"temp"
|
||||
],
|
||||
"textfields": [
|
||||
"item1"
|
||||
],
|
||||
"main": "temp"
|
||||
},
|
||||
"id": 1586112780896
|
||||
}
|
||||
],
|
||||
"presets": [
|
||||
{
|
||||
"graphic_id": 1586112780892,
|
||||
"values": {
|
||||
"nafn": "Bla",
|
||||
"titill": "test"
|
||||
},
|
||||
"sort": 1,
|
||||
"id": 1586205588587
|
||||
},
|
||||
{
|
||||
"graphic_id": 1586112780892,
|
||||
"values": {
|
||||
"nafn": "Bla 2",
|
||||
"titill": "test 2"
|
||||
},
|
||||
"sort": 2,
|
||||
"id": 1586205644890
|
||||
}
|
||||
],
|
||||
"playing": [
|
||||
{
|
||||
"graphic": {
|
||||
"name": "Nafn",
|
||||
"engine": "text",
|
||||
"settings": {
|
||||
"properties": [
|
||||
"nafn",
|
||||
"titill"
|
||||
],
|
||||
"main": "<%- nafn %>",
|
||||
"html": "<div class=\"outer\">\n<div class=\"inside\">\n<h2><%- nafn %></h2>\n<h4><%- titill %></h4>\n</div>\n</div>",
|
||||
"css": "#Nafn {\nposition: absolute;\nbottom: 50px;\nleft: 0px;\nwidth: 100%;\nright: 0;\nbackground: transparent;\ncolor: black;\nfont-family: Raleway;\ndisplay: flex;\njustify-content: center;\n}\n\n#Nafn .outer {\nborder: 4px solid white;\npadding: 6px;\n}\n\n#Nafn .inside {\npadding: 8px 24px;\nbackground: white;\ndisplay: flex;\nflex-direction: column;\n}\n\n#Nafn .inside h2 {\nfont-weight: bold;\nfont-size: 40px;\ntext-align: center;\ntext-transform: uppercase;\npadding: 0;\nmargin: 0;\nline-height: 120%;\n}\n\n#Nafn .inside h4 {\nfont-weight: normal;\nfont-size: 18px;\npadding: 0;\nmargin: 0;\ntext-align: center;\nline-height: 125%;\ntext-transform: uppercase;\n}"
|
||||
},
|
||||
"id": 1586112780892
|
||||
},
|
||||
"name": "Nafn",
|
||||
"html": "<div class=\"outer\">\n<div class=\"inside\">\n<h2>Bla 2</h2>\n<h4>test 2</h4>\n</div>\n</div>",
|
||||
"css": "#Nafn {\nposition: absolute;\nbottom: 50px;\nleft: 0px;\nwidth: 100%;\nright: 0;\nbackground: transparent;\ncolor: black;\nfont-family: Raleway;\ndisplay: flex;\njustify-content: center;\n}\n\n#Nafn .outer {\nborder: 4px solid white;\npadding: 6px;\n}\n\n#Nafn .inside {\npadding: 8px 24px;\nbackground: white;\ndisplay: flex;\nflex-direction: column;\n}\n\n#Nafn .inside h2 {\nfont-weight: bold;\nfont-size: 40px;\ntext-align: center;\ntext-transform: uppercase;\npadding: 0;\nmargin: 0;\nline-height: 120%;\n}\n\n#Nafn .inside h4 {\nfont-weight: normal;\nfont-size: 18px;\npadding: 0;\nmargin: 0;\ntext-align: center;\nline-height: 125%;\ntext-transform: uppercase;\n}",
|
||||
"data": {
|
||||
"nafn": "Bla 2",
|
||||
"titill": "test 2"
|
||||
},
|
||||
"is_deleted": false,
|
||||
"id": 1586213076185
|
||||
}
|
||||
],
|
||||
"schedule": [
|
||||
{
|
||||
"graphic_id": 1586112780892,
|
||||
"values": {
|
||||
"nafn": "Bla 2",
|
||||
"titill": "test 2"
|
||||
},
|
||||
"sort": 1,
|
||||
"id": 1586213073361,
|
||||
"graphic": {
|
||||
"name": "Nafn",
|
||||
"engine": "text",
|
||||
"settings": {
|
||||
"properties": [
|
||||
"nafn",
|
||||
"titill"
|
||||
],
|
||||
"main": "<%- nafn %>",
|
||||
"html": "<div class=\"outer\">\n<div class=\"inside\">\n<h2><%- nafn %></h2>\n<h4><%- titill %></h4>\n</div>\n</div>",
|
||||
"css": "#Nafn {\nposition: absolute;\nbottom: 50px;\nleft: 0px;\nwidth: 100%;\nright: 0;\nbackground: transparent;\ncolor: black;\nfont-family: Raleway;\ndisplay: flex;\njustify-content: center;\n}\n\n#Nafn .outer {\nborder: 4px solid white;\npadding: 6px;\n}\n\n#Nafn .inside {\npadding: 8px 24px;\nbackground: white;\ndisplay: flex;\nflex-direction: column;\n}\n\n#Nafn .inside h2 {\nfont-weight: bold;\nfont-size: 40px;\ntext-align: center;\ntext-transform: uppercase;\npadding: 0;\nmargin: 0;\nline-height: 120%;\n}\n\n#Nafn .inside h4 {\nfont-weight: normal;\nfont-size: 18px;\npadding: 0;\nmargin: 0;\ntext-align: center;\nline-height: 125%;\ntext-transform: uppercase;\n}"
|
||||
},
|
||||
"id": 1586112780892
|
||||
}
|
||||
},
|
||||
{
|
||||
"graphic_id": 1586112780892,
|
||||
"values": {
|
||||
"nafn": "Bla",
|
||||
"titill": "test"
|
||||
},
|
||||
"sort": 2,
|
||||
"id": 1586213074043,
|
||||
"graphic": {
|
||||
"name": "Nafn",
|
||||
"engine": "text",
|
||||
"settings": {
|
||||
"properties": [
|
||||
"nafn",
|
||||
"titill"
|
||||
],
|
||||
"main": "<%- nafn %>",
|
||||
"html": "<div class=\"outer\">\n<div class=\"inside\">\n<h2><%- nafn %></h2>\n<h4><%- titill %></h4>\n</div>\n</div>",
|
||||
"css": "#Nafn {\nposition: absolute;\nbottom: 50px;\nleft: 0px;\nwidth: 100%;\nright: 0;\nbackground: transparent;\ncolor: black;\nfont-family: Raleway;\ndisplay: flex;\njustify-content: center;\n}\n\n#Nafn .outer {\nborder: 4px solid white;\npadding: 6px;\n}\n\n#Nafn .inside {\npadding: 8px 24px;\nbackground: white;\ndisplay: flex;\nflex-direction: column;\n}\n\n#Nafn .inside h2 {\nfont-weight: bold;\nfont-size: 40px;\ntext-align: center;\ntext-transform: uppercase;\npadding: 0;\nmargin: 0;\nline-height: 120%;\n}\n\n#Nafn .inside h4 {\nfont-weight: normal;\nfont-size: 18px;\npadding: 0;\nmargin: 0;\ntext-align: center;\nline-height: 125%;\ntext-transform: uppercase;\n}"
|
||||
},
|
||||
"id": 1586112780892
|
||||
}
|
||||
}
|
||||
],
|
||||
"settings": {
|
||||
"casparplayhost": "localhost:3000",
|
||||
"casparhost": "host.docker.internal"
|
||||
},
|
||||
"version": 1,
|
||||
"trash": []
|
||||
}
|
2772
package-lock.json
generated
2772
package-lock.json
generated
File diff suppressed because it is too large
Load diff
14
package.json
14
package.json
|
@ -14,7 +14,7 @@
|
|||
"start:win": "node --experimental-modules index.mjs | bunyan -o short",
|
||||
"dev": "run-p js:watch start:watch",
|
||||
"build": "run-p js:build:main js:build:client js:build:status",
|
||||
"docker": "docker run -it --rm --name my-running-script -p 3000:3000 -v \"%cd%\":/usr/src/app -w /usr/src/app node",
|
||||
"docker": "docker run -it --rm --name my-running-script -p 3000:3000 -v \"%cd%\":/usr/src/app -w /usr/src/app node:alpine",
|
||||
"docker:install": "npm run docker -- npm install",
|
||||
"docker:dev": "npm run docker -- npm run dev"
|
||||
},
|
||||
|
@ -34,19 +34,17 @@
|
|||
},
|
||||
"homepage": "https://github.com/nfp-projects/caspar-sup#readme",
|
||||
"dependencies": {
|
||||
"bunyan": "^1.8.12",
|
||||
"bunyan-lite": "^1.0.1",
|
||||
"casparcg-connection": "4.9.0",
|
||||
"koa": "^2.4.1",
|
||||
"koa-better-serve": "^2.0.7",
|
||||
"koa-socket": "^4.4.0",
|
||||
"lodash.template": "^4.5.0",
|
||||
"lodash": "^4.5.0",
|
||||
"lowdb": "^1.0.0",
|
||||
"nconf": "^0.9.1",
|
||||
"socket.io": "^2.3.0",
|
||||
"node-static": "^0.7.11",
|
||||
"socket.io-serveronly": "^2.3.0",
|
||||
"tslib": "^1.11.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"asbundle": "TheThing/asbundle",
|
||||
"asbundle": "^2.6.1",
|
||||
"dragula": "^3.7.2",
|
||||
"mithril": "^1.1.5",
|
||||
"nodemon": "^2.0.2",
|
||||
|
|
Loading…
Reference in a new issue