@opentapd/tplugin-cli 0.19.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Readme.cloud.md +13 -0
- package/Readme.ex.md +13 -0
- package/Readme.oa.md +23 -0
- package/cli.js +109 -0
- package/config.json +12 -0
- package/index.js +5 -0
- package/lib/create.js +314 -0
- package/lib/deploy.js +278 -0
- package/lib/encrypt.js +59 -0
- package/lib/init.js +132 -0
- package/lib/install.js +59 -0
- package/lib/lint.js +55 -0
- package/lib/login.js +194 -0
- package/lib/logout.js +21 -0
- package/lib/repo.js +52 -0
- package/lib/resources.js +256 -0
- package/lib/serve.js +455 -0
- package/lib/workspace.js +57 -0
- package/package.json +79 -0
- package/scf-bin/node.js +50 -0
- package/scf-bin/python.py +59 -0
- package/util/axios.js +52 -0
- package/util/checkNodeVersion.js +21 -0
- package/util/checkPluginYaml.js +19 -0
- package/util/createDevWorkspace.js +62 -0
- package/util/enhanceErrorMessages.js +23 -0
- package/util/errorHandler.js +131 -0
- package/util/getPluginCode.js +38 -0
- package/util/selectWorkspace.js +70 -0
- package/util/session.js +119 -0
- package/util/spinner.js +14 -0
- package/util/tapd.js +14 -0
- package/util/tools.js +46 -0
- package/util/trimObjectValue.js +10 -0
package/Readme.cloud.md
ADDED
package/Readme.ex.md
ADDED
package/Readme.oa.md
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# TAPD 托管命令行
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
## IDC 网络的使用
|
|
5
|
+
|
|
6
|
+
### 怎看自己是不是IDC网络
|
|
7
|
+
|
|
8
|
+
查看这个[链接](https://iwiki.woa.com/tencent/static/iwiki-editor-pro/dist/preview.html?space=&page=1227785302&id=131410&name=6997554869969258912(1).MP4&size=1160018&language=zh)
|
|
9
|
+
|
|
10
|
+
### 如果是 IDC 网路怎么办
|
|
11
|
+
|
|
12
|
+
```bash
|
|
13
|
+
export TPLUGIN_ENV='idc'
|
|
14
|
+
|
|
15
|
+
tplugin-cli logout
|
|
16
|
+
|
|
17
|
+
tplugin-cli login
|
|
18
|
+
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
[快速入门](https://o.tapd.woa.com/document/plugin-doc/introduction/getting-started.html)
|
|
22
|
+
|
|
23
|
+
### 欢迎反馈
|
package/cli.js
ADDED
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
const { program } = require('commander');
|
|
5
|
+
const chalk = require('chalk');
|
|
6
|
+
const packageJson = require('./package.json');
|
|
7
|
+
const enhanceErrorMessages = require('./util/enhanceErrorMessages');
|
|
8
|
+
const errorHandler = require('./util/errorHandler');
|
|
9
|
+
const tpluginConf = require('./config');
|
|
10
|
+
|
|
11
|
+
process.on('uncaughtException', errorHandler);
|
|
12
|
+
process.on('unhandledRejection', (error) => {
|
|
13
|
+
errorHandler(error, { exit: false });
|
|
14
|
+
});
|
|
15
|
+
/**
|
|
16
|
+
* 获取执行某个命令的Runner
|
|
17
|
+
* @description 执行fn函数,并catch errorhandler
|
|
18
|
+
*/
|
|
19
|
+
function actionRunner(fn) {
|
|
20
|
+
return process.env.NODE_ENV === 'test'
|
|
21
|
+
? fn
|
|
22
|
+
: (...args) => fn(...args).catch(errorHandler);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// version 获取CLI版本
|
|
26
|
+
program.version(packageJson.version)
|
|
27
|
+
.usage('<command> [options]');
|
|
28
|
+
|
|
29
|
+
// create <code> 创建插件
|
|
30
|
+
program.command('create <code>')
|
|
31
|
+
.description('通过CLI创建一个TAPD插件')
|
|
32
|
+
.option('-n, --name <name>', '插件名字')
|
|
33
|
+
.action(actionRunner((code, opts) => require('./lib/create')(code, opts)));
|
|
34
|
+
|
|
35
|
+
// login 登录
|
|
36
|
+
program.command('login')
|
|
37
|
+
.description('用户登录,用于登录使用 cli')
|
|
38
|
+
.option('--login-by-tgit', '使用工蜂登录态登录')
|
|
39
|
+
.action(actionRunner(opts => require('./lib/login')(opts)))
|
|
40
|
+
.allowUnknownOption();
|
|
41
|
+
|
|
42
|
+
// logout 退出登录
|
|
43
|
+
program.command('logout')
|
|
44
|
+
.description('退出当前用户登录用户')
|
|
45
|
+
.action(actionRunner(() => require('./lib/logout')()));
|
|
46
|
+
|
|
47
|
+
// lint 检查插件配置
|
|
48
|
+
program.command('lint')
|
|
49
|
+
.description('插件检查,检查当前插件配置是否正确')
|
|
50
|
+
.action(actionRunner(async () => {
|
|
51
|
+
await require('./lib/lint')();
|
|
52
|
+
console.log('');
|
|
53
|
+
}));
|
|
54
|
+
|
|
55
|
+
// serve 启动本地插件调试
|
|
56
|
+
program.command('serve')
|
|
57
|
+
.description('用于运行和调试本地插件代码,可以选择一个项目作为调试项目,启动后,本地插件代码将直接于目标项目生效')
|
|
58
|
+
.action(actionRunner(() => require('./lib/serve')()));
|
|
59
|
+
|
|
60
|
+
// install 安装指令,安装插件到某个项目
|
|
61
|
+
program.command('install')
|
|
62
|
+
.description('安装测试项目')
|
|
63
|
+
.action(actionRunner(async () => {
|
|
64
|
+
await require('./lib/install')();
|
|
65
|
+
console.log('');
|
|
66
|
+
}));
|
|
67
|
+
|
|
68
|
+
// init 初始化插件
|
|
69
|
+
program.command('init')
|
|
70
|
+
.description('初始化插件配置信息,用于本地调试鉴权')
|
|
71
|
+
.action(actionRunner(() => require('./lib/init')()));
|
|
72
|
+
|
|
73
|
+
// deploy 部署插件
|
|
74
|
+
program.command('deploy')
|
|
75
|
+
.description('部署应用')
|
|
76
|
+
.action(actionRunner(() => require('./lib/deploy')()));
|
|
77
|
+
|
|
78
|
+
// encrtypt 加密敏感变量
|
|
79
|
+
program.command('encrypt <value>')
|
|
80
|
+
.description('加密敏感变量')
|
|
81
|
+
.action(actionRunner(value => require('./lib/encrypt')(value)));
|
|
82
|
+
|
|
83
|
+
// resource 添加新的UI扩展模块
|
|
84
|
+
program.command('resources')
|
|
85
|
+
.description('添加扩展模块模板')
|
|
86
|
+
.action(actionRunner(() => require('./lib/resources')()));
|
|
87
|
+
|
|
88
|
+
// workspace 创建个人专属开发项目
|
|
89
|
+
if (tpluginConf.tapd.pluginEnv !== 'cloud') {
|
|
90
|
+
program.command('workspace')
|
|
91
|
+
.description('创建TAPD开发项目')
|
|
92
|
+
.action(actionRunner(() => require('./lib/workspace')()));
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// repo 手动拉取最新部署的代码包指令
|
|
96
|
+
if (tpluginConf.tapd.pluginEnv !== 'oa') {
|
|
97
|
+
program.command('repo <code>')
|
|
98
|
+
.description('手动拉取最新部署的代码包指令')
|
|
99
|
+
.action(actionRunner(code => require('./lib/repo')(code)));
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
enhanceErrorMessages('missingArgument', argName => `Missing required argument ${chalk.yellow(`<${argName}>`)}.`);
|
|
103
|
+
|
|
104
|
+
enhanceErrorMessages('unknownOption', optionName => `Unknown option ${chalk.yellow(optionName)}.`);
|
|
105
|
+
|
|
106
|
+
enhanceErrorMessages('optionMissingArgument', (option, flag) => `Missing required argument for option ${chalk.yellow(option.flags)}${
|
|
107
|
+
flag ? `, got ${chalk.yellow(flag)}` : ''}`);
|
|
108
|
+
|
|
109
|
+
module.exports = program;
|
package/config.json
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
{
|
|
2
|
+
"tapd": {
|
|
3
|
+
"openHost": "https://open.tapd.cn",
|
|
4
|
+
"tapdHost": "https://tapd.cn",
|
|
5
|
+
"websocketHost": "wss://proxifer.tapd.cn/proxy",
|
|
6
|
+
"apiHost": "https://api.tapd.cn",
|
|
7
|
+
"upgradeWebsocketHost": "wss://upgrader.tapd.cn",
|
|
8
|
+
"pluginEnv": "cloud"
|
|
9
|
+
},
|
|
10
|
+
"npm": {},
|
|
11
|
+
"pip": {}
|
|
12
|
+
}
|
package/index.js
ADDED
package/lib/create.js
ADDED
|
@@ -0,0 +1,314 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright 2021 Tencent Inc. All rights reserved.
|
|
3
|
+
* Author: terrysxu@tencent.com
|
|
4
|
+
* Author: raferzeng@tencent.com
|
|
5
|
+
*
|
|
6
|
+
* The implementation of CLI: create <code>
|
|
7
|
+
*/
|
|
8
|
+
const inquirer = require('inquirer');
|
|
9
|
+
const chalk = require('chalk');
|
|
10
|
+
const { chdir } = require('process');
|
|
11
|
+
const { exec } = require('child_process');
|
|
12
|
+
const tapdsdk = require('../util/tapd');
|
|
13
|
+
const Session = require('../util/session');
|
|
14
|
+
const spinner = require('../util/spinner');
|
|
15
|
+
const tpluginConf = require('../config');
|
|
16
|
+
const json5 = require('json5');
|
|
17
|
+
const _ = require('lodash');
|
|
18
|
+
const fs = require('fs-extra');
|
|
19
|
+
const path = require('path');
|
|
20
|
+
const { downloadAndUnzip } = require('../util/tools');
|
|
21
|
+
const { promisify } = require('util');
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* @description 根据code和option配置,创建插件
|
|
25
|
+
* @param code 唯一标识
|
|
26
|
+
* @param options 选择的创建配置
|
|
27
|
+
*/
|
|
28
|
+
module.exports = async (code, options) => {
|
|
29
|
+
// 初始化Session
|
|
30
|
+
const session = new Session();
|
|
31
|
+
|
|
32
|
+
// 校验登录态
|
|
33
|
+
session.checkAuth();
|
|
34
|
+
|
|
35
|
+
await checkAppParams({
|
|
36
|
+
code,
|
|
37
|
+
name: options.name || code,
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
spinner.start('加载应用模板...');
|
|
41
|
+
// 加载创建模板
|
|
42
|
+
const createTmpl = await getCreateTmpl();
|
|
43
|
+
|
|
44
|
+
if (!createTmpl || !createTmpl.status) {
|
|
45
|
+
spinner.fail(chalk.red('获取模板失败'));
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
spinner.stop();
|
|
50
|
+
|
|
51
|
+
const tmpList = Object.entries(createTmpl.data)
|
|
52
|
+
.map(([key, value]) => ({
|
|
53
|
+
name: `${key} (${value.desc})`,
|
|
54
|
+
value: key,
|
|
55
|
+
}));
|
|
56
|
+
|
|
57
|
+
// 选择创建模板
|
|
58
|
+
const selectedTmpl = await inquirer.prompt([{
|
|
59
|
+
type: 'list',
|
|
60
|
+
name: 'template',
|
|
61
|
+
message: '请选择你要创建的模板:',
|
|
62
|
+
choices: tmpList,
|
|
63
|
+
}]);
|
|
64
|
+
|
|
65
|
+
// 支持的挂载点
|
|
66
|
+
const supportEntrances = _.get(createTmpl, `data.${selectedTmpl.template}.support_entrances`, false);
|
|
67
|
+
const entranceConfigs = supportEntrances ? await selectEntrances() : {};
|
|
68
|
+
|
|
69
|
+
const params = {
|
|
70
|
+
code,
|
|
71
|
+
name: options.name || code,
|
|
72
|
+
template: selectedTmpl.template,
|
|
73
|
+
...entranceConfigs,
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
spinner.start('稍等片刻,正在创建...');
|
|
77
|
+
// 调起创建插件
|
|
78
|
+
const res = await create(params);
|
|
79
|
+
|
|
80
|
+
if (!res || !res.status) {
|
|
81
|
+
spinner.fail('创建插件失败');
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
if (res && res.status) {
|
|
86
|
+
spinner.stop();
|
|
87
|
+
// 创建完成后,拉取代码
|
|
88
|
+
await cloneRepo(res, code);
|
|
89
|
+
}
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* checkAppParams(): 检查插件参数
|
|
94
|
+
* @return array data
|
|
95
|
+
*/
|
|
96
|
+
async function checkAppParams(params) {
|
|
97
|
+
const { data } = await tapdsdk.request({ url: '/open_user_app/check_app_params', method: 'POST', params });
|
|
98
|
+
return data;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* getCreateTmpl(): 获取创建模板列表
|
|
103
|
+
* @return array data
|
|
104
|
+
*/
|
|
105
|
+
async function getCreateTmpl() {
|
|
106
|
+
const { data } = await tapdsdk.request({ url: '/open_user_app/templates', method: 'POST' });
|
|
107
|
+
return data;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* getTmpRepoUrl(): 获取仓库当前代码制品code.zip的临时下载链接
|
|
112
|
+
* @return array data
|
|
113
|
+
*/
|
|
114
|
+
async function getTmpRepoUrl(params) {
|
|
115
|
+
const { data } = await tapdsdk.request({ url: '/open_user_app/get_tmp_repo_url', method: 'POST', params });
|
|
116
|
+
return data;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* getEntranceOpts(): 获取可选过载点列表
|
|
121
|
+
* @return {_key: string, _tags: string, _name: string, ...others: any }[]
|
|
122
|
+
*/
|
|
123
|
+
async function getEntranceOpts() {
|
|
124
|
+
const { data } = await tapdsdk.request({ url: '/open_user_app/entrance_templates', method: 'POST' });
|
|
125
|
+
|
|
126
|
+
return (data.data || []).map((entrance) => {
|
|
127
|
+
// json 解析
|
|
128
|
+
const demo = json5.parse(entrance.demo);
|
|
129
|
+
delete demo.url;
|
|
130
|
+
return {
|
|
131
|
+
...demo,
|
|
132
|
+
_key: entrance.identifier,
|
|
133
|
+
_tags: entrance.tags,
|
|
134
|
+
_name: entrance.name,
|
|
135
|
+
};
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// create(params): 创建插件请求
|
|
140
|
+
async function create(params) {
|
|
141
|
+
const { data } = await tapdsdk.request({ url: '/open_user_app/create_app', method: 'POST', params });
|
|
142
|
+
return data;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* @description clone 创建的插件代码库
|
|
147
|
+
* @param res 插件创建基本信息
|
|
148
|
+
* @param code 插件标识code
|
|
149
|
+
*/
|
|
150
|
+
async function cloneRepo(res, code) {
|
|
151
|
+
if (tpluginConf.tapd.pluginEnv === 'oa') {
|
|
152
|
+
const repoList = [
|
|
153
|
+
{
|
|
154
|
+
name: res.data.git_repo_url,
|
|
155
|
+
value: res.data.git_repo_url,
|
|
156
|
+
},
|
|
157
|
+
{
|
|
158
|
+
name: res.data.git_ssh_url,
|
|
159
|
+
value: res.data.git_ssh_url,
|
|
160
|
+
},
|
|
161
|
+
{
|
|
162
|
+
name: '先缓缓, 稍后手动clone仓库',
|
|
163
|
+
value: 'later',
|
|
164
|
+
},
|
|
165
|
+
];
|
|
166
|
+
// 选择是否拉取仓库
|
|
167
|
+
const gitRepo = await inquirer.prompt([{
|
|
168
|
+
type: 'list',
|
|
169
|
+
name: 'repo',
|
|
170
|
+
message: '应用创建成功,并自动为您生成了代码库,请clone下来进行开发: ',
|
|
171
|
+
choices: repoList,
|
|
172
|
+
}]);
|
|
173
|
+
|
|
174
|
+
if (gitRepo.repo === 'later') {
|
|
175
|
+
spinner.succeed(`应用创建成功, 仓库地址:${res.data.git_repo_url}, ${res.data.git_ssh_url}`);
|
|
176
|
+
return;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
const promiseExec = promisify(exec);
|
|
180
|
+
|
|
181
|
+
await promiseExec(`git clone ${gitRepo.repo}`);
|
|
182
|
+
spinner.succeed('代码拉取成功');
|
|
183
|
+
chdir(code);
|
|
184
|
+
const packageJsonPath = path.join(process.cwd(), 'package.json');
|
|
185
|
+
if (fs.pathExistsSync(packageJsonPath)) {
|
|
186
|
+
// 设置 npm 源到 tencent 源
|
|
187
|
+
if (tpluginConf.tapd.pluginEnv === 'oa') {
|
|
188
|
+
await promiseExec(`npm config set registry ${tpluginConf.npm.registry}`);
|
|
189
|
+
}
|
|
190
|
+
spinner.start('稍等片刻,正在安装依赖...');
|
|
191
|
+
await promiseExec('npm install');
|
|
192
|
+
spinner.succeed('依赖安装成功');
|
|
193
|
+
}
|
|
194
|
+
// ex逻辑
|
|
195
|
+
} else {
|
|
196
|
+
try {
|
|
197
|
+
const params = {
|
|
198
|
+
code,
|
|
199
|
+
};
|
|
200
|
+
|
|
201
|
+
// 获取临时下载仓库链接
|
|
202
|
+
const repoRes = await getTmpRepoUrl(params);
|
|
203
|
+
|
|
204
|
+
if (!repoRes || !repoRes.status) {
|
|
205
|
+
spinner.fail(`应用创建成功,但是获取临时下载仓库链接失败,请手动执行tplugin repo ${code}下载当前${code}插件代码`);
|
|
206
|
+
return;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
const repoList = [
|
|
210
|
+
{
|
|
211
|
+
name: `自动下载${code}仓库`,
|
|
212
|
+
value: 'now',
|
|
213
|
+
},
|
|
214
|
+
{
|
|
215
|
+
name: `先缓缓, 稍后手动下载${code}仓库`,
|
|
216
|
+
value: 'later',
|
|
217
|
+
},
|
|
218
|
+
];
|
|
219
|
+
// 选择是否下载仓库
|
|
220
|
+
const gitRepo = await inquirer.prompt([{
|
|
221
|
+
type: 'list',
|
|
222
|
+
name: 'repo',
|
|
223
|
+
message: `应用创建成功,并自动为您生成了${code}代码库,请下载下来进行开发: `,
|
|
224
|
+
choices: repoList,
|
|
225
|
+
}]);
|
|
226
|
+
|
|
227
|
+
if (gitRepo.repo === 'later') {
|
|
228
|
+
spinner.succeed(`应用创建成功,请手动执行tplugin repo ${code}下载当前${code}插件代码`);
|
|
229
|
+
return;
|
|
230
|
+
}
|
|
231
|
+
await downloadAndUnzip(repoRes.data.download_url);
|
|
232
|
+
} catch (e) {
|
|
233
|
+
e.title = `下载失败,请手动执行tplugin repo ${code}下载当前${code}插件代码`;
|
|
234
|
+
throw e;
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
// selectEntrances(): 选择模板
|
|
240
|
+
async function selectEntrances() {
|
|
241
|
+
spinner.start('加载应用模板...');
|
|
242
|
+
const entranceOpts = await getEntranceOpts();
|
|
243
|
+
|
|
244
|
+
if (!entranceOpts.length) {
|
|
245
|
+
spinner.fail(chalk.red('获取扩展模块模板失败'));
|
|
246
|
+
return;
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
spinner.stop();
|
|
250
|
+
|
|
251
|
+
// 数据格式转化
|
|
252
|
+
const entranceList = entranceOpts.map((item) => {
|
|
253
|
+
const { _key, _name } = item;
|
|
254
|
+
return {
|
|
255
|
+
name: `${_key} (${_name})`,
|
|
256
|
+
value: item,
|
|
257
|
+
};
|
|
258
|
+
});
|
|
259
|
+
|
|
260
|
+
const required = function (value) {
|
|
261
|
+
return value.length ? true : '请按空格键选择扩展模块';
|
|
262
|
+
};
|
|
263
|
+
|
|
264
|
+
// 使用空格选择扩展模块
|
|
265
|
+
const selectedTmpl = await inquirer.prompt([{
|
|
266
|
+
type: 'checkbox',
|
|
267
|
+
name: 'entrance',
|
|
268
|
+
message: '请选择扩展模块:',
|
|
269
|
+
choices: entranceList,
|
|
270
|
+
loop: false,
|
|
271
|
+
validate: required,
|
|
272
|
+
}]);
|
|
273
|
+
|
|
274
|
+
const entrance = selectedTmpl.entrance.filter(item => !item._tags);
|
|
275
|
+
const objectEntrances = selectedTmpl.entrance.filter(item => item._tags);
|
|
276
|
+
let tagsQue = [];
|
|
277
|
+
|
|
278
|
+
// 针对业务挂载点,选择扩展的业务对象,如:需求、缺陷、迭代、任务
|
|
279
|
+
if (objectEntrances.length) {
|
|
280
|
+
const requiredObj = function (value) {
|
|
281
|
+
return value.length ? true : '请按空格键选择业务对象';
|
|
282
|
+
};
|
|
283
|
+
tagsQue = objectEntrances.map(item => ({
|
|
284
|
+
type: 'checkbox',
|
|
285
|
+
name: item._key,
|
|
286
|
+
message: `请选择 ${item._key} 作用的业务对象:`,
|
|
287
|
+
choices: item._tags.split(','),
|
|
288
|
+
validate: requiredObj,
|
|
289
|
+
}));
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
const entranceTmpl = await inquirer.prompt(tagsQue);
|
|
293
|
+
|
|
294
|
+
// 格式化挂载点配置
|
|
295
|
+
const formmatedObjectEntrances = objectEntrances.reduce((pre, objEntrance) => {
|
|
296
|
+
const tmp = entranceTmpl[objEntrance._key];
|
|
297
|
+
return pre.concat(tmp.map(tag => ({
|
|
298
|
+
...objEntrance,
|
|
299
|
+
tag,
|
|
300
|
+
})));
|
|
301
|
+
}, []);
|
|
302
|
+
|
|
303
|
+
const resourceConfigs = entrance.concat(formmatedObjectEntrances);
|
|
304
|
+
|
|
305
|
+
// 组装返回数据
|
|
306
|
+
return {
|
|
307
|
+
entrances: resourceConfigs.map(entrance => (entrance._tags ? `${entrance._key}_${entrance.tag}` : entrance._key)),
|
|
308
|
+
resources_configs: JSON.stringify(resourceConfigs.map(entrance => ({
|
|
309
|
+
..._.omit(entrance, ['_key', '_tags', '_name']),
|
|
310
|
+
key: entrance._key,
|
|
311
|
+
path: entrance._tags ? `pages/${entrance._key}_${entrance.tag}` : `pages/${entrance._key}`,
|
|
312
|
+
}))),
|
|
313
|
+
};
|
|
314
|
+
}
|