muon-ui 0.7.0 → 0.8.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 +1 -0
- package/dist/cli.cjs +269 -120
- package/dist/cli.cjs.map +1 -1
- package/dist/index.cjs +2 -2
- package/dist/index.mjs +2 -2
- package/dist/native/linux-amd64/muon-bootstrap +0 -0
- package/dist/native/linux-amd64/muon-builder +0 -0
- package/dist/native/linux-arm64/muon-bootstrap +0 -0
- package/dist/native/linux-arm64/{muon-prepare → muon-builder} +0 -0
- package/dist/native/linux-armhf/muon-bootstrap +0 -0
- package/dist/native/linux-armhf/{muon-prepare → muon-builder} +0 -0
- package/dist/native/muon-bootstrap.png +0 -0
- package/dist/native/windows-amd64/muon-bootstrap.exe +0 -0
- package/dist/native/windows-amd64/muon-builder.exe +0 -0
- package/dist/native/windows-i686/muon-bootstrap.exe +0 -0
- package/dist/native/windows-i686/muon-builder.exe +0 -0
- package/dist/runtime/linux-amd64/CREDITS.md +24 -0
- package/dist/runtime/linux-amd64/muon-core +0 -0
- package/dist/runtime/linux-arm64/CREDITS.md +24 -0
- package/dist/runtime/linux-arm64/muon-core +0 -0
- package/dist/runtime/linux-armhf/CREDITS.md +24 -0
- package/dist/runtime/linux-armhf/muon-core +0 -0
- package/dist/runtime/windows-amd64/CREDITS.md +24 -0
- package/dist/runtime/windows-amd64/libcardio.dll +0 -0
- package/dist/runtime/windows-amd64/libmuon-ui.dll +0 -0
- package/dist/runtime/windows-amd64/muon-core.exe +0 -0
- package/dist/runtime/windows-i686/CREDITS.md +24 -0
- package/dist/runtime/windows-i686/libcardio.dll +0 -0
- package/dist/runtime/windows-i686/libmuon-ui.dll +0 -0
- package/dist/runtime/windows-i686/muon-core.exe +0 -0
- package/dist/{vite-options-FFh0NWUa.cjs → vite-internals-ChWiL2TL.cjs} +1225 -102
- package/dist/vite-internals-ChWiL2TL.cjs.map +1 -0
- package/dist/vite.cjs +10 -8
- package/dist/vite.cjs.map +1 -1
- package/dist/vite.mjs +876 -49
- package/dist/vite.mjs.map +1 -1
- package/muon.d.ts +129 -27
- package/package.json +14 -10
- package/vite.d.ts +165 -13
- package/dist/native/linux-amd64/muon-prepare +0 -0
- package/dist/native/windows-amd64/muon-prepare.exe +0 -0
- package/dist/native/windows-i686/muon-prepare.exe +0 -0
- package/dist/vite-options-FFh0NWUa.cjs.map +0 -1
package/dist/vite.mjs
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
/*!
|
|
2
2
|
* name: muon-ui
|
|
3
|
-
* version: 0.
|
|
3
|
+
* version: 0.8.0
|
|
4
4
|
* description: A multi-platform GUI application framework that uses CEF as its backend
|
|
5
5
|
* author: Kouji Matsui (@kekyo@mi.kekyo.net)
|
|
6
6
|
* license: MIT
|
|
7
7
|
* repository.url: https://github.com/kekyo/muon-ui.git
|
|
8
|
-
* git.commit.hash:
|
|
8
|
+
* git.commit.hash: 9bb6148e155dab16c4ca441073b144e21981b038
|
|
9
9
|
*/
|
|
10
|
-
import { basename, dirname, isAbsolute, join, relative, resolve, sep, win32 } from "node:path";
|
|
10
|
+
import { basename, dirname, extname, isAbsolute, join, relative, resolve, sep, win32 } from "node:path";
|
|
11
11
|
import { constants, writeFileSync } from "node:fs";
|
|
12
12
|
import { access, chmod, copyFile, cp, mkdir, mkdtemp, readFile, readdir, rm, stat, writeFile } from "node:fs/promises";
|
|
13
13
|
import { createHash, randomBytes } from "node:crypto";
|
|
@@ -15,6 +15,7 @@ import { tmpdir } from "node:os";
|
|
|
15
15
|
import { fileURLToPath } from "node:url";
|
|
16
16
|
import __screwUpDefaultImportModule0 from "adm-zip";
|
|
17
17
|
import { spawn } from "node:child_process";
|
|
18
|
+
import * as __screwUpDefaultImportModule0$1 from "sharp";
|
|
18
19
|
//#region \0rolldown/runtime.js
|
|
19
20
|
var __commonJSMin = (cb, mod) => () => (mod || (cb((mod = { exports: {} }).exports, mod), cb = null), mod.exports);
|
|
20
21
|
//#endregion
|
|
@@ -1292,7 +1293,7 @@ var encodeTaggedBytes = (tag, bytes) => Buffer.concat([
|
|
|
1292
1293
|
encodeVarUint(BigInt(bytes.length)),
|
|
1293
1294
|
Buffer.from(bytes)
|
|
1294
1295
|
]);
|
|
1295
|
-
var isJsonObject$
|
|
1296
|
+
var isJsonObject$4 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
1296
1297
|
var isPath = (path, first, second) => path.length === 2 && path[0] === first && path[1] === second;
|
|
1297
1298
|
var isHexString = (value) => value.length % 2 === 0 && /^[0-9a-fA-F]*$/.test(value);
|
|
1298
1299
|
var decodeHexString = (value) => {
|
|
@@ -1325,7 +1326,7 @@ var encodeTlvValue = (value, path) => {
|
|
|
1325
1326
|
encodeVarUint(BigInt(value.length)),
|
|
1326
1327
|
...value.map((entry) => encodeTlvValue(entry, path))
|
|
1327
1328
|
]);
|
|
1328
|
-
if (isJsonObject$
|
|
1329
|
+
if (isJsonObject$4(value)) {
|
|
1329
1330
|
const entries = Object.entries(value);
|
|
1330
1331
|
return Buffer.concat([
|
|
1331
1332
|
Buffer.from([tlvObjectTag]),
|
|
@@ -1439,7 +1440,7 @@ var findMuonBootstrapEmbeddedConfigSlot = (content) => {
|
|
|
1439
1440
|
if (candidate === void 0) throw new Error("Embedded muon-bootstrap config slot was not found.");
|
|
1440
1441
|
return candidate;
|
|
1441
1442
|
};
|
|
1442
|
-
var fileExists$
|
|
1443
|
+
var fileExists$4 = async (path) => {
|
|
1443
1444
|
try {
|
|
1444
1445
|
return (await stat(path)).isFile();
|
|
1445
1446
|
} catch {
|
|
@@ -1455,10 +1456,10 @@ var resolveMuonConfigInputPath = async (configPath) => {
|
|
|
1455
1456
|
"muon.json"
|
|
1456
1457
|
]) {
|
|
1457
1458
|
const candidate = join(directory, fileName);
|
|
1458
|
-
if (await fileExists$
|
|
1459
|
+
if (await fileExists$4(candidate)) return candidate;
|
|
1459
1460
|
}
|
|
1460
1461
|
}
|
|
1461
|
-
if (!await fileExists$
|
|
1462
|
+
if (!await fileExists$4(configPath)) throw new Error(`muon config does not exist: ${configPath}`);
|
|
1462
1463
|
return configPath;
|
|
1463
1464
|
};
|
|
1464
1465
|
var readMuonConfigInput = async (configPath) => {
|
|
@@ -1571,7 +1572,7 @@ var targetDescriptors = {
|
|
|
1571
1572
|
cefTarget: "linux64",
|
|
1572
1573
|
os: "linux",
|
|
1573
1574
|
arch: "amd64",
|
|
1574
|
-
distributionDirectoryName: "dist-muon
|
|
1575
|
+
distributionDirectoryName: "dist-muon/linux-amd64",
|
|
1575
1576
|
runtimeExecutableName: "muon-core",
|
|
1576
1577
|
bootstrapExecutableName: "muon-bootstrap",
|
|
1577
1578
|
launcherExtension: "",
|
|
@@ -1586,7 +1587,7 @@ var targetDescriptors = {
|
|
|
1586
1587
|
cefTarget: "linuxarm",
|
|
1587
1588
|
os: "linux",
|
|
1588
1589
|
arch: "armhf",
|
|
1589
|
-
distributionDirectoryName: "dist-muon
|
|
1590
|
+
distributionDirectoryName: "dist-muon/linux-armhf",
|
|
1590
1591
|
runtimeExecutableName: "muon-core",
|
|
1591
1592
|
bootstrapExecutableName: "muon-bootstrap",
|
|
1592
1593
|
launcherExtension: "",
|
|
@@ -1601,7 +1602,7 @@ var targetDescriptors = {
|
|
|
1601
1602
|
cefTarget: "linuxarm64",
|
|
1602
1603
|
os: "linux",
|
|
1603
1604
|
arch: "arm64",
|
|
1604
|
-
distributionDirectoryName: "dist-muon
|
|
1605
|
+
distributionDirectoryName: "dist-muon/linux-arm64",
|
|
1605
1606
|
runtimeExecutableName: "muon-core",
|
|
1606
1607
|
bootstrapExecutableName: "muon-bootstrap",
|
|
1607
1608
|
launcherExtension: "",
|
|
@@ -1616,7 +1617,7 @@ var targetDescriptors = {
|
|
|
1616
1617
|
cefTarget: "windows32",
|
|
1617
1618
|
os: "windows",
|
|
1618
1619
|
arch: "i686",
|
|
1619
|
-
distributionDirectoryName: "dist-muon
|
|
1620
|
+
distributionDirectoryName: "dist-muon/windows-i686",
|
|
1620
1621
|
runtimeExecutableName: "muon-core.exe",
|
|
1621
1622
|
bootstrapExecutableName: "muon-bootstrap.exe",
|
|
1622
1623
|
launcherExtension: ".exe",
|
|
@@ -1636,7 +1637,7 @@ var targetDescriptors = {
|
|
|
1636
1637
|
cefTarget: "windows64",
|
|
1637
1638
|
os: "windows",
|
|
1638
1639
|
arch: "amd64",
|
|
1639
|
-
distributionDirectoryName: "dist-muon
|
|
1640
|
+
distributionDirectoryName: "dist-muon/windows-amd64",
|
|
1640
1641
|
runtimeExecutableName: "muon-core.exe",
|
|
1641
1642
|
bootstrapExecutableName: "muon-bootstrap.exe",
|
|
1642
1643
|
launcherExtension: ".exe",
|
|
@@ -1707,8 +1708,8 @@ var getDefaultMuonPrepareTarget = (platform, architecture) => {
|
|
|
1707
1708
|
throw new Error(`Unsupported Muon prepare target: platform=${platform}, arch=${architecture}`);
|
|
1708
1709
|
}
|
|
1709
1710
|
};
|
|
1710
|
-
var
|
|
1711
|
-
var moduleDirectory$
|
|
1711
|
+
var getBuilderExecutableName = (platform) => platform === "win32" ? "muon-builder.exe" : "muon-builder";
|
|
1712
|
+
var moduleDirectory$4 = typeof __dirname === "string" ? __dirname : dirname(fileURLToPath(import.meta.url));
|
|
1712
1713
|
var canExecute = async (path) => {
|
|
1713
1714
|
try {
|
|
1714
1715
|
await access(path, constants.X_OK);
|
|
@@ -1717,12 +1718,12 @@ var canExecute = async (path) => {
|
|
|
1717
1718
|
return false;
|
|
1718
1719
|
}
|
|
1719
1720
|
};
|
|
1720
|
-
var
|
|
1721
|
-
const explicit = options.prepareExecutablePath ?? options.environment.
|
|
1721
|
+
var resolveMuonBuilderExecutable = async (options) => {
|
|
1722
|
+
const explicit = options.prepareExecutablePath ?? options.environment.MUON_BUILDER_PATH;
|
|
1722
1723
|
if (explicit !== void 0 && explicit !== "") return explicit;
|
|
1723
|
-
const executableName =
|
|
1724
|
+
const executableName = getBuilderExecutableName(process.platform);
|
|
1724
1725
|
const target = getDefaultMuonPrepareTarget(process.platform, process.arch);
|
|
1725
|
-
const candidates = [join(moduleDirectory$
|
|
1726
|
+
const candidates = [join(moduleDirectory$4, "native", target, executableName), join(moduleDirectory$4, "..", "dist", "native", target, executableName)];
|
|
1726
1727
|
for (const candidate of candidates) if (await canExecute(candidate)) return candidate;
|
|
1727
1728
|
return candidates[0] ?? executableName;
|
|
1728
1729
|
};
|
|
@@ -1741,14 +1742,100 @@ var createMuonPrepareArguments = (options) => {
|
|
|
1741
1742
|
if (options.quiet) args.push("--quiet");
|
|
1742
1743
|
return args;
|
|
1743
1744
|
};
|
|
1744
|
-
|
|
1745
|
-
|
|
1746
|
-
|
|
1747
|
-
|
|
1748
|
-
|
|
1749
|
-
|
|
1750
|
-
var
|
|
1751
|
-
|
|
1745
|
+
var spinnerFrames = [
|
|
1746
|
+
"-",
|
|
1747
|
+
"\\",
|
|
1748
|
+
"|",
|
|
1749
|
+
"/"
|
|
1750
|
+
];
|
|
1751
|
+
var spinnerIntervalMilliseconds = 100;
|
|
1752
|
+
var terminalLineStart = "\r";
|
|
1753
|
+
var terminalClearLine = "\x1B[K";
|
|
1754
|
+
var isMuonPrepareStatusLine = (line) => {
|
|
1755
|
+
const trimmed = line.trimEnd();
|
|
1756
|
+
return trimmed.endsWith("...") || trimmed === "Failed to prepare CEF." || trimmed.startsWith("Downloading CEF binary:");
|
|
1757
|
+
};
|
|
1758
|
+
var shouldKeepMuonPrepareStatusAfterLine = (line) => line.startsWith("Muon files copied to staging:");
|
|
1759
|
+
var createPlainStderrForwarder = () => ({
|
|
1760
|
+
write: (chunk) => {
|
|
1761
|
+
process.stderr.write(chunk);
|
|
1762
|
+
},
|
|
1763
|
+
flush: () => {}
|
|
1764
|
+
});
|
|
1765
|
+
var createSpinnerStderrForwarder = () => {
|
|
1766
|
+
let pending = "";
|
|
1767
|
+
let activeStatus = void 0;
|
|
1768
|
+
let frameIndex = 0;
|
|
1769
|
+
let timer = void 0;
|
|
1770
|
+
const writeRaw = (chunk) => {
|
|
1771
|
+
process.stderr.write(chunk);
|
|
1772
|
+
};
|
|
1773
|
+
const stopTimer = () => {
|
|
1774
|
+
if (timer !== void 0) {
|
|
1775
|
+
clearInterval(timer);
|
|
1776
|
+
timer = void 0;
|
|
1777
|
+
}
|
|
1778
|
+
};
|
|
1779
|
+
const renderStatus = () => {
|
|
1780
|
+
if (activeStatus === void 0) return;
|
|
1781
|
+
writeRaw(`${terminalLineStart}${spinnerFrames[frameIndex] ?? spinnerFrames[0]} ${activeStatus}${terminalClearLine}`);
|
|
1782
|
+
frameIndex = (frameIndex + 1) % spinnerFrames.length;
|
|
1783
|
+
};
|
|
1784
|
+
const ensureTimer = () => {
|
|
1785
|
+
if (timer === void 0) timer = setInterval(renderStatus, spinnerIntervalMilliseconds);
|
|
1786
|
+
};
|
|
1787
|
+
const finishStatus = () => {
|
|
1788
|
+
if (activeStatus === void 0) return;
|
|
1789
|
+
const status = activeStatus;
|
|
1790
|
+
activeStatus = void 0;
|
|
1791
|
+
stopTimer();
|
|
1792
|
+
frameIndex = 0;
|
|
1793
|
+
writeRaw(`${terminalLineStart}${status}${terminalClearLine}\n`);
|
|
1794
|
+
};
|
|
1795
|
+
const startStatus = (status) => {
|
|
1796
|
+
if (activeStatus !== void 0 && activeStatus !== status) finishStatus();
|
|
1797
|
+
activeStatus = status;
|
|
1798
|
+
renderStatus();
|
|
1799
|
+
ensureTimer();
|
|
1800
|
+
};
|
|
1801
|
+
const writeLine = (line) => {
|
|
1802
|
+
const text = line.replace(/\r?\n$/, "");
|
|
1803
|
+
if (isMuonPrepareStatusLine(text)) {
|
|
1804
|
+
startStatus(text.trimEnd());
|
|
1805
|
+
return;
|
|
1806
|
+
}
|
|
1807
|
+
if (activeStatus !== void 0 && shouldKeepMuonPrepareStatusAfterLine(text)) {
|
|
1808
|
+
writeRaw(`${terminalLineStart}${terminalClearLine}${line.endsWith("\n") ? line : `${line}\n`}`);
|
|
1809
|
+
renderStatus();
|
|
1810
|
+
return;
|
|
1811
|
+
}
|
|
1812
|
+
finishStatus();
|
|
1813
|
+
writeRaw(line);
|
|
1814
|
+
};
|
|
1815
|
+
return {
|
|
1816
|
+
write: (chunk) => {
|
|
1817
|
+
pending += chunk;
|
|
1818
|
+
for (;;) {
|
|
1819
|
+
const newlineIndex = pending.indexOf("\n");
|
|
1820
|
+
if (newlineIndex < 0) break;
|
|
1821
|
+
const line = pending.slice(0, newlineIndex + 1);
|
|
1822
|
+
pending = pending.slice(newlineIndex + 1);
|
|
1823
|
+
writeLine(line);
|
|
1824
|
+
}
|
|
1825
|
+
},
|
|
1826
|
+
flush: () => {
|
|
1827
|
+
if (pending.length > 0) {
|
|
1828
|
+
const line = pending;
|
|
1829
|
+
pending = "";
|
|
1830
|
+
writeLine(line);
|
|
1831
|
+
}
|
|
1832
|
+
finishStatus();
|
|
1833
|
+
}
|
|
1834
|
+
};
|
|
1835
|
+
};
|
|
1836
|
+
var createMuonPrepareStderrForwarder = () => process.stderr.isTTY === true ? createSpinnerStderrForwarder() : createPlainStderrForwarder();
|
|
1837
|
+
var runMuonPrepareCommand = async (options) => {
|
|
1838
|
+
const child = spawn(await resolveMuonBuilderExecutable(options), [...options.args], {
|
|
1752
1839
|
cwd: options.cwd,
|
|
1753
1840
|
env: options.environment,
|
|
1754
1841
|
stdio: [
|
|
@@ -1761,22 +1848,46 @@ var runMuonPrepare = async (options) => {
|
|
|
1761
1848
|
let stderr = "";
|
|
1762
1849
|
child.stdout.setEncoding("utf8");
|
|
1763
1850
|
child.stderr.setEncoding("utf8");
|
|
1851
|
+
const stderrForwarder = options.quiet ? void 0 : createMuonPrepareStderrForwarder();
|
|
1764
1852
|
child.stdout.on("data", (chunk) => {
|
|
1765
1853
|
stdout += chunk;
|
|
1766
1854
|
});
|
|
1767
1855
|
child.stderr.on("data", (chunk) => {
|
|
1768
1856
|
stderr += chunk;
|
|
1769
|
-
|
|
1857
|
+
stderrForwarder?.write(chunk);
|
|
1770
1858
|
});
|
|
1771
|
-
const exitCode = await
|
|
1772
|
-
|
|
1773
|
-
|
|
1774
|
-
|
|
1775
|
-
|
|
1859
|
+
const exitCode = await (async () => {
|
|
1860
|
+
try {
|
|
1861
|
+
return await new Promise((resolvePromise, reject) => {
|
|
1862
|
+
child.on("error", reject);
|
|
1863
|
+
child.on("close", (code) => {
|
|
1864
|
+
resolvePromise(code ?? 1);
|
|
1865
|
+
});
|
|
1866
|
+
});
|
|
1867
|
+
} finally {
|
|
1868
|
+
stderrForwarder?.flush();
|
|
1869
|
+
}
|
|
1870
|
+
})();
|
|
1871
|
+
if (exitCode !== 0) throw new Error(`muon-builder failed with exit code ${exitCode}.\n${stderr.trim()}`);
|
|
1872
|
+
return stdout;
|
|
1873
|
+
};
|
|
1874
|
+
/**
|
|
1875
|
+
* Invokes the native muon-builder executable and returns the prepared runtime.
|
|
1876
|
+
*
|
|
1877
|
+
* @param options Native prepare invocation options.
|
|
1878
|
+
* @returns Prepared runtime location.
|
|
1879
|
+
*/
|
|
1880
|
+
var runMuonPrepare = async (options) => {
|
|
1881
|
+
const args = createMuonPrepareArguments(options);
|
|
1882
|
+
const stdout = await runMuonPrepareCommand({
|
|
1883
|
+
prepareExecutablePath: options.prepareExecutablePath,
|
|
1884
|
+
environment: options.environment,
|
|
1885
|
+
cwd: options.cwd,
|
|
1886
|
+
quiet: options.quiet,
|
|
1887
|
+
args
|
|
1776
1888
|
});
|
|
1777
|
-
if (exitCode !== 0) throw new Error(`muon-prepare failed with exit code ${exitCode}.\n${stderr.trim()}`);
|
|
1778
1889
|
const result = JSON.parse(stdout);
|
|
1779
|
-
if (result.stagePath !== void 0 && typeof result.stagePath !== "string" || typeof result.muonPath !== "string" || typeof result.cefPath !== "string" || typeof result.cacheHit !== "boolean") throw new Error(`muon-
|
|
1890
|
+
if (result.stagePath !== void 0 && typeof result.stagePath !== "string" || typeof result.muonPath !== "string" || typeof result.cefPath !== "string" || typeof result.cacheHit !== "boolean") throw new Error(`muon-builder returned invalid JSON: ${stdout}`);
|
|
1780
1891
|
return {
|
|
1781
1892
|
...result.stagePath === void 0 ? {} : { stagePath: result.stagePath },
|
|
1782
1893
|
muonPath: result.muonPath,
|
|
@@ -1784,6 +1895,675 @@ var runMuonPrepare = async (options) => {
|
|
|
1784
1895
|
cacheHit: result.cacheHit
|
|
1785
1896
|
};
|
|
1786
1897
|
};
|
|
1898
|
+
/**
|
|
1899
|
+
* Invokes the native muon-builder executable to write Windows PE resources.
|
|
1900
|
+
*
|
|
1901
|
+
* @param options Resource update invocation options.
|
|
1902
|
+
*/
|
|
1903
|
+
var runMuonPrepareResourceUpdate = async (options) => {
|
|
1904
|
+
await runMuonPrepareCommand({
|
|
1905
|
+
prepareExecutablePath: options.prepareExecutablePath,
|
|
1906
|
+
environment: options.environment,
|
|
1907
|
+
cwd: options.cwd,
|
|
1908
|
+
quiet: options.quiet,
|
|
1909
|
+
args: [
|
|
1910
|
+
"resource",
|
|
1911
|
+
"--input",
|
|
1912
|
+
options.inputPath,
|
|
1913
|
+
"--updates-json",
|
|
1914
|
+
options.updatesJsonPath,
|
|
1915
|
+
"--output",
|
|
1916
|
+
options.outputPath,
|
|
1917
|
+
...options.quiet ? ["--quiet"] : []
|
|
1918
|
+
]
|
|
1919
|
+
});
|
|
1920
|
+
};
|
|
1921
|
+
//#endregion
|
|
1922
|
+
//#region src/windows-icon.ts
|
|
1923
|
+
var sharp = __resolveDefaultExport$1(__screwUpDefaultImportModule0$1, true);
|
|
1924
|
+
globalThis.__screwUpIsInCJS_27e672935538 = false;
|
|
1925
|
+
function __resolveDefaultExport$1(module, isESM) {
|
|
1926
|
+
const __isInCJS = typeof globalThis !== "undefined" && globalThis.__screwUpIsInCJS_27e672935538 === true;
|
|
1927
|
+
const maybe = module;
|
|
1928
|
+
const hasDefault = !!(maybe && typeof maybe === "object" && "default" in maybe);
|
|
1929
|
+
const unwrapNamespaceDefault = (value) => {
|
|
1930
|
+
if (!value || typeof value !== "object") return value;
|
|
1931
|
+
const inner = value;
|
|
1932
|
+
if ((inner.__esModule === true || typeof Symbol !== "undefined" && inner[Symbol.toStringTag] === "Module") && "default" in inner) return inner.default;
|
|
1933
|
+
return value;
|
|
1934
|
+
};
|
|
1935
|
+
const resolvedDefault = hasDefault ? unwrapNamespaceDefault(maybe.default) : void 0;
|
|
1936
|
+
if (__isInCJS) return hasDefault ? resolvedDefault ?? module : module;
|
|
1937
|
+
if (isESM) {
|
|
1938
|
+
if (hasDefault) return resolvedDefault;
|
|
1939
|
+
throw new Error("Default export not found.");
|
|
1940
|
+
}
|
|
1941
|
+
return hasDefault ? resolvedDefault ?? module : module;
|
|
1942
|
+
}
|
|
1943
|
+
var normalizedIconSize = 256;
|
|
1944
|
+
var windowsIconDibSizes = [
|
|
1945
|
+
16,
|
|
1946
|
+
24,
|
|
1947
|
+
32,
|
|
1948
|
+
48,
|
|
1949
|
+
64,
|
|
1950
|
+
128
|
|
1951
|
+
];
|
|
1952
|
+
var pngSignature = Buffer.from([
|
|
1953
|
+
137,
|
|
1954
|
+
80,
|
|
1955
|
+
78,
|
|
1956
|
+
71,
|
|
1957
|
+
13,
|
|
1958
|
+
10,
|
|
1959
|
+
26,
|
|
1960
|
+
10
|
|
1961
|
+
]);
|
|
1962
|
+
/**
|
|
1963
|
+
* Creates a normalized square PNG icon image.
|
|
1964
|
+
*
|
|
1965
|
+
* @param pngData Source PNG bytes.
|
|
1966
|
+
* @param source Diagnostic source label used in errors.
|
|
1967
|
+
* @param label User-facing diagnostic label.
|
|
1968
|
+
* @returns PNG bytes normalized to the Muon base icon size.
|
|
1969
|
+
* @remarks Non-square images are fitted into transparent padding without
|
|
1970
|
+
* stretching. The normalized PNG is the source for all platform-specific icon
|
|
1971
|
+
* derivatives.
|
|
1972
|
+
*/
|
|
1973
|
+
var createNormalizedIconPngData = async (pngData, source, label) => {
|
|
1974
|
+
await assertPngData(pngData, source, label);
|
|
1975
|
+
try {
|
|
1976
|
+
return await sharp(pngData).resize(normalizedIconSize, normalizedIconSize, {
|
|
1977
|
+
fit: "contain",
|
|
1978
|
+
background: {
|
|
1979
|
+
r: 0,
|
|
1980
|
+
g: 0,
|
|
1981
|
+
b: 0,
|
|
1982
|
+
alpha: 0
|
|
1983
|
+
}
|
|
1984
|
+
}).ensureAlpha().png().toBuffer();
|
|
1985
|
+
} catch {
|
|
1986
|
+
throw new Error(`${label} must be a valid PNG: ${source}`);
|
|
1987
|
+
}
|
|
1988
|
+
};
|
|
1989
|
+
/**
|
|
1990
|
+
* Creates a normalized square PNG icon image for Windows resources.
|
|
1991
|
+
*
|
|
1992
|
+
* @param pngData Source PNG bytes.
|
|
1993
|
+
* @param source Diagnostic source label used in errors.
|
|
1994
|
+
* @returns PNG bytes normalized to the Muon base icon size.
|
|
1995
|
+
*/
|
|
1996
|
+
var createNormalizedMuonIconPngData = async (pngData, source) => await createNormalizedIconPngData(pngData, source, "Windows resource icon");
|
|
1997
|
+
/**
|
|
1998
|
+
* Creates a Windows ICO file from PNG bytes.
|
|
1999
|
+
*
|
|
2000
|
+
* @param pngData Source PNG bytes.
|
|
2001
|
+
* @param source Diagnostic source label used in errors.
|
|
2002
|
+
* @returns ICO file bytes containing 16, 24, 32, 48, 64, 128, and 256 pixel images.
|
|
2003
|
+
* @remarks The 256px entry is PNG-compressed. Smaller entries are 32-bit DIB
|
|
2004
|
+
* images, matching the common Windows ICO layout recommended by Microsoft.
|
|
2005
|
+
*/
|
|
2006
|
+
var createWindowsIconBufferFromPngData = async (pngData, source) => {
|
|
2007
|
+
const normalizedPng = await createNormalizedMuonIconPngData(pngData, source);
|
|
2008
|
+
const images = [];
|
|
2009
|
+
for (const size of windowsIconDibSizes) {
|
|
2010
|
+
const rawImage = await resizePngToRawRgba(normalizedPng, size, source);
|
|
2011
|
+
images.push({
|
|
2012
|
+
data: createDibIconImage(rawImage),
|
|
2013
|
+
size,
|
|
2014
|
+
bitCount: 32
|
|
2015
|
+
});
|
|
2016
|
+
}
|
|
2017
|
+
images.push({
|
|
2018
|
+
data: normalizedPng,
|
|
2019
|
+
size: normalizedIconSize,
|
|
2020
|
+
bitCount: 32
|
|
2021
|
+
});
|
|
2022
|
+
return createIco(images);
|
|
2023
|
+
};
|
|
2024
|
+
/**
|
|
2025
|
+
* Creates a Windows ICO file from a PNG file.
|
|
2026
|
+
*
|
|
2027
|
+
* @param sourcePath Source PNG file path.
|
|
2028
|
+
* @param outputPath Output ICO file path.
|
|
2029
|
+
* @returns Promise resolved when the ICO file has been written.
|
|
2030
|
+
*/
|
|
2031
|
+
var createWindowsIconFromPngFile = async (sourcePath, outputPath) => {
|
|
2032
|
+
const icon = await createWindowsIconBufferFromPngData(await readFile(sourcePath), sourcePath);
|
|
2033
|
+
await mkdir(dirname(outputPath), { recursive: true });
|
|
2034
|
+
await writeFile(outputPath, icon);
|
|
2035
|
+
};
|
|
2036
|
+
var assertPngData = async (data, source, label) => {
|
|
2037
|
+
if (data.length === 0) throw new Error(`${label} PNG must not be empty: ${source}`);
|
|
2038
|
+
if (!data.subarray(0, pngSignature.length).equals(pngSignature)) throw new Error(`${label} must be a valid PNG: ${source}`);
|
|
2039
|
+
try {
|
|
2040
|
+
if ((await sharp(data).metadata()).format !== "png") throw new Error();
|
|
2041
|
+
} catch {
|
|
2042
|
+
throw new Error(`${label} must be a valid PNG: ${source}`);
|
|
2043
|
+
}
|
|
2044
|
+
};
|
|
2045
|
+
var resizePngToRawRgba = async (pngData, size, source) => {
|
|
2046
|
+
try {
|
|
2047
|
+
const { data, info } = await sharp(pngData).resize(size, size, {
|
|
2048
|
+
fit: "fill",
|
|
2049
|
+
kernel: "lanczos3"
|
|
2050
|
+
}).ensureAlpha().raw().toBuffer({ resolveWithObject: true });
|
|
2051
|
+
if (info.width !== size || info.height !== size || info.channels !== 4) throw new Error();
|
|
2052
|
+
return {
|
|
2053
|
+
data,
|
|
2054
|
+
width: info.width,
|
|
2055
|
+
height: info.height
|
|
2056
|
+
};
|
|
2057
|
+
} catch {
|
|
2058
|
+
throw new Error(`Failed to resize Windows resource icon PNG: ${source}`);
|
|
2059
|
+
}
|
|
2060
|
+
};
|
|
2061
|
+
var createDibIconImage = (image) => {
|
|
2062
|
+
const pixelBytes = image.width * image.height * 4;
|
|
2063
|
+
const maskBytes = Math.ceil(image.width / 32) * 4 * image.height;
|
|
2064
|
+
const output = Buffer.alloc(40 + pixelBytes + maskBytes);
|
|
2065
|
+
output.writeUInt32LE(40, 0);
|
|
2066
|
+
output.writeInt32LE(image.width, 4);
|
|
2067
|
+
output.writeInt32LE(image.height * 2, 8);
|
|
2068
|
+
output.writeUInt16LE(1, 12);
|
|
2069
|
+
output.writeUInt16LE(32, 14);
|
|
2070
|
+
output.writeUInt32LE(0, 16);
|
|
2071
|
+
output.writeUInt32LE(pixelBytes + maskBytes, 20);
|
|
2072
|
+
output.writeInt32LE(0, 24);
|
|
2073
|
+
output.writeInt32LE(0, 28);
|
|
2074
|
+
output.writeUInt32LE(0, 32);
|
|
2075
|
+
output.writeUInt32LE(0, 36);
|
|
2076
|
+
for (let y = 0; y < image.height; y += 1) {
|
|
2077
|
+
const sourceY = image.height - 1 - y;
|
|
2078
|
+
for (let x = 0; x < image.width; x += 1) {
|
|
2079
|
+
const sourceOffset = (sourceY * image.width + x) * 4;
|
|
2080
|
+
const outputOffset = 40 + (y * image.width + x) * 4;
|
|
2081
|
+
output[outputOffset] = image.data[sourceOffset + 2];
|
|
2082
|
+
output[outputOffset + 1] = image.data[sourceOffset + 1];
|
|
2083
|
+
output[outputOffset + 2] = image.data[sourceOffset];
|
|
2084
|
+
output[outputOffset + 3] = image.data[sourceOffset + 3];
|
|
2085
|
+
}
|
|
2086
|
+
}
|
|
2087
|
+
return output;
|
|
2088
|
+
};
|
|
2089
|
+
var createIco = (images) => {
|
|
2090
|
+
const directorySize = 6 + images.length * 16;
|
|
2091
|
+
let imageOffset = directorySize;
|
|
2092
|
+
const header = Buffer.alloc(directorySize);
|
|
2093
|
+
header.writeUInt16LE(0, 0);
|
|
2094
|
+
header.writeUInt16LE(1, 2);
|
|
2095
|
+
header.writeUInt16LE(images.length, 4);
|
|
2096
|
+
const imageData = [];
|
|
2097
|
+
images.forEach((image, index) => {
|
|
2098
|
+
const entryOffset = 6 + index * 16;
|
|
2099
|
+
header[entryOffset] = image.size === 256 ? 0 : image.size;
|
|
2100
|
+
header[entryOffset + 1] = image.size === 256 ? 0 : image.size;
|
|
2101
|
+
header[entryOffset + 2] = 0;
|
|
2102
|
+
header[entryOffset + 3] = 0;
|
|
2103
|
+
header.writeUInt16LE(1, entryOffset + 4);
|
|
2104
|
+
header.writeUInt16LE(image.bitCount, entryOffset + 6);
|
|
2105
|
+
header.writeUInt32LE(image.data.length, entryOffset + 8);
|
|
2106
|
+
header.writeUInt32LE(imageOffset, entryOffset + 12);
|
|
2107
|
+
imageOffset += image.data.length;
|
|
2108
|
+
imageData.push(image.data);
|
|
2109
|
+
});
|
|
2110
|
+
return Buffer.concat([header, ...imageData]);
|
|
2111
|
+
};
|
|
2112
|
+
//#endregion
|
|
2113
|
+
//#region src/windows-resource.ts
|
|
2114
|
+
var defaultLanguage = 1033;
|
|
2115
|
+
var defaultCodePage = 1200;
|
|
2116
|
+
var moduleDirectory$3 = typeof __dirname === "string" ? __dirname : dirname(fileURLToPath(import.meta.url));
|
|
2117
|
+
/**
|
|
2118
|
+
* Merges Windows resource options while preserving field-level fallback.
|
|
2119
|
+
*/
|
|
2120
|
+
var mergeMuonWindowsResourceOptions = (primary, fallback) => {
|
|
2121
|
+
if (primary === void 0) return fallback;
|
|
2122
|
+
if (fallback === void 0) return primary;
|
|
2123
|
+
const merged = { ...fallback };
|
|
2124
|
+
if (primary.iconPath !== void 0) merged.iconPath = primary.iconPath;
|
|
2125
|
+
if (primary.productName !== void 0) merged.productName = primary.productName;
|
|
2126
|
+
if (primary.fileDescription !== void 0) merged.fileDescription = primary.fileDescription;
|
|
2127
|
+
if (primary.companyName !== void 0) merged.companyName = primary.companyName;
|
|
2128
|
+
if (primary.version !== void 0) merged.version = primary.version;
|
|
2129
|
+
if (primary.copyright !== void 0) merged.copyright = primary.copyright;
|
|
2130
|
+
if (primary.language !== void 0) merged.language = primary.language;
|
|
2131
|
+
if (primary.codePage !== void 0) merged.codePage = primary.codePage;
|
|
2132
|
+
return merged;
|
|
2133
|
+
};
|
|
2134
|
+
/**
|
|
2135
|
+
* Resolves Windows resource metadata from options, config files, and package metadata.
|
|
2136
|
+
*/
|
|
2137
|
+
var resolveMuonWindowsResource = async (input) => {
|
|
2138
|
+
const projectJson = await readProjectJson(input.root);
|
|
2139
|
+
const sources = [
|
|
2140
|
+
createOptionsSource$1(input.options, input.root, "windowsResource"),
|
|
2141
|
+
readConfigWindowsResourceSource(input.muonConfig, input.muonConfigDirectory, "muon.json"),
|
|
2142
|
+
createProjectSource(projectJson, input.root),
|
|
2143
|
+
createPackageSource(input.packageJson, input.root)
|
|
2144
|
+
].filter((source) => source !== void 0);
|
|
2145
|
+
const productName = resolveStringField$1(sources, "productName", input.defaults.productName);
|
|
2146
|
+
const fileDescription = resolveStringField$1(sources, "fileDescription", input.defaults.fileDescription);
|
|
2147
|
+
const companyName = resolveStringField$1(sources, "companyName", input.defaults.companyName);
|
|
2148
|
+
const version = resolveStringField$1(sources, "version", input.defaults.version);
|
|
2149
|
+
const copyright = resolveOptionalStringField(sources, "copyright", input.defaults.copyright);
|
|
2150
|
+
const language = resolveNumericField(sources, "language", defaultLanguage);
|
|
2151
|
+
const codePage = resolveNumericField(sources, "codePage", defaultCodePage);
|
|
2152
|
+
const fixedVersion = normalizeWindowsVersion(version);
|
|
2153
|
+
return {
|
|
2154
|
+
iconPath: await resolveIconPath$1(sources, await resolveDefaultWindowsIcon(input.packageDirectory)),
|
|
2155
|
+
productName,
|
|
2156
|
+
fileDescription,
|
|
2157
|
+
companyName,
|
|
2158
|
+
version,
|
|
2159
|
+
fixedVersion,
|
|
2160
|
+
copyright,
|
|
2161
|
+
language,
|
|
2162
|
+
codePage
|
|
2163
|
+
};
|
|
2164
|
+
};
|
|
2165
|
+
/**
|
|
2166
|
+
* Removes build-only Windows resource settings from runtime config.
|
|
2167
|
+
*/
|
|
2168
|
+
var stripBuildOnlyWindowsResourceConfig = (sourceConfig) => {
|
|
2169
|
+
const sourceWindows = sourceConfig.windows;
|
|
2170
|
+
if (!isJsonObject$3(sourceWindows)) return sourceConfig;
|
|
2171
|
+
const windowsConfig = {};
|
|
2172
|
+
for (const [key, value] of Object.entries(sourceWindows)) if (key !== "resource") windowsConfig[key] = value;
|
|
2173
|
+
const output = {};
|
|
2174
|
+
for (const [key, value] of Object.entries(sourceConfig)) if (key !== "windows") output[key] = value;
|
|
2175
|
+
if (Object.keys(windowsConfig).length > 0) output.windows = windowsConfig;
|
|
2176
|
+
return output;
|
|
2177
|
+
};
|
|
2178
|
+
/**
|
|
2179
|
+
* Returns true when the file has a Windows PE header.
|
|
2180
|
+
*/
|
|
2181
|
+
var isWindowsPeExecutable = async (path) => {
|
|
2182
|
+
const content = await readFile(path);
|
|
2183
|
+
if (content.length < 64 || content.toString("ascii", 0, 2) !== "MZ") return false;
|
|
2184
|
+
const peOffset = content.readUInt32LE(60);
|
|
2185
|
+
return peOffset + 4 <= content.length && content.toString("ascii", peOffset, peOffset + 4) === "PE\0\0";
|
|
2186
|
+
};
|
|
2187
|
+
/**
|
|
2188
|
+
* Applies resolved resource metadata to a Windows PE executable in place.
|
|
2189
|
+
*/
|
|
2190
|
+
var updateWindowsPeResources = async (input) => {
|
|
2191
|
+
if (!await isWindowsPeExecutable(input.executablePath)) return false;
|
|
2192
|
+
const mode = (await stat(input.executablePath)).mode & 511;
|
|
2193
|
+
const tempDirectory = await mkdtemp(join(tmpdir(), "muon-windows-resource-"));
|
|
2194
|
+
const updatesJsonPath = join(tempDirectory, "updates.json");
|
|
2195
|
+
const outputPath = join(tempDirectory, "output.exe");
|
|
2196
|
+
const iconPath = input.resource.iconPath === void 0 ? void 0 : join(tempDirectory, "icon.ico");
|
|
2197
|
+
try {
|
|
2198
|
+
if (input.resource.iconPath !== void 0 && iconPath !== void 0) await createWindowsIconFromPngFile(input.resource.iconPath, iconPath);
|
|
2199
|
+
await writeFile(updatesJsonPath, `${JSON.stringify(createEngraverUpdate(input.resource, iconPath), null, 2)}\n`);
|
|
2200
|
+
await runMuonPrepareResourceUpdate({
|
|
2201
|
+
inputPath: input.executablePath,
|
|
2202
|
+
updatesJsonPath,
|
|
2203
|
+
outputPath,
|
|
2204
|
+
quiet: true,
|
|
2205
|
+
prepareExecutablePath: void 0,
|
|
2206
|
+
environment: input.environment,
|
|
2207
|
+
cwd: input.cwd
|
|
2208
|
+
});
|
|
2209
|
+
await copyFile(outputPath, input.executablePath);
|
|
2210
|
+
await chmod(input.executablePath, mode === 0 ? 493 : mode);
|
|
2211
|
+
return true;
|
|
2212
|
+
} finally {
|
|
2213
|
+
await rm(tempDirectory, {
|
|
2214
|
+
recursive: true,
|
|
2215
|
+
force: true
|
|
2216
|
+
});
|
|
2217
|
+
}
|
|
2218
|
+
};
|
|
2219
|
+
var createEngraverUpdate = (resource, iconPath) => {
|
|
2220
|
+
const strings = {
|
|
2221
|
+
CompanyName: resource.companyName,
|
|
2222
|
+
FileDescription: resource.fileDescription,
|
|
2223
|
+
FileVersion: resource.version,
|
|
2224
|
+
ProductName: resource.productName,
|
|
2225
|
+
ProductVersion: resource.version
|
|
2226
|
+
};
|
|
2227
|
+
if (resource.copyright !== void 0) strings.LegalCopyright = resource.copyright;
|
|
2228
|
+
return {
|
|
2229
|
+
version: {
|
|
2230
|
+
language: resource.language,
|
|
2231
|
+
codePage: resource.codePage,
|
|
2232
|
+
fixed: {
|
|
2233
|
+
fileVersion: resource.fixedVersion,
|
|
2234
|
+
productVersion: resource.fixedVersion,
|
|
2235
|
+
fileOS: "windows32",
|
|
2236
|
+
fileType: "app"
|
|
2237
|
+
},
|
|
2238
|
+
strings
|
|
2239
|
+
},
|
|
2240
|
+
icons: iconPath === void 0 ? [] : [{
|
|
2241
|
+
id: 1,
|
|
2242
|
+
language: resource.language,
|
|
2243
|
+
path: iconPath
|
|
2244
|
+
}]
|
|
2245
|
+
};
|
|
2246
|
+
};
|
|
2247
|
+
var readProjectJson = async (root) => {
|
|
2248
|
+
const projectJsonPath = join(root, "project.json");
|
|
2249
|
+
if (!await fileExists$3(projectJsonPath)) return {};
|
|
2250
|
+
return await readJsonObjectFile$1(projectJsonPath, "project.json");
|
|
2251
|
+
};
|
|
2252
|
+
var readJsonObjectFile$1 = async (filePath, label) => {
|
|
2253
|
+
const parsed = (0, import_dist.parse)(await readFile(filePath, "utf8"));
|
|
2254
|
+
if (!isJsonObject$3(parsed)) throw new Error(`${label} must contain a JSON object: ${filePath}`);
|
|
2255
|
+
return parsed;
|
|
2256
|
+
};
|
|
2257
|
+
var createOptionsSource$1 = (options, directory, label) => {
|
|
2258
|
+
if (options === void 0) return;
|
|
2259
|
+
return {
|
|
2260
|
+
options: validateWindowsResourceOptions(options, label),
|
|
2261
|
+
directory
|
|
2262
|
+
};
|
|
2263
|
+
};
|
|
2264
|
+
var readConfigWindowsResourceSource = (config, directory, label) => {
|
|
2265
|
+
const windows = config.windows;
|
|
2266
|
+
if (windows === void 0) return;
|
|
2267
|
+
if (!isJsonObject$3(windows)) throw new Error(`${label} windows must be an object when present.`);
|
|
2268
|
+
const resource = windows.resource;
|
|
2269
|
+
if (resource === void 0) return;
|
|
2270
|
+
return createOptionsSource$1(validateWindowsResourceOptions(resource, `${label} windows.resource`), directory, `${label} windows.resource`);
|
|
2271
|
+
};
|
|
2272
|
+
var createProjectSource = (projectJson, directory) => {
|
|
2273
|
+
const topLevel = {};
|
|
2274
|
+
copyStringField(projectJson, "iconPath", topLevel, "iconPath");
|
|
2275
|
+
copyStringField(projectJson, "productName", topLevel, "productName");
|
|
2276
|
+
copyStringField(projectJson, "name", topLevel, "productName");
|
|
2277
|
+
copyStringField(projectJson, "fileDescription", topLevel, "fileDescription");
|
|
2278
|
+
copyStringField(projectJson, "description", topLevel, "fileDescription");
|
|
2279
|
+
copyStringField(projectJson, "companyName", topLevel, "companyName");
|
|
2280
|
+
copyStringField(projectJson, "version", topLevel, "version");
|
|
2281
|
+
copyStringField(projectJson, "copyright", topLevel, "copyright");
|
|
2282
|
+
const author = stringifyAuthor(projectJson.author);
|
|
2283
|
+
if (author !== void 0 && topLevel.companyName === void 0) topLevel.companyName = author;
|
|
2284
|
+
const options = mergeMuonWindowsResourceOptions(readConfigWindowsResourceSource(projectJson, directory, "project.json")?.options, topLevel);
|
|
2285
|
+
if (options === void 0 || Object.keys(options).length === 0) return;
|
|
2286
|
+
return {
|
|
2287
|
+
options,
|
|
2288
|
+
directory
|
|
2289
|
+
};
|
|
2290
|
+
};
|
|
2291
|
+
var createPackageSource = (packageJson, directory) => {
|
|
2292
|
+
const options = {};
|
|
2293
|
+
copyStringField(packageJson, "name", options, "productName");
|
|
2294
|
+
copyStringField(packageJson, "description", options, "fileDescription");
|
|
2295
|
+
copyStringField(packageJson, "version", options, "version");
|
|
2296
|
+
copyStringField(packageJson, "copyright", options, "copyright");
|
|
2297
|
+
const author = stringifyAuthor(packageJson.author);
|
|
2298
|
+
if (author !== void 0) options.companyName = author;
|
|
2299
|
+
return Object.keys(options).length === 0 ? void 0 : {
|
|
2300
|
+
options,
|
|
2301
|
+
directory
|
|
2302
|
+
};
|
|
2303
|
+
};
|
|
2304
|
+
var copyStringField = (source, sourceKey, target, targetKey) => {
|
|
2305
|
+
const value = source[sourceKey];
|
|
2306
|
+
if (typeof value === "string" && value.trim() !== "") target[targetKey] = value.trim();
|
|
2307
|
+
};
|
|
2308
|
+
var validateWindowsResourceOptions = (value, label) => {
|
|
2309
|
+
if (!isJsonObject$3(value)) throw new Error(`${label} must be an object.`);
|
|
2310
|
+
const output = {};
|
|
2311
|
+
copyOptionalStringResourceField(value, "iconPath", output);
|
|
2312
|
+
copyOptionalStringResourceField(value, "productName", output);
|
|
2313
|
+
copyOptionalStringResourceField(value, "fileDescription", output);
|
|
2314
|
+
copyOptionalStringResourceField(value, "companyName", output);
|
|
2315
|
+
copyOptionalStringResourceField(value, "version", output);
|
|
2316
|
+
copyOptionalStringResourceField(value, "copyright", output);
|
|
2317
|
+
copyOptionalNumberResourceField(value, "language", output, label);
|
|
2318
|
+
copyOptionalNumberResourceField(value, "codePage", output, label);
|
|
2319
|
+
return output;
|
|
2320
|
+
};
|
|
2321
|
+
var copyOptionalStringResourceField = (source, key, target) => {
|
|
2322
|
+
const value = source[key];
|
|
2323
|
+
if (value === void 0) return;
|
|
2324
|
+
if (typeof value !== "string") throw new Error(`${key} must be a string when present.`);
|
|
2325
|
+
if (value.trim() !== "") target[key] = value.trim();
|
|
2326
|
+
};
|
|
2327
|
+
var copyOptionalNumberResourceField = (source, key, target, label) => {
|
|
2328
|
+
const value = source[key];
|
|
2329
|
+
if (value === void 0) return;
|
|
2330
|
+
if (typeof value !== "number" || !Number.isInteger(value) || value < 0 || value > 65535) throw new Error(`${label} ${key} must be an integer from 0 to 65535.`);
|
|
2331
|
+
target[key] = value;
|
|
2332
|
+
};
|
|
2333
|
+
var resolveStringField$1 = (sources, field, fallback) => {
|
|
2334
|
+
return resolveOptionalStringField(sources, field, fallback) ?? fallback;
|
|
2335
|
+
};
|
|
2336
|
+
var resolveOptionalStringField = (sources, field, fallback) => {
|
|
2337
|
+
for (const source of sources) {
|
|
2338
|
+
const value = source.options[field];
|
|
2339
|
+
if (value !== void 0 && value.trim() !== "") return value.trim();
|
|
2340
|
+
}
|
|
2341
|
+
return fallback;
|
|
2342
|
+
};
|
|
2343
|
+
var resolveNumericField = (sources, field, fallback) => {
|
|
2344
|
+
for (const source of sources) {
|
|
2345
|
+
const value = source.options[field];
|
|
2346
|
+
if (value !== void 0) return value;
|
|
2347
|
+
}
|
|
2348
|
+
return fallback;
|
|
2349
|
+
};
|
|
2350
|
+
var resolveIconPath$1 = async (sources, defaultIconPath) => {
|
|
2351
|
+
for (const source of sources) {
|
|
2352
|
+
const value = source.options.iconPath;
|
|
2353
|
+
if (value !== void 0 && value.trim() !== "") {
|
|
2354
|
+
const iconPath = resolveResourcePath$1(source.directory, value);
|
|
2355
|
+
await assertIconPath$1(iconPath, true);
|
|
2356
|
+
return iconPath;
|
|
2357
|
+
}
|
|
2358
|
+
}
|
|
2359
|
+
if (defaultIconPath !== void 0 && await fileExists$3(defaultIconPath)) {
|
|
2360
|
+
await assertIconPath$1(defaultIconPath, false);
|
|
2361
|
+
return defaultIconPath;
|
|
2362
|
+
}
|
|
2363
|
+
};
|
|
2364
|
+
var assertIconPath$1 = async (iconPath, required) => {
|
|
2365
|
+
if (extname(iconPath).toLowerCase() !== ".png") throw new Error(`Windows resource icon must be a .png file: ${iconPath}`);
|
|
2366
|
+
if (required && !await fileExists$3(iconPath)) throw new Error(`Windows resource icon does not exist: ${iconPath}`);
|
|
2367
|
+
if (await fileExists$3(iconPath)) await createNormalizedMuonIconPngData(await readFile(iconPath), iconPath);
|
|
2368
|
+
};
|
|
2369
|
+
var resolveDefaultWindowsIcon = async (packageDirectory) => {
|
|
2370
|
+
const candidates = [
|
|
2371
|
+
join(resolve(packageDirectory), "native", "muon-bootstrap.png"),
|
|
2372
|
+
join(moduleDirectory$3, "native", "muon-bootstrap.png"),
|
|
2373
|
+
join(moduleDirectory$3, "..", "dist", "native", "muon-bootstrap.png"),
|
|
2374
|
+
join(moduleDirectory$3, "..", "..", "images", "muon-bootstrap-256.png")
|
|
2375
|
+
];
|
|
2376
|
+
for (const candidate of candidates) if (await fileExists$3(candidate)) return candidate;
|
|
2377
|
+
};
|
|
2378
|
+
var resolveResourcePath$1 = (directory, path) => {
|
|
2379
|
+
return isAbsolute(path) ? path : resolve(directory, path);
|
|
2380
|
+
};
|
|
2381
|
+
var normalizeWindowsVersion = (version) => {
|
|
2382
|
+
const normalized = version.trim();
|
|
2383
|
+
const match = /^(\d+)(?:\.(\d+))?(?:\.(\d+))?(?:\.(\d+))?(?:$|[-+])/.exec(normalized);
|
|
2384
|
+
if (match === null) throw new Error(`Windows resource version must start with numeric parts: ${version}`);
|
|
2385
|
+
const values = [
|
|
2386
|
+
match[1],
|
|
2387
|
+
match[2],
|
|
2388
|
+
match[3],
|
|
2389
|
+
match[4]
|
|
2390
|
+
].map((value) => value === void 0 ? 0 : Number.parseInt(value, 10));
|
|
2391
|
+
for (const value of values) if (!Number.isInteger(value) || value < 0 || value > 65535) throw new Error(`Windows resource version part must be from 0 to 65535: ${version}`);
|
|
2392
|
+
return values.join(".");
|
|
2393
|
+
};
|
|
2394
|
+
var stringifyAuthor = (value) => {
|
|
2395
|
+
if (typeof value === "string" && value.trim() !== "") return value.trim();
|
|
2396
|
+
if (!isJsonObject$3(value) || typeof value.name !== "string") return;
|
|
2397
|
+
const name = value.name.trim();
|
|
2398
|
+
if (name === "") return;
|
|
2399
|
+
return value.email === void 0 || typeof value.email !== "string" ? name : `${name} <${value.email}>`;
|
|
2400
|
+
};
|
|
2401
|
+
var fileExists$3 = async (path) => {
|
|
2402
|
+
try {
|
|
2403
|
+
await access(path, constants.F_OK);
|
|
2404
|
+
return true;
|
|
2405
|
+
} catch {
|
|
2406
|
+
return false;
|
|
2407
|
+
}
|
|
2408
|
+
};
|
|
2409
|
+
var isJsonObject$3 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
2410
|
+
//#endregion
|
|
2411
|
+
//#region src/linux-desktop.ts
|
|
2412
|
+
var defaultIconFileName = "muon-desktop-icon.png";
|
|
2413
|
+
var defaultDesktopConfigFileName = "muon-desktop.json";
|
|
2414
|
+
var moduleDirectory$2 = typeof __dirname === "string" ? __dirname : dirname(fileURLToPath(import.meta.url));
|
|
2415
|
+
/**
|
|
2416
|
+
* Resolves Linux desktop integration metadata from options, config files, and
|
|
2417
|
+
* package metadata.
|
|
2418
|
+
*/
|
|
2419
|
+
var resolveMuonLinuxDesktop = async (input) => {
|
|
2420
|
+
const sources = [createOptionsSource(input.options, input.root, "linuxDesktop"), readConfigLinuxDesktopSource(input.muonConfig, input.muonConfigDirectory, "muon.json")].filter((source) => source !== void 0);
|
|
2421
|
+
return {
|
|
2422
|
+
desktopId: sanitizeDesktopId(resolveStringField(sources, "desktopId", input.defaults.desktopId)),
|
|
2423
|
+
name: resolveStringField(sources, "name", input.defaults.name),
|
|
2424
|
+
comment: resolveStringField(sources, "comment", input.defaults.comment),
|
|
2425
|
+
categories: resolveCategories(sources, input.defaults.categories),
|
|
2426
|
+
startupNotify: resolveBooleanField(sources, "startupNotify", input.defaults.startupNotify),
|
|
2427
|
+
iconPath: await resolveIconPath(sources, await resolveDefaultLinuxDesktopIcon(input.packageDirectory)),
|
|
2428
|
+
iconFileName: defaultIconFileName,
|
|
2429
|
+
configFileName: defaultDesktopConfigFileName
|
|
2430
|
+
};
|
|
2431
|
+
};
|
|
2432
|
+
/**
|
|
2433
|
+
* Removes build-only Linux desktop settings from runtime config.
|
|
2434
|
+
*/
|
|
2435
|
+
var stripBuildOnlyLinuxDesktopConfig = (sourceConfig) => {
|
|
2436
|
+
const sourceLinux = sourceConfig.linux;
|
|
2437
|
+
if (!isJsonObject$2(sourceLinux)) return sourceConfig;
|
|
2438
|
+
const linuxConfig = {};
|
|
2439
|
+
for (const [key, value] of Object.entries(sourceLinux)) if (key !== "desktop") linuxConfig[key] = value;
|
|
2440
|
+
const output = {};
|
|
2441
|
+
for (const [key, value] of Object.entries(sourceConfig)) if (key !== "linux") output[key] = value;
|
|
2442
|
+
if (Object.keys(linuxConfig).length > 0) output.linux = linuxConfig;
|
|
2443
|
+
return output;
|
|
2444
|
+
};
|
|
2445
|
+
/**
|
|
2446
|
+
* Writes normalized Linux desktop sidecar files into a target distribution.
|
|
2447
|
+
*/
|
|
2448
|
+
var writeLinuxDesktopDistributionFiles = async (outputPath, desktop) => {
|
|
2449
|
+
const iconData = await createNormalizedIconPngData(await readFile(desktop.iconPath), desktop.iconPath, "Linux desktop icon");
|
|
2450
|
+
await writeFile(join(outputPath, desktop.iconFileName), iconData);
|
|
2451
|
+
await writeFile(join(outputPath, desktop.configFileName), `${JSON.stringify({
|
|
2452
|
+
desktopId: desktop.desktopId,
|
|
2453
|
+
name: desktop.name,
|
|
2454
|
+
comment: desktop.comment,
|
|
2455
|
+
categories: desktop.categories,
|
|
2456
|
+
startupNotify: desktop.startupNotify,
|
|
2457
|
+
iconFileName: desktop.iconFileName
|
|
2458
|
+
}, void 0, 2)}\n`);
|
|
2459
|
+
};
|
|
2460
|
+
var createOptionsSource = (options, directory, label) => {
|
|
2461
|
+
if (options === void 0) return;
|
|
2462
|
+
return {
|
|
2463
|
+
options: validateLinuxDesktopOptions(options, label),
|
|
2464
|
+
directory
|
|
2465
|
+
};
|
|
2466
|
+
};
|
|
2467
|
+
var readConfigLinuxDesktopSource = (config, directory, label) => {
|
|
2468
|
+
const linux = config.linux;
|
|
2469
|
+
if (linux === void 0) return;
|
|
2470
|
+
if (!isJsonObject$2(linux)) throw new Error(`${label} linux must be an object when present.`);
|
|
2471
|
+
const desktop = linux.desktop;
|
|
2472
|
+
if (desktop === void 0) return;
|
|
2473
|
+
return createOptionsSource(validateLinuxDesktopOptions(desktop, `${label} linux.desktop`), directory, `${label} linux.desktop`);
|
|
2474
|
+
};
|
|
2475
|
+
var validateLinuxDesktopOptions = (value, label) => {
|
|
2476
|
+
if (!isJsonObject$2(value)) throw new Error(`${label} must be an object.`);
|
|
2477
|
+
const output = {};
|
|
2478
|
+
copyOptionalStringDesktopField(value, "desktopId", output);
|
|
2479
|
+
copyOptionalStringDesktopField(value, "name", output);
|
|
2480
|
+
copyOptionalStringDesktopField(value, "comment", output);
|
|
2481
|
+
copyOptionalStringDesktopField(value, "iconPath", output);
|
|
2482
|
+
copyOptionalCategoriesField(value, output, label);
|
|
2483
|
+
copyOptionalBooleanDesktopField(value, "startupNotify", output, label);
|
|
2484
|
+
return output;
|
|
2485
|
+
};
|
|
2486
|
+
var copyOptionalStringDesktopField = (source, key, target) => {
|
|
2487
|
+
const value = source[key];
|
|
2488
|
+
if (value === void 0) return;
|
|
2489
|
+
if (typeof value !== "string") throw new Error(`${key} must be a string when present.`);
|
|
2490
|
+
if (value.trim() !== "") target[key] = value.trim();
|
|
2491
|
+
};
|
|
2492
|
+
var copyOptionalCategoriesField = (source, target, label) => {
|
|
2493
|
+
const value = source.categories;
|
|
2494
|
+
if (value === void 0) return;
|
|
2495
|
+
if (!Array.isArray(value) || !value.every((entry) => typeof entry === "string" && entry.trim() !== "" && !entry.includes(";") && !entry.includes("\n") && !entry.includes("\r"))) throw new Error(`${label} categories must be a string array without semicolons when present.`);
|
|
2496
|
+
target.categories = value.map((entry) => entry.trim());
|
|
2497
|
+
};
|
|
2498
|
+
var copyOptionalBooleanDesktopField = (source, key, target, label) => {
|
|
2499
|
+
const value = source[key];
|
|
2500
|
+
if (value === void 0) return;
|
|
2501
|
+
if (typeof value !== "boolean") throw new Error(`${label} ${key} must be a boolean when present.`);
|
|
2502
|
+
target[key] = value;
|
|
2503
|
+
};
|
|
2504
|
+
var resolveStringField = (sources, field, fallback) => {
|
|
2505
|
+
for (const source of sources) {
|
|
2506
|
+
const value = source.options[field];
|
|
2507
|
+
if (value !== void 0 && value.trim() !== "") return value.trim();
|
|
2508
|
+
}
|
|
2509
|
+
return fallback;
|
|
2510
|
+
};
|
|
2511
|
+
var resolveCategories = (sources, fallback) => {
|
|
2512
|
+
for (const source of sources) if (source.options.categories !== void 0) return source.options.categories;
|
|
2513
|
+
return fallback;
|
|
2514
|
+
};
|
|
2515
|
+
var resolveBooleanField = (sources, field, fallback) => {
|
|
2516
|
+
for (const source of sources) {
|
|
2517
|
+
const value = source.options[field];
|
|
2518
|
+
if (value !== void 0) return value;
|
|
2519
|
+
}
|
|
2520
|
+
return fallback;
|
|
2521
|
+
};
|
|
2522
|
+
var resolveIconPath = async (sources, defaultIconPath) => {
|
|
2523
|
+
for (const source of sources) {
|
|
2524
|
+
const value = source.options.iconPath;
|
|
2525
|
+
if (value !== void 0 && value.trim() !== "") {
|
|
2526
|
+
const iconPath = resolveResourcePath(source.directory, value);
|
|
2527
|
+
await assertIconPath(iconPath, true);
|
|
2528
|
+
return iconPath;
|
|
2529
|
+
}
|
|
2530
|
+
}
|
|
2531
|
+
if (defaultIconPath !== void 0 && await fileExists$2(defaultIconPath)) {
|
|
2532
|
+
await assertIconPath(defaultIconPath, false);
|
|
2533
|
+
return defaultIconPath;
|
|
2534
|
+
}
|
|
2535
|
+
throw new Error("Linux desktop icon does not exist.");
|
|
2536
|
+
};
|
|
2537
|
+
var assertIconPath = async (iconPath, required) => {
|
|
2538
|
+
if (extname(iconPath).toLowerCase() !== ".png") throw new Error(`Linux desktop icon must be a .png file: ${iconPath}`);
|
|
2539
|
+
if (required && !await fileExists$2(iconPath)) throw new Error(`Linux desktop icon does not exist: ${iconPath}`);
|
|
2540
|
+
if (await fileExists$2(iconPath)) await createNormalizedIconPngData(await readFile(iconPath), iconPath, "Linux desktop icon");
|
|
2541
|
+
};
|
|
2542
|
+
var resolveDefaultLinuxDesktopIcon = async (packageDirectory) => {
|
|
2543
|
+
const candidates = [
|
|
2544
|
+
join(resolve(packageDirectory), "native", "muon-bootstrap.png"),
|
|
2545
|
+
join(moduleDirectory$2, "native", "muon-bootstrap.png"),
|
|
2546
|
+
join(moduleDirectory$2, "..", "dist", "native", "muon-bootstrap.png"),
|
|
2547
|
+
join(moduleDirectory$2, "..", "..", "images", "muon-bootstrap-256.png")
|
|
2548
|
+
];
|
|
2549
|
+
for (const candidate of candidates) if (await fileExists$2(candidate)) return candidate;
|
|
2550
|
+
};
|
|
2551
|
+
var sanitizeDesktopId = (value) => {
|
|
2552
|
+
const sanitized = value.trim().toLowerCase().replace(/[^a-z0-9._-]+/g, "-").replace(/^[.-]+/g, "").replace(/[.-]+$/g, "");
|
|
2553
|
+
return sanitized.length > 0 ? sanitized : "muon-app";
|
|
2554
|
+
};
|
|
2555
|
+
var resolveResourcePath = (directory, path) => {
|
|
2556
|
+
return isAbsolute(path) ? path : resolve(directory, path);
|
|
2557
|
+
};
|
|
2558
|
+
var fileExists$2 = async (path) => {
|
|
2559
|
+
try {
|
|
2560
|
+
await access(path, constants.F_OK);
|
|
2561
|
+
return true;
|
|
2562
|
+
} catch {
|
|
2563
|
+
return false;
|
|
2564
|
+
}
|
|
2565
|
+
};
|
|
2566
|
+
var isJsonObject$2 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
1787
2567
|
//#endregion
|
|
1788
2568
|
//#region src/build.ts
|
|
1789
2569
|
var AdmZip = __resolveDefaultExport(__screwUpDefaultImportModule0, false);
|
|
@@ -1844,17 +2624,49 @@ var buildMuonApp = async (options = {}) => {
|
|
|
1844
2624
|
const appId = resolveAppId(packageJson, options.appId);
|
|
1845
2625
|
const buildConfig = await readBuildConfig(root, options.configPath);
|
|
1846
2626
|
const assetInput = resolveAssetInput(root, options.assetSourcePath, options.assetPrefix, buildConfig);
|
|
2627
|
+
const windowsResource = await resolveMuonWindowsResource({
|
|
2628
|
+
root,
|
|
2629
|
+
packageDirectory,
|
|
2630
|
+
packageJson,
|
|
2631
|
+
muonConfig: buildConfig.config,
|
|
2632
|
+
muonConfigDirectory: buildConfig.directory,
|
|
2633
|
+
options: options.windowsResource,
|
|
2634
|
+
defaults: {
|
|
2635
|
+
productName: appName,
|
|
2636
|
+
fileDescription: appName,
|
|
2637
|
+
companyName: "Unknown",
|
|
2638
|
+
version: "0.0.0",
|
|
2639
|
+
copyright: void 0
|
|
2640
|
+
}
|
|
2641
|
+
});
|
|
2642
|
+
const linuxDesktop = await resolveMuonLinuxDesktop({
|
|
2643
|
+
root,
|
|
2644
|
+
packageDirectory,
|
|
2645
|
+
muonConfig: buildConfig.config,
|
|
2646
|
+
muonConfigDirectory: buildConfig.directory,
|
|
2647
|
+
options: options.linuxDesktop,
|
|
2648
|
+
defaults: {
|
|
2649
|
+
desktopId: appId,
|
|
2650
|
+
name: resolveLinuxDesktopDefaultName(packageJson, appName),
|
|
2651
|
+
comment: resolvePackageDescription(packageJson),
|
|
2652
|
+
categories: ["Utility"],
|
|
2653
|
+
startupNotify: true
|
|
2654
|
+
}
|
|
2655
|
+
});
|
|
1847
2656
|
const salt = Buffer.from(options.assetSalt ?? randomBytes(assetSaltByteLength));
|
|
1848
2657
|
const results = [];
|
|
1849
2658
|
for (const target of targets) {
|
|
1850
2659
|
const result = await buildMuonTarget({
|
|
1851
2660
|
packageDirectory,
|
|
2661
|
+
root,
|
|
1852
2662
|
outputRoot,
|
|
1853
2663
|
appName,
|
|
1854
2664
|
appId,
|
|
1855
2665
|
target,
|
|
1856
2666
|
assetInput,
|
|
1857
2667
|
sourceConfig: buildConfig.config,
|
|
2668
|
+
windowsResource,
|
|
2669
|
+
linuxDesktop,
|
|
1858
2670
|
salt
|
|
1859
2671
|
});
|
|
1860
2672
|
results.push(result);
|
|
@@ -1912,6 +2724,8 @@ var sanitizeAppId = (value) => {
|
|
|
1912
2724
|
const sanitized = (value.startsWith("@") ? value.slice(1) : value).trim().toLowerCase().replace("/", ".").replace(/[^a-z0-9._-]+/g, ".").replace(/^[.]+/g, "").replace(/[.]+$/g, "");
|
|
1913
2725
|
return sanitized.length > 0 ? sanitized : defaultAppId;
|
|
1914
2726
|
};
|
|
2727
|
+
var resolveLinuxDesktopDefaultName = (packageJson, appName) => typeof packageJson.name === "string" && packageJson.name.trim() !== "" ? packageJson.name.trim() : appName;
|
|
2728
|
+
var resolvePackageDescription = (packageJson) => typeof packageJson.description === "string" ? packageJson.description.trim() : "";
|
|
1915
2729
|
var readBuildConfig = async (root, configPath) => {
|
|
1916
2730
|
const resolvedConfigPath = await resolveConfigPath(root, configPath);
|
|
1917
2731
|
if (resolvedConfigPath === void 0) return {
|
|
@@ -1985,7 +2799,7 @@ var buildMuonTarget = async (input) => {
|
|
|
1985
2799
|
await copyFile(sourceBootstrapPath, launcherPath);
|
|
1986
2800
|
await chmod(launcherPath, executableMode);
|
|
1987
2801
|
const asset = await writeAssetArchive(input.assetInput, assetZipPath, input.salt);
|
|
1988
|
-
const embeddedConfig = createEmbeddedConfig(input.sourceConfig, asset, input.appId);
|
|
2802
|
+
const embeddedConfig = createEmbeddedConfig(input.sourceConfig, asset, input.appId, input.linuxDesktop.desktopId);
|
|
1989
2803
|
await withTemporaryConfig(embeddedConfig, async (configPath) => {
|
|
1990
2804
|
await embedMuonConfigInRuntime({
|
|
1991
2805
|
runtimePath: outputPath,
|
|
@@ -1998,13 +2812,21 @@ var buildMuonTarget = async (input) => {
|
|
|
1998
2812
|
outputPath: void 0
|
|
1999
2813
|
});
|
|
2000
2814
|
});
|
|
2815
|
+
if (descriptor.os === "windows") await updateWindowsPeResources({
|
|
2816
|
+
executablePath: launcherPath,
|
|
2817
|
+
resource: input.windowsResource,
|
|
2818
|
+
environment: process.env,
|
|
2819
|
+
cwd: input.root
|
|
2820
|
+
});
|
|
2821
|
+
else if (descriptor.os === "linux") await writeLinuxDesktopDistributionFiles(outputPath, input.linuxDesktop);
|
|
2001
2822
|
return {
|
|
2002
2823
|
target: input.target,
|
|
2003
2824
|
distributionDirectoryName: descriptor.distributionDirectoryName,
|
|
2004
2825
|
outputPath,
|
|
2005
2826
|
launcherPath,
|
|
2006
2827
|
asset,
|
|
2007
|
-
embeddedConfig
|
|
2828
|
+
embeddedConfig,
|
|
2829
|
+
...descriptor.os === "linux" ? { linuxDesktop: input.linuxDesktop } : {}
|
|
2008
2830
|
};
|
|
2009
2831
|
};
|
|
2010
2832
|
var verifyTargetInputs = async (input) => {
|
|
@@ -2079,13 +2901,13 @@ var createZipArchive = (entries) => {
|
|
|
2079
2901
|
for (const entry of entries) zip.addFile(entry.name, entry.data);
|
|
2080
2902
|
return zip.toBuffer();
|
|
2081
2903
|
};
|
|
2082
|
-
var createEmbeddedConfig = (sourceConfig, asset, appId) => {
|
|
2904
|
+
var createEmbeddedConfig = (sourceConfig, asset, appId, desktopId) => {
|
|
2083
2905
|
const sourceAsset = sourceConfig.asset;
|
|
2084
2906
|
if (sourceAsset !== void 0 && !isJsonObject$1(sourceAsset)) throw new Error("muon.json asset must be an object when present.");
|
|
2085
2907
|
const sourceBootstrap = sourceConfig.bootstrap;
|
|
2086
2908
|
if (sourceBootstrap !== void 0 && !isJsonObject$1(sourceBootstrap)) throw new Error("muon.json bootstrap must be an object when present.");
|
|
2087
2909
|
return {
|
|
2088
|
-
...sourceConfig,
|
|
2910
|
+
...stripBuildOnlyLinuxDesktopConfig(stripBuildOnlyWindowsResourceConfig(sourceConfig)),
|
|
2089
2911
|
asset: {
|
|
2090
2912
|
...sourceAsset ?? {},
|
|
2091
2913
|
sourcePath: appConfigSourcePath,
|
|
@@ -2094,7 +2916,8 @@ var createEmbeddedConfig = (sourceConfig, asset, appId) => {
|
|
|
2094
2916
|
},
|
|
2095
2917
|
bootstrap: {
|
|
2096
2918
|
...sourceBootstrap ?? {},
|
|
2097
|
-
appId
|
|
2919
|
+
appId,
|
|
2920
|
+
desktopId
|
|
2098
2921
|
}
|
|
2099
2922
|
};
|
|
2100
2923
|
};
|
|
@@ -2142,7 +2965,7 @@ var getErrorMessage$1 = (error) => error instanceof Error ? error.message : Stri
|
|
|
2142
2965
|
//#region src/gitignore.ts
|
|
2143
2966
|
var muonGitignoreEntries = [
|
|
2144
2967
|
".muon/",
|
|
2145
|
-
"dist-muon
|
|
2968
|
+
"dist-muon/",
|
|
2146
2969
|
"artifacts/"
|
|
2147
2970
|
];
|
|
2148
2971
|
var muonGitignoreEntryAliases = {
|
|
@@ -2152,11 +2975,13 @@ var muonGitignoreEntryAliases = {
|
|
|
2152
2975
|
".muon",
|
|
2153
2976
|
"/.muon"
|
|
2154
2977
|
],
|
|
2155
|
-
"dist-muon
|
|
2156
|
-
"dist-muon
|
|
2157
|
-
"/dist-muon
|
|
2158
|
-
"dist-muon
|
|
2159
|
-
"/dist-muon
|
|
2978
|
+
"dist-muon/": [
|
|
2979
|
+
"dist-muon/",
|
|
2980
|
+
"/dist-muon/",
|
|
2981
|
+
"dist-muon",
|
|
2982
|
+
"/dist-muon",
|
|
2983
|
+
"dist-muon/*",
|
|
2984
|
+
"/dist-muon/*"
|
|
2160
2985
|
],
|
|
2161
2986
|
"artifacts/": [
|
|
2162
2987
|
"artifacts/",
|
|
@@ -2403,7 +3228,7 @@ var startMuonViteBrowserBridge = async ({ server, pluginOptions, platform, archi
|
|
|
2403
3228
|
environment,
|
|
2404
3229
|
cwd: server.config.root
|
|
2405
3230
|
});
|
|
2406
|
-
if (preparedRuntime.stagePath === void 0) throw new Error("muon-
|
|
3231
|
+
if (preparedRuntime.stagePath === void 0) throw new Error("muon-builder did not return a staged runtime path.");
|
|
2407
3232
|
const paths = await createRuntimePaths(server, preparedRuntime.stagePath, platform, await resolveProjectConfigPath(server));
|
|
2408
3233
|
await writeLaunchScript(paths, platform);
|
|
2409
3234
|
let cleanupPromise = void 0;
|
|
@@ -2456,12 +3281,12 @@ var attachMuonVitePluginOptions = (plugin, options) => {
|
|
|
2456
3281
|
};
|
|
2457
3282
|
//#endregion
|
|
2458
3283
|
//#region src/vite.ts
|
|
2459
|
-
var suppressViteMuonBuildEnvironmentKey = "MUON_SUPPRESS_VITE_MUON_BUILD";
|
|
2460
3284
|
/**
|
|
2461
3285
|
* Creates a Vite plugin that launches Muon during Vite dev startup.
|
|
2462
3286
|
*
|
|
2463
3287
|
* @param options Muon plugin options used for development startup and build.
|
|
2464
3288
|
* @returns Vite plugin instance.
|
|
3289
|
+
* @defaultValue `options` defaults to `{}`.
|
|
2465
3290
|
*/
|
|
2466
3291
|
var muon = (options = {}) => {
|
|
2467
3292
|
let resolvedConfig = void 0;
|
|
@@ -2485,7 +3310,7 @@ var muon = (options = {}) => {
|
|
|
2485
3310
|
},
|
|
2486
3311
|
closeBundle: async () => {
|
|
2487
3312
|
if (resolvedConfig === void 0 || resolvedConfig.command !== "build") return;
|
|
2488
|
-
if (process.env[
|
|
3313
|
+
if (process.env["MUON_SUPPRESS_VITE_MUON_BUILD"] === "1") return;
|
|
2489
3314
|
if (options.build === false) return;
|
|
2490
3315
|
const buildOptions = typeof options.build === "object" ? options.build : {};
|
|
2491
3316
|
await buildMuonApp(createMuonBuildOptions(resolvedConfig, buildOptions));
|
|
@@ -2518,6 +3343,8 @@ var createMuonBuildOptions = (config, buildOptions) => {
|
|
|
2518
3343
|
if (buildOptions.appId !== void 0) options.appId = buildOptions.appId;
|
|
2519
3344
|
if (buildOptions.outputRoot !== void 0) options.outputRoot = buildOptions.outputRoot;
|
|
2520
3345
|
if (buildOptions.configPath !== void 0) options.configPath = buildOptions.configPath;
|
|
3346
|
+
if (buildOptions.windowsResource !== void 0) options.windowsResource = buildOptions.windowsResource;
|
|
3347
|
+
if (buildOptions.linuxDesktop !== void 0) options.linuxDesktop = buildOptions.linuxDesktop;
|
|
2521
3348
|
if (buildOptions.packageDirectory !== void 0) options.packageDirectory = buildOptions.packageDirectory;
|
|
2522
3349
|
if (buildOptions.assetSalt !== void 0) options.assetSalt = buildOptions.assetSalt;
|
|
2523
3350
|
return options;
|