muon-ui 0.11.0 → 0.13.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 (40) hide show
  1. package/dist/cli.cjs +401 -66
  2. package/dist/cli.cjs.map +1 -1
  3. package/dist/index.cjs +2 -2
  4. package/dist/index.mjs +2 -2
  5. package/dist/native/linux-amd64/muon-bootstrap +0 -0
  6. package/dist/native/linux-amd64/muon-builder +0 -0
  7. package/dist/native/linux-amd64/muon-runtime-helper +0 -0
  8. package/dist/native/linux-arm64/muon-bootstrap +0 -0
  9. package/dist/native/linux-arm64/muon-builder +0 -0
  10. package/dist/native/linux-arm64/muon-runtime-helper +0 -0
  11. package/dist/native/linux-armhf/muon-bootstrap +0 -0
  12. package/dist/native/linux-armhf/muon-builder +0 -0
  13. package/dist/native/linux-armhf/muon-runtime-helper +0 -0
  14. package/dist/native/windows-amd64/muon-bootstrap.exe +0 -0
  15. package/dist/native/windows-amd64/muon-builder.exe +0 -0
  16. package/dist/native/windows-i686/muon-bootstrap.exe +0 -0
  17. package/dist/native/windows-i686/muon-builder.exe +0 -0
  18. package/dist/runtime/linux-amd64/libmuon-ui.so +0 -0
  19. package/dist/runtime/linux-amd64/muon-core +0 -0
  20. package/dist/runtime/linux-arm64/libmuon-ui.so +0 -0
  21. package/dist/runtime/linux-arm64/muon-core +0 -0
  22. package/dist/runtime/linux-armhf/libmuon-ui.so +0 -0
  23. package/dist/runtime/linux-armhf/muon-core +0 -0
  24. package/dist/runtime/windows-amd64/libcardio.dll +0 -0
  25. package/dist/runtime/windows-amd64/libmuon-ui.dll +0 -0
  26. package/dist/runtime/windows-amd64/muon-core.exe +0 -0
  27. package/dist/runtime/windows-i686/libcardio.dll +0 -0
  28. package/dist/runtime/windows-i686/libmuon-ui.dll +0 -0
  29. package/dist/runtime/windows-i686/muon-core.exe +0 -0
  30. package/dist/{vite-internals-Dha0jYI8.cjs → vite-internals-6HS7FULY.cjs} +360 -154
  31. package/dist/vite-internals-6HS7FULY.cjs.map +1 -0
  32. package/dist/vite.cjs +37 -17
  33. package/dist/vite.cjs.map +1 -1
  34. package/dist/vite.mjs +336 -166
  35. package/dist/vite.mjs.map +1 -1
  36. package/muon-virtual-modules.d.ts +90 -0
  37. package/muon.d.ts +6 -86
  38. package/package.json +10 -8
  39. package/vite.d.ts +53 -0
  40. package/dist/vite-internals-Dha0jYI8.cjs.map +0 -1
package/dist/cli.cjs CHANGED
@@ -1,14 +1,14 @@
1
1
  #!/usr/bin/env node
2
2
  /*!
3
3
  * name: muon-ui
4
- * version: 0.11.0
4
+ * version: 0.13.0
5
5
  * description: A multi-platform GUI application framework that uses CEF as its backend
6
6
  * author: Kouji Matsui (@kekyo@mi.kekyo.net)
7
7
  * license: MIT
8
8
  * repository.url: https://github.com/kekyo/muon-ui.git
9
- * git.commit.hash: db70f7643ac9fb1f61ab79f1de55c3dd8686de8d
9
+ * git.commit.hash: 8eedbe10e5a89eef8f7061d528518353bd09083e
10
10
  */
11
- const require_vite_internals = require("./vite-internals-Dha0jYI8.cjs");
11
+ const require_vite_internals = require("./vite-internals-6HS7FULY.cjs");
12
12
  let commander = require("commander");
13
13
  let node_child_process = require("node:child_process");
14
14
  let node_fs = require("node:fs");
@@ -76,6 +76,62 @@ var loadViteMuonOptions = async (cwd) => {
76
76
  pluginOptions: muonPlugins[0]
77
77
  };
78
78
  };
