neo-cmp-cli 1.0.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.md +236 -0
- package/bin/neo.js +2 -0
- package/package.json +74 -0
- package/src/config/default.config.js +136 -0
- package/src/config/index.js +9 -0
- package/src/initData/defaultTemplate.html +13 -0
- package/src/initData/neo.config.js +99 -0
- package/src/module/index.js +244 -0
- package/src/module/inspect.js +40 -0
- package/src/module/main.js +109 -0
- package/src/module/neoInit.js +44 -0
- package/src/module/neoInitByCopy.js +37 -0
- package/src/oss/publish2oss.js +218 -0
- package/src/plugins/README.md +2 -0
- package/src/template/react-custom-widget-template/.editorconfig +10 -0
- package/src/template/react-custom-widget-template/.prettierrc.js +12 -0
- package/src/template/react-custom-widget-template/README.md +51 -0
- package/src/template/react-custom-widget-template/commitlint.config.js +59 -0
- package/src/template/react-custom-widget-template/neo.config.js +112 -0
- package/src/template/react-custom-widget-template/package.json +56 -0
- package/src/template/react-custom-widget-template/public/css/base.css +283 -0
- package/src/template/react-custom-widget-template/public/scripts/app/bluebird.js +6679 -0
- package/src/template/react-custom-widget-template/public/template.html +13 -0
- package/src/template/react-custom-widget-template/src/assets/css/common.scss +127 -0
- package/src/template/react-custom-widget-template/src/assets/css/mixin.scss +47 -0
- package/src/template/react-custom-widget-template/src/components/info-card/index.jsx +45 -0
- package/src/template/react-custom-widget-template/src/components/info-card/model.js +81 -0
- package/src/template/react-custom-widget-template/src/components/info-card/register.js +4 -0
- package/src/template/react-custom-widget-template/src/components/info-card/style.scss +67 -0
- package/src/template/react-custom-widget-template/src/preview.js +5 -0
- package/src/template/react-ts-custom-widget-template/.editorconfig +10 -0
- package/src/template/react-ts-custom-widget-template/.prettierrc.js +12 -0
- package/src/template/react-ts-custom-widget-template/README.md +53 -0
- package/src/template/react-ts-custom-widget-template/commitlint.config.js +59 -0
- package/src/template/react-ts-custom-widget-template/neo.config.js +106 -0
- package/src/template/react-ts-custom-widget-template/package.json +59 -0
- package/src/template/react-ts-custom-widget-template/public/css/base.css +283 -0
- package/src/template/react-ts-custom-widget-template/public/scripts/app/bluebird.js +6679 -0
- package/src/template/react-ts-custom-widget-template/public/template.html +13 -0
- package/src/template/react-ts-custom-widget-template/src/assets/css/common.scss +127 -0
- package/src/template/react-ts-custom-widget-template/src/assets/css/mixin.scss +47 -0
- package/src/template/react-ts-custom-widget-template/src/components/info-card/index.tsx +70 -0
- package/src/template/react-ts-custom-widget-template/src/components/info-card/plugin.ts +80 -0
- package/src/template/react-ts-custom-widget-template/src/components/info-card/register.ts +5 -0
- package/src/template/react-ts-custom-widget-template/src/components/info-card/style.scss +105 -0
- package/src/template/react-ts-custom-widget-template/src/components/list-widget/README.md +2 -0
- package/src/template/react-ts-custom-widget-template/src/components/list-widget/index.tsx +208 -0
- package/src/template/react-ts-custom-widget-template/src/components/list-widget/model.ts +92 -0
- package/src/template/react-ts-custom-widget-template/src/components/list-widget/register.ts +5 -0
- package/src/template/react-ts-custom-widget-template/src/components/list-widget/style.scss +350 -0
- package/src/template/react-ts-custom-widget-template/src/preview.tsx +37 -0
- package/src/template/react-ts-custom-widget-template/tsconfig.json +68 -0
- package/src/template/vue2-neo-custom-widget/.editorconfig +10 -0
- package/src/template/vue2-neo-custom-widget/.prettierrc.js +12 -0
- package/src/template/vue2-neo-custom-widget/README.md +52 -0
- package/src/template/vue2-neo-custom-widget/commitlint.config.js +59 -0
- package/src/template/vue2-neo-custom-widget/neo.config.js +122 -0
- package/src/template/vue2-neo-custom-widget/package.json +59 -0
- package/src/template/vue2-neo-custom-widget/public/css/base.css +283 -0
- package/src/template/vue2-neo-custom-widget/public/scripts/app/bluebird.js +6679 -0
- package/src/template/vue2-neo-custom-widget/public/template.html +13 -0
- package/src/template/vue2-neo-custom-widget/src/assets/css/common.scss +126 -0
- package/src/template/vue2-neo-custom-widget/src/assets/css/mixin.scss +47 -0
- package/src/template/vue2-neo-custom-widget/src/preview.js +9 -0
- package/src/template/vue2-neo-custom-widget/src/widgets/info-card/index.vue +131 -0
- package/src/template/vue2-neo-custom-widget/src/widgets/info-card/plugin.js +81 -0
- package/src/template/vue2-neo-custom-widget/src/widgets/info-card/register.js +8 -0
- package/src/utils/getConfigObj.js +18 -0
- package/src/utils/getEntries.js +54 -0
- package/src/utils/neoConfigInit.js +13 -0
- package/src/utils/neoParams.js +12 -0
- package/src/utils/pathUtils.js +23 -0
- package/src/utils/projectNameValidator.js +76 -0
- package/src/utils/replaceInFiles.js +47 -0
- package/src/utils/replaceInPackage.js +134 -0
- package/test/demo.js +3 -0
|
@@ -0,0 +1,244 @@
|
|
|
1
|
+
const figlet = require('figlet'); // 用于输出图形文字
|
|
2
|
+
const yargs = require('yargs'); // 命令行工具
|
|
3
|
+
const chalk = require('chalk'); // 带样式的log输出
|
|
4
|
+
const inquirer = require('inquirer'); // 问答式交互
|
|
5
|
+
|
|
6
|
+
const neoInit = require('./neoInit.js');
|
|
7
|
+
const neoInitByCopy = require('./neoInitByCopy.js');
|
|
8
|
+
const inspect = require('./inspect.js'); // 输出当前项目配置文件
|
|
9
|
+
const neoConfigInit = require('../utils/neoConfigInit.js');
|
|
10
|
+
const { validateProjectName } = require('../utils/projectNameValidator.js');
|
|
11
|
+
const mainAction = require('./main.js'); // 入口文件
|
|
12
|
+
|
|
13
|
+
// neo 的 package 文件
|
|
14
|
+
const neoPackage = require('../../package.json');
|
|
15
|
+
|
|
16
|
+
const titleTip = function (msg) {
|
|
17
|
+
return chalk.green(chalk.bold(msg));
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
const bigTip = figlet.textSync('neo', {
|
|
21
|
+
font: 'Lean'
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
console.log(chalk.green(bigTip));
|
|
25
|
+
console.log(chalk.green(`当前版本:v${neoPackage.version}.\n`));
|
|
26
|
+
|
|
27
|
+
yargs
|
|
28
|
+
.command(
|
|
29
|
+
'init [options]',
|
|
30
|
+
'创建一个自定义组件',
|
|
31
|
+
(yargs) => {
|
|
32
|
+
yargs
|
|
33
|
+
.reset()
|
|
34
|
+
.usage(titleTip('Usage') + ': $0 init [options]')
|
|
35
|
+
.option('type', {
|
|
36
|
+
alias: 't',
|
|
37
|
+
describe: '自定义组件类型(react ts 技术栈/ vue2.0 技术栈/ react 技术栈)'
|
|
38
|
+
})
|
|
39
|
+
.option('name', {
|
|
40
|
+
alias: 'n',
|
|
41
|
+
describe: '自定义组件项目名称'
|
|
42
|
+
})
|
|
43
|
+
/*
|
|
44
|
+
// 暂不提供 github 下载模式(网络原因,下载速度慢)
|
|
45
|
+
.option('mode', {
|
|
46
|
+
alias: 'm',
|
|
47
|
+
describe: '自定义组件下载模式(github / copy)',
|
|
48
|
+
default: 'copy'
|
|
49
|
+
})
|
|
50
|
+
*/
|
|
51
|
+
.alias('h', 'help');
|
|
52
|
+
},
|
|
53
|
+
(argv) => {
|
|
54
|
+
if (argv.type && argv.name) {
|
|
55
|
+
if (argv.mode === 'github') {
|
|
56
|
+
neoInit(argv.type, argv.name);
|
|
57
|
+
} else {
|
|
58
|
+
neoInitByCopy(argv.type, argv.name);
|
|
59
|
+
}
|
|
60
|
+
} else {
|
|
61
|
+
const questions = [];
|
|
62
|
+
// 初始化项目模板时,当用户未设置项目类型type时,以列表形式展示当前可以使用的项目模板
|
|
63
|
+
const neoWidgetTemplates = [
|
|
64
|
+
{
|
|
65
|
+
name: 'react&ts 自定义组件',
|
|
66
|
+
value: 'react-ts',
|
|
67
|
+
short: 'react-ts'
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
name: 'react 自定义组件',
|
|
71
|
+
value: 'react',
|
|
72
|
+
short: 'react'
|
|
73
|
+
},
|
|
74
|
+
{
|
|
75
|
+
name: 'vue2 自定义组件',
|
|
76
|
+
value: 'vue2',
|
|
77
|
+
short: 'vue2'
|
|
78
|
+
}
|
|
79
|
+
/*
|
|
80
|
+
{
|
|
81
|
+
name: 'vue3 自定义组件',
|
|
82
|
+
value: 'vue3',
|
|
83
|
+
short: 'vue3'
|
|
84
|
+
}
|
|
85
|
+
*/
|
|
86
|
+
];
|
|
87
|
+
|
|
88
|
+
if (!argv.type) {
|
|
89
|
+
questions.push({
|
|
90
|
+
name: 'type',
|
|
91
|
+
type: 'list',
|
|
92
|
+
message: '请选择您要创建的自定义组件类型: ',
|
|
93
|
+
default: 'react-ts',
|
|
94
|
+
choices: neoWidgetTemplates
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
// 当用户未设置存放项目的目录地址时,提示用户
|
|
98
|
+
if (!argv.name) {
|
|
99
|
+
questions.push({
|
|
100
|
+
name: 'name',
|
|
101
|
+
type: 'input',
|
|
102
|
+
message: '请设置自定义组件项目名称(默认 neoCustomWidget):',
|
|
103
|
+
default: 'neoCustomWidget'
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
inquirer.prompt(questions).then((ans) => {
|
|
107
|
+
// 验证项目名称是否合法
|
|
108
|
+
const { isValid, errors } = validateProjectName(ans.name);
|
|
109
|
+
if (!isValid) {
|
|
110
|
+
console.error(errors.join('\n'));
|
|
111
|
+
process.exit(1);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
if (argv.mode === 'github') {
|
|
115
|
+
neoInit(ans.type, ans.name);
|
|
116
|
+
} else {
|
|
117
|
+
neoInitByCopy(ans.type, ans.name);
|
|
118
|
+
}
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
)
|
|
123
|
+
.command(
|
|
124
|
+
'config init',
|
|
125
|
+
'初始化 neo 配置文件',
|
|
126
|
+
(yargs) => {
|
|
127
|
+
yargs
|
|
128
|
+
.reset()
|
|
129
|
+
.usage(titleTip('Usage') + ': $0 config init')
|
|
130
|
+
.alias('h', 'help');
|
|
131
|
+
},
|
|
132
|
+
() => {
|
|
133
|
+
neoConfigInit('neo.config.js');
|
|
134
|
+
}
|
|
135
|
+
)
|
|
136
|
+
.command(
|
|
137
|
+
'preview',
|
|
138
|
+
'开启组件预览模式(仅预览组件本身内容)',
|
|
139
|
+
(yargs) => {
|
|
140
|
+
yargs
|
|
141
|
+
.reset()
|
|
142
|
+
.usage(titleTip('Usage') + ': $0 dev')
|
|
143
|
+
.alias('h', 'help');
|
|
144
|
+
},
|
|
145
|
+
(argv) => {
|
|
146
|
+
mainAction.preview();
|
|
147
|
+
}
|
|
148
|
+
)
|
|
149
|
+
.command(
|
|
150
|
+
'linkDebug',
|
|
151
|
+
'开启外链调试模式(在线上页面设计器端调试)',
|
|
152
|
+
(yargs) => {
|
|
153
|
+
yargs
|
|
154
|
+
.reset()
|
|
155
|
+
.usage(titleTip('Usage') + ': $0 dev')
|
|
156
|
+
.alias('h', 'help');
|
|
157
|
+
},
|
|
158
|
+
(argv) => {
|
|
159
|
+
mainAction.linkDebug();
|
|
160
|
+
}
|
|
161
|
+
)
|
|
162
|
+
.command(
|
|
163
|
+
'build',
|
|
164
|
+
'构建生产环境代码',
|
|
165
|
+
(yargs) => {
|
|
166
|
+
yargs
|
|
167
|
+
.reset()
|
|
168
|
+
.usage(titleTip('Usage') + ': $0 build')
|
|
169
|
+
.alias('h', 'help');
|
|
170
|
+
},
|
|
171
|
+
(argv) => {
|
|
172
|
+
mainAction.build();
|
|
173
|
+
}
|
|
174
|
+
)
|
|
175
|
+
.command(
|
|
176
|
+
'build2lib',
|
|
177
|
+
'构建lib库',
|
|
178
|
+
(yargs) => {
|
|
179
|
+
yargs
|
|
180
|
+
.reset()
|
|
181
|
+
.usage(titleTip('Usage') + ': $0 build2lib')
|
|
182
|
+
.alias('h', 'help');
|
|
183
|
+
},
|
|
184
|
+
(argv) => {
|
|
185
|
+
mainAction.build2lib(); // 构建library
|
|
186
|
+
}
|
|
187
|
+
)
|
|
188
|
+
.command(
|
|
189
|
+
'publish2oss',
|
|
190
|
+
'发布到oss',
|
|
191
|
+
(yargs) => {
|
|
192
|
+
yargs
|
|
193
|
+
.reset()
|
|
194
|
+
.usage(titleTip('Usage') + ': $0 build2lib')
|
|
195
|
+
.alias('h', 'help');
|
|
196
|
+
},
|
|
197
|
+
(argv) => {
|
|
198
|
+
mainAction.publish2oss(); // 构建并发布脚本到oss
|
|
199
|
+
}
|
|
200
|
+
)
|
|
201
|
+
.command(
|
|
202
|
+
'build2esm',
|
|
203
|
+
'构建esm模块',
|
|
204
|
+
(yargs) => {
|
|
205
|
+
yargs
|
|
206
|
+
.reset()
|
|
207
|
+
.usage(titleTip('Usage') + ': $0 build2esm')
|
|
208
|
+
.option('fileName', {
|
|
209
|
+
alias: 'n',
|
|
210
|
+
describe: '输出的文件名',
|
|
211
|
+
default: ''
|
|
212
|
+
})
|
|
213
|
+
.alias('h', 'help');
|
|
214
|
+
},
|
|
215
|
+
(argv) => {
|
|
216
|
+
mainAction.build2esm(argv.fileName); // 构建esm
|
|
217
|
+
}
|
|
218
|
+
)
|
|
219
|
+
.command(
|
|
220
|
+
'inspect',
|
|
221
|
+
'输出当前配置文件',
|
|
222
|
+
(yargs) => {
|
|
223
|
+
yargs
|
|
224
|
+
.reset()
|
|
225
|
+
.usage(titleTip('Usage') + ': $0 inspect')
|
|
226
|
+
.option('type', {
|
|
227
|
+
alias: 't',
|
|
228
|
+
describe: '环境类型(本地调试环境/生产环境/library构建环境)',
|
|
229
|
+
default: 'build'
|
|
230
|
+
})
|
|
231
|
+
.alias('h', 'help');
|
|
232
|
+
},
|
|
233
|
+
(argv) => {
|
|
234
|
+
inspect(argv.type);
|
|
235
|
+
}
|
|
236
|
+
)
|
|
237
|
+
.alias('h', 'help')
|
|
238
|
+
.alias('v', 'version')
|
|
239
|
+
.help()
|
|
240
|
+
.updateStrings({
|
|
241
|
+
'Usage:': titleTip('Usage:'),
|
|
242
|
+
'Commands:': titleTip('Commands:'),
|
|
243
|
+
'Options:': titleTip('Options:')
|
|
244
|
+
}).argv;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
const path = require('path');
|
|
2
|
+
const ora = require('ora');
|
|
3
|
+
const fs = require('fs');
|
|
4
|
+
const { getCurWebpackConfig } = require('akfun'); // 用于获取当前webpack配置的方法
|
|
5
|
+
const curConfig = require('../config/index');
|
|
6
|
+
const { consoleTag } = require('../utils/neoParams'); // 输出标记
|
|
7
|
+
|
|
8
|
+
// 根据当前配置文件内容创建指定名称的文件
|
|
9
|
+
const createConfigJs = function (fileName, fileCont) {
|
|
10
|
+
let filePath = path.resolve(process.cwd(), fileName);
|
|
11
|
+
|
|
12
|
+
fs.writeFile(filePath, JSON.stringify(fileCont, null, 2), (err) => {
|
|
13
|
+
if (err) {
|
|
14
|
+
throw Error(err);
|
|
15
|
+
}
|
|
16
|
+
});
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* 用于输出当前项目配置文件
|
|
21
|
+
*/
|
|
22
|
+
module.exports = (type) => {
|
|
23
|
+
const spinner = ora(`${consoleTag}正在获取当前环境的配置数据...`).start();
|
|
24
|
+
if (type === 'dev') {
|
|
25
|
+
const devConfig = getCurWebpackConfig(type, curConfig);
|
|
26
|
+
createConfigJs('current-neo-dev-config.js', devConfig);
|
|
27
|
+
spinner.succeed(`${consoleTag}当前配置数据已输出至 current-neo-dev-config.js中。`);
|
|
28
|
+
} else if (type === 'lib') {
|
|
29
|
+
const libraryConfig = getCurWebpackConfig(type, curConfig);
|
|
30
|
+
createConfigJs('current-neo-build2lib-config.js', libraryConfig);
|
|
31
|
+
spinner.succeed(`${consoleTag}当前配置数据已输出至 current-neo-build2lib-config.js中。`);
|
|
32
|
+
} else if (type === 'build') {
|
|
33
|
+
const prodConfig = getCurWebpackConfig(type, curConfig);
|
|
34
|
+
// 默认输出生产环境的配置文件
|
|
35
|
+
createConfigJs('current-neo-build-config.js', prodConfig);
|
|
36
|
+
spinner.succeed(`${consoleTag}当前配置数据已输出至 current-neo-build-config.js。`);
|
|
37
|
+
} else {
|
|
38
|
+
spinner.fail(`type 不能为空。`);
|
|
39
|
+
}
|
|
40
|
+
};
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
const akfun = require('akfun');
|
|
2
|
+
const path = require('path');
|
|
3
|
+
const neoInit = require('./neoInit');
|
|
4
|
+
const neoInitByCopy = require('./neoInitByCopy');
|
|
5
|
+
const inspect = require('./inspect');
|
|
6
|
+
const neoConfigInit = require('../utils/neoConfigInit.js');
|
|
7
|
+
const { consoleTag } = require('../utils/neoParams');
|
|
8
|
+
const curConfig = require('../config/index'); // 获取当前项目根目录下的配置文件
|
|
9
|
+
const publish2oss = require('../oss/publish2oss');
|
|
10
|
+
const getEntries = require('../utils/getEntries');
|
|
11
|
+
|
|
12
|
+
const getValue = (originValue, defaultValue) => {
|
|
13
|
+
return originValue !== undefined ? originValue : defaultValue;
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
module.exports = {
|
|
17
|
+
neoInit,
|
|
18
|
+
neoInitByCopy,
|
|
19
|
+
inspect,
|
|
20
|
+
neoConfigInit,
|
|
21
|
+
preview: () => {
|
|
22
|
+
// 预览组件本身内容
|
|
23
|
+
if (!curConfig.preview) {
|
|
24
|
+
console.error('未找到 preview 相关配置。');
|
|
25
|
+
process.exit(1);
|
|
26
|
+
}
|
|
27
|
+
curConfig.dev = Object.assign(curConfig.dev, curConfig.preview); // 将 preview 设置给 dev
|
|
28
|
+
delete curConfig.preview;
|
|
29
|
+
|
|
30
|
+
akfun.dev(curConfig, consoleTag);
|
|
31
|
+
},
|
|
32
|
+
linkDebug: () => {
|
|
33
|
+
// 外链调试模式
|
|
34
|
+
if (!curConfig.linkDebug) {
|
|
35
|
+
console.error('未找到 debug 相关配置。');
|
|
36
|
+
process.exit(1);
|
|
37
|
+
}
|
|
38
|
+
// 将 linkDebug 设置给 dev
|
|
39
|
+
curConfig.dev = Object.assign(curConfig.dev, curConfig.linkDebug);
|
|
40
|
+
|
|
41
|
+
delete curConfig.linkDebug;
|
|
42
|
+
|
|
43
|
+
delete curConfig.dev.ignoreNodeModules; // 需要注入依赖
|
|
44
|
+
curConfig.webpack.ignoreNodeModules = false;
|
|
45
|
+
|
|
46
|
+
const curEntry = curConfig.dev.entry;
|
|
47
|
+
|
|
48
|
+
if (!curEntry || Object.keys(curEntry).length === 0) {
|
|
49
|
+
// 如果未配置 entry,则自动生成 entry
|
|
50
|
+
const entries = getEntries('linkDebug', curConfig.componentsDir);
|
|
51
|
+
if (entries && Object.keys(entries).length > 0) {
|
|
52
|
+
curConfig.dev.entry = entries;
|
|
53
|
+
console.info('已自动生成 entry 入口配置:', entries);
|
|
54
|
+
} else {
|
|
55
|
+
console.error('未找到自定义组件,请检查 neo.config.js 中的 linkDebug / entry 配置。');
|
|
56
|
+
process.exit(1);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
akfun.dev(curConfig, consoleTag);
|
|
61
|
+
},
|
|
62
|
+
build: () => akfun.build('build', curConfig, consoleTag), // 构建脚本:生产环境
|
|
63
|
+
build2lib: () => {
|
|
64
|
+
const curEntry = curConfig.build2lib.entry;
|
|
65
|
+
|
|
66
|
+
if (!curEntry || Object.keys(curEntry).length === 0) {
|
|
67
|
+
// 如果未配置 entry,则自动生成 entry
|
|
68
|
+
const entries = getEntries('build2lib', curConfig.componentsDir);
|
|
69
|
+
if (entries && Object.keys(entries).length > 0) {
|
|
70
|
+
curConfig.build2lib.entry = entries;
|
|
71
|
+
console.info('已自动生成 entry 入口配置:', entries);
|
|
72
|
+
} else {
|
|
73
|
+
console.error('未找到自定义组件,请检查 neo.config.js 中的 build2lib / entry 配置。');
|
|
74
|
+
process.exit(1);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
akfun.build('lib', curConfig, consoleTag);
|
|
79
|
+
}, // 构建脚本:生产环境
|
|
80
|
+
publish2oss: () => {
|
|
81
|
+
// 将 publish2oss 相关配置设置给 build2lib
|
|
82
|
+
const publish2ossConfig = curConfig.publish2oss;
|
|
83
|
+
curConfig.build2lib = Object.assign(curConfig.build2lib, publish2ossConfig);
|
|
84
|
+
|
|
85
|
+
const curEntry = curConfig.build2lib.entry;
|
|
86
|
+
|
|
87
|
+
if (!curEntry || Object.keys(curEntry).length === 0) {
|
|
88
|
+
// 如果未配置 entry,则自动生成 entry
|
|
89
|
+
const entries = getEntries('build2lib', curConfig.componentsDir);
|
|
90
|
+
if (entries && Object.keys(entries).length > 0) {
|
|
91
|
+
curConfig.build2lib.entry = entries;
|
|
92
|
+
console.info('已自动生成 entry 入口配置:', entries);
|
|
93
|
+
} else {
|
|
94
|
+
console.error('未找到自定义组件,请检查 neo.config.js 中的 publish2oss / entry 配置。');
|
|
95
|
+
process.exit(1);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
akfun.build('lib', curConfig, consoleTag, () => {
|
|
100
|
+
// 构建完成后,执行 publish2oss
|
|
101
|
+
publish2oss(
|
|
102
|
+
publish2ossConfig.ossType,
|
|
103
|
+
publish2ossConfig.ossConfig,
|
|
104
|
+
publish2ossConfig.assetsRoot
|
|
105
|
+
);
|
|
106
|
+
});
|
|
107
|
+
},
|
|
108
|
+
build2esm: (fileName) => akfun.build2esm(fileName, curConfig, consoleTag) // 构建esm输出模块
|
|
109
|
+
};
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
const { gitClone } = require('akfun');
|
|
2
|
+
const { consoleTag } = require('../utils/neoParams'); // 输出标记
|
|
3
|
+
const { replaceInPackage } = require('../utils/replaceInPackage');
|
|
4
|
+
|
|
5
|
+
const templateList = {
|
|
6
|
+
react: {
|
|
7
|
+
projectName: 'react-custom-widget-template',
|
|
8
|
+
url: 'git@github.com:wibetter/react-custom-widget-template.git'
|
|
9
|
+
},
|
|
10
|
+
'react-ts': {
|
|
11
|
+
projectName: 'react-ts-custom-widget-template',
|
|
12
|
+
url: 'git@github.com:wibetter/react-ts-custom-widget-template.git'
|
|
13
|
+
},
|
|
14
|
+
vue2: {
|
|
15
|
+
projectName: 'vue2-neo-custom-widget',
|
|
16
|
+
url: 'git@github.com:wibetter/vue2-neo-custom-widget.git'
|
|
17
|
+
}
|
|
18
|
+
/*
|
|
19
|
+
'vue3': {
|
|
20
|
+
projectName: 'vue3-neo-custom-widget',
|
|
21
|
+
url: 'git@github.com:wibetter/vue3-neo-custom-widget.git'
|
|
22
|
+
}
|
|
23
|
+
*/
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
const neoInit = function (type, projectName) {
|
|
27
|
+
const currentTemplate = templateList[type || 'react'];
|
|
28
|
+
const currentTemplateUrl = currentTemplate.url;
|
|
29
|
+
const finalProjectName = projectName || 'neoCustomWidget';
|
|
30
|
+
|
|
31
|
+
gitClone(
|
|
32
|
+
currentTemplateUrl,
|
|
33
|
+
finalProjectName,
|
|
34
|
+
() => {
|
|
35
|
+
// 克隆完成后,替换项目名称
|
|
36
|
+
replaceInPackage(finalProjectName, currentTemplate.projectName, finalProjectName);
|
|
37
|
+
replaceInPackage(finalProjectPath, 'wibetter', 'xxx');
|
|
38
|
+
replaceInPackage(finalProjectPath, 'neo自定义组件模板', 'neo自定义组件');
|
|
39
|
+
},
|
|
40
|
+
consoleTag
|
|
41
|
+
);
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
module.exports = neoInit;
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
const fs = require('fs-extra');
|
|
2
|
+
const path = require('path');
|
|
3
|
+
const { consoleTag } = require('../utils/neoParams'); // 输出标记
|
|
4
|
+
const { replaceInPackage } = require('../utils/replaceInPackage');
|
|
5
|
+
|
|
6
|
+
const templateList = {
|
|
7
|
+
react: {
|
|
8
|
+
projectName: 'react-custom-widget-template',
|
|
9
|
+
dir: path.resolve(__dirname, '../template/react-custom-widget-template')
|
|
10
|
+
},
|
|
11
|
+
'react-ts': {
|
|
12
|
+
projectName: 'react-ts-custom-widget-template',
|
|
13
|
+
dir: path.resolve(__dirname, '../template/react-ts-custom-widget-template')
|
|
14
|
+
},
|
|
15
|
+
vue2: {
|
|
16
|
+
projectName: 'vue2-neo-custom-widget',
|
|
17
|
+
dir: path.resolve(__dirname, '../template/vue2-neo-custom-widget')
|
|
18
|
+
}
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
const neoInitByCopy = function (type, projectName) {
|
|
22
|
+
const currentTemplate = templateList[type || 'react'];
|
|
23
|
+
const currentTemplateDir = currentTemplate.dir;
|
|
24
|
+
const finalProjectName = projectName || 'neoCustomWidget';
|
|
25
|
+
const finalProjectPath = path.resolve(process.cwd(), finalProjectName);
|
|
26
|
+
|
|
27
|
+
fs.copy(currentTemplateDir, finalProjectPath)
|
|
28
|
+
.then(() => {
|
|
29
|
+
replaceInPackage(finalProjectPath, currentTemplate.projectName, finalProjectName);
|
|
30
|
+
replaceInPackage(finalProjectPath, 'wibetter', 'xxx');
|
|
31
|
+
replaceInPackage(finalProjectPath, 'neo自定义组件模板', 'neo自定义组件');
|
|
32
|
+
console.log(`${consoleTag}已创建自定义组件(${finalProjectName})!`);
|
|
33
|
+
})
|
|
34
|
+
.catch((err) => console.error(`${consoleTag}自定义组件模板下载失败:`, err));
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
module.exports = neoInitByCopy;
|
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
const { aliBOS, baiduBOS } = require('akfun');
|
|
2
|
+
const fs = require('fs');
|
|
3
|
+
const path = require('path');
|
|
4
|
+
const { catchCurPackageJson } = require('../utils/pathUtils');
|
|
5
|
+
const getConfigObj = require('../utils/getConfigObj');
|
|
6
|
+
|
|
7
|
+
// 获取当前项目的package文件
|
|
8
|
+
const currentPackageJsonDir = catchCurPackageJson();
|
|
9
|
+
const currentPackageJson = getConfigObj(currentPackageJsonDir);
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* 将构建产物上传到指定 oss 存储桶
|
|
13
|
+
*
|
|
14
|
+
* @param {string} ossType oss 类型:baidu、ali
|
|
15
|
+
* @param {object} ossConfig oss 配置
|
|
16
|
+
* @param {string} assetsRoot 构建产物的目录
|
|
17
|
+
* @param {array} fileExtensions 需要上传的文件类型,默认 ['.js', '.css']
|
|
18
|
+
*/
|
|
19
|
+
const publish2oss = (ossType, ossConfig, assetsRoot, fileExtensions = ['.js', '.css']) => {
|
|
20
|
+
if (ossType !== 'baidu' && ossType !== 'ali') {
|
|
21
|
+
console.error(`不支持的oss类型: ${ossType}`);
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
const bosClient = getBosClient(ossType, ossConfig);
|
|
25
|
+
if (!assetsRoot) {
|
|
26
|
+
console.error('assetsRoot 不能为空');
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
if (!fs.existsSync(assetsRoot)) {
|
|
30
|
+
console.error(`assetsRoot 不存在: ${assetsRoot}`);
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
const files = fs.readdirSync(assetsRoot); // 读取构建目录下的所有文件
|
|
34
|
+
|
|
35
|
+
// 并行上传所有指定类型的文件
|
|
36
|
+
const uploadPromises = files.map(async (file) => {
|
|
37
|
+
const filePath = path.join(assetsRoot, file);
|
|
38
|
+
// 获取文件状态
|
|
39
|
+
const fileStat = fs.statSync(filePath);
|
|
40
|
+
// 检查文件扩展名
|
|
41
|
+
// const fileExt = path.extname(file);
|
|
42
|
+
const fileInfo = path.parse(filePath);
|
|
43
|
+
if (fileStat.isFile() && fileExtensions.includes(fileInfo.ext)) {
|
|
44
|
+
const objectKey = addVersionToFilename(file);
|
|
45
|
+
try {
|
|
46
|
+
// 判断线上是否存在重名文件,避免被覆盖
|
|
47
|
+
const historyResult = await bosClient.get(objectKey);
|
|
48
|
+
if (historyResult && historyResult.url) {
|
|
49
|
+
return {
|
|
50
|
+
success: false,
|
|
51
|
+
status: '文件上传失败',
|
|
52
|
+
widgetName: fileInfo.name,
|
|
53
|
+
fileName: file,
|
|
54
|
+
filepath: filePath,
|
|
55
|
+
ossPath: historyResult.url,
|
|
56
|
+
error: '线上存在重名文件。'
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
// 上传文件
|
|
60
|
+
const result = await bosClient.upload(objectKey, filePath);
|
|
61
|
+
return {
|
|
62
|
+
success: true,
|
|
63
|
+
status: '文件上传成功',
|
|
64
|
+
fileName: file,
|
|
65
|
+
widgetName: fileInfo.name,
|
|
66
|
+
filepath: filePath,
|
|
67
|
+
ossPath: getFilePath(ossType, ossConfig.bucket, objectKey),
|
|
68
|
+
resultMsg: result
|
|
69
|
+
};
|
|
70
|
+
} catch (error) {
|
|
71
|
+
return {
|
|
72
|
+
success: false,
|
|
73
|
+
status: '文件上传失败',
|
|
74
|
+
widgetName: fileInfo.name,
|
|
75
|
+
fileName: file,
|
|
76
|
+
filepath: filePath,
|
|
77
|
+
error: error.message
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
Promise.all(uploadPromises)
|
|
84
|
+
.then((results) => {
|
|
85
|
+
/*
|
|
86
|
+
const { succeedFiles, errorFiles } = getResultFiles(results);
|
|
87
|
+
if (succeedFiles.length > 0) {
|
|
88
|
+
console.info('已成功上传如下文件:\n', succeedFiles);
|
|
89
|
+
}
|
|
90
|
+
if (errorFiles.length > 0) {
|
|
91
|
+
console.info('上传失败的文件有:\n', errorFiles);
|
|
92
|
+
}
|
|
93
|
+
*/
|
|
94
|
+
const widgetFilesMap = getResultFilesByWidgetName(results);
|
|
95
|
+
if (widgetFilesMap) {
|
|
96
|
+
console.info('上传至 OSS 的文件信息:\n', widgetFilesMap);
|
|
97
|
+
}
|
|
98
|
+
})
|
|
99
|
+
.catch((error) => {
|
|
100
|
+
console.error('批量上传文件异常:\n', error);
|
|
101
|
+
});
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
// 根据 ossType 获取对应的 BosClient
|
|
105
|
+
const getBosClient = (ossType, ossConfig) => {
|
|
106
|
+
if (ossType === 'baidu') {
|
|
107
|
+
return new baiduBOS(
|
|
108
|
+
ossConfig.endpoint,
|
|
109
|
+
ossConfig.bucket,
|
|
110
|
+
ossConfig.AccessKeyId || ossConfig.AccessKeyID || ossConfig.accessKeyId || ossConfig.accessKeyID,
|
|
111
|
+
ossConfig.AccessKeySecret
|
|
112
|
+
);
|
|
113
|
+
} else if (ossType === 'ali') {
|
|
114
|
+
return new aliBOS(
|
|
115
|
+
ossConfig.endpoint,
|
|
116
|
+
ossConfig.bucket,
|
|
117
|
+
ossConfig.AccessKeyId || ossConfig.AccessKeyID || ossConfig.accessKeyId || ossConfig.accessKeyID,
|
|
118
|
+
ossConfig.AccessKeySecret
|
|
119
|
+
);
|
|
120
|
+
}
|
|
121
|
+
};
|
|
122
|
+
|
|
123
|
+
const getFilePath = (ossType, bucket, objectKey) => {
|
|
124
|
+
const regions = {
|
|
125
|
+
baidu: 'bj.bcebos.com',
|
|
126
|
+
ali: 'oss-cn-beijing.aliyuncs.com'
|
|
127
|
+
};
|
|
128
|
+
return `https://${bucket}.${regions[ossType]}/${objectKey}`;
|
|
129
|
+
};
|
|
130
|
+
|
|
131
|
+
// 获取上传成功和失败的文件信息
|
|
132
|
+
const getResultFiles = (files) => {
|
|
133
|
+
const succeedFiles = [];
|
|
134
|
+
const errorFiles = [];
|
|
135
|
+
files.forEach((file) => {
|
|
136
|
+
if (file && file.success) {
|
|
137
|
+
succeedFiles.push({
|
|
138
|
+
fileName: file.fileName,
|
|
139
|
+
ossPath: file.ossPath
|
|
140
|
+
});
|
|
141
|
+
} else if (file && !file.success) {
|
|
142
|
+
errorFiles.push({
|
|
143
|
+
fileName: file.fileName,
|
|
144
|
+
error: file.error,
|
|
145
|
+
ossPath: file.ossPath
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
});
|
|
149
|
+
return {
|
|
150
|
+
succeedFiles,
|
|
151
|
+
errorFiles
|
|
152
|
+
};
|
|
153
|
+
};
|
|
154
|
+
|
|
155
|
+
// 获取上传文件关键信息(文件名、oss路径)
|
|
156
|
+
const getResultFile = (file) => {
|
|
157
|
+
if (file && file.success) {
|
|
158
|
+
return {
|
|
159
|
+
fileName: file.fileName,
|
|
160
|
+
ossPath: file.ossPath
|
|
161
|
+
};
|
|
162
|
+
} else if (file && !file.success) {
|
|
163
|
+
return {
|
|
164
|
+
error: file.error,
|
|
165
|
+
fileName: file.fileName,
|
|
166
|
+
ossPath: file.ossPath
|
|
167
|
+
};
|
|
168
|
+
}
|
|
169
|
+
};
|
|
170
|
+
|
|
171
|
+
// 按组件名称进行分类
|
|
172
|
+
const getResultFilesByWidgetName = (files) => {
|
|
173
|
+
const widgetFilesMap = {};
|
|
174
|
+
files.forEach((file) => {
|
|
175
|
+
if (!file || !file.widgetName) {
|
|
176
|
+
return;
|
|
177
|
+
}
|
|
178
|
+
let widgetName = file.widgetName;
|
|
179
|
+
if (widgetName.includes('Plugin')) {
|
|
180
|
+
widgetName = widgetName.replace('Plugin', '');
|
|
181
|
+
}
|
|
182
|
+
if (widgetFilesMap[widgetName]) {
|
|
183
|
+
widgetFilesMap[widgetName].push(getResultFile(file));
|
|
184
|
+
} else {
|
|
185
|
+
widgetFilesMap[widgetName] = [getResultFile(file)];
|
|
186
|
+
}
|
|
187
|
+
});
|
|
188
|
+
|
|
189
|
+
return widgetFilesMap;
|
|
190
|
+
};
|
|
191
|
+
|
|
192
|
+
// 文件名中添加当前项目版本号
|
|
193
|
+
function addVersionToFilename(filename, version = currentPackageJson.version) {
|
|
194
|
+
// 找到最后一个点的位置,用于分离文件名和扩展名
|
|
195
|
+
let lastDotIndex = filename.lastIndexOf('.umd');
|
|
196
|
+
if (lastDotIndex === -1) {
|
|
197
|
+
lastDotIndex = filename.lastIndexOf('.esm');
|
|
198
|
+
}
|
|
199
|
+
if (lastDotIndex === -1) {
|
|
200
|
+
lastDotIndex = filename.lastIndexOf('.lib');
|
|
201
|
+
}
|
|
202
|
+
if (lastDotIndex === -1) {
|
|
203
|
+
lastDotIndex = filename.lastIndexOf('.');
|
|
204
|
+
}
|
|
205
|
+
// 如果没有扩展名(没有点),直接在文件名后添加版本号
|
|
206
|
+
if (lastDotIndex === -1) {
|
|
207
|
+
return `${filename}-${version}`;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
// 分离文件名的基础部分和扩展名
|
|
211
|
+
const baseName = filename.substring(0, lastDotIndex);
|
|
212
|
+
const extension = filename.substring(lastDotIndex);
|
|
213
|
+
|
|
214
|
+
// 组合新的文件名:基础名-版本号.扩展名
|
|
215
|
+
return `${baseName}-${version}${extension}`;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
module.exports = publish2oss;
|