@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.
- package/dist/capacitor-shell-starter.d.ts +21 -0
- package/dist/capacitor-shell-starter.js +121 -1
- package/dist/native-build-info.json +2 -2
- package/dist/native-build-target.js +381 -292
- package/package.json +12 -12
- package/templates/phaser-game/README.md +7 -0
- package/templates/phaser-game/apps/target-devvit/README.md +12 -0
- package/templates/phaser-game/apps/target-devvit/src/server/bridge.ts +513 -0
- package/templates/phaser-game/apps/target-devvit/src/server/index.ts +8 -291
- package/templates/phaser-game/vite.shared.ts +5 -1
|
@@ -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
|
|
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,
|
|
332
|
-
return relative(realpathSync2(gameRoot), realpathSync2(
|
|
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
|
|
354
|
-
if (
|
|
355
|
-
variants[name] =
|
|
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(
|
|
398
|
-
const bytes = readFileSync3(
|
|
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: ${
|
|
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 ${
|
|
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: ${
|
|
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}: ${
|
|
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}: ${
|
|
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: ${
|
|
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}: ${
|
|
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:
|
|
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
|
|
854
|
-
const bytes = readFileSync4(
|
|
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: ${
|
|
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: ${
|
|
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: ${
|
|
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: ${
|
|
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: ${
|
|
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: ${
|
|
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
|
|
887
|
-
if (
|
|
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,
|
|
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
|
|
938
|
-
const matches = result.manifest.outputs.filter((output2) => output2.path ===
|
|
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 ${
|
|
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: ${
|
|
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
|
|
1223
|
-
const rootRelativePath =
|
|
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
|
|
1586
|
-
return
|
|
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(
|
|
1592
|
-
const status = lstatIfPresent(
|
|
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: ${
|
|
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: ${
|
|
1597
|
+
throw new Error(`Web artifact output must be a directory when it already exists: ${path10}`);
|
|
1598
1598
|
}
|
|
1599
|
-
return canonicalizeThroughExistingAncestor(
|
|
1599
|
+
return canonicalizeThroughExistingAncestor(path10);
|
|
1600
1600
|
}
|
|
1601
|
-
function lstatIfPresent(
|
|
1601
|
+
function lstatIfPresent(path10) {
|
|
1602
1602
|
try {
|
|
1603
|
-
return lstatSync2(
|
|
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(
|
|
1612
|
-
const normalizedPath = resolve3(
|
|
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: ${
|
|
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 = (
|
|
1675
|
-
if (!snapshots.has(
|
|
1676
|
-
snapshots.set(
|
|
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(
|
|
1679
|
-
writeFileSync3(
|
|
1678
|
+
mkdirSync3(dirname3(path10), { recursive: true });
|
|
1679
|
+
writeFileSync3(path10, contents);
|
|
1680
1680
|
};
|
|
1681
|
-
const remove = (
|
|
1682
|
-
if (!snapshots.has(
|
|
1683
|
-
snapshots.set(
|
|
1681
|
+
const remove = (path10) => {
|
|
1682
|
+
if (!snapshots.has(path10)) {
|
|
1683
|
+
snapshots.set(path10, existsSync5(path10) ? readFileSync6(path10) : void 0);
|
|
1684
1684
|
}
|
|
1685
|
-
rmSync3(
|
|
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 [
|
|
1693
|
+
for (const [path10, contents] of [...snapshots.entries()].reverse()) {
|
|
1694
1694
|
if (contents === void 0) {
|
|
1695
|
-
rmSync3(
|
|
1695
|
+
rmSync3(path10, { force: true });
|
|
1696
1696
|
} else {
|
|
1697
|
-
writeFileSync3(
|
|
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((
|
|
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(
|
|
1794
|
-
const parsed = JSON.parse(readFileSync6(
|
|
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: ${
|
|
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(
|
|
1816
|
-
return sharp3(
|
|
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(
|
|
2291
|
-
return JSON.parse(readFileSync7(resolve5(
|
|
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
|
|
2446
|
-
const stat = lstatSync4(
|
|
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: ${
|
|
2448
|
+
throw new Error(`Mini-game artifacts must not contain symbolic links: ${path10}`);
|
|
2449
2449
|
}
|
|
2450
|
-
const artifactPath = toArtifactRelativePath(root,
|
|
2450
|
+
const artifactPath = toArtifactRelativePath(root, path10);
|
|
2451
2451
|
assertMiniGameArtifactPathAllowed(artifactPath);
|
|
2452
2452
|
artifactPaths.push(artifactPath);
|
|
2453
2453
|
if (stat.isDirectory()) {
|
|
2454
|
-
pending.push(
|
|
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: ${
|
|
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(
|
|
2469
|
-
const segments =
|
|
2470
|
-
if (
|
|
2471
|
-
throw new Error(`${label} must be a safe artifact-relative path: ${
|
|
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
|
|
2477
|
-
assertMiniGameArtifactRelativePath(
|
|
2478
|
-
const portableKey = miniGamePortablePathKey(
|
|
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}, ${
|
|
2481
|
+
throw new Error(`Mini-game artifact paths collide on portable filesystems: ${previous}, ${path10}.`);
|
|
2482
2482
|
}
|
|
2483
|
-
seen.set(portableKey,
|
|
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,
|
|
2521
|
-
const resolved = resolve6(root,
|
|
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: ${
|
|
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: ${
|
|
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: ${
|
|
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,
|
|
2537
|
-
const artifactPath = relative4(root,
|
|
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(
|
|
2542
|
-
return
|
|
2541
|
+
function isInsideRoot(path10, root) {
|
|
2542
|
+
return path10 === root || path10.startsWith(`${root}/`);
|
|
2543
2543
|
}
|
|
2544
|
-
function miniGamePortablePathKey(
|
|
2545
|
-
return
|
|
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(
|
|
2553
|
-
const segments =
|
|
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: ${
|
|
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: ${
|
|
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: ${
|
|
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: ${
|
|
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(
|
|
3045
|
-
return resolve7(
|
|
3044
|
+
function platformTargetsFilePath(path10 = process.env[platformTargetsFileEnv] ?? "mpgd.targets.json") {
|
|
3045
|
+
return resolve7(path10);
|
|
3046
3046
|
}
|
|
3047
|
-
function loadPlatformTargetsConfig(
|
|
3048
|
-
const resolvedPath = platformTargetsFilePath(
|
|
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,
|
|
3056
|
-
return isAbsolute4(
|
|
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(
|
|
4069
|
-
if (!existsSync6(
|
|
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(
|
|
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
|
|
4086
|
+
const path10 = join4(outputDir, `${target2}.json`);
|
|
4087
4087
|
const content = `${JSON.stringify(config2, null, 2)}
|
|
4088
4088
|
`;
|
|
4089
|
-
mkdirSync4(dirname5(
|
|
4090
|
-
writeFileSync4(
|
|
4089
|
+
mkdirSync4(dirname5(path10), { recursive: true });
|
|
4090
|
+
writeFileSync4(path10, content);
|
|
4091
4091
|
return {
|
|
4092
4092
|
target: target2,
|
|
4093
|
-
path:
|
|
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
|
|
5127
|
-
if (
|
|
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(
|
|
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: ${
|
|
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: ${
|
|
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",
|
|
5145
|
-
sharedConfigSha256: requireManifestString(manifest, "sharedConfigSha256",
|
|
5146
|
-
renderConfigSha256: requireManifestString(manifest, "renderConfigSha256",
|
|
5147
|
-
generatorVersion: requireManifestString(manifest, "generatorVersion",
|
|
5148
|
-
targetProfile: requireManifestString(manifest, "targetProfile",
|
|
5149
|
-
targetProfileVersion: requireManifestString(manifest, "targetProfileVersion",
|
|
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(
|
|
5153
|
-
const normalized =
|
|
5152
|
+
function requirePortableArtifactPath(path10) {
|
|
5153
|
+
const normalized = path10.replaceAll("\\", "/");
|
|
5154
5154
|
const segments = normalized.split("/");
|
|
5155
|
-
if (normalized.length === 0 || isAbsolute5(
|
|
5156
|
-
throw new Error(`Invalid icon manifest artifact path: ${
|
|
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(
|
|
5160
|
+
function readFileBytes(path10) {
|
|
5161
5161
|
try {
|
|
5162
|
-
return readFileSync11(
|
|
5162
|
+
return readFileSync11(path10);
|
|
5163
5163
|
} catch (error) {
|
|
5164
|
-
throw new Error(`Failed to read icon manifest ${
|
|
5164
|
+
throw new Error(`Failed to read icon manifest ${path10}: ${formatError5(error)}`);
|
|
5165
5165
|
}
|
|
5166
5166
|
}
|
|
5167
|
-
function requireManifestString(record, key,
|
|
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}: ${
|
|
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,
|
|
5253
|
-
if (!isAbsolute5(
|
|
5254
|
-
return
|
|
5252
|
+
function toPortablePath(baseDir, path10) {
|
|
5253
|
+
if (!isAbsolute5(path10)) {
|
|
5254
|
+
return path10;
|
|
5255
5255
|
}
|
|
5256
|
-
const relativePath = relative5(baseDir,
|
|
5256
|
+
const relativePath = relative5(baseDir, path10);
|
|
5257
5257
|
if (relativePath.length > 0 && !relativePath.startsWith("..") && !isAbsolute5(relativePath)) {
|
|
5258
5258
|
return relativePath;
|
|
5259
5259
|
}
|
|
5260
|
-
return
|
|
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
|
|
5622
|
+
const path10 = resolve9(directory, entry.name);
|
|
5623
5623
|
if (entry.isSymbolicLink()) {
|
|
5624
|
-
throw new Error(`PWA artifact must not contain symbolic links: ${
|
|
5624
|
+
throw new Error(`PWA artifact must not contain symbolic links: ${path10}`);
|
|
5625
5625
|
}
|
|
5626
5626
|
if (entry.isDirectory()) {
|
|
5627
|
-
pendingDirectories.push(
|
|
5627
|
+
pendingDirectories.push(path10);
|
|
5628
5628
|
} else if (entry.isFile()) {
|
|
5629
|
-
files.push(
|
|
5629
|
+
files.push(path10);
|
|
5630
5630
|
}
|
|
5631
5631
|
}
|
|
5632
5632
|
}
|
|
5633
|
-
return files.filter((
|
|
5634
|
-
url: toPrecacheUrl(artifactRoot,
|
|
5635
|
-
source: readFileSync12(
|
|
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,
|
|
5660
|
-
const portablePath = relative6(root,
|
|
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
|
|
6062
|
-
return
|
|
6061
|
+
const path10 = relative7(root, candidate);
|
|
6062
|
+
return path10 === "" || path10 !== ".." && !path10.startsWith(`..${sep4}`) && !isAbsolute6(path10);
|
|
6063
6063
|
}
|
|
6064
|
-
function portablePathComparisonKey(
|
|
6065
|
-
const portablePath =
|
|
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(
|
|
6071
|
-
const normalizedPath = resolve11(
|
|
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: ${
|
|
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(
|
|
6132
|
-
rmSync5(
|
|
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,
|
|
6172
|
+
function assertMiniGameJavaScriptAstSafety(source, path10, forbiddenGlobals) {
|
|
6173
6173
|
let ast;
|
|
6174
6174
|
try {
|
|
6175
6175
|
ast = parse(source, {
|
|
6176
6176
|
ecmaVersion: "latest",
|
|
6177
|
-
sourceType:
|
|
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 ${
|
|
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,
|
|
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,
|
|
6207
|
+
function assertSafeNode(node, ancestors, path10, scopeAnalysis, forbiddenGlobals) {
|
|
6208
6208
|
if (node.type === "ImportExpression") {
|
|
6209
|
-
throw new Error(`Mini-game ${
|
|
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 ${
|
|
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 ${
|
|
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 ${
|
|
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 ${
|
|
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 ${
|
|
6230
|
+
throw new Error(`Mini-game ${path10} contains forbidden eval.`);
|
|
6231
6231
|
}
|
|
6232
6232
|
if (node.name === "Function") {
|
|
6233
|
-
throw new Error(`Mini-game ${
|
|
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 ${
|
|
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 ${
|
|
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 ${
|
|
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 ${
|
|
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 ${
|
|
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 ${
|
|
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 ${
|
|
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 ${
|
|
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 ${
|
|
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 ${
|
|
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 ${
|
|
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 ${
|
|
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 ${
|
|
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 ${
|
|
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 ${
|
|
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 ${
|
|
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,
|
|
8166
|
-
const file = files.find((candidate) => candidate.path ===
|
|
8167
|
-
if (file === void 0 || !existsSync10(join5(artifactRoot,
|
|
8168
|
-
throw new Error(`Mini-game artifact is missing required evidence file: ${
|
|
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(
|
|
8242
|
+
function readJson(path10, label) {
|
|
8243
8243
|
try {
|
|
8244
|
-
return JSON.parse(readFileSync13(
|
|
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(
|
|
8312
|
-
writeFileSync9(
|
|
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
|
|
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
|
|
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
|
|
9235
|
+
import path7 from "node:path";
|
|
9179
9236
|
function inspectSignedIosArchive(archive, input) {
|
|
9180
|
-
return inspectSignedIosApplication(
|
|
9237
|
+
return inspectSignedIosApplication(path7.join(archive, "Products/Applications/App.app"), input);
|
|
9181
9238
|
}
|
|
9182
9239
|
function inspectSignedIosIpa(ipa, input) {
|
|
9183
|
-
if (!
|
|
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 =
|
|
9200
|
-
const extracted = mkdtempSync3(
|
|
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(
|
|
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 =
|
|
9213
|
-
if (!
|
|
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 (!
|
|
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
|
-
|
|
9245
|
-
|
|
9301
|
+
path7.join(appPath, "capacitor.config.json"),
|
|
9302
|
+
path7.join(appPath, "public/capacitor.config.json")
|
|
9246
9303
|
];
|
|
9247
|
-
if (!configFiles.some((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 (
|
|
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(
|
|
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
|
|
9288
|
-
import
|
|
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 =
|
|
9322
|
-
if (!
|
|
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
|
|
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
|
|
9341
|
-
import
|
|
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(
|
|
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 =
|
|
9733
|
-
const release =
|
|
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(
|
|
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 =
|
|
9900
|
-
if (!
|
|
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 =
|
|
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 =
|
|
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("$") ||
|
|
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("$") ||
|
|
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 =
|
|
10294
|
-
const within =
|
|
10295
|
-
if (within === "" || within.startsWith("..") ||
|
|
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(
|
|
10300
|
-
current =
|
|
10301
|
-
if (!
|
|
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
|
|
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(
|
|
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) =>
|
|
10360
|
-
const resourceRoots = ["main", "release"].map((sourceSet) =>
|
|
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 =
|
|
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 (!
|
|
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(
|
|
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(
|
|
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" ?
|
|
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(
|
|
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 =
|
|
10420
|
-
if (
|
|
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) =>
|
|
10431
|
-
const appGradle = appBuildFile === void 0 ? "" :
|
|
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 =
|
|
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 =
|
|
10560
|
+
const nativeDirectory = path9.join(shellApp, "android");
|
|
10473
10561
|
const gradleRelative = requireOneNativeFile(nativeDirectory, ["app/build.gradle", "app/build.gradle.kts"], "android");
|
|
10474
|
-
const gradle =
|
|
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 =
|
|
10479
|
-
const projectFile =
|
|
10480
|
-
const project =
|
|
10481
|
-
const infoRelative =
|
|
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) =>
|
|
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 =
|
|
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 =
|
|
10590
|
+
const project = readFileSync18(path9.join(nativeDirectory, projectRelative), "utf8");
|
|
10503
10591
|
const appTargetId = readIosAppTargetId(project);
|
|
10504
|
-
const schemeSource =
|
|
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(
|
|
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 =
|
|
10560
|
-
const overlayValues =
|
|
10561
|
-
const main =
|
|
10562
|
-
const mainValues =
|
|
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(
|
|
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(
|
|
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 =
|
|
10635
|
-
const within =
|
|
10636
|
-
if (within === "" || within.startsWith("..") ||
|
|
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(
|
|
10641
|
-
current =
|
|
10642
|
-
if (!
|
|
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
|
|
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) =>
|
|
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) =>
|
|
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) =>
|
|
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 (!
|
|
11234
|
+
if (!existsSync20(file)) {
|
|
11147
11235
|
throw new Error(`Missing ${label}: ${file}`);
|
|
11148
11236
|
}
|
|
11149
|
-
return
|
|
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) || !
|
|
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
|
-
|
|
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 (
|
|
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 =
|
|
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
|
-
|
|
11935
|
+
writeFileSync14(packageFile, contents.replace(`${marker}${originalPath}"`, `${marker}${rewrittenPath}"`));
|
|
11847
11936
|
}
|
|
11848
11937
|
function readSwiftPackagePath(packageFile, swiftPackageName) {
|
|
11849
|
-
const contents =
|
|
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 (!
|
|
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 (!
|
|
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((
|
|
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
|
|
11920
|
-
const stat =
|
|
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(
|
|
12014
|
+
matches.push(...findNamedArtifactFiles(path10, fileName));
|
|
11926
12015
|
} else if (stat.isFile() && entry === fileName) {
|
|
11927
|
-
matches.push(
|
|
12016
|
+
matches.push(path10);
|
|
11928
12017
|
}
|
|
11929
12018
|
}
|
|
11930
12019
|
return matches;
|
|
11931
12020
|
}
|
|
11932
|
-
function listZipEntries(
|
|
11933
|
-
const result = spawnSync5("unzip", ["-Z1",
|
|
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 ${
|
|
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 (!
|
|
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(
|
|
12003
|
-
return resolveFromPlatformTargetsBase(configBaseDir,
|
|
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();
|