ee-bin 2.0.0-beta.2 → 4.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/config/bin_default.js +181 -0
- package/index.js +118 -0
- package/lib/extend.js +78 -0
- package/lib/{utils.cjs → utils.js} +69 -34
- package/package.json +8 -5
- package/tools/encrypt.js +179 -0
- package/tools/{incrUpdater.cjs → incrUpdater.js} +27 -111
- package/tools/move.js +69 -0
- package/tools/serve.js +240 -0
- package/index.cjs +0 -137
- package/tools/encrypt.cjs +0 -316
- package/tools/move.cjs +0 -85
- package/tools/replaceDist.cjs +0 -83
- package/tools/serve.cjs +0 -167
- /package/lib/{pargv.cjs → pargv.js} +0 -0
- /package/tools/{iconGen.cjs → iconGen.js} +0 -0
package/tools/encrypt.js
ADDED
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const path = require('path');
|
|
4
|
+
const fs = require('fs');
|
|
5
|
+
const fsPro = require('fs-extra');
|
|
6
|
+
const is = require('is-type-of');
|
|
7
|
+
const bytenode = require('bytenode');
|
|
8
|
+
const JavaScriptObfuscator = require('javascript-obfuscator');
|
|
9
|
+
const globby = require('globby');
|
|
10
|
+
const chalk = require('chalk');
|
|
11
|
+
const { loadConfig } = require('../lib/utils');
|
|
12
|
+
const { extend } = require('../lib/extend');
|
|
13
|
+
|
|
14
|
+
const EncryptTypes = ['bytecode', 'confusion', 'strict'];
|
|
15
|
+
|
|
16
|
+
class Encrypt {
|
|
17
|
+
constructor(options = {}) {
|
|
18
|
+
// cli args
|
|
19
|
+
const { config, out, target } = options;
|
|
20
|
+
this.basePath = process.cwd();
|
|
21
|
+
this.target = target;
|
|
22
|
+
|
|
23
|
+
const conf = loadConfig(config).encrypt;
|
|
24
|
+
this.config = conf[target];
|
|
25
|
+
const outputFolder = out || this.config.encryptDir;
|
|
26
|
+
this.encryptDir = path.join(this.basePath, outputFolder);
|
|
27
|
+
this.filesExt = this.config.fileExt;
|
|
28
|
+
this.type = this.config.type;
|
|
29
|
+
this.bOpt = this.config.bytecodeOptions;
|
|
30
|
+
this.cOpt = this.config.confusionOptions;
|
|
31
|
+
this.cleanFiles = this.config.cleanFiles;
|
|
32
|
+
this.patterns = this.config.files || null;
|
|
33
|
+
this.specFiles = this.config.specificFiles;
|
|
34
|
+
|
|
35
|
+
this.codefiles = this._initCodeFiles();
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* 初始化需要加密的文件列表
|
|
40
|
+
*/
|
|
41
|
+
_initCodeFiles() {
|
|
42
|
+
if (!this.patterns) return;
|
|
43
|
+
|
|
44
|
+
const files = globby.sync(this.patterns, { cwd: this.basePath });
|
|
45
|
+
return files;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* 加密代码
|
|
50
|
+
*/
|
|
51
|
+
encrypt() {
|
|
52
|
+
if (EncryptTypes.indexOf(this.type) == -1) return;
|
|
53
|
+
if (this.target == 'frontend' && (this.type == 'bytecode' || this.type == 'strict')) return;
|
|
54
|
+
|
|
55
|
+
console.log(chalk.blue('[ee-bin] [encrypt] ') + `start ciphering ${this.target}`);
|
|
56
|
+
for (const file of this.codefiles) {
|
|
57
|
+
const fullpath = path.join(this.encryptDir, file);
|
|
58
|
+
if (!fs.statSync(fullpath).isFile()) continue;
|
|
59
|
+
|
|
60
|
+
// 特殊文件处理
|
|
61
|
+
if (this.specFiles.includes(file)) {
|
|
62
|
+
this.generate(fullpath, 'confusion');
|
|
63
|
+
continue;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
this.generate(fullpath);
|
|
67
|
+
}
|
|
68
|
+
console.log(chalk.blue('[ee-bin] [encrypt] ') + 'end ciphering');
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* 递归
|
|
73
|
+
*/
|
|
74
|
+
loop(dirPath) {
|
|
75
|
+
let files = [];
|
|
76
|
+
if (fs.existsSync(dirPath)) {
|
|
77
|
+
files = fs.readdirSync(dirPath);
|
|
78
|
+
files.forEach((file, index) => {
|
|
79
|
+
let curPath = dirPath + '/' + file;
|
|
80
|
+
if (fs.statSync(curPath).isDirectory()) {
|
|
81
|
+
this.loop(curPath);
|
|
82
|
+
} else {
|
|
83
|
+
const extname = path.extname(curPath);
|
|
84
|
+
if (this.filesExt.indexOf(extname) !== -1) {
|
|
85
|
+
this.generate(curPath);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* 生成文件
|
|
94
|
+
*/
|
|
95
|
+
generate(curPath, type) {
|
|
96
|
+
let encryptType = type ? type : this.type;
|
|
97
|
+
|
|
98
|
+
let tips = chalk.blue('[ee-bin] [encrypt] ') + 'file: ' + chalk.green(`${curPath}`) + ' ' + chalk.cyan(`(${encryptType})`);
|
|
99
|
+
console.log(tips);
|
|
100
|
+
if (encryptType == 'strict') {
|
|
101
|
+
this.generateJSConfuseFile(curPath);
|
|
102
|
+
this.generateBytecodeFile(curPath);
|
|
103
|
+
} else if (encryptType == 'bytecode') {
|
|
104
|
+
this.generateBytecodeFile(curPath);
|
|
105
|
+
} else if (encryptType == 'confusion') {
|
|
106
|
+
this.generateJSConfuseFile(curPath);
|
|
107
|
+
} else {
|
|
108
|
+
// none
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* 使用 javascript-obfuscator 生成压缩/混淆文件
|
|
114
|
+
*/
|
|
115
|
+
generateJSConfuseFile(file) {
|
|
116
|
+
let opt = Object.assign({
|
|
117
|
+
compact: true,
|
|
118
|
+
stringArray: true,
|
|
119
|
+
stringArrayThreshold: 1,
|
|
120
|
+
}, this.cOpt);
|
|
121
|
+
|
|
122
|
+
let code = fs.readFileSync(file, "utf8");
|
|
123
|
+
let result = JavaScriptObfuscator.obfuscate(code, opt);
|
|
124
|
+
fs.writeFileSync(file, result.getObfuscatedCode(), "utf8");
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* 生成字节码文件
|
|
129
|
+
*/
|
|
130
|
+
generateBytecodeFile(curPath) {
|
|
131
|
+
if (path.extname(curPath) !== '.js') {
|
|
132
|
+
return
|
|
133
|
+
}
|
|
134
|
+
//let jscFile = curPath.replace(/.js/g, '.jsc');
|
|
135
|
+
let jscFile = curPath + 'c';
|
|
136
|
+
let opt = Object.assign({
|
|
137
|
+
filename: curPath,
|
|
138
|
+
output: jscFile,
|
|
139
|
+
electron: true
|
|
140
|
+
}, this.bOpt);
|
|
141
|
+
|
|
142
|
+
bytenode.compileFile(opt);
|
|
143
|
+
fsPro.removeSync(curPath);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
function encrypt(options = {}) {
|
|
148
|
+
const electronOpt = extend(true, {
|
|
149
|
+
target: 'electron',
|
|
150
|
+
}, options);
|
|
151
|
+
const electronEpt = new Encrypt(electronOpt);
|
|
152
|
+
electronEpt.encrypt();
|
|
153
|
+
|
|
154
|
+
const frontendOpt = extend(true, {
|
|
155
|
+
target: 'frontend',
|
|
156
|
+
}, options);
|
|
157
|
+
const frontendEpt = new Encrypt(frontendOpt);
|
|
158
|
+
frontendEpt.encrypt();
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
function cleanEncrypt(options = {}) {
|
|
162
|
+
// [todo] 删除前端和主进程代码
|
|
163
|
+
return;
|
|
164
|
+
let files = options.dir !== undefined ? options.dir : ['./public/electron'];
|
|
165
|
+
files = is.string(files) ? [files] : files;
|
|
166
|
+
|
|
167
|
+
files.forEach((file) => {
|
|
168
|
+
const tmpFile = path.join(process.cwd(), file);
|
|
169
|
+
if (fs.existsSync(tmpFile)) {
|
|
170
|
+
fsPro.removeSync(tmpFile);
|
|
171
|
+
console.log(chalk.blue('[ee-bin] [encrypt] ') + 'clean up tmp files: ' + chalk.magenta(`${tmpFile}`));
|
|
172
|
+
}
|
|
173
|
+
})
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
module.exports = {
|
|
177
|
+
encrypt,
|
|
178
|
+
cleanEncrypt,
|
|
179
|
+
};
|
|
@@ -4,7 +4,7 @@ const path = require('path');
|
|
|
4
4
|
const fs = require('fs');
|
|
5
5
|
const crypto = require('crypto')
|
|
6
6
|
const chalk = require('chalk');
|
|
7
|
-
const
|
|
7
|
+
const { loadConfig, rm, getPackage, writeJsonSync } = require('../lib/utils');
|
|
8
8
|
const admZip = require('adm-zip')
|
|
9
9
|
|
|
10
10
|
/**
|
|
@@ -12,15 +12,15 @@ const admZip = require('adm-zip')
|
|
|
12
12
|
* @class
|
|
13
13
|
*/
|
|
14
14
|
|
|
15
|
-
|
|
16
|
-
|
|
15
|
+
class IncrUpdater {
|
|
16
|
+
|
|
17
17
|
/**
|
|
18
18
|
* 执行
|
|
19
19
|
*/
|
|
20
20
|
run(options = {}) {
|
|
21
21
|
console.log('[ee-bin] [updater] Start');
|
|
22
22
|
const { config, asarFile, platform } = options;
|
|
23
|
-
const binCfg =
|
|
23
|
+
const binCfg = loadConfig(config);
|
|
24
24
|
const cfg = binCfg.updater;
|
|
25
25
|
|
|
26
26
|
if (!cfg) {
|
|
@@ -28,20 +28,21 @@ module.exports = {
|
|
|
28
28
|
return;
|
|
29
29
|
}
|
|
30
30
|
|
|
31
|
-
|
|
32
|
-
this.generateFile(cfg, asarFile, platform);
|
|
33
|
-
} else {
|
|
34
|
-
this.generateFileOld(cfg, asarFile);
|
|
35
|
-
}
|
|
31
|
+
this.generateFile(cfg, asarFile, platform);
|
|
36
32
|
|
|
37
33
|
console.log('[ee-bin] [updater] End');
|
|
38
|
-
}
|
|
34
|
+
}
|
|
39
35
|
|
|
40
36
|
/**
|
|
41
37
|
* 生成增量升级文件
|
|
42
38
|
*/
|
|
43
39
|
generateFile(config, asarFile, platform) {
|
|
44
40
|
const cfg = config[platform];
|
|
41
|
+
if (!cfg) {
|
|
42
|
+
console.log(chalk.blue('[ee-bin] [updater] ') + chalk.red(`Error: ${platform} config does not exist`));
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
|
|
45
46
|
let latestVersionInfo = {}
|
|
46
47
|
const homeDir = process.cwd();
|
|
47
48
|
console.log(chalk.blue('[ee-bin] [updater] ') + chalk.green(`${platform} config:`), cfg);
|
|
@@ -66,7 +67,7 @@ module.exports = {
|
|
|
66
67
|
return;
|
|
67
68
|
}
|
|
68
69
|
|
|
69
|
-
const packageJson =
|
|
70
|
+
const packageJson = getPackage();
|
|
70
71
|
const version = packageJson.version;
|
|
71
72
|
let platformForFilename = platform;
|
|
72
73
|
if (platform.indexOf("_") !== -1) {
|
|
@@ -79,7 +80,7 @@ module.exports = {
|
|
|
79
80
|
zipName = path.basename(cfg.output.zip, '.zip') + `-${platformForFilename}-${version}.zip`;
|
|
80
81
|
const asarZipPath = path.join(homeDir, cfg.output.directory, zipName);
|
|
81
82
|
if (fs.existsSync(asarZipPath)) {
|
|
82
|
-
|
|
83
|
+
rm(asarZipPath);
|
|
83
84
|
}
|
|
84
85
|
const zip = new admZip();
|
|
85
86
|
// 添加 asar 文件
|
|
@@ -114,107 +115,17 @@ module.exports = {
|
|
|
114
115
|
const jsonName = path.basename(cfg.output.file, '.json') + `-${platformForFilename}.json`;
|
|
115
116
|
latestVersionInfo = item;
|
|
116
117
|
const updaterJsonFilePath = path.join(homeDir, cfg.output.directory, jsonName);
|
|
117
|
-
|
|
118
|
+
writeJsonSync(updaterJsonFilePath, latestVersionInfo);
|
|
118
119
|
|
|
119
120
|
// 删除缓存文件,防止生成的 zip 是旧版本
|
|
120
121
|
if (cfg.cleanCache) {
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
122
|
+
rm(path.join(homeDir, cfg.output.directory, 'mac'));
|
|
123
|
+
rm(path.join(homeDir, cfg.output.directory, 'mac-arm64'));
|
|
124
|
+
rm(path.join(homeDir, cfg.output.directory, 'win-unpacked'));
|
|
125
|
+
rm(path.join(homeDir, cfg.output.directory, 'win-ia32-unpacked'));
|
|
126
|
+
rm(path.join(homeDir, cfg.output.directory, 'linux-unpacked'));
|
|
126
127
|
}
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
/**
|
|
130
|
-
* 将废弃
|
|
131
|
-
*/
|
|
132
|
-
generateFileOld(cfg, asarFile) {
|
|
133
|
-
var latestVersionInfo = {}
|
|
134
|
-
const homeDir = process.cwd();
|
|
135
|
-
console.log(chalk.blue('[ee-bin] [updater] ') + chalk.green('config:'), cfg);
|
|
136
|
-
|
|
137
|
-
let asarFilePath = "";
|
|
138
|
-
if (asarFile) {
|
|
139
|
-
asarFilePath = path.normalize(path.join(homeDir, asarFile));
|
|
140
|
-
} else if (Array.isArray(cfg.asarFile)) {
|
|
141
|
-
// 检查文件列表,如果存在就跳出
|
|
142
|
-
for (const filep of cfg.asarFile) {
|
|
143
|
-
asarFilePath = path.normalize(path.join(homeDir, filep));
|
|
144
|
-
if (fs.existsSync(asarFilePath)) {
|
|
145
|
-
break;
|
|
146
|
-
}
|
|
147
|
-
}
|
|
148
|
-
} else {
|
|
149
|
-
asarFilePath = path.normalize(path.join(homeDir, cfg.asarFile));
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
if (!fs.existsSync(asarFilePath)) {
|
|
153
|
-
console.log(chalk.blue('[ee-bin] [updater] ') + chalk.red(`Error: ${asarFilePath} does not exist`));
|
|
154
|
-
return;
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
const packageJson = Utils.getPackage();
|
|
158
|
-
const version = packageJson.version;
|
|
159
|
-
const platformForFilename = Utils.getPlatform("-");
|
|
160
|
-
const platformForKey = Utils.getPlatform("_");
|
|
161
|
-
|
|
162
|
-
// 生成 zip
|
|
163
|
-
let zipName = "";
|
|
164
|
-
if (cfg.output.noPlatform === true) {
|
|
165
|
-
zipName = path.basename(cfg.output.zip, '.zip') + `-${version}.zip`;
|
|
166
|
-
} else {
|
|
167
|
-
zipName = path.basename(cfg.output.zip, '.zip') + `-${platformForFilename}-${version}.zip`;
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
const asarZipPath = path.join(homeDir, cfg.output.directory, zipName);
|
|
171
|
-
if (fs.existsSync(asarZipPath) && cfg.cleanCache) {
|
|
172
|
-
Utils.rm(asarZipPath);
|
|
173
|
-
}
|
|
174
|
-
const zip = new admZip();
|
|
175
|
-
zip.addLocalFile(asarFilePath);
|
|
176
|
-
zip.writeZip(asarZipPath, (err) => {
|
|
177
|
-
if (err) {
|
|
178
|
-
console.log(chalk.blue('[ee-bin] [updater] create zip ') + chalk.red(`Error: ${err}`));
|
|
179
|
-
}
|
|
180
|
-
});
|
|
181
|
-
|
|
182
|
-
const sha1 = this.generateSha1(asarFilePath);
|
|
183
|
-
const date = this._getFormattedDate();
|
|
184
|
-
const fileStat = fs.statSync(asarFilePath);
|
|
185
|
-
|
|
186
|
-
const item = {
|
|
187
|
-
version: version,
|
|
188
|
-
file: zipName,
|
|
189
|
-
size: fileStat.size,
|
|
190
|
-
sha1: sha1,
|
|
191
|
-
releaseDate: date,
|
|
192
|
-
};
|
|
193
|
-
let jsonName = "";
|
|
194
|
-
if (cfg.output.noPlatform === true) {
|
|
195
|
-
jsonName = cfg.output.file;
|
|
196
|
-
latestVersionInfo = item;
|
|
197
|
-
} else {
|
|
198
|
-
// 生成与系统有关的文件
|
|
199
|
-
jsonName = path.basename(cfg.output.file, '.json') + `-${platformForFilename}.json`;
|
|
200
|
-
if (platformForKey !== "") {
|
|
201
|
-
latestVersionInfo[platformForKey] = item;
|
|
202
|
-
} else {
|
|
203
|
-
console.log(chalk.blue('[ee-bin] [updater] ') + chalk.red(`Error: ${platformForFilename} is not supported`));
|
|
204
|
-
}
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
const updaterJsonFilePath = path.join(homeDir, cfg.output.directory, jsonName);
|
|
208
|
-
Utils.writeJsonSync(updaterJsonFilePath, latestVersionInfo);
|
|
209
|
-
|
|
210
|
-
// 删除缓存文件,防止生成的 zip 是旧版本
|
|
211
|
-
if (cfg.cleanCache) {
|
|
212
|
-
Utils.rm(path.join(homeDir, cfg.output.directory, 'mac'));
|
|
213
|
-
Utils.rm(path.join(homeDir, cfg.output.directory, 'mac-arm64'));
|
|
214
|
-
Utils.rm(path.join(homeDir, cfg.output.directory, 'win-unpacked'));
|
|
215
|
-
Utils.rm(path.join(homeDir, cfg.output.directory, 'linux-unpacked'));
|
|
216
|
-
}
|
|
217
|
-
},
|
|
128
|
+
}
|
|
218
129
|
|
|
219
130
|
generateSha1(filepath = "") {
|
|
220
131
|
let sha1 = '';
|
|
@@ -239,7 +150,7 @@ module.exports = {
|
|
|
239
150
|
console.log(chalk.blue('[ee-bin] [updater] ') + chalk.red(`Error: ${error}`));
|
|
240
151
|
}
|
|
241
152
|
return sha1;
|
|
242
|
-
}
|
|
153
|
+
}
|
|
243
154
|
|
|
244
155
|
_getFormattedDate() {
|
|
245
156
|
const date = new Date(); // 获取当前日期
|
|
@@ -248,5 +159,10 @@ module.exports = {
|
|
|
248
159
|
const day = date.getDate().toString().padStart(2, '0'); // 获取日
|
|
249
160
|
|
|
250
161
|
return `${year}-${month}-${day}`;
|
|
251
|
-
}
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
module.exports = {
|
|
166
|
+
IncrUpdater,
|
|
167
|
+
incrUpdater: new IncrUpdater()
|
|
252
168
|
}
|
package/tools/move.js
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const path = require('path');
|
|
4
|
+
const fs = require('fs');
|
|
5
|
+
const fsPro = require('fs-extra');
|
|
6
|
+
const chalk = require('chalk');
|
|
7
|
+
const { loadConfig, rm } = require('../lib/utils');
|
|
8
|
+
|
|
9
|
+
const homeDir = process.cwd();
|
|
10
|
+
|
|
11
|
+
// 移动资源
|
|
12
|
+
function move(options = {}) {
|
|
13
|
+
console.log('[ee-bin] [move] Start moving resources');
|
|
14
|
+
const { config, flag } = options;
|
|
15
|
+
const binCfg = loadConfig(config);
|
|
16
|
+
const moveConfig = binCfg.move;
|
|
17
|
+
|
|
18
|
+
let flags;
|
|
19
|
+
const flagString = flag.trim();
|
|
20
|
+
if (flagString.indexOf(',') !== -1) {
|
|
21
|
+
flags = flagString.split(',');
|
|
22
|
+
} else {
|
|
23
|
+
flags = [flagString];
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
for (let i = 0; i < flags.length; i++) {
|
|
27
|
+
let f = flags[i];
|
|
28
|
+
let cfg = moveConfig[f];
|
|
29
|
+
|
|
30
|
+
if (!cfg) {
|
|
31
|
+
console.log(chalk.blue('[ee-bin] [move] ') + chalk.red(`Error: ${f} config does not exist` ));
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const { src, dest, dist, target } = cfg;
|
|
36
|
+
const source = dist ? dist : src;
|
|
37
|
+
const destination = target ? target : dest;
|
|
38
|
+
|
|
39
|
+
console.log(chalk.blue('[ee-bin] [move] ') + chalk.green(`Move flag: ${f}`));
|
|
40
|
+
console.log(chalk.blue('[ee-bin] [move] ') + chalk.green('config:'), cfg);
|
|
41
|
+
|
|
42
|
+
const srcResource = path.join(homeDir, source);
|
|
43
|
+
if (!fs.existsSync(srcResource)) {
|
|
44
|
+
const errorTips = chalk.bgRed('Error') + ` ${source} resource does not exist !`;
|
|
45
|
+
console.error(errorTips);
|
|
46
|
+
return
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// clear the historical resource and copy it to the ee resource directory
|
|
50
|
+
const destResource = path.join(homeDir, destination);
|
|
51
|
+
if (fs.statSync(srcResource).isDirectory() && !fs.existsSync(destResource)) {
|
|
52
|
+
fs.mkdirSync(destResource, {recursive: true, mode: 0o777});
|
|
53
|
+
} else {
|
|
54
|
+
rm(destResource);
|
|
55
|
+
console.log('[ee-bin] [move] Clear history resources:', destResource);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
fsPro.copySync(srcResource, destResource);
|
|
59
|
+
|
|
60
|
+
// [todo] go project, special treatment of package.json, reserved only necessary
|
|
61
|
+
console.log(`[ee-bin] [move] Copy ${srcResource} to ${destResource}`);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
console.log('[ee-bin] [move] End');
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
module.exports = {
|
|
68
|
+
move
|
|
69
|
+
}
|
package/tools/serve.js
ADDED
|
@@ -0,0 +1,240 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const debug = require('debug')('ee-bin:serve');
|
|
4
|
+
const path = require('path');
|
|
5
|
+
const fsPro = require('fs-extra');
|
|
6
|
+
const { loadConfig } = require('../lib/utils');
|
|
7
|
+
const is = require('is-type-of');
|
|
8
|
+
const chalk = require('chalk');
|
|
9
|
+
const crossSpawn = require('cross-spawn');
|
|
10
|
+
const { buildSync } = require('esbuild');
|
|
11
|
+
const chokidar = require('chokidar');
|
|
12
|
+
|
|
13
|
+
class ServeProcess {
|
|
14
|
+
|
|
15
|
+
constructor() {
|
|
16
|
+
process.env.NODE_ENV = 'prod'; // dev / prod
|
|
17
|
+
this.execProcess = {};
|
|
18
|
+
this.electronDir = './electron';
|
|
19
|
+
this.defaultBundleDir = './public/electron';
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* 启动前端、主进程服务
|
|
24
|
+
*/
|
|
25
|
+
dev(options = {}) {
|
|
26
|
+
// 设置一个环境变量
|
|
27
|
+
process.env.NODE_ENV = 'dev';
|
|
28
|
+
const { config, serve } = options;
|
|
29
|
+
const binCfg = loadConfig(config);
|
|
30
|
+
const binCmd = 'dev';
|
|
31
|
+
const binCmdConfig = binCfg[binCmd];
|
|
32
|
+
|
|
33
|
+
let command = serve;
|
|
34
|
+
if (!command) {
|
|
35
|
+
command = Object.keys(binCmdConfig).join();
|
|
36
|
+
}
|
|
37
|
+
const opt = {
|
|
38
|
+
binCmd,
|
|
39
|
+
binCmdConfig,
|
|
40
|
+
command,
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// build electron main code
|
|
44
|
+
const cmds = this._formatCmds(command);
|
|
45
|
+
if (cmds.indexOf("electron") !== -1) {
|
|
46
|
+
// watche electron main code
|
|
47
|
+
const electronConfig = binCmdConfig.electron;
|
|
48
|
+
if (electronConfig.watch) {
|
|
49
|
+
const cmd = 'electron';
|
|
50
|
+
const watcher = chokidar.watch([this.electronDir], {
|
|
51
|
+
persistent: true
|
|
52
|
+
});
|
|
53
|
+
watcher.on('change', async (f) => {
|
|
54
|
+
console.log(chalk.blue('[ee-bin] [dev] ') + `File ${f} has been changed`);
|
|
55
|
+
console.log(chalk.blue('[ee-bin] [dev] ') + `Restart ${cmd}`);
|
|
56
|
+
|
|
57
|
+
// rebuild code
|
|
58
|
+
this.bundle(binCfg.build.electron);
|
|
59
|
+
let subPorcess = this.execProcess[cmd];
|
|
60
|
+
subPorcess.kill();
|
|
61
|
+
delete this.execProcess[cmd];
|
|
62
|
+
|
|
63
|
+
// restart electron command
|
|
64
|
+
let onlyElectronOpt = {
|
|
65
|
+
binCmd,
|
|
66
|
+
binCmdConfig,
|
|
67
|
+
command: cmd,
|
|
68
|
+
}
|
|
69
|
+
this.multiExec(onlyElectronOpt);
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// When starting for the first time, build the code for the electron directory
|
|
74
|
+
this.bundle(binCfg.build.electron);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
this.multiExec(opt);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* 启动主进程服务
|
|
82
|
+
*/
|
|
83
|
+
start(options = {}) {
|
|
84
|
+
const { config } = options;
|
|
85
|
+
const binCfg = loadConfig(config);
|
|
86
|
+
const binCmd = 'start';
|
|
87
|
+
const binCmdConfig = {
|
|
88
|
+
start: binCfg[binCmd]
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
const opt = {
|
|
92
|
+
binCmd,
|
|
93
|
+
binCmdConfig,
|
|
94
|
+
command: binCmd,
|
|
95
|
+
}
|
|
96
|
+
this.multiExec(opt);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
sleep(ms) {
|
|
100
|
+
return new Promise(resolve => setTimeout(resolve, ms));
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* 构建
|
|
105
|
+
*/
|
|
106
|
+
build(options = {}) {
|
|
107
|
+
const { config, cmds, env } = options;
|
|
108
|
+
process.env.NODE_ENV = env;
|
|
109
|
+
const binCfg = loadConfig(config);
|
|
110
|
+
const binCmd = 'build';
|
|
111
|
+
const binCmdConfig = binCfg[binCmd];
|
|
112
|
+
|
|
113
|
+
if (!cmds || cmds == "") {
|
|
114
|
+
const tip = chalk.bgYellow('Warning') + ' Please modify the ' + chalk.blue('build') + ' property in the bin file';
|
|
115
|
+
console.log(tip);
|
|
116
|
+
return
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
if (cmds.indexOf("electron") !== -1) {
|
|
120
|
+
this.bundle(binCmdConfig.electron);
|
|
121
|
+
return;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
const opt = {
|
|
125
|
+
binCmd,
|
|
126
|
+
binCmdConfig,
|
|
127
|
+
command: cmds,
|
|
128
|
+
}
|
|
129
|
+
this.multiExec(opt);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* 执行自定义命令
|
|
134
|
+
*/
|
|
135
|
+
exec(options = {}) {
|
|
136
|
+
const { config, cmds } = options;
|
|
137
|
+
const binCfg = loadConfig(config);
|
|
138
|
+
const binCmd = 'exec';
|
|
139
|
+
const binCmdConfig = binCfg[binCmd];
|
|
140
|
+
|
|
141
|
+
const opt = {
|
|
142
|
+
binCmd,
|
|
143
|
+
binCmdConfig,
|
|
144
|
+
command: cmds,
|
|
145
|
+
}
|
|
146
|
+
this.multiExec(opt);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* 支持多个命令
|
|
151
|
+
*/
|
|
152
|
+
multiExec(opt = {}) {
|
|
153
|
+
//console.log('multiExec opt:', opt)
|
|
154
|
+
const { binCmd, binCmdConfig, command } = opt;
|
|
155
|
+
const cmds = this._formatCmds(command);
|
|
156
|
+
|
|
157
|
+
for (let i = 0; i < cmds.length; i++) {
|
|
158
|
+
let cmd = cmds[i];
|
|
159
|
+
const cfg = binCmdConfig[cmd];
|
|
160
|
+
|
|
161
|
+
if (!cfg) {
|
|
162
|
+
console.log(chalk.blue(`[ee-bin] [${binCmd}] `) + chalk.red(`Error: [${binCmd} ${cmd}] config does not exist` ));
|
|
163
|
+
continue;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
// frontend 如果是 file:// 协议,则不启动
|
|
167
|
+
if (binCmd == 'dev' && cmd == 'frontend' && cfg.protocol == 'file://') {
|
|
168
|
+
continue;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
console.log(chalk.blue(`[ee-bin] [${binCmd}] `) + "Run " + chalk.green(`[${binCmd} ${cmd}]` + " command"));
|
|
172
|
+
console.log(chalk.blue(`[ee-bin] [${binCmd}] `) + chalk.green('config:'), JSON.stringify(cfg));
|
|
173
|
+
|
|
174
|
+
const execDir = path.join(process.cwd(), cfg.directory);
|
|
175
|
+
const execArgs = is.string(cfg.args) ? [cfg.args] : cfg.args;
|
|
176
|
+
const stdio = cfg.stdio ? cfg.stdio: 'inherit';
|
|
177
|
+
|
|
178
|
+
const handler = cfg.sync ? crossSpawn.sync : crossSpawn;
|
|
179
|
+
|
|
180
|
+
this.execProcess[cmd] = handler(
|
|
181
|
+
cfg.cmd,
|
|
182
|
+
execArgs,
|
|
183
|
+
{ stdio: stdio, cwd: execDir, maxBuffer: 1024 * 1024 * 1024 },
|
|
184
|
+
);
|
|
185
|
+
console.log(chalk.blue(`[ee-bin] [${binCmd}] `) + 'The ' + chalk.green(`[${binCmd} ${cmd}]`) + ` command is ${cfg.sync ? 'run completed' : 'running'}`);
|
|
186
|
+
|
|
187
|
+
if(!cfg.sync) {
|
|
188
|
+
this.execProcess[cmd].on('exit', () => {
|
|
189
|
+
if (cmd == 'electron') {
|
|
190
|
+
console.log(chalk.blue(`[ee-bin] [${binCmd}] `) + chalk.green('Press "CTRL+C" to exit'));
|
|
191
|
+
return
|
|
192
|
+
}
|
|
193
|
+
console.log(chalk.blue(`[ee-bin] [${binCmd}] `) + 'The ' + chalk.green(`[${binCmd} ${cmd}]`) + ' command has been executed and exited');
|
|
194
|
+
});
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
// esbuild
|
|
200
|
+
bundle(bundleConfig) {
|
|
201
|
+
const { bundleType } = bundleConfig;
|
|
202
|
+
if (bundleType == 'copy') {
|
|
203
|
+
const srcResource = path.join(process.cwd(), this.electronDir);
|
|
204
|
+
const destResource = path.join(process.cwd(), this.defaultBundleDir);
|
|
205
|
+
fsPro.removeSync(destResource);
|
|
206
|
+
fsPro.copySync(srcResource, destResource);
|
|
207
|
+
} else {
|
|
208
|
+
const esbuildOptions = bundleConfig[bundleConfig.type];
|
|
209
|
+
// todo 不压缩
|
|
210
|
+
// if (this.isDev()) {
|
|
211
|
+
// esbuildOptions.minify = false;
|
|
212
|
+
// }
|
|
213
|
+
debug('esbuild options:%O', esbuildOptions);
|
|
214
|
+
buildSync(esbuildOptions);
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
// format commands
|
|
219
|
+
_formatCmds(command) {
|
|
220
|
+
let cmds;
|
|
221
|
+
const cmdString = command.trim();
|
|
222
|
+
if (cmdString.indexOf(',') !== -1) {
|
|
223
|
+
cmds = cmdString.split(',');
|
|
224
|
+
} else {
|
|
225
|
+
cmds = [cmdString];
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
return cmds;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
// env
|
|
232
|
+
isDev() {
|
|
233
|
+
return process.env.NODE_ENV === 'dev';
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
module.exports = {
|
|
238
|
+
ServeProcess,
|
|
239
|
+
serveProcess: new ServeProcess()
|
|
240
|
+
}
|