positron.js 1.0.6 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +7 -8
- package/builder.js +148 -1
- package/core/linux/main.cpp +1123 -0
- package/core/mac/main.swift +45 -20
- package/core/win/main.cs +46 -12
- package/index.js +75 -34
- package/package.json +3 -2
- package/packager.js +101 -7
- package/screen.js +7 -5
- package/tray.js +9 -1
package/packager.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
const fs = require("fs");
|
|
2
2
|
const path = require("path");
|
|
3
|
-
const { execSync, execFileSync } = require("child_process");
|
|
3
|
+
const { execSync, execFileSync, spawnSync } = require("child_process");
|
|
4
4
|
const { info, error, success } = require("./logs");
|
|
5
5
|
const https = require("https");
|
|
6
6
|
const esbuild = require("esbuild");
|
|
@@ -8,7 +8,8 @@ const findPackageJson = require("./findpackage");
|
|
|
8
8
|
|
|
9
9
|
const MAJOR_NODE_V = 24;
|
|
10
10
|
|
|
11
|
-
const
|
|
11
|
+
const min = process.argv.includes("--minify") || process.argv.includes("--min");
|
|
12
|
+
const ob = process.argv.includes("--obfuscate") || process.argv.includes("--ob");
|
|
12
13
|
|
|
13
14
|
const arch = process.argv.includes("--x64") ? "x64" : process.argv.includes("--arm64") ? "arm64" : process.arch;
|
|
14
15
|
|
|
@@ -22,13 +23,25 @@ function performPackager() {
|
|
|
22
23
|
if (fs.existsSync(distDir)) fs.rmSync(distDir, { recursive: true, force: true });
|
|
23
24
|
fs.mkdirSync(distDir, { recursive: true });
|
|
24
25
|
|
|
26
|
+
let selectedPlatform = false;
|
|
27
|
+
|
|
25
28
|
if (process.argv.includes("--mac") || process.argv.includes("--m")) {
|
|
26
29
|
packageMacOS(appRoot, distDir, appName);
|
|
27
|
-
|
|
30
|
+
selectedPlatform = true;
|
|
31
|
+
}
|
|
32
|
+
if (process.argv.includes("--windows") || process.argv.includes("--w")) {
|
|
28
33
|
packageWindows(appRoot, distDir, appName);
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
34
|
+
selectedPlatform = true;
|
|
35
|
+
}
|
|
36
|
+
if (process.argv.includes("--linux") || process.argv.includes("--l")) {
|
|
37
|
+
packageLinux(appRoot, distDir, appName);
|
|
38
|
+
selectedPlatform = true;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
if (selectedPlatform) return;
|
|
42
|
+
if (process.platform === "win32") packageWindows(appRoot, distDir, appName);
|
|
43
|
+
else if (process.platform === "linux") packageLinux(appRoot, distDir, appName);
|
|
44
|
+
else packageMacOS(appRoot, distDir, appName);
|
|
32
45
|
}
|
|
33
46
|
|
|
34
47
|
function handleJavaScriptPipeline(appRoot, resourcesPath) {
|
|
@@ -89,7 +102,7 @@ async function packageMacOS(appRoot, distDir, appName) {
|
|
|
89
102
|
<key>CFBundleExecutable</key>
|
|
90
103
|
<string>${appName}</string>
|
|
91
104
|
<key>CFBundleIdentifier</key>
|
|
92
|
-
<string
|
|
105
|
+
<string>${package.bundleIdentifier || `com.${package.author || "positron"}.${appName.toLowerCase()}`}</string>
|
|
93
106
|
<key>CFBundleName</key>
|
|
94
107
|
<string>${appName}</string>
|
|
95
108
|
<key>CFBundlePackageType</key>
|
|
@@ -215,6 +228,57 @@ async function packageWindows(appRoot, distDir, appName) {
|
|
|
215
228
|
success(`Successfully packaged Windows app directory at: ${outputFolder}`);
|
|
216
229
|
}
|
|
217
230
|
|
|
231
|
+
async function packageLinux(appRoot, distDir, appName) {
|
|
232
|
+
const outputFolder = path.join(distDir, `${appName}-linux`);
|
|
233
|
+
fs.mkdirSync(outputFolder, { recursive: true });
|
|
234
|
+
|
|
235
|
+
info(`[Packager] Creating Linux App structure...`);
|
|
236
|
+
|
|
237
|
+
const binFolder = path.join(appRoot, "bin");
|
|
238
|
+
const compiledBinary = path.join(binFolder, "positron-runtime");
|
|
239
|
+
|
|
240
|
+
if (!fs.existsSync(compiledBinary)) {
|
|
241
|
+
error("Fatal: Native compiled binary missing from bin/. Run build first.");
|
|
242
|
+
process.exit(1);
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
const binaryPath = path.join(outputFolder, appName);
|
|
246
|
+
fs.copyFileSync(compiledBinary, binaryPath);
|
|
247
|
+
fs.chmodSync(binaryPath, "755");
|
|
248
|
+
|
|
249
|
+
const resourcesPath = path.join(outputFolder, "resources");
|
|
250
|
+
fs.mkdirSync(resourcesPath, { recursive: true });
|
|
251
|
+
|
|
252
|
+
handleJavaScriptPipeline(appRoot, resourcesPath);
|
|
253
|
+
|
|
254
|
+
const bundledJs = path.join(resourcesPath, "index.js");
|
|
255
|
+
const backendName = appName.replace(/([a-z0-9])([A-Z])/g, '$1-$2').replace(/[\s_]+/g, '-').toLowerCase() + '-backend';
|
|
256
|
+
|
|
257
|
+
if (fs.existsSync(bundledJs)) {
|
|
258
|
+
await compileWithPkg(bundledJs, "linux", resourcesPath, backendName);
|
|
259
|
+
} else {
|
|
260
|
+
error(`[Packager] Fatal: Bundled JavaScript entry point missing at ${bundledJs}`);
|
|
261
|
+
process.exit(1);
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
const desktopContent = `[Desktop Entry]
|
|
265
|
+
Name=${appName}
|
|
266
|
+
Exec=./${appName}
|
|
267
|
+
Icon=utilities-terminal
|
|
268
|
+
Type=Application
|
|
269
|
+
Categories=Utility;`;
|
|
270
|
+
fs.writeFileSync(path.join(outputFolder, `${appName}.desktop`), desktopContent);
|
|
271
|
+
|
|
272
|
+
if(!process.argv.includes('--keep-package-json') || !process.argv.includes('--kpj')) {
|
|
273
|
+
fs.rmSync(path.join(resourcesPath, "package.json"), { force: true });
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
fs.rmSync(path.join(resourcesPath, "icon.icns"), { force: true });
|
|
277
|
+
fs.rmSync(path.join(resourcesPath, "icon.ico"), { force: true });
|
|
278
|
+
|
|
279
|
+
success(`Successfully packaged Linux app directory at: ${outputFolder}`);
|
|
280
|
+
}
|
|
281
|
+
|
|
218
282
|
function copyAppAssets(src, dest, ignoredFiles = []) {
|
|
219
283
|
const ignoreList = ["node_modules", "dist", "bin", ".git"];
|
|
220
284
|
|
|
@@ -238,6 +302,34 @@ function copyAppAssets(src, dest, ignoredFiles = []) {
|
|
|
238
302
|
copyRecursive(srcPath, destPath);
|
|
239
303
|
} else {
|
|
240
304
|
fs.copyFileSync(srcPath, destPath);
|
|
305
|
+
|
|
306
|
+
if(min && item.endsWith(".js")) {
|
|
307
|
+
info(`Minifying JavaScript file: ${destPath}`);
|
|
308
|
+
try {
|
|
309
|
+
esbuild.buildSync({
|
|
310
|
+
"bundle": false,
|
|
311
|
+
"minify": true,
|
|
312
|
+
"sourcemap": false,
|
|
313
|
+
"target": `node${MAJOR_NODE_V}`,
|
|
314
|
+
"entryPoints": [srcPath],
|
|
315
|
+
"outfile": destPath,
|
|
316
|
+
})
|
|
317
|
+
} catch (err) {
|
|
318
|
+
error(`JavaScript minification failed for ${destPath}:`, err);
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
if(ob && item.endsWith(".js")) {
|
|
323
|
+
info(`Obfuscating JavaScript file: ${destPath}`);
|
|
324
|
+
try {
|
|
325
|
+
const obResult = spawnSync("npx", ["javascript-obfuscator", destPath, "--compact", "true", "--self-defending", "true", "--string-array", "true", "--string-array-encoding", "base64", "--string-array-threshold", "1", "--output", destPath], { stdio:"inherit" });
|
|
326
|
+
if (obResult.error) throw obResult.error;
|
|
327
|
+
if (obResult.status !== 0) throw new Error("javascript-obfuscator failed");
|
|
328
|
+
} catch (err) {
|
|
329
|
+
error(`JavaScript obfuscation failed for ${destPath}:`, err);
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
|
|
241
333
|
}
|
|
242
334
|
}
|
|
243
335
|
}
|
|
@@ -268,6 +360,8 @@ async function compileWithPkg(bundledJsPath, targetPlatform, outputFolder, appNa
|
|
|
268
360
|
finalBinaryName = `${appName}.exe`;
|
|
269
361
|
} else if (targetPlatform === "darwin") {
|
|
270
362
|
pkgTarget = `node${MAJOR_NODE_V}-macos-${arch}`;
|
|
363
|
+
} else if (targetPlatform === "linux") {
|
|
364
|
+
pkgTarget = `node${MAJOR_NODE_V}-linux-${arch}`;
|
|
271
365
|
}
|
|
272
366
|
|
|
273
367
|
const outputPath = path.join(outputFolder, finalBinaryName);
|
package/screen.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const {
|
|
1
|
+
const { spawnSync } = require('child_process');
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Gets the screen size of the primary display. The implementation varies based on the operating system:
|
|
@@ -11,16 +11,18 @@ function getScreenSize() {
|
|
|
11
11
|
|
|
12
12
|
try {
|
|
13
13
|
if (platform === 'win32') {
|
|
14
|
-
const
|
|
15
|
-
|
|
14
|
+
const result = spawnSync("powershell", ["-command", "Get-CimInstance Win32_VideoController | Select-Object CurrentHorizontalResolution, CurrentVerticalResolution | Format-List"]);
|
|
15
|
+
if (result.error || result.status !== 0) throw new Error("Failed to execute powershell");
|
|
16
|
+
const output = result.stdout.toString();
|
|
16
17
|
const width = output.match(/CurrentHorizontalResolution\s*:\s*(\d+)/)?.[1];
|
|
17
18
|
const height = output.match(/CurrentVerticalResolution\s*:\s*(\d+)/)?.[1];
|
|
18
19
|
return { width: parseInt(width), height: parseInt(height) };
|
|
19
20
|
}
|
|
20
21
|
|
|
21
22
|
if (platform === 'darwin') {
|
|
22
|
-
const
|
|
23
|
-
|
|
23
|
+
const result = spawnSync("system_profiler", ["SPDisplaysDataType"]);
|
|
24
|
+
if (result.error || result.status !== 0) throw new Error("Failed to execute system_profiler");
|
|
25
|
+
const output = result.stdout.toString().split('\\n').filter(line => line.includes('Resolution')).join('\\n');
|
|
24
26
|
const match = output.match(/(\d+) x (\d+)/);
|
|
25
27
|
return { width: parseInt(match[1]), height: parseInt(match[2]) };
|
|
26
28
|
}
|
package/tray.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
const { app } = require("./index");
|
|
2
2
|
const { Menu } = require("./menu");
|
|
3
|
+
const { warn } = require("./logs");
|
|
3
4
|
|
|
4
5
|
let createdTray = false;
|
|
5
6
|
|
|
@@ -7,8 +8,10 @@ module.exports = {
|
|
|
7
8
|
|
|
8
9
|
create(menu, title = "", icon = "") {
|
|
9
10
|
|
|
11
|
+
if(process.platform == "linux") return warn("Tray is not supported on Linux at this time.");
|
|
12
|
+
|
|
10
13
|
if(createdTray) {
|
|
11
|
-
|
|
14
|
+
warn("Tray already created. Use setMenu, setTitle, or setIcon to update the existing tray.");
|
|
12
15
|
return;
|
|
13
16
|
}
|
|
14
17
|
|
|
@@ -34,6 +37,9 @@ create(menu, title = "", icon = "") {
|
|
|
34
37
|
},
|
|
35
38
|
|
|
36
39
|
setMenu(menu) {
|
|
40
|
+
|
|
41
|
+
if(process.platform == "linux") return warn("Tray is not supported on Linux at this time.");
|
|
42
|
+
|
|
37
43
|
if(menu instanceof Menu) {
|
|
38
44
|
menu = menu.template
|
|
39
45
|
}
|
|
@@ -54,10 +60,12 @@ create(menu, title = "", icon = "") {
|
|
|
54
60
|
},
|
|
55
61
|
|
|
56
62
|
setTitle(title) {
|
|
63
|
+
if(process.platform == "linux") return warn("Tray is not supported on Linux at this time.");
|
|
57
64
|
app.sendToNative("createTray", [title, "setTitle"]);
|
|
58
65
|
},
|
|
59
66
|
|
|
60
67
|
setIcon(iconPath) {
|
|
68
|
+
if(process.platform == "linux") return warn("Tray is not supported on Linux at this time.");
|
|
61
69
|
app.sendToNative("createTray", [iconPath, "setIcon"]);
|
|
62
70
|
}
|
|
63
71
|
|