muon-ui 0.1.0 → 0.2.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.
Files changed (36) hide show
  1. package/dist/{build-CCuZpajl.cjs → build-BxDRaTmF.cjs} +83 -26
  2. package/dist/{build-CCuZpajl.cjs.map → build-BxDRaTmF.cjs.map} +1 -1
  3. package/dist/cli.cjs +12 -10
  4. package/dist/cli.cjs.map +1 -1
  5. package/dist/index.cjs +2 -2
  6. package/dist/index.mjs +2 -2
  7. package/dist/native/linux64/muon-bootstrap +0 -0
  8. package/dist/native/linux64/muon-prepare +0 -0
  9. package/dist/native/linuxarm/muon-bootstrap +0 -0
  10. package/dist/native/linuxarm/muon-prepare +0 -0
  11. package/dist/native/linuxarm64/muon-bootstrap +0 -0
  12. package/dist/native/linuxarm64/muon-prepare +0 -0
  13. package/dist/native/windows32/muon-bootstrap.exe +0 -0
  14. package/dist/native/windows32/muon-prepare.exe +0 -0
  15. package/dist/native/windows64/muon-bootstrap.exe +0 -0
  16. package/dist/native/windows64/muon-prepare.exe +0 -0
  17. package/dist/runtime/{linuxarm64/THIRD_PARTY_NOTICES.md → linux64/LICENSE_muon} +59 -16
  18. package/dist/runtime/linux64/muon-core +0 -0
  19. package/dist/runtime/{windows32/THIRD_PARTY_NOTICES.md → linuxarm/LICENSE_muon} +59 -16
  20. package/dist/runtime/linuxarm/muon-core +0 -0
  21. package/dist/runtime/{linux64/THIRD_PARTY_NOTICES.md → linuxarm64/LICENSE_muon} +59 -16
  22. package/dist/runtime/linuxarm64/muon-core +0 -0
  23. package/dist/runtime/{linuxarm/THIRD_PARTY_NOTICES.md → windows32/LICENSE_muon} +59 -16
  24. package/dist/runtime/windows32/libcardio.dll +0 -0
  25. package/dist/runtime/windows32/libmuon-ui.dll +0 -0
  26. package/dist/runtime/windows32/muon-core.exe +0 -0
  27. package/dist/runtime/windows64/LICENSE_muon +266 -0
  28. package/dist/runtime/windows64/libcardio.dll +0 -0
  29. package/dist/runtime/windows64/libmuon-ui.dll +0 -0
  30. package/dist/runtime/windows64/muon-core.exe +0 -0
  31. package/dist/vite.cjs +59 -18
  32. package/dist/vite.cjs.map +1 -1
  33. package/dist/vite.mjs +135 -47
  34. package/dist/vite.mjs.map +1 -1
  35. package/package.json +8 -8
  36. package/dist/runtime/windows64/THIRD_PARTY_NOTICES.md +0 -223
package/dist/vite.mjs CHANGED
@@ -1,11 +1,11 @@
1
1
  /*!
2
2
  * name: muon-ui
3
- * version: 0.1.0
3
+ * version: 0.2.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: 35f9658786642562593735d3b589c1d7ab270ecf
8
+ * git.commit.hash: 6251ff88aafa8ae873657f39aed1ebba2fa329a4
9
9
  */
10
10
  import { basename, dirname, isAbsolute, join, relative, resolve, sep, win32 } from "node:path";
11
11
  import { constants, writeFileSync } from "node:fs";
@@ -1292,7 +1292,7 @@ var encodeTaggedBytes = (tag, bytes) => Buffer.concat([
1292
1292
  encodeVarUint(BigInt(bytes.length)),
1293
1293
  Buffer.from(bytes)
1294
1294
  ]);
1295
- var isJsonObject$1 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
1295
+ var isJsonObject$2 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
1296
1296
  var isPath = (path, first, second) => path.length === 2 && path[0] === first && path[1] === second;
1297
1297
  var isHexString = (value) => value.length % 2 === 0 && /^[0-9a-fA-F]*$/.test(value);
1298
1298
  var decodeHexString = (value) => {
@@ -1325,7 +1325,7 @@ var encodeTlvValue = (value, path) => {
1325
1325
  encodeVarUint(BigInt(value.length)),
1326
1326
  ...value.map((entry) => encodeTlvValue(entry, path))
1327
1327
  ]);
1328
- if (isJsonObject$1(value)) {
1328
+ if (isJsonObject$2(value)) {
1329
1329
  const entries = Object.entries(value);
1330
1330
  return Buffer.concat([
1331
1331
  Buffer.from([tlvObjectTag]),
@@ -1439,7 +1439,7 @@ var findMuonBootstrapEmbeddedConfigSlot = (content) => {
1439
1439
  if (candidate === void 0) throw new Error("Embedded muon-bootstrap config slot was not found.");
1440
1440
  return candidate;
1441
1441
  };
1442
- var fileExists$1 = async (path) => {
1442
+ var fileExists$2 = async (path) => {
1443
1443
  try {
1444
1444
  return (await stat(path)).isFile();
1445
1445
  } catch {
@@ -1455,10 +1455,10 @@ var resolveMuonConfigInputPath = async (configPath) => {
1455
1455
  "muon.json"
1456
1456
  ]) {
1457
1457
  const candidate = join(directory, fileName);
1458
- if (await fileExists$1(candidate)) return candidate;
1458
+ if (await fileExists$2(candidate)) return candidate;
1459
1459
  }
1460
1460
  }
1461
- if (!await fileExists$1(configPath)) throw new Error(`muon config does not exist: ${configPath}`);
1461
+ if (!await fileExists$2(configPath)) throw new Error(`muon config does not exist: ${configPath}`);
1462
1462
  return configPath;
1463
1463
  };
1464
1464
  var readMuonConfigInput = async (configPath) => {
@@ -1771,6 +1771,7 @@ var defaultConfigFileNames = [
1771
1771
  ];
1772
1772
  var appConfigFromPath = "./assets.zip";
1773
1773
  var defaultAppName = "muon-app";
1774
+ var muonLicenseFileName = "LICENSE_muon";
1774
1775
  var directoryMode = 493;
1775
1776
  var executableMode = 493;
1776
1777
  var assetSaltByteLength = 16;
@@ -1800,8 +1801,8 @@ var buildMuonApp = async (options = {}) => {
1800
1801
  const targets = resolveBuildTargets(options);
1801
1802
  const outputRoot = resolve(root, options.outputRoot ?? ".");
1802
1803
  const appName = await resolveAppName(root, options.appName);
1803
- const assetInput = resolveAssetInput(root, options.assetSourcePath, options.assetPrefix);
1804
- const sourceConfig = await readBuildConfig(root, options.configPath);
1804
+ const buildConfig = await readBuildConfig(root, options.configPath);
1805
+ const assetInput = resolveAssetInput(root, options.assetSourcePath, options.assetPrefix, buildConfig);
1805
1806
  const salt = Buffer.from(options.assetSalt ?? randomBytes(assetSaltByteLength));
1806
1807
  const results = [];
1807
1808
  for (const target of targets) {
@@ -1811,7 +1812,7 @@ var buildMuonApp = async (options = {}) => {
1811
1812
  appName,
1812
1813
  target,
1813
1814
  assetInput,
1814
- sourceConfig,
1815
+ sourceConfig: buildConfig.config,
1815
1816
  salt
1816
1817
  });
1817
1818
  results.push(result);
@@ -1831,9 +1832,10 @@ var resolveBuildTargets = (options) => {
1831
1832
  if (options.targets !== void 0 && options.targets.length > 0) return [...new Set(options.targets.map((target) => normalizeMuonBuildTarget(target)))];
1832
1833
  return [getDefaultMuonBuildTarget()];
1833
1834
  };
1834
- var resolveAssetInput = (root, assetSourcePath, assetPrefix) => {
1835
+ var resolveAssetInput = (root, assetSourcePath, assetPrefix, buildConfig) => {
1836
+ const configuredAssetSourcePath = assetSourcePath === void 0 ? readConfigAssetFrom(buildConfig.config) : void 0;
1835
1837
  return {
1836
- sourcePath: resolve(root, assetSourcePath ?? "assets"),
1838
+ sourcePath: assetSourcePath !== void 0 ? resolve(root, assetSourcePath) : configuredAssetSourcePath !== void 0 ? resolve(buildConfig.directory, configuredAssetSourcePath) : resolve(root, "assets"),
1837
1839
  prefix: normalizeZipPrefix(assetPrefix ?? "")
1838
1840
  };
1839
1841
  };
@@ -1843,7 +1845,7 @@ var normalizeZipPrefix = (prefix) => {
1843
1845
  };
1844
1846
  var resolveAppName = async (root, appName) => {
1845
1847
  if (appName !== void 0) return sanitizeAppName(appName);
1846
- const packageJson = await readJsonObjectFile(join(root, "package.json"));
1848
+ const packageJson = await readJsonObjectFile(join(root, "package.json"), "package.json");
1847
1849
  const packageName = typeof packageJson.name === "string" ? packageJson.name : defaultAppName;
1848
1850
  return sanitizeAppName(packageName.startsWith("@") ? packageName.slice(packageName.indexOf("/") + 1) : packageName);
1849
1851
  };
@@ -1853,23 +1855,49 @@ var sanitizeAppName = (name) => {
1853
1855
  };
1854
1856
  var readBuildConfig = async (root, configPath) => {
1855
1857
  const resolvedConfigPath = await resolveConfigPath(root, configPath);
1856
- if (resolvedConfigPath === void 0) return {};
1857
- return readJsonObjectFile(resolvedConfigPath);
1858
+ if (resolvedConfigPath === void 0) return {
1859
+ config: {},
1860
+ directory: root
1861
+ };
1862
+ return {
1863
+ config: await readJsonObjectFile(resolvedConfigPath, "Muon config file"),
1864
+ directory: dirname(resolvedConfigPath)
1865
+ };
1866
+ };
1867
+ var readConfigAssetFrom = (sourceConfig) => {
1868
+ const sourceAsset = sourceConfig.asset;
1869
+ if (sourceAsset === void 0) return;
1870
+ if (!isJsonObject$1(sourceAsset)) throw new Error("muon.json asset must be an object when present.");
1871
+ const sourceAssetFrom = sourceAsset.from;
1872
+ if (sourceAssetFrom === void 0) return;
1873
+ if (typeof sourceAssetFrom !== "string") throw new Error("muon.json asset.from must be a string when present.");
1874
+ return sourceAssetFrom;
1858
1875
  };
1859
1876
  var resolveConfigPath = async (root, configPath) => {
1860
1877
  if (configPath !== void 0) {
1861
1878
  const resolvedPath = resolve(root, configPath);
1862
- if (await fileExists(resolvedPath)) return resolvedPath;
1879
+ if (await fileExists$1(resolvedPath)) return resolvedPath;
1863
1880
  throw new Error(`Muon config file does not exist: ${resolvedPath}`);
1864
1881
  }
1865
1882
  for (const fileName of defaultConfigFileNames) {
1866
1883
  const candidatePath = join(root, fileName);
1867
- if (await fileExists(candidatePath)) return candidatePath;
1884
+ if (await fileExists$1(candidatePath)) return candidatePath;
1868
1885
  }
1869
1886
  };
1870
- var readJsonObjectFile = async (filePath) => {
1871
- const parsed = (0, import_dist.parse)(await readFile(filePath, "utf8"));
1872
- if (!isJsonObject(parsed)) throw new Error(`Expected JSON object in ${filePath}`);
1887
+ var readJsonObjectFile = async (filePath, label) => {
1888
+ let content;
1889
+ try {
1890
+ content = await readFile(filePath, "utf8");
1891
+ } catch (error) {
1892
+ throw new Error(`${label} could not be read: ${filePath}: ${getErrorMessage$1(error)}`);
1893
+ }
1894
+ let parsed;
1895
+ try {
1896
+ parsed = (0, import_dist.parse)(content);
1897
+ } catch (error) {
1898
+ throw new Error(`${label} could not be parsed: ${filePath}: ${getErrorMessage$1(error)}`);
1899
+ }
1900
+ if (!isJsonObject$1(parsed)) throw new Error(`${label} must contain a JSON object: ${filePath}`);
1873
1901
  return parsed;
1874
1902
  };
1875
1903
  var buildMuonTarget = async (input) => {
@@ -1924,7 +1952,7 @@ var verifyTargetInputs = async (input) => {
1924
1952
  await assertDirectory(input.sourceRuntimePath, `Muon runtime for ${input.target}`);
1925
1953
  await assertFile(input.sourceBootstrapPath, `Muon bootstrap for ${input.target}`);
1926
1954
  for (const fileName of input.descriptor.runtimeFiles) await assertFile(join(input.sourceRuntimePath, fileName), `Muon runtime file ${fileName} for ${input.target}`);
1927
- await assertFile(join(input.sourceRuntimePath, "THIRD_PARTY_NOTICES.md"), `Muon third-party notices for ${input.target}`);
1955
+ await assertFile(join(input.sourceRuntimePath, muonLicenseFileName), `Muon license file for ${input.target}`);
1928
1956
  };
1929
1957
  var getLauncherFileName = (appName, descriptor) => {
1930
1958
  if (descriptor.launcherExtension.length > 0 && !appName.endsWith(descriptor.launcherExtension)) return `${appName}${descriptor.launcherExtension}`;
@@ -1932,21 +1960,33 @@ var getLauncherFileName = (appName, descriptor) => {
1932
1960
  };
1933
1961
  var copyRuntimeFiles = async (sourceRuntimePath, outputPath, descriptor) => {
1934
1962
  for (const fileName of descriptor.runtimeFiles) await copyFile(join(sourceRuntimePath, fileName), join(outputPath, fileName));
1935
- await copyFile(join(sourceRuntimePath, "THIRD_PARTY_NOTICES.md"), join(outputPath, "THIRD_PARTY_NOTICES.md"));
1963
+ await copyFile(join(sourceRuntimePath, muonLicenseFileName), join(outputPath, muonLicenseFileName));
1936
1964
  };
1937
1965
  var writeAssetArchive = async (input, outputPath, salt) => {
1938
- await assertDirectory(input.sourcePath, "Muon asset source");
1939
- const entries = await collectZipEntries(input.sourcePath, input.prefix);
1940
- if (entries.length === 0) throw new Error(`Muon asset source has no files: ${input.sourcePath}`);
1941
- const archive = createZipArchive(entries);
1966
+ const sourceStats = await statOrUndefined(input.sourcePath);
1967
+ if (sourceStats === void 0) throw new Error(`Muon asset source does not exist: ${input.sourcePath}`);
1968
+ const archive = sourceStats.isDirectory() ? await createAssetArchiveFromDirectory(input) : sourceStats.isFile() ? await readFile(input.sourcePath) : void 0;
1969
+ if (archive === void 0) throw new Error(`Muon asset source is not a directory or file: ${input.sourcePath}`);
1942
1970
  await writeFile(outputPath, archive);
1943
1971
  return {
1944
1972
  path: outputPath,
1945
1973
  signature: createHash("sha1").update(archive).update(salt).digest("hex"),
1946
1974
  salt: salt.toString("hex"),
1947
- entryCount: entries.length
1975
+ entryCount: sourceStats.isDirectory() ? readZipEntryCount(archive, outputPath) : readZipEntryCount(archive, input.sourcePath)
1948
1976
  };
1949
1977
  };
1978
+ var createAssetArchiveFromDirectory = async (input) => {
1979
+ const entries = await collectZipEntries(input.sourcePath, input.prefix);
1980
+ if (entries.length === 0) throw new Error(`Muon asset source has no files: ${input.sourcePath}`);
1981
+ return createZipArchive(entries);
1982
+ };
1983
+ var readZipEntryCount = (archive, sourcePath) => {
1984
+ const endSignature = 101010256;
1985
+ const lastPossibleOffset = archive.length - 22;
1986
+ const firstPossibleOffset = Math.max(0, lastPossibleOffset - 65535);
1987
+ for (let offset = lastPossibleOffset; offset >= firstPossibleOffset; offset -= 1) if (archive.readUInt32LE(offset) === endSignature) return archive.readUInt16LE(offset + 10);
1988
+ throw new Error(`Muon asset ZIP could not be read: ${sourcePath}`);
1989
+ };
1950
1990
  var collectZipEntries = async (sourcePath, prefix) => {
1951
1991
  const entries = [];
1952
1992
  const walk = async (directoryPath) => {
@@ -1978,7 +2018,7 @@ var createZipArchive = (entries) => {
1978
2018
  };
1979
2019
  var createEmbeddedConfig = (sourceConfig, asset) => {
1980
2020
  const sourceAsset = sourceConfig.asset;
1981
- if (sourceAsset !== void 0 && !isJsonObject(sourceAsset)) throw new Error("muon.json asset must be an object when present.");
2021
+ if (sourceAsset !== void 0 && !isJsonObject$1(sourceAsset)) throw new Error("muon.json asset must be an object when present.");
1982
2022
  return {
1983
2023
  ...sourceConfig,
1984
2024
  asset: {
@@ -2003,14 +2043,21 @@ var withTemporaryConfig = async (config, callback) => {
2003
2043
  }
2004
2044
  };
2005
2045
  var assertDirectory = async (path, label) => {
2006
- const stats = await stat(path).catch(() => void 0);
2046
+ const stats = await statOrUndefined(path);
2007
2047
  if (stats === void 0 || !stats.isDirectory()) throw new Error(`${label} directory does not exist: ${path}`);
2008
2048
  };
2009
2049
  var assertFile = async (path, label) => {
2010
- const stats = await stat(path).catch(() => void 0);
2050
+ const stats = await statOrUndefined(path);
2011
2051
  if (stats === void 0 || !stats.isFile()) throw new Error(`${label} file does not exist: ${path}`);
2012
2052
  };
2013
- var fileExists = async (path) => {
2053
+ var statOrUndefined = async (path) => {
2054
+ try {
2055
+ return await stat(path);
2056
+ } catch {
2057
+ return;
2058
+ }
2059
+ };
2060
+ var fileExists$1 = async (path) => {
2014
2061
  try {
2015
2062
  await access(path, constants.F_OK);
2016
2063
  return true;
@@ -2018,9 +2065,10 @@ var fileExists = async (path) => {
2018
2065
  return false;
2019
2066
  }
2020
2067
  };
2021
- var isJsonObject = (value) => {
2068
+ var isJsonObject$1 = (value) => {
2022
2069
  return typeof value === "object" && value !== null && !Array.isArray(value);
2023
2070
  };
2071
+ var getErrorMessage$1 = (error) => error instanceof Error ? error.message : String(error);
2024
2072
  //#endregion
2025
2073
  //#region src/vite-internals.ts
2026
2074
  var getServerOpenValue = (server) => {
@@ -2029,6 +2077,11 @@ var getServerOpenValue = (server) => {
2029
2077
  };
2030
2078
  var resolveFromRoot = (root, path) => isAbsolute(path) ? path : resolve(root, path);
2031
2079
  var moduleDirectory = typeof __dirname === "string" ? __dirname : dirname(fileURLToPath(import.meta.url));
2080
+ var defaultProjectConfigFileNames = [
2081
+ "muon.json5",
2082
+ "muon.jsonc",
2083
+ "muon.json"
2084
+ ];
2032
2085
  /**
2033
2086
  * Resolves the muon-core runtime directory used by the Vite plugin.
2034
2087
  *
@@ -2040,16 +2093,21 @@ var getMuonExecutablePath = (runtimePath, platform) => join(runtimePath, platfor
2040
2093
  var getLaunchScriptFileName = (platform) => platform === "win32" ? "open-muon.cmd" : "open-muon.sh";
2041
2094
  var quotePosix = (value) => `'${value.replaceAll("'", "'\\''")}'`;
2042
2095
  var getPlatformDirectoryName = (path, platform) => platform === "win32" ? win32.dirname(path) : dirname(path);
2096
+ var getOptionalPosixValue = (value) => value === void 0 ? "''" : quotePosix(value);
2043
2097
  var createPosixMuonLaunchScript = ({ muonExecutablePath, projectConfigPath, overrideConfigPath }) => `#!/usr/bin/env bash
2044
2098
  set -euo pipefail
2045
2099
  MUON_EXECUTABLE=${quotePosix(muonExecutablePath)}
2046
2100
  MUON_EXECUTABLE_DIRECTORY=${quotePosix(getPlatformDirectoryName(muonExecutablePath, "linux"))}
2047
- MUON_PROJECT_CONFIG=${quotePosix(projectConfigPath)}
2101
+ MUON_PROJECT_CONFIG=${getOptionalPosixValue(projectConfigPath)}
2048
2102
  MUON_OVERRIDE_CONFIG=${quotePosix(overrideConfigPath)}
2049
2103
 
2050
- if [[ ! -f "$MUON_PROJECT_CONFIG" ]]; then
2051
- echo "Muon startup failed: project config does not exist: $MUON_PROJECT_CONFIG" >&2
2052
- exit 1
2104
+ MUON_CONFIG_ARGS=()
2105
+ if [[ -n "$MUON_PROJECT_CONFIG" ]]; then
2106
+ if [[ ! -f "$MUON_PROJECT_CONFIG" ]]; then
2107
+ echo "Muon startup failed: project config does not exist: $MUON_PROJECT_CONFIG" >&2
2108
+ exit 1
2109
+ fi
2110
+ MUON_CONFIG_ARGS+=("-c" "$MUON_PROJECT_CONFIG")
2053
2111
  fi
2054
2112
 
2055
2113
  if [[ ! -x "$MUON_EXECUTABLE" ]]; then
@@ -2061,23 +2119,20 @@ if [[ ! -f "$MUON_OVERRIDE_CONFIG" ]]; then
2061
2119
  echo "Muon startup failed: generated override config does not exist: $MUON_OVERRIDE_CONFIG" >&2
2062
2120
  exit 1
2063
2121
  fi
2122
+ MUON_CONFIG_ARGS+=("-c" "$MUON_OVERRIDE_CONFIG")
2064
2123
 
2065
2124
  cd "$MUON_EXECUTABLE_DIRECTORY"
2066
- exec "$MUON_EXECUTABLE" -c "$MUON_PROJECT_CONFIG" -c "$MUON_OVERRIDE_CONFIG"
2125
+ exec "$MUON_EXECUTABLE" "\${MUON_CONFIG_ARGS[@]}"
2067
2126
  `;
2068
2127
  var escapeWindowsCmdValue = (value) => value.replaceAll("%", "%%").replaceAll("\r", "").replaceAll("\n", "");
2128
+ var getOptionalWindowsCmdValue = (value) => value === void 0 ? "" : escapeWindowsCmdValue(value);
2069
2129
  var createWindowsMuonLaunchScript = ({ muonExecutablePath, projectConfigPath, overrideConfigPath }) => `@echo off
2070
2130
  setlocal
2071
2131
  set "MUON_EXECUTABLE=${escapeWindowsCmdValue(muonExecutablePath)}"
2072
2132
  set "MUON_EXECUTABLE_DIRECTORY=${escapeWindowsCmdValue(getPlatformDirectoryName(muonExecutablePath, "win32"))}"
2073
- set "MUON_PROJECT_CONFIG=${escapeWindowsCmdValue(projectConfigPath)}"
2133
+ set "MUON_PROJECT_CONFIG=${getOptionalWindowsCmdValue(projectConfigPath)}"
2074
2134
  set "MUON_OVERRIDE_CONFIG=${escapeWindowsCmdValue(overrideConfigPath)}"
2075
2135
 
2076
- if not exist "%MUON_PROJECT_CONFIG%" (
2077
- echo Muon startup failed: project config does not exist: %MUON_PROJECT_CONFIG% 1>&2
2078
- exit /b 1
2079
- )
2080
-
2081
2136
  if not exist "%MUON_EXECUTABLE%" (
2082
2137
  echo Muon startup failed: executable does not exist: %MUON_EXECUTABLE% 1>&2
2083
2138
  exit /b 1
@@ -2089,7 +2144,16 @@ if not exist "%MUON_OVERRIDE_CONFIG%" (
2089
2144
  )
2090
2145
 
2091
2146
  pushd "%MUON_EXECUTABLE_DIRECTORY%"
2092
- "%MUON_EXECUTABLE%" -c "%MUON_PROJECT_CONFIG%" -c "%MUON_OVERRIDE_CONFIG%"
2147
+ if defined MUON_PROJECT_CONFIG (
2148
+ if not exist "%MUON_PROJECT_CONFIG%" (
2149
+ echo Muon startup failed: project config does not exist: %MUON_PROJECT_CONFIG% 1>&2
2150
+ popd
2151
+ exit /b 1
2152
+ )
2153
+ "%MUON_EXECUTABLE%" -c "%MUON_PROJECT_CONFIG%" -c "%MUON_OVERRIDE_CONFIG%"
2154
+ ) else (
2155
+ "%MUON_EXECUTABLE%" -c "%MUON_OVERRIDE_CONFIG%"
2156
+ )
2093
2157
  set "MUON_EXIT_CODE=%ERRORLEVEL%"
2094
2158
  popd
2095
2159
  exit /b %MUON_EXIT_CODE%
@@ -2125,16 +2189,40 @@ var writeMuonOverrideConfig = (server, openValue, overrideConfigPath) => {
2125
2189
  }
2126
2190
  writeFileSync(overrideConfigPath, `${JSON.stringify(createMuonOverrideConfig(startUrl), null, 2)}\n`);
2127
2191
  };
2128
- var createRuntimePaths = async (server, stagePath, platform) => {
2192
+ var createRuntimePaths = async (server, stagePath, platform, projectConfigPath) => {
2129
2193
  const temporaryDirectory = await mkdtemp(join(tmpdir(), "muon-vite-"));
2130
2194
  return {
2131
2195
  temporaryDirectory,
2132
2196
  launchScriptPath: join(temporaryDirectory, getLaunchScriptFileName(platform)),
2133
2197
  overrideConfigPath: join(temporaryDirectory, "muon.vite.json"),
2134
- projectConfigPath: join(server.config.root, "muon.json"),
2198
+ projectConfigPath,
2135
2199
  muonExecutablePath: getMuonExecutablePath(stagePath, platform)
2136
2200
  };
2137
2201
  };
2202
+ var fileExists = async (path) => {
2203
+ try {
2204
+ await access(path, constants.F_OK);
2205
+ return true;
2206
+ } catch {
2207
+ return false;
2208
+ }
2209
+ };
2210
+ var isJsonObject = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
2211
+ var getErrorMessage = (error) => error instanceof Error ? error.message : String(error);
2212
+ var resolveProjectConfigPath = async (server) => {
2213
+ for (const fileName of defaultProjectConfigFileNames) {
2214
+ const candidatePath = join(server.config.root, fileName);
2215
+ if (!await fileExists(candidatePath)) continue;
2216
+ try {
2217
+ if (!isJsonObject((0, import_dist.parse)(await readFile(candidatePath, "utf8")))) throw new Error("muon config root must be an object");
2218
+ return candidatePath;
2219
+ } catch (error) {
2220
+ server.config.logger.warn(`Muon project config will be ignored because it could not be read or parsed: ${candidatePath}: ${getErrorMessage(error)}`);
2221
+ return;
2222
+ }
2223
+ }
2224
+ server.config.logger.warn(`Muon project config was not found in ${server.config.root}; launching with generated Vite config only.`);
2225
+ };
2138
2226
  var writeLaunchScript = async (paths, platform) => {
2139
2227
  await writeFile(paths.launchScriptPath, createMuonLaunchScript({
2140
2228
  muonExecutablePath: paths.muonExecutablePath,
@@ -2165,7 +2253,7 @@ var startMuonViteBrowserBridge = async ({ server, pluginOptions, platform, archi
2165
2253
  cwd: server.config.root
2166
2254
  });
2167
2255
  if (preparedRuntime.stagePath === void 0) throw new Error("muon-prepare did not return a staged runtime path.");
2168
- const paths = await createRuntimePaths(server, preparedRuntime.stagePath, platform);
2256
+ const paths = await createRuntimePaths(server, preparedRuntime.stagePath, platform, await resolveProjectConfigPath(server));
2169
2257
  await writeLaunchScript(paths, platform);
2170
2258
  const previousBrowser = environment.BROWSER;
2171
2259
  environment.BROWSER = paths.launchScriptPath;