Make service-core librariable
This commit is contained in:
parent
a7c5cee7da
commit
e0413bbaa6
11 changed files with 117 additions and 66 deletions
|
@ -4,8 +4,6 @@
|
||||||
"description": "NodeJS Test Service",
|
"description": "NodeJS Test Service",
|
||||||
"port": 4270,
|
"port": 4270,
|
||||||
"managePort": 4269,
|
"managePort": 4269,
|
||||||
"hasManage": true,
|
|
||||||
"appRepository": "thething/sc-helloworld",
|
"appRepository": "thething/sc-helloworld",
|
||||||
"manageRepository": null,
|
"manageRepository": null
|
||||||
"useDev": true
|
|
||||||
}
|
}
|
|
@ -1,13 +1,13 @@
|
||||||
import fs from 'fs'
|
import fs from 'fs'
|
||||||
import { EventEmitter } from 'events'
|
import { EventEmitter } from 'events'
|
||||||
import { request } from './client.mjs'
|
import { request } from './client.mjs'
|
||||||
import { getPathFromRoot, getUrlFromRoot, runCommand } from './util.mjs'
|
|
||||||
|
|
||||||
const fsp = fs.promises
|
const fsp = fs.promises
|
||||||
|
|
||||||
export default class Core extends EventEmitter{
|
export default class Core extends EventEmitter{
|
||||||
constructor(config, db, log, closeCb) {
|
constructor(util, config, db, log, closeCb) {
|
||||||
super()
|
super()
|
||||||
|
this._util = util
|
||||||
this._config = config
|
this._config = config
|
||||||
this._db = db
|
this._db = db
|
||||||
this._log = log
|
this._log = log
|
||||||
|
@ -107,39 +107,39 @@ export default class Core extends EventEmitter{
|
||||||
}
|
}
|
||||||
|
|
||||||
async installVersion(name, active, version) {
|
async installVersion(name, active, version) {
|
||||||
if (fs.existsSync(getPathFromRoot(`./${name}/` + version.name))) {
|
if (fs.existsSync(this._util.getPathFromRoot(`./${name}/` + version.name))) {
|
||||||
await runCommand('rmdir', ['/S', '/Q', `"${getPathFromRoot(`./${name}/` + version.name)}"`])
|
await this._util.runCommand('rmdir', ['/S', '/Q', `"${this._util.getPathFromRoot(`./${name}/` + version.name)}"`])
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
await fsp.mkdir(getPathFromRoot(`./${name}/` + version.name))
|
await fsp.mkdir(this._util.getPathFromRoot(`./${name}/` + version.name))
|
||||||
} catch(err) {
|
} catch(err) {
|
||||||
if (err.code !== 'EEXIST') {
|
if (err.code !== 'EEXIST') {
|
||||||
throw err
|
throw err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// await fsp.mkdir(getPathFromRoot(`./${name}/` + version.name + '/node_modules'))
|
// await fsp.mkdir(this._util.getPathFromRoot(`./${name}/` + version.name + '/node_modules'))
|
||||||
this.logActive(name, active, `[Core] Downloading ${version.name} (${version.url}) to ${version.name + '/' + version.name + '.zip'}\n`)
|
this.logActive(name, active, `[Core] Downloading ${version.name} (${version.url}) to ${version.name + '/' + version.name + '.zip'}\n`)
|
||||||
let filePath = getPathFromRoot(`./${name}/` + version.name + '/' + version.name + '.zip')
|
let filePath = this._util.getPathFromRoot(`./${name}/` + version.name + '/' + version.name + '.zip')
|
||||||
await request(version.url, filePath)
|
await request(version.url, filePath)
|
||||||
this.logActive(name, active, `[Core] Downloading finished, starting extraction\n`)
|
this.logActive(name, active, `[Core] Downloading finished, starting extraction\n`)
|
||||||
await runCommand(
|
await this._util.runCommand(
|
||||||
'"C:\\Program Files\\7-Zip\\7z.exe"',
|
'"C:\\Program Files\\7-Zip\\7z.exe"',
|
||||||
['x', `"${filePath}"`],
|
['x', `"${filePath}"`],
|
||||||
getPathFromRoot(`./${name}/` + version.name + '/'),
|
this._util.getPathFromRoot(`./${name}/` + version.name + '/'),
|
||||||
this.logActive.bind(this, name, active)
|
this.logActive.bind(this, name, active)
|
||||||
)
|
)
|
||||||
|
|
||||||
if (!fs.existsSync(getPathFromRoot(`./${name}/` + version.name + '/index.mjs'))) {
|
if (!fs.existsSync(this._util.getPathFromRoot(`./${name}/` + version.name + '/index.mjs'))) {
|
||||||
this.logActive(name, active, `\n[Core] ERROR: Missing index.mjs in the folder, exiting\n`)
|
this.logActive(name, active, `\n[Core] ERROR: Missing index.mjs in the folder, exiting\n`)
|
||||||
throw new Error(`Missing index.mjs in ${getPathFromRoot(`./${name}/` + version.name + '/index.mjs')}`)
|
throw new Error(`Missing index.mjs in ${this._util.getPathFromRoot(`./${name}/` + version.name + '/index.mjs')}`)
|
||||||
}
|
}
|
||||||
|
|
||||||
this.logActive(name, active, `\n[Core] Starting npm install\n`)
|
this.logActive(name, active, `\n[Core] Starting npm install\n`)
|
||||||
|
|
||||||
await runCommand(
|
await this._util.runCommand(
|
||||||
'npm.cmd',
|
'npm.cmd',
|
||||||
['install', '--production', '--no-optional', '--no-package-lock', '--no-audit'],
|
['install', '--production', '--no-optional', '--no-package-lock', '--no-audit'],
|
||||||
getPathFromRoot(`./${name}/` + version.name + '/'),
|
this._util.getPathFromRoot(`./${name}/` + version.name + '/'),
|
||||||
this.logActive.bind(this, name, active)
|
this.logActive.bind(this, name, active)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -188,7 +188,7 @@ export default class Core extends EventEmitter{
|
||||||
async tryStartProgram(name, active, version) {
|
async tryStartProgram(name, active, version) {
|
||||||
if (!version) return false
|
if (!version) return false
|
||||||
this.logActive(name, active, `[${name}] Attempting to start ${version}\n`)
|
this.logActive(name, active, `[${name}] Attempting to start ${version}\n`)
|
||||||
let indexPath = getUrlFromRoot(`./${name}/` + version + '/index.mjs')
|
let indexPath = this._util.getUrlFromRoot(`./${name}/` + version + '/index.mjs')
|
||||||
let module
|
let module
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
|
@ -131,9 +131,9 @@ const lodashId = {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const adapter = new FileAsync('db.json')
|
export default function GetDB(util, log) {
|
||||||
|
const adapter = new FileAsync(util.getPathFromRoot('./db.json'))
|
||||||
|
|
||||||
export default function GetDB(log) {
|
|
||||||
return lowdb(adapter)
|
return lowdb(adapter)
|
||||||
.then(function(db) {
|
.then(function(db) {
|
||||||
db._.mixin(lodashId)
|
db._.mixin(lodashId)
|
|
@ -1,6 +1,5 @@
|
||||||
import nodewindows from 'node-windows'
|
import nodewindows from 'node-windows'
|
||||||
import bunyan from 'bunyan-lite'
|
import bunyan from 'bunyan-lite'
|
||||||
import lowdb from './db.mjs'
|
|
||||||
|
|
||||||
export default function getLog(name) {
|
export default function getLog(name) {
|
||||||
let settings
|
let settings
|
|
@ -2,16 +2,21 @@ import path from 'path'
|
||||||
import { spawn } from 'child_process'
|
import { spawn } from 'child_process'
|
||||||
import { fileURLToPath, pathToFileURL } from 'url'
|
import { fileURLToPath, pathToFileURL } from 'url'
|
||||||
|
|
||||||
export function getPathFromRoot(add) {
|
export default class Util {
|
||||||
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
constructor(root_import_meta_url) {
|
||||||
return path.join(__dirname,'../', add)
|
this._root_import_meta_url = root_import_meta_url
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getUrlFromRoot(add) {
|
getPathFromRoot(add) {
|
||||||
return path.join(import.meta.url,'../../', add)
|
const __dirname = path.dirname(fileURLToPath(this._root_import_meta_url));
|
||||||
|
return path.join(__dirname,'./', add)
|
||||||
}
|
}
|
||||||
|
|
||||||
export function runCommand(command, options = [], folder = null, stream = function() {}) {
|
getUrlFromRoot(add) {
|
||||||
|
return path.join(this._root_import_meta_url,'../', add)
|
||||||
|
}
|
||||||
|
|
||||||
|
runCommand(command, options = [], folder = null, stream = function() {}) {
|
||||||
return new Promise(function(res, rej) {
|
return new Promise(function(res, rej) {
|
||||||
stream(`[Command] ${folder ? folder : ''}${command} ${options.join(' ')}\n`)
|
stream(`[Command] ${folder ? folder : ''}${command} ${options.join(' ')}\n`)
|
||||||
let processor = spawn(command, options, {
|
let processor = spawn(command, options, {
|
||||||
|
@ -40,3 +45,4 @@ export function runCommand(command, options = [], folder = null, stream = functi
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1 +0,0 @@
|
||||||
@ECHO off
|
|
|
@ -1,5 +0,0 @@
|
||||||
export function start(config, db, log, core) {
|
|
||||||
return import('./api/server.mjs').then(function(module) {
|
|
||||||
return module.run(config, db, log, core)
|
|
||||||
})
|
|
||||||
}
|
|
47
lib.mjs
Normal file
47
lib.mjs
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
import Util from './core/util.mjs'
|
||||||
|
import { readFileSync } from 'fs'
|
||||||
|
import { getLog } from './core/log.mjs'
|
||||||
|
import lowdb from './core/db.mjs'
|
||||||
|
|
||||||
|
export default class ServiceCore {
|
||||||
|
constructor(name, root_import_meta_url) {
|
||||||
|
if (!root_import_meta_url) {
|
||||||
|
throw new Error('ServiceCore must be called with the full string from "import.meta.url" from a file residing in the root directory')
|
||||||
|
}
|
||||||
|
this._root_import_meta_url = root_import_meta_url
|
||||||
|
this.util = new Util(this._root_import_meta_url)
|
||||||
|
this.log = getLog(name)
|
||||||
|
this.db = null
|
||||||
|
this.config = null
|
||||||
|
this.core = null
|
||||||
|
}
|
||||||
|
|
||||||
|
close(err) {
|
||||||
|
if (err) {
|
||||||
|
log.fatal(err, 'App recorded a fatal error')
|
||||||
|
process.exit(4)
|
||||||
|
}
|
||||||
|
log.warn('App asked to be restarted')
|
||||||
|
process.exit(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
async init() {
|
||||||
|
try {
|
||||||
|
this.config = JSON.parse(readFileSync(this.util.getPathFromRoot('./config.json')))
|
||||||
|
} catch (err) {
|
||||||
|
throw new Error('Unable to read config.json from root directory: ' + err)
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
this.db = await lowdb(this.util, this.log)
|
||||||
|
} catch (err) {
|
||||||
|
throw new Error('Unable to read initialise lowdb: ' + err)
|
||||||
|
}
|
||||||
|
|
||||||
|
this.core = new Core(this.util, this.config, this.db, this.log, (err) => this.close(err))
|
||||||
|
}
|
||||||
|
|
||||||
|
async startModule(module) {
|
||||||
|
return module.start(config, db, log, core)
|
||||||
|
}
|
||||||
|
}
|
|
@ -2,7 +2,7 @@
|
||||||
"name": "service-core",
|
"name": "service-core",
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"description": "Core boiler plate code to install node server as windows service",
|
"description": "Core boiler plate code to install node server as windows service",
|
||||||
"main": "index.js",
|
"main": "lib.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "nodemon --watch dev/api --watch core --watch runner.mjs --watch db.mjs --watch log.mjs runner.mjs | bunyan",
|
"dev": "nodemon --watch dev/api --watch core --watch runner.mjs --watch db.mjs --watch log.mjs runner.mjs | bunyan",
|
||||||
"test": "echo \"Error: no test specified\" && exit 1"
|
"test": "echo \"Error: no test specified\" && exit 1"
|
||||||
|
|
11
runner.mjs
11
runner.mjs
|
@ -1,7 +1,8 @@
|
||||||
import { readFileSync } from 'fs'
|
import { readFileSync } from 'fs'
|
||||||
import getLog from './log.mjs'
|
import getLog from './core/log.mjs'
|
||||||
import lowdb from './db.mjs'
|
import lowdb from './core/db.mjs'
|
||||||
import Core from './core/core.mjs'
|
import Core from './core/core.mjs'
|
||||||
|
import Util from './core/util.mjs'
|
||||||
|
|
||||||
let config
|
let config
|
||||||
|
|
||||||
|
@ -32,8 +33,10 @@ const close = function(err) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
lowdb(log).then(function(db) {
|
const util = new Util(import.meta.url)
|
||||||
let core = new Core(config, db, log, close)
|
|
||||||
|
lowdb(util, log).then(function(db) {
|
||||||
|
let core = new Core(util, config, db, log, close)
|
||||||
|
|
||||||
if (config.useDev) {
|
if (config.useDev) {
|
||||||
return import('./dev/index.mjs').then(function(module) {
|
return import('./dev/index.mjs').then(function(module) {
|
||||||
|
|
|
@ -1,8 +1,12 @@
|
||||||
import path from 'path'
|
import path from 'path'
|
||||||
import { readFileSync } from 'fs'
|
import { readFileSync } from 'fs'
|
||||||
import { getPathFromRoot } from '../core/util.mjs'
|
|
||||||
import nodewindows from 'node-windows'
|
import nodewindows from 'node-windows'
|
||||||
|
|
||||||
|
function getPathFromRoot(add) {
|
||||||
|
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
||||||
|
return path.join(__dirname,'../', add)
|
||||||
|
}
|
||||||
|
|
||||||
let config = JSON.parse(readFileSync(getPathFromRoot('./config.json')))
|
let config = JSON.parse(readFileSync(getPathFromRoot('./config.json')))
|
||||||
|
|
||||||
const Service = nodewindows.Service
|
const Service = nodewindows.Service
|
||||||
|
|
Loading…
Reference in a new issue