@absolutejs/absolute 0.20.0-beta.103 → 0.20.0-beta.104

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.
@@ -7,12 +7,12 @@ import {
7
7
  } from "./index-zh6hhrwy.js";
8
8
  import {
9
9
  start
10
- } from "./index-rvpd4w9t.js";
10
+ } from "./index-27hhdgtg.js";
11
11
  import {
12
12
  ABSOLUTE_MOBILE_CLIENT_MANIFEST_FORMAT,
13
13
  ABSOLUTE_MOBILE_PAGE_PROTOCOL_VERSION,
14
14
  resolveAbsoluteMobileRoute
15
- } from "./index-6ff78meg.js";
15
+ } from "./index-67kedtn7.js";
16
16
  import"./index-bzs19w3r.js";
17
17
  import"./index-s2tazax7.js";
18
18
  import {
@@ -16777,14 +16777,14 @@ var require_main = __commonJS(function(exports) {
16777
16777
  // src/cli/scripts/mobile.ts
16778
16778
  import {
16779
16779
  access as access13,
16780
- mkdir as mkdir13,
16780
+ mkdir as mkdir14,
16781
16781
  mkdtemp as mkdtemp4,
16782
- readFile as readFile17,
16782
+ readFile as readFile18,
16783
16783
  rm as rm7,
16784
- writeFile as writeFile15
16784
+ writeFile as writeFile16
16785
16785
  } from "fs/promises";
16786
16786
  import { createPublicKey as createPublicKey2 } from "crypto";
16787
- import { join as join14, relative as relative12, resolve as resolve13 } from "path";
16787
+ import { join as join15, relative as relative12, resolve as resolve13 } from "path";
16788
16788
  import { createInterface } from "readline/promises";
16789
16789
 
16790
16790
  // src/mobile/nativeDeepLinks.ts
@@ -18454,14 +18454,156 @@ var applyAbsoluteNativeObservability = async (config, platforms = config.platfor
18454
18454
  return { changed: changed.some(Boolean) };
18455
18455
  };
18456
18456
 
18457
+ // src/mobile/nativeReleaseReadiness.ts
18458
+ import { mkdir as mkdir3, readFile as readFile6, readdir as readdir3, rename as rename6, writeFile as writeFile6 } from "fs/promises";
18459
+ import { dirname as dirname3, join as join6 } from "path";
18460
+ var START3 = "// absolutejs:release-readiness:start";
18461
+ var END3 = "// absolutejs:release-readiness:end";
18462
+ var ANDROID_PLUGIN3 = "AbsoluteReleaseReadinessPlugin.java";
18463
+ var optionalSource4 = async (path) => {
18464
+ try {
18465
+ return await readFile6(path, "utf8");
18466
+ } catch (error) {
18467
+ if (typeof error === "object" && error !== null && Reflect.get(error, "code") === "ENOENT")
18468
+ return null;
18469
+ throw error;
18470
+ }
18471
+ };
18472
+ var writeChanged4 = async (path, source) => {
18473
+ const current = await optionalSource4(path);
18474
+ if (current === source)
18475
+ return false;
18476
+ await mkdir3(dirname3(path), { recursive: true });
18477
+ if (current === null) {
18478
+ await writeFile6(path, source, { flag: "wx" });
18479
+ return true;
18480
+ }
18481
+ const temporary = `${path}.${crypto.randomUUID()}.tmp`;
18482
+ await writeFile6(temporary, source, { flag: "wx" });
18483
+ await rename6(temporary, path);
18484
+ return true;
18485
+ };
18486
+ var activityInRoot = async (root) => {
18487
+ let entries;
18488
+ try {
18489
+ entries = await readdir3(root, { recursive: true });
18490
+ } catch (error) {
18491
+ if (typeof error === "object" && error !== null && Reflect.get(error, "code") === "ENOENT")
18492
+ return;
18493
+ throw error;
18494
+ }
18495
+ const candidate = entries.find((entry) => entry.endsWith("/MainActivity.java") || entry.endsWith("/MainActivity.kt") || entry === "MainActivity.java" || entry === "MainActivity.kt");
18496
+ return candidate ? join6(root, candidate) : undefined;
18497
+ };
18498
+ var activityPath = async (config) => {
18499
+ const roots = [
18500
+ join6(config.nativeProjectDirectory, "android/app/src/main/java"),
18501
+ join6(config.nativeProjectDirectory, "android/app/src/main/kotlin")
18502
+ ];
18503
+ const candidates = await Promise.all(roots.map(activityInRoot));
18504
+ const candidate = candidates.find((value) => value !== undefined);
18505
+ if (candidate)
18506
+ return candidate;
18507
+ throw new TypeError("Android MainActivity.java or MainActivity.kt was not found.");
18508
+ };
18509
+ var registrationRegion = (kotlin, generatedMethod) => {
18510
+ if (generatedMethod)
18511
+ return kotlin ? ` ${START3}
18512
+ override fun onCreate(savedInstanceState: android.os.Bundle?) {
18513
+ registerPlugin(AbsoluteReleaseReadinessPlugin::class.java)
18514
+ super.onCreate(savedInstanceState)
18515
+ }
18516
+ ${END3}
18517
+ ` : ` ${START3}
18518
+ @Override
18519
+ public void onCreate(android.os.Bundle savedInstanceState) {
18520
+ registerPlugin(AbsoluteReleaseReadinessPlugin.class);
18521
+ super.onCreate(savedInstanceState);
18522
+ }
18523
+ ${END3}
18524
+ `;
18525
+ return kotlin ? ` ${START3}
18526
+ registerPlugin(AbsoluteReleaseReadinessPlugin::class.java)
18527
+ ${END3}
18528
+ ` : ` ${START3}
18529
+ registerPlugin(AbsoluteReleaseReadinessPlugin.class);
18530
+ ${END3}
18531
+ `;
18532
+ };
18533
+ var injectRegistration = (source) => {
18534
+ const kotlin = /\bfun\s+onCreate\s*\(/u.test(source) || source.includes("BridgeActivity()");
18535
+ const existingStart = source.indexOf(START3);
18536
+ const existingEnd = source.indexOf(END3);
18537
+ if (existingStart < 0 !== existingEnd < 0 || existingStart >= 0 && existingEnd < existingStart)
18538
+ throw new TypeError("AbsoluteJS release-readiness markers are malformed.");
18539
+ if (existingStart >= 0) {
18540
+ const from = source.lastIndexOf(`
18541
+ `, existingStart) + 1;
18542
+ const newline = source.indexOf(`
18543
+ `, existingEnd + END3.length);
18544
+ const through = newline < 0 ? source.length : newline + 1;
18545
+ const generatedMethod = source.slice(from, through).includes("onCreate(");
18546
+ return `${source.slice(0, from)}${registrationRegion(kotlin, generatedMethod)}${source.slice(through)}`;
18547
+ }
18548
+ const onCreate = kotlin ? source.search(/\boverride\s+fun\s+onCreate\s*\([^)]*\)\s*\{/u) : source.search(/\b(?:public|protected)\s+void\s+onCreate\s*\([^)]*\)\s*\{/u);
18549
+ if (onCreate >= 0) {
18550
+ const brace = source.indexOf("{", onCreate);
18551
+ const insert = source.indexOf(`
18552
+ `, brace) + 1;
18553
+ if (insert <= 0)
18554
+ throw new TypeError("Could not inject Android release readiness into MainActivity.");
18555
+ return `${source.slice(0, insert)}${registrationRegion(kotlin, false)}${source.slice(insert)}`;
18556
+ }
18557
+ const close = source.lastIndexOf("}");
18558
+ if (close < 0)
18559
+ throw new TypeError("Could not find the Android MainActivity class body.");
18560
+ const separator = source[close - 1] === `
18561
+ ` ? "" : `
18562
+ `;
18563
+ return `${source.slice(0, close)}${separator}${registrationRegion(kotlin, true)}${source.slice(close)}`;
18564
+ };
18565
+ var pluginSource = (packageName) => `package ${packageName};
18566
+
18567
+ import android.util.Log;
18568
+ import com.getcapacitor.JSObject;
18569
+ import com.getcapacitor.Plugin;
18570
+ import com.getcapacitor.PluginCall;
18571
+ import com.getcapacitor.PluginMethod;
18572
+ import com.getcapacitor.annotation.CapacitorPlugin;
18573
+
18574
+ @CapacitorPlugin(name = "AbsoluteReleaseReadiness")
18575
+ public final class AbsoluteReleaseReadinessPlugin extends Plugin {
18576
+ @PluginMethod
18577
+ public void ready(PluginCall call) {
18578
+ Log.i("AbsoluteJS", "Capacitor embedded web content ready");
18579
+ call.resolve(new JSObject().put("ready", true));
18580
+ }
18581
+ }
18582
+ `;
18583
+ var applyAbsoluteNativeReleaseReadiness = async (config, platforms = config.platforms) => {
18584
+ if (config.engine !== "capacitor" || !platforms.includes("android"))
18585
+ return { changed: false };
18586
+ const mainActivityPath = await activityPath(config);
18587
+ const activity = await readFile6(mainActivityPath, "utf8");
18588
+ const packageName = activity.match(/^\s*package\s+([A-Za-z0-9_.]+)\s*[;\n]/mu)?.[1];
18589
+ if (!packageName)
18590
+ throw new TypeError("Android MainActivity package declaration was not found.");
18591
+ const pluginPath = join6(config.nativeProjectDirectory, "android/app/src/main/java", packageName.replaceAll(".", "/"), ANDROID_PLUGIN3);
18592
+ const changed = await Promise.all([
18593
+ writeChanged4(mainActivityPath, injectRegistration(activity)),
18594
+ writeChanged4(pluginPath, pluginSource(packageName))
18595
+ ]);
18596
+ return { changed: changed.some(Boolean) };
18597
+ };
18598
+
18457
18599
  // src/mobile/associationFiles.ts
18458
18600
  import {
18459
18601
  access,
18460
- mkdir as mkdir3,
18461
- readFile as readFile6,
18462
- rename as rename6,
18602
+ mkdir as mkdir4,
18603
+ readFile as readFile7,
18604
+ rename as rename7,
18463
18605
  rm as rm3,
18464
- writeFile as writeFile6
18606
+ writeFile as writeFile7
18465
18607
  } from "fs/promises";
18466
18608
  import { resolve } from "path";
18467
18609
  import { Elysia } from "elysia";
@@ -18525,7 +18667,7 @@ var createAbsoluteMobileAssociationDocuments = (config, options = {}) => {
18525
18667
  var writeAtomic = async (path, source) => {
18526
18668
  let current;
18527
18669
  try {
18528
- current = await readFile6(path, "utf8");
18670
+ current = await readFile7(path, "utf8");
18529
18671
  } catch (error) {
18530
18672
  if (!(error instanceof Error) || !("code" in error) || error.code !== "ENOENT") {
18531
18673
  throw error;
@@ -18534,8 +18676,8 @@ var writeAtomic = async (path, source) => {
18534
18676
  if (current === source)
18535
18677
  return false;
18536
18678
  const temporary = `${path}.${crypto.randomUUID()}.tmp`;
18537
- await writeFile6(temporary, source, { flag: "wx" });
18538
- await rename6(temporary, path);
18679
+ await writeFile7(temporary, source, { flag: "wx" });
18680
+ await rename7(temporary, path);
18539
18681
  return true;
18540
18682
  };
18541
18683
  var exists = async (path) => {
@@ -18550,7 +18692,7 @@ var assertOwnedOutput = async (root) => {
18550
18692
  const path = resolve(root, OWNERSHIP_FILE);
18551
18693
  let ownership;
18552
18694
  try {
18553
- ownership = JSON.parse(await readFile6(path, "utf8"));
18695
+ ownership = JSON.parse(await readFile7(path, "utf8"));
18554
18696
  } catch {
18555
18697
  throw new TypeError(`Association output ${root} already exists and is not owned by AbsoluteJS.`);
18556
18698
  }
@@ -18564,12 +18706,12 @@ var publishGeneratedDirectory = async (temporary, root) => {
18564
18706
  await assertOwnedOutput(root);
18565
18707
  const backup = `${root}.${crypto.randomUUID()}.previous`;
18566
18708
  if (hasCurrent)
18567
- await rename6(root, backup);
18709
+ await rename7(root, backup);
18568
18710
  try {
18569
- await rename6(temporary, root);
18711
+ await rename7(temporary, root);
18570
18712
  } catch (error) {
18571
18713
  if (hasCurrent)
18572
- await rename6(backup, root);
18714
+ await rename7(backup, root);
18573
18715
  throw error;
18574
18716
  }
18575
18717
  if (hasCurrent)
@@ -18577,7 +18719,7 @@ var publishGeneratedDirectory = async (temporary, root) => {
18577
18719
  };
18578
18720
  var materializeHost = async (root, host, files) => {
18579
18721
  const directory = resolve(root, host, ".well-known");
18580
- await mkdir3(directory, { recursive: true });
18722
+ await mkdir4(directory, { recursive: true });
18581
18723
  return Promise.all(files.map(async ([name, document2]) => {
18582
18724
  const path = resolve(directory, name);
18583
18725
  await writeAtomic(path, `${JSON.stringify(document2, null, 2)}
@@ -18615,7 +18757,7 @@ var materializeAbsoluteMobileAssociationFiles = async (config, outputDirectory)
18615
18757
  if (documents.apple) {
18616
18758
  files.push(["apple-app-site-association", documents.apple]);
18617
18759
  }
18618
- await mkdir3(temporary, { recursive: true });
18760
+ await mkdir4(temporary, { recursive: true });
18619
18761
  try {
18620
18762
  const temporaryPaths = (await Promise.all(config.deepLinkHosts.map((host) => materializeHost(temporary, host, files)))).flat();
18621
18763
  await writeAtomic(resolve(temporary, OWNERSHIP_FILE), `${JSON.stringify({ format: 1, hosts: config.deepLinkHosts }, null, 2)}
@@ -18660,8 +18802,8 @@ var verifyAbsoluteMobileAssociationFiles = async (config, request = globalThis.f
18660
18802
  };
18661
18803
 
18662
18804
  // src/mobile/androidWebView.ts
18663
- import { mkdir as mkdir4, writeFile as writeFile7 } from "fs/promises";
18664
- import { dirname as dirname3, resolve as resolve2 } from "path";
18805
+ import { mkdir as mkdir5, writeFile as writeFile8 } from "fs/promises";
18806
+ import { dirname as dirname4, resolve as resolve2 } from "path";
18665
18807
  var CDP_COMMAND_TIMEOUT_MS = 1e4;
18666
18808
  var WEBVIEW_ATTACH_TIMEOUT_MS = 30000;
18667
18809
  var WEBVIEW_POLL_MS = 200;
@@ -18955,8 +19097,8 @@ var createSession = (options, capture, socket, hostPort, target, connection) =>
18955
19097
  throw new Error("Android WebView screenshot returned no image data.");
18956
19098
  }
18957
19099
  const absolutePath = resolve2(path);
18958
- await mkdir4(dirname3(absolutePath), { recursive: true });
18959
- await writeFile7(absolutePath, Buffer.from(data, "base64"));
19100
+ await mkdir5(dirname4(absolutePath), { recursive: true });
19101
+ await writeFile8(absolutePath, Buffer.from(data, "base64"));
18960
19102
  return absolutePath;
18961
19103
  },
18962
19104
  tap: async (coordinateX, coordinateY) => {
@@ -19103,13 +19245,13 @@ var waitForAbsoluteAndroidHmrApply = async (session, options) => {
19103
19245
  };
19104
19246
 
19105
19247
  // src/mobile/releaseDoctor.ts
19106
- import { access as access4, readFile as readFile8, readdir as readdir3 } from "fs/promises";
19107
- import { dirname as dirname5, extname, join as join7, relative as relative3 } from "path";
19248
+ import { access as access4, readFile as readFile9, readdir as readdir4 } from "fs/promises";
19249
+ import { dirname as dirname6, extname, join as join8, relative as relative3 } from "path";
19108
19250
 
19109
19251
  // src/mobile/mobileBundleInspection.ts
19110
19252
  import { createHash } from "crypto";
19111
- import { access as access2, readFile as readFile7, stat } from "fs/promises";
19112
- import { join as join6, relative, resolve as resolve3 } from "path";
19253
+ import { access as access2, readFile as readFile8, stat } from "fs/promises";
19254
+ import { join as join7, relative, resolve as resolve3 } from "path";
19113
19255
  var MOBILE_FRAMEWORKS = new Set([
19114
19256
  "angular",
19115
19257
  "ember",
@@ -19134,7 +19276,7 @@ var pathExists = async (path) => {
19134
19276
  }
19135
19277
  };
19136
19278
  var readObject = async (path) => {
19137
- const value = JSON.parse(await readFile7(path, "utf8"));
19279
+ const value = JSON.parse(await readFile8(path, "utf8"));
19138
19280
  if (!isObject(value))
19139
19281
  throw new TypeError("JSON root must be an object.");
19140
19282
  return value;
@@ -19162,14 +19304,14 @@ var requireBundleFile = async (root, value, field, expectedHash) => {
19162
19304
  if (expectedHash !== undefined) {
19163
19305
  if (!SHA256_PATTERN.test(expectedHash))
19164
19306
  throw new TypeError(`${field} has an invalid SHA-256 digest.`);
19165
- const actual = createHash("sha256").update(await readFile7(path)).digest("hex");
19307
+ const actual = createHash("sha256").update(await readFile8(path)).digest("hex");
19166
19308
  if (actual !== expectedHash)
19167
19309
  throw new TypeError(`${field} failed its SHA-256 integrity check.`);
19168
19310
  }
19169
19311
  return portable;
19170
19312
  };
19171
19313
  var inspectAbsoluteMobileBundle = async (config, projectRoot) => {
19172
- const manifestPath = join6(config.bundleDirectory, "absolute-mobile-manifest.json");
19314
+ const manifestPath = join7(config.bundleDirectory, "absolute-mobile-manifest.json");
19173
19315
  const manifest = portablePath(projectRoot, manifestPath);
19174
19316
  if (!await pathExists(manifestPath))
19175
19317
  return { manifest, status: "missing" };
@@ -19266,8 +19408,8 @@ import {
19266
19408
  createPublicKey,
19267
19409
  X509Certificate
19268
19410
  } from "crypto";
19269
- import { access as access3, mkdir as mkdir5 } from "fs/promises";
19270
- import { dirname as dirname4, isAbsolute, relative as relative2, resolve as resolve4, sep } from "path";
19411
+ import { access as access3, mkdir as mkdir6 } from "fs/promises";
19412
+ import { dirname as dirname5, isAbsolute, relative as relative2, resolve as resolve4, sep } from "path";
19271
19413
  import { pathToFileURL } from "url";
19272
19414
  import { Elysia as Elysia2 } from "elysia";
19273
19415
  var ABSOLUTE_MOBILE_UPDATE_SERVER_FORMAT = 1;
@@ -19484,7 +19626,7 @@ var writeAbsoluteMobileUpdateRegistry = async (options) => {
19484
19626
  return;
19485
19627
  });
19486
19628
  }
19487
- await mkdir5(dirname4(path), { recursive: true });
19629
+ await mkdir6(dirname5(path), { recursive: true });
19488
19630
  await Bun.write(path, renderAbsoluteMobileUpdateRegistry({
19489
19631
  ...options.health ? { health: options.health } : {},
19490
19632
  ...options.rollout ? { rollout: options.rollout } : {},
@@ -19527,14 +19669,14 @@ var inspectReleaseAsset = async (path, isDirectory, isFile) => {
19527
19669
  return findHmrAsset(path);
19528
19670
  if (!isFile || !RELEASE_ASSET_EXTENSIONS.has(extname(path)))
19529
19671
  return;
19530
- const source = await readFile8(path, "utf8");
19672
+ const source = await readFile9(path, "utf8");
19531
19673
  return HMR_ASSET_PATTERN.test(source) ? path : undefined;
19532
19674
  };
19533
19675
  var findHmrAsset = async (root) => {
19534
19676
  if (!await pathExists2(root))
19535
19677
  return;
19536
- const entries = await readdir3(root, { withFileTypes: true });
19537
- const matches = await Promise.all(entries.map((entry) => inspectReleaseAsset(join7(root, entry.name), entry.isDirectory(), entry.isFile())));
19678
+ const entries = await readdir4(root, { withFileTypes: true });
19679
+ const matches = await Promise.all(entries.map((entry) => inspectReleaseAsset(join8(root, entry.name), entry.isDirectory(), entry.isFile())));
19538
19680
  return matches.find((match) => match !== undefined);
19539
19681
  };
19540
19682
  var pass = (id, detail, path) => ({ detail, id, path, status: "pass" });
@@ -19564,7 +19706,7 @@ var mobileUpdateServerCheck = async (config, projectRoot) => {
19564
19706
  };
19565
19707
  var isRecord3 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
19566
19708
  var readJsonObject = async (path) => {
19567
- const value = JSON.parse(await readFile8(path, "utf8"));
19709
+ const value = JSON.parse(await readFile9(path, "utf8"));
19568
19710
  if (typeof value !== "object" || value === null || Array.isArray(value))
19569
19711
  throw new TypeError("JSON root must be an object.");
19570
19712
  return Object.fromEntries(Object.entries(value));
@@ -19583,7 +19725,7 @@ var packageDeclarations = (manifest) => {
19583
19725
  };
19584
19726
  var versionCore = (version) => version.split("-")[0]?.split(".").slice(0, 2).join(".");
19585
19727
  var capacitorVersionCheck = async (config, projectRoot) => {
19586
- const manifestPath = join7(projectRoot, "package.json");
19728
+ const manifestPath = join8(projectRoot, "package.json");
19587
19729
  try {
19588
19730
  const manifest = await readJsonObject(manifestPath);
19589
19731
  const declarations = packageDeclarations(manifest);
@@ -19596,7 +19738,7 @@ var capacitorVersionCheck = async (config, projectRoot) => {
19596
19738
  const declared = declarations.get(name);
19597
19739
  if (!declared || !EXACT_VERSION_PATTERN.test(declared))
19598
19740
  throw new TypeError(`${name} must be a direct exact dependency.`);
19599
- const installed = await readJsonObject(join7(projectRoot, "node_modules", name, "package.json"));
19741
+ const installed = await readJsonObject(await findAbsoluteInstalledPackageManifest(projectRoot, name));
19600
19742
  if (installed.version !== declared)
19601
19743
  throw new TypeError(`${name} does not match its installed version.`);
19602
19744
  return declared;
@@ -19619,7 +19761,7 @@ var satisfiesGeneratedVersion = (declared, installed) => {
19619
19761
  return actual[0] === expected[0] && actual[1] === expected[1] && (actual[2] ?? NOT_FOUND3) >= (expected[2] ?? 0);
19620
19762
  };
19621
19763
  var expoVersionCheck = async (config) => {
19622
- const manifestPath = join7(config.nativeProjectDirectory, "package.json");
19764
+ const manifestPath = join8(config.nativeProjectDirectory, "package.json");
19623
19765
  try {
19624
19766
  const manifest = await readJsonObject(manifestPath);
19625
19767
  const declarations = packageDeclarations(manifest);
@@ -19629,13 +19771,13 @@ var expoVersionCheck = async (config) => {
19629
19771
  throw new TypeError(`Generated Expo project is missing ${missingRequired}.`);
19630
19772
  const installedVersions = await Promise.all([...declarations].map(async ([name, declared]) => ({
19631
19773
  declared,
19632
- installed: await readJsonObject(join7(config.nativeProjectDirectory, "node_modules", name, "package.json")),
19774
+ installed: await readJsonObject(join8(config.nativeProjectDirectory, "node_modules", name, "package.json")),
19633
19775
  name
19634
19776
  })));
19635
19777
  const mismatch = installedVersions.find(({ declared, installed }) => typeof installed.version !== "string" || !satisfiesGeneratedVersion(declared, installed.version));
19636
19778
  if (mismatch)
19637
19779
  throw new TypeError(`Generated Expo dependency ${mismatch.name}@${mismatch.declared} does not match its installed version.`);
19638
- if (!await pathExists2(join7(config.nativeProjectDirectory, "bun.lock")))
19780
+ if (!await pathExists2(join8(config.nativeProjectDirectory, "bun.lock")))
19639
19781
  throw new TypeError("Generated Expo dependency lockfile is missing.");
19640
19782
  return pass("mobile.expo-versions", `Generated Expo SDK dependencies are pinned, installed, and locked (${declarations.get("expo")}).`, manifestPath);
19641
19783
  } catch (error) {
@@ -19643,9 +19785,9 @@ var expoVersionCheck = async (config) => {
19643
19785
  }
19644
19786
  };
19645
19787
  var dependencyLockAt = async (directory) => (await Promise.all(LOCK_FILES.map(async (name) => ({
19646
- exists: await pathExists2(join7(directory, name)),
19788
+ exists: await pathExists2(join8(directory, name)),
19647
19789
  name,
19648
- path: join7(directory, name)
19790
+ path: join8(directory, name)
19649
19791
  })))).find(({ exists: exists2 }) => exists2);
19650
19792
  var declaredWorkspacePatterns = (declared) => {
19651
19793
  if (Array.isArray(declared))
@@ -19655,7 +19797,7 @@ var declaredWorkspacePatterns = (declared) => {
19655
19797
  return [];
19656
19798
  };
19657
19799
  var ownsWorkspace = async (directory, projectRoot) => {
19658
- const manifest = await readJsonObject(join7(directory, "package.json")).catch(() => {
19800
+ const manifest = await readJsonObject(join8(directory, "package.json")).catch(() => {
19659
19801
  return;
19660
19802
  });
19661
19803
  const workspacePath = relative3(directory, projectRoot).replace(/\\/gu, "/");
@@ -19666,7 +19808,7 @@ var ancestorDirectories = (projectRoot) => {
19666
19808
  let directory = projectRoot;
19667
19809
  while (true) {
19668
19810
  directories.push(directory);
19669
- const parent = dirname5(directory);
19811
+ const parent = dirname6(directory);
19670
19812
  if (parent === directory)
19671
19813
  return directories;
19672
19814
  directory = parent;
@@ -19681,6 +19823,18 @@ var findAbsoluteDependencyLock = async (projectRoot) => {
19681
19823
  }));
19682
19824
  return candidates.find((candidate) => candidate !== undefined);
19683
19825
  };
19826
+ var findAbsoluteInstalledPackageManifest = async (projectRoot, name) => {
19827
+ const candidates = await Promise.all(ancestorDirectories(projectRoot).map(async (directory, index) => {
19828
+ if (index > 0 && !await ownsWorkspace(directory, projectRoot))
19829
+ return;
19830
+ const candidate = join8(directory, "node_modules", name, "package.json");
19831
+ return await pathExists2(candidate) ? candidate : undefined;
19832
+ }));
19833
+ const installed = candidates.find((candidate) => candidate !== undefined);
19834
+ if (installed)
19835
+ return installed;
19836
+ throw new TypeError(`${name} is not installed for this application.`);
19837
+ };
19684
19838
  var dependencyLockCheck = async (projectRoot) => {
19685
19839
  const present = await findAbsoluteDependencyLock(projectRoot);
19686
19840
  return present ? pass("mobile.dependency-lock", `Dependency graph is locked by ${present.name}.`, present.path) : fail("mobile.dependency-lock", "No supported dependency lockfile is present.", projectRoot, "Install dependencies with the project package manager and commit its lockfile before release.");
@@ -19725,7 +19879,7 @@ var capacitorConfigReleaseCheck = async (nativeConfigPath) => {
19725
19879
  if (!await pathExists2(nativeConfigPath)) {
19726
19880
  return fail("android.capacitor-config", "The generated Android Capacitor config is missing.", nativeConfigPath, "Run `absolute mobile sync android` before release validation.");
19727
19881
  }
19728
- const unsafe = isUnsafeCapacitorConfig(await readFile8(nativeConfigPath, "utf8"));
19882
+ const unsafe = isUnsafeCapacitorConfig(await readFile9(nativeConfigPath, "utf8"));
19729
19883
  return unsafe ? fail("android.capacitor-config", "Android Capacitor config contains a development server URL, cleartext transport, navigation allowlist, or invalid JSON.", nativeConfigPath, "Run `absolute mobile sync android`; do not ship development transport overrides.") : pass("android.capacitor-config", "Android Capacitor config contains no development transport overrides.", nativeConfigPath);
19730
19884
  };
19731
19885
  var capacitorIdentityCheck = async (config, platform, nativeConfigPath) => {
@@ -19742,12 +19896,12 @@ var manifestReleaseCheck = async (manifestPath) => {
19742
19896
  if (!await pathExists2(manifestPath)) {
19743
19897
  return fail("android.cleartext", "The Android manifest is missing.", manifestPath, "Run `absolute mobile sync android` before release validation.");
19744
19898
  }
19745
- const source = await readFile8(manifestPath, "utf8");
19899
+ const source = await readFile9(manifestPath, "utf8");
19746
19900
  const cleartext = /android:usesCleartextTraffic=["']true["']/u.test(source);
19747
19901
  const networkConfigName = source.match(/android:networkSecurityConfig=["']@xml\/([a-z0-9_]+)["']/u)?.[1];
19748
- const networkConfigPath = networkConfigName ? join7(dirname5(manifestPath), "res", "xml", `${networkConfigName}.xml`) : undefined;
19902
+ const networkConfigPath = networkConfigName ? join8(dirname6(manifestPath), "res", "xml", `${networkConfigName}.xml`) : undefined;
19749
19903
  const developmentTrustReference = /android:networkSecurityConfig=["']@xml\/absolutejs_dev_network_security["']/u.test(source);
19750
- const developmentTrustContents = networkConfigPath ? await readFile8(networkConfigPath, "utf8").then((value) => value.includes("@raw/absolutejs_dev_ca")).catch(() => false) : false;
19904
+ const developmentTrustContents = networkConfigPath ? await readFile9(networkConfigPath, "utf8").then((value) => value.includes("@raw/absolutejs_dev_ca")).catch(() => false) : false;
19751
19905
  const developmentTrust = developmentTrustReference || developmentTrustContents;
19752
19906
  return cleartext || developmentTrust ? fail("android.cleartext", developmentTrust ? "Android still references the AbsoluteJS development certificate authority." : "Android explicitly permits cleartext traffic.", manifestPath, "Run `absolute mobile sync android`; do not ship development transport or trust overrides.") : pass("android.cleartext", "Android does not explicitly permit cleartext traffic.", manifestPath);
19753
19907
  };
@@ -19758,13 +19912,13 @@ var hmrAssetsReleaseCheck = async (publicRoot) => {
19758
19912
  var embeddedBundleReleaseCheck = async (config, projectRoot, platform, publicRoot) => {
19759
19913
  const inspection = await inspectAbsoluteMobileBundle({ ...config, bundleDirectory: publicRoot }, projectRoot);
19760
19914
  if (inspection.status === "valid")
19761
- return pass(`${platform}.bundle-integrity`, `Packaged mobile manifest, runtime, routes, and ${inspection.pageCount ?? 0} page asset(s) passed structural and SHA-256 validation.`, join7(publicRoot, "absolute-mobile-manifest.json"));
19762
- return fail(`${platform}.bundle-integrity`, inspection.status === "missing" ? "The packaged mobile manifest is missing." : `The packaged mobile bundle is invalid: ${inspection.issue ?? "unknown validation error"}`, join7(publicRoot, "absolute-mobile-manifest.json"), "Rebuild the production mobile bundle and run Capacitor sync for this platform.");
19915
+ return pass(`${platform}.bundle-integrity`, `Packaged mobile manifest, runtime, routes, and ${inspection.pageCount ?? 0} page asset(s) passed structural and SHA-256 validation.`, join8(publicRoot, "absolute-mobile-manifest.json"));
19916
+ return fail(`${platform}.bundle-integrity`, inspection.status === "missing" ? "The packaged mobile manifest is missing." : `The packaged mobile bundle is invalid: ${inspection.issue ?? "unknown validation error"}`, join8(publicRoot, "absolute-mobile-manifest.json"), "Rebuild the production mobile bundle and run Capacitor sync for this platform.");
19763
19917
  };
19764
19918
  var contentSecurityPolicyCheck = async (config, platform, publicRoot) => {
19765
- const path = join7(publicRoot, "index.html");
19919
+ const path = join8(publicRoot, "index.html");
19766
19920
  try {
19767
- const source = await readFile8(path, "utf8");
19921
+ const source = await readFile9(path, "utf8");
19768
19922
  const requirements = [
19769
19923
  "Content-Security-Policy",
19770
19924
  "default-src 'self'",
@@ -19793,12 +19947,12 @@ var validateExpoCodeSigningProjection = async (config, expo) => {
19793
19947
  return;
19794
19948
  if (!generatedUpdates || generatedUpdates.codeSigningCertificate !== "./certs/absolute-mobile-update.pem" || !isRecord3(generatedUpdates.codeSigningMetadata) || generatedUpdates.codeSigningMetadata.keyid !== configuredSigning.keyId || generatedUpdates.codeSigningMetadata.alg !== configuredSigning.algorithm)
19795
19949
  throw new TypeError("Generated Expo code-signing metadata does not match mobile config.");
19796
- const generatedCertificate = await readFile8(join7(config.nativeProjectDirectory, "certs", "absolute-mobile-update.pem"), "utf8");
19950
+ const generatedCertificate = await readFile9(join8(config.nativeProjectDirectory, "certs", "absolute-mobile-update.pem"), "utf8");
19797
19951
  if (generatedCertificate !== configuredSigning.certificatePem)
19798
19952
  throw new TypeError("Generated Expo code-signing certificate does not match mobile config.");
19799
19953
  };
19800
19954
  var expoApplicationConfigCheck = async (config, projectRoot) => {
19801
- const path = join7(config.nativeProjectDirectory, "app.json");
19955
+ const path = join8(config.nativeProjectDirectory, "app.json");
19802
19956
  try {
19803
19957
  const root = await readJsonObject(path);
19804
19958
  if (!isRecord3(root.expo))
@@ -19821,12 +19975,12 @@ var expoApplicationConfigCheck = async (config, projectRoot) => {
19821
19975
  }
19822
19976
  };
19823
19977
  var expoEmbeddedAssetsCheck = async (config) => {
19824
- const generated = join7(config.nativeProjectDirectory, "src", "generated", "webAssets.ts");
19825
- const assetsRoot = join7(config.nativeProjectDirectory, "assets", "absolute");
19978
+ const generated = join8(config.nativeProjectDirectory, "src", "generated", "webAssets.ts");
19979
+ const assetsRoot = join8(config.nativeProjectDirectory, "assets", "absolute");
19826
19980
  try {
19827
19981
  const [source, manifest] = await Promise.all([
19828
- readFile8(generated, "utf8"),
19829
- readJsonObject(join7(config.bundleDirectory, "absolute-mobile-manifest.json"))
19982
+ readFile9(generated, "utf8"),
19983
+ readJsonObject(join8(config.bundleDirectory, "absolute-mobile-manifest.json"))
19830
19984
  ]);
19831
19985
  if (source.includes("embedded AbsoluteJS bundle is unavailable") || typeof manifest.appBuild !== "string" || !source.includes(JSON.stringify(manifest.appBuild)) || !source.includes(JSON.stringify(config.productionOrigin))) {
19832
19986
  throw new TypeError("Generated Expo assets do not contain the prepared production release identity.");
@@ -19841,7 +19995,7 @@ var expoEmbeddedAssetsCheck = async (config) => {
19841
19995
  }))).sort();
19842
19996
  if (sourceFiles.length === 0 || embeddedFiles.length !== 1)
19843
19997
  throw new TypeError("Generated Expo asset count does not match the prepared mobile bundle.");
19844
- const contents = await Promise.all(sourceFiles.map((path) => readFile8(join7(config.bundleDirectory, path))));
19998
+ const contents = await Promise.all(sourceFiles.map((path) => readFile9(join8(config.bundleDirectory, path))));
19845
19999
  let offset = 0;
19846
20000
  const entries = sourceFiles.map((path, index) => {
19847
20001
  const entry = {
@@ -19852,7 +20006,7 @@ var expoEmbeddedAssetsCheck = async (config) => {
19852
20006
  offset += entry.length;
19853
20007
  return entry;
19854
20008
  });
19855
- const archive = await readFile8(join7(assetsRoot, embeddedFiles[0] ?? ""));
20009
+ const archive = await readFile9(join8(assetsRoot, embeddedFiles[0] ?? ""));
19856
20010
  if (!archive.equals(Buffer.concat(contents)) || entries.some((entry) => !source.includes(JSON.stringify(entry))))
19857
20011
  throw new TypeError("Generated Expo asset bytes differ from the prepared mobile bundle.");
19858
20012
  return pass("expo.bundle-projection", `Expo embeds the complete signed mobile bundle as one opaque archive containing ${sourceFiles.length} file(s).`, generated);
@@ -19864,20 +20018,20 @@ var sourceFiles = async (root, extensions) => {
19864
20018
  if (!await pathExists2(root))
19865
20019
  return [];
19866
20020
  const files = await Array.fromAsync(new Bun.Glob("**/*").scan({ cwd: root, onlyFiles: true }));
19867
- return files.filter((file) => extensions.has(extname(file))).map((file) => join7(root, file));
20021
+ return files.filter((file) => extensions.has(extname(file))).map((file) => join8(root, file));
19868
20022
  };
19869
20023
  var containsPattern = async (paths, pattern) => {
19870
- const sources = await Promise.all(paths.map((path) => readFile8(path, "utf8")));
20024
+ const sources = await Promise.all(paths.map((path) => readFile9(path, "utf8")));
19871
20025
  const index = sources.findIndex((source) => pattern.test(source));
19872
20026
  return index === NOT_FOUND3 ? undefined : paths[index];
19873
20027
  };
19874
20028
  var androidNativeSecurityCheck = async (androidRoot) => {
19875
- const manifestPath = join7(androidRoot, "app/src/main/AndroidManifest.xml");
20029
+ const manifestPath = join8(androidRoot, "app/src/main/AndroidManifest.xml");
19876
20030
  try {
19877
- const manifest = await readFile8(manifestPath, "utf8");
20031
+ const manifest = await readFile9(manifestPath, "utf8");
19878
20032
  if (/android:debuggable=["']true["']/u.test(manifest))
19879
20033
  throw new TypeError("Android release manifest explicitly enables application debugging.");
19880
- const sources = await sourceFiles(join7(androidRoot, "app/src/main"), new Set([".java", ".kt"]));
20034
+ const sources = await sourceFiles(join8(androidRoot, "app/src/main"), new Set([".java", ".kt"]));
19881
20035
  const debugSource = await containsPattern(sources, /setWebContentsDebuggingEnabled\s*\(\s*true\s*\)/u);
19882
20036
  if (debugSource)
19883
20037
  return fail("android.native-debugging", "Android application source unconditionally enables WebView debugging.", debugSource, "Remove the unconditional WebView debugging call; use the platform debug-build behavior during development.");
@@ -19887,7 +20041,7 @@ var androidNativeSecurityCheck = async (androidRoot) => {
19887
20041
  }
19888
20042
  };
19889
20043
  var androidExportedComponentsCheck = async (manifestPath) => {
19890
- const source = await readFile8(manifestPath, "utf8").catch(() => "");
20044
+ const source = await readFile9(manifestPath, "utf8").catch(() => "");
19891
20045
  const exported = [
19892
20046
  ...source.matchAll(/<(?:activity|activity-alias|provider|receiver|service)\b[^>]*>/giu)
19893
20047
  ].map(([tag]) => tag).filter((tag) => /android:exported=["']true["']/iu.test(tag)).map((tag) => tag.match(/android:name=["']([^"']+)["']/iu)?.[1]).filter((name) => Boolean(name) && name !== ".MainActivity");
@@ -19895,7 +20049,7 @@ var androidExportedComponentsCheck = async (manifestPath) => {
19895
20049
  };
19896
20050
  var androidDeepLinkProjectionCheck = async (config, manifestPath) => {
19897
20051
  try {
19898
- const source = await readFile8(manifestPath, "utf8");
20052
+ const source = await readFile9(manifestPath, "utf8");
19899
20053
  const hasWebHost = (host) => [...source.matchAll(/<data\b[^>]*>/giu)].some(([tag]) => tag.includes('android:scheme="https"') && tag.includes(`android:host="${host}"`));
19900
20054
  if (!source.includes('android:autoVerify="true"') || !source.includes("android.intent.category.BROWSABLE") || config.deepLinkHosts.some((host) => !hasWebHost(host)) || config.deepLinkScheme && !source.includes(`android:scheme="${config.deepLinkScheme}"`))
19901
20055
  throw new TypeError("Android App Link or custom-scheme projection does not match mobile config.");
@@ -19909,15 +20063,15 @@ var nativeUpdateWatchdogCheck = async (config, platform) => {
19909
20063
  return;
19910
20064
  const timeout = String(config.updates.bootTimeoutMs);
19911
20065
  if (platform === "ios") {
19912
- const path = join7(config.nativeProjectDirectory, "ios/App/App/AppDelegate.swift");
19913
- const configPath = join7(config.nativeProjectDirectory, "ios/App/App/capacitor.config.json");
20066
+ const path = join8(config.nativeProjectDirectory, "ios/App/App/AppDelegate.swift");
20067
+ const configPath = join8(config.nativeProjectDirectory, "ios/App/App/capacitor.config.json");
19914
20068
  const [source, nativeConfig] = await Promise.all([
19915
- readFile8(path, "utf8").catch(() => ""),
19916
- readFile8(configPath, "utf8").catch(() => "")
20069
+ readFile9(path, "utf8").catch(() => ""),
20070
+ readFile9(configPath, "utf8").catch(() => "")
19917
20071
  ]);
19918
20072
  return source.includes("AbsoluteMobileUpdateWatchdogPlugin") && source.includes("recoverInterruptedBoot()") && source.includes(`.milliseconds(${timeout})`) && source.includes("quarantinedReleases") && nativeConfig.includes("AbsoluteMobileUpdateWatchdogPlugin") ? pass("ios.update-watchdog", `The native update boot watchdog is projected with a ${timeout}ms deadline.`, path) : fail("ios.update-watchdog", "The iOS update boot watchdog does not match mobile config.", path, "Run `absolute mobile sync ios` before building the release.");
19919
20073
  }
19920
- const sourceRoot = join7(config.nativeProjectDirectory, "android/app/src/main");
20074
+ const sourceRoot = join8(config.nativeProjectDirectory, "android/app/src/main");
19921
20075
  const sources = await sourceFiles(sourceRoot, new Set([".java", ".kt"]));
19922
20076
  const [activity, plugin] = await Promise.all([
19923
20077
  containsPattern(sources, /recoverInterruptedBoot\s*\(\s*this\s*\)/u),
@@ -19930,27 +20084,27 @@ var nativeObservabilityProjectionCheck = async (config, platform) => {
19930
20084
  return;
19931
20085
  const nativeRoot = config.nativeProjectDirectory;
19932
20086
  if (config.engine === "expo") {
19933
- const moduleRoot = join7(nativeRoot, "modules", "absolute-mobile-observability");
19934
- const configPath = join7(moduleRoot, "expo-module.config.json");
19935
- const sourcePath = platform === "android" ? join7(moduleRoot, "android/src/main/java/expo/modules/absolutemobileobservability/AbsoluteMobileObservabilityModule.kt") : join7(moduleRoot, "ios/AbsoluteMobileObservabilityModule.swift");
20087
+ const moduleRoot = join8(nativeRoot, "modules", "absolute-mobile-observability");
20088
+ const configPath = join8(moduleRoot, "expo-module.config.json");
20089
+ const sourcePath = platform === "android" ? join8(moduleRoot, "android/src/main/java/expo/modules/absolutemobileobservability/AbsoluteMobileObservabilityModule.kt") : join8(moduleRoot, "ios/AbsoluteMobileObservabilityModule.swift");
19936
20090
  const [moduleConfig, source] = await Promise.all([
19937
- readFile8(configPath, "utf8").catch(() => ""),
19938
- readFile8(sourcePath, "utf8").catch(() => "")
20091
+ readFile9(configPath, "utf8").catch(() => ""),
20092
+ readFile9(sourcePath, "utf8").catch(() => "")
19939
20093
  ]);
19940
20094
  const valid = moduleConfig.includes("AbsoluteMobileObservabilityModule") && source.includes("AbsoluteMobileObservability") && (platform === "android" ? source.includes("getHistoricalProcessExitReasons") : source.includes("MXMetricManagerSubscriber"));
19941
20095
  return valid ? pass(`${platform}.native-observability`, `The Expo ${platform} native process collector is projected and autolinkable.`, sourcePath) : fail(`${platform}.native-observability`, `The Expo ${platform} native process collector is missing or incomplete.`, sourcePath, `Run \`absolute mobile build ${platform}\` before building the release.`);
19942
20096
  }
19943
20097
  if (platform === "ios") {
19944
- const delegatePath = join7(nativeRoot, "ios/App/App/AppDelegate.swift");
19945
- const configPath = join7(nativeRoot, "ios/App/App/capacitor.config.json");
20098
+ const delegatePath = join8(nativeRoot, "ios/App/App/AppDelegate.swift");
20099
+ const configPath = join8(nativeRoot, "ios/App/App/capacitor.config.json");
19946
20100
  const [delegate, nativeConfig] = await Promise.all([
19947
- readFile8(delegatePath, "utf8").catch(() => ""),
19948
- readFile8(configPath, "utf8").catch(() => "")
20101
+ readFile9(delegatePath, "utf8").catch(() => ""),
20102
+ readFile9(configPath, "utf8").catch(() => "")
19949
20103
  ]);
19950
20104
  const valid = delegate.includes("AbsoluteMobileObservabilityPlugin") && delegate.includes("MXMetricManagerSubscriber") && nativeConfig.includes("AbsoluteMobileObservabilityPlugin");
19951
20105
  return valid ? pass("ios.native-observability", "The iOS MetricKit native process collector is projected and registered.", delegatePath) : fail("ios.native-observability", "The iOS MetricKit native process collector is missing or unregistered.", delegatePath, "Run `absolute mobile sync ios` before building the release.");
19952
20106
  }
19953
- const sourceRoot = join7(nativeRoot, "android/app/src/main");
20107
+ const sourceRoot = join8(nativeRoot, "android/app/src/main");
19954
20108
  const sources = await sourceFiles(sourceRoot, new Set([".java", ".kt"]));
19955
20109
  const [registration, plugin] = await Promise.all([
19956
20110
  containsPattern(sources, /registerPlugin\s*\(\s*AbsoluteMobileObservabilityPlugin(?:::class\.java|\.class)\s*\)/u),
@@ -19971,14 +20125,14 @@ var iosNativeSecurityCheck = async (iosRoot) => {
19971
20125
  return pass("ios.native-debugging", "iOS source does not enable release debugger attachment or WebView inspection.", entitlementPaths[0] ?? iosRoot);
19972
20126
  };
19973
20127
  var iosDeepLinkProjectionCheck = async (config, iosRoot) => {
19974
- const infoPath = join7(iosRoot, "App/App/Info.plist");
19975
- const entitlementsPath = join7(iosRoot, "App/AbsoluteJS.entitlements");
19976
- const projectPath2 = join7(iosRoot, "App/App.xcodeproj/project.pbxproj");
20128
+ const infoPath = join8(iosRoot, "App/App/Info.plist");
20129
+ const entitlementsPath = join8(iosRoot, "App/AbsoluteJS.entitlements");
20130
+ const projectPath2 = join8(iosRoot, "App/App.xcodeproj/project.pbxproj");
19977
20131
  try {
19978
20132
  const [info, entitlements, project] = await Promise.all([
19979
- readFile8(infoPath, "utf8"),
19980
- readFile8(entitlementsPath, "utf8"),
19981
- readFile8(projectPath2, "utf8")
20133
+ readFile9(infoPath, "utf8"),
20134
+ readFile9(entitlementsPath, "utf8"),
20135
+ readFile9(projectPath2, "utf8")
19982
20136
  ]);
19983
20137
  if (config.deepLinkScheme && (!info.includes("<key>CFBundleURLTypes</key>") || !info.includes(`<string>${config.deepLinkScheme}</string>`)))
19984
20138
  throw new TypeError("iOS custom URL scheme does not match mobile config.");
@@ -19994,7 +20148,7 @@ var iosDeepLinkProjectionCheck = async (config, iosRoot) => {
19994
20148
  var syncSchemaReleaseCheck = (projectRoot) => {
19995
20149
  if (!projectUsesAbsoluteSync(projectRoot))
19996
20150
  return;
19997
- const manifestPath = join7(projectRoot, "package.json");
20151
+ const manifestPath = join8(projectRoot, "package.json");
19998
20152
  try {
19999
20153
  const schema = discoverAbsoluteSyncSchema(projectRoot);
20000
20154
  const versions = schema.components.map((component) => `${component.id}@${component.version}`).join(", ");
@@ -20024,8 +20178,8 @@ var IOS_USAGE_KEYS = {
20024
20178
  var androidDevicePermissionCheck = async (config, permissions) => {
20025
20179
  if (!config.platforms.includes("android") || permissions.length === 0)
20026
20180
  return;
20027
- const path = join7(config.nativeProjectDirectory, "android/app/src/main/AndroidManifest.xml");
20028
- const source = await readFile8(path, "utf8");
20181
+ const path = join8(config.nativeProjectDirectory, "android/app/src/main/AndroidManifest.xml");
20182
+ const source = await readFile9(path, "utf8");
20029
20183
  const missing = permissions.filter((permission) => !source.includes(`android:name="${permission}"`) && !source.includes(`android:name='${permission}'`));
20030
20184
  if (missing.length === 0)
20031
20185
  return;
@@ -20034,9 +20188,9 @@ var androidDevicePermissionCheck = async (config, permissions) => {
20034
20188
  var iosDevicePermissionCheck = async (config, purposes) => {
20035
20189
  if (!config.platforms.includes("ios") || purposes.length === 0)
20036
20190
  return;
20037
- const iosRoot = join7(config.nativeProjectDirectory, "ios");
20038
- const path = config.engine === "expo" ? await uniqueExpoIosFile(iosRoot, "**/Info.plist", "Info.plist") : join7(iosRoot, "App/App/Info.plist");
20039
- const source = await readFile8(path, "utf8");
20191
+ const iosRoot = join8(config.nativeProjectDirectory, "ios");
20192
+ const path = config.engine === "expo" ? await uniqueExpoIosFile(iosRoot, "**/Info.plist", "Info.plist") : join8(iosRoot, "App/App/Info.plist");
20193
+ const source = await readFile9(path, "utf8");
20040
20194
  const missing = purposes.filter((purpose) => !source.includes(`<key>${IOS_USAGE_KEYS[purpose]}</key>`));
20041
20195
  if (missing.length === 0)
20042
20196
  return;
@@ -20046,7 +20200,7 @@ var expoIosPrivacyCapabilityCheck = async (iosRoot, project, requirements) => {
20046
20200
  if (requirements.iosPrivacyAccessedApis.length === 0)
20047
20201
  return;
20048
20202
  const privacyPath = await uniqueExpoIosFile(iosRoot, "**/PrivacyInfo.xcprivacy", "privacy manifest");
20049
- const privacy = await readFile8(privacyPath, "utf8");
20203
+ const privacy = await readFile9(privacyPath, "utf8");
20050
20204
  const missing = requirements.iosPrivacyAccessedApis.some(({ api, reasons }) => !privacy.includes(`<string>${api}</string>`) || reasons.some((reason) => !privacy.includes(`<string>${reason}</string>`)));
20051
20205
  if (!missing && project.includes(privacyPath.split(/[\\/]/u).at(-1) ?? ""))
20052
20206
  return;
@@ -20056,15 +20210,15 @@ var expoIosPushCapabilityCheck = async (iosRoot, requirements) => {
20056
20210
  if (!requirements.iosPushNotifications)
20057
20211
  return;
20058
20212
  const entitlementsPath = await uniqueExpoIosFile(iosRoot, "**/*.entitlements", "entitlements");
20059
- const entitlements = await readFile8(entitlementsPath, "utf8");
20213
+ const entitlements = await readFile9(entitlementsPath, "utf8");
20060
20214
  if (entitlements.includes("<key>aps-environment</key>"))
20061
20215
  return;
20062
20216
  return fail("mobile.device-capabilities", "Expo iOS push entitlement does not match detected capabilities.", entitlementsPath, "Run `absolute mobile build ios` to regenerate native push integration.");
20063
20217
  };
20064
20218
  var expoIosCapabilityProjectionCheck = async (config, requirements) => {
20065
- const iosRoot = join7(config.nativeProjectDirectory, "ios");
20219
+ const iosRoot = join8(config.nativeProjectDirectory, "ios");
20066
20220
  const projectPath2 = await uniqueExpoIosFile(iosRoot, "**/*.xcodeproj/project.pbxproj", "Xcode project");
20067
- const project = await readFile8(projectPath2, "utf8");
20221
+ const project = await readFile9(projectPath2, "utf8");
20068
20222
  const privacy = await expoIosPrivacyCapabilityCheck(iosRoot, project, requirements);
20069
20223
  if (privacy)
20070
20224
  return privacy;
@@ -20075,28 +20229,28 @@ var iosCapabilityProjectionCheck = async (config, requirements) => {
20075
20229
  return;
20076
20230
  if (config.engine === "expo")
20077
20231
  return expoIosCapabilityProjectionCheck(config, requirements);
20078
- const appRoot = join7(config.nativeProjectDirectory, "ios/App/App");
20079
- const infoPath = join7(appRoot, "Info.plist");
20080
- const info = await readFile8(infoPath, "utf8").catch(() => "");
20232
+ const appRoot = join8(config.nativeProjectDirectory, "ios/App/App");
20233
+ const infoPath = join8(appRoot, "Info.plist");
20234
+ const info = await readFile9(infoPath, "utf8").catch(() => "");
20081
20235
  if (requirements.iosSystemBars && !/<key>UIViewControllerBasedStatusBarAppearance<\/key>\s*<true\s*\/>/u.test(info))
20082
20236
  return fail("mobile.device-capabilities", "iOS system-bar capability is missing its required view-controller setting.", infoPath, "Run `absolute mobile sync ios` to regenerate native capability settings.");
20083
20237
  if (requirements.iosPrivacyAccessedApis.length > 0) {
20084
- const privacyPath = join7(appRoot, "PrivacyInfo.xcprivacy");
20085
- const projectPath2 = join7(config.nativeProjectDirectory, "ios/App/App.xcodeproj/project.pbxproj");
20238
+ const privacyPath = join8(appRoot, "PrivacyInfo.xcprivacy");
20239
+ const projectPath2 = join8(config.nativeProjectDirectory, "ios/App/App.xcodeproj/project.pbxproj");
20086
20240
  const [privacy, project] = await Promise.all([
20087
- readFile8(privacyPath, "utf8").catch(() => ""),
20088
- readFile8(projectPath2, "utf8").catch(() => "")
20241
+ readFile9(privacyPath, "utf8").catch(() => ""),
20242
+ readFile9(projectPath2, "utf8").catch(() => "")
20089
20243
  ]);
20090
20244
  const missing = requirements.iosPrivacyAccessedApis.some(({ api, reasons }) => !privacy.includes(`<string>${api}</string>`) || reasons.some((reason) => !privacy.includes(`<string>${reason}</string>`)));
20091
20245
  if (missing || !project.includes("PrivacyInfo.xcprivacy in Resources"))
20092
20246
  return fail("mobile.device-capabilities", "iOS privacy manifest or target membership does not match detected native capabilities.", privacyPath, "Run `absolute mobile sync ios` to regenerate and target PrivacyInfo.xcprivacy.");
20093
20247
  }
20094
20248
  if (requirements.iosPushNotifications) {
20095
- const entitlementsPath = join7(config.nativeProjectDirectory, "ios/App/AbsoluteJS.entitlements");
20096
- const delegatePath = join7(appRoot, "AppDelegate.swift");
20249
+ const entitlementsPath = join8(config.nativeProjectDirectory, "ios/App/AbsoluteJS.entitlements");
20250
+ const delegatePath = join8(appRoot, "AppDelegate.swift");
20097
20251
  const [entitlements, delegate] = await Promise.all([
20098
- readFile8(entitlementsPath, "utf8").catch(() => ""),
20099
- readFile8(delegatePath, "utf8").catch(() => "")
20252
+ readFile9(entitlementsPath, "utf8").catch(() => ""),
20253
+ readFile9(delegatePath, "utf8").catch(() => "")
20100
20254
  ]);
20101
20255
  if (!entitlements.includes("<key>aps-environment</key>") || !delegate.includes("capacitorDidRegisterForRemoteNotifications") || !delegate.includes("capacitorDidFailToRegisterForRemoteNotifications"))
20102
20256
  return fail("mobile.device-capabilities", "iOS push entitlement or AppDelegate forwarding does not match detected capabilities.", entitlementsPath, "Run `absolute mobile sync ios` to regenerate native push integration.");
@@ -20104,13 +20258,13 @@ var iosCapabilityProjectionCheck = async (config, requirements) => {
20104
20258
  return;
20105
20259
  };
20106
20260
  var deviceCapabilityReleaseCheck = async (config, projectRoot) => {
20107
- const manifestPath = join7(projectRoot, "package.json");
20261
+ const manifestPath = join8(projectRoot, "package.json");
20108
20262
  try {
20109
20263
  const plan = resolveAbsoluteDeviceCapabilityPlan(projectRoot, config.engine);
20110
20264
  const assertPackages = async () => {
20111
20265
  if (config.engine === "capacitor")
20112
20266
  return assertAbsoluteDeviceCapabilityPackages(projectRoot, plan);
20113
- const generated = await readJsonObject(join7(config.nativeProjectDirectory, "package.json"));
20267
+ const generated = await readJsonObject(join8(config.nativeProjectDirectory, "package.json"));
20114
20268
  const declarations = packageDeclarations(generated);
20115
20269
  const missing = plan.requiredPackages.filter((spec) => {
20116
20270
  const separator = spec.lastIndexOf("@");
@@ -20137,11 +20291,11 @@ var deviceCapabilityReleaseCheck = async (config, projectRoot) => {
20137
20291
  }
20138
20292
  };
20139
20293
  var inspectAndroidRelease = async (config, projectRoot) => {
20140
- const androidRoot = join7(config.nativeProjectDirectory, "android");
20141
- const nativeConfigPath = join7(androidRoot, "app", "src", "main", "assets", "capacitor.config.json");
20142
- const manifestPath = join7(androidRoot, "app", "src", "main", "AndroidManifest.xml");
20143
- const publicRoot = join7(androidRoot, "app", "src", "main", "assets", "public");
20144
- const journalPath = join7(projectRoot, ".absolutejs", "mobile", "dev-session", "journal.json");
20294
+ const androidRoot = join8(config.nativeProjectDirectory, "android");
20295
+ const nativeConfigPath = join8(androidRoot, "app", "src", "main", "assets", "capacitor.config.json");
20296
+ const manifestPath = join8(androidRoot, "app", "src", "main", "AndroidManifest.xml");
20297
+ const publicRoot = join8(androidRoot, "app", "src", "main", "assets", "public");
20298
+ const journalPath = join8(projectRoot, ".absolutejs", "mobile", "dev-session", "journal.json");
20145
20299
  const checks = await Promise.all([
20146
20300
  journalReleaseCheck(journalPath, "android"),
20147
20301
  capacitorConfigReleaseCheck(nativeConfigPath),
@@ -20162,9 +20316,9 @@ var inspectAndroidRelease = async (config, projectRoot) => {
20162
20316
  }));
20163
20317
  };
20164
20318
  var inspectExpoAndroidRelease = async (config, projectRoot) => {
20165
- const androidRoot = join7(config.nativeProjectDirectory, "android");
20166
- const manifestPath = join7(androidRoot, "app", "src", "main", "AndroidManifest.xml");
20167
- const journalPath = join7(projectRoot, ".absolutejs", "mobile", "expo-dev-session", "journal.json");
20319
+ const androidRoot = join8(config.nativeProjectDirectory, "android");
20320
+ const manifestPath = join8(androidRoot, "app", "src", "main", "AndroidManifest.xml");
20321
+ const journalPath = join8(projectRoot, ".absolutejs", "mobile", "expo-dev-session", "journal.json");
20168
20322
  const checks = await Promise.all([
20169
20323
  journalReleaseCheck(journalPath, "android"),
20170
20324
  expoApplicationConfigCheck(config, projectRoot),
@@ -20190,7 +20344,7 @@ var uniqueExpoIosFile = async (iosRoot, pattern, label) => {
20190
20344
  const [path] = paths;
20191
20345
  if (!path)
20192
20346
  throw new TypeError(`Generated Expo iOS project is missing its ${label}.`);
20193
- return join7(iosRoot, path);
20347
+ return join8(iosRoot, path);
20194
20348
  };
20195
20349
  var expoIosNativeProjectionCheck = async (config, iosRoot) => {
20196
20350
  try {
@@ -20200,9 +20354,9 @@ var expoIosNativeProjectionCheck = async (config, iosRoot) => {
20200
20354
  uniqueExpoIosFile(iosRoot, "**/*.xcodeproj/project.pbxproj", "Xcode project")
20201
20355
  ]);
20202
20356
  const [info, entitlements, project] = await Promise.all([
20203
- readFile8(infoPath, "utf8"),
20204
- readFile8(entitlementsPath, "utf8"),
20205
- readFile8(projectPath2, "utf8")
20357
+ readFile9(infoPath, "utf8"),
20358
+ readFile9(entitlementsPath, "utf8"),
20359
+ readFile9(projectPath2, "utf8")
20206
20360
  ]);
20207
20361
  if (/<key>NSAllowsArbitraryLoads<\/key>\s*<true\s*\/>/u.test(info))
20208
20362
  throw new TypeError("Expo iOS App Transport Security permits arbitrary network loads.");
@@ -20218,8 +20372,8 @@ var expoIosNativeProjectionCheck = async (config, iosRoot) => {
20218
20372
  }
20219
20373
  };
20220
20374
  var inspectExpoIosRelease = async (config, projectRoot) => {
20221
- const iosRoot = join7(config.nativeProjectDirectory, "ios");
20222
- const journalPath = join7(projectRoot, ".absolutejs", "mobile", "expo-dev-session", "journal.json");
20375
+ const iosRoot = join8(config.nativeProjectDirectory, "ios");
20376
+ const journalPath = join8(projectRoot, ".absolutejs", "mobile", "expo-dev-session", "journal.json");
20223
20377
  const checks = [
20224
20378
  await journalReleaseCheck(journalPath, "ios")
20225
20379
  ];
@@ -20242,11 +20396,11 @@ var inspectExpoIosRelease = async (config, projectRoot) => {
20242
20396
  }));
20243
20397
  };
20244
20398
  var inspectIosRelease = async (config, projectRoot) => {
20245
- const iosAppRoot = join7(config.nativeProjectDirectory, "ios", "App", "App");
20246
- const nativeConfigPath = join7(iosAppRoot, "capacitor.config.json");
20247
- const infoPath = join7(iosAppRoot, "Info.plist");
20248
- const publicRoot = join7(iosAppRoot, "public");
20249
- const journalPath = join7(projectRoot, ".absolutejs", "mobile", "ios-dev-session", "journal.json");
20399
+ const iosAppRoot = join8(config.nativeProjectDirectory, "ios", "App", "App");
20400
+ const nativeConfigPath = join8(iosAppRoot, "capacitor.config.json");
20401
+ const infoPath = join8(iosAppRoot, "Info.plist");
20402
+ const publicRoot = join8(iosAppRoot, "public");
20403
+ const journalPath = join8(projectRoot, ".absolutejs", "mobile", "ios-dev-session", "journal.json");
20250
20404
  const checks = [
20251
20405
  await journalReleaseCheck(journalPath, "ios")
20252
20406
  ];
@@ -20258,7 +20412,7 @@ var inspectIosRelease = async (config, projectRoot) => {
20258
20412
  }
20259
20413
  if (!await pathExists2(nativeConfigPath)) {
20260
20414
  checks.push(fail("ios.capacitor-config", "The generated iOS Capacitor config is missing.", nativeConfigPath, "Run `absolute mobile sync ios` before release validation."));
20261
- } else if (isUnsafeCapacitorConfig(await readFile8(nativeConfigPath, "utf8"))) {
20415
+ } else if (isUnsafeCapacitorConfig(await readFile9(nativeConfigPath, "utf8"))) {
20262
20416
  checks.push(fail("ios.capacitor-config", "iOS Capacitor config contains a development server URL, cleartext transport, navigation allowlist, or invalid JSON.", nativeConfigPath, "Run `absolute mobile sync ios`; do not ship development transport overrides."));
20263
20417
  } else {
20264
20418
  checks.push(pass("ios.capacitor-config", "iOS Capacitor config contains no development transport overrides.", nativeConfigPath));
@@ -20267,12 +20421,12 @@ var inspectIosRelease = async (config, projectRoot) => {
20267
20421
  if (!await pathExists2(infoPath)) {
20268
20422
  checks.push(fail("ios.transport-security", "The iOS Info.plist is missing.", infoPath, "Run `absolute mobile sync ios` before release validation."));
20269
20423
  } else {
20270
- const info = await readFile8(infoPath, "utf8");
20424
+ const info = await readFile9(infoPath, "utf8");
20271
20425
  checks.push(/<key>NSAllowsArbitraryLoads<\/key>\s*<true\s*\/>/u.test(info) ? fail("ios.transport-security", "iOS App Transport Security permits arbitrary network loads.", infoPath, "Remove NSAllowsArbitraryLoads from the release Info.plist.") : pass("ios.transport-security", "iOS App Transport Security does not permit arbitrary loads.", infoPath));
20272
20426
  }
20273
20427
  const hmrAsset = await findHmrAsset(publicRoot);
20274
20428
  checks.push(hmrAsset ? fail("ios.hmr-assets", "A packaged iOS asset contains the development HMR client.", hmrAsset, "Rebuild the production mobile bundle and run Capacitor sync again.") : pass("ios.hmr-assets", "Packaged iOS assets contain no development HMR markers.", publicRoot));
20275
- checks.push(await embeddedBundleReleaseCheck(config, projectRoot, "ios", publicRoot), await contentSecurityPolicyCheck(config, "ios", publicRoot), await iosNativeSecurityCheck(join7(config.nativeProjectDirectory, "ios")), await iosDeepLinkProjectionCheck(config, join7(config.nativeProjectDirectory, "ios")));
20429
+ checks.push(await embeddedBundleReleaseCheck(config, projectRoot, "ios", publicRoot), await contentSecurityPolicyCheck(config, "ios", publicRoot), await iosNativeSecurityCheck(join8(config.nativeProjectDirectory, "ios")), await iosDeepLinkProjectionCheck(config, join8(config.nativeProjectDirectory, "ios")));
20276
20430
  const nativeObservability = await nativeObservabilityProjectionCheck(config, "ios");
20277
20431
  if (nativeObservability)
20278
20432
  checks.push(nativeObservability);
@@ -20342,16 +20496,16 @@ import { createHash as createHash2 } from "crypto";
20342
20496
  import {
20343
20497
  access as access5,
20344
20498
  copyFile,
20345
- mkdir as mkdir6,
20499
+ mkdir as mkdir7,
20346
20500
  mkdtemp,
20347
- readFile as readFile9,
20501
+ readFile as readFile10,
20348
20502
  realpath,
20349
- rename as rename7,
20503
+ rename as rename8,
20350
20504
  rm as rm4,
20351
20505
  stat as stat2,
20352
- writeFile as writeFile8
20506
+ writeFile as writeFile9
20353
20507
  } from "fs/promises";
20354
- import { dirname as dirname6, isAbsolute as isAbsolute2, join as join8, relative as relative4, resolve as resolve5, sep as sep2 } from "path";
20508
+ import { dirname as dirname7, isAbsolute as isAbsolute2, join as join9, relative as relative4, resolve as resolve5, sep as sep2 } from "path";
20355
20509
  var ABSOLUTE_ANDROID_RELEASE_FORMAT = 1;
20356
20510
  var isRecord4 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
20357
20511
  var requireManifest = (value) => {
@@ -20430,7 +20584,7 @@ var windowsJarsignerPath = (path, capture) => {
20430
20584
  }
20431
20585
  return translated;
20432
20586
  };
20433
- var sha256File = async (path) => createHash2("sha256").update(await readFile9(path)).digest("hex");
20587
+ var sha256File = async (path) => createHash2("sha256").update(await readFile10(path)).digest("hex");
20434
20588
  var fingerprintExpoAndroidProject = async (nativeDirectory) => {
20435
20589
  const root = await realpath(nativeDirectory);
20436
20590
  const files = await Array.fromAsync(new Bun.Glob("**/*").scan({ cwd: root, onlyFiles: true }));
@@ -20438,7 +20592,7 @@ var fingerprintExpoAndroidProject = async (nativeDirectory) => {
20438
20592
  const parts = path.replaceAll("\\", "/").split("/");
20439
20593
  return !parts.includes(".gradle") && !parts.includes("build");
20440
20594
  }).sort().map(async (path) => {
20441
- const contents = await readFile9(join8(root, path));
20595
+ const contents = await readFile10(join9(root, path));
20442
20596
  return `${path.replaceAll("\\", "/")}\x00${createHash2("sha256").update(contents).digest("hex")}\x00`;
20443
20597
  }));
20444
20598
  return createHash2("sha256").update(records.join("")).digest("hex");
@@ -20453,11 +20607,11 @@ var safeOutputDirectory = (projectRoot, requested) => {
20453
20607
  return output;
20454
20608
  };
20455
20609
  var installRelease = async (artifactPath, metadata, outputRoot) => {
20456
- const releaseRoot = join8(outputRoot, metadata.releaseId);
20610
+ const releaseRoot = join9(outputRoot, metadata.releaseId);
20457
20611
  const artifactName = "app-release.aab";
20458
- const destination = join8(releaseRoot, artifactName);
20612
+ const destination = join9(releaseRoot, artifactName);
20459
20613
  if (await pathExists3(releaseRoot)) {
20460
- const existing = requireManifestIdentity(JSON.parse(await readFile9(join8(releaseRoot, "release.json"), "utf8")), metadata);
20614
+ const existing = requireManifestIdentity(JSON.parse(await readFile10(join9(releaseRoot, "release.json"), "utf8")), metadata);
20461
20615
  const [installedBytes, installedSha256] = await Promise.all([
20462
20616
  stat2(destination).then(({ size }) => size),
20463
20617
  sha256File(destination)
@@ -20467,17 +20621,17 @@ var installRelease = async (artifactPath, metadata, outputRoot) => {
20467
20621
  }
20468
20622
  return { artifactPath: destination, metadata: existing, releaseRoot };
20469
20623
  }
20470
- await mkdir6(dirname6(releaseRoot), { recursive: true });
20471
- const staging = await mkdtemp(join8(dirname6(releaseRoot), ".android-stage-"));
20624
+ await mkdir7(dirname7(releaseRoot), { recursive: true });
20625
+ const staging = await mkdtemp(join9(dirname7(releaseRoot), ".android-stage-"));
20472
20626
  try {
20473
- await copyFile(artifactPath, join8(staging, artifactName));
20627
+ await copyFile(artifactPath, join9(staging, artifactName));
20474
20628
  const complete = {
20475
20629
  ...metadata,
20476
20630
  artifact: artifactName
20477
20631
  };
20478
- await writeFile8(join8(staging, "release.json"), `${JSON.stringify(complete, null, "\t")}
20632
+ await writeFile9(join9(staging, "release.json"), `${JSON.stringify(complete, null, "\t")}
20479
20633
  `, { flag: "wx" });
20480
- await rename7(staging, releaseRoot);
20634
+ await rename8(staging, releaseRoot);
20481
20635
  return { artifactPath: destination, metadata: complete, releaseRoot };
20482
20636
  } finally {
20483
20637
  await rm4(staging, { force: true, recursive: true }).catch(() => {
@@ -20505,8 +20659,8 @@ var buildAbsoluteAndroidRelease = async (options) => {
20505
20659
  const projectRoot = resolve5(options.projectRoot);
20506
20660
  const host = options.host ?? detectAbsoluteMobileHost();
20507
20661
  const androidRoot = options.androidRoot ?? process.env.ANDROID_HOME ?? process.env.ANDROID_SDK_ROOT ?? absoluteManagedAndroidSdkRoot(host);
20508
- const nativeDirectory = join8(options.config.nativeProjectDirectory, "android");
20509
- const manifest = requireManifest(JSON.parse(await readFile9(join8(options.config.bundleDirectory, "absolute-mobile-manifest.json"), "utf8")));
20662
+ const nativeDirectory = join9(options.config.nativeProjectDirectory, "android");
20663
+ const manifest = requireManifest(JSON.parse(await readFile10(join9(options.config.bundleDirectory, "absolute-mobile-manifest.json"), "utf8")));
20510
20664
  if (manifest.appId !== options.config.appId) {
20511
20665
  throw new TypeError("Embedded mobile manifest appId does not match mobile.appId.");
20512
20666
  }
@@ -20595,20 +20749,20 @@ var buildAbsoluteAndroidRelease = async (options) => {
20595
20749
  import { createHash as createHash3 } from "crypto";
20596
20750
  import {
20597
20751
  access as access6,
20598
- mkdir as mkdir7,
20752
+ mkdir as mkdir8,
20599
20753
  mkdtemp as mkdtemp2,
20600
- readFile as readFile10,
20601
- rename as rename8,
20754
+ readFile as readFile11,
20755
+ rename as rename9,
20602
20756
  rm as rm5,
20603
20757
  stat as stat3,
20604
- writeFile as writeFile9
20758
+ writeFile as writeFile10
20605
20759
  } from "fs/promises";
20606
20760
  import { homedir } from "os";
20607
20761
  import {
20608
20762
  basename,
20609
- dirname as dirname7,
20763
+ dirname as dirname8,
20610
20764
  isAbsolute as isAbsolute3,
20611
- join as join9,
20765
+ join as join10,
20612
20766
  relative as relative5,
20613
20767
  resolve as resolve6,
20614
20768
  sep as sep3
@@ -20662,7 +20816,10 @@ var parseAbsoluteAndroidInstalledApp = (appId, output) => {
20662
20816
  var ABSOLUTE_BUNDLETOOL_VERSION = "1.18.3";
20663
20817
  var ABSOLUTE_BUNDLETOOL_SHA256 = "a099cfa1543f55593bc2ed16a70a7c67fe54b1747bb7301f37fdfd6d91028e29";
20664
20818
  var ABSOLUTE_BUNDLETOOL_URL = `https://github.com/google/bundletool/releases/download/${ABSOLUTE_BUNDLETOOL_VERSION}/bundletool-all-${ABSOLUTE_BUNDLETOOL_VERSION}.jar`;
20665
- var EMBEDDED_READY_MARKER = "Expo embedded web content ready";
20819
+ var EMBEDDED_READY_MARKERS = {
20820
+ capacitor: "Capacitor embedded web content ready",
20821
+ expo: "Expo embedded web content ready"
20822
+ };
20666
20823
  var RELEASE_READY_POLL_MS = 250;
20667
20824
  var RELEASE_READY_TIMEOUT_MS = 30000;
20668
20825
  var RELEASE_STABILITY_MS = 2000;
@@ -20675,7 +20832,7 @@ var exists2 = async (path) => {
20675
20832
  return false;
20676
20833
  }
20677
20834
  };
20678
- var sha256 = async (path) => createHash3("sha256").update(await readFile10(path)).digest("hex");
20835
+ var sha256 = async (path) => createHash3("sha256").update(await readFile11(path)).digest("hex");
20679
20836
  var inside = (root, candidate) => {
20680
20837
  const path = relative5(resolve6(root), resolve6(candidate));
20681
20838
  return path === "" || !isAbsolute3(path) && path !== ".." && !path.startsWith(`..${sep3}`);
@@ -20717,7 +20874,7 @@ var parseMetadata = (value) => {
20717
20874
  throw new TypeError("Android release ID does not match its artifact digest.");
20718
20875
  return metadata;
20719
20876
  };
20720
- var absoluteBundletoolPath = (root = process.env.ABSOLUTE_BUNDLETOOL_ROOT ?? join9(homedir(), ".absolutejs", "tools", "bundletool")) => join9(root, ABSOLUTE_BUNDLETOOL_VERSION, "bundletool.jar");
20877
+ var absoluteBundletoolPath = (root = process.env.ABSOLUTE_BUNDLETOOL_ROOT ?? join10(homedir(), ".absolutejs", "tools", "bundletool")) => join10(root, ABSOLUTE_BUNDLETOOL_VERSION, "bundletool.jar");
20721
20878
  var inspectAbsoluteBundletool = async (root) => {
20722
20879
  const path = absoluteBundletoolPath(root);
20723
20880
  if (!await exists2(path))
@@ -20731,9 +20888,9 @@ var readAbsoluteAndroidRelease = async (projectRoot, requested) => {
20731
20888
  const selected = resolve6(root, requested);
20732
20889
  if (!inside(root, selected))
20733
20890
  throw new TypeError("mobile test android --release must remain inside the project.");
20734
- const metadataPath = basename(selected) === "release.json" ? selected : join9(selected, "release.json");
20735
- const releaseRoot = dirname7(metadataPath);
20736
- const metadata = parseMetadata(JSON.parse(await readFile10(metadataPath, "utf8")));
20891
+ const metadataPath = basename(selected) === "release.json" ? selected : join10(selected, "release.json");
20892
+ const releaseRoot = dirname8(metadataPath);
20893
+ const metadata = parseMetadata(JSON.parse(await readFile11(metadataPath, "utf8")));
20737
20894
  const artifactPath = resolve6(releaseRoot, metadata.artifact);
20738
20895
  if (!inside(releaseRoot, artifactPath) || basename(artifactPath) !== metadata.artifact)
20739
20896
  throw new TypeError("Android release artifact path is invalid.");
@@ -20761,12 +20918,12 @@ var ensureAbsoluteBundletool = async (options) => {
20761
20918
  const digest = createHash3("sha256").update(bytes).digest("hex");
20762
20919
  if (digest !== ABSOLUTE_BUNDLETOOL_SHA256)
20763
20920
  throw new TypeError("Downloaded Bundletool failed checksum verification.");
20764
- await mkdir7(dirname7(inspected.path), { recursive: true });
20765
- const staging = await mkdtemp2(join9(dirname7(inspected.path), ".install-"));
20766
- const candidate = join9(staging, "bundletool.jar");
20921
+ await mkdir8(dirname8(inspected.path), { recursive: true });
20922
+ const staging = await mkdtemp2(join10(dirname8(inspected.path), ".install-"));
20923
+ const candidate = join10(staging, "bundletool.jar");
20767
20924
  try {
20768
- await writeFile9(candidate, bytes, { flag: "wx" });
20769
- await rename8(candidate, inspected.path).catch(async (error) => {
20925
+ await writeFile10(candidate, bytes, { flag: "wx" });
20926
+ await rename9(candidate, inspected.path).catch(async (error) => {
20770
20927
  if (await exists2(inspected.path))
20771
20928
  return;
20772
20929
  throw error;
@@ -20803,7 +20960,7 @@ var adb = (path, serial, ...args) => [
20803
20960
  serial,
20804
20961
  ...args
20805
20962
  ];
20806
- var waitForMarker = async (run, adbPath, serial, appId, timeoutMs) => {
20963
+ var waitForMarker = async (run, adbPath, serial, appId, engine, timeoutMs) => {
20807
20964
  const startedAt = performance.now();
20808
20965
  const inspect = async () => {
20809
20966
  if (performance.now() - startedAt >= timeoutMs)
@@ -20814,9 +20971,9 @@ var waitForMarker = async (run, adbPath, serial, appId, timeoutMs) => {
20814
20971
  ]);
20815
20972
  if (process2.exitCode !== 0 || !process2.stdout.trim())
20816
20973
  throw new Error("The installed Android release exited before becoming ready.");
20817
- if (logs.stdout.includes(EMBEDDED_READY_MARKER))
20974
+ if (logs.stdout.includes(EMBEDDED_READY_MARKERS[engine]))
20818
20975
  return;
20819
- const failedPhase = /Expo embedded web phase: (assets-(?:root|directory|destination|module|source|download|copy|read|write|finalize|unexpected)|devices)-failed/u.exec(logs.stdout)?.[1];
20976
+ const failedPhase = engine === "expo" ? /Expo embedded web phase: (assets-(?:root|directory|destination|module|source|download|copy|read|write|finalize|unexpected)|devices)-failed/u.exec(logs.stdout)?.[1] : undefined;
20820
20977
  if (failedPhase)
20821
20978
  throw new Error(`The installed release could not initialize its embedded ${failedPhase} runtime offline.`);
20822
20979
  await Bun.sleep(RELEASE_READY_POLL_MS);
@@ -20834,14 +20991,12 @@ var launch = async (run, adbPath, serial, appId, launchUrl) => {
20834
20991
  return Math.round(performance.now() - startedAt);
20835
20992
  };
20836
20993
  var runAbsoluteAndroidReleaseAcceptance = async (options) => {
20837
- if (options.release.metadata.engine !== "expo")
20838
- throw new TypeError("Installed AAB release acceptance currently requires the Expo engine.");
20839
20994
  if (!options.serial.startsWith("emulator-"))
20840
20995
  throw new TypeError("Installed release acceptance changes network state and therefore requires an Android emulator.");
20841
20996
  const run = options.run ?? defaultRun;
20842
20997
  const startedAt = performance.now();
20843
- await mkdir7(options.artifactDirectory, { recursive: true });
20844
- const apksPath = join9(options.artifactDirectory, "release.apks");
20998
+ await mkdir8(options.artifactDirectory, { recursive: true });
20999
+ const apksPath = join10(options.artifactDirectory, "release.apks");
20845
21000
  const windowsJava = (options.host ?? detectAbsoluteMobileHost()) === "wsl" && options.java.toLowerCase().endsWith(".exe");
20846
21001
  const toolPath = async (path) => {
20847
21002
  if (!windowsJava)
@@ -20896,12 +21051,12 @@ var runAbsoluteAndroidReleaseAcceptance = async (options) => {
20896
21051
  ]);
20897
21052
  await requireSuccess(run, adb(options.adb, options.serial, "shell", "am", "force-stop", options.release.metadata.appId), "Android release stop");
20898
21053
  launchMs = await launch(run, options.adb, options.serial, options.release.metadata.appId, options.launchUrl);
20899
- await waitForMarker(run, options.adb, options.serial, options.release.metadata.appId, RELEASE_READY_TIMEOUT_MS);
21054
+ await waitForMarker(run, options.adb, options.serial, options.release.metadata.appId, options.release.metadata.engine, RELEASE_READY_TIMEOUT_MS);
20900
21055
  await Bun.sleep(options.stabilityMs ?? RELEASE_STABILITY_MS);
20901
21056
  await requireSuccess(run, adb(options.adb, options.serial, "shell", "am", "force-stop", options.release.metadata.appId), "Android release relaunch stop");
20902
21057
  await requireSuccess(run, adb(options.adb, options.serial, "logcat", "-c"), "Android release relaunch log isolation");
20903
21058
  relaunchMs = await launch(run, options.adb, options.serial, options.release.metadata.appId, options.launchUrl);
20904
- await waitForMarker(run, options.adb, options.serial, options.release.metadata.appId, RELEASE_READY_TIMEOUT_MS);
21059
+ await waitForMarker(run, options.adb, options.serial, options.release.metadata.appId, options.release.metadata.engine, RELEASE_READY_TIMEOUT_MS);
20905
21060
  } finally {
20906
21061
  await Promise.all([
20907
21062
  requireSuccess(run, adb(options.adb, options.serial, "shell", "svc", "wifi", wifi.stdout.trim() === "1" ? "enable" : "disable"), "Android Wi-Fi restore"),
@@ -20969,7 +21124,7 @@ var testAbsoluteIosPhysicalDevice = async (options) => {
20969
21124
  };
20970
21125
 
20971
21126
  // src/mobile/iosConformance.ts
20972
- import { readFile as readFile11, stat as stat4 } from "fs/promises";
21127
+ import { readFile as readFile12, stat as stat4 } from "fs/promises";
20973
21128
  var HMR_LINE = new RegExp(String.raw`\[hmr:ios\]\s+([^\n]*?)\s+(applied in|falling back to reload after|failed after)\s+(\d+)ms(?:; server\s+(\d+)ms, client\s+(\d+)ms)?`, "u");
20974
21129
  var parseAbsoluteIosHmrLog = (line) => {
20975
21130
  const match = HMR_LINE.exec(line);
@@ -21007,7 +21162,7 @@ var waitForAbsoluteIosHmrLog = async (options) => {
21007
21162
  if (Date.now() > deadline)
21008
21163
  throw new Error(`No iOS native HMR acknowledgement was observed within ${timeoutMs}ms.`);
21009
21164
  options.signal?.throwIfAborted();
21010
- const contents = await readFile11(options.logPath).catch(() => Buffer.alloc(0));
21165
+ const contents = await readFile12(options.logPath).catch(() => Buffer.alloc(0));
21011
21166
  if (contents.byteLength < offset) {
21012
21167
  offset = 0;
21013
21168
  buffered = "";
@@ -21028,8 +21183,8 @@ var waitForAbsoluteIosHmrLog = async (options) => {
21028
21183
  };
21029
21184
 
21030
21185
  // src/mobile/nativeTestReport.ts
21031
- import { mkdir as mkdir8, readFile as readFile12, writeFile as writeFile10 } from "fs/promises";
21032
- import { join as join10 } from "path";
21186
+ import { mkdir as mkdir9, readFile as readFile13, writeFile as writeFile11 } from "fs/promises";
21187
+ import { join as join11 } from "path";
21033
21188
  var secretPattern = /(authorization|access[_ -]?token|refresh[_ -]?token|socket[_ -]?ticket|password|cookie)(\s*[=:]\s*)([^\s,;]+)/giu;
21034
21189
  var bearerPattern = /bearer\s+[^\s,;]+/giu;
21035
21190
  var coordinatePattern = /\b(latitude|longitude|lat|lng)(\s*[=:]\s*)-?\d+(?:\.\d+)?/giu;
@@ -21158,7 +21313,7 @@ var createAbsoluteNativeTestReport = (options) => ({
21158
21313
  run: options.run
21159
21314
  });
21160
21315
  var readPackageVersionForNativeReport = async (packageJsonPath) => {
21161
- const manifest = JSON.parse(await readFile12(packageJsonPath, "utf8"));
21316
+ const manifest = JSON.parse(await readFile13(packageJsonPath, "utf8"));
21162
21317
  if (typeof manifest !== "object" || manifest === null)
21163
21318
  return "unknown";
21164
21319
  const version = Reflect.get(manifest, "version");
@@ -21196,13 +21351,13 @@ ${table(report.manualChecks)}
21196
21351
  `;
21197
21352
  };
21198
21353
  var writeAbsoluteNativeTestReport = async (directory, report) => {
21199
- await mkdir8(directory, { recursive: true });
21200
- const jsonPath = join10(directory, "report.json");
21201
- const markdownPath = join10(directory, "report.md");
21354
+ await mkdir9(directory, { recursive: true });
21355
+ const jsonPath = join11(directory, "report.json");
21356
+ const markdownPath = join11(directory, "report.md");
21202
21357
  await Promise.all([
21203
- writeFile10(jsonPath, `${JSON.stringify(report, null, 2)}
21358
+ writeFile11(jsonPath, `${JSON.stringify(report, null, 2)}
21204
21359
  `),
21205
- writeFile10(markdownPath, renderAbsoluteNativeTestReport(report))
21360
+ writeFile11(markdownPath, renderAbsoluteNativeTestReport(report))
21206
21361
  ]);
21207
21362
  return { directory, jsonPath, markdownPath };
21208
21363
  };
@@ -21553,8 +21708,8 @@ var publishAbsoluteIosRelease = async (options) => {
21553
21708
  };
21554
21709
 
21555
21710
  // src/mobile/mobileInspect.ts
21556
- import { access as access8, readFile as readFile13 } from "fs/promises";
21557
- import { join as join11, relative as relative7, resolve as resolve8 } from "path";
21711
+ import { access as access8, readFile as readFile14 } from "fs/promises";
21712
+ import { join as join12, relative as relative7, resolve as resolve8 } from "path";
21558
21713
  var ABSOLUTE_MOBILE_INSPECTION_FORMAT = 1;
21559
21714
  var MOBILE_PACKAGE_NAMES = new Set([
21560
21715
  "@absolutejs/absolute",
@@ -21581,7 +21736,7 @@ var pathExists4 = async (path) => {
21581
21736
  }
21582
21737
  };
21583
21738
  var readObject2 = async (path) => {
21584
- const value = JSON.parse(await readFile13(path, "utf8"));
21739
+ const value = JSON.parse(await readFile14(path, "utf8"));
21585
21740
  if (!isObject2(value))
21586
21741
  throw new TypeError("JSON root must be an object.");
21587
21742
  return value;
@@ -21593,13 +21748,13 @@ var addPackageDeclarations = (declarations, value) => {
21593
21748
  declarations.set(name, declared);
21594
21749
  };
21595
21750
  var packageInspections = async (projectRoot, additionalNames) => {
21596
- const project = await readObject2(join11(projectRoot, "package.json"));
21751
+ const project = await readObject2(join12(projectRoot, "package.json"));
21597
21752
  const declarations = new Map;
21598
21753
  for (const field2 of ["dependencies", "devDependencies"])
21599
21754
  addPackageDeclarations(declarations, project[field2]);
21600
21755
  const names = [...new Set([...declarations.keys(), ...additionalNames])].filter((name) => MOBILE_PACKAGE_NAMES.has(name) || name.startsWith("@capacitor/") || additionalNames.includes(name)).sort();
21601
21756
  return Promise.all(names.map(async (name) => {
21602
- const installedManifest = await readObject2(join11(projectRoot, "node_modules", name, "package.json")).catch(() => {
21757
+ const installedManifest = await readObject2(join12(projectRoot, "node_modules", name, "package.json")).catch(() => {
21603
21758
  return;
21604
21759
  });
21605
21760
  const installed = installedManifest?.version;
@@ -21658,7 +21813,7 @@ var inspectAbsoluteMobileProject = async (config, projectRoot, options = {}) =>
21658
21813
  },
21659
21814
  format: ABSOLUTE_MOBILE_INSPECTION_FORMAT,
21660
21815
  nativeProjects: await Promise.all(config.platforms.map(async (platform) => {
21661
- const path = join11(config.nativeProjectDirectory, platform);
21816
+ const path = join12(config.nativeProjectDirectory, platform);
21662
21817
  return {
21663
21818
  initialized: await pathExists4(path),
21664
21819
  path: portablePath2(projectRoot, path),
@@ -21715,8 +21870,8 @@ var renderAbsoluteMobileProjectInspection = (report) => {
21715
21870
 
21716
21871
  // src/mobile/ciWorkflow.ts
21717
21872
  import { existsSync } from "fs";
21718
- import { access as access9, mkdir as mkdir9, readFile as readFile14, writeFile as writeFile11 } from "fs/promises";
21719
- import { dirname as dirname8, extname as extname2, relative as relative8, resolve as resolve9, sep as sep5 } from "path";
21873
+ import { access as access9, mkdir as mkdir10, readFile as readFile15, writeFile as writeFile12 } from "fs/promises";
21874
+ import { dirname as dirname9, extname as extname2, relative as relative8, resolve as resolve9, sep as sep5 } from "path";
21720
21875
  var ABSOLUTE_MOBILE_CI_WORKFLOW_FORMAT = 1;
21721
21876
  var SECRET_NAME_PATTERN = /^[A-Z][A-Z0-9_]*$/u;
21722
21877
  var CI_ENV_INDENTATION = 6;
@@ -22191,12 +22346,12 @@ ${bundleAuditSteps}${platforms.includes("android") ? androidJob({ customSecrets,
22191
22346
  var writeAbsoluteMobileGithubWorkflow = async (options) => {
22192
22347
  const path = workflowOutputPath(options.projectRoot, options.outputPath);
22193
22348
  const generated = createAbsoluteMobileGithubWorkflow(options);
22194
- const previous = await exists3(path) ? await readFile14(path, "utf8") : undefined;
22349
+ const previous = await exists3(path) ? await readFile15(path, "utf8") : undefined;
22195
22350
  if (previous !== undefined && previous !== generated.workflow && !options.force)
22196
22351
  throw new TypeError(`${relative8(options.projectRoot, path)} already exists and differs. Rerun with --force to replace the generated workflow.`);
22197
22352
  if (previous !== generated.workflow) {
22198
- await mkdir9(dirname8(path), { recursive: true });
22199
- await writeFile11(path, generated.workflow);
22353
+ await mkdir10(dirname9(path), { recursive: true });
22354
+ await writeFile12(path, generated.workflow);
22200
22355
  }
22201
22356
  return {
22202
22357
  changed: previous !== generated.workflow,
@@ -22212,23 +22367,23 @@ var writeAbsoluteMobileGithubWorkflow = async (options) => {
22212
22367
  import { createHash as createHash4, sign, verify } from "crypto";
22213
22368
  import {
22214
22369
  cp,
22215
- mkdir as mkdir10,
22370
+ mkdir as mkdir11,
22216
22371
  mkdtemp as mkdtemp3,
22217
- readdir as readdir4,
22218
- readFile as readFile15,
22219
- rename as rename9,
22372
+ readdir as readdir5,
22373
+ readFile as readFile16,
22374
+ rename as rename10,
22220
22375
  rm as rm6,
22221
22376
  stat as stat5,
22222
- writeFile as writeFile12
22377
+ writeFile as writeFile13
22223
22378
  } from "fs/promises";
22224
- import { dirname as dirname9, join as join12, relative as relative9, resolve as resolve10 } from "path";
22379
+ import { dirname as dirname10, join as join13, relative as relative9, resolve as resolve10 } from "path";
22225
22380
  var UPDATE_MANIFEST_FILE = "update.json";
22226
22381
  var UPDATE_FILES_DIRECTORY = "files";
22227
22382
  var sha2562 = (value) => createHash4("sha256").update(value).digest("hex");
22228
22383
  var listFiles = async (root, directory = root) => {
22229
- const entries = await readdir4(directory, { withFileTypes: true });
22384
+ const entries = await readdir5(directory, { withFileTypes: true });
22230
22385
  const paths = await Promise.all(entries.map(async (entry) => {
22231
- const path = join12(directory, entry.name);
22386
+ const path = join13(directory, entry.name);
22232
22387
  if (entry.isDirectory())
22233
22388
  return listFiles(root, path);
22234
22389
  if (!entry.isFile())
@@ -22238,10 +22393,10 @@ var listFiles = async (root, directory = root) => {
22238
22393
  return paths.flat().sort((left, right) => left.localeCompare(right));
22239
22394
  };
22240
22395
  var inspectFiles = async (root, paths) => Promise.all(paths.map(async (path) => {
22241
- const source = join12(root, path);
22396
+ const source = join13(root, path);
22242
22397
  const [metadata, contents] = await Promise.all([
22243
22398
  stat5(source),
22244
- readFile15(source)
22399
+ readFile16(source)
22245
22400
  ]);
22246
22401
  return { bytes: metadata.size, path, sha256: sha2562(contents) };
22247
22402
  }));
@@ -22276,17 +22431,17 @@ var buildAbsoluteMobileUpdate = async (options) => {
22276
22431
  value: signature.toString("base64")
22277
22432
  }
22278
22433
  });
22279
- await mkdir10(outputRoot, { recursive: true });
22280
- const outputDirectory = join12(outputRoot, manifest.releaseId);
22281
- const staging = await mkdtemp3(join12(outputRoot, ".stage-"));
22434
+ await mkdir11(outputRoot, { recursive: true });
22435
+ const outputDirectory = join13(outputRoot, manifest.releaseId);
22436
+ const staging = await mkdtemp3(join13(outputRoot, ".stage-"));
22282
22437
  try {
22283
- await cp(bundleDirectory, join12(staging, UPDATE_FILES_DIRECTORY), {
22438
+ await cp(bundleDirectory, join13(staging, UPDATE_FILES_DIRECTORY), {
22284
22439
  force: true,
22285
22440
  recursive: true
22286
22441
  });
22287
- await writeFile12(join12(staging, UPDATE_MANIFEST_FILE), `${JSON.stringify(manifest, null, "\t")}
22442
+ await writeFile13(join13(staging, UPDATE_MANIFEST_FILE), `${JSON.stringify(manifest, null, "\t")}
22288
22443
  `);
22289
- await rename9(staging, outputDirectory);
22444
+ await rename10(staging, outputDirectory);
22290
22445
  } catch (error) {
22291
22446
  await rm6(staging, { force: true, recursive: true });
22292
22447
  if (typeof error === "object" && error !== null && Reflect.get(error, "code") === "EEXIST")
@@ -22295,11 +22450,11 @@ var buildAbsoluteMobileUpdate = async (options) => {
22295
22450
  }
22296
22451
  return {
22297
22452
  manifest,
22298
- manifestPath: join12(outputDirectory, UPDATE_MANIFEST_FILE),
22453
+ manifestPath: join13(outputDirectory, UPDATE_MANIFEST_FILE),
22299
22454
  outputDirectory
22300
22455
  };
22301
22456
  };
22302
- var readAbsoluteMobileUpdate = async (directory) => parseAbsoluteMobileUpdateManifest(JSON.parse(await readFile15(join12(resolve10(directory), UPDATE_MANIFEST_FILE), "utf8")));
22457
+ var readAbsoluteMobileUpdate = async (directory) => parseAbsoluteMobileUpdateManifest(JSON.parse(await readFile16(join13(resolve10(directory), UPDATE_MANIFEST_FILE), "utf8")));
22303
22458
  var verifyAbsoluteMobileUpdateSignature = (manifestValue, publicKey) => {
22304
22459
  const manifest = parseAbsoluteMobileUpdateManifest(manifestValue);
22305
22460
  const valid = verify("sha256", absoluteMobileUpdateSigningPayload(unsignedAbsoluteMobileUpdate(manifest)), { dsaEncoding: "ieee-p1363", key: publicKey }, Buffer.from(manifest.signature.value, "base64"));
@@ -22309,8 +22464,8 @@ var verifyAbsoluteMobileUpdateSignature = (manifestValue, publicKey) => {
22309
22464
  };
22310
22465
 
22311
22466
  // src/mobile/expoUpdate.ts
22312
- import { access as access10, mkdir as mkdir11, readFile as readFile16, writeFile as writeFile13 } from "fs/promises";
22313
- import { dirname as dirname10, extname as extname3, join as join13 } from "path";
22467
+ import { access as access10, mkdir as mkdir12, readFile as readFile17, writeFile as writeFile14 } from "fs/promises";
22468
+ import { dirname as dirname11, extname as extname3, join as join14 } from "path";
22314
22469
  var ABSOLUTE_EXPO_UPDATE_DESCRIPTOR = "_absolute/expo-update.json";
22315
22470
  var ABSOLUTE_EXPO_UPDATE_FORMAT = 1;
22316
22471
  var object2 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
@@ -22376,7 +22531,7 @@ var parseAbsoluteExpoUpdateDescriptor = (value) => {
22376
22531
  };
22377
22532
  };
22378
22533
  var finalizeAbsoluteExpoUpdateExport = async (options) => {
22379
- const metadata = JSON.parse(await readFile16(join13(options.exportDirectory, "metadata.json"), "utf8"));
22534
+ const metadata = JSON.parse(await readFile17(join14(options.exportDirectory, "metadata.json"), "utf8"));
22380
22535
  if (!object2(metadata) || !object2(metadata.fileMetadata))
22381
22536
  throw new TypeError("Expo export metadata.json is invalid.");
22382
22537
  const descriptor = parseAbsoluteExpoUpdateDescriptor({
@@ -22387,20 +22542,20 @@ var finalizeAbsoluteExpoUpdateExport = async (options) => {
22387
22542
  runtimeVersion: options.runtimeVersion
22388
22543
  });
22389
22544
  const referenced = Object.values(descriptor.platforms).flatMap((entry) => entry ? [entry.launchAsset, ...entry.assets] : []);
22390
- await Promise.all(referenced.map(({ path }) => access10(join13(options.exportDirectory, path)).catch(() => {
22545
+ await Promise.all(referenced.map(({ path }) => access10(join14(options.exportDirectory, path)).catch(() => {
22391
22546
  throw new TypeError(`Expo export metadata references missing asset ${path}.`);
22392
22547
  })));
22393
- const destination = join13(options.exportDirectory, ABSOLUTE_EXPO_UPDATE_DESCRIPTOR);
22394
- await mkdir11(dirname10(destination), { recursive: true });
22395
- await writeFile13(destination, `${JSON.stringify(descriptor, null, "\t")}
22548
+ const destination = join14(options.exportDirectory, ABSOLUTE_EXPO_UPDATE_DESCRIPTOR);
22549
+ await mkdir12(dirname11(destination), { recursive: true });
22550
+ await writeFile14(destination, `${JSON.stringify(descriptor, null, "\t")}
22396
22551
  `);
22397
22552
  return { descriptor, path: destination };
22398
22553
  };
22399
22554
 
22400
22555
  // src/mobile/expoCodeSigning.ts
22401
22556
  var import_code_signing_certificates = __toESM(require_main(), 1);
22402
- import { access as access11, mkdir as mkdir12, writeFile as writeFile14 } from "fs/promises";
22403
- import { dirname as dirname11, isAbsolute as isAbsolute5, relative as relative10, resolve as resolve11, sep as sep6 } from "path";
22557
+ import { access as access11, mkdir as mkdir13, writeFile as writeFile15 } from "fs/promises";
22558
+ import { dirname as dirname12, isAbsolute as isAbsolute5, relative as relative10, resolve as resolve11, sep as sep6 } from "path";
22404
22559
  var exists4 = async (path) => access11(path).then(() => true).catch(() => false);
22405
22560
  var inside2 = (root, path) => {
22406
22561
  const location = relative10(root, path);
@@ -22410,7 +22565,7 @@ var generateAbsoluteExpoCodeSigning = async (options) => {
22410
22565
  const root = resolve11(options.projectRoot);
22411
22566
  const certificatePath = resolve11(root, options.certificatePath);
22412
22567
  const privateKeyPath = resolve11(root, options.privateKeyPath);
22413
- const publicKeyPath = resolve11(root, options.publicKeyPath ?? resolve11(dirname11(privateKeyPath), "public-key.pem"));
22568
+ const publicKeyPath = resolve11(root, options.publicKeyPath ?? resolve11(dirname12(privateKeyPath), "public-key.pem"));
22414
22569
  if (!inside2(root, certificatePath))
22415
22570
  throw new TypeError("Expo code-signing certificate must be written inside the project so store builds can embed it.");
22416
22571
  if (inside2(root, privateKeyPath) || inside2(root, publicKeyPath))
@@ -22440,11 +22595,11 @@ var generateAbsoluteExpoCodeSigning = async (options) => {
22440
22595
  import_code_signing_certificates.validateSelfSignedCertificate(certificate, keyPair);
22441
22596
  const { privateKeyPEM, publicKeyPEM } = import_code_signing_certificates.convertKeyPairToPEM(keyPair);
22442
22597
  const certificatePem = import_code_signing_certificates.convertCertificateToCertificatePEM(certificate);
22443
- await Promise.all([certificatePath, privateKeyPath, publicKeyPath].map((path) => mkdir12(dirname11(path), { recursive: true })));
22598
+ await Promise.all([certificatePath, privateKeyPath, publicKeyPath].map((path) => mkdir13(dirname12(path), { recursive: true })));
22444
22599
  await Promise.all([
22445
- writeFile14(certificatePath, certificatePem, { flag: "wx", mode: 420 }),
22446
- writeFile14(privateKeyPath, privateKeyPEM, { flag: "wx", mode: 384 }),
22447
- writeFile14(publicKeyPath, publicKeyPEM, { flag: "wx", mode: 420 })
22600
+ writeFile15(certificatePath, certificatePem, { flag: "wx", mode: 420 }),
22601
+ writeFile15(privateKeyPath, privateKeyPEM, { flag: "wx", mode: 384 }),
22602
+ writeFile15(publicKeyPath, publicKeyPEM, { flag: "wx", mode: 420 })
22448
22603
  ]);
22449
22604
  return {
22450
22605
  certificatePath,
@@ -22672,7 +22827,7 @@ var CAPACITOR_SYNC_PACKAGE_SPECS = [
22672
22827
  ];
22673
22828
  var packageNameFromSpec = (spec) => spec.slice(0, spec.lastIndexOf("@"));
22674
22829
  var directProjectPackages = async (projectRoot) => {
22675
- const manifest = JSON.parse(await readFile17(join14(projectRoot, "package.json"), "utf8"));
22830
+ const manifest = JSON.parse(await readFile18(join15(projectRoot, "package.json"), "utf8"));
22676
22831
  if (!isRecord7(manifest))
22677
22832
  throw new TypeError("Application package.json must contain an object.");
22678
22833
  const names = new Set;
@@ -22686,7 +22841,7 @@ var directProjectPackages = async (projectRoot) => {
22686
22841
  };
22687
22842
  var resolvedPackageVersion = async (projectRoot, packageName) => {
22688
22843
  try {
22689
- const manifest = JSON.parse(await readFile17(join14(projectRoot, "node_modules", packageName, "package.json"), "utf8"));
22844
+ const manifest = JSON.parse(await readFile18(join15(projectRoot, "node_modules", packageName, "package.json"), "utf8"));
22690
22845
  return isRecord7(manifest) && typeof manifest.version === "string" ? manifest.version : undefined;
22691
22846
  } catch {
22692
22847
  return;
@@ -22736,18 +22891,8 @@ var requireMobileConfig = (value) => {
22736
22891
  }
22737
22892
  return value;
22738
22893
  };
22739
- var capacitorExecutable = async (projectRoot) => {
22740
- const executable = join14(projectRoot, "node_modules", ".bin", "cap");
22741
- try {
22742
- await access13(executable);
22743
- return executable;
22744
- } catch {
22745
- throw new TypeError(`Capacitor is not installed in this app. Run: bun add ${CAPACITOR_PACKAGES.join(" ")}`);
22746
- }
22747
- };
22748
22894
  var runCapacitor = async (projectRoot, args) => {
22749
- const executable = await capacitorExecutable(projectRoot);
22750
- const process2 = Bun.spawn([executable, ...args], {
22895
+ const process2 = Bun.spawn(["bun", "x", "--no-install", "cap", ...args], {
22751
22896
  cwd: projectRoot,
22752
22897
  stderr: "inherit",
22753
22898
  stdin: "inherit",
@@ -22755,12 +22900,12 @@ var runCapacitor = async (projectRoot, args) => {
22755
22900
  });
22756
22901
  const exitCode = await process2.exited;
22757
22902
  if (exitCode !== 0) {
22758
- throw new TypeError(`Capacitor exited with status ${exitCode}.`);
22903
+ throw new TypeError(`Capacitor exited with status ${exitCode}. Ensure this app directly depends on: ${CAPACITOR_PACKAGES.join(" ")}`);
22759
22904
  }
22760
22905
  };
22761
22906
  var runCapacitorForPlatforms = (projectRoot, command, platforms) => platforms.reduce((pending, platform2) => pending.then(() => runCapacitor(projectRoot, [command, platform2])), Promise.resolve());
22762
22907
  var expoExecutable = async (project) => {
22763
- const executable = join14(project, "node_modules", ".bin", "expo");
22908
+ const executable = join15(project, "node_modules", ".bin", "expo");
22764
22909
  try {
22765
22910
  await access13(executable);
22766
22911
  return executable;
@@ -22794,14 +22939,14 @@ var runExpo = async (project, args, options = {}) => {
22794
22939
  };
22795
22940
  var ensureExpoPackages = async (project, args) => {
22796
22941
  try {
22797
- const manifest = JSON.parse(await readFile17(join14(project, "package.json"), "utf8"));
22942
+ const manifest = JSON.parse(await readFile18(join15(project, "package.json"), "utf8"));
22798
22943
  const dependencies = typeof manifest === "object" && manifest !== null ? Reflect.get(manifest, "dependencies") : undefined;
22799
22944
  if (typeof dependencies !== "object" || dependencies === null || Array.isArray(dependencies))
22800
22945
  throw new TypeError("Generated Expo dependencies are invalid.");
22801
22946
  await Promise.all(Object.entries(dependencies).map(async ([name, expected]) => {
22802
22947
  if (typeof expected !== "string")
22803
22948
  throw new TypeError("Generated Expo dependency version is invalid.");
22804
- const installed = JSON.parse(await readFile17(join14(project, "node_modules", name, "package.json"), "utf8"));
22949
+ const installed = JSON.parse(await readFile18(join15(project, "node_modules", name, "package.json"), "utf8"));
22805
22950
  const actual = typeof installed === "object" && installed !== null ? Reflect.get(installed, "version") : undefined;
22806
22951
  if (typeof actual !== "string")
22807
22952
  throw new TypeError("Installed Expo dependency version is invalid.");
@@ -22959,6 +23104,7 @@ var initialize = async (args) => {
22959
23104
  await applyAbsoluteNativeBackgroundSync(projectRoot, mobile);
22960
23105
  await applyAbsoluteNativeUpdates(mobile);
22961
23106
  await applyAbsoluteNativeObservability(mobile);
23107
+ await applyAbsoluteNativeReleaseReadiness(mobile);
22962
23108
  };
22963
23109
  var sync = async (args) => {
22964
23110
  const { mobile, projectRoot } = await loadMobile(valueAfter(args, "--config"));
@@ -22994,6 +23140,7 @@ var sync = async (args) => {
22994
23140
  await applyAbsoluteNativeBackgroundSync(projectRoot, mobile, platforms);
22995
23141
  await applyAbsoluteNativeUpdates(mobile, platforms);
22996
23142
  await applyAbsoluteNativeObservability(mobile, platforms);
23143
+ await applyAbsoluteNativeReleaseReadiness(mobile, platforms);
22997
23144
  };
22998
23145
  var associations = async (args) => {
22999
23146
  const { mobile, projectRoot } = await loadMobile(valueAfter(args, "--config"));
@@ -23160,9 +23307,9 @@ var prepareExpoMobileUpdateExport = async (options) => {
23160
23307
  temporaryDirectory: undefined
23161
23308
  };
23162
23309
  await ensureExpoPackages(mobile.nativeProjectDirectory, options.args);
23163
- const temporaryParent = join14(options.projectRoot, ".absolutejs", "mobile", "expo-update-exports");
23164
- await mkdir13(temporaryParent, { recursive: true });
23165
- const temporaryDirectory = await mkdtemp4(join14(temporaryParent, ".stage-"));
23310
+ const temporaryParent = join15(options.projectRoot, ".absolutejs", "mobile", "expo-update-exports");
23311
+ await mkdir14(temporaryParent, { recursive: true });
23312
+ const temporaryDirectory = await mkdtemp4(join15(temporaryParent, ".stage-"));
23166
23313
  try {
23167
23314
  await runExpo(mobile.nativeProjectDirectory, [
23168
23315
  "export",
@@ -23174,7 +23321,7 @@ var prepareExpoMobileUpdateExport = async (options) => {
23174
23321
  temporaryDirectory,
23175
23322
  "--clear"
23176
23323
  ], { production: true });
23177
- const generatedApp = JSON.parse(await readFile17(join14(mobile.nativeProjectDirectory, "app.json"), "utf8"));
23324
+ const generatedApp = JSON.parse(await readFile18(join15(mobile.nativeProjectDirectory, "app.json"), "utf8"));
23178
23325
  const expoConfig = isRecord7(generatedApp) ? generatedApp.expo : undefined;
23179
23326
  if (!isRecord7(expoConfig))
23180
23327
  throw new TypeError("Generated Expo app configuration is invalid.");
@@ -23217,11 +23364,11 @@ var buildMobileUpdate = async (args) => {
23217
23364
  let expoExportDirectory;
23218
23365
  try {
23219
23366
  await start(mobileBuildServerEntry(args), valueAfter(args, "--web-outdir"), configPath, { prepareOnly: true });
23220
- const embedded = JSON.parse(await readFile17(join14(mobile.bundleDirectory, "absolute-mobile-manifest.json"), "utf8"));
23367
+ const embedded = JSON.parse(await readFile18(join15(mobile.bundleDirectory, "absolute-mobile-manifest.json"), "utf8"));
23221
23368
  const runtimeFingerprint = isRecord7(embedded) ? embedded.nativeRuntime : undefined;
23222
23369
  if (typeof runtimeFingerprint !== "string" || !/^[a-f0-9]{64}$/u.test(runtimeFingerprint))
23223
23370
  throw new TypeError("Prepared mobile bundle is missing its native runtime fingerprint.");
23224
- const privateKey = await readFile17(resolve13(projectRoot, signingKeyPath));
23371
+ const privateKey = await readFile18(resolve13(projectRoot, signingKeyPath));
23225
23372
  const configuredPublicKey = Buffer.from(mobile.updates.publicKeys[keyId], "base64");
23226
23373
  const derivedPublicKey = createPublicKey2(privateKey).export({
23227
23374
  format: "der",
@@ -23242,7 +23389,7 @@ var buildMobileUpdate = async (args) => {
23242
23389
  channel: mobile.updates.channel,
23243
23390
  classification,
23244
23391
  keyId,
23245
- outputDirectory: valueAfter(args, "--outdir") ?? join14(projectRoot, ".absolutejs", "mobile", "updates"),
23392
+ outputDirectory: valueAfter(args, "--outdir") ?? join15(projectRoot, ".absolutejs", "mobile", "updates"),
23246
23393
  privateKey,
23247
23394
  runtimeFingerprint
23248
23395
  });
@@ -23770,6 +23917,7 @@ var prepareCapacitorAndroidReleaseProject = async (mobile, projectRoot) => {
23770
23917
  await applyAbsoluteNativeBackgroundSync(projectRoot, mobile, ["android"]);
23771
23918
  await applyAbsoluteNativeUpdates(mobile, ["android"]);
23772
23919
  await applyAbsoluteNativeObservability(mobile, ["android"]);
23920
+ await applyAbsoluteNativeReleaseReadiness(mobile, ["android"]);
23773
23921
  };
23774
23922
  var prepareAndroidReleaseProject = (mobile, projectRoot, args) => mobile.engine === "expo" ? prepareExpoAndroidReleaseProject(mobile, projectRoot, args) : prepareCapacitorAndroidReleaseProject(mobile, projectRoot);
23775
23923
  var buildAndroid = async (args, prepareVersionCode) => {
@@ -23821,7 +23969,7 @@ var buildAndroid = async (args, prepareVersionCode) => {
23821
23969
  const durationMs = Math.round(performance.now() - startedAt);
23822
23970
  console.log(`Built ${release.metadata.signed ? "signed" : "unsigned"} Android App Bundle in ${getDurationString(durationMs)}.`);
23823
23971
  console.log(`Artifact: ${release.artifactPath}`);
23824
- console.log(`Metadata: ${join14(release.releaseRoot, "release.json")}`);
23972
+ console.log(`Metadata: ${join15(release.releaseRoot, "release.json")}`);
23825
23973
  return release;
23826
23974
  } finally {
23827
23975
  sendTelemetryEvent("mobile:android-release-build", {
@@ -23977,7 +24125,7 @@ var buildIos = async (args, prepareBuildNumber) => {
23977
24125
  const durationMs = Math.round(performance.now() - startedAt);
23978
24126
  console.log(`Built ${release.metadata.signed ? "signed" : "unsigned"} iOS IPA ${release.metadata.marketingVersion}${release.metadata.buildNumber ? ` (${release.metadata.buildNumber})` : ""} in ${getDurationString(durationMs)}.`);
23979
24127
  console.log(`Artifact: ${release.artifactPath}`);
23980
- console.log(`Metadata: ${join14(release.releaseRoot, "release.json")}`);
24128
+ console.log(`Metadata: ${join15(release.releaseRoot, "release.json")}`);
23981
24129
  return release;
23982
24130
  } finally {
23983
24131
  stopListeningForCancellation();
@@ -24089,7 +24237,7 @@ var appendSyncSchemaDoctorCheck = (checks, projectRoot) => {
24089
24237
  checks.push({
24090
24238
  id: "sync.storage-schema",
24091
24239
  label: `Offline schema ${schema.components.map((component) => `${component.id}@${component.version}`).join(", ")}`,
24092
- path: join14(projectRoot, "package.json"),
24240
+ path: join15(projectRoot, "package.json"),
24093
24241
  platform: "host",
24094
24242
  status: "pass"
24095
24243
  });
@@ -24097,7 +24245,7 @@ var appendSyncSchemaDoctorCheck = (checks, projectRoot) => {
24097
24245
  checks.push({
24098
24246
  id: "sync.storage-schema",
24099
24247
  label: "Offline schema metadata is invalid",
24100
- path: join14(projectRoot, "package.json"),
24248
+ path: join15(projectRoot, "package.json"),
24101
24249
  platform: "host",
24102
24250
  remediation: error instanceof Error ? error.message : String(error),
24103
24251
  status: "fail"
@@ -24308,12 +24456,12 @@ var waitForRequestedAndroidHmr = async (args, session, checks, timeoutMs) => {
24308
24456
  });
24309
24457
  };
24310
24458
  var writeAndroidFailureArtifacts = async (options) => {
24311
- await mkdir13(options.artifactRoot, { recursive: true });
24312
- const screenshot = options.session ? await options.session.screenshot(join14(options.artifactRoot, "android-failure.png")).catch(() => {
24459
+ await mkdir14(options.artifactRoot, { recursive: true });
24460
+ const screenshot = options.session ? await options.session.screenshot(join15(options.artifactRoot, "android-failure.png")).catch(() => {
24313
24461
  return;
24314
24462
  }) : undefined;
24315
- const diagnosticPath = join14(options.artifactRoot, "android-failure.json");
24316
- await writeFile15(diagnosticPath, `${JSON.stringify({
24463
+ const diagnosticPath = join15(options.artifactRoot, "android-failure.json");
24464
+ await writeFile16(diagnosticPath, `${JSON.stringify({
24317
24465
  diagnostics: options.session?.diagnostics ?? [],
24318
24466
  error: options.error instanceof Error ? options.error.message : String(options.error),
24319
24467
  platform: "android",
@@ -24334,7 +24482,7 @@ var captureAndroidReleaseScreenshot = async (adb2, serial, destination) => {
24334
24482
  ]);
24335
24483
  if (exitCode !== 0)
24336
24484
  throw new Error(`Android release screenshot failed: ${stderr.trim() || `status ${exitCode}`}`);
24337
- await writeFile15(destination, bytes);
24485
+ await writeFile16(destination, bytes);
24338
24486
  return destination;
24339
24487
  };
24340
24488
  var printAndroidReleaseAcceptance = (result, json) => {
@@ -24351,8 +24499,6 @@ var testAndroidRelease = async (args, mobile, projectRoot) => {
24351
24499
  throw new TypeError("mobile test android --release requires a release directory or release.json path.");
24352
24500
  if (!mobile.platforms.includes("android"))
24353
24501
  throw new TypeError("mobile test android requires android in mobile.platforms.");
24354
- if (mobile.engine !== "expo")
24355
- throw new TypeError("mobile test android --release currently requires mobile.engine: expo; use the ordinary test command for Capacitor.");
24356
24502
  const release = await readAbsoluteAndroidRelease(projectRoot, requested);
24357
24503
  if (release.metadata.appId !== mobile.appId)
24358
24504
  throw new TypeError(`Android release app ID ${release.metadata.appId} does not match mobile.appId ${mobile.appId}.`);
@@ -24390,7 +24536,7 @@ var testAndroidRelease = async (args, mobile, projectRoot) => {
24390
24536
  release,
24391
24537
  serial
24392
24538
  });
24393
- const screenshot = reportRoot ? await captureAndroidReleaseScreenshot(adb2, serial, join14(reportRoot, "android-release.png")) : undefined;
24539
+ const screenshot = reportRoot ? await captureAndroidReleaseScreenshot(adb2, serial, join15(reportRoot, "android-release.png")) : undefined;
24394
24540
  sendTelemetryEvent("mobile:android-release-conformance", {
24395
24541
  durationMs: result.durationMs,
24396
24542
  engine: result.engine,
@@ -24437,9 +24583,9 @@ var testAndroidRelease = async (args, mobile, projectRoot) => {
24437
24583
  platform: "android",
24438
24584
  success: false
24439
24585
  });
24440
- await mkdir13(artifactRoot, { recursive: true });
24441
- const diagnosticPath = join14(artifactRoot, "android-release-failure.json");
24442
- await writeFile15(diagnosticPath, `${JSON.stringify({
24586
+ await mkdir14(artifactRoot, { recursive: true });
24587
+ const diagnosticPath = join15(artifactRoot, "android-release-failure.json");
24588
+ await writeFile16(diagnosticPath, `${JSON.stringify({
24443
24589
  error: sanitizeNativeReportText(error instanceof Error ? error.message : String(error)),
24444
24590
  platform: "android",
24445
24591
  provider: mobile.engine,
@@ -24533,7 +24679,7 @@ var testAndroid = async (args) => {
24533
24679
  console.log(JSON.stringify(report, null, 2));
24534
24680
  else
24535
24681
  printAndroidTestReport(report);
24536
- const screenshot = reportRoot ? await session.screenshot(join14(artifactRoot, "android-emulator.png")) : undefined;
24682
+ const screenshot = reportRoot ? await session.screenshot(join15(artifactRoot, "android-emulator.png")) : undefined;
24537
24683
  await writeRequestedAndroidReport({
24538
24684
  adb: adb2,
24539
24685
  args,
@@ -24732,8 +24878,8 @@ var requireCapturedCommand = (command, label) => {
24732
24878
  return result;
24733
24879
  };
24734
24880
  var writeIosFailureArtifacts = async (options) => {
24735
- await mkdir13(options.artifactRoot, { recursive: true });
24736
- const screenshot = join14(options.artifactRoot, "ios-failure.png");
24881
+ await mkdir14(options.artifactRoot, { recursive: true });
24882
+ const screenshot = join15(options.artifactRoot, "ios-failure.png");
24737
24883
  const screenshotResult = captureCommand3([
24738
24884
  options.xcrun,
24739
24885
  "simctl",
@@ -24742,8 +24888,8 @@ var writeIosFailureArtifacts = async (options) => {
24742
24888
  "screenshot",
24743
24889
  screenshot
24744
24890
  ]);
24745
- const diagnosticPath = join14(options.artifactRoot, "ios-failure.json");
24746
- await writeFile15(diagnosticPath, `${JSON.stringify({
24891
+ const diagnosticPath = join15(options.artifactRoot, "ios-failure.json");
24892
+ await writeFile16(diagnosticPath, `${JSON.stringify({
24747
24893
  appId: options.appId,
24748
24894
  error: options.error instanceof Error ? options.error.message : String(options.error),
24749
24895
  platform: "ios",
@@ -24996,8 +25142,8 @@ var testIos = async (args) => {
24996
25142
  mobile.appId
24997
25143
  ], "iOS app launch");
24998
25144
  await waitForIosHmrClient({ https, port, timeoutMs });
24999
- await mkdir13(artifactRoot, { recursive: true });
25000
- const screenshot = join14(artifactRoot, "ios-simulator.png");
25145
+ await mkdir14(artifactRoot, { recursive: true });
25146
+ const screenshot = join15(artifactRoot, "ios-simulator.png");
25001
25147
  requireCapturedCommand([xcrun, "simctl", "io", simulator.udid, "screenshot", screenshot], "iOS simulator screenshot");
25002
25148
  const hmrApply = await waitForRequestedIosHmr(args, instance, timeoutMs);
25003
25149
  const report = {