lambda-service
Version:
405 lines (325 loc) • 12 kB
JavaScript
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _chalk = _interopRequireDefault(require("chalk"));
var _path = require("path");
var _fs = require("fs");
var _assert = _interopRequireWildcard(require("assert"));
var _mkdirp = _interopRequireDefault(require("mkdirp"));
var _lodash = require("lodash");
var _dotenv = require("dotenv");
var _signale = _interopRequireDefault(require("signale"));
var _umiUtils = require("umi-utils");
var _error = require("umi-core/lib/error");
var _getPaths = _interopRequireDefault(require("./getPaths"));
var _getPlugins = _interopRequireDefault(require("./getPlugins"));
var _PluginAPI = _interopRequireDefault(require("./PluginAPI"));
var _UserConfig = _interopRequireDefault(require("./UserConfig"));
var _registerBabel = _interopRequireDefault(require("./registerBabel"));
var _getCodeFrame = _interopRequireDefault(require("./utils/getCodeFrame"));
function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; return newObj; } }
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { Promise.resolve(value).then(_next, _throw); } }
function _asyncToGenerator(fn) { return function () { var self = this, args = arguments; return new Promise(function (resolve, reject) { var gen = fn.apply(self, args); function _next(value) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value); } function _throw(err) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err); } _next(undefined); }); }; }
const debug = require('debug')('umi-build-dev:Service');
class Service {
constructor({
cwd
}) {
// 设置当前node的工作目录
this.cwd = cwd || process.cwd(); // 获取package内容
try {
this.pkg = require((0, _path.join)(this.cwd, 'package.json')); // eslint-disable-line
} catch (e) {
this.pkg = {};
} // 使用babel/register 改造require使得导入模块时自动转译
// 默认忽略node_modules
(0, _registerBabel.default)({
cwd: this.cwd
});
this.commands = {};
this.pluginHooks = {};
this.pluginMethods = {};
this.generators = {};
this.UmiError = _error.UmiError;
this.printUmiError = _error.printUmiError; // 获取用户文件配置
this.config = _UserConfig.default.getConfig({
cwd: this.cwd,
service: this
});
debug(`user config: ${JSON.stringify(this.config)}`); // resolve plugins
this.plugins = this.resolvePlugins();
this.extraPlugins = [];
debug(`plugins: ${this.plugins.map(p => p.id).join(' | ')}`); // 获取paths配置 === api.paths
this.paths = (0, _getPaths.default)(this);
}
printUmiError(error, opts) {
this.applyPlugins('onPrintUmiError', {
args: {
error,
opts
}
});
(0, _error.printUmiError)(error, opts);
}
resolvePlugins() {
try {
(0, _assert.default)(Array.isArray(this.config.plugins || []), `Configure item ${_chalk.default.underline.cyan('plugins')} should be Array, but got ${_chalk.default.red(typeof this.config.plugins)}`);
return (0, _getPlugins.default)({
cwd: (0, _umiUtils.winPath)(this.cwd),
plugins: this.config.plugins || []
});
} catch (e) {
if (process.env.UMI_TEST) {
throw new Error(e);
} else {
this.printUmiError(e);
process.exit(1);
}
}
}
initPlugin(plugin) {
const id = plugin.id,
apply = plugin.apply,
opts = plugin.opts;
try {
(0, _assert.default)(typeof apply === 'function', `
plugin must export a function, e.g.
export default function(api) {
// Implement functions via api
}
`.trim());
const api = new Proxy(new _PluginAPI.default(id, this), {
get: (target, prop) => {
if (this.pluginMethods[prop]) {
return this.pluginMethods[prop];
}
if ([// methods
'changePluginOption', 'applyPlugins', '_applyPluginsAsync', 'writeTmpFile', // properties
'cwd', 'config', 'webpackConfig', 'pkg', 'paths', 'routes', // error handler
'UmiError', 'printUmiError', // dev methods
'restart', 'printError', 'printWarn', 'refreshBrowser', 'rebuildTmpFiles', 'rebuildHTML'].includes(prop)) {
if (typeof this[prop] === 'function') {
return this[prop].bind(this);
} else {
return this[prop];
}
} else {
return target[prop];
}
}
});
api.onOptionChange = fn => {
(0, _assert.default)(typeof fn === 'function', `The first argument for api.onOptionChange should be function in ${id}.`);
plugin.onOptionChange = fn;
};
apply(api, opts);
plugin._api = api;
} catch (e) {
if (process.env.UMI_TEST) {
throw new Error(e);
} else {
_signale.default.error(`
Plugin ${_chalk.default.cyan.underline(id)} initialize failed
${(0, _getCodeFrame.default)(e, {
cwd: this.cwd
})}
`.trim());
debug(e);
process.exit(1);
}
}
}
initPlugins() {
this.plugins.forEach(plugin => {
this.initPlugin(plugin);
});
let count = 0;
while (this.extraPlugins.length) {
const extraPlugins = (0, _lodash.cloneDeep)(this.extraPlugins);
this.extraPlugins = [];
extraPlugins.forEach(plugin => {
this.initPlugin(plugin);
this.plugins.push(plugin);
});
count += 1;
(0, _assert.default)(count <= 10, `插件注册死循环?`);
} // Throw error for methods that can't be called after plugins is initialized
this.plugins.forEach(plugin => {
;
['onOptionChange', 'register', 'registerMethod', 'registerPlugin'].forEach(method => {
plugin._api[method] = () => {
throw new Error(`api.${method}() should not be called after plugin is initialized.`);
};
});
});
}
changePluginOption(id, newOpts) {
(0, _assert.default)(id, `id must supplied`);
const plugin = this.plugins.filter(p => p.id === id)[0];
(0, _assert.default)(plugin, `plugin ${id} not found`);
plugin.opts = newOpts;
if (plugin.onOptionChange) {
plugin.onOptionChange(newOpts);
} else {
this.restart(`plugin ${id}'s option changed`);
}
}
applyPlugins(key, opts = {}) {
debug(`apply plugins ${key}`);
return (this.pluginHooks[key] || []).reduce((memo, {
fn
}) => {
try {
return fn({
memo,
args: opts.args
});
} catch (e) {
console.error(_chalk.default.red(`Plugin apply failed: ${e.message}`));
throw e;
}
}, opts.initialValue);
}
_applyPluginsAsync(key, opts = {}) {
var _this = this;
return _asyncToGenerator(function* () {
debug(`apply plugins async ${key}`);
const hooks = _this.pluginHooks[key] || [];
let memo = opts.initialValue;
var _iteratorNormalCompletion = true;
var _didIteratorError = false;
var _iteratorError = undefined;
try {
for (var _iterator = hooks[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
const hook = _step.value;
const fn = hook.fn; // eslint-disable-next-line no-await-in-loop
memo = yield fn({
memo,
args: opts.args
});
}
} catch (err) {
_didIteratorError = true;
_iteratorError = err;
} finally {
try {
if (!_iteratorNormalCompletion && _iterator.return != null) {
_iterator.return();
}
} finally {
if (_didIteratorError) {
throw _iteratorError;
}
}
}
return memo;
})();
}
loadEnv() {
const basePath = (0, _path.join)(this.cwd, '.env');
const localPath = `${basePath}.local`;
const load = path => {
if ((0, _fs.existsSync)(path)) {
debug(`load env from ${path}`);
const parsed = (0, _dotenv.parse)((0, _fs.readFileSync)(path, 'utf-8'));
Object.keys(parsed).forEach(key => {
// eslint-disable-next-line no-prototype-builtins
if (!process.env.hasOwnProperty(key)) {
process.env[key] = parsed[key];
}
});
}
};
load(basePath);
load(localPath);
}
writeTmpFile(file, content) {
const paths = this.paths;
const path = (0, _path.join)(paths.absTmpDirPath, file);
_mkdirp.default.sync((0, _path.dirname)(path));
(0, _fs.writeFileSync)(path, content, 'utf-8');
}
init() {
// load env
this.loadEnv(); // init plugins
this.initPlugins(); // reload user config
const userConfig = new _UserConfig.default(this);
const config = userConfig.getConfig({
force: true
});
mergeConfig(this.config, config);
this.userConfig = userConfig;
if (config.browserslist) {
(0, _umiUtils.deprecate)('config.browserslist', 'use config.targets instead');
}
debug('got user config');
debug(this.config); // assign user's outputPath config to paths object
if (config.outputPath) {
const paths = this.paths;
paths.outputPath = config.outputPath;
paths.absOutputPath = (0, _path.join)(paths.cwd, config.outputPath);
}
debug('got paths');
debug(this.paths);
}
registerCommand(name, opts, fn) {
if (typeof opts === 'function') {
fn = opts;
opts = null;
}
opts = opts || {};
(0, _assert.default)(!(name in this.commands), `Command ${name} exists, please select another one.`);
this.commands[name] = {
fn,
opts
};
}
run(name = 'help', args) {
this.init();
return this.runCommand(name, args);
}
runCommand(rawName, rawArgs) {
debug(`raw command name: ${rawName}, args: ${JSON.stringify(rawArgs)}`);
const _this$applyPlugins = this.applyPlugins('_modifyCommand', {
initialValue: {
name: rawName,
args: rawArgs
}
}),
name = _this$applyPlugins.name,
args = _this$applyPlugins.args;
debug(`run ${name} with args ${JSON.stringify(args)}`);
const command = this.commands[name];
if (!command) {
_signale.default.error(`Command ${_chalk.default.underline.cyan(name)} does not exists`);
process.exit(1);
}
const fn = command.fn,
opts = command.opts;
if (opts.webpack) {
// webpack config
this.webpackConfig = require('./getWebpackConfig').default(this);
if (this.config.ssr) {
// when use ssr, push client-manifest plugin into client webpackConfig
this.webpackConfig.plugins.push(new (require('./plugins/commands/getChunkMapPlugin').default(this))()); // server webpack config
this.ssrWebpackConfig = require('./getWebpackConfig').default(this, {
ssr: this.config.ssr
});
}
}
return fn(args);
}
}
exports.default = Service;
function mergeConfig(oldConfig, newConfig) {
Object.keys(oldConfig).forEach(key => {
if (!(key in newConfig)) {
delete oldConfig[key];
}
});
(0, _lodash.assign)(oldConfig, newConfig);
return oldConfig;
}
;