79
+ var getRuntimePluginConfigFromViteBuild = async (root) => {
80
+ const vite = await import("vite");
81
+ let resolvedRuntimeStates = [];
82
+ const inspector = {
83
+ name: "muon-run-vite-build-inspector",
84
+ enforce: "post",
85
+ configResolved: (config) => {
86
+ const runtimeStates = config.plugins.map((plugin) => require_vite_internals.getMuonVitePluginRuntimeState(plugin)).filter((runtimeState) => runtimeState !== void 0);
87
+ if (runtimeStates.length > 1) throw new Error("Multiple muon() plugin definitions were found in vite.config.*.");
88
+ resolvedRuntimeStates = runtimeStates;
89
+ }
90
+ };
91
+ const previous = process.env[require_vite_internals.muonBuildSequenceSuppressViteBuildEnvironmentKey];
92
+ process.env[require_vite_internals.muonBuildSequenceSuppressViteBuildEnvironmentKey] = "1";
93
+ try {
94
+ await vite.build({
95
+ root,
96
+ logLevel: "silent",
97
+ plugins: [inspector]
98
+ });
99
+ } finally {
100
+ if (previous === void 0) delete process.env[require_vite_internals.muonBuildSequenceSuppressViteBuildEnvironmentKey];
101
+ else process.env[require_vite_internals.muonBuildSequenceSuppressViteBuildEnvironmentKey] = previous;
102
+ }
103
+ const runtimePluginConfig = resolvedRuntimeStates[0]?.getRuntimePluginConfig();
104
+ if (runtimePluginConfig === void 0) throw new Error("muon Vite plugin runtime config was not resolved.");
105
+ return runtimePluginConfig;
106
+ };
107
+ var copyViteOutputAsRunAssets = async (project, assetSourcePath, assetPrefix) => {
108
+ if (project.viteOutputDirectory === void 0) throw new Error("Vite output directory could not be resolved.");
109
+ await assertDevelopmentAssetDirectory(project.viteOutputDirectory);
110
+ const destinationPath = (0, node_path.join)(assetSourcePath, ...assetPrefix.split("/"));
111
+ await (0, node_fs_promises.mkdir)((0, node_path.dirname)(destinationPath), { recursive: true });
112
+ await (0, node_fs_promises.cp)(project.viteOutputDirectory, destinationPath, { recursive: true });
113
+ };
114
+ var prepareViteRunAssets = async (cwd) => {
115
+ const project = await require_vite_internals.loadMuonBuildSequenceProject(cwd);
116
+ if (project.pluginOptions === void 0) return;
117
+ const buildOptions = require_vite_internals.resolveMuonViteBuildOptions(project.pluginOptions);
118
+ const packagedAssetOptions = require_vite_internals.createVitePackagedAssetOptions(project.viteBase ?? "/");
119
+ const assetSourcePath = (0, node_path.join)(project.root, ".muon", "run", "assets");
120
+ await (0, node_fs_promises.rm)(assetSourcePath, {
121
+ recursive: true,
122
+ force: true
123
+ });
124
+ const runtimePluginConfig = await getRuntimePluginConfigFromViteBuild(project.viteBuildRoot);
125
+ await copyViteOutputAsRunAssets(project, assetSourcePath, packagedAssetOptions.assetPrefix);
126
+ return {
127
+ root: project.root,
128
+ pluginOptions: project.pluginOptions,
129
+ configPath: buildOptions.configPath,
130
+ assetSourcePath,
131
+ browserStartPage: packagedAssetOptions.browserStartPage,
132
+ runtimePluginConfig
133
+ };
134
+ };
79
135
  var resolveProjectConfigPath = async (root, configPath) => {
80
136
  if (configPath !== void 0) {
81
137
  const resolvedPath = resolveFromRoot(root, configPath);
@@ -125,6 +181,11 @@ var readConfigAssetSourcePath = (config) => {
125
181
  if (sourcePath.trim().length === 0) throw new Error("muon config asset.sourcePath must not be empty.");
126
182
  return sourcePath;
127
183
  };
184
+ var hasConfigBrowserStartPage = (config) => {
185
+ if (config === void 0) return false;
186
+ const browser = config.browser;
187
+ return isJsonObject$1(browser) && browser.startPage !== void 0;
188
+ };
128
189
  var assertDevelopmentAssetDirectory = async (assetSourcePath) => {
129
190
  if (await directoryExists(assetSourcePath)) return;
130
191
  try {
@@ -155,50 +216,48 @@ var resolveAssetSource = async (root, assetSourcePath, projectConfig) => {
155
216
  overrideAssetSourcePath: defaultAssetSourcePath
156
217
  };
157
218
  };
158
- var createMuonDevOverrideConfig = (assetSourcePath, enableDebugger) => ({
159
- ...assetSourcePath === void 0 ? {} : { asset: { sourcePath: assetSourcePath } },
160
- ...enableDebugger ? {
161
- cdp: { enable: true },
162
- browser: { keybind: {
219
+ var createMuonDevOverrideConfig = (assetSourcePath, enableDebugger, browserStartPage, runtimePluginConfig) => {
220
+ const browser = browserStartPage === void 0 && !enableDebugger ? void 0 : {
221
+ ...browserStartPage === void 0 ? {} : { startPage: browserStartPage },
222
+ ...enableDebugger ? { keybind: {
163
223
  devtools: "f12",
164
224
  recycle: "ctrl+f12"
165
- } }
166
- } : {}
167
- });
225
+ } } : {}
226
+ };
227
+ return {
228
+ ...assetSourcePath === void 0 ? {} : { asset: { sourcePath: assetSourcePath } },
229
+ ...enableDebugger ? { cdp: { enable: true } } : {},
230
+ ...browser === void 0 ? {} : { browser },
231
+ ...runtimePluginConfig === void 0 ? {} : { plugin: runtimePluginConfig }
232
+ };
233
+ };
168
234
  var writeMuonDevOverrideConfig = async (overrideConfigPath, overrideConfig) => {
169
235
  await (0, node_fs_promises.mkdir)((0, node_path.dirname)(overrideConfigPath), { recursive: true });
170
236
  await (0, node_fs_promises.writeFile)(overrideConfigPath, `${JSON.stringify(overrideConfig, null, 2)}\n`);
171
237
  };
172
238
  var runMuonExecutable = async (muonExecutablePath, configPaths, environment) => {
173
- const args = configPaths.flatMap((configPath) => ["-c", configPath]);
174
- let exitCode = 0;
175
- do {
176
- const child = (0, node_child_process.spawn)(muonExecutablePath, args, {
177
- cwd: (0, node_path.dirname)(muonExecutablePath),
178
- env: environment,
179
- stdio: [
180
- "ignore",
181
- "inherit",
182
- "inherit"
183
- ]
184
- });
185
- exitCode = await new Promise((resolvePromise, reject) => {
186
- child.once("error", reject);
187
- child.once("close", (code) => {
188
- resolvePromise(code ?? 1);
189
- });
239
+ const child = (0, node_child_process.spawn)(muonExecutablePath, configPaths.flatMap((configPath) => ["-c", configPath]), {
240
+ cwd: (0, node_path.dirname)(muonExecutablePath),
241
+ env: environment,
242
+ stdio: [
243
+ "ignore",
244
+ "inherit",
245
+ "inherit"
246
+ ]
247
+ });
248
+ return await new Promise((resolvePromise, reject) => {
249
+ child.once("error", reject);
250
+ child.once("close", (code) => {
251
+ resolvePromise(code ?? 1);
190
252
  });
191
- } while (exitCode === muonRecycleExitCode);
192
- return exitCode;
253
+ });
193
254
  };
194
- /**
195
- * Launches muon directly against local development assets.
196
- *
197
- * @param options Development startup options.
198
- * @returns Development startup result after the muon process exits.
199
- */
200
- var runMuonDev = async (options = {}) => {
201
- const loadedViteOptions = await loadViteMuonOptions((0, node_path.resolve)(options.root ?? process.cwd()));
255
+ var runMuonDevOnce = async (options, cwd) => {
256
+ const preparedViteAssets = options.assetSourcePath === void 0 ? await prepareViteRunAssets(cwd) : void 0;
257
+ const loadedViteOptions = preparedViteAssets === void 0 ? await loadViteMuonOptions(cwd) : {
258
+ root: preparedViteAssets.root,
259
+ pluginOptions: preparedViteAssets.pluginOptions
260
+ };
202
261
  const root = loadedViteOptions.root;
203
262
  const pluginOptions = loadedViteOptions.pluginOptions;
204
263
  const platform = options.platform ?? process.platform;
@@ -213,8 +272,12 @@ var runMuonDev = async (options = {}) => {
213
272
  const cefPath = options.cefPath !== void 0 ? resolveFromRoot(root, options.cefPath) : pluginOptions?.cefPath === void 0 ? void 0 : resolveFromRoot(root, pluginOptions.cefPath);
214
273
  const stagePath = options.stagePath !== void 0 ? resolveFromRoot(root, options.stagePath) : pluginOptions?.stagePath === void 0 ? (0, node_path.resolve)(root, ".muon", target) : resolveFromRoot(root, pluginOptions.stagePath);
215
274
  const enableDebugger = options.enableDebugger ?? pluginOptions?.enableDebugger ?? true;
216
- const projectConfig = await resolveProjectConfig(root, options.configPath);
217
- const asset = await resolveAssetSource(root, options.assetSourcePath, projectConfig);
275
+ const projectConfig = await resolveProjectConfig(root, options.configPath ?? preparedViteAssets?.configPath);
276
+ const asset = preparedViteAssets === void 0 ? await resolveAssetSource(root, options.assetSourcePath, projectConfig) : {
277
+ assetSourcePath: preparedViteAssets.assetSourcePath,
278
+ overrideAssetSourcePath: preparedViteAssets.assetSourcePath
279
+ };
280
+ const browserStartPage = preparedViteAssets?.browserStartPage !== void 0 && !hasConfigBrowserStartPage(projectConfig.config) ? preparedViteAssets.browserStartPage : void 0;
218
281
  const overrideConfigPath = (0, node_path.join)(root, ".muon", "run", "muon.run.json");
219
282
  await require_vite_internals.ensureMuonGitignoreEntry(root);
220
283
  const preparedRuntime = await require_vite_internals.runMuonPrepare({
@@ -230,7 +293,7 @@ var runMuonDev = async (options = {}) => {
230
293
  cwd: root
231
294
  });
232
295
  if (preparedRuntime.stagePath === void 0) throw new Error("muon-builder did not return a staged runtime path.");
233
- await writeMuonDevOverrideConfig(overrideConfigPath, createMuonDevOverrideConfig(asset.overrideAssetSourcePath, enableDebugger));
296
+ await writeMuonDevOverrideConfig(overrideConfigPath, createMuonDevOverrideConfig(asset.overrideAssetSourcePath, enableDebugger, browserStartPage, preparedViteAssets?.runtimePluginConfig));
234
297
  const muonExecutablePath = require_vite_internals.getMuonExecutablePath(preparedRuntime.stagePath, platform);
235
298
  const exitCode = await runMuonExecutable(muonExecutablePath, [...projectConfig.configPath === void 0 ? [] : [projectConfig.configPath], overrideConfigPath], environment);
236
299
  return {
@@ -246,6 +309,20 @@ var runMuonDev = async (options = {}) => {
246
309
  exitCode
247
310
  };
248
311
  };
312
+ /**
313
+ * Launches muon directly against local development assets.
314
+ *
315
+ * @param options Development startup options.
316
+ * @returns Development startup result after the muon process exits.
317
+ */
318
+ var runMuonDev = async (options = {}) => {
319
+ const cwd = (0, node_path.resolve)(options.root ?? process.cwd());
320
+ let result;
321
+ do
322
+ result = await runMuonDevOnce(options, cwd);
323
+ while (result.exitCode === muonRecycleExitCode);
324
+ return result;
325
+ };
249
326
  //#endregion
250
327
  //#region src/pack.ts
251
328
  var AdmZip = __resolveDefaultExport(adm_zip.default, false);
@@ -280,7 +357,41 @@ var defaultPackageBuildDirectory = ".muon/pack";
280
357
  var systemRuntimeRoot = "/var/lib/muon/apps";
281
358
  var systemCefCacheRoot = "/var/cache/muon/cef";
282
359
  var runtimeHelperExecutableName = "muon-runtime-helper";
283
- var debGtk3RuntimeDependency = "libgtk-3-0t64 | libgtk-3-0";
360
+ var portableProfilePath = "profile";
361
+ var portableInstallMetadata = {
362
+ type: "portable",
363
+ runtimeMode: "in-place"
364
+ };
365
+ var debRuntimeDependencies = [
366
+ "libc6",
367
+ "libgcc-s1",
368
+ "libstdc++6",
369
+ "libffi8",
370
+ "libexpat1",
371
+ "libdbus-1-3",
372
+ "libglib2.0-0t64 | libglib2.0-0",
373
+ "libgtk-3-0t64 | libgtk-3-0",
374
+ "libatk-bridge2.0-0t64 | libatk-bridge2.0-0",
375
+ "libatk1.0-0t64 | libatk1.0-0",
376
+ "libatspi2.0-0t64 | libatspi2.0-0",
377
+ "libcups2t64 | libcups2",
378
+ "libnspr4",
379
+ "libnss3",
380
+ "libgbm1",
381
+ "libasound2t64 | libasound2",
382
+ "libudev1",
383
+ "libx11-6",
384
+ "libxcb1",
385
+ "libxcomposite1",
386
+ "libxdamage1",
387
+ "libxext6",
388
+ "libxfixes3",
389
+ "libxi6",
390
+ "libxkbcommon0",
391
+ "libxrandr2",
392
+ "libcairo2",
393
+ "libpango-1.0-0"
394
+ ];
284
395
  var isJsonObject = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
285
396
  var readJsonObjectFile = async (path) => {
286
397
  const parsed = (0, import_dist.parse)(await (0, node_fs_promises.readFile)(path, "utf8"));
@@ -369,6 +480,7 @@ var packTypeSupportsTarget = (type, target) => {
369
480
  const descriptor = require_vite_internals.getMuonTargetDescriptor(target);
370
481
  return type === "zip" && descriptor.os === "windows" || type === "tar.gz" && descriptor.os === "linux" || type === "deb" && descriptor.os === "linux" || type === "nsis" && descriptor.os === "windows";
371
482
  };
483
+ var isPortablePackType = (type) => type === "zip" || type === "tar.gz";
372
484
  var createPackTargetPlan = (types, targets) => {
373
485
  const plan = targets.map((target) => ({
374
486
  target,
@@ -404,6 +516,17 @@ var runTool = async (executable, args, cwd, environment) => {
404
516
  });
405
517
  if (exitCode !== 0) throw new Error(`${executable} failed with exit code ${exitCode}: ${stderr.trim()}`);
406
518
  };
519
+ var isUnavailableToolError = (error, executable) => {
520
+ if (!(error instanceof Error)) return false;
521
+ const nodeError = error;
522
+ return nodeError.code === "ENOENT" && (nodeError.syscall === `spawn ${executable}` || nodeError.path === executable);
523
+ };
524
+ var reportSkippedUnavailableTool = (progress, executable, type, target) => {
525
+ progress?.({
526
+ phase: "pack",
527
+ status: `Warning: ${executable} is not available; skipping ${type} package for ${target}.`
528
+ });
529
+ };
407
530
  var statOrUndefined = async (path) => {
408
531
  try {
409
532
  return await (0, node_fs_promises.stat)(path);
@@ -427,9 +550,10 @@ var addDirectoryToZip = async (zip, directory, entryRoot) => {
427
550
  };
428
551
  await walk(directory);
429
552
  };
553
+ var getPortableArchiveEntryRoot = (target, metadata) => `${metadata.packageName}/${target.target}`;
430
554
  var packageZip = async (target, metadata, artifactsRoot) => {
431
555
  const zip = new AdmZip();
432
- await addDirectoryToZip(zip, target.outputPath, target.distributionDirectoryName);
556
+ await addDirectoryToZip(zip, target.outputPath, getPortableArchiveEntryRoot(target, metadata));
433
557
  const outputPath = (0, node_path.join)(artifactsRoot, `${metadata.packageName}-${metadata.version}-${target.target}.zip`);
434
558
  await (0, node_fs_promises.mkdir)((0, node_path.dirname)(outputPath), { recursive: true });
435
559
  await (0, node_fs_promises.writeFile)(outputPath, zip.toBuffer());
@@ -459,13 +583,16 @@ var createTarGzEntryGenerator = async function* (directory, entryRoot) {
459
583
  var packageTarGz = async (target, metadata, artifactsRoot) => {
460
584
  const outputPath = (0, node_path.join)(artifactsRoot, `${metadata.packageName}-${metadata.version}-${target.target}.tar.gz`);
461
585
  await (0, node_fs_promises.mkdir)((0, node_path.dirname)(outputPath), { recursive: true });
462
- await (0, tar_vern.storeReaderToFile)((0, tar_vern.createTarPacker)(createTarGzEntryGenerator(target.outputPath, target.distributionDirectoryName), "gzip"), outputPath);
586
+ await (0, tar_vern.storeReaderToFile)((0, tar_vern.createTarPacker)(createTarGzEntryGenerator(target.outputPath, getPortableArchiveEntryRoot(target, metadata)), "gzip"), outputPath);
463
587
  return {
464
588
  type: "tar.gz",
465
589
  target: target.target,
466
590
  path: outputPath
467
591
  };
468
592
  };
593
+ var writePortableInstallMetadata = async (target) => {
594
+ await (0, node_fs_promises.writeFile)((0, node_path.join)(target.outputPath, "muon-install.json"), `${JSON.stringify(portableInstallMetadata, void 0, 2)}\n`);
595
+ };
469
596
  var packageDeb = async (root, target, metadata, artifactsRoot, packageBuildRoot, environment, linuxSandbox, progress) => {
470
597
  const descriptor = require_vite_internals.getMuonTargetDescriptor(target.target);
471
598
  if (descriptor.os !== "linux") throw new Error(`Unsupported deb target: ${target.target}`);
@@ -523,7 +650,7 @@ var packageDeb = async (root, target, metadata, artifactsRoot, packageBuildRoot,
523
650
  `Version: ${metadata.version}`,
524
651
  `Architecture: ${architecture}`,
525
652
  `Maintainer: ${metadata.author}`,
526
- `Depends: ${debGtk3RuntimeDependency}`,
653
+ `Depends: ${debRuntimeDependencies.join(", ")}`,
527
654
  `Description: ${metadata.description}`,
528
655
  ""
529
656
  ].join("\n"));
@@ -562,12 +689,20 @@ var packageDeb = async (root, target, metadata, artifactsRoot, packageBuildRoot,
562
689
  phase: "pack",
563
690
  status: "Running dpkg-deb"
564
691
  });
565
- await runTool("dpkg-deb", [
566
- "--root-owner-group",
567
- "--build",
568
- packageRoot,
569
- outputPath
570
- ], root, environment);
692
+ try {
693
+ await runTool("dpkg-deb", [
694
+ "--root-owner-group",
695
+ "--build",
696
+ packageRoot,
697
+ outputPath
698
+ ], root, environment);
699
+ } catch (error) {
700
+ if (isUnavailableToolError(error, "dpkg-deb")) {
701
+ reportSkippedUnavailableTool(progress, "dpkg-deb", "deb", target.target);
702
+ return;
703
+ }
704
+ throw error;
705
+ }
571
706
  return {
572
707
  type: "deb",
573
708
  target: target.target,
@@ -577,7 +712,7 @@ var packageDeb = async (root, target, metadata, artifactsRoot, packageBuildRoot,
577
712
  var escapeNsis = (value) => value.replaceAll("\\", "\\\\").replaceAll("\"", "$\\\"");
578
713
  var nsisUninstallRegistryRoot = "Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall";
579
714
  var createNsisUninstallRegistryKey = (appId) => `${nsisUninstallRegistryRoot}\\${appId}`;
580
- var packageNsis = async (root, target, metadata, windowsResource, artifactsRoot, packageBuildRoot, environment, progress) => {
715
+ var packageNsis = async (root, target, metadata, windowsResource, windowsCodeSigning, artifactsRoot, packageBuildRoot, environment, progress) => {
581
716
  const descriptor = require_vite_internals.getMuonTargetDescriptor(target.target);
582
717
  if (descriptor.os !== "windows") throw new Error(`Unsupported nsis target: ${target.target}`);
583
718
  const scriptPath = (0, node_path.join)(packageBuildRoot, "nsis", `${metadata.packageName}-${target.target}.nsi`);
@@ -590,10 +725,17 @@ var packageNsis = async (root, target, metadata, windowsResource, artifactsRoot,
590
725
  await (0, node_fs_promises.mkdir)((0, node_path.dirname)(outputPath), { recursive: true });
591
726
  const iconPath = (0, node_path.join)((0, node_path.dirname)(scriptPath), `${metadata.packageName}-${target.target}.ico`);
592
727
  await require_vite_internals.createWindowsIconFromPngFile(windowsResource.iconPath, iconPath);
728
+ const codeSigningDirectives = await createNsisCodeSigningDirectives({
729
+ root,
730
+ scriptPath,
731
+ target: target.target,
732
+ codeSigning: windowsCodeSigning
733
+ });
593
734
  await (0, node_fs_promises.writeFile)(scriptPath, [
594
735
  "Unicode true",
595
736
  `Name "${escapeNsis(nsisDisplayName)}"`,
596
737
  `OutFile "${escapeNsis(outputPath)}"`,
738
+ ...codeSigningDirectives,
597
739
  `InstallDir "$LOCALAPPDATA\\Programs\\${escapeNsis(nsisInstallDirectoryName)}"`,
598
740
  "RequestExecutionLevel user",
599
741
  "ShowInstDetails nevershow",
@@ -634,7 +776,15 @@ var packageNsis = async (root, target, metadata, windowsResource, artifactsRoot,
634
776
  phase: "pack",
635
777
  status: "Running makensis"
636
778
  });
637
- await runTool("makensis", [scriptPath], root, environment);
779
+ try {
780
+ await runTool("makensis", [scriptPath], root, environment);
781
+ } catch (error) {
782
+ if (isUnavailableToolError(error, "makensis")) {
783
+ reportSkippedUnavailableTool(progress, "makensis", "nsis", target.target);
784
+ return;
785
+ }
786
+ throw error;
787
+ }
638
788
  if (await statOrUndefined(outputPath) === void 0) throw new Error(`makensis did not create installer: ${outputPath}`);
639
789
  return {
640
790
  type: "nsis",
@@ -656,6 +806,51 @@ var createNsisResourceDirectives = (resource, iconPath) => {
656
806
  if (resource.copyright !== void 0) lines.push(`VIAddVersionKey /LANG=${resource.language} "LegalCopyright" "${escapeNsis(resource.copyright)}"`);
657
807
  return lines;
658
808
  };
809
+ var createNsisCodeSigningWrapperScript = (configPath) => [
810
+ "#!/usr/bin/env node",
811
+ "const { readFileSync } = require('node:fs');",
812
+ "const { spawnSync } = require('node:child_process');",
813
+ `const config = JSON.parse(readFileSync(${JSON.stringify(configPath)}, 'utf8'));`,
814
+ "const [kind, target, path] = process.argv.slice(2);",
815
+ "const args = config.args.map((arg) => arg.replaceAll('{path}', path).replaceAll('{target}', target).replaceAll('{kind}', kind));",
816
+ "const result = spawnSync(config.command, args, { cwd: config.cwd, env: process.env, stdio: 'inherit' });",
817
+ "if (result.error) {",
818
+ " console.error(result.error.message);",
819
+ " process.exit(1);",
820
+ "}",
821
+ "process.exit(result.status ?? 1);",
822
+ ""
823
+ ].join("\n");
824
+ var createNsisCodeSigningDirectiveCommand = (input) => `"${escapeNsis(process.execPath)}" "${escapeNsis(input.wrapperPath)}" "${input.kind}" "${input.target}" "%1"`;
825
+ var createNsisCodeSigningDirectives = async (input) => {
826
+ const codeSigning = input.codeSigning;
827
+ if (codeSigning === void 0) return [];
828
+ const signsInstaller = require_vite_internals.includesWindowsCodeSigningTarget(codeSigning, "nsisInstaller");
829
+ const signsUninstaller = require_vite_internals.includesWindowsCodeSigningTarget(codeSigning, "nsisUninstaller");
830
+ if (!signsInstaller && !signsUninstaller) return [];
831
+ const scriptDirectory = (0, node_path.dirname)(input.scriptPath);
832
+ const configPath = (0, node_path.join)(scriptDirectory, `${(0, node_path.basename)(input.scriptPath)}.sign.json`);
833
+ const wrapperPath = (0, node_path.join)(scriptDirectory, `${(0, node_path.basename)(input.scriptPath)}.sign.cjs`);
834
+ await (0, node_fs_promises.writeFile)(configPath, `${JSON.stringify({
835
+ command: codeSigning.command,
836
+ args: codeSigning.args,
837
+ cwd: input.root
838
+ }, void 0, 2)}\n`);
839
+ await (0, node_fs_promises.writeFile)(wrapperPath, createNsisCodeSigningWrapperScript(configPath));
840
+ await (0, node_fs_promises.chmod)(wrapperPath, 493);
841
+ const lines = [];
842
+ if (signsInstaller) lines.push(`!finalize '${createNsisCodeSigningDirectiveCommand({
843
+ wrapperPath,
844
+ kind: "nsisInstaller",
845
+ target: input.target
846
+ })}' = 0`);
847
+ if (signsUninstaller) lines.push(`!uninstfinalize '${createNsisCodeSigningDirectiveCommand({
848
+ wrapperPath,
849
+ kind: "nsisUninstaller",
850
+ target: input.target
851
+ })}' = 0`);
852
+ return lines;
853
+ };
659
854
  var reapplyPackWindowsResources = async (targets, resource, root, environment) => {
660
855
  for (const target of targets) {
661
856
  const descriptor = require_vite_internals.getMuonTargetDescriptor(target.target);
@@ -675,6 +870,86 @@ var reapplyPackWindowsResources = async (targets, resource, root, environment) =
675
870
  }
676
871
  }
677
872
  };
873
+ var signPackWindowsExecutables = async (targets, codeSigning, root, environment, progress) => {
874
+ if (codeSigning === void 0) return;
875
+ progress?.({
876
+ phase: "pack",
877
+ status: "Signing Windows executables"
878
+ });
879
+ for (const target of targets) {
880
+ const descriptor = require_vite_internals.getMuonTargetDescriptor(target.target);
881
+ if (descriptor.os !== "windows") continue;
882
+ await require_vite_internals.signWindowsExecutable({
883
+ codeSigning,
884
+ kind: "runtime",
885
+ target: target.target,
886
+ path: (0, node_path.join)(target.outputPath, descriptor.runtimeExecutableName),
887
+ cwd: root,
888
+ environment
889
+ });
890
+ await require_vite_internals.signWindowsExecutable({
891
+ codeSigning,
892
+ kind: "launcher",
893
+ target: target.target,
894
+ path: target.launcherPath,
895
+ cwd: root,
896
+ environment
897
+ });
898
+ }
899
+ };
900
+ var createPortableBuildOptions = (input) => {
901
+ const buildOptions = {
902
+ root: input.project.root,
903
+ targets: input.targets,
904
+ allTargets: false,
905
+ outputRoot: input.outputRoot
906
+ };
907
+ if (input.project.pluginOptions !== void 0) {
908
+ if (input.project.viteOutputDirectory === void 0) throw new Error("Vite output directory could not be resolved.");
909
+ Object.assign(buildOptions, input.pluginBuildOptions);
910
+ const packagedAssetOptions = require_vite_internals.createVitePackagedAssetOptions(input.project.viteBase ?? "/");
911
+ buildOptions.assetSourcePath = input.project.viteOutputDirectory;
912
+ buildOptions.assetPrefix = packagedAssetOptions.assetPrefix;
913
+ if (packagedAssetOptions.browserStartPage !== void 0) buildOptions.browserStartPage = packagedAssetOptions.browserStartPage;
914
+ }
915
+ buildOptions.targets = input.targets;
916
+ buildOptions.allTargets = false;
917
+ buildOptions.outputRoot = input.outputRoot;
918
+ if (input.options.configPath !== void 0) buildOptions.configPath = input.options.configPath;
919
+ if (input.iconPath !== void 0) buildOptions.iconPath = input.iconPath;
920
+ if (input.options.appName !== void 0) buildOptions.appName = input.options.appName;
921
+ if (input.options.appId !== void 0) buildOptions.appId = input.options.appId;
922
+ if (input.options.packageDirectory !== void 0) buildOptions.packageDirectory = input.options.packageDirectory;
923
+ if (input.windowsResourceOptions !== void 0) buildOptions.windowsResource = input.windowsResourceOptions;
924
+ if (input.windowsCodeSigningOptions !== void 0) buildOptions.windowsCodeSigning = input.windowsCodeSigningOptions;
925
+ if (input.linuxDesktopOptions !== void 0) buildOptions.linuxDesktop = input.linuxDesktopOptions;
926
+ if (input.progress !== void 0) buildOptions.progress = input.progress;
927
+ buildOptions.environment = input.environment;
928
+ buildOptions.browserProfilePathOverride = portableProfilePath;
929
+ return buildOptions;
930
+ };
931
+ var buildPortableTargets = async (input) => {
932
+ if (input.targets.length === 0) return /* @__PURE__ */ new Map();
933
+ input.progress?.({
934
+ phase: "pack",
935
+ status: "Building portable distributions"
936
+ });
937
+ const build = await require_vite_internals.buildMuonApp(createPortableBuildOptions({
938
+ project: input.project,
939
+ pluginBuildOptions: input.pluginBuildOptions,
940
+ options: input.options,
941
+ outputRoot: (0, node_path.join)(input.packageBuildRoot, "portable-build"),
942
+ targets: input.targets,
943
+ windowsResourceOptions: input.windowsResourceOptions,
944
+ windowsCodeSigningOptions: input.windowsCodeSigningOptions,
945
+ linuxDesktopOptions: input.linuxDesktopOptions,
946
+ iconPath: input.iconPath,
947
+ environment: input.environment,
948
+ progress: input.progress
949
+ }));
950
+ await Promise.all(build.targets.map(writePortableInstallMetadata));
951
+ return new Map(build.targets.map((target) => [target.target, target]));
952
+ };
678
953
  /**
679
954
  * Runs the muon build sequence and creates redistributable packages.
680
955
  *
@@ -703,6 +978,7 @@ var packMuonApp = async (options) => {
703
978
  includeRuntimeHelper: linuxSandbox === "setuid"
704
979
  };
705
980
  const windowsResourceOptions = require_vite_internals.mergeMuonWindowsResourceOptions(options.windowsResource, pluginBuildOptions.windowsResource);
981
+ const windowsCodeSigningOptions = options.windowsCodeSigning !== void 0 ? options.windowsCodeSigning : pluginBuildOptions.windowsCodeSigning;
706
982
  const linuxDesktopOptions = require_vite_internals.mergeMuonLinuxDesktopOptions(options.linuxDesktop, pluginBuildOptions.linuxDesktop);
707
983
  const iconPath = options.iconPath ?? pluginBuildOptions.iconPath;
708
984
  if (options.configPath !== void 0) buildOptions.configPath = options.configPath;
@@ -711,8 +987,10 @@ var packMuonApp = async (options) => {
711
987
  if (options.appId !== void 0) buildOptions.appId = options.appId;
712
988
  if (options.packageDirectory !== void 0) buildOptions.packageDirectory = options.packageDirectory;
713
989
  if (windowsResourceOptions !== void 0) buildOptions.windowsResource = windowsResourceOptions;
990
+ if (windowsCodeSigningOptions !== void 0) buildOptions.windowsCodeSigning = windowsCodeSigningOptions;
714
991
  if (linuxDesktopOptions !== void 0) buildOptions.linuxDesktop = linuxDesktopOptions;
715
992
  if (progress !== void 0) buildOptions.progress = progress;
993
+ buildOptions.environment = environment;
716
994
  const windowsResourceConfig = await require_vite_internals.readMuonConfigForWindowsResource(root, options.configPath);
717
995
  const windowsResource = await require_vite_internals.resolveMuonWindowsResource({
718
996
  root,
@@ -730,13 +1008,21 @@ var packMuonApp = async (options) => {
730
1008
  copyright: void 0
731
1009
  }
732
1010
  });
1011
+ const windowsCodeSigning = require_vite_internals.resolveMuonWindowsCodeSigning({
1012
+ muonConfig: windowsResourceConfig.config,
1013
+ options: windowsCodeSigningOptions
1014
+ });
733
1015
  progress?.({
734
1016
  phase: "pack",
735
1017
  status: "Building distributions"
736
1018
  });
737
1019
  const build = await require_vite_internals.runMuonBuildSequence(buildOptions, project);
738
- if (options.packageVersion !== void 0) await reapplyPackWindowsResources(build.targets, windowsResource, root, environment);
1020
+ if (options.packageVersion !== void 0) {
1021
+ await reapplyPackWindowsResources(build.targets, windowsResource, root, environment);
1022
+ await signPackWindowsExecutables(build.targets, windowsCodeSigning, root, environment, progress);
1023
+ }
739
1024
  const typesByTarget = new Map(targetPlan.map((entry) => [entry.target, entry.types]));
1025
+ const portableTargets = targetPlan.filter((entry) => entry.types.some(isPortablePackType)).map((entry) => entry.target);
740
1026
  await (0, node_fs_promises.rm)(packageBuildRoot, {
741
1027
  recursive: true,
742
1028
  force: true
@@ -750,6 +1036,23 @@ var packMuonApp = async (options) => {
750
1036
  force: true
751
1037
  });
752
1038
  await (0, node_fs_promises.mkdir)(artifactsRoot, { recursive: true });
1039
+ const portableTargetsByTarget = await buildPortableTargets({
1040
+ project,
1041
+ pluginBuildOptions,
1042
+ options,
1043
+ packageBuildRoot,
1044
+ targets: portableTargets,
1045
+ windowsResourceOptions,
1046
+ windowsCodeSigningOptions,
1047
+ linuxDesktopOptions,
1048
+ iconPath,
1049
+ environment,
1050
+ progress
1051
+ });
1052
+ if (options.packageVersion !== void 0) {
1053
+ await reapplyPackWindowsResources([...portableTargetsByTarget.values()], windowsResource, root, environment);
1054
+ await signPackWindowsExecutables([...portableTargetsByTarget.values()], windowsCodeSigning, root, environment, progress);
1055
+ }
753
1056
  const artifacts = [];
754
1057
  const totalArtifacts = targetPlan.reduce((sum, entry) => sum + entry.types.length, 0);
755
1058
  let artifactIndex = 0;
@@ -760,10 +1063,17 @@ var packMuonApp = async (options) => {
760
1063
  status: `Packaging ${type} ${target.target} (${artifactIndex}/${totalArtifacts})`
761
1064
  });
762
1065
  let artifact;
763
- if (type === "zip") artifact = await packageZip(target, metadata, artifactsRoot);
764
- else if (type === "tar.gz") artifact = await packageTarGz(target, metadata, artifactsRoot);
765
- else if (type === "deb") artifact = await packageDeb(root, target, metadata, artifactsRoot, packageBuildRoot, environment, linuxSandbox, progress);
766
- else artifact = await packageNsis(root, target, metadata, windowsResource, artifactsRoot, packageBuildRoot, environment, progress);
1066
+ if (type === "zip") {
1067
+ const portableTarget = portableTargetsByTarget.get(target.target);
1068
+ if (portableTarget === void 0) throw new Error(`Portable target was not built: ${target.target}`);
1069
+ artifact = await packageZip(portableTarget, metadata, artifactsRoot);
1070
+ } else if (type === "tar.gz") {
1071
+ const portableTarget = portableTargetsByTarget.get(target.target);
1072
+ if (portableTarget === void 0) throw new Error(`Portable target was not built: ${target.target}`);
1073
+ artifact = await packageTarGz(portableTarget, metadata, artifactsRoot);
1074
+ } else if (type === "deb") artifact = await packageDeb(root, target, metadata, artifactsRoot, packageBuildRoot, environment, linuxSandbox, progress);
1075
+ else artifact = await packageNsis(root, target, metadata, windowsResource, windowsCodeSigning, artifactsRoot, packageBuildRoot, environment, progress);
1076
+ if (artifact === void 0) continue;
767
1077
  artifacts.push(artifact);
768
1078
  progress?.({
769
1079
  phase: "pack",
@@ -783,8 +1093,8 @@ var packMuonApp = async (options) => {
783
1093
  };
784
1094
  //#endregion
785
1095
  //#region src/generated/packageMetadata.ts
786
- var version = "0.11.0";
787
- var git_commit_hash = "db70f7643ac9fb1f61ab79f1de55c3dd8686de8d";
1096
+ var version = "0.13.0";
1097
+ var git_commit_hash = "8eedbe10e5a89eef8f7061d528518353bd09083e";
788
1098
  //#endregion
789
1099
  //#region src/cli.ts
790
1100
  var readTargetValues = (value) => {
@@ -796,6 +1106,12 @@ var appendTargetValues = (value, previous) => {
796
1106
  var appendPackTypeValues = (value, previous) => {
797
1107
  return [...previous ?? [], ...readTargetValues(value)];
798
1108
  };
1109
+ var appendWindowsSignArgValue = (value, previous) => {
1110
+ return [...previous ?? [], value];
1111
+ };
1112
+ var appendWindowsSignTargetValues = (value, previous) => {
1113
+ return [...previous ?? [], ...readTargetValues(value)];
1114
+ };
799
1115
  var readCommaSeparatedValues = (value) => value.split(",").map((entry) => entry.trim()).filter((entry) => entry.length > 0);
800
1116
  var readBooleanValue = (value, label) => {
801
1117
  const normalized = value.trim().toLowerCase();
@@ -830,7 +1146,22 @@ var createLinuxDesktopOptions = (commandOptions) => {
830
1146
  if (commandOptions.linuxStartupNotify !== void 0) options.startupNotify = readBooleanValue(commandOptions.linuxStartupNotify, "--linux-startup-notify");
831
1147
  return Object.keys(options).length === 0 ? void 0 : options;
832
1148
  };
833
- var runBuildCommand = async (commandOptions) => {
1149
+ var createWindowsCodeSigningOptions = (commandOptions, command) => {
1150
+ if (command.getOptionValueSource("windowsCodeSigning") === "cli" && commandOptions.windowsCodeSigning === false) return false;
1151
+ const args = commandOptions.windowsSignArg ?? [];
1152
+ const targets = commandOptions.windowsSignTarget ?? [];
1153
+ if (commandOptions.windowsSignCommand === void 0) {
1154
+ if (args.length > 0 || targets.length > 0) throw new Error("--windows-sign-command is required when Windows signing arguments or targets are specified.");
1155
+ return;
1156
+ }
1157
+ const options = {
1158
+ command: commandOptions.windowsSignCommand,
1159
+ args
1160
+ };
1161
+ if (targets.length > 0) options.targets = targets;
1162
+ return options;
1163
+ };
1164
+ var runBuildCommand = async (commandOptions, command) => {
834
1165
  const targets = commandOptions.target;
835
1166
  if (commandOptions.all === true && targets.length > 0) throw new Error("Specify either --all or --target, not both.");
836
1167
  const buildOptions = {
@@ -844,6 +1175,8 @@ var runBuildCommand = async (commandOptions) => {
844
1175
  if (commandOptions.icon !== void 0) buildOptions.iconPath = commandOptions.icon;
845
1176
  const windowsResource = createWindowsResourceOptions(commandOptions);
846
1177
  if (windowsResource !== void 0) buildOptions.windowsResource = windowsResource;
1178
+ const windowsCodeSigning = createWindowsCodeSigningOptions(commandOptions, command);
1179
+ if (windowsCodeSigning !== void 0) buildOptions.windowsCodeSigning = windowsCodeSigning;
847
1180
  const linuxDesktop = createLinuxDesktopOptions(commandOptions);
848
1181
  if (linuxDesktop !== void 0) buildOptions.linuxDesktop = linuxDesktop;
849
1182
  if (commandOptions.outDir !== void 0) buildOptions.outputRoot = commandOptions.outDir;
@@ -862,7 +1195,7 @@ var runBuildCommand = async (commandOptions) => {
862
1195
  if (commandOptions.json === true) console.log(JSON.stringify(result, null, 2));
863
1196
  else for (const target of result.targets) console.log(target.outputPath);
864
1197
  };
865
- var runPackCommand = async (commandOptions) => {
1198
+ var runPackCommand = async (commandOptions, command) => {
866
1199
  const targets = commandOptions.target;
867
1200
  if (commandOptions.all === true && targets.length > 0) throw new Error("Specify either --all or --target, not both.");
868
1201
  const packOptions = {
@@ -876,6 +1209,8 @@ var runPackCommand = async (commandOptions) => {
876
1209
  if (commandOptions.icon !== void 0) packOptions.iconPath = commandOptions.icon;
877
1210
  const windowsResource = createWindowsResourceOptions(commandOptions);
878
1211
  if (windowsResource !== void 0) packOptions.windowsResource = windowsResource;
1212
+ const windowsCodeSigning = createWindowsCodeSigningOptions(commandOptions, command);
1213
+ if (windowsCodeSigning !== void 0) packOptions.windowsCodeSigning = windowsCodeSigning;
879
1214
  const linuxDesktop = createLinuxDesktopOptions(commandOptions);
880
1215
  if (linuxDesktop !== void 0) packOptions.linuxDesktop = linuxDesktop;
881
1216
  if (commandOptions.linuxSandbox !== void 0) packOptions.linuxSandbox = commandOptions.linuxSandbox;
@@ -974,11 +1309,11 @@ var createCliCommand = () => {
974
1309
  program.outputHelp({ error: true });
975
1310
  process.exitCode = 1;
976
1311
  });
977
- program.command("build").description("Build CEF-free muon app distribution directories").option("--target <target>", "public target or comma-separated public targets", appendTargetValues, []).option("--all", "build all supported targets").option("--assets <path>", "asset root path").option("--config <path>", "muon config path").option("--icon <path>", "static application PNG icon path").option("--windows-icon <path>", "Windows PNG icon resource path").option("--windows-product-name <name>", "Windows product name").option("--windows-file-description <text>", "Windows file description").option("--windows-company-name <name>", "Windows company name").option("--windows-version <version>", "Windows resource version").option("--windows-copyright <text>", "Windows legal copyright").option("--linux-desktop-id <id>", "Linux desktop entry identifier").option("--linux-name <name>", "Linux desktop display name").option("--linux-comment <text>", "Linux desktop comment").option("--linux-icon <path>", "Linux desktop PNG icon path").option("--linux-categories <list>", "Linux desktop categories").option("--linux-startup-notify <boolean>", "Linux startup notification").option("--out-dir <path>", "output root directory").option("--name <name>", "launcher file name").option("--app-id <id>", "stable application identifier").option("--package-directory <path>", "muon package dist directory").option("--json", "write result as JSON").action(async (options) => {
978
- await runBuildCommand(options);
1312
+ program.command("build").description("Build CEF-free muon app distribution directories").option("--target <target>", "public target or comma-separated public targets", appendTargetValues, []).option("--all", "build all supported targets").option("--assets <path>", "asset root path").option("--config <path>", "muon config path").option("--icon <path>", "static application PNG icon path").option("--windows-icon <path>", "Windows PNG icon resource path").option("--windows-product-name <name>", "Windows product name").option("--windows-file-description <text>", "Windows file description").option("--windows-company-name <name>", "Windows company name").option("--windows-version <version>", "Windows resource version").option("--windows-copyright <text>", "Windows legal copyright").option("--windows-sign-command <command>", "Windows code signing command").option("--windows-sign-arg <arg>", "Windows code signing command argument", appendWindowsSignArgValue).option("--windows-sign-target <target>", "Windows code signing target or comma-separated targets", appendWindowsSignTargetValues).option("--no-windows-code-signing", "disable muon.json Windows signing").option("--linux-desktop-id <id>", "Linux desktop entry identifier").option("--linux-name <name>", "Linux desktop display name").option("--linux-comment <text>", "Linux desktop comment").option("--linux-icon <path>", "Linux desktop PNG icon path").option("--linux-categories <list>", "Linux desktop categories").option("--linux-startup-notify <boolean>", "Linux startup notification").option("--out-dir <path>", "output root directory").option("--name <name>", "launcher file name").option("--app-id <id>", "stable application identifier").option("--package-directory <path>", "muon package dist directory").option("--json", "write result as JSON").action(async (options, command) => {
1313
+ await runBuildCommand(options, command);
979
1314
  });
980
- program.command("pack").description("Build and package a muon app").option("--type <type>", "package type or comma-separated package types: zip, tar.gz, tgz, deb, nsis (default: all)", appendPackTypeValues).option("--target <target>", "public target, platform, arch, or comma-separated selectors", appendTargetValues, []).option("--all", "build all supported targets").option("--config <path>", "muon config path").option("--icon <path>", "static application PNG icon path").option("--windows-icon <path>", "Windows PNG icon resource path").option("--windows-product-name <name>", "Windows product name").option("--windows-file-description <text>", "Windows file description").option("--windows-company-name <name>", "Windows company name").option("--windows-version <version>", "Windows resource version").option("--windows-copyright <text>", "Windows legal copyright").option("--linux-desktop-id <id>", "Linux desktop entry identifier").option("--linux-name <name>", "Linux desktop display name").option("--linux-comment <text>", "Linux desktop comment").option("--linux-icon <path>", "Linux desktop PNG icon path").option("--linux-categories <list>", "Linux desktop categories").option("--linux-startup-notify <boolean>", "Linux startup notification").option("--linux-sandbox <mode>", "Linux deb CEF sandbox mode: disabled, setuid").option("--name <name>", "launcher file name").option("--app-id <id>", "stable application identifier").option("--package-directory <path>", "muon package dist directory").option("--artifacts-dir <path>", "package artifact output directory").option("--package-name <name>", "package name override").option("--package-version <version>", "package version override").option("--description <text>", "package description override").option("--author <text>", "package author override").option("--json", "write result as JSON").action(async (options) => {
981
- await runPackCommand(options);
1315
+ program.command("pack").description("Build and package a muon app").option("--type <type>", "package type or comma-separated package types: zip, tar.gz, tgz, deb, nsis (default: all)", appendPackTypeValues).option("--target <target>", "public target, platform, arch, or comma-separated selectors", appendTargetValues, []).option("--all", "build all supported targets").option("--config <path>", "muon config path").option("--icon <path>", "static application PNG icon path").option("--windows-icon <path>", "Windows PNG icon resource path").option("--windows-product-name <name>", "Windows product name").option("--windows-file-description <text>", "Windows file description").option("--windows-company-name <name>", "Windows company name").option("--windows-version <version>", "Windows resource version").option("--windows-copyright <text>", "Windows legal copyright").option("--windows-sign-command <command>", "Windows code signing command").option("--windows-sign-arg <arg>", "Windows code signing command argument", appendWindowsSignArgValue).option("--windows-sign-target <target>", "Windows code signing target or comma-separated targets", appendWindowsSignTargetValues).option("--no-windows-code-signing", "disable muon.json Windows signing").option("--linux-desktop-id <id>", "Linux desktop entry identifier").option("--linux-name <name>", "Linux desktop display name").option("--linux-comment <text>", "Linux desktop comment").option("--linux-icon <path>", "Linux desktop PNG icon path").option("--linux-categories <list>", "Linux desktop categories").option("--linux-startup-notify <boolean>", "Linux startup notification").option("--linux-sandbox <mode>", "Linux deb CEF sandbox mode: disabled, setuid").option("--name <name>", "launcher file name").option("--app-id <id>", "stable application identifier").option("--package-directory <path>", "muon package dist directory").option("--artifacts-dir <path>", "package artifact output directory").option("--package-name <name>", "package name override").option("--package-version <version>", "package version override").option("--description <text>", "package description override").option("--author <text>", "package author override").option("--json", "write result as JSON").action(async (options, command) => {
1316
+ await runPackCommand(options, command);
982
1317
  });
983
1318
  const devCommand = program.command("run").description("Launch muon directly with local development assets").option("--muon-path <path>", "muon runtime file root").option("--cef-path <path>", "CEF file root").option("--stage-dir <path>", "prepared runtime output directory").option("--config <path>", "muon config path").option("--assets <path>", "development asset directory").option("--no-debugger", "disable muon debugger defaults").option("--json", "write result as JSON").action(async (options) => {
984
1319
  await runDevCommand(options, devCommand);