@aiot-toolkit/shared-utils
Advanced tools
Comparing version 1.0.7-beta.2 to 1.0.7-beta.3
@@ -1,2 +0,325 @@ | ||
"use strict";var _fs=_interopRequireDefault(require("fs")),_path=_interopRequireDefault(require("path")),_index=require("../index"),_util=require("./util"),_eventBus=_interopRequireDefault(require("../../event-bus"));function _interopRequireDefault(e){return e&&e.__esModule?e:{default:e}}const{PACKAGER_BUILD_DONE:PACKAGER_BUILD_DONE}=_eventBus.default;function BuildModeManager(e){(0,_util.initProjectConfig)(e),this.setRoot(e)}BuildModeManager.prototype._read=function(){let e={};try{e=(0,_index.readJson)(this._configFile)}catch(e){console.log("ENOENT"===e.code?e.message:e)}e.modeOptions||(e.modeOptions={current:-1,list:[]});const t=e.modeOptions;return t.list=t.list.filter((e=>null!==e.id&&-1!==e.id)),e},BuildModeManager.prototype._write=function(e){const t=e.modeOptions;t.list=t.list.filter((e=>null!==e.id&&-1!==e.id)).reduce(((e,t)=>(e.find((e=>e.id===t.id))||e.push(t),e)),[]),this._configFile&&_fs.default.writeFileSync(this._configFile,JSON.stringify(e,null,2))},BuildModeManager.prototype.getConfig=function(){return this._read().modeOptions},BuildModeManager.prototype.getAllPages=function(){if(!this.root)return[];const e=_path.default.join(this.root,"src/manifest.json");try{const t=(0,_index.readJson)(e).router.pages||{};return Object.keys(t)}catch(e){return console.log("ENOENT"===e.code?e.message:e),[]}},BuildModeManager.prototype._addMode=function(e,t,i){const o=e.modeOptions;let n;return n=o.list.length?Math.max.apply(null,o.list.map((e=>e.id)))+1:0,t.id=n,o.list.push(t),o.current=t.id,i||this._write(e),o},BuildModeManager.prototype.addMode=function(e){const t=this._read();return this._addMode(t,e,!1)},BuildModeManager.prototype.addModes=function(e){const t=this._read();return e.forEach((e=>{this._addMode(t,e,!0)})),this._write(t),t.modeOptions},BuildModeManager.prototype.delete=function(e){const t=this._read(),i=t.modeOptions,o=i.list.findIndex((t=>t.id===e));return i.current=-1,-1!==o&&(i.list.splice(o,1),this._write(t)),i},BuildModeManager.prototype.update=function(e){const t=this._read(),i=t.modeOptions,o=i.list.findIndex((t=>t.id===e.id));return-1!==o&&(i.list[o]=e),this._write(t),i},BuildModeManager.prototype.select=function(e){const t=this._read(),i=t.modeOptions;return-1!==i.list.findIndex((t=>t.id===e))&&(i.current=e,this._write(t),_eventBus.default.emit(PACKAGER_BUILD_DONE)),i},BuildModeManager.prototype.setToNormal=function(){const e=this._read(),t=e.modeOptions;return t.current=-1,this._write(e),_eventBus.default.emit(PACKAGER_BUILD_DONE),t},BuildModeManager.prototype.setRoot=function(e){if("string"==typeof e){this.root=e,this._configFile=_path.default.resolve(e,_util.CONFIG_FILE);return this._read().modeOptions}return null},module.exports=BuildModeManager; | ||
"use strict"; | ||
var _fs = _interopRequireDefault(require("fs")); | ||
var _path = _interopRequireDefault(require("path")); | ||
var _index = require("../index"); | ||
var _util = require("./util"); | ||
var _eventBus = _interopRequireDefault(require("../../event-bus")); | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
/** | ||
* Copyright (C) 2017, hapjs.org. All rights reserved. | ||
*/ | ||
const { | ||
PACKAGER_BUILD_DONE | ||
} = _eventBus.default; | ||
/** | ||
* 编译模式管理器 | ||
* @constructor | ||
* @example | ||
* const { BuildModeManager } = require('@aiot-toolkit/shared-utils/lib/BuildModeManager') | ||
* const bmm = new BuildModeManager(root) | ||
* const modeOptions = bmm.getConfig() // {current: 0, list: [{}]} | ||
* bmm.addMode({name, pathName, query, scene}) // {current: 1, list: [{name, pathName, query, scene}]} | ||
* bmm.update({id: 1, name, pathName, query, scene}) // 更新 id=1 的编译模式 | ||
* bmm.delete(1) // 删除 id=1 的编译模式 | ||
* | ||
* @param {String} [root] - 项目根目录。可通过 {@link BuildModeManager#setRoot} 重设 | ||
*/ | ||
function BuildModeManager(root) { | ||
(0, _util.initProjectConfig)(root); | ||
this.setRoot(root); | ||
} | ||
/** | ||
* 读取配置 | ||
* @private | ||
* @returns {ProjectConfig} | ||
*/ | ||
BuildModeManager.prototype._read = function () { | ||
let config = {}; | ||
try { | ||
config = (0, _index.readJson)(this._configFile); | ||
} catch (err) { | ||
console.log(err.code === 'ENOENT' ? err.message : err); // ignore | ||
} | ||
if (!config.modeOptions) { | ||
config.modeOptions = { | ||
current: -1, | ||
list: [] | ||
}; | ||
} | ||
const modeOptions = config.modeOptions; | ||
modeOptions.list = modeOptions.list.filter(m => m.id !== null && m.id !== -1); | ||
return config; | ||
}; | ||
/** | ||
* 写入文件,会移除无效 id 和 重复 id | ||
* | ||
* @private | ||
* @param {Object} config - 项目配置参数 | ||
*/ | ||
BuildModeManager.prototype._write = function (config) { | ||
const modeOptions = config.modeOptions; // -1 为“普通模式” | ||
modeOptions.list = modeOptions.list.filter(m => m.id !== null && m.id !== -1).reduce((modes, mode) => { | ||
if (!modes.find(m => m.id === mode.id)) { | ||
modes.push(mode); | ||
} | ||
return modes; | ||
}, []); | ||
if (this._configFile) { | ||
_fs.default.writeFileSync(this._configFile, JSON.stringify(config, null, 2)); | ||
} | ||
}; | ||
/** | ||
* 获取编译模式配置 | ||
* | ||
* @returns {BuildModeOptions} 当前编译模式配置 | ||
*/ | ||
BuildModeManager.prototype.getConfig = function () { | ||
const config = this._read(); | ||
return config.modeOptions; | ||
}; | ||
/** | ||
* 获取应用的所有页面 | ||
* | ||
* @returns {Array<String>} | ||
*/ | ||
BuildModeManager.prototype.getAllPages = function () { | ||
if (!this.root) { | ||
return []; | ||
} | ||
const manifestPath = _path.default.join(this.root, 'src/manifest.json'); | ||
try { | ||
const manifest = (0, _index.readJson)(manifestPath); | ||
const routerPages = manifest.router.pages || {}; | ||
const pages = Object.keys(routerPages); | ||
return pages; | ||
} catch (err) { | ||
console.log(err.code === 'ENOENT' ? err.message : err); | ||
return []; | ||
} | ||
}; | ||
/** | ||
* 添加编译模式 | ||
* | ||
* @private | ||
* @param {Object} config - 项目配置信息 | ||
* @param {Object} mode - 自定义编译模式条件参数 | ||
* @param {String} mode.name - 名称 | ||
* @param {String} mode.pathName - 启动页面 | ||
* @param {String} [mode.query] - 启动参数 | ||
* @param {String|null} [mode.scene] - 场景值 | ||
* @returns {BuildModeOptions} 当前编译模式配置 | ||
*/ | ||
BuildModeManager.prototype._addMode = function (config, mode, lazy) { | ||
const modeOptions = config.modeOptions; | ||
let nextId; | ||
if (modeOptions.list.length) { | ||
nextId = Math.max.apply(null, modeOptions.list.map(m => m.id)) + 1; | ||
} else { | ||
nextId = 0; | ||
} | ||
mode.id = nextId; | ||
modeOptions.list.push(mode); | ||
modeOptions.current = mode.id; | ||
if (!lazy) { | ||
this._write(config); | ||
} | ||
return modeOptions; | ||
}; | ||
/** | ||
* 添加编译模式 | ||
* | ||
* @param {Object} mode - 自定义编译模式条件参数 | ||
* @param {String} mode.name - 名称 | ||
* @param {String} mode.pathName - 启动页面 | ||
* @param {String} [mode.query] - 启动参数 | ||
* @param {String|null} [mode.scene] - 场景值 | ||
* @returns {BuildModeOptions} 当前编译模式配置 | ||
*/ | ||
BuildModeManager.prototype.addMode = function (mode) { | ||
const config = this._read(); | ||
return this._addMode(config, mode, false); | ||
}; | ||
/** | ||
* 添加多个编译模式 | ||
* | ||
* @param {Array<Object>} modes - 待添加的编译模式列表 | ||
* @param {String} modes[].name - 名称 | ||
* @param {String} modes[].pathName - 启动页面 | ||
* @param {String} [modes[].query] - 启动参数 | ||
* @param {String|null} [modes[].scene] - 场景值 | ||
* @returns {BuildModeOptions} 当前编译模式配置 | ||
*/ | ||
BuildModeManager.prototype.addModes = function (modes) { | ||
const config = this._read(); | ||
modes.forEach(mode => { | ||
this._addMode(config, mode, true); | ||
}); | ||
this._write(config); | ||
return config.modeOptions; | ||
}; | ||
/** | ||
* 删除 id={id} 的编译模式 | ||
* | ||
* @param {Number} id - 编译模式 id | ||
* @returns {BuildModeOptions} 当前编译模式配置 | ||
*/ | ||
BuildModeManager.prototype.delete = function (id) { | ||
const config = this._read(); | ||
const modeOptions = config.modeOptions; | ||
const index = modeOptions.list.findIndex(m => m.id === id); | ||
modeOptions.current = -1; | ||
if (index !== -1) { | ||
modeOptions.list.splice(index, 1); | ||
this._write(config); | ||
} | ||
return modeOptions; | ||
}; | ||
/** | ||
* 更新编译模式 | ||
* | ||
* @param {Object} mode - 编译模式参数 | ||
* @param {Number} mode.id - 目标模式 id | ||
* @param {String} mode.name - 名称 | ||
* @param {String} mode.pathName - 启动页面 | ||
* @param {String} [mode.query] - 启动参数 | ||
* @param {String|null} [mode.scene] - 场景值 | ||
* @returns {BuildModeOptions} 当前编译模式配置 | ||
*/ | ||
BuildModeManager.prototype.update = function (mode) { | ||
const config = this._read(); | ||
const modeOptions = config.modeOptions; | ||
const index = modeOptions.list.findIndex(m => m.id === mode.id); | ||
if (index !== -1) { | ||
modeOptions.list[index] = mode; | ||
} | ||
this._write(config); | ||
return modeOptions; | ||
}; | ||
/** | ||
* 选择编译模式 | ||
* @param {Number} id - 目标编译模式 id | ||
* @returns {BuildModeOptions} 当前编译模式配置 | ||
*/ | ||
BuildModeManager.prototype.select = function (id) { | ||
const config = this._read(); | ||
const modeOptions = config.modeOptions; | ||
const index = modeOptions.list.findIndex(m => m.id === id); | ||
if (index !== -1) { | ||
modeOptions.current = id; | ||
this._write(config); | ||
_eventBus.default.emit(PACKAGER_BUILD_DONE); | ||
} | ||
return modeOptions; | ||
}; | ||
/** | ||
* 设置为普通编译模式 | ||
* @returns {BuildModeOptions} 当前编译模式配置 | ||
*/ | ||
BuildModeManager.prototype.setToNormal = function () { | ||
const config = this._read(); | ||
const modeOptions = config.modeOptions; | ||
modeOptions.current = -1; | ||
this._write(config); | ||
_eventBus.default.emit(PACKAGER_BUILD_DONE); | ||
return modeOptions; | ||
}; | ||
/** | ||
* 重新设置根目录,便于在多个项目间切换 | ||
* 主要用于内部开发 | ||
* | ||
* @param {String} [root] - 根目录 | ||
* @returns {BuildModeOptions|null} 当前编译模式配置 | ||
*/ | ||
BuildModeManager.prototype.setRoot = function (root) { | ||
if (typeof root === 'string') { | ||
this.root = root; | ||
this._configFile = _path.default.resolve(root, _util.CONFIG_FILE); | ||
const config = this._read(); | ||
return config.modeOptions; | ||
} | ||
return null; | ||
}; | ||
module.exports = BuildModeManager; | ||
/** | ||
* @typedef BuildModeOptions | ||
* @desc 编译模式配置信息 | ||
* @property {Number} current - 当前编译模式的 id, -1 表示默认`普通编译` | ||
* @property {Array<Object>} list - 编译模式列表 | ||
* @property {Number} list[].current - 编译模式 id | ||
* @property {String} list[].id - 编译模式 id | ||
* @property {String} list[].name - 编译模式名称 | ||
* @property {String} list[].pathName - 编译模式启动页面 | ||
* @property {String} list[].query - 编译模式启动参数 | ||
* @property {Number} list[].scene - 编译模式进入场景 | ||
*/ | ||
//# sourceMappingURL=BuildModeManager.js.map |
@@ -1,2 +0,95 @@ | ||
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.readJson=readJson,exports.initProjectConfig=initProjectConfig,exports.getLaunchPage=getLaunchPage,exports.CONFIG_FILE=void 0;var _fs=_interopRequireDefault(require("fs")),_path=_interopRequireDefault(require("path")),_config=_interopRequireDefault(require("../../config"));function _interopRequireDefault(e){return e&&e.__esModule?e:{default:e}}const CONFIG_FILE=".quickapp.preview.json";function readJson(e){try{return JSON.parse(_fs.default.readFileSync(e).toString())}catch(t){throw t instanceof SyntaxError?new SyntaxError(`Failed to parse ${e}, format error`):t.message.startsWith("ENOENT:")?(t.message=`Failed to read ${e}, the file cannot be found`,t):(console.error("Failed to read %s",e),t)}}function initProjectConfig(e){const t=_path.default.join(e,CONFIG_FILE);_fs.default.existsSync(t)||_fs.default.writeFileSync(t,JSON.stringify({},null,2))}function getLaunchPage(){let e="";const t=_path.default.join(_config.default.projectPath,CONFIG_FILE);if(_fs.default.existsSync(t))try{const{modeOptions:r}=readJson(t);if(r&&"number"==typeof r.current&&r.list){const t=r.list.find((e=>e.id===r.current));t&&(e=`${t.pathName}?${t.query}`)}}catch(e){console.log("ENOENT"===e.code?e.message:e)}return e}exports.CONFIG_FILE=CONFIG_FILE; | ||
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { | ||
value: true | ||
}); | ||
exports.readJson = readJson; | ||
exports.initProjectConfig = initProjectConfig; | ||
exports.getLaunchPage = getLaunchPage; | ||
exports.CONFIG_FILE = void 0; | ||
var _fs = _interopRequireDefault(require("fs")); | ||
var _path = _interopRequireDefault(require("path")); | ||
var _config = _interopRequireDefault(require("../../config")); | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
/** | ||
* Copyright (C) 2017, hapjs.org. All rights reserved. | ||
*/ | ||
const CONFIG_FILE = '.quickapp.preview.json'; | ||
/** | ||
* 读取一份 json 内容 | ||
* | ||
* @param {String} jsonpath - json 路径 | ||
* @returns {Object} json | ||
*/ | ||
exports.CONFIG_FILE = CONFIG_FILE; | ||
function readJson(jsonpath) { | ||
try { | ||
return JSON.parse(_fs.default.readFileSync(jsonpath).toString()); | ||
} catch (err) { | ||
if (err instanceof SyntaxError) { | ||
throw new SyntaxError(`Failed to parse ${jsonpath}, format error`); | ||
} else if (err.message.startsWith('ENOENT:')) { | ||
err.message = `Failed to read ${jsonpath}, the file cannot be found`; | ||
throw err; | ||
} else { | ||
console.error('Failed to read %s', jsonpath); | ||
throw err; | ||
} | ||
} | ||
} | ||
/** | ||
* 检测项目下 .quickapp.preview.json 文件(当前用于记录编译模式),无则新建 | ||
* | ||
* @param {String} root - 项目路径 | ||
*/ | ||
function initProjectConfig(root) { | ||
const proConfPath = _path.default.join(root, CONFIG_FILE); | ||
if (!_fs.default.existsSync(proConfPath)) { | ||
_fs.default.writeFileSync(proConfPath, JSON.stringify({}, null, 2)); | ||
} | ||
} | ||
/** | ||
* 获取当前编译模式的启动页面(带参数) | ||
* | ||
* @returns {String} page - 启动页面 | ||
*/ | ||
function getLaunchPage() { | ||
let page = ''; | ||
const proConfPath = _path.default.join(_config.default.projectPath, CONFIG_FILE); | ||
if (_fs.default.existsSync(proConfPath)) { | ||
try { | ||
const { | ||
modeOptions | ||
} = readJson(proConfPath); | ||
if (modeOptions && typeof modeOptions.current === 'number' && modeOptions.list) { | ||
const mode = modeOptions.list.find(item => { | ||
return item.id === modeOptions.current; | ||
}); | ||
if (mode) { | ||
page = `${mode.pathName}?${mode.query}`; | ||
} | ||
} | ||
} catch (err) { | ||
console.log(err.code === 'ENOENT' ? err.message : err); // ignore | ||
} | ||
} | ||
return page; | ||
} | ||
//# sourceMappingURL=util.js.map |
469
lib/index.js
@@ -1,2 +0,469 @@ | ||
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.logWarn=logWarn,exports.mkdirsSync=mkdirsSync,exports.getIPv4IPAddress=getIPv4IPAddress,exports.getServerIPAndPort=getServerIPAndPort,exports.getDefaultServerHost=getDefaultServerHost,exports.getClientIPAddress=getClientIPAddress,exports.stripPrefixForIPV4MappedIPV6Address=stripPrefixForIPV4MappedIPV6Address,exports.outputQRCodeOnTerminal=outputQRCodeOnTerminal,exports.relateCwd=relateCwd,exports.equals=equals,exports.extend=extend,exports.renderString=renderString,exports.KnownError=KnownError,exports.setCustomConfig=setCustomConfig,exports.getProjectDslName=getProjectDslName,exports.getDeviceInfo=getDeviceInfo,exports.readJson=readJson,Object.defineProperty(exports,"getLaunchPage",{enumerable:!0,get:function(){return _util.getLaunchPage}}),exports.colorconsole=exports.logger=void 0;var _os=_interopRequireDefault(require("os")),_fs=_interopRequireDefault(require("fs")),_path=_interopRequireDefault(require("path")),_http=_interopRequireDefault(require("http")),_console=require("console"),_chalk=_interopRequireDefault(require("chalk")),_qrcodeTerminal=_interopRequireDefault(require("qrcode-terminal")),_config=_interopRequireDefault(require("../config")),_util=require("./buildMode/util");function _interopRequireDefault(e){return e&&e.__esModule?e:{default:e}}const logLevelMap={};function prependLevel(e,r){if(!logLevelMap[e]){const r=e.toUpperCase();logLevelMap[e]=r}"string"==typeof r[0]&&r[0].length>1&&"["!==r[0][0]&&(r[0]=`[${logLevelMap[e]}] ${r[0]}`)}const logger={logs:[],add(e){this.logs.push(e)},clear(){this.logs=[]},get(){return this.logs.join("\n")}};exports.logger=logger;let originConsole=global.console,console=_console.Console?new _console.Console(process.stdout,process.stderr):originConsole;const colorconsole={attach(e){e&&_console.Console&&(console=new _console.Console(e,e))},trace(...e){prependLevel("trace",e),console.trace(...e)},log(...e){prependLevel("log",e),console.log(_chalk.default.green(...e))},info(...e){prependLevel("info",e),console.info(_chalk.default.green(...e))},warn(...e){prependLevel("warn",e),console.warn(_chalk.default.yellow.bold(...e))},error(...e){prependLevel("error",e),console.error(_chalk.default.red.bold(...e))},throw(...e){throw new Error(_chalk.default.red.bold(...e))}};function logWarn(e,r,t){r&&r.length&&r.forEach((r=>{const o=r.line&&r.column?"\t@"+r.line+":"+r.column:"";t||(r.reason.startsWith("ERROR")?colorconsole.error(e.resourcePath,r.reason+o):colorconsole.warn(e.resourcePath,r.reason+o))}))}function mkdirsSync(e){return!!_fs.default.existsSync(e)||(mkdirsSync(_path.default.dirname(e))?(_fs.default.mkdirSync(e),!0):void 0)}function getIPv4IPAddress(){const e=_os.default.networkInterfaces();let r;for(const t in e)if(Object.prototype.hasOwnProperty.call(e,t)){if(e[t].every((e=>!("IPv4"===e.family&&!e.internal&&"127.0.0.1"!==e.address)||(r=e,!1))),void 0!==r)break}return r&&r.address}function getServerIPAndPort(e){return(getIPv4IPAddress()||"127.0.0.1")+""+(80===e?"":":"+e)}function getDefaultServerHost(){return getServerIPAndPort(_config.default.server.port)}function getClientIPAddress(e){return stripPrefixForIPV4MappedIPV6Address(e.headers["x-forwarded-for"]||e.connection&&e.connection.remoteAddress||e.socket&&e.socket.remoteAddress||e.connection&&e.connection.socket&&e.connection.socket.remoteAddress)}function stripPrefixForIPV4MappedIPV6Address(e){return/^::1$/.test(e)&&(e="127.0.0.1"),/^::.{0,4}:(\d{1,3}\.){3}\d{1,3}/.test(e)&&(e=e.replace(/^.*:/,"")),e}function outputQRCodeOnTerminal(e){console.info(`\nGenerate QR code for HTTP server: ${e}`),_qrcodeTerminal.default.generate(e,{small:!0})}function relateCwd(e){const r=_config.default.projectPath;return _path.default.relative(r,e)}function equals(e,r,t,...o){if(t){if(t(e,r,...o))return!0}const n=Object.prototype.toString.call(e);if(n!==Object.prototype.toString.call(r))return!1;if("[object Null]"===n||"[object Undefined]"===n)return!0;if("[object Object]"!==n&&"[object Array]"!==n)return Object(e).toString()===Object(r).toString();const s={};Object.keys(e).forEach((e=>s[e]=!0)),Object.keys(r).forEach((e=>s[e]=!0));const l=Object.keys(s);for(let o=0;o<l.length;o++){const n=l[o];if(!equals(e[n],r[n],t,n))return!1}return!0}function extend(e,...r){if("function"==typeof Object.assign)Object.assign(e,...r);else{const t=r.shift();for(const r in t)e[r]=t[r];r.length&&extend(e,...r)}return e}function renderString(e,r){return e.replace(/{{(.*?)}}/gm,((e,t)=>(t=t.trim(),void 0!==r[t]?r[t]:t)))}function KnownError(e){const r=new Error(e);return r.name="KnownError",r.__KNOWN=!0,r}function setCustomConfig(e,r){e=_config.default.projectPath=e||_config.default.projectPath;const t=_path.default.join(e,"quickapp.config.js");if(_fs.default.existsSync(t)){let e={};try{e=require(t)}catch(e){colorconsole.error(`Error reading project custom configuration file: ${e.message}`)}const r=Object.assign(_config.default.server,e.server);Object.assign(_config.default,e,{server:r})}r&&(_config.default.server.port=r)}exports.colorconsole=colorconsole;const illegalExtsList=[".css",".less",".scss",".styl",".sass",".log",".json",".js"].map((e=>"app"+e));function getProjectDslName(e){const r=_fs.default.readdirSync(_path.default.join(e,_config.default.sourceRoot)).filter((e=>/^app\..*/.test(e)&&!illegalExtsList.includes(e)));let t;return r&&r[0]?(t=_path.default.extname(r[0]).slice(1),colorconsole.info(`Get the app file suffix: ${t}`)):colorconsole.error("Cannot get the correct app file suffix"),"ux"===t?"xvm":t}function getDeviceInfo(e,r){const t=_http.default.request({path:"/deviceinfo",host:e.ip,port:e.port,timeout:3e3},(e=>{e.on("data",(e=>{r(null,JSON.parse(e))}))})).on("error",(e=>{r(e)})).on("timeout",(function(){t.abort()}));t.end()}function readJson(e){try{return JSON.parse(_fs.default.readFileSync(e).toString())}catch(r){throw r instanceof SyntaxError?new SyntaxError(`Failed to parse ${e}, format error`):r.message.startsWith("ENOENT:")?(r.message=`Failed to read ${e}, the file cannot be found`,r):(r.message=`Failed to read ${e} ${r.message}`,r)}} | ||
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { | ||
value: true | ||
}); | ||
exports.logWarn = logWarn; | ||
exports.mkdirsSync = mkdirsSync; | ||
exports.getIPv4IPAddress = getIPv4IPAddress; | ||
exports.getServerIPAndPort = getServerIPAndPort; | ||
exports.getDefaultServerHost = getDefaultServerHost; | ||
exports.getClientIPAddress = getClientIPAddress; | ||
exports.stripPrefixForIPV4MappedIPV6Address = stripPrefixForIPV4MappedIPV6Address; | ||
exports.outputQRCodeOnTerminal = outputQRCodeOnTerminal; | ||
exports.relateCwd = relateCwd; | ||
exports.equals = equals; | ||
exports.extend = extend; | ||
exports.renderString = renderString; | ||
exports.KnownError = KnownError; | ||
exports.setCustomConfig = setCustomConfig; | ||
exports.getProjectDslName = getProjectDslName; | ||
exports.getDeviceInfo = getDeviceInfo; | ||
exports.readJson = readJson; | ||
Object.defineProperty(exports, "getLaunchPage", { | ||
enumerable: true, | ||
get: function () { | ||
return _util.getLaunchPage; | ||
} | ||
}); | ||
exports.colorconsole = exports.logger = void 0; | ||
var _os = _interopRequireDefault(require("os")); | ||
var _fs = _interopRequireDefault(require("fs")); | ||
var _path = _interopRequireDefault(require("path")); | ||
var _http = _interopRequireDefault(require("http")); | ||
var _console = require("console"); | ||
var _chalk = _interopRequireDefault(require("chalk")); | ||
var _qrcodeTerminal = _interopRequireDefault(require("qrcode-terminal")); | ||
var _config = _interopRequireDefault(require("../config")); | ||
var _util = require("./buildMode/util"); | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
/** | ||
* Copyright (C) 2017, hapjs.org. All rights reserved. | ||
*/ | ||
const logLevelMap = {}; | ||
function prependLevel(levelName, args) { | ||
if (!logLevelMap[levelName]) { | ||
const logLevel = levelName.toUpperCase(); | ||
logLevelMap[levelName] = logLevel; | ||
} | ||
if (typeof args[0] === 'string' && args[0].length > 1 && args[0][0] !== '[') { | ||
args[0] = `[${logLevelMap[levelName]}] ${args[0]}`; | ||
} | ||
} | ||
const logger = { | ||
logs: [], | ||
add(args) { | ||
this.logs.push(args); | ||
}, | ||
clear() { | ||
this.logs = []; | ||
}, | ||
get() { | ||
return this.logs.join('\n'); | ||
} | ||
}; | ||
/** | ||
* 带颜色的 info, log, warn, error, trace 的打印日志输出流 | ||
*/ | ||
exports.logger = logger; | ||
let originConsole = global.console; | ||
let console = _console.Console ? new _console.Console(process.stdout, process.stderr) : originConsole; | ||
const colorconsole = { | ||
attach(writable) { | ||
if (writable && _console.Console) { | ||
console = new _console.Console(writable, writable); | ||
} | ||
}, | ||
trace(...args) { | ||
prependLevel(`trace`, args); | ||
console.trace(...args); | ||
}, | ||
log(...args) { | ||
prependLevel(`log`, args); | ||
console.log(_chalk.default.green(...args)); | ||
}, | ||
info(...args) { | ||
prependLevel(`info`, args); | ||
console.info(_chalk.default.green(...args)); | ||
}, | ||
warn(...args) { | ||
prependLevel(`warn`, args); | ||
console.warn(_chalk.default.yellow.bold(...args)); | ||
}, | ||
error(...args) { | ||
prependLevel(`error`, args); | ||
console.error(_chalk.default.red.bold(...args)); | ||
}, | ||
throw(...args) { | ||
throw new Error(_chalk.default.red.bold(...args)); | ||
} | ||
}; | ||
/** | ||
* 打印日志 | ||
* @param loader | ||
* @param logs | ||
* @param suppresslog | ||
*/ | ||
exports.colorconsole = colorconsole; | ||
function logWarn(loader, logs, suppresslog) { | ||
if (logs && logs.length) { | ||
logs.forEach(log => { | ||
const logAddr = log.line && log.column ? '\t@' + log.line + ':' + log.column : ''; | ||
if (suppresslog) return; | ||
if (log.reason.startsWith('ERROR')) { | ||
colorconsole.error(loader.resourcePath, log.reason + logAddr); | ||
} else { | ||
colorconsole.warn(loader.resourcePath, log.reason + logAddr); | ||
} | ||
}); | ||
} | ||
} | ||
/** | ||
* 创建任意深度的路径的文件夹 | ||
* @param dirname | ||
* @returns {boolean} | ||
*/ | ||
function mkdirsSync(dirname) { | ||
if (_fs.default.existsSync(dirname)) { | ||
return true; | ||
} else { | ||
if (mkdirsSync(_path.default.dirname(dirname))) { | ||
_fs.default.mkdirSync(dirname); | ||
return true; | ||
} | ||
} | ||
} | ||
/** | ||
* 获取服务器端的IP | ||
*/ | ||
function getIPv4IPAddress() { | ||
const ifaces = _os.default.networkInterfaces(); | ||
let result; | ||
for (const prop in ifaces) { | ||
if (Object.prototype.hasOwnProperty.call(ifaces, prop)) { | ||
const iface = ifaces[prop]; | ||
iface.every(eachAlias => { | ||
if (eachAlias.family === 'IPv4' && !eachAlias.internal && eachAlias.address !== '127.0.0.1') { | ||
result = eachAlias; | ||
return false; | ||
} | ||
return true; | ||
}); | ||
if (result !== void 0) { | ||
break; | ||
} | ||
} | ||
} | ||
return result && result.address; | ||
} | ||
/** | ||
* 取得server端的IP和port | ||
* @param port {number} | ||
* @returns {string} | ||
*/ | ||
function getServerIPAndPort(port) { | ||
return (getIPv4IPAddress() || '127.0.0.1') + `${port === 80 ? '' : ':' + port}`; | ||
} | ||
/** | ||
* 获取默认的服务器地址 | ||
*/ | ||
function getDefaultServerHost() { | ||
return getServerIPAndPort(_config.default.server.port); | ||
} | ||
/** | ||
* 获取客户端ip | ||
* @param req node Http IncomingRequest Object | ||
* @returns {any|*|string} | ||
*/ | ||
function getClientIPAddress(req) { | ||
const ip = req.headers['x-forwarded-for'] || req.connection && req.connection.remoteAddress || req.socket && req.socket.remoteAddress || req.connection && req.connection.socket && req.connection.socket.remoteAddress; | ||
return stripPrefixForIPV4MappedIPV6Address(ip); | ||
} | ||
/** | ||
* 检测可能是IpV4-mapped IpV6 格式的ip | ||
* - https://en.wikipedia.org/wiki/IPv6#IPv4-mapped_IPv6_addresses | ||
* | ||
* @param ip IpV4-mapped IpV6 string | ||
* @returns {*} | ||
*/ | ||
function stripPrefixForIPV4MappedIPV6Address(ip) { | ||
if (/^::1$/.test(ip)) { | ||
ip = '127.0.0.1'; | ||
} | ||
if (/^::.{0,4}:(\d{1,3}\.){3}\d{1,3}/.test(ip)) { | ||
ip = ip.replace(/^.*:/, ''); | ||
} | ||
return ip; | ||
} | ||
/** | ||
* 命令行输出二维码 | ||
* @param text | ||
*/ | ||
function outputQRCodeOnTerminal(text) { | ||
console.info(`\nGenerate QR code for HTTP server: ${text}`); | ||
_qrcodeTerminal.default.generate(text, { | ||
small: true | ||
}); | ||
} | ||
/** | ||
* 相对工作目录的路径 | ||
* | ||
* @param {String} filepath - 输入路径 | ||
* @returns {String} - 输出相对路径 | ||
*/ | ||
function relateCwd(filepath) { | ||
const CWD = _config.default.projectPath; | ||
return _path.default.relative(CWD, filepath); | ||
} | ||
/** | ||
* 比较两个对象是否相同 | ||
* @param o1 | ||
* @param o2 | ||
* @param fn {Function} 对比函数 | ||
*/ | ||
function equals(o1, o2, fn, ...args) { | ||
if (fn) { | ||
const fnRet = fn(o1, o2, ...args); | ||
if (fnRet) { | ||
return true; | ||
} | ||
} | ||
const toStr1 = Object.prototype.toString.call(o1); | ||
const toStr2 = Object.prototype.toString.call(o2); | ||
if (toStr1 !== toStr2) { | ||
return false; | ||
} | ||
if (toStr1 === '[object Null]' || toStr1 === '[object Undefined]') { | ||
return true; | ||
} | ||
if (toStr1 !== '[object Object]' && toStr1 !== '[object Array]') { | ||
return Object(o1).toString() === Object(o2).toString(); | ||
} | ||
const keyMap = {}; | ||
Object.keys(o1).forEach(k => keyMap[k] = true); | ||
Object.keys(o2).forEach(k => keyMap[k] = true); | ||
const keyList = Object.keys(keyMap); | ||
for (let i = 0; i < keyList.length; i++) { | ||
const keyName = keyList[i]; | ||
const isEqual = equals(o1[keyName], o2[keyName], fn, keyName); | ||
if (!isEqual) { | ||
return false; | ||
} | ||
} | ||
return true; | ||
} | ||
/** | ||
* 扩展对象属性 | ||
* @param dest | ||
* @param src | ||
*/ | ||
function extend(target, ...src) { | ||
if (typeof Object.assign === 'function') { | ||
Object.assign(target, ...src); | ||
} else { | ||
const first = src.shift(); // 覆盖旧值 | ||
for (const key in first) { | ||
target[key] = first[key]; | ||
} | ||
if (src.length) { | ||
extend(target, ...src); | ||
} | ||
} | ||
return target; | ||
} | ||
/** | ||
* 简单的模板字符串渲染函数 | ||
* | ||
* @param {String} tpl - 模板字符串 | ||
* @param {Object} data - 渲染数据 | ||
* @returns {String} | ||
*/ | ||
function renderString(tpl, data) { | ||
return tpl.replace(/{{(.*?)}}/gm, (_, key) => { | ||
key = key.trim(); | ||
return data[key] !== undefined ? data[key] : key; | ||
}); | ||
} | ||
function KnownError(message) { | ||
const err = new Error(message); | ||
err.name = 'KnownError'; | ||
err.__KNOWN = true; | ||
return err; | ||
} | ||
/** | ||
* 获取并设置自定义配置项 | ||
* @param {String} projectPath - 项目路径 | ||
* @param {String} port - server端口 | ||
*/ | ||
function setCustomConfig(projectPath, port) { | ||
projectPath = _config.default.projectPath = projectPath || _config.default.projectPath; | ||
const defaultConfig = 'quickapp.config.js'; | ||
const defaultConfigPath = _path.default.join(projectPath, defaultConfig); | ||
if (_fs.default.existsSync(defaultConfigPath)) { | ||
let customConf = {}; | ||
try { | ||
customConf = require(defaultConfigPath); | ||
} catch (err) { | ||
colorconsole.error(`Error reading project custom configuration file: ${err.message}`); | ||
} // 保证 customConf server 字段无内容也可保证默认值 | ||
const server = Object.assign(_config.default.server, customConf.server); | ||
Object.assign(_config.default, customConf, { | ||
server | ||
}); | ||
} | ||
port && (_config.default.server.port = port); | ||
} | ||
const illegalExtsList = ['.css', '.less', '.scss', '.styl', '.sass', '.log', '.json', '.js'].map(e => 'app' + e); | ||
/** | ||
* 获取当前项目所使用的DSL | ||
* @param projectPath | ||
*/ | ||
function getProjectDslName(projectPath) { | ||
// 根据项目中src/app的后缀名判断 | ||
const srcFiles = _fs.default.readdirSync(_path.default.join(projectPath, _config.default.sourceRoot)); | ||
const appFileNames = srcFiles.filter(f => /^app\..*/.test(f) && !illegalExtsList.includes(f)); | ||
let appFileExt; | ||
if (appFileNames && appFileNames[0]) { | ||
appFileExt = _path.default.extname(appFileNames[0]).slice(1); | ||
colorconsole.info(`Get the app file suffix: ${appFileExt}`); | ||
} else { | ||
colorconsole.error(`Cannot get the correct app file suffix`); | ||
} | ||
return appFileExt === 'ux' ? 'xvm' : appFileExt; | ||
} | ||
/** | ||
* 获取手机设备信息(1020新增接口) | ||
* @param client {{ ip, port }} | ||
* @param callback | ||
*/ | ||
function getDeviceInfo(client, callback) { | ||
const req = _http.default.request({ | ||
path: '/deviceinfo', | ||
host: client.ip, | ||
port: client.port, | ||
timeout: 3000 | ||
}, res => { | ||
res.on('data', data => { | ||
callback(null, JSON.parse(data)); | ||
}); | ||
}).on('error', err => { | ||
callback(err); | ||
}).on('timeout', function () { | ||
// abort方法会触发error事件 | ||
req.abort(); | ||
}); | ||
req.end(); | ||
} | ||
/** | ||
* 读取一份 json 内容 | ||
* | ||
* @param {String} jsonpath - json 路径 | ||
* @returns {Object} json | ||
*/ | ||
function readJson(jsonpath) { | ||
try { | ||
return JSON.parse(_fs.default.readFileSync(jsonpath).toString()); | ||
} catch (err) { | ||
if (err instanceof SyntaxError) { | ||
throw new SyntaxError(`Failed to parse ${jsonpath}, format error`); | ||
} else if (err.message.startsWith('ENOENT:')) { | ||
err.message = `Failed to read ${jsonpath}, the file cannot be found`; | ||
throw err; | ||
} else { | ||
err.message = `Failed to read ${jsonpath} ${err.message}`; | ||
throw err; | ||
} | ||
} | ||
} | ||
//# sourceMappingURL=index.js.map |
@@ -1,2 +0,172 @@ | ||
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.getRecords=getRecords,exports.getProjectClients=getProjectClients,exports.recordClient=recordClient,exports.getRecordClient=getRecordClient,exports.clearProjectRecord=clearProjectRecord,exports.removeClientBySn=removeClientBySn;var _fs=_interopRequireDefault(require("fs")),_path=_interopRequireDefault(require("path")),_index=require("./index"),_config=_interopRequireDefault(require("../config"));function _interopRequireDefault(e){return e&&e.__esModule?e:{default:e}}function getRecords(e){let r={records:{}};try{r=JSON.parse(_fs.default.readFileSync(e).toString())}catch(e){_index.colorconsole.error(`Error reading hap-toolkit-client-records.json file: ${e.message}`)}return r}function writeRecords(e,r){_fs.default.writeFileSync(e,JSON.stringify(r,null,2))}function getProjectClients(e){const r=_config.default.projectPath;let t=e.records;t=t instanceof Object?t:{};const o=t[r];return o&&o instanceof Array?o:[]}function recordClient(e,r,t){const o=_path.default.dirname(e),i=_config.default.projectPath;let n;if((0,_index.mkdirsSync)(o),_fs.default.existsSync(e)){n=getRecords(e);let o=getProjectClients(n);for(t&&t(`writeClientLogFile(): before: ${JSON.stringify(n.records)}`),o=o.filter((e=>e.ip!==r.ip||e.port!==r.port));o.length>4;)o.shift();n.records[i]=o}else n={records:{}},n.records[i]=[];n.records[i].push(r),writeRecords(e,n),t&&t(`writeClientLogFile(): after: ${JSON.stringify(n.records)}`)}function getRecordClient(e,r,t){if(_fs.default.existsSync(e)){return getProjectClients(getRecords(e)).find((e=>e.sn===r&&e.ip===t&&e.port))}}function clearProjectRecord(e){if(_fs.default.existsSync(e)){const r=getRecords(e),t=_config.default.projectPath;r.records[t]=[],writeRecords(e,r),_index.colorconsole.info("### App Server ### Clear debugging equipment records")}else _index.colorconsole.info("### App Server ### There are no debugging equipment records that need to be cleared")}function removeClientBySn(e,r,t){if(_fs.default.existsSync(e)){const o=_config.default.projectPath,i=getRecords(e),n=i.records,c=getProjectClients(i);t&&t(`_removeItemFromClientLogFile(): before: ${JSON.stringify(n)}`),n[o]=c.filter((e=>e.sn!==r)),writeRecords(e,i),t&&t(`_removeItemFromClientLogFile(): after: ${JSON.stringify(n)}`)}} | ||
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { | ||
value: true | ||
}); | ||
exports.getRecords = getRecords; | ||
exports.getProjectClients = getProjectClients; | ||
exports.recordClient = recordClient; | ||
exports.getRecordClient = getRecordClient; | ||
exports.clearProjectRecord = clearProjectRecord; | ||
exports.removeClientBySn = removeClientBySn; | ||
var _fs = _interopRequireDefault(require("fs")); | ||
var _path = _interopRequireDefault(require("path")); | ||
var _index = require("./index"); | ||
var _config = _interopRequireDefault(require("../config")); | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
/** | ||
* Copyright (C) 2017, hapjs.org. All rights reserved. | ||
*/ | ||
/** | ||
* 读取记录文件 | ||
* @param {String} clientRecordPath - 记录文件的地址 | ||
* @returns {Object} - 记录的全部设备信息 | ||
*/ | ||
function getRecords(clientRecordPath) { | ||
let recordData = { | ||
records: {} | ||
}; | ||
try { | ||
recordData = JSON.parse(_fs.default.readFileSync(clientRecordPath).toString()); | ||
} catch (err) { | ||
_index.colorconsole.error(`Error reading hap-toolkit-client-records.json file: ${err.message}`); | ||
} | ||
return recordData; | ||
} | ||
/** | ||
* 将设备记录写入记录文件 | ||
* @param {String} clientRecordPath - 记录文件的地址 | ||
* @param {Object} recordData - 要写入的全部设备记录 | ||
*/ | ||
function writeRecords(clientRecordPath, recordData) { | ||
_fs.default.writeFileSync(clientRecordPath, JSON.stringify(recordData, null, 2)); | ||
} | ||
/** | ||
* 读取一个项目的设备记录 | ||
* @param {Object} recordData - 全部设备信息 | ||
* @returns {Array} - 设备记录 | ||
*/ | ||
function getProjectClients(recordData) { | ||
const projectPath = _config.default.projectPath; | ||
let records = recordData.records; | ||
records = records instanceof Object ? records : {}; | ||
const clients = records[projectPath]; | ||
if (clients && clients instanceof Array) { | ||
return clients; | ||
} | ||
return []; | ||
} | ||
/** | ||
* 保存设备记录 | ||
* @param {String} clientRecordPath - 记录文件的地址 | ||
* @param {String} newClient - 新的设备记录 | ||
* @param {callback} logHook - log信息的钩子,参数为要打印的信息 | ||
*/ | ||
function recordClient(clientRecordPath, newClient, logHook) { | ||
const pathParentDir = _path.default.dirname(clientRecordPath); | ||
const projectPath = _config.default.projectPath; | ||
let recordData; | ||
(0, _index.mkdirsSync)(pathParentDir); | ||
if (_fs.default.existsSync(clientRecordPath)) { | ||
recordData = getRecords(clientRecordPath); | ||
let clients = getProjectClients(recordData); | ||
logHook && logHook(`writeClientLogFile(): before: ${JSON.stringify(recordData.records)}`); | ||
clients = clients.filter(client => { | ||
return client.ip !== newClient.ip || client.port !== newClient.port; | ||
}); // 保留最后的4条记录,最多记录5条 | ||
while (clients.length > 4) { | ||
clients.shift(); | ||
} | ||
recordData.records[projectPath] = clients; | ||
} else { | ||
recordData = { | ||
records: {} | ||
}; | ||
recordData.records[projectPath] = []; | ||
} // 写入文件 | ||
recordData.records[projectPath].push(newClient); | ||
writeRecords(clientRecordPath, recordData); | ||
logHook && logHook(`writeClientLogFile(): after: ${JSON.stringify(recordData.records)}`); | ||
} | ||
/** | ||
* 根据设备sn和ip获取设备的记录 | ||
* @param {String} clientRecordPath - 记录文件地址 | ||
* @param {String} sn - 设备序列号 | ||
* @param {String} ip | ||
* @returns {Object} - 匹配的设备记录 | ||
*/ | ||
function getRecordClient(clientRecordPath, sn, ip) { | ||
if (_fs.default.existsSync(clientRecordPath)) { | ||
const recordData = getRecords(clientRecordPath); | ||
const clients = getProjectClients(recordData); | ||
return clients.find(client => { | ||
return client.sn === sn && client.ip === ip && client.port; | ||
}); | ||
} | ||
} | ||
/** | ||
* 清除一个项目的设备记录 | ||
* @param {String} clientRecordPath | ||
*/ | ||
function clearProjectRecord(clientRecordPath) { | ||
if (_fs.default.existsSync(clientRecordPath)) { | ||
const recordData = getRecords(clientRecordPath); | ||
const projectPath = _config.default.projectPath; | ||
recordData.records[projectPath] = []; | ||
writeRecords(clientRecordPath, recordData); | ||
_index.colorconsole.info('### App Server ### Clear debugging equipment records'); | ||
} else { | ||
_index.colorconsole.info('### App Server ### There are no debugging equipment records that need to be cleared'); | ||
} | ||
} | ||
/** | ||
* 从端口映射记录文件中移除项目的一个设备记录 | ||
* @param {String} clientRecordPath - 记录文件的地址 | ||
* @param {String} sn - 设备序列号 | ||
* @param {callback} logHook - log信息的钩子,参数为要打印的信息 | ||
*/ | ||
function removeClientBySn(clientRecordPath, sn, logHook) { | ||
if (_fs.default.existsSync(clientRecordPath)) { | ||
const projectPath = _config.default.projectPath; | ||
const recordData = getRecords(clientRecordPath); | ||
const records = recordData.records; | ||
const clients = getProjectClients(recordData); | ||
logHook && logHook(`_removeItemFromClientLogFile(): before: ${JSON.stringify(records)}`); | ||
records[projectPath] = clients.filter(it => { | ||
return it.sn !== sn; | ||
}); | ||
writeRecords(clientRecordPath, recordData); | ||
logHook && logHook(`_removeItemFromClientLogFile(): after: ${JSON.stringify(records)}`); | ||
} | ||
} | ||
//# sourceMappingURL=record-client.js.map |
{ | ||
"name": "@aiot-toolkit/shared-utils", | ||
"version": "1.0.7-beta.2", | ||
"version": "1.0.7-beta.3", | ||
"description": "aiot shared utils", | ||
@@ -33,3 +33,3 @@ "engines": { | ||
}, | ||
"gitHead": "e92485beedec8953e69b743fa9da3ade7de0bb14" | ||
"gitHead": "82194f13f6b136777fca7607aeca23ec5650db38" | ||
} |
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
Minified code
QualityThis package contains minified code. This may be harmless in some cases where minified code is included in packaged libraries, however packages on npm should not minify code.
Found 1 instance in 1 package
31278
979
2
2