ee-bin 2.0.0-beta.2 → 4.0.0-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.
@@ -0,0 +1,112 @@
1
+ /**
2
+ * ee-bin 配置
3
+ * 仅适用于开发环境
4
+ */
5
+ module.exports = {
6
+ /**
7
+ * development serve ("frontend" "electron" )
8
+ * ee-bin dev
9
+ */
10
+ dev: {
11
+ frontend: {
12
+ directory: './frontend',
13
+ cmd: 'npm',
14
+ args: ['run', 'dev'],
15
+ protocol: 'http://',
16
+ hostname: 'localhost',
17
+ port: 8080,
18
+ indexPath: 'index.html',
19
+ },
20
+ electron: {
21
+ directory: './',
22
+ cmd: 'electron',
23
+ args: ['.', '--env=local'],
24
+ loadingPage: '/public/html/loading.html',
25
+ },
26
+ },
27
+
28
+ /**
29
+ * 构建
30
+ * ee-bin build
31
+ */
32
+ build: {
33
+ frontend: {
34
+ directory: './frontend',
35
+ cmd: 'npm',
36
+ args: ['run', 'build'],
37
+ },
38
+ electron: {
39
+ bundler: 'esbuild',
40
+ language: 'javascript',
41
+ javascript: {
42
+ entryPoints: ['./electron/**/*.js'],
43
+ platform: 'node',
44
+ bundle: false,
45
+ minify: false,
46
+ outdir: 'public/electron',
47
+ packages: 'external',
48
+ sourcemap:false,
49
+ sourcesContent: false
50
+ },
51
+ typescript: {
52
+ entryPoints: ['./electron/**/*.ts'],
53
+ tsconfig: './tsconfig.json',
54
+ platform: 'node',
55
+ format: 'cjs',
56
+ bundle: false,
57
+ minify: false,
58
+ outdir: 'public/electron',
59
+ packages: 'external',
60
+ sourcemap:false,
61
+ sourcesContent: false
62
+ }
63
+ }
64
+ },
65
+
66
+ /**
67
+ * 移动资源
68
+ * ee-bin move
69
+ */
70
+ move: {
71
+ frontend_dist: {
72
+ src: './frontend/dist',
73
+ dest: './public/dist'
74
+ }
75
+ },
76
+
77
+ /**
78
+ * 预发布模式(prod)
79
+ * ee-bin start
80
+ */
81
+ start: {
82
+ directory: './',
83
+ cmd: 'electron',
84
+ args: ['.', '--env=prod']
85
+ },
86
+
87
+ /**
88
+ * 加密
89
+ */
90
+ encrypt: {
91
+ type: 'none',
92
+ files: [
93
+ './public/electron/**/*.(js|json)',
94
+ ],
95
+ fileExt: ['.js'],
96
+ cleanFiles: ['./public/electron'],
97
+ specificFiles: ['./public/electron/preload/bridge.js'],
98
+ encryptDir: './',
99
+ confusionOptions: {
100
+ compact: true,
101
+ stringArray: true,
102
+ stringArrayEncoding: ['none'],
103
+ deadCodeInjection: false,
104
+ }
105
+ },
106
+
107
+ /**
108
+ * 执行自定义命令
109
+ * ee-bin exec
110
+ */
111
+ exec: {},
112
+ };
package/index.js ADDED
@@ -0,0 +1,117 @@
1
+ #!/usr/bin/env node
2
+
3
+ const { program } = require('commander');
4
+ const { move } = require('./tools/move');
5
+ const { encrypt, cleanEncrypt } = require('./tools/encrypt');
6
+ const { serveProcess } = require('./tools/serve');
7
+ const { incrUpdater } = require('./tools/incrUpdater');
8
+
9
+ /**
10
+ * dev
11
+ */
12
+ program
13
+ .command('dev')
14
+ .description('create frontend-serve and electron-serve')
15
+ .option('--config <folder>', 'config file')
16
+ .option('--serve <mode>', 'serve mode')
17
+ .action(function() {
18
+ serveProcess.dev(this.opts());
19
+ });
20
+
21
+ /**
22
+ * build
23
+ */
24
+ program
25
+ .command('build')
26
+ .description('building multiple resources')
27
+ .option('--config <folder>', 'config file')
28
+ .option('--cmds <flag>', 'custom commands')
29
+ .action(function() {
30
+ serveProcess.build(this.opts());
31
+ });
32
+
33
+ /**
34
+ * start
35
+ */
36
+ program
37
+ .command('start')
38
+ .description('preview effect')
39
+ .option('--config <folder>', 'config file')
40
+ .action(function() {
41
+ serveProcess.start(this.opts());
42
+ });
43
+
44
+ /**
45
+ * exec
46
+ */
47
+ program
48
+ .command('exec')
49
+ .description('create frontend-serve and electron-serve')
50
+ .option('--config <folder>', 'config file')
51
+ .option('--cmds <flag>', 'custom commands')
52
+ .action(function() {
53
+ serveProcess.exec(this.opts());
54
+ });
55
+
56
+ /**
57
+ * move - Moves resources
58
+ */
59
+ program
60
+ .command('move')
61
+ .description('Move multip resources')
62
+ .option('--config <folder>', 'config file')
63
+ .option('--flag <flag>', 'Custom flag')
64
+ .action(function() {
65
+ move(this.opts());
66
+ });
67
+
68
+ /**
69
+ * encrypt - Code encryption
70
+ */
71
+ program
72
+ .command('encrypt')
73
+ .description('Code encryption')
74
+ .option('--config <folder>', 'config file')
75
+ .option('--out <folder>', 'output directory')
76
+ .action(function() {
77
+ encrypt(this.opts());
78
+ });
79
+
80
+ /**
81
+ * clean - Clear the encrypted code
82
+ */
83
+ program
84
+ .command('clean')
85
+ .description('Clear the encrypted code')
86
+ .option('-d, --dir <folder>', 'clean directory')
87
+ .action(function() {
88
+ cleanEncrypt(this.opts());
89
+ });
90
+
91
+ /**
92
+ * icon
93
+ */
94
+ program
95
+ .command('icon')
96
+ .description('Generate logo')
97
+ .option('-i, --input <file>', 'image file default /public/images/logo.png')
98
+ .option('-o, --output <folder>', 'output directory default /build/icons/')
99
+ .action(function() {
100
+ const iconGen = require('./tools/iconGen');
101
+ iconGen.run();
102
+ });
103
+
104
+ /**
105
+ * updater
106
+ */
107
+ program
108
+ .command('updater')
109
+ .description('updater commands')
110
+ .option('--config <folder>', 'config file')
111
+ .option('--asar-file <file>', 'asar file path')
112
+ .option('--platform <flag>', 'platform')
113
+ .action(function() {
114
+ incrUpdater.run(this.opts());
115
+ });
116
+
117
+ program.parse();
package/lib/extend.js ADDED
@@ -0,0 +1,78 @@
1
+ 'use strict';
2
+
3
+ const hasOwn = Object.prototype.hasOwnProperty;
4
+ const toStr = Object.prototype.toString;
5
+
6
+ function isPlainObject(obj) {
7
+ if (!obj || toStr.call(obj) !== '[object Object]') {
8
+ return false;
9
+ }
10
+
11
+ var hasOwnConstructor = hasOwn.call(obj, 'constructor');
12
+ var hasIsPrototypeOf = obj.constructor && obj.constructor.prototype && hasOwn.call(obj.constructor.prototype, 'isPrototypeOf');
13
+ // Not own constructor property must be Object
14
+ if (obj.constructor && !hasOwnConstructor && !hasIsPrototypeOf) {
15
+ return false;
16
+ }
17
+
18
+ // Own properties are enumerated firstly, so to speed up,
19
+ // if last one is own, then all properties are own.
20
+ var key;
21
+ for (key in obj) { /**/ }
22
+
23
+ return typeof key === 'undefined' || hasOwn.call(obj, key);
24
+ };
25
+
26
+ function extend() {
27
+ var options, name, src, copy, clone;
28
+ var target = arguments[0];
29
+ var i = 1;
30
+ var length = arguments.length;
31
+ var deep = false;
32
+
33
+ // Handle a deep copy situation
34
+ if (typeof target === 'boolean') {
35
+ deep = target;
36
+ target = arguments[1] || {};
37
+ // skip the boolean and the target
38
+ i = 2;
39
+ } else if ((typeof target !== 'object' && typeof target !== 'function') || target == null) {
40
+ target = {};
41
+ }
42
+
43
+ for (; i < length; ++i) {
44
+ options = arguments[i];
45
+ // Only deal with non-null/undefined values
46
+ if (options == null) continue;
47
+
48
+ // Extend the base object
49
+ for (name in options) {
50
+ if (name === '__proto__') continue;
51
+
52
+ src = target[name];
53
+ copy = options[name];
54
+
55
+ // Prevent never-ending loop
56
+ if (target === copy) continue;
57
+
58
+ // Recurse if we're merging plain objects
59
+ if (deep && copy && isPlainObject(copy)) {
60
+ clone = src && isPlainObject(src) ? src : {};
61
+ // Never move original objects, clone them
62
+ target[name] = extend(deep, clone, copy);
63
+
64
+ // Don't bring in undefined values
65
+ } else if (typeof copy !== 'undefined') {
66
+ target[name] = copy;
67
+ }
68
+ }
69
+ }
70
+
71
+ // Return the modified object
72
+ return target;
73
+ };
74
+
75
+ module.exports = {
76
+ extend,
77
+ isPlainObject,
78
+ };
@@ -1,5 +1,6 @@
1
1
  'use strict';
