electrobun 1.17.3-beta.9 → 1.18.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 +23 -4
- package/bin/electrobun.cjs +11 -1
- package/dist/api/bun/ElectrobunConfig.ts +42 -1
- package/dist/api/bun/__tests__/ffi-contract.test.ts +105 -0
- package/dist/api/bun/core/BrowserView.ts +5 -8
- package/dist/api/bun/core/BrowserWindow.ts +34 -2
- package/dist/api/bun/core/GpuWindow.ts +30 -2
- package/dist/api/bun/core/Paths.ts +1 -1
- package/dist/api/bun/core/Updater.ts +19 -12
- package/dist/api/bun/index.ts +2 -0
- package/dist/api/bun/preload/.generated/compiled.ts +1 -1
- package/dist/api/bun/preload/webviewTag.ts +16 -2
- package/dist/api/bun/proc/native.ts +84 -24
- package/dist/api/bun/webGPU.ts +7 -32
- package/dist/api/bun/webgpuAdapter.ts +0 -5
- package/dist/api/shared/bun-version.ts +1 -1
- package/dist/api/shared/cef-version.ts +2 -2
- package/package.json +2 -2
- package/src/cli/index.ts +299 -31
package/src/cli/index.ts
CHANGED
|
@@ -1462,6 +1462,13 @@ const _commandDefaults = {
|
|
|
1462
1462
|
},
|
|
1463
1463
|
};
|
|
1464
1464
|
|
|
1465
|
+
type FileAssociation = {
|
|
1466
|
+
ext: string[];
|
|
1467
|
+
name: string;
|
|
1468
|
+
role?: "Editor" | "Viewer" | "Shell" | "None";
|
|
1469
|
+
icon?: string;
|
|
1470
|
+
};
|
|
1471
|
+
|
|
1465
1472
|
// Default values merged with user's electrobun.config.ts
|
|
1466
1473
|
// For the user-facing type, see ElectrobunConfig in src/bun/ElectrobunConfig.ts
|
|
1467
1474
|
const defaultConfig = {
|
|
@@ -1471,6 +1478,7 @@ const defaultConfig = {
|
|
|
1471
1478
|
version: "0.1.0",
|
|
1472
1479
|
description: "" as string | undefined,
|
|
1473
1480
|
urlSchemes: undefined as string[] | undefined,
|
|
1481
|
+
fileAssociations: undefined as FileAssociation[] | undefined,
|
|
1474
1482
|
},
|
|
1475
1483
|
build: {
|
|
1476
1484
|
buildFolder: "build",
|
|
@@ -1779,6 +1787,151 @@ ${schemesXml}
|
|
|
1779
1787
|
</array>`;
|
|
1780
1788
|
}
|
|
1781
1789
|
|
|
1790
|
+
// Generates CFBundleDocumentTypes and UTExportedTypeDeclarations for file associations.
|
|
1791
|
+
// Each association gets a UTI derived from the app identifier (e.g., com.example.app.myext).
|
|
1792
|
+
// LSItemContentTypes in CFBundleDocumentTypes references these UTIs so Launch Services
|
|
1793
|
+
// properly associates files with the app on modern macOS.
|
|
1794
|
+
function generateDocumentTypes(
|
|
1795
|
+
fileAssociations: FileAssociation[] | undefined,
|
|
1796
|
+
projectRoot: string,
|
|
1797
|
+
appIdentifier: string,
|
|
1798
|
+
): string {
|
|
1799
|
+
if (!fileAssociations || fileAssociations.length === 0) {
|
|
1800
|
+
return "";
|
|
1801
|
+
}
|
|
1802
|
+
|
|
1803
|
+
const validAssociations = fileAssociations.filter((assoc) => {
|
|
1804
|
+
if (!assoc.ext || assoc.ext.length === 0) {
|
|
1805
|
+
console.log(
|
|
1806
|
+
`WARNING: fileAssociations entry "${assoc.name || "(unnamed)"}" has no extensions — skipping`,
|
|
1807
|
+
);
|
|
1808
|
+
return false;
|
|
1809
|
+
}
|
|
1810
|
+
if (!assoc.name) {
|
|
1811
|
+
console.log(
|
|
1812
|
+
`WARNING: fileAssociations entry with extensions [${assoc.ext.join(", ")}] has no name — skipping`,
|
|
1813
|
+
);
|
|
1814
|
+
return false;
|
|
1815
|
+
}
|
|
1816
|
+
return true;
|
|
1817
|
+
});
|
|
1818
|
+
|
|
1819
|
+
if (validAssociations.length === 0) {
|
|
1820
|
+
return "";
|
|
1821
|
+
}
|
|
1822
|
+
|
|
1823
|
+
// Clean extensions and warn about leading dots
|
|
1824
|
+
const cleaned = validAssociations.map((assoc) => ({
|
|
1825
|
+
...assoc,
|
|
1826
|
+
ext: assoc.ext.map((ext) => {
|
|
1827
|
+
const clean = ext.replace(/^\./, "");
|
|
1828
|
+
if (clean !== ext) {
|
|
1829
|
+
console.log(
|
|
1830
|
+
`WARNING: fileAssociations ext "${ext}" has a leading dot — stripping to "${clean}"`,
|
|
1831
|
+
);
|
|
1832
|
+
}
|
|
1833
|
+
return clean;
|
|
1834
|
+
}),
|
|
1835
|
+
}));
|
|
1836
|
+
|
|
1837
|
+
// Generate CFBundleDocumentTypes with LSItemContentTypes
|
|
1838
|
+
const docTypes = cleaned
|
|
1839
|
+
.map((assoc) => {
|
|
1840
|
+
const role = assoc.role || "Viewer";
|
|
1841
|
+
// Resolve icon: only reference if file exists to avoid dangling plist entries
|
|
1842
|
+
let iconName = "";
|
|
1843
|
+
if (assoc.icon) {
|
|
1844
|
+
const iconSourcePath = join(projectRoot, assoc.icon);
|
|
1845
|
+
if (existsSync(iconSourcePath)) {
|
|
1846
|
+
iconName = basename(assoc.icon).replace(/\.icns$/i, "");
|
|
1847
|
+
} else {
|
|
1848
|
+
console.log(
|
|
1849
|
+
`WARNING: Document type icon not found: ${iconSourcePath} — skipping icon reference`,
|
|
1850
|
+
);
|
|
1851
|
+
}
|
|
1852
|
+
}
|
|
1853
|
+
const iconLine = iconName
|
|
1854
|
+
? ` <key>CFBundleTypeIconFile</key>\n <string>${escapeXml(iconName)}</string>\n`
|
|
1855
|
+
: "";
|
|
1856
|
+
// One UTI per extension, all listed under LSItemContentTypes
|
|
1857
|
+
const utiXml = assoc.ext
|
|
1858
|
+
.map(
|
|
1859
|
+
(ext) =>
|
|
1860
|
+
` <string>${escapeXml(appIdentifier)}.${escapeXml(ext)}</string>`,
|
|
1861
|
+
)
|
|
1862
|
+
.join("\n");
|
|
1863
|
+
const extsXml = assoc.ext
|
|
1864
|
+
.map(
|
|
1865
|
+
(ext) =>
|
|
1866
|
+
` <string>${escapeXml(ext)}</string>`,
|
|
1867
|
+
)
|
|
1868
|
+
.join("\n");
|
|
1869
|
+
|
|
1870
|
+
return ` <dict>
|
|
1871
|
+
<key>CFBundleTypeName</key>
|
|
1872
|
+
<string>${escapeXml(assoc.name)}</string>
|
|
1873
|
+
<key>CFBundleTypeRole</key>
|
|
1874
|
+
<string>${escapeXml(role)}</string>
|
|
1875
|
+
${iconLine} <key>LSItemContentTypes</key>
|
|
1876
|
+
<array>
|
|
1877
|
+
${utiXml}
|
|
1878
|
+
</array>
|
|
1879
|
+
<key>CFBundleTypeExtensions</key>
|
|
1880
|
+
<array>
|
|
1881
|
+
${extsXml}
|
|
1882
|
+
</array>
|
|
1883
|
+
</dict>`;
|
|
1884
|
+
})
|
|
1885
|
+
.join("\n");
|
|
1886
|
+
|
|
1887
|
+
// Generate UTExportedTypeDeclarations — one per extension
|
|
1888
|
+
const utiDecls = cleaned
|
|
1889
|
+
.flatMap((assoc) => {
|
|
1890
|
+
let iconName = "";
|
|
1891
|
+
if (assoc.icon) {
|
|
1892
|
+
const iconSourcePath = join(projectRoot, assoc.icon);
|
|
1893
|
+
if (existsSync(iconSourcePath)) {
|
|
1894
|
+
iconName = basename(assoc.icon).replace(/\.icns$/i, "");
|
|
1895
|
+
}
|
|
1896
|
+
}
|
|
1897
|
+
const iconLine = iconName
|
|
1898
|
+
? ` <key>UTTypeIconFiles</key>
|
|
1899
|
+
<array>
|
|
1900
|
+
<string>${escapeXml(iconName)}</string>
|
|
1901
|
+
</array>\n`
|
|
1902
|
+
: "";
|
|
1903
|
+
return assoc.ext.map(
|
|
1904
|
+
(ext) => ` <dict>
|
|
1905
|
+
<key>UTTypeIdentifier</key>
|
|
1906
|
+
<string>${escapeXml(appIdentifier)}.${escapeXml(ext)}</string>
|
|
1907
|
+
<key>UTTypeDescription</key>
|
|
1908
|
+
<string>${escapeXml(assoc.name)}</string>
|
|
1909
|
+
<key>UTTypeConformsTo</key>
|
|
1910
|
+
<array>
|
|
1911
|
+
<string>public.data</string>
|
|
1912
|
+
</array>
|
|
1913
|
+
${iconLine} <key>UTTypeTagSpecification</key>
|
|
1914
|
+
<dict>
|
|
1915
|
+
<key>public.filename-extension</key>
|
|
1916
|
+
<array>
|
|
1917
|
+
<string>${escapeXml(ext)}</string>
|
|
1918
|
+
</array>
|
|
1919
|
+
</dict>
|
|
1920
|
+
</dict>`,
|
|
1921
|
+
);
|
|
1922
|
+
})
|
|
1923
|
+
.join("\n");
|
|
1924
|
+
|
|
1925
|
+
return ` <key>CFBundleDocumentTypes</key>
|
|
1926
|
+
<array>
|
|
1927
|
+
${docTypes}
|
|
1928
|
+
</array>
|
|
1929
|
+
<key>UTExportedTypeDeclarations</key>
|
|
1930
|
+
<array>
|
|
1931
|
+
${utiDecls}
|
|
1932
|
+
</array>`;
|
|
1933
|
+
}
|
|
1934
|
+
|
|
1782
1935
|
// Execute command handling
|
|
1783
1936
|
(async () => {
|
|
1784
1937
|
if (commandArg === "init") {
|
|
@@ -1913,7 +2066,7 @@ ${schemesXml}
|
|
|
1913
2066
|
console.log(
|
|
1914
2067
|
"Different architecture, different APIs. Do not use Electron patterns.",
|
|
1915
2068
|
);
|
|
1916
|
-
console.log("Docs: https://
|
|
2069
|
+
console.log("Docs: https://docs.electrobunny.ai/electrobun/llms.txt");
|
|
1917
2070
|
console.log(
|
|
1918
2071
|
"━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━",
|
|
1919
2072
|
);
|
|
@@ -1932,9 +2085,7 @@ ${schemesXml}
|
|
|
1932
2085
|
try {
|
|
1933
2086
|
await runBuild(config, buildEnvironment);
|
|
1934
2087
|
} catch (error) {
|
|
1935
|
-
|
|
1936
|
-
console.error(error.message);
|
|
1937
|
-
}
|
|
2088
|
+
console.error("Build failed:", error);
|
|
1938
2089
|
process.exit(1);
|
|
1939
2090
|
}
|
|
1940
2091
|
} else if (commandArg === "run") {
|
|
@@ -1950,9 +2101,7 @@ ${schemesXml}
|
|
|
1950
2101
|
try {
|
|
1951
2102
|
await runBuild(config, "dev");
|
|
1952
2103
|
} catch (error) {
|
|
1953
|
-
|
|
1954
|
-
console.error(error.message);
|
|
1955
|
-
}
|
|
2104
|
+
console.error("Build failed:", error);
|
|
1956
2105
|
process.exit(1);
|
|
1957
2106
|
}
|
|
1958
2107
|
await runAppWithSignalHandling(config);
|
|
@@ -2059,18 +2208,97 @@ ${schemesXml}
|
|
|
2059
2208
|
const iconDestPath = join(appBundleFolderResourcesPath, "AppIcon.icns");
|
|
2060
2209
|
if (existsSync(iconSourceFolder)) {
|
|
2061
2210
|
if (OS === "macos") {
|
|
2062
|
-
|
|
2063
|
-
|
|
2064
|
-
|
|
2065
|
-
|
|
2066
|
-
|
|
2067
|
-
stdio: ["ignore", "
|
|
2068
|
-
|
|
2069
|
-
|
|
2070
|
-
|
|
2211
|
+
if (config.build.mac.icons.endsWith(".icon")) {
|
|
2212
|
+
// .icon format (Icon Composer) — compile with actool
|
|
2213
|
+
// Produces Assets.car (Liquid Glass on macOS 26+) and .icns fallback
|
|
2214
|
+
const actoolCheck = Bun.spawnSync(
|
|
2215
|
+
["xcrun", "--find", "actool"],
|
|
2216
|
+
{ stdio: ["ignore", "pipe", "pipe"] },
|
|
2217
|
+
);
|
|
2218
|
+
if (actoolCheck.exitCode !== 0) {
|
|
2219
|
+
throw new Error(
|
|
2220
|
+
"Building .icon files requires Xcode (actool is not available from Command Line Tools alone). " +
|
|
2221
|
+
"Install Xcode from the App Store, or set mac.icons to an .iconset folder instead.",
|
|
2222
|
+
);
|
|
2223
|
+
}
|
|
2224
|
+
|
|
2225
|
+
const iconStem = basename(config.build.mac.icons, ".icon");
|
|
2226
|
+
const partialPlistPath = join(
|
|
2227
|
+
buildFolder,
|
|
2228
|
+
".actool-partial-info.plist",
|
|
2229
|
+
);
|
|
2230
|
+
|
|
2231
|
+
console.log(
|
|
2232
|
+
"Compiling .icon file with actool (requires Xcode)...",
|
|
2233
|
+
);
|
|
2234
|
+
const result = Bun.spawnSync(
|
|
2235
|
+
[
|
|
2236
|
+
"xcrun",
|
|
2237
|
+
"actool",
|
|
2238
|
+
"--compile",
|
|
2239
|
+
appBundleFolderResourcesPath,
|
|
2240
|
+
"--app-icon",
|
|
2241
|
+
iconStem,
|
|
2242
|
+
"--platform",
|
|
2243
|
+
"macosx",
|
|
2244
|
+
"--minimum-deployment-target",
|
|
2245
|
+
"11.0",
|
|
2246
|
+
"--output-partial-info-plist",
|
|
2247
|
+
partialPlistPath,
|
|
2248
|
+
iconSourceFolder,
|
|
2249
|
+
],
|
|
2250
|
+
{
|
|
2251
|
+
cwd: projectRoot,
|
|
2252
|
+
stdio: ["ignore", "inherit", "inherit"],
|
|
2253
|
+
env: {
|
|
2254
|
+
...process.env,
|
|
2255
|
+
ELECTROBUN_BUILD_ENV: buildEnvironment,
|
|
2256
|
+
},
|
|
2071
2257
|
},
|
|
2072
|
-
|
|
2073
|
-
|
|
2258
|
+
);
|
|
2259
|
+
|
|
2260
|
+
if (result.exitCode !== 0) {
|
|
2261
|
+
throw new Error(
|
|
2262
|
+
`actool failed to compile ${config.build.mac.icons} (exit code ${result.exitCode})`,
|
|
2263
|
+
);
|
|
2264
|
+
}
|
|
2265
|
+
|
|
2266
|
+
// actool produces <stem>.icns — rename to AppIcon.icns so
|
|
2267
|
+
// CFBundleIconFile ("AppIcon") resolves correctly
|
|
2268
|
+
const actoolIcns = join(
|
|
2269
|
+
appBundleFolderResourcesPath,
|
|
2270
|
+
`${iconStem}.icns`,
|
|
2271
|
+
);
|
|
2272
|
+
if (existsSync(actoolIcns) && actoolIcns !== iconDestPath) {
|
|
2273
|
+
renameSync(actoolIcns, iconDestPath);
|
|
2274
|
+
}
|
|
2275
|
+
} else {
|
|
2276
|
+
// Use iconutil to convert .iconset folder to .icns
|
|
2277
|
+
const result = Bun.spawnSync(
|
|
2278
|
+
[
|
|
2279
|
+
"iconutil",
|
|
2280
|
+
"-c",
|
|
2281
|
+
"icns",
|
|
2282
|
+
"-o",
|
|
2283
|
+
iconDestPath,
|
|
2284
|
+
iconSourceFolder,
|
|
2285
|
+
],
|
|
2286
|
+
{
|
|
2287
|
+
cwd: appBundleFolderResourcesPath,
|
|
2288
|
+
stdio: ["ignore", "inherit", "inherit"],
|
|
2289
|
+
env: {
|
|
2290
|
+
...process.env,
|
|
2291
|
+
ELECTROBUN_BUILD_ENV: buildEnvironment,
|
|
2292
|
+
},
|
|
2293
|
+
},
|
|
2294
|
+
);
|
|
2295
|
+
|
|
2296
|
+
if (result.exitCode !== 0) {
|
|
2297
|
+
throw new Error(
|
|
2298
|
+
`iconutil failed to convert ${config.build.mac.icons} (exit code ${result.exitCode})`,
|
|
2299
|
+
);
|
|
2300
|
+
}
|
|
2301
|
+
}
|
|
2074
2302
|
} else {
|
|
2075
2303
|
console.log(
|
|
2076
2304
|
`WARNING: Cannot build macOS icons on ${OS} - iconutil is only available on macOS`,
|
|
@@ -2137,6 +2365,26 @@ Categories=Utility;Application;
|
|
|
2137
2365
|
cpSync(iconPath, targetIconPath, { dereference: true });
|
|
2138
2366
|
}
|
|
2139
2367
|
}
|
|
2368
|
+
|
|
2369
|
+
// Copy document type icon files to the app bundle Resources folder
|
|
2370
|
+
if (targetOS === "macos" && config.app.fileAssociations) {
|
|
2371
|
+
for (const assoc of config.app.fileAssociations) {
|
|
2372
|
+
if (assoc.icon) {
|
|
2373
|
+
const iconSourcePath = join(projectRoot, assoc.icon);
|
|
2374
|
+
if (existsSync(iconSourcePath)) {
|
|
2375
|
+
const iconFileName = basename(iconSourcePath);
|
|
2376
|
+
const iconDestPath = join(
|
|
2377
|
+
appBundleFolderResourcesPath,
|
|
2378
|
+
iconFileName,
|
|
2379
|
+
);
|
|
2380
|
+
cpSync(iconSourcePath, iconDestPath, {
|
|
2381
|
+
dereference: true,
|
|
2382
|
+
});
|
|
2383
|
+
}
|
|
2384
|
+
// Missing icon warning is handled by generateDocumentTypes
|
|
2385
|
+
}
|
|
2386
|
+
}
|
|
2387
|
+
}
|
|
2140
2388
|
};
|
|
2141
2389
|
|
|
2142
2390
|
// Run preBuild hook before anything starts
|
|
@@ -2212,8 +2460,20 @@ Categories=Utility;Application;
|
|
|
2212
2460
|
config.app.urlSchemes,
|
|
2213
2461
|
config.app.identifier,
|
|
2214
2462
|
);
|
|
2463
|
+
// Generate document type associations
|
|
2464
|
+
const documentTypes = generateDocumentTypes(
|
|
2465
|
+
config.app.fileAssociations,
|
|
2466
|
+
projectRoot,
|
|
2467
|
+
config.app.identifier,
|
|
2468
|
+
);
|
|
2469
|
+
|
|
2470
|
+
// When using .icon format, CFBundleIconName is needed for Assets.car lookup
|
|
2471
|
+
const iconName = config.build.mac?.icons?.endsWith(".icon")
|
|
2472
|
+
? basename(config.build.mac.icons, ".icon")
|
|
2473
|
+
: null;
|
|
2215
2474
|
|
|
2216
2475
|
InfoPlistContents = `<?xml version="1.0" encoding="UTF-8"?>
|
|
2476
|
+
|
|
2217
2477
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
2218
2478
|
<plist version="1.0">
|
|
2219
2479
|
<dict>
|
|
@@ -2228,7 +2488,9 @@ Categories=Utility;Application;
|
|
|
2228
2488
|
<key>CFBundlePackageType</key>
|
|
2229
2489
|
<string>APPL</string>
|
|
2230
2490
|
<key>CFBundleIconFile</key>
|
|
2231
|
-
<string>AppIcon</string>${
|
|
2491
|
+
<string>AppIcon</string>${iconName ? `\n <key>CFBundleIconName</key>\n <string>${iconName}</string>` : ""}${usageDescriptions ? "\n" +
|
|
2492
|
+
usageDescriptions : ""}${urlTypes ? "\n" + urlTypes : ""}${documentTypes ?
|
|
2493
|
+
"\n" + documentTypes : ""}
|
|
2232
2494
|
</dict>
|
|
2233
2495
|
</plist>`;
|
|
2234
2496
|
|
|
@@ -2328,10 +2590,12 @@ Categories=Utility;Application;
|
|
|
2328
2590
|
}
|
|
2329
2591
|
|
|
2330
2592
|
// Use rcedit to embed the icon into launcher.exe
|
|
2331
|
-
|
|
2332
|
-
|
|
2333
|
-
|
|
2334
|
-
|
|
2593
|
+
const { execFileSync } = await import("child_process");
|
|
2594
|
+
const rceditPkgPath = require.resolve("rcedit/package.json");
|
|
2595
|
+
const rceditDir = dirname(rceditPkgPath);
|
|
2596
|
+
const rceditX64 = join(rceditDir, "bin", "rcedit-x64.exe");
|
|
2597
|
+
const rceditExe = existsSync(rceditX64) ? rceditX64 : join(rceditDir, "bin", "rcedit.exe");
|
|
2598
|
+
execFileSync(rceditExe, [bunCliLauncherDestination, "--set-icon", iconPath]);
|
|
2335
2599
|
console.log(`Successfully embedded icon into launcher.exe`);
|
|
2336
2600
|
|
|
2337
2601
|
// Clean up temp ICO file
|
|
@@ -2425,10 +2689,12 @@ Categories=Utility;Application;
|
|
|
2425
2689
|
}
|
|
2426
2690
|
|
|
2427
2691
|
// Use rcedit to embed the icon into bun.exe
|
|
2428
|
-
|
|
2429
|
-
|
|
2430
|
-
|
|
2431
|
-
|
|
2692
|
+
const { execFileSync } = await import("child_process");
|
|
2693
|
+
const rceditPkgPath = require.resolve("rcedit/package.json");
|
|
2694
|
+
const rceditDir = dirname(rceditPkgPath);
|
|
2695
|
+
const rceditX64 = join(rceditDir, "bin", "rcedit-x64.exe");
|
|
2696
|
+
const rceditExe = existsSync(rceditX64) ? rceditX64 : join(rceditDir, "bin", "rcedit.exe");
|
|
2697
|
+
execFileSync(rceditExe, [bunBinaryDestInBundlePath, "--set-icon", iconPath]);
|
|
2432
2698
|
console.log(`Successfully embedded icon into bun.exe`);
|
|
2433
2699
|
|
|
2434
2700
|
// Clean up temp ICO file
|
|
@@ -4610,10 +4876,12 @@ Categories=Utility;Application;
|
|
|
4610
4876
|
}
|
|
4611
4877
|
|
|
4612
4878
|
// Use rcedit to embed the icon
|
|
4613
|
-
|
|
4614
|
-
|
|
4615
|
-
|
|
4616
|
-
|
|
4879
|
+
const { execFileSync } = await import("child_process");
|
|
4880
|
+
const rceditPkgPath = require.resolve("rcedit/package.json");
|
|
4881
|
+
const rceditDir = dirname(rceditPkgPath);
|
|
4882
|
+
const rceditX64 = join(rceditDir, "bin", "rcedit-x64.exe");
|
|
4883
|
+
const rceditExe = existsSync(rceditX64) ? rceditX64 : join(rceditDir, "bin", "rcedit.exe");
|
|
4884
|
+
execFileSync(rceditExe, [outputExePath, "--set-icon", iconPath]);
|
|
4617
4885
|
console.log(`Successfully embedded icon into ${setupFileName}`);
|
|
4618
4886
|
|
|
4619
4887
|
// Clean up temp ICO file
|