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/README.md
CHANGED
|
@@ -34,6 +34,8 @@ Positron is built as a lightweight, secure alternative to Electron. Below is a d
|
|
|
34
34
|
- Node.js (v16+)
|
|
35
35
|
- macOS: Xcode Command Line Tools (swiftc)
|
|
36
36
|
- Windows: .NET SDK (CLI tools capable of executing `dotnet publish`)
|
|
37
|
+
- C++ compiler (G++ is the default), GTK+ 3 and WebKit2GTK on Linux
|
|
38
|
+
- Docker if building for Linux on macOS or Windows
|
|
37
39
|
|
|
38
40
|
## Install
|
|
39
41
|
```bash
|
|
@@ -76,7 +78,8 @@ To create a native extension, provide a custom positron property block within yo
|
|
|
76
78
|
"command": "toast:show",
|
|
77
79
|
"platforms": {
|
|
78
80
|
"darwin": "src/mac/ToastPlugin.swift",
|
|
79
|
-
"win32": "src/win/ToastPlugin.cs"
|
|
81
|
+
"win32": "src/win/ToastPlugin.cs",
|
|
82
|
+
"linux":"src/linux/ToastPlugin.cpp"
|
|
80
83
|
}
|
|
81
84
|
}
|
|
82
85
|
}
|
|
@@ -112,10 +115,10 @@ npx positron run
|
|
|
112
115
|
### Packaging
|
|
113
116
|
This will rebuild the binary, then create a deployable version of the app
|
|
114
117
|
```bash
|
|
115
|
-
npx positron package [--m | --w] [--arm64 || --x64]
|
|
118
|
+
npx positron package [--m | --w || --l] [--arm64 || --x64]
|
|
116
119
|
```
|
|
117
120
|
|
|
118
|
-
> Note: Windows
|
|
121
|
+
> Note: Windows & Linux support either arm64 or x64, while macOS only supports arm64.
|
|
119
122
|
|
|
120
123
|
## IPC Protocol Specification
|
|
121
124
|
Communication relies on structured JSON communication frames routed through the IPC WebSocket server.
|
|
@@ -143,12 +146,8 @@ Communication relies on structured JSON communication frames routed through the
|
|
|
143
146
|
}
|
|
144
147
|
```
|
|
145
148
|
|
|
146
|
-
## Environment Flags
|
|
147
|
-
- POSITRON_PACKAGED: Set to "true" inside production bundles to suppress localized development shell background re-compilation triggers.
|
|
148
|
-
- POSITRON_IPC_PORT: The port that the IPC server runs on.
|
|
149
|
-
|
|
150
149
|
## License
|
|
151
150
|
MIT
|
|
152
151
|
|
|
153
152
|
## Documentation
|
|
154
|
-
Read
|
|
153
|
+
[Read here](https://positronjs.gitbook.io/v1)
|
package/builder.js
CHANGED
|
@@ -11,11 +11,13 @@ function performNativeBuild() {
|
|
|
11
11
|
|
|
12
12
|
let buildingForWindows = process.argv.includes("--windows") || process.argv.includes("--w");
|
|
13
13
|
let buildingForMac = process.argv.includes("--mac") || process.argv.includes("--m");
|
|
14
|
+
let buildingForLinux = process.argv.includes("--linux") || process.argv.includes("--l");
|
|
14
15
|
|
|
15
16
|
|
|
16
17
|
const appRoot = process.cwd(); // The developer's project folder
|
|
17
18
|
const nativeExtensionsMac = [];
|
|
18
19
|
const nativeExtensionsWindows = [];
|
|
20
|
+
const nativeExtensionsLinux = [];
|
|
19
21
|
|
|
20
22
|
// 1. Discover Extensions from the developer's package.json
|
|
21
23
|
const rootPackagePath = path.join(appRoot, "package.json");
|
|
@@ -50,6 +52,7 @@ function performNativeBuild() {
|
|
|
50
52
|
else {
|
|
51
53
|
if(!depPackage.positron.platforms.darwin) missing.push("platforms.darwin");
|
|
52
54
|
if(!depPackage.positron.platforms.win32) missing.push("platforms.win32");
|
|
55
|
+
if(!depPackage.positron.platforms.linux) missing.push("platforms.linux");
|
|
53
56
|
}
|
|
54
57
|
|
|
55
58
|
if(missing.includes("className") || missing.includes("command") || missing.includes("platforms")) {
|
|
@@ -75,15 +78,26 @@ function performNativeBuild() {
|
|
|
75
78
|
} else {
|
|
76
79
|
warn(`[Builder] Dependency "${dep}" is missing a Windows platform source file. Skipping Windows native extension build for this dependency.`);
|
|
77
80
|
}
|
|
81
|
+
if(!missing.includes("platforms.linux")) {
|
|
82
|
+
nativeExtensionsLinux.push({
|
|
83
|
+
className: depPackage.positron.className,
|
|
84
|
+
command: depPackage.positron.command,
|
|
85
|
+
sourceFile: path.join(depDir, depPackage.positron.platforms.linux)
|
|
86
|
+
});
|
|
87
|
+
} else {
|
|
88
|
+
warn(`[Builder] Dependency "${dep}" is missing a Linux platform source file. Skipping Linux native extension build for this dependency.`);
|
|
89
|
+
}
|
|
78
90
|
}
|
|
79
91
|
}
|
|
80
92
|
}
|
|
81
93
|
|
|
82
|
-
if(buildingForWindows == false && buildingForMac == false) {
|
|
94
|
+
if(buildingForWindows == false && buildingForMac == false && buildingForLinux == false) {
|
|
83
95
|
if (process.platform === "win32") {
|
|
84
96
|
buildingForWindows = true;
|
|
85
97
|
} else if (process.platform === "darwin") {
|
|
86
98
|
buildingForMac = true;
|
|
99
|
+
} else if (process.platform === "linux") {
|
|
100
|
+
buildingForLinux = true;
|
|
87
101
|
} else {
|
|
88
102
|
error("[Builder] Unsupported platform for native build.");
|
|
89
103
|
return false;
|
|
@@ -245,6 +259,19 @@ function performNativeBuild() {
|
|
|
245
259
|
dotnetArgs.push(`/p:ApplicationIcon=${iconPath}`);
|
|
246
260
|
}
|
|
247
261
|
|
|
262
|
+
// Add package.json metadata to Windows executable
|
|
263
|
+
const appName = rootPackage.productName || rootPackage.name || "PositronApp";
|
|
264
|
+
const version = rootPackage.version || "1.0.0";
|
|
265
|
+
const author = rootPackage.author || "Positron";
|
|
266
|
+
const bundleId = rootPackage.bundleIdentifier || `com.${author.toLowerCase().replace(/[^a-z0-9]/g, '')}.${appName.toLowerCase().replace(/[^a-z0-9]/g, '')}`;
|
|
267
|
+
const winCategory = rootPackage.winCategory || rootPackage.macCategory || "An application built with Positron.js";
|
|
268
|
+
|
|
269
|
+
dotnetArgs.push(`/p:Version=${version}`);
|
|
270
|
+
dotnetArgs.push(`/p:Authors=${author}`);
|
|
271
|
+
dotnetArgs.push(`/p:Company=${author}`);
|
|
272
|
+
dotnetArgs.push(`/p:Product=${bundleId}`);
|
|
273
|
+
dotnetArgs.push(`/p:Description=${winCategory}`);
|
|
274
|
+
|
|
248
275
|
cp.execFileSync("dotnet", dotnetArgs, { stdio: "inherit" });
|
|
249
276
|
success("[Builder] Windows native compilation successful.");
|
|
250
277
|
return true;
|
|
@@ -254,6 +281,126 @@ function performNativeBuild() {
|
|
|
254
281
|
}
|
|
255
282
|
}
|
|
256
283
|
|
|
284
|
+
if (buildingForLinux) {
|
|
285
|
+
info(`[Builder] Stitching ${nativeExtensionsLinux.length} native Linux extensions...`);
|
|
286
|
+
|
|
287
|
+
const coreLinuxDir = path.join(__dirname, "core", "linux");
|
|
288
|
+
|
|
289
|
+
let registryContent = `// Auto-generated by Positron. Do not edit.\n`;
|
|
290
|
+
registryContent += `#include <string>\n#include <unordered_map>\n#include <vector>\n\n`;
|
|
291
|
+
registryContent += `using namespace std;\n\n`;
|
|
292
|
+
|
|
293
|
+
nativeExtensionsLinux.forEach((ext, index) => {
|
|
294
|
+
registryContent += `void handle_${ext.className}(int windowId, vector<string> args);\n`;
|
|
295
|
+
});
|
|
296
|
+
|
|
297
|
+
registryContent += `\nunordered_map<string, void(*)(int, vector<string>)> getExtensionRegistry() {\n`;
|
|
298
|
+
registryContent += ` return {\n`;
|
|
299
|
+
|
|
300
|
+
nativeExtensionsLinux.forEach((ext, index) => {
|
|
301
|
+
const comma = index === nativeExtensionsLinux.length - 1 ? "" : ",";
|
|
302
|
+
registryContent += ` {"${ext.command}", handle_${ext.className}}${comma}\n`;
|
|
303
|
+
});
|
|
304
|
+
|
|
305
|
+
registryContent += ` };\n}\n`;
|
|
306
|
+
|
|
307
|
+
fs.writeFileSync(path.join(coreLinuxDir, "Registry.cpp"), registryContent);
|
|
308
|
+
|
|
309
|
+
if (process.platform !== "linux") {
|
|
310
|
+
info("[Builder] Cross-compiling for Linux using Docker...");
|
|
311
|
+
try {
|
|
312
|
+
const dockerVer = cp.spawnSync("docker", ["--version"], { stdio: "ignore" });
|
|
313
|
+
if (dockerVer.error || dockerVer.status !== 0) throw new Error("Docker is not available");
|
|
314
|
+
} catch (e) {
|
|
315
|
+
error("[Builder] Fatal: Docker is required to cross-compile for Linux on macOS/Windows.");
|
|
316
|
+
process.exit(1);
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
const dockerArch = arch === "arm64" ? "linux/arm64" : "linux/amd64";
|
|
320
|
+
const dockerTag = `positron-linux-builder-${arch}`;
|
|
321
|
+
const dockerfileContent = [
|
|
322
|
+
"FROM ubuntu:latest",
|
|
323
|
+
"ENV DEBIAN_FRONTEND=noninteractive",
|
|
324
|
+
"RUN apt-get update && apt-get install -y "+
|
|
325
|
+
"g++ pkg-config "+
|
|
326
|
+
"libgtk-3-dev libwebkit2gtk-4.1-dev libjson-glib-dev "+
|
|
327
|
+
"libsoup2.4-dev libnotify-dev",
|
|
328
|
+
"WORKDIR /app"
|
|
329
|
+
].join("\n");
|
|
330
|
+
|
|
331
|
+
fs.writeFileSync(path.join(coreLinuxDir, "Dockerfile.linux"), dockerfileContent);
|
|
332
|
+
info(`[Builder] Building Docker image for ${dockerArch}...`);
|
|
333
|
+
|
|
334
|
+
try {
|
|
335
|
+
const buildRes = cp.spawnSync("docker", ["build", "--platform", dockerArch, "-t", dockerTag, "-f", path.join(coreLinuxDir, "Dockerfile.linux"), coreLinuxDir], { stdio: "inherit" });
|
|
336
|
+
if (buildRes.error) throw buildRes.error;
|
|
337
|
+
if (buildRes.status !== 0) throw new Error("Docker build failed");
|
|
338
|
+
|
|
339
|
+
const outBinaryDir = path.join(appRoot, "bin");
|
|
340
|
+
|
|
341
|
+
if(!fs.existsSync(outBinaryDir)) fs.mkdirSync(outBinaryDir, { recursive: true });
|
|
342
|
+
|
|
343
|
+
const extensionSources = nativeExtensionsLinux.map(e => e.sourceFile);
|
|
344
|
+
const mappedExtensions = extensionSources.map(s => {
|
|
345
|
+
if (s.startsWith(appRoot)) {
|
|
346
|
+
return "/app/" + path.relative(appRoot, s).replace(/\\/g, '/');
|
|
347
|
+
} else if (s.startsWith(__dirname)) {
|
|
348
|
+
return "/framework/" + path.relative(__dirname, s).replace(/\\/g, '/');
|
|
349
|
+
}
|
|
350
|
+
return s;
|
|
351
|
+
});
|
|
352
|
+
|
|
353
|
+
const compiler = process.argv.find(arg => arg.startsWith("--compiler="))?.split("=")[1] || "g++";
|
|
354
|
+
|
|
355
|
+
const gccArgs = [
|
|
356
|
+
compiler, "-O3",
|
|
357
|
+
"/framework/core/linux/main.cpp",
|
|
358
|
+
"/framework/core/linux/Registry.cpp",
|
|
359
|
+
...mappedExtensions,
|
|
360
|
+
"-o", "/app/bin/positron-runtime",
|
|
361
|
+
"$(pkg-config --cflags --libs gtk+-3.0 webkit2gtk-4.1 json-glib-1.0 libnotify)"
|
|
362
|
+
].join(" ");
|
|
363
|
+
|
|
364
|
+
info("[Builder] Compiling inside Docker container...");
|
|
365
|
+
const runRes = cp.spawnSync("docker", ["run", "--rm", "--platform", dockerArch, "-v", `\${appRoot}:/app`, "-v", `\${__dirname}:/framework`, dockerTag, "bash", "-c", gccArgs], { stdio: "inherit" });
|
|
366
|
+
if (runRes.error) throw runRes.error;
|
|
367
|
+
if (runRes.status !== 0) throw new Error("Docker run failed");
|
|
368
|
+
|
|
369
|
+
success("[Builder] Linux native cross-compilation successful.");
|
|
370
|
+
return true;
|
|
371
|
+
} catch (err) {
|
|
372
|
+
error("[Builder] Linux cross-compilation via Docker failed:", err.message);
|
|
373
|
+
return false;
|
|
374
|
+
}
|
|
375
|
+
} else {
|
|
376
|
+
info("[Builder] Compiling Linux native binary natively via g++...");
|
|
377
|
+
try {
|
|
378
|
+
const pkgRes = cp.spawnSync("pkg-config", ["--cflags", "--libs", "gtk+-3.0", "webkit2gtk-4.1", "json-glib-1.0", "libnotify"], { encoding: 'utf8' });
|
|
379
|
+
if (pkgRes.error) throw pkgRes.error;
|
|
380
|
+
if (pkgRes.status !== 0) throw new Error("pkg-config failed");
|
|
381
|
+
const pkgConfigOutput = pkgRes.stdout.trim().split(/\\s+/);
|
|
382
|
+
|
|
383
|
+
const extensionSources = nativeExtensionsLinux.map(e => e.sourceFile);
|
|
384
|
+
const gccArgs = [
|
|
385
|
+
"-O3",
|
|
386
|
+
path.join(coreLinuxDir, "main.cpp"),
|
|
387
|
+
path.join(coreLinuxDir, "Registry.cpp"),
|
|
388
|
+
...extensionSources,
|
|
389
|
+
"-o", path.join(outBinaryDir, "positron-runtime"),
|
|
390
|
+
...pkgConfigOutput
|
|
391
|
+
];
|
|
392
|
+
|
|
393
|
+
cp.execFileSync("g++", gccArgs, { stdio: "inherit" });
|
|
394
|
+
success("[Builder] Linux native compilation successful.");
|
|
395
|
+
return true;
|
|
396
|
+
} catch (err) {
|
|
397
|
+
error("[Builder] Linux compilation failed:", err.message);
|
|
398
|
+
warn("Ensure you have installed: libgtk-3-dev libwebkit2gtk-4.1-dev libjson-glib-dev libsoup2.4-dev");
|
|
399
|
+
return false;
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
|
|
257
404
|
return false; // Unsupported platform
|
|
258
405
|
|
|
259
406
|
}
|