file-lane 2.0.2-dev.8 → 2.0.3-beta.1
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 +240 -6
- package/lib/FileLane.d.ts +56 -9
- package/lib/FileLane.js +217 -76
- package/lib/FileLaneCompilation.d.ts +16 -0
- package/lib/FileLaneCompilation.js +17 -0
- package/lib/enum/FileLaneTriggerType.d.ts +8 -0
- package/lib/enum/FileLaneTriggerType.js +11 -0
- package/lib/index.d.ts +4 -2
- package/lib/index.js +4 -1
- package/lib/interface/IChangedFile.d.ts +9 -0
- package/lib/interface/IChangedFile.js +9 -0
- package/lib/interface/IFileLaneConfig.d.ts +54 -20
- package/lib/interface/IFileLaneEvents.d.ts +52 -0
- package/lib/interface/IFileLaneEvents.js +2 -0
- package/lib/interface/IFileParam.d.ts +0 -1
- package/lib/interface/ILoader.d.ts +7 -0
- package/lib/utils/FileLaneUtil.d.ts +1 -7
- package/lib/utils/FileLaneUtil.js +9 -57
- package/package.json +6 -6
package/README.md
CHANGED
|
@@ -1,13 +1,247 @@
|
|
|
1
|
-
#
|
|
1
|
+
# 项目介绍
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
file-lane模块用于文件转换,可实现文件1对1的转换,也可实现1对多、多对1的文件转换。
|
|
4
4
|
|
|
5
|
-
<img src="./doc/flow.
|
|
5
|
+
<img src="./doc/flow-detail.png" style="max-width: 1000px; width: 100%"/>
|
|
6
6
|
|
|
7
|
-
##
|
|
7
|
+
## 安装使用
|
|
8
|
+
|
|
9
|
+
- 安装
|
|
10
|
+
|
|
11
|
+
`npm i file-lane`
|
|
12
|
+
|
|
13
|
+
- 快速上手
|
|
14
|
+
|
|
15
|
+
```javascript
|
|
16
|
+
const { FileLane } = require('file-lane')
|
|
17
|
+
const { UxLoader } = require('aiot-toolkit/aiotpack')
|
|
18
|
+
const Path = require('path')
|
|
19
|
+
|
|
20
|
+
const projectPath = Path.join(__dirname, '../testProject')
|
|
21
|
+
|
|
22
|
+
// 定义项目转换的配置参数,output和module为必要配置内容
|
|
23
|
+
const projectConfig = {
|
|
24
|
+
// output指定转换后项目的存储位置
|
|
25
|
+
get output() {
|
|
26
|
+
const name = Path.basename(projectPath)
|
|
27
|
+
const result = `../.temp_${name}`
|
|
28
|
+
return result
|
|
29
|
+
},
|
|
30
|
+
// 转换过程中使用的转换模块配置
|
|
31
|
+
module: {
|
|
32
|
+
rules: [
|
|
33
|
+
{
|
|
34
|
+
test: [/.+\.ux$/],
|
|
35
|
+
exclude: [/app\.ux/],
|
|
36
|
+
loader: [UxLoader]
|
|
37
|
+
}
|
|
38
|
+
]
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// 开始执行文件转换
|
|
43
|
+
new FileLane(projectConfig).start()
|
|
44
|
+
// 开启watch模式
|
|
45
|
+
// new FileLane(projectConfig).start({ watch: true })
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
## 参数配置
|
|
49
|
+
|
|
50
|
+
- 必填参数
|
|
51
|
+
- [output](#output)
|
|
52
|
+
- [module](#module)
|
|
53
|
+
- 可选参数
|
|
54
|
+
- [fileCollector](#fileCollector)
|
|
55
|
+
- [include](#include)
|
|
56
|
+
- [exclude](#exclude)
|
|
57
|
+
- [plugins](#plugins)
|
|
58
|
+
- [preWorks](#preWorks)
|
|
59
|
+
- [followWorks](#followWorks)
|
|
60
|
+
- [watchIgnores](#watchIgnores)
|
|
61
|
+
|
|
62
|
+
<a id="output">output</a>
|
|
63
|
+
|
|
64
|
+
描述: 输出目录
|
|
65
|
+
|
|
66
|
+
参数类型: string
|
|
67
|
+
|
|
68
|
+
示例:
|
|
69
|
+
|
|
70
|
+
```
|
|
71
|
+
'temp_project'
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
<a id="module">module</a>
|
|
75
|
+
|
|
76
|
+
描述: 文件转换规则集
|
|
77
|
+
|
|
78
|
+
参数类型: { rules: IRule[] } // IRule:转换规则
|
|
79
|
+
|
|
80
|
+
```javascript
|
|
81
|
+
interface IRule {
|
|
82
|
+
// 配置文件
|
|
83
|
+
test: MatchType
|
|
84
|
+
|
|
85
|
+
// 文件的 Loader,从前向后依次执行,前一个 loader 结果做为后一个 loader 的入参
|
|
86
|
+
loader: ILoaderClass[]
|
|
87
|
+
exclude?: MatchType
|
|
88
|
+
include?: MatchType
|
|
89
|
+
}
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
示例:
|
|
8
93
|
|
|
9
94
|
```
|
|
10
|
-
|
|
95
|
+
{
|
|
96
|
+
rules: [
|
|
97
|
+
{
|
|
98
|
+
test: [/.+\.ux$/],
|
|
99
|
+
exclude: [/app\.ux/],
|
|
100
|
+
loader: [UxLoader]
|
|
101
|
+
}
|
|
102
|
+
]
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
<a id="fileCollector">fileCollector</a>
|
|
108
|
+
|
|
109
|
+
描述: 文件收集器,输入文件路径,返回待合并的文件路径,常用于多转1,默认值为直接使用源文件
|
|
110
|
+
|
|
111
|
+
参数类型:
|
|
112
|
+
|
|
113
|
+
```
|
|
114
|
+
(file: string) => string[]
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
示例:
|
|
118
|
+
|
|
119
|
+
```javascript
|
|
120
|
+
// src/a.hml -->[src/a.hml, src/a.js, src/a.css]
|
|
121
|
+
(file: string) => {
|
|
122
|
+
const fileList = [file]
|
|
123
|
+
const { dir, name, ext } = path.parse(file)
|
|
124
|
+
|
|
125
|
+
if (ext === '.hml') {
|
|
126
|
+
['.js', '.css'].map((item) => {
|
|
127
|
+
const collectFile = path.join(dir, `${name}${item}`)
|
|
128
|
+
// 若路径真实存在,则push到文件列表中
|
|
129
|
+
if (fs.existsSync(collectFile)) {
|
|
130
|
+
fileList.push(collectFile)
|
|
131
|
+
}
|
|
132
|
+
})
|
|
133
|
+
return fileList
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
<a id="include">include</a>
|
|
139
|
+
|
|
140
|
+
描述: 指定文件范围
|
|
141
|
+
|
|
142
|
+
参数类型:
|
|
143
|
+
|
|
144
|
+
```
|
|
145
|
+
OneMatchType | OneMatchType[]
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
示例:
|
|
149
|
+
|
|
150
|
+
```javascript
|
|
151
|
+
// 匹配包含有src字符串的文件
|
|
152
|
+
include = ['src']
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
<a id="exclude">exclude</a>
|
|
156
|
+
|
|
157
|
+
描述: 需排除的文件范围
|
|
158
|
+
|
|
159
|
+
参数类型:
|
|
160
|
+
|
|
161
|
+
```
|
|
162
|
+
OneMatchType | OneMatchType[]
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
示例:
|
|
166
|
+
|
|
167
|
+
```javascript
|
|
168
|
+
// 排除路径中包含有node_modules字符串的文件
|
|
169
|
+
exclude = [/node_modules/]
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
<a id="plugins">plugins</a>
|
|
173
|
+
|
|
174
|
+
描述: 插件,在每个文件转换完成前后,所有文件转换完成前后,在打包完成前后会触发
|
|
175
|
+
|
|
176
|
+
参数类型:
|
|
177
|
+
|
|
178
|
+
```
|
|
179
|
+
IPlugin[]
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
示例:
|
|
183
|
+
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
<a id="preWorks">preWorks</a>
|
|
189
|
+
|
|
190
|
+
描述: 前置工作,所有文件转换前的工作
|
|
191
|
+
|
|
192
|
+
参数类型:
|
|
193
|
+
|
|
194
|
+
```
|
|
195
|
+
PreWork[]
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
示例:
|
|
199
|
+
|
|
200
|
+
```javascript
|
|
201
|
+
preWorks = [validateManifest]
|
|
202
|
+
|
|
203
|
+
const validateManifest: PreWork<IJavascriptCompileOption> = async (context) => {
|
|
204
|
+
// 校验manifest.json文件的内容
|
|
205
|
+
}
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
<a id="followWorks">followWorks</a>
|
|
209
|
+
|
|
210
|
+
描述: 后续工作,所有文件转换后的工作
|
|
211
|
+
|
|
212
|
+
参数类型:
|
|
213
|
+
|
|
214
|
+
```
|
|
215
|
+
FollowWoker<O>[]
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
示例:
|
|
219
|
+
|
|
220
|
+
```javascript
|
|
221
|
+
followWorks = [
|
|
222
|
+
{
|
|
223
|
+
worker: toRpk,
|
|
224
|
+
workerDescribe: 'follow work'
|
|
225
|
+
}
|
|
226
|
+
]
|
|
227
|
+
|
|
228
|
+
const toRpk: FollowWork<IJavascriptCompileOption> = async (context, config, compilerOption) => {
|
|
229
|
+
// 生成rpk逻辑
|
|
230
|
+
}
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
<a id="watchIgnores">watchIgnores</a>
|
|
234
|
+
|
|
235
|
+
描述: 配置watch时忽略的文件或者文件夹
|
|
236
|
+
|
|
237
|
+
参数类型:
|
|
238
|
+
|
|
239
|
+
```
|
|
240
|
+
MatchType
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
示例:
|
|
11
244
|
|
|
12
|
-
|
|
245
|
+
```javascript
|
|
246
|
+
watchIgnores = [/node_modules/, '/build/', '/dist/']
|
|
13
247
|
```
|
package/lib/FileLane.d.ts
CHANGED
|
@@ -1,25 +1,49 @@
|
|
|
1
1
|
import IFileLaneConfig from './interface/IFileLaneConfig';
|
|
2
|
+
import IFileLaneEvents from './interface/IFileLaneEvents';
|
|
2
3
|
/**
|
|
3
4
|
* FileLane
|
|
4
5
|
*
|
|
5
6
|
* 文件车道,用于将文件进行对应转换,支持1对1、1对N、N对1
|
|
6
7
|
*
|
|
8
|
+
* 打包过程中,有以下事件
|
|
9
|
+
* 1. 打包成功:onBuildSuccess
|
|
10
|
+
* 2. 打包失败: onBuildError
|
|
11
|
+
* 3. 产生日志: onLog
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* ```
|
|
15
|
+
* new FileLane<IJavascriptCompileOption>(
|
|
16
|
+
* fileLaneConfig,
|
|
17
|
+
* projectPath,
|
|
18
|
+
* compilerOption,
|
|
19
|
+
* {
|
|
20
|
+
* onBuildSuccess: (data) => {},
|
|
21
|
+
* onBuildError: (data) => {},
|
|
22
|
+
* onLog: (logs) => {}
|
|
23
|
+
* }).start()
|
|
24
|
+
* ```
|
|
25
|
+
*
|
|
7
26
|
* @description
|
|
8
27
|
*/
|
|
9
28
|
declare class FileLane<O = any> {
|
|
10
29
|
readonly config: IFileLaneConfig<O>;
|
|
11
30
|
readonly compilerOption?: O | undefined;
|
|
31
|
+
private readonly events?;
|
|
12
32
|
private context;
|
|
13
33
|
private watcher?;
|
|
34
|
+
/**
|
|
35
|
+
* 每次编译的数据对象
|
|
36
|
+
*/
|
|
14
37
|
private compilation?;
|
|
15
|
-
private
|
|
38
|
+
private changeFileList;
|
|
39
|
+
private triggerCount;
|
|
16
40
|
/**
|
|
17
41
|
* 实例化FileLane
|
|
18
42
|
* @param config fileLane 配置
|
|
19
43
|
* @param projectPath 项目路径
|
|
20
44
|
* @param compilerOption 编译参数,不同语言的项目具有的参数不同,即使同一项目开发者也会设置不同的参数
|
|
21
45
|
*/
|
|
22
|
-
constructor(config: IFileLaneConfig<O>, projectPath?: string, compilerOption?: O | undefined);
|
|
46
|
+
constructor(config: IFileLaneConfig<O>, projectPath?: string, compilerOption?: O | undefined, events?: IFileLaneEvents | undefined);
|
|
23
47
|
/**
|
|
24
48
|
* 运行
|
|
25
49
|
* @param params
|
|
@@ -35,8 +59,9 @@ declare class FileLane<O = any> {
|
|
|
35
59
|
}): Promise<void>;
|
|
36
60
|
private validateConfig;
|
|
37
61
|
private processExitHandler;
|
|
38
|
-
|
|
39
|
-
|
|
62
|
+
private sigintHandler;
|
|
63
|
+
stop(): Promise<void>;
|
|
64
|
+
dispose(): Promise<void>;
|
|
40
65
|
/**
|
|
41
66
|
*
|
|
42
67
|
* @param fileList 原始文件列表
|
|
@@ -45,6 +70,15 @@ declare class FileLane<O = any> {
|
|
|
45
70
|
private initCompilation;
|
|
46
71
|
private buildFile;
|
|
47
72
|
private runLoaders;
|
|
73
|
+
/**
|
|
74
|
+
* 处理日志
|
|
75
|
+
* 1. 触发onLog事件
|
|
76
|
+
* 2. 如果有错误日志,则抛出错误
|
|
77
|
+
* @param logs
|
|
78
|
+
* @param onError
|
|
79
|
+
* @returns
|
|
80
|
+
*/
|
|
81
|
+
private handlerLogs;
|
|
48
82
|
private writeFiles;
|
|
49
83
|
private runLoader;
|
|
50
84
|
/**
|
|
@@ -55,13 +89,21 @@ declare class FileLane<O = any> {
|
|
|
55
89
|
private findLoader;
|
|
56
90
|
private triggerPlugins;
|
|
57
91
|
/**
|
|
58
|
-
*
|
|
92
|
+
* start开始时的准备工作
|
|
59
93
|
*/
|
|
60
|
-
private
|
|
94
|
+
private complyBeforeWorks;
|
|
61
95
|
/**
|
|
62
|
-
*
|
|
96
|
+
* start结束后的收尾工作
|
|
63
97
|
*/
|
|
64
|
-
private
|
|
98
|
+
private complyAfterWork;
|
|
99
|
+
/**
|
|
100
|
+
* 执行项目转换的前置工作
|
|
101
|
+
*/
|
|
102
|
+
private complyBeforeCompile;
|
|
103
|
+
/**
|
|
104
|
+
* 执行项目转换的后续工作
|
|
105
|
+
*/
|
|
106
|
+
private complyAfterCompile;
|
|
65
107
|
private watch;
|
|
66
108
|
/**
|
|
67
109
|
* 采集所有要处理的真实文件路径列表
|
|
@@ -74,10 +116,15 @@ declare class FileLane<O = any> {
|
|
|
74
116
|
* @param onChange
|
|
75
117
|
*/
|
|
76
118
|
private listenFileChange;
|
|
77
|
-
private get outputPath();
|
|
78
119
|
/**
|
|
79
120
|
* 清除输出文件夹
|
|
80
121
|
*/
|
|
81
122
|
private cleanOutput;
|
|
123
|
+
/**
|
|
124
|
+
* 1. 配置的忽略文件夹
|
|
125
|
+
* 2. 默认应该忽略的文件及文件夹
|
|
126
|
+
* @returns
|
|
127
|
+
*/
|
|
128
|
+
private getIgnoreConfig;
|
|
82
129
|
}
|
|
83
130
|
export default FileLane;
|
package/lib/FileLane.js
CHANGED
|
@@ -13,22 +13,39 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
13
13
|
};
|
|
14
14
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
15
|
const shared_utils_1 = require("@aiot-toolkit/shared-utils");
|
|
16
|
-
const ColorConsole_1 = __importDefault(require("@aiot-toolkit/shared-utils/lib/ColorConsole"));
|
|
17
|
-
const FileUtil_1 = __importDefault(require("@aiot-toolkit/shared-utils/lib/utils/FileUtil"));
|
|
18
16
|
const chokidar_1 = __importDefault(require("chokidar"));
|
|
19
17
|
const fs_extra_1 = __importDefault(require("fs-extra"));
|
|
20
18
|
const lodash_1 = __importDefault(require("lodash"));
|
|
21
19
|
const path_1 = __importDefault(require("path"));
|
|
22
|
-
const ws_1 = __importDefault(require("ws"));
|
|
23
20
|
const FileLaneCompilation_1 = __importDefault(require("./FileLaneCompilation"));
|
|
24
21
|
const CompilationEvent_1 = __importDefault(require("./event/CompilationEvent"));
|
|
25
22
|
const FileEvent_1 = __importDefault(require("./event/FileEvent"));
|
|
26
23
|
const FileLaneUtil_1 = __importDefault(require("./utils/FileLaneUtil"));
|
|
24
|
+
const IChangedFile_1 = require("./interface/IChangedFile");
|
|
25
|
+
const FileLaneTriggerType_1 = __importDefault(require("./enum/FileLaneTriggerType"));
|
|
27
26
|
/**
|
|
28
27
|
* FileLane
|
|
29
28
|
*
|
|
30
29
|
* 文件车道,用于将文件进行对应转换,支持1对1、1对N、N对1
|
|
31
30
|
*
|
|
31
|
+
* 打包过程中,有以下事件
|
|
32
|
+
* 1. 打包成功:onBuildSuccess
|
|
33
|
+
* 2. 打包失败: onBuildError
|
|
34
|
+
* 3. 产生日志: onLog
|
|
35
|
+
*
|
|
36
|
+
* @example
|
|
37
|
+
* ```
|
|
38
|
+
* new FileLane<IJavascriptCompileOption>(
|
|
39
|
+
* fileLaneConfig,
|
|
40
|
+
* projectPath,
|
|
41
|
+
* compilerOption,
|
|
42
|
+
* {
|
|
43
|
+
* onBuildSuccess: (data) => {},
|
|
44
|
+
* onBuildError: (data) => {},
|
|
45
|
+
* onLog: (logs) => {}
|
|
46
|
+
* }).start()
|
|
47
|
+
* ```
|
|
48
|
+
*
|
|
32
49
|
* @description
|
|
33
50
|
*/
|
|
34
51
|
class FileLane {
|
|
@@ -38,14 +55,18 @@ class FileLane {
|
|
|
38
55
|
* @param projectPath 项目路径
|
|
39
56
|
* @param compilerOption 编译参数,不同语言的项目具有的参数不同,即使同一项目开发者也会设置不同的参数
|
|
40
57
|
*/
|
|
41
|
-
constructor(config, projectPath, compilerOption) {
|
|
58
|
+
constructor(config, projectPath, compilerOption, events) {
|
|
42
59
|
this.config = config;
|
|
43
60
|
this.compilerOption = compilerOption;
|
|
61
|
+
this.events = events;
|
|
62
|
+
this.changeFileList = [];
|
|
63
|
+
this.triggerCount = 0;
|
|
44
64
|
this.processExitHandler = () => {
|
|
45
65
|
this.dispose();
|
|
46
66
|
};
|
|
47
67
|
this.context = FileLaneUtil_1.default.createContext(config.output, projectPath);
|
|
48
68
|
process.on('exit', this.processExitHandler);
|
|
69
|
+
process.on('SIGINT', this.sigintHandler);
|
|
49
70
|
}
|
|
50
71
|
/**
|
|
51
72
|
* 运行
|
|
@@ -56,18 +77,18 @@ class FileLane {
|
|
|
56
77
|
return __awaiter(this, void 0, void 0, function* () {
|
|
57
78
|
const errorList = this.validateConfig();
|
|
58
79
|
if (errorList && errorList.length) {
|
|
59
|
-
|
|
80
|
+
shared_utils_1.ColorConsole.error(`### file-lane ### ${errorList.map((item, index) => `${index + 1}. ${item}`).join('\r\n')}`);
|
|
60
81
|
return;
|
|
61
82
|
}
|
|
62
|
-
this.
|
|
83
|
+
yield this.complyBeforeWorks();
|
|
63
84
|
const fileList = this.collectFile();
|
|
64
85
|
if (!fileList || !fileList.length) {
|
|
65
86
|
return;
|
|
66
87
|
}
|
|
67
|
-
yield this.build(fileList);
|
|
68
88
|
if (params === null || params === void 0 ? void 0 : params.watch) {
|
|
69
89
|
this.watch();
|
|
70
90
|
}
|
|
91
|
+
yield this.build(fileList, FileLaneTriggerType_1.default.START);
|
|
71
92
|
});
|
|
72
93
|
}
|
|
73
94
|
validateConfig() {
|
|
@@ -117,24 +138,36 @@ class FileLane {
|
|
|
117
138
|
}
|
|
118
139
|
return result;
|
|
119
140
|
}
|
|
120
|
-
|
|
121
|
-
this.dispose();
|
|
141
|
+
sigintHandler() {
|
|
122
142
|
process.exit();
|
|
123
143
|
}
|
|
144
|
+
stop() {
|
|
145
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
146
|
+
if (this.watcher) {
|
|
147
|
+
this.watcher.removeAllListeners();
|
|
148
|
+
yield this.watcher.close();
|
|
149
|
+
}
|
|
150
|
+
});
|
|
151
|
+
}
|
|
124
152
|
dispose() {
|
|
125
|
-
|
|
126
|
-
this.
|
|
127
|
-
|
|
153
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
154
|
+
this.complyAfterWork();
|
|
155
|
+
yield this.stop();
|
|
156
|
+
this.cleanOutput();
|
|
157
|
+
});
|
|
128
158
|
}
|
|
129
159
|
/**
|
|
130
160
|
*
|
|
131
161
|
* @param fileList 原始文件列表
|
|
132
162
|
*/
|
|
133
|
-
build(fileList) {
|
|
163
|
+
build(fileList, trigger) {
|
|
134
164
|
return __awaiter(this, void 0, void 0, function* () {
|
|
135
|
-
|
|
165
|
+
var _a;
|
|
166
|
+
const { onBuildSuccess, onBuildError } = this.events || {};
|
|
167
|
+
const t1 = Date.now();
|
|
168
|
+
this.initCompilation(trigger);
|
|
136
169
|
try {
|
|
137
|
-
yield this.
|
|
170
|
+
yield this.complyBeforeCompile();
|
|
138
171
|
this.triggerPlugins(new CompilationEvent_1.default(CompilationEvent_1.default.PROJECT_START));
|
|
139
172
|
for (let item of fileList) {
|
|
140
173
|
this.triggerPlugins(new FileEvent_1.default(FileEvent_1.default.FILE_START_COMPILATION, FileLaneUtil_1.default.pathToFileParam(item)));
|
|
@@ -144,22 +177,37 @@ class FileLane {
|
|
|
144
177
|
this.triggerPlugins(new CompilationEvent_1.default(CompilationEvent_1.default.PROJECT_END));
|
|
145
178
|
// 执行extra
|
|
146
179
|
this.triggerPlugins(new CompilationEvent_1.default(CompilationEvent_1.default.FLLOW_WORK_START));
|
|
147
|
-
yield this.
|
|
180
|
+
yield this.complyAfterCompile();
|
|
148
181
|
this.triggerPlugins(new CompilationEvent_1.default(CompilationEvent_1.default.FLLOW_WORK_END));
|
|
149
|
-
|
|
182
|
+
onBuildSuccess === null || onBuildSuccess === void 0 ? void 0 : onBuildSuccess({
|
|
183
|
+
costTime: Date.now() - t1,
|
|
184
|
+
info: (_a = this.compilation) === null || _a === void 0 ? void 0 : _a.info
|
|
185
|
+
});
|
|
186
|
+
shared_utils_1.ColorConsole.success({
|
|
150
187
|
word: 'Success: build finish!',
|
|
151
|
-
style:
|
|
188
|
+
style: shared_utils_1.ColorConsole.getStyle(shared_utils_1.Loglevel.SUCCESS)
|
|
152
189
|
});
|
|
153
190
|
}
|
|
154
191
|
catch (error) {
|
|
155
|
-
|
|
156
|
-
|
|
192
|
+
if (onBuildError) {
|
|
193
|
+
onBuildError === null || onBuildError === void 0 ? void 0 : onBuildError(error);
|
|
194
|
+
}
|
|
195
|
+
else {
|
|
196
|
+
shared_utils_1.ColorConsole.throw(`ERROR: `, { word: 'build error' }, `, ${error || 'unknown error'}`);
|
|
197
|
+
}
|
|
198
|
+
// 非监听模式,则结束任务
|
|
199
|
+
if (!this.watcher) {
|
|
200
|
+
process.exit();
|
|
201
|
+
}
|
|
157
202
|
}
|
|
158
203
|
});
|
|
159
204
|
}
|
|
160
|
-
initCompilation() {
|
|
205
|
+
initCompilation(trigger) {
|
|
161
206
|
const { plugins } = this.config;
|
|
162
207
|
const compilation = new FileLaneCompilation_1.default();
|
|
208
|
+
compilation.trigger = trigger;
|
|
209
|
+
compilation.triggerCount = ++this.triggerCount;
|
|
210
|
+
compilation.info.trigger = trigger;
|
|
163
211
|
plugins === null || plugins === void 0 ? void 0 : plugins.forEach((item) => {
|
|
164
212
|
item.compilation = compilation;
|
|
165
213
|
item.apply();
|
|
@@ -196,17 +244,53 @@ class FileLane {
|
|
|
196
244
|
}
|
|
197
245
|
}
|
|
198
246
|
});
|
|
199
|
-
|
|
247
|
+
const loader = new item();
|
|
248
|
+
result = yield this.runLoader(result, loader);
|
|
249
|
+
if (loader.logs) {
|
|
250
|
+
this.handlerLogs(loader.logs, () => {
|
|
251
|
+
throw new Error(`loader error: ${item.name}`);
|
|
252
|
+
});
|
|
253
|
+
}
|
|
200
254
|
}
|
|
201
255
|
return result;
|
|
202
256
|
});
|
|
203
257
|
}
|
|
258
|
+
/**
|
|
259
|
+
* 处理日志
|
|
260
|
+
* 1. 触发onLog事件
|
|
261
|
+
* 2. 如果有错误日志,则抛出错误
|
|
262
|
+
* @param logs
|
|
263
|
+
* @param onError
|
|
264
|
+
* @returns
|
|
265
|
+
*/
|
|
266
|
+
handlerLogs(logs, onError) {
|
|
267
|
+
var _a;
|
|
268
|
+
if (!(logs === null || logs === void 0 ? void 0 : logs.length)) {
|
|
269
|
+
return;
|
|
270
|
+
}
|
|
271
|
+
const onLog = (_a = this.events) === null || _a === void 0 ? void 0 : _a.onLog;
|
|
272
|
+
if (onLog) {
|
|
273
|
+
onLog(logs);
|
|
274
|
+
}
|
|
275
|
+
else {
|
|
276
|
+
logs.forEach((item) => {
|
|
277
|
+
shared_utils_1.ColorConsole.logger(item);
|
|
278
|
+
});
|
|
279
|
+
}
|
|
280
|
+
const hasError = logs.find((item) => item.level && [shared_utils_1.Loglevel.ERROR, shared_utils_1.Loglevel.THROW].includes(item.level));
|
|
281
|
+
if (hasError) {
|
|
282
|
+
onError();
|
|
283
|
+
}
|
|
284
|
+
}
|
|
204
285
|
writeFiles(fileList) {
|
|
205
286
|
return __awaiter(this, void 0, void 0, function* () {
|
|
206
287
|
if (!fileList || !fileList.length) {
|
|
207
288
|
return;
|
|
208
289
|
}
|
|
209
|
-
const buildPath = this.
|
|
290
|
+
const buildPath = FileLaneUtil_1.default.getOutputPath(this.context);
|
|
291
|
+
if (!fs_extra_1.default.existsSync(buildPath)) {
|
|
292
|
+
shared_utils_1.FileUtil.mkdirSync(buildPath, { hidden: true });
|
|
293
|
+
}
|
|
210
294
|
return Promise.all(fileList.map((item) => {
|
|
211
295
|
const resolvePath = path_1.default.relative(this.context.projectPath, item.path);
|
|
212
296
|
// 将相对路径与输出路径拼接,形成最新的文件路径
|
|
@@ -215,9 +299,8 @@ class FileLane {
|
|
|
215
299
|
}));
|
|
216
300
|
});
|
|
217
301
|
}
|
|
218
|
-
runLoader(fileList,
|
|
302
|
+
runLoader(fileList, loader) {
|
|
219
303
|
return __awaiter(this, void 0, void 0, function* () {
|
|
220
|
-
const loader = new loaderType();
|
|
221
304
|
loader.context = this.context;
|
|
222
305
|
loader.compilerOption = this.compilerOption;
|
|
223
306
|
return loader.parser(fileList);
|
|
@@ -234,8 +317,8 @@ class FileLane {
|
|
|
234
317
|
let loaders = [];
|
|
235
318
|
for (let rule of rules) {
|
|
236
319
|
// 1. 检查filePath是否符合规则test
|
|
237
|
-
if (
|
|
238
|
-
|
|
320
|
+
if (shared_utils_1.FileUtil.match(parse, rule.test) &&
|
|
321
|
+
shared_utils_1.FileUtil.include(filePath, rule.include, rule.exclude)) {
|
|
239
322
|
// 2. 符合规则就添加到返回列表中
|
|
240
323
|
loaders.push(...rule.loader);
|
|
241
324
|
}
|
|
@@ -250,33 +333,71 @@ class FileLane {
|
|
|
250
333
|
});
|
|
251
334
|
}
|
|
252
335
|
/**
|
|
253
|
-
*
|
|
336
|
+
* start开始时的准备工作
|
|
254
337
|
*/
|
|
255
|
-
|
|
338
|
+
complyBeforeWorks() {
|
|
256
339
|
return __awaiter(this, void 0, void 0, function* () {
|
|
257
|
-
const {
|
|
258
|
-
if (
|
|
259
|
-
for (let item of
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
340
|
+
const { beforeWorks } = this.config;
|
|
341
|
+
if (beforeWorks) {
|
|
342
|
+
for (let item of beforeWorks) {
|
|
343
|
+
yield item(this.context);
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
});
|
|
347
|
+
}
|
|
348
|
+
/**
|
|
349
|
+
* start结束后的收尾工作
|
|
350
|
+
*/
|
|
351
|
+
complyAfterWork() {
|
|
352
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
353
|
+
const { afterWorks } = this.config;
|
|
354
|
+
if (afterWorks) {
|
|
355
|
+
for (let item of afterWorks) {
|
|
356
|
+
yield item(this.context);
|
|
267
357
|
}
|
|
268
358
|
}
|
|
269
359
|
});
|
|
270
360
|
}
|
|
271
361
|
/**
|
|
272
|
-
*
|
|
362
|
+
* 执行项目转换的前置工作
|
|
273
363
|
*/
|
|
274
|
-
|
|
364
|
+
complyBeforeCompile() {
|
|
275
365
|
return __awaiter(this, void 0, void 0, function* () {
|
|
276
|
-
const {
|
|
277
|
-
if (
|
|
278
|
-
for (let item of
|
|
279
|
-
yield item(
|
|
366
|
+
const { beforeCompile } = this.config;
|
|
367
|
+
if (beforeCompile) {
|
|
368
|
+
for (let item of beforeCompile) {
|
|
369
|
+
yield item({
|
|
370
|
+
context: this.context,
|
|
371
|
+
config: this.config,
|
|
372
|
+
compilerOption: this.compilerOption,
|
|
373
|
+
compalition: this.compilation
|
|
374
|
+
});
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
});
|
|
378
|
+
}
|
|
379
|
+
/**
|
|
380
|
+
* 执行项目转换的后续工作
|
|
381
|
+
*/
|
|
382
|
+
complyAfterCompile() {
|
|
383
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
384
|
+
const { afterCompile } = this.config;
|
|
385
|
+
if (afterCompile) {
|
|
386
|
+
for (let item of afterCompile) {
|
|
387
|
+
try {
|
|
388
|
+
shared_utils_1.ColorConsole.info(`FollowWork: ${item.workerDescribe} start`);
|
|
389
|
+
yield item.worker({
|
|
390
|
+
context: this.context,
|
|
391
|
+
config: this.config,
|
|
392
|
+
compilerOption: this.compilerOption,
|
|
393
|
+
compalition: this.compilation
|
|
394
|
+
});
|
|
395
|
+
shared_utils_1.ColorConsole.info(`FollowWork: ${item.workerDescribe} end`);
|
|
396
|
+
}
|
|
397
|
+
catch (error) {
|
|
398
|
+
shared_utils_1.ColorConsole.throw(`FollowWork: ${item.workerDescribe} error, ${error}`);
|
|
399
|
+
process.exit();
|
|
400
|
+
}
|
|
280
401
|
}
|
|
281
402
|
}
|
|
282
403
|
});
|
|
@@ -284,18 +405,15 @@ class FileLane {
|
|
|
284
405
|
watch() {
|
|
285
406
|
return __awaiter(this, void 0, void 0, function* () {
|
|
286
407
|
// 监听文件变化,并触发 build
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
type: 'restart'
|
|
297
|
-
}));
|
|
298
|
-
}));
|
|
408
|
+
const onChange = () => __awaiter(this, void 0, void 0, function* () {
|
|
409
|
+
const fileList = this.config.collectFile
|
|
410
|
+
? this.config.collectFile(this.changeFileList)
|
|
411
|
+
: this.collectFile();
|
|
412
|
+
// 开始编译前,记录列表置空
|
|
413
|
+
this.changeFileList = [];
|
|
414
|
+
yield this.build(fileList, FileLaneTriggerType_1.default.UPDATE);
|
|
415
|
+
});
|
|
416
|
+
this.listenFileChange(onChange);
|
|
299
417
|
});
|
|
300
418
|
}
|
|
301
419
|
/**
|
|
@@ -308,8 +426,8 @@ class FileLane {
|
|
|
308
426
|
let files = [];
|
|
309
427
|
if (entryFileList) {
|
|
310
428
|
entryFileList.forEach((filePath) => {
|
|
311
|
-
if (
|
|
312
|
-
|
|
429
|
+
if (shared_utils_1.FileUtil.include(filePath, this.config.include, this.config.exclude)) {
|
|
430
|
+
shared_utils_1.ColorConsole.log(`### file-lane ### file change: ${filePath}`);
|
|
313
431
|
files.push(filePath);
|
|
314
432
|
}
|
|
315
433
|
});
|
|
@@ -318,7 +436,7 @@ class FileLane {
|
|
|
318
436
|
// 1.取出projectPath
|
|
319
437
|
const projectPath = this.context.projectPath;
|
|
320
438
|
// 2. 循环文件夹,取出所有匹配的文件路径
|
|
321
|
-
files =
|
|
439
|
+
files = shared_utils_1.FileUtil.readAlldirSync(projectPath, this.config.include, this.config.exclude);
|
|
322
440
|
}
|
|
323
441
|
return files;
|
|
324
442
|
}
|
|
@@ -328,54 +446,77 @@ class FileLane {
|
|
|
328
446
|
*/
|
|
329
447
|
listenFileChange(onChange) {
|
|
330
448
|
const watcher = chokidar_1.default.watch(this.context.projectPath, {
|
|
331
|
-
ignored: this.
|
|
449
|
+
ignored: this.getIgnoreConfig()
|
|
332
450
|
});
|
|
333
451
|
const throttledOnChange = lodash_1.default.throttle(onChange, 1000, {
|
|
334
|
-
leading:
|
|
335
|
-
trailing:
|
|
452
|
+
leading: false,
|
|
453
|
+
trailing: true
|
|
336
454
|
});
|
|
337
|
-
const handler = (
|
|
455
|
+
const handler = (path, type) => {
|
|
338
456
|
const { exclude, include } = this.config;
|
|
339
|
-
//
|
|
340
|
-
|
|
341
|
-
|
|
457
|
+
// 执行onChange回调
|
|
458
|
+
const validFile = shared_utils_1.FileUtil.include(path, include, exclude);
|
|
459
|
+
if (validFile) {
|
|
460
|
+
this.changeFileList.push({ path, type });
|
|
461
|
+
throttledOnChange();
|
|
342
462
|
}
|
|
343
463
|
};
|
|
344
464
|
watcher
|
|
345
465
|
.on('ready', () => {
|
|
346
|
-
|
|
466
|
+
shared_utils_1.ColorConsole.log(`### file-lane ### Initial scan complete. Ready for Watch.`);
|
|
347
467
|
watcher
|
|
348
468
|
.on('add', (path) => {
|
|
349
469
|
// 监听文件添加事件
|
|
350
|
-
handler(path);
|
|
470
|
+
handler(path, IChangedFile_1.HandlerType.ADD);
|
|
351
471
|
})
|
|
352
472
|
.on('change', (path) => {
|
|
353
473
|
// 监听文件修改事件
|
|
354
|
-
handler(path);
|
|
474
|
+
handler(path, IChangedFile_1.HandlerType.CHANGE);
|
|
355
475
|
})
|
|
356
476
|
.on('unlink', (filePath) => {
|
|
357
477
|
// 监听文件删除事件
|
|
358
|
-
handler(filePath);
|
|
478
|
+
handler(filePath, IChangedFile_1.HandlerType.UNLINK);
|
|
359
479
|
});
|
|
360
480
|
})
|
|
361
481
|
.on('error', (error) => {
|
|
362
482
|
// 监听错误
|
|
363
483
|
FileLaneUtil_1.default.checkError(error.message);
|
|
484
|
+
watcher.close();
|
|
364
485
|
});
|
|
365
486
|
if (this.watcher) {
|
|
366
487
|
this.watcher.close();
|
|
367
488
|
}
|
|
368
489
|
this.watcher = watcher;
|
|
369
490
|
}
|
|
370
|
-
get outputPath() {
|
|
371
|
-
const { output, projectPath } = this.context;
|
|
372
|
-
return path_1.default.join(projectPath, output);
|
|
373
|
-
}
|
|
374
491
|
/**
|
|
375
492
|
* 清除输出文件夹
|
|
376
493
|
*/
|
|
377
494
|
cleanOutput() {
|
|
378
|
-
|
|
495
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
496
|
+
shared_utils_1.FileUtil.del(FileLaneUtil_1.default.getOutputPath(this.context));
|
|
497
|
+
});
|
|
498
|
+
}
|
|
499
|
+
/**
|
|
500
|
+
* 1. 配置的忽略文件夹
|
|
501
|
+
* 2. 默认应该忽略的文件及文件夹
|
|
502
|
+
* @returns
|
|
503
|
+
*/
|
|
504
|
+
getIgnoreConfig() {
|
|
505
|
+
let ignoreList = [];
|
|
506
|
+
// 1.
|
|
507
|
+
if (this.config.watchIgnores) {
|
|
508
|
+
if (Array.isArray(this.config.watchIgnores)) {
|
|
509
|
+
ignoreList.push(...this.config.watchIgnores);
|
|
510
|
+
}
|
|
511
|
+
else {
|
|
512
|
+
ignoreList.push(this.config.watchIgnores);
|
|
513
|
+
}
|
|
514
|
+
}
|
|
515
|
+
// 2. 忽略.开头的隐藏文件夹
|
|
516
|
+
ignoreList.push(/(^|[\/\\])\../);
|
|
517
|
+
// 3. 忽略output目录
|
|
518
|
+
ignoreList.push(path_1.default.join(this.context.projectPath, this.config.output));
|
|
519
|
+
return ignoreList;
|
|
379
520
|
}
|
|
380
521
|
}
|
|
381
522
|
exports.default = FileLane;
|
|
@@ -1,7 +1,23 @@
|
|
|
1
|
+
import FileLaneTriggerType from './enum/FileLaneTriggerType';
|
|
1
2
|
import AsyncEventDispatcher from './event/asyncEvent/AsyncEventDispatcher';
|
|
3
|
+
import IFileParam from './interface/IFileParam';
|
|
2
4
|
/**
|
|
3
5
|
* FileLaneCompilation
|
|
4
6
|
*/
|
|
5
7
|
declare class FileLaneCompilation extends AsyncEventDispatcher {
|
|
8
|
+
buildFileList: IFileParam<any>[];
|
|
9
|
+
/**
|
|
10
|
+
* 触发方式
|
|
11
|
+
*
|
|
12
|
+
*/
|
|
13
|
+
trigger: FileLaneTriggerType;
|
|
14
|
+
/**
|
|
15
|
+
* 触发次数
|
|
16
|
+
*/
|
|
17
|
+
triggerCount: number;
|
|
18
|
+
info: {
|
|
19
|
+
trigger: FileLaneTriggerType;
|
|
20
|
+
[key: string]: any;
|
|
21
|
+
};
|
|
6
22
|
}
|
|
7
23
|
export default FileLaneCompilation;
|
|
@@ -3,10 +3,27 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const FileLaneTriggerType_1 = __importDefault(require("./enum/FileLaneTriggerType"));
|
|
6
7
|
const AsyncEventDispatcher_1 = __importDefault(require("./event/asyncEvent/AsyncEventDispatcher"));
|
|
7
8
|
/**
|
|
8
9
|
* FileLaneCompilation
|
|
9
10
|
*/
|
|
10
11
|
class FileLaneCompilation extends AsyncEventDispatcher_1.default {
|
|
12
|
+
constructor() {
|
|
13
|
+
super(...arguments);
|
|
14
|
+
this.buildFileList = [];
|
|
15
|
+
/**
|
|
16
|
+
* 触发方式
|
|
17
|
+
*
|
|
18
|
+
*/
|
|
19
|
+
this.trigger = FileLaneTriggerType_1.default.START;
|
|
20
|
+
/**
|
|
21
|
+
* 触发次数
|
|
22
|
+
*/
|
|
23
|
+
this.triggerCount = 0;
|
|
24
|
+
this.info = {
|
|
25
|
+
trigger: FileLaneTriggerType_1.default.START
|
|
26
|
+
};
|
|
27
|
+
}
|
|
11
28
|
}
|
|
12
29
|
exports.default = FileLaneCompilation;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
/**
|
|
4
|
+
* FileLaneTriggerType
|
|
5
|
+
*/
|
|
6
|
+
var FileLaneTriggerType;
|
|
7
|
+
(function (FileLaneTriggerType) {
|
|
8
|
+
FileLaneTriggerType[FileLaneTriggerType["START"] = 1] = "START";
|
|
9
|
+
FileLaneTriggerType[FileLaneTriggerType["UPDATE"] = 2] = "UPDATE";
|
|
10
|
+
})(FileLaneTriggerType || (FileLaneTriggerType = {}));
|
|
11
|
+
exports.default = FileLaneTriggerType;
|
package/lib/index.d.ts
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import FileLane from './FileLane';
|
|
2
|
-
import IFileLaneConfig from './interface/IFileLaneConfig';
|
|
2
|
+
import IFileLaneConfig, { FollowWork, PreWork } from './interface/IFileLaneConfig';
|
|
3
3
|
import IFileLaneContext from './interface/IFileLaneContext';
|
|
4
4
|
import IFileParam from './interface/IFileParam';
|
|
5
5
|
import ILoader from './interface/ILoader';
|
|
6
6
|
import IPlugin from './interface/IPlugin';
|
|
7
|
-
|
|
7
|
+
import FileLaneUtil from './utils/FileLaneUtil';
|
|
8
|
+
export { FileLane, IFileLaneConfig, IFileLaneContext, IFileParam, ILoader, IPlugin, FileLaneUtil, PreWork, FollowWork };
|
|
9
|
+
export default FileLane;
|
package/lib/index.js
CHANGED
|
@@ -3,6 +3,9 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.FileLane = void 0;
|
|
6
|
+
exports.FileLaneUtil = exports.FileLane = void 0;
|
|
7
7
|
const FileLane_1 = __importDefault(require("./FileLane"));
|
|
8
8
|
exports.FileLane = FileLane_1.default;
|
|
9
|
+
const FileLaneUtil_1 = __importDefault(require("./utils/FileLaneUtil"));
|
|
10
|
+
exports.FileLaneUtil = FileLaneUtil_1.default;
|
|
11
|
+
exports.default = FileLane_1.default;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.HandlerType = void 0;
|
|
4
|
+
var HandlerType;
|
|
5
|
+
(function (HandlerType) {
|
|
6
|
+
HandlerType[HandlerType["ADD"] = 0] = "ADD";
|
|
7
|
+
HandlerType[HandlerType["CHANGE"] = 1] = "CHANGE";
|
|
8
|
+
HandlerType[HandlerType["UNLINK"] = 2] = "UNLINK";
|
|
9
|
+
})(HandlerType || (exports.HandlerType = HandlerType = {}));
|
|
@@ -1,14 +1,38 @@
|
|
|
1
|
-
import { MatchType } from '@aiot-toolkit/shared-utils
|
|
1
|
+
import { MatchType } from '@aiot-toolkit/shared-utils';
|
|
2
2
|
import IFileLaneContext from './IFileLaneContext';
|
|
3
3
|
import ILoader from './ILoader';
|
|
4
4
|
import IPlugin from './IPlugin';
|
|
5
|
+
import FileLaneCompilation from '../FileLaneCompilation';
|
|
6
|
+
import { IChangedFile } from './IChangedFile';
|
|
5
7
|
export type ILoaderClass = (new (...args: any[]) => ILoader) & {
|
|
6
8
|
raw?: boolean;
|
|
7
9
|
};
|
|
10
|
+
export interface IRule {
|
|
11
|
+
/**
|
|
12
|
+
* 配置文件
|
|
13
|
+
*/
|
|
14
|
+
test: MatchType;
|
|
15
|
+
/**
|
|
16
|
+
* 文件的 Loader,从前向后依次执行,前一个 loader 结果做为后一个 loader 的入参
|
|
17
|
+
*/
|
|
18
|
+
loader: ILoaderClass[];
|
|
19
|
+
exclude?: MatchType;
|
|
20
|
+
include?: MatchType;
|
|
21
|
+
}
|
|
8
22
|
/**
|
|
9
23
|
* IFileLaneConfig
|
|
10
24
|
*/
|
|
11
25
|
export default interface IFileLaneConfig<O = any> {
|
|
26
|
+
/**
|
|
27
|
+
* 项目文件采集器
|
|
28
|
+
*
|
|
29
|
+
* @param entryFileList 输入的文件列表
|
|
30
|
+
*
|
|
31
|
+
* @returns 返回项目中所有待处理的文件路径
|
|
32
|
+
*
|
|
33
|
+
* @description 用于采集所有要处理的真实文件路径列表,或者输入文件列表中要处理的真实文件路径列表
|
|
34
|
+
*/
|
|
35
|
+
collectFile?: (entryFileList?: IChangedFile[]) => string[];
|
|
12
36
|
/**
|
|
13
37
|
* 文件收集器
|
|
14
38
|
*
|
|
@@ -45,15 +69,7 @@ export default interface IFileLaneConfig<O = any> {
|
|
|
45
69
|
/**
|
|
46
70
|
* 转换规则
|
|
47
71
|
*/
|
|
48
|
-
rules:
|
|
49
|
-
/**
|
|
50
|
-
* 配置文件
|
|
51
|
-
*/
|
|
52
|
-
test: MatchType;
|
|
53
|
-
loader: ILoaderClass[];
|
|
54
|
-
exclude?: MatchType;
|
|
55
|
-
include?: MatchType;
|
|
56
|
-
}[];
|
|
72
|
+
rules: IRule[];
|
|
57
73
|
};
|
|
58
74
|
/**
|
|
59
75
|
* 插件
|
|
@@ -64,25 +80,43 @@ export default interface IFileLaneConfig<O = any> {
|
|
|
64
80
|
*/
|
|
65
81
|
plugins?: IPlugin[];
|
|
66
82
|
/**
|
|
67
|
-
*
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
*
|
|
83
|
+
* 启动阶段的准备工作
|
|
84
|
+
*/
|
|
85
|
+
beforeWorks?: BeforeWork[];
|
|
86
|
+
/**
|
|
87
|
+
* 收尾阶段的工作
|
|
72
88
|
*/
|
|
73
|
-
|
|
89
|
+
afterWorks?: AfterWork[];
|
|
74
90
|
/**
|
|
75
|
-
*
|
|
91
|
+
* 项目转换的前置工作
|
|
92
|
+
*/
|
|
93
|
+
beforeCompile?: PreWork[];
|
|
94
|
+
/**
|
|
95
|
+
* 项目转换的后续工作
|
|
76
96
|
*
|
|
77
97
|
* xts--[zip]
|
|
78
98
|
* ux--[webpack, zip]
|
|
79
99
|
* uxInspect--[webpack, zipPhone, zipWatch, zipTv]
|
|
80
100
|
*/
|
|
81
|
-
|
|
101
|
+
afterCompile?: FollowWoker<O>[];
|
|
82
102
|
/**
|
|
83
103
|
* 配置watch时忽略的文件或者文件夹
|
|
84
104
|
*/
|
|
85
105
|
watchIgnores?: MatchType;
|
|
106
|
+
projectPath: string;
|
|
86
107
|
}
|
|
87
|
-
|
|
88
|
-
|
|
108
|
+
type FollowWoker<O> = {
|
|
109
|
+
worker: FollowWork<O>;
|
|
110
|
+
workerDescribe?: string;
|
|
111
|
+
};
|
|
112
|
+
type CompileParam<O = any> = {
|
|
113
|
+
context: IFileLaneContext;
|
|
114
|
+
config: IFileLaneConfig;
|
|
115
|
+
compilerOption?: O;
|
|
116
|
+
compalition?: FileLaneCompilation;
|
|
117
|
+
};
|
|
118
|
+
export type BeforeWork = (context: IFileLaneContext) => Promise<any>;
|
|
119
|
+
export type PreWork<O = any> = (preWorkParams: CompileParam<O>) => Promise<any>;
|
|
120
|
+
export type FollowWork<O = any> = (followParams: CompileParam<O>) => Promise<any>;
|
|
121
|
+
export type AfterWork = (context: IFileLaneContext) => Promise<any>;
|
|
122
|
+
export {};
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { ILog } from '@aiot-toolkit/shared-utils/lib/interface/ILog';
|
|
2
|
+
import FileLaneTriggerType from '../enum/FileLaneTriggerType';
|
|
3
|
+
/**
|
|
4
|
+
* IFileLaneEvents
|
|
5
|
+
*/
|
|
6
|
+
export default interface IFileLaneEvents {
|
|
7
|
+
/**
|
|
8
|
+
* 转换成功
|
|
9
|
+
* @param data
|
|
10
|
+
* @returns
|
|
11
|
+
*/
|
|
12
|
+
onBuildSuccess?: (data: IFileLaneSuccessData) => void;
|
|
13
|
+
/**
|
|
14
|
+
* 转换失败
|
|
15
|
+
* @default 错误消息打印到控制台
|
|
16
|
+
* @param error
|
|
17
|
+
* @returns
|
|
18
|
+
*/
|
|
19
|
+
onBuildError?: (error: unknown) => void;
|
|
20
|
+
/**
|
|
21
|
+
* 日志触发的方法,打包过程中可能多次触发
|
|
22
|
+
* @default 日志打印到控制台
|
|
23
|
+
* @param logs
|
|
24
|
+
* @returns
|
|
25
|
+
*/
|
|
26
|
+
onLog?: (logs: ILog[]) => void;
|
|
27
|
+
}
|
|
28
|
+
export interface IFileLaneSuccessData {
|
|
29
|
+
/**
|
|
30
|
+
* 耗时(毫秒)
|
|
31
|
+
*/
|
|
32
|
+
costTime: number;
|
|
33
|
+
info?: {
|
|
34
|
+
/**
|
|
35
|
+
* 触发类型
|
|
36
|
+
*/
|
|
37
|
+
trigger: FileLaneTriggerType;
|
|
38
|
+
/**
|
|
39
|
+
* rpk 文件绝对路径
|
|
40
|
+
*/
|
|
41
|
+
rpk?: string;
|
|
42
|
+
/**
|
|
43
|
+
* 差异文件列表
|
|
44
|
+
*/
|
|
45
|
+
diffList?: string[];
|
|
46
|
+
/**
|
|
47
|
+
* 差异文件压缩包
|
|
48
|
+
*/
|
|
49
|
+
diffFile?: string;
|
|
50
|
+
[key: string]: any;
|
|
51
|
+
};
|
|
52
|
+
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { ILog } from '@aiot-toolkit/shared-utils/lib/interface/ILog';
|
|
1
2
|
import IFileLaneContext from './IFileLaneContext';
|
|
2
3
|
import IFileParam from './IFileParam';
|
|
3
4
|
/**
|
|
@@ -7,4 +8,10 @@ export default interface ILoader {
|
|
|
7
8
|
context?: IFileLaneContext;
|
|
8
9
|
compilerOption?: any;
|
|
9
10
|
parser(files: IFileParam[]): Promise<IFileParam[]> | IFileParam[];
|
|
11
|
+
/**
|
|
12
|
+
* 日志列表
|
|
13
|
+
*
|
|
14
|
+
* 其中有 `THROW` `ERROR` 时,会中断打包,并触发 `onBuildError` 事件
|
|
15
|
+
*/
|
|
16
|
+
logs?: ILog[];
|
|
10
17
|
}
|
|
@@ -11,14 +11,8 @@ declare class FileLaneUtil {
|
|
|
11
11
|
* @returns
|
|
12
12
|
*/
|
|
13
13
|
static pathToFileParam(path: string, readContent?: boolean): IFileParam;
|
|
14
|
-
/**
|
|
15
|
-
* 将buildPath文件夹的内容压缩成zip包,放置于targetPath路径下
|
|
16
|
-
* @param buildPath
|
|
17
|
-
* @param targetPath
|
|
18
|
-
* @param zipRootDirNames 可自定义压缩包内最外层目录的名称
|
|
19
|
-
*/
|
|
20
|
-
static zipProject(buildPath: string[], targetFile: string, zipRootDirNames?: string[]): Promise<void>;
|
|
21
14
|
static createContext(output: string, projectPath?: string): IFileLaneContext;
|
|
22
15
|
static checkError(message: string): void;
|
|
16
|
+
static getOutputPath(context: IFileLaneContext): string;
|
|
23
17
|
}
|
|
24
18
|
export default FileLaneUtil;
|
|
@@ -1,20 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
-
});
|
|
10
|
-
};
|
|
11
2
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
12
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
13
4
|
};
|
|
14
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
6
|
const shared_utils_1 = require("@aiot-toolkit/shared-utils");
|
|
16
|
-
const ColorConsole_1 = __importDefault(require("@aiot-toolkit/shared-utils/lib/ColorConsole"));
|
|
17
|
-
const archiver_1 = __importDefault(require("archiver"));
|
|
18
7
|
const fs_extra_1 = __importDefault(require("fs-extra"));
|
|
19
8
|
const path_1 = __importDefault(require("path"));
|
|
20
9
|
/**
|
|
@@ -40,49 +29,6 @@ class FileLaneUtil {
|
|
|
40
29
|
content
|
|
41
30
|
};
|
|
42
31
|
}
|
|
43
|
-
/**
|
|
44
|
-
* 将buildPath文件夹的内容压缩成zip包,放置于targetPath路径下
|
|
45
|
-
* @param buildPath
|
|
46
|
-
* @param targetPath
|
|
47
|
-
* @param zipRootDirNames 可自定义压缩包内最外层目录的名称
|
|
48
|
-
*/
|
|
49
|
-
static zipProject(buildPath, targetFile, zipRootDirNames) {
|
|
50
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
51
|
-
return new Promise((resolve, reject) => {
|
|
52
|
-
const output = fs_extra_1.default.createWriteStream(targetFile);
|
|
53
|
-
const archive = archiver_1.default.create('zip', {
|
|
54
|
-
zlib: { level: 9 }
|
|
55
|
-
});
|
|
56
|
-
// 监听错误
|
|
57
|
-
archive.on('error', (err) => {
|
|
58
|
-
ColorConsole_1.default.throw(`${err.message}`);
|
|
59
|
-
reject();
|
|
60
|
-
});
|
|
61
|
-
// 监听写入流打开的事件
|
|
62
|
-
output.on('open', () => {
|
|
63
|
-
ColorConsole_1.default.info(`Write stream is open`);
|
|
64
|
-
});
|
|
65
|
-
output.on('close', () => {
|
|
66
|
-
ColorConsole_1.default.info(`Write stream is closed`);
|
|
67
|
-
resolve();
|
|
68
|
-
});
|
|
69
|
-
// 将压缩文件导入到输出流中
|
|
70
|
-
archive.pipe(output);
|
|
71
|
-
// 指定压缩目录
|
|
72
|
-
buildPath.forEach((folder, index) => {
|
|
73
|
-
const folderName = path_1.default.basename(folder); // 获取文件夹名
|
|
74
|
-
if (zipRootDirNames && zipRootDirNames[index]) {
|
|
75
|
-
archive.directory(folder, zipRootDirNames[index]);
|
|
76
|
-
}
|
|
77
|
-
else {
|
|
78
|
-
archive.directory(folder, folderName);
|
|
79
|
-
}
|
|
80
|
-
});
|
|
81
|
-
// 完成压缩,关闭输出流
|
|
82
|
-
archive.finalize();
|
|
83
|
-
});
|
|
84
|
-
});
|
|
85
|
-
}
|
|
86
32
|
static createContext(output, projectPath) {
|
|
87
33
|
const cwd = process.cwd();
|
|
88
34
|
return {
|
|
@@ -93,14 +39,20 @@ class FileLaneUtil {
|
|
|
93
39
|
}
|
|
94
40
|
static checkError(message) {
|
|
95
41
|
if (message.includes('System limit for number of file watchers reached')) {
|
|
96
|
-
|
|
42
|
+
shared_utils_1.ColorConsole.error('There are too many files to watch, ', {
|
|
97
43
|
word: 'please configure the content to be ignored.',
|
|
98
44
|
style: {
|
|
99
|
-
bgColor:
|
|
45
|
+
bgColor: shared_utils_1.ColorConsole.getStyle(shared_utils_1.Loglevel.ERROR).color || '#FF0000'
|
|
100
46
|
}
|
|
101
47
|
}, '(For example, node_modules)');
|
|
102
48
|
}
|
|
103
|
-
|
|
49
|
+
else {
|
|
50
|
+
shared_utils_1.ColorConsole.throw(`### file-lane ### watch error ${message}`);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
static getOutputPath(context) {
|
|
54
|
+
const { output, projectPath } = context;
|
|
55
|
+
return path_1.default.join(projectPath, output);
|
|
104
56
|
}
|
|
105
57
|
}
|
|
106
58
|
exports.default = FileLaneUtil;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "file-lane",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.3-beta.1",
|
|
4
4
|
"description": "File conversion tool, can be one-to-one, one to N, N to one",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"file",
|
|
@@ -20,13 +20,13 @@
|
|
|
20
20
|
"test": "node ./__tests__/file-lane.test.js"
|
|
21
21
|
},
|
|
22
22
|
"dependencies": {
|
|
23
|
-
"@aiot-toolkit/shared-utils": "2.0.
|
|
24
|
-
"
|
|
25
|
-
"
|
|
23
|
+
"@aiot-toolkit/shared-utils": "2.0.3-beta.1",
|
|
24
|
+
"chokidar": "^3.6.0",
|
|
25
|
+
"fs-extra": "^11.2.0",
|
|
26
26
|
"lodash": "^4.17.21"
|
|
27
27
|
},
|
|
28
28
|
"devDependencies": {
|
|
29
|
-
"@types/
|
|
29
|
+
"@types/fs-extra": "^11.0.4"
|
|
30
30
|
},
|
|
31
|
-
"gitHead": "
|
|
31
|
+
"gitHead": "77b1b0aab9b5c227b5cc355b585a7c93761cc9a3"
|
|
32
32
|
}
|