positron.js 1.0.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/LICENSE +7 -0
- package/README.md +154 -0
- package/bin/positron.js +40 -0
- package/builder.js +229 -0
- package/core/mac/main.swift +1154 -0
- package/core/win/PositronRuntime.csproj +14 -0
- package/core/win/main.cs +1124 -0
- package/extensions.js +42 -0
- package/findpackage.js +34 -0
- package/index.js +912 -0
- package/ipc.js +81 -0
- package/logs.js +19 -0
- package/menu.js +100 -0
- package/package.json +30 -0
- package/packager.js +260 -0
- package/pbannerfull.png +0 -0
- package/positronicon.png +0 -0
- package/screen.js +35 -0
- package/store.js +104 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
Copyright 2026 Bryce
|
|
2
|
+
|
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
|
4
|
+
|
|
5
|
+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
|
6
|
+
|
|
7
|
+
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
# Positron
|
|
2
|
+
|
|
3
|
+

|
|
4
|
+
|
|
5
|
+
Positron is a lightweight, cross-platform hybrid application framework designed to build desktop applications using a native compiled runtime shell (Swift/Cocoa/WebKit on macOS, and C#/.NET on Windows) driven by a Node.js main process.
|
|
6
|
+
Unlike traditional resource-heavy frameworks, Positron separates the native windowing/render process from the JavaScript application state, establishing a lightweight, dual-process environment unified by a localized WebSocket IPC channel.
|
|
7
|
+
|
|
8
|
+
## Architecture & Core Components
|
|
9
|
+
Positron operates via a split architecture:
|
|
10
|
+
1. The Node.js Master Process (index.js): Manages application lifecycles, creates windows, sets native menus, and hosts the IPC WebSocket server.
|
|
11
|
+
2. The Native Runtime Process: A platform-specific, pre-compiled native binary (positron-runtime) responsible for rendering web views and implementing host OS features.
|
|
12
|
+
3. IPC Router (ipc.js): A unified, asynchronous routing layer that handles bidirectional events between your web app render layers and your backend.
|
|
13
|
+
|
|
14
|
+
## Features
|
|
15
|
+
- Native Framework Integration: Drops specialized heavy chromium embeddings in favor of native UI viewports (WebKit on macOS, .NET Webview2 on Windows).
|
|
16
|
+
- Stitched Native Extensions: Seamlessly hooks developer-created third-party plugins directly into the native build registry at compile time.
|
|
17
|
+
- Production Packager: Automatically abstracts bundle constraints to output native macOS .app structures (complete with mandatory Info.plist manifests) and clean Windows application folders.
|
|
18
|
+
- Zero-Config Dev Builds: Automatically detects missing platform-specific native binaries on launch and compiles them in the background.
|
|
19
|
+
|
|
20
|
+
## Why Use Positron?
|
|
21
|
+
|
|
22
|
+
Positron is built as a lightweight, secure alternative to Electron. Below is a detailed breakdown of how Positron compares to Electron across key architectural and performance metrics.
|
|
23
|
+
|
|
24
|
+
| Metric | Electron | Positron |
|
|
25
|
+
| :--- | :--- | :--- |
|
|
26
|
+
| **Render Engine** | Chromium (bundled in every app) | System-native viewports (WebKit/WKWebView on macOS, WebView2 on Windows) |
|
|
27
|
+
| **Process Model** | Multi-process tree (Main, Renderers, GPU, Network, Utility processes) | Dual-process layout (Single native Swift/C# UI runtime + Background Node.js controller) |
|
|
28
|
+
| **Minimum Bundle Size** | ~100MB+ (compressed), ~300MB+ (extracted) | **~60MB - 100MB** (depending on bundled assets and compiled backend) |
|
|
29
|
+
| **Memory Footprint** | Heavy (runs full Chromium engine processes) | **Lightweight** (reuses system WebKit/WebView2 instances) |
|
|
30
|
+
| **Native Extensions** | Requires Node C++ Addons (N-API/NAN) compiled against Node headers | **Stitched Native Extensions** written directly in Swift (macOS) or C# (Windows) |
|
|
31
|
+
| **Security Isolation** | IPC bridging to Node with complex sandbox/context-isolation setups | **Strict separation by design**; renderer has zero direct access to Node.js APIs |
|
|
32
|
+
|
|
33
|
+
## Prerequisites
|
|
34
|
+
- Node.js (v16+)
|
|
35
|
+
- macOS: Xcode Command Line Tools (swiftc)
|
|
36
|
+
- Windows: .NET SDK (CLI tools capable of executing `dotnet publish`)
|
|
37
|
+
|
|
38
|
+
## Install
|
|
39
|
+
```bash
|
|
40
|
+
npm i positron.js
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## Usage Example
|
|
44
|
+
Initialize your main entry point using the exposed Window and ipc instances:
|
|
45
|
+
```js
|
|
46
|
+
const { Window, ipc } = require('positron.js');
|
|
47
|
+
|
|
48
|
+
// Bind asynchronous IPC listeners from renderer layers
|
|
49
|
+
ipc.handle('get-app-version', (payload, { reply }) => {
|
|
50
|
+
console.log('Renderer requested version details.');
|
|
51
|
+
reply({ version: '1.0.0-alpha' });
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
// Spawn a native window instance
|
|
55
|
+
const mainWindow = new Window({
|
|
56
|
+
width: 1024,
|
|
57
|
+
height: 768
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
// Load web application files
|
|
61
|
+
mainWindow.on("ready", () => {
|
|
62
|
+
mainWindow.loadFile('public/index.html');
|
|
63
|
+
mainWindow.setTitle('My First Positron App');
|
|
64
|
+
})
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
## Native Extensions Configuration
|
|
68
|
+
Positron allows local dependencies to plug natively into the platform-level shell compilation pipeline.
|
|
69
|
+
To create a native extension, provide a custom positron property block within your extension dependency's package.json:
|
|
70
|
+
```json
|
|
71
|
+
{
|
|
72
|
+
"name": "positron-toast-plugin",
|
|
73
|
+
"version": "1.0.0",
|
|
74
|
+
"positron": {
|
|
75
|
+
"className": "ToastPlugin",
|
|
76
|
+
"command": "toast:show",
|
|
77
|
+
"platforms": {
|
|
78
|
+
"darwin": "src/mac/ToastPlugin.swift",
|
|
79
|
+
"win32": "src/win/ToastPlugin.cs"
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
When builder.js executes, it parses your project dependencies, finds native extensions, and stitches their commands directly into the core platform registries (Registry.swift or Registry.cs).
|
|
86
|
+
|
|
87
|
+
## Compilation & Packaging Pipeline
|
|
88
|
+
|
|
89
|
+
### Compilation
|
|
90
|
+
Triggered automatically during development if the binary is missing, or manually during pipeline compilation:
|
|
91
|
+
- macOS: Compiles main.swift, the stitched Registry.swift, and extension source files into bin/positron-runtime using swiftc.
|
|
92
|
+
- Windows: Invokes dotnet publish to build a single, self-contained Release profile binary output to bin/positron-runtime.exe.
|
|
93
|
+
|
|
94
|
+
#### Build
|
|
95
|
+
This will build (or rebuild) the binary, then exit
|
|
96
|
+
```bash
|
|
97
|
+
npx positron build
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
#### Dev
|
|
101
|
+
This will build (or rebuild) the binary, then start the app
|
|
102
|
+
```bash
|
|
103
|
+
npx positron dev
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
#### Run
|
|
107
|
+
This run the app without building
|
|
108
|
+
```bash
|
|
109
|
+
npx positron run
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
### Packaging
|
|
113
|
+
This will rebuild the binary, then create a deployable version of the app
|
|
114
|
+
```bash
|
|
115
|
+
npx positron package [--m | --w] [--arm64 || --x64]
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
> Note: Windows supports either arm64 or x64, while macOS only supports arm64 on Apple Silicon.
|
|
119
|
+
|
|
120
|
+
## IPC Protocol Specification
|
|
121
|
+
Communication relies on structured JSON communication frames routed through the IPC WebSocket server.
|
|
122
|
+
|
|
123
|
+
### Outbound Commands (Main Node ➔ Native Runtime)
|
|
124
|
+
|
|
125
|
+
```json
|
|
126
|
+
{
|
|
127
|
+
"windowId": 1,
|
|
128
|
+
"command": "loadURL",
|
|
129
|
+
"args": ["https://google.com"]
|
|
130
|
+
}
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
### Inbound Events (Native Runtime ➔ Main Node)
|
|
135
|
+
```json
|
|
136
|
+
{
|
|
137
|
+
"event": "ipcMessage",
|
|
138
|
+
"windowId": 1,
|
|
139
|
+
"data": {
|
|
140
|
+
"channel": "form-submit",
|
|
141
|
+
"payload": "{\"username\":\"alice\"}"
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
```
|
|
145
|
+
|
|
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
|
+
## License
|
|
151
|
+
MIT
|
|
152
|
+
|
|
153
|
+
## Documentation
|
|
154
|
+
Read docs [here](https://positronjs.gitbook.io/v1)
|
package/bin/positron.js
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
#! /usr/bin/env node
|
|
2
|
+
|
|
3
|
+
const { performNativeBuild } = require("../builder");
|
|
4
|
+
const performPackager = require("../packager");
|
|
5
|
+
const { spawn } = require("child_process");
|
|
6
|
+
const [, , command] = process.argv;
|
|
7
|
+
const { info, success, error } = require("../logs");
|
|
8
|
+
|
|
9
|
+
switch (command) {
|
|
10
|
+
case "build":
|
|
11
|
+
info("Starting manual Positron build...");
|
|
12
|
+
const success = performNativeBuild();
|
|
13
|
+
process.exit(success ? 0 : 1);
|
|
14
|
+
break;
|
|
15
|
+
|
|
16
|
+
case "dev":
|
|
17
|
+
info("Starting Positron in development mode...");
|
|
18
|
+
performNativeBuild();
|
|
19
|
+
spawn("node", ["."], { stdio: "inherit" });
|
|
20
|
+
break;
|
|
21
|
+
|
|
22
|
+
case "run":
|
|
23
|
+
spawn("node", ["."], { stdio: "inherit" });
|
|
24
|
+
break;
|
|
25
|
+
|
|
26
|
+
case "package":
|
|
27
|
+
info("Packaging Positron application for production...");
|
|
28
|
+
const buildPassed = performNativeBuild();
|
|
29
|
+
if (!buildPassed) {
|
|
30
|
+
error("Packaging aborted due to build failures.");
|
|
31
|
+
process.exit(1);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
performPackager();
|
|
35
|
+
break;
|
|
36
|
+
|
|
37
|
+
default:
|
|
38
|
+
console.log("Usage: npx positron [build | dev | run]");
|
|
39
|
+
process.exit(0);
|
|
40
|
+
}
|
package/builder.js
ADDED
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
const fs = require("fs");
|
|
2
|
+
const path = require("path");
|
|
3
|
+
const cp = require("child_process");
|
|
4
|
+
const { success, error, info } = require("./logs");
|
|
5
|
+
|
|
6
|
+
const arch = process.argv.includes("--x64") ? "x64" : process.argv.includes("--arm64") ? "arm64" : process.arch;
|
|
7
|
+
|
|
8
|
+
function performNativeBuild() {
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
let buildingForWindows = process.argv.includes("--windows") || process.argv.includes("--w");
|
|
12
|
+
let buildingForMac = process.argv.includes("--mac") || process.argv.includes("--m");
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
const appRoot = process.cwd(); // The developer's project folder
|
|
16
|
+
const nativeExtensionsMac = [];
|
|
17
|
+
const nativeExtensionsWindows = [];
|
|
18
|
+
|
|
19
|
+
// 1. Discover Extensions from the developer's package.json
|
|
20
|
+
const rootPackagePath = path.join(appRoot, "package.json");
|
|
21
|
+
if (!fs.existsSync(rootPackagePath)) return false;
|
|
22
|
+
|
|
23
|
+
const rootPackage = JSON.parse(fs.readFileSync(rootPackagePath, "utf8"));
|
|
24
|
+
const dependencies = Object.keys(rootPackage.dependencies || {});
|
|
25
|
+
|
|
26
|
+
for (const dep of dependencies) {
|
|
27
|
+
const depPackagePath = path.join(appRoot, "node_modules", dep, "package.json");
|
|
28
|
+
if (fs.existsSync(depPackagePath)) {
|
|
29
|
+
const depPackage = JSON.parse(fs.readFileSync(depPackagePath, "utf8"));
|
|
30
|
+
if (depPackage.positron) {
|
|
31
|
+
const depDir = path.dirname(depPackagePath);
|
|
32
|
+
|
|
33
|
+
let missing = [];
|
|
34
|
+
if(!depPackage.positron.className) missing.push("className");
|
|
35
|
+
if(!depPackage.positron.command) missing.push("command");
|
|
36
|
+
if(!depPackage.positron.platforms) missing.push("platforms");
|
|
37
|
+
else {
|
|
38
|
+
if(!depPackage.positron.platforms.darwin) missing.push("platforms.darwin");
|
|
39
|
+
if(!depPackage.positron.platforms.win32) missing.push("platforms.win32");
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
if(missing.includes("className") || missing.includes("command") || missing.includes("platforms")) {
|
|
43
|
+
warn(`[Builder] Dependency "${dep}" has an invalid positron field. Missing: ${missing.join(", ")}. Skipping native extension build for this dependency.`);
|
|
44
|
+
continue;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
if(!missing.includes("platforms.darwin")) {
|
|
48
|
+
nativeExtensionsMac.push({
|
|
49
|
+
className: depPackage.positron.className,
|
|
50
|
+
command: depPackage.positron.command,
|
|
51
|
+
sourceFile: path.join(depDir, depPackage.positron.platforms.darwin)
|
|
52
|
+
});
|
|
53
|
+
} else {
|
|
54
|
+
warn(`[Builder] Dependency "${dep}" is missing a macOS platform source file. Skipping macOS native extension build for this dependency.`);
|
|
55
|
+
}
|
|
56
|
+
if(!missing.includes("platforms.win32")) {
|
|
57
|
+
nativeExtensionsWindows.push({
|
|
58
|
+
className: depPackage.positron.className,
|
|
59
|
+
command: depPackage.positron.command,
|
|
60
|
+
sourceFile: path.join(depDir, depPackage.positron.platforms.win32)
|
|
61
|
+
});
|
|
62
|
+
} else {
|
|
63
|
+
warn(`[Builder] Dependency "${dep}" is missing a Windows platform source file. Skipping Windows native extension build for this dependency.`);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
if(buildingForWindows == false && buildingForMac == false) {
|
|
70
|
+
if (process.platform === "win32") {
|
|
71
|
+
buildingForWindows = true;
|
|
72
|
+
} else if (process.platform === "darwin") {
|
|
73
|
+
buildingForMac = true;
|
|
74
|
+
} else {
|
|
75
|
+
error("[Builder] Unsupported platform for native build.");
|
|
76
|
+
return false;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
if (buildingForMac) {
|
|
81
|
+
info(`[Builder] Stitching ${nativeExtensionsMac.length} native extensions...`);
|
|
82
|
+
|
|
83
|
+
let registryContent = `// Auto-generated by Positron. Do not edit.\n`;
|
|
84
|
+
registryContent += `func getExtensionRegistry() -> [String: (Int, [String]) -> Void] {\n`;
|
|
85
|
+
|
|
86
|
+
if (nativeExtensionsMac.length === 0) {
|
|
87
|
+
registryContent += ` return [:]\n`;
|
|
88
|
+
} else {
|
|
89
|
+
registryContent += ` return [\n`;
|
|
90
|
+
|
|
91
|
+
nativeExtensionsMac.forEach((ext, index) => {
|
|
92
|
+
|
|
93
|
+
const comma = index === nativeExtensionsMac.length - 1 ? "" : ",";
|
|
94
|
+
registryContent += ` "${ext.command}": ${ext.className}.handle${comma}\n`;
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
registryContent += ` ]\n`;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
registryContent += `}\n`;
|
|
101
|
+
|
|
102
|
+
const coreMacDir = path.join(__dirname, "core", "mac");
|
|
103
|
+
fs.writeFileSync(path.join(coreMacDir, "Registry.swift"), registryContent);
|
|
104
|
+
|
|
105
|
+
info("[Builder] Compiling native binary...");
|
|
106
|
+
const outBinaryDir = path.join(appRoot, "bin");
|
|
107
|
+
if (!fs.existsSync(outBinaryDir)) fs.mkdirSync(outBinaryDir, { recursive: true });
|
|
108
|
+
|
|
109
|
+
const binaryName = "positron-runtime";
|
|
110
|
+
const extensionSources = nativeExtensionsMac.map(e => e.sourceFile);
|
|
111
|
+
|
|
112
|
+
let addedFrameworksSet = new Set();
|
|
113
|
+
|
|
114
|
+
nativeExtensionsMac.forEach(ext => {
|
|
115
|
+
if (ext.macFrameworks && Array.isArray(ext.macFrameworks)) {
|
|
116
|
+
ext.macFrameworks.forEach(fw => {
|
|
117
|
+
addedFrameworksSet.add(fw);
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
let addedFrameworksArgs = [];
|
|
123
|
+
addedFrameworksSet.forEach(fw => {
|
|
124
|
+
addedFrameworksArgs.push("-framework", fw);
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
try {
|
|
128
|
+
cp.execFileSync("swiftc", [
|
|
129
|
+
path.join(coreMacDir, "main.swift"),
|
|
130
|
+
path.join(coreMacDir, "Registry.swift"),
|
|
131
|
+
...extensionSources,
|
|
132
|
+
"-o", path.join(outBinaryDir, binaryName),
|
|
133
|
+
"-framework", "Cocoa",
|
|
134
|
+
"-framework", "WebKit",
|
|
135
|
+
...addedFrameworksArgs
|
|
136
|
+
]);
|
|
137
|
+
success("[Builder] Native compilation successful.");
|
|
138
|
+
|
|
139
|
+
if(process.platform == "darwin") {
|
|
140
|
+
cp.execFile("chmod", ["+x", path.join(outBinaryDir, binaryName)], (err) => {
|
|
141
|
+
if (err) {
|
|
142
|
+
error("Failed to set executable permissions on native binary:", err);
|
|
143
|
+
}
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
try {
|
|
147
|
+
const iconPathEscaped = path.join(__dirname, "positronicon.png").replace(/"/g, '\\"');
|
|
148
|
+
const binPathEscaped = path.join(outBinaryDir, binaryName).replace(/"/g, '\\"');
|
|
149
|
+
const swiftScript = `import Cocoa; NSWorkspace.shared.setIcon(NSImage(contentsOfFile: "${iconPathEscaped}"), forFile: "${binPathEscaped}", options: [])`;
|
|
150
|
+
cp.execFileSync("swift", ["-e", swiftScript], { stdio: "ignore" });
|
|
151
|
+
} catch (err) {
|
|
152
|
+
error("Failed to set custom icon on native binary:", err);
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
return true;
|
|
157
|
+
} catch (err) {
|
|
158
|
+
error("[Builder] Compilation failed:", err.message);
|
|
159
|
+
return false;
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
|
|
164
|
+
if (buildingForWindows) {
|
|
165
|
+
info(`[Builder] Stitching ${nativeExtensionsWindows.length} native Windows extensions...`);
|
|
166
|
+
|
|
167
|
+
const coreWinDir = path.join(__dirname, "core", "win");
|
|
168
|
+
const extensionsDir = path.join(coreWinDir, "extensions");
|
|
169
|
+
|
|
170
|
+
// 1. Clean and prepare a staging folder for all native extensions
|
|
171
|
+
if (fs.existsSync(extensionsDir)) fs.rmSync(extensionsDir, { recursive: true, force: true });
|
|
172
|
+
fs.mkdirSync(extensionsDir, { recursive: true });
|
|
173
|
+
|
|
174
|
+
let registryContent = `// Auto-generated by Positron. Do not edit.\n`;
|
|
175
|
+
registryContent += `using System;\nusing System.Collections.Generic;\n\n`;
|
|
176
|
+
registryContent += `namespace PositronWindows {\n`;
|
|
177
|
+
registryContent += ` public static class ExtensionRegistry {\n`;
|
|
178
|
+
registryContent += ` public static Dictionary<string, Action<int, List<string>>> GetExtensions() {\n`;
|
|
179
|
+
registryContent += ` return new Dictionary<string, Action<int, List<string>>> {\n`;
|
|
180
|
+
|
|
181
|
+
nativeExtensionsWindows.forEach((ext, index) => {
|
|
182
|
+
const comma = index === nativeExtensionsWindows.length - 1 ? "" : ",";
|
|
183
|
+
registryContent += ` { "${ext.command}", ${ext.className}.Handle }${comma}\n`;
|
|
184
|
+
|
|
185
|
+
const destFile = path.join(extensionsDir, `ext_${index}.cs`);
|
|
186
|
+
fs.copyFileSync(ext.sourceFile, destFile);
|
|
187
|
+
});
|
|
188
|
+
|
|
189
|
+
registryContent += ` };\n`;
|
|
190
|
+
registryContent += ` }\n`;
|
|
191
|
+
registryContent += ` }\n}\n`;
|
|
192
|
+
|
|
193
|
+
fs.writeFileSync(path.join(extensionsDir, "Registry.cs"), registryContent);
|
|
194
|
+
|
|
195
|
+
info("[Builder] Compiling Windows native binary via .NET CLI...");
|
|
196
|
+
const outBinaryDir = path.join(appRoot, "bin");
|
|
197
|
+
if (!fs.existsSync(outBinaryDir)) fs.mkdirSync(outBinaryDir, { recursive: true });
|
|
198
|
+
|
|
199
|
+
try {
|
|
200
|
+
|
|
201
|
+
const iconPath = path.join(appRoot, "icon.ico");
|
|
202
|
+
const dotnetArgs = [
|
|
203
|
+
"publish",
|
|
204
|
+
path.join(coreWinDir, "PositronRuntime.csproj"),
|
|
205
|
+
"-c", "Release",
|
|
206
|
+
"-r", `win-${arch}`,
|
|
207
|
+
"--self-contained", "true",
|
|
208
|
+
"-o", outBinaryDir,
|
|
209
|
+
"/p:PublishSingleFile=true",
|
|
210
|
+
"/p:IncludeNativeLibrariesForSelfContained=true"
|
|
211
|
+
];
|
|
212
|
+
if (fs.existsSync(iconPath)) {
|
|
213
|
+
dotnetArgs.push(`/p:ApplicationIcon=${iconPath}`);
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
cp.execFileSync("dotnet", dotnetArgs, { stdio: "inherit" });
|
|
217
|
+
success("[Builder] Windows native compilation successful.");
|
|
218
|
+
return true;
|
|
219
|
+
} catch (err) {
|
|
220
|
+
error("[Builder] Windows compilation failed:", err.message);
|
|
221
|
+
return false;
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
return false; // Unsupported platform
|
|
226
|
+
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
module.exports = { performNativeBuild };
|