@webos-tools/cli
Version:
Command Line Interface for development webOS application and service
291 lines (257 loc) • 10.7 kB
JavaScript
/*
* Copyright (c) 2020-2024 LG Electronics Inc.
*
* SPDX-License-Identifier: Apache-2.0
*/
const fs = require('fs'),
Validator = require('jsonschema').Validator,
mkdirp = require('mkdirp'),
log = require('npmlog'),
path = require('path'),
shelljs = require('shelljs'),
errHndl = require('./error-handler.js'),
clone = require('./../util/objclone').deepCopy;
const Cli = (function() {
let instance;
function finish(err, returnValue, next) {
if (next && typeof next === 'function') {
if (!returnValue) {
return setImmediate(next, err);
}
return setImmediate(next, err, returnValue);
}
return err || returnValue;
}
function init() {
const
workParentDir = path.resolve(process.env.APPDATA || process.env.HOME || process.env.USERPROFILE),
builtinFiles = {
"config": {
"dir": path.join(__dirname, "../../files", "conf"),
"file": "config.json"
},
"commands": {
"dir": path.join(__dirname, "../../files", "conf"),
"file": "command-service.json"
},
"deviceList": {
"dir": path.join(__dirname, "../../files", "conf"),
"file": "novacom-devices.json"
},
"deviceListSchema": {
"dir": path.join(__dirname, "../../files", "schema"),
"file": "NovacomDevices.schema"
},
"template": {
"dir": path.join(__dirname, "../../files", "conf"),
"file": "template.json"
},
"env": {
"dir": path.join(__dirname, "../../files", "conf"),
"file": "sdk.json"
}
},
queryPath = path.join(__dirname, "../../files/conf/query");
function _store(store, n, file) {
store[n] = JSON.parse(fs.readFileSync(file));
store[n + 'File'] = file;
}
for (const key in builtinFiles) {
const filePath = path.join(builtinFiles[key].dir, builtinFiles[key].file);
_store(this, key, filePath);
}
const
workDir = (this.config.dataDir) ? path.join(workParentDir, this.config.dataDir) : path.join(workParentDir, '.webos'),
builtinDeviceListFile = path.join(builtinFiles.deviceList.dir, builtinFiles.deviceList.file),
userDeviceListFile = path.join(workDir, builtinFiles.deviceList.file);
if (!fs.existsSync(workDir)) {
mkdirp.sync(workDir);
}
try {
const userDeviceList = JSON.parse(fs.readFileSync(userDeviceListFile)),
result = validateDevice(this.deviceListSchema, userDeviceList);
if (result && result.resultValue) {
this.deviceList = userDeviceList;
} else {
log.verbose("cli-appdata#init()", "schema check failure:", userDeviceListFile);
log.verbose("cli-appdata#init()", "result:", result);
log.verbose("cli-appdata#init()", "copy " + builtinDeviceListFile + " to " + userDeviceListFile);
shelljs.cp('-f', builtinDeviceListFile, userDeviceListFile);
}
} catch (err) {
log.verbose("cli-appdata#init()", "err:", err);
log.verbose("cli-appdata#init()", "copy " + builtinDeviceListFile + " to " + userDeviceListFile);
shelljs.cp('-f', builtinDeviceListFile, userDeviceListFile);
}
this.builtinDeviceListFile = builtinDeviceListFile;
this.deviceListFile = userDeviceListFile;
this.workDir = workDir;
this.queryPath = queryPath;
if (this.config.simulatorConfig) {
this.simulatorConfigPath = path.join(workDir, this.config.simulatorConfig);
}
return true;
}
function validateDevice(schema, data) {
let result = {
resultValue: false,
err: null
};
const schemaArray = {
"id": "test",
"type": "array",
"items": {
"$ref": "/deviceSchema"
}
};
const v = new Validator();
try {
v.addSchema(schema, "/deviceSchema");
result = v.validate(data, schemaArray);
if (result && result.errors.length > 0) {
let errMsg = "Invalid device info.";
for (const idx in result.errors) {
errMsg = errMsg.concat("\n");
let res,
errMsgLine = result.errors[idx].property + " " + result.errors[idx].message;
const regex = /instance\[*.*\]*\./g;
if ((res = regex.exec(errMsgLine)) !== null) {
errMsgLine = errMsgLine.substring(res[0].length);
}
errMsg = errMsg.concat(errMsgLine);
}
result.err = new Error(errMsg);
} else {
result.resultValue = true;
}
} catch (err) {
// ignore exception
result.err = err;
}
return result;
}
function CliAppData() {
if (instance) {
return instance;
}
instance = this;
if (!this.inialized) {
this.inialized = init.call(this);
}
}
CliAppData.prototype = {
getSimulatorConfigPath: function(next) {
return finish(null, this.simulatorConfigPath, next);
},
getPath: function(next) {
return finish(null, this.workDir, next);
},
getAppDir: function(next) {
return finish(null, path.join(__dirname, '..'), next);
},
getConfig: function(next) {
return finish(null, clone(this.config), next);
},
compareProfile: function(query, next) {
next(null, query.toLowerCase() === this.config.profile.toLowerCase());
},
compareProfileSync: function(query) {
return query.toLowerCase() === this.config.profile.toLowerCase();
},
getDeviceList: function(renewal, next) {
return finish(null, clone(this.deviceList), next);
},
getCommandService: function(next) {
return finish(null, clone(this.commands), next);
},
setDeviceList: function(deviceListData, next) {
log.info("cli-appdata#CliAppData#setDeviceList()");
try {
const result = validateDevice(this.deviceListSchema, deviceListData);
if (result && !result.resultValue) {
const err = result.err || "invalid data";
return finish(err, this.deviceList, next);
}
this.deviceList = deviceListData;
fs.writeFileSync(this.deviceListFile, JSON.stringify(this.deviceList, null, Number(4)));
} catch (err) {
return finish(err, this.deviceList, next);
}
return finish(null, this.deviceList, next);
},
setConfig: function(configData, next) {
try {
this.config = configData;
fs.writeFileSync(this.configFile, JSON.stringify(this.config, null, Number(4)) + "\n");
} catch (err) {
return finish(err, this.config, next);
}
return finish(null, this.config, next);
},
setTemplate: function(templateData, next) {
try {
this.template = templateData;
fs.writeFileSync(this.templateFile, JSON.stringify(this.template, null, Number(4)) + "\n");
} catch (err) {
return finish(err, this.template, next);
}
},
setEnv: function(envData, next) {
try {
this.env = envData;
fs.writeFileSync(this.envFile, JSON.stringify(this.env, null, Number(4)) + "\n");
} catch (err) {
return finish(err, this.env, next);
}
},
setKey: function(keyPath, next) {
try {
const dstPubkey = path.join(__dirname, "../../files/conf", "pubkey.pem");
if (fs.existsSync(dstPubkey)) {
shelljs.rm(dstPubkey);
}
if (keyPath) {
shelljs.cp(keyPath, dstPubkey);
}
} catch (err) {
return finish(errHndl.getErrMsg(err), keyPath, next);
}
return finish(null, keyPath, next);
},
setQuery: function(queryBasePath, next) {
try {
if (fs.existsSync(this.queryPath)) {
shelljs.ls(this.queryPath).forEach(function(file) {
shelljs.rm(path.join(__dirname, "../../files/conf/query",file));
});
} else {
fs.mkdirSync(this.queryPath);
}
shelljs.ls(queryBasePath+'/*.json').forEach(function(file) {
shelljs.cp(file, path.join(__dirname, "../../files/conf", "query"));
});
} catch (err) {
return finish(err, this.queryPath, next);
}
return finish(null, this.queryPath, next);
},
resetDeviceList: function(next) {
log.info("cli-appdata#CliAppData#resetDeviceList()");
try {
if (fs.existsSync(this.deviceListFile)) {
shelljs.rm(this.deviceListFile);
}
shelljs.cp(this.builtinDeviceListFile, this.deviceListFile);
this.deviceList = JSON.parse(fs.readFileSync(this.deviceListFile));
} catch (err) {
log.verbose("cli-appdata#CliAppData#resetDeviceList()", "err:", err);
return finish(err, clone(this.deviceList), next);
}
return finish(null, clone(this.deviceList), next);
}
};
return CliAppData;
}());
if (typeof module !== 'undefined' && module.exports) {
module.exports = Cli;
}