2023-06-23 22:40:31 +00:00
"use strict" ;
2023-12-14 15:29:19 +00:00
var _ _createBinding = ( this && this . _ _createBinding ) || ( Object . create ? ( function ( o , m , k , k2 ) {
if ( k2 === undefined ) k2 = k ;
var desc = Object . getOwnPropertyDescriptor ( m , k ) ;
if ( ! desc || ( "get" in desc ? ! m . _ _esModule : desc . writable || desc . configurable ) ) {
desc = { enumerable : true , get : function ( ) { return m [ k ] ; } } ;
}
Object . defineProperty ( o , k2 , desc ) ;
} ) : ( function ( o , m , k , k2 ) {
if ( k2 === undefined ) k2 = k ;
o [ k2 ] = m [ k ] ;
} ) ) ;
var _ _setModuleDefault = ( this && this . _ _setModuleDefault ) || ( Object . create ? ( function ( o , v ) {
Object . defineProperty ( o , "default" , { enumerable : true , value : v } ) ;
} ) : function ( o , v ) {
o [ "default" ] = v ;
} ) ;
var _ _importStar = ( this && this . _ _importStar ) || function ( mod ) {
if ( mod && mod . _ _esModule ) return mod ;
var result = { } ;
if ( mod != null ) for ( var k in mod ) if ( k !== "default" && Object . prototype . hasOwnProperty . call ( mod , k ) ) _ _createBinding ( result , mod , k ) ;
_ _setModuleDefault ( result , mod ) ;
return result ;
} ;
2023-06-23 22:40:31 +00:00
var _ _importDefault = ( this && this . _ _importDefault ) || function ( mod ) {
return ( mod && mod . _ _esModule ) ? mod : { "default" : mod } ;
} ;
Object . defineProperty ( exports , "__esModule" , { value : true } ) ;
2023-12-14 20:31:36 +00:00
require ( "dotenv/config" ) ;
2023-06-23 22:40:31 +00:00
const express _1 = _ _importDefault ( require ( "express" ) ) ;
const promises _1 = _ _importDefault ( require ( "fs/promises" ) ) ;
const fs _1 = require ( "fs" ) ;
const os _1 = require ( "os" ) ;
const path _1 = require ( "path" ) ;
const crypto _1 = require ( "crypto" ) ;
const sqlite3 _1 = require ( "sqlite3" ) ;
const body _parser _1 = _ _importDefault ( require ( "body-parser" ) ) ;
const multer _1 = _ _importDefault ( require ( "multer" ) ) ;
const uuid _1 = require ( "uuid" ) ;
const mime _1 = require ( "mime" ) ;
2023-12-01 00:25:43 +00:00
const log _1 = require ( "./log" ) ;
2023-12-14 15:29:19 +00:00
const Handlebars = _ _importStar ( require ( "handlebars" ) ) ;
2023-06-23 22:40:31 +00:00
const port = typeof process . env [ 'PORT' ] !== 'undefined' ? parseInt ( process . env [ 'PORT' ] , 10 ) : 3333 ;
const data = typeof process . env [ 'DATADIR' ] !== 'undefined' ? process . env [ 'DATADIR' ] : './data' ;
const dbPath = ( 0 , path _1 . join ) ( data , 'queue.sqlite' ) ;
const app = ( 0 , express _1 . default ) ( ) ;
const tmp = ( 0 , os _1 . tmpdir ) ( ) ;
const db = new sqlite3 _1 . Database ( dbPath ) ;
2023-12-01 01:52:53 +00:00
let log = ( 0 , log _1 . createLog ) ( 'server' ) ;
2023-06-23 22:40:31 +00:00
const accepted = [ 'application/zip' , 'application/x-zip-compressed' ] ;
const storage = multer _1 . default . diskStorage ( {
destination : function ( req , file , cb ) {
cb ( null , tmp ) ;
} ,
filename : function ( req , file , cb ) {
cb ( null , ` ${ + new Date ( ) } _ ${ file . originalname } ` ) ;
}
} ) ;
function fileFilter ( req , file , cb ) {
if ( accepted . indexOf ( file . mimetype ) !== - 1 ) {
cb ( null , true ) ;
}
else {
2023-12-01 00:25:43 +00:00
log . warn ( ` Filetype ${ file . mimetype } is not of type zip ` ) ;
2023-06-23 22:40:31 +00:00
cb ( new Error ( "Dataset is not of type zip" ) , false ) ;
}
}
2023-06-24 00:22:05 +00:00
const uploadZip = ( 0 , multer _1 . default ) ( { storage , fileFilter } ) ;
2023-11-29 17:47:20 +00:00
const uploadOnnx = ( 0 , multer _1 . default ) ( { storage , fileFilter } ) ;
2023-06-23 22:40:31 +00:00
app . use ( body _parser _1 . default . json ( ) ) ;
app . use ( body _parser _1 . default . urlencoded ( { extended : true } ) ) ;
2023-12-14 15:29:19 +00:00
async function createTemplate ( filePath ) {
let tmpl ;
try {
tmpl = await promises _1 . default . readFile ( filePath , 'utf8' ) ;
}
catch ( err ) {
log . error ( err ) ;
return null ;
}
return Handlebars . compile ( tmpl ) ;
}
let index ;
2023-06-23 22:40:31 +00:00
function hash ( path ) {
return new Promise ( ( resolve , reject ) => {
const hashSum = ( 0 , crypto _1 . createHash ) ( 'sha256' ) ;
const stream = ( 0 , fs _1 . createReadStream ) ( path ) ;
stream . on ( 'error' , ( err ) => reject ( err ) ) ;
stream . on ( 'data' , ( chunk ) => hashSum . update ( chunk ) ) ;
stream . on ( 'end' , ( ) => resolve ( hashSum . digest ( 'hex' ) ) ) ;
} ) ;
}
async function exists ( path ) {
try {
await promises _1 . default . access ( path ) ;
return true ;
}
catch {
return false ;
}
}
async function add ( email , name , dataset , model ) {
const query = ` INSERT INTO queue
( id , email , name , dataset , model )
VALUES ( ? , ? , ? , ? , ? ) ; ` ;
const id = ( 0 , uuid _1 . v4 ) ( ) ;
return new Promise ( ( resolve , reject ) => {
return db . run ( query , [ id , email , name , dataset , model ] , ( err , row ) => {
if ( err )
return reject ( err ) ;
2023-12-01 00:25:43 +00:00
log . info ( ` Added job ${ id } to queue ` ) ;
2023-06-23 22:40:31 +00:00
return resolve ( id ) ;
} ) ;
} ) ;
}
async function status ( id ) {
const query = ` SELECT name, model, started, completed, failed, meta FROM queue WHERE id = ? LIMIT 1; ` ;
let jobStatus = 'Unknown' ;
return new Promise ( ( resolve , reject ) => {
return db . all ( query , [ id ] , ( err , rows ) => {
if ( err )
return reject ( err ) ;
2023-06-24 00:22:05 +00:00
if ( rows . length !== 1 ) {
return resolve ( jobStatus ) ;
}
const obj = rows [ 0 ] ;
2023-06-23 22:40:31 +00:00
if ( rows [ 0 ] . started === null ) {
jobStatus = ` Has not started ` ;
}
else if ( rows [ 0 ] . failed !== null ) {
jobStatus = ` Failed <br /> <pre> ${ rows [ 0 ] . meta } </pre> ` ;
}
else if ( rows [ 0 ] . completed !== null ) {
2023-06-30 14:53:59 +00:00
jobStatus = ` Completed ${ rows [ 0 ] . completed } <a href="/model/ ${ id } ">Download</a> ` ;
2023-06-23 22:40:31 +00:00
}
2023-06-24 00:22:05 +00:00
else if ( rows [ 0 ] . started !== null ) {
jobStatus = ` Started ${ rows [ 0 ] . started } ` ;
}
2023-12-01 00:25:43 +00:00
log . info ( ` Got status for job ${ id } : ${ jobStatus } ` ) ;
2023-06-23 22:40:31 +00:00
return resolve ( jobStatus ) ;
} ) ;
} ) ;
}
async function name ( id ) {
const query = ` SELECT name, meta FROM queue WHERE id = ? LIMIT 1; ` ;
return new Promise ( ( resolve , reject ) => {
return db . all ( query , [ id ] , ( err , rows ) => {
if ( err )
return reject ( err ) ;
if ( rows . length < 1 ) {
return reject ( new Error ( ` Job ${ id } does not exist ` ) ) ;
}
return resolve ( rows [ 0 ] . name ) ;
} ) ;
} ) ;
}
async function dataset ( id ) {
const query = ` SELECT dataset FROM queue WHERE id = ? LIMIT 1; ` ;
return new Promise ( ( resolve , reject ) => {
return db . all ( query , [ id ] , ( err , rows ) => {
if ( err )
return reject ( err ) ;
if ( rows . length < 1 ) {
return reject ( new Error ( ` Dataset ${ id } does not exist ` ) ) ;
}
return resolve ( rows [ 0 ] . dataset ) ;
} ) ;
} ) ;
}
async function job ( ) {
const query = ` SELECT id FROM queue WHERE
started IS NULL
AND completed IS NULL
AND failed IS NULL
ORDER BY created ASC
LIMIT 1 ; ` ;
return new Promise ( ( resolve , reject ) => {
return db . all ( query , [ ] , ( err , rows ) => {
if ( err )
return reject ( err ) ;
if ( rows . length < 1 ) {
2023-06-24 00:22:05 +00:00
return resolve ( [ ] ) ;
}
return resolve ( [ rows [ 0 ] . id ] ) ;
} ) ;
} ) ;
}
async function jobs ( ) {
const query = ` SELECT id FROM queue WHERE
started IS NULL
AND completed IS NULL
AND failed IS NULL
ORDER BY created ASC ; ` ;
return new Promise ( ( resolve , reject ) => {
return db . all ( query , [ ] , ( err , rows ) => {
if ( err )
return reject ( err ) ;
return resolve ( rows . map ( ( el ) => el . id ) ) ;
} ) ;
} ) ;
}
async function claim ( id ) {
const query = ` SELECT * FROM queue WHERE id = ? LIMIT 1; ` ;
return new Promise ( ( resolve , reject ) => {
return db . all ( query , [ id ] , ( err , rows ) => {
if ( err )
return reject ( err ) ;
if ( rows . length < 1 ) {
return reject ( new Error ( ` Dataset ${ id } does not exist ` ) ) ;
2023-06-23 22:40:31 +00:00
}
2023-06-24 00:22:05 +00:00
if ( rows [ 0 ] . started !== null ) {
return reject ( new Error ( ` Job ${ id } is already claimed ` ) ) ;
}
const claimQuery = ` UPDATE queue SET started = CURRENT_TIMESTAMP WHERE id = ?; ` ;
return db . run ( claimQuery , [ id ] , ( err , row ) => {
if ( err )
return reject ( err ) ;
return resolve ( rows [ 0 ] ) ;
} ) ;
} ) ;
} ) ;
}
async function fail ( id , meta ) {
const query = ` UPDATE queue SET failed = CURRENT_TIMESTAMP, meta = ? WHERE id = ?; ` ;
return new Promise ( ( resolve , reject ) => {
return db . run ( query , [ meta , id ] , ( err , row ) => {
if ( err )
return reject ( err ) ;
return resolve ( true ) ;
} ) ;
} ) ;
}
async function complete ( id , meta ) {
const query = ` UPDATE queue SET completed = CURRENT_TIMESTAMP, meta = ? WHERE id = ?; ` ;
return new Promise ( ( resolve , reject ) => {
return db . run ( query , [ meta , id ] , ( err , row ) => {
if ( err )
return reject ( err ) ;
return resolve ( true ) ;
2023-06-23 22:40:31 +00:00
} ) ;
} ) ;
}
2023-12-14 16:19:42 +00:00
async function all ( ) {
const query = ` SELECT * FROM queue ORDER BY created DESC; ` ;
return new Promise ( ( resolve , reject ) => {
return db . all ( query , [ ] , ( err , rows ) => {
if ( err )
return reject ( err ) ;
return resolve ( rows ) ;
} ) ;
} ) ;
}
function annotate ( row ) {
row . hasModel = row . completed != null ;
if ( row . completed != null ) {
row . status = 'Completed' ;
}
else if ( row . failed != null ) {
row . status = 'Failed' ;
}
else if ( row . started != null ) {
row . status = 'Training' ;
}
else {
row . status = 'Waiting' ;
}
return row ;
}
2023-06-23 22:40:31 +00:00
app . get ( '/' , async ( req , res , next ) => {
2023-12-14 16:19:42 +00:00
let html ;
let rows ;
let input ;
try {
rows = await all ( ) ;
}
catch ( err ) {
log . error ( err ) ;
return next ( 'ERROR: Could not retrieve jobs from queue' ) ;
}
rows = rows . map ( annotate ) ;
input = {
rows ,
hasTable : typeof rows == 'undefined' ? false : rows . length > 0
} ;
html = index ( input ) ;
2023-06-23 22:40:31 +00:00
res . send ( html ) ;
} ) ;
2023-06-24 00:22:05 +00:00
app . post ( '/' , uploadZip . single ( 'dataset' ) , async ( req , res , next ) => {
2023-06-23 22:40:31 +00:00
let fileHash ;
let filePath ;
let fileExists ;
let id ;
req . setTimeout ( 0 ) ;
2023-06-30 14:46:15 +00:00
if ( typeof req . file === 'undefined' || req . file === null ) {
2023-12-01 00:25:43 +00:00
log . error ( 'No file in upload' ) ;
2023-06-23 22:40:31 +00:00
return next ( 'ERROR: Please upload dataset as zip file' ) ;
}
try {
fileHash = await hash ( req . file . path ) ;
}
catch ( err ) {
2023-12-01 00:25:43 +00:00
log . error ( err ) ;
2023-06-23 22:40:31 +00:00
return next ( ` Error hashing file ${ req . file . originalname } ` ) ;
}
filePath = ( 0 , path _1 . join ) ( data , ` ${ fileHash } .zip ` ) ;
try {
fileExists = await exists ( filePath ) ;
}
catch ( err ) {
2023-12-01 00:25:43 +00:00
log . error ( err ) ;
2023-06-23 22:40:31 +00:00
}
if ( ! fileExists ) {
try {
2023-06-24 00:22:05 +00:00
await promises _1 . default . copyFile ( req . file . path , filePath ) ;
2023-12-01 00:25:43 +00:00
log . info ( ` Saved dataset with hash ${ fileHash } ` ) ;
2023-06-23 22:40:31 +00:00
}
catch ( err ) {
2023-12-01 00:25:43 +00:00
log . error ( err ) ;
2023-06-23 22:40:31 +00:00
return next ( err ) ;
}
}
else {
2023-12-01 00:25:43 +00:00
log . warn ( ` Dataset with hash ${ fileHash } already exists... ` ) ;
2023-06-24 00:22:05 +00:00
}
try {
await promises _1 . default . unlink ( req . file . path ) ;
}
catch ( err ) {
2023-12-01 00:25:43 +00:00
log . error ( err ) ;
2023-06-23 22:40:31 +00:00
}
try {
id = await add ( req . body . email , req . body . name , fileHash , req . body . model ) ;
}
catch ( err ) {
2023-12-01 00:25:43 +00:00
log . info ( err ) ;
2023-06-23 22:40:31 +00:00
return next ( ` Error adding training job ${ req . body . name } ` ) ;
}
res . send ( ` <html><body>Dataset for job ${ req . body . name } has been uploaded successfully. You will be emailed when your job has started and when it has completed training. <br /> Monitor job status here: <a href="/job/ ${ id } "> ${ id } </a></body></html> ` ) ;
} ) ;
2023-06-24 00:22:05 +00:00
app . post ( '/job/:id' , uploadOnnx . single ( 'model' ) , async ( req , res , next ) => {
let filePath ;
let meta = null ;
let id ;
req . setTimeout ( 0 ) ;
2023-06-30 14:46:15 +00:00
if ( typeof req . file === 'undefined' || req . file === null ) {
2023-12-01 00:25:43 +00:00
log . error ( 'No file in upload' ) ;
2023-11-29 17:47:20 +00:00
return next ( 'ERROR: Please model as zip file' ) ;
2023-06-24 00:22:05 +00:00
}
2023-06-30 14:50:29 +00:00
id = req . params . id ;
2023-11-29 17:47:20 +00:00
filePath = ( 0 , path _1 . join ) ( data , ` ${ id } .zip ` ) ;
2023-06-24 00:22:05 +00:00
if ( typeof req . body . meta !== 'undefined' ) {
meta = req . body . meta ;
}
try {
await promises _1 . default . copyFile ( req . file . path , filePath ) ;
2023-12-01 00:25:43 +00:00
log . info ( ` Saved model for job ${ id } ` ) ;
2023-06-24 00:22:05 +00:00
}
catch ( err ) {
2023-12-01 00:25:43 +00:00
log . error ( err ) ;
2023-06-24 00:22:05 +00:00
return next ( err ) ;
}
try {
await promises _1 . default . unlink ( req . file . path ) ;
}
catch ( err ) {
2023-12-01 00:25:43 +00:00
log . error ( err ) ;
2023-06-24 00:22:05 +00:00
}
try {
await complete ( id , meta ) ;
}
catch ( err ) {
2023-12-01 00:25:43 +00:00
log . error ( err ) ;
2023-06-24 00:22:05 +00:00
return next ( ` Error completing training job ${ id } ` ) ;
}
res . json ( { id } ) ;
} ) ;
2023-06-23 22:40:31 +00:00
app . get ( '/job/:id' , async ( req , res , next ) => {
let jobStatus ;
if ( typeof req . params . id === 'undefined' || req . params . id === null ) {
2023-12-01 00:25:43 +00:00
log . error ( ` No job id provided ` ) ;
2023-06-23 22:40:31 +00:00
return next ( 'Invalid request' ) ;
}
if ( req . params . id . length !== 36 ) {
2023-12-01 00:25:43 +00:00
log . error ( ` Job id ${ req . params . id } is invalid ` ) ;
2023-06-23 22:40:31 +00:00
return next ( 'Invalid job id' ) ;
}
try {
jobStatus = await status ( req . params . id ) ;
}
catch ( err ) {
2023-12-01 00:25:43 +00:00
log . error ( err ) ;
2023-06-23 22:40:31 +00:00
return next ( 'Error getting job status' ) ;
}
return res . send ( ` <html><body>Job: ${ req . params . id } <br /> Status: ${ jobStatus } </body></html> ` ) ;
} ) ;
app . get ( '/model/:id' , async ( req , res , next ) => {
let filePath ;
let fileExists = false ;
let id ;
let fileName ;
let fileStream ;
let mimeType ;
let stream ;
if ( typeof req . params . id === 'undefined' || req . params . id === null ) {
2023-12-01 00:25:43 +00:00
log . error ( ` No job id provided ` ) ;
2023-06-23 22:40:31 +00:00
return next ( 'Invalid request' ) ;
}
id = req . params . id ;
2023-11-29 17:47:20 +00:00
filePath = ( 0 , path _1 . join ) ( data , ` ${ id } .zip ` ) ;
2023-06-23 22:40:31 +00:00
try {
fileExists = await exists ( filePath ) ;
}
catch ( err ) {
2023-12-01 00:25:43 +00:00
log . error ( err ) ;
2023-06-23 22:40:31 +00:00
return next ( ` Error checking whether model for job ${ id } exists ` ) ;
}
if ( ! fileExists ) {
2023-12-01 00:25:43 +00:00
log . warn ( ` Model for job ${ id } does not exist ` ) ;
2023-06-23 22:40:31 +00:00
return next ( ` Model for job ${ id } does not exist ` ) ;
}
try {
fileName = await name ( id ) ;
}
catch ( err ) {
2023-12-01 00:25:43 +00:00
log . error ( err ) ;
2023-06-23 22:40:31 +00:00
return next ( ` Error getting job ${ id } ` ) ;
}
mimeType = ( 0 , mime _1 . getType ) ( filePath ) ;
2023-11-29 17:47:20 +00:00
res . setHeader ( 'Content-disposition' , ` attachment; filename= ${ fileName } .zip ` ) ;
2023-06-23 22:40:31 +00:00
res . setHeader ( 'Content-type' , mimeType ) ;
stream = ( 0 , fs _1 . createReadStream ) ( filePath ) ;
stream . pipe ( res ) ;
} ) ;
app . get ( '/dataset/:id' , async ( req , res , next ) => {
let filePath ;
let fileExists = false ;
let id ;
let datasetHash ;
let fileStream ;
let mimeType ;
let stream ;
if ( typeof req . params . id === 'undefined' || req . params . id === null ) {
2023-12-01 00:25:43 +00:00
log . error ( ` No dataset id provided ` ) ;
2023-06-23 22:40:31 +00:00
return next ( 'Invalid request' ) ;
}
id = req . params . id ;
try {
datasetHash = await dataset ( id ) ;
}
catch ( err ) {
2023-12-01 00:25:43 +00:00
log . error ( err ) ;
2023-06-23 22:40:31 +00:00
return next ( ` Error getting dataset for job ${ id } ` ) ;
}
filePath = ( 0 , path _1 . join ) ( data , ` ${ datasetHash } .zip ` ) ;
try {
fileExists = await exists ( filePath ) ;
}
catch ( err ) {
2023-12-01 00:25:43 +00:00
log . error ( err ) ;
2023-06-23 22:40:31 +00:00
return next ( ` Error checking whether dataset for job ${ id } exists ` ) ;
}
if ( ! fileExists ) {
2023-12-01 00:25:43 +00:00
log . warn ( ` Dataset for job ${ id } does not exist ` ) ;
2023-06-23 22:40:31 +00:00
return next ( ` Dataset for job ${ id } does not exist ` ) ;
}
mimeType = ( 0 , mime _1 . getType ) ( filePath ) ;
res . setHeader ( 'Content-disposition' , ` attachment; filename= ${ datasetHash } .zip ` ) ;
res . setHeader ( 'Content-type' , mimeType ) ;
stream = ( 0 , fs _1 . createReadStream ) ( filePath ) ;
stream . pipe ( res ) ;
} ) ;
app . get ( '/job' , async ( req , res , next ) => {
2023-06-24 00:22:05 +00:00
let jobArr ;
2023-06-23 22:40:31 +00:00
try {
2023-06-24 00:22:05 +00:00
jobArr = await job ( ) ;
2023-06-23 22:40:31 +00:00
}
catch ( err ) {
2023-12-01 00:25:43 +00:00
log . error ( err ) ;
2023-06-23 22:40:31 +00:00
return next ( 'Error getting job' ) ;
}
2023-06-24 00:22:05 +00:00
res . json ( jobArr ) ;
} ) ;
app . get ( '/jobs' , async ( req , res , next ) => {
let jobArr ;
try {
jobArr = await jobs ( ) ;
}
catch ( err ) {
2023-12-01 00:25:43 +00:00
log . error ( err ) ;
2023-06-24 00:22:05 +00:00
return next ( 'Error getting job' ) ;
}
res . json ( jobArr ) ;
} ) ;
app . post ( '/job/claim/:id' , async ( req , res , next ) => {
let id ;
let jobObj ;
let resObj = { } ;
if ( typeof req . params . id === 'undefined' || req . params . id === null ) {
2023-12-01 00:25:43 +00:00
log . error ( ` No dataset id provided ` ) ;
2023-06-24 00:22:05 +00:00
return next ( 'Invalid request' ) ;
}
id = req . params . id ;
try {
jobObj = await claim ( id ) ;
2023-12-01 00:25:43 +00:00
log . info ( ` Job ${ id } was claimed ` ) ;
2023-06-24 00:22:05 +00:00
}
catch ( err ) {
2023-12-01 00:25:43 +00:00
log . error ( err ) ;
2023-06-24 00:22:05 +00:00
return next ( 'Error claiming job' ) ;
}
resObj . id = id ;
resObj . path = ` /dataset/ ${ id } ` ;
resObj . dataset = jobObj . dataset ;
resObj . model = jobObj . model ;
resObj . name = jobObj . name ;
2023-06-30 15:08:21 +00:00
resObj . email = jobObj . email ;
2023-06-24 00:22:05 +00:00
res . json ( resObj ) ;
} ) ;
app . post ( '/job/fail/:id' , async ( req , res , next ) => {
let id ;
let meta = null ;
if ( typeof req . params . id === 'undefined' || req . params . id === null ) {
2023-12-01 00:25:43 +00:00
log . error ( ` No dataset id provided ` ) ;
2023-06-24 00:22:05 +00:00
return next ( 'Invalid request' ) ;
}
id = req . params . id ;
if ( typeof req . body . meta !== 'undefined' ) {
meta = req . body . meta ;
}
try {
await fail ( id , meta ) ;
2023-12-01 00:25:43 +00:00
log . info ( ` Job ${ id } failed ` ) ;
2023-06-24 00:22:05 +00:00
}
catch ( err ) {
2023-12-01 00:25:43 +00:00
log . error ( err ) ;
2023-06-24 00:22:05 +00:00
return next ( 'Error failing job' ) ;
}
res . json ( true ) ;
2023-06-23 22:40:31 +00:00
} ) ;
2023-12-14 15:29:19 +00:00
app . listen ( port , async ( ) => {
index = await createTemplate ( './views/index.hbs' ) ;
2023-12-01 00:25:43 +00:00
log . info ( ` yolo_web running on port ${ port } ` ) ;
2023-06-23 22:40:31 +00:00
} ) ;
//# sourceMappingURL=index.js.map