From e0413bbaa69e73495a692873c214d931b16807a7 Mon Sep 17 00:00:00 2001 From: Jonatan Nilsson Date: Tue, 8 Sep 2020 08:11:42 +0000 Subject: [PATCH] Make service-core librariable --- config.json | 4 +-- core/core.mjs | 28 ++++++++-------- db.mjs => core/db.mjs | 4 +-- log.mjs => core/log.mjs | 1 - core/util.mjs | 74 ++++++++++++++++++++++------------------- dev/build.bat | 1 - index.mjs | 5 --- lib.mjs | 47 ++++++++++++++++++++++++++ package.json | 2 +- runner.mjs | 11 +++--- service/service.mjs | 6 +++- 11 files changed, 117 insertions(+), 66 deletions(-) rename db.mjs => core/db.mjs (97%) rename log.mjs => core/log.mjs (98%) delete mode 100644 dev/build.bat delete mode 100644 index.mjs create mode 100644 lib.mjs diff --git a/config.json b/config.json index 4b0ca1f..9a09038 100644 --- a/config.json +++ b/config.json @@ -4,8 +4,6 @@ "description": "NodeJS Test Service", "port": 4270, "managePort": 4269, - "hasManage": true, "appRepository": "thething/sc-helloworld", - "manageRepository": null, - "useDev": true + "manageRepository": null } \ No newline at end of file diff --git a/core/core.mjs b/core/core.mjs index ed0894c..3eaa36a 100644 --- a/core/core.mjs +++ b/core/core.mjs @@ -1,13 +1,13 @@ import fs from 'fs' import { EventEmitter } from 'events' import { request } from './client.mjs' -import { getPathFromRoot, getUrlFromRoot, runCommand } from './util.mjs' const fsp = fs.promises export default class Core extends EventEmitter{ - constructor(config, db, log, closeCb) { + constructor(util, config, db, log, closeCb) { super() + this._util = util this._config = config this._db = db this._log = log @@ -107,39 +107,39 @@ export default class Core extends EventEmitter{ } async installVersion(name, active, version) { - if (fs.existsSync(getPathFromRoot(`./${name}/` + version.name))) { - await runCommand('rmdir', ['/S', '/Q', `"${getPathFromRoot(`./${name}/` + version.name)}"`]) + if (fs.existsSync(this._util.getPathFromRoot(`./${name}/` + version.name))) { + await this._util.runCommand('rmdir', ['/S', '/Q', `"${this._util.getPathFromRoot(`./${name}/` + version.name)}"`]) } try { - await fsp.mkdir(getPathFromRoot(`./${name}/` + version.name)) + await fsp.mkdir(this._util.getPathFromRoot(`./${name}/` + version.name)) } catch(err) { if (err.code !== 'EEXIST') { 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`) - 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) this.logActive(name, active, `[Core] Downloading finished, starting extraction\n`) - await runCommand( + await this._util.runCommand( '"C:\\Program Files\\7-Zip\\7z.exe"', ['x', `"${filePath}"`], - getPathFromRoot(`./${name}/` + version.name + '/'), + this._util.getPathFromRoot(`./${name}/` + version.name + '/'), 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`) - 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`) - await runCommand( + await this._util.runCommand( 'npm.cmd', ['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) ) @@ -188,7 +188,7 @@ export default class Core extends EventEmitter{ async tryStartProgram(name, active, version) { if (!version) return false 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 try { diff --git a/db.mjs b/core/db.mjs similarity index 97% rename from db.mjs rename to core/db.mjs index ae2b5db..14add32 100644 --- a/db.mjs +++ b/core/db.mjs @@ -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) .then(function(db) { db._.mixin(lodashId) diff --git a/log.mjs b/core/log.mjs similarity index 98% rename from log.mjs rename to core/log.mjs index 3a0b978..9e50523 100644 --- a/log.mjs +++ b/core/log.mjs @@ -1,6 +1,5 @@ import nodewindows from 'node-windows' import bunyan from 'bunyan-lite' -import lowdb from './db.mjs' export default function getLog(name) { let settings diff --git a/core/util.mjs b/core/util.mjs index 7c5ba3e..d0b1801 100644 --- a/core/util.mjs +++ b/core/util.mjs @@ -2,41 +2,47 @@ import path from 'path' import { spawn } from 'child_process' import { fileURLToPath, pathToFileURL } from 'url' -export function getPathFromRoot(add) { - const __dirname = path.dirname(fileURLToPath(import.meta.url)); - return path.join(__dirname,'../', add) -} +export default class Util { + constructor(root_import_meta_url) { + this._root_import_meta_url = root_import_meta_url + } -export function getUrlFromRoot(add) { - return path.join(import.meta.url,'../../', add) -} + getPathFromRoot(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() {}) { - return new Promise(function(res, rej) { - stream(`[Command] ${folder ? folder : ''}${command} ${options.join(' ')}\n`) - let processor = spawn(command, options, { - shell: true, - cwd: folder, + getUrlFromRoot(add) { + return path.join(this._root_import_meta_url,'../', add) + } + + runCommand(command, options = [], folder = null, stream = function() {}) { + return new Promise(function(res, rej) { + stream(`[Command] ${folder ? folder : ''}${command} ${options.join(' ')}\n`) + let processor = spawn(command, options, { + shell: true, + cwd: folder, + }) + let timeOuter = setTimeout(function() { + processor.stdin.write('n\n') + }, 250) + processor.stdout.on('data', function(data) { + stream(data.toString()) + }) + processor.stderr.on('data', function(data) { + stream(data.toString()) + }) + processor.on('error', function(err) { + clearInterval(timeOuter) + rej(err) + }) + processor.on('exit', function (code) { + clearInterval(timeOuter) + if (code !== 0) { + return rej(new Error('Program returned error code: ' + code)) + } + res(code) + }) }) - let timeOuter = setTimeout(function() { - processor.stdin.write('n\n') - }, 250) - processor.stdout.on('data', function(data) { - stream(data.toString()) - }) - processor.stderr.on('data', function(data) { - stream(data.toString()) - }) - processor.on('error', function(err) { - clearInterval(timeOuter) - rej(err) - }) - processor.on('exit', function (code) { - clearInterval(timeOuter) - if (code !== 0) { - return rej(new Error('Program returned error code: ' + code)) - } - res(code) - }) - }) + } } diff --git a/dev/build.bat b/dev/build.bat deleted file mode 100644 index 56eeb8a..0000000 --- a/dev/build.bat +++ /dev/null @@ -1 +0,0 @@ -@ECHO off diff --git a/index.mjs b/index.mjs deleted file mode 100644 index 9e27ec0..0000000 --- a/index.mjs +++ /dev/null @@ -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) - }) -} \ No newline at end of file diff --git a/lib.mjs b/lib.mjs new file mode 100644 index 0000000..582c943 --- /dev/null +++ b/lib.mjs @@ -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) + } +} diff --git a/package.json b/package.json index 1e8aaa4..e2eb67b 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "service-core", "version": "1.0.0", "description": "Core boiler plate code to install node server as windows service", - "main": "index.js", + "main": "lib.js", "scripts": { "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" diff --git a/runner.mjs b/runner.mjs index c5a8914..fbd5fb4 100644 --- a/runner.mjs +++ b/runner.mjs @@ -1,7 +1,8 @@ import { readFileSync } from 'fs' -import getLog from './log.mjs' -import lowdb from './db.mjs' +import getLog from './core/log.mjs' +import lowdb from './core/db.mjs' import Core from './core/core.mjs' +import Util from './core/util.mjs' let config @@ -32,8 +33,10 @@ const close = function(err) { }) } -lowdb(log).then(function(db) { - let core = new Core(config, db, log, close) +const util = new Util(import.meta.url) + +lowdb(util, log).then(function(db) { + let core = new Core(util, config, db, log, close) if (config.useDev) { return import('./dev/index.mjs').then(function(module) { diff --git a/service/service.mjs b/service/service.mjs index d445c68..cadd83c 100644 --- a/service/service.mjs +++ b/service/service.mjs @@ -1,8 +1,12 @@ import path from 'path' import { readFileSync } from 'fs' -import { getPathFromRoot } from '../core/util.mjs' 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'))) const Service = nodewindows.Service