@mpgd/cli 0.36.0 → 0.36.1

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.
@@ -1,6 +1,6 @@
1
1
  // node_modules/.cache/mpgd-native-build/tools/target/build-target.js
2
2
  import { spawnSync as spawnSync5 } from "node:child_process";
3
- import { cpSync as cpSync4, existsSync as existsSync21, lstatSync as lstatSync10, mkdirSync as mkdirSync12, mkdtempSync as mkdtempSync5, readdirSync as readdirSync7, readFileSync as readFileSync19, realpathSync as realpathSync9, rmSync as rmSync11, statSync as statSync7, writeFileSync as writeFileSync13 } from "node:fs";
3
+ import { cpSync as cpSync4, existsSync as existsSync22, lstatSync as lstatSync11, mkdirSync as mkdirSync12, mkdtempSync as mkdtempSync5, readdirSync as readdirSync7, readFileSync as readFileSync20, realpathSync as realpathSync9, rmSync as rmSync11, statSync as statSync7, writeFileSync as writeFileSync14 } from "node:fs";
4
4
  import { tmpdir as tmpdir4 } from "node:os";
5
5
  import { basename as basename4, dirname as dirname9, join as join9, relative as relative9, resolve as resolve14 } from "node:path";
6
6
  import { loadEnv } from "vite";
@@ -328,8 +328,8 @@ function resolveSecureGamePath(gameRoot, configuredPath) {
328
328
  }
329
329
  return real;
330
330
  }
331
- function toGameRelativePath(gameRoot, path9) {
332
- return relative(realpathSync2(gameRoot), realpathSync2(path9)).split("\\").join("/");
331
+ function toGameRelativePath(gameRoot, path10) {
332
+ return relative(realpathSync2(gameRoot), realpathSync2(path10)).split("\\").join("/");
333
333
  }
334
334
  function readAppIconConfig(input, label) {
335
335
  assertRecord(input, label);
@@ -350,9 +350,9 @@ function readVariants(input, label) {
350
350
  assertRecord(input, label);
351
351
  const variants = {};
352
352
  for (const name of variantNames) {
353
- const path9 = readOptionalString(input[name], `${label}.${name}`);
354
- if (path9 !== void 0) {
355
- variants[name] = path9;
353
+ const path10 = readOptionalString(input[name], `${label}.${name}`);
354
+ if (path10 !== void 0) {
355
+ variants[name] = path10;
356
356
  }
357
357
  }
358
358
  for (const key of Object.keys(input)) {
@@ -394,38 +394,38 @@ import sharp from "sharp";
394
394
  var pngSignature = Buffer.from([137, 80, 78, 71, 13, 10, 26, 10]);
395
395
  var maximumDimension = 8192;
396
396
  var maximumPixels = maximumDimension * maximumDimension;
397
- async function validateBrandImage(path9, options) {
398
- const bytes = readFileSync3(path9);
397
+ async function validateBrandImage(path10, options) {
398
+ const bytes = readFileSync3(path10);
399
399
  const format = sniffFormat(bytes);
400
400
  if (format === "png" && hasPngChunk(bytes, "acTL")) {
401
- throw new Error(`Animated or multi-page brand images are not supported: ${path9}`);
401
+ throw new Error(`Animated or multi-page brand images are not supported: ${path10}`);
402
402
  }
403
403
  const warnings = format === "svg" ? validateSvg(bytes, options.strict) : [];
404
404
  let metadata;
405
405
  try {
406
406
  metadata = await sharp(bytes, { animated: true, limitInputPixels: maximumPixels }).metadata();
407
407
  } catch (error) {
408
- throw new Error(`Invalid brand image ${path9}: ${formatError2(error)}`);
408
+ throw new Error(`Invalid brand image ${path10}: ${formatError2(error)}`);
409
409
  }
410
410
  const width = metadata.width;
411
411
  const height = metadata.height;
412
412
  if (width === void 0 || height === void 0 || width < 1 || height < 1) {
413
- throw new Error(`Brand image has no usable dimensions: ${path9}`);
413
+ throw new Error(`Brand image has no usable dimensions: ${path10}`);
414
414
  }
415
415
  if (width !== height) {
416
- throw new Error(`Brand image must be square, got ${width}x${height}: ${path9}`);
416
+ throw new Error(`Brand image must be square, got ${width}x${height}: ${path10}`);
417
417
  }
418
418
  if (width > maximumDimension || height > maximumDimension) {
419
- throw new Error(`Brand image exceeds ${maximumDimension}x${maximumDimension}: ${path9}`);
419
+ throw new Error(`Brand image exceeds ${maximumDimension}x${maximumDimension}: ${path10}`);
420
420
  }
421
421
  if ((metadata.pages ?? 1) > 1) {
422
- throw new Error(`Animated or multi-page brand images are not supported: ${path9}`);
422
+ throw new Error(`Animated or multi-page brand images are not supported: ${path10}`);
423
423
  }
424
424
  if (format === "png" && options.minimumSize !== void 0 && width < options.minimumSize) {
425
- throw new Error(`PNG brand image must be at least ${options.minimumSize}x${options.minimumSize}; got ${width}x${height}: ${path9}`);
425
+ throw new Error(`PNG brand image must be at least ${options.minimumSize}x${options.minimumSize}; got ${width}x${height}: ${path10}`);
426
426
  }
427
427
  return {
428
- path: path9,
428
+ path: path10,
429
429
  bytes,
430
430
  format,
431
431
  width,
@@ -850,28 +850,28 @@ async function verifyGeneratedTargetIcons(result) {
850
850
  }
851
851
  assertManifestOutputsMatchProfile(result);
852
852
  for (const output of result.manifest.outputs) {
853
- const path9 = resolve2(result.outputDir, output.path.slice("icons/".length));
854
- const bytes = readFileSync4(path9);
853
+ const path10 = resolve2(result.outputDir, output.path.slice("icons/".length));
854
+ const bytes = readFileSync4(path10);
855
855
  if (sha256(bytes) !== output.sha256) {
856
- throw new Error(`Stale generated icon output: ${path9}`);
856
+ throw new Error(`Stale generated icon output: ${path10}`);
857
857
  }
858
858
  let metadata;
859
859
  try {
860
860
  metadata = await sharp2(bytes).metadata();
861
861
  } catch {
862
- throw new Error(`Generated icon is not a decodable PNG: ${path9}`);
862
+ throw new Error(`Generated icon is not a decodable PNG: ${path10}`);
863
863
  }
864
864
  if (metadata.format !== "png" || metadata.width !== output.width || metadata.height !== output.height || (metadata.pages ?? 1) !== 1) {
865
- throw new Error(`Generated icon must be a ${output.width}x${output.height} single-page PNG: ${path9}`);
865
+ throw new Error(`Generated icon must be a ${output.width}x${output.height} single-page PNG: ${path10}`);
866
866
  }
867
867
  if (await pixelSha256(bytes) !== output.pixelSha256) {
868
- throw new Error(`Generated icon pixel digest mismatch: ${path9}`);
868
+ throw new Error(`Generated icon pixel digest mismatch: ${path10}`);
869
869
  }
870
870
  if (output.opaque && !await isPngOpaque(bytes)) {
871
- throw new Error(`Generated icon expected to be opaque: ${path9}`);
871
+ throw new Error(`Generated icon expected to be opaque: ${path10}`);
872
872
  }
873
873
  if (result.profile.id === "devvit" && bytes.byteLength > devvitIconMaximumBytes) {
874
- throw new Error(`Devvit marketing icon must be at most ${devvitIconMaximumBytes} bytes: ${path9}`);
874
+ throw new Error(`Devvit marketing icon must be at most ${devvitIconMaximumBytes} bytes: ${path10}`);
875
875
  }
876
876
  }
877
877
  }
@@ -883,13 +883,13 @@ async function resolveOutputImage(input) {
883
883
  }
884
884
  async function loadVariantSources(gameRoot, appIcon, strict) {
885
885
  const entries = await Promise.all(brandImageVariants.map(async (variant) => {
886
- const path9 = appIcon.variants?.[variant];
887
- if (path9 === void 0) {
886
+ const path10 = appIcon.variants?.[variant];
887
+ if (path10 === void 0) {
888
888
  return void 0;
889
889
  }
890
890
  return [
891
891
  variant,
892
- await validateBrandImage(resolveSecureGamePath(gameRoot, path9), { strict })
892
+ await validateBrandImage(resolveSecureGamePath(gameRoot, path10), { strict })
893
893
  ];
894
894
  }));
895
895
  return Object.fromEntries(entries.filter((entry) => entry !== void 0));
@@ -934,14 +934,14 @@ function assertManifestOutputsMatchProfile(result) {
934
934
  throw new Error(`Generated icon output count does not match ${result.profile.id} profile.`);
935
935
  }
936
936
  for (const expected of expectedOutputs) {
937
- const path9 = `icons/${expected.file}`;
938
- const matches = result.manifest.outputs.filter((output2) => output2.path === path9);
937
+ const path10 = `icons/${expected.file}`;
938
+ const matches = result.manifest.outputs.filter((output2) => output2.path === path10);
939
939
  if (matches.length !== 1) {
940
- throw new Error(`Generated icon manifest must contain exactly one ${path9} output.`);
940
+ throw new Error(`Generated icon manifest must contain exactly one ${path10} output.`);
941
941
  }
942
942
  const output = matches[0];
943
943
  if (output === void 0 || output.target !== result.target || output.purpose !== expected.purpose || output.width !== expected.width || output.height !== expected.height || output.format !== "png" || output.opaque !== expected.opaque || !/^[0-9a-f]{64}$/u.test(output.sha256) || !/^[0-9a-f]{64}$/u.test(output.pixelSha256)) {
944
- throw new Error(`Generated icon manifest output does not match profile: ${path9}`);
944
+ throw new Error(`Generated icon manifest output does not match profile: ${path10}`);
945
945
  }
946
946
  }
947
947
  }
@@ -1219,8 +1219,8 @@ function indexHtmlLinksExistingManifest(indexFile, manifests) {
1219
1219
  }
1220
1220
  function rootManifestNameFromHref(href) {
1221
1221
  const pathEnd = href.search(/[?#]/u);
1222
- const path9 = (pathEnd < 0 ? href : href.slice(0, pathEnd)).trim();
1223
- const rootRelativePath = path9.startsWith("./") ? path9.slice(2) : path9.startsWith("/") ? path9.slice(1) : path9;
1222
+ const path10 = (pathEnd < 0 ? href : href.slice(0, pathEnd)).trim();
1223
+ const rootRelativePath = path10.startsWith("./") ? path10.slice(2) : path10.startsWith("/") ? path10.slice(1) : path10;
1224
1224
  return rootRelativePath.length > 0 && !rootRelativePath.includes("/") && !rootRelativePath.includes("\\") && installableManifestNames.has(rootRelativePath.toLowerCase()) ? rootRelativePath : void 0;
1225
1225
  }
1226
1226
  function readHtmlAttribute(tag, expectedName) {
@@ -1582,25 +1582,25 @@ function assertExistingWebOutputsAreGeneratedArtifacts(outputs) {
1582
1582
  }
1583
1583
  }
1584
1584
  function isPathWithin(root, candidate) {
1585
- const path9 = relative3(root, candidate);
1586
- return path9 === "" || path9 !== ".." && !path9.startsWith(`..${sep}`) && !isAbsolute2(path9);
1585
+ const path10 = relative3(root, candidate);
1586
+ return path10 === "" || path10 !== ".." && !path10.startsWith(`..${sep}`) && !isAbsolute2(path10);
1587
1587
  }
1588
1588
  function pathsOverlap(first, second) {
1589
1589
  return isPathWithin(first, second) || isPathWithin(second, first);
1590
1590
  }
1591
- function canonicalizeWebArtifactOutput(path9) {
1592
- const status = lstatIfPresent(path9);
1591
+ function canonicalizeWebArtifactOutput(path10) {
1592
+ const status = lstatIfPresent(path10);
1593
1593
  if (status?.isSymbolicLink() === true) {
1594
- throw new Error(`Web artifact output must not be a symbolic link: ${path9}`);
1594
+ throw new Error(`Web artifact output must not be a symbolic link: ${path10}`);
1595
1595
  }
1596
1596
  if (status !== void 0 && !status.isDirectory()) {
1597
- throw new Error(`Web artifact output must be a directory when it already exists: ${path9}`);
1597
+ throw new Error(`Web artifact output must be a directory when it already exists: ${path10}`);
1598
1598
  }
1599
- return canonicalizeThroughExistingAncestor(path9);
1599
+ return canonicalizeThroughExistingAncestor(path10);
1600
1600
  }
1601
- function lstatIfPresent(path9) {
1601
+ function lstatIfPresent(path10) {
1602
1602
  try {
1603
- return lstatSync2(path9);
1603
+ return lstatSync2(path10);
1604
1604
  } catch (error) {
1605
1605
  if (error.code === "ENOENT") {
1606
1606
  return void 0;
@@ -1608,14 +1608,14 @@ function lstatIfPresent(path9) {
1608
1608
  throw error;
1609
1609
  }
1610
1610
  }
1611
- function canonicalizeThroughExistingAncestor(path9) {
1612
- const normalizedPath = resolve3(path9);
1611
+ function canonicalizeThroughExistingAncestor(path10) {
1612
+ const normalizedPath = resolve3(path10);
1613
1613
  const suffix = [];
1614
1614
  let existingAncestor = normalizedPath;
1615
1615
  while (!existsSync4(existingAncestor)) {
1616
1616
  const parent = dirname2(existingAncestor);
1617
1617
  if (parent === existingAncestor) {
1618
- throw new Error(`Cannot resolve an existing ancestor for web output: ${path9}`);
1618
+ throw new Error(`Cannot resolve an existing ancestor for web output: ${path10}`);
1619
1619
  }
1620
1620
  suffix.unshift(basename(existingAncestor));
1621
1621
  existingAncestor = parent;
@@ -1671,18 +1671,18 @@ function stageWrapperIcon(result, wrapperApp) {
1671
1671
  }
1672
1672
  async function stageNativeIconResources(result, shellApp) {
1673
1673
  const snapshots = /* @__PURE__ */ new Map();
1674
- const write = (path9, contents) => {
1675
- if (!snapshots.has(path9)) {
1676
- snapshots.set(path9, existsSync5(path9) ? readFileSync6(path9) : void 0);
1674
+ const write = (path10, contents) => {
1675
+ if (!snapshots.has(path10)) {
1676
+ snapshots.set(path10, existsSync5(path10) ? readFileSync6(path10) : void 0);
1677
1677
  }
1678
- mkdirSync3(dirname3(path9), { recursive: true });
1679
- writeFileSync3(path9, contents);
1678
+ mkdirSync3(dirname3(path10), { recursive: true });
1679
+ writeFileSync3(path10, contents);
1680
1680
  };
1681
- const remove = (path9) => {
1682
- if (!snapshots.has(path9)) {
1683
- snapshots.set(path9, existsSync5(path9) ? readFileSync6(path9) : void 0);
1681
+ const remove = (path10) => {
1682
+ if (!snapshots.has(path10)) {
1683
+ snapshots.set(path10, existsSync5(path10) ? readFileSync6(path10) : void 0);
1684
1684
  }
1685
- rmSync3(path9, { force: true });
1685
+ rmSync3(path10, { force: true });
1686
1686
  };
1687
1687
  if (result.profile.id === "android-adaptive") {
1688
1688
  await stageAndroid(result, shellApp, write, remove);
@@ -1690,11 +1690,11 @@ async function stageNativeIconResources(result, shellApp) {
1690
1690
  stageIos(result, shellApp, write);
1691
1691
  }
1692
1692
  return () => {
1693
- for (const [path9, contents] of [...snapshots.entries()].reverse()) {
1693
+ for (const [path10, contents] of [...snapshots.entries()].reverse()) {
1694
1694
  if (contents === void 0) {
1695
- rmSync3(path9, { force: true });
1695
+ rmSync3(path10, { force: true });
1696
1696
  } else {
1697
- writeFileSync3(path9, contents);
1697
+ writeFileSync3(path10, contents);
1698
1698
  }
1699
1699
  }
1700
1700
  };
@@ -1767,7 +1767,7 @@ function stageWebManifest(result, gameDist, manifestSourceDirectory) {
1767
1767
  stagedPath,
1768
1768
  publicWebManifestPath,
1769
1769
  publicJsonManifestPath
1770
- ].find((path9) => existsSync5(path9));
1770
+ ].find((path10) => existsSync5(path10));
1771
1771
  const manifest = manifestPath !== void 0 ? readWebManifest(manifestPath) : {
1772
1772
  name: basename2(result.gameRoot),
1773
1773
  short_name: basename2(result.gameRoot),
@@ -1790,10 +1790,10 @@ function stageWebManifest(result, gameDist, manifestSourceDirectory) {
1790
1790
  }
1791
1791
  ensureInstallableWebManifestLink(gameDist);
1792
1792
  }
1793
- function readWebManifest(path9) {
1794
- const parsed = JSON.parse(readFileSync6(path9, "utf8"));
1793
+ function readWebManifest(path10) {
1794
+ const parsed = JSON.parse(readFileSync6(path10, "utf8"));
1795
1795
  if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
1796
- throw new Error(`Web app manifest must contain a JSON object: ${path9}`);
1796
+ throw new Error(`Web app manifest must contain a JSON object: ${path10}`);
1797
1797
  }
1798
1798
  return parsed;
1799
1799
  }
@@ -1812,8 +1812,8 @@ function androidAdaptiveXml(hasMonochrome) {
1812
1812
  </adaptive-icon>
1813
1813
  `;
1814
1814
  }
1815
- async function resizePng(path9, size) {
1816
- return sharp3(path9).resize(size, size, { kernel: sharp3.kernel.lanczos3 }).png({ compressionLevel: 9, effort: 10 }).toBuffer();
1815
+ async function resizePng(path10, size) {
1816
+ return sharp3(path10).resize(size, size, { kernel: sharp3.kernel.lanczos3 }).png({ compressionLevel: 9, effort: 10 }).toBuffer();
1817
1817
  }
1818
1818
  function cacheOutputPath(result, output) {
1819
1819
  return resolve4(result.outputDir, basename2(output.path));
@@ -2287,8 +2287,8 @@ function readConfiguredPath(value) {
2287
2287
  import { readFileSync as readFileSync7 } from "node:fs";
2288
2288
  import { resolve as resolve5 } from "node:path";
2289
2289
  import { pathToFileURL } from "node:url";
2290
- function readJsonFile(path9) {
2291
- return JSON.parse(readFileSync7(resolve5(path9), "utf8"));
2290
+ function readJsonFile(path10) {
2291
+ return JSON.parse(readFileSync7(resolve5(path10), "utf8"));
2292
2292
  }
2293
2293
  function isCliEntrypoint(metaUrl) {
2294
2294
  const scriptPath = process.argv[1];
@@ -2442,20 +2442,20 @@ function listMiniGameArtifactFiles(artifactRoot) {
2442
2442
  throw new Error("Mini-game artifact traversal lost its current directory.");
2443
2443
  }
2444
2444
  for (const entry of readdirSync2(directory, { withFileTypes: true })) {
2445
- const path9 = resolve6(directory, entry.name);
2446
- const stat = lstatSync4(path9);
2445
+ const path10 = resolve6(directory, entry.name);
2446
+ const stat = lstatSync4(path10);
2447
2447
  if (stat.isSymbolicLink()) {
2448
- throw new Error(`Mini-game artifacts must not contain symbolic links: ${path9}`);
2448
+ throw new Error(`Mini-game artifacts must not contain symbolic links: ${path10}`);
2449
2449
  }
2450
- const artifactPath = toArtifactRelativePath(root, path9);
2450
+ const artifactPath = toArtifactRelativePath(root, path10);
2451
2451
  assertMiniGameArtifactPathAllowed(artifactPath);
2452
2452
  artifactPaths.push(artifactPath);
2453
2453
  if (stat.isDirectory()) {
2454
- pending.push(path9);
2454
+ pending.push(path10);
2455
2455
  continue;
2456
2456
  }
2457
2457
  if (!stat.isFile()) {
2458
- throw new Error(`Mini-game artifacts must contain regular files only: ${path9}`);
2458
+ throw new Error(`Mini-game artifacts must contain regular files only: ${path10}`);
2459
2459
  }
2460
2460
  files.push({ path: artifactPath, bytes: stat.size });
2461
2461
  }
@@ -2465,22 +2465,22 @@ function listMiniGameArtifactFiles(artifactRoot) {
2465
2465
  return left.path < right.path ? -1 : left.path > right.path ? 1 : 0;
2466
2466
  });
2467
2467
  }
2468
- function assertMiniGameArtifactRelativePath(path9, label) {
2469
- const segments = path9.split("/");
2470
- if (path9.length === 0 || path9.includes("\\") || path9.startsWith("/") || /^[A-Za-z]:/u.test(path9) || isAbsolute3(path9) || segments.some((segment) => segment.length === 0 || segment === "." || segment === "..") || segments.some((segment) => /[. ]$/u.test(segment) || /[<>:"|?*\u0000-\u001f]/u.test(segment) || /^(?:con|prn|aux|nul|clock\$|conin\$|conout\$|com[1-9\u00b9\u00b2\u00b3]|lpt[1-9\u00b9\u00b2\u00b3])(?:\..*)?$/iu.test(segment))) {
2471
- throw new Error(`${label} must be a safe artifact-relative path: ${path9}`);
2468
+ function assertMiniGameArtifactRelativePath(path10, label) {
2469
+ const segments = path10.split("/");
2470
+ if (path10.length === 0 || path10.includes("\\") || path10.startsWith("/") || /^[A-Za-z]:/u.test(path10) || isAbsolute3(path10) || segments.some((segment) => segment.length === 0 || segment === "." || segment === "..") || segments.some((segment) => /[. ]$/u.test(segment) || /[<>:"|?*\u0000-\u001f]/u.test(segment) || /^(?:con|prn|aux|nul|clock\$|conin\$|conout\$|com[1-9\u00b9\u00b2\u00b3]|lpt[1-9\u00b9\u00b2\u00b3])(?:\..*)?$/iu.test(segment))) {
2471
+ throw new Error(`${label} must be a safe artifact-relative path: ${path10}`);
2472
2472
  }
2473
2473
  }
2474
2474
  function assertMiniGameArtifactPathsPortable(paths) {
2475
2475
  const seen = /* @__PURE__ */ new Map();
2476
- for (const path9 of paths) {
2477
- assertMiniGameArtifactRelativePath(path9, "Mini-game artifact path");
2478
- const portableKey = miniGamePortablePathKey(path9);
2476
+ for (const path10 of paths) {
2477
+ assertMiniGameArtifactRelativePath(path10, "Mini-game artifact path");
2478
+ const portableKey = miniGamePortablePathKey(path10);
2479
2479
  const previous = seen.get(portableKey);
2480
2480
  if (previous !== void 0) {
2481
- throw new Error(`Mini-game artifact paths collide on portable filesystems: ${previous}, ${path9}.`);
2481
+ throw new Error(`Mini-game artifact paths collide on portable filesystems: ${previous}, ${path10}.`);
2482
2482
  }
2483
- seen.set(portableKey, path9);
2483
+ seen.set(portableKey, path10);
2484
2484
  }
2485
2485
  }
2486
2486
  function readMiniGameSubpackages(gameConfig) {
@@ -2517,40 +2517,40 @@ function assertSubpackageRoots(subpackages) {
2517
2517
  }
2518
2518
  }
2519
2519
  }
2520
- function resolveArtifactPath(root, path9) {
2521
- const resolved = resolve6(root, path9);
2520
+ function resolveArtifactPath(root, path10) {
2521
+ const resolved = resolve6(root, path10);
2522
2522
  const relativePath = relative4(root, resolved);
2523
2523
  if (relativePath.length === 0 || relativePath === ".." || relativePath.startsWith(`..${sep2}`) || isAbsolute3(relativePath)) {
2524
- throw new Error(`Mini-game path escapes its artifact root: ${path9}`);
2524
+ throw new Error(`Mini-game path escapes its artifact root: ${path10}`);
2525
2525
  }
2526
2526
  try {
2527
2527
  const stat = lstatSync4(resolved);
2528
2528
  if (stat.isSymbolicLink()) {
2529
- throw new Error(`Mini-game path must not be a symbolic link: ${path9}`);
2529
+ throw new Error(`Mini-game path must not be a symbolic link: ${path10}`);
2530
2530
  }
2531
2531
  } catch (error) {
2532
- throw new Error(`Mini-game subpackage root does not exist: ${path9} (${formatError4(error)})`);
2532
+ throw new Error(`Mini-game subpackage root does not exist: ${path10} (${formatError4(error)})`);
2533
2533
  }
2534
2534
  return resolved;
2535
2535
  }
2536
- function toArtifactRelativePath(root, path9) {
2537
- const artifactPath = relative4(root, path9).replaceAll("\\", "/");
2536
+ function toArtifactRelativePath(root, path10) {
2537
+ const artifactPath = relative4(root, path10).replaceAll("\\", "/");
2538
2538
  assertMiniGameArtifactRelativePath(artifactPath, "Mini-game artifact file");
2539
2539
  return artifactPath;
2540
2540
  }
2541
- function isInsideRoot(path9, root) {
2542
- return path9 === root || path9.startsWith(`${root}/`);
2541
+ function isInsideRoot(path10, root) {
2542
+ return path10 === root || path10.startsWith(`${root}/`);
2543
2543
  }
2544
- function miniGamePortablePathKey(path9) {
2545
- return path9.normalize("NFC").toLowerCase();
2544
+ function miniGamePortablePathKey(path10) {
2545
+ return path10.normalize("NFC").toLowerCase();
2546
2546
  }
2547
2547
  function assertWithinBudget(actual, maximum, label) {
2548
2548
  if (actual > maximum) {
2549
2549
  throw new Error(`Mini-game ${label} exceeds its package budget: ${String(actual)} > ${String(maximum)} bytes.`);
2550
2550
  }
2551
2551
  }
2552
- function assertMiniGameArtifactPathAllowed(path9) {
2553
- const segments = path9.split("/");
2552
+ function assertMiniGameArtifactPathAllowed(path10) {
2553
+ const segments = path10.split("/");
2554
2554
  const fileName = segments.at(-1) ?? "";
2555
2555
  const normalizedFileName = fileName.toLowerCase();
2556
2556
  const normalizedSegments = segments.map((segment) => segment.toLowerCase());
@@ -2564,16 +2564,16 @@ function assertMiniGameArtifactPathAllowed(path9) {
2564
2564
  "tests"
2565
2565
  ]);
2566
2566
  if (normalizedSegments.some((segment) => forbiddenSegments.has(segment))) {
2567
- throw new Error(`Mini-game artifact contains a forbidden development path: ${path9}`);
2567
+ throw new Error(`Mini-game artifact contains a forbidden development path: ${path10}`);
2568
2568
  }
2569
2569
  if (normalizedFileName === ".ds_store" || normalizedFileName === ".env" || normalizedFileName.startsWith(".env.") || normalizedFileName === ".npmrc" || normalizedFileName === "credentials.json" || normalizedFileName === "project.private.config.json" || /^service-account.*\.json$/iu.test(fileName) || /\.(?:map|jsx|ts|tsx|mts|cts|pem|key|p12|pfx)$/iu.test(fileName)) {
2570
- throw new Error(`Mini-game artifact contains a forbidden development or credential file: ${path9}`);
2570
+ throw new Error(`Mini-game artifact contains a forbidden development or credential file: ${path10}`);
2571
2571
  }
2572
2572
  if (/\.(?:html?|css|svg)$/iu.test(fileName)) {
2573
- throw new Error(`Mini-game artifact contains a browser-only asset: ${path9}`);
2573
+ throw new Error(`Mini-game artifact contains a browser-only asset: ${path10}`);
2574
2574
  }
2575
2575
  if (/\.(?:aac|m4a|mp3|ogg|opus|wav|webm)$/iu.test(fileName)) {
2576
- throw new Error(`Mini-game Canvas MVP does not support audio assets yet: ${path9}`);
2576
+ throw new Error(`Mini-game Canvas MVP does not support audio assets yet: ${path10}`);
2577
2577
  }
2578
2578
  }
2579
2579
  function isRecord2(input) {
@@ -3041,19 +3041,19 @@ var effectiveTargetConfigOutputDirEnv = "MPGD_EFFECTIVE_TARGET_CONFIG_OUTPUT_DIR
3041
3041
  var targetIntegrationConfigKeys = /* @__PURE__ */ new Set([...targetIntegrations, "presentationMode"]);
3042
3042
  var integrationAvailabilityStateSet2 = new Set(integrationAvailabilityStates);
3043
3043
  var presentationModeSet2 = new Set(presentationModes);
3044
- function platformTargetsFilePath(path9 = process.env[platformTargetsFileEnv] ?? "mpgd.targets.json") {
3045
- return resolve7(path9);
3044
+ function platformTargetsFilePath(path10 = process.env[platformTargetsFileEnv] ?? "mpgd.targets.json") {
3045
+ return resolve7(path10);
3046
3046
  }
3047
- function loadPlatformTargetsConfig(path9 = platformTargetsFilePath()) {
3048
- const resolvedPath = platformTargetsFilePath(path9);
3047
+ function loadPlatformTargetsConfig(path10 = platformTargetsFilePath()) {
3048
+ const resolvedPath = platformTargetsFilePath(path10);
3049
3049
  return {
3050
3050
  path: resolvedPath,
3051
3051
  baseDir: dirname4(resolvedPath),
3052
3052
  config: assertPlatformTargetsConfigShape(readJsonFile(resolvedPath))
3053
3053
  };
3054
3054
  }
3055
- function resolveFromPlatformTargetsBase(baseDir, path9) {
3056
- return isAbsolute4(path9) ? path9 : resolve7(baseDir, path9);
3055
+ function resolveFromPlatformTargetsBase(baseDir, path10) {
3056
+ return isAbsolute4(path10) ? path10 : resolve7(baseDir, path10);
3057
3057
  }
3058
3058
  function releaseManifestPath(baseDir = dirname4(platformTargetsFilePath())) {
3059
3059
  return resolveFromPlatformTargetsBase(baseDir, process.env[releaseManifestFileEnv] ?? "artifacts/release-manifest.json");
@@ -4065,14 +4065,14 @@ function writeEffectiveTargetConfigs(options = {}) {
4065
4065
  writeFileSync4(indexPath, indexContent);
4066
4066
  return index;
4067
4067
  }
4068
- function readExistingArtifactIndex(path9, version) {
4069
- if (!existsSync6(path9)) {
4068
+ function readExistingArtifactIndex(path10, version) {
4069
+ if (!existsSync6(path10)) {
4070
4070
  return {
4071
4071
  version,
4072
4072
  artifacts: []
4073
4073
  };
4074
4074
  }
4075
- const parsed = JSON.parse(readFileSync9(path9, "utf8"));
4075
+ const parsed = JSON.parse(readFileSync9(path10, "utf8"));
4076
4076
  if (parsed.version !== version) {
4077
4077
  return {
4078
4078
  version,
@@ -4083,14 +4083,14 @@ function readExistingArtifactIndex(path9, version) {
4083
4083
  }
4084
4084
  function writeEffectiveTargetConfig(target2, config2, outputDir) {
4085
4085
  assertDeploymentTargetName(target2);
4086
- const path9 = join4(outputDir, `${target2}.json`);
4086
+ const path10 = join4(outputDir, `${target2}.json`);
4087
4087
  const content = `${JSON.stringify(config2, null, 2)}
4088
4088
  `;
4089
- mkdirSync4(dirname5(path9), { recursive: true });
4090
- writeFileSync4(path9, content);
4089
+ mkdirSync4(dirname5(path10), { recursive: true });
4090
+ writeFileSync4(path10, content);
4091
4091
  return {
4092
4092
  target: target2,
4093
- path: path9,
4093
+ path: path10,
4094
4094
  digest: sha2562(content),
4095
4095
  version: config2.version
4096
4096
  };
@@ -5123,51 +5123,51 @@ function readNativeVersionEvidence(target2) {
5123
5123
  return {};
5124
5124
  }
5125
5125
  function readIconManifestEvidence(artifactPath) {
5126
- const path9 = readOptionalString2(process.env.MPGD_ICON_MANIFEST_PATH);
5127
- if (path9 === void 0) {
5126
+ const path10 = readOptionalString2(process.env.MPGD_ICON_MANIFEST_PATH);
5127
+ if (path10 === void 0) {
5128
5128
  throw new Error("MPGD_ICON_MANIFEST_PATH is required when generating a release manifest.");
5129
5129
  }
5130
- const bytes = readFileBytes(path9);
5130
+ const bytes = readFileBytes(path10);
5131
5131
  const parsed = JSON.parse(bytes.toString("utf8"));
5132
5132
  if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
5133
- throw new Error(`Invalid icon manifest: ${path9}`);
5133
+ throw new Error(`Invalid icon manifest: ${path10}`);
5134
5134
  }
5135
5135
  const manifest = parsed;
5136
5136
  const canonicalSource = manifest.canonicalSource;
5137
5137
  if (typeof canonicalSource !== "object" || canonicalSource === null || Array.isArray(canonicalSource)) {
5138
- throw new Error(`Invalid icon manifest canonicalSource: ${path9}`);
5138
+ throw new Error(`Invalid icon manifest canonicalSource: ${path10}`);
5139
5139
  }
5140
5140
  const canonicalSourceRecord = canonicalSource;
5141
5141
  return {
5142
5142
  path: requirePortableArtifactPath(artifactPath),
5143
5143
  digest: createHash4("sha256").update(bytes).digest("hex"),
5144
- sourceSha256: requireManifestString(canonicalSourceRecord, "sha256", path9),
5145
- sharedConfigSha256: requireManifestString(manifest, "sharedConfigSha256", path9),
5146
- renderConfigSha256: requireManifestString(manifest, "renderConfigSha256", path9),
5147
- generatorVersion: requireManifestString(manifest, "generatorVersion", path9),
5148
- targetProfile: requireManifestString(manifest, "targetProfile", path9),
5149
- targetProfileVersion: requireManifestString(manifest, "targetProfileVersion", path9)
5144
+ sourceSha256: requireManifestString(canonicalSourceRecord, "sha256", path10),
5145
+ sharedConfigSha256: requireManifestString(manifest, "sharedConfigSha256", path10),
5146
+ renderConfigSha256: requireManifestString(manifest, "renderConfigSha256", path10),
5147
+ generatorVersion: requireManifestString(manifest, "generatorVersion", path10),
5148
+ targetProfile: requireManifestString(manifest, "targetProfile", path10),
5149
+ targetProfileVersion: requireManifestString(manifest, "targetProfileVersion", path10)
5150
5150
  };
5151
5151
  }
5152
- function requirePortableArtifactPath(path9) {
5153
- const normalized = path9.replaceAll("\\", "/");
5152
+ function requirePortableArtifactPath(path10) {
5153
+ const normalized = path10.replaceAll("\\", "/");
5154
5154
  const segments = normalized.split("/");
5155
- if (normalized.length === 0 || isAbsolute5(path9) || isAbsolute5(normalized) || /^[A-Za-z]:\//u.test(normalized) || segments.some((segment) => segment.length === 0 || segment === "." || segment === "..")) {
5156
- throw new Error(`Invalid icon manifest artifact path: ${path9}`);
5155
+ if (normalized.length === 0 || isAbsolute5(path10) || isAbsolute5(normalized) || /^[A-Za-z]:\//u.test(normalized) || segments.some((segment) => segment.length === 0 || segment === "." || segment === "..")) {
5156
+ throw new Error(`Invalid icon manifest artifact path: ${path10}`);
5157
5157
  }
5158
5158
  return normalized;
5159
5159
  }
5160
- function readFileBytes(path9) {
5160
+ function readFileBytes(path10) {
5161
5161
  try {
5162
- return readFileSync11(path9);
5162
+ return readFileSync11(path10);
5163
5163
  } catch (error) {
5164
- throw new Error(`Failed to read icon manifest ${path9}: ${formatError5(error)}`);
5164
+ throw new Error(`Failed to read icon manifest ${path10}: ${formatError5(error)}`);
5165
5165
  }
5166
5166
  }
5167
- function requireManifestString(record, key, path9) {
5167
+ function requireManifestString(record, key, path10) {
5168
5168
  const value = record[key];
5169
5169
  if (typeof value !== "string" || value.length === 0) {
5170
- throw new Error(`Invalid icon manifest ${key}: ${path9}`);
5170
+ throw new Error(`Invalid icon manifest ${key}: ${path10}`);
5171
5171
  }
5172
5172
  return value;
5173
5173
  }
@@ -5249,15 +5249,15 @@ function makeEffectiveConfigPathsPortable(manifest, baseDir) {
5249
5249
  ]))
5250
5250
  });
5251
5251
  }
5252
- function toPortablePath(baseDir, path9) {
5253
- if (!isAbsolute5(path9)) {
5254
- return path9;
5252
+ function toPortablePath(baseDir, path10) {
5253
+ if (!isAbsolute5(path10)) {
5254
+ return path10;
5255
5255
  }
5256
- const relativePath = relative5(baseDir, path9);
5256
+ const relativePath = relative5(baseDir, path10);
5257
5257
  if (relativePath.length > 0 && !relativePath.startsWith("..") && !isAbsolute5(relativePath)) {
5258
5258
  return relativePath;
5259
5259
  }
5260
- return path9;
5260
+ return path10;
5261
5261
  }
5262
5262
  function createBuildId() {
5263
5263
  const now = /* @__PURE__ */ new Date();
@@ -5619,20 +5619,20 @@ function listPrecacheEntries(artifactRoot) {
5619
5619
  throw new Error("PWA artifact traversal lost its directory.");
5620
5620
  }
5621
5621
  for (const entry of readdirSync3(directory, { withFileTypes: true })) {
5622
- const path9 = resolve9(directory, entry.name);
5622
+ const path10 = resolve9(directory, entry.name);
5623
5623
  if (entry.isSymbolicLink()) {
5624
- throw new Error(`PWA artifact must not contain symbolic links: ${path9}`);
5624
+ throw new Error(`PWA artifact must not contain symbolic links: ${path10}`);
5625
5625
  }
5626
5626
  if (entry.isDirectory()) {
5627
- pendingDirectories.push(path9);
5627
+ pendingDirectories.push(path10);
5628
5628
  } else if (entry.isFile()) {
5629
- files.push(path9);
5629
+ files.push(path10);
5630
5630
  }
5631
5631
  }
5632
5632
  }
5633
- return files.filter((path9) => !path9.endsWith(".map") && !path9.endsWith(`${sep3}pwa-release.json`) && !path9.endsWith(`${sep3}service-worker.js`)).map((path9) => ({
5634
- url: toPrecacheUrl(artifactRoot, path9),
5635
- source: readFileSync12(path9)
5633
+ return files.filter((path10) => !path10.endsWith(".map") && !path10.endsWith(`${sep3}pwa-release.json`) && !path10.endsWith(`${sep3}service-worker.js`)).map((path10) => ({
5634
+ url: toPrecacheUrl(artifactRoot, path10),
5635
+ source: readFileSync12(path10)
5636
5636
  })).sort((left, right) => compareCodeUnits(left.url, right.url));
5637
5637
  }
5638
5638
  function normalizePrecacheEntries(entries) {
@@ -5656,8 +5656,8 @@ function normalizePrecacheUrls(urls) {
5656
5656
  }
5657
5657
  return normalized.sort(compareCodeUnits);
5658
5658
  }
5659
- function toPrecacheUrl(root, path9) {
5660
- const portablePath = relative6(root, path9).split(sep3).join("/");
5659
+ function toPrecacheUrl(root, path10) {
5660
+ const portablePath = relative6(root, path10).split(sep3).join("/");
5661
5661
  return assertMicrosoftStorePwaPrecacheUrl(`./${portablePath}`);
5662
5662
  }
5663
5663
  function requireGameSpecificPwaId(value) {
@@ -6058,23 +6058,23 @@ function pathsOverlap2(first, second) {
6058
6058
  return isPathWithin2(first, second) || isPathWithin2(second, first);
6059
6059
  }
6060
6060
  function isPathWithin2(root, candidate) {
6061
- const path9 = relative7(root, candidate);
6062
- return path9 === "" || path9 !== ".." && !path9.startsWith(`..${sep4}`) && !isAbsolute6(path9);
6061
+ const path10 = relative7(root, candidate);
6062
+ return path10 === "" || path10 !== ".." && !path10.startsWith(`..${sep4}`) && !isAbsolute6(path10);
6063
6063
  }
6064
- function portablePathComparisonKey(path9) {
6065
- const portablePath = path9.replaceAll("\\", "/").split("/").map((segment) => {
6064
+ function portablePathComparisonKey(path10) {
6065
+ const portablePath = path10.replaceAll("\\", "/").split("/").map((segment) => {
6066
6066
  return segment === "." || segment === ".." ? segment : segment.replace(/[. ]+$/u, "");
6067
6067
  }).join("/");
6068
6068
  return canonicalizeThroughExistingAncestor2(portablePath).normalize("NFC").toLowerCase();
6069
6069
  }
6070
- function canonicalizeThroughExistingAncestor2(path9) {
6071
- const normalizedPath = resolve11(path9);
6070
+ function canonicalizeThroughExistingAncestor2(path10) {
6071
+ const normalizedPath = resolve11(path10);
6072
6072
  const suffix = [];
6073
6073
  let existingAncestor = normalizedPath;
6074
6074
  while (!existsSync10(existingAncestor)) {
6075
6075
  const parent = dirname6(existingAncestor);
6076
6076
  if (parent === existingAncestor) {
6077
- throw new Error(`Cannot resolve an existing ancestor for mini-game output: ${path9}`);
6077
+ throw new Error(`Cannot resolve an existing ancestor for mini-game output: ${path10}`);
6078
6078
  }
6079
6079
  suffix.unshift(basename3(existingAncestor));
6080
6080
  existingAncestor = parent;
@@ -6128,8 +6128,8 @@ function cleanupMiniGameArtifactBackup(backupRoot, removeDirectory = removeMiniG
6128
6128
  reportWarning(`The new mini-game artifact is active, but its prior backup could not be removed: ${backupRoot} (${formatError6(error)}). Remove this backup manually.`);
6129
6129
  }
6130
6130
  }
6131
- function removeMiniGameArtifactBackupDirectory(path9) {
6132
- rmSync5(path9, { force: true, maxRetries: 3, recursive: true, retryDelay: 100 });
6131
+ function removeMiniGameArtifactBackupDirectory(path10) {
6132
+ rmSync5(path10, { force: true, maxRetries: 3, recursive: true, retryDelay: 100 });
6133
6133
  }
6134
6134
  function assertMiniGameRequiredFiles(artifactRoot) {
6135
6135
  for (const file of [
@@ -6169,17 +6169,17 @@ function assertMiniGameJavaScriptSafety(artifactRoot, forbiddenMarkers, forbidde
6169
6169
  }
6170
6170
  }
6171
6171
  }
6172
- function assertMiniGameJavaScriptAstSafety(source, path9, forbiddenGlobals) {
6172
+ function assertMiniGameJavaScriptAstSafety(source, path10, forbiddenGlobals) {
6173
6173
  let ast;
6174
6174
  try {
6175
6175
  ast = parse(source, {
6176
6176
  ecmaVersion: "latest",
6177
- sourceType: path9.toLowerCase().endsWith(".mjs") ? "module" : "script",
6177
+ sourceType: path10.toLowerCase().endsWith(".mjs") ? "module" : "script",
6178
6178
  allowHashBang: true,
6179
6179
  allowReturnOutsideFunction: true
6180
6180
  });
6181
6181
  } catch (error) {
6182
- throw new Error(`Mini-game ${path9} is not valid JavaScript: ${formatError6(error)}`);
6182
+ throw new Error(`Mini-game ${path10} is not valid JavaScript: ${formatError6(error)}`);
6183
6183
  }
6184
6184
  const scopeAnalysis = createMiniGameScopeAnalysis(ast);
6185
6185
  const ancestors = [];
@@ -6194,7 +6194,7 @@ function assertMiniGameJavaScriptAstSafety(source, path9, forbiddenGlobals) {
6194
6194
  if (!isAstRecord(input)) {
6195
6195
  return;
6196
6196
  }
6197
- assertSafeNode(input, ancestors, path9, scopeAnalysis, forbiddenGlobals);
6197
+ assertSafeNode(input, ancestors, path10, scopeAnalysis, forbiddenGlobals);
6198
6198
  for (const [key, value] of Object.entries(input)) {
6199
6199
  if (key !== "start" && key !== "end" && key !== "loc" && key !== "range") {
6200
6200
  ancestors.push({ node: input, childKey: key });
@@ -6204,57 +6204,57 @@ function assertMiniGameJavaScriptAstSafety(source, path9, forbiddenGlobals) {
6204
6204
  }
6205
6205
  }
6206
6206
  }
6207
- function assertSafeNode(node, ancestors, path9, scopeAnalysis, forbiddenGlobals) {
6207
+ function assertSafeNode(node, ancestors, path10, scopeAnalysis, forbiddenGlobals) {
6208
6208
  if (node.type === "ImportExpression") {
6209
- throw new Error(`Mini-game ${path9} contains forbidden dynamic import.`);
6209
+ throw new Error(`Mini-game ${path10} contains forbidden dynamic import.`);
6210
6210
  }
6211
6211
  const parent = ancestors.at(-1)?.node;
6212
6212
  if (forbiddenGlobals.size > 0 && isMiniGameProtectedIntrinsicMutation(node, ancestors, scopeAnalysis)) {
6213
- throw new Error(`Mini-game ${path9} contains forbidden protected intrinsic mutation.`);
6213
+ throw new Error(`Mini-game ${path10} contains forbidden protected intrinsic mutation.`);
6214
6214
  }
6215
6215
  if (isMiniGameFunctionNode(node) && (parent?.type === "MethodDefinition" && parent.value === node || parent?.type === "PropertyDefinition" && parent.value === node || parent?.type === "Property" && parent.value === node) && readMiniGameFunctionReturnValues(node).some((value) => {
6216
6216
  return isReturnedDynamicCodeConstructorSource(value, ancestors, scopeAnalysis);
6217
6217
  })) {
6218
- throw new Error(`Mini-game ${path9} contains forbidden dynamic-code constructor.`);
6218
+ throw new Error(`Mini-game ${path10} contains forbidden dynamic-code constructor.`);
6219
6219
  }
6220
6220
  if (node.type === "Identifier" && typeof node.name === "string" && isExecutableIdentifierReference(ancestors)) {
6221
6221
  const scope = scopeAnalysis.scopeByNode.get(node) ?? scopeAnalysis.programScope;
6222
6222
  const binding = resolveMiniGameBinding(node.name, scope);
6223
6223
  if (binding === void 0 && forbiddenGlobals.has(node.name)) {
6224
- throw new Error(`Mini-game ${path9} contains forbidden platform global ${node.name}.`);
6224
+ throw new Error(`Mini-game ${path10} contains forbidden platform global ${node.name}.`);
6225
6225
  }
6226
6226
  if (binding !== void 0 && isInvocationArgument(node, ancestors) && (scopeAnalysis.dynamicCodeConstructorAliases.has(binding) || scopeAnalysis.dynamicCodeConstructorContainers.has(binding) || scopeAnalysis.dynamicCodeConstructorFactories.has(binding) || scopeAnalysis.dynamicCodeConstructorContainerFactories.has(binding))) {
6227
- throw new Error(`Mini-game ${path9} contains forbidden dynamic-code constructor.`);
6227
+ throw new Error(`Mini-game ${path10} contains forbidden dynamic-code constructor.`);
6228
6228
  }
6229
6229
  if (node.name === "eval") {
6230
- throw new Error(`Mini-game ${path9} contains forbidden eval.`);
6230
+ throw new Error(`Mini-game ${path10} contains forbidden eval.`);
6231
6231
  }
6232
6232
  if (node.name === "Function") {
6233
- throw new Error(`Mini-game ${path9} contains forbidden Function constructor.`);
6233
+ throw new Error(`Mini-game ${path10} contains forbidden Function constructor.`);
6234
6234
  }
6235
6235
  if (node.name === "importScripts" && !isTypeofReference(node, ancestors)) {
6236
- throw new Error(`Mini-game ${path9} contains forbidden importScripts.`);
6236
+ throw new Error(`Mini-game ${path10} contains forbidden importScripts.`);
6237
6237
  }
6238
6238
  }
6239
6239
  if (node.type === "MemberExpression") {
6240
6240
  const propertyNames = readMiniGameMemberNames(node, ancestors, scopeAnalysis);
6241
6241
  if (node.computed === true && propertyNames.size === 0 && isGlobalObjectAliasSource(node.object, ancestors, scopeAnalysis) && !isMiniGameSymbolValue(node.property, ancestors, scopeAnalysis)) {
6242
- throw new Error(`Mini-game ${path9} contains forbidden computed global read.`);
6242
+ throw new Error(`Mini-game ${path10} contains forbidden computed global read.`);
6243
6243
  }
6244
6244
  const forbiddenPlatformGlobal = [...propertyNames].find((propertyName) => {
6245
6245
  return forbiddenGlobals.has(propertyName);
6246
6246
  });
6247
6247
  if (forbiddenPlatformGlobal !== void 0) {
6248
- throw new Error(`Mini-game ${path9} contains forbidden platform global ${forbiddenPlatformGlobal}.`);
6248
+ throw new Error(`Mini-game ${path10} contains forbidden platform global ${forbiddenPlatformGlobal}.`);
6249
6249
  }
6250
6250
  const forbiddenDynamicCodeProperty = [...propertyNames].find((propertyName) => {
6251
6251
  return ["eval", "Function", "importScripts"].includes(propertyName);
6252
6252
  });
6253
6253
  if (forbiddenDynamicCodeProperty !== void 0 && (node.computed === true || isGlobalObjectAliasSource(node.object, ancestors, scopeAnalysis)) && !isTypeofReference(node, ancestors)) {
6254
- throw new Error(`Mini-game ${path9} contains forbidden ${forbiddenDynamicCodeProperty}.`);
6254
+ throw new Error(`Mini-game ${path10} contains forbidden ${forbiddenDynamicCodeProperty}.`);
6255
6255
  }
6256
6256
  if (isInvocationArgument(node, ancestors) && isDynamicCodeConstructorSource(node, ancestors, scopeAnalysis)) {
6257
- throw new Error(`Mini-game ${path9} contains forbidden dynamic-code constructor.`);
6257
+ throw new Error(`Mini-game ${path10} contains forbidden dynamic-code constructor.`);
6258
6258
  }
6259
6259
  }
6260
6260
  if (node.type === "Property") {
@@ -6264,17 +6264,17 @@ function assertSafeNode(node, ancestors, path9, scopeAnalysis, forbiddenGlobals)
6264
6264
  return forbiddenGlobals.has(propertyName);
6265
6265
  });
6266
6266
  if (isObjectPatternProperty && forbiddenPlatformGlobal !== void 0) {
6267
- throw new Error(`Mini-game ${path9} contains forbidden platform global ${forbiddenPlatformGlobal}.`);
6267
+ throw new Error(`Mini-game ${path10} contains forbidden platform global ${forbiddenPlatformGlobal}.`);
6268
6268
  }
6269
6269
  if (isGlobalObjectDestructuring(ancestors, scopeAnalysis)) {
6270
6270
  if (node.computed === true) {
6271
- throw new Error(`Mini-game ${path9} contains forbidden computed destructuring.`);
6271
+ throw new Error(`Mini-game ${path10} contains forbidden computed destructuring.`);
6272
6272
  }
6273
6273
  const forbiddenDynamicCodeProperty = [...propertyNames].find((propertyName) => {
6274
6274
  return ["eval", "Function", "importScripts"].includes(propertyName);
6275
6275
  });
6276
6276
  if (forbiddenDynamicCodeProperty !== void 0) {
6277
- throw new Error(`Mini-game ${path9} contains forbidden ${forbiddenDynamicCodeProperty} destructuring.`);
6277
+ throw new Error(`Mini-game ${path10} contains forbidden ${forbiddenDynamicCodeProperty} destructuring.`);
6278
6278
  }
6279
6279
  }
6280
6280
  }
@@ -6283,35 +6283,35 @@ function assertSafeNode(node, ancestors, path9, scopeAnalysis, forbiddenGlobals)
6283
6283
  const arguments_ = Array.isArray(node.arguments) ? node.arguments : [];
6284
6284
  const firstArgument = arguments_[0];
6285
6285
  if (isDynamicCodeConstructorInvocation(node.callee, arguments_, ancestors, scopeAnalysis)) {
6286
- throw new Error(`Mini-game ${path9} contains forbidden dynamic-code constructor.`);
6286
+ throw new Error(`Mini-game ${path10} contains forbidden dynamic-code constructor.`);
6287
6287
  }
6288
6288
  if (isUnknownComputedGlobalMember(node.callee, ancestors, scopeAnalysis)) {
6289
- throw new Error(`Mini-game ${path9} contains forbidden computed global call.`);
6289
+ throw new Error(`Mini-game ${path10} contains forbidden computed global call.`);
6290
6290
  }
6291
6291
  if (isReflectiveDynamicCodeGlobalRead(node, ancestors, scopeAnalysis, forbiddenGlobals)) {
6292
- throw new Error(`Mini-game ${path9} contains forbidden reflective global lookup.`);
6292
+ throw new Error(`Mini-game ${path10} contains forbidden reflective global lookup.`);
6293
6293
  }
6294
6294
  if (calleeNames.has("createElement") && resolveMiniGameStaticStrings(firstArgument, ancestors, scopeAnalysis).has("script")) {
6295
- throw new Error(`Mini-game ${path9} contains forbidden script element creation.`);
6295
+ throw new Error(`Mini-game ${path10} contains forbidden script element creation.`);
6296
6296
  }
6297
6297
  }
6298
6298
  if (node.type === "NewExpression" && isAstRecord(node.callee)) {
6299
6299
  const calleeNames = readMiniGameMemberNames(node.callee, ancestors, scopeAnalysis);
6300
6300
  if (isDynamicCodeConstructorSource(node.callee, ancestors, scopeAnalysis)) {
6301
- throw new Error(`Mini-game ${path9} contains forbidden dynamic-code constructor.`);
6301
+ throw new Error(`Mini-game ${path10} contains forbidden dynamic-code constructor.`);
6302
6302
  }
6303
6303
  if (isUnknownComputedGlobalMember(node.callee, ancestors, scopeAnalysis)) {
6304
- throw new Error(`Mini-game ${path9} contains forbidden computed global construction.`);
6304
+ throw new Error(`Mini-game ${path10} contains forbidden computed global construction.`);
6305
6305
  }
6306
6306
  const forbiddenWorker = [...calleeNames].find((calleeName) => {
6307
6307
  return calleeName === "Worker" || calleeName === "SharedWorker";
6308
6308
  });
6309
6309
  if (forbiddenWorker !== void 0) {
6310
- throw new Error(`Mini-game ${path9} contains forbidden ${forbiddenWorker} construction.`);
6310
+ throw new Error(`Mini-game ${path10} contains forbidden ${forbiddenWorker} construction.`);
6311
6311
  }
6312
6312
  }
6313
6313
  if (node.type === "TaggedTemplateExpression" && isDynamicCodeConstructorSource(node.tag, ancestors, scopeAnalysis)) {
6314
- throw new Error(`Mini-game ${path9} contains forbidden dynamic-code constructor.`);
6314
+ throw new Error(`Mini-game ${path10} contains forbidden dynamic-code constructor.`);
6315
6315
  }
6316
6316
  }
6317
6317
  function isInvocationArgument(node, ancestors) {
@@ -8162,10 +8162,10 @@ function createEvidence(input, files, effectiveTargetConfig, iconManifest, packa
8162
8162
  files
8163
8163
  };
8164
8164
  }
8165
- function requireEvidenceFile(artifactRoot, files, path9) {
8166
- const file = files.find((candidate) => candidate.path === path9);
8167
- if (file === void 0 || !existsSync10(join5(artifactRoot, path9))) {
8168
- throw new Error(`Mini-game artifact is missing required evidence file: ${path9}`);
8165
+ function requireEvidenceFile(artifactRoot, files, path10) {
8166
+ const file = files.find((candidate) => candidate.path === path10);
8167
+ if (file === void 0 || !existsSync10(join5(artifactRoot, path10))) {
8168
+ throw new Error(`Mini-game artifact is missing required evidence file: ${path10}`);
8169
8169
  }
8170
8170
  return file;
8171
8171
  }
@@ -8239,9 +8239,9 @@ function verifyNamedDigest(artifactRoot, reference, expectedPath, label) {
8239
8239
  throw new Error(`Mini-game artifact ${label} digest mismatch.`);
8240
8240
  }
8241
8241
  }
8242
- function readJson(path9, label) {
8242
+ function readJson(path10, label) {
8243
8243
  try {
8244
- return JSON.parse(readFileSync13(path9, "utf8"));
8244
+ return JSON.parse(readFileSync13(path10, "utf8"));
8245
8245
  } catch (error) {
8246
8246
  throw new Error(`${label} is unreadable: ${formatError6(error)}`);
8247
8247
  }
@@ -8308,8 +8308,8 @@ function assertWechatAppId(appId, production) {
8308
8308
  throw new Error("WeChat Mini Game app id must be a valid AppID or the staging placeholder.");
8309
8309
  }
8310
8310
  }
8311
- function writeJson(path9, input) {
8312
- writeFileSync9(path9, `${JSON.stringify(input, null, 2)}
8311
+ function writeJson(path10, input) {
8312
+ writeFileSync9(path10, `${JSON.stringify(input, null, 2)}
8313
8313
  `);
8314
8314
  }
8315
8315
 
@@ -8425,7 +8425,7 @@ function isProcessAlive(pid) {
8425
8425
  }
8426
8426
 
8427
8427
  // node_modules/.cache/mpgd-native-build/tools/target/native-build-execution.js
8428
- import { existsSync as existsSync20, mkdirSync as mkdirSync11, mkdtempSync as mkdtempSync4, readdirSync as readdirSync6, rmSync as rmSync10, statSync as statSync6 } from "node:fs";
8428
+ import { existsSync as existsSync21, mkdirSync as mkdirSync11, mkdtempSync as mkdtempSync4, readdirSync as readdirSync6, rmSync as rmSync10, statSync as statSync6 } from "node:fs";
8429
8429
  import { tmpdir as tmpdir3 } from "node:os";
8430
8430
  import { dirname as dirname8, isAbsolute as isAbsolute9, join as join8 } from "node:path";
8431
8431
 
@@ -9171,16 +9171,73 @@ function createNativeShellStage(input) {
9171
9171
  }
9172
9172
  }
9173
9173
 
9174
+ // node_modules/.cache/mpgd-native-build/tools/target/native-shell-csp.js
9175
+ import { existsSync as existsSync16, lstatSync as lstatSync9, readFileSync as readFileSync16, writeFileSync as writeFileSync12 } from "node:fs";
9176
+ import path6 from "node:path";
9177
+ var capacitorShellContentSecurityPolicy = [
9178
+ "default-src 'self'",
9179
+ "script-src 'self' 'wasm-unsafe-eval'",
9180
+ "style-src 'self' 'unsafe-inline'",
9181
+ "img-src 'self' data: blob:",
9182
+ "font-src 'self' data:",
9183
+ "media-src 'self' data: blob:",
9184
+ "connect-src 'self' https: wss:",
9185
+ "worker-src 'self' blob:",
9186
+ "object-src 'none'",
9187
+ "base-uri 'self'",
9188
+ "form-action 'none'"
9189
+ ].join("; ");
9190
+ var metaTagPattern = /<meta\b[^>]*>/giu;
9191
+ var httpEquivPattern = /\bhttp-equiv\s*=\s*(?:"([^"]*)"|'([^']*)'|([^\s"'=<>`]+))/iu;
9192
+ var headOpenPattern = /<head\b[^>]*>/iu;
9193
+ function hasEnforcingCspMeta(html) {
9194
+ for (const [tag] of html.matchAll(metaTagPattern)) {
9195
+ const httpEquiv = httpEquivPattern.exec(tag);
9196
+ if (httpEquiv === null) {
9197
+ continue;
9198
+ }
9199
+ const value = httpEquiv[1] ?? httpEquiv[2] ?? httpEquiv[3] ?? "";
9200
+ if (value.toLowerCase() === "content-security-policy") {
9201
+ return true;
9202
+ }
9203
+ }
9204
+ return false;
9205
+ }
9206
+ var capacitorShellCspMetaTag = `<meta http-equiv="Content-Security-Policy" content="${capacitorShellContentSecurityPolicy}">`;
9207
+ function injectCapacitorShellCsp(html) {
9208
+ if (hasEnforcingCspMeta(html)) {
9209
+ return html;
9210
+ }
9211
+ const head = headOpenPattern.exec(html);
9212
+ if (head === null) {
9213
+ throw new Error("Capacitor shell index.html must contain a <head> element for its CSP.");
9214
+ }
9215
+ const insertAt = head.index + head[0].length;
9216
+ return `${html.slice(0, insertAt)}
9217
+ ${capacitorShellCspMetaTag}${html.slice(insertAt)}`;
9218
+ }
9219
+ function applyCapacitorShellCsp(webDir) {
9220
+ const indexFile = path6.join(webDir, "index.html");
9221
+ if (!existsSync16(indexFile) || lstatSync9(indexFile).isSymbolicLink()) {
9222
+ throw new Error("Capacitor shell web bundle must contain a regular index.html.");
9223
+ }
9224
+ const html = readFileSync16(indexFile, "utf8");
9225
+ const hardened = injectCapacitorShellCsp(html);
9226
+ if (hardened !== html) {
9227
+ writeFileSync12(indexFile, hardened);
9228
+ }
9229
+ }
9230
+
9174
9231
  // node_modules/.cache/mpgd-native-build/tools/target/native-ios-inspection.js
9175
9232
  import { spawnSync as spawnSync3 } from "node:child_process";
9176
- import { existsSync as existsSync16, mkdtempSync as mkdtempSync3, readFileSync as readFileSync16, rmSync as rmSync9, statSync as statSync4 } from "node:fs";
9233
+ import { existsSync as existsSync17, mkdtempSync as mkdtempSync3, readFileSync as readFileSync17, rmSync as rmSync9, statSync as statSync4 } from "node:fs";
9177
9234
  import { tmpdir as tmpdir2 } from "node:os";
9178
- import path6 from "node:path";
9235
+ import path7 from "node:path";
9179
9236
  function inspectSignedIosArchive(archive, input) {
9180
- return inspectSignedIosApplication(path6.join(archive, "Products/Applications/App.app"), input);
9237
+ return inspectSignedIosApplication(path7.join(archive, "Products/Applications/App.app"), input);
9181
9238
  }
9182
9239
  function inspectSignedIosIpa(ipa, input) {
9183
- if (!existsSync16(ipa) || !statSync4(ipa).isFile()) {
9240
+ if (!existsSync17(ipa) || !statSync4(ipa).isFile()) {
9184
9241
  throw new Error("iOS store IPA is missing.");
9185
9242
  }
9186
9243
  const runner = input.runner ?? { run: runCommand2 };
@@ -9196,24 +9253,24 @@ function inspectSignedIosIpa(ipa, input) {
9196
9253
  if (appManifests.length !== 1) {
9197
9254
  throw new Error("iOS store IPA must contain exactly one app manifest.");
9198
9255
  }
9199
- const appRelative = path6.dirname(appManifests[0] ?? "");
9200
- const extracted = mkdtempSync3(path6.join(tmpdir2(), "mpgd-ios-inspection-"));
9256
+ const appRelative = path7.dirname(appManifests[0] ?? "");
9257
+ const extracted = mkdtempSync3(path7.join(tmpdir2(), "mpgd-ios-inspection-"));
9201
9258
  try {
9202
9259
  const result = runner.run("unzip", ["-q", ipa, "-d", extracted]);
9203
9260
  if (result.status !== 0) {
9204
9261
  throw new Error("iOS store IPA could not be extracted.");
9205
9262
  }
9206
- return inspectSignedIosApplication(path6.join(extracted, appRelative), input);
9263
+ return inspectSignedIosApplication(path7.join(extracted, appRelative), input);
9207
9264
  } finally {
9208
9265
  rmSync9(extracted, { recursive: true, force: true });
9209
9266
  }
9210
9267
  }
9211
9268
  function inspectSignedIosApplication(appPath, input) {
9212
- const plist = path6.join(appPath, "Info.plist");
9213
- if (!existsSync16(plist) || !statSync4(plist).isFile()) {
9269
+ const plist = path7.join(appPath, "Info.plist");
9270
+ if (!existsSync17(plist) || !statSync4(plist).isFile()) {
9214
9271
  throw new Error("Signed iOS app manifest is missing.");
9215
9272
  }
9216
- if (!existsSync16(path6.join(appPath, "Assets.car")) || existsSync16(path6.join(appPath, "Info-Smoke.plist"))) {
9273
+ if (!existsSync17(path7.join(appPath, "Assets.car")) || existsSync17(path7.join(appPath, "Info-Smoke.plist"))) {
9217
9274
  throw new Error("Signed iOS app contains smoke assets or omits release icons.");
9218
9275
  }
9219
9276
  const runner = input.runner ?? { run: runCommand2 };
@@ -9241,21 +9298,21 @@ ${signingInfo.stderr}`;
9241
9298
  return [name, expected];
9242
9299
  }));
9243
9300
  const configFiles = [
9244
- path6.join(appPath, "capacitor.config.json"),
9245
- path6.join(appPath, "public/capacitor.config.json")
9301
+ path7.join(appPath, "capacitor.config.json"),
9302
+ path7.join(appPath, "public/capacitor.config.json")
9246
9303
  ];
9247
- if (!configFiles.some((file) => existsSync16(file))) {
9304
+ if (!configFiles.some((file) => existsSync17(file))) {
9248
9305
  throw new Error("Signed iOS app Capacitor configuration is missing.");
9249
9306
  }
9250
9307
  for (const configFile of configFiles) {
9251
- if (existsSync16(configFile)) {
9308
+ if (existsSync17(configFile)) {
9252
9309
  assertNoDebugServer(configFile);
9253
9310
  }
9254
9311
  }
9255
9312
  return { ...observed, teamId: input.expectedTeamId, signed: true };
9256
9313
  }
9257
9314
  function assertNoDebugServer(file) {
9258
- const value = JSON.parse(readFileSync16(file, "utf8"));
9315
+ const value = JSON.parse(readFileSync17(file, "utf8"));
9259
9316
  if (typeof value !== "object" || value === null || Array.isArray(value)) {
9260
9317
  throw new Error("Signed iOS app has malformed Capacitor configuration.");
9261
9318
  }
@@ -9284,8 +9341,8 @@ function runCommand2(command, args) {
9284
9341
 
9285
9342
  // node_modules/.cache/mpgd-native-build/tools/target/native-ios-signing.js
9286
9343
  import { spawnSync as spawnSync4 } from "node:child_process";
9287
- import { existsSync as existsSync17, statSync as statSync5 } from "node:fs";
9288
- import path7 from "node:path";
9344
+ import { existsSync as existsSync18, statSync as statSync5 } from "node:fs";
9345
+ import path8 from "node:path";
9289
9346
  function resolveIosSigningPlan(environment, mode) {
9290
9347
  const teamId = environment.MPGD_IOS_TEAM_ID?.trim();
9291
9348
  if (teamId === void 0 || !/^[A-Z0-9]{10}$/u.test(teamId)) {
@@ -9318,8 +9375,8 @@ function resolveIosSigningPlan(environment, mode) {
9318
9375
  if (configuredExportFile === void 0 || configuredExportFile.trim() === "") {
9319
9376
  throw new Error("iOS store export requires MPGD_IOS_EXPORT_OPTIONS_PLIST.");
9320
9377
  }
9321
- const exportOptionsPlist = path7.resolve(configuredExportFile);
9322
- if (!existsSync17(exportOptionsPlist) || !statSync5(exportOptionsPlist).isFile()) {
9378
+ const exportOptionsPlist = path8.resolve(configuredExportFile);
9379
+ if (!existsSync18(exportOptionsPlist) || !statSync5(exportOptionsPlist).isFile()) {
9323
9380
  throw new Error("iOS export options plist must be an existing host file.");
9324
9381
  }
9325
9382
  const method = spawnSync4("/usr/libexec/PlistBuddy", ["-c", "Print :method", exportOptionsPlist], {
@@ -9333,12 +9390,12 @@ function resolveIosSigningPlan(environment, mode) {
9333
9390
  }
9334
9391
 
9335
9392
  // node_modules/.cache/mpgd-native-build/tools/target/native-release-identity.js
9336
- import { existsSync as existsSync19, readFileSync as readFileSync18 } from "node:fs";
9393
+ import { existsSync as existsSync20, readFileSync as readFileSync19 } from "node:fs";
9337
9394
  import { dirname as dirname7, isAbsolute as isAbsolute8, join as join7, relative as relative8, resolve as resolve13 } from "node:path";
9338
9395
 
9339
9396
  // node_modules/.cache/mpgd-native-build/packages/cli/src/capacitor-shell-starter.js
9340
- import { chmodSync as chmodSync2, existsSync as existsSync18, lstatSync as lstatSync9, mkdirSync as mkdirSync10, readdirSync as readdirSync5, readFileSync as readFileSync17, realpathSync as realpathSync8, renameSync as renameSync4, unlinkSync as unlinkSync2, writeFileSync as writeFileSync12 } from "node:fs";
9341
- import path8 from "node:path";
9397
+ import { chmodSync as chmodSync2, existsSync as existsSync19, lstatSync as lstatSync10, mkdirSync as mkdirSync10, readdirSync as readdirSync5, readFileSync as readFileSync18, realpathSync as realpathSync8, renameSync as renameSync4, unlinkSync as unlinkSync2, writeFileSync as writeFileSync13 } from "node:fs";
9398
+ import path9 from "node:path";
9342
9399
  import { DOMParser as DOMParser2 } from "@xmldom/xmldom";
9343
9400
 
9344
9401
  // node_modules/.cache/mpgd-native-build/packages/cli/src/native-shell-identity.js
@@ -9720,8 +9777,39 @@ var javaKeywords = new Set(`
9720
9777
  synchronized this throw throws transient try void volatile while true false null record sealed
9721
9778
  permits var yield
9722
9779
  `.trim().split(/\s+/u));
9780
+ var androidBackupDomains = ["root", "file", "database", "sharedpref", "external"];
9781
+ var androidBackupExcludes = androidBackupDomains.map((domain) => `<exclude domain="${domain}" path="." />`);
9782
+ var androidBackupRulesXml = [
9783
+ '<?xml version="1.0" encoding="utf-8"?>',
9784
+ "<!--",
9785
+ " Generated by mpgd target init capacitor. WebView storage and the",
9786
+ " game-services SharedPreferences save store hold player data, so the whole",
9787
+ " private data tree stays out of Android backups.",
9788
+ "-->",
9789
+ "<full-backup-content>",
9790
+ ...androidBackupExcludes.map((line) => ` ${line}`),
9791
+ "</full-backup-content>",
9792
+ ""
9793
+ ].join("\n");
9794
+ var androidDataExtractionRulesXml = [
9795
+ '<?xml version="1.0" encoding="utf-8"?>',
9796
+ "<!--",
9797
+ " Generated by mpgd target init capacitor. WebView storage and the",
9798
+ " game-services SharedPreferences save store hold player data, so neither",
9799
+ " cloud backup nor Android 12+ device-to-device transfer may copy them.",
9800
+ "-->",
9801
+ "<data-extraction-rules>",
9802
+ " <cloud-backup>",
9803
+ ...androidBackupExcludes.map((line) => ` ${line}`),
9804
+ " </cloud-backup>",
9805
+ " <device-transfer>",
9806
+ ...androidBackupExcludes.map((line) => ` ${line}`),
9807
+ " </device-transfer>",
9808
+ "</data-extraction-rules>",
9809
+ ""
9810
+ ].join("\n");
9723
9811
  function assertAndroidLauncherClasses(nativeDirectory, gradle) {
9724
- const application = readAndroidApplication(path8.join(nativeDirectory, "app/src/main/AndroidManifest.xml"));
9812
+ const application = readAndroidApplication(path9.join(nativeDirectory, "app/src/main/AndroidManifest.xml"));
9725
9813
  if (application === void 0) {
9726
9814
  throw new Error("Existing android project launcher activity is missing.");
9727
9815
  }
@@ -9729,8 +9817,8 @@ function assertAndroidLauncherClasses(nativeDirectory, gradle) {
9729
9817
  const manifestRoot = application.parentNode;
9730
9818
  const manifestPackage = manifestRoot?.getAttribute("package");
9731
9819
  const namespace = /\bnamespace\s*(?:=\s*)?["']([A-Za-z_][\w]*(?:\.[A-Za-z_][\w]*)+)["']/u.exec(stripGradleComments(gradle))?.[1] ?? (manifestPackage === null || manifestPackage === "" ? void 0 : manifestPackage);
9732
- const releaseFile = path8.join(nativeDirectory, "app/src/release/AndroidManifest.xml");
9733
- const release = existsSync18(releaseFile) ? readAndroidApplication(releaseFile, false) : void 0;
9820
+ const releaseFile = path9.join(nativeDirectory, "app/src/release/AndroidManifest.xml");
9821
+ const release = existsSync19(releaseFile) ? readAndroidApplication(releaseFile, false) : void 0;
9734
9822
  if (release !== void 0) {
9735
9823
  assertAndroidLauncherEnabled(release, "Release application");
9736
9824
  }
@@ -9840,7 +9928,7 @@ function resolvesAndroidClass(nativeDirectory, qualified, sourceFiles, visited,
9840
9928
  if (!isNativeFile(nativeDirectory, relative10)) {
9841
9929
  continue;
9842
9930
  }
9843
- const source = stripSourceCommentsAndStrings(readFileSync17(path8.join(nativeDirectory, relative10), "utf8"));
9931
+ const source = stripSourceCommentsAndStrings(readFileSync18(path9.join(nativeDirectory, relative10), "utf8"));
9844
9932
  const declaredPackage = /\bpackage\s+([A-Za-z_][\w]*(?:\.[A-Za-z_][\w]*)+)\s*;?/u.exec(source)?.[1];
9845
9933
  if (declaredPackage !== packageName) {
9846
9934
  continue;
@@ -9896,15 +9984,15 @@ function listNativeFiles(nativeDirectory, relativeRoot, extension) {
9896
9984
  const files = [];
9897
9985
  while (pending.length > 0) {
9898
9986
  const relative10 = pending.pop() ?? "";
9899
- const full = path8.join(nativeDirectory, relative10);
9900
- if (!existsSync18(full) || lstatSync9(full).isSymbolicLink()) {
9987
+ const full = path9.join(nativeDirectory, relative10);
9988
+ if (!existsSync19(full) || lstatSync10(full).isSymbolicLink()) {
9901
9989
  continue;
9902
9990
  }
9903
9991
  for (const entry of readdirSync5(full, { withFileTypes: true })) {
9904
9992
  if (entry.isSymbolicLink()) {
9905
9993
  continue;
9906
9994
  }
9907
- const child = path8.join(relative10, entry.name);
9995
+ const child = path9.join(relative10, entry.name);
9908
9996
  if (entry.isDirectory()) {
9909
9997
  pending.push(child);
9910
9998
  } else if (entry.isFile() && entry.name.endsWith(extension)) {
@@ -10110,7 +10198,7 @@ function assertReferencedIosFiles(nativeDirectory, project, infoRelative) {
10110
10198
  throw new Error(`Existing ios project is incomplete; referenced app file ${relative10} is missing.`);
10111
10199
  }
10112
10200
  }
10113
- const info = readFileSync17(path8.join(nativeDirectory, infoRelative), "utf8");
10201
+ const info = readFileSync18(path9.join(nativeDirectory, infoRelative), "utf8");
10114
10202
  assertSceneDelegateFiles(nativeDirectory, info, "Release", compiledSources);
10115
10203
  return compiledSources;
10116
10204
  }
@@ -10241,7 +10329,7 @@ function readPbxGroupPath(project, parents, referenceId) {
10241
10329
  const groupPath = /\bpath\s*=\s*(?:"([^"]+)"|([^;]+))\s*;/u.exec(group);
10242
10330
  const value = (groupPath?.[1] ?? groupPath?.[2])?.trim();
10243
10331
  if (value !== void 0) {
10244
- if (value.includes("$") || path8.isAbsolute(value)) {
10332
+ if (value.includes("$") || path9.isAbsolute(value)) {
10245
10333
  throw new Error("Existing ios project build input group path is unsupported.");
10246
10334
  }
10247
10335
  parts.push(value);
@@ -10263,7 +10351,7 @@ function assertPbxFileReference(nativeDirectory, project, referenceId, parentGro
10263
10351
  }
10264
10352
  const relative10 = /\bpath\s*=\s*(?:"([^"]+)"|([^;]+))\s*;/u.exec(reference);
10265
10353
  const filePath = (relative10?.[1] ?? relative10?.[2])?.trim();
10266
- if (filePath === void 0 || filePath.includes("$") || path8.isAbsolute(filePath)) {
10354
+ if (filePath === void 0 || filePath.includes("$") || path9.isAbsolute(filePath)) {
10267
10355
  throw new Error("Existing ios project App build input path is unsupported.");
10268
10356
  }
10269
10357
  if (filePath === "public" || filePath === "capacitor.config.json") {
@@ -10290,19 +10378,19 @@ function assertPbxFileReference(nativeDirectory, project, referenceId, parentGro
10290
10378
  return [resolved];
10291
10379
  }
10292
10380
  function isNativeEntry(directory, relative10) {
10293
- const file = path8.resolve(directory, relative10);
10294
- const within = path8.relative(directory, file);
10295
- if (within === "" || within.startsWith("..") || path8.isAbsolute(within)) {
10381
+ const file = path9.resolve(directory, relative10);
10382
+ const within = path9.relative(directory, file);
10383
+ if (within === "" || within.startsWith("..") || path9.isAbsolute(within)) {
10296
10384
  return false;
10297
10385
  }
10298
10386
  let current = directory;
10299
- for (const segment of within.split(path8.sep)) {
10300
- current = path8.join(current, segment);
10301
- if (!existsSync18(current) || lstatSync9(current).isSymbolicLink()) {
10387
+ for (const segment of within.split(path9.sep)) {
10388
+ current = path9.join(current, segment);
10389
+ if (!existsSync19(current) || lstatSync10(current).isSymbolicLink()) {
10302
10390
  return false;
10303
10391
  }
10304
10392
  }
10305
- return lstatSync9(file).isFile() || lstatSync9(file).isDirectory();
10393
+ return lstatSync10(file).isFile() || lstatSync10(file).isDirectory();
10306
10394
  }
10307
10395
  function assertSceneDelegateFiles(nativeDirectory, source, label, compiledSources) {
10308
10396
  const values = parsePlistDictionary(source, label);
@@ -10331,7 +10419,7 @@ function assertSceneDelegateFiles(nativeDirectory, source, label, compiledSource
10331
10419
  if (!compiledSources.has(relative10)) {
10332
10420
  return false;
10333
10421
  }
10334
- const text = stripSourceCommentsAndStrings(readFileSync17(path8.join(nativeDirectory, relative10), "utf8"));
10422
+ const text = stripSourceCommentsAndStrings(readFileSync18(path9.join(nativeDirectory, relative10), "utf8"));
10335
10423
  return hasUsableTopLevelSwiftSceneDelegate(text, className);
10336
10424
  })) {
10337
10425
  throw new Error(`Existing ios project ${label} scene delegate ${delegate} is missing from App Sources.`);
@@ -10356,29 +10444,29 @@ function hasUsableTopLevelSwiftSceneDelegate(source, className) {
10356
10444
  return false;
10357
10445
  }
10358
10446
  function assertAndroidManifestResources(nativeDirectory) {
10359
- const manifestFiles = ["main", "release"].map((sourceSet) => path8.join(nativeDirectory, `app/src/${sourceSet}/AndroidManifest.xml`)).filter((file) => existsSync18(file));
10360
- const resourceRoots = ["main", "release"].map((sourceSet) => path8.join(nativeDirectory, `app/src/${sourceSet}/res`));
10447
+ const manifestFiles = ["main", "release"].map((sourceSet) => path9.join(nativeDirectory, `app/src/${sourceSet}/AndroidManifest.xml`)).filter((file) => existsSync19(file));
10448
+ const resourceRoots = ["main", "release"].map((sourceSet) => path9.join(nativeDirectory, `app/src/${sourceSet}/res`));
10361
10449
  const references = manifestFiles.flatMap((file) => {
10362
- const manifest = readFileSync17(file, "utf8").replace(/<!--[\s\S]*?-->/gu, "");
10450
+ const manifest = readFileSync18(file, "utf8").replace(/<!--[\s\S]*?-->/gu, "");
10363
10451
  return [...manifest.matchAll(/(?<![\w+])@([a-z]+)\/([A-Za-z_][A-Za-z0-9_.]*)/gu)];
10364
10452
  });
10365
10453
  for (const reference of references) {
10366
10454
  const type = reference[1] ?? "";
10367
10455
  const name = reference[2] ?? "";
10368
10456
  const found = resourceRoots.some((resourceRoot) => {
10369
- if (!existsSync18(resourceRoot)) {
10457
+ if (!existsSync19(resourceRoot)) {
10370
10458
  return false;
10371
10459
  }
10372
10460
  const folders = readdirSync5(resourceRoot, { withFileTypes: true }).filter((entry) => entry.isDirectory()).map((entry) => entry.name);
10373
10461
  return folders.some((folder) => {
10374
10462
  const densityFallback = (type === "mipmap" || type === "drawable") && new RegExp(`^${type}-(?:ldpi|mdpi|hdpi|xhdpi|xxhdpi|xxxhdpi|nodpi|anydpi)$`, "u").test(folder);
10375
10463
  if (folder === type || densityFallback) {
10376
- return readdirSync5(path8.join(resourceRoot, folder)).some((file) => file === `${name}.xml` || file.startsWith(`${name}.`));
10464
+ return readdirSync5(path9.join(resourceRoot, folder)).some((file) => file === `${name}.xml` || file.startsWith(`${name}.`));
10377
10465
  }
10378
10466
  if (folder !== "values") {
10379
10467
  return false;
10380
10468
  }
10381
- return readdirSync5(path8.join(resourceRoot, folder)).some((file) => file.endsWith(".xml") && readAndroidValueResource(path8.join(resourceRoot, folder, file), type, name).length > 0);
10469
+ return readdirSync5(path9.join(resourceRoot, folder)).some((file) => file.endsWith(".xml") && readAndroidValueResource(path9.join(resourceRoot, folder, file), type, name).length > 0);
10382
10470
  });
10383
10471
  });
10384
10472
  if (!found) {
@@ -10391,13 +10479,13 @@ function assertNativeDisplayName(nativeDirectory, platform, expectedDisplayName,
10391
10479
  if (platform === "ios" && !isNativeFile(nativeDirectory, relative10)) {
10392
10480
  throw new Error(`Existing ${platform} project is incomplete; native display name resource is missing.`);
10393
10481
  }
10394
- const source = platform === "ios" ? readFileSync17(path8.join(nativeDirectory, relative10), "utf8") : "";
10482
+ const source = platform === "ios" ? readFileSync18(path9.join(nativeDirectory, relative10), "utf8") : "";
10395
10483
  const labels = platform === "ios" ? [parsePlistDictionary(source, "Release").get("CFBundleDisplayName")].filter((value) => value?.tagName === "string").map((value) => value?.textContent ?? "") : [];
10396
10484
  if (platform === "ios" && (labels.length !== 1 || labels[0] !== expectedDisplayName)) {
10397
10485
  throw new Error(`Existing ${platform} project display name differs or cannot be read safely.`);
10398
10486
  }
10399
10487
  if (platform === "android") {
10400
- const main = readAndroidApplication(path8.join(nativeDirectory, "app/src/main/AndroidManifest.xml"));
10488
+ const main = readAndroidApplication(path9.join(nativeDirectory, "app/src/main/AndroidManifest.xml"));
10401
10489
  if (main === void 0) {
10402
10490
  throw new Error("Existing android project application label is missing.");
10403
10491
  }
@@ -10416,8 +10504,8 @@ function assertNativeDisplayName(nativeDirectory, platform, expectedDisplayName,
10416
10504
  throw new Error("Existing android project launcher label differs from the requested name.");
10417
10505
  }
10418
10506
  }
10419
- const overlayFile = path8.join(nativeDirectory, "app/src/release/AndroidManifest.xml");
10420
- if (existsSync18(overlayFile)) {
10507
+ const overlayFile = path9.join(nativeDirectory, "app/src/release/AndroidManifest.xml");
10508
+ if (existsSync19(overlayFile)) {
10421
10509
  const release = readAndroidApplication(overlayFile, false);
10422
10510
  if (release !== void 0) {
10423
10511
  if (hasAndroidMergerDirective(release)) {
@@ -10427,8 +10515,8 @@ function assertNativeDisplayName(nativeDirectory, platform, expectedDisplayName,
10427
10515
  if (releaseLabel !== null && resolveAndroidLabel(nativeDirectory, releaseLabel) !== expectedDisplayName) {
10428
10516
  throw new Error("Existing android Release application label differs from the requested name.");
10429
10517
  }
10430
- const appBuildFile = ["app/build.gradle", "app/build.gradle.kts"].map((relative11) => path8.join(nativeDirectory, relative11)).find((file) => existsSync18(file));
10431
- const appGradle = appBuildFile === void 0 ? "" : readFileSync17(appBuildFile, "utf8");
10518
+ const appBuildFile = ["app/build.gradle", "app/build.gradle.kts"].map((relative11) => path9.join(nativeDirectory, relative11)).find((file) => existsSync19(file));
10519
+ const appGradle = appBuildFile === void 0 ? "" : readFileSync18(appBuildFile, "utf8");
10432
10520
  const manifestPackage = main.parentNode?.getAttribute("package");
10433
10521
  const namespace = /\bnamespace\s*(?:=\s*)?["']([A-Za-z_][\w]*(?:\.[A-Za-z_][\w]*)+)["']/u.exec(stripGradleComments(appGradle))?.[1] ?? (manifestPackage === null || manifestPackage === "" ? void 0 : manifestPackage);
10434
10522
  const launcherNames = /* @__PURE__ */ new Set();
@@ -10464,21 +10552,21 @@ function assertNativeDisplayName(nativeDirectory, platform, expectedDisplayName,
10464
10552
  }
10465
10553
  }
10466
10554
  function assertAndroidReleaseDisplayName(shellApp, expectedDisplayName) {
10467
- const nativeDirectory = path8.join(shellApp, "android");
10555
+ const nativeDirectory = path9.join(shellApp, "android");
10468
10556
  assertAndroidManifestResources(nativeDirectory);
10469
10557
  assertNativeDisplayName(nativeDirectory, "android", expectedDisplayName);
10470
10558
  }
10471
10559
  function assertAndroidReleaseLauncherIntegrity(shellApp) {
10472
- const nativeDirectory = path8.join(shellApp, "android");
10560
+ const nativeDirectory = path9.join(shellApp, "android");
10473
10561
  const gradleRelative = requireOneNativeFile(nativeDirectory, ["app/build.gradle", "app/build.gradle.kts"], "android");
10474
- const gradle = readFileSync17(path8.join(nativeDirectory, gradleRelative), "utf8");
10562
+ const gradle = readFileSync18(path9.join(nativeDirectory, gradleRelative), "utf8");
10475
10563
  assertAndroidLauncherClasses(nativeDirectory, gradle);
10476
10564
  }
10477
10565
  function assertIosReleaseDisplayName(shellApp, expectedDisplayName) {
10478
- const nativeDirectory = path8.join(shellApp, "ios");
10479
- const projectFile = path8.join(nativeDirectory, "App/App.xcodeproj/project.pbxproj");
10480
- const project = readFileSync17(projectFile, "utf8");
10481
- const infoRelative = path8.join("App", readIosReleaseInfoPlist(project));
10566
+ const nativeDirectory = path9.join(shellApp, "ios");
10567
+ const projectFile = path9.join(nativeDirectory, "App/App.xcodeproj/project.pbxproj");
10568
+ const project = readFileSync18(projectFile, "utf8");
10569
+ const infoRelative = path9.join("App", readIosReleaseInfoPlist(project));
10482
10570
  if (!isNativeFile(nativeDirectory, infoRelative)) {
10483
10571
  throw new Error("Existing ios project Release Info.plist is missing or unsafe.");
10484
10572
  }
@@ -10488,20 +10576,20 @@ function assertIosReleaseDisplayName(shellApp, expectedDisplayName) {
10488
10576
  }
10489
10577
  function assertNoIosLocalizedDisplayNameOverride(nativeDirectory, project) {
10490
10578
  const files = listNativeFiles(nativeDirectory, "App/App", ".strings");
10491
- if (/\bInfoPlist\.strings\b/u.test(project) || isNativeFile(nativeDirectory, "App/InfoPlist.strings") || files.some((relative10) => path8.basename(relative10) === "InfoPlist.strings")) {
10579
+ if (/\bInfoPlist\.strings\b/u.test(project) || isNativeFile(nativeDirectory, "App/InfoPlist.strings") || files.some((relative10) => path9.basename(relative10) === "InfoPlist.strings")) {
10492
10580
  throw new Error("Existing ios project localized InfoPlist.strings overrides are unsupported.");
10493
10581
  }
10494
10582
  }
10495
10583
  function assertIosArchiveScheme(shellApp) {
10496
- const nativeDirectory = path8.join(shellApp, "ios");
10584
+ const nativeDirectory = path9.join(shellApp, "ios");
10497
10585
  const projectRelative = "App/App.xcodeproj/project.pbxproj";
10498
10586
  const schemeRelative = "App/App.xcodeproj/xcshareddata/xcschemes/App.xcscheme";
10499
10587
  if (!isNativeFile(nativeDirectory, projectRelative) || !isNativeFile(nativeDirectory, schemeRelative)) {
10500
10588
  throw new Error("Existing ios project shared App archive scheme is missing or unsafe.");
10501
10589
  }
10502
- const project = readFileSync17(path8.join(nativeDirectory, projectRelative), "utf8");
10590
+ const project = readFileSync18(path9.join(nativeDirectory, projectRelative), "utf8");
10503
10591
  const appTargetId = readIosAppTargetId(project);
10504
- const schemeSource = readFileSync17(path8.join(nativeDirectory, schemeRelative), "utf8");
10592
+ const schemeSource = readFileSync18(path9.join(nativeDirectory, schemeRelative), "utf8");
10505
10593
  const scheme = parseXml(schemeSource, "ios project App archive scheme").documentElement;
10506
10594
  if (scheme?.tagName !== "Scheme") {
10507
10595
  throw new Error("Existing ios project App archive scheme is malformed.");
@@ -10528,7 +10616,7 @@ function hasAndroidMergerDirectiveDeep(element) {
10528
10616
  return hasAndroidMergerDirective(element) || childElements(element).some(hasAndroidMergerDirectiveDeep);
10529
10617
  }
10530
10618
  function readAndroidApplication(file, required = true) {
10531
- const root = parseXml(readFileSync17(file, "utf8"), "android manifest").documentElement;
10619
+ const root = parseXml(readFileSync18(file, "utf8"), "android manifest").documentElement;
10532
10620
  const application = root === null ? void 0 : childElements(root).find((element) => element.tagName === "application");
10533
10621
  if (root?.tagName !== "manifest" || required && application === void 0) {
10534
10622
  throw new Error("Existing android project manifest application is missing.");
@@ -10556,22 +10644,22 @@ function readAndroidString(nativeDirectory, key) {
10556
10644
  if (!/^[A-Za-z_][A-Za-z0-9_]*$/u.test(key)) {
10557
10645
  throw new Error("Existing android project application label is unsupported.");
10558
10646
  }
10559
- const overlay = path8.join(nativeDirectory, "app/src/release/res/values");
10560
- const overlayValues = existsSync18(overlay) && lstatSync9(overlay).isDirectory() ? readdirSync5(overlay).filter((file) => file.endsWith(".xml")).flatMap((file) => readAndroidValueResource(path8.join(overlay, file), "string", key)) : [];
10561
- const main = path8.join(nativeDirectory, "app/src/main/res/values");
10562
- const mainValues = existsSync18(main) && lstatSync9(main).isDirectory() ? readdirSync5(main).filter((file) => file.endsWith(".xml")).flatMap((file) => readAndroidValueResource(path8.join(main, file), "string", key)) : [];
10647
+ const overlay = path9.join(nativeDirectory, "app/src/release/res/values");
10648
+ const overlayValues = existsSync19(overlay) && lstatSync10(overlay).isDirectory() ? readdirSync5(overlay).filter((file) => file.endsWith(".xml")).flatMap((file) => readAndroidValueResource(path9.join(overlay, file), "string", key)) : [];
10649
+ const main = path9.join(nativeDirectory, "app/src/main/res/values");
10650
+ const mainValues = existsSync19(main) && lstatSync10(main).isDirectory() ? readdirSync5(main).filter((file) => file.endsWith(".xml")).flatMap((file) => readAndroidValueResource(path9.join(main, file), "string", key)) : [];
10563
10651
  const values = overlayValues.length > 0 ? overlayValues : mainValues;
10564
10652
  if (values.length !== 1) {
10565
10653
  throw new Error("Existing android project application label resource is missing or ambiguous.");
10566
10654
  }
10567
- const qualified = ["main", "release"].flatMap((sourceSet) => listNativeFiles(nativeDirectory, `app/src/${sourceSet}/res`, ".xml").filter((relative10) => /^values-[^/]+$/u.test(path8.basename(path8.dirname(relative10)))).flatMap((relative10) => readAndroidValueResource(path8.join(nativeDirectory, relative10), "string", key)));
10655
+ const qualified = ["main", "release"].flatMap((sourceSet) => listNativeFiles(nativeDirectory, `app/src/${sourceSet}/res`, ".xml").filter((relative10) => /^values-[^/]+$/u.test(path9.basename(path9.dirname(relative10)))).flatMap((relative10) => readAndroidValueResource(path9.join(nativeDirectory, relative10), "string", key)));
10568
10656
  if (qualified.some((value) => value !== values[0])) {
10569
10657
  throw new Error("Existing android project configuration-qualified application label differs.");
10570
10658
  }
10571
10659
  return values[0] ?? "";
10572
10660
  }
10573
10661
  function readAndroidValueResource(file, type, name) {
10574
- const root = parseXml(readFileSync17(file, "utf8"), "android values resource").documentElement;
10662
+ const root = parseXml(readFileSync18(file, "utf8"), "android values resource").documentElement;
10575
10663
  if (root?.tagName !== "resources") {
10576
10664
  throw new Error("Existing android values resource is malformed.");
10577
10665
  }
@@ -10631,19 +10719,19 @@ function requireOneNativeFile(directory, candidates, platform) {
10631
10719
  return present[0] ?? "";
10632
10720
  }
10633
10721
  function isNativeFile(directory, relative10) {
10634
- const file = path8.resolve(directory, relative10);
10635
- const within = path8.relative(directory, file);
10636
- if (within === "" || within.startsWith("..") || path8.isAbsolute(within)) {
10722
+ const file = path9.resolve(directory, relative10);
10723
+ const within = path9.relative(directory, file);
10724
+ if (within === "" || within.startsWith("..") || path9.isAbsolute(within)) {
10637
10725
  return false;
10638
10726
  }
10639
10727
  let current = directory;
10640
- for (const segment of within.split(path8.sep)) {
10641
- current = path8.join(current, segment);
10642
- if (!existsSync18(current) || lstatSync9(current).isSymbolicLink()) {
10728
+ for (const segment of within.split(path9.sep)) {
10729
+ current = path9.join(current, segment);
10730
+ if (!existsSync19(current) || lstatSync10(current).isSymbolicLink()) {
10643
10731
  return false;
10644
10732
  }
10645
10733
  }
10646
- return lstatSync9(file).isFile();
10734
+ return lstatSync10(file).isFile();
10647
10735
  }
10648
10736
 
10649
10737
  // node_modules/.cache/mpgd-native-build/tools/target/native-release-identity.js
@@ -10657,7 +10745,7 @@ function assertNativeReleaseIdentity(input) {
10657
10745
  const candidates = [
10658
10746
  join7(input.shellApp, "android/app/build.gradle"),
10659
10747
  join7(input.shellApp, "android/app/build.gradle.kts")
10660
- ].filter((file) => existsSync19(file));
10748
+ ].filter((file) => existsSync20(file));
10661
10749
  if (candidates.length !== 1) {
10662
10750
  throw new Error("Android native release requires exactly one Gradle app build file.");
10663
10751
  }
@@ -10809,7 +10897,7 @@ function assertAndroidAppliedScripts(appBuild, androidRoot) {
10809
10897
  throw new Error("Native release preflight cannot resolve an applied Gradle script.");
10810
10898
  }
10811
10899
  };
10812
- const rootFiles = ["build.gradle", "build.gradle.kts"].map((name) => join7(androidRoot, name)).filter((file) => existsSync19(file));
10900
+ const rootFiles = ["build.gradle", "build.gradle.kts"].map((name) => join7(androidRoot, name)).filter((file) => existsSync20(file));
10813
10901
  if (rootFiles.length !== 1) {
10814
10902
  throw new Error("Native release preflight requires one Android root Gradle build file.");
10815
10903
  }
@@ -10819,7 +10907,7 @@ function assertAndroidAppliedScripts(appBuild, androidRoot) {
10819
10907
  if (/\b(?:afterEvaluate|projectsEvaluated)\b/u.test(rootCode) && /\b(?:project|subprojects|allprojects|android)\b/u.test(rootCode)) {
10820
10908
  throw new Error("Native release preflight cannot resolve root Gradle app callbacks.");
10821
10909
  }
10822
- const settingsFiles = ["settings.gradle", "settings.gradle.kts"].map((name) => join7(androidRoot, name)).filter((file) => existsSync19(file));
10910
+ const settingsFiles = ["settings.gradle", "settings.gradle.kts"].map((name) => join7(androidRoot, name)).filter((file) => existsSync20(file));
10823
10911
  if (settingsFiles.length !== 1) {
10824
10912
  throw new Error("Native release preflight requires one Android settings Gradle file.");
10825
10913
  }
@@ -11143,10 +11231,10 @@ function stripOptionalQuotes(value) {
11143
11231
  return value;
11144
11232
  }
11145
11233
  function readRequiredFile(file, label) {
11146
- if (!existsSync19(file)) {
11234
+ if (!existsSync20(file)) {
11147
11235
  throw new Error(`Missing ${label}: ${file}`);
11148
11236
  }
11149
- return readFileSync18(file, "utf8");
11237
+ return readFileSync19(file, "utf8");
11150
11238
  }
11151
11239
  function requireFinalSemVer2(value, label) {
11152
11240
  const normalized = requireValue(value, label);
@@ -11198,6 +11286,7 @@ async function executeNativeTargetBuild(input) {
11198
11286
  const stage = createNativeShellStage({ shellApp, webDir });
11199
11287
  try {
11200
11288
  input.replaceDirectory(webBundle, stage.webDir);
11289
+ applyCapacitorShellCsp(stage.webDir);
11201
11290
  input.ensureCapacitorPlatform(stage.shellApp, platform, environment);
11202
11291
  await stageNativeIconResources(input.generatedIcons, stage.shellApp);
11203
11292
  runNativeSyncWithIdentityCheck({ ...identityInput, shellApp: stage.shellApp }, () => {
@@ -11246,7 +11335,7 @@ function androidSignedReleaseGradleArgs(environment) {
11246
11335
  if (initScript === void 0 || initScript === "") {
11247
11336
  return ["bundleRelease", "--no-daemon"];
11248
11337
  }
11249
- if (!isAbsolute9(initScript) || !existsSync20(initScript) || !statSync6(initScript).isFile()) {
11338
+ if (!isAbsolute9(initScript) || !existsSync21(initScript) || !statSync6(initScript).isFile()) {
11250
11339
  throw new Error("Android upload signing init script must be an existing absolute file.");
11251
11340
  }
11252
11341
  return ["bundleRelease", "--no-daemon", "--init-script", initScript];
@@ -11509,7 +11598,7 @@ if (process.env.MPGD_SKIP_BUILD_TARGET_PREFLIGHT !== "1") {
11509
11598
  run("pnpm", ["validate:target-config"], targetScopedEnv);
11510
11599
  run("pnpm", ["validate:effective-config"], targetScopedEnv);
11511
11600
  run("pnpm", ["validate:targets"], targetScopedEnv);
11512
- run("node", ["tools/run-ttsx.mjs", "tools/package/build-packages.ts"], process.env);
11601
+ run("node", ["tools/run-ttsx.mjs", "tools/package/build-packages.ts", "--reuse-unchanged"], process.env);
11513
11602
  }
11514
11603
  var gameApp = targetPath(target.gameApp);
11515
11604
  var webTargetPaths = target.kind === "web" ? resolveWebTargetPaths(target, targetName) : void 0;
@@ -11737,7 +11826,7 @@ try {
11737
11826
  function createRuntimeTargetConfigMatrixFile(matrix) {
11738
11827
  const directory = mkdtempSync5(join9(tmpdir4(), "mpgd-target-config-matrix-"));
11739
11828
  const file = join9(directory, "matrix.json");
11740
- writeFileSync13(file, `${JSON.stringify(matrix)}
11829
+ writeFileSync14(file, `${JSON.stringify(matrix)}
11741
11830
  `);
11742
11831
  return file;
11743
11832
  }
@@ -11757,7 +11846,7 @@ function replaceDirectory(source, destination) {
11757
11846
  function mirrorAitRuntimeAssets(gameApp2, wrapperApp) {
11758
11847
  const sourceAssets = `${gameApp2}/dist/assets`;
11759
11848
  const destinationAssets = `${wrapperApp}/public/assets`;
11760
- if (existsSync21(sourceAssets)) {
11849
+ if (existsSync22(sourceAssets)) {
11761
11850
  replaceDirectory(sourceAssets, destinationAssets);
11762
11851
  } else {
11763
11852
  rmSync11(destinationAssets, { recursive: true, force: true });
@@ -11839,14 +11928,14 @@ function copyIosSyncSwiftPackage(shellApp, releaseArtifact, packageName, swiftPa
11839
11928
  }
11840
11929
  function rewriteIosSyncSwiftPackagePath(releaseArtifact, packageName, swiftPackageName) {
11841
11930
  const packageFile = targetPath(`${releaseArtifact}/App/CapApp-SPM/Package.swift`);
11842
- const contents = readFileSync19(packageFile, "utf8");
11931
+ const contents = readFileSync20(packageFile, "utf8");
11843
11932
  const originalPath = readSwiftPackagePath(packageFile, swiftPackageName);
11844
11933
  const rewrittenPath = `../../node_modules/${packageName}`;
11845
11934
  const marker = `.package(name: "${swiftPackageName}", path: "`;
11846
- writeFileSync13(packageFile, contents.replace(`${marker}${originalPath}"`, `${marker}${rewrittenPath}"`));
11935
+ writeFileSync14(packageFile, contents.replace(`${marker}${originalPath}"`, `${marker}${rewrittenPath}"`));
11847
11936
  }
11848
11937
  function readSwiftPackagePath(packageFile, swiftPackageName) {
11849
- const contents = readFileSync19(packageFile, "utf8");
11938
+ const contents = readFileSync20(packageFile, "utf8");
11850
11939
  const marker = `.package(name: "${swiftPackageName}", path: "`;
11851
11940
  const index = contents.indexOf(marker);
11852
11941
  if (index < 0 || contents.indexOf(marker, index + marker.length) >= 0) {
@@ -11864,7 +11953,7 @@ function copyFile(source, destination) {
11864
11953
  cpSync4(source, destination);
11865
11954
  }
11866
11955
  function removeFilesByExtension(directory, extension) {
11867
- if (!existsSync21(directory)) {
11956
+ if (!existsSync22(directory)) {
11868
11957
  return;
11869
11958
  }
11870
11959
  for (const file of readdirSync7(directory)) {
@@ -11879,7 +11968,7 @@ function safeArtifactFileStem(value) {
11879
11968
  return stem.length === 0 ? "mpgd-kit" : stem;
11880
11969
  }
11881
11970
  function ensureCapacitorPlatform(shellApp, platform, commandEnv) {
11882
- if (!existsSync21(`${shellApp}/${platform}`)) {
11971
+ if (!existsSync22(`${shellApp}/${platform}`)) {
11883
11972
  run("pnpm", ["--dir", shellApp, "cap", "add", platform], commandEnv);
11884
11973
  }
11885
11974
  }
@@ -11903,7 +11992,7 @@ function writeManifest(target2, releaseProfile, artifact, commandEnv) {
11903
11992
  function findEmbeddedIconManifestArtifactPath(artifact) {
11904
11993
  const artifactPath = targetPath(artifact);
11905
11994
  const fileName = "mpgd-icon-manifest.json";
11906
- const matches = statSync7(artifactPath).isDirectory() ? findNamedArtifactFiles(artifactPath, fileName).map((path9) => relative9(artifactPath, path9).replaceAll("\\", "/")) : listZipEntries(artifactPath).filter((entry) => basename4(entry) === fileName);
11995
+ const matches = statSync7(artifactPath).isDirectory() ? findNamedArtifactFiles(artifactPath, fileName).map((path10) => relative9(artifactPath, path10).replaceAll("\\", "/")) : listZipEntries(artifactPath).filter((entry) => basename4(entry) === fileName);
11907
11996
  if (matches.length !== 1) {
11908
11997
  throw new Error(`Expected exactly one ${fileName} in release artifact ${artifactPath}; found ${matches.length}.`);
11909
11998
  }
@@ -11916,21 +12005,21 @@ function findEmbeddedIconManifestArtifactPath(artifact) {
11916
12005
  function findNamedArtifactFiles(root, fileName) {
11917
12006
  const matches = [];
11918
12007
  for (const entry of readdirSync7(root)) {
11919
- const path9 = join9(root, entry);
11920
- const stat = lstatSync10(path9);
12008
+ const path10 = join9(root, entry);
12009
+ const stat = lstatSync11(path10);
11921
12010
  if (stat.isSymbolicLink()) {
11922
12011
  continue;
11923
12012
  }
11924
12013
  if (stat.isDirectory()) {
11925
- matches.push(...findNamedArtifactFiles(path9, fileName));
12014
+ matches.push(...findNamedArtifactFiles(path10, fileName));
11926
12015
  } else if (stat.isFile() && entry === fileName) {
11927
- matches.push(path9);
12016
+ matches.push(path10);
11928
12017
  }
11929
12018
  }
11930
12019
  return matches;
11931
12020
  }
11932
- function listZipEntries(path9) {
11933
- const result = spawnSync5("unzip", ["-Z1", path9], {
12021
+ function listZipEntries(path10) {
12022
+ const result = spawnSync5("unzip", ["-Z1", path10], {
11934
12023
  cwd: process.cwd(),
11935
12024
  env: nativeInspectionEnvironment(),
11936
12025
  encoding: "utf8"
@@ -11940,7 +12029,7 @@ function listZipEntries(path9) {
11940
12029
  }
11941
12030
  const toleratedPrefixWarning = result.status === 1 && result.stdout.trim().length > 0 && result.stderr.includes("extra bytes at beginning or within zipfile") && result.stderr.includes("(attempting to process anyway)");
11942
12031
  if (result.status !== 0 && !toleratedPrefixWarning) {
11943
- throw new Error(`Failed to list release artifact ${path9}: ${result.stderr.trim() || `exit ${String(result.status)}`}`);
12032
+ throw new Error(`Failed to list release artifact ${path10}: ${result.stderr.trim() || `exit ${String(result.status)}`}`);
11944
12033
  }
11945
12034
  return result.stdout.split("\n").filter((entry) => entry.length > 0);
11946
12035
  }
@@ -11967,7 +12056,7 @@ function isMiniGameTarget(target2) {
11967
12056
  }
11968
12057
  function buildMiniGameBundle(bundleKind, outputDir, stagingRoot, gameApp2, profile2, commandEnv) {
11969
12058
  const viteConfig = join9(gameApp2, "vite.minigame.config.ts");
11970
- if (!existsSync21(viteConfig)) {
12059
+ if (!existsSync22(viteConfig)) {
11971
12060
  throw new Error(`Mini-game target requires a game-owned vite.minigame.config.ts: ${viteConfig}`);
11972
12061
  }
11973
12062
  run("pnpm", ["exec", "vite", "build", "--config", "vite.minigame.config.ts", "--mode", profile2], {
@@ -11999,8 +12088,8 @@ function withProcessEnv(env2, keys, callback) {
11999
12088
  }
12000
12089
  }
12001
12090
  }
12002
- function targetPath(path9) {
12003
- return resolveFromPlatformTargetsBase(configBaseDir, path9);
12091
+ function targetPath(path10) {
12092
+ return resolveFromPlatformTargetsBase(configBaseDir, path10);
12004
12093
  }
12005
12094
  function findFileByExtension(directory, extension) {
12006
12095
  const files = readdirSync7(directory).filter((file) => file.endsWith(extension)).sort();