file-lane 2.0.2-dev.7 → 2.0.2

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 CHANGED
@@ -1,13 +1,247 @@
1
- # `file-lane`
1
+ # 项目介绍
2
2
 
3
- 用于文件转换,可1个文件转换为1个文件,也可1转多、多转1
3
+ file-lane模块用于文件转换,可实现文件11的转换,也可实现1对多、多对1的文件转换。
4
4
 
5
- <img src="./doc/flow.jpg" style="max-width: 1000px; width: 100%"/>
5
+ <img src="./doc/flow-detail.png" style="max-width: 1000px; width: 100%"/>
6
6
 
7
- ## Usage
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
- const fileLane = require('file-lane');
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
- // TODO: DEMONSTRATE API
245
+ ```javascript
246
+ watchIgnores = [/node_modules/, '/build/', '/dist/']
13
247
  ```
package/lib/FileLane.d.ts CHANGED
@@ -9,17 +9,22 @@ import IFileLaneConfig from './interface/IFileLaneConfig';
9
9
  declare class FileLane<O = any> {
10
10
  readonly config: IFileLaneConfig<O>;
11
11
  readonly compilerOption?: O | undefined;
12
+ private readonly events?;
12
13
  private context;
13
14
  private watcher?;
14
15
  private compilation?;
15
- private ws;
16
+ private changeFileList;
16
17
  /**
17
18
  * 实例化FileLane
18
19
  * @param config fileLane 配置
19
20
  * @param projectPath 项目路径
20
21
  * @param compilerOption 编译参数,不同语言的项目具有的参数不同,即使同一项目开发者也会设置不同的参数
21
22
  */
22
- constructor(config: IFileLaneConfig<O>, projectPath?: string, compilerOption?: O | undefined);
23
+ constructor(config: IFileLaneConfig<O>, projectPath?: string, compilerOption?: O | undefined, events?: {
24
+ onBuildSuccess?: (data: {
25
+ costTime: number;
26
+ }) => void;
27
+ } | undefined);
23
28
  /**
24
29
  * 运行
25
30
  * @param params
@@ -35,6 +40,7 @@ declare class FileLane<O = any> {
35
40
  }): Promise<void>;
36
41
  private validateConfig;
37
42
  private processExitHandler;
43
+ private sigintHandler;
38
44
  stop(): void;
39
45
  dispose(): void;
40
46
  /**
@@ -55,13 +61,21 @@ declare class FileLane<O = any> {
55
61
  private findLoader;
56
62
  private triggerPlugins;
57
63
  /**
58
- * 运行转换初始的任务
64
+ * start开始时的准备工作
59
65
  */
60
- private runPreWorks;
66
+ private complyBeforeWorks;
61
67
  /**
62
- * 运行转换后续的任务
68
+ * start结束后的收尾工作
63
69
  */
64
- private runFollowWorks;
70
+ private complyAfterWork;
71
+ /**
72
+ * 执行项目转换的前置工作
73
+ */
74
+ private complyBeforeCompile;
75
+ /**
76
+ * 执行项目转换的后续工作
77
+ */
78
+ private complyAfterCompile;
65
79
  private watch;
66
80
  /**
67
81
  * 采集所有要处理的真实文件路径列表
@@ -74,10 +88,15 @@ declare class FileLane<O = any> {
74
88
  * @param onChange
75
89
  */
76
90
  private listenFileChange;
77
- private get outputPath();
78
91
  /**
79
92
  * 清除输出文件夹
80
93
  */
81
94
  private cleanOutput;
95
+ /**
96
+ * 1. 配置的忽略文件夹
97
+ * 2. 默认应该忽略的文件及文件夹
98
+ * @returns
99
+ */
100
+ private getIgnoreConfig;
82
101
  }
83
102
  export default FileLane;
package/lib/FileLane.js CHANGED
@@ -13,17 +13,15 @@ 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");
27
25
  /**
28
26
  * FileLane
29
27
  *
@@ -38,14 +36,17 @@ class FileLane {
38
36
  * @param projectPath 项目路径
39
37
  * @param compilerOption 编译参数,不同语言的项目具有的参数不同,即使同一项目开发者也会设置不同的参数
40
38
  */
41
- constructor(config, projectPath, compilerOption) {
39
+ constructor(config, projectPath, compilerOption, events) {
42
40
  this.config = config;
43
41
  this.compilerOption = compilerOption;
42
+ this.events = events;
43
+ this.changeFileList = [];
44
44
  this.processExitHandler = () => {
45
45
  this.dispose();
46
46
  };
47
47
  this.context = FileLaneUtil_1.default.createContext(config.output, projectPath);
48
48
  process.on('exit', this.processExitHandler);
49
+ process.on('SIGINT', this.sigintHandler);
49
50
  }
50
51
  /**
51
52
  * 运行
@@ -56,10 +57,10 @@ class FileLane {
56
57
  return __awaiter(this, void 0, void 0, function* () {
57
58
  const errorList = this.validateConfig();
58
59
  if (errorList && errorList.length) {
59
- ColorConsole_1.default.error(`### file-lane ### ${errorList.map((item, index) => `${index + 1}. ${item}`).join('\r\n')}`);
60
+ shared_utils_1.ColorConsole.error(`### file-lane ### ${errorList.map((item, index) => `${index + 1}. ${item}`).join('\r\n')}`);
60
61
  return;
61
62
  }
62
- this.cleanOutput();
63
+ yield this.complyBeforeWorks();
63
64
  const fileList = this.collectFile();
64
65
  if (!fileList || !fileList.length) {
65
66
  return;
@@ -117,14 +118,18 @@ class FileLane {
117
118
  }
118
119
  return result;
119
120
  }
121
+ sigintHandler() {
122
+ process.exit();
123
+ }
120
124
  stop() {
121
- this.dispose();
122
125
  process.exit();
123
126
  }
124
127
  dispose() {
128
+ this.complyAfterWork();
125
129
  if (this.watcher) {
126
130
  this.watcher.close();
127
131
  }
132
+ this.cleanOutput();
128
133
  }
129
134
  /**
130
135
  *
@@ -132,9 +137,11 @@ class FileLane {
132
137
  */
133
138
  build(fileList) {
134
139
  return __awaiter(this, void 0, void 0, function* () {
140
+ const { onBuildSuccess } = this.events || {};
141
+ const t1 = Date.now();
135
142
  this.initCompilation();
136
143
  try {
137
- yield this.runPreWorks(fileList);
144
+ yield this.complyBeforeCompile();
138
145
  this.triggerPlugins(new CompilationEvent_1.default(CompilationEvent_1.default.PROJECT_START));
139
146
  for (let item of fileList) {
140
147
  this.triggerPlugins(new FileEvent_1.default(FileEvent_1.default.FILE_START_COMPILATION, FileLaneUtil_1.default.pathToFileParam(item)));
@@ -144,16 +151,18 @@ class FileLane {
144
151
  this.triggerPlugins(new CompilationEvent_1.default(CompilationEvent_1.default.PROJECT_END));
145
152
  // 执行extra
146
153
  this.triggerPlugins(new CompilationEvent_1.default(CompilationEvent_1.default.FLLOW_WORK_START));
147
- yield this.runFollowWorks();
154
+ yield this.complyAfterCompile();
148
155
  this.triggerPlugins(new CompilationEvent_1.default(CompilationEvent_1.default.FLLOW_WORK_END));
149
- ColorConsole_1.default.success({
156
+ onBuildSuccess === null || onBuildSuccess === void 0 ? void 0 : onBuildSuccess({ costTime: Date.now() - t1 });
157
+ shared_utils_1.ColorConsole.success({
150
158
  word: 'Success: build finish!',
151
- style: ColorConsole_1.default.getStyle(shared_utils_1.LOG_LEVEL.Success)
159
+ style: shared_utils_1.ColorConsole.getStyle(shared_utils_1.Loglevel.SUCCESS)
152
160
  });
153
161
  }
154
162
  catch (error) {
155
- console.log('error', error);
156
- ColorConsole_1.default.throw(`ERROR: build error, ${error || 'unknown error'}`);
163
+ shared_utils_1.ColorConsole.throw(`ERROR: `, { word: 'build error' }, `, ${error || 'unknown error'}`);
164
+ // 结束任务
165
+ process.exit();
157
166
  }
158
167
  });
159
168
  }
@@ -206,7 +215,10 @@ class FileLane {
206
215
  if (!fileList || !fileList.length) {
207
216
  return;
208
217
  }
209
- const buildPath = this.outputPath;
218
+ const buildPath = FileLaneUtil_1.default.getOutputPath(this.context);
219
+ if (!fs_extra_1.default.existsSync(buildPath)) {
220
+ shared_utils_1.FileUtil.mkdirSync(buildPath, { hidden: true });
221
+ }
210
222
  return Promise.all(fileList.map((item) => {
211
223
  const resolvePath = path_1.default.relative(this.context.projectPath, item.path);
212
224
  // 将相对路径与输出路径拼接,形成最新的文件路径
@@ -234,8 +246,8 @@ class FileLane {
234
246
  let loaders = [];
235
247
  for (let rule of rules) {
236
248
  // 1. 检查filePath是否符合规则test
237
- if (FileUtil_1.default.match(parse, rule.test) &&
238
- FileUtil_1.default.include(filePath, rule.include, rule.exclude)) {
249
+ if (shared_utils_1.FileUtil.match(parse, rule.test) &&
250
+ shared_utils_1.FileUtil.include(filePath, rule.include, rule.exclude)) {
239
251
  // 2. 符合规则就添加到返回列表中
240
252
  loaders.push(...rule.loader);
241
253
  }
@@ -250,33 +262,71 @@ class FileLane {
250
262
  });
251
263
  }
252
264
  /**
253
- * 运行转换初始的任务
265
+ * start开始时的准备工作
254
266
  */
255
- runPreWorks(fileList) {
267
+ complyBeforeWorks() {
256
268
  return __awaiter(this, void 0, void 0, function* () {
257
- const { preWorks } = this.config;
258
- if (preWorks) {
259
- for (let item of preWorks) {
260
- try {
261
- yield item(this.context, fileList, this.config, this.compilerOption);
262
- }
263
- catch (error) {
264
- // prework的item error
265
- ColorConsole_1.default.throw((error === null || error === void 0 ? void 0 : error.toString()) || 'unkonw error');
266
- }
269
+ const { beforeWorks } = this.config;
270
+ if (beforeWorks) {
271
+ for (let item of beforeWorks) {
272
+ yield item(this.context);
273
+ }
274
+ }
275
+ });
276
+ }
277
+ /**
278
+ * start结束后的收尾工作
279
+ */
280
+ complyAfterWork() {
281
+ return __awaiter(this, void 0, void 0, function* () {
282
+ const { afterWorks } = this.config;
283
+ if (afterWorks) {
284
+ for (let item of afterWorks) {
285
+ yield item(this.context);
286
+ }
287
+ }
288
+ });
289
+ }
290
+ /**
291
+ * 执行项目转换的前置工作
292
+ */
293
+ complyBeforeCompile() {
294
+ return __awaiter(this, void 0, void 0, function* () {
295
+ const { beforeCompile } = this.config;
296
+ if (beforeCompile) {
297
+ for (let item of beforeCompile) {
298
+ yield item({
299
+ context: this.context,
300
+ config: this.config,
301
+ compilerOption: this.compilerOption,
302
+ compalition: this.compilation
303
+ });
267
304
  }
268
305
  }
269
306
  });
270
307
  }
271
308
  /**
272
- * 运行转换后续的任务
309
+ * 执行项目转换的后续工作
273
310
  */
274
- runFollowWorks() {
311
+ complyAfterCompile() {
275
312
  return __awaiter(this, void 0, void 0, function* () {
276
- const { followWorks } = this.config;
277
- if (followWorks) {
278
- for (let item of followWorks) {
279
- yield item(this.context, this.config, this.compilerOption);
313
+ const { afterCompile } = this.config;
314
+ if (afterCompile) {
315
+ for (let item of afterCompile) {
316
+ try {
317
+ shared_utils_1.ColorConsole.info(`FollowWork: ${item.workerDescribe} start`);
318
+ yield item.worker({
319
+ context: this.context,
320
+ config: this.config,
321
+ compilerOption: this.compilerOption,
322
+ compalition: this.compilation
323
+ });
324
+ shared_utils_1.ColorConsole.info(`FollowWork: ${item.workerDescribe} end`);
325
+ }
326
+ catch (error) {
327
+ shared_utils_1.ColorConsole.throw(`FollowWork: ${item.workerDescribe} error, ${error}`);
328
+ process.exit();
329
+ }
280
330
  }
281
331
  }
282
332
  });
@@ -284,18 +334,15 @@ class FileLane {
284
334
  watch() {
285
335
  return __awaiter(this, void 0, void 0, function* () {
286
336
  // 监听文件变化,并触发 build
287
- this.listenFileChange(() => __awaiter(this, void 0, void 0, function* () {
288
- var _a, _b, _c;
289
- const fileList = this.collectFile();
290
- if (!this.ws && ((_a = this.compilerOption) === null || _a === void 0 ? void 0 : _a.hasOwnProperty('server'))) {
291
- const port = (_b = this.compilerOption.server) === null || _b === void 0 ? void 0 : _b.port;
292
- this.ws = new ws_1.default(`ws://localhost:${port}`);
293
- }
337
+ const onChange = () => __awaiter(this, void 0, void 0, function* () {
338
+ const fileList = this.config.collectFile
339
+ ? this.config.collectFile(this.changeFileList)
340
+ : this.collectFile();
341
+ // 开始编译前,记录列表置空
342
+ this.changeFileList = [];
294
343
  yield this.build(fileList);
295
- (_c = this.ws) === null || _c === void 0 ? void 0 : _c.send(JSON.stringify({
296
- type: 'restart'
297
- }));
298
- }));
344
+ });
345
+ this.listenFileChange(onChange);
299
346
  });
300
347
  }
301
348
  /**
@@ -308,8 +355,8 @@ class FileLane {
308
355
  let files = [];
309
356
  if (entryFileList) {
310
357
  entryFileList.forEach((filePath) => {
311
- if (FileUtil_1.default.include(filePath, this.config.include, this.config.exclude)) {
312
- ColorConsole_1.default.log(`### file-lane ### file change: ${filePath}`);
358
+ if (shared_utils_1.FileUtil.include(filePath, this.config.include, this.config.exclude)) {
359
+ shared_utils_1.ColorConsole.log(`### file-lane ### file change: ${filePath}`);
313
360
  files.push(filePath);
314
361
  }
315
362
  });
@@ -318,7 +365,7 @@ class FileLane {
318
365
  // 1.取出projectPath
319
366
  const projectPath = this.context.projectPath;
320
367
  // 2. 循环文件夹,取出所有匹配的文件路径
321
- files = FileUtil_1.default.readAlldirSync(projectPath, this.config.include, this.config.exclude);
368
+ files = shared_utils_1.FileUtil.readAlldirSync(projectPath, this.config.include, this.config.exclude);
322
369
  }
323
370
  return files;
324
371
  }
@@ -328,54 +375,77 @@ class FileLane {
328
375
  */
329
376
  listenFileChange(onChange) {
330
377
  const watcher = chokidar_1.default.watch(this.context.projectPath, {
331
- ignored: this.config.watchIgnores
378
+ ignored: this.getIgnoreConfig()
332
379
  });
333
380
  const throttledOnChange = lodash_1.default.throttle(onChange, 1000, {
334
- leading: true,
335
- trailing: false
381
+ leading: false,
382
+ trailing: true
336
383
  });
337
- const handler = (filePath) => {
384
+ const handler = (path, type) => {
338
385
  const { exclude, include } = this.config;
339
- // 判断是否为删除,执行onChange回调
340
- if (FileUtil_1.default.include(filePath, include, exclude)) {
341
- throttledOnChange([filePath]);
386
+ // 执行onChange回调
387
+ const validFile = shared_utils_1.FileUtil.include(path, include, exclude);
388
+ if (validFile) {
389
+ this.changeFileList.push({ path, type });
390
+ throttledOnChange();
342
391
  }
343
392
  };
344
393
  watcher
345
394
  .on('ready', () => {
346
- ColorConsole_1.default.log(`### file-lane ### Initial scan complete. Ready for Watch.`);
395
+ shared_utils_1.ColorConsole.log(`### file-lane ### Initial scan complete. Ready for Watch.`);
347
396
  watcher
348
397
  .on('add', (path) => {
349
398
  // 监听文件添加事件
350
- handler(path);
399
+ handler(path, IChangedFile_1.HandlerType.ADD);
351
400
  })
352
401
  .on('change', (path) => {
353
402
  // 监听文件修改事件
354
- handler(path);
403
+ handler(path, IChangedFile_1.HandlerType.CHANGE);
355
404
  })
356
405
  .on('unlink', (filePath) => {
357
406
  // 监听文件删除事件
358
- handler(filePath);
407
+ handler(filePath, IChangedFile_1.HandlerType.UNLINK);
359
408
  });
360
409
  })
361
410
  .on('error', (error) => {
362
411
  // 监听错误
363
412
  FileLaneUtil_1.default.checkError(error.message);
413
+ watcher.close();
364
414
  });
365
415
  if (this.watcher) {
366
416
  this.watcher.close();
367
417
  }
368
418
  this.watcher = watcher;
369
419
  }
370
- get outputPath() {
371
- const { output, projectPath } = this.context;
372
- return path_1.default.join(projectPath, output);
373
- }
374
420
  /**
375
421
  * 清除输出文件夹
376
422
  */
377
423
  cleanOutput() {
378
- fs_extra_1.default.removeSync(this.outputPath);
424
+ return __awaiter(this, void 0, void 0, function* () {
425
+ shared_utils_1.FileUtil.del(FileLaneUtil_1.default.getOutputPath(this.context));
426
+ });
427
+ }
428
+ /**
429
+ * 1. 配置的忽略文件夹
430
+ * 2. 默认应该忽略的文件及文件夹
431
+ * @returns
432
+ */
433
+ getIgnoreConfig() {
434
+ let ignoreList = [];
435
+ // 1.
436
+ if (this.config.watchIgnores) {
437
+ if (Array.isArray(this.config.watchIgnores)) {
438
+ ignoreList.push(...this.config.watchIgnores);
439
+ }
440
+ else {
441
+ ignoreList.push(this.config.watchIgnores);
442
+ }
443
+ }
444
+ // 2. 忽略.开头的隐藏文件夹
445
+ ignoreList.push(/(^|[\/\\])\../);
446
+ // 3. 忽略output目录
447
+ ignoreList.push(path_1.default.join(this.context.projectPath, this.config.output));
448
+ return ignoreList;
379
449
  }
380
450
  }
381
451
  exports.default = FileLane;
@@ -1,7 +1,10 @@
1
1
  import AsyncEventDispatcher from './event/asyncEvent/AsyncEventDispatcher';
2
+ import IFileParam from './interface/IFileParam';
2
3
  /**
3
4
  * FileLaneCompilation
4
5
  */
5
6
  declare class FileLaneCompilation extends AsyncEventDispatcher {
7
+ buildFileList: IFileParam<any>[];
8
+ diffJson: string[];
6
9
  }
7
10
  export default FileLaneCompilation;
@@ -8,5 +8,10 @@ const AsyncEventDispatcher_1 = __importDefault(require("./event/asyncEvent/Async
8
8
  * FileLaneCompilation
9
9
  */
10
10
  class FileLaneCompilation extends AsyncEventDispatcher_1.default {
11
+ constructor() {
12
+ super(...arguments);
13
+ this.buildFileList = [];
14
+ this.diffJson = [];
15
+ }
11
16
  }
12
17
  exports.default = FileLaneCompilation;
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
- export { FileLane, IFileLaneConfig, IFileLaneContext, IFileParam, ILoader, IPlugin };
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
+ export interface IChangedFile {
2
+ path: string;
3
+ type: HandlerType;
4
+ }
5
+ export declare enum HandlerType {
6
+ ADD = 0,
7
+ CHANGE = 1,
8
+ UNLINK = 2
9
+ }
@@ -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/lib/utils/FileUtil';
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,42 @@ export default interface IFileLaneConfig<O = any> {
64
80
  */
65
81
  plugins?: IPlugin[];
66
82
  /**
67
- * 前置工作
68
- *
69
- * @param context 上下文
70
- * @param fileList 待转换的文件列表
71
- * @returns
83
+ * 启动阶段的准备工作
84
+ */
85
+ beforeWorks?: BeforeWork[];
86
+ /**
87
+ * 收尾阶段的工作
72
88
  */
73
- preWorks?: PreWork[];
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
- followWorks?: FollowWork<O>[];
101
+ afterCompile?: FollowWoker<O>[];
82
102
  /**
83
103
  * 配置watch时忽略的文件或者文件夹
84
104
  */
85
105
  watchIgnores?: MatchType;
86
106
  }
87
- export type FollowWork<O = any> = (context: IFileLaneContext, config?: IFileLaneConfig, compilerOption?: O) => Promise<any>;
88
- export type PreWork<O = any> = (context: IFileLaneContext, fileList: string[], config: IFileLaneConfig, compilerOption?: O) => Promise<any>;
107
+ type FollowWoker<O> = {
108
+ worker: FollowWork<O>;
109
+ workerDescribe?: string;
110
+ };
111
+ type CompileParam<O = any> = {
112
+ context: IFileLaneContext;
113
+ config: IFileLaneConfig;
114
+ compilerOption?: O;
115
+ compalition?: FileLaneCompilation;
116
+ };
117
+ export type BeforeWork = (context: IFileLaneContext) => Promise<any>;
118
+ export type PreWork<O = any> = (preWorkParams: CompileParam<O>) => Promise<any>;
119
+ export type FollowWork<O = any> = (followParams: CompileParam<O>) => Promise<any>;
120
+ export type AfterWork = (context: IFileLaneContext) => Promise<any>;
121
+ export {};
@@ -1,4 +1,3 @@
1
- /// <reference types="node" />
2
1
  /**
3
2
  * IFileParam
4
3
  */
@@ -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
- ColorConsole_1.default.error('There are too many files to watch, ', {
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: ColorConsole_1.default.getStyle(shared_utils_1.LOG_LEVEL.Error).color || '#FF0000'
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
- ColorConsole_1.default.throw(`### file-lane ### watch error ${message}`);
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.2-dev.7",
3
+ "version": "2.0.2",
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.2-dev.7",
24
- "archiver": "^6.0.1",
25
- "chokidar": "^3.5.3",
23
+ "@aiot-toolkit/shared-utils": "2.0.2",
24
+ "chokidar": "^3.6.0",
25
+ "fs-extra": "^11.2.0",
26
26
  "lodash": "^4.17.21"
27
27
  },
28
28
  "devDependencies": {
29
- "@types/archiver": "^5.3.2"
29
+ "@types/fs-extra": "^11.0.4"
30
30
  },
31
- "gitHead": "26fa71dd55c1f68727ccc2d627a40822074b8ba1"
31
+ "gitHead": "8ca4bf2ed7bcf11911e5c514696951bdba4fc12d"
32
32
  }