agora-toolchain 3.8.1-beta → 3.8.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/package.json +6 -2
- package/presets/electron.vite.config-standalone.js +71 -0
- package/presets/electron.vite.config.js +237 -0
- package/presets/webpack.base.js +0 -9
- package/presets/webpack.worker.prod.js +0 -9
- package/scripts/bundle.vite.js +30 -0
- package/scripts/pack-client-sdk.js +221 -63
- package/tools/bundle-options.js +3 -0
- package/tools/pack-options.js +1 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "agora-toolchain",
|
|
3
|
-
"version": "3.8.1
|
|
3
|
+
"version": "3.8.1",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"bin": {
|
|
6
6
|
"agora-tc-transpile": "./scripts/transpile.js",
|
|
@@ -11,7 +11,8 @@
|
|
|
11
11
|
"agora-tc-bundle-worker": "./scripts/bundle-worker.js",
|
|
12
12
|
"agora-tc-pack-app": "./scripts/pack-client-app.js",
|
|
13
13
|
"agora-tc-pack-sdk": "./scripts/pack-client-sdk.js",
|
|
14
|
-
"agora-tc-sign": "./scripts/sign-client.js"
|
|
14
|
+
"agora-tc-sign": "./scripts/sign-client.js",
|
|
15
|
+
"agora-tc-bundle-vite": "./scripts/bundle.vite.js"
|
|
15
16
|
},
|
|
16
17
|
"devDependencies": {
|
|
17
18
|
"@types/node": "^20.10.3",
|
|
@@ -42,6 +43,8 @@
|
|
|
42
43
|
"@babel/preset-react": "^7.24.1",
|
|
43
44
|
"@babel/preset-typescript": "^7.23.3",
|
|
44
45
|
"@hot-loader/react-dom": "^17.0.2",
|
|
46
|
+
"@rollup/plugin-commonjs": "^24.0.1",
|
|
47
|
+
"@vitejs/plugin-legacy": "^7.2.1",
|
|
45
48
|
"autoprefixer": "^10.4.19",
|
|
46
49
|
"babel-loader": "^9.1.3",
|
|
47
50
|
"buffer": "^6.0.3",
|
|
@@ -52,6 +55,7 @@
|
|
|
52
55
|
"css-loader": "^6.10.0",
|
|
53
56
|
"dotenv": "^16.3.1",
|
|
54
57
|
"electron-builder": "^24.13.3",
|
|
58
|
+
"electron-vite": "^5.0.0",
|
|
55
59
|
"html-webpack-plugin": "^5.6.0",
|
|
56
60
|
"karma": "^6.4.2",
|
|
57
61
|
"karma-chrome-launcher": "^3.2.0",
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { defineConfig } from 'electron-vite';
|
|
2
|
+
import commonjs from '@rollup/plugin-commonjs';
|
|
3
|
+
|
|
4
|
+
export default defineConfig(() => {
|
|
5
|
+
const config = {};
|
|
6
|
+
|
|
7
|
+
const outDirPrefix = 'dist';
|
|
8
|
+
const mainEntry = 'src/electron/bootstrap-sdk.ts';
|
|
9
|
+
const preloadEntry = 'src/electron/preload.ts';
|
|
10
|
+
|
|
11
|
+
config.main = {
|
|
12
|
+
build: {
|
|
13
|
+
outDir: `${outDirPrefix}/electron/main`,
|
|
14
|
+
rollupOptions: {
|
|
15
|
+
input: {
|
|
16
|
+
index: mainEntry,
|
|
17
|
+
},
|
|
18
|
+
external: ['electron-screenshots', 'original-fs'],
|
|
19
|
+
plugins: [
|
|
20
|
+
commonjs({
|
|
21
|
+
include: [
|
|
22
|
+
/fcr-ui-scene[/\\]lib[/\\].*/,
|
|
23
|
+
/fcr-ui-scene-mobile[/\\]lib[/\\].*/,
|
|
24
|
+
/fcr-ui-widget-sdk[/\\]lib[/\\].*/,
|
|
25
|
+
/agora-ui-foundation[/\\]lib[/\\].*/,
|
|
26
|
+
/fcr-core[/\\]lib[/\\].*/,
|
|
27
|
+
/agora-rte-sdk[/\\]lib[/\\].*/,
|
|
28
|
+
/agora-foundation[/\\]lib[/\\].*/,
|
|
29
|
+
/foundation[/\\]lib[/\\].*/,
|
|
30
|
+
],
|
|
31
|
+
}),
|
|
32
|
+
],
|
|
33
|
+
},
|
|
34
|
+
bytecode: true,
|
|
35
|
+
},
|
|
36
|
+
define: {
|
|
37
|
+
'process.env.BUILD_TOOL': JSON.stringify('vite'),
|
|
38
|
+
},
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
config.preload = {
|
|
42
|
+
build: {
|
|
43
|
+
outDir: `${outDirPrefix}/electron/preload`,
|
|
44
|
+
rollupOptions: {
|
|
45
|
+
input: {
|
|
46
|
+
index: preloadEntry,
|
|
47
|
+
},
|
|
48
|
+
plugins: [
|
|
49
|
+
commonjs({
|
|
50
|
+
include: [
|
|
51
|
+
/fcr-ui-scene[/\\]lib[/\\].*/,
|
|
52
|
+
/fcr-ui-scene-mobile[/\\]lib[/\\].*/,
|
|
53
|
+
/fcr-ui-widget-sdk[/\\]lib[/\\].*/,
|
|
54
|
+
/agora-ui-foundation[/\\]lib[/\\].*/,
|
|
55
|
+
/fcr-core[/\\]lib[/\\].*/,
|
|
56
|
+
/agora-rte-sdk[/\\]lib[/\\].*/,
|
|
57
|
+
/agora-foundation[/\\]lib[/\\].*/,
|
|
58
|
+
/foundation[/\\]lib[/\\].*/,
|
|
59
|
+
],
|
|
60
|
+
}),
|
|
61
|
+
],
|
|
62
|
+
},
|
|
63
|
+
bytecode: true,
|
|
64
|
+
},
|
|
65
|
+
define: {
|
|
66
|
+
'process.env.BUILD_TOOL': JSON.stringify('vite'),
|
|
67
|
+
},
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
return config;
|
|
71
|
+
});
|
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
import { defineConfig } from 'electron-vite';
|
|
2
|
+
import commonjs from '@rollup/plugin-commonjs';
|
|
3
|
+
import legacy from '@vitejs/plugin-legacy';
|
|
4
|
+
import { existsSync } from 'fs';
|
|
5
|
+
import { resolveCwd, resolveModule } from '../tools/paths';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Generate dynamic alias based on whether src directory exists
|
|
9
|
+
* Similar to sourceAlias in webpack-utils.js
|
|
10
|
+
*/
|
|
11
|
+
function generateWorkspaceAlias(libNames) {
|
|
12
|
+
const aliases = [];
|
|
13
|
+
|
|
14
|
+
libNames.forEach((libName) => {
|
|
15
|
+
try {
|
|
16
|
+
const modulePath = resolveModule(libName);
|
|
17
|
+
const srcPath = `${modulePath}/src`;
|
|
18
|
+
// const libPath = `${modulePath}/lib`;
|
|
19
|
+
|
|
20
|
+
// Check if src directory exists
|
|
21
|
+
if (existsSync(srcPath)) {
|
|
22
|
+
console.log(`source linker: ${libName} linked to src`);
|
|
23
|
+
// Link to src if it exists
|
|
24
|
+
aliases.push(
|
|
25
|
+
{ find: new RegExp(`^${libName}/lib/(.*)`), replacement: `${srcPath}/$1` },
|
|
26
|
+
{ find: libName, replacement: srcPath },
|
|
27
|
+
);
|
|
28
|
+
}
|
|
29
|
+
} catch (e) {
|
|
30
|
+
console.log(`source linker: ${libName} not found, using default paths`);
|
|
31
|
+
// Fallback to relative path if module not found
|
|
32
|
+
const relativePath = resolveCwd(`../${libName}/src`);
|
|
33
|
+
if (existsSync(relativePath)) {
|
|
34
|
+
aliases.push(
|
|
35
|
+
{ find: new RegExp(`^${libName}/lib/(.*)`), replacement: `${relativePath}/$1` },
|
|
36
|
+
{ find: libName, replacement: relativePath },
|
|
37
|
+
);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
return aliases;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export default defineConfig(() => {
|
|
46
|
+
const config = {};
|
|
47
|
+
|
|
48
|
+
const outDirPrefix = process.env.VITE_OUT_DIR || 'dist';
|
|
49
|
+
const mainEntry = process.env.VITE_MAIN_ENTRY || 'electron/main/index.ts';
|
|
50
|
+
const preloadEntry = process.env.VITE_PRELOAD_ENTRY || 'electron/preload/index.js';
|
|
51
|
+
const rendererEntry =
|
|
52
|
+
process.env.VITE_RENDERER_ENTRY || 'electron/renderer/public/index.vite.html';
|
|
53
|
+
|
|
54
|
+
// Check if entry files exist
|
|
55
|
+
const mainEntryPath = resolveCwd(mainEntry);
|
|
56
|
+
const preloadEntryPath = resolveCwd(preloadEntry);
|
|
57
|
+
const rendererEntryPath = resolveCwd(rendererEntry);
|
|
58
|
+
|
|
59
|
+
const hasMain = existsSync(mainEntryPath);
|
|
60
|
+
const hasPreload = existsSync(preloadEntryPath);
|
|
61
|
+
const hasRenderer = existsSync(rendererEntryPath);
|
|
62
|
+
|
|
63
|
+
console.log('Using electron-vite config with:');
|
|
64
|
+
console.log(' Main entry:', mainEntry, hasMain ? '✓' : '✗');
|
|
65
|
+
console.log(' Preload entry:', preloadEntry, hasPreload ? '✓' : '✗');
|
|
66
|
+
console.log(' Renderer entry:', rendererEntry, hasRenderer ? '✓' : '✗');
|
|
67
|
+
console.log(' Output dir prefix:', outDirPrefix);
|
|
68
|
+
|
|
69
|
+
if (!hasMain && !hasPreload && !hasRenderer) {
|
|
70
|
+
console.error(
|
|
71
|
+
'Error: No valid entry points found. Please specify --main, --preload, or --renderer.',
|
|
72
|
+
);
|
|
73
|
+
process.exit(1);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
if (hasMain) {
|
|
77
|
+
config.main = {
|
|
78
|
+
// 主进程构建配置
|
|
79
|
+
build: {
|
|
80
|
+
outDir: `${outDirPrefix}/electron/main`,
|
|
81
|
+
rollupOptions: {
|
|
82
|
+
input: {
|
|
83
|
+
index: resolveCwd(mainEntry),
|
|
84
|
+
},
|
|
85
|
+
external: ['electron-screenshots', 'original-fs'],
|
|
86
|
+
plugins: [
|
|
87
|
+
commonjs({
|
|
88
|
+
include: [
|
|
89
|
+
/fcr-ui-scene[/\\]lib[/\\].*/,
|
|
90
|
+
/fcr-ui-scene-mobile[/\\]lib[/\\].*/,
|
|
91
|
+
/fcr-ui-widget-sdk[/\\]lib[/\\].*/,
|
|
92
|
+
/agora-ui-foundation[/\\]lib[/\\].*/,
|
|
93
|
+
/fcr-core[/\\]lib[/\\].*/,
|
|
94
|
+
/agora-rte-sdk[/\\]lib[/\\].*/,
|
|
95
|
+
/agora-foundation[/\\]lib[/\\].*/,
|
|
96
|
+
/foundation[/\\]lib[/\\].*/,
|
|
97
|
+
],
|
|
98
|
+
}),
|
|
99
|
+
],
|
|
100
|
+
},
|
|
101
|
+
bytecode: true,
|
|
102
|
+
},
|
|
103
|
+
define: {
|
|
104
|
+
'process.env.BUILD_TOOL': JSON.stringify('vite'),
|
|
105
|
+
},
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
if (hasPreload) {
|
|
110
|
+
config.preload = {
|
|
111
|
+
// 预加载脚本构建配置
|
|
112
|
+
build: {
|
|
113
|
+
outDir: `${outDirPrefix}/electron/preload`,
|
|
114
|
+
rollupOptions: {
|
|
115
|
+
input: {
|
|
116
|
+
index: resolveCwd(preloadEntry),
|
|
117
|
+
},
|
|
118
|
+
plugins: [
|
|
119
|
+
commonjs({
|
|
120
|
+
include: [
|
|
121
|
+
/fcr-ui-scene[/\\]lib[/\\].*/,
|
|
122
|
+
/fcr-ui-scene-mobile[/\\]lib[/\\].*/,
|
|
123
|
+
/fcr-ui-widget-sdk[/\\]lib[/\\].*/,
|
|
124
|
+
/agora-ui-foundation[/\\]lib[/\\].*/,
|
|
125
|
+
/fcr-core[/\\]lib[/\\].*/,
|
|
126
|
+
/agora-rte-sdk[/\\]lib[/\\].*/,
|
|
127
|
+
/agora-foundation[/\\]lib[/\\].*/,
|
|
128
|
+
/foundation[/\\]lib[/\\].*/,
|
|
129
|
+
],
|
|
130
|
+
}),
|
|
131
|
+
],
|
|
132
|
+
},
|
|
133
|
+
bytecode: true,
|
|
134
|
+
},
|
|
135
|
+
define: {
|
|
136
|
+
'process.env.BUILD_TOOL': JSON.stringify('vite'),
|
|
137
|
+
},
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
if (hasRenderer) {
|
|
142
|
+
config.renderer = {
|
|
143
|
+
plugins: [
|
|
144
|
+
commonjs({
|
|
145
|
+
include: [
|
|
146
|
+
/fcr-ui-scene[/\\]lib[/\\].*/,
|
|
147
|
+
/fcr-ui-scene-mobile[/\\]lib[/\\].*/,
|
|
148
|
+
/fcr-ui-widget-sdk[/\\]lib[/\\].*/,
|
|
149
|
+
/agora-ui-foundation[/\\]lib[/\\].*/,
|
|
150
|
+
/fcr-core[/\\]lib[/\\].*/,
|
|
151
|
+
/agora-rte-sdk[/\\]lib[/\\].*/,
|
|
152
|
+
/agora-foundation[/\\]lib[/\\].*/,
|
|
153
|
+
/foundation[/\\]lib[/\\].*/,
|
|
154
|
+
],
|
|
155
|
+
}),
|
|
156
|
+
legacy({
|
|
157
|
+
targets: ['defaults'],
|
|
158
|
+
modernPolyfills: true,
|
|
159
|
+
// add stage 3 proposals polyfills
|
|
160
|
+
// MapIterator.find
|
|
161
|
+
additionalLegacyPolyfills: ['core-js/proposals/iterator-helpers'],
|
|
162
|
+
}),
|
|
163
|
+
],
|
|
164
|
+
// 渲染进程构建配置
|
|
165
|
+
root: '.',
|
|
166
|
+
publicDir: resolveCwd('public'), // 指定 public 目录
|
|
167
|
+
build: {
|
|
168
|
+
outDir: `${outDirPrefix}/electron/renderer`,
|
|
169
|
+
rollupOptions: {
|
|
170
|
+
input: {
|
|
171
|
+
index: resolveCwd(rendererEntry),
|
|
172
|
+
},
|
|
173
|
+
},
|
|
174
|
+
},
|
|
175
|
+
resolve: {
|
|
176
|
+
alias: [
|
|
177
|
+
// Node.js polyfills (对应 webpack 的 resolve.fallback)
|
|
178
|
+
{ find: 'crypto', replacement: 'crypto-browserify' },
|
|
179
|
+
{ find: 'stream', replacement: 'stream-browserify' },
|
|
180
|
+
{ find: 'zlib', replacement: 'zlib-browserify' },
|
|
181
|
+
{ find: 'vm', replacement: 'vm-browserify' },
|
|
182
|
+
{ find: 'buffer', replacement: 'buffer/' },
|
|
183
|
+
{ find: 'process', replacement: 'process/browser' },
|
|
184
|
+
|
|
185
|
+
// workspace packages 别名 - 动态生成
|
|
186
|
+
...generateWorkspaceAlias([
|
|
187
|
+
'agora-ui-foundation',
|
|
188
|
+
'agora-foundation',
|
|
189
|
+
'fcr-ui-scene',
|
|
190
|
+
'fcr-core',
|
|
191
|
+
'agora-rte-sdk',
|
|
192
|
+
'fcr-ui-widget-sdk',
|
|
193
|
+
'fcr-ui-scene-mobile',
|
|
194
|
+
]),
|
|
195
|
+
],
|
|
196
|
+
},
|
|
197
|
+
css: {
|
|
198
|
+
postcss: {
|
|
199
|
+
plugins: [require('autoprefixer')],
|
|
200
|
+
},
|
|
201
|
+
},
|
|
202
|
+
optimizeDeps: {
|
|
203
|
+
include: [
|
|
204
|
+
'react',
|
|
205
|
+
'react-dom',
|
|
206
|
+
'antd',
|
|
207
|
+
'mobx',
|
|
208
|
+
'mobx-react',
|
|
209
|
+
// 包含 Node.js polyfills
|
|
210
|
+
'buffer',
|
|
211
|
+
'process',
|
|
212
|
+
'stream-browserify',
|
|
213
|
+
'crypto-browserify',
|
|
214
|
+
'zlib-browserify',
|
|
215
|
+
'vm-browserify',
|
|
216
|
+
],
|
|
217
|
+
},
|
|
218
|
+
define: {
|
|
219
|
+
'process.env.BUILD_TOOL': JSON.stringify('vite'),
|
|
220
|
+
'process.env.DEVTOOLS_DISABLED': JSON.stringify(process.env.DEVTOOLS_DISABLED),
|
|
221
|
+
},
|
|
222
|
+
// 渲染进程的现代装饰器配置
|
|
223
|
+
esbuild: {
|
|
224
|
+
target: 'es2022',
|
|
225
|
+
tsconfigRaw: {
|
|
226
|
+
compilerOptions: {
|
|
227
|
+
experimentalDecorators: false,
|
|
228
|
+
useDefineForClassFields: true,
|
|
229
|
+
jsx: 'react-jsx',
|
|
230
|
+
},
|
|
231
|
+
},
|
|
232
|
+
},
|
|
233
|
+
};
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
return config;
|
|
237
|
+
});
|
package/presets/webpack.base.js
CHANGED
|
@@ -32,15 +32,6 @@ module.exports = createConfig = ({ entry, out = 'lib/worker' }) => {
|
|
|
32
32
|
},
|
|
33
33
|
module: {
|
|
34
34
|
rules: [
|
|
35
|
-
{
|
|
36
|
-
test: /worker-entry/,
|
|
37
|
-
use: {
|
|
38
|
-
loader: require.resolve('worker-loader'),
|
|
39
|
-
options: {
|
|
40
|
-
inline: 'no-fallback',
|
|
41
|
-
},
|
|
42
|
-
},
|
|
43
|
-
},
|
|
44
35
|
{
|
|
45
36
|
test: /\.(ts|tsx)$/,
|
|
46
37
|
use: [
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
require('dotenv/config');
|
|
3
|
+
const { build } = require('electron-vite');
|
|
4
|
+
const path = require('path');
|
|
5
|
+
const { main, preload, renderer, out } = require('../tools/bundle-options');
|
|
6
|
+
|
|
7
|
+
// Set environment variables for config to use
|
|
8
|
+
if (main) process.env.VITE_MAIN_ENTRY = main;
|
|
9
|
+
if (preload) process.env.VITE_PRELOAD_ENTRY = preload;
|
|
10
|
+
if (renderer) process.env.VITE_RENDERER_ENTRY = renderer;
|
|
11
|
+
if (out) process.env.VITE_OUT_DIR = out;
|
|
12
|
+
|
|
13
|
+
async function bundleVite() {
|
|
14
|
+
try {
|
|
15
|
+
const configPath = path.join(__dirname, '../presets/electron.vite.config.js');
|
|
16
|
+
|
|
17
|
+
// Build with electron-vite
|
|
18
|
+
await build({
|
|
19
|
+
configFile: configPath,
|
|
20
|
+
dir: process.cwd(),
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
console.log('Vite bundle completed successfully');
|
|
24
|
+
} catch (error) {
|
|
25
|
+
console.error('Vite bundle failed:', error);
|
|
26
|
+
process.exit(1);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
bundleVite();
|
|
@@ -2,34 +2,39 @@
|
|
|
2
2
|
const builder = require('electron-builder');
|
|
3
3
|
const fs = require('fs');
|
|
4
4
|
const path = require('path');
|
|
5
|
-
const
|
|
6
|
-
const {
|
|
5
|
+
const crypto = require('crypto');
|
|
6
|
+
const { platform, arch, main: _mainScript } = require('../tools/pack-options');
|
|
7
7
|
const { resolveCwd } = require('../tools/paths');
|
|
8
8
|
|
|
9
|
-
const isDebug = true;
|
|
10
|
-
|
|
11
9
|
const Platform = builder.Platform;
|
|
10
|
+
const AES_KEY = 'FCRUISCENE';
|
|
11
|
+
const AES_ALGORITHM = 'aes-256-ecb';
|
|
12
|
+
|
|
13
|
+
function getAesKey() {
|
|
14
|
+
return crypto.createHash('sha256').update(AES_KEY).digest();
|
|
15
|
+
}
|
|
12
16
|
|
|
13
17
|
const targetPlatform = platform;
|
|
14
18
|
|
|
15
19
|
const targetArch = arch;
|
|
16
20
|
|
|
21
|
+
const mainScript = _mainScript ?? 'dist/electron/bootstrap-sdk.js';
|
|
22
|
+
|
|
17
23
|
// 读取 package.json 获取版本号
|
|
18
24
|
const packageJsonPath = resolveCwd('package.json');
|
|
19
25
|
const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
|
|
20
26
|
const originalVersion = packageJson.version;
|
|
21
27
|
let builderVersion = packageJson.version;
|
|
22
28
|
// Windows 不支持预发布版本号(如 3.7.8-rc.2),需要转换为标准版本号
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
29
|
+
// 移除预发布标识符(-rc.2, -beta.1 等)
|
|
30
|
+
const baseVersion = builderVersion.split('-')[0];
|
|
31
|
+
// 获取 job 号(从环境变量)
|
|
32
|
+
const jobNumber = process.env.BUILD_NUMBER || process.env.JOB_NUMBER || '0';
|
|
33
|
+
|
|
34
|
+
// Windows 版本号格式: major.minor.patch.jobNumber
|
|
35
|
+
builderVersion = `${baseVersion}.${jobNumber}`;
|
|
36
|
+
|
|
37
|
+
console.log(`Convnert version number from ${originalVersion} to ${builderVersion}`);
|
|
33
38
|
|
|
34
39
|
function copyDirSync(source, target) {
|
|
35
40
|
if (!fs.existsSync(target)) {
|
|
@@ -58,35 +63,25 @@ if (fs.existsSync(resolveCwd('public/assets'))) {
|
|
|
58
63
|
copyDirSync(resolveCwd('public/assets'), resolveCwd('dist/assets'));
|
|
59
64
|
}
|
|
60
65
|
|
|
61
|
-
// Let's get that intellisense working
|
|
62
66
|
/**
|
|
63
67
|
* @type {import('electron-builder').Configuration}
|
|
64
68
|
* @see https://www.electron.build/configuration/configuration
|
|
65
69
|
*/
|
|
66
|
-
const
|
|
70
|
+
const builderOptions = {
|
|
67
71
|
appId: 'io.agora.meeting.core',
|
|
68
72
|
protocols: {
|
|
69
73
|
name: 'fcr-meeting',
|
|
70
74
|
// Don't forget to set `MimeType: "x-scheme-handler/deeplink"` for `linux.desktop` entry!
|
|
71
75
|
schemes: ['fcr-meeting'],
|
|
72
76
|
},
|
|
73
|
-
|
|
74
|
-
// "store" | "normal" | "maximum". - For testing builds, use 'store' to reduce build time significantly.
|
|
75
|
-
compression: isDebug ? 'store' : 'normal',
|
|
77
|
+
compression: 'normal',
|
|
76
78
|
removePackageScripts: true,
|
|
77
79
|
buildVersion: builderVersion,
|
|
78
80
|
buildNumber: jobNumber,
|
|
79
|
-
|
|
80
|
-
afterSign: async (context) => {
|
|
81
|
-
// Mac releases require hardening+notarization: https://developer.apple.com/documentation/xcode/notarizing_macos_software_before_distribution
|
|
82
|
-
if (!isDebug && context.electronPlatformName === 'darwin') {
|
|
83
|
-
await notarizeMac(context);
|
|
84
|
-
}
|
|
85
|
-
},
|
|
86
81
|
nodeGypRebuild: false,
|
|
87
82
|
buildDependenciesFromSource: false,
|
|
88
83
|
extraMetadata: {
|
|
89
|
-
main:
|
|
84
|
+
main: mainScript,
|
|
90
85
|
bundleType: 'NATIVE_BUNDLE',
|
|
91
86
|
},
|
|
92
87
|
asarUnpack: ['node_modules/agora-electron-sdk'],
|
|
@@ -100,32 +95,32 @@ const options = {
|
|
|
100
95
|
'!**/artifactory_deps/**/*',
|
|
101
96
|
'!**/mac-release/**/*',
|
|
102
97
|
'!**/scr/**/*',
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
98
|
+
'!**/node_modules/**/{CHANGELOG.md,README.md,README,readme.md,README.zh.md}',
|
|
99
|
+
'!**/node_modules/**/{nodemon.json,rollup.config.js,tsconfig.json,typedoc.json,rc_message.proto}',
|
|
100
|
+
'!**/node_modules/*/{test,__tests__,tests,powered-test,example,examples}',
|
|
101
|
+
'!**/node_modules/.bin',
|
|
107
102
|
|
|
108
103
|
'!**/node_modules/fcr-ui-scene/release/**/*',
|
|
109
104
|
'!**/node_modules/fcr-ui-scene/src/**/*',
|
|
110
105
|
'!**/node_modules/agora-rte-sdk/src/**/*',
|
|
111
106
|
'!**/node_modules/agora-ui-foundation/src/**/*',
|
|
112
107
|
'!**/node_modules/agora-foundation/src/**/*',
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
108
|
+
|
|
109
|
+
'!**/*.{iml,o,hprof,orig,pyc,pyo,rbc,swp,csproj,sln,xproj}',
|
|
110
|
+
'!.editorconfig',
|
|
111
|
+
'!**/{.DS_Store,.git,.hg,.svn,CVS,RCS,SCCS,.gitignore,.gitattributes}',
|
|
112
|
+
'!**/{__pycache__,thumbs.db,.flowconfig,.idea,.vs,.nyc_output}',
|
|
113
|
+
'!**/{appveyor.yml,.travis.yml,circle.yml}',
|
|
114
|
+
'!**/{npm-debug.log,yarn.lock,.yarn-integrity,.yarn-metadata.json}',
|
|
115
|
+
'!**/*.dSYM',
|
|
116
|
+
'!**/*.{lproj}',
|
|
117
|
+
'!**/*.config.js',
|
|
118
|
+
'!**/*.config.ts',
|
|
119
|
+
'!**/*.config.json',
|
|
120
|
+
'!**/*.config.yaml',
|
|
121
|
+
'!**/*.config.yml',
|
|
122
|
+
'!**/*.config.xml',
|
|
123
|
+
'!**/*.config.html',
|
|
129
124
|
],
|
|
130
125
|
extraResources: [
|
|
131
126
|
// 内置资源
|
|
@@ -183,19 +178,182 @@ const options = {
|
|
|
183
178
|
},
|
|
184
179
|
};
|
|
185
180
|
|
|
186
|
-
//
|
|
187
|
-
|
|
188
|
-
.
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
181
|
+
// 计算 ASAR 文件的 SHA256 hash
|
|
182
|
+
function calculateAsarHash(asarPath) {
|
|
183
|
+
console.log(`Calculating ASAR hash for: ${asarPath}`);
|
|
184
|
+
|
|
185
|
+
if (!fs.existsSync(asarPath)) {
|
|
186
|
+
throw new Error(`ASAR file not found: ${asarPath}`);
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
const fileBuffer = fs.readFileSync(asarPath);
|
|
190
|
+
const hash = crypto.createHash('sha256').update(fileBuffer).digest('hex');
|
|
191
|
+
|
|
192
|
+
console.log(`ASAR SHA256 hash: ${hash}`);
|
|
193
|
+
return hash;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
function encryptHash(hash) {
|
|
197
|
+
const cipher = crypto.createCipheriv(AES_ALGORITHM, getAesKey(), null);
|
|
198
|
+
const encrypted = Buffer.concat([cipher.update(hash, 'utf8'), cipher.final()]);
|
|
199
|
+
return encrypted.toString('base64');
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
// 保存 ASAR hash 到文件
|
|
203
|
+
function saveAsarHash(hash, outputDir) {
|
|
204
|
+
const hashFilePath = path.join(outputDir, 'asar-hash.enc');
|
|
205
|
+
const hashJsonPath = path.join(outputDir, 'asar-hash.json');
|
|
206
|
+
const encryptedHash = encryptHash(hash);
|
|
207
|
+
|
|
208
|
+
// 保存加密后的 hash 文本
|
|
209
|
+
fs.writeFileSync(hashFilePath, encryptedHash);
|
|
210
|
+
console.log(`ASAR encrypted hash saved to: ${hashFilePath}`);
|
|
211
|
+
|
|
212
|
+
// 保存 JSON 格式(包含更多元数据)
|
|
213
|
+
const hashData = {
|
|
214
|
+
hash: encryptedHash,
|
|
215
|
+
algorithm: 'sha256',
|
|
216
|
+
encryption: AES_ALGORITHM,
|
|
217
|
+
timestamp: new Date().toISOString(),
|
|
218
|
+
version: builderVersion,
|
|
219
|
+
platform: targetPlatform,
|
|
220
|
+
arch: targetArch,
|
|
221
|
+
};
|
|
222
|
+
// fs.writeFileSync(hashJsonPath, JSON.stringify(hashData, null, 2));
|
|
223
|
+
// console.log(`ASAR hash metadata saved to: ${hashJsonPath}`);
|
|
224
|
+
|
|
225
|
+
return { hashFilePath, hashJsonPath };
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
// 查找打包后的 ASAR 文件路径和 resources 目录
|
|
229
|
+
function findAsarPath(releaseDir) {
|
|
230
|
+
let asarPath = null;
|
|
231
|
+
let resourcesDir = null;
|
|
232
|
+
|
|
233
|
+
if (targetPlatform === 'darwin') {
|
|
234
|
+
// macOS: 先在 mac-{arch}/.app 包内查找,找不到再找 mac/.app
|
|
235
|
+
const archDir = path.join(releaseDir, `mac-${targetArch}`);
|
|
236
|
+
const macDir = path.join(releaseDir, 'mac');
|
|
237
|
+
|
|
238
|
+
// 尝试在 mac-{arch} 目录中查找
|
|
239
|
+
if (fs.existsSync(archDir)) {
|
|
240
|
+
const appFiles = fs.readdirSync(archDir).filter((f) => f.endsWith('.app'));
|
|
241
|
+
if (appFiles.length > 0) {
|
|
242
|
+
resourcesDir = path.join(archDir, appFiles[0], 'Contents', 'Resources');
|
|
243
|
+
asarPath = path.join(resourcesDir, 'app.asar');
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
// 如果在 mac-{arch} 中没找到,尝试在 mac 目录中查找
|
|
248
|
+
if (!asarPath && fs.existsSync(macDir)) {
|
|
249
|
+
const appFiles = fs.readdirSync(macDir).filter((f) => f.endsWith('.app'));
|
|
250
|
+
if (appFiles.length > 0) {
|
|
251
|
+
resourcesDir = path.join(macDir, appFiles[0], 'Contents', 'Resources');
|
|
252
|
+
asarPath = path.join(resourcesDir, 'app.asar');
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
} else if (targetPlatform === 'win32') {
|
|
256
|
+
// Windows: 在解压的安装目录中查找
|
|
257
|
+
const unpackedDir = path.join(releaseDir, 'win-x64-unpacked');
|
|
258
|
+
if (fs.existsSync(unpackedDir)) {
|
|
259
|
+
resourcesDir = path.join(unpackedDir, 'resources');
|
|
260
|
+
asarPath = path.join(resourcesDir, 'app.asar');
|
|
261
|
+
}
|
|
262
|
+
} else if (targetPlatform === 'linux') {
|
|
263
|
+
// Linux: 在解压的安装目录中查找
|
|
264
|
+
const unpackedDir = path.join(releaseDir, 'linux-unpacked');
|
|
265
|
+
if (fs.existsSync(unpackedDir)) {
|
|
266
|
+
resourcesDir = path.join(unpackedDir, 'resources');
|
|
267
|
+
asarPath = path.join(resourcesDir, 'app.asar');
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
return { asarPath, resourcesDir };
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
async function packWithElectronBuilder() {
|
|
275
|
+
console.log('Packaging with electron-builder...');
|
|
276
|
+
|
|
277
|
+
let targets;
|
|
278
|
+
if (targetPlatform === 'darwin') {
|
|
279
|
+
targets = Platform.MAC.createTarget(['dmg'], [builder.Arch[targetArch]]);
|
|
280
|
+
} else if (targetPlatform === 'win32') {
|
|
281
|
+
targets = Platform.WINDOWS.createTarget(['nsis'], [builder.Arch[targetArch]]);
|
|
282
|
+
} else if (targetPlatform === 'linux') {
|
|
283
|
+
targets = Platform.LINUX.createTarget();
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
try {
|
|
287
|
+
const result = await builder.build({
|
|
288
|
+
targets,
|
|
289
|
+
config: builderOptions,
|
|
290
|
+
publish: 'never',
|
|
291
|
+
});
|
|
292
|
+
|
|
293
|
+
console.log('Packaging completed successfully');
|
|
294
|
+
|
|
295
|
+
return result;
|
|
296
|
+
} catch (error) {
|
|
297
|
+
console.error('Packaging failed:', error);
|
|
298
|
+
throw error;
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
async function generateAsarHash() {
|
|
303
|
+
console.log('\n=== Generating ASAR Hash ===');
|
|
304
|
+
|
|
305
|
+
const releaseDir = resolveCwd('release');
|
|
306
|
+
const { asarPath, resourcesDir } = findAsarPath(releaseDir);
|
|
307
|
+
|
|
308
|
+
if (!asarPath || !resourcesDir) {
|
|
309
|
+
console.warn(
|
|
310
|
+
'Warning: Could not find ASAR file or resources directory. Hash generation skipped.',
|
|
311
|
+
);
|
|
312
|
+
console.warn(`Find AsarPath result: ${JSON.stringify({ asarPath, resourcesDir })}`);
|
|
313
|
+
console.warn('This may be normal if the app is not packaged as ASAR.');
|
|
314
|
+
return null;
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
if (!fs.existsSync(asarPath)) {
|
|
318
|
+
console.warn(`Warning: ASAR file not found at expected path: ${asarPath}`);
|
|
319
|
+
return null;
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
try {
|
|
323
|
+
// 计算 hash
|
|
324
|
+
const hash = calculateAsarHash(asarPath);
|
|
325
|
+
|
|
326
|
+
// 保存 hash 到 resources 目录(与 app.asar 同级)
|
|
327
|
+
const { hashFilePath, hashJsonPath } = saveAsarHash(hash, resourcesDir);
|
|
328
|
+
|
|
329
|
+
console.log('\n=== ASAR Hash Generation Complete ===');
|
|
330
|
+
console.log(`Hash: ${hash}`);
|
|
331
|
+
console.log(`Saved to: ${hashFilePath}`);
|
|
332
|
+
// console.log(`Metadata: ${hashJsonPath}`);
|
|
333
|
+
console.log('\nHash files are stored in the resources directory alongside app.asar');
|
|
334
|
+
|
|
335
|
+
return hash;
|
|
336
|
+
} catch (error) {
|
|
337
|
+
console.error('Error generating ASAR hash:', error);
|
|
338
|
+
throw error;
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
async function main() {
|
|
343
|
+
try {
|
|
344
|
+
console.log(`Starting vite-based packaging for ${targetPlatform}-${targetArch}...`);
|
|
345
|
+
|
|
346
|
+
// 1. 使用 electron-builder 打包
|
|
347
|
+
await packWithElectronBuilder();
|
|
348
|
+
|
|
349
|
+
// 2. 生成 ASAR hash
|
|
350
|
+
await generateAsarHash();
|
|
351
|
+
|
|
352
|
+
console.log('\n=== Vite-based packaging completed successfully! ===');
|
|
353
|
+
} catch (error) {
|
|
354
|
+
console.error('Packaging process failed:', error);
|
|
355
|
+
process.exit(1);
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
main();
|
package/tools/bundle-options.js
CHANGED
|
@@ -2,6 +2,9 @@ const { program } = require('commander');
|
|
|
2
2
|
|
|
3
3
|
const opts = program
|
|
4
4
|
.option('--entry <entry>', 'Entry file ')
|
|
5
|
+
.option('--main <main>', 'Main process entry file')
|
|
6
|
+
.option('--preload <preload>', 'Preload script entry file')
|
|
7
|
+
.option('--renderer <renderer>', 'Renderer process entry file')
|
|
5
8
|
.option('--analyze', 'Run in analyze mode')
|
|
6
9
|
.option('--out <out>', 'Output directory')
|
|
7
10
|
.parse(process.argv)
|
package/tools/pack-options.js
CHANGED