"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = void 0; function _react() { const data = _interopRequireDefault(require("react")); _react = function _react() { return data; }; return data; } require("regenerator-runtime/runtime"); function _assert() { const data = _interopRequireDefault(require("assert")); _assert = function _assert() { return data; }; return data; } function _emptyDir() { const data = _interopRequireDefault(require("empty-dir")); _emptyDir = function _emptyDir() { return data; }; return data; } function _express() { const data = _interopRequireDefault(require("express")); _express = function _express() { return data; }; return data; } function _compression() { const data = _interopRequireDefault(require("compression")); _compression = function _compression() { return data; }; return data; } function _clearModule() { const data = _interopRequireDefault(require("clear-module")); _clearModule = function _clearModule() { return data; }; return data; } function _sockjs() { const data = _interopRequireDefault(require("sockjs")); _sockjs = function _sockjs() { return data; }; return data; } function _path() { const data = require("path"); _path = function _path() { return data; }; return data; } function _launchEditor() { const data = _interopRequireDefault(require("@umijs/launch-editor")); _launchEditor = function _launchEditor() { return data; }; return data; } function _openBrowser() { const data = _interopRequireDefault(require("react-dev-utils/openBrowser")); _openBrowser = function _openBrowser() { return data; }; return data; } function _fs() { const data = require("fs"); _fs = function _fs() { return data; }; return data; } function _child_process() { const data = require("child_process"); _child_process = function _child_process() { return data; }; return data; } function _umi() { const data = require("umi"); _umi = function _umi() { return data; }; return data; } function _resolveFrom() { const data = _interopRequireDefault(require("resolve-from")); _resolveFrom = function _resolveFrom() { return data; }; return data; } var _index = _interopRequireDefault(require("./routes/index")); var _common = _interopRequireDefault(require("./routes/common")); var _resize = _interopRequireDefault(require("./routes/resize")); var _Config = _interopRequireDefault(require("./Config")); var _getClientScript = _interopRequireWildcard(require("./getClientScript")); var _listDirectory = _interopRequireDefault(require("./listDirectory")); var _installCreator = _interopRequireDefault(require("./installCreator")); var _npmClient = require("./npmClient"); var _ActiveProjectError = _interopRequireDefault(require("./ActiveProjectError")); var _Actions = require("./Actions"); var _checkProject = require("./checkProject"); var _isDepFileExists = _interopRequireDefault(require("./utils/isDepFileExists")); var _terminal = _interopRequireDefault(require("./terminal")); var _detectLanguage = _interopRequireDefault(require("./detectLanguage")); var _detectNpmClients = _interopRequireDefault(require("./detectNpmClients")); var _debug = _interopRequireWildcard(require("./debug")); function _getRequireWildcardCache() { if (typeof WeakMap !== "function") return null; var cache = new WeakMap(); _getRequireWildcardCache = function _getRequireWildcardCache() { return cache; }; return cache; } function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; } function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); } function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); } function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; } function _iterableToArrayLimit(arr, i) { if (typeof Symbol === "undefined" || !(Symbol.iterator in Object(arr))) return; var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"] != null) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; } function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; } function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; } function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } function _objectWithoutProperties(source, excluded) { if (source == null) return {}; var target = _objectWithoutPropertiesLoose(source, excluded); var key, i; if (Object.getOwnPropertySymbols) { var sourceSymbolKeys = Object.getOwnPropertySymbols(source); for (i = 0; i < sourceSymbolKeys.length; i++) { key = sourceSymbolKeys[i]; if (excluded.indexOf(key) >= 0) continue; if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; target[key] = source[key]; } } return target; } function _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; } 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 winPath = _umi().utils.winPath, lodash = _umi().utils.lodash, semver = _umi().utils.semver, portfinder = _umi().utils.portfinder, rimraf = _umi().utils.rimraf, chalk = _umi().utils.chalk; const pick = lodash.pick, uniq = lodash.uniq; class UmiUI { constructor() { this.cwd = void 0; this.servicesByKey = void 0; this.ctx = void 0; this.server = void 0; this.socketServer = void 0; this.logs = void 0; this.config = void 0; this.send = void 0; this.developMode = false; this.npmClients = []; this.basicUIPath = void 0; this.basicConfigPath = void 0; this.getService = cwd => { const serviceModule = process.env.BIGFISH_COMPAT ? '@alipay/bigfish/_Service.js' : 'umi/_Service.js'; const servicePath = process.env.LOCAL_DEBUG ? 'umi/lib/cjs' : _resolveFrom().default.silent(cwd, serviceModule) || 'umi/lib/cjs'; (0, _debug.default)(`Service path: ${servicePath}`); // eslint-disable-next-line import/no-dynamic-require const _require = require(servicePath), UmiService = _require.Service; const service = new UmiService({ cwd }); return service; }; this.cwd = process.cwd(); // 兼容旧版 Bigfish this.basicUIPath = process.env.BASIC_UI_PATH || ''; // export default { serices, ... } this.basicConfigPath = process.env.BASIC_CONFIG_PATH || ''; this.servicesByKey = {}; this.server = null; this.socketServer = null; this.config = new _Config.default({ onSave: data => { if (this.send) { this.send({ type: '@@project/list/progress', payload: data }); } } }); this.npmClients = []; this.logs = []; this.ctx = { cwd: process.cwd(), developMode: !!process.env.DEVELOP_MODE, config: this.config, basicUIPath: this.basicUIPath, servicesByKey: this.servicesByKey, npmClients: this.npmClients, logs: this.logs }; this.developMode = !!process.env.DEVELOP_MODE; if (process.env.CURRENT_PROJECT) { const key = this.config.addProjectWithPath((0, _path().join)(process.cwd(), process.env.CURRENT_PROJECT)); this.config.setCurrentProject(key); } process.nextTick(() => { this.initNpmClients(); }); } openProject(key, service, opts) { var _this = this; return _asyncToGenerator(function* () { const _ref = opts || {}, lang = _ref.lang; const project = _this.config.data.projectsByKey[key]; (0, _assert().default)(project, `project of key ${key} not exists`); // Check exists. if (!(0, _fs().existsSync)(project.path)) { throw new _ActiveProjectError.default({ title: { 'zh-CN': `项目 ${project.path} 路径不存在。`, 'en-US': `Project ${project.path} not exists.` }, lang, actions: [_Actions.BackToHomeAction] }); } // Check umi valid. if (!(0, _checkProject.isUmiProject)(project.path)) { throw new _ActiveProjectError.default({ title: { 'zh-CN': `项目 ${project.path} 不是 Umi 项目。`, 'en-US': `Project ${project.path} is not a valid Umi project.` }, lang, actions: [_Actions.BackToHomeAction] }); } if (process.env.BIGFISH_COMPAT && (0, _checkProject.isUsingUmi)(project.path)) { throw new _ActiveProjectError.default({ title: { 'zh-CN': `项目 ${project.path} 是 Umi 项目,不能使用 Bigfish 打开。`, 'en-US': `Project ${project.path} is Umi Project, don't open it with Bigfish.` }, lang, actions: [_Actions.BackToHomeAction] }); } if (!process.env.BIGFISH_COMPAT && (0, _checkProject.isUsingBigfish)(project.path)) { throw new _ActiveProjectError.default({ title: { 'zh-CN': `项目 ${project.path} 是 Bigfish 项目,不能使用 Umi 打开。`, 'en-US': `Project ${project.path} is Bigfish Project, don't open it with Umi.` }, lang, actions: [_Actions.BackToHomeAction] }); } if (!_this.developMode && service) { _this.servicesByKey[key] = service; } else if (!_this.servicesByKey[key]) { // Attach Service (0, _debug.default)(`Attach service for ${key}`); // Use local service and detect version compatibility const binModule = process.env.BIGFISH_COMPAT ? '@alipay/bigfish/bin/bigfish.js' : 'umi/bin/umi.js'; const pkgModule = process.env.BIGFISH_COMPAT ? '@alipay/bigfish/package.json' : 'umi/package.json'; const cwd = project.path; const localBin = (0, _isDepFileExists.default)(cwd, binModule); if (process.env.UI_CHECK_LOCAL !== 'none' && localBin) { const _JSON$parse = JSON.parse((0, _fs().readFileSync)((0, _path().join)(cwd, 'node_modules', pkgModule), 'utf-8')), version = _JSON$parse.version; if (!semver.gt(version, process.env.BIGFISH_COMPAT ? '3.0.0' : '3.0.0')) { throw new _ActiveProjectError.default({ title: process.env.BIGFISH_COMPAT ? `本地项目的 Bigfish 版本(${version})过低,请升级到 @alipay/bigfish@3.0 或以上,查看详情。` : { 'zh-CN': `本地项目的 Umi 版本(${version})过低,请升级到 umi@3.0 或以上,查看详情。`, 'en-US': `Umi version (${version}) of the project is too low, please upgrade to umi@2.12 or above, view details.` }, lang, actions: [_Actions.ReInstallDependencyAction, _Actions.OpenProjectAction, _Actions.BackToHomeAction] }); } } try { const currentService = _this.getService(cwd); (0, _debug.default)(`Attach service for ${key} after new and before init()`); yield currentService.init(); (0, _debug.default)(`Attach service for ${key} ${chalk.green('SUCCESS')}`); _this.servicesByKey[key] = currentService; } catch (e) { if ((0, _checkProject.isDepLost)(e) || (0, _checkProject.isPluginLost)(e)) { throw new _ActiveProjectError.default({ title: { 'zh-CN': `依赖文件没找到。`, 'en-US': 'Dependency file not found.' }, message: e.message, stack: e.stack, lang, actions: [_Actions.ReInstallDependencyAction, _Actions.BackToHomeAction] }); } else { throw new _ActiveProjectError.default({ title: { 'zh-CN': '其他错误', 'en-US': 'Other Errors' }, message: e.message, stack: e.stack, lang, // exception tag exception: true, actions: [_Actions.BackToHomeAction] }); } } } _this.config.editProject(key, { opened_at: +new Date() }); })(); } openProjectInEditor(key, callback = {}, lang = 'zh-CN') { var _this2 = this; return _asyncToGenerator(function* () { let launchPath = key; if (!(key.startsWith('/') && (0, _fs().existsSync)(key))) { const project = _this2.config.data.projectsByKey[key]; (0, _assert().default)(project, `project of key ${key} not exists`); launchPath = project.path; } if (!(0, _fs().existsSync)(launchPath)) { if (callback.failure) { const msg = { 'zh-CN': `打开编辑器失败 ${launchPath},项目不存在`, 'en-US': `Open Editor Failure, ${launchPath}, project does not exist` }; console.error(chalk.red(msg[lang])); callback.failure({ message: msg[lang] }); } if (callback.success) { callback.success(); } } else { try { const res = yield (0, _launchEditor().default)(launchPath); if (res && res.success) { callback.success(res); } else { callback.failure(res); } } catch (e) { callback.failure(e); } } })(); } openConfigFileInEditor(projectPath, { success, failure, lang }) { return _asyncToGenerator(function* () { let configFile; const configFiles = ['.umirc.js', '.umirc.ts', 'config/config.js', 'config/config.ts']; for (var _i = 0, _configFiles = configFiles; _i < _configFiles.length; _i++) { const file = _configFiles[_i]; if ((0, _fs().existsSync)((0, _path().join)(projectPath, file))) { configFile = (0, _path().join)(projectPath, file); break; } } try { (0, _assert().default)(configFile, lang === 'zh-CN' ? '在编辑器中打开失败,因为配置文件不存在。' : `Open failed with editor, since configFile not exists.`); const res = yield (0, _launchEditor().default)(configFile); if (res && res.success) { success(res); } else { failure(res); } } catch (e) { console.error(e); failure({ message: e.message }); } })(); } getExtraAssets({ key, success }) { var _this3 = this; return _asyncToGenerator(function* () { const service = _this3.servicesByKey[key]; const uiPlugins = yield service.applyPlugins({ key: 'addUIPlugin', type: service.ApplyPluginsType.add, initialValue: [] }); (0, _debug.default)('uiPlugins', uiPlugins); const script = (0, _getClientScript.default)(uiPlugins); success({ script }); })(); } getBasicAssets() { const script = this.basicUIPath ? (0, _getClientScript.getBasicScriptContent)(this.basicUIPath) : ''; return { script }; } installDeps(npmClient, projectPath, { onProgress, onSuccess, taobaoSpeedUp }) { return _asyncToGenerator(function* () { yield (0, _npmClient.installDeps)(npmClient, projectPath, { taobaoSpeedUp, onData(data) { onProgress({ install: data }); } }); onSuccess(); })(); } createProject(opts = {}, { onSuccess, onFailure, onProgress, lang }) { var _this4 = this; return _asyncToGenerator(function* () { let key = opts.key; let retryFrom = opts.retryFrom; let createOpts = opts; if (key) { (0, _assert().default)('retryFrom' in opts, `key 和 retryFrom 必须同时提供。`); // eslint-disable-next-line prefer-destructuring createOpts = _this4.config.data.projectsByKey[key].createOpts; } const setProgress = args => { (0, _assert().default)(key, `key is not initialized.`); _this4.config.setCreatingProgress(key, args); }; const sigintHandler = () => { if (key) { _this4.config.setCreatingProgress(key, { stepStatus: 3, failure: { message: 'exit UmiUi server' } }); } process.exit(); }; try { (0, _assert().default)(createOpts.baseDir, `baseDir must be supplied`); (0, _assert().default)(createOpts.name, `name must be supplied`); (0, _assert().default)(createOpts.type, `type must be supplied`); const targetDir = (0, _path().join)(createOpts.baseDir, createOpts.name); if (!retryFrom) { // 步骤: // // 1. 校验 // a) 比如检查目标目录是否为空或不存在 // 2. 添加项目状态到本地存储,后面每一步都更新状态到存储 // 3. 安装 create-umi 或更新他 // 4. create-umi 创建 // 如果是 ant-design-pro,还需要拆几步出来,比如 git clone // 5. 安装依赖 // // 项目步骤: // 1. 校验参数 // 2. 安装/更新 create-umi // 3. 使用 create-umi 初始化项目 // 4. 安装依赖 // // 结束后打开项目。 // 0 (0, _assert().default)(!(0, _fs().existsSync)(targetDir) || _emptyDir().default.sync(targetDir), `target dir ${targetDir} exists and not empty`); // 1 key = _this4.config.addProject({ path: targetDir, name: createOpts.name, npmClient: createOpts.npmClient, createOpts }); // get create key onSuccess({ key }); setProgress({ // 表示第几个 step,从 0 开始 step: 1, // 0: 未开始 // 1: 执行中 // 2: 执行完成 // 3: 执行失败 stepStatus: 0, steps: { 'zh-CN': ['校验参数', '安装或更新 create-umi', '初始化项目', '安装依赖'], 'en-US': ['Validate Params', 'Install or Update create-umi', 'Initialize Project', 'Install Dependency'] } }); } // catch exit process.on('SIGINT', sigintHandler); // 1 let creatorPath; // step 2 依赖 step 1 if (retryFrom === 2) { retryFrom = 1; } if (!retryFrom || retryFrom <= 1) { setProgress({ step: 1, stepStatus: 1 }); creatorPath = yield (0, _installCreator.default)({ // npmClient: createOpts.npmClient, onData(data) { onProgress({ install: data }); } }); setProgress({ stepStatus: 2 }); } // 2 if (!retryFrom || retryFrom <= 2) { setProgress({ step: 2, stepStatus: 1 }); (0, _clearModule().default)(creatorPath); yield require(creatorPath).run({ cwd: targetDir, type: createOpts.type || {}, args: createOpts.args || {} }); setProgress({ stepStatus: 2 }); } // 3 if (!retryFrom || retryFrom <= 3) { setProgress({ step: 3, stepStatus: 1 }); // 重装 node_modules 时先清空,否则可能会失败 if (retryFrom === 3) { rimraf.sync((0, _path().join)(targetDir, 'node_modules')); } yield (0, _npmClient.installDeps)(createOpts.npmClient, targetDir, { taobaoSpeedUp: _this4.hasTaobaoSpeedUp(), onData(data) { onProgress({ install: data }); } }); setProgress({ stepStatus: 2 }); setProgress({ success: true }); } } catch (e) { if (key) { _this4.config.setCreatingProgress(key, { stepStatus: 3, failure: e }); } onFailure(e); } finally { process.removeListener('SIGINT', sigintHandler); } })(); } checkDirValid({ dir }, { onSuccess, onFailure }) { try { // 入参校验 (0, _assert().default)(dir, `payload.dir must be supplied`); if (!(0, _fs().existsSync)(dir)) { return onSuccess(); } // 非目录判断和权限校验 const stat = (0, _fs().statSync)(dir); (0, _assert().default)(stat.isDirectory(), `target directory must be a directory`); // 费空目录判断 (0, _assert().default)(_emptyDir().default.sync(dir), `target directory must be empty`); } catch (e) { onFailure(e); } } initNpmClients() { const ret = ['tnpm', 'cnpm', 'npm', 'ayarn', 'tyarn', 'yarn'].filter(npmClient => { try { (0, _child_process().execSync)(`${npmClient} --version`, { stdio: 'ignore' }); return true; } catch (e) {} return false; }); (0, _debug.default)('ret', ret); this.npmClients = ret; } getNpmClients() { return this.npmClients; } getRouteComponents({ service }) { var _this5 = this; return _asyncToGenerator(function* () { const routes = yield service.getRoutes(); const getComponents = routes => routes.reduce((memo, route) => { if (route.component && !route.component.startsWith('()')) { const component = (0, _path().isAbsolute)(route.component) ? route.component : require.resolve((0, _path().join)(_this5.cwd, route.component)); memo.push(winPath(component)); } if (route.routes) { memo = memo.concat(getComponents(route.routes)); } return memo; }, []); return uniq(getComponents(routes)); })(); } detectLanguage({ success, failure, key }) { var _this6 = this; return _asyncToGenerator(function* () { const service = _this6.servicesByKey[key]; try { const routeComponents = yield _this6.getRouteComponents({ service }); const language = (0, _detectLanguage.default)(service.cwd, { routeComponents }); success({ language }); } catch (e) { failure(e); } })(); } // reloadProject(key: string) {} handleCoreData({ type, payload, lang, key }, { log, send, success, failure, progress }) { var _this7 = this; return _asyncToGenerator(function* () { switch (type) { case '@@project/getBasicAssets': success(_this7.getBasicAssets()); break; case '@@project/getExtraAssets': _this7.getExtraAssets({ key, success }); break; case '@@project/list': _this7.config.checkValid(); _this7.config.load(); success({ data: _this7.config.data }); break; case '@@project/detail': success({ data: _this7.config.data.projectsByKey[payload.key] }); break; case '@@project/add': // TODO: 检验是否 umi 项目,不是则抛错给客户端 try { (0, _assert().default)((0, _fs().existsSync)(payload.path), `Add project failed, since path ${payload.path} don't exists.`); log('info', `Add project ${payload.path} with name ${payload.name}`); _this7.config.addProject({ path: payload.path, name: payload.name }); success(); } catch (e) { console.error(chalk.red(`Error: Add project FAILED`)); console.error(e); failure({ message: e.message }); } break; case '@@project/delete': if (_this7.config.data.projectsByKey[payload.key]) { log('info', `Delete project: ${_this7.getProjectName(payload.key)}`); _this7.config.deleteProject(payload.key); success(); } break; case '@@project/getKeyOrAddWithPath': success({ key: _this7.config.getKeyOrAddWithPath(payload.path) }); break; case '@@project/open': { log('info', `Open project: ${_this7.getProjectName(payload.key)}`); try { yield _this7.openProject(payload.key, null, { lang }); success(); } catch (e) { failure(pick(e, ['title', 'message', 'stack', 'actions', 'exception'])); console.error(chalk.red(`Error: Attach Project of key ${payload.key} FAILED`)); } break; } case '@@project/openInEditor': log('info', `Open in editor: ${_this7.getProjectName(payload.key)}`); _this7.openProjectInEditor(payload.key, { success, failure }, lang); break; case '@@project/edit': log('info', `Edit project: ${_this7.getProjectName(payload.key)}`); _this7.config.editProject(payload.key, { name: payload.name, cloudUrl: payload.cloudUrl }); success(); break; case '@@project/setCurrentProject': _this7.config.load(); // 重新 load _this7.config.setCurrentProject(payload.key); success(); break; case '@@project/clearCurrentProject': _this7.config.clearCurrentProject(); success(); break; case '@@project/create': log('info', `Create project: ${_this7.getProjectName(payload.key)}`); _this7.createProject(payload, { onSuccess: success, onFailure(e) { failure({ message: e.message }); }, onProgress: progress, lang }); break; case '@@project/checkDirValid': _this7.checkDirValid(payload, { onSuccess: success, onFailure(e) { failure({ message: e.message }); } }); break; case '@@project/createTemplateList': success({ data: [{ title: 'Ant Design Pro', description: 'A layout-only ant-design-pro boilerplate, use together with umi block', url: 'https://preview.pro.ant.design/' }, { title: 'Basic Template', description: 'A simple boilerplate, support typescript.' }] }); break; case '@@project/getNpmClients': success({ data: _this7.getNpmClients() }); break; case '@@project/getSharedDataDir': success({ tmpDir: (0, _path().join)((0, _path().dirname)(_this7.config.dbPath), 'shared-data', key) }); break; case '@@project/detectLanguage': try { (0, _assert().default)(key && _this7.servicesByKey[key], `Detect language failed, key must be supplied.`); _this7.detectLanguage({ key, success, failure }); } catch (e) { console.error(e); failure({ message: e.message }); } break; case '@@project/detectNpmClients': try { (0, _assert().default)(key && _this7.servicesByKey[key], `Detect language failed, key must be supplied.`); const service = _this7.servicesByKey[key]; success({ npmClients: (0, _detectNpmClients.default)(service.cwd) }); } catch (e) { console.error(e); failure({ message: e.message }); } break; case '@@fs/getCwd': success({ cwd: _this7.cwd }); break; case '@@fs/listDirectory': { try { const data = (0, _listDirectory.default)(payload.dirPath, { directoryOnly: true }); success({ data }); } catch (e) { failure({ message: e.message }); } break; } case '@@log/getHistory': success({ data: _this7.logs }); break; case '@@log/clear': _this7.logs = []; success(); break; case '@@actions/installDependencies': _this7.config.setProjectNpmClient({ key: payload.key, npmClient: payload.npmClient }); _this7.installDeps(payload.npmClient, payload.projectPath, { taobaoSpeedUp: _this7.hasTaobaoSpeedUp(), onProgress: progress, onSuccess: success }); break; case '@@actions/reInstallDependencies': _this7.config.setProjectNpmClient({ key: payload.key, npmClient: payload.npmClient }); rimraf.sync((0, _path().join)(payload.projectPath, 'node_modules')); _this7.installDeps(payload.npmClient, payload.projectPath, { taobaoSpeedUp: _this7.hasTaobaoSpeedUp(), onProgress: progress, onSuccess: success }); break; case '@@actions/openConfigFile': _this7.openConfigFileInEditor(payload.projectPath, { success, failure, lang }); break; case '@@actions/openProjectInEditor': _this7.openProjectInEditor(payload.projectPath, { success, failure }, lang); break; case '@@app/notify': try { const notifier = require('node-notifier'); const buildInImages = { error: winPath((0, _path().resolve)(__dirname, 'assets', 'error.png')), info: winPath((0, _path().resolve)(__dirname, 'assets', 'info.png')), success: winPath((0, _path().resolve)(__dirname, 'assets', 'success.png')), warning: winPath((0, _path().resolve)(__dirname, 'assets', 'warning.png')) }; const type = payload.type, restPayload = _objectWithoutProperties(payload, ["type"]); const noticeConfig = _objectSpread(_objectSpread({}, restPayload), {}, { contentImage: buildInImages[type] || buildInImages.info, icon: winPath((0, _path().resolve)(__dirname, 'assets', 'umi.png')), sound: true }); notifier.notify(noticeConfig); success(); } catch (e) { console.error(chalk.red(`Error: Notify for ${e.message} FAILED`)); failure(e); } break; default: // log('error', chalk.red(`Unhandled message type ${type}`)); // failure(); break; } })(); } start(opts) { var _this8 = this; return _asyncToGenerator(function* () { const _ref2 = opts || {}, browser = _ref2.browser, _ref2$full = _ref2.full, full = _ref2$full === void 0 ? false : _ref2$full; _this8.ctx.full = full; _this8.ctx.browser = browser; return new Promise( /*#__PURE__*/function () { var _ref3 = _asyncToGenerator(function* (resolve, reject) { console.log(`🚀 Starting Umi UI using umi@${process.env.UMI_VERSION}...`); const app = (0, _express().default)(); app.use((0, _compression().default)()); // Serve Static (Production Only) if (!process.env.LOCAL_DEBUG) { app.use(_express().default.static((0, _path().join)(__dirname, '..', 'web/dist'), { index: false })); } /** * Terminal shell resize server */ app.get('/terminal/resize', (0, _resize.default)(_this8.ctx)); // 访问域名打开 app.get('/', (0, _index.default)(_this8.ctx)); app.use('/*', (0, _common.default)(_this8.ctx)); const ss = _sockjs().default.createServer(); const conns = {}; function send(action) { const message = JSON.stringify(action); (0, _debug.debugSocket)(chalk.green.bold('>>>>'), formatLogMessage(message)); Object.keys(conns).forEach(id => { conns[id].write(message); }); } function formatLogMessage(message) { let ret = message.length > 500 ? `${message.slice(0, 500)} ${chalk.gray('...')}` : message; ret = ret.replace(/{"type":"(.+?)"/, `{"type":"${chalk.magenta.bold('$1')}"`); return ret; } ss.on('connection', conn => { if (!conn) { return; } conns[conn.id] = conn; (0, _debug.debugSocket)(`🔗 ${chalk.green('Connected to')}: ${conn.id}`); function success(type, payload) { send({ type: `${type}/success`, payload }); } function failure(type, payload) { send({ type: `${type}/failure`, payload }); } function progress(type, payload) { send({ type: `${type}/progress`, payload }); } _this8.send = send; // 给 packages/umi/src/scripts/dev.js 用 global.g_send = send; const log = (type, message) => { const payload = { date: +new Date(), type, message }; const msg = `${chalk.gray(`[${type}]`)} ${message}`; const logFunc = type === 'error' ? console.error : _debug.debugSocket; logFunc(msg); _this8.logs.push(payload); send({ type: '@@log/message', payload }); }; conn.on('close', () => { (0, _debug.debugSocket)(`😿 ${chalk.red('Disconnected to')}: ${conn.id}`); delete conns[conn.id]; }); conn.on('data', /*#__PURE__*/function () { var _ref4 = _asyncToGenerator(function* (message) { try { const _JSON$parse2 = JSON.parse(message), type = _JSON$parse2.type, payload = _JSON$parse2.payload, lang = _JSON$parse2.$lang, key = _JSON$parse2.$key; (0, _debug.debugSocket)(chalk.blue.bold('<<<<'), formatLogMessage(message)); const serviceArgs = { action: { type, payload, lang }, log, send, success: success.bind(_this8, type), failure: failure.bind(_this8, type), progress: progress.bind(_this8, type) }; // Bigfish extend service if (_this8.basicConfigPath) { const _ref5 = // eslint-disable-next-line import/no-dynamic-require require(_this8.basicConfigPath).default || require(_this8.basicConfigPath) || [], services = _ref5.services; if ((services === null || services === void 0 ? void 0 : services.length) > 0) { // register framework services services.forEach(baseUIService => { baseUIService(serviceArgs); }); } } if (type.startsWith('@@')) { yield _this8.handleCoreData({ type, payload, lang, key }, { log, send, success: success.bind(_this8, type), failure: failure.bind(_this8, type), progress: progress.bind(_this8, type) }); } else { (0, _assert().default)(_this8.servicesByKey[key], `service of key ${key} not exists.`); const service = _this8.servicesByKey[key]; yield service.applyPlugins({ key: 'onUISocket', type: service.ApplyPluginsType.event, args: serviceArgs }); } // eslint-disable-next-line no-empty } catch (e) { console.error(chalk.red(e.stack)); } }); return function (_x3) { return _ref4.apply(this, arguments); }; }()); }); const port = yield portfinder.getPortPromise({ port: process.env.UMI_UI_PORT || process.env.UMI_PORT || 3000 }); const server = app.listen(port, process.env.HOST || '127.0.0.1', err => { if (err) { reject(err); } else { const _process$argv$slice = process.argv.slice(2), _process$argv$slice2 = _slicedToArray(_process$argv$slice, 1), command = _process$argv$slice2[0]; const url = `http://localhost:${port}/`; console.log(command === 'dev' ? `🌈 Umi UI mini Ready on port 3000.` : `⛽️ Ready on ${url}.`); if (browser) { (0, _openBrowser().default)(url); } resolve({ port, server: _this8.server }); // just TEST or ALL ? if (process.send) { const message = { type: 'UI_SERVER_DONE', data: { port, url } }; (0, _debug.default)(`send ${JSON.stringify(message)}`); process.send(message); } } }); ss.installHandlers(server, { prefix: '/umiui', log: () => {} }); _terminal.default.call(_this8, server); _this8.socketServer = ss; _this8.server = server; }); return function (_x, _x2) { return _ref3.apply(this, arguments); }; }()); })(); } /** * 返回 projcet name,如果 project 不存在,则返回 key * @param key project key */ getProjectName(key) { if (!key) { return ''; } const project = this.config.data.projectsByKey[key]; if (!project) { return key; } return project.name; } /** * 是否使用淘宝加速 * @param key project key */ hasTaobaoSpeedUp() { // 一期默认开启,二期走全局配置。 return true; } } exports.default = UmiUI;