From ecfdb637380735301f704cbb01f4e0f2b0507be8 Mon Sep 17 00:00:00 2001 From: zyao89 Date: Thu, 19 Sep 2019 20:31:10 +0800 Subject: [PATCH 01/10] =?UTF-8?q?:art:=20=E6=8A=BD=E7=A6=BB=20microsExtral?= =?UTF-8?q?=20=E5=92=8C=20deploy,=20=E9=87=8D=E6=9E=84=E9=83=A8=E5=88=86?= =?UTF-8?q?=E5=8A=9F=E8=83=BD=E9=80=BB=E8=BE=91.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 1 - config/constants.js | 2 +- config/default.js | 1 - libs/MicroAppConfig.js | 43 +------------------- libs/Service/Base.js | 79 +++++++++++++++++++++++++++++++++--- libs/Service/Constants.js | 3 ++ libs/Service/PluginAPI.js | 21 ++++++++++ libs/Service/index.js | 13 +++++- libs/Service/methods/init.js | 2 + micro-app.config.js | 1 - package.json | 1 + simple/micro-app.config.js | 1 - utils/requireMicro.js | 11 +++-- yarn.lock | 7 +++- 14 files changed, 126 insertions(+), 60 deletions(-) diff --git a/README.md b/README.md index 11ed4c3..302e97d 100644 --- a/README.md +++ b/README.md @@ -96,7 +96,6 @@ module.exports = { server: { entry: '', // 服务端入口 port: 8088, // 服务端口号 - contentBase: 'public', // 静态文件地址 options: { // 服务端回调参数 }, diff --git a/config/constants.js b/config/constants.js index 964b483..43ea062 100644 --- a/config/constants.js +++ b/config/constants.js @@ -9,8 +9,8 @@ module.exports = { NODE_MODULES_NAME: 'node_modules', SCOPE_NAME: '@micro-app', // namespace CONFIG_NAME: 'micro-app.config.js', + EXTRAL_CONFIG_NAME: 'micro-app.extral.config.js', TYPES: [], // support types INJECT_ID: '_MICRO_APP_INJECT_', - NODE_ENV: process.env.NODE_ENV || 'production', // "production" | "development" PACKAGE_JSON: 'package.json', }; diff --git a/config/default.js b/config/default.js index 3d8a6c8..d772fe4 100644 --- a/config/default.js +++ b/config/default.js @@ -53,7 +53,6 @@ module.exports = { // host: ‘’, // 服务 IP // port: 8888, // 服务端口号 // options: { }, // 服务端注入附加参数 - // contentBase: '', // 服务端静态文件目录 // proxy: { // 服务代理 // '/api': { diff --git a/libs/MicroAppConfig.js b/libs/MicroAppConfig.js index 5fbf09b..29f32cf 100644 --- a/libs/MicroAppConfig.js +++ b/libs/MicroAppConfig.js @@ -73,8 +73,7 @@ class MicroAppConfig { } get isOpenSoftLink() { - const MicroAppConfig = this.globalMicroAppConfig; - return MicroAppConfig.OPEN_SOFT_LINK && this.root !== this.originalRoot; + return this.root !== this.originalRoot; } get path() { @@ -96,7 +95,7 @@ class MicroAppConfig { } get mode() { - return CONSTANTS.NODE_ENV || 'production'; + return process.env.NODE_ENV || 'production'; // "production" | "development" } get isDev() { @@ -285,38 +284,6 @@ class MicroAppConfig { return []; } - get globalMicroAppConfig() { - const MicroAppConfig = global.MicroAppConfig; - if (MicroAppConfig && _.isPlainObject(MicroAppConfig)) { - return _.cloneDeep(MicroAppConfig); - } - return {}; - } - - // TODO 拆离 - get microsExtral() { - const config = this.config; - const result = {}; - const MicroAppConfig = this.globalMicroAppConfig; - this.micros.forEach(micro => { - result[micro] = Object.assign({}, config[`micros$$${micro}`] || { - disabled: false, // 禁用入口 - disable: false, - link: false, - }); - - // 附加内容需要参考全局配置 - if (!MicroAppConfig.OPEN_SOFT_LINK) { // 强制禁止使用 软链接 - result[micro].link = false; - } - if (!MicroAppConfig.OPEN_DISABLED_ENTRY) { // 强制禁止使用 开启禁用指定模块入口, 优化开发速度 - result[micro].disabled = false; - result[micro].disable = false; - } - }); - return result; - } - // 后端共享 get _shared() { const config = this.config; @@ -431,12 +398,6 @@ class MicroAppConfig { return alias; } - // TODO 拆离 - get deploy() { - const config = this.config; - return config.deploy; - } - // server get server() { const config = this.config; diff --git a/libs/Service/Base.js b/libs/Service/Base.js index e9a3737..8143b4a 100644 --- a/libs/Service/Base.js +++ b/libs/Service/Base.js @@ -3,13 +3,16 @@ const tryRequire = require('try-require'); const assert = require('assert'); const _ = require('lodash'); +const semverRegex = require('semver-regex'); const CONSTANTS = require('../../config/constants'); const requireMicro = require('../../utils/requireMicro'); +const loadFile = require('../../utils/loadFile'); const logger = require('../../utils/logger'); const { SharedProps } = require('./Constants'); +const MICROS_EXTRAL_CONFIG_KEY = Symbol('MICROS_EXTRAL_CONFIG_KEY'); // 全局状态集 const GLOBAL_STATE = {}; @@ -26,6 +29,10 @@ class BaseService { this.selfConfig = this.self.toConfig(true); this.selfServerConfig = this.self.toServerConfig(true); this.micros = new Set((this.self.micros || [])); + + this.__initDefaultEnv__(); + this.__initGlobalMicroAppConfig__(); + this.microsConfig = this._initMicrosConfig(); this.microsServerConfig = this._initMicrosServerConfig(); @@ -35,6 +42,34 @@ class BaseService { this.state = GLOBAL_STATE; // 状态集 } + __initDefaultEnv__() { + const env = { + VERSION: { + force: true, + value: semverRegex().exec(this.version)[0], + }, + }; + Object.keys(env).forEach(key => { + const _k = `MICRO_APP_${key.toUpperCase()}`; + const item = env[key]; + if (item.force || _.isUndefined(process.env[_k])) { + process.env[_k] = item.value; + } + }); + } + + __initGlobalMicroAppConfig__() { + // 加载高级配置 + this[MICROS_EXTRAL_CONFIG_KEY] = loadFile(this.root, CONSTANTS.EXTRAL_CONFIG_NAME); + + // 全局指令, 不可靠配置 + if (!global.MicroAppConfig) { + global.MicroAppConfig = {}; + } + const MicroAppConfig = global.MicroAppConfig; + MicroAppConfig.microsExtralConfig = this.microsExtralConfig; + } + get root() { return CONSTANTS.ROOT; } @@ -43,16 +78,50 @@ class BaseService { return CONSTANTS.VERSION; } + get pkg() { + return this.self.package || {}; + } + get mode() { - return CONSTANTS.NODE_ENV || 'production'; + return process.env.NODE_ENV || 'production'; // "production" | "development" + } + + get strictMode() { + return this.self.strict; } get self() { const _self = requireMicro.self(); - assert(_self, logger.toString.error('not found "micro-app.config.js"')); + if (!_self) { + logger.error(`Not Found "${CONSTANTS.CONFIG_NAME}"`); + logger.warn(`must be to create "${CONSTANTS.CONFIG_NAME}" in "${this.root}"`); + process.exit(1); + } return _self; } + get microsExtralConfig() { + const microsExtral = this[MICROS_EXTRAL_CONFIG_KEY] || {}; + const result = {}; + Array.from(this.micros).forEach(key => { + result[key] = Object.assign({}, microsExtral[key] || { + disabled: false, // 禁用入口 + disable: false, + link: false, + }); + + // 附加内容需要参考全局配置 + if (!process.env.MICRO_APP_OPEN_SOFT_LINK) { // 强制禁止使用 软链接 + result[key].link = false; + } + if (!process.env.MICRO_APP_OPEN_DISABLED_ENTRY) { // 强制禁止使用 开启禁用指定模块入口, 优化开发速度 + result[key].disabled = false; + result[key].disable = false; + } + }); + return Object.assign({}, microsExtral, result); + } + _initMicrosConfig() { const config = {}; const micros = _.cloneDeep([ ...this.micros ]); @@ -62,7 +131,7 @@ class BaseService { config[key] = microConfig.toConfig(true); } else { this.micros.delete(key); - logger.error(`not found micros: "${key}"`); + logger.error(`Not Found micros: "${key}"`); } }); config[this.self.key] = this.selfConfig || this.self.toConfig(true); @@ -78,7 +147,7 @@ class BaseService { config[key] = microConfig.toServerConfig(true); } else { this.micros.delete(key); - logger.error(`not found micros: "${key}"`); + logger.error(`Not Found micros: "${key}"`); } }); config[this.self.key] = this.selfServerConfig || this.self.toServerConfig(true); @@ -101,7 +170,7 @@ class BaseService { logger.debug('dotenv parsed envs:\n', JSON.stringify(this.env, null, 4)); } } else { - logger.warn('not found "dotenv"'); + logger.warn('Not Found "dotenv"'); } if (env === 'production') { // fixed this.env.NODE_ENV = env; diff --git a/libs/Service/Constants.js b/libs/Service/Constants.js index 2fcdecd..b8600f3 100644 --- a/libs/Service/Constants.js +++ b/libs/Service/Constants.js @@ -19,8 +19,11 @@ const contants = { SharedProps: [ 'root', 'mode', + 'strictMode', 'env', 'version', + 'pkg', + 'microsExtralConfig', 'applyPluginHooks', 'applyPluginHooksAsync', 'resolvePlugin', diff --git a/libs/Service/PluginAPI.js b/libs/Service/PluginAPI.js index 863d50c..12ee849 100644 --- a/libs/Service/PluginAPI.js +++ b/libs/Service/PluginAPI.js @@ -2,6 +2,8 @@ const assert = require('assert'); const _ = require('lodash'); +const semver = require('semver'); + const BaseAPI = require('./BaseAPI'); const DEFAULT_METHODS = require('./methods'); const { SharedProps } = require('./Constants'); @@ -44,6 +46,25 @@ class PluginAPI extends BaseAPI { }); } + assertVersion(range) { + const version = this.service.version; + if (typeof range === 'number') { + if (!Number.isInteger(range)) { + throw new Error('Expected string or integer value.'); + } + range = `^${range}.0.0-0`; + } + if (typeof range !== 'string') { + throw new Error('Expected string or integer value.'); + } + + if (semver.satisfies(version, range)) return; + + throw new Error( + `Require @micro-app/core "${range}", but was loaded with "${version}".` + ); + } + setState(key, value) { this.service.state[key] = value; } diff --git a/libs/Service/index.js b/libs/Service/index.js index f9a3a20..43e4d60 100644 --- a/libs/Service/index.js +++ b/libs/Service/index.js @@ -20,6 +20,7 @@ const { PreLoadPlugins, SharedProps } = require('./Constants'); class Service extends BaseService { constructor() { super(); + this.initialized = false; this.plugins = PreLoadPlugins.map(this.resolvePlugin).filter(item => !!item); this.extraPlugins = []; // 临时存储扩展模块 @@ -207,11 +208,12 @@ e.g. if (link) { const apply = tryRequire(link); if (apply) { - return { + const defaultConfig = apply.configuration || {}; + return Object.assign({}, defaultConfig, { ...item, apply: apply.default || apply, opts, - }; + }); } } logger.warn(`[Plugin] not found plugin: "${id || item}"\n --> link: "${link}"`); @@ -277,6 +279,11 @@ e.g. } init() { + if (this.initialized) { + return; + } + this.initialized = true; + this._initDotEnv(); this._initPlugins(); this.applyPluginHooks('onPluginInitDone'); @@ -284,6 +291,7 @@ e.g. this.applyPluginHooks('beforeMergeConfig', this.config); this._mergeConfig(); this.applyPluginHooks('afterMergeConfig', this.config); + this.config = this.applyPluginHooks('modifyDefaultConfig', this.config); // 注入全局的别名 injectAliasModule(this.config.resolveShared); @@ -296,6 +304,7 @@ e.g. this.applyPluginHooks('beforeMergeServerConfig', this.serverConfig); this._mergeServerConfig(); this.applyPluginHooks('afterMergeServerConfig', this.serverConfig); + this.serverConfig = this.applyPluginHooks('modifyDefaultServerConfig', this.serverConfig); this.applyPluginHooks('onInitWillDone'); this.applyPluginHooks('onInitDone'); diff --git a/libs/Service/methods/init.js b/libs/Service/methods/init.js index 960fc9b..cdb7a99 100644 --- a/libs/Service/methods/init.js +++ b/libs/Service/methods/init.js @@ -3,9 +3,11 @@ module.exports = [ 'onPluginInitDone', 'beforeMergeConfig', + 'modifyDefaultConfig', 'afterMergeConfig', 'beforeMergeServerConfig', 'afterMergeServerConfig', + 'modifyDefaultServerConfig', 'onInitWillDone', 'onInitDone', ]; diff --git a/micro-app.config.js b/micro-app.config.js index 200460a..f4287b5 100644 --- a/micro-app.config.js +++ b/micro-app.config.js @@ -55,7 +55,6 @@ module.exports = { server: { entry: '', // 服务端入口 port: 8088, // 服务端口号 - contentBase: 'public', // 静态文件地址 options: { // 服务端回调参数 }, diff --git a/package.json b/package.json index 3245b92..0eae250 100644 --- a/package.json +++ b/package.json @@ -55,6 +55,7 @@ "module-alias": "^2.2.1", "ora": "^3.4.0", "semver": "^6.3.0", + "semver-regex": "^3.1.0", "stream-to-string": "^1.2.0", "try-require": "^1.2.1", "webpack-merge": "^4.2.2" diff --git a/simple/micro-app.config.js b/simple/micro-app.config.js index 551f251..0afc5f3 100644 --- a/simple/micro-app.config.js +++ b/simple/micro-app.config.js @@ -44,7 +44,6 @@ module.exports = { server: { entry: './server/entry.js', // path port: 8088, - contentBase: 'public', // path options: { }, }, }; diff --git a/utils/requireMicro.js b/utils/requireMicro.js index 044e707..d998860 100644 --- a/utils/requireMicro.js +++ b/utils/requireMicro.js @@ -33,13 +33,12 @@ const isExists = function(p) { } }; -// 开发模式软链接 +// @custom 开发模式软链接 +// 当 global.MicroAppConfig.microsExtralConfig 存在时, 才会开启软链功能 const fixedDevLink = function(id, micPath) { - const _selfConfig = self(); - if (!_selfConfig) throw new Error('Not Found "micro-app.config.js"'); - // extral config - const microsExtral = _selfConfig.microsExtral || {}; - const extralConfig = microsExtral[id]; + const MicroAppConfig = global.MicroAppConfig || {}; + const microsExtralConfig = MicroAppConfig.microsExtralConfig || {}; + const extralConfig = microsExtralConfig[id]; if (extralConfig && extralConfig.link && fs.existsSync(extralConfig.link)) { return extralConfig.link; } diff --git a/yarn.lock b/yarn.lock index ceb39d6..6af64b4 100644 --- a/yarn.lock +++ b/yarn.lock @@ -915,7 +915,7 @@ axobject-query@^2.0.2: dependencies: ast-types-flow "0.0.7" -babel-eslint@^10.0.2: +babel-eslint@^10.0.3: version "10.0.3" resolved "https://registry.yarnpkg.com/babel-eslint/-/babel-eslint-10.0.3.tgz#81a2c669be0f205e19462fed2482d33e4687a88a" integrity sha512-z3U7eMY6r/3f3/JB9mTsLjyxrv0Yb1zb8PCWCLpguxfCzBIZUwy23R1t/XKewP+8mEN2Ck8Dtr4q20z6ce6SoA== @@ -5037,6 +5037,11 @@ schema-utils@^1.0.0: ajv-errors "^1.0.0" ajv-keywords "^3.1.0" +semver-regex@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/semver-regex/-/semver-regex-3.1.0.tgz#23368cb577bf2668e78bf9c3e8e519fc029ca069" + integrity sha512-xJqZonbAohJmpogzq1Mx7DB4DT3LO+sG5J4i/rcRyZ527dcUqsTVb5T0vM5gwOBf3KO0v7i94EpbdvwSukJyAQ== + "semver@2 || 3 || 4 || 5", semver@^5.3.0, semver@^5.4.1, semver@^5.5.0, semver@^5.5.1, semver@^5.6.0: version "5.7.1" resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" From 980b952e08a2b89da66175860d93cc9dfd360a7e Mon Sep 17 00:00:00 2001 From: zyao89 Date: Fri, 20 Sep 2019 14:14:58 +0800 Subject: [PATCH 02/10] :art: remove cloneDeep of defaultOpts --- libs/Service/PluginAPI.js | 11 ++++++----- libs/Service/index.js | 36 ++++++++++++++++++++++-------------- 2 files changed, 28 insertions(+), 19 deletions(-) diff --git a/libs/Service/PluginAPI.js b/libs/Service/PluginAPI.js index 12ee849..7bd190c 100644 --- a/libs/Service/PluginAPI.js +++ b/libs/Service/PluginAPI.js @@ -73,7 +73,7 @@ class PluginAPI extends BaseAPI { return this.service.state[key] || value; } - register(hook, fn) { + register(hook, fn, type) { assert( typeof hook === 'string', `The first argument of api.register() must be string, but got ${hook}` @@ -86,6 +86,7 @@ class PluginAPI extends BaseAPI { pluginHooks[hook] = pluginHooks[hook] || []; pluginHooks[hook].push({ fn, + type, }); } @@ -109,21 +110,21 @@ class PluginAPI extends BaseAPI { if (apply) { this.register(name, opts => { return apply(opts, ...args); - }); + }, type); } else if (type === this.API_TYPE.ADD) { this.register(name, opts => { return (opts.last || []).concat( typeof args[0] === 'function' ? args[0](opts.last, opts.args) : args[0] ); - }); + }, type); } else if (type === this.API_TYPE.MODIFY) { this.register(name, opts => { return typeof args[0] === 'function' ? args[0](opts.last, opts.args) : args[0]; - }); + }, type); } else if (type === this.API_TYPE.EVENT) { this.register(name, opts => { return args[0](opts.args); - }); + }, type); } else { throw new Error(`unexpected api type ${type}`); } diff --git a/libs/Service/index.js b/libs/Service/index.js index 43e4d60..1a212dd 100644 --- a/libs/Service/index.js +++ b/libs/Service/index.js @@ -62,6 +62,8 @@ class Service extends BaseService { assert(count <= 10, '插件注册死循环?'); } + // TODO 排序重组, reload(); + // Throw error for methods that can't be called after plugins is initialized this.plugins.forEach(plugin => { Object.keys(plugin._api).forEach(method => { @@ -69,7 +71,8 @@ class Service extends BaseService { 'onOptionChange', ].includes(method)) { plugin._api[method] = () => { - throw logger.toString.error(`api.${method}() should not be called after plugin is initialized.`); + logger.error(`api.${method}() should not be called after plugin is initialized.`); + throw Error(); }; } }); @@ -79,7 +82,12 @@ class Service extends BaseService { } _initPlugin(plugin) { - const { id, apply, opts = {} } = plugin; + const { id, apply, opts = {}, mode } = plugin; + if (mode && mode !== this.mode) { + // 当前模式与插件不匹配 + logger.warn(`[Plugin] _initPlugin() skip "${id}"`); + return; + } assert(typeof apply === 'function', logger.toString.error('\n' + ` plugin "${id}" must export a function, @@ -222,12 +230,12 @@ e.g. applyPluginHooks(key, opts = {}) { logger.debug(`[Plugin] applyPluginHooks( ${key} )`); - let defaultOpts = opts; - try { - defaultOpts = _.cloneDeep(opts); - } catch (error) { - logger.debug(`[Plugin] Plugin: ${key}, _.cloneDeep() error`); - } + const defaultOpts = opts; + // try { + // defaultOpts = _.cloneDeep(opts); + // } catch (error) { + // logger.debug(`[Plugin] Plugin: ${key}, _.cloneDeep() error`); + // } return (this.pluginHooks[key] || []).reduce((last, { fn }) => { try { return fn({ @@ -243,12 +251,12 @@ e.g. async applyPluginHooksAsync(key, opts = {}) { logger.debug(`[Plugin] applyPluginHooksAsync( ${key} )`); - let defaultOpts = opts; - try { - defaultOpts = _.cloneDeep(opts); - } catch (error) { - logger.debug(`[Plugin] Plugin: ${key}, _.cloneDeep() error`); - } + const defaultOpts = opts; + // try { + // defaultOpts = _.cloneDeep(opts); + // } catch (error) { + // logger.debug(`[Plugin] Plugin: ${key}, _.cloneDeep() error`); + // } const hooks = this.pluginHooks[key] || []; let last = opts; for (const hook of hooks) { From dabf60a5d94082b2c568d986621244754b6d78d7 Mon Sep 17 00:00:00 2001 From: zyao89 Date: Wed, 25 Sep 2019 02:04:50 +0800 Subject: [PATCH 03/10] =?UTF-8?q?:art:=20=E6=8F=90=E5=8F=96base,=20?= =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E5=A4=9A=E5=A4=84bug=E9=80=BB=E8=BE=91.=20?= =?UTF-8?q?=E5=A2=9E=E5=8A=A0=20microsExtraConfig=20=E6=96=B9=E6=B3=95=20?= =?UTF-8?q?=E7=AD=89.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 1 - config/constants.js | 2 +- libs/MicroAppConfig.js | 15 +----- libs/Service/BaseAPI.js | 18 ------- libs/Service/Constants.js | 3 +- libs/Service/PluginAPI.js | 42 ++------------- libs/Service/PluginAPI.test.js | 20 ++++++- libs/Service/base/BaseAPI.js | 53 ++++++++++++++++++ libs/Service/{ => base}/BaseAPI.test.js | 0 libs/Service/{Base.js => base/BaseService.js} | 54 +++++++++++++++---- libs/Service/index.js | 24 +++++---- micro-app.config.js | 30 ++++------- package.json | 2 +- plugins/commands/help.js | 2 +- plugins/commands/show.js | 20 ++++++- plugins/commands/show.test.js | 1 + test/index.js | 25 +++++---- test/semver.js | 23 ++++++++ utils/injectAliasModule.js | 3 +- utils/logger.js | 22 +++++--- 20 files changed, 222 insertions(+), 138 deletions(-) delete mode 100644 libs/Service/BaseAPI.js create mode 100644 libs/Service/base/BaseAPI.js rename libs/Service/{ => base}/BaseAPI.test.js (100%) rename libs/Service/{Base.js => base/BaseService.js} (78%) create mode 100644 test/semver.js diff --git a/README.md b/README.md index 302e97d..4898e4b 100644 --- a/README.md +++ b/README.md @@ -252,7 +252,6 @@ npx micro-app show methods * onServerRunFail ( 服务运行启动失败时事件 ) * beforeServerEntry ( 服务进入业务逻辑前事件 ) * afterServerEntry ( 服务从业务逻辑出来后事件 ) - * modifyWebpackConfig ( 对服务启动前对 webpack config 进行修改, 需要返回所有参数 ) * beforeDevServer ( 开发服务创建前事件 ) * afterDevServer ( 开发服务创建后事件 ) * onBuildSuccess ( 构建成功时事件 ) diff --git a/config/constants.js b/config/constants.js index 43ea062..75c610f 100644 --- a/config/constants.js +++ b/config/constants.js @@ -9,7 +9,7 @@ module.exports = { NODE_MODULES_NAME: 'node_modules', SCOPE_NAME: '@micro-app', // namespace CONFIG_NAME: 'micro-app.config.js', - EXTRAL_CONFIG_NAME: 'micro-app.extral.config.js', + EXTRAL_CONFIG_NAME: 'micro-app.extra.config.js', TYPES: [], // support types INJECT_ID: '_MICRO_APP_INJECT_', PACKAGE_JSON: 'package.json', diff --git a/libs/MicroAppConfig.js b/libs/MicroAppConfig.js index 29f32cf..3805e3b 100644 --- a/libs/MicroAppConfig.js +++ b/libs/MicroAppConfig.js @@ -72,7 +72,7 @@ class MicroAppConfig { return config[symbols.ORIGINAL_ROOT] || this.root || ''; } - get isOpenSoftLink() { + get hasSoftLink() { return this.root !== this.originalRoot; } @@ -414,16 +414,6 @@ class MicroAppConfig { return server.port; } - get contentBase() { - const server = this.server; - if (server.contentBase) { - return path.resolve(this.root, server.contentBase); - } else if (server.staticBase) { - return path.resolve(this.root, server.staticBase); - } - return '.'; - } - // 服务代理 get proxy() { const server = this.server; @@ -475,7 +465,7 @@ class MicroAppConfig { root: this.root, nodeModules: this.nodeModules, originalRoot: this.originalRoot, - isOpenSoftLink: this.isOpenSoftLink, + hasSoftLink: this.hasSoftLink, }; if (notSimple) { json.micros = this.micros; @@ -517,7 +507,6 @@ class MicroAppConfig { shared: this.shared, sharedObj: this._shared, resolveShared: this.resolveShared, - contentBase: this.contentBase, port: this.port, host: this.host, proxy: this.proxy, diff --git a/libs/Service/BaseAPI.js b/libs/Service/BaseAPI.js deleted file mode 100644 index 39c33fe..0000000 --- a/libs/Service/BaseAPI.js +++ /dev/null @@ -1,18 +0,0 @@ -'use strict'; - -const logger = require('../../utils/logger'); - -class BaseAPI { - - constructor() { - this.logger = logger; - - this.API_TYPE = { - ADD: Symbol('add'), - MODIFY: Symbol('modify'), - EVENT: Symbol('event'), - }; - } -} - -module.exports = BaseAPI; diff --git a/libs/Service/Constants.js b/libs/Service/Constants.js index b8600f3..8a20f4d 100644 --- a/libs/Service/Constants.js +++ b/libs/Service/Constants.js @@ -16,6 +16,7 @@ const contants = { }; }), + // service 对 pluginAPI 暴露的所有方法 SharedProps: [ 'root', 'mode', @@ -23,7 +24,7 @@ const contants = { 'env', 'version', 'pkg', - 'microsExtralConfig', + 'microsExtraConfig', 'microsExtralConfig', 'applyPluginHooks', 'applyPluginHooksAsync', 'resolvePlugin', diff --git a/libs/Service/PluginAPI.js b/libs/Service/PluginAPI.js index 7bd190c..d650bc4 100644 --- a/libs/Service/PluginAPI.js +++ b/libs/Service/PluginAPI.js @@ -2,20 +2,15 @@ const assert = require('assert'); const _ = require('lodash'); -const semver = require('semver'); -const BaseAPI = require('./BaseAPI'); +const BaseAPI = require('./base/BaseAPI'); const DEFAULT_METHODS = require('./methods'); const { SharedProps } = require('./Constants'); -const logger = require('../../utils/logger'); - class PluginAPI extends BaseAPI { constructor(id, service) { - super(); - this.id = id; - this.service = service; + super(id, service); this._addMethods(); } @@ -46,33 +41,6 @@ class PluginAPI extends BaseAPI { }); } - assertVersion(range) { - const version = this.service.version; - if (typeof range === 'number') { - if (!Number.isInteger(range)) { - throw new Error('Expected string or integer value.'); - } - range = `^${range}.0.0-0`; - } - if (typeof range !== 'string') { - throw new Error('Expected string or integer value.'); - } - - if (semver.satisfies(version, range)) return; - - throw new Error( - `Require @micro-app/core "${range}", but was loaded with "${version}".` - ); - } - - setState(key, value) { - this.service.state[key] = value; - } - - getState(key, value) { - return this.service.state[key] || value; - } - register(hook, fn, type) { assert( typeof hook === 'string', @@ -137,8 +105,8 @@ class PluginAPI extends BaseAPI { return this.service.registerCommand(name, opts, fn); } - extendMethod(name, fn) { - return this.service.extendMethod(name, fn); + extendMethod(name, opts, fn) { + return this.service.extendMethod(name, opts, fn); } registerPlugin(opts) { @@ -158,7 +126,7 @@ class PluginAPI extends BaseAPI { 'Only id, apply and opts is valid plugin properties' ); this.service.extraPlugins.push(opts); - logger.debug(`[Plugin] registerPlugin( ${id} ); Success!`); + this.logger.debug(`[Plugin] registerPlugin( ${id} ); Success!`); } } diff --git a/libs/Service/PluginAPI.test.js b/libs/Service/PluginAPI.test.js index fba1562..8edb576 100644 --- a/libs/Service/PluginAPI.test.js +++ b/libs/Service/PluginAPI.test.js @@ -56,7 +56,25 @@ describe('PluginAPI', () => { api.extendMethod('a', fn); expect(service.extendMethods.a).not.toBeUndefined(); expect(service.extendMethods.a).not.toBeNull(); - expect(service.extendMethods.a).toEqual(fn); + expect(service.extendMethods.a).toMatchObject({}); + expect(service.extendMethods.a.fn).toEqual(fn); + }); + + it('test extendMethod - 2', () => { + const service = new Service(); + const api = new PluginAPI('abc', service); + + const fn = args => { + console.log(args); + }; + api.extendMethod('a', { + description: 'abc', + }, fn); + expect(service.extendMethods.a).not.toBeUndefined(); + expect(service.extendMethods.a).not.toBeNull(); + expect(service.extendMethods.a).toMatchObject({}); + expect(service.extendMethods.a.fn).toEqual(fn); + expect(service.extendMethods.a.description).toEqual('abc'); }); }); diff --git a/libs/Service/base/BaseAPI.js b/libs/Service/base/BaseAPI.js new file mode 100644 index 0000000..296d53d --- /dev/null +++ b/libs/Service/base/BaseAPI.js @@ -0,0 +1,53 @@ +'use strict'; + +const semver = require('semver'); +const logger = require('../../../utils/logger'); +const CONSTANTS = require('../../../config/constants'); + +class BaseAPI { + + constructor(id, service) { + this.logger = logger; + + this.id = id; + this.service = service; + + this.API_TYPE = { + ADD: Symbol('add'), + MODIFY: Symbol('modify'), + EVENT: Symbol('event'), + }; + } + + get version() { + return this.service.version || CONSTANTS.VERSION; + } + + setState(key, value) { + this.service.state[key] = value; + } + + getState(key, value) { + return this.service.state[key] || value; + } + + assertVersion(range) { + if (typeof range === 'number') { + if (!Number.isInteger(range)) { + this.logger.throw('Expected string or integer value.'); + } + range = `^${range}.0.0-0`; + } + if (typeof range !== 'string') { + this.logger.throw('Expected string or integer value.'); + } + + const version = this.version; + + if (semver.satisfies(version, range)) return; + + this.logger.throw(`Require ${CONSTANTS.SCOPE_NAME}/core "${range}", but was loaded with "${version}".`); + } +} + +module.exports = BaseAPI; diff --git a/libs/Service/BaseAPI.test.js b/libs/Service/base/BaseAPI.test.js similarity index 100% rename from libs/Service/BaseAPI.test.js rename to libs/Service/base/BaseAPI.test.js diff --git a/libs/Service/Base.js b/libs/Service/base/BaseService.js similarity index 78% rename from libs/Service/Base.js rename to libs/Service/base/BaseService.js index 8143b4a..d2cc3ac 100644 --- a/libs/Service/Base.js +++ b/libs/Service/base/BaseService.js @@ -5,13 +5,13 @@ const assert = require('assert'); const _ = require('lodash'); const semverRegex = require('semver-regex'); -const CONSTANTS = require('../../config/constants'); +const CONSTANTS = require('../../../config/constants'); -const requireMicro = require('../../utils/requireMicro'); -const loadFile = require('../../utils/loadFile'); -const logger = require('../../utils/logger'); +const requireMicro = require('../../../utils/requireMicro'); +const loadFile = require('../../../utils/loadFile'); +const logger = require('../../../utils/logger'); -const { SharedProps } = require('./Constants'); +const { SharedProps } = require('../Constants'); const MICROS_EXTRAL_CONFIG_KEY = Symbol('MICROS_EXTRAL_CONFIG_KEY'); // 全局状态集 @@ -39,9 +39,15 @@ class BaseService { this.env = {}; // 环境变量 this.config = {}; this.serverConfig = {}; + this.state = GLOBAL_STATE; // 状态集 } + /** + * @private + * + * @memberof BaseService + */ __initDefaultEnv__() { const env = { VERSION: { @@ -58,9 +64,21 @@ class BaseService { }); } + /** + * @private + * + * @memberof BaseService + */ __initGlobalMicroAppConfig__() { // 加载高级配置 - this[MICROS_EXTRAL_CONFIG_KEY] = loadFile(this.root, CONSTANTS.EXTRAL_CONFIG_NAME); + const extraConfig = this[MICROS_EXTRAL_CONFIG_KEY] = loadFile(this.root, CONSTANTS.EXTRAL_CONFIG_NAME); + + if (extraConfig && _.isPlainObject(extraConfig)) { + Object.keys(extraConfig).forEach(key => { + const item = extraConfig[key]; + logger.debug(`【 Extra Config 】${key}: \n${JSON.stringify(item, false, 4)}`); + }); + } // 全局指令, 不可靠配置 if (!global.MicroAppConfig) { @@ -100,6 +118,10 @@ class BaseService { return _self; } + get microsExtraConfig() { + return this.microsExtralConfig; + } + get microsExtralConfig() { const microsExtral = this[MICROS_EXTRAL_CONFIG_KEY] || {}; const result = {}; @@ -111,10 +133,10 @@ class BaseService { }); // 附加内容需要参考全局配置 - if (!process.env.MICRO_APP_OPEN_SOFT_LINK) { // 强制禁止使用 软链接 + if (process.env.MICRO_APP_OPEN_SOFT_LINK !== 'true') { // 强制禁止使用 软链接 result[key].link = false; } - if (!process.env.MICRO_APP_OPEN_DISABLED_ENTRY) { // 强制禁止使用 开启禁用指定模块入口, 优化开发速度 + if (process.env.MICRO_APP_OPEN_DISABLED_ENTRY !== 'true') { // 强制禁止使用 开启禁用指定模块入口, 优化开发速度 result[key].disabled = false; result[key].disable = false; } @@ -178,12 +200,22 @@ class BaseService { } } - extendMethod(name, fn) { + extendMethod(name, opts, fn) { assert(typeof name === 'string', 'name must be string.'); assert(name || /^_/i.test(name), `${name} cannot begin with '_'.`); assert(!this[name] || !this.extendMethods[name] || !this.pluginMethods[name] || !SharedProps.includes(name), `api.${name} exists.`); - assert(typeof fn === 'function', 'opts must be function.'); - this.extendMethods[name] = fn; + if (typeof opts === 'function') { + fn = opts; + opts = null; + } + assert(typeof fn === 'function', 'fn must be function.'); + opts = opts || {}; + assert(_.isPlainObject(opts), 'opts must be object.'); + this.extendMethods[name] = { + ...opts, + fn, + }; + logger.debug(`[Plugin] extendMethods( ${name} ); Success!`); } registerCommand(name, opts, fn) { diff --git a/libs/Service/index.js b/libs/Service/index.js index 1a212dd..ad32781 100644 --- a/libs/Service/index.js +++ b/libs/Service/index.js @@ -5,7 +5,7 @@ const assert = require('assert'); const merge = require('webpack-merge'); const _ = require('lodash'); -const BaseService = require('./Base'); +const BaseService = require('./base/BaseService'); const logger = require('../../utils/logger'); @@ -71,8 +71,7 @@ class Service extends BaseService { 'onOptionChange', ].includes(method)) { plugin._api[method] = () => { - logger.error(`api.${method}() should not be called after plugin is initialized.`); - throw Error(); + logger.throw(`api.${method}() should not be called after plugin is initialized.`); }; } }); @@ -102,7 +101,7 @@ e.g. return; // ban private } if (this.extendMethods[prop]) { - return this.extendMethods[prop]; + return this.extendMethods[prop].fn; } if (this.pluginMethods[prop]) { return this.pluginMethods[prop].fn; @@ -173,7 +172,6 @@ e.g. 'host', 'port', ]), - contentBase: selfServerConfig.contentBase || selfServerConfig.staticBase, entrys: serverEntrys, hooks: serverHooks, }); @@ -219,6 +217,7 @@ e.g. const defaultConfig = apply.configuration || {}; return Object.assign({}, defaultConfig, { ...item, + link: require.resolve(link), apply: apply.default || apply, opts, }); @@ -243,8 +242,7 @@ e.g. args: defaultOpts, }); } catch (e) { - logger.error(`[Plugin] Plugin apply failed: ${e.message}`); - throw e; + logger.throw(`[Plugin] Plugin apply failed: ${e.message}`); } }, opts); } @@ -290,10 +288,12 @@ e.g. if (this.initialized) { return; } - this.initialized = true; this._initDotEnv(); this._initPlugins(); + + this.initialized = true; // 再此之前可重新 init + this.applyPluginHooks('onPluginInitDone'); // merge config this.applyPluginHooks('beforeMergeConfig', this.config); @@ -303,9 +303,10 @@ e.g. // 注入全局的别名 injectAliasModule(this.config.resolveShared); + const microsExtralConfig = this.microsExtralConfig; injectAliasModulePath(Array.from(this.micros) .map(key => this.microsConfig[key]) - .filter(item => item.isOpenSoftLink) + .filter(item => item.hasSoftLink && !!microsExtralConfig[item.key].link) .map(item => item.nodeModules)); // merge server @@ -325,7 +326,7 @@ e.g. return this.runCommand(name, args); } - runCommand(rawName, rawArgs) { + runCommand(rawName, rawArgs = { _: [] }) { logger.debug(`[Plugin] raw command name: ${rawName}, args: `, rawArgs); const { name = rawName, args } = this.applyPluginHooks('modifyCommand', { name: rawName, @@ -336,12 +337,13 @@ e.g. const command = this.commands[name]; if (!command) { logger.error(`Command "${name}" does not exists`); - process.exit(1); + return this.runCommand('help', { _: [] }); } const { fn, opts } = command; this.applyPluginHooks('onRunCommand', { name, + args, opts, }); diff --git a/micro-app.config.js b/micro-app.config.js index f4287b5..db685ba 100644 --- a/micro-app.config.js +++ b/micro-app.config.js @@ -45,7 +45,7 @@ module.exports = { strict: true, - micros: [ 'test' ], // 被注册的容器 + // micros: [ 'test' ], // 被注册的容器 // micros$$test: { // 单独配置 // disabled: true, // 禁用入口 // link: '', // 本地路径, 进行本地开发使用的软链接. @@ -60,23 +60,13 @@ module.exports = { }, }, - plugins: [ - [{ - id: 'test', - description: '这是test', - link: __dirname + '/test/testPlugin', - }, { - a: 1, - }], - ], - - // deploy: { - // git: 'git+ssh://git@xxxxx.git', - // branch: 'test', - // // branch: { - // // name: 'develop', - // // extends: true, - // // }, - // message: '', // 提交 message 中增加内容 - // }, + // plugins: [ + // [{ + // id: 'test', + // description: '这是test', + // link: __dirname + '/test/testPlugin', + // }, { + // a: 1, + // }], + // ], }; diff --git a/package.json b/package.json index 0eae250..f84c6ed 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@micro-app/core", - "version": "0.1.3", + "version": "0.1.4-beta.3", "description": "[Core] Pluggable micro application framework.", "main": "src/index.js", "scripts": { diff --git a/plugins/commands/help.js b/plugins/commands/help.js index 998771a..6170e49 100644 --- a/plugins/commands/help.js +++ b/plugins/commands/help.js @@ -43,7 +43,7 @@ module.exports = function(api) { function logHelpForCommand(name, command) { if (!command) { - api.logger.error(`\n command "${name}" does not exist.`); + api.logger.error(`\n Command "${name}" does not exist.`); } else { const opts = command.opts || {}; if (opts.usage) { diff --git a/plugins/commands/show.js b/plugins/commands/show.js index cd6e4dd..81cb329 100644 --- a/plugins/commands/show.js +++ b/plugins/commands/show.js @@ -33,6 +33,7 @@ Examples: }, args => { const pluginHooks = api.service.pluginHooks; const pluginMethods = api.service.pluginMethods; + const extendMethods = api.service.extendMethods; const plugins = api.service.plugins; const info = api.self.toJSON(true); const env = api.env || {}; @@ -62,6 +63,14 @@ Examples: }; return obj; }, {})); + case 'process.env': + api.logger.logo(`${chalk.green('Process Env List')}:`); + return showAliasList(Object.keys(process.env).reduce((obj, key) => { + obj[key] = { + description: process.env[key], + }; + return obj; + }, {})); case 'micros': api.logger.logo(`${chalk.green('Micros List')}:`); return showAliasList(micros.reduce((obj, key) => { @@ -88,11 +97,18 @@ Examples: }, {})); case 'methods': api.logger.logo(`${chalk.green('Plugin Methods')}:`); - return showAliasList(pluginMethods); + showAliasList(pluginMethods); + return showAliasList(extendMethods); case 'plugins': api.logger.logo(`${chalk.green('Plugin List')}:`); return showAliasList(plugins.reduce((obj, item) => { - obj[item.id] = { description: item.description, link: args.link && item.link }; + let key = item.id; + let i = 0; + while (obj[key]) { + i++; + key = `${key} (${i})`; + } + obj[key] = { description: item.description, link: args.link && item.link }; return obj; }, {})); case 'hooks': diff --git a/plugins/commands/show.test.js b/plugins/commands/show.test.js index 5cd488b..bc6a0ed 100644 --- a/plugins/commands/show.test.js +++ b/plugins/commands/show.test.js @@ -108,6 +108,7 @@ describe('show', () => { }); api.service = { pluginMethods: [ 'a', 'b', 'c' ], + extendMethods: {}, }; show(api); }); diff --git a/test/index.js b/test/index.js index 72dc3ce..9962618 100644 --- a/test/index.js +++ b/test/index.js @@ -43,17 +43,17 @@ // console.log(a); const logger = require('../utils/logger'); -logger.error('abc'); -logger.info('abc'); -logger.success('abc'); -logger.logo('abc'); -logger.warn('abc'); -logger.debug('abc'); -const spinner = logger.spinner('abc'); -spinner.start(); -setTimeout(() => { - spinner.fail('cc'); -}, 3000); +// logger.error('abc'); +// logger.info('abc'); +// logger.success('abc'); +// logger.logo('abc'); +// logger.warn('abc'); +// logger.debug('abc'); +// const spinner = logger.spinner('abc'); +// spinner.start(); +// setTimeout(() => { +// spinner.fail('cc'); +// }, 3000); // const _ = require('lodash'); @@ -64,3 +64,6 @@ setTimeout(() => { // const c = _.merge({}, a, b); // logger.debug(c); // logger.warn(wmerge.smart(a, b)); + + +logger.throw('abc'); diff --git a/test/semver.js b/test/semver.js new file mode 100644 index 0000000..b8b4187 --- /dev/null +++ b/test/semver.js @@ -0,0 +1,23 @@ +'use strict'; + +const semver = require('semver'); +const logger = require('../utils/logger'); + +function assertVersion(range) { + const version = '0.1.4'; + if (typeof range === 'number') { + if (!Number.isInteger(range)) { + logger.throw('Expected string or integer value.'); + } + range = `^${range}.0.0-0`; + } + if (typeof range !== 'string') { + logger.throw('Expected string or integer value.'); + } + + if (semver.satisfies(version, range)) return; + + logger.throw(`Require @micro-app/core "${range}", but was loaded with "${version}".`); +} + +assertVersion('>0.0.0'); diff --git a/utils/injectAliasModule.js b/utils/injectAliasModule.js index c72133f..427e170 100644 --- a/utils/injectAliasModule.js +++ b/utils/injectAliasModule.js @@ -1,7 +1,6 @@ 'use strict'; -const tryRequire = require('try-require'); -const moduleAlias = tryRequire('module-alias'); +const moduleAlias = require('module-alias'); function injectAliasModule(alias) { if (alias && JSON.stringify(alias) !== '{}') { diff --git a/utils/logger.js b/utils/logger.js index 3f0f49f..3ea0fd4 100644 --- a/utils/logger.js +++ b/utils/logger.js @@ -9,28 +9,28 @@ const CONSTANTS = require('../config/constants'); const toString = { debug() { const message = utils.format(...(arguments || [])); - return `${chalk.bgMagenta(' DEBUG ')} ${message} \n`; + return `${chalk.bgMagenta(' DEBUG ')} ${message} \r\n`; }, warn() { const message = utils.format(...(arguments || [])); - return `${chalk.bgYellowBright.black(' WARN ')} ${chalk.yellowBright(message)} \n`; + return `${chalk.bgYellowBright.black(' WARN ')} ${chalk.yellowBright(message)} \r\n`; }, error() { const message = utils.format(...(arguments || [])); - return `${chalk.bgRed(' ERROR ')} ${chalk.redBright(message)} \n`; + return `${chalk.bgRed(' ERROR ')} ${chalk.redBright(message)} \r\n`; }, info() { const message = utils.format(...(arguments || [])); - return `${chalk.bgBlue(' INFO ')} ${chalk.blueBright(message)} \n`; + return `${chalk.bgBlue(' INFO ')} ${chalk.blueBright(message)} \r\n`; }, success() { const message = utils.format(...(arguments || [])); - return `${chalk.bgHex('#007007')(' SUCCESS ')} ${chalk.greenBright(message)} \n`; + return `${chalk.bgHex('#007007')(' SUCCESS ')} ${chalk.greenBright(message)} \r\n`; }, logo() { const message = utils.format(...(arguments || [])); const { NAME } = CONSTANTS; - return `${chalk.bgHex('#662F88')(` ${NAME} `)} ${message} \n`; + return `${chalk.bgHex('#662F88')(` ${NAME} `)} ${message} \r\n`; }, }; @@ -43,7 +43,7 @@ module.exports = { return process.stdout.write(toString.warn.call(toString, ...arguments)); }, error() { - return process.stdout.write(toString.error.call(toString, ...arguments)); + return process.stderr.write(toString.error.call(toString, ...arguments)); }, info() { return process.stdout.write(toString.info.call(toString, ...arguments)); @@ -63,4 +63,12 @@ module.exports = { return ora(typeof message === 'string' ? defulatOpts : Object.assign({}, defulatOpts, message)); }, toString, + + throw() { + this.error(...arguments); + const error = new Error(); + const stack = error.stack.split(/\r?\n/mg); + process.stderr.write(chalk.grey(stack.slice(2).join('\r\n')) + '\r\n'); + process.exit(1); + }, }; From 6b50ed1857983281bcb58d50a8e5e0adfb0659ed Mon Sep 17 00:00:00 2001 From: zyao89 Date: Wed, 25 Sep 2019 09:35:13 +0800 Subject: [PATCH 04/10] :enhance: update --- utils/loadFile.js | 2 +- utils/requireMicro.js | 6 +++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/utils/loadFile.js b/utils/loadFile.js index 10c487e..96744f7 100644 --- a/utils/loadFile.js +++ b/utils/loadFile.js @@ -6,7 +6,7 @@ const path = require('path'); const symbols = require('../config/symbols'); function isSupport(filename) { - return [ '.js' ].some(ext => { + return [ '.js', '.json' ].some(ext => { return filename.endsWith(ext); }); } diff --git a/utils/requireMicro.js b/utils/requireMicro.js index d998860..b26bbe4 100644 --- a/utils/requireMicro.js +++ b/utils/requireMicro.js @@ -80,6 +80,10 @@ const requireMicro = function(id) { return null; }; -requireMicro.self = self; module.exports = requireMicro; + +module.exports.self = self; + +module.exports._cache = configCache; +module.exports._selfKey = SELF_CONFIG; From 30b4fe3a7422fc5bba971f68b227cc9545086d93 Mon Sep 17 00:00:00 2001 From: zyao89 Date: Sat, 28 Sep 2019 21:21:44 +0800 Subject: [PATCH 05/10] =?UTF-8?q?:bug:=20fixed=20node=5Fmodules=20?= =?UTF-8?q?=E4=B8=8D=E7=BB=9F=E4=B8=80=E7=9A=84=E9=97=AE=E9=A2=98.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- config/default.js | 13 ------------- libs/Service/base/BaseService.js | 12 +++++++++--- libs/Service/index.js | 18 ++++++++++++------ micro-app.extra.config.js | 8 ++++++++ package.json | 2 +- test/semver.js | 4 ++-- 6 files changed, 32 insertions(+), 25 deletions(-) create mode 100644 micro-app.extra.config.js diff --git a/config/default.js b/config/default.js index d772fe4..2191550 100644 --- a/config/default.js +++ b/config/default.js @@ -27,9 +27,6 @@ module.exports = { // }, ], - webpack: { // webpack 配置信息 (只有自己为主容器时,才会使用) - }, - alias: { // 共享别名 // api: './client/api.js', // 默认为前后端通用 // service: { @@ -41,10 +38,6 @@ module.exports = { micros: [ // 需要注入的子模块 // 'test' ], - // micros$$test: { // 单独配置 - // disabled: true, // 禁用入口 - // lnk: '‘, // 软链接, 用于本地调试 - // }, // 服务端配置 server: { @@ -63,12 +56,6 @@ module.exports = { // }, }, - // 自动向主容器同步 package.json - deploy: { - // git: 'ssh://git@....git', - // branch: 'develop', - }, - // 一些插件配置项 (弃用) // plugin: { // ReplaceFileNotExists: { diff --git a/libs/Service/base/BaseService.js b/libs/Service/base/BaseService.js index d2cc3ac..1b6055b 100644 --- a/libs/Service/base/BaseService.js +++ b/libs/Service/base/BaseService.js @@ -11,6 +11,8 @@ const requireMicro = require('../../../utils/requireMicro'); const loadFile = require('../../../utils/loadFile'); const logger = require('../../../utils/logger'); +const { injectAliasModulePath } = require('../../../utils/injectAliasModule'); + const { SharedProps } = require('../Constants'); const MICROS_EXTRAL_CONFIG_KEY = Symbol('MICROS_EXTRAL_CONFIG_KEY'); @@ -25,10 +27,14 @@ class BaseService { this.pluginMethods = {}; this.commands = {}; + // fixed soft link - node_modules 不统一 + const _self = this.self; + injectAliasModulePath([ _self.nodeModules ]); + // 当前服务 - this.selfConfig = this.self.toConfig(true); - this.selfServerConfig = this.self.toServerConfig(true); - this.micros = new Set((this.self.micros || [])); + this.selfConfig = _self.toConfig(true); + this.selfServerConfig = _self.toServerConfig(true); + this.micros = new Set((_self.micros || [])); this.__initDefaultEnv__(); this.__initGlobalMicroAppConfig__(); diff --git a/libs/Service/index.js b/libs/Service/index.js index ad32781..fbccf3f 100644 --- a/libs/Service/index.js +++ b/libs/Service/index.js @@ -64,6 +64,10 @@ class Service extends BaseService { // TODO 排序重组, reload(); + + // 过滤掉没有初始化的 plugin + this.plugins = this.plugins.filter(plugin => !!plugin._api); + // Throw error for methods that can't be called after plugins is initialized this.plugins.forEach(plugin => { Object.keys(plugin._api).forEach(method => { @@ -84,7 +88,7 @@ class Service extends BaseService { const { id, apply, opts = {}, mode } = plugin; if (mode && mode !== this.mode) { // 当前模式与插件不匹配 - logger.warn(`[Plugin] _initPlugin() skip "${id}"`); + logger.warn(`[Plugin] {${this.mode}} - initPlugin() skip "${id}"`); return; } assert(typeof apply === 'function', @@ -294,6 +298,13 @@ e.g. this.initialized = true; // 再此之前可重新 init + // 注入 custom node_modules + const microsExtralConfig = this.microsExtralConfig; + injectAliasModulePath(Array.from(this.micros) + .map(key => this.microsConfig[key]) + .filter(item => item.hasSoftLink && !!microsExtralConfig[item.key].link) + .map(item => item.nodeModules)); + this.applyPluginHooks('onPluginInitDone'); // merge config this.applyPluginHooks('beforeMergeConfig', this.config); @@ -303,11 +314,6 @@ e.g. // 注入全局的别名 injectAliasModule(this.config.resolveShared); - const microsExtralConfig = this.microsExtralConfig; - injectAliasModulePath(Array.from(this.micros) - .map(key => this.microsConfig[key]) - .filter(item => item.hasSoftLink && !!microsExtralConfig[item.key].link) - .map(item => item.nodeModules)); // merge server this.applyPluginHooks('beforeMergeServerConfig', this.serverConfig); diff --git a/micro-app.extra.config.js b/micro-app.extra.config.js new file mode 100644 index 0000000..957d391 --- /dev/null +++ b/micro-app.extra.config.js @@ -0,0 +1,8 @@ +'use strict'; + +module.exports = { + test: { // 单独配置 + disabled: true, // 禁用入口 + link: '', // 本地路径, 进行本地开发使用的软链接. + }, +}; diff --git a/package.json b/package.json index f84c6ed..f60034a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@micro-app/core", - "version": "0.1.4-beta.3", + "version": "0.1.6", "description": "[Core] Pluggable micro application framework.", "main": "src/index.js", "scripts": { diff --git a/test/semver.js b/test/semver.js index b8b4187..1b2cfe7 100644 --- a/test/semver.js +++ b/test/semver.js @@ -4,7 +4,7 @@ const semver = require('semver'); const logger = require('../utils/logger'); function assertVersion(range) { - const version = '0.1.4'; + const version = require('../package.json').version; if (typeof range === 'number') { if (!Number.isInteger(range)) { logger.throw('Expected string or integer value.'); @@ -20,4 +20,4 @@ function assertVersion(range) { logger.throw(`Require @micro-app/core "${range}", but was loaded with "${version}".`); } -assertVersion('>0.0.0'); +assertVersion('>=0.1.5'); From 094528eb6e2549eb8e128c55af91e1e8a88ea595 Mon Sep 17 00:00:00 2001 From: zyao89 Date: Sat, 28 Sep 2019 21:23:41 +0800 Subject: [PATCH 06/10] :update: version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index f60034a..8d46376 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@micro-app/core", - "version": "0.1.6", + "version": "0.1.7", "description": "[Core] Pluggable micro application framework.", "main": "src/index.js", "scripts": { From 9e1a3afaaacb2cc61a42dc02d0f28c108488eb9a Mon Sep 17 00:00:00 2001 From: zyao89 Date: Sun, 29 Sep 2019 02:00:02 +0800 Subject: [PATCH 07/10] :bug: fixed bug. fork module-alias. --- libs/MicroAppConfig.js | 2 +- libs/Service/base/BaseService.js | 30 ++--- libs/Service/index.js | 20 ++- package.json | 3 +- utils/injectAliasModule.js | 2 +- utils/module-alias/README.md | 159 +++++++++++++++++++++++ utils/module-alias/index.js | 212 +++++++++++++++++++++++++++++++ utils/module-alias/register.js | 3 + yarn.lock | 5 - 9 files changed, 401 insertions(+), 35 deletions(-) create mode 100644 utils/module-alias/README.md create mode 100644 utils/module-alias/index.js create mode 100644 utils/module-alias/register.js diff --git a/libs/MicroAppConfig.js b/libs/MicroAppConfig.js index 3805e3b..2a2b227 100644 --- a/libs/MicroAppConfig.js +++ b/libs/MicroAppConfig.js @@ -442,7 +442,7 @@ class MicroAppConfig { p = p.link; } id = id || p; - if (!tryRequire.resolve(p)) { + if (p && !tryRequire.resolve(p)) { p = path.resolve(this.root, p); } return { diff --git a/libs/Service/base/BaseService.js b/libs/Service/base/BaseService.js index 1b6055b..6a333e8 100644 --- a/libs/Service/base/BaseService.js +++ b/libs/Service/base/BaseService.js @@ -1,6 +1,5 @@ 'use strict'; -const tryRequire = require('try-require'); const assert = require('assert'); const _ = require('lodash'); const semverRegex = require('semver-regex'); @@ -11,8 +10,6 @@ const requireMicro = require('../../../utils/requireMicro'); const loadFile = require('../../../utils/loadFile'); const logger = require('../../../utils/logger'); -const { injectAliasModulePath } = require('../../../utils/injectAliasModule'); - const { SharedProps } = require('../Constants'); const MICROS_EXTRAL_CONFIG_KEY = Symbol('MICROS_EXTRAL_CONFIG_KEY'); @@ -27,9 +24,7 @@ class BaseService { this.pluginMethods = {}; this.commands = {}; - // fixed soft link - node_modules 不统一 const _self = this.self; - injectAliasModulePath([ _self.nodeModules ]); // 当前服务 this.selfConfig = _self.toConfig(true); @@ -184,22 +179,19 @@ class BaseService { _initDotEnv() { const env = process.env.NODE_ENV; - const dotenv = tryRequire('dotenv'); - if (dotenv) { - const result = dotenv.config(); - if (result.error) { - logger.error(result.error); - } else if (result.parsed) { - const config = result.parsed; - if (config.HOSTNAME) { // fixed - process.env.HOSTNAME = config.HOSTNAME; - } - Object.assign(this.env, config); - logger.debug('dotenv parsed envs:\n', JSON.stringify(this.env, null, 4)); + const dotenv = require('dotenv'); + const result = dotenv.config(); + if (result.error) { + logger.error(result.error); + } else if (result.parsed) { + const config = result.parsed; + if (config.HOSTNAME) { // fixed + process.env.HOSTNAME = config.HOSTNAME; } - } else { - logger.warn('Not Found "dotenv"'); + Object.assign(this.env, config); + logger.debug('dotenv parsed envs:\n', JSON.stringify(this.env, null, 4)); } + if (env === 'production') { // fixed this.env.NODE_ENV = env; process.env.NODE_ENV = env; diff --git a/libs/Service/index.js b/libs/Service/index.js index fbccf3f..5355171 100644 --- a/libs/Service/index.js +++ b/libs/Service/index.js @@ -22,10 +22,23 @@ class Service extends BaseService { super(); this.initialized = false; + // fixed soft link - node_modules 不统一 + this.__initInjectAliasModule__(); + this.plugins = PreLoadPlugins.map(this.resolvePlugin).filter(item => !!item); this.extraPlugins = []; // 临时存储扩展模块 } + __initInjectAliasModule__() { + injectAliasModulePath(this.self.nodeModules); + // 注入 custom node_modules + const microsExtralConfig = this.microsExtralConfig; + injectAliasModulePath(Array.from(this.micros) + .map(key => this.microsConfig[key]) + .filter(item => item.hasSoftLink && !!microsExtralConfig[item.key].link) + .map(item => item.nodeModules)); + } + _getPlugins() { const micros = Array.from(this.micros); const plugins = this.selfConfig.plugins || []; @@ -298,13 +311,6 @@ e.g. this.initialized = true; // 再此之前可重新 init - // 注入 custom node_modules - const microsExtralConfig = this.microsExtralConfig; - injectAliasModulePath(Array.from(this.micros) - .map(key => this.microsConfig[key]) - .filter(item => item.hasSoftLink && !!microsExtralConfig[item.key].link) - .map(item => item.nodeModules)); - this.applyPluginHooks('onPluginInitDone'); // merge config this.applyPluginHooks('beforeMergeConfig', this.config); diff --git a/package.json b/package.json index 8d46376..3278ba1 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@micro-app/core", - "version": "0.1.7", + "version": "0.1.8", "description": "[Core] Pluggable micro application framework.", "main": "src/index.js", "scripts": { @@ -52,7 +52,6 @@ "cheerio": "^1.0.0-rc.3", "dotenv": "^8.1.0", "lodash": "^4.17.15", - "module-alias": "^2.2.1", "ora": "^3.4.0", "semver": "^6.3.0", "semver-regex": "^3.1.0", diff --git a/utils/injectAliasModule.js b/utils/injectAliasModule.js index 427e170..df23873 100644 --- a/utils/injectAliasModule.js +++ b/utils/injectAliasModule.js @@ -1,6 +1,6 @@ 'use strict'; -const moduleAlias = require('module-alias'); +const moduleAlias = require('./module-alias'); function injectAliasModule(alias) { if (alias && JSON.stringify(alias) !== '{}') { diff --git a/utils/module-alias/README.md b/utils/module-alias/README.md new file mode 100644 index 0000000..0faaafa --- /dev/null +++ b/utils/module-alias/README.md @@ -0,0 +1,159 @@ +# module-alias +[![NPM Version][npm-image]][npm-url] +[![Build Status][travis-image]][travis-url] + +Create aliases of directories and register custom module paths in NodeJS like a boss! + +No more shit-coding paths in Node like so: + +```js +require('../../../../some/very/deep/module') +``` +Enough of this madness! + +Just create an alias and do it the right way: + +```js +var module = require('@deep/module') +// Or ES6 +import module from '@deep/module' +``` + +It also allows you to register directories that will act just like `node_modules` but with your own private modules, so that you can access them directly: + +```js +require('my_private_module'); +// Or ES6 +import module from 'my_private_module' +``` + +**WARNING:** This module should not be used in other npm modules since it modifies the default `require` behavior! It is designed to be used for development of final projects i.e. web-sites, applications etc. + +## Install + +``` +npm i --save module-alias +``` + +## Usage + +Add your custom configuration to your `package.json` (in your application's root) + +```js +// Aliases +"_moduleAliases": { + "@root" : ".", // Application's root + "@deep" : "src/some/very/deep/directory/or/file", + "@my_module" : "lib/some-file.js", + "something" : "src/foo", // Or without @. Actually, it could be any string +} + +// Custom module directories, just like `node_modules` but with your private modules (optional) +"_moduleDirectories": ["node_modules_custom"], +``` + +Then add this line at the very main file of your app, before any code + +```js +require('module-alias/register') +``` + +**And you're all set!** Now you can do stuff like: + +```js +require('something') +const module = require('@root/some-module') +const veryDeepModule = require('@deep/my-module') +const customModule = require('my_private_module') // module from `node_modules_custom` directory + +// Or ES6 +import 'something' +import module from '@root/some-module' +import veryDeepModule from '@deep/my-module' +import customModule from 'my_private_module' // module from `node_modules_custom` directory +``` + +## Advanced usage + +If you don't want to modify your `package.json` or you just prefer to set it all up programmatically, then the following methods are available for you: + +* `addAlias('alias', 'target_path')` - register a single alias +* `addAliases({ 'alias': 'target_path', ... }) ` - register multiple aliases +* `addPath(path)` - Register custom modules directory (like node_modules, but with your own modules) + +_Examples:_ +```js +const moduleAlias = require('module-alias') + +// +// Register alias +// +moduleAlias.addAlias('@client', __dirname + '/src/client') + +// Or multiple aliases +moduleAlias.addAliases({ + '@root' : __dirname, + '@client': __dirname + '/src/client', + ... +}) + +// Custom handler function (starting from v2.1) +moduleAlias.addAlias('@src', (fromPath, request, alias) => { + // fromPath - Full path of the file from which `require` was called + // request - The path (first argument) that was passed into `require` + // alias - The same alias that was passed as first argument to `addAlias` (`@src` in this case) + + // Return any custom target path for the `@src` alias depending on arguments + if (fromPath.startsWith(__dirname + '/others')) return __dirname + '/others' + return __dirname + '/src' +}) + +// +// Register custom modules directory +// +moduleAlias.addPath(__dirname + '/node_modules_custom') +moduleAlias.addPath(__dirname + '/src') + +// +// Import settings from a specific package.json +// +moduleAlias(__dirname + '/package.json') + +// Or let mudule-alias to figure where your package.json is +// located. By default it will look in the same directory +// where you have your node_modules (application's root) +moduleAlias() +``` + +## Usage with WebPack + +Luckily, WebPack has a built in support for aliases and custom modules directories so it's easy to make it work on the client side as well! + +```js +// webpack.config.js +const npm_package = require('./package.json') + +module.exports = { + entry: { ... }, + resolve: { + root: __dirname, + alias: npm_package._moduleAliases || {}, + modules: npm_package._moduleDirectories || [] // eg: ["node_modules", "node_modules_custom", "src"] + } +} +``` + +## How it works? + +In order to register an alias it modifies the internal `Module._resolveFilename` method so that when you use `require` or `import` it first checks whether the given string starts with one of the registered aliases, if so, it replaces the alias in the string with the target path of the alias. + +In order to register a custom modules path (`addPath`) it modifies the internal `Module._nodeModulePaths` method so that the given directory then acts like it's the `node_modules` directory. + +[npm-image]: https://img.shields.io/npm/v/module-alias.svg +[npm-url]: https://npmjs.org/package/module-alias +[travis-image]: https://img.shields.io/travis/ilearnio/module-alias/master.svg +[travis-url]: https://travis-ci.org/ilearnio/module-alias + +## Refactor your code (for already existing projects) + +If you are using this on an existing project, you can use [relative-to-alias](https://github.com/s-yadav/relative-to-alias) to refactor your code to start using aliases. diff --git a/utils/module-alias/index.js b/utils/module-alias/index.js new file mode 100644 index 0000000..0056b06 --- /dev/null +++ b/utils/module-alias/index.js @@ -0,0 +1,212 @@ +'use strict'; + +const BuiltinModule = require('module'); + +// Guard against poorly mocked module constructors +const Module = module.constructor.length > 1 + ? module.constructor + : BuiltinModule; + +const nodePath = require('path'); + +let modulePaths = []; +let moduleAliases = {}; +let moduleAliasNames = []; + +const oldNodeModulePaths = Module._nodeModulePaths; +Module._nodeModulePaths = function(from) { + let paths = oldNodeModulePaths.call(this, from); + + // Only include the module path for top-level modules + // that were not installed: + if (from.indexOf('node_modules') === -1) { + paths = [ ...new Set(modulePaths.concat(paths)) ]; + } + + return paths; +}; + +const oldResolveFilename = Module._resolveFilename; +Module._resolveFilename = function(request, parentModule, isMain, options) { + for (let i = moduleAliasNames.length; i-- > 0;) { + const alias = moduleAliasNames[i]; + if (isPathMatchesAlias(request, alias)) { + let aliasTarget = moduleAliases[alias]; + // Custom function handler + if (typeof moduleAliases[alias] === 'function') { + const fromPath = parentModule.filename; + aliasTarget = moduleAliases[alias](fromPath, request, alias); + if (!aliasTarget || typeof aliasTarget !== 'string') { + throw new Error('[module-alias] Expecting custom handler function to return path.'); + } + } + request = nodePath.join(aliasTarget, request.substr(alias.length)); + // Only use the first match + break; + } + } + + return oldResolveFilename.call(this, request, parentModule, isMain, options); +}; + +function isPathMatchesAlias(path, alias) { + // Matching /^alias(\/|$)/ + if (path.indexOf(alias) === 0) { + if (path.length === alias.length) return true; + if (path[alias.length] === '/') return true; + } + + return false; +} + +function addPathHelper(path, targetArray) { + path = nodePath.normalize(path); + if (targetArray && targetArray.indexOf(path) === -1) { + targetArray.push(path); + } +} + +function removePathHelper(path, targetArray) { + if (targetArray) { + const index = targetArray.indexOf(path); + if (index !== -1) { + targetArray.splice(index, 1); + } + } +} + +function addPath(path) { + let parent; + path = nodePath.normalize(path); + + if (modulePaths.indexOf(path) === -1) { + modulePaths.push(path); + // Enable the search path for the current top-level module + addPathHelper(path, require.main.paths); + parent = module.parent; + + // Also modify the paths of the module that was used to load the + // app-module-paths module and all of it's parents + while (parent && parent !== require.main) { + addPathHelper(path, parent.paths); + parent = parent.parent; + } + } +} + +function addAliases(aliases) { + for (const alias in aliases) { + addAlias(alias, aliases[alias]); + } +} + +function addAlias(alias, target) { + moduleAliases[alias] = target; + // Cost of sorting is lower here than during resolution + moduleAliasNames = Object.keys(moduleAliases); + moduleAliasNames.sort(); +} + +/** + * Reset any changes maded (resets all registered aliases + * and custom module directories) + * The function is undocumented and for testing purposes only + */ +function reset() { + // Reset all changes in paths caused by addPath function + modulePaths.forEach(function(path) { + removePathHelper(path, require.main.paths); + + // Delete from require.cache if the module has been required before. + // This is required for node >= 11 + Object.getOwnPropertyNames(require.cache).forEach(function(name) { + if (name.indexOf(path) !== -1) { + delete require.cache[name]; + } + }); + + let parent = module.parent; + while (parent && parent !== require.main) { + removePathHelper(path, parent.paths); + parent = parent.parent; + } + }); + + modulePaths = []; + moduleAliases = {}; +} + +/** + * Import aliases from package.json + * @param {object} options + */ +function init(options) { + if (typeof options === 'string') { + options = { base: options }; + } + + options = options || {}; + + let candidatePackagePaths; + if (options.base) { + candidatePackagePaths = [ nodePath.resolve(options.base.replace(/\/package\.json$/, '')) ]; + } else { + // There is probably 99% chance that the project root directory in located + // above the node_modules directory, + // Or that package.json is in the node process' current working directory (when + // running a package manager script, e.g. `yarn start` / `npm run start`) + candidatePackagePaths = [ nodePath.join(__dirname, '../..'), process.cwd() ]; + } + + let npmPackage; + let base; + for (const i in candidatePackagePaths) { + try { + base = candidatePackagePaths[i]; + + npmPackage = require(nodePath.join(base, 'package.json')); + break; + } catch (e) { + // noop + } + } + + if (typeof npmPackage !== 'object') { + const pathString = candidatePackagePaths.join(',\n'); + throw new Error('Unable to find package.json in any of:\n[' + pathString + ']'); + } + + // + // Import aliases + // + + const aliases = npmPackage._moduleAliases || {}; + + for (const alias in aliases) { + if (aliases[alias][0] !== '/') { + aliases[alias] = nodePath.join(base, aliases[alias]); + } + } + + addAliases(aliases); + + // + // Register custom module directories (like node_modules) + // + + if (npmPackage._moduleDirectories instanceof Array) { + npmPackage._moduleDirectories.forEach(function(dir) { + if (dir === 'node_modules') return; + + const modulePath = nodePath.join(base, dir); + addPath(modulePath); + }); + } +} + +module.exports = init; +module.exports.addPath = addPath; +module.exports.addAlias = addAlias; +module.exports.addAliases = addAliases; +module.exports.isPathMatchesAlias = isPathMatchesAlias; +module.exports.reset = reset; diff --git a/utils/module-alias/register.js b/utils/module-alias/register.js new file mode 100644 index 0000000..113bb15 --- /dev/null +++ b/utils/module-alias/register.js @@ -0,0 +1,3 @@ +'use strict'; + +require('.')(); diff --git a/yarn.lock b/yarn.lock index 6af64b4..44ffd5d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3920,11 +3920,6 @@ mkdirp@^0.5.0, mkdirp@^0.5.1: dependencies: minimist "0.0.8" -module-alias@^2.2.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/module-alias/-/module-alias-2.2.1.tgz#553aea9dc7f99cd45fd75e34a574960dc46550da" - integrity sha512-LTez0Eo+YtfUhgzhu/LqxkUzOpD+k5C0wXBLun0L1qE2BhHf6l09dqam8e7BnoMYA6mAlP0vSsGFQ8QHhGN/aQ== - move-concurrently@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/move-concurrently/-/move-concurrently-1.0.1.tgz#be2c005fda32e0b29af1f05d7c4b33214c701f92" From 932dc73ec3f7ea46df338794e916d991225f5341 Mon Sep 17 00:00:00 2001 From: zyao89 Date: Sun, 29 Sep 2019 03:46:33 +0800 Subject: [PATCH 08/10] :enhance: mode support function. --- libs/Service/index.js | 20 ++++++++++++++++---- utils/module-alias/index.js | 4 ++-- 2 files changed, 18 insertions(+), 6 deletions(-) diff --git a/libs/Service/index.js b/libs/Service/index.js index 5355171..13cbf1d 100644 --- a/libs/Service/index.js +++ b/libs/Service/index.js @@ -99,10 +99,22 @@ class Service extends BaseService { _initPlugin(plugin) { const { id, apply, opts = {}, mode } = plugin; - if (mode && mode !== this.mode) { - // 当前模式与插件不匹配 - logger.warn(`[Plugin] {${this.mode}} - initPlugin() skip "${id}"`); - return; + if (mode) { // 默认为全支持 + let _mode = mode; + if (_.isFunction(_mode)) { // 支持方法判断 + _mode = _mode(this.mode); + } + if (Array.isArray(_mode)) { + if (!_mode.some(item => item === this.mode)) { + // 当前模式与插件不匹配 + logger.warn(`[Plugin] { ${this.mode} } - initPlugin() skip "${id}". support modes: { ${_mode.join(', ')} }`); + return; + } + } else if (_mode !== this.mode) { + // 当前模式与插件不匹配 + logger.warn(`[Plugin] { ${this.mode} } - initPlugin() skip "${id}". support mode: { ${_mode} }`); + return; + } } assert(typeof apply === 'function', logger.toString.error('\n' + ` diff --git a/utils/module-alias/index.js b/utils/module-alias/index.js index 0056b06..d1771cc 100644 --- a/utils/module-alias/index.js +++ b/utils/module-alias/index.js @@ -82,7 +82,7 @@ function addPath(path) { if (modulePaths.indexOf(path) === -1) { modulePaths.push(path); // Enable the search path for the current top-level module - addPathHelper(path, require.main.paths); + require.main && addPathHelper(path, require.main.paths); parent = module.parent; // Also modify the paths of the module that was used to load the @@ -115,7 +115,7 @@ function addAlias(alias, target) { function reset() { // Reset all changes in paths caused by addPath function modulePaths.forEach(function(path) { - removePathHelper(path, require.main.paths); + require.main && removePathHelper(path, require.main.paths); // Delete from require.cache if the module has been required before. // This is required for node >= 11 From ad8a348fd99b60e58d95544fac1144e9fbad6390 Mon Sep 17 00:00:00 2001 From: zyao89 Date: Sun, 29 Sep 2019 03:50:26 +0800 Subject: [PATCH 09/10] :test: update config. --- micro-app.config.js | 24 ++++++++++-------------- 1 file changed, 10 insertions(+), 14 deletions(-) diff --git a/micro-app.config.js b/micro-app.config.js index db685ba..c9024d4 100644 --- a/micro-app.config.js +++ b/micro-app.config.js @@ -45,11 +45,7 @@ module.exports = { strict: true, - // micros: [ 'test' ], // 被注册的容器 - // micros$$test: { // 单独配置 - // disabled: true, // 禁用入口 - // link: '', // 本地路径, 进行本地开发使用的软链接. - // }, + micros: [ 'test' ], // 被注册的容器 // 服务配置 server: { @@ -60,13 +56,13 @@ module.exports = { }, }, - // plugins: [ - // [{ - // id: 'test', - // description: '这是test', - // link: __dirname + '/test/testPlugin', - // }, { - // a: 1, - // }], - // ], + plugins: [ + [{ + id: 'test', + description: '这是test', + link: __dirname + '/test/testPlugin', + }, { + a: 1, + }], + ], }; From 826bd79a3ff4967f53a5aec4e84903054642a287 Mon Sep 17 00:00:00 2001 From: zyao89 Date: Sun, 29 Sep 2019 03:56:23 +0800 Subject: [PATCH 10/10] :update: test coveralls --- plugins/commands/show.test.js | 7 +++++++ utils/test/logger.test.js | 24 ++++++++++++++++++++++++ 2 files changed, 31 insertions(+) create mode 100644 utils/test/logger.test.js diff --git a/plugins/commands/show.test.js b/plugins/commands/show.test.js index bc6a0ed..b693688 100644 --- a/plugins/commands/show.test.js +++ b/plugins/commands/show.test.js @@ -141,4 +141,11 @@ describe('show', () => { }); + it('process.env', () => { + const api = customAPI({ + _: [ 'process.env' ], + }); + show(api); + }); + }); diff --git a/utils/test/logger.test.js b/utils/test/logger.test.js new file mode 100644 index 0000000..e4382b3 --- /dev/null +++ b/utils/test/logger.test.js @@ -0,0 +1,24 @@ +'use strict'; + +/* global expect */ + +describe('Logger', () => { + + it('test logger', () => { + + const logger = require('../logger'); + logger.error('abc'); + logger.info('abc'); + logger.success('abc'); + logger.logo('abc'); + logger.warn('abc'); + logger.debug('abc'); + const spinner = logger.spinner('abc'); + spinner.start(); + setTimeout(() => { + spinner.success('cc'); + }, 3000); + + }); + +});