mock-service-cli 2.1.1 → 2.2.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/CHANGELOG.md CHANGED
@@ -2,6 +2,20 @@
2
2
 
3
3
  All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
4
4
 
5
+ ## [2.2.0](https://github.com/chandq/mock-service-cli/compare/v2.1.1...v2.2.0) (2021-12-31)
6
+
7
+
8
+ ### Features
9
+
10
+ * 丰富日志工具函数 ([4dcd69c](https://github.com/chandq/mock-service-cli/commit/4dcd69c6400f65aaf77ea4a2923c9900d5954d09))
11
+ * 监听文件变化和写文件互斥执行 ([cfeab8e](https://github.com/chandq/mock-service-cli/commit/cfeab8ede05573974125a9fa91f1db6afa8a898d))
12
+ * record operation log ([42b74d8](https://github.com/chandq/mock-service-cli/commit/42b74d8be0e694600c999490d3fe93bfb3620051))
13
+
14
+
15
+ ### Bug Fixes
16
+
17
+ * issue of write large file failed ([d1c470d](https://github.com/chandq/mock-service-cli/commit/d1c470daf9829916016b73993b114fc5ffe3c985))
18
+
5
19
  ### [2.1.1](https://github.com/chandq/mock-service-cli/compare/v2.1.0...v2.1.1) (2021-12-30)
6
20
 
7
21
 
package/README.md CHANGED
@@ -55,6 +55,7 @@ This will install `mock-service-cli` globally so that it may be run from the com
55
55
  | `-v` or `--version` | Print the version and exit. | |
56
56
  | `-S` or `--socket-server` | Start socket server which used to save api response data for future mock. | false |
57
57
  | `-a` or `--api-stat` | Whether print api url and file path info or not, default false. | false |
58
+ | `-l` or `--log` | Whether record operation info by write file, default false. | false |
58
59
 
59
60
  ## Example
60
61
 
@@ -6,6 +6,8 @@ const colors = require('colors/safe'),
6
6
  nodemon = require('nodemon');
7
7
  const argv = require('minimist')(process.argv.slice(2));
8
8
  const { logger } = require('../lib/utils');
9
+ const spawn = require('child_process').spawn;
10
+ const node = process.execPath;
9
11
  process.title = 'mock-service-cli';
10
12
 
11
13
  if (argv.h || argv.help) {
@@ -22,6 +24,7 @@ if (argv.h || argv.help) {
22
24
  ' -s --silent Suppress log messages from output',
23
25
  ' -S --socket-server Whether start socket server or not, default false.',
24
26
  ' -a --api-stat Whether print api url and file path or not, default false.',
27
+ ' -l --log Whether record operation info by write file, default false.',
25
28
  '',
26
29
  ' -h --help Print this list and exit.',
27
30
  ' -v --version Print the version and exit.'
@@ -94,16 +97,34 @@ const watchMockFiles = function (watchDir) {
94
97
  );
95
98
  });
96
99
  };
100
+ // Node子进程启动MockServer
101
+ const startMockServer = function () {
102
+ spawn(node, [path.resolve(__dirname, '../lib/mockServer.js')], {
103
+ stdio: 'inherit'
104
+ });
105
+ };
97
106
 
98
107
  if (specifiedFile) {
99
108
  process.env.SPECIFIED_FILE = path.resolve(process.cwd(), specifiedFile);
100
- watchMockFiles(process.env.SPECIFIED_FILE);
109
+ if (isStartSocketServer) {
110
+ startMockServer();
111
+ } else {
112
+ watchMockFiles(process.env.SPECIFIED_FILE);
113
+ }
101
114
  } else if (watchDir) {
102
115
  process.env.SPECIFIED_DIR = path.resolve(process.cwd(), watchDir);
103
116
  // log.info('SPECIFIED_DIR::', process.env.SPECIFIED_DIR);
104
- watchMockFiles(process.env.SPECIFIED_DIR);
117
+ if (isStartSocketServer) {
118
+ startMockServer();
119
+ } else {
120
+ watchMockFiles(process.env.SPECIFIED_DIR);
121
+ }
105
122
  } else {
106
123
  watchDir = process.env.SPECIFIED_DIR = path.resolve(process.cwd(), './mock');
107
124
  // log.info('SPECIFIED_DIR::', process.env.SPECIFIED_DIR);
108
- watchMockFiles(watchDir);
125
+ if (isStartSocketServer) {
126
+ startMockServer();
127
+ } else {
128
+ watchMockFiles(watchDir);
129
+ }
109
130
  }
@@ -2,7 +2,7 @@
2
2
  * @description: 生成Mock文件、获取mock数据统计
3
3
  * @Date: 2021-12-22 16:57:08
4
4
  * @LastEditors: chendq
5
- * @LastEditTime: 2021-12-30 16:43:04
5
+ * @LastEditTime: 2021-12-31 22:55:00
6
6
  * @Author: chendq
7
7
  */
8
8
  const fsa = require('fs-extra'),
@@ -10,8 +10,18 @@ const fsa = require('fs-extra'),
10
10
  path = require('path'),
11
11
  _ = require('lodash'),
12
12
  colors = require('colors/safe');
13
- const { getFileLatestContent, SupportMethods, filePath2ApiUrl, logger, getDataType } = require('./utils');
13
+ const {
14
+ getFileLatestContent,
15
+ SupportMethods,
16
+ filePath2ApiUrl,
17
+ logger,
18
+ getDataType,
19
+ getLogger,
20
+ writeStream
21
+ } = require('./utils');
14
22
  const log = logger(process.env.SILENT);
23
+ const processArgv = JSON.parse(process.env.ARGV);
24
+ let LOGGER = getLogger();
15
25
 
16
26
  const methodRegExp = new RegExp(`(${SupportMethods.join('|')}) +(.*)`, 'i');
17
27
  /**
@@ -43,6 +53,7 @@ const genMockFiles = function ({ url: apiUrl, method, data: resJsonData, dir: mo
43
53
  return;
44
54
  }
45
55
  apiUrl = apiUrl.trim().split('?')[0];
56
+ LOGGER = getLogger(mockDir);
46
57
  const normalizeApiUrl = filePath2ApiUrl(path.normalize(apiUrl));
47
58
  const mockListFilePath = path.resolve(process.cwd(), `${mockDir}/mock-list.json`);
48
59
  const mockFilePath = path.resolve(process.cwd(), `${mockDir}/${encodeURIComponent(path.normalize(apiUrl))}.json`);
@@ -63,7 +74,7 @@ const genMockFiles = function ({ url: apiUrl, method, data: resJsonData, dir: mo
63
74
  }
64
75
  if (!oldMockListContent || !_.isEqual(oldMockListContent, newMockListContent)) {
65
76
  Object.keys(newMockListContent).length > 0 &&
66
- fs.writeFileSync(mockListFilePath, JSON.stringify(newMockListContent, null, 2));
77
+ writeStream(mockListFilePath, JSON.stringify(newMockListContent, null, 2));
67
78
  }
68
79
 
69
80
  // mock文件存在
@@ -78,12 +89,17 @@ const genMockFiles = function ({ url: apiUrl, method, data: resJsonData, dir: mo
78
89
  return;
79
90
  }
80
91
  mockFileContent[method] = resJsonData;
81
- Object.keys(mockFileContent).length > 0 &&
82
- fsa.writeFileSync(mockFilePath, JSON.stringify(mockFileContent, null, 2));
92
+ writeStream(mockFilePath, JSON.stringify(mockFileContent, null, 2));
93
+ if (processArgv.l || processArgv.log) {
94
+ LOGGER.log(`Update file: ${method} ${apiUrl} ${mockFilePath}`);
95
+ }
83
96
  } else {
84
97
  // fsa.ensureFileSync(mockFilePath);
85
- Object.keys(mockFilePath).length > 0 &&
86
- fsa.writeFileSync(mockFilePath, JSON.stringify({ [method]: resJsonData }, null, 2));
98
+
99
+ writeStream(mockFilePath, JSON.stringify({ [method]: resJsonData }, null, 2));
100
+ if (processArgv.l || processArgv.log) {
101
+ LOGGER.log(`Write new file: ${method} ${apiUrl} ${mockFilePath}`);
102
+ }
87
103
  }
88
104
  // console.debug('file::', `${mockDir}/${apiUrl}`, newMockListContent);
89
105
  };
@@ -176,7 +192,7 @@ const getMockStatFromDir = dirPath => {
176
192
  }
177
193
  }
178
194
  });
179
- fs.writeFileSync(mockListFilePath, JSON.stringify(reverseMockList, null, 2));
195
+ writeStream(mockListFilePath, JSON.stringify(reverseMockList, null, 2));
180
196
  }
181
197
  return mockDataMap;
182
198
  };
package/lib/utils.js CHANGED
@@ -1,27 +1,40 @@
1
1
  /*
2
- * @description:
2
+ * @description: 工具函数库
3
3
  * @Date: 2021-12-25 17:52:48
4
4
  * @LastEditors: chendq
5
- * @LastEditTime: 2021-12-30 13:17:12
5
+ * @LastEditTime: 2021-12-31 23:10:02
6
6
  * @Author: chendq
7
7
  */
8
+ const fs = require('fs');
9
+ const path = require('path');
8
10
  /**
9
11
  * @description: 输出和错误输出写入不同文件
10
- * @param {*}
11
- * @return {*}
12
+ * @param {string} logFileDirPath
13
+ * @return {object}
12
14
  */
13
- const path = require('path');
14
- const getLogger = function () {
15
- const fs = require('fs');
16
- const output = fs.createWriteStream('./stdout.log');
17
- const errorOutput = fs.createWriteStream('./stderr.log');
15
+ const getLogger = function (logFileDirPath) {
16
+ const options = {
17
+ flags: 'a', // append模式
18
+ encoding: 'utf8' // utf8编码
19
+ };
20
+ const output = fs.createWriteStream(
21
+ path.resolve(logFileDirPath ? logFileDirPath : process.cwd(), './stdout.log'),
22
+ options
23
+ );
24
+ const errorOutput = fs.createWriteStream(
25
+ path.resolve(logFileDirPath ? logFileDirPath : process.cwd(), './stderr.log'),
26
+ options
27
+ );
18
28
  // 自定义日志打印
19
29
  const logger = new console.Console(output, errorOutput);
20
30
 
21
- logger.log('向 stdout 中写入数据');
22
- logger.error('向 stderr 中写入数据');
31
+ // logger.log('向 stdout 中写入数据');
32
+ // logger.error('向 stderr 中写入数据');
23
33
 
24
- return logger;
34
+ return {
35
+ log: (...args) => logger.log.call(null, `[${dateFormat('YYYY-mm-dd HH:MM:SS:fff')}] - `, ...args),
36
+ error: (...args) => logger.error.call(null, `[${dateFormat('YYYY-mm-dd HH:MM:SS:fff')}] - `, ...args)
37
+ };
25
38
  };
26
39
  /**
27
40
  * @description: 格式化时间日期
@@ -29,7 +42,7 @@ const getLogger = function () {
29
42
  * @param {*} date
30
43
  * @returns {*}
31
44
  */
32
- function dateFormat(fmt, date) {
45
+ function dateFormat(fmt, date = new Date()) {
33
46
  let ret;
34
47
  const opt = {
35
48
  'Y+': date.getFullYear().toString(), // 年
@@ -37,7 +50,8 @@ function dateFormat(fmt, date) {
37
50
  'd+': date.getDate().toString(), // 日
38
51
  'H+': date.getHours().toString(), // 时
39
52
  'M+': date.getMinutes().toString(), // 分
40
- 'S+': date.getSeconds().toString() // 秒
53
+ 'S+': date.getSeconds().toString(), // 秒
54
+ 'f+': date.getMilliseconds().toString() // 毫秒
41
55
  // 有其他格式化字符需求可以继续添加,必须转化成字符串
42
56
  };
43
57
  // eslint-disable-next-line guard-for-in
@@ -101,6 +115,51 @@ const filePath2ApiUrl = function (filePath) {
101
115
  const getDataType = function (data) {
102
116
  return Object.prototype.toString.call(data).slice(8, -1).toLowerCase();
103
117
  };
118
+ /**
119
+ * @description: 流方式写文件(适合写超大文件)
120
+ * @param {string} filePath
121
+ * @param {object} data
122
+ * @return {*}
123
+ */
124
+ const writeStream = function (filePath, data) {
125
+ // 创建一个可写流 也会创建一个test1.txt文件
126
+ const writerStream = fs.createWriteStream(filePath);
127
+ // 将数据写入流
128
+ writerStream.write(data, 'utf-8');
129
+ // 标记文件的结束
130
+ writerStream.end();
131
+ writerStream.on('finish', () => {
132
+ // console.log('写入完成');
133
+ });
134
+ writerStream.on('error', () => {
135
+ console.error(`${filePath} 写入失败`);
136
+ });
137
+ };
138
+ /**
139
+ * @description: 流方式读文件(适合写超大文件)
140
+ * @param {string} filePath
141
+ * @return {*}
142
+ */
143
+ const readeStream = function (filePath) {
144
+ let data = '';
145
+ // 创建可读流
146
+ return new Promise((resovle, reject) => {
147
+ const readerStream = fs.createReadStream(filePath);
148
+ // 设置编码为 utf8。
149
+ readerStream.setEncoding('UTF8');
150
+ // 处理流事件 --> data, end, and error
151
+ readerStream.on('data', function (chunk) {
152
+ data += chunk;
153
+ });
154
+ readerStream.on('end', function () {
155
+ resovle(data);
156
+ });
157
+ readerStream.on('error', function (err) {
158
+ reject(err);
159
+ console.log(err.stack);
160
+ });
161
+ });
162
+ };
104
163
 
105
164
  module.exports = {
106
165
  getLogger,
@@ -110,5 +169,7 @@ module.exports = {
110
169
  isValidMethod,
111
170
  getFileLatestContent,
112
171
  filePath2ApiUrl,
113
- getDataType
172
+ getDataType,
173
+ writeStream,
174
+ readeStream
114
175
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mock-service-cli",
3
- "version": "2.1.1",
3
+ "version": "2.2.0",
4
4
  "description": "🦅 Local mock server",
5
5
  "main": "./lib/mockServer.js",
6
6
  "bin": {