2
2
 
3
+ const debug = require('debug')('ee-bin:lib:utils');
3
4
  const path = require('path');
4
5
  const fs = require('fs');
5
6
  const chalk = require('chalk');
@@ -7,22 +8,26 @@ const is = require('is-type-of');
7
8
  const { loadTsConfig } = require('config-file-ts');
8
9
  const JsonLib = require('json5');
9
10
  const mkdirp = require('mkdirp');
11
+ const OS = require('os');
12
+ const defaultConfig = require('../config/bin_default');
13
+ const { extend } = require('./extend');
10
14
 
11
15
  const _basePath = process.cwd();
16
+ const userBin = './cmd/bin.js';
12
17
 
13
- function checkConfig(prop) {
14
- const filepath = path.join(_basePath, prop);
15
- if (fs.existsSync(filepath)) {
16
- return true;
17
- }
18
+ function loadConfig(binFile) {
19
+ const binPath = binFile ? binFile : userBin;
20
+ const userConfig = loadFile(binPath);
21
+ const result = extend(true, defaultConfig, userConfig);
22
+ debug('[loadConfig] bin:%j', result)
18
23
 
19
- return false;
20
- }
24
+ return result
25
+ };
21
26
 
22
- function loadConfig(prop) {
23
- const configFile = path.join(_basePath, prop);
27
+ function loadFile(filepath) {
28
+ const configFile = path.join(_basePath, filepath);
24
29
  if (!fs.existsSync(configFile)) {
25
- const errorTips = 'config file ' + chalk.blue(`${configFile}`) + ' does not exist !';
30
+ const errorTips = 'file ' + chalk.blue(`${configFile}`) + ' does not exist !';
26
31
  throw new Error(errorTips)
27
32
  }
28
33
 
@@ -45,24 +50,6 @@ function loadConfig(prop) {
45
50
  return result || {}
46
51
  };
47
52
 
48
- function loadEncryptConfig() {
49
- const configFile = './electron/config/encrypt.js';
50
- const filepath = path.join(_basePath, configFile);
51
- if (!fs.existsSync(filepath)) {
52
- const errorTips = 'config file ' + chalk.blue(`${filepath}`) + ' does not exist !';
53
- throw new Error(errorTips)
54
- }
55
- const obj = require(filepath);
56
- if (!obj) return obj;
57
-
58
- let ret = obj;
59
- if (is.function(obj) && !is.class(obj)) {
60
- ret = obj();
61
- }
62
-
63
- return ret || {};
64
- };
65
-
66
53
  /**
67
54
  * get electron program
68
55
  */
@@ -108,10 +95,30 @@ function compareVersion(v1, v2) {
108
95
  return 0
109
96
  }
110
97
 
111
- function isWindows(prop) {
98
+ function isWindows() {
112
99
  return process.platform === 'win32'
113
100
  }
114
101
 
102
+ function isOSX() {
103
+ return process.platform === 'darwin'
104
+ }
105
+
106
+ function isMacOS() {
107
+ return isOSX()
108
+ }
109
+
110
+ function isLinux() {
111
+ return process.platform === 'linux'
112
+ }
113
+
114
+ function isx86() {
115
+ return process.arch === 'ia32'
116
+ }
117
+
118
+ function isx64() {
119
+ return process.arch === 'x64'
120
+ }
121
+
115
122
  /**
116
123
  * Delete a file or folder
117
124
  */
@@ -133,9 +140,7 @@ function rm(name) {
133
140
  * 获取项目根目录package.json
134
141
  */
135
142
  function getPackage () {
136
- const homeDir = process.cwd();
137
- const content = readJsonSync(path.join(homeDir, 'package.json'));
138
-
143
+ const content = readJsonSync(path.join(_basePath, 'package.json'));
139
144
  return content;
140
145
  }
141
146
 
@@ -160,13 +165,43 @@ function writeJsonSync (filepath, str, options) {
160
165
  fs.writeFileSync(filepath, str);
161
166
  };
162
167
 
168
+ function getPlatform(delimiter = "_", isDiffArch = false) {
169
+ let os = "";
170
+ if (isWindows()) {
171
+ os = "windows";
172
+ if (isDiffArch) {
173
+ const arch = isx64() ? "64" : "32";
174
+ os += delimiter + arch;
175
+ }
176
+ } else if (isMacOS()) {
177
+ let isAppleSilicon = false;
178
+ const cpus = OS.cpus();
179
+ for (let cpu of cpus) {
180
+ if (cpu.model.includes('Apple')) {
181
+ isAppleSilicon = true;
182
+ break;
183
+ }
184
+ }
185
+ const core = isAppleSilicon? "apple" : "intel";
186
+ os = "macos" + delimiter + core;
187
+ } else if (isLinux()) {
188
+ os = "linux";
189
+ }
190
+
191
+ return os;
192
+ }
193
+
163
194
  module.exports = {
164
195
  loadConfig,
165
- checkConfig,
166
- loadEncryptConfig,
167
196
  getElectronProgram,
168
197
  compareVersion,
169
198
  isWindows,
199
+ isOSX,
200
+ isMacOS,
201
+ isLinux,
202
+ isx86,
203
+ isx64,
204
+ getPlatform,
170
205
  rm,
171
206
  getPackage,
172
207
  readJsonSync,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ee-bin",
3
- "version": "2.0.0-beta.2",
3
+ "version": "4.0.0-beta.1",
4
4
  "description": "ee bin",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -9,20 +9,22 @@
9
9
  "author": "",
10
10
  "license": "ISC",
11
11
  "bin": {
12
- "ee-bin": "index.cjs"
12
+ "ee-bin": "index.js"
13
13
  },
14
14
  "dependencies": {
15
+ "adm-zip": "^0.4.11",
15
16
  "bytenode": "^1.3.6",
16
17
  "chalk": "^4.1.2",
17
18
  "commander": "^11.0.0",
18
19
  "config-file-ts": "^0.2.8-rc1",
19
20
  "cross-spawn": "^7.0.3",
21
+ "debug": "^4.4.0",
22
+ "esbuild": "0.24.2",
20
23
  "fs-extra": "^10.0.0",
21
24
  "globby": "^10.0.0",
22
25
  "is-type-of": "^1.2.1",
23
26
  "javascript-obfuscator": "^4.0.2",
24
- "mkdirp": "^2.1.3",
25
- "adm-zip": "^0.4.11",
26
- "json5": "^2.2.3"
27
+ "json5": "^2.2.3",
28
+ "mkdirp": "^2.1.3"
27
29
  }
28
30
  }
@@ -0,0 +1,197 @@
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
+
13
+ const EncryptTypes = ['bytecode', 'confusion', 'strict'];
14
+
15
+ class Encrypt {
16
+ constructor(options = {}) {
17
+ // cli args
18
+ const { config, out } = options;
19
+ this.basePath = process.cwd();
20
+
21
+ const cfg = loadConfig(config);
22
+ this.config = cfg.encrypt;
23
+ const outputFolder = out || this.config.encryptDir;
24
+ this.encryptDir = path.join(this.basePath, outputFolder);
25
+ this.filesExt = this.config.fileExt;
26
+ this.type = this.config.type;
27
+ this.bOpt = this.config.bytecodeOptions;
28
+ this.cOpt = this.config.confusionOptions;
29
+ this.cleanFiles = this.config.cleanFiles;
30
+ this.patterns = this.config.files || null;
31
+ this.specFiles = this.config.specificFiles;
32
+
33
+ this.codefiles = this._initCodeFiles();
34
+ }
35
+
36
+ /**
37
+ * 初始化需要加密的文件列表
38
+ */
39
+ _initCodeFiles() {
40
+ if (!this.patterns) return;
41
+
42
+ const files = globby.sync(this.patterns, { cwd: this.basePath });
43
+ return files;
44
+ }
45
+
46
+ /**
47
+ * 备份代码
48
+ */
49
+ backup() {
50
+ // clean
51
+ this.cleanCode();
52
+
53
+ console.log(chalk.blue('[ee-bin] [encrypt] ') + 'backup start');
54
+ this.codefiles.forEach((filepath) => {
55
+ let source = path.join(this.basePath, filepath);
56
+ if (fs.existsSync(source)) {
57
+ let target = path.join(this.encryptCodeDir, filepath);
58
+ fsPro.copySync(source, target);
59
+ }
60
+ })
61
+
62
+ console.log(chalk.blue('[ee-bin] [encrypt] ') + 'backup end');
63
+ return true;
64
+ }
65
+
66
+ /**
67
+ * 清除加密代码
68
+ */
69
+ cleanCode() {
70
+ this.cleanFiles.forEach((file) => {
71
+ let tmpFile = path.join(this.basePath, file);
72
+ fsPro.removeSync(tmpFile);
73
+ console.log(chalk.blue('[ee-bin] [encrypt] ') + 'clean up tmp files:' + chalk.magenta(`${tmpFile}`));
74
+ })
75
+ }
76
+
77
+ /**
78
+ * 加密代码
79
+ */
80
+ encrypt() {
81
+ console.log(chalk.blue('[ee-bin] [encrypt] ') + 'start ciphering');
82
+ console.log(this.codefiles);
83
+ for (const file of this.codefiles) {
84
+ const fullpath = path.join(this.encryptCodeDir, file);
85
+ if (!fs.statSync(fullpath).isFile()) continue;
86
+
87
+ // 特殊文件处理
88
+ if (this.specFiles.includes(file)) {
89
+ this.generate(fullpath, 'confusion');
90
+ continue;
91
+ }
92
+
93
+ this.generate(fullpath);
94
+ }
95
+ console.log(chalk.blue('[ee-bin] [encrypt] ') + 'end ciphering');
96
+ };
97
+
98
+ /**
99
+ * 递归
100
+ */
101
+ loop(dirPath) {
102
+ let files = [];
103
+ if (fs.existsSync(dirPath)) {
104
+ files = fs.readdirSync(dirPath);
105
+ files.forEach((file, index) => {
106
+ let curPath = dirPath + '/' + file;
107
+ if (fs.statSync(curPath).isDirectory()) {
108
+ this.loop(curPath);
109
+ } else {
110
+ const extname = path.extname(curPath);
111
+ if (this.filesExt.indexOf(extname) !== -1) {
112
+ this.generate(curPath);
113
+ }
114
+ }
115
+ });
116
+ }
117
+ }
118
+
119
+ /**
120
+ * 生成文件
121
+ */
122
+ generate(curPath, type) {
123
+ let encryptType = type ? type : this.type;
124
+
125
+ let tips = chalk.blue('[ee-bin] [encrypt] ') + 'file: ' + chalk.green(`${curPath}`) + ' ' + chalk.cyan(`(${encryptType})`);
126
+ console.log(tips);
127
+ if (encryptType == 'strict') {
128
+ this.generateJSConfuseFile(curPath);
129
+ this.generateBytecodeFile(curPath);
130
+ } else if (encryptType == 'bytecode') {
131
+ this.generateBytecodeFile(curPath);
132
+ } else if (encryptType == 'confusion') {
133
+ this.generateJSConfuseFile(curPath);
134
+ } else {
135
+ // none
136
+ }
137
+ }
138
+
139
+ /**
140
+ * 使用 javascript-obfuscator 生成压缩/混淆文件
141
+ */
142
+ generateJSConfuseFile(file) {
143
+ let opt = Object.assign({
144
+ compact: true,
145
+ stringArray: true,
146
+ stringArrayThreshold: 1,
147
+ }, this.cOpt);
148
+
149
+ let code = fs.readFileSync(file, "utf8");
150
+ let result = JavaScriptObfuscator.obfuscate(code, opt);
151
+ fs.writeFileSync(file, result.getObfuscatedCode(), "utf8");
152
+ }
153
+
154
+ /**
155
+ * 生成字节码文件
156
+ */
157
+ generateBytecodeFile(curPath) {
158
+ if (path.extname(curPath) !== '.js') {
159
+ return
160
+ }
161
+ //let jscFile = curPath.replace(/.js/g, '.jsc');
162
+ let jscFile = curPath + 'c';
163
+ let opt = Object.assign({
164
+ filename: curPath,
165
+ output: jscFile,
166
+ electron: true
167
+ }, this.bOpt);
168
+
169
+ bytenode.compileFile(opt);
170
+ fsPro.removeSync(curPath);
171
+ }
172
+ }
173
+
174
+ function encrypt(options = {}) {
175
+ const enc = new Encrypt(options);
176
+ if (EncryptTypes.indexOf(enc.type) == -1) return;
177
+ //if (!enc.backup()) return;
178
+ enc.encrypt();
179
+ }
180
+
181
+ function cleanEncrypt(options = {}) {
182
+ let files = options.dir !== undefined ? options.dir : ['./public/electron'];
183
+ files = is.string(files) ? [files] : files;
184
+
185
+ files.forEach((file) => {
186
+ const tmpFile = path.join(process.cwd(), file);
187
+ if (fs.existsSync(tmpFile)) {
188
+ fsPro.removeSync(tmpFile);
189
+ console.log(chalk.blue('[ee-bin] [encrypt] ') + 'clean up tmp files: ' + chalk.magenta(`${tmpFile}`));
190
+ }
191
+ })
192
+ }
193
+
194
+ module.exports = {
195
+ encrypt,
196
+ cleanEncrypt,
197
+ };