pake-cli 2.3.8 → 2.4.0-beta1
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 +2 -2
- package/dist/cli.js +28 -16
- package/dist/dev.js +644 -639
- package/dist/dev.js.map +1 -1
- package/package.json +1 -1
- package/src-tauri/.pake/pake.json +29 -0
- package/src-tauri/.pake/tauri.conf.json +75 -0
- package/src-tauri/.pake/tauri.macos.conf.json +29 -0
- package/src-tauri/pake.json +5 -2
- package/src-tauri/rust_proxy.toml +1 -5
- package/src-tauri/src/app/config.rs +8 -5
- package/src-tauri/src/app/menu.rs +1 -1
- package/src-tauri/src/app/window.rs +8 -7
- package/src-tauri/src/inject/event.js +11 -9
- package/src-tauri/src/inject/style.js +1 -1
- package/src-tauri/src/main.rs +26 -4
- package/src-tauri/src/util.rs +3 -0
- package/src-tauri/.cargo/config.toml +0 -10
package/dist/dev.js
CHANGED
|
@@ -17,218 +17,223 @@ import http from 'http';
|
|
|
17
17
|
import { promisify } from 'util';
|
|
18
18
|
import fs from 'fs';
|
|
19
19
|
|
|
20
|
-
const DEFAULT_PAKE_OPTIONS = {
|
|
21
|
-
icon: '',
|
|
22
|
-
height: 780,
|
|
23
|
-
width: 1200,
|
|
24
|
-
fullscreen: false,
|
|
25
|
-
resizable: true,
|
|
26
|
-
transparent: false,
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
20
|
+
const DEFAULT_PAKE_OPTIONS = {
|
|
21
|
+
icon: '',
|
|
22
|
+
height: 780,
|
|
23
|
+
width: 1200,
|
|
24
|
+
fullscreen: false,
|
|
25
|
+
resizable: true,
|
|
26
|
+
transparent: false,
|
|
27
|
+
alwaysOnTop: false,
|
|
28
|
+
disabledWebShortcuts: false,
|
|
29
|
+
activationShortcut: '',
|
|
30
|
+
userAgent: '',
|
|
31
|
+
showSystemTray: false,
|
|
32
|
+
multiArch: false,
|
|
33
|
+
targets: 'deb',
|
|
34
|
+
iterCopyFile: false,
|
|
35
|
+
systemTrayIcon: '',
|
|
36
|
+
debug: false,
|
|
37
|
+
inject: [],
|
|
38
|
+
safeDomain: [],
|
|
39
|
+
};
|
|
40
|
+
// Just for cli development
|
|
41
|
+
const DEFAULT_DEV_PAKE_OPTIONS = {
|
|
42
|
+
...DEFAULT_PAKE_OPTIONS,
|
|
43
|
+
url: 'https://weread.qq.com',
|
|
44
|
+
name: 'WeRead',
|
|
45
|
+
safeDomain: ['weread.qq.com'],
|
|
46
|
+
transparent: true,
|
|
45
47
|
};
|
|
46
48
|
|
|
47
|
-
const logger = {
|
|
48
|
-
info(...msg) {
|
|
49
|
-
log.info(...msg.map(m => chalk.white(m)));
|
|
50
|
-
},
|
|
51
|
-
debug(...msg) {
|
|
52
|
-
log.debug(...msg);
|
|
53
|
-
},
|
|
54
|
-
error(...msg) {
|
|
55
|
-
log.error(...msg.map(m => chalk.red(m)));
|
|
56
|
-
},
|
|
57
|
-
warn(...msg) {
|
|
58
|
-
log.info(...msg.map(m => chalk.yellow(m)));
|
|
59
|
-
},
|
|
60
|
-
success(...msg) {
|
|
61
|
-
log.info(...msg.map(m => chalk.green(m)));
|
|
62
|
-
},
|
|
49
|
+
const logger = {
|
|
50
|
+
info(...msg) {
|
|
51
|
+
log.info(...msg.map(m => chalk.white(m)));
|
|
52
|
+
},
|
|
53
|
+
debug(...msg) {
|
|
54
|
+
log.debug(...msg);
|
|
55
|
+
},
|
|
56
|
+
error(...msg) {
|
|
57
|
+
log.error(...msg.map(m => chalk.red(m)));
|
|
58
|
+
},
|
|
59
|
+
warn(...msg) {
|
|
60
|
+
log.info(...msg.map(m => chalk.yellow(m)));
|
|
61
|
+
},
|
|
62
|
+
success(...msg) {
|
|
63
|
+
log.info(...msg.map(m => chalk.green(m)));
|
|
64
|
+
},
|
|
63
65
|
};
|
|
64
66
|
|
|
65
|
-
// Convert the current module URL to a file path
|
|
66
|
-
const currentModulePath = fileURLToPath(import.meta.url);
|
|
67
|
-
// Resolve the parent directory of the current module
|
|
68
|
-
const npmDirectory = path.join(path.dirname(currentModulePath), '..');
|
|
69
|
-
const tauriConfigDirectory = path.join(npmDirectory, 'src-tauri');
|
|
67
|
+
// Convert the current module URL to a file path
|
|
68
|
+
const currentModulePath = fileURLToPath(import.meta.url);
|
|
69
|
+
// Resolve the parent directory of the current module
|
|
70
|
+
const npmDirectory = path.join(path.dirname(currentModulePath), '..');
|
|
71
|
+
const tauriConfigDirectory = path.join(npmDirectory, 'src-tauri', '.pake') ;
|
|
70
72
|
|
|
71
|
-
const { platform: platform$2 } = process;
|
|
72
|
-
const IS_MAC = platform$2 === 'darwin';
|
|
73
|
-
const IS_WIN = platform$2 === 'win32';
|
|
73
|
+
const { platform: platform$2 } = process;
|
|
74
|
+
const IS_MAC = platform$2 === 'darwin';
|
|
75
|
+
const IS_WIN = platform$2 === 'win32';
|
|
74
76
|
const IS_LINUX = platform$2 === 'linux';
|
|
75
77
|
|
|
76
|
-
// Generates an identifier based on the given URL.
|
|
77
|
-
function getIdentifier(url) {
|
|
78
|
-
const postFixHash = crypto.createHash('md5').update(url).digest('hex').substring(0, 6);
|
|
79
|
-
return `com.pake.${postFixHash}`;
|
|
80
|
-
}
|
|
81
|
-
async function promptText(message, initial) {
|
|
82
|
-
const response = await prompts({
|
|
83
|
-
type: 'text',
|
|
84
|
-
name: 'content',
|
|
85
|
-
message,
|
|
86
|
-
initial,
|
|
87
|
-
});
|
|
88
|
-
return response.content;
|
|
89
|
-
}
|
|
90
|
-
function capitalizeFirstLetter(string) {
|
|
91
|
-
return string.charAt(0).toUpperCase() + string.slice(1);
|
|
92
|
-
}
|
|
93
|
-
function getSpinner(text) {
|
|
94
|
-
const loadingType = {
|
|
95
|
-
interval: 80,
|
|
96
|
-
frames: ['✦', '✶', '✺', '✵', '✸', '✹', '✺'],
|
|
97
|
-
};
|
|
98
|
-
return ora({
|
|
99
|
-
text: `${chalk.cyan(text)}\n`,
|
|
100
|
-
spinner: loadingType,
|
|
101
|
-
color: 'cyan',
|
|
102
|
-
}).start();
|
|
78
|
+
// Generates an identifier based on the given URL.
|
|
79
|
+
function getIdentifier(url) {
|
|
80
|
+
const postFixHash = crypto.createHash('md5').update(url).digest('hex').substring(0, 6);
|
|
81
|
+
return `com.pake.${postFixHash}`;
|
|
82
|
+
}
|
|
83
|
+
async function promptText(message, initial) {
|
|
84
|
+
const response = await prompts({
|
|
85
|
+
type: 'text',
|
|
86
|
+
name: 'content',
|
|
87
|
+
message,
|
|
88
|
+
initial,
|
|
89
|
+
});
|
|
90
|
+
return response.content;
|
|
91
|
+
}
|
|
92
|
+
function capitalizeFirstLetter(string) {
|
|
93
|
+
return string.charAt(0).toUpperCase() + string.slice(1);
|
|
94
|
+
}
|
|
95
|
+
function getSpinner(text) {
|
|
96
|
+
const loadingType = {
|
|
97
|
+
interval: 80,
|
|
98
|
+
frames: ['✦', '✶', '✺', '✵', '✸', '✹', '✺'],
|
|
99
|
+
};
|
|
100
|
+
return ora({
|
|
101
|
+
text: `${chalk.cyan(text)}\n`,
|
|
102
|
+
spinner: loadingType,
|
|
103
|
+
color: 'cyan',
|
|
104
|
+
}).start();
|
|
103
105
|
}
|
|
104
106
|
|
|
105
|
-
async function handleIcon(options) {
|
|
106
|
-
if (options.icon) {
|
|
107
|
-
if (options.icon.startsWith('http')) {
|
|
108
|
-
return downloadIcon(options.icon);
|
|
109
|
-
}
|
|
110
|
-
else {
|
|
111
|
-
return path.resolve(options.icon);
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
else {
|
|
115
|
-
logger.warn('✼ No icon given, default in use. For a custom icon, use --icon option.');
|
|
116
|
-
const iconPath = IS_WIN
|
|
117
|
-
? 'src-tauri/png/icon_256.ico'
|
|
118
|
-
: IS_LINUX
|
|
119
|
-
? 'src-tauri/png/icon_512.png'
|
|
120
|
-
: 'src-tauri/icons/icon.icns';
|
|
121
|
-
return path.join(npmDirectory, iconPath);
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
async function downloadIcon(iconUrl) {
|
|
125
|
-
const spinner = getSpinner('Downloading icon...');
|
|
126
|
-
try {
|
|
127
|
-
const iconResponse = await axios.get(iconUrl, { responseType: 'arraybuffer' });
|
|
128
|
-
const iconData = await iconResponse.data;
|
|
129
|
-
if (!iconData) {
|
|
130
|
-
return null;
|
|
131
|
-
}
|
|
132
|
-
const fileDetails = await fileTypeFromBuffer(iconData);
|
|
133
|
-
if (!fileDetails) {
|
|
134
|
-
return null;
|
|
135
|
-
}
|
|
136
|
-
const { path: tempPath } = await dir();
|
|
137
|
-
let iconPath = `${tempPath}/icon.${fileDetails.ext}`;
|
|
138
|
-
// Fix this for linux
|
|
139
|
-
if (IS_LINUX) {
|
|
140
|
-
iconPath = 'png/linux_temp.png';
|
|
141
|
-
await fsExtra.outputFile(`${npmDirectory}/src-tauri/${iconPath}`, iconData);
|
|
142
|
-
}
|
|
143
|
-
else {
|
|
144
|
-
await fsExtra.outputFile(iconPath, iconData);
|
|
145
|
-
}
|
|
146
|
-
await fsExtra.outputFile(iconPath, iconData);
|
|
147
|
-
spinner.succeed(chalk.green('Icon downloaded successfully!'));
|
|
148
|
-
return iconPath;
|
|
149
|
-
}
|
|
150
|
-
catch (error) {
|
|
151
|
-
spinner.fail(chalk.red('Icon download failed!'));
|
|
152
|
-
if (error.response && error.response.status === 404) {
|
|
153
|
-
return null;
|
|
154
|
-
}
|
|
155
|
-
throw error;
|
|
156
|
-
}
|
|
107
|
+
async function handleIcon(options) {
|
|
108
|
+
if (options.icon) {
|
|
109
|
+
if (options.icon.startsWith('http')) {
|
|
110
|
+
return downloadIcon(options.icon);
|
|
111
|
+
}
|
|
112
|
+
else {
|
|
113
|
+
return path.resolve(options.icon);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
else {
|
|
117
|
+
logger.warn('✼ No icon given, default in use. For a custom icon, use --icon option.');
|
|
118
|
+
const iconPath = IS_WIN
|
|
119
|
+
? 'src-tauri/png/icon_256.ico'
|
|
120
|
+
: IS_LINUX
|
|
121
|
+
? 'src-tauri/png/icon_512.png'
|
|
122
|
+
: 'src-tauri/icons/icon.icns';
|
|
123
|
+
return path.join(npmDirectory, iconPath);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
async function downloadIcon(iconUrl) {
|
|
127
|
+
const spinner = getSpinner('Downloading icon...');
|
|
128
|
+
try {
|
|
129
|
+
const iconResponse = await axios.get(iconUrl, { responseType: 'arraybuffer' });
|
|
130
|
+
const iconData = await iconResponse.data;
|
|
131
|
+
if (!iconData) {
|
|
132
|
+
return null;
|
|
133
|
+
}
|
|
134
|
+
const fileDetails = await fileTypeFromBuffer(iconData);
|
|
135
|
+
if (!fileDetails) {
|
|
136
|
+
return null;
|
|
137
|
+
}
|
|
138
|
+
const { path: tempPath } = await dir();
|
|
139
|
+
let iconPath = `${tempPath}/icon.${fileDetails.ext}`;
|
|
140
|
+
// Fix this for linux
|
|
141
|
+
if (IS_LINUX) {
|
|
142
|
+
iconPath = 'png/linux_temp.png';
|
|
143
|
+
await fsExtra.outputFile(`${npmDirectory}/src-tauri/${iconPath}`, iconData);
|
|
144
|
+
}
|
|
145
|
+
else {
|
|
146
|
+
await fsExtra.outputFile(iconPath, iconData);
|
|
147
|
+
}
|
|
148
|
+
await fsExtra.outputFile(iconPath, iconData);
|
|
149
|
+
spinner.succeed(chalk.green('Icon downloaded successfully!'));
|
|
150
|
+
return iconPath;
|
|
151
|
+
}
|
|
152
|
+
catch (error) {
|
|
153
|
+
spinner.fail(chalk.red('Icon download failed!'));
|
|
154
|
+
if (error.response && error.response.status === 404) {
|
|
155
|
+
return null;
|
|
156
|
+
}
|
|
157
|
+
throw error;
|
|
158
|
+
}
|
|
157
159
|
}
|
|
158
160
|
|
|
159
|
-
// Extracts the domain from a given URL.
|
|
160
|
-
function getDomain(inputUrl) {
|
|
161
|
-
try {
|
|
162
|
-
const url = new URL(inputUrl);
|
|
163
|
-
// Use PSL to parse domain names.
|
|
164
|
-
const parsed = psl.parse(url.hostname);
|
|
165
|
-
// If domain is available, split it and return the SLD.
|
|
166
|
-
if ('domain' in parsed && parsed.domain) {
|
|
167
|
-
return parsed.domain.split('.')[0];
|
|
168
|
-
}
|
|
169
|
-
else {
|
|
170
|
-
return null;
|
|
171
|
-
}
|
|
172
|
-
}
|
|
173
|
-
catch (error) {
|
|
174
|
-
return null;
|
|
175
|
-
}
|
|
161
|
+
// Extracts the domain from a given URL.
|
|
162
|
+
function getDomain(inputUrl) {
|
|
163
|
+
try {
|
|
164
|
+
const url = new URL(inputUrl);
|
|
165
|
+
// Use PSL to parse domain names.
|
|
166
|
+
const parsed = psl.parse(url.hostname);
|
|
167
|
+
// If domain is available, split it and return the SLD.
|
|
168
|
+
if ('domain' in parsed && parsed.domain) {
|
|
169
|
+
return parsed.domain.split('.')[0];
|
|
170
|
+
}
|
|
171
|
+
else {
|
|
172
|
+
return null;
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
catch (error) {
|
|
176
|
+
return null;
|
|
177
|
+
}
|
|
176
178
|
}
|
|
177
179
|
|
|
178
|
-
function resolveAppName(name, platform) {
|
|
179
|
-
const domain = getDomain(name) || 'pake';
|
|
180
|
-
return platform !== 'linux' ? capitalizeFirstLetter(domain) : domain;
|
|
181
|
-
}
|
|
182
|
-
function isValidName(name, platform) {
|
|
183
|
-
const platformRegexMapping = {
|
|
184
|
-
linux: /^[a-z0-9]+(-[a-z0-9]+)*$/,
|
|
185
|
-
default: /^[a-zA-Z0-9]
|
|
186
|
-
};
|
|
187
|
-
const reg = platformRegexMapping[platform] || platformRegexMapping.default;
|
|
188
|
-
return !!name && reg.test(name);
|
|
189
|
-
}
|
|
190
|
-
async function handleOptions(options, url) {
|
|
191
|
-
const { platform } = process;
|
|
192
|
-
const isActions = process.env.GITHUB_ACTIONS;
|
|
193
|
-
let name = options.name;
|
|
194
|
-
const pathExists = await fsExtra.pathExists(url);
|
|
195
|
-
if (!options.name) {
|
|
196
|
-
const defaultName = pathExists ? '' : resolveAppName(url, platform);
|
|
197
|
-
const promptMessage = 'Enter your application name';
|
|
198
|
-
const namePrompt = await promptText(promptMessage, defaultName);
|
|
199
|
-
name = namePrompt || defaultName;
|
|
200
|
-
}
|
|
201
|
-
if (!isValidName(name, platform)) {
|
|
202
|
-
const LINUX_NAME_ERROR = `✕ name should only include lowercase letters, numbers, and dashes, and must contain at least one lowercase letter. Examples: com-123-xxx, 123pan, pan123, weread, we-read.`;
|
|
203
|
-
const DEFAULT_NAME_ERROR = `✕ Name should only include letters and numbers, and must contain at least one letter. Examples: 123pan, 123Pan, Pan123, weread, WeRead, WERead.`;
|
|
204
|
-
const errorMsg = platform === 'linux' ? LINUX_NAME_ERROR : DEFAULT_NAME_ERROR;
|
|
205
|
-
logger.error(errorMsg);
|
|
206
|
-
if (isActions) {
|
|
207
|
-
name = resolveAppName(url, platform);
|
|
208
|
-
logger.warn(`✼ Inside github actions, use the default name: ${name}`);
|
|
209
|
-
}
|
|
210
|
-
else {
|
|
211
|
-
process.exit(1);
|
|
212
|
-
}
|
|
213
|
-
}
|
|
214
|
-
const appOptions = {
|
|
215
|
-
...options,
|
|
216
|
-
name,
|
|
217
|
-
identifier: getIdentifier(url),
|
|
218
|
-
};
|
|
219
|
-
appOptions.icon = await handleIcon(appOptions);
|
|
220
|
-
return appOptions;
|
|
180
|
+
function resolveAppName(name, platform) {
|
|
181
|
+
const domain = getDomain(name) || 'pake';
|
|
182
|
+
return platform !== 'linux' ? capitalizeFirstLetter(domain) : domain;
|
|
183
|
+
}
|
|
184
|
+
function isValidName(name, platform) {
|
|
185
|
+
const platformRegexMapping = {
|
|
186
|
+
linux: /^[a-z0-9]+(-[a-z0-9]+)*$/,
|
|
187
|
+
default: /^[a-zA-Z0-9]+([-a-zA-Z0-9])*$/,
|
|
188
|
+
};
|
|
189
|
+
const reg = platformRegexMapping[platform] || platformRegexMapping.default;
|
|
190
|
+
return !!name && reg.test(name);
|
|
191
|
+
}
|
|
192
|
+
async function handleOptions(options, url) {
|
|
193
|
+
const { platform } = process;
|
|
194
|
+
const isActions = process.env.GITHUB_ACTIONS;
|
|
195
|
+
let name = options.name;
|
|
196
|
+
const pathExists = await fsExtra.pathExists(url);
|
|
197
|
+
if (!options.name) {
|
|
198
|
+
const defaultName = pathExists ? '' : resolveAppName(url, platform);
|
|
199
|
+
const promptMessage = 'Enter your application name';
|
|
200
|
+
const namePrompt = await promptText(promptMessage, defaultName);
|
|
201
|
+
name = namePrompt || defaultName;
|
|
202
|
+
}
|
|
203
|
+
if (!isValidName(name, platform)) {
|
|
204
|
+
const LINUX_NAME_ERROR = `✕ name should only include lowercase letters, numbers, and dashes, and must contain at least one lowercase letter. Examples: com-123-xxx, 123pan, pan123, weread, we-read.`;
|
|
205
|
+
const DEFAULT_NAME_ERROR = `✕ Name should only include letters and numbers, and dashes (dashes must not at the beginning), and must contain at least one letter. Examples: 123pan, 123Pan, Pan123, weread, WeRead, WERead, we-read.`;
|
|
206
|
+
const errorMsg = platform === 'linux' ? LINUX_NAME_ERROR : DEFAULT_NAME_ERROR;
|
|
207
|
+
logger.error(errorMsg);
|
|
208
|
+
if (isActions) {
|
|
209
|
+
name = resolveAppName(url, platform);
|
|
210
|
+
logger.warn(`✼ Inside github actions, use the default name: ${name}`);
|
|
211
|
+
}
|
|
212
|
+
else {
|
|
213
|
+
process.exit(1);
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
const appOptions = {
|
|
217
|
+
...options,
|
|
218
|
+
name,
|
|
219
|
+
identifier: getIdentifier(url),
|
|
220
|
+
};
|
|
221
|
+
appOptions.icon = await handleIcon(appOptions);
|
|
222
|
+
return appOptions;
|
|
221
223
|
}
|
|
222
224
|
|
|
223
225
|
var windows = [
|
|
224
226
|
{
|
|
225
|
-
url: "https://weread.qq.com
|
|
227
|
+
url: "https://weread.qq.com",
|
|
228
|
+
url_type: "web",
|
|
226
229
|
transparent: true,
|
|
227
230
|
fullscreen: false,
|
|
228
231
|
width: 1200,
|
|
229
232
|
height: 780,
|
|
230
233
|
resizable: true,
|
|
231
|
-
|
|
234
|
+
always_on_top: false,
|
|
235
|
+
activation_shortcut: "",
|
|
236
|
+
disabled_web_shortcuts: false
|
|
232
237
|
}
|
|
233
238
|
];
|
|
234
239
|
var user_agent = {
|
|
@@ -236,11 +241,6 @@ var user_agent = {
|
|
|
236
241
|
linux: "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36",
|
|
237
242
|
windows: "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36"
|
|
238
243
|
};
|
|
239
|
-
var menu = {
|
|
240
|
-
macos: false,
|
|
241
|
-
linux: false,
|
|
242
|
-
windows: false
|
|
243
|
-
};
|
|
244
244
|
var system_tray = {
|
|
245
245
|
macos: false,
|
|
246
246
|
linux: true,
|
|
@@ -251,7 +251,6 @@ var inject = [
|
|
|
251
251
|
var pakeConf = {
|
|
252
252
|
windows: windows,
|
|
253
253
|
user_agent: user_agent,
|
|
254
|
-
menu: menu,
|
|
255
254
|
system_tray: system_tray,
|
|
256
255
|
inject: inject
|
|
257
256
|
};
|
|
@@ -274,7 +273,7 @@ var tauri$3 = {
|
|
|
274
273
|
},
|
|
275
274
|
systemTray: {
|
|
276
275
|
iconPath: "png/icon_512.png",
|
|
277
|
-
iconAsTemplate:
|
|
276
|
+
iconAsTemplate: false
|
|
278
277
|
},
|
|
279
278
|
allowlist: {
|
|
280
279
|
all: true,
|
|
@@ -405,469 +404,475 @@ var LinuxConf = {
|
|
|
405
404
|
tauri: tauri
|
|
406
405
|
};
|
|
407
406
|
|
|
408
|
-
const platformConfigs = {
|
|
409
|
-
win32: WinConf,
|
|
410
|
-
darwin: MacConf,
|
|
411
|
-
linux: LinuxConf,
|
|
412
|
-
};
|
|
413
|
-
const { platform: platform$1 } = process;
|
|
414
|
-
// @ts-ignore
|
|
415
|
-
const platformConfig = platformConfigs[platform$1];
|
|
416
|
-
let tauriConfig = {
|
|
417
|
-
tauri: {
|
|
418
|
-
...CommonConf.tauri,
|
|
419
|
-
bundle: platformConfig.tauri.bundle,
|
|
420
|
-
},
|
|
421
|
-
package: CommonConf.package,
|
|
422
|
-
build: CommonConf.build,
|
|
423
|
-
pake: pakeConf,
|
|
407
|
+
const platformConfigs = {
|
|
408
|
+
win32: WinConf,
|
|
409
|
+
darwin: MacConf,
|
|
410
|
+
linux: LinuxConf,
|
|
411
|
+
};
|
|
412
|
+
const { platform: platform$1 } = process;
|
|
413
|
+
// @ts-ignore
|
|
414
|
+
const platformConfig = platformConfigs[platform$1];
|
|
415
|
+
let tauriConfig = {
|
|
416
|
+
tauri: {
|
|
417
|
+
...CommonConf.tauri,
|
|
418
|
+
bundle: platformConfig.tauri.bundle,
|
|
419
|
+
},
|
|
420
|
+
package: CommonConf.package,
|
|
421
|
+
build: CommonConf.build,
|
|
422
|
+
pake: pakeConf,
|
|
424
423
|
};
|
|
425
424
|
|
|
426
|
-
function shellExec(command) {
|
|
427
|
-
return new Promise((resolve, reject) => {
|
|
428
|
-
shelljs.exec(command, { async: true, silent: false, cwd: npmDirectory }, code => {
|
|
429
|
-
if (code === 0) {
|
|
430
|
-
resolve(0);
|
|
431
|
-
}
|
|
432
|
-
else {
|
|
433
|
-
reject(new Error(`${code}`));
|
|
434
|
-
}
|
|
435
|
-
});
|
|
436
|
-
});
|
|
425
|
+
function shellExec(command) {
|
|
426
|
+
return new Promise((resolve, reject) => {
|
|
427
|
+
shelljs.exec(command, { async: true, silent: false, cwd: npmDirectory }, code => {
|
|
428
|
+
if (code === 0) {
|
|
429
|
+
resolve(0);
|
|
430
|
+
}
|
|
431
|
+
else {
|
|
432
|
+
reject(new Error(`${code}`));
|
|
433
|
+
}
|
|
434
|
+
});
|
|
435
|
+
});
|
|
437
436
|
}
|
|
438
437
|
|
|
439
|
-
const resolve = promisify(dns.resolve);
|
|
440
|
-
const ping = async (host) => {
|
|
441
|
-
const lookup = promisify(dns.lookup);
|
|
442
|
-
const ip = await lookup(host);
|
|
443
|
-
const start = new Date();
|
|
444
|
-
// Prevent timeouts from affecting user experience.
|
|
445
|
-
const requestPromise = new Promise((resolve, reject) => {
|
|
446
|
-
const req = http.get(`http://${ip.address}`, res => {
|
|
447
|
-
const delay = new Date().getTime() - start.getTime();
|
|
448
|
-
res.resume();
|
|
449
|
-
resolve(delay);
|
|
450
|
-
});
|
|
451
|
-
req.on('error', err => {
|
|
452
|
-
reject(err);
|
|
453
|
-
});
|
|
454
|
-
});
|
|
455
|
-
const timeoutPromise = new Promise((_, reject) => {
|
|
456
|
-
setTimeout(() => {
|
|
457
|
-
reject(new Error('Request timed out after 3 seconds'));
|
|
458
|
-
}, 1000);
|
|
459
|
-
});
|
|
460
|
-
return Promise.race([requestPromise, timeoutPromise]);
|
|
461
|
-
};
|
|
462
|
-
async function isChinaDomain(domain) {
|
|
463
|
-
try {
|
|
464
|
-
const [ip] = await resolve(domain);
|
|
465
|
-
return await isChinaIP(ip, domain);
|
|
466
|
-
}
|
|
467
|
-
catch (error) {
|
|
468
|
-
logger.debug(`${domain} can't be parse!`);
|
|
469
|
-
return true;
|
|
470
|
-
}
|
|
471
|
-
}
|
|
472
|
-
async function isChinaIP(ip, domain) {
|
|
473
|
-
try {
|
|
474
|
-
const delay = await ping(ip);
|
|
475
|
-
logger.debug(`${domain} latency is ${delay} ms`);
|
|
476
|
-
return delay >
|
|
477
|
-
}
|
|
478
|
-
catch (error) {
|
|
479
|
-
logger.debug(`ping ${domain} failed!`);
|
|
480
|
-
return true;
|
|
481
|
-
}
|
|
438
|
+
const resolve = promisify(dns.resolve);
|
|
439
|
+
const ping = async (host) => {
|
|
440
|
+
const lookup = promisify(dns.lookup);
|
|
441
|
+
const ip = await lookup(host);
|
|
442
|
+
const start = new Date();
|
|
443
|
+
// Prevent timeouts from affecting user experience.
|
|
444
|
+
const requestPromise = new Promise((resolve, reject) => {
|
|
445
|
+
const req = http.get(`http://${ip.address}`, res => {
|
|
446
|
+
const delay = new Date().getTime() - start.getTime();
|
|
447
|
+
res.resume();
|
|
448
|
+
resolve(delay);
|
|
449
|
+
});
|
|
450
|
+
req.on('error', err => {
|
|
451
|
+
reject(err);
|
|
452
|
+
});
|
|
453
|
+
});
|
|
454
|
+
const timeoutPromise = new Promise((_, reject) => {
|
|
455
|
+
setTimeout(() => {
|
|
456
|
+
reject(new Error('Request timed out after 3 seconds'));
|
|
457
|
+
}, 1000);
|
|
458
|
+
});
|
|
459
|
+
return Promise.race([requestPromise, timeoutPromise]);
|
|
460
|
+
};
|
|
461
|
+
async function isChinaDomain(domain) {
|
|
462
|
+
try {
|
|
463
|
+
const [ip] = await resolve(domain);
|
|
464
|
+
return await isChinaIP(ip, domain);
|
|
465
|
+
}
|
|
466
|
+
catch (error) {
|
|
467
|
+
logger.debug(`${domain} can't be parse!`);
|
|
468
|
+
return true;
|
|
469
|
+
}
|
|
470
|
+
}
|
|
471
|
+
async function isChinaIP(ip, domain) {
|
|
472
|
+
try {
|
|
473
|
+
const delay = await ping(ip);
|
|
474
|
+
logger.debug(`${domain} latency is ${delay} ms`);
|
|
475
|
+
return delay > 500;
|
|
476
|
+
}
|
|
477
|
+
catch (error) {
|
|
478
|
+
logger.debug(`ping ${domain} failed!`);
|
|
479
|
+
return true;
|
|
480
|
+
}
|
|
482
481
|
}
|
|
483
482
|
|
|
484
|
-
async function installRust() {
|
|
485
|
-
const isActions = process.env.GITHUB_ACTIONS;
|
|
486
|
-
const isInChina = await isChinaDomain('sh.rustup.rs');
|
|
487
|
-
const rustInstallScriptForMac = isInChina && !isActions
|
|
488
|
-
? 'export RUSTUP_DIST_SERVER="https://rsproxy.cn" && export RUSTUP_UPDATE_ROOT="https://rsproxy.cn/rustup" && curl --proto "=https" --tlsv1.2 -sSf https://rsproxy.cn/rustup-init.sh | sh'
|
|
489
|
-
: "curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y";
|
|
490
|
-
const rustInstallScriptForWindows = 'winget install --id Rustlang.Rustup';
|
|
491
|
-
const spinner = getSpinner('Downloading Rust...');
|
|
492
|
-
try {
|
|
493
|
-
await shellExec(IS_WIN ? rustInstallScriptForWindows : rustInstallScriptForMac);
|
|
494
|
-
spinner.succeed(chalk.green('Rust installed successfully!'));
|
|
495
|
-
}
|
|
496
|
-
catch (error) {
|
|
497
|
-
console.error('Error installing Rust:', error.message);
|
|
498
|
-
spinner.fail(chalk.red('Rust installation failed!'));
|
|
499
|
-
process.exit(1);
|
|
500
|
-
}
|
|
501
|
-
}
|
|
502
|
-
function checkRustInstalled() {
|
|
503
|
-
return shelljs.exec('rustc --version', { silent: true }).code === 0;
|
|
483
|
+
async function installRust() {
|
|
484
|
+
const isActions = process.env.GITHUB_ACTIONS;
|
|
485
|
+
const isInChina = await isChinaDomain('sh.rustup.rs');
|
|
486
|
+
const rustInstallScriptForMac = isInChina && !isActions
|
|
487
|
+
? 'export RUSTUP_DIST_SERVER="https://rsproxy.cn" && export RUSTUP_UPDATE_ROOT="https://rsproxy.cn/rustup" && curl --proto "=https" --tlsv1.2 -sSf https://rsproxy.cn/rustup-init.sh | sh'
|
|
488
|
+
: "curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y";
|
|
489
|
+
const rustInstallScriptForWindows = 'winget install --id Rustlang.Rustup';
|
|
490
|
+
const spinner = getSpinner('Downloading Rust...');
|
|
491
|
+
try {
|
|
492
|
+
await shellExec(IS_WIN ? rustInstallScriptForWindows : rustInstallScriptForMac);
|
|
493
|
+
spinner.succeed(chalk.green('Rust installed successfully!'));
|
|
494
|
+
}
|
|
495
|
+
catch (error) {
|
|
496
|
+
console.error('Error installing Rust:', error.message);
|
|
497
|
+
spinner.fail(chalk.red('Rust installation failed!'));
|
|
498
|
+
process.exit(1);
|
|
499
|
+
}
|
|
500
|
+
}
|
|
501
|
+
function checkRustInstalled() {
|
|
502
|
+
return shelljs.exec('rustc --version', { silent: true }).code === 0;
|
|
504
503
|
}
|
|
505
504
|
|
|
506
|
-
async function combineFiles(files, output) {
|
|
507
|
-
const contents = files.map(file => {
|
|
508
|
-
const fileContent = fs.readFileSync(file);
|
|
509
|
-
if (file.endsWith('.css')) {
|
|
510
|
-
return "window.addEventListener('DOMContentLoaded', (_event) => { const css = `" + fileContent + "`; const style = document.createElement('style'); style.innerHTML = css; document.head.appendChild(style); });";
|
|
511
|
-
}
|
|
512
|
-
return "window.addEventListener('DOMContentLoaded', (_event) => { " + fileContent + " });";
|
|
513
|
-
});
|
|
514
|
-
fs.writeFileSync(output, contents.join('\n'));
|
|
515
|
-
return files;
|
|
505
|
+
async function combineFiles(files, output) {
|
|
506
|
+
const contents = files.map(file => {
|
|
507
|
+
const fileContent = fs.readFileSync(file);
|
|
508
|
+
if (file.endsWith('.css')) {
|
|
509
|
+
return "window.addEventListener('DOMContentLoaded', (_event) => { const css = `" + fileContent + "`; const style = document.createElement('style'); style.innerHTML = css; document.head.appendChild(style); });";
|
|
510
|
+
}
|
|
511
|
+
return "window.addEventListener('DOMContentLoaded', (_event) => { " + fileContent + " });";
|
|
512
|
+
});
|
|
513
|
+
fs.writeFileSync(output, contents.join('\n'));
|
|
514
|
+
return files;
|
|
516
515
|
}
|
|
517
516
|
|
|
518
|
-
async function mergeConfig(url, options, tauriConf) {
|
|
519
|
-
const { width, height, fullscreen, transparent,
|
|
520
|
-
const { platform } = process;
|
|
521
|
-
// Set Windows parameters.
|
|
522
|
-
const tauriConfWindowOptions = {
|
|
523
|
-
width,
|
|
524
|
-
height,
|
|
525
|
-
fullscreen,
|
|
526
|
-
transparent,
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
tauriConf.
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
const
|
|
540
|
-
const
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
tauriConf.pake.windows[0].
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
}
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
}
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
}
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
}
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
const
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
517
|
+
async function mergeConfig(url, options, tauriConf) {
|
|
518
|
+
const { width, height, fullscreen, transparent, alwaysOnTop, disabledWebShortcuts, userAgent, showSystemTray, systemTrayIcon, iterCopyFile, identifier, name, resizable = true, inject, safeDomain, } = options;
|
|
519
|
+
const { platform } = process;
|
|
520
|
+
// Set Windows parameters.
|
|
521
|
+
const tauriConfWindowOptions = {
|
|
522
|
+
width,
|
|
523
|
+
height,
|
|
524
|
+
fullscreen,
|
|
525
|
+
transparent,
|
|
526
|
+
alwaysOnTop,
|
|
527
|
+
disabledWebShortcuts,
|
|
528
|
+
resizable,
|
|
529
|
+
};
|
|
530
|
+
Object.assign(tauriConf.pake.windows[0], { url, ...tauriConfWindowOptions });
|
|
531
|
+
tauriConf.package.productName = name;
|
|
532
|
+
tauriConf.tauri.bundle.identifier = identifier;
|
|
533
|
+
//Judge the type of URL, whether it is a file or a website.
|
|
534
|
+
const pathExists = await fsExtra.pathExists(url);
|
|
535
|
+
if (pathExists) {
|
|
536
|
+
logger.warn('✼ Your input might be a local file.');
|
|
537
|
+
tauriConf.pake.windows[0].url_type = 'local';
|
|
538
|
+
const fileName = path.basename(url);
|
|
539
|
+
const dirName = path.dirname(url);
|
|
540
|
+
const distDir = path.join(npmDirectory, 'dist');
|
|
541
|
+
const distBakDir = path.join(npmDirectory, 'dist_bak');
|
|
542
|
+
if (!iterCopyFile) {
|
|
543
|
+
const urlPath = path.join(distDir, fileName);
|
|
544
|
+
await fsExtra.copy(url, urlPath);
|
|
545
|
+
}
|
|
546
|
+
else {
|
|
547
|
+
fsExtra.moveSync(distDir, distBakDir, { overwrite: true });
|
|
548
|
+
fsExtra.copySync(dirName, distDir, { overwrite: true });
|
|
549
|
+
// ignore it, because about_pake.html have be erased.
|
|
550
|
+
// const filesToCopyBack = ['cli.js', 'about_pake.html'];
|
|
551
|
+
const filesToCopyBack = ['cli.js'];
|
|
552
|
+
await Promise.all(filesToCopyBack.map(file => fsExtra.copy(path.join(distBakDir, file), path.join(distDir, file))));
|
|
553
|
+
}
|
|
554
|
+
tauriConf.pake.windows[0].url = fileName;
|
|
555
|
+
tauriConf.pake.windows[0].url_type = 'local';
|
|
556
|
+
}
|
|
557
|
+
else {
|
|
558
|
+
tauriConf.pake.windows[0].url_type = 'web';
|
|
559
|
+
// Set the secure domain for calling window.__TAURI__ to the application domain that has been set.
|
|
560
|
+
tauriConf.tauri.security.dangerousRemoteDomainIpcAccess = [
|
|
561
|
+
{
|
|
562
|
+
domain: new URL(url).hostname,
|
|
563
|
+
windows: ['pake'],
|
|
564
|
+
enableTauriAPI: true,
|
|
565
|
+
},
|
|
566
|
+
];
|
|
567
|
+
}
|
|
568
|
+
if (safeDomain.length > 0) {
|
|
569
|
+
tauriConf.tauri.security.dangerousRemoteDomainIpcAccess = [
|
|
570
|
+
...tauriConf.tauri.security.dangerousRemoteDomainIpcAccess,
|
|
571
|
+
...safeDomain.map(domain => ({
|
|
572
|
+
domain,
|
|
573
|
+
windows: ['pake'],
|
|
574
|
+
enableTauriAPI: true,
|
|
575
|
+
})),
|
|
576
|
+
];
|
|
577
|
+
}
|
|
578
|
+
const platformMap = {
|
|
579
|
+
win32: 'windows',
|
|
580
|
+
linux: 'linux',
|
|
581
|
+
darwin: 'macos',
|
|
582
|
+
};
|
|
583
|
+
const currentPlatform = platformMap[platform];
|
|
584
|
+
if (userAgent.length > 0) {
|
|
585
|
+
tauriConf.pake.user_agent[currentPlatform] = userAgent;
|
|
586
|
+
}
|
|
587
|
+
tauriConf.pake.system_tray[currentPlatform] = showSystemTray;
|
|
588
|
+
// Processing targets are currently only open to Linux.
|
|
589
|
+
if (platform === 'linux') {
|
|
590
|
+
delete tauriConf.tauri.bundle.deb.files;
|
|
591
|
+
const validTargets = ['all', 'deb', 'appimage'];
|
|
592
|
+
if (validTargets.includes(options.targets)) {
|
|
593
|
+
tauriConf.tauri.bundle.targets = options.targets === 'all' ? ['deb', 'appimage'] : [options.targets];
|
|
594
|
+
}
|
|
595
|
+
else {
|
|
596
|
+
logger.warn(`✼ The target must be one of ${validTargets.join(', ')}, the default 'deb' will be used.`);
|
|
597
|
+
}
|
|
598
|
+
}
|
|
599
|
+
// Set icon.
|
|
600
|
+
const platformIconMap = {
|
|
601
|
+
win32: {
|
|
602
|
+
fileExt: '.ico',
|
|
603
|
+
path: `png/${name.toLowerCase()}_256.ico`,
|
|
604
|
+
defaultIcon: 'png/icon_256.ico',
|
|
605
|
+
message: 'Windows icon must be .ico and 256x256px.',
|
|
606
|
+
},
|
|
607
|
+
linux: {
|
|
608
|
+
fileExt: '.png',
|
|
609
|
+
path: `png/${name.toLowerCase()}_512.png`,
|
|
610
|
+
defaultIcon: 'png/icon_512.png',
|
|
611
|
+
message: 'Linux icon must be .png and 512x512px.',
|
|
612
|
+
},
|
|
613
|
+
darwin: {
|
|
614
|
+
fileExt: '.icns',
|
|
615
|
+
path: `icons/${name.toLowerCase()}.icns`,
|
|
616
|
+
defaultIcon: 'icons/icon.icns',
|
|
617
|
+
message: 'macOS icon must be .icns type.',
|
|
618
|
+
},
|
|
619
|
+
};
|
|
620
|
+
const iconInfo = platformIconMap[platform];
|
|
621
|
+
const exists = await fsExtra.pathExists(options.icon);
|
|
622
|
+
if (exists) {
|
|
623
|
+
let updateIconPath = true;
|
|
624
|
+
let customIconExt = path.extname(options.icon).toLowerCase();
|
|
625
|
+
if (customIconExt !== iconInfo.fileExt) {
|
|
626
|
+
updateIconPath = false;
|
|
627
|
+
logger.warn(`✼ ${iconInfo.message}, but you give ${customIconExt}`);
|
|
628
|
+
tauriConf.tauri.bundle.icon = [iconInfo.defaultIcon];
|
|
629
|
+
}
|
|
630
|
+
else {
|
|
631
|
+
const iconPath = path.join(npmDirectory, 'src-tauri/', iconInfo.path);
|
|
632
|
+
tauriConf.tauri.bundle.resources = [iconInfo.path];
|
|
633
|
+
await fsExtra.copy(options.icon, iconPath);
|
|
634
|
+
}
|
|
635
|
+
if (updateIconPath) {
|
|
636
|
+
tauriConf.tauri.bundle.icon = [options.icon];
|
|
637
|
+
}
|
|
638
|
+
else {
|
|
639
|
+
logger.warn(`✼ Icon will remain as default.`);
|
|
640
|
+
}
|
|
641
|
+
}
|
|
642
|
+
else {
|
|
643
|
+
logger.warn('✼ Custom icon path may be invalid, default icon will be used instead.');
|
|
644
|
+
tauriConf.tauri.bundle.icon = [iconInfo.defaultIcon];
|
|
645
|
+
}
|
|
646
|
+
// Set tray icon path.
|
|
647
|
+
let trayIconPath = platform === 'darwin' ? 'png/icon_512.png' : tauriConf.tauri.bundle.icon[0];
|
|
648
|
+
if (systemTrayIcon.length > 0) {
|
|
649
|
+
try {
|
|
650
|
+
await fsExtra.pathExists(systemTrayIcon);
|
|
651
|
+
// 需要判断图标格式,默认只支持ico和png两种
|
|
652
|
+
let iconExt = path.extname(systemTrayIcon).toLowerCase();
|
|
653
|
+
if (iconExt == '.png' || iconExt == '.ico') {
|
|
654
|
+
const trayIcoPath = path.join(npmDirectory, `src-tauri/png/${name.toLowerCase()}${iconExt}`);
|
|
655
|
+
trayIconPath = `png/${name.toLowerCase()}${iconExt}`;
|
|
656
|
+
await fsExtra.copy(systemTrayIcon, trayIcoPath);
|
|
657
|
+
}
|
|
658
|
+
else {
|
|
659
|
+
logger.warn(`✼ System tray icon must be .ico or .png, but you provided ${iconExt}.`);
|
|
660
|
+
logger.warn(`✼ Default system tray icon will be used.`);
|
|
661
|
+
}
|
|
662
|
+
}
|
|
663
|
+
catch {
|
|
664
|
+
logger.warn(`✼ ${systemTrayIcon} not exists!`);
|
|
665
|
+
logger.warn(`✼ Default system tray icon will remain unchanged.`);
|
|
666
|
+
}
|
|
667
|
+
}
|
|
668
|
+
tauriConf.tauri.systemTray.iconPath = trayIconPath;
|
|
669
|
+
const injectFilePath = path.join(npmDirectory, `src-tauri/src/inject/custom.js`);
|
|
670
|
+
// inject js or css files
|
|
671
|
+
if (inject?.length > 0) {
|
|
672
|
+
if (!inject.every(item => item.endsWith('.css') || item.endsWith('.js'))) {
|
|
673
|
+
logger.error('The injected file must be in either CSS or JS format.');
|
|
674
|
+
return;
|
|
675
|
+
}
|
|
676
|
+
const files = inject.map(filepath => path.isAbsolute(filepath) ? filepath : path.join(process.cwd(), filepath));
|
|
677
|
+
tauriConf.pake.inject = files;
|
|
678
|
+
await combineFiles(files, injectFilePath);
|
|
679
|
+
}
|
|
680
|
+
else {
|
|
681
|
+
tauriConf.pake.inject = [];
|
|
682
|
+
await fsExtra.writeFile(injectFilePath, '');
|
|
683
|
+
}
|
|
684
|
+
// Save config file.
|
|
685
|
+
const platformConfigPaths = {
|
|
686
|
+
win32: 'tauri.windows.conf.json',
|
|
687
|
+
darwin: 'tauri.macos.conf.json',
|
|
688
|
+
linux: 'tauri.linux.conf.json',
|
|
689
|
+
};
|
|
690
|
+
const configPath = path.join(tauriConfigDirectory, platformConfigPaths[platform]);
|
|
691
|
+
const bundleConf = { tauri: { bundle: tauriConf.tauri.bundle } };
|
|
692
|
+
await fsExtra.outputJSON(configPath, bundleConf, { spaces: 4 });
|
|
693
|
+
const pakeConfigPath = path.join(tauriConfigDirectory, 'pake.json');
|
|
694
|
+
await fsExtra.outputJSON(pakeConfigPath, tauriConf.pake, { spaces: 4 });
|
|
695
|
+
let tauriConf2 = JSON.parse(JSON.stringify(tauriConf));
|
|
696
|
+
delete tauriConf2.pake;
|
|
697
|
+
delete tauriConf2.tauri.bundle;
|
|
698
|
+
{
|
|
699
|
+
tauriConf2.tauri.bundle = bundleConf.tauri.bundle;
|
|
700
|
+
}
|
|
701
|
+
const configJsonPath = path.join(tauriConfigDirectory, 'tauri.conf.json');
|
|
702
|
+
await fsExtra.outputJSON(configJsonPath, tauriConf2, { spaces: 4 });
|
|
698
703
|
}
|
|
699
704
|
|
|
700
|
-
class BaseBuilder {
|
|
701
|
-
constructor(options) {
|
|
702
|
-
this.options = options;
|
|
703
|
-
}
|
|
704
|
-
async prepare() {
|
|
705
|
-
const tauriSrcPath = path.join(npmDirectory, 'src-tauri');
|
|
706
|
-
const tauriTargetPath = path.join(tauriSrcPath, 'target');
|
|
707
|
-
const tauriTargetPathExists = await fsExtra.pathExists(tauriTargetPath);
|
|
708
|
-
if (!IS_MAC && !tauriTargetPathExists) {
|
|
709
|
-
logger.warn('✼ The first use requires installing system dependencies.');
|
|
710
|
-
logger.warn('✼ See more in https://tauri.app/v1/guides/getting-started/prerequisites.');
|
|
711
|
-
}
|
|
712
|
-
if (!checkRustInstalled()) {
|
|
713
|
-
const res = await prompts({
|
|
714
|
-
type: 'confirm',
|
|
715
|
-
message: 'Rust not detected. Install now?',
|
|
716
|
-
name: 'value',
|
|
717
|
-
});
|
|
718
|
-
if (res.value) {
|
|
719
|
-
await installRust();
|
|
720
|
-
}
|
|
721
|
-
else {
|
|
722
|
-
logger.error('✕ Rust required to package your webapp.');
|
|
723
|
-
process.exit(0);
|
|
724
|
-
}
|
|
725
|
-
}
|
|
726
|
-
const isChina = await isChinaDomain('www.npmjs.com');
|
|
727
|
-
const spinner = getSpinner('Installing package...');
|
|
728
|
-
const rustProjectDir = path.join(tauriSrcPath, '.cargo');
|
|
729
|
-
const projectConf = path.join(rustProjectDir, 'config');
|
|
730
|
-
await fsExtra.ensureDir(rustProjectDir);
|
|
731
|
-
if (isChina) {
|
|
732
|
-
logger.info('✺ Located in China, using npm/rsProxy CN mirror.');
|
|
733
|
-
const projectCnConf = path.join(tauriSrcPath, 'rust_proxy.toml');
|
|
734
|
-
await fsExtra.copy(projectCnConf, projectConf);
|
|
735
|
-
await shellExec(`cd "${npmDirectory}" && npm install --registry=https://registry.npmmirror.com`);
|
|
736
|
-
}
|
|
737
|
-
else {
|
|
738
|
-
await shellExec(`cd "${npmDirectory}" && npm install`);
|
|
739
|
-
}
|
|
740
|
-
spinner.succeed(chalk.green('Package installed!'));
|
|
741
|
-
if (!tauriTargetPathExists) {
|
|
742
|
-
logger.warn('✼ The first packaging may be slow, please be patient and wait, it will be faster afterwards.');
|
|
743
|
-
}
|
|
744
|
-
}
|
|
745
|
-
async build(url) {
|
|
746
|
-
await this.buildAndCopy(url, this.options.targets);
|
|
747
|
-
}
|
|
748
|
-
async start(url) {
|
|
749
|
-
await mergeConfig(url, this.options, tauriConfig);
|
|
750
|
-
}
|
|
751
|
-
async buildAndCopy(url, target) {
|
|
752
|
-
const { name } = this.options;
|
|
753
|
-
await mergeConfig(url, this.options, tauriConfig);
|
|
754
|
-
// Build app
|
|
755
|
-
const spinner = getSpinner('Building app...');
|
|
756
|
-
setTimeout(() => spinner.stop(), 3000);
|
|
757
|
-
await shellExec(`cd "${npmDirectory}" && ${this.getBuildCommand()}`);
|
|
758
|
-
// Copy app
|
|
759
|
-
const fileName = this.getFileName();
|
|
760
|
-
const fileType = this.getFileType(target);
|
|
761
|
-
const appPath = this.getBuildAppPath(npmDirectory, fileName, fileType);
|
|
762
|
-
const distPath = path.resolve(`${name}.${fileType}`);
|
|
763
|
-
await fsExtra.copy(appPath, distPath);
|
|
764
|
-
await fsExtra.remove(appPath);
|
|
765
|
-
logger.success('✔ Build success!');
|
|
766
|
-
logger.success('✔ App installer located in', distPath);
|
|
767
|
-
}
|
|
768
|
-
getFileType(target) {
|
|
769
|
-
return target;
|
|
770
|
-
}
|
|
771
|
-
getBuildCommand() {
|
|
772
|
-
// the debug option should support `--debug` and `--release`
|
|
773
|
-
return this.options.debug ? 'npm run build:debug' : 'npm run build';
|
|
774
|
-
}
|
|
775
|
-
getBasePath() {
|
|
776
|
-
return 'src-tauri/target/release/bundle/';
|
|
777
|
-
}
|
|
778
|
-
getBuildAppPath(npmDirectory, fileName, fileType) {
|
|
779
|
-
return path.join(npmDirectory, this.getBasePath(), fileType.toLowerCase(), `${fileName}.${fileType}`);
|
|
780
|
-
}
|
|
705
|
+
class BaseBuilder {
|
|
706
|
+
constructor(options) {
|
|
707
|
+
this.options = options;
|
|
708
|
+
}
|
|
709
|
+
async prepare() {
|
|
710
|
+
const tauriSrcPath = path.join(npmDirectory, 'src-tauri');
|
|
711
|
+
const tauriTargetPath = path.join(tauriSrcPath, 'target');
|
|
712
|
+
const tauriTargetPathExists = await fsExtra.pathExists(tauriTargetPath);
|
|
713
|
+
if (!IS_MAC && !tauriTargetPathExists) {
|
|
714
|
+
logger.warn('✼ The first use requires installing system dependencies.');
|
|
715
|
+
logger.warn('✼ See more in https://tauri.app/v1/guides/getting-started/prerequisites.');
|
|
716
|
+
}
|
|
717
|
+
if (!checkRustInstalled()) {
|
|
718
|
+
const res = await prompts({
|
|
719
|
+
type: 'confirm',
|
|
720
|
+
message: 'Rust not detected. Install now?',
|
|
721
|
+
name: 'value',
|
|
722
|
+
});
|
|
723
|
+
if (res.value) {
|
|
724
|
+
await installRust();
|
|
725
|
+
}
|
|
726
|
+
else {
|
|
727
|
+
logger.error('✕ Rust required to package your webapp.');
|
|
728
|
+
process.exit(0);
|
|
729
|
+
}
|
|
730
|
+
}
|
|
731
|
+
const isChina = await isChinaDomain('www.npmjs.com');
|
|
732
|
+
const spinner = getSpinner('Installing package...');
|
|
733
|
+
const rustProjectDir = path.join(tauriSrcPath, '.cargo');
|
|
734
|
+
const projectConf = path.join(rustProjectDir, 'config.toml');
|
|
735
|
+
await fsExtra.ensureDir(rustProjectDir);
|
|
736
|
+
if (isChina) {
|
|
737
|
+
logger.info('✺ Located in China, using npm/rsProxy CN mirror.');
|
|
738
|
+
const projectCnConf = path.join(tauriSrcPath, 'rust_proxy.toml');
|
|
739
|
+
await fsExtra.copy(projectCnConf, projectConf);
|
|
740
|
+
await shellExec(`cd "${npmDirectory}" && npm install --registry=https://registry.npmmirror.com`);
|
|
741
|
+
}
|
|
742
|
+
else {
|
|
743
|
+
await shellExec(`cd "${npmDirectory}" && npm install`);
|
|
744
|
+
}
|
|
745
|
+
spinner.succeed(chalk.green('Package installed!'));
|
|
746
|
+
if (!tauriTargetPathExists) {
|
|
747
|
+
logger.warn('✼ The first packaging may be slow, please be patient and wait, it will be faster afterwards.');
|
|
748
|
+
}
|
|
749
|
+
}
|
|
750
|
+
async build(url) {
|
|
751
|
+
await this.buildAndCopy(url, this.options.targets);
|
|
752
|
+
}
|
|
753
|
+
async start(url) {
|
|
754
|
+
await mergeConfig(url, this.options, tauriConfig);
|
|
755
|
+
}
|
|
756
|
+
async buildAndCopy(url, target) {
|
|
757
|
+
const { name } = this.options;
|
|
758
|
+
await mergeConfig(url, this.options, tauriConfig);
|
|
759
|
+
// Build app
|
|
760
|
+
const spinner = getSpinner('Building app...');
|
|
761
|
+
setTimeout(() => spinner.stop(), 3000);
|
|
762
|
+
await shellExec(`cd "${npmDirectory}" && ${this.getBuildCommand()}`);
|
|
763
|
+
// Copy app
|
|
764
|
+
const fileName = this.getFileName();
|
|
765
|
+
const fileType = this.getFileType(target);
|
|
766
|
+
const appPath = this.getBuildAppPath(npmDirectory, fileName, fileType);
|
|
767
|
+
const distPath = path.resolve(`${name}.${fileType}`);
|
|
768
|
+
await fsExtra.copy(appPath, distPath);
|
|
769
|
+
await fsExtra.remove(appPath);
|
|
770
|
+
logger.success('✔ Build success!');
|
|
771
|
+
logger.success('✔ App installer located in', distPath);
|
|
772
|
+
}
|
|
773
|
+
getFileType(target) {
|
|
774
|
+
return target;
|
|
775
|
+
}
|
|
776
|
+
getBuildCommand() {
|
|
777
|
+
// the debug option should support `--debug` and `--release`
|
|
778
|
+
return this.options.debug ? 'npm run build:debug' : 'npm run build';
|
|
779
|
+
}
|
|
780
|
+
getBasePath() {
|
|
781
|
+
return 'src-tauri/target/release/bundle/';
|
|
782
|
+
}
|
|
783
|
+
getBuildAppPath(npmDirectory, fileName, fileType) {
|
|
784
|
+
return path.join(npmDirectory, this.getBasePath(), fileType.toLowerCase(), `${fileName}.${fileType}`);
|
|
785
|
+
}
|
|
781
786
|
}
|
|
782
787
|
|
|
783
|
-
class MacBuilder extends BaseBuilder {
|
|
784
|
-
constructor(options) {
|
|
785
|
-
super(options);
|
|
786
|
-
this.options.targets = 'dmg';
|
|
787
|
-
}
|
|
788
|
-
getFileName() {
|
|
789
|
-
const { name } = this.options;
|
|
790
|
-
let arch;
|
|
791
|
-
if (this.options.multiArch) {
|
|
792
|
-
arch = 'universal';
|
|
793
|
-
}
|
|
794
|
-
else {
|
|
795
|
-
arch = process.arch === 'arm64' ? 'aarch64' : process.arch;
|
|
796
|
-
}
|
|
797
|
-
return `${name}_${tauriConfig.package.version}_${arch}`;
|
|
798
|
-
}
|
|
799
|
-
getBuildCommand() {
|
|
800
|
-
return this.options.multiArch ? 'npm run build:mac' : super.getBuildCommand();
|
|
801
|
-
}
|
|
802
|
-
getBasePath() {
|
|
803
|
-
return this.options.multiArch
|
|
804
|
-
? 'src-tauri/target/universal-apple-darwin/release/bundle'
|
|
805
|
-
: super.getBasePath();
|
|
806
|
-
}
|
|
788
|
+
class MacBuilder extends BaseBuilder {
|
|
789
|
+
constructor(options) {
|
|
790
|
+
super(options);
|
|
791
|
+
this.options.targets = 'dmg';
|
|
792
|
+
}
|
|
793
|
+
getFileName() {
|
|
794
|
+
const { name } = this.options;
|
|
795
|
+
let arch;
|
|
796
|
+
if (this.options.multiArch) {
|
|
797
|
+
arch = 'universal';
|
|
798
|
+
}
|
|
799
|
+
else {
|
|
800
|
+
arch = process.arch === 'arm64' ? 'aarch64' : process.arch;
|
|
801
|
+
}
|
|
802
|
+
return `${name}_${tauriConfig.package.version}_${arch}`;
|
|
803
|
+
}
|
|
804
|
+
getBuildCommand() {
|
|
805
|
+
return this.options.multiArch ? 'npm run build:mac' : super.getBuildCommand();
|
|
806
|
+
}
|
|
807
|
+
getBasePath() {
|
|
808
|
+
return this.options.multiArch
|
|
809
|
+
? 'src-tauri/target/universal-apple-darwin/release/bundle'
|
|
810
|
+
: super.getBasePath();
|
|
811
|
+
}
|
|
807
812
|
}
|
|
808
813
|
|
|
809
|
-
class WinBuilder extends BaseBuilder {
|
|
810
|
-
constructor(options) {
|
|
811
|
-
super(options);
|
|
812
|
-
this.options.targets = 'msi';
|
|
813
|
-
}
|
|
814
|
-
getFileName() {
|
|
815
|
-
const { name } = this.options;
|
|
816
|
-
const { arch } = process;
|
|
817
|
-
const language = tauriConfig.tauri.bundle.windows.wix.language[0];
|
|
818
|
-
return `${name}_${tauriConfig.package.version}_${arch}_${language}`;
|
|
819
|
-
}
|
|
814
|
+
class WinBuilder extends BaseBuilder {
|
|
815
|
+
constructor(options) {
|
|
816
|
+
super(options);
|
|
817
|
+
this.options.targets = 'msi';
|
|
818
|
+
}
|
|
819
|
+
getFileName() {
|
|
820
|
+
const { name } = this.options;
|
|
821
|
+
const { arch } = process;
|
|
822
|
+
const language = tauriConfig.tauri.bundle.windows.wix.language[0];
|
|
823
|
+
return `${name}_${tauriConfig.package.version}_${arch}_${language}`;
|
|
824
|
+
}
|
|
820
825
|
}
|
|
821
826
|
|
|
822
|
-
class LinuxBuilder extends BaseBuilder {
|
|
823
|
-
constructor(options) {
|
|
824
|
-
super(options);
|
|
825
|
-
}
|
|
826
|
-
getFileName() {
|
|
827
|
-
const { name } = this.options;
|
|
828
|
-
const arch = process.arch === 'x64' ? 'amd64' : process.arch;
|
|
829
|
-
return `${name}_${tauriConfig.package.version}_${arch}`;
|
|
830
|
-
}
|
|
831
|
-
// Customize it, considering that there are all targets.
|
|
832
|
-
async build(url) {
|
|
833
|
-
const targetTypes = ['deb', 'appimage'];
|
|
834
|
-
for (const target of targetTypes) {
|
|
835
|
-
if (this.options.targets === target || this.options.targets === 'all') {
|
|
836
|
-
await this.buildAndCopy(url, target);
|
|
837
|
-
}
|
|
838
|
-
}
|
|
839
|
-
}
|
|
840
|
-
getFileType(target) {
|
|
841
|
-
if (target === 'appimage') {
|
|
842
|
-
return 'AppImage';
|
|
843
|
-
}
|
|
844
|
-
return super.getFileType(target);
|
|
845
|
-
}
|
|
827
|
+
class LinuxBuilder extends BaseBuilder {
|
|
828
|
+
constructor(options) {
|
|
829
|
+
super(options);
|
|
830
|
+
}
|
|
831
|
+
getFileName() {
|
|
832
|
+
const { name } = this.options;
|
|
833
|
+
const arch = process.arch === 'x64' ? 'amd64' : process.arch;
|
|
834
|
+
return `${name}_${tauriConfig.package.version}_${arch}`;
|
|
835
|
+
}
|
|
836
|
+
// Customize it, considering that there are all targets.
|
|
837
|
+
async build(url) {
|
|
838
|
+
const targetTypes = ['deb', 'appimage'];
|
|
839
|
+
for (const target of targetTypes) {
|
|
840
|
+
if (this.options.targets === target || this.options.targets === 'all') {
|
|
841
|
+
await this.buildAndCopy(url, target);
|
|
842
|
+
}
|
|
843
|
+
}
|
|
844
|
+
}
|
|
845
|
+
getFileType(target) {
|
|
846
|
+
if (target === 'appimage') {
|
|
847
|
+
return 'AppImage';
|
|
848
|
+
}
|
|
849
|
+
return super.getFileType(target);
|
|
850
|
+
}
|
|
846
851
|
}
|
|
847
852
|
|
|
848
|
-
const { platform } = process;
|
|
849
|
-
const buildersMap = {
|
|
850
|
-
darwin: MacBuilder,
|
|
851
|
-
win32: WinBuilder,
|
|
852
|
-
linux: LinuxBuilder,
|
|
853
|
-
};
|
|
854
|
-
class BuilderProvider {
|
|
855
|
-
static create(options) {
|
|
856
|
-
const Builder = buildersMap[platform];
|
|
857
|
-
if (!Builder) {
|
|
858
|
-
throw new Error('The current system is not supported!');
|
|
859
|
-
}
|
|
860
|
-
return new Builder(options);
|
|
861
|
-
}
|
|
853
|
+
const { platform } = process;
|
|
854
|
+
const buildersMap = {
|
|
855
|
+
darwin: MacBuilder,
|
|
856
|
+
win32: WinBuilder,
|
|
857
|
+
linux: LinuxBuilder,
|
|
858
|
+
};
|
|
859
|
+
class BuilderProvider {
|
|
860
|
+
static create(options) {
|
|
861
|
+
const Builder = buildersMap[platform];
|
|
862
|
+
if (!Builder) {
|
|
863
|
+
throw new Error('The current system is not supported!');
|
|
864
|
+
}
|
|
865
|
+
return new Builder(options);
|
|
866
|
+
}
|
|
862
867
|
}
|
|
863
868
|
|
|
864
|
-
async function startBuild() {
|
|
865
|
-
log.setDefaultLevel('debug');
|
|
866
|
-
const appOptions = await handleOptions(DEFAULT_DEV_PAKE_OPTIONS, DEFAULT_DEV_PAKE_OPTIONS.url);
|
|
867
|
-
log.debug('PakeAppOptions', appOptions);
|
|
868
|
-
const builder = BuilderProvider.create(appOptions);
|
|
869
|
-
await builder.prepare();
|
|
870
|
-
await builder.start(DEFAULT_DEV_PAKE_OPTIONS.url);
|
|
871
|
-
}
|
|
869
|
+
async function startBuild() {
|
|
870
|
+
log.setDefaultLevel('debug');
|
|
871
|
+
const appOptions = await handleOptions(DEFAULT_DEV_PAKE_OPTIONS, DEFAULT_DEV_PAKE_OPTIONS.url);
|
|
872
|
+
log.debug('PakeAppOptions', appOptions);
|
|
873
|
+
const builder = BuilderProvider.create(appOptions);
|
|
874
|
+
await builder.prepare();
|
|
875
|
+
await builder.start(DEFAULT_DEV_PAKE_OPTIONS.url);
|
|
876
|
+
}
|
|
872
877
|
startBuild();
|
|
873
878
|
//# sourceMappingURL=dev.js.map
|