muon-ui 0.8.0 → 0.9.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 +9 -13
- package/dist/cli.cjs +48 -32
- 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-builder +0 -0
- package/dist/native/linux-armhf/muon-bootstrap +0 -0
- package/dist/native/linux-armhf/muon-builder +0 -0
- package/dist/native/muon-256.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/libmuon-ui.so +0 -0
- package/dist/runtime/linux-amd64/muon-core +0 -0
- package/dist/runtime/linux-arm64/libmuon-ui.so +0 -0
- package/dist/runtime/linux-arm64/muon-core +0 -0
- package/dist/runtime/linux-armhf/libmuon-ui.so +0 -0
- package/dist/runtime/linux-armhf/muon-core +0 -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/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-internals-ChWiL2TL.cjs → vite-internals-HXgH7b5M.cjs} +291 -75
- package/dist/vite-internals-HXgH7b5M.cjs.map +1 -0
- package/dist/vite.cjs +446 -6
- package/dist/vite.cjs.map +1 -1
- package/dist/vite.mjs +748 -115
- package/dist/vite.mjs.map +1 -1
- package/muon.d.ts +12 -0
- package/package.json +7 -7
- package/vite.d.ts +118 -8
- package/dist/native/muon-bootstrap.png +0 -0
- package/dist/vite-internals-ChWiL2TL.cjs.map +0 -1
package/dist/vite.mjs
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
/*!
|
|
2
2
|
* name: muon-ui
|
|
3
|
-
* version: 0.
|
|
3
|
+
* version: 0.9.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: 3437b522a51d8772713b72722b109c5ff30fc711
|
|
9
9
|
*/
|
|
10
10
|
import { basename, dirname, extname, isAbsolute, join, relative, resolve, sep, win32 } from "node:path";
|
|
11
|
-
import { constants, writeFileSync } from "node:fs";
|
|
11
|
+
import { constants, existsSync, readFileSync, 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";
|
|
14
14
|
import { tmpdir } from "node:os";
|
|
@@ -1293,8 +1293,10 @@ var encodeTaggedBytes = (tag, bytes) => Buffer.concat([
|
|
|
1293
1293
|
encodeVarUint(BigInt(bytes.length)),
|
|
1294
1294
|
Buffer.from(bytes)
|
|
1295
1295
|
]);
|
|
1296
|
-
var isJsonObject$
|
|
1296
|
+
var isJsonObject$5 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
1297
1297
|
var isPath = (path, first, second) => path.length === 2 && path[0] === first && path[1] === second;
|
|
1298
|
+
var isPluginSignaturePath = (path) => path.length === 3 && path[0] === "plugin" && path[1] === "plugins" && path[2] === "signature";
|
|
1299
|
+
var isPluginSaltPath = (path) => path.length === 3 && path[0] === "plugin" && path[1] === "plugins" && path[2] === "salt";
|
|
1298
1300
|
var isHexString = (value) => value.length % 2 === 0 && /^[0-9a-fA-F]*$/.test(value);
|
|
1299
1301
|
var decodeHexString = (value) => {
|
|
1300
1302
|
const bytes = Buffer.alloc(value.length / 2);
|
|
@@ -1304,6 +1306,8 @@ var decodeHexString = (value) => {
|
|
|
1304
1306
|
var encodeKnownBinaryString = (path, value) => {
|
|
1305
1307
|
if (isPath(path, "asset", "signature")) return value.length === 40 && isHexString(value) ? decodeHexString(value) : void 0;
|
|
1306
1308
|
if (isPath(path, "asset", "salt")) return isHexString(value) ? decodeHexString(value) : void 0;
|
|
1309
|
+
if (isPluginSignaturePath(path)) return value.length === 40 && isHexString(value) ? decodeHexString(value) : void 0;
|
|
1310
|
+
if (isPluginSaltPath(path)) return isHexString(value) ? decodeHexString(value) : void 0;
|
|
1307
1311
|
if (isPath(path, "browser", "backgroundColor")) {
|
|
1308
1312
|
const hex = value.startsWith("#") ? value.slice(1) : value;
|
|
1309
1313
|
return hex.length === 6 && isHexString(hex) ? decodeHexString(hex) : void 0;
|
|
@@ -1326,7 +1330,7 @@ var encodeTlvValue = (value, path) => {
|
|
|
1326
1330
|
encodeVarUint(BigInt(value.length)),
|
|
1327
1331
|
...value.map((entry) => encodeTlvValue(entry, path))
|
|
1328
1332
|
]);
|
|
1329
|
-
if (isJsonObject$
|
|
1333
|
+
if (isJsonObject$5(value)) {
|
|
1330
1334
|
const entries = Object.entries(value);
|
|
1331
1335
|
return Buffer.concat([
|
|
1332
1336
|
Buffer.from([tlvObjectTag]),
|
|
@@ -1351,8 +1355,8 @@ var encodeMuonConfigTlv = (config) => encodeTlvValue(config, []);
|
|
|
1351
1355
|
*/
|
|
1352
1356
|
var createMuonEmbeddedConfigSlot = (payload = void 0) => {
|
|
1353
1357
|
if (payload !== void 0 && payload.length > muonEmbeddedConfigPayloadCapacity) throw new Error(`Encoded muon config exceeds the embedded slot capacity: ${payload.length} > ${muonEmbeddedConfigPayloadCapacity}`);
|
|
1354
|
-
|
|
1355
|
-
|
|
1358
|
+
if (payload === void 0) return createEmptySlot();
|
|
1359
|
+
const slot = randomBytes(muonEmbeddedConfigSlotSize);
|
|
1356
1360
|
Buffer.from(payload).copy(slot, 0);
|
|
1357
1361
|
return slot;
|
|
1358
1362
|
};
|
|
@@ -1364,9 +1368,12 @@ var createMuonEmbeddedConfigSlot = (payload = void 0) => {
|
|
|
1364
1368
|
*/
|
|
1365
1369
|
var createMuonBootstrapEmbeddedConfigSlot = (payload = void 0) => {
|
|
1366
1370
|
if (payload !== void 0 && payload.length > muonBootstrapEmbeddedConfigPayloadCapacity) throw new Error(`Encoded muon config exceeds the embedded bootstrap slot capacity: ${payload.length} > ${muonBootstrapEmbeddedConfigPayloadCapacity}`);
|
|
1367
|
-
|
|
1368
|
-
|
|
1369
|
-
|
|
1371
|
+
if (payload === void 0) {
|
|
1372
|
+
const slot = Buffer.alloc(muonBootstrapEmbeddedConfigSlotSize, 0);
|
|
1373
|
+
muonBootstrapEmbeddedConfigEmptySlotMarker.copy(slot, 0);
|
|
1374
|
+
return slot;
|
|
1375
|
+
}
|
|
1376
|
+
const slot = randomBytes(muonBootstrapEmbeddedConfigSlotSize);
|
|
1370
1377
|
Buffer.from(payload).copy(slot, 0);
|
|
1371
1378
|
return slot;
|
|
1372
1379
|
};
|
|
@@ -1440,7 +1447,7 @@ var findMuonBootstrapEmbeddedConfigSlot = (content) => {
|
|
|
1440
1447
|
if (candidate === void 0) throw new Error("Embedded muon-bootstrap config slot was not found.");
|
|
1441
1448
|
return candidate;
|
|
1442
1449
|
};
|
|
1443
|
-
var fileExists$
|
|
1450
|
+
var fileExists$6 = async (path) => {
|
|
1444
1451
|
try {
|
|
1445
1452
|
return (await stat(path)).isFile();
|
|
1446
1453
|
} catch {
|
|
@@ -1456,10 +1463,10 @@ var resolveMuonConfigInputPath = async (configPath) => {
|
|
|
1456
1463
|
"muon.json"
|
|
1457
1464
|
]) {
|
|
1458
1465
|
const candidate = join(directory, fileName);
|
|
1459
|
-
if (await fileExists$
|
|
1466
|
+
if (await fileExists$6(candidate)) return candidate;
|
|
1460
1467
|
}
|
|
1461
1468
|
}
|
|
1462
|
-
if (!await fileExists$
|
|
1469
|
+
if (!await fileExists$6(configPath)) throw new Error(`muon config does not exist: ${configPath}`);
|
|
1463
1470
|
return configPath;
|
|
1464
1471
|
};
|
|
1465
1472
|
var readMuonConfigInput = async (configPath) => {
|
|
@@ -1662,6 +1669,20 @@ Object.fromEntries(allMuonTargets.map((target) => [targetDescriptors[target].cef
|
|
|
1662
1669
|
*/
|
|
1663
1670
|
var getMuonTargetDescriptor = (target) => targetDescriptors[target];
|
|
1664
1671
|
/**
|
|
1672
|
+
* Returns the runtime app identifier embedded for one target distribution.
|
|
1673
|
+
*
|
|
1674
|
+
* @param appId Base sanitized application identifier.
|
|
1675
|
+
* @param target Public Muon target.
|
|
1676
|
+
* @returns Target runtime application identifier.
|
|
1677
|
+
*
|
|
1678
|
+
* @remarks Windows targets append their public architecture name so 32-bit and
|
|
1679
|
+
* 64-bit packages do not share runtime state or installer identities.
|
|
1680
|
+
*/
|
|
1681
|
+
var getMuonTargetRuntimeAppId = (appId, target) => {
|
|
1682
|
+
const descriptor = getMuonTargetDescriptor(target);
|
|
1683
|
+
return descriptor.os === "windows" ? `${appId}.${descriptor.arch}` : appId;
|
|
1684
|
+
};
|
|
1685
|
+
/**
|
|
1665
1686
|
* Normalizes a user supplied public Muon target.
|
|
1666
1687
|
*
|
|
1667
1688
|
* @param target Target value supplied by the user.
|
|
@@ -2110,6 +2131,68 @@ var createIco = (images) => {
|
|
|
2110
2131
|
return Buffer.concat([header, ...imageData]);
|
|
2111
2132
|
};
|
|
2112
2133
|
//#endregion
|
|
2134
|
+
//#region src/app-icon.ts
|
|
2135
|
+
/**
|
|
2136
|
+
* ZIP entry used for the generated static application icon asset.
|
|
2137
|
+
*/
|
|
2138
|
+
var appIconAssetEntryName = "main/.muon/app-icon.png";
|
|
2139
|
+
/**
|
|
2140
|
+
* Runtime asset URL injected as the generated initial title bar icon.
|
|
2141
|
+
*/
|
|
2142
|
+
var appIconAssetUrl = "asset://main/.muon/app-icon.png";
|
|
2143
|
+
/**
|
|
2144
|
+
* Creates a static application icon source from API or CLI options.
|
|
2145
|
+
*/
|
|
2146
|
+
var createAppIconOptionsSource = (iconPath, directory, label = "iconPath") => {
|
|
2147
|
+
if (iconPath === void 0) return;
|
|
2148
|
+
if (typeof iconPath !== "string") throw new Error(`${label} must be a string when present.`);
|
|
2149
|
+
if (iconPath.trim() === "") return;
|
|
2150
|
+
return {
|
|
2151
|
+
iconPath: iconPath.trim(),
|
|
2152
|
+
directory
|
|
2153
|
+
};
|
|
2154
|
+
};
|
|
2155
|
+
/**
|
|
2156
|
+
* Reads the top-level `iconPath` from a Muon config object.
|
|
2157
|
+
*/
|
|
2158
|
+
var readConfigAppIconSource = (config, directory, label) => {
|
|
2159
|
+
const value = config.iconPath;
|
|
2160
|
+
if (value === void 0) return;
|
|
2161
|
+
if (typeof value !== "string") throw new Error(`${label} iconPath must be a string when present.`);
|
|
2162
|
+
return createAppIconOptionsSource(value, directory);
|
|
2163
|
+
};
|
|
2164
|
+
/**
|
|
2165
|
+
* Reads the top-level `iconPath` from project metadata.
|
|
2166
|
+
*/
|
|
2167
|
+
var readProjectAppIconSource = (projectJson, directory) => {
|
|
2168
|
+
const value = projectJson.iconPath;
|
|
2169
|
+
return typeof value === "string" ? createAppIconOptionsSource(value, directory) : void 0;
|
|
2170
|
+
};
|
|
2171
|
+
/**
|
|
2172
|
+
* Resolves and validates the first available static application icon source.
|
|
2173
|
+
*/
|
|
2174
|
+
var resolveMuonAppIconPath = async (sources) => {
|
|
2175
|
+
for (const source of sources) {
|
|
2176
|
+
const iconPath = resolveResourcePath$2(source.directory, source.iconPath);
|
|
2177
|
+
await assertMuonAppIconPath(iconPath);
|
|
2178
|
+
return iconPath;
|
|
2179
|
+
}
|
|
2180
|
+
};
|
|
2181
|
+
var assertMuonAppIconPath = async (iconPath) => {
|
|
2182
|
+
if (extname(iconPath).toLowerCase() !== ".png") throw new Error(`Muon app icon must be a .png file: ${iconPath}`);
|
|
2183
|
+
if (!await fileExists$5(iconPath)) throw new Error(`Muon app icon does not exist: ${iconPath}`);
|
|
2184
|
+
await createNormalizedIconPngData(await readFile(iconPath), iconPath, "Muon app icon");
|
|
2185
|
+
};
|
|
2186
|
+
var resolveResourcePath$2 = (directory, value) => isAbsolute(value) ? value : resolve(directory, value);
|
|
2187
|
+
var fileExists$5 = async (path) => {
|
|
2188
|
+
try {
|
|
2189
|
+
await access(path, constants.F_OK);
|
|
2190
|
+
return true;
|
|
2191
|
+
} catch {
|
|
2192
|
+
return false;
|
|
2193
|
+
}
|
|
2194
|
+
};
|
|
2195
|
+
//#endregion
|
|
2113
2196
|
//#region src/windows-resource.ts
|
|
2114
2197
|
var defaultLanguage = 1033;
|
|
2115
2198
|
var defaultCodePage = 1200;
|
|
@@ -2135,13 +2218,22 @@ var mergeMuonWindowsResourceOptions = (primary, fallback) => {
|
|
|
2135
2218
|
* Resolves Windows resource metadata from options, config files, and package metadata.
|
|
2136
2219
|
*/
|
|
2137
2220
|
var resolveMuonWindowsResource = async (input) => {
|
|
2138
|
-
const projectJson = await readProjectJson(input.root);
|
|
2139
|
-
const
|
|
2221
|
+
const projectJson = await readProjectJson$1(input.root);
|
|
2222
|
+
const windowsSources = [
|
|
2140
2223
|
createOptionsSource$1(input.options, input.root, "windowsResource"),
|
|
2141
2224
|
readConfigWindowsResourceSource(input.muonConfig, input.muonConfigDirectory, "muon.json"),
|
|
2225
|
+
readConfigWindowsResourceSource(projectJson, input.root, "project.json")
|
|
2226
|
+
].filter((source) => source !== void 0);
|
|
2227
|
+
const sources = [
|
|
2228
|
+
...windowsSources,
|
|
2142
2229
|
createProjectSource(projectJson, input.root),
|
|
2143
2230
|
createPackageSource(input.packageJson, input.root)
|
|
2144
2231
|
].filter((source) => source !== void 0);
|
|
2232
|
+
const appIconSources = [
|
|
2233
|
+
createAppIconOptionsSource(input.appIconPath, input.root),
|
|
2234
|
+
readConfigAppIconSource(input.muonConfig, input.muonConfigDirectory, "muon.json"),
|
|
2235
|
+
readProjectAppIconSource(projectJson, input.root)
|
|
2236
|
+
].filter((source) => source !== void 0);
|
|
2145
2237
|
const productName = resolveStringField$1(sources, "productName", input.defaults.productName);
|
|
2146
2238
|
const fileDescription = resolveStringField$1(sources, "fileDescription", input.defaults.fileDescription);
|
|
2147
2239
|
const companyName = resolveStringField$1(sources, "companyName", input.defaults.companyName);
|
|
@@ -2151,7 +2243,7 @@ var resolveMuonWindowsResource = async (input) => {
|
|
|
2151
2243
|
const codePage = resolveNumericField(sources, "codePage", defaultCodePage);
|
|
2152
2244
|
const fixedVersion = normalizeWindowsVersion(version);
|
|
2153
2245
|
return {
|
|
2154
|
-
iconPath: await
|
|
2246
|
+
iconPath: await resolveWindowsIconPath(windowsSources, appIconSources, await resolveDefaultWindowsIcon(input.packageDirectory)),
|
|
2155
2247
|
productName,
|
|
2156
2248
|
fileDescription,
|
|
2157
2249
|
companyName,
|
|
@@ -2167,7 +2259,7 @@ var resolveMuonWindowsResource = async (input) => {
|
|
|
2167
2259
|
*/
|
|
2168
2260
|
var stripBuildOnlyWindowsResourceConfig = (sourceConfig) => {
|
|
2169
2261
|
const sourceWindows = sourceConfig.windows;
|
|
2170
|
-
if (!isJsonObject$
|
|
2262
|
+
if (!isJsonObject$4(sourceWindows)) return sourceConfig;
|
|
2171
2263
|
const windowsConfig = {};
|
|
2172
2264
|
for (const [key, value] of Object.entries(sourceWindows)) if (key !== "resource") windowsConfig[key] = value;
|
|
2173
2265
|
const output = {};
|
|
@@ -2188,15 +2280,24 @@ var isWindowsPeExecutable = async (path) => {
|
|
|
2188
2280
|
* Applies resolved resource metadata to a Windows PE executable in place.
|
|
2189
2281
|
*/
|
|
2190
2282
|
var updateWindowsPeResources = async (input) => {
|
|
2283
|
+
return await updateWindowsPeResourceFile(input, createEngraverUpdate);
|
|
2284
|
+
};
|
|
2285
|
+
/**
|
|
2286
|
+
* Applies only resolved icon metadata to a Windows PE executable in place.
|
|
2287
|
+
*/
|
|
2288
|
+
var updateWindowsPeIconResource = async (input) => {
|
|
2289
|
+
return await updateWindowsPeResourceFile(input, createEngraverIconUpdate);
|
|
2290
|
+
};
|
|
2291
|
+
var updateWindowsPeResourceFile = async (input, createUpdate) => {
|
|
2191
2292
|
if (!await isWindowsPeExecutable(input.executablePath)) return false;
|
|
2192
2293
|
const mode = (await stat(input.executablePath)).mode & 511;
|
|
2193
2294
|
const tempDirectory = await mkdtemp(join(tmpdir(), "muon-windows-resource-"));
|
|
2194
2295
|
const updatesJsonPath = join(tempDirectory, "updates.json");
|
|
2195
2296
|
const outputPath = join(tempDirectory, "output.exe");
|
|
2196
|
-
const iconPath =
|
|
2297
|
+
const iconPath = join(tempDirectory, "icon.ico");
|
|
2197
2298
|
try {
|
|
2198
|
-
|
|
2199
|
-
await writeFile(updatesJsonPath, `${JSON.stringify(
|
|
2299
|
+
await createWindowsIconFromPngFile(input.resource.iconPath, iconPath);
|
|
2300
|
+
await writeFile(updatesJsonPath, `${JSON.stringify(createUpdate(input.resource, iconPath), null, 2)}\n`);
|
|
2200
2301
|
await runMuonPrepareResourceUpdate({
|
|
2201
2302
|
inputPath: input.executablePath,
|
|
2202
2303
|
updatesJsonPath,
|
|
@@ -2237,21 +2338,23 @@ var createEngraverUpdate = (resource, iconPath) => {
|
|
|
2237
2338
|
},
|
|
2238
2339
|
strings
|
|
2239
2340
|
},
|
|
2240
|
-
icons: iconPath
|
|
2241
|
-
id: 1,
|
|
2242
|
-
language: resource.language,
|
|
2243
|
-
path: iconPath
|
|
2244
|
-
}]
|
|
2341
|
+
icons: createEngraverIcons(resource, iconPath)
|
|
2245
2342
|
};
|
|
2246
2343
|
};
|
|
2247
|
-
var
|
|
2344
|
+
var createEngraverIconUpdate = (resource, iconPath) => ({ icons: createEngraverIcons(resource, iconPath) });
|
|
2345
|
+
var createEngraverIcons = (resource, iconPath) => [{
|
|
2346
|
+
id: 1,
|
|
2347
|
+
language: resource.language,
|
|
2348
|
+
path: iconPath
|
|
2349
|
+
}];
|
|
2350
|
+
var readProjectJson$1 = async (root) => {
|
|
2248
2351
|
const projectJsonPath = join(root, "project.json");
|
|
2249
|
-
if (!await fileExists$
|
|
2250
|
-
return await readJsonObjectFile$
|
|
2352
|
+
if (!await fileExists$4(projectJsonPath)) return {};
|
|
2353
|
+
return await readJsonObjectFile$3(projectJsonPath, "project.json");
|
|
2251
2354
|
};
|
|
2252
|
-
var readJsonObjectFile$
|
|
2355
|
+
var readJsonObjectFile$3 = async (filePath, label) => {
|
|
2253
2356
|
const parsed = (0, import_dist.parse)(await readFile(filePath, "utf8"));
|
|
2254
|
-
if (!isJsonObject$
|
|
2357
|
+
if (!isJsonObject$4(parsed)) throw new Error(`${label} must contain a JSON object: ${filePath}`);
|
|
2255
2358
|
return parsed;
|
|
2256
2359
|
};
|
|
2257
2360
|
var createOptionsSource$1 = (options, directory, label) => {
|
|
@@ -2264,14 +2367,13 @@ var createOptionsSource$1 = (options, directory, label) => {
|
|
|
2264
2367
|
var readConfigWindowsResourceSource = (config, directory, label) => {
|
|
2265
2368
|
const windows = config.windows;
|
|
2266
2369
|
if (windows === void 0) return;
|
|
2267
|
-
if (!isJsonObject$
|
|
2370
|
+
if (!isJsonObject$4(windows)) throw new Error(`${label} windows must be an object when present.`);
|
|
2268
2371
|
const resource = windows.resource;
|
|
2269
2372
|
if (resource === void 0) return;
|
|
2270
2373
|
return createOptionsSource$1(validateWindowsResourceOptions(resource, `${label} windows.resource`), directory, `${label} windows.resource`);
|
|
2271
2374
|
};
|
|
2272
2375
|
var createProjectSource = (projectJson, directory) => {
|
|
2273
2376
|
const topLevel = {};
|
|
2274
|
-
copyStringField(projectJson, "iconPath", topLevel, "iconPath");
|
|
2275
2377
|
copyStringField(projectJson, "productName", topLevel, "productName");
|
|
2276
2378
|
copyStringField(projectJson, "name", topLevel, "productName");
|
|
2277
2379
|
copyStringField(projectJson, "fileDescription", topLevel, "fileDescription");
|
|
@@ -2306,7 +2408,7 @@ var copyStringField = (source, sourceKey, target, targetKey) => {
|
|
|
2306
2408
|
if (typeof value === "string" && value.trim() !== "") target[targetKey] = value.trim();
|
|
2307
2409
|
};
|
|
2308
2410
|
var validateWindowsResourceOptions = (value, label) => {
|
|
2309
|
-
if (!isJsonObject$
|
|
2411
|
+
if (!isJsonObject$4(value)) throw new Error(`${label} must be an object.`);
|
|
2310
2412
|
const output = {};
|
|
2311
2413
|
copyOptionalStringResourceField(value, "iconPath", output);
|
|
2312
2414
|
copyOptionalStringResourceField(value, "productName", output);
|
|
@@ -2347,33 +2449,35 @@ var resolveNumericField = (sources, field, fallback) => {
|
|
|
2347
2449
|
}
|
|
2348
2450
|
return fallback;
|
|
2349
2451
|
};
|
|
2350
|
-
var
|
|
2351
|
-
for (const source of
|
|
2452
|
+
var resolveWindowsIconPath = async (windowsSources, appIconSources, defaultIconPath) => {
|
|
2453
|
+
for (const source of windowsSources) {
|
|
2352
2454
|
const value = source.options.iconPath;
|
|
2353
2455
|
if (value !== void 0 && value.trim() !== "") {
|
|
2354
2456
|
const iconPath = resolveResourcePath$1(source.directory, value);
|
|
2355
|
-
await assertIconPath$1(iconPath
|
|
2457
|
+
await assertIconPath$1(iconPath);
|
|
2356
2458
|
return iconPath;
|
|
2357
2459
|
}
|
|
2358
2460
|
}
|
|
2359
|
-
|
|
2360
|
-
|
|
2361
|
-
|
|
2362
|
-
|
|
2461
|
+
const appIconPath = await resolveMuonAppIconPath(appIconSources);
|
|
2462
|
+
if (appIconPath !== void 0) return appIconPath;
|
|
2463
|
+
await assertIconPath$1(defaultIconPath);
|
|
2464
|
+
return defaultIconPath;
|
|
2363
2465
|
};
|
|
2364
|
-
var assertIconPath$1 = async (iconPath
|
|
2466
|
+
var assertIconPath$1 = async (iconPath) => {
|
|
2365
2467
|
if (extname(iconPath).toLowerCase() !== ".png") throw new Error(`Windows resource icon must be a .png file: ${iconPath}`);
|
|
2366
|
-
if (
|
|
2367
|
-
|
|
2468
|
+
if (!await fileExists$4(iconPath)) throw new Error(`Windows resource icon does not exist: ${iconPath}`);
|
|
2469
|
+
await createNormalizedMuonIconPngData(await readFile(iconPath), iconPath);
|
|
2368
2470
|
};
|
|
2369
2471
|
var resolveDefaultWindowsIcon = async (packageDirectory) => {
|
|
2472
|
+
const sourceIconPath = join(moduleDirectory$3, "..", "..", "images", "muon-256.png");
|
|
2370
2473
|
const candidates = [
|
|
2371
|
-
join(resolve(packageDirectory), "native", "muon-
|
|
2372
|
-
join(moduleDirectory$3, "native", "muon-
|
|
2373
|
-
join(moduleDirectory$3, "..", "dist", "native", "muon-
|
|
2374
|
-
|
|
2474
|
+
join(resolve(packageDirectory), "native", "muon-256.png"),
|
|
2475
|
+
join(moduleDirectory$3, "native", "muon-256.png"),
|
|
2476
|
+
join(moduleDirectory$3, "..", "dist", "native", "muon-256.png"),
|
|
2477
|
+
sourceIconPath
|
|
2375
2478
|
];
|
|
2376
|
-
for (const candidate of candidates) if (await fileExists$
|
|
2479
|
+
for (const candidate of candidates) if (await fileExists$4(candidate)) return candidate;
|
|
2480
|
+
return sourceIconPath;
|
|
2377
2481
|
};
|
|
2378
2482
|
var resolveResourcePath$1 = (directory, path) => {
|
|
2379
2483
|
return isAbsolute(path) ? path : resolve(directory, path);
|
|
@@ -2393,12 +2497,12 @@ var normalizeWindowsVersion = (version) => {
|
|
|
2393
2497
|
};
|
|
2394
2498
|
var stringifyAuthor = (value) => {
|
|
2395
2499
|
if (typeof value === "string" && value.trim() !== "") return value.trim();
|
|
2396
|
-
if (!isJsonObject$
|
|
2500
|
+
if (!isJsonObject$4(value) || typeof value.name !== "string") return;
|
|
2397
2501
|
const name = value.name.trim();
|
|
2398
2502
|
if (name === "") return;
|
|
2399
2503
|
return value.email === void 0 || typeof value.email !== "string" ? name : `${name} <${value.email}>`;
|
|
2400
2504
|
};
|
|
2401
|
-
var fileExists$
|
|
2505
|
+
var fileExists$4 = async (path) => {
|
|
2402
2506
|
try {
|
|
2403
2507
|
await access(path, constants.F_OK);
|
|
2404
2508
|
return true;
|
|
@@ -2406,7 +2510,7 @@ var fileExists$3 = async (path) => {
|
|
|
2406
2510
|
return false;
|
|
2407
2511
|
}
|
|
2408
2512
|
};
|
|
2409
|
-
var isJsonObject$
|
|
2513
|
+
var isJsonObject$4 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
2410
2514
|
//#endregion
|
|
2411
2515
|
//#region src/linux-desktop.ts
|
|
2412
2516
|
var defaultIconFileName = "muon-desktop-icon.png";
|
|
@@ -2417,14 +2521,20 @@ var moduleDirectory$2 = typeof __dirname === "string" ? __dirname : dirname(file
|
|
|
2417
2521
|
* package metadata.
|
|
2418
2522
|
*/
|
|
2419
2523
|
var resolveMuonLinuxDesktop = async (input) => {
|
|
2524
|
+
const projectJson = await readProjectJson(input.root);
|
|
2420
2525
|
const sources = [createOptionsSource(input.options, input.root, "linuxDesktop"), readConfigLinuxDesktopSource(input.muonConfig, input.muonConfigDirectory, "muon.json")].filter((source) => source !== void 0);
|
|
2526
|
+
const appIconSources = [
|
|
2527
|
+
createAppIconOptionsSource(input.appIconPath, input.root),
|
|
2528
|
+
readConfigAppIconSource(input.muonConfig, input.muonConfigDirectory, "muon.json"),
|
|
2529
|
+
readProjectAppIconSource(projectJson, input.root)
|
|
2530
|
+
].filter((source) => source !== void 0);
|
|
2421
2531
|
return {
|
|
2422
2532
|
desktopId: sanitizeDesktopId(resolveStringField(sources, "desktopId", input.defaults.desktopId)),
|
|
2423
2533
|
name: resolveStringField(sources, "name", input.defaults.name),
|
|
2424
2534
|
comment: resolveStringField(sources, "comment", input.defaults.comment),
|
|
2425
2535
|
categories: resolveCategories(sources, input.defaults.categories),
|
|
2426
2536
|
startupNotify: resolveBooleanField(sources, "startupNotify", input.defaults.startupNotify),
|
|
2427
|
-
iconPath: await
|
|
2537
|
+
iconPath: await resolveLinuxIconPath(sources, appIconSources, await resolveDefaultLinuxDesktopIcon(input.packageDirectory)),
|
|
2428
2538
|
iconFileName: defaultIconFileName,
|
|
2429
2539
|
configFileName: defaultDesktopConfigFileName
|
|
2430
2540
|
};
|
|
@@ -2434,7 +2544,7 @@ var resolveMuonLinuxDesktop = async (input) => {
|
|
|
2434
2544
|
*/
|
|
2435
2545
|
var stripBuildOnlyLinuxDesktopConfig = (sourceConfig) => {
|
|
2436
2546
|
const sourceLinux = sourceConfig.linux;
|
|
2437
|
-
if (!isJsonObject$
|
|
2547
|
+
if (!isJsonObject$3(sourceLinux)) return sourceConfig;
|
|
2438
2548
|
const linuxConfig = {};
|
|
2439
2549
|
for (const [key, value] of Object.entries(sourceLinux)) if (key !== "desktop") linuxConfig[key] = value;
|
|
2440
2550
|
const output = {};
|
|
@@ -2457,6 +2567,16 @@ var writeLinuxDesktopDistributionFiles = async (outputPath, desktop) => {
|
|
|
2457
2567
|
iconFileName: desktop.iconFileName
|
|
2458
2568
|
}, void 0, 2)}\n`);
|
|
2459
2569
|
};
|
|
2570
|
+
var readJsonObjectFile$2 = async (filePath, label) => {
|
|
2571
|
+
const parsed = (0, import_dist.parse)(await readFile(filePath, "utf8"));
|
|
2572
|
+
if (!isJsonObject$3(parsed)) throw new Error(`${label} must contain a JSON object: ${filePath}`);
|
|
2573
|
+
return parsed;
|
|
2574
|
+
};
|
|
2575
|
+
var readProjectJson = async (root) => {
|
|
2576
|
+
const projectJsonPath = join(root, "project.json");
|
|
2577
|
+
if (!await fileExists$3(projectJsonPath)) return {};
|
|
2578
|
+
return await readJsonObjectFile$2(projectJsonPath, "project.json");
|
|
2579
|
+
};
|
|
2460
2580
|
var createOptionsSource = (options, directory, label) => {
|
|
2461
2581
|
if (options === void 0) return;
|
|
2462
2582
|
return {
|
|
@@ -2467,13 +2587,13 @@ var createOptionsSource = (options, directory, label) => {
|
|
|
2467
2587
|
var readConfigLinuxDesktopSource = (config, directory, label) => {
|
|
2468
2588
|
const linux = config.linux;
|
|
2469
2589
|
if (linux === void 0) return;
|
|
2470
|
-
if (!isJsonObject$
|
|
2590
|
+
if (!isJsonObject$3(linux)) throw new Error(`${label} linux must be an object when present.`);
|
|
2471
2591
|
const desktop = linux.desktop;
|
|
2472
2592
|
if (desktop === void 0) return;
|
|
2473
2593
|
return createOptionsSource(validateLinuxDesktopOptions(desktop, `${label} linux.desktop`), directory, `${label} linux.desktop`);
|
|
2474
2594
|
};
|
|
2475
2595
|
var validateLinuxDesktopOptions = (value, label) => {
|
|
2476
|
-
if (!isJsonObject$
|
|
2596
|
+
if (!isJsonObject$3(value)) throw new Error(`${label} must be an object.`);
|
|
2477
2597
|
const output = {};
|
|
2478
2598
|
copyOptionalStringDesktopField(value, "desktopId", output);
|
|
2479
2599
|
copyOptionalStringDesktopField(value, "name", output);
|
|
@@ -2519,7 +2639,7 @@ var resolveBooleanField = (sources, field, fallback) => {
|
|
|
2519
2639
|
}
|
|
2520
2640
|
return fallback;
|
|
2521
2641
|
};
|
|
2522
|
-
var
|
|
2642
|
+
var resolveLinuxIconPath = async (sources, appIconSources, defaultIconPath) => {
|
|
2523
2643
|
for (const source of sources) {
|
|
2524
2644
|
const value = source.options.iconPath;
|
|
2525
2645
|
if (value !== void 0 && value.trim() !== "") {
|
|
@@ -2528,7 +2648,9 @@ var resolveIconPath = async (sources, defaultIconPath) => {
|
|
|
2528
2648
|
return iconPath;
|
|
2529
2649
|
}
|
|
2530
2650
|
}
|
|
2531
|
-
|
|
2651
|
+
const appIconPath = await resolveMuonAppIconPath(appIconSources);
|
|
2652
|
+
if (appIconPath !== void 0) return appIconPath;
|
|
2653
|
+
if (defaultIconPath !== void 0 && await fileExists$3(defaultIconPath)) {
|
|
2532
2654
|
await assertIconPath(defaultIconPath, false);
|
|
2533
2655
|
return defaultIconPath;
|
|
2534
2656
|
}
|
|
@@ -2536,17 +2658,17 @@ var resolveIconPath = async (sources, defaultIconPath) => {
|
|
|
2536
2658
|
};
|
|
2537
2659
|
var assertIconPath = async (iconPath, required) => {
|
|
2538
2660
|
if (extname(iconPath).toLowerCase() !== ".png") throw new Error(`Linux desktop icon must be a .png file: ${iconPath}`);
|
|
2539
|
-
if (required && !await fileExists$
|
|
2540
|
-
if (await fileExists$
|
|
2661
|
+
if (required && !await fileExists$3(iconPath)) throw new Error(`Linux desktop icon does not exist: ${iconPath}`);
|
|
2662
|
+
if (await fileExists$3(iconPath)) await createNormalizedIconPngData(await readFile(iconPath), iconPath, "Linux desktop icon");
|
|
2541
2663
|
};
|
|
2542
2664
|
var resolveDefaultLinuxDesktopIcon = async (packageDirectory) => {
|
|
2543
2665
|
const candidates = [
|
|
2544
|
-
join(resolve(packageDirectory), "native", "muon-
|
|
2545
|
-
join(moduleDirectory$2, "native", "muon-
|
|
2546
|
-
join(moduleDirectory$2, "..", "dist", "native", "muon-
|
|
2547
|
-
join(moduleDirectory$2, "..", "..", "images", "muon-
|
|
2666
|
+
join(resolve(packageDirectory), "native", "muon-256.png"),
|
|
2667
|
+
join(moduleDirectory$2, "native", "muon-256.png"),
|
|
2668
|
+
join(moduleDirectory$2, "..", "dist", "native", "muon-256.png"),
|
|
2669
|
+
join(moduleDirectory$2, "..", "..", "images", "muon-256.png")
|
|
2548
2670
|
];
|
|
2549
|
-
for (const candidate of candidates) if (await fileExists$
|
|
2671
|
+
for (const candidate of candidates) if (await fileExists$3(candidate)) return candidate;
|
|
2550
2672
|
};
|
|
2551
2673
|
var sanitizeDesktopId = (value) => {
|
|
2552
2674
|
const sanitized = value.trim().toLowerCase().replace(/[^a-z0-9._-]+/g, "-").replace(/^[.-]+/g, "").replace(/[.-]+$/g, "");
|
|
@@ -2555,7 +2677,7 @@ var sanitizeDesktopId = (value) => {
|
|
|
2555
2677
|
var resolveResourcePath = (directory, path) => {
|
|
2556
2678
|
return isAbsolute(path) ? path : resolve(directory, path);
|
|
2557
2679
|
};
|
|
2558
|
-
var fileExists$
|
|
2680
|
+
var fileExists$3 = async (path) => {
|
|
2559
2681
|
try {
|
|
2560
2682
|
await access(path, constants.F_OK);
|
|
2561
2683
|
return true;
|
|
@@ -2563,7 +2685,7 @@ var fileExists$2 = async (path) => {
|
|
|
2563
2685
|
return false;
|
|
2564
2686
|
}
|
|
2565
2687
|
};
|
|
2566
|
-
var isJsonObject$
|
|
2688
|
+
var isJsonObject$3 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
2567
2689
|
//#endregion
|
|
2568
2690
|
//#region src/build.ts
|
|
2569
2691
|
var AdmZip = __resolveDefaultExport(__screwUpDefaultImportModule0, false);
|
|
@@ -2586,7 +2708,7 @@ function __resolveDefaultExport(module, isESM) {
|
|
|
2586
2708
|
}
|
|
2587
2709
|
return hasDefault ? resolvedDefault ?? module : module;
|
|
2588
2710
|
}
|
|
2589
|
-
var defaultConfigFileNames = [
|
|
2711
|
+
var defaultConfigFileNames$1 = [
|
|
2590
2712
|
"muon.json5",
|
|
2591
2713
|
"muon.jsonc",
|
|
2592
2714
|
"muon.json"
|
|
@@ -2623,14 +2745,21 @@ var buildMuonApp = async (options = {}) => {
|
|
|
2623
2745
|
const appName = resolveAppName(packageJson, options.appName);
|
|
2624
2746
|
const appId = resolveAppId(packageJson, options.appId);
|
|
2625
2747
|
const buildConfig = await readBuildConfig(root, options.configPath);
|
|
2626
|
-
const
|
|
2748
|
+
const sourceConfig = applyRuntimePluginConfig(buildConfig.config, options.runtimePluginConfig ?? { mode: "simple" });
|
|
2749
|
+
assertNoUserInitialTitleBarIcon(sourceConfig);
|
|
2750
|
+
const resolvedBuildConfig = {
|
|
2751
|
+
...buildConfig,
|
|
2752
|
+
config: sourceConfig
|
|
2753
|
+
};
|
|
2754
|
+
const assetInput = resolveAssetInput(root, options.assetSourcePath, options.assetPrefix, resolvedBuildConfig);
|
|
2627
2755
|
const windowsResource = await resolveMuonWindowsResource({
|
|
2628
2756
|
root,
|
|
2629
2757
|
packageDirectory,
|
|
2630
2758
|
packageJson,
|
|
2631
|
-
muonConfig:
|
|
2759
|
+
muonConfig: sourceConfig,
|
|
2632
2760
|
muonConfigDirectory: buildConfig.directory,
|
|
2633
2761
|
options: options.windowsResource,
|
|
2762
|
+
appIconPath: options.iconPath,
|
|
2634
2763
|
defaults: {
|
|
2635
2764
|
productName: appName,
|
|
2636
2765
|
fileDescription: appName,
|
|
@@ -2642,9 +2771,10 @@ var buildMuonApp = async (options = {}) => {
|
|
|
2642
2771
|
const linuxDesktop = await resolveMuonLinuxDesktop({
|
|
2643
2772
|
root,
|
|
2644
2773
|
packageDirectory,
|
|
2645
|
-
muonConfig:
|
|
2774
|
+
muonConfig: sourceConfig,
|
|
2646
2775
|
muonConfigDirectory: buildConfig.directory,
|
|
2647
2776
|
options: options.linuxDesktop,
|
|
2777
|
+
appIconPath: options.iconPath,
|
|
2648
2778
|
defaults: {
|
|
2649
2779
|
desktopId: appId,
|
|
2650
2780
|
name: resolveLinuxDesktopDefaultName(packageJson, appName),
|
|
@@ -2664,7 +2794,7 @@ var buildMuonApp = async (options = {}) => {
|
|
|
2664
2794
|
appId,
|
|
2665
2795
|
target,
|
|
2666
2796
|
assetInput,
|
|
2667
|
-
sourceConfig
|
|
2797
|
+
sourceConfig,
|
|
2668
2798
|
windowsResource,
|
|
2669
2799
|
linuxDesktop,
|
|
2670
2800
|
salt
|
|
@@ -2701,8 +2831,8 @@ var normalizeZipPrefix = (prefix) => {
|
|
|
2701
2831
|
};
|
|
2702
2832
|
var readPackageJson = async (root) => {
|
|
2703
2833
|
const packageJsonPath = join(root, "package.json");
|
|
2704
|
-
if (!await fileExists$
|
|
2705
|
-
return await readJsonObjectFile(packageJsonPath, "package.json");
|
|
2834
|
+
if (!await fileExists$2(packageJsonPath)) return {};
|
|
2835
|
+
return await readJsonObjectFile$1(packageJsonPath, "package.json");
|
|
2706
2836
|
};
|
|
2707
2837
|
var resolvePackageName = (packageJson) => {
|
|
2708
2838
|
return typeof packageJson.name === "string" ? packageJson.name : defaultAppName;
|
|
@@ -2733,14 +2863,27 @@ var readBuildConfig = async (root, configPath) => {
|
|
|
2733
2863
|
directory: root
|
|
2734
2864
|
};
|
|
2735
2865
|
return {
|
|
2736
|
-
config: await readJsonObjectFile(resolvedConfigPath, "Muon config file"),
|
|
2866
|
+
config: await readJsonObjectFile$1(resolvedConfigPath, "Muon config file"),
|
|
2737
2867
|
directory: dirname(resolvedConfigPath)
|
|
2738
2868
|
};
|
|
2739
2869
|
};
|
|
2870
|
+
var applyRuntimePluginConfig = (sourceConfig, runtimePluginConfig) => {
|
|
2871
|
+
if (runtimePluginConfig === void 0) return sourceConfig;
|
|
2872
|
+
const sourcePlugin = sourceConfig.plugin;
|
|
2873
|
+
if (sourcePlugin !== void 0 && !isJsonObject$2(sourcePlugin)) throw new Error("muon.json plugin must be an object when runtime plugin config is applied.");
|
|
2874
|
+
const plugin = sourcePlugin ?? {};
|
|
2875
|
+
return {
|
|
2876
|
+
...sourceConfig,
|
|
2877
|
+
plugin: {
|
|
2878
|
+
...plugin,
|
|
2879
|
+
...runtimePluginConfig
|
|
2880
|
+
}
|
|
2881
|
+
};
|
|
2882
|
+
};
|
|
2740
2883
|
var readConfigAssetSourcePath = (sourceConfig) => {
|
|
2741
2884
|
const sourceAsset = sourceConfig.asset;
|
|
2742
2885
|
if (sourceAsset === void 0) return;
|
|
2743
|
-
if (!isJsonObject$
|
|
2886
|
+
if (!isJsonObject$2(sourceAsset)) throw new Error("muon.json asset must be an object when present.");
|
|
2744
2887
|
const sourceAssetPath = sourceAsset.sourcePath;
|
|
2745
2888
|
if (sourceAssetPath === void 0) return;
|
|
2746
2889
|
if (typeof sourceAssetPath !== "string") throw new Error("muon.json asset.sourcePath must be a string when present.");
|
|
@@ -2749,28 +2892,28 @@ var readConfigAssetSourcePath = (sourceConfig) => {
|
|
|
2749
2892
|
var resolveConfigPath = async (root, configPath) => {
|
|
2750
2893
|
if (configPath !== void 0) {
|
|
2751
2894
|
const resolvedPath = resolve(root, configPath);
|
|
2752
|
-
if (await fileExists$
|
|
2895
|
+
if (await fileExists$2(resolvedPath)) return resolvedPath;
|
|
2753
2896
|
throw new Error(`Muon config file does not exist: ${resolvedPath}`);
|
|
2754
2897
|
}
|
|
2755
|
-
for (const fileName of defaultConfigFileNames) {
|
|
2898
|
+
for (const fileName of defaultConfigFileNames$1) {
|
|
2756
2899
|
const candidatePath = join(root, fileName);
|
|
2757
|
-
if (await fileExists$
|
|
2900
|
+
if (await fileExists$2(candidatePath)) return candidatePath;
|
|
2758
2901
|
}
|
|
2759
2902
|
};
|
|
2760
|
-
var readJsonObjectFile = async (filePath, label) => {
|
|
2903
|
+
var readJsonObjectFile$1 = async (filePath, label) => {
|
|
2761
2904
|
let content;
|
|
2762
2905
|
try {
|
|
2763
2906
|
content = await readFile(filePath, "utf8");
|
|
2764
2907
|
} catch (error) {
|
|
2765
|
-
throw new Error(`${label} could not be read: ${filePath}: ${getErrorMessage$
|
|
2908
|
+
throw new Error(`${label} could not be read: ${filePath}: ${getErrorMessage$3(error)}`);
|
|
2766
2909
|
}
|
|
2767
2910
|
let parsed;
|
|
2768
2911
|
try {
|
|
2769
2912
|
parsed = (0, import_dist.parse)(content);
|
|
2770
2913
|
} catch (error) {
|
|
2771
|
-
throw new Error(`${label} could not be parsed: ${filePath}: ${getErrorMessage$
|
|
2914
|
+
throw new Error(`${label} could not be parsed: ${filePath}: ${getErrorMessage$3(error)}`);
|
|
2772
2915
|
}
|
|
2773
|
-
if (!isJsonObject$
|
|
2916
|
+
if (!isJsonObject$2(parsed)) throw new Error(`${label} must contain a JSON object: ${filePath}`);
|
|
2774
2917
|
return parsed;
|
|
2775
2918
|
};
|
|
2776
2919
|
var buildMuonTarget = async (input) => {
|
|
@@ -2780,6 +2923,8 @@ var buildMuonTarget = async (input) => {
|
|
|
2780
2923
|
const outputPath = join(input.outputRoot, descriptor.distributionDirectoryName);
|
|
2781
2924
|
const launcherPath = join(outputPath, getLauncherFileName(input.appName, descriptor));
|
|
2782
2925
|
const assetZipPath = join(outputPath, "assets.zip");
|
|
2926
|
+
const runtimeAppId = getMuonTargetRuntimeAppId(input.appId, input.target);
|
|
2927
|
+
const appIconPath = descriptor.os === "windows" ? input.windowsResource.iconPath : input.linuxDesktop.iconPath;
|
|
2783
2928
|
await verifyTargetInputs({
|
|
2784
2929
|
sourceRuntimePath,
|
|
2785
2930
|
sourceBootstrapPath,
|
|
@@ -2798,8 +2943,11 @@ var buildMuonTarget = async (input) => {
|
|
|
2798
2943
|
await chmod(join(outputPath, descriptor.runtimeExecutableName), executableMode);
|
|
2799
2944
|
await copyFile(sourceBootstrapPath, launcherPath);
|
|
2800
2945
|
await chmod(launcherPath, executableMode);
|
|
2801
|
-
const asset = await writeAssetArchive(input.assetInput, assetZipPath, input.salt
|
|
2802
|
-
|
|
2946
|
+
const asset = await writeAssetArchive(input.assetInput, assetZipPath, input.salt, [{
|
|
2947
|
+
name: appIconAssetEntryName,
|
|
2948
|
+
data: await readFile(appIconPath)
|
|
2949
|
+
}]);
|
|
2950
|
+
const embeddedConfig = createEmbeddedConfig(input.sourceConfig, asset, runtimeAppId, input.linuxDesktop.desktopId, appIconAssetUrl);
|
|
2803
2951
|
await withTemporaryConfig(embeddedConfig, async (configPath) => {
|
|
2804
2952
|
await embedMuonConfigInRuntime({
|
|
2805
2953
|
runtimePath: outputPath,
|
|
@@ -2812,19 +2960,27 @@ var buildMuonTarget = async (input) => {
|
|
|
2812
2960
|
outputPath: void 0
|
|
2813
2961
|
});
|
|
2814
2962
|
});
|
|
2815
|
-
if (descriptor.os === "windows")
|
|
2816
|
-
|
|
2817
|
-
|
|
2818
|
-
|
|
2819
|
-
|
|
2820
|
-
|
|
2821
|
-
|
|
2963
|
+
if (descriptor.os === "windows") {
|
|
2964
|
+
await updateWindowsPeIconResource({
|
|
2965
|
+
executablePath: join(outputPath, descriptor.runtimeExecutableName),
|
|
2966
|
+
resource: input.windowsResource,
|
|
2967
|
+
environment: process.env,
|
|
2968
|
+
cwd: input.root
|
|
2969
|
+
});
|
|
2970
|
+
await updateWindowsPeResources({
|
|
2971
|
+
executablePath: launcherPath,
|
|
2972
|
+
resource: input.windowsResource,
|
|
2973
|
+
environment: process.env,
|
|
2974
|
+
cwd: input.root
|
|
2975
|
+
});
|
|
2976
|
+
} else if (descriptor.os === "linux") await writeLinuxDesktopDistributionFiles(outputPath, input.linuxDesktop);
|
|
2822
2977
|
return {
|
|
2823
2978
|
target: input.target,
|
|
2824
2979
|
distributionDirectoryName: descriptor.distributionDirectoryName,
|
|
2825
2980
|
outputPath,
|
|
2826
2981
|
launcherPath,
|
|
2827
2982
|
asset,
|
|
2983
|
+
runtimeAppId,
|
|
2828
2984
|
embeddedConfig,
|
|
2829
2985
|
...descriptor.os === "linux" ? { linuxDesktop: input.linuxDesktop } : {}
|
|
2830
2986
|
};
|
|
@@ -2847,10 +3003,10 @@ var copyRuntimeFiles = async (sourceRuntimePath, outputPath, descriptor) => {
|
|
|
2847
3003
|
}
|
|
2848
3004
|
await copyFile(join(sourceRuntimePath, muonLicenseFileName), join(outputPath, muonLicenseFileName));
|
|
2849
3005
|
};
|
|
2850
|
-
var writeAssetArchive = async (input, outputPath, salt) => {
|
|
3006
|
+
var writeAssetArchive = async (input, outputPath, salt, extraEntries) => {
|
|
2851
3007
|
const sourceStats = await statOrUndefined(input.sourcePath);
|
|
2852
3008
|
if (sourceStats === void 0) throw new Error(`Muon asset source does not exist: ${input.sourcePath}`);
|
|
2853
|
-
const archive = sourceStats.isDirectory() ? await createAssetArchiveFromDirectory(input) : sourceStats.isFile() ? await
|
|
3009
|
+
const archive = sourceStats.isDirectory() ? await createAssetArchiveFromDirectory(input, extraEntries) : sourceStats.isFile() ? await createAssetArchiveFromZipFile(input.sourcePath, extraEntries) : void 0;
|
|
2854
3010
|
if (archive === void 0) throw new Error(`Muon asset source is not a directory or file: ${input.sourcePath}`);
|
|
2855
3011
|
await writeFile(outputPath, archive);
|
|
2856
3012
|
return {
|
|
@@ -2860,10 +3016,30 @@ var writeAssetArchive = async (input, outputPath, salt) => {
|
|
|
2860
3016
|
entryCount: sourceStats.isDirectory() ? readZipEntryCount(archive, outputPath) : readZipEntryCount(archive, input.sourcePath)
|
|
2861
3017
|
};
|
|
2862
3018
|
};
|
|
2863
|
-
var createAssetArchiveFromDirectory = async (input) => {
|
|
3019
|
+
var createAssetArchiveFromDirectory = async (input, extraEntries) => {
|
|
2864
3020
|
const entries = await collectZipEntries(input.sourcePath, input.prefix);
|
|
2865
3021
|
if (entries.length === 0) throw new Error(`Muon asset source has no files: ${input.sourcePath}`);
|
|
2866
|
-
return createZipArchive(entries);
|
|
3022
|
+
return createZipArchive(appendZipEntries(entries, extraEntries));
|
|
3023
|
+
};
|
|
3024
|
+
var createAssetArchiveFromZipFile = async (sourcePath, extraEntries) => {
|
|
3025
|
+
const zip = new AdmZip(await readFile(sourcePath));
|
|
3026
|
+
for (const entry of extraEntries) {
|
|
3027
|
+
assertSafeZipEntryName(entry.name);
|
|
3028
|
+
if (zip.getEntry(entry.name) !== null) throw new Error(`Muon app icon asset entry already exists: ${entry.name}`);
|
|
3029
|
+
zip.addFile(entry.name, entry.data);
|
|
3030
|
+
}
|
|
3031
|
+
return zip.toBuffer();
|
|
3032
|
+
};
|
|
3033
|
+
var appendZipEntries = (entries, extraEntries) => {
|
|
3034
|
+
const output = [...entries];
|
|
3035
|
+
const names = new Set(entries.map((entry) => entry.name));
|
|
3036
|
+
for (const entry of extraEntries) {
|
|
3037
|
+
assertSafeZipEntryName(entry.name);
|
|
3038
|
+
if (names.has(entry.name)) throw new Error(`Muon app icon asset entry already exists: ${entry.name}`);
|
|
3039
|
+
names.add(entry.name);
|
|
3040
|
+
output.push(entry);
|
|
3041
|
+
}
|
|
3042
|
+
return output;
|
|
2867
3043
|
};
|
|
2868
3044
|
var readZipEntryCount = (archive, sourcePath) => {
|
|
2869
3045
|
const endSignature = 101010256;
|
|
@@ -2901,13 +3077,20 @@ var createZipArchive = (entries) => {
|
|
|
2901
3077
|
for (const entry of entries) zip.addFile(entry.name, entry.data);
|
|
2902
3078
|
return zip.toBuffer();
|
|
2903
3079
|
};
|
|
2904
|
-
var createEmbeddedConfig = (sourceConfig, asset, appId, desktopId) => {
|
|
3080
|
+
var createEmbeddedConfig = (sourceConfig, asset, appId, desktopId, initialTitleBarIcon) => {
|
|
2905
3081
|
const sourceAsset = sourceConfig.asset;
|
|
2906
|
-
if (sourceAsset !== void 0 && !isJsonObject$
|
|
3082
|
+
if (sourceAsset !== void 0 && !isJsonObject$2(sourceAsset)) throw new Error("muon.json asset must be an object when present.");
|
|
2907
3083
|
const sourceBootstrap = sourceConfig.bootstrap;
|
|
2908
|
-
if (sourceBootstrap !== void 0 && !isJsonObject$
|
|
3084
|
+
if (sourceBootstrap !== void 0 && !isJsonObject$2(sourceBootstrap)) throw new Error("muon.json bootstrap must be an object when present.");
|
|
3085
|
+
const runtimeConfig = stripBuildOnlyAppIconConfig(stripBuildOnlyLinuxDesktopConfig(stripBuildOnlyWindowsResourceConfig(sourceConfig)));
|
|
3086
|
+
const sourceBrowser = runtimeConfig.browser;
|
|
3087
|
+
if (sourceBrowser !== void 0 && !isJsonObject$2(sourceBrowser)) throw new Error("muon.json browser must be an object when present.");
|
|
2909
3088
|
return {
|
|
2910
|
-
...
|
|
3089
|
+
...runtimeConfig,
|
|
3090
|
+
browser: {
|
|
3091
|
+
...sourceBrowser ?? {},
|
|
3092
|
+
initialTitleBarIcon
|
|
3093
|
+
},
|
|
2911
3094
|
asset: {
|
|
2912
3095
|
...sourceAsset ?? {},
|
|
2913
3096
|
sourcePath: appConfigSourcePath,
|
|
@@ -2921,6 +3104,17 @@ var createEmbeddedConfig = (sourceConfig, asset, appId, desktopId) => {
|
|
|
2921
3104
|
}
|
|
2922
3105
|
};
|
|
2923
3106
|
};
|
|
3107
|
+
var assertNoUserInitialTitleBarIcon = (sourceConfig) => {
|
|
3108
|
+
const sourceBrowser = sourceConfig.browser;
|
|
3109
|
+
if (sourceBrowser === void 0) return;
|
|
3110
|
+
if (!isJsonObject$2(sourceBrowser)) throw new Error("muon.json browser must be an object when present.");
|
|
3111
|
+
if (sourceBrowser.initialTitleBarIcon !== void 0) throw new Error("muon.json browser.initialTitleBarIcon is generated by muon build; use top-level iconPath instead.");
|
|
3112
|
+
};
|
|
3113
|
+
var stripBuildOnlyAppIconConfig = (sourceConfig) => {
|
|
3114
|
+
const output = {};
|
|
3115
|
+
for (const [key, value] of Object.entries(sourceConfig)) if (key !== "iconPath") output[key] = value;
|
|
3116
|
+
return output;
|
|
3117
|
+
};
|
|
2924
3118
|
var withTemporaryConfig = async (config, callback) => {
|
|
2925
3119
|
const tempDirectory = await mkdtemp(join(tmpdir(), "muon-build-config-"));
|
|
2926
3120
|
const configPath = join(tempDirectory, "muon.json");
|
|
@@ -2949,7 +3143,7 @@ var statOrUndefined = async (path) => {
|
|
|
2949
3143
|
return;
|
|
2950
3144
|
}
|
|
2951
3145
|
};
|
|
2952
|
-
var fileExists$
|
|
3146
|
+
var fileExists$2 = async (path) => {
|
|
2953
3147
|
try {
|
|
2954
3148
|
await access(path, constants.F_OK);
|
|
2955
3149
|
return true;
|
|
@@ -2957,10 +3151,415 @@ var fileExists$1 = async (path) => {
|
|
|
2957
3151
|
return false;
|
|
2958
3152
|
}
|
|
2959
3153
|
};
|
|
2960
|
-
var isJsonObject$
|
|
3154
|
+
var isJsonObject$2 = (value) => {
|
|
2961
3155
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
2962
3156
|
};
|
|
2963
|
-
var getErrorMessage$
|
|
3157
|
+
var getErrorMessage$3 = (error) => error instanceof Error ? error.message : String(error);
|
|
3158
|
+
//#endregion
|
|
3159
|
+
//#region src/capability.ts
|
|
3160
|
+
var virtualModulePrefix = "\0muon-capability:";
|
|
3161
|
+
var moduleNamePattern = /^[A-Za-z_$][A-Za-z0-9_$]*:[A-Za-z_$][A-Za-z0-9_$]*(?:\.[A-Za-z_$][A-Za-z0-9_$]*)*$/u;
|
|
3162
|
+
var jsIdentifierPattern = /^[A-Za-z_$][A-Za-z0-9_$]*$/u;
|
|
3163
|
+
var normalizePath = (path) => (path.split("?")[0] ?? "").replaceAll("\\", "/");
|
|
3164
|
+
var hashCapabilityRule = (index, rule) => `cap-${createHash("sha1").update(JSON.stringify({
|
|
3165
|
+
index,
|
|
3166
|
+
pluginName: rule.pluginName,
|
|
3167
|
+
sources: [...rule.sources ?? []],
|
|
3168
|
+
packages: [...rule.packages ?? []],
|
|
3169
|
+
allow: [...rule.allow]
|
|
3170
|
+
})).digest("hex").slice(0, 16)}`;
|
|
3171
|
+
var parseCapabilitySpecifier = (source) => {
|
|
3172
|
+
if (!moduleNamePattern.test(source)) return;
|
|
3173
|
+
const separator = source.indexOf(":");
|
|
3174
|
+
return {
|
|
3175
|
+
moduleName: source,
|
|
3176
|
+
namespace: `${source.slice(0, separator)}.${source.slice(separator + 1)}`
|
|
3177
|
+
};
|
|
3178
|
+
};
|
|
3179
|
+
var escapeRegExp = (source) => source.replace(/[\\^$+?.()|[\]{}]/gu, "\\$&");
|
|
3180
|
+
var globToRegExp = (glob, separator) => {
|
|
3181
|
+
let source = "^";
|
|
3182
|
+
for (let index = 0; index < glob.length; index += 1) {
|
|
3183
|
+
const current = glob[index] ?? "";
|
|
3184
|
+
const next = glob[index + 1];
|
|
3185
|
+
if (current === "*" && next === "*") {
|
|
3186
|
+
source += ".*";
|
|
3187
|
+
index += 1;
|
|
3188
|
+
continue;
|
|
3189
|
+
}
|
|
3190
|
+
if (current === "*") {
|
|
3191
|
+
source += `[^${escapeRegExp(separator)}]*`;
|
|
3192
|
+
continue;
|
|
3193
|
+
}
|
|
3194
|
+
source += escapeRegExp(current);
|
|
3195
|
+
}
|
|
3196
|
+
source += "$";
|
|
3197
|
+
return new RegExp(source, "u");
|
|
3198
|
+
};
|
|
3199
|
+
var isGlobMatch = (glob, value, separator) => globToRegExp(glob, separator).test(value);
|
|
3200
|
+
var toRootRelativeImporter = (root, importer) => normalizePath(relative(root, importer));
|
|
3201
|
+
var readPackageName = (packageJsonPath) => {
|
|
3202
|
+
try {
|
|
3203
|
+
const parsed = JSON.parse(readFileSync(packageJsonPath, "utf8"));
|
|
3204
|
+
return typeof parsed === "object" && parsed !== null && !Array.isArray(parsed) && typeof parsed.name === "string" ? parsed.name : void 0;
|
|
3205
|
+
} catch {
|
|
3206
|
+
return;
|
|
3207
|
+
}
|
|
3208
|
+
};
|
|
3209
|
+
var getImporterPackageName = (root, importer) => {
|
|
3210
|
+
const normalizedRoot = normalizePath(root);
|
|
3211
|
+
const rootPackageJsonPath = join(root, "package.json");
|
|
3212
|
+
let directory = dirname(normalizePath(importer));
|
|
3213
|
+
for (;;) {
|
|
3214
|
+
const packageJsonPath = join(directory, "package.json");
|
|
3215
|
+
if (packageJsonPath !== rootPackageJsonPath && existsSync(packageJsonPath)) return readPackageName(packageJsonPath);
|
|
3216
|
+
if (normalizePath(directory) === normalizedRoot) return;
|
|
3217
|
+
const parent = dirname(directory);
|
|
3218
|
+
if (parent === directory) return;
|
|
3219
|
+
directory = parent;
|
|
3220
|
+
}
|
|
3221
|
+
};
|
|
3222
|
+
var matchesCapabilityRuleImporter = (rule, root, importer) => {
|
|
3223
|
+
const relativeImporter = toRootRelativeImporter(root, importer);
|
|
3224
|
+
if (rule.sources?.some((pattern) => isGlobMatch(normalizePath(pattern), relativeImporter, "/")) ?? false) return true;
|
|
3225
|
+
const packageName = getImporterPackageName(root, importer);
|
|
3226
|
+
return packageName === void 0 ? false : rule.packages?.includes(packageName) ?? false;
|
|
3227
|
+
};
|
|
3228
|
+
var hasNamespaceFunctionAllow = (namespace, allow) => allow.some((entry) => {
|
|
3229
|
+
if (entry.startsWith(`${namespace}.`)) return true;
|
|
3230
|
+
return isGlobMatch(entry, `${namespace}.placeholder`, ".");
|
|
3231
|
+
});
|
|
3232
|
+
var getExactExportName = (namespace, functionPath) => {
|
|
3233
|
+
const prefix = `${namespace}.`;
|
|
3234
|
+
if (!functionPath.startsWith(prefix)) return;
|
|
3235
|
+
const name = functionPath.slice(prefix.length);
|
|
3236
|
+
if (!jsIdentifierPattern.test(name)) return;
|
|
3237
|
+
return name;
|
|
3238
|
+
};
|
|
3239
|
+
var getExportedFunctions = (namespace, allow) => allow.flatMap((functionPath) => {
|
|
3240
|
+
const exportName = getExactExportName(namespace, functionPath);
|
|
3241
|
+
return exportName === void 0 ? [] : [[exportName, functionPath]];
|
|
3242
|
+
});
|
|
3243
|
+
var createRuleRuntimeEntry = (rule, index) => ({
|
|
3244
|
+
id: hashCapabilityRule(index, rule),
|
|
3245
|
+
allow: [...rule.allow]
|
|
3246
|
+
});
|
|
3247
|
+
var validateCapabilityRule = (rule) => {
|
|
3248
|
+
if ((rule.sources === void 0 || rule.sources.length === 0) && (rule.packages === void 0 || rule.packages.length === 0)) throw new Error("Muon capability import rule requires sources or packages.");
|
|
3249
|
+
};
|
|
3250
|
+
var createModuleVirtualId = (rule) => `${virtualModulePrefix}${rule.index}:${rule.moduleName}`;
|
|
3251
|
+
var parseModuleVirtualId = (id) => {
|
|
3252
|
+
if (!id.startsWith(virtualModulePrefix)) return;
|
|
3253
|
+
const payload = id.slice(17);
|
|
3254
|
+
const separator = payload.indexOf(":");
|
|
3255
|
+
if (separator <= 0) return;
|
|
3256
|
+
const index = Number.parseInt(payload.slice(0, separator), 10);
|
|
3257
|
+
if (!Number.isInteger(index) || index < 0) return;
|
|
3258
|
+
return {
|
|
3259
|
+
index,
|
|
3260
|
+
moduleName: payload.slice(separator + 1)
|
|
3261
|
+
};
|
|
3262
|
+
};
|
|
3263
|
+
var createExecutorSpawnExport = (capabilityId, functionPath) => `export const spawn = async (options = {}) => {
|
|
3264
|
+
const source = await __muonCall(${JSON.stringify(capabilityId)}, ${JSON.stringify(functionPath)}, [JSON.stringify(options ?? {})]);
|
|
3265
|
+
return JSON.parse(source);
|
|
3266
|
+
};`;
|
|
3267
|
+
var createGenericFunctionExport = (exportName, capabilityId, functionPath) => `export const ${exportName} = async (...args) =>
|
|
3268
|
+
await __muonCall(${JSON.stringify(capabilityId)}, ${JSON.stringify(functionPath)}, args);`;
|
|
3269
|
+
var createModuleSource = (rule) => {
|
|
3270
|
+
const exportedFunctions = getExportedFunctions(rule.namespace, rule.rule.allow);
|
|
3271
|
+
if (exportedFunctions.length === 0) throw new Error(`Muon capability import has no exact function exports: ${rule.moduleName}`);
|
|
3272
|
+
return `const __muonCall = globalThis.__muon_plugin_call;
|
|
3273
|
+
if (typeof __muonCall !== "function") {
|
|
3274
|
+
throw new Error("Muon plugin capability bridge is not available.");
|
|
3275
|
+
}
|
|
3276
|
+
|
|
3277
|
+
${exportedFunctions.map(([exportName, functionPath]) => rule.namespace === "muon.executor" && exportName === "spawn" ? createExecutorSpawnExport(rule.id, functionPath) : createGenericFunctionExport(exportName, rule.id, functionPath)).join("\n\n")}
|
|
3278
|
+
`;
|
|
3279
|
+
};
|
|
3280
|
+
/**
|
|
3281
|
+
* Creates a capability virtual module resolver for a bundler adapter.
|
|
3282
|
+
*
|
|
3283
|
+
* @param root Bundler project root.
|
|
3284
|
+
* @param options Capability import options.
|
|
3285
|
+
*/
|
|
3286
|
+
var createMuonCapabilityModuleResolver = (root, options) => {
|
|
3287
|
+
const rules = [...options?.imports ?? []];
|
|
3288
|
+
for (const rule of rules) validateCapabilityRule(rule);
|
|
3289
|
+
const runtimeEntries = rules.map((rule, index) => createRuleRuntimeEntry(rule, index));
|
|
3290
|
+
const resolveRule = (source, importer) => {
|
|
3291
|
+
const parsed = parseCapabilitySpecifier(source);
|
|
3292
|
+
if (parsed === void 0) return;
|
|
3293
|
+
if (!rules.some((rule) => hasNamespaceFunctionAllow(parsed.namespace, rule.allow))) return;
|
|
3294
|
+
if (importer === void 0) throw new Error(`Muon capability import is not allowed without an importer: ${source}`);
|
|
3295
|
+
const relativeImporter = toRootRelativeImporter(root, importer);
|
|
3296
|
+
for (let index = 0; index < rules.length; index += 1) {
|
|
3297
|
+
const rule = rules[index];
|
|
3298
|
+
if (rule === void 0 || !matchesCapabilityRuleImporter(rule, root, importer) || !hasNamespaceFunctionAllow(parsed.namespace, rule.allow)) continue;
|
|
3299
|
+
return {
|
|
3300
|
+
index,
|
|
3301
|
+
id: runtimeEntries[index]?.id ?? hashCapabilityRule(index, rule),
|
|
3302
|
+
rule,
|
|
3303
|
+
namespace: parsed.namespace,
|
|
3304
|
+
moduleName: parsed.moduleName
|
|
3305
|
+
};
|
|
3306
|
+
}
|
|
3307
|
+
throw new Error(`Muon capability import is not allowed: ${source} from ${relativeImporter}`);
|
|
3308
|
+
};
|
|
3309
|
+
return {
|
|
3310
|
+
resolveId: (source, importer) => {
|
|
3311
|
+
const rule = resolveRule(source, importer);
|
|
3312
|
+
return rule === void 0 ? void 0 : { id: createModuleVirtualId(rule) };
|
|
3313
|
+
},
|
|
3314
|
+
load: (id) => {
|
|
3315
|
+
const parsed = parseModuleVirtualId(id);
|
|
3316
|
+
if (parsed === void 0) return;
|
|
3317
|
+
const source = parseCapabilitySpecifier(parsed.moduleName);
|
|
3318
|
+
const rule = rules[parsed.index];
|
|
3319
|
+
const runtimeEntry = runtimeEntries[parsed.index];
|
|
3320
|
+
if (source === void 0 || rule === void 0 || runtimeEntry === void 0) return;
|
|
3321
|
+
return createModuleSource({
|
|
3322
|
+
index: parsed.index,
|
|
3323
|
+
id: runtimeEntry.id,
|
|
3324
|
+
rule,
|
|
3325
|
+
namespace: source.namespace,
|
|
3326
|
+
moduleName: source.moduleName
|
|
3327
|
+
});
|
|
3328
|
+
},
|
|
3329
|
+
getRuntimePluginConfig: () => ({
|
|
3330
|
+
mode: "validate",
|
|
3331
|
+
capabilities: runtimeEntries
|
|
3332
|
+
})
|
|
3333
|
+
};
|
|
3334
|
+
};
|
|
3335
|
+
//#endregion
|
|
3336
|
+
//#region src/plugin-access.ts
|
|
3337
|
+
var defaultConfigFileNames = [
|
|
3338
|
+
"muon.json5",
|
|
3339
|
+
"muon.jsonc",
|
|
3340
|
+
"muon.json"
|
|
3341
|
+
];
|
|
3342
|
+
var defaultPluginPages = ["asset://main/**"];
|
|
3343
|
+
var isJsonObject$1 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
3344
|
+
var isStringArray = (value) => Array.isArray(value) && value.every((entry) => typeof entry === "string");
|
|
3345
|
+
var isSha1HexString = (value) => value.length === 40 && /^[0-9a-fA-F]+$/.test(value);
|
|
3346
|
+
var isHexByteString = (value) => value.length % 2 === 0 && /^[0-9a-fA-F]*$/.test(value);
|
|
3347
|
+
var getErrorMessage$2 = (error) => error instanceof Error ? error.message : String(error);
|
|
3348
|
+
var fileExists$1 = async (path) => {
|
|
3349
|
+
try {
|
|
3350
|
+
await access(path, constants.F_OK);
|
|
3351
|
+
return true;
|
|
3352
|
+
} catch {
|
|
3353
|
+
return false;
|
|
3354
|
+
}
|
|
3355
|
+
};
|
|
3356
|
+
var resolveMuonConfigPath = async (root, configPath) => {
|
|
3357
|
+
if (configPath !== void 0) {
|
|
3358
|
+
const resolvedPath = resolve(root, configPath);
|
|
3359
|
+
if (await fileExists$1(resolvedPath)) return resolvedPath;
|
|
3360
|
+
throw new Error(`Muon config file does not exist: ${resolvedPath}`);
|
|
3361
|
+
}
|
|
3362
|
+
for (const fileName of defaultConfigFileNames) {
|
|
3363
|
+
const candidatePath = join(root, fileName);
|
|
3364
|
+
if (await fileExists$1(candidatePath)) return candidatePath;
|
|
3365
|
+
}
|
|
3366
|
+
};
|
|
3367
|
+
var readJsonObjectFile = async (path, label) => {
|
|
3368
|
+
let content;
|
|
3369
|
+
try {
|
|
3370
|
+
content = await readFile(path, "utf8");
|
|
3371
|
+
} catch (error) {
|
|
3372
|
+
throw new Error(`${label} could not be read: ${path}: ${getErrorMessage$2(error)}`);
|
|
3373
|
+
}
|
|
3374
|
+
let parsed;
|
|
3375
|
+
try {
|
|
3376
|
+
parsed = (0, import_dist.parse)(content);
|
|
3377
|
+
} catch (error) {
|
|
3378
|
+
throw new Error(`${label} could not be parsed: ${path}: ${getErrorMessage$2(error)}`);
|
|
3379
|
+
}
|
|
3380
|
+
if (!isJsonObject$1(parsed)) throw new Error(`${label} must contain a JSON object: ${path}`);
|
|
3381
|
+
return parsed;
|
|
3382
|
+
};
|
|
3383
|
+
var readOptionalStringArray = (object, key, configPath) => {
|
|
3384
|
+
const value = object[key];
|
|
3385
|
+
if (value === void 0) return;
|
|
3386
|
+
if (!isStringArray(value)) throw new Error(`muon.json ${configPath} must be an array of strings.`);
|
|
3387
|
+
return value;
|
|
3388
|
+
};
|
|
3389
|
+
var readPluginAccessImportOptions = (value, configPath) => {
|
|
3390
|
+
if (!isJsonObject$1(value)) throw new Error(`muon.json ${configPath} must be an object.`);
|
|
3391
|
+
const sources = readOptionalStringArray(value, "sources", `${configPath}.sources`);
|
|
3392
|
+
const packages = readOptionalStringArray(value, "packages", `${configPath}.packages`);
|
|
3393
|
+
const allow = readOptionalStringArray(value, "allow", `${configPath}.allow`);
|
|
3394
|
+
const options = {};
|
|
3395
|
+
if (sources !== void 0) options.sources = sources;
|
|
3396
|
+
if (packages !== void 0) options.packages = packages;
|
|
3397
|
+
if (allow !== void 0) options.allow = allow;
|
|
3398
|
+
return options;
|
|
3399
|
+
};
|
|
3400
|
+
var readPluginAccessEntryOptions = (value, index) => {
|
|
3401
|
+
const configPath = `plugin.plugins[${index}]`;
|
|
3402
|
+
if (!isJsonObject$1(value)) throw new Error(`muon.json ${configPath} must be an object.`);
|
|
3403
|
+
if (typeof value.name !== "string") throw new Error(`muon.json ${configPath}.name must be a string.`);
|
|
3404
|
+
if (value.signature !== void 0) {
|
|
3405
|
+
if (typeof value.signature !== "string") throw new Error(`muon.json ${configPath}.signature must be a string.`);
|
|
3406
|
+
if (!isSha1HexString(value.signature)) throw new Error(`muon.json ${configPath}.signature must be a 40-character SHA-1 hex string.`);
|
|
3407
|
+
}
|
|
3408
|
+
if (value.salt !== void 0) {
|
|
3409
|
+
if (typeof value.salt !== "string") throw new Error(`muon.json ${configPath}.salt must be a string.`);
|
|
3410
|
+
if (!isHexByteString(value.salt)) throw new Error(`muon.json ${configPath}.salt must be a hexadecimal byte string.`);
|
|
3411
|
+
}
|
|
3412
|
+
const allow = readOptionalStringArray(value, "allow", `${configPath}.allow`);
|
|
3413
|
+
const rawImports = value.imports;
|
|
3414
|
+
if (rawImports !== void 0 && !Array.isArray(rawImports)) throw new Error(`muon.json ${configPath}.imports must be an array.`);
|
|
3415
|
+
const imports = rawImports === void 0 ? void 0 : rawImports.map((entry, importIndex) => readPluginAccessImportOptions(entry, `${configPath}.imports[${importIndex}]`));
|
|
3416
|
+
const options = { name: value.name };
|
|
3417
|
+
if (value.signature !== void 0) options.signature = value.signature;
|
|
3418
|
+
if (value.salt !== void 0) options.salt = value.salt;
|
|
3419
|
+
if (allow !== void 0) options.allow = allow;
|
|
3420
|
+
if (imports !== void 0) options.imports = imports;
|
|
3421
|
+
return options;
|
|
3422
|
+
};
|
|
3423
|
+
var readPluginAccessOptions = (config) => {
|
|
3424
|
+
const browser = config.browser;
|
|
3425
|
+
if (isJsonObject$1(browser) && browser.plugin !== void 0) throw new Error("muon.json browser.plugin is no longer supported; use plugin.mode and plugin.pages instead.");
|
|
3426
|
+
const plugin = config.plugin;
|
|
3427
|
+
if (plugin === void 0) return {};
|
|
3428
|
+
if (!isJsonObject$1(plugin)) throw new Error("muon.json plugin must be an object.");
|
|
3429
|
+
const options = {};
|
|
3430
|
+
if (plugin.path !== void 0) {
|
|
3431
|
+
if (typeof plugin.path !== "string") throw new Error("muon.json plugin.path must be a string.");
|
|
3432
|
+
if (plugin.path.length === 0) throw new Error("muon.json plugin.path must not be empty.");
|
|
3433
|
+
options.path = plugin.path;
|
|
3434
|
+
}
|
|
3435
|
+
if (plugin.mode !== void 0) {
|
|
3436
|
+
if (typeof plugin.mode !== "string") throw new Error("muon.json plugin.mode must be a string.");
|
|
3437
|
+
if (plugin.mode.length === 0) throw new Error("muon.json plugin.mode must not be empty.");
|
|
3438
|
+
if (plugin.mode !== "simple" && plugin.mode !== "validate") throw new Error("muon.json plugin.mode has unknown value.");
|
|
3439
|
+
options.mode = plugin.mode;
|
|
3440
|
+
}
|
|
3441
|
+
const pages = readOptionalStringArray(plugin, "pages", "plugin.pages");
|
|
3442
|
+
if (pages !== void 0) options.pages = pages;
|
|
3443
|
+
const rawPlugins = plugin.plugins;
|
|
3444
|
+
if (rawPlugins !== void 0) {
|
|
3445
|
+
if (!Array.isArray(rawPlugins)) throw new Error("muon.json plugin.plugins must be an array.");
|
|
3446
|
+
options.plugins = rawPlugins.map((entry, index) => readPluginAccessEntryOptions(entry, index));
|
|
3447
|
+
}
|
|
3448
|
+
return options;
|
|
3449
|
+
};
|
|
3450
|
+
var hasImportSourceSelector = (entry) => entry.sources !== void 0 && entry.sources.length > 0 || entry.packages !== void 0 && entry.packages.length > 0;
|
|
3451
|
+
var validatePluginAccessOptions = (resolved) => {
|
|
3452
|
+
for (const [pluginIndex, plugin] of resolved.plugins.entries()) {
|
|
3453
|
+
const pluginPath = `plugin.plugins[${pluginIndex}]`;
|
|
3454
|
+
if (plugin.name === "internal" && plugin.signature !== void 0) throw new Error(`muon.json ${pluginPath}.signature is not supported for internal plugins.`);
|
|
3455
|
+
if (plugin.name === "internal" && plugin.salt !== void 0) throw new Error(`muon.json ${pluginPath}.salt is not supported for internal plugins.`);
|
|
3456
|
+
if (plugin.signature !== void 0 && plugin.salt === void 0) throw new Error(`muon.json ${pluginPath}.signature requires ${pluginPath}.salt.`);
|
|
3457
|
+
if (resolved.mode === "validate") {
|
|
3458
|
+
if (plugin.allow !== void 0) throw new Error(`muon.json ${pluginPath}.allow is only supported in simple mode; use ${pluginPath}.imports[].allow in validate mode.`);
|
|
3459
|
+
if (plugin.imports === void 0) throw new Error(`muon.json ${pluginPath}.imports is required in validate mode.`);
|
|
3460
|
+
if (plugin.imports.length === 0) throw new Error(`muon.json ${pluginPath}.imports must not be empty in validate mode.`);
|
|
3461
|
+
for (const [importIndex, entry] of plugin.imports.entries()) {
|
|
3462
|
+
const importPath = `${pluginPath}.imports[${importIndex}]`;
|
|
3463
|
+
if (!hasImportSourceSelector(entry)) throw new Error(`muon.json ${importPath} requires sources or packages.`);
|
|
3464
|
+
if (entry.allow === void 0) throw new Error(`muon.json ${importPath}.allow is required in validate mode.`);
|
|
3465
|
+
if (entry.allow.length === 0) throw new Error(`muon.json ${importPath}.allow must not be empty in validate mode.`);
|
|
3466
|
+
}
|
|
3467
|
+
continue;
|
|
3468
|
+
}
|
|
3469
|
+
if (plugin.allow === void 0) throw new Error(`muon.json ${pluginPath}.allow is required in simple mode.`);
|
|
3470
|
+
if (plugin.imports !== void 0) throw new Error(`muon.json ${pluginPath}.imports is only supported in validate mode.`);
|
|
3471
|
+
}
|
|
3472
|
+
return resolved;
|
|
3473
|
+
};
|
|
3474
|
+
var getValidateImportAllow = (entry, pluginIndex, importIndex) => {
|
|
3475
|
+
if (entry.allow === void 0 || entry.allow.length === 0) throw new Error(`muon.json plugin.plugins[${pluginIndex}].imports[${importIndex}].allow is required in validate mode.`);
|
|
3476
|
+
return entry.allow;
|
|
3477
|
+
};
|
|
3478
|
+
var getSimplePluginAllow = (plugin, pluginIndex) => {
|
|
3479
|
+
if (plugin.allow === void 0) throw new Error(`muon.json plugin.plugins[${pluginIndex}].allow is required in simple mode.`);
|
|
3480
|
+
return plugin.allow;
|
|
3481
|
+
};
|
|
3482
|
+
var toCapabilityImports = (plugins) => plugins.flatMap((plugin, pluginIndex) => (plugin.imports ?? []).map((entry, importIndex) => {
|
|
3483
|
+
if (!hasImportSourceSelector(entry)) throw new Error(`muon.json plugin.plugins[${pluginIndex}].imports[${importIndex}] requires sources or packages.`);
|
|
3484
|
+
const rule = {
|
|
3485
|
+
allow: getValidateImportAllow(entry, pluginIndex, importIndex),
|
|
3486
|
+
pluginName: plugin.name
|
|
3487
|
+
};
|
|
3488
|
+
if (entry.sources !== void 0) rule.sources = entry.sources;
|
|
3489
|
+
if (entry.packages !== void 0) rule.packages = entry.packages;
|
|
3490
|
+
return rule;
|
|
3491
|
+
}));
|
|
3492
|
+
var toValidateRuntimePluginEntries = (plugins) => plugins.map((plugin, pluginIndex) => {
|
|
3493
|
+
const allow = [];
|
|
3494
|
+
const seenAllow = /* @__PURE__ */ new Set();
|
|
3495
|
+
for (const [importIndex, entry] of (plugin.imports ?? []).entries()) for (const functionPath of getValidateImportAllow(entry, pluginIndex, importIndex)) if (!seenAllow.has(functionPath)) {
|
|
3496
|
+
seenAllow.add(functionPath);
|
|
3497
|
+
allow.push(functionPath);
|
|
3498
|
+
}
|
|
3499
|
+
return {
|
|
3500
|
+
name: plugin.name,
|
|
3501
|
+
...plugin.signature === void 0 ? {} : { signature: plugin.signature },
|
|
3502
|
+
...plugin.salt === void 0 ? {} : { salt: plugin.salt },
|
|
3503
|
+
allow
|
|
3504
|
+
};
|
|
3505
|
+
});
|
|
3506
|
+
var toSimpleRuntimePluginEntries = (plugins) => plugins.map((plugin, pluginIndex) => ({
|
|
3507
|
+
name: plugin.name,
|
|
3508
|
+
...plugin.signature === void 0 ? {} : { signature: plugin.signature },
|
|
3509
|
+
...plugin.salt === void 0 ? {} : { salt: plugin.salt },
|
|
3510
|
+
allow: [...getSimplePluginAllow(plugin, pluginIndex)]
|
|
3511
|
+
}));
|
|
3512
|
+
var shouldOverlayRuntimePlugins = (resolved, override) => override !== false && (override?.plugins !== void 0 || resolved.mode === "validate" && resolved.plugins.length > 0);
|
|
3513
|
+
var toRuntimePluginEntries = (resolved) => resolved.mode === "validate" ? toValidateRuntimePluginEntries(resolved.plugins) : toSimpleRuntimePluginEntries(resolved.plugins);
|
|
3514
|
+
var mergePluginAccessOptions = (base, override) => ({
|
|
3515
|
+
...override?.path === void 0 ? {} : { path: override.path },
|
|
3516
|
+
mode: override?.mode ?? base.mode ?? "validate",
|
|
3517
|
+
pages: override?.pages ?? base.pages ?? defaultPluginPages,
|
|
3518
|
+
plugins: override?.plugins ?? base.plugins ?? []
|
|
3519
|
+
});
|
|
3520
|
+
var createRuntimeOverlay = (root, resolved, override) => {
|
|
3521
|
+
if (override === false) return {};
|
|
3522
|
+
const path = override?.path !== void 0 ? resolve(root, override.path) : void 0;
|
|
3523
|
+
const plugins = shouldOverlayRuntimePlugins(resolved, override) ? toRuntimePluginEntries(resolved) : void 0;
|
|
3524
|
+
return {
|
|
3525
|
+
pages: resolved.pages,
|
|
3526
|
+
...path === void 0 ? {} : { path },
|
|
3527
|
+
...plugins === void 0 ? {} : { plugins }
|
|
3528
|
+
};
|
|
3529
|
+
};
|
|
3530
|
+
/**
|
|
3531
|
+
* Resolves public plugin access config from muon.json and Vite overrides.
|
|
3532
|
+
*
|
|
3533
|
+
* @param input Resolution inputs.
|
|
3534
|
+
* @returns Effective plugin access config for bundler integrations.
|
|
3535
|
+
*/
|
|
3536
|
+
var resolveMuonPluginAccessOptions = async ({ root, configPath, pluginAccess, onConfigReadError }) => {
|
|
3537
|
+
const resolvedConfigPath = await resolveMuonConfigPath(root, configPath);
|
|
3538
|
+
let base = {};
|
|
3539
|
+
if (resolvedConfigPath !== void 0) try {
|
|
3540
|
+
base = readPluginAccessOptions(await readJsonObjectFile(resolvedConfigPath, "Muon config file"));
|
|
3541
|
+
} catch (error) {
|
|
3542
|
+
if (onConfigReadError === void 0) throw error;
|
|
3543
|
+
onConfigReadError(error);
|
|
3544
|
+
}
|
|
3545
|
+
if (pluginAccess === false) {
|
|
3546
|
+
const resolved = validatePluginAccessOptions(mergePluginAccessOptions(base, { mode: "simple" }));
|
|
3547
|
+
return {
|
|
3548
|
+
mode: "simple",
|
|
3549
|
+
pages: resolved.pages,
|
|
3550
|
+
capabilityOptions: { imports: [] },
|
|
3551
|
+
runtimeOverlay: createRuntimeOverlay(root, resolved, pluginAccess)
|
|
3552
|
+
};
|
|
3553
|
+
}
|
|
3554
|
+
const resolved = validatePluginAccessOptions(mergePluginAccessOptions(base, pluginAccess));
|
|
3555
|
+
const capabilityOptions = { imports: resolved.mode === "validate" ? toCapabilityImports(resolved.plugins) : [] };
|
|
3556
|
+
return {
|
|
3557
|
+
mode: resolved.mode,
|
|
3558
|
+
pages: resolved.pages,
|
|
3559
|
+
capabilityOptions,
|
|
3560
|
+
runtimeOverlay: createRuntimeOverlay(root, resolved, pluginAccess)
|
|
3561
|
+
};
|
|
3562
|
+
};
|
|
2964
3563
|
//#endregion
|
|
2965
3564
|
//#region src/gitignore.ts
|
|
2966
3565
|
var muonGitignoreEntries = [
|
|
@@ -3124,7 +3723,7 @@ var getWebSocketOrigin = (startUrl) => {
|
|
|
3124
3723
|
else if (url.protocol === "http:") url.protocol = "ws:";
|
|
3125
3724
|
return url.origin;
|
|
3126
3725
|
};
|
|
3127
|
-
var createMuonOverrideConfig = (startUrl, enableDebugger) => {
|
|
3726
|
+
var createMuonOverrideConfig = (startUrl, enableDebugger, runtimePluginConfig) => {
|
|
3128
3727
|
const origin = new URL(startUrl).origin;
|
|
3129
3728
|
return {
|
|
3130
3729
|
...enableDebugger ? { cdp: { enable: true } } : {},
|
|
@@ -3133,19 +3732,22 @@ var createMuonOverrideConfig = (startUrl, enableDebugger) => {
|
|
|
3133
3732
|
...enableDebugger ? { keybind: {
|
|
3134
3733
|
devtools: "f12",
|
|
3135
3734
|
recycle: "ctrl+f12"
|
|
3136
|
-
} } : {}
|
|
3137
|
-
|
|
3735
|
+
} } : {}
|
|
3736
|
+
},
|
|
3737
|
+
plugin: {
|
|
3738
|
+
...runtimePluginConfig,
|
|
3739
|
+
pages: [`${origin}/**`]
|
|
3138
3740
|
},
|
|
3139
3741
|
network: { allow: [`${origin}/**`, `${getWebSocketOrigin(startUrl)}/**`] }
|
|
3140
3742
|
};
|
|
3141
3743
|
};
|
|
3142
|
-
var writeMuonOverrideConfig = (server, overrideConfigPath,
|
|
3744
|
+
var writeMuonOverrideConfig = (server, overrideConfigPath, pluginOptions, getRuntimePluginConfig) => {
|
|
3143
3745
|
const startUrl = getBaseUrl(server);
|
|
3144
3746
|
if (startUrl === void 0) {
|
|
3145
3747
|
server.config.logger.warn("Muon Vite plugin could not resolve a Vite URL.");
|
|
3146
3748
|
return false;
|
|
3147
3749
|
}
|
|
3148
|
-
writeFileSync(overrideConfigPath, `${JSON.stringify(createMuonOverrideConfig(startUrl, enableDebugger), null, 2)}\n`);
|
|
3750
|
+
writeFileSync(overrideConfigPath, `${JSON.stringify(createMuonOverrideConfig(startUrl, pluginOptions.enableDebugger !== false, getRuntimePluginConfig()), null, 2)}\n`);
|
|
3149
3751
|
return true;
|
|
3150
3752
|
};
|
|
3151
3753
|
var createRuntimePaths = async (server, stagePath, platform, projectConfigPath) => {
|
|
@@ -3167,7 +3769,7 @@ var fileExists = async (path) => {
|
|
|
3167
3769
|
}
|
|
3168
3770
|
};
|
|
3169
3771
|
var isJsonObject = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
3170
|
-
var getErrorMessage = (error) => error instanceof Error ? error.message : String(error);
|
|
3772
|
+
var getErrorMessage$1 = (error) => error instanceof Error ? error.message : String(error);
|
|
3171
3773
|
var resolveProjectConfigPath = async (server) => {
|
|
3172
3774
|
for (const fileName of defaultProjectConfigFileNames) {
|
|
3173
3775
|
const candidatePath = join(server.config.root, fileName);
|
|
@@ -3176,7 +3778,7 @@ var resolveProjectConfigPath = async (server) => {
|
|
|
3176
3778
|
if (!isJsonObject((0, import_dist.parse)(await readFile(candidatePath, "utf8")))) throw new Error("muon config root must be an object");
|
|
3177
3779
|
return candidatePath;
|
|
3178
3780
|
} catch (error) {
|
|
3179
|
-
server.config.logger.warn(`Muon project config will be ignored because it could not be read or parsed: ${candidatePath}: ${getErrorMessage(error)}`);
|
|
3781
|
+
server.config.logger.warn(`Muon project config will be ignored because it could not be read or parsed: ${candidatePath}: ${getErrorMessage$1(error)}`);
|
|
3180
3782
|
return;
|
|
3181
3783
|
}
|
|
3182
3784
|
}
|
|
@@ -3204,11 +3806,11 @@ var launchMuon = (paths, platform, server) => {
|
|
|
3204
3806
|
windowsHide: false
|
|
3205
3807
|
});
|
|
3206
3808
|
child.once("error", (error) => {
|
|
3207
|
-
server.config.logger.warn(`Muon startup failed: ${getErrorMessage(error)}`);
|
|
3809
|
+
server.config.logger.warn(`Muon startup failed: ${getErrorMessage$1(error)}`);
|
|
3208
3810
|
});
|
|
3209
3811
|
child.unref();
|
|
3210
3812
|
};
|
|
3211
|
-
var startMuonViteBrowserBridge = async ({ server, pluginOptions, platform, architecture, environment }) => {
|
|
3813
|
+
var startMuonViteBrowserBridge = async ({ server, pluginOptions, getRuntimePluginConfig, platform, architecture, environment }) => {
|
|
3212
3814
|
await ensureMuonGitignoreEntry(server.config.root);
|
|
3213
3815
|
if (pluginOptions.open === false || server.httpServer === null) return;
|
|
3214
3816
|
const target = getDefaultMuonPrepareTarget(platform, architecture);
|
|
@@ -3254,7 +3856,7 @@ var startMuonViteBrowserBridge = async ({ server, pluginOptions, platform, archi
|
|
|
3254
3856
|
cleanup();
|
|
3255
3857
|
});
|
|
3256
3858
|
server.httpServer.once("listening", () => {
|
|
3257
|
-
if (writeMuonOverrideConfig(server, paths.overrideConfigPath, pluginOptions
|
|
3859
|
+
if (writeMuonOverrideConfig(server, paths.overrideConfigPath, pluginOptions, getRuntimePluginConfig)) launchMuon(paths, platform, server);
|
|
3258
3860
|
});
|
|
3259
3861
|
};
|
|
3260
3862
|
//#endregion
|
|
@@ -3281,6 +3883,7 @@ var attachMuonVitePluginOptions = (plugin, options) => {
|
|
|
3281
3883
|
};
|
|
3282
3884
|
//#endregion
|
|
3283
3885
|
//#region src/vite.ts
|
|
3886
|
+
var getErrorMessage = (error) => error instanceof Error ? error.message : String(error);
|
|
3284
3887
|
/**
|
|
3285
3888
|
* Creates a Vite plugin that launches Muon during Vite dev startup.
|
|
3286
3889
|
*
|
|
@@ -3290,19 +3893,33 @@ var attachMuonVitePluginOptions = (plugin, options) => {
|
|
|
3290
3893
|
*/
|
|
3291
3894
|
var muon = (options = {}) => {
|
|
3292
3895
|
let resolvedConfig = void 0;
|
|
3896
|
+
let capabilityResolver = void 0;
|
|
3897
|
+
let resolvedPluginAccess = void 0;
|
|
3293
3898
|
return attachMuonVitePluginOptions({
|
|
3294
3899
|
name: "muon",
|
|
3295
3900
|
config: (config) => {
|
|
3296
3901
|
if (config.server?.watch === null) return null;
|
|
3297
3902
|
return { server: { watch: createMuonWatchOptions(config.server?.watch) } };
|
|
3298
3903
|
},
|
|
3299
|
-
configResolved: (config) => {
|
|
3904
|
+
configResolved: async (config) => {
|
|
3300
3905
|
resolvedConfig = config;
|
|
3906
|
+
resolvedPluginAccess = await resolveMuonPluginAccessOptions({
|
|
3907
|
+
root: config.root,
|
|
3908
|
+
configPath: resolveMuonConfigPathForViteCommand(config, options),
|
|
3909
|
+
pluginAccess: options.pluginAccess,
|
|
3910
|
+
...config.command === "serve" ? { onConfigReadError: (error) => {
|
|
3911
|
+
config.logger.warn(`Muon project config will be ignored because it could not be read or parsed: ${getErrorMessage(error)}`);
|
|
3912
|
+
} } : {}
|
|
3913
|
+
});
|
|
3914
|
+
capabilityResolver = resolvedPluginAccess.mode === "validate" ? createMuonCapabilityModuleResolver(config.root, resolvedPluginAccess.capabilityOptions) : void 0;
|
|
3301
3915
|
},
|
|
3916
|
+
resolveId: (source, importer) => capabilityResolver?.resolveId(source, importer)?.id,
|
|
3917
|
+
load: (id) => capabilityResolver?.load(id),
|
|
3302
3918
|
configureServer: async (server) => {
|
|
3303
3919
|
await startMuonViteBrowserBridge({
|
|
3304
3920
|
server,
|
|
3305
3921
|
pluginOptions: options,
|
|
3922
|
+
getRuntimePluginConfig: () => resolveMuonRuntimePluginConfig(capabilityResolver, resolvedPluginAccess),
|
|
3306
3923
|
platform: process.platform,
|
|
3307
3924
|
architecture: process.arch,
|
|
3308
3925
|
environment: process.env
|
|
@@ -3313,7 +3930,7 @@ var muon = (options = {}) => {
|
|
|
3313
3930
|
if (process.env["MUON_SUPPRESS_VITE_MUON_BUILD"] === "1") return;
|
|
3314
3931
|
if (options.build === false) return;
|
|
3315
3932
|
const buildOptions = typeof options.build === "object" ? options.build : {};
|
|
3316
|
-
await buildMuonApp(createMuonBuildOptions(resolvedConfig, buildOptions));
|
|
3933
|
+
await buildMuonApp(createMuonBuildOptions(resolvedConfig, buildOptions, resolveMuonRuntimePluginConfig(capabilityResolver, resolvedPluginAccess)));
|
|
3317
3934
|
}
|
|
3318
3935
|
}, options);
|
|
3319
3936
|
};
|
|
@@ -3330,7 +3947,7 @@ var createMuonWatchOptions = (watch) => ({
|
|
|
3330
3947
|
...watch ?? {},
|
|
3331
3948
|
ignored: mergeMuonWatchIgnored(watch?.ignored)
|
|
3332
3949
|
});
|
|
3333
|
-
var createMuonBuildOptions = (config, buildOptions) => {
|
|
3950
|
+
var createMuonBuildOptions = (config, buildOptions, runtimePluginConfig) => {
|
|
3334
3951
|
const outDir = isAbsolute(config.build.outDir) ? config.build.outDir : resolve(config.root, config.build.outDir);
|
|
3335
3952
|
const options = {
|
|
3336
3953
|
root: config.root,
|
|
@@ -3343,12 +3960,28 @@ var createMuonBuildOptions = (config, buildOptions) => {
|
|
|
3343
3960
|
if (buildOptions.appId !== void 0) options.appId = buildOptions.appId;
|
|
3344
3961
|
if (buildOptions.outputRoot !== void 0) options.outputRoot = buildOptions.outputRoot;
|
|
3345
3962
|
if (buildOptions.configPath !== void 0) options.configPath = buildOptions.configPath;
|
|
3963
|
+
if (buildOptions.iconPath !== void 0) options.iconPath = buildOptions.iconPath;
|
|
3346
3964
|
if (buildOptions.windowsResource !== void 0) options.windowsResource = buildOptions.windowsResource;
|
|
3347
3965
|
if (buildOptions.linuxDesktop !== void 0) options.linuxDesktop = buildOptions.linuxDesktop;
|
|
3348
3966
|
if (buildOptions.packageDirectory !== void 0) options.packageDirectory = buildOptions.packageDirectory;
|
|
3349
3967
|
if (buildOptions.assetSalt !== void 0) options.assetSalt = buildOptions.assetSalt;
|
|
3968
|
+
options.runtimePluginConfig = runtimePluginConfig;
|
|
3350
3969
|
return options;
|
|
3351
3970
|
};
|
|
3971
|
+
var resolveMuonConfigPathForViteCommand = (config, options) => {
|
|
3972
|
+
if (config.command !== "build" || typeof options.build !== "object") return;
|
|
3973
|
+
return options.build.configPath;
|
|
3974
|
+
};
|
|
3975
|
+
var resolveMuonRuntimePluginConfig = (capabilityResolver, pluginAccess) => pluginAccess?.mode === "simple" ? {
|
|
3976
|
+
mode: "simple",
|
|
3977
|
+
...pluginAccess.runtimeOverlay
|
|
3978
|
+
} : {
|
|
3979
|
+
...capabilityResolver?.getRuntimePluginConfig() ?? {
|
|
3980
|
+
mode: "validate",
|
|
3981
|
+
capabilities: []
|
|
3982
|
+
},
|
|
3983
|
+
...pluginAccess?.runtimeOverlay ?? {}
|
|
3984
|
+
};
|
|
3352
3985
|
//#endregion
|
|
3353
3986
|
export { muon as default };
|
|
3354
3987
|
|