@absolutejs/absolute 0.20.0-beta.101 → 0.20.0-beta.102

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.
@@ -611,11 +611,11 @@ __export(exports_config, {
611
611
  normalizeAbsoluteMobileConfig: () => normalizeAbsoluteMobileConfig
612
612
  });
613
613
  import { readFileSync as readFileSync2 } from "fs";
614
- import { resolve as resolve6 } from "path";
615
- import { createHash as createHash8, createPublicKey, X509Certificate as X509Certificate2 } from "crypto";
614
+ import { resolve as resolve7 } from "path";
615
+ import { createHash as createHash9, createPublicKey, X509Certificate as X509Certificate2 } from "crypto";
616
616
  var APP_ID_PATTERN, SCHEME_PATTERN, APPLE_APP_ID_PREFIX_PATTERN, CERTIFICATE_FINGERPRINT_PATTERN, UPDATE_NAME_PATTERN, UPDATE_PUBLIC_KEY_PATTERN, ENVIRONMENT_NAME_PATTERN, DEFAULT_UPDATE_BOOT_TIMEOUT_MS = 20000, DEFAULT_UPDATE_HEALTH_FAILURE_RATE = 0.2, DEFAULT_UPDATE_HEALTH_MINIMUM_REPORTS = 20, DEFAULT_UPDATE_ROLLOUT_FAILURE_RATE = 0.05, DEFAULT_UPDATE_ROLLOUT_OBSERVATION_MINUTES = 60, MINUTE_MS, DEFAULT_UPDATE_ROLLOUT_STAGES, MINIMUM_UPDATE_BOOT_TIMEOUT_MS = 5000, MAXIMUM_UPDATE_BOOT_TIMEOUT_MS = 120000, HOSTNAME_PATTERN, EXPO_RESERVED_ROUTE_PREFIXES, resolveProjectPath = (projectRoot, value, field2) => {
617
- const root = resolve6(projectRoot);
618
- const path = resolve6(root, value);
617
+ const root = resolve7(projectRoot);
618
+ const path = resolve7(root, value);
619
619
  if (path !== root && !path.startsWith(`${root}/`)) {
620
620
  throw new TypeError(`${field2} must remain inside the project root.`);
621
621
  }
@@ -787,7 +787,7 @@ var APP_ID_PATTERN, SCHEME_PATTERN, APPLE_APP_ID_PREFIX_PATTERN, CERTIFICATE_FIN
787
787
  expoCodeSigning = {
788
788
  algorithm: "rsa-v1_5-sha256",
789
789
  certificatePem,
790
- certificateSha256: createHash8("sha256").update(certificate.raw).digest("hex"),
790
+ certificateSha256: createHash9("sha256").update(certificate.raw).digest("hex"),
791
791
  keyId
792
792
  };
793
793
  }
@@ -1017,14 +1017,14 @@ __export(exports_associationFiles, {
1017
1017
  verifyAbsoluteMobileAssociationFiles: () => verifyAbsoluteMobileAssociationFiles
1018
1018
  });
1019
1019
  import {
1020
- access as access8,
1021
- mkdir as mkdir7,
1022
- readFile as readFile10,
1023
- rename as rename8,
1024
- rm as rm7,
1025
- writeFile as writeFile8
1020
+ access as access9,
1021
+ mkdir as mkdir8,
1022
+ readFile as readFile11,
1023
+ rename as rename9,
1024
+ rm as rm8,
1025
+ writeFile as writeFile9
1026
1026
  } from "fs/promises";
1027
- import { resolve as resolve7 } from "path";
1027
+ import { resolve as resolve8 } from "path";
1028
1028
  import { Elysia } from "elysia";
1029
1029
  var JSON_HEADERS, OWNERSHIP_FILE = ".absolutejs-mobile-associations.json", HTTP_OK = 200, VERIFY_TIMEOUT_MS = 1e4, ANDROID_ASSOCIATION_PATH = "/.well-known/assetlinks.json", APPLE_ASSOCIATION_PATH = "/.well-known/apple-app-site-association", missingIdentity = (field2, platform2) => new TypeError(`${field2} is required to publish ${platform2} deep-link association files.`), createAppleDocument = (config, requireAll) => {
1030
1030
  if (!config.platforms.includes("ios"))
@@ -1091,7 +1091,7 @@ var JSON_HEADERS, OWNERSHIP_FILE = ".absolutejs-mobile-associations.json", HTTP_
1091
1091
  }, writeAtomic = async (path, source) => {
1092
1092
  let current;
1093
1093
  try {
1094
- current = await readFile10(path, "utf8");
1094
+ current = await readFile11(path, "utf8");
1095
1095
  } catch (error) {
1096
1096
  if (!(error instanceof Error) || !("code" in error) || error.code !== "ENOENT") {
1097
1097
  throw error;
@@ -1100,21 +1100,21 @@ var JSON_HEADERS, OWNERSHIP_FILE = ".absolutejs-mobile-associations.json", HTTP_
1100
1100
  if (current === source)
1101
1101
  return false;
1102
1102
  const temporary = `${path}.${crypto.randomUUID()}.tmp`;
1103
- await writeFile8(temporary, source, { flag: "wx" });
1104
- await rename8(temporary, path);
1103
+ await writeFile9(temporary, source, { flag: "wx" });
1104
+ await rename9(temporary, path);
1105
1105
  return true;
1106
- }, exists2 = async (path) => {
1106
+ }, exists3 = async (path) => {
1107
1107
  try {
1108
- await access8(path);
1108
+ await access9(path);
1109
1109
  return true;
1110
1110
  } catch {
1111
1111
  return false;
1112
1112
  }
1113
1113
  }, assertOwnedOutput = async (root) => {
1114
- const path = resolve7(root, OWNERSHIP_FILE);
1114
+ const path = resolve8(root, OWNERSHIP_FILE);
1115
1115
  let ownership;
1116
1116
  try {
1117
- ownership = JSON.parse(await readFile10(path, "utf8"));
1117
+ ownership = JSON.parse(await readFile11(path, "utf8"));
1118
1118
  } catch {
1119
1119
  throw new TypeError(`Association output ${root} already exists and is not owned by AbsoluteJS.`);
1120
1120
  }
@@ -1122,26 +1122,26 @@ var JSON_HEADERS, OWNERSHIP_FILE = ".absolutejs-mobile-associations.json", HTTP_
1122
1122
  throw new TypeError(`Association output ${root} has an unsupported ownership manifest.`);
1123
1123
  }
1124
1124
  }, publishGeneratedDirectory = async (temporary, root) => {
1125
- const hasCurrent = await exists2(root);
1125
+ const hasCurrent = await exists3(root);
1126
1126
  if (hasCurrent)
1127
1127
  await assertOwnedOutput(root);
1128
1128
  const backup = `${root}.${crypto.randomUUID()}.previous`;
1129
1129
  if (hasCurrent)
1130
- await rename8(root, backup);
1130
+ await rename9(root, backup);
1131
1131
  try {
1132
- await rename8(temporary, root);
1132
+ await rename9(temporary, root);
1133
1133
  } catch (error) {
1134
1134
  if (hasCurrent)
1135
- await rename8(backup, root);
1135
+ await rename9(backup, root);
1136
1136
  throw error;
1137
1137
  }
1138
1138
  if (hasCurrent)
1139
- await rm7(backup, { force: true, recursive: true });
1139
+ await rm8(backup, { force: true, recursive: true });
1140
1140
  }, materializeHost = async (root, host, files) => {
1141
- const directory = resolve7(root, host, ".well-known");
1142
- await mkdir7(directory, { recursive: true });
1141
+ const directory = resolve8(root, host, ".well-known");
1142
+ await mkdir8(directory, { recursive: true });
1143
1143
  return Promise.all(files.map(async ([name, document2]) => {
1144
- const path = resolve7(directory, name);
1144
+ const path = resolve8(directory, name);
1145
1145
  await writeAtomic(path, `${JSON.stringify(document2, null, 2)}
1146
1146
  `);
1147
1147
  return path;
@@ -1164,7 +1164,7 @@ var JSON_HEADERS, OWNERSHIP_FILE = ".absolutejs-mobile-associations.json", HTTP_
1164
1164
  });
1165
1165
  return endpoints;
1166
1166
  }), materializeAbsoluteMobileAssociationFiles = async (config, outputDirectory) => {
1167
- const root = resolve7(outputDirectory);
1167
+ const root = resolve8(outputDirectory);
1168
1168
  const temporary = `${root}.${crypto.randomUUID()}.tmp`;
1169
1169
  const documents = createAbsoluteMobileAssociationDocuments(config, {
1170
1170
  requireAll: true
@@ -1175,16 +1175,16 @@ var JSON_HEADERS, OWNERSHIP_FILE = ".absolutejs-mobile-associations.json", HTTP_
1175
1175
  if (documents.apple) {
1176
1176
  files.push(["apple-app-site-association", documents.apple]);
1177
1177
  }
1178
- await mkdir7(temporary, { recursive: true });
1178
+ await mkdir8(temporary, { recursive: true });
1179
1179
  try {
1180
1180
  const temporaryPaths = (await Promise.all(config.deepLinkHosts.map((host) => materializeHost(temporary, host, files)))).flat();
1181
- await writeAtomic(resolve7(temporary, OWNERSHIP_FILE), `${JSON.stringify({ format: 1, hosts: config.deepLinkHosts }, null, 2)}
1181
+ await writeAtomic(resolve8(temporary, OWNERSHIP_FILE), `${JSON.stringify({ format: 1, hosts: config.deepLinkHosts }, null, 2)}
1182
1182
  `);
1183
1183
  await publishGeneratedDirectory(temporary, root);
1184
- const written = temporaryPaths.map((path) => resolve7(root, path.slice(temporary.length + 1)));
1184
+ const written = temporaryPaths.map((path) => resolve8(root, path.slice(temporary.length + 1)));
1185
1185
  return { root, written };
1186
1186
  } catch (error) {
1187
- await rm7(temporary, { force: true, recursive: true });
1187
+ await rm8(temporary, { force: true, recursive: true });
1188
1188
  throw error;
1189
1189
  }
1190
1190
  }, verifyAbsoluteMobileAssociationFiles = async (config, request = globalThis.fetch) => {
@@ -1367,13 +1367,13 @@ var ABSOLUTE_MOBILE_PAGE_MEDIA_TYPE = "application/vnd.absolute.page+json", ABSO
1367
1367
  }, headerVaryValues, envelopeResponse = (response, status) => new Response(JSON.stringify({
1368
1368
  protocol: ABSOLUTE_MOBILE_PAGE_PROTOCOL_VERSION,
1369
1369
  response
1370
- }), { headers: responseHeaders(), status }), isRecord5 = (value) => typeof value === "object" && value !== null && !Array.isArray(value), normalizeJsonValue = (value) => {
1370
+ }), { headers: responseHeaders(), status }), isRecord6 = (value) => typeof value === "object" && value !== null && !Array.isArray(value), normalizeJsonValue = (value) => {
1371
1371
  const serialized = JSON.stringify(value);
1372
1372
  if (serialized === undefined) {
1373
1373
  throw new TypeError("Mobile page props must be JSON-serializable.");
1374
1374
  }
1375
1375
  const parsed = JSON.parse(serialized);
1376
- if (!isRecord5(parsed)) {
1376
+ if (!isRecord6(parsed)) {
1377
1377
  throw new TypeError("Mobile page props must serialize to an object.");
1378
1378
  }
1379
1379
  return parsed;
@@ -1607,26 +1607,26 @@ __export(exports_materializedBundle, {
1607
1607
  materializeAbsoluteMobileCompatibilityBundle: () => materializeAbsoluteMobileCompatibilityBundle,
1608
1608
  readAbsoluteMobileMaterializedReleases: () => readAbsoluteMobileMaterializedReleases
1609
1609
  });
1610
- import { createHash as createHash10 } from "crypto";
1610
+ import { createHash as createHash11 } from "crypto";
1611
1611
  import {
1612
- access as access9,
1613
- mkdir as mkdir10,
1614
- mkdtemp as mkdtemp6,
1615
- readFile as readFile13,
1616
- rename as rename10,
1617
- rm as rm9,
1618
- writeFile as writeFile11
1612
+ access as access10,
1613
+ mkdir as mkdir11,
1614
+ mkdtemp as mkdtemp7,
1615
+ readFile as readFile14,
1616
+ rename as rename11,
1617
+ rm as rm10,
1618
+ writeFile as writeFile12
1619
1619
  } from "fs/promises";
1620
- import { dirname as dirname8, join as join11, resolve as resolvePath4 } from "path";
1620
+ import { dirname as dirname9, join as join12, resolve as resolvePath4 } from "path";
1621
1621
  import { pathToFileURL } from "url";
1622
- var ABSOLUTE_MOBILE_MATERIALIZED_BUNDLE_FORMAT = 1, CURRENT_BUNDLE_FILE = "current.json", BUNDLES_DIRECTORY = "bundles", ARTIFACT_FILE2 = "artifact.json", BUNDLE_ID_PATTERN, isRecord7 = (value) => typeof value === "object" && value !== null && !Array.isArray(value), errorHasCode3 = (error, code) => typeof error === "object" && error !== null && Reflect.get(error, "code") === code, bundleIdFor = (currentReleaseId, releases) => {
1622
+ var ABSOLUTE_MOBILE_MATERIALIZED_BUNDLE_FORMAT = 1, CURRENT_BUNDLE_FILE = "current.json", BUNDLES_DIRECTORY = "bundles", ARTIFACT_FILE2 = "artifact.json", BUNDLE_ID_PATTERN, isRecord8 = (value) => typeof value === "object" && value !== null && !Array.isArray(value), errorHasCode3 = (error, code) => typeof error === "object" && error !== null && Reflect.get(error, "code") === code, bundleIdFor = (currentReleaseId, releases) => {
1623
1623
  const identity = JSON.stringify({
1624
1624
  currentReleaseId,
1625
1625
  releases: releases.map(({ releaseId }) => releaseId)
1626
1626
  });
1627
- return `amb_${createHash10("sha256").update(identity).digest("hex")}`;
1627
+ return `amb_${createHash11("sha256").update(identity).digest("hex")}`;
1628
1628
  }, parseBundleIndex = (value) => {
1629
- if (!isRecord7(value) || value.format !== ABSOLUTE_MOBILE_MATERIALIZED_BUNDLE_FORMAT || typeof value.bundleId !== "string" || !BUNDLE_ID_PATTERN.test(value.bundleId) || typeof value.currentReleaseId !== "string" || !Array.isArray(value.releases)) {
1629
+ if (!isRecord8(value) || value.format !== ABSOLUTE_MOBILE_MATERIALIZED_BUNDLE_FORMAT || typeof value.bundleId !== "string" || !BUNDLE_ID_PATTERN.test(value.bundleId) || typeof value.currentReleaseId !== "string" || !Array.isArray(value.releases)) {
1630
1630
  throw new TypeError("Invalid materialized mobile compatibility bundle.");
1631
1631
  }
1632
1632
  const releases = value.releases.map(parseAbsoluteMobileCompatibilityArtifact);
@@ -1648,29 +1648,29 @@ var ABSOLUTE_MOBILE_MATERIALIZED_BUNDLE_FORMAT = 1, CURRENT_BUNDLE_FILE = "curre
1648
1648
  releases
1649
1649
  };
1650
1650
  }, writeRelease = async (root, release) => {
1651
- const directory = join11(root, release.artifact.releaseId);
1652
- const producerPath = join11(directory, release.artifact.producer.module);
1653
- await mkdir10(dirname8(producerPath), { recursive: true });
1651
+ const directory = join12(root, release.artifact.releaseId);
1652
+ const producerPath = join12(directory, release.artifact.producer.module);
1653
+ await mkdir11(dirname9(producerPath), { recursive: true });
1654
1654
  await Promise.all([
1655
- writeFile11(join11(directory, ARTIFACT_FILE2), `${JSON.stringify(release.artifact, null, "\t")}
1655
+ writeFile12(join12(directory, ARTIFACT_FILE2), `${JSON.stringify(release.artifact, null, "\t")}
1656
1656
  `),
1657
- writeFile11(producerPath, new Uint8Array(await release.producer.arrayBuffer()))
1657
+ writeFile12(producerPath, new Uint8Array(await release.producer.arrayBuffer()))
1658
1658
  ]);
1659
1659
  }, installImmutableBundle = async (bundlesRoot, bundleId, releases) => {
1660
- const destination = join11(bundlesRoot, bundleId);
1660
+ const destination = join12(bundlesRoot, bundleId);
1661
1661
  try {
1662
- await access9(destination);
1662
+ await access10(destination);
1663
1663
  return destination;
1664
1664
  } catch (error) {
1665
1665
  if (!errorHasCode3(error, "ENOENT"))
1666
1666
  throw error;
1667
1667
  }
1668
- const staging = await mkdtemp6(join11(bundlesRoot, ".stage-"));
1668
+ const staging = await mkdtemp7(join12(bundlesRoot, ".stage-"));
1669
1669
  try {
1670
1670
  await Promise.all(releases.map((release) => writeRelease(staging, release)));
1671
- await rename10(staging, destination);
1671
+ await rename11(staging, destination);
1672
1672
  } catch (error) {
1673
- await rm9(staging, { force: true, recursive: true });
1673
+ await rm10(staging, { force: true, recursive: true });
1674
1674
  if (errorHasCode3(error, "EEXIST") || errorHasCode3(error, "ENOTEMPTY")) {
1675
1675
  return destination;
1676
1676
  }
@@ -1679,7 +1679,7 @@ var ABSOLUTE_MOBILE_MATERIALIZED_BUNDLE_FORMAT = 1, CURRENT_BUNDLE_FILE = "curre
1679
1679
  return destination;
1680
1680
  }, readCompatibilityModule = (modulePath) => import(pathToFileURL(modulePath).href), resolveProducerHandler = (loaded, exportName) => {
1681
1681
  const value = loaded[exportName];
1682
- if (!isRecord7(value) || typeof value.handle !== "function") {
1682
+ if (!isRecord8(value) || typeof value.handle !== "function") {
1683
1683
  throw new TypeError(`Compatibility producer export ${exportName} must expose handle(request).`);
1684
1684
  }
1685
1685
  const { handle } = value;
@@ -1696,15 +1696,15 @@ var ABSOLUTE_MOBILE_MATERIALIZED_BUNDLE_FORMAT = 1, CURRENT_BUNDLE_FILE = "curre
1696
1696
  };
1697
1697
  }, loadAbsoluteMobileMaterializedBundle = async (root) => {
1698
1698
  const resolvedRoot = resolvePath4(root);
1699
- const serialized = await readFile13(join11(resolvedRoot, CURRENT_BUNDLE_FILE), "utf8");
1699
+ const serialized = await readFile14(join12(resolvedRoot, CURRENT_BUNDLE_FILE), "utf8");
1700
1700
  const parsed = JSON.parse(serialized);
1701
1701
  const index = parseBundleIndex(parsed);
1702
- const bundleRoot = join11(resolvedRoot, BUNDLES_DIRECTORY, index.bundleId);
1702
+ const bundleRoot = join12(resolvedRoot, BUNDLES_DIRECTORY, index.bundleId);
1703
1703
  return {
1704
1704
  artifacts: index.releases,
1705
1705
  currentReleaseId: index.currentReleaseId,
1706
1706
  loadProducer: async (artifact) => {
1707
- const modulePath = join11(bundleRoot, artifact.releaseId, artifact.producer.module);
1707
+ const modulePath = join12(bundleRoot, artifact.releaseId, artifact.producer.module);
1708
1708
  await verifyAbsoluteMobileCompatibilityProducer({
1709
1709
  artifact,
1710
1710
  producer: Bun.file(modulePath)
@@ -1730,8 +1730,8 @@ var ABSOLUTE_MOBILE_MATERIALIZED_BUNDLE_FORMAT = 1, CURRENT_BUNDLE_FILE = "curre
1730
1730
  return release;
1731
1731
  });
1732
1732
  const root = resolvePath4(input.root);
1733
- const bundlesRoot = join11(root, BUNDLES_DIRECTORY);
1734
- await mkdir10(bundlesRoot, { recursive: true });
1733
+ const bundlesRoot = join12(root, BUNDLES_DIRECTORY);
1734
+ await mkdir11(bundlesRoot, { recursive: true });
1735
1735
  const bundleId = bundleIdFor(input.currentReleaseId, artifacts);
1736
1736
  await installImmutableBundle(bundlesRoot, bundleId, orderedReleases);
1737
1737
  const index = {
@@ -1740,21 +1740,21 @@ var ABSOLUTE_MOBILE_MATERIALIZED_BUNDLE_FORMAT = 1, CURRENT_BUNDLE_FILE = "curre
1740
1740
  format: ABSOLUTE_MOBILE_MATERIALIZED_BUNDLE_FORMAT,
1741
1741
  releases: artifacts
1742
1742
  };
1743
- const pointerPath = join11(root, CURRENT_BUNDLE_FILE);
1744
- const temporaryPointerPath = join11(root, `.current-${crypto.randomUUID()}.json`);
1745
- await writeFile11(temporaryPointerPath, `${JSON.stringify(index, null, "\t")}
1743
+ const pointerPath = join12(root, CURRENT_BUNDLE_FILE);
1744
+ const temporaryPointerPath = join12(root, `.current-${crypto.randomUUID()}.json`);
1745
+ await writeFile12(temporaryPointerPath, `${JSON.stringify(index, null, "\t")}
1746
1746
  `, { flag: "wx" });
1747
- await rename10(temporaryPointerPath, pointerPath);
1747
+ await rename11(temporaryPointerPath, pointerPath);
1748
1748
  return index;
1749
1749
  }, readAbsoluteMobileMaterializedReleases = async (root) => {
1750
1750
  const resolvedRoot = resolvePath4(root);
1751
1751
  try {
1752
- const serialized = await readFile13(join11(resolvedRoot, CURRENT_BUNDLE_FILE), "utf8");
1752
+ const serialized = await readFile14(join12(resolvedRoot, CURRENT_BUNDLE_FILE), "utf8");
1753
1753
  const parsed = JSON.parse(serialized);
1754
1754
  const index = parseBundleIndex(parsed);
1755
- const bundleRoot = join11(resolvedRoot, BUNDLES_DIRECTORY, index.bundleId);
1755
+ const bundleRoot = join12(resolvedRoot, BUNDLES_DIRECTORY, index.bundleId);
1756
1756
  return Promise.all(index.releases.map(async (artifact) => {
1757
- const producer = Bun.file(join11(bundleRoot, artifact.releaseId, artifact.producer.module));
1757
+ const producer = Bun.file(join12(bundleRoot, artifact.releaseId, artifact.producer.module));
1758
1758
  await verifyAbsoluteMobileCompatibilityProducer({
1759
1759
  artifact,
1760
1760
  producer
@@ -1775,7 +1775,7 @@ var init_materializedBundle = __esm(() => {
1775
1775
 
1776
1776
  // src/mobile/deviceCapabilities.ts
1777
1777
  import { existsSync as existsSync3, readFileSync as readFileSync3 } from "fs";
1778
- import { extname as extname3, join as join12, relative as relative9, resolve as resolve10 } from "path";
1778
+ import { extname as extname3, join as join13, relative as relative10, resolve as resolve11 } from "path";
1779
1779
  import { fileURLToPath } from "url";
1780
1780
  import ts from "typescript";
1781
1781
  var DEVICES_PACKAGE = "@absolutejs/devices", ABSOLUTE_MOBILE_SHELL_DEVICE_CAPABILITIES, ADAPTERS, SOURCE_GLOB, IGNORED_DIRECTORIES, IDENTIFIER_PATTERN, providerModulePattern = (provider) => new RegExp(`^@absolutejs/devices-${provider}/[a-z][a-z0-9-]*$`, "u"), providerPackagePattern = (provider) => provider === "capacitor" ? /^@capacitor\/[a-z][a-z0-9-]*@\d+\.\d+\.\d+$/u : /^(?:expo-[a-z][a-z0-9-]*|@react-native-[a-z0-9-]+\/[a-z][a-z0-9-]*)@\d+\.\d+\.\d+$/u, providerLabel = (provider) => provider === "capacitor" ? "Capacitor" : "Expo", ANDROID_PERMISSION_PATTERN, IOS_USAGE_DESCRIPTIONS, IOS_PRIVACY_ACCESSED_API_REASONS, IOS_PRIVACY_ACCESSED_APIS, object = (value) => typeof value === "object" && value !== null && !Array.isArray(value), readJson = (path) => {
@@ -1903,7 +1903,7 @@ var DEVICES_PACKAGE = "@absolutejs/devices", ABSOLUTE_MOBILE_SHELL_DEVICE_CAPABI
1903
1903
  };
1904
1904
  }, loadAbsoluteDeviceCapabilityProviders = (projectRoot, provider = "capacitor") => {
1905
1905
  const adapter = ADAPTERS[provider];
1906
- let path = join12(resolve10(projectRoot), "node_modules", adapter, "package.json");
1906
+ let path = join13(resolve11(projectRoot), "node_modules", adapter, "package.json");
1907
1907
  try {
1908
1908
  readFileSync3(path, "utf8");
1909
1909
  } catch {
@@ -1958,7 +1958,7 @@ var DEVICES_PACKAGE = "@absolutejs/devices", ABSOLUTE_MOBILE_SHELL_DEVICE_CAPABI
1958
1958
  if (missing.includes(spec))
1959
1959
  return false;
1960
1960
  try {
1961
- return readJson(join12(resolve10(projectRoot), "node_modules", packageName, "package.json")).version !== spec.slice(separator + 1);
1961
+ return readJson(join13(resolve11(projectRoot), "node_modules", packageName, "package.json")).version !== spec.slice(separator + 1);
1962
1962
  } catch {
1963
1963
  return true;
1964
1964
  }
@@ -1967,7 +1967,7 @@ var DEVICES_PACKAGE = "@absolutejs/devices", ABSOLUTE_MOBILE_SHELL_DEVICE_CAPABI
1967
1967
  if (unmet.length > 0)
1968
1968
  throw new TypeError(`Device capabilities ${plan.capabilities.join(", ")} require ${unmet.join(", ")}. Run absolute mobile sync and approve the detected capability plugins.`);
1969
1969
  }, directAbsoluteProjectPackages = (projectRoot) => {
1970
- const manifest = readJson(join12(resolve10(projectRoot), "package.json"));
1970
+ const manifest = readJson(join13(resolve11(projectRoot), "package.json"));
1971
1971
  const packages = new Set;
1972
1972
  for (const field2 of ["dependencies", "devDependencies"]) {
1973
1973
  const dependencies = manifest[field2];
@@ -1977,16 +1977,16 @@ var DEVICES_PACKAGE = "@absolutejs/devices", ABSOLUTE_MOBILE_SHELL_DEVICE_CAPABI
1977
1977
  }
1978
1978
  return packages;
1979
1979
  }, discoverAbsoluteDeviceCapabilities = (projectRoot, providers = loadAbsoluteDeviceCapabilityProviders(projectRoot)) => {
1980
- const root = resolve10(projectRoot);
1980
+ const root = resolve11(projectRoot);
1981
1981
  if (!existsSync3(root))
1982
1982
  return [];
1983
1983
  const known = new Set(Object.keys(providers));
1984
1984
  const capabilities = new Set;
1985
1985
  for (const path of SOURCE_GLOB.scanSync({ cwd: root })) {
1986
- const portable = relative9(root, resolve10(root, path)).replaceAll("\\", "/");
1986
+ const portable = relative10(root, resolve11(root, path)).replaceAll("\\", "/");
1987
1987
  if (isIgnored(portable))
1988
1988
  continue;
1989
- const source = readFileSync3(resolve10(root, portable), "utf8");
1989
+ const source = readFileSync3(resolve11(root, portable), "utf8");
1990
1990
  for (const name of importedCapabilities(source, portable))
1991
1991
  if (known.has(name))
1992
1992
  capabilities.add(name);
@@ -1996,12 +1996,12 @@ var DEVICES_PACKAGE = "@absolutejs/devices", ABSOLUTE_MOBILE_SHELL_DEVICE_CAPABI
1996
1996
  const packageName = spec.slice(0, spec.lastIndexOf("@"));
1997
1997
  return !directPackages.has(packageName);
1998
1998
  }), projectImportsAbsoluteDeviceCapability = (projectRoot, capability) => {
1999
- const root = resolve10(projectRoot);
1999
+ const root = resolve11(projectRoot);
2000
2000
  for (const path of SOURCE_GLOB.scanSync({ cwd: root })) {
2001
- const portable = relative9(root, resolve10(root, path)).replaceAll("\\", "/");
2001
+ const portable = relative10(root, resolve11(root, path)).replaceAll("\\", "/");
2002
2002
  if (isIgnored(portable))
2003
2003
  continue;
2004
- const source = readFileSync3(resolve10(root, portable), "utf8");
2004
+ const source = readFileSync3(resolve11(root, portable), "utf8");
2005
2005
  if (importedCapabilities(source, portable).has(capability))
2006
2006
  return true;
2007
2007
  }
@@ -2068,10 +2068,10 @@ var init_deviceCapabilities = __esm(() => {
2068
2068
 
2069
2069
  // src/mobile/nativeAuth.ts
2070
2070
  import { readFileSync as readFileSync4 } from "fs";
2071
- import { join as join13 } from "path";
2071
+ import { join as join14 } from "path";
2072
2072
  var ABSOLUTE_AUTH_PACKAGE = "@absolutejs/auth", ABSOLUTE_EXPO_AUTH_CORE_VERSION = "0.76.3", ABSOLUTE_EXPO_AUTH_PACKAGE = "@absolutejs/auth-expo", ABSOLUTE_EXPO_AUTH_VERSION = "0.0.6", ABSOLUTE_EXPO_SYNC_CORE_VERSION = "2.31.0", ABSOLUTE_EXPO_SYNC_PACKAGE = "@absolutejs/sync-expo", ABSOLUTE_EXPO_SYNC_VERSION = "0.0.4", ABSOLUTE_NATIVE_AUTH_CLIENTS_ENV = "ABSOLUTE_AUTH_NATIVE_CLIENTS", ABSOLUTE_NATIVE_AUTH_SCOPES, ABSOLUTE_SYNC_PACKAGE = "@absolutejs/sync", readPackageManifest = (projectRoot) => {
2073
2073
  try {
2074
- return JSON.parse(readFileSync4(join13(projectRoot, "package.json"), "utf8"));
2074
+ return JSON.parse(readFileSync4(join14(projectRoot, "package.json"), "utf8"));
2075
2075
  } catch {
2076
2076
  return;
2077
2077
  }
@@ -2241,7 +2241,7 @@ var init_client = __esm(() => {
2241
2241
 
2242
2242
  // src/mobile/syncSchema.ts
2243
2243
  import { readFileSync as readFileSync5 } from "fs";
2244
- import { dirname as dirname9, join as join14, resolve as resolve11 } from "path";
2244
+ import { dirname as dirname10, join as join15, resolve as resolve12 } from "path";
2245
2245
  var object2 = (value) => typeof value === "object" && value !== null && !Array.isArray(value), manifestAt = (path) => {
2246
2246
  try {
2247
2247
  const value = JSON.parse(readFileSync5(path, "utf8"));
@@ -2258,13 +2258,13 @@ var object2 = (value) => typeof value === "object" && value !== null && !Array.i
2258
2258
  return;
2259
2259
  return Reflect.get(sync, "localSchema");
2260
2260
  }, packageManifestPath = (projectRoot, packageName) => {
2261
- let directory = resolve11(projectRoot);
2261
+ let directory = resolve12(projectRoot);
2262
2262
  while (true) {
2263
- const candidate = join14(directory, "node_modules", packageName, "package.json");
2263
+ const candidate = join15(directory, "node_modules", packageName, "package.json");
2264
2264
  const manifest = manifestAt(candidate);
2265
2265
  if (manifest && Reflect.get(manifest, "name") === packageName)
2266
2266
  return candidate;
2267
- const parent = dirname9(directory);
2267
+ const parent = dirname10(directory);
2268
2268
  if (parent === directory)
2269
2269
  return;
2270
2270
  directory = parent;
@@ -2491,7 +2491,7 @@ var object2 = (value) => typeof value === "object" && value !== null && !Array.i
2491
2491
  Reflect.get(manifest, "devDependencies"),
2492
2492
  Reflect.get(manifest, "peerDependencies")
2493
2493
  ].flatMap((dependencies) => object2(dependencies) ? Object.keys(dependencies) : []).filter((name, index, names) => names.indexOf(name) === index).sort(), discoverAbsoluteSyncSchema = (projectRoot) => {
2494
- const appManifestPath = join14(resolve11(projectRoot), "package.json");
2494
+ const appManifestPath = join15(resolve12(projectRoot), "package.json");
2495
2495
  const appManifest = manifestAt(appManifestPath);
2496
2496
  if (!appManifest)
2497
2497
  return {
@@ -6838,9 +6838,9 @@ var require_sha256 = __commonJS(function(exports, module) {
6838
6838
  var forge = require_forge();
6839
6839
  require_md();
6840
6840
  require_util();
6841
- var sha2562 = module.exports = forge.sha256 = forge.sha256 || {};
6842
- forge.md.sha256 = forge.md.algorithms.sha256 = sha2562;
6843
- sha2562.create = function() {
6841
+ var sha2563 = module.exports = forge.sha256 = forge.sha256 || {};
6842
+ forge.md.sha256 = forge.md.algorithms.sha256 = sha2563;
6843
+ sha2563.create = function() {
6844
6844
  if (!_initialized) {
6845
6845
  _init();
6846
6846
  }
@@ -19350,8 +19350,8 @@ var init_compatibilityDispatcher = __esm(() => {
19350
19350
 
19351
19351
  // src/cli/scripts/telemetry.ts
19352
19352
  import { existsSync as existsSync5, mkdirSync, readFileSync as readFileSync6, writeFileSync } from "fs";
19353
- import { homedir as homedir3 } from "os";
19354
- import { join as join21 } from "path";
19353
+ import { homedir as homedir4 } from "os";
19354
+ import { join as join22 } from "path";
19355
19355
  var configDir, configPath, getTelemetryConfig = () => {
19356
19356
  try {
19357
19357
  if (!existsSync5(configPath))
@@ -19364,14 +19364,14 @@ var configDir, configPath, getTelemetryConfig = () => {
19364
19364
  }
19365
19365
  };
19366
19366
  var init_telemetry = __esm(() => {
19367
- configDir = join21(homedir3(), ".absolutejs");
19368
- configPath = join21(configDir, "telemetry.json");
19367
+ configDir = join22(homedir4(), ".absolutejs");
19368
+ configPath = join22(configDir, "telemetry.json");
19369
19369
  });
19370
19370
 
19371
19371
  // src/cli/telemetryEvent.ts
19372
19372
  import { existsSync as existsSync6, readFileSync as readFileSync7 } from "fs";
19373
19373
  import { arch, platform as platform3 } from "os";
19374
- import { dirname as dirname14, join as join22, parse } from "path";
19374
+ import { dirname as dirname15, join as join23, parse } from "path";
19375
19375
  var checkCandidate = (candidate) => {
19376
19376
  if (!existsSync6(candidate)) {
19377
19377
  return null;
@@ -19391,12 +19391,12 @@ var checkCandidate = (candidate) => {
19391
19391
  }, findPackageVersion = () => {
19392
19392
  let { dir } = import.meta;
19393
19393
  while (dir !== parse(dir).root) {
19394
- const candidate = join22(dir, "package.json");
19394
+ const candidate = join23(dir, "package.json");
19395
19395
  const version = checkCandidate(candidate);
19396
19396
  if (version) {
19397
19397
  return version;
19398
19398
  }
19399
- dir = dirname14(dir);
19399
+ dir = dirname15(dir);
19400
19400
  }
19401
19401
  return "unknown";
19402
19402
  }, sendTelemetryEvent = (event, payload) => {
@@ -19437,7 +19437,7 @@ __export(exports_mobilePreview, {
19437
19437
  createAbsoluteMobilePreviewPlugin: () => createAbsoluteMobilePreviewPlugin
19438
19438
  });
19439
19439
  import { Elysia as Elysia3 } from "elysia";
19440
- var ABSOLUTE_MOBILE_PREVIEW_PATH = "/__absolute/mobile-preview", escapeHtml2 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;"), isRecord10 = (value) => typeof value === "object" && value !== null, normalizeEntry2 = (entry) => {
19440
+ var ABSOLUTE_MOBILE_PREVIEW_PATH = "/__absolute/mobile-preview", escapeHtml2 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;"), isRecord11 = (value) => typeof value === "object" && value !== null, normalizeEntry2 = (entry) => {
19441
19441
  const parsed = new URL(entry ?? "/", "https://absolute.invalid");
19442
19442
  return `${parsed.pathname}${parsed.search}${parsed.hash}`;
19443
19443
  }, absoluteMobilePreviewDocument = (mobile) => {
@@ -19485,7 +19485,7 @@ var ABSOLUTE_MOBILE_PREVIEW_PATH = "/__absolute/mobile-preview", escapeHtml2 = (
19485
19485
  "X-Robots-Tag": "noindex, nofollow"
19486
19486
  }
19487
19487
  })).post("/__absolute/mobile-preview-telemetry", ({ body, status }) => {
19488
- const value = isRecord10(body) ? body : undefined;
19488
+ const value = isRecord11(body) ? body : undefined;
19489
19489
  const durationMs = value?.durationMs;
19490
19490
  const platform4 = value?.platform;
19491
19491
  if (typeof durationMs !== "number" || !Number.isFinite(durationMs) || durationMs < 0 || durationMs > 300000 || platform4 !== "android" && platform4 !== "ios") {
@@ -20032,7 +20032,7 @@ __export(exports_mobileUpdate, {
20032
20032
  parseMobileUpdateManifest: () => parseMobileUpdateManifest
20033
20033
  });
20034
20034
  import {
20035
- createHash as createHash16,
20035
+ createHash as createHash17,
20036
20036
  createHmac,
20037
20037
  createPrivateKey,
20038
20038
  createPublicKey as createPublicKey2,
@@ -20042,7 +20042,7 @@ import {
20042
20042
  verify as verify2,
20043
20043
  X509Certificate as X509Certificate3
20044
20044
  } from "crypto";
20045
- import { readFile as readFile24, stat as stat5 } from "fs/promises";
20045
+ import { readFile as readFile25, stat as stat6 } from "fs/promises";
20046
20046
  import path from "path";
20047
20047
  var MOBILE_UPDATE_REGISTRY_FORMAT = 1, DEFAULT_PREFIX = "absolutejs/mobile-updates", MAX_FILE_BYTES, MAX_TOTAL_BYTES, DAY_MS, DEFAULT_MIN_AGE_MS, DEFAULT_GRACE_PERIOD_MS, DEFAULT_RETAIN_RECENT = 5, HASH, RELEASE, APP_ID, NAME, EXPO_DESCRIPTOR = "_absolute/expo-update.json", EXPO_CODE_SIGNING_ALGORITHM = "rsa-v1_5-sha256", HEALTH_TOKEN_VERSION = 1, HEALTH_KINDS, FAILURE_HEALTH_KINDS, MobileUpdateRegistryError, object6 = (value) => typeof value === "object" && value !== null && !Array.isArray(value), text2 = (value, field2) => {
20048
20048
  if (typeof value !== "string" || value.length === 0)
@@ -20192,7 +20192,7 @@ var MOBILE_UPDATE_REGISTRY_FORMAT = 1, DEFAULT_PREFIX = "absolutejs/mobile-updat
20192
20192
  if (!prefix || prefix.split("/").some((segment) => segment === "." || segment === ".."))
20193
20193
  throw new MobileUpdateRegistryError("Mobile update prefix is invalid");
20194
20194
  return prefix;
20195
- }, appHash = (appId) => createHash16("sha256").update(appId).digest("hex"), digest = (bytes) => createHash16("sha256").update(bytes).digest("hex"), json = (value) => new TextEncoder().encode(`${JSON.stringify(value, null, 2)}
20195
+ }, appHash = (appId) => createHash17("sha256").update(appId).digest("hex"), digest = (bytes) => createHash17("sha256").update(bytes).digest("hex"), json = (value) => new TextEncoder().encode(`${JSON.stringify(value, null, 2)}
20196
20196
  `), decode2 = (value) => JSON.parse(new TextDecoder().decode(value)), fileDigest = async (file) => {
20197
20197
  const hasher = new Bun.CryptoHasher("sha256");
20198
20198
  for await (const chunk of file.stream())
@@ -20203,7 +20203,7 @@ var MOBILE_UPDATE_REGISTRY_FORMAT = 1, DEFAULT_PREFIX = "absolutejs/mobile-updat
20203
20203
  return false;
20204
20204
  if (input.rollout === 1)
20205
20205
  return true;
20206
- const value = createHash16("sha256").update(`${input.appId}\x00${input.channel}\x00${input.releaseId}\x00${input.installationId}`).digest().readUInt32BE(0);
20206
+ const value = createHash17("sha256").update(`${input.appId}\x00${input.channel}\x00${input.releaseId}\x00${input.installationId}`).digest().readUInt32BE(0);
20207
20207
  return value / 4294967296 < input.rollout;
20208
20208
  }, base64Url = (value) => Buffer.from(value).toString("base64url"), healthPromotionId = (channel) => channel.promotionId ?? digest(new TextEncoder().encode(`${channel.appId}\x00${channel.channel}\x00${channel.releaseId ?? "embedded"}\x00${channel.promotedAt}`)), finiteMetric = (value, field2) => {
20209
20209
  if (typeof value !== "number" || !Number.isFinite(value) || value < 0)
@@ -20243,7 +20243,7 @@ var MOBILE_UPDATE_REGISTRY_FORMAT = 1, DEFAULT_PREFIX = "absolutejs/mobile-updat
20243
20243
  const releaseRoot = (manifest) => `${root(manifest.appId)}/releases/${manifest.releaseId}`;
20244
20244
  const manifestKey = (manifest) => `${releaseRoot(manifest)}/update.json`;
20245
20245
  const fileKey = (manifest, file) => `${releaseRoot(manifest)}/files/${file.path}`;
20246
- const contentBlobKey = (appId, sha2563) => `${root(appId)}/blobs/${sha2563}`;
20246
+ const contentBlobKey = (appId, sha2564) => `${root(appId)}/blobs/${sha2564}`;
20247
20247
  const tombstoneKey = (appId, releaseId) => `${root(appId)}/gc/${releaseId}.json`;
20248
20248
  const healthRoot = (appId, promotionId, releaseId) => `${root(appId)}/health/${promotionId}/${releaseId}`;
20249
20249
  const pauseKey = (appId, promotionId, releaseId) => `${healthRoot(appId, promotionId, releaseId)}/paused.json`;
@@ -20864,10 +20864,10 @@ var MOBILE_UPDATE_REGISTRY_FORMAT = 1, DEFAULT_PREFIX = "absolutejs/mobile-updat
20864
20864
  const objectBytesByDigest = new Map;
20865
20865
  for (const blobObject of objects) {
20866
20866
  if (blobObject.key.startsWith(blobPrefix)) {
20867
- const sha2563 = blobObject.key.slice(blobPrefix.length);
20868
- if (HASH.test(sha2563)) {
20869
- objectKeysByDigest.set(sha2563, blobObject.key);
20870
- objectBytesByDigest.set(sha2563, blobObject.size);
20867
+ const sha2564 = blobObject.key.slice(blobPrefix.length);
20868
+ if (HASH.test(sha2564)) {
20869
+ objectKeysByDigest.set(sha2564, blobObject.key);
20870
+ objectBytesByDigest.set(sha2564, blobObject.size);
20871
20871
  }
20872
20872
  }
20873
20873
  if (!blobObject.key.startsWith(releasePrefix))
@@ -20950,7 +20950,7 @@ var MOBILE_UPDATE_REGISTRY_FORMAT = 1, DEFAULT_PREFIX = "absolutejs/mobile-updat
20950
20950
  }).toSorted((left, right) => right.createdAt.localeCompare(left.createdAt));
20951
20951
  const protectedReleaseIds = new Set(releases.filter((release) => release.protectedBy.length > 0).map((release) => release.releaseId));
20952
20952
  const protectedDigests = new Set(manifests.filter((manifest) => protectedReleaseIds.has(manifest.releaseId)).flatMap((manifest) => manifest.files.map((file) => file.sha256)));
20953
- const reclaimableContentBytes = [...objectBytesByDigest].filter(([sha2563]) => !protectedDigests.has(sha2563)).reduce((total, [, bytes]) => total + bytes, 0);
20953
+ const reclaimableContentBytes = [...objectBytesByDigest].filter(([sha2564]) => !protectedDigests.has(sha2564)).reduce((total, [, bytes]) => total + bytes, 0);
20954
20954
  const contentBlobBytes = [...objectBytesByDigest.values()].reduce((total, bytes) => total + bytes, 0);
20955
20955
  const releaseBytes = releases.reduce((total, release) => total + release.bytes, 0);
20956
20956
  const totalBytes = objects.reduce((total, object22) => total + object22.size, 0);
@@ -21047,13 +21047,13 @@ var MOBILE_UPDATE_REGISTRY_FORMAT = 1, DEFAULT_PREFIX = "absolutejs/mobile-updat
21047
21047
  for (const file of manifest?.manifest.files ?? [])
21048
21048
  referencedDigests.add(file.sha256);
21049
21049
  }
21050
- for (const [sha2563, key] of afterReleaseSweep.objectKeysByDigest) {
21051
- if (referencedDigests.has(sha2563))
21050
+ for (const [sha2564, key] of afterReleaseSweep.objectKeysByDigest) {
21051
+ if (referencedDigests.has(sha2564))
21052
21052
  continue;
21053
21053
  const head = await options.store.head(key);
21054
21054
  await remove(key);
21055
21055
  result.reclaimedBytes += head?.size ?? 0;
21056
- result.sweptContentBlobs.push(sha2563);
21056
+ result.sweptContentBlobs.push(sha2564);
21057
21057
  }
21058
21058
  return result;
21059
21059
  };
@@ -21075,7 +21075,7 @@ var MOBILE_UPDATE_REGISTRY_FORMAT = 1, DEFAULT_PREFIX = "absolutejs/mobile-updat
21075
21075
  verifyManifestSignature(manifest, options.publicKeys);
21076
21076
  await assertNotMarked(manifest.appId, manifest.releaseId);
21077
21077
  const localRoot = path.resolve(input.releaseDirectory);
21078
- const localManifest = parseMobileUpdateManifest(JSON.parse(await readFile24(path.join(localRoot, "update.json"), "utf8")));
21078
+ const localManifest = parseMobileUpdateManifest(JSON.parse(await readFile25(path.join(localRoot, "update.json"), "utf8")));
21079
21079
  if (JSON.stringify(localManifest) !== JSON.stringify(manifest))
21080
21080
  throw new MobileUpdateRegistryError("Local mobile update manifest changed");
21081
21081
  const existing = await readManifest(manifest.appId, manifest.releaseId);
@@ -21093,7 +21093,7 @@ var MOBILE_UPDATE_REGISTRY_FORMAT = 1, DEFAULT_PREFIX = "absolutejs/mobile-updat
21093
21093
  if (!existing) {
21094
21094
  for (const file of manifest.files) {
21095
21095
  const local = path.join(localRoot, "files", file.path);
21096
- const metadata = await stat5(local).catch(() => null);
21096
+ const metadata = await stat6(local).catch(() => null);
21097
21097
  if (!metadata?.isFile() || metadata.size !== file.bytes)
21098
21098
  throw new MobileUpdateRegistryError(`Mobile update file ${file.path} size changed`);
21099
21099
  if (await fileDigest(Bun.file(local)) !== file.sha256)
@@ -21208,10 +21208,10 @@ var MOBILE_UPDATE_REGISTRY_FORMAT = 1, DEFAULT_PREFIX = "absolutejs/mobile-updat
21208
21208
  }
21209
21209
  };
21210
21210
  }, expoUpdateId = (releaseId) => {
21211
- const hash = RELEASE.test(releaseId) ? releaseId.slice("amu_".length, "amu_".length + 32) : createHash16("sha256").update(releaseId).digest("hex").slice(0, 32);
21211
+ const hash = RELEASE.test(releaseId) ? releaseId.slice("amu_".length, "amu_".length + 32) : createHash17("sha256").update(releaseId).digest("hex").slice(0, 32);
21212
21212
  return `${hash.slice(0, 8)}-${hash.slice(8, 12)}-${hash.slice(12, 16)}-${hash.slice(16, 20)}-${hash.slice(20)}`;
21213
- }, expoContentType = (extension2, launch) => {
21214
- if (launch)
21213
+ }, expoContentType = (extension2, launch2) => {
21214
+ if (launch2)
21215
21215
  return "application/javascript";
21216
21216
  const normalized = extension2?.toLowerCase();
21217
21217
  if (normalized === "png")
@@ -21361,8 +21361,8 @@ var MOBILE_UPDATE_REGISTRY_FORMAT = 1, DEFAULT_PREFIX = "absolutejs/mobile-updat
21361
21361
  });
21362
21362
  }
21363
21363
  const pathname = new URL(request.url).pathname.replace(/^\/+/, "");
21364
- const relative18 = pathname.startsWith(`${route}/`) ? pathname.slice(route.length + 1) : "";
21365
- if (request.method === "POST" && relative18 === "health") {
21364
+ const relative19 = pathname.startsWith(`${route}/`) ? pathname.slice(route.length + 1) : "";
21365
+ if (request.method === "POST" && relative19 === "health") {
21366
21366
  if (!options.registry.recordUpdateHealth)
21367
21367
  return new Response(null, { status: 404 });
21368
21368
  const appId = request.headers.get("x-absolute-mobile-app");
@@ -21405,7 +21405,7 @@ var MOBILE_UPDATE_REGISTRY_FORMAT = 1, DEFAULT_PREFIX = "absolutejs/mobile-updat
21405
21405
  }
21406
21406
  if (request.method !== "GET")
21407
21407
  return new Response(null, { status: 405 });
21408
- if (relative18 === "update.json") {
21408
+ if (relative19 === "update.json") {
21409
21409
  const expoProtocolVersion = request.headers.get("expo-protocol-version");
21410
21410
  const expoProtocol = expoProtocolVersion !== null;
21411
21411
  if (expoProtocol && expoProtocolVersion !== "1")
@@ -21472,12 +21472,12 @@ var MOBILE_UPDATE_REGISTRY_FORMAT = 1, DEFAULT_PREFIX = "absolutejs/mobile-updat
21472
21472
  return new Response(null, { status: 204 });
21473
21473
  const origin2 = new URL(request.url).origin;
21474
21474
  const releaseRoute = `${origin2}/${route}/${selected.manifest.releaseId}/files`;
21475
- const protocolAsset = (asset2, launch = false) => {
21475
+ const protocolAsset = (asset2, launch2 = false) => {
21476
21476
  const file2 = selected.manifest.files.find((candidate) => candidate.path === asset2.path);
21477
21477
  if (!file2)
21478
21478
  throw new MobileUpdateRegistryError(`Expo update references missing signed asset ${asset2.path}`);
21479
21479
  return {
21480
- contentType: expoContentType(asset2.extension, launch),
21480
+ contentType: expoContentType(asset2.extension, launch2),
21481
21481
  ...asset2.extension ? { fileExtension: `.${asset2.extension}` } : {},
21482
21482
  key: file2.sha256,
21483
21483
  hash: Buffer.from(file2.sha256, "hex").toString("base64url"),
@@ -21523,7 +21523,7 @@ var MOBILE_UPDATE_REGISTRY_FORMAT = 1, DEFAULT_PREFIX = "absolutejs/mobile-updat
21523
21523
  }
21524
21524
  });
21525
21525
  }
21526
- const match = /^(amu_[a-f0-9]{64})\/files\/(.+)$/.exec(relative18);
21526
+ const match = /^(amu_[a-f0-9]{64})\/files\/(.+)$/.exec(relative19);
21527
21527
  if (!match?.[1] || !match[2])
21528
21528
  return new Response(null, { status: 404 });
21529
21529
  const file = await options.registry.readUpdateFile({
@@ -21616,15 +21616,15 @@ import {
21616
21616
  createPublicKey as createPublicKey3,
21617
21617
  X509Certificate as X509Certificate4
21618
21618
  } from "crypto";
21619
- import { access as access17, mkdir as mkdir18 } from "fs/promises";
21620
- import { dirname as dirname19, isAbsolute as isAbsolute9, relative as relative18, resolve as resolve20, sep as sep11 } from "path";
21619
+ import { access as access18, mkdir as mkdir19 } from "fs/promises";
21620
+ import { dirname as dirname20, isAbsolute as isAbsolute10, relative as relative19, resolve as resolve21, sep as sep12 } from "path";
21621
21621
  import { pathToFileURL as pathToFileURL5 } from "url";
21622
21622
  import { Elysia as Elysia4 } from "elysia";
21623
21623
  var ABSOLUTE_MOBILE_UPDATE_SERVER_FORMAT = 1, DEFAULT_MOBILE_UPDATE_REGISTRY_MODULE = "mobile.update.ts", object7 = (value) => typeof value === "object" && value !== null && !Array.isArray(value), projectPath3 = (projectRoot, requested) => {
21624
- const root = resolve20(projectRoot);
21625
- const path2 = resolve20(root, requested);
21626
- const projectRelative = relative18(root, path2);
21627
- if (projectRelative === ".." || projectRelative.startsWith(`..${sep11}`) || isAbsolute9(projectRelative))
21624
+ const root = resolve21(projectRoot);
21625
+ const path2 = resolve21(root, requested);
21626
+ const projectRelative = relative19(root, path2);
21627
+ if (projectRelative === ".." || projectRelative.startsWith(`..${sep12}`) || isAbsolute10(projectRelative))
21628
21628
  throw new TypeError("mobile.updates.server.registry must remain inside the project.");
21629
21629
  return path2;
21630
21630
  }, isRegistry4 = (value) => object7(value) && [
@@ -21647,7 +21647,7 @@ var ABSOLUTE_MOBILE_UPDATE_SERVER_FORMAT = 1, DEFAULT_MOBILE_UPDATE_REGISTRY_MOD
21647
21647
  return metadata;
21648
21648
  }, loadAbsoluteMobileUpdateServerModule = async (projectRoot, requestedModulePath = DEFAULT_MOBILE_UPDATE_REGISTRY_MODULE) => {
21649
21649
  const modulePath = projectPath3(projectRoot, requestedModulePath);
21650
- await access17(modulePath).catch(() => {
21650
+ await access18(modulePath).catch(() => {
21651
21651
  throw new TypeError(`Mobile update server registry does not exist: ${modulePath}. Run \`absolute mobile update provision\`.`);
21652
21652
  });
21653
21653
  const loaded = await import(pathToFileURL5(modulePath).href);
@@ -21836,13 +21836,13 @@ ${generated}`);
21836
21836
  }, writeAbsoluteMobileUpdateRegistry = async (options) => {
21837
21837
  const path2 = projectPath3(options.projectRoot, options.modulePath ?? DEFAULT_MOBILE_UPDATE_REGISTRY_MODULE);
21838
21838
  if (!options.force) {
21839
- await access17(path2).then(() => {
21839
+ await access18(path2).then(() => {
21840
21840
  throw new TypeError(`Mobile update registry already exists: ${path2}. Pass --force to replace it.`);
21841
21841
  }, () => {
21842
21842
  return;
21843
21843
  });
21844
21844
  }
21845
- await mkdir18(dirname19(path2), { recursive: true });
21845
+ await mkdir19(dirname20(path2), { recursive: true });
21846
21846
  await Bun.write(path2, renderAbsoluteMobileUpdateRegistry({
21847
21847
  ...options.health ? { health: options.health } : {},
21848
21848
  ...options.rollout ? { rollout: options.rollout } : {},
@@ -24000,6 +24000,8 @@ var encodedWindowsExpoAndroidCommand = (project, androidRoot, appId, args, captu
24000
24000
  "$env:GRADLE_OPTS = (($env:GRADLE_OPTS + ' -Dorg.gradle.daemon=false').Trim())",
24001
24001
  "$autolinkingCache = Join-Path $mappedProject 'android\\build\\generated\\autolinking'",
24002
24002
  "if ([IO.Directory]::Exists($autolinkingCache)) { [IO.Directory]::Delete($autolinkingCache, $true) }",
24003
+ "$reactGeneratedResources = Join-Path $mappedProject 'android\\app\\build\\generated\\res\\react'",
24004
+ "if ([IO.Directory]::Exists($reactGeneratedResources)) { [IO.Directory]::Delete($reactGeneratedResources, $true) }",
24003
24005
  ...mode === "development" ? [
24004
24006
  "$expo = Join-Path $mappedProject 'node_modules\\.bin\\expo.exe'",
24005
24007
  "& $expo @expoArguments",
@@ -24887,6 +24889,29 @@ var buildAbsoluteAndroidRelease = async (options) => {
24887
24889
  };
24888
24890
  return installRelease(artifactPath, metadata, safeOutputDirectory(projectRoot, options.outputDirectory));
24889
24891
  };
24892
+ // src/mobile/androidReleaseAcceptance.ts
24893
+ import { createHash as createHash5 } from "crypto";
24894
+ import {
24895
+ access as access6,
24896
+ mkdir as mkdir4,
24897
+ mkdtemp as mkdtemp3,
24898
+ readFile as readFile6,
24899
+ rename as rename5,
24900
+ rm as rm4,
24901
+ stat as stat2,
24902
+ writeFile as writeFile5
24903
+ } from "fs/promises";
24904
+ import { homedir as homedir2 } from "os";
24905
+ import {
24906
+ basename,
24907
+ dirname as dirname3,
24908
+ isAbsolute as isAbsolute3,
24909
+ join as join6,
24910
+ relative as relative4,
24911
+ resolve as resolve4,
24912
+ sep as sep3
24913
+ } from "path";
24914
+
24890
24915
  // src/mobile/androidUpgradeConformance.ts
24891
24916
  import { performance as performance2 } from "perf_hooks";
24892
24917
  var captureCommand4 = async (command) => {
@@ -24980,21 +25005,291 @@ var runAbsoluteAndroidUpgradeConformance = async (options) => {
24980
25005
  state
24981
25006
  };
24982
25007
  };
25008
+
25009
+ // src/mobile/androidReleaseAcceptance.ts
25010
+ var ABSOLUTE_BUNDLETOOL_VERSION = "1.18.3";
25011
+ var ABSOLUTE_BUNDLETOOL_SHA256 = "a099cfa1543f55593bc2ed16a70a7c67fe54b1747bb7301f37fdfd6d91028e29";
25012
+ var ABSOLUTE_BUNDLETOOL_URL = `https://github.com/google/bundletool/releases/download/${ABSOLUTE_BUNDLETOOL_VERSION}/bundletool-all-${ABSOLUTE_BUNDLETOOL_VERSION}.jar`;
25013
+ var EMBEDDED_READY_MARKER = "Expo embedded web content ready";
25014
+ var RELEASE_READY_POLL_MS = 250;
25015
+ var RELEASE_READY_TIMEOUT_MS = 30000;
25016
+ var RELEASE_STABILITY_MS = 2000;
25017
+ var isRecord2 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
25018
+ var exists2 = async (path) => {
25019
+ try {
25020
+ await access6(path);
25021
+ return true;
25022
+ } catch {
25023
+ return false;
25024
+ }
25025
+ };
25026
+ var sha256 = async (path) => createHash5("sha256").update(await readFile6(path)).digest("hex");
25027
+ var inside = (root, candidate) => {
25028
+ const path = relative4(resolve4(root), resolve4(candidate));
25029
+ return path === "" || !isAbsolute3(path) && path !== ".." && !path.startsWith(`..${sep3}`);
25030
+ };
25031
+ var requireString = (value, name) => {
25032
+ if (typeof value !== "string" || !value)
25033
+ throw new TypeError(`Android release ${name} is invalid.`);
25034
+ return value;
25035
+ };
25036
+ var parseMetadata = (value) => {
25037
+ if (!isRecord2(value))
25038
+ throw new TypeError("Android release metadata must contain an object.");
25039
+ const { bytes } = value;
25040
+ const { versionCode } = value;
25041
+ if (!Number.isSafeInteger(bytes) || Number(bytes) < 1)
25042
+ throw new TypeError("Android release bytes is invalid.");
25043
+ if (versionCode !== undefined && (!Number.isSafeInteger(versionCode) || Number(versionCode) < 1))
25044
+ throw new TypeError("Android release versionCode is invalid.");
25045
+ if (value.format !== 1 || value.platform !== "android" || value.type !== "aab" || value.engine !== "capacitor" && value.engine !== "expo" || typeof value.signed !== "boolean")
25046
+ throw new TypeError("Android release metadata contract is invalid.");
25047
+ const metadata = {
25048
+ appBuild: requireString(value.appBuild, "appBuild"),
25049
+ appId: requireString(value.appId, "appId"),
25050
+ artifact: requireString(value.artifact, "artifact"),
25051
+ bytes: Number(bytes),
25052
+ engine: value.engine,
25053
+ format: 1,
25054
+ platform: "android",
25055
+ releaseId: requireString(value.releaseId, "releaseId"),
25056
+ runtime: requireString(value.runtime, "runtime"),
25057
+ sha256: requireString(value.sha256, "sha256"),
25058
+ signed: value.signed,
25059
+ type: "aab",
25060
+ ...versionCode === undefined ? {} : { versionCode: Number(versionCode) }
25061
+ };
25062
+ if (!/^[a-f0-9]{64}$/u.test(metadata.sha256))
25063
+ throw new TypeError("Android release sha256 is invalid.");
25064
+ if (metadata.releaseId !== `amobile_android_${metadata.sha256}`)
25065
+ throw new TypeError("Android release ID does not match its artifact digest.");
25066
+ return metadata;
25067
+ };
25068
+ var absoluteBundletoolPath = (root = process.env.ABSOLUTE_BUNDLETOOL_ROOT ?? join6(homedir2(), ".absolutejs", "tools", "bundletool")) => join6(root, ABSOLUTE_BUNDLETOOL_VERSION, "bundletool.jar");
25069
+ var inspectAbsoluteBundletool = async (root) => {
25070
+ const path = absoluteBundletoolPath(root);
25071
+ if (!await exists2(path))
25072
+ return { path, ready: false };
25073
+ if (await sha256(path) !== ABSOLUTE_BUNDLETOOL_SHA256)
25074
+ throw new TypeError(`Managed Bundletool ${ABSOLUTE_BUNDLETOOL_VERSION} failed checksum verification. Remove ${path} and rerun the command.`);
25075
+ return { path, ready: true };
25076
+ };
25077
+ var readAbsoluteAndroidRelease = async (projectRoot, requested) => {
25078
+ const root = resolve4(projectRoot);
25079
+ const selected = resolve4(root, requested);
25080
+ if (!inside(root, selected))
25081
+ throw new TypeError("mobile test android --release must remain inside the project.");
25082
+ const metadataPath = basename(selected) === "release.json" ? selected : join6(selected, "release.json");
25083
+ const releaseRoot = dirname3(metadataPath);
25084
+ const metadata = parseMetadata(JSON.parse(await readFile6(metadataPath, "utf8")));
25085
+ const artifactPath = resolve4(releaseRoot, metadata.artifact);
25086
+ if (!inside(releaseRoot, artifactPath) || basename(artifactPath) !== metadata.artifact)
25087
+ throw new TypeError("Android release artifact path is invalid.");
25088
+ const [artifactStat, artifactSha256] = await Promise.all([
25089
+ stat2(artifactPath),
25090
+ sha256(artifactPath)
25091
+ ]);
25092
+ if (artifactStat.size !== metadata.bytes || artifactSha256 !== metadata.sha256)
25093
+ throw new TypeError(`Immutable Android release ${metadata.releaseId} is missing or modified.`);
25094
+ return { artifactPath, metadata, metadataPath, releaseRoot };
25095
+ };
25096
+ var defaultDownload = async (url) => {
25097
+ const response = await fetch(url);
25098
+ if (!response.ok)
25099
+ throw new Error(`Bundletool download failed (${response.status}).`);
25100
+ return new Uint8Array(await response.arrayBuffer());
25101
+ };
25102
+ var ensureAbsoluteBundletool = async (options) => {
25103
+ const inspected = await inspectAbsoluteBundletool(options.root);
25104
+ if (inspected.ready)
25105
+ return inspected.path;
25106
+ if (!options.approved)
25107
+ throw new TypeError(`Bundletool ${ABSOLUTE_BUNDLETOOL_VERSION} is required. Rerun with --yes to download the checksum-pinned official release.`);
25108
+ const bytes = await (options.download ?? defaultDownload)(ABSOLUTE_BUNDLETOOL_URL);
25109
+ const digest = createHash5("sha256").update(bytes).digest("hex");
25110
+ if (digest !== ABSOLUTE_BUNDLETOOL_SHA256)
25111
+ throw new TypeError("Downloaded Bundletool failed checksum verification.");
25112
+ await mkdir4(dirname3(inspected.path), { recursive: true });
25113
+ const staging = await mkdtemp3(join6(dirname3(inspected.path), ".install-"));
25114
+ const candidate = join6(staging, "bundletool.jar");
25115
+ try {
25116
+ await writeFile5(candidate, bytes, { flag: "wx" });
25117
+ await rename5(candidate, inspected.path).catch(async (error) => {
25118
+ if (await exists2(inspected.path))
25119
+ return;
25120
+ throw error;
25121
+ });
25122
+ } finally {
25123
+ await rm4(staging, { force: true, recursive: true });
25124
+ }
25125
+ if (await sha256(inspected.path) !== ABSOLUTE_BUNDLETOOL_SHA256)
25126
+ throw new TypeError("Installed Bundletool failed checksum verification.");
25127
+ return inspected.path;
25128
+ };
25129
+ var defaultRun = async (command) => {
25130
+ const process2 = Bun.spawn(command, {
25131
+ stderr: "pipe",
25132
+ stdin: "ignore",
25133
+ stdout: "pipe"
25134
+ });
25135
+ const [exitCode, stderr, stdout] = await Promise.all([
25136
+ process2.exited,
25137
+ new Response(process2.stderr).text(),
25138
+ new Response(process2.stdout).text()
25139
+ ]);
25140
+ return { exitCode, stderr, stdout };
25141
+ };
25142
+ var requireSuccess2 = async (run, command, label) => {
25143
+ const result = await run(command);
25144
+ if (result.exitCode !== 0)
25145
+ throw new Error(`${label} failed: ${result.stderr.trim() || result.stdout.trim()}`);
25146
+ return result;
25147
+ };
25148
+ var adb = (path, serial, ...args) => [
25149
+ path,
25150
+ "-s",
25151
+ serial,
25152
+ ...args
25153
+ ];
25154
+ var waitForMarker = async (run, adbPath, serial, appId, timeoutMs) => {
25155
+ const startedAt = performance.now();
25156
+ const inspect = async () => {
25157
+ if (performance.now() - startedAt >= timeoutMs)
25158
+ throw new Error("The installed release launched but its embedded web content did not become ready offline.");
25159
+ const [logs, process2] = await Promise.all([
25160
+ run(adb(adbPath, serial, "logcat", "-d", "-s", "AbsoluteJS:I", "*:S")),
25161
+ run(adb(adbPath, serial, "shell", "pidof", appId))
25162
+ ]);
25163
+ if (process2.exitCode !== 0 || !process2.stdout.trim())
25164
+ throw new Error("The installed Android release exited before becoming ready.");
25165
+ if (logs.stdout.includes(EMBEDDED_READY_MARKER))
25166
+ return;
25167
+ 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];
25168
+ if (failedPhase)
25169
+ throw new Error(`The installed release could not initialize its embedded ${failedPhase} runtime offline.`);
25170
+ await Bun.sleep(RELEASE_READY_POLL_MS);
25171
+ await inspect();
25172
+ };
25173
+ return inspect();
25174
+ };
25175
+ var launch = async (run, adbPath, serial, appId, launchUrl) => {
25176
+ const resolved = await requireSuccess2(run, adb(adbPath, serial, "shell", "cmd", "package", "resolve-activity", "--brief", appId), "Android launch activity discovery");
25177
+ const activity = resolved.stdout.split(/\r?\n/u).map((line) => line.trim()).findLast((line) => line.includes("/"));
25178
+ if (!activity)
25179
+ throw new Error(`Android could not resolve a launch activity for ${appId}.`);
25180
+ const startedAt = performance.now();
25181
+ await requireSuccess2(run, adb(adbPath, serial, "shell", "am", "start", "-W", "-n", activity, ...launchUrl ? ["-a", "android.intent.action.VIEW", "-d", launchUrl] : []), "Android release launch");
25182
+ return Math.round(performance.now() - startedAt);
25183
+ };
25184
+ var runAbsoluteAndroidReleaseAcceptance = async (options) => {
25185
+ if (options.release.metadata.engine !== "expo")
25186
+ throw new TypeError("Installed AAB release acceptance currently requires the Expo engine.");
25187
+ if (!options.serial.startsWith("emulator-"))
25188
+ throw new TypeError("Installed release acceptance changes network state and therefore requires an Android emulator.");
25189
+ const run = options.run ?? defaultRun;
25190
+ const startedAt = performance.now();
25191
+ await mkdir4(options.artifactDirectory, { recursive: true });
25192
+ const apksPath = join6(options.artifactDirectory, "release.apks");
25193
+ const windowsJava = (options.host ?? detectAbsoluteMobileHost()) === "wsl" && options.java.toLowerCase().endsWith(".exe");
25194
+ const toolPath = async (path) => {
25195
+ if (!windowsJava)
25196
+ return path;
25197
+ const converted = await requireSuccess2(run, ["wslpath", "-w", path], "Bundletool Windows path translation");
25198
+ const translated = converted.stdout.trim();
25199
+ if (!translated)
25200
+ throw new Error(`Bundletool could not translate ${basename(path)} for the Windows JDK.`);
25201
+ return translated;
25202
+ };
25203
+ const [bundletoolPath, artifactPath, outputPath, adbPath] = await Promise.all([
25204
+ toolPath(options.bundletool),
25205
+ toolPath(options.release.artifactPath),
25206
+ toolPath(apksPath),
25207
+ toolPath(options.adb)
25208
+ ]);
25209
+ await requireSuccess2(run, [
25210
+ options.java,
25211
+ "-jar",
25212
+ bundletoolPath,
25213
+ "build-apks",
25214
+ `--bundle=${artifactPath}`,
25215
+ `--output=${outputPath}`,
25216
+ "--mode=universal",
25217
+ "--overwrite"
25218
+ ], "Bundletool APK generation");
25219
+ const installStartedAt = performance.now();
25220
+ await requireSuccess2(run, [
25221
+ options.java,
25222
+ "-jar",
25223
+ bundletoolPath,
25224
+ "install-apks",
25225
+ `--apks=${outputPath}`,
25226
+ `--adb=${adbPath}`,
25227
+ `--device-id=${options.serial}`
25228
+ ], "Bundletool release installation");
25229
+ const installMs = Math.round(performance.now() - installStartedAt);
25230
+ const installed = await inspectAbsoluteAndroidInstalledApp(options.adb, options.serial, options.release.metadata.appId, run);
25231
+ if (options.release.metadata.versionCode !== undefined && installed.versionCode !== options.release.metadata.versionCode)
25232
+ throw new Error(`Installed Android versionCode ${installed.versionCode ?? "unknown"} does not match release ${options.release.metadata.versionCode}.`);
25233
+ await requireSuccess2(run, adb(options.adb, options.serial, "logcat", "-c"), "Android release log isolation");
25234
+ const [wifi, mobile] = await Promise.all([
25235
+ requireSuccess2(run, adb(options.adb, options.serial, "shell", "settings", "get", "global", "wifi_on"), "Android Wi-Fi state inspection"),
25236
+ requireSuccess2(run, adb(options.adb, options.serial, "shell", "settings", "get", "global", "mobile_data"), "Android mobile-data state inspection")
25237
+ ]);
25238
+ let launchMs;
25239
+ let relaunchMs;
25240
+ try {
25241
+ await Promise.all([
25242
+ requireSuccess2(run, adb(options.adb, options.serial, "shell", "svc", "wifi", "disable"), "Android Wi-Fi disable"),
25243
+ requireSuccess2(run, adb(options.adb, options.serial, "shell", "svc", "data", "disable"), "Android mobile-data disable")
25244
+ ]);
25245
+ await requireSuccess2(run, adb(options.adb, options.serial, "shell", "am", "force-stop", options.release.metadata.appId), "Android release stop");
25246
+ launchMs = await launch(run, options.adb, options.serial, options.release.metadata.appId, options.launchUrl);
25247
+ await waitForMarker(run, options.adb, options.serial, options.release.metadata.appId, RELEASE_READY_TIMEOUT_MS);
25248
+ await Bun.sleep(options.stabilityMs ?? RELEASE_STABILITY_MS);
25249
+ await requireSuccess2(run, adb(options.adb, options.serial, "shell", "am", "force-stop", options.release.metadata.appId), "Android release relaunch stop");
25250
+ await requireSuccess2(run, adb(options.adb, options.serial, "logcat", "-c"), "Android release relaunch log isolation");
25251
+ relaunchMs = await launch(run, options.adb, options.serial, options.release.metadata.appId, options.launchUrl);
25252
+ await waitForMarker(run, options.adb, options.serial, options.release.metadata.appId, RELEASE_READY_TIMEOUT_MS);
25253
+ } finally {
25254
+ await Promise.all([
25255
+ requireSuccess2(run, adb(options.adb, options.serial, "shell", "svc", "wifi", wifi.stdout.trim() === "1" ? "enable" : "disable"), "Android Wi-Fi restore"),
25256
+ requireSuccess2(run, adb(options.adb, options.serial, "shell", "svc", "data", mobile.stdout.trim() === "1" ? "enable" : "disable"), "Android mobile-data restore")
25257
+ ]);
25258
+ }
25259
+ return {
25260
+ apksBytes: await stat2(apksPath).then(({ size }) => size),
25261
+ artifactBytes: options.release.metadata.bytes,
25262
+ artifactSha256: options.release.metadata.sha256,
25263
+ durationMs: Math.round(performance.now() - startedAt),
25264
+ embeddedOffline: true,
25265
+ engine: options.release.metadata.engine,
25266
+ installed: {
25267
+ ...installed.versionCode === undefined ? {} : { versionCode: installed.versionCode },
25268
+ ...installed.versionName === undefined ? {} : { versionName: installed.versionName }
25269
+ },
25270
+ installMs,
25271
+ launchMs,
25272
+ relaunchMs,
25273
+ releaseId: options.release.metadata.releaseId,
25274
+ signed: options.release.metadata.signed,
25275
+ status: "pass"
25276
+ };
25277
+ };
24983
25278
  // src/mobile/iosRelease.ts
24984
- import { createHash as createHash5 } from "crypto";
25279
+ import { createHash as createHash6 } from "crypto";
24985
25280
  import {
24986
- access as access6,
25281
+ access as access7,
24987
25282
  copyFile as copyFile3,
24988
- mkdir as mkdir4,
24989
- mkdtemp as mkdtemp3,
25283
+ mkdir as mkdir5,
25284
+ mkdtemp as mkdtemp4,
24990
25285
  readdir as readdir3,
24991
- readFile as readFile6,
24992
- rename as rename5,
24993
- rm as rm4,
24994
- stat as stat2,
24995
- writeFile as writeFile5
25286
+ readFile as readFile7,
25287
+ rename as rename6,
25288
+ rm as rm5,
25289
+ stat as stat3,
25290
+ writeFile as writeFile6
24996
25291
  } from "fs/promises";
24997
- import { dirname as dirname3, isAbsolute as isAbsolute3, join as join6, relative as relative4, resolve as resolve4, sep as sep3 } from "path";
25292
+ import { dirname as dirname4, isAbsolute as isAbsolute4, join as join7, relative as relative5, resolve as resolve5, sep as sep4 } from "path";
24998
25293
  var ABSOLUTE_IOS_RELEASE_FORMAT = 1;
24999
25294
  var developmentTeamArgument = (value) => {
25000
25295
  if (value === undefined)
@@ -25004,9 +25299,9 @@ var developmentTeamArgument = (value) => {
25004
25299
  throw new TypeError("iOS development team must contain ten letters or digits.");
25005
25300
  return `DEVELOPMENT_TEAM=${team}`;
25006
25301
  };
25007
- var isRecord2 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
25302
+ var isRecord3 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
25008
25303
  var requireManifest2 = (value) => {
25009
- if (!isRecord2(value) || typeof value.appBuild !== "string" || typeof value.appId !== "string" || typeof value.runtime !== "string") {
25304
+ if (!isRecord3(value) || typeof value.appBuild !== "string" || typeof value.appId !== "string" || typeof value.runtime !== "string") {
25010
25305
  throw new TypeError("Invalid embedded AbsoluteJS mobile manifest.");
25011
25306
  }
25012
25307
  return {
@@ -25017,13 +25312,13 @@ var requireManifest2 = (value) => {
25017
25312
  };
25018
25313
  var pathExists4 = async (path) => {
25019
25314
  try {
25020
- await access6(path);
25315
+ await access7(path);
25021
25316
  return true;
25022
25317
  } catch {
25023
25318
  return false;
25024
25319
  }
25025
25320
  };
25026
- var defaultRun = async (command, options = {}) => {
25321
+ var defaultRun2 = async (command, options = {}) => {
25027
25322
  const process2 = Bun.spawn(command, {
25028
25323
  cwd: options.cwd,
25029
25324
  env: options.env,
@@ -25064,8 +25359,8 @@ var ignoredFingerprintDirectories = new Set([
25064
25359
  var fingerprintFiles = async (root, current = root, options = {}) => {
25065
25360
  const entries = await readdir3(current, { withFileTypes: true });
25066
25361
  const nested = await Promise.all(entries.sort((left, right) => left.name.localeCompare(right.name)).map(async (entry) => {
25067
- const path = join6(current, entry.name);
25068
- const projectRelative = relative4(root, path).replaceAll("\\", "/");
25362
+ const path = join7(current, entry.name);
25363
+ const projectRelative = relative5(root, path).replaceAll("\\", "/");
25069
25364
  const ignored = entry.isDirectory() && (ignoredFingerprintDirectories.has(entry.name) || projectRelative === "App/App/public" && options.includePublicBundle !== true);
25070
25365
  if (ignored)
25071
25366
  return [];
@@ -25076,11 +25371,11 @@ var fingerprintFiles = async (root, current = root, options = {}) => {
25076
25371
  return nested.flat();
25077
25372
  };
25078
25373
  var fingerprintAbsoluteIosNativeProject = async (nativeDirectory, options = {}) => {
25079
- const hasher = createHash5("sha256");
25374
+ const hasher = createHash6("sha256");
25080
25375
  const files = await fingerprintFiles(nativeDirectory, nativeDirectory, options);
25081
- const contents = await Promise.all(files.map((file) => readFile6(file)));
25376
+ const contents = await Promise.all(files.map((file) => readFile7(file)));
25082
25377
  files.forEach((file, index) => {
25083
- hasher.update(relative4(nativeDirectory, file).replaceAll("\\", "/"));
25378
+ hasher.update(relative5(nativeDirectory, file).replaceAll("\\", "/"));
25084
25379
  hasher.update("\x00");
25085
25380
  hasher.update(contents[index] ?? new Uint8Array);
25086
25381
  hasher.update("\x00");
@@ -25088,21 +25383,21 @@ var fingerprintAbsoluteIosNativeProject = async (nativeDirectory, options = {})
25088
25383
  return hasher.digest("hex");
25089
25384
  };
25090
25385
  var safeOutputDirectory2 = (projectRoot, requested) => {
25091
- const root = resolve4(projectRoot);
25092
- const output = resolve4(root, requested ?? ".absolutejs/mobile/releases/ios");
25093
- const projectRelative = relative4(root, output);
25094
- if (projectRelative === ".." || projectRelative.startsWith(`..${sep3}`) || isAbsolute3(projectRelative)) {
25386
+ const root = resolve5(projectRoot);
25387
+ const output = resolve5(root, requested ?? ".absolutejs/mobile/releases/ios");
25388
+ const projectRelative = relative5(root, output);
25389
+ if (projectRelative === ".." || projectRelative.startsWith(`..${sep4}`) || isAbsolute4(projectRelative)) {
25095
25390
  throw new TypeError("mobile build --outdir must remain inside the project.");
25096
25391
  }
25097
25392
  return output;
25098
25393
  };
25099
- var sha256File2 = async (path) => createHash5("sha256").update(await readFile6(path)).digest("hex");
25394
+ var sha256File2 = async (path) => createHash6("sha256").update(await readFile7(path)).digest("hex");
25100
25395
  var findByExtension = async (root, extension) => {
25101
25396
  if (!await pathExists4(root))
25102
25397
  return;
25103
25398
  const entries = await readdir3(root, { withFileTypes: true });
25104
25399
  const matches2 = await Promise.all(entries.map(async (entry) => {
25105
- const path = join6(root, entry.name);
25400
+ const path = join7(root, entry.name);
25106
25401
  if (entry.isDirectory() && entry.name.endsWith(extension))
25107
25402
  return path;
25108
25403
  if (entry.isFile() && entry.name.endsWith(extension))
@@ -25116,7 +25411,7 @@ var findAllByExtension = async (root, extension, options = {}) => {
25116
25411
  return [];
25117
25412
  const entries = await readdir3(root, { withFileTypes: true });
25118
25413
  const matches2 = await Promise.all(entries.map(async (entry) => {
25119
- const path = join6(root, entry.name);
25414
+ const path = join7(root, entry.name);
25120
25415
  if (entry.name.endsWith(extension))
25121
25416
  return [path];
25122
25417
  if (!entry.isDirectory() || options.excludedDirectories?.has(entry.name))
@@ -25126,17 +25421,17 @@ var findAllByExtension = async (root, extension, options = {}) => {
25126
25421
  return matches2.flat().sort();
25127
25422
  };
25128
25423
  var resolveAbsoluteIosXcodeProject = async (nativeDirectory, options = {}) => {
25129
- const requestedWorkspace = options.workspacePath ? resolve4(nativeDirectory, options.workspacePath) : undefined;
25424
+ const requestedWorkspace = options.workspacePath ? resolve5(nativeDirectory, options.workspacePath) : undefined;
25130
25425
  if (requestedWorkspace) {
25131
- const requestedRelative = relative4(nativeDirectory, requestedWorkspace);
25132
- if (requestedRelative === ".." || requestedRelative.startsWith(`..${sep3}`) || isAbsolute3(requestedRelative))
25426
+ const requestedRelative = relative5(nativeDirectory, requestedWorkspace);
25427
+ if (requestedRelative === ".." || requestedRelative.startsWith(`..${sep4}`) || isAbsolute4(requestedRelative))
25133
25428
  throw new TypeError("iOS release workspacePath must remain inside the native iOS project.");
25134
25429
  }
25135
25430
  const workspaces = requestedWorkspace ? [requestedWorkspace] : await findAllByExtension(nativeDirectory, ".xcworkspace", {
25136
25431
  excludedDirectories: new Set(["Pods", "DerivedData", "build"])
25137
25432
  });
25138
25433
  if (workspaces.length !== 1)
25139
- throw new TypeError(workspaces.length > 1 ? `iOS release found multiple Xcode workspaces: ${workspaces.map((path) => relative4(nativeDirectory, path)).join(", ")}. Pass an explicit workspacePath.` : "iOS release could not find an Xcode workspace.");
25434
+ throw new TypeError(workspaces.length > 1 ? `iOS release found multiple Xcode workspaces: ${workspaces.map((path) => relative5(nativeDirectory, path)).join(", ")}. Pass an explicit workspacePath.` : "iOS release could not find an Xcode workspace.");
25140
25435
  const [workspacePath] = workspaces;
25141
25436
  if (!workspacePath || !await pathExists4(workspacePath))
25142
25437
  throw new TypeError("iOS release could not find an Xcode workspace.");
@@ -25146,7 +25441,7 @@ var resolveAbsoluteIosXcodeProject = async (nativeDirectory, options = {}) => {
25146
25441
  excludedDirectories: new Set(["Pods", "DerivedData", "build"])
25147
25442
  });
25148
25443
  const schemes = [
25149
- ...new Set(schemeFiles.map((path) => path.slice(path.lastIndexOf(sep3) + 1, -".xcscheme".length)))
25444
+ ...new Set(schemeFiles.map((path) => path.slice(path.lastIndexOf(sep4) + 1, -".xcscheme".length)))
25150
25445
  ];
25151
25446
  if (schemes.length !== 1 || !schemes[0])
25152
25447
  throw new TypeError(schemes.length > 1 ? `iOS release found multiple shared Xcode schemes: ${schemes.join(", ")}. Pass an explicit scheme.` : "iOS release could not find a shared Xcode scheme.");
@@ -25169,7 +25464,7 @@ var requireBuildNumber = (value) => {
25169
25464
  return value;
25170
25465
  };
25171
25466
  var requireAbsoluteIosReleaseMetadata = (value) => {
25172
- if (!isRecord2(value) || value.artifact !== "App.ipa" || typeof value.appBuild !== "string" || typeof value.appId !== "string" || typeof value.bytes !== "number" || !Number.isSafeInteger(value.bytes) || value.bytes < 1 || value.engine !== "capacitor" && value.engine !== "expo" || value.format !== ABSOLUTE_IOS_RELEASE_FORMAT || typeof value.marketingVersion !== "string" || value.platform !== "ios" || typeof value.releaseId !== "string" || typeof value.runtime !== "string" || typeof value.sha256 !== "string" || typeof value.signed !== "boolean" || value.type !== "ipa" || value.buildNumber !== undefined && (typeof value.buildNumber !== "number" || !Number.isSafeInteger(value.buildNumber) || value.buildNumber < 1) || !/^amobile_ios_[a-f0-9]{64}$/u.test(value.releaseId) || !/^[a-f0-9]{64}$/u.test(value.sha256) || value.releaseId !== `amobile_ios_${value.sha256}`) {
25467
+ if (!isRecord3(value) || value.artifact !== "App.ipa" || typeof value.appBuild !== "string" || typeof value.appId !== "string" || typeof value.bytes !== "number" || !Number.isSafeInteger(value.bytes) || value.bytes < 1 || value.engine !== "capacitor" && value.engine !== "expo" || value.format !== ABSOLUTE_IOS_RELEASE_FORMAT || typeof value.marketingVersion !== "string" || value.platform !== "ios" || typeof value.releaseId !== "string" || typeof value.runtime !== "string" || typeof value.sha256 !== "string" || typeof value.signed !== "boolean" || value.type !== "ipa" || value.buildNumber !== undefined && (typeof value.buildNumber !== "number" || !Number.isSafeInteger(value.buildNumber) || value.buildNumber < 1) || !/^amobile_ios_[a-f0-9]{64}$/u.test(value.releaseId) || !/^[a-f0-9]{64}$/u.test(value.sha256) || value.releaseId !== `amobile_ios_${value.sha256}`) {
25173
25468
  throw new TypeError("Invalid AbsoluteJS iOS release metadata.");
25174
25469
  }
25175
25470
  return {
@@ -25190,18 +25485,18 @@ var requireAbsoluteIosReleaseMetadata = (value) => {
25190
25485
  };
25191
25486
  };
25192
25487
  var installRelease2 = async (artifactPath, metadata, outputRoot) => {
25193
- const releaseRoot = join6(outputRoot, metadata.releaseId);
25194
- const destination = join6(releaseRoot, "App.ipa");
25488
+ const releaseRoot = join7(outputRoot, metadata.releaseId);
25489
+ const destination = join7(releaseRoot, "App.ipa");
25195
25490
  if (await pathExists4(releaseRoot)) {
25196
- const value = JSON.parse(await readFile6(join6(releaseRoot, "release.json"), "utf8"));
25197
- if (!isRecord2(value) || value.artifact !== "App.ipa" || Object.entries(metadata).some(([key, expected]) => Reflect.get(value, key) !== expected)) {
25491
+ const value = JSON.parse(await readFile7(join7(releaseRoot, "release.json"), "utf8"));
25492
+ if (!isRecord3(value) || value.artifact !== "App.ipa" || Object.entries(metadata).some(([key, expected]) => Reflect.get(value, key) !== expected)) {
25198
25493
  throw new TypeError(`Immutable iOS release ${metadata.releaseId} does not match its content.`);
25199
25494
  }
25200
- const [bytes, sha256] = await Promise.all([
25201
- stat2(destination).then(({ size }) => size),
25495
+ const [bytes, sha2562] = await Promise.all([
25496
+ stat3(destination).then(({ size }) => size),
25202
25497
  sha256File2(destination)
25203
25498
  ]);
25204
- if (bytes !== metadata.bytes || sha256 !== metadata.sha256)
25499
+ if (bytes !== metadata.bytes || sha2562 !== metadata.sha256)
25205
25500
  throw new TypeError(`Immutable iOS release ${metadata.releaseId} artifact is missing or modified.`);
25206
25501
  return {
25207
25502
  artifactPath: destination,
@@ -25212,20 +25507,20 @@ var installRelease2 = async (artifactPath, metadata, outputRoot) => {
25212
25507
  releaseRoot
25213
25508
  };
25214
25509
  }
25215
- await mkdir4(dirname3(releaseRoot), { recursive: true });
25216
- const staging = await mkdtemp3(join6(dirname3(releaseRoot), ".ios-stage-"));
25510
+ await mkdir5(dirname4(releaseRoot), { recursive: true });
25511
+ const staging = await mkdtemp4(join7(dirname4(releaseRoot), ".ios-stage-"));
25217
25512
  try {
25218
- await copyFile3(artifactPath, join6(staging, "App.ipa"));
25513
+ await copyFile3(artifactPath, join7(staging, "App.ipa"));
25219
25514
  const complete = {
25220
25515
  ...metadata,
25221
25516
  artifact: "App.ipa"
25222
25517
  };
25223
- await writeFile5(join6(staging, "release.json"), `${JSON.stringify(complete, null, "\t")}
25518
+ await writeFile6(join7(staging, "release.json"), `${JSON.stringify(complete, null, "\t")}
25224
25519
  `, { flag: "wx" });
25225
- await rename5(staging, releaseRoot);
25520
+ await rename6(staging, releaseRoot);
25226
25521
  return { artifactPath: destination, metadata: complete, releaseRoot };
25227
25522
  } finally {
25228
- await rm4(staging, { force: true, recursive: true }).catch(() => {
25523
+ await rm5(staging, { force: true, recursive: true }).catch(() => {
25229
25524
  return;
25230
25525
  });
25231
25526
  }
@@ -25238,10 +25533,10 @@ var buildAbsoluteIosRelease = async (options) => {
25238
25533
  const marketingVersion = options.config.iosVersion;
25239
25534
  if (!marketingVersion)
25240
25535
  throw new TypeError("iOS release builds require mobile.ios.version in absolutejs.config.ts.");
25241
- const manifest = requireManifest2(JSON.parse(await readFile6(join6(options.config.bundleDirectory, "absolute-mobile-manifest.json"), "utf8")));
25536
+ const manifest = requireManifest2(JSON.parse(await readFile7(join7(options.config.bundleDirectory, "absolute-mobile-manifest.json"), "utf8")));
25242
25537
  if (manifest.appId !== options.config.appId)
25243
25538
  throw new TypeError("Embedded mobile manifest appId does not match mobile.appId.");
25244
- const nativeDirectory = join6(options.config.nativeProjectDirectory, "ios");
25539
+ const nativeDirectory = join7(options.config.nativeProjectDirectory, "ios");
25245
25540
  const xcode = await resolveAbsoluteIosXcodeProject(nativeDirectory, {
25246
25541
  scheme: options.scheme,
25247
25542
  workspacePath: options.workspacePath
@@ -25249,18 +25544,18 @@ var buildAbsoluteIosRelease = async (options) => {
25249
25544
  let buildNumber = requireBuildNumber(options.buildNumber);
25250
25545
  if (options.prepareBuildNumber) {
25251
25546
  const nativeFingerprint = await fingerprintAbsoluteIosNativeProject(nativeDirectory);
25252
- const buildIdentity = createHash5("sha256").update(`${manifest.appBuild}\x00${nativeFingerprint}\x00${marketingVersion}`).digest("hex");
25547
+ const buildIdentity = createHash6("sha256").update(`${manifest.appBuild}\x00${nativeFingerprint}\x00${marketingVersion}`).digest("hex");
25253
25548
  buildNumber = requireBuildNumber(await options.prepareBuildNumber(buildIdentity));
25254
25549
  }
25255
- const stagingParent = resolve4(options.projectRoot, ".absolutejs/mobile");
25256
- await mkdir4(stagingParent, { recursive: true });
25257
- const staging = await mkdtemp3(join6(stagingParent, ".ios-build-"));
25258
- const archivePath = join6(staging, "App.xcarchive");
25259
- const exportPath = join6(staging, "export");
25260
- const exportPlist = join6(staging, "ExportOptions.plist");
25261
- await mkdir4(exportPath, { recursive: true });
25262
- await writeFile5(exportPlist, exportOptions());
25263
- const run = options.run ?? defaultRun;
25550
+ const stagingParent = resolve5(options.projectRoot, ".absolutejs/mobile");
25551
+ await mkdir5(stagingParent, { recursive: true });
25552
+ const staging = await mkdtemp4(join7(stagingParent, ".ios-build-"));
25553
+ const archivePath = join7(staging, "App.xcarchive");
25554
+ const exportPath = join7(staging, "export");
25555
+ const exportPlist = join7(staging, "ExportOptions.plist");
25556
+ await mkdir5(exportPath, { recursive: true });
25557
+ await writeFile6(exportPlist, exportOptions());
25558
+ const run = options.run ?? defaultRun2;
25264
25559
  try {
25265
25560
  const developmentTeam = developmentTeamArgument(options.developmentTeam);
25266
25561
  const versionArguments = [
@@ -25285,7 +25580,7 @@ var buildAbsoluteIosRelease = async (options) => {
25285
25580
  ], { cwd: nativeDirectory, env: options.env });
25286
25581
  if (archiveExit !== 0)
25287
25582
  throw new TypeError("Xcode failed to archive the iOS app.");
25288
- const archivedApp = await findByExtension(join6(archivePath, "Products", "Applications"), ".app");
25583
+ const archivedApp = await findByExtension(join7(archivePath, "Products", "Applications"), ".app");
25289
25584
  const capture = options.capture ?? defaultCapture2;
25290
25585
  const signed = archivedApp ? capture([
25291
25586
  "codesign",
@@ -25311,11 +25606,11 @@ var buildAbsoluteIosRelease = async (options) => {
25311
25606
  const artifactPath = await findByExtension(exportPath, ".ipa");
25312
25607
  if (!artifactPath)
25313
25608
  throw new TypeError("Xcode did not produce an exported IPA.");
25314
- const [bytes, sha256] = await Promise.all([
25315
- stat2(artifactPath).then(({ size }) => size),
25609
+ const [bytes, sha2562] = await Promise.all([
25610
+ stat3(artifactPath).then(({ size }) => size),
25316
25611
  sha256File2(artifactPath)
25317
25612
  ]);
25318
- const releaseId = `amobile_ios_${sha256}`;
25613
+ const releaseId = `amobile_ios_${sha2562}`;
25319
25614
  return await installRelease2(artifactPath, {
25320
25615
  appBuild: manifest.appBuild,
25321
25616
  appId: manifest.appId,
@@ -25327,23 +25622,23 @@ var buildAbsoluteIosRelease = async (options) => {
25327
25622
  platform: "ios",
25328
25623
  releaseId,
25329
25624
  runtime: manifest.runtime,
25330
- sha256,
25625
+ sha256: sha2562,
25331
25626
  signed,
25332
25627
  type: "ipa"
25333
25628
  }, safeOutputDirectory2(options.projectRoot, options.outputDirectory));
25334
25629
  } finally {
25335
- await rm4(staging, { force: true, recursive: true }).catch(() => {
25630
+ await rm5(staging, { force: true, recursive: true }).catch(() => {
25336
25631
  return;
25337
25632
  });
25338
25633
  }
25339
25634
  };
25340
25635
  var installAbsoluteIosRelease = async (options) => {
25341
25636
  const metadata = requireAbsoluteIosReleaseMetadata(options.metadata);
25342
- const [bytes, sha256] = await Promise.all([
25343
- stat2(options.artifactPath).then(({ size }) => size),
25637
+ const [bytes, sha2562] = await Promise.all([
25638
+ stat3(options.artifactPath).then(({ size }) => size),
25344
25639
  sha256File2(options.artifactPath)
25345
25640
  ]);
25346
- if (bytes !== metadata.bytes || sha256 !== metadata.sha256)
25641
+ if (bytes !== metadata.bytes || sha2562 !== metadata.sha256)
25347
25642
  throw new TypeError("Remote iOS release artifact does not match its signed metadata.");
25348
25643
  const { artifact: _artifact, ...releaseMetadata } = metadata;
25349
25644
  return installRelease2(options.artifactPath, releaseMetadata, safeOutputDirectory2(options.projectRoot, options.outputDirectory));
@@ -25419,7 +25714,7 @@ var assertAbsoluteIosInstalledAppUpgrade = (before, after) => {
25419
25714
  throw new Error(`iOS CFBundleVersion did not increase (${before.buildNumber} -> ${after.buildNumber}).`);
25420
25715
  };
25421
25716
  // src/mobile/iosConformance.ts
25422
- import { readFile as readFile7, stat as stat3 } from "fs/promises";
25717
+ import { readFile as readFile8, stat as stat4 } from "fs/promises";
25423
25718
  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");
25424
25719
  var parseAbsoluteIosHmrLog = (line) => {
25425
25720
  const match = HMR_LINE.exec(line);
@@ -25451,13 +25746,13 @@ var waitForAbsoluteIosHmrLog = async (options) => {
25451
25746
  const sleep = options.sleep ?? Bun.sleep;
25452
25747
  const timeoutMs = options.timeoutMs ?? 30000;
25453
25748
  const deadline = Date.now() + timeoutMs;
25454
- let offset = options.startOffset ?? await stat3(options.logPath).then(({ size }) => size).catch(() => 0);
25749
+ let offset = options.startOffset ?? await stat4(options.logPath).then(({ size }) => size).catch(() => 0);
25455
25750
  let buffered = "";
25456
25751
  const poll = async () => {
25457
25752
  if (Date.now() > deadline)
25458
25753
  throw new Error(`No iOS native HMR acknowledgement was observed within ${timeoutMs}ms.`);
25459
25754
  options.signal?.throwIfAborted();
25460
- const contents = await readFile7(options.logPath).catch(() => Buffer.alloc(0));
25755
+ const contents = await readFile8(options.logPath).catch(() => Buffer.alloc(0));
25461
25756
  if (contents.byteLength < offset) {
25462
25757
  offset = 0;
25463
25758
  buffered = "";
@@ -25477,28 +25772,28 @@ var waitForAbsoluteIosHmrLog = async (options) => {
25477
25772
  return poll();
25478
25773
  };
25479
25774
  // src/mobile/iosSimulatorController.ts
25480
- import { createHash as createHash6, randomUUID as randomUUID3 } from "crypto";
25775
+ import { createHash as createHash7, randomUUID as randomUUID3 } from "crypto";
25481
25776
  import {
25482
- access as access7,
25777
+ access as access8,
25483
25778
  copyFile as copyFile4,
25484
- mkdir as mkdir5,
25485
- readFile as readFile8,
25486
- rename as rename6,
25487
- rm as rm5,
25488
- writeFile as writeFile6
25779
+ mkdir as mkdir6,
25780
+ readFile as readFile9,
25781
+ rename as rename7,
25782
+ rm as rm6,
25783
+ writeFile as writeFile7
25489
25784
  } from "fs/promises";
25490
25785
  import { isIP as isIP2 } from "net";
25491
- import { dirname as dirname4, isAbsolute as isAbsolute4, join as join7, relative as relative5, resolve as resolve5, sep as sep4 } from "path";
25786
+ import { dirname as dirname5, isAbsolute as isAbsolute5, join as join8, relative as relative6, resolve as resolve6, sep as sep5 } from "path";
25492
25787
  init_getDurationString();
25493
25788
  var ABSOLUTE_IOS_SIMULATOR_NAME = "AbsoluteJS iPhone";
25494
25789
  var BOOT_TIMEOUT_MS = 180000;
25495
25790
  var BOOT_POLL_MS = 1000;
25496
25791
  var DEV_JOURNAL_FORMAT = 1;
25497
25792
  var NATIVE_CACHE_FORMAT = 1;
25498
- var isRecord3 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
25793
+ var isRecord4 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
25499
25794
  var pathExists5 = async (path) => {
25500
25795
  try {
25501
- await access7(path);
25796
+ await access8(path);
25502
25797
  return true;
25503
25798
  } catch {
25504
25799
  return false;
@@ -25527,7 +25822,7 @@ var defaultCapture3 = (command, options = {}) => {
25527
25822
  };
25528
25823
  }
25529
25824
  };
25530
- var defaultRun2 = async (command, options = {}) => {
25825
+ var defaultRun3 = async (command, options = {}) => {
25531
25826
  const process2 = Bun.spawn(command, {
25532
25827
  cwd: options.cwd,
25533
25828
  env: options.env,
@@ -25593,7 +25888,7 @@ var defaultStartNativeLogs = (command, options, onLine) => {
25593
25888
  }
25594
25889
  };
25595
25890
  };
25596
- var requireSuccess2 = async (command, label, run, options) => {
25891
+ var requireSuccess3 = async (command, label, run, options) => {
25597
25892
  const exitCode = await run(command, options);
25598
25893
  if (exitCode !== 0)
25599
25894
  throw new Error(`${label} failed with status ${exitCode}.`);
@@ -25604,7 +25899,7 @@ var trustIosSimulatorDevelopmentCa = async (options, udid, run, log) => {
25604
25899
  if (!options.certificateAuthorityPath) {
25605
25900
  throw new Error("iOS Simulator HTTPS requires the AbsoluteJS development CA certificate.");
25606
25901
  }
25607
- await requireSuccess2([
25902
+ await requireSuccess3([
25608
25903
  options.project.xcrun,
25609
25904
  "simctl",
25610
25905
  "keychain",
@@ -25641,7 +25936,7 @@ var requireCapturedSuccess = (result, label) => {
25641
25936
  var parseJson = (source, label) => {
25642
25937
  try {
25643
25938
  const parsed = JSON.parse(source);
25644
- if (isRecord3(parsed))
25939
+ if (isRecord4(parsed))
25645
25940
  return parsed;
25646
25941
  } catch {}
25647
25942
  throw new Error(`Invalid ${label} JSON from simctl.`);
@@ -25652,7 +25947,7 @@ var parseIosDeviceTypes = (source) => {
25652
25947
  if (!Array.isArray(types))
25653
25948
  return [];
25654
25949
  return types.flatMap((type) => {
25655
- if (!isRecord3(type))
25950
+ if (!isRecord4(type))
25656
25951
  return [];
25657
25952
  const { identifier } = type;
25658
25953
  const { name } = type;
@@ -25665,7 +25960,7 @@ var parseIosRuntimes = (source) => {
25665
25960
  if (!Array.isArray(runtimes))
25666
25961
  return [];
25667
25962
  return runtimes.flatMap((runtime) => {
25668
- if (!isRecord3(runtime))
25963
+ if (!isRecord4(runtime))
25669
25964
  return [];
25670
25965
  const { identifier } = runtime;
25671
25966
  const { name } = runtime;
@@ -25685,13 +25980,13 @@ var parseIosRuntimes = (source) => {
25685
25980
  var parseIosSimulators = (source) => {
25686
25981
  const parsed = parseJson(source, "device");
25687
25982
  const { devices } = parsed;
25688
- if (!isRecord3(devices))
25983
+ if (!isRecord4(devices))
25689
25984
  return [];
25690
25985
  return Object.entries(devices).flatMap(([runtime, values]) => {
25691
25986
  if (!Array.isArray(values))
25692
25987
  return [];
25693
25988
  return values.flatMap((device) => {
25694
- if (!isRecord3(device))
25989
+ if (!isRecord4(device))
25695
25990
  return [];
25696
25991
  const { name } = device;
25697
25992
  const { state } = device;
@@ -25733,21 +26028,21 @@ var preferredIphoneType = (types) => types.filter((type) => type.name.startsWith
25733
26028
  return rightPro - leftPro;
25734
26029
  })[0];
25735
26030
  var journalPaths = (projectRoot) => {
25736
- const root = join7(projectRoot, ".absolutejs", "mobile", "ios-dev-session");
26031
+ const root = join8(projectRoot, ".absolutejs", "mobile", "ios-dev-session");
25737
26032
  return {
25738
- configBackup: join7(root, "capacitor-config.backup"),
25739
- infoBackup: join7(root, "Info.plist.backup"),
25740
- journal: join7(root, "journal.json"),
26033
+ configBackup: join8(root, "capacitor-config.backup"),
26034
+ infoBackup: join8(root, "Info.plist.backup"),
26035
+ journal: join8(root, "journal.json"),
25741
26036
  root
25742
26037
  };
25743
26038
  };
25744
- var nativeCachePath = (projectRoot) => join7(projectRoot, ".absolutejs", "mobile", "ios-native-cache.json");
26039
+ var nativeCachePath = (projectRoot) => join8(projectRoot, ".absolutejs", "mobile", "ios-native-cache.json");
25745
26040
  var isInside = (root, path) => {
25746
- const value = relative5(resolve5(root), resolve5(path));
25747
- return value === "" || !value.startsWith(`..${sep4}`) && value !== ".." && !isAbsolute4(value);
26041
+ const value = relative6(resolve6(root), resolve6(path));
26042
+ return value === "" || !value.startsWith(`..${sep5}`) && value !== ".." && !isAbsolute5(value);
25748
26043
  };
25749
26044
  var parseJournal = (value) => {
25750
- if (!isRecord3(value) || value.format !== DEV_JOURNAL_FORMAT)
26045
+ if (!isRecord4(value) || value.format !== DEV_JOURNAL_FORMAT)
25751
26046
  return null;
25752
26047
  const { configBackupPath } = value;
25753
26048
  const { infoBackupPath } = value;
@@ -25766,10 +26061,10 @@ var parseJournal = (value) => {
25766
26061
  var repairAbsoluteIosDevSession = async (projectRoot) => {
25767
26062
  const paths = journalPaths(projectRoot);
25768
26063
  if (!await pathExists5(paths.journal)) {
25769
- await rm5(paths.root, { force: true, recursive: true });
26064
+ await rm6(paths.root, { force: true, recursive: true });
25770
26065
  return false;
25771
26066
  }
25772
- const journal = await readFile8(paths.journal, "utf8").then((source) => parseJournal(JSON.parse(source))).catch(() => null);
26067
+ const journal = await readFile9(paths.journal, "utf8").then((source) => parseJournal(JSON.parse(source))).catch(() => null);
25773
26068
  if (!journal || !isInside(projectRoot, journal.nativeConfigPath) || !isInside(projectRoot, journal.infoPath) || !isInside(paths.root, journal.configBackupPath) || !isInside(paths.root, journal.infoBackupPath)) {
25774
26069
  throw new Error(`Refusing unsafe or invalid iOS dev journal at ${paths.journal}.`);
25775
26070
  }
@@ -25777,7 +26072,7 @@ var repairAbsoluteIosDevSession = async (projectRoot) => {
25777
26072
  await copyFile4(journal.configBackupPath, journal.nativeConfigPath);
25778
26073
  if (await pathExists5(journal.infoBackupPath))
25779
26074
  await copyFile4(journal.infoBackupPath, journal.infoPath);
25780
- await rm5(paths.root, { force: true, recursive: true });
26075
+ await rm6(paths.root, { force: true, recursive: true });
25781
26076
  return true;
25782
26077
  };
25783
26078
  var iosDevelopmentInfoPlist = (source, cleartext) => {
@@ -25803,19 +26098,19 @@ var iosDevelopmentInfoPlist = (source, cleartext) => {
25803
26098
  var writeDevProjection = async (project, port, https, serverHost = "localhost") => {
25804
26099
  const paths = journalPaths(project.projectRoot);
25805
26100
  await repairAbsoluteIosDevSession(project.projectRoot);
25806
- const nativeConfigPath = join7(project.nativeDirectory, "App", "App", "capacitor.config.json");
25807
- const infoPath = join7(project.nativeDirectory, "App", "App", "Info.plist");
26101
+ const nativeConfigPath = join8(project.nativeDirectory, "App", "App", "capacitor.config.json");
26102
+ const infoPath = join8(project.nativeDirectory, "App", "App", "Info.plist");
25808
26103
  const [configSource, infoSource] = await Promise.all([
25809
- readFile8(nativeConfigPath, "utf8"),
25810
- readFile8(infoPath, "utf8")
26104
+ readFile9(nativeConfigPath, "utf8"),
26105
+ readFile9(infoPath, "utf8")
25811
26106
  ]);
25812
26107
  const parsed = JSON.parse(configSource);
25813
- if (!isRecord3(parsed))
26108
+ if (!isRecord4(parsed))
25814
26109
  throw new Error(`Invalid Capacitor native config at ${nativeConfigPath}.`);
25815
- await mkdir5(paths.root, { recursive: true });
26110
+ await mkdir6(paths.root, { recursive: true });
25816
26111
  await Promise.all([
25817
- writeFile6(paths.configBackup, configSource, { flag: "wx" }),
25818
- writeFile6(paths.infoBackup, infoSource, { flag: "wx" })
26112
+ writeFile7(paths.configBackup, configSource, { flag: "wx" }),
26113
+ writeFile7(paths.infoBackup, infoSource, { flag: "wx" })
25819
26114
  ]);
25820
26115
  const journal = {
25821
26116
  configBackupPath: paths.configBackup,
@@ -25824,7 +26119,7 @@ var writeDevProjection = async (project, port, https, serverHost = "localhost")
25824
26119
  infoPath,
25825
26120
  nativeConfigPath
25826
26121
  };
25827
- await writeFile6(paths.journal, `${JSON.stringify(journal, null, "\t")}
26122
+ await writeFile7(paths.journal, `${JSON.stringify(journal, null, "\t")}
25828
26123
  `, {
25829
26124
  flag: "wx"
25830
26125
  });
@@ -25833,21 +26128,21 @@ var writeDevProjection = async (project, port, https, serverHost = "localhost")
25833
26128
  developmentUrl.searchParams.set("__absolute_target", "capacitor-ios");
25834
26129
  const existingServer = parsed.server;
25835
26130
  parsed.server = {
25836
- ...isRecord3(existingServer) ? existingServer : {},
26131
+ ...isRecord4(existingServer) ? existingServer : {},
25837
26132
  cleartext: !https,
25838
26133
  url: developmentUrl.href
25839
26134
  };
25840
26135
  await Promise.all([
25841
- writeFile6(nativeConfigPath, `${JSON.stringify(parsed, null, "\t")}
26136
+ writeFile7(nativeConfigPath, `${JSON.stringify(parsed, null, "\t")}
25842
26137
  `),
25843
- writeFile6(infoPath, iosDevelopmentInfoPlist(infoSource, !https))
26138
+ writeFile7(infoPath, iosDevelopmentInfoPlist(infoSource, !https))
25844
26139
  ]);
25845
26140
  };
25846
26141
  var parseNativeCache = (value) => {
25847
- if (!isRecord3(value))
26142
+ if (!isRecord4(value))
25848
26143
  return null;
25849
26144
  const { appId, fingerprint, format, installations } = value;
25850
- if (format !== NATIVE_CACHE_FORMAT || typeof appId !== "string" || typeof fingerprint !== "string" || !isRecord3(installations) || !Object.values(installations).every((identity) => typeof identity === "string"))
26145
+ if (format !== NATIVE_CACHE_FORMAT || typeof appId !== "string" || typeof fingerprint !== "string" || !isRecord4(installations) || !Object.values(installations).every((identity) => typeof identity === "string"))
25851
26146
  return null;
25852
26147
  return {
25853
26148
  appId,
@@ -25859,19 +26154,19 @@ var parseNativeCache = (value) => {
25859
26154
  ]))
25860
26155
  };
25861
26156
  };
25862
- var readNativeCache = (projectRoot) => readFile8(nativeCachePath(projectRoot), "utf8").then((source) => parseNativeCache(JSON.parse(source))).catch(() => null);
26157
+ var readNativeCache = (projectRoot) => readFile9(nativeCachePath(projectRoot), "utf8").then((source) => parseNativeCache(JSON.parse(source))).catch(() => null);
25863
26158
  var writeNativeCache = async (projectRoot, cache) => {
25864
26159
  const destination = nativeCachePath(projectRoot);
25865
26160
  const temporary = `${destination}.${process.pid}.${randomUUID3()}.tmp`;
25866
- await mkdir5(dirname4(destination), { recursive: true });
26161
+ await mkdir6(dirname5(destination), { recursive: true });
25867
26162
  try {
25868
- await writeFile6(temporary, `${JSON.stringify(cache, null, "\t")}
26163
+ await writeFile7(temporary, `${JSON.stringify(cache, null, "\t")}
25869
26164
  `, {
25870
26165
  flag: "wx"
25871
26166
  });
25872
- await rename6(temporary, destination);
26167
+ await rename7(temporary, destination);
25873
26168
  } finally {
25874
- await rm5(temporary, { force: true }).catch(() => {
26169
+ await rm6(temporary, { force: true }).catch(() => {
25875
26170
  return;
25876
26171
  });
25877
26172
  }
@@ -25977,12 +26272,12 @@ var physicalIosAppIsInstalled = (project, identifier, capture) => {
25977
26272
  return result.exitCode === 0 && result.stdout.includes(project.config.appId);
25978
26273
  };
25979
26274
  var buildIosDebugApp = async (project, udid, fingerprint, run, signal) => {
25980
- const derivedDataPath = join7(project.projectRoot, ".absolutejs", "mobile", "ios-derived-data", createHash6("sha256").update(project.config.appId).digest("hex").slice(0, 16));
25981
- await mkdir5(derivedDataPath, { recursive: true });
25982
- await requireSuccess2([
26275
+ const derivedDataPath = join8(project.projectRoot, ".absolutejs", "mobile", "ios-derived-data", createHash7("sha256").update(project.config.appId).digest("hex").slice(0, 16));
26276
+ await mkdir6(derivedDataPath, { recursive: true });
26277
+ await requireSuccess3([
25983
26278
  project.xcodebuild,
25984
26279
  "-workspace",
25985
- join7(project.nativeDirectory, "App", "App.xcworkspace"),
26280
+ join8(project.nativeDirectory, "App", "App.xcworkspace"),
25986
26281
  "-scheme",
25987
26282
  "App",
25988
26283
  "-configuration",
@@ -25993,18 +26288,18 @@ var buildIosDebugApp = async (project, udid, fingerprint, run, signal) => {
25993
26288
  derivedDataPath,
25994
26289
  "build"
25995
26290
  ], "iOS simulator build", run, { cwd: project.nativeDirectory, signal });
25996
- const appPath = join7(derivedDataPath, "Build", "Products", "Debug-iphonesimulator", "App.app");
26291
+ const appPath = join8(derivedDataPath, "Build", "Products", "Debug-iphonesimulator", "App.app");
25997
26292
  if (!await pathExists5(appPath))
25998
26293
  throw new Error(`Xcode did not produce the simulator app at ${appPath}.`);
25999
26294
  return appPath;
26000
26295
  };
26001
26296
  var buildPhysicalIosDebugApp = async (project, identifier, run, signal) => {
26002
- const derivedDataPath = join7(project.projectRoot, ".absolutejs", "mobile", "ios-derived-data", createHash6("sha256").update(project.config.appId).digest("hex").slice(0, 16));
26003
- await mkdir5(derivedDataPath, { recursive: true });
26004
- await requireSuccess2([
26297
+ const derivedDataPath = join8(project.projectRoot, ".absolutejs", "mobile", "ios-derived-data", createHash7("sha256").update(project.config.appId).digest("hex").slice(0, 16));
26298
+ await mkdir6(derivedDataPath, { recursive: true });
26299
+ await requireSuccess3([
26005
26300
  project.xcodebuild,
26006
26301
  "-workspace",
26007
- join7(project.nativeDirectory, "App", "App.xcworkspace"),
26302
+ join8(project.nativeDirectory, "App", "App.xcworkspace"),
26008
26303
  "-scheme",
26009
26304
  "App",
26010
26305
  "-configuration",
@@ -26016,7 +26311,7 @@ var buildPhysicalIosDebugApp = async (project, identifier, run, signal) => {
26016
26311
  "-allowProvisioningUpdates",
26017
26312
  "build"
26018
26313
  ], "iOS physical-device build (configure automatic signing and a Development Team in Xcode if this is the first run)", run, { cwd: project.nativeDirectory, signal });
26019
- const appPath = join7(derivedDataPath, "Build", "Products", "Debug-iphoneos", "App.app");
26314
+ const appPath = join8(derivedDataPath, "Build", "Products", "Debug-iphoneos", "App.app");
26020
26315
  if (!await pathExists5(appPath))
26021
26316
  throw new Error(`Xcode did not produce the physical-device app at ${appPath}.`);
26022
26317
  return appPath;
@@ -26032,7 +26327,7 @@ var ensurePhysicalIosDebugApp = async (options) => {
26032
26327
  const appPath = await buildPhysicalIosDebugApp(options.project, options.identifier, options.run, options.signal);
26033
26328
  throwIfAborted2(options.signal);
26034
26329
  options.transition("installing");
26035
- await requireSuccess2([
26330
+ await requireSuccess3([
26036
26331
  options.project.xcrun,
26037
26332
  "devicectl",
26038
26333
  "device",
@@ -26065,7 +26360,7 @@ var ensureIosDebugApp = async (options) => {
26065
26360
  const appPath = await buildIosDebugApp(options.project, options.udid, options.fingerprint, options.run, options.signal);
26066
26361
  throwIfAborted2(options.signal);
26067
26362
  options.transition("installing");
26068
- await requireSuccess2([options.project.xcrun, "simctl", "install", options.udid, appPath], "iOS simulator app installation", options.run, { signal: options.signal });
26363
+ await requireSuccess3([options.project.xcrun, "simctl", "install", options.udid, appPath], "iOS simulator app installation", options.run, { signal: options.signal });
26069
26364
  const updated = installedAppIdentity(options.project, options.udid, options.capture);
26070
26365
  if (updated) {
26071
26366
  await writeNativeCache(options.project.projectRoot, {
@@ -26151,7 +26446,7 @@ var prepareAbsoluteIosDevProject = async (config, options) => {
26151
26446
  if (detectAbsoluteMobileHost() !== "macos")
26152
26447
  throw new Error("iOS development requires macOS and Xcode.");
26153
26448
  const target = options.target ?? "simulator";
26154
- const projectRoot = resolve5(options.projectRoot);
26449
+ const projectRoot = resolve6(options.projectRoot);
26155
26450
  const checks = await inspectAbsoluteMobileToolchain({ host: "macos" });
26156
26451
  const failed = checks.filter((check) => check.platform === "ios" && !(target === "device" && check.id === "ios.runtime") && (check.status === "fail" || check.status === "warn"));
26157
26452
  if (failed.length > 0)
@@ -26160,20 +26455,20 @@ var prepareAbsoluteIosDevProject = async (config, options) => {
26160
26455
  const xcodebuild = checks.find((check) => check.id === "ios.xcodebuild")?.path;
26161
26456
  if (!xcrun || !xcodebuild)
26162
26457
  throw new Error("Xcode tools disappeared after readiness checks.");
26163
- const cap = join7(projectRoot, "node_modules", ".bin", "cap");
26458
+ const cap = join8(projectRoot, "node_modules", ".bin", "cap");
26164
26459
  if (!await pathExists5(cap))
26165
26460
  throw new Error("Capacitor CLI is not installed. Run absolute mobile init first.");
26166
26461
  await writeAbsoluteCapacitorConfig(config, { projectRoot });
26167
- await mkdir5(config.bundleDirectory, { recursive: true });
26168
- const placeholder = join7(config.bundleDirectory, "index.html");
26462
+ await mkdir6(config.bundleDirectory, { recursive: true });
26463
+ const placeholder = join8(config.bundleDirectory, "index.html");
26169
26464
  if (!await pathExists5(placeholder))
26170
- await writeFile6(placeholder, `<!doctype html><title>AbsoluteJS mobile development</title>
26465
+ await writeFile7(placeholder, `<!doctype html><title>AbsoluteJS mobile development</title>
26171
26466
  `);
26172
- const nativeDirectory = join7(config.nativeProjectDirectory, "ios");
26467
+ const nativeDirectory = join8(config.nativeProjectDirectory, "ios");
26173
26468
  if (!await pathExists5(nativeDirectory)) {
26174
26469
  if (!options.createNativeProject)
26175
26470
  throw new Error("iOS native project has not been created.");
26176
- const run = options.run ?? defaultRun2;
26471
+ const run = options.run ?? defaultRun3;
26177
26472
  if (await run([cap, "add", "ios"], { cwd: projectRoot }) !== 0)
26178
26473
  throw new Error("Capacitor iOS project creation failed.");
26179
26474
  }
@@ -26226,7 +26521,7 @@ var prepareIosSimulatorTarget = async (options) => {
26226
26521
  ]);
26227
26522
  options.transition("connecting");
26228
26523
  await waitForBootedSimulator(options.project, device.udid, options.capture, options.sleep, options.startOptions.signal);
26229
- await requireSuccess2([options.project.xcrun, "simctl", "bootstatus", device.udid, "-b"], "iOS simulator boot readiness", options.run, { signal: options.startOptions.signal });
26524
+ await requireSuccess3([options.project.xcrun, "simctl", "bootstatus", device.udid, "-b"], "iOS simulator boot readiness", options.run, { signal: options.startOptions.signal });
26230
26525
  await trustIosSimulatorDevelopmentCa(options.startOptions, device.udid, options.run, options.log);
26231
26526
  return { caEnrollmentServer: null, startedSimulator, udid: device.udid };
26232
26527
  };
@@ -26236,7 +26531,7 @@ var startAbsoluteIosDevSession = async (options) => {
26236
26531
  const targetKind = deviceIdentifier ? "device" : "simulator";
26237
26532
  const serverHost = deviceIdentifier ? normalizeAbsoluteIosDeviceHost(options.serverHost ?? "") : "localhost";
26238
26533
  const capture = options.capture ?? defaultCapture3;
26239
- const run = options.run ?? defaultRun2;
26534
+ const run = options.run ?? defaultRun3;
26240
26535
  const sleep = options.sleep ?? Bun.sleep;
26241
26536
  const spawn2 = options.spawn ?? defaultSpawn;
26242
26537
  const log = options.log ?? console.log;
@@ -26276,13 +26571,13 @@ var startAbsoluteIosDevSession = async (options) => {
26276
26571
  nativeLogs = attachNativeLogs(project, udid, options);
26277
26572
  return;
26278
26573
  }
26279
- await requireSuccess2(iosLaunchCommand(project, udid, deviceIdentifier !== undefined), "iOS app relaunch", run, { signal: options.signal });
26574
+ await requireSuccess3(iosLaunchCommand(project, udid, deviceIdentifier !== undefined), "iOS app relaunch", run, { signal: options.signal });
26280
26575
  };
26281
26576
  try {
26282
26577
  await repairAbsoluteIosDevSession(project.projectRoot);
26283
26578
  throwIfAborted2(options.signal);
26284
26579
  transition("syncing");
26285
- await requireSuccess2([project.cap, "sync", "ios"], "Capacitor iOS synchronization", run, { cwd: project.projectRoot, signal: options.signal });
26580
+ await requireSuccess3([project.cap, "sync", "ios"], "Capacitor iOS synchronization", run, { cwd: project.projectRoot, signal: options.signal });
26286
26581
  transition("configuring");
26287
26582
  if (options.embeddedBundle !== true)
26288
26583
  await writeDevProjection(project, options.port, options.https === true, serverHost);
@@ -26348,7 +26643,7 @@ var startAbsoluteIosDevSession = async (options) => {
26348
26643
  nativeLogs = attachNativeLogs(project, udid, options);
26349
26644
  transition("launching");
26350
26645
  if (!deviceIdentifier || !nativeLogs)
26351
- await requireSuccess2(iosLaunchCommand(project, udid, deviceIdentifier !== undefined), "iOS app launch", run, { signal: options.signal });
26646
+ await requireSuccess3(iosLaunchCommand(project, udid, deviceIdentifier !== undefined), "iOS app launch", run, { signal: options.signal });
26352
26647
  transition("ready");
26353
26648
  timings.total = performance.now() - startedAt;
26354
26649
  log(options.embeddedBundle === true ? `iOS ${targetKind} connected with the embedded bundle and backend on port ${options.port} in ${getDurationString(timings.total)} (${nativeCacheHit ? "native cache hit" : "native build installed"}).` : `iOS ${targetKind} connected with HMR on port ${options.port} in ${getDurationString(timings.total)} (${nativeCacheHit ? "native cache hit" : "native build installed"}).`);
@@ -26397,11 +26692,11 @@ var startAbsoluteIosDevSession = async (options) => {
26397
26692
  screenshot: async (destination) => {
26398
26693
  if (deviceIdentifier)
26399
26694
  throw new Error("Physical iOS screenshots are captured in Xcode Device Hub; the CLI never records a device screen automatically.");
26400
- const resolved = resolve5(project.projectRoot, destination);
26695
+ const resolved = resolve6(project.projectRoot, destination);
26401
26696
  if (!isInside(project.projectRoot, resolved))
26402
26697
  throw new Error("iOS screenshot destination must remain inside the project.");
26403
- await mkdir5(dirname4(resolved), { recursive: true });
26404
- await requireSuccess2([
26698
+ await mkdir6(dirname5(resolved), { recursive: true });
26699
+ await requireSuccess3([
26405
26700
  project.xcrun,
26406
26701
  "simctl",
26407
26702
  "io",
@@ -26427,7 +26722,7 @@ var startAbsoluteIosDevSession = async (options) => {
26427
26722
  };
26428
26723
  // src/mobile/iosNativeWatcher.ts
26429
26724
  import { watch } from "fs";
26430
- import { basename } from "path";
26725
+ import { basename as basename2 } from "path";
26431
26726
  var NATIVE_CHANGE_DEBOUNCE_MS = 500;
26432
26727
  var ROOT_NATIVE_INPUTS = new Set([
26433
26728
  "absolute.config.js",
@@ -26517,28 +26812,28 @@ var createAbsoluteIosNativeWatcher = async (options) => {
26517
26812
  options.signal?.addEventListener("abort", close, { once: true });
26518
26813
  return { close };
26519
26814
  };
26520
- var isAbsoluteIosNativeRootInput = (path) => ROOT_NATIVE_INPUTS.has(basename(path));
26815
+ var isAbsoluteIosNativeRootInput = (path) => ROOT_NATIVE_INPUTS.has(basename2(path));
26521
26816
  // src/mobile/remoteMacProtocol.ts
26522
- import { createHash as createHash7, randomUUID as randomUUID4 } from "crypto";
26817
+ import { createHash as createHash8, randomUUID as randomUUID4 } from "crypto";
26523
26818
  import {
26524
26819
  chmod,
26525
- mkdir as mkdir6,
26526
- mkdtemp as mkdtemp4,
26527
- readFile as readFile9,
26528
- rename as rename7,
26529
- rm as rm6,
26530
- writeFile as writeFile7
26820
+ mkdir as mkdir7,
26821
+ mkdtemp as mkdtemp5,
26822
+ readFile as readFile10,
26823
+ rename as rename8,
26824
+ rm as rm7,
26825
+ writeFile as writeFile8
26531
26826
  } from "fs/promises";
26532
- import { homedir as homedir2 } from "os";
26827
+ import { homedir as homedir3 } from "os";
26533
26828
  import { isIP as isIP3 } from "net";
26534
26829
  import {
26535
- dirname as dirname5,
26536
- isAbsolute as isAbsolute5,
26537
- join as join8,
26830
+ dirname as dirname6,
26831
+ isAbsolute as isAbsolute6,
26832
+ join as join9,
26538
26833
  posix,
26539
- relative as relative6,
26834
+ relative as relative7,
26540
26835
  resolve as resolvePath3,
26541
- sep as sep5
26836
+ sep as sep6
26542
26837
  } from "path";
26543
26838
 
26544
26839
  // src/mobile/remoteMacWire.ts
@@ -26553,14 +26848,14 @@ var REMOTE_RELEASE_LEASE_HEARTBEAT_MS = 15000;
26553
26848
  var REMOTE_RELEASE_LEASE_STALE_SECONDS = 120;
26554
26849
  var PROFILE_NAME = /^[a-z0-9](?:[a-z0-9._-]{0,62}[a-z0-9])?$/u;
26555
26850
  var SSH_DESTINATION = /^(?:[A-Za-z0-9._-]+@)?[A-Za-z0-9._:-]+$/u;
26556
- var defaultProfilePath = () => join8(homedir2(), ".absolutejs", "mobile", "remote-macs.json");
26851
+ var defaultProfilePath = () => join9(homedir3(), ".absolutejs", "mobile", "remote-macs.json");
26557
26852
  var emptyStore = () => ({
26558
26853
  format: PROFILE_FORMAT,
26559
26854
  profiles: {}
26560
26855
  });
26561
26856
  var loadStore = async (path = defaultProfilePath()) => {
26562
26857
  try {
26563
- const parsed = JSON.parse(await readFile9(path, "utf8"));
26858
+ const parsed = JSON.parse(await readFile10(path, "utf8"));
26564
26859
  if (parsed.format !== PROFILE_FORMAT || typeof parsed.profiles !== "object" || parsed.profiles === null || Array.isArray(parsed.profiles))
26565
26860
  throw new Error("Unsupported remote Mac profile format.");
26566
26861
  for (const [key, profile] of Object.entries(parsed.profiles)) {
@@ -26577,13 +26872,13 @@ var loadStore = async (path = defaultProfilePath()) => {
26577
26872
  }
26578
26873
  };
26579
26874
  var saveStore = async (store, path = defaultProfilePath()) => {
26580
- await mkdir6(dirname5(path), { recursive: true });
26875
+ await mkdir7(dirname6(path), { recursive: true });
26581
26876
  const temporary = `${path}.${randomUUID4()}.tmp`;
26582
- await writeFile7(temporary, `${JSON.stringify(store, null, 2)}
26877
+ await writeFile8(temporary, `${JSON.stringify(store, null, 2)}
26583
26878
  `, {
26584
26879
  mode: 384
26585
26880
  });
26586
- await rename7(temporary, path);
26881
+ await rename8(temporary, path);
26587
26882
  await chmod(path, 384);
26588
26883
  };
26589
26884
  var validateAbsoluteRemoteMacProfileName = (name) => {
@@ -26751,16 +27046,16 @@ var removeAbsoluteRemoteMacProfile = async (name, profilePath) => {
26751
27046
  await saveStore(store, profilePath);
26752
27047
  return true;
26753
27048
  };
26754
- var projectIdentity = (projectRoot, appId) => createHash7("sha256").update(`${resolvePath3(projectRoot)}\x00${appId}`).digest("hex").slice(0, 20);
27049
+ var projectIdentity = (projectRoot, appId) => createHash8("sha256").update(`${resolvePath3(projectRoot)}\x00${appId}`).digest("hex").slice(0, 20);
26755
27050
  var createAbsoluteRemoteExpoIosDevProject = (config, projectRoot, profile) => {
26756
27051
  if (config.engine !== "expo")
26757
27052
  throw new TypeError("Remote Expo execution requires mobile.engine: expo.");
26758
27053
  return createAbsoluteRemoteIosDevProject(config, projectRoot, profile);
26759
27054
  };
26760
27055
  var createAbsoluteRemoteIosDevProject = (config, projectRoot, profile) => ({
26761
- cap: join8(resolvePath3(projectRoot), "node_modules", ".bin", "cap"),
27056
+ cap: join9(resolvePath3(projectRoot), "node_modules", ".bin", "cap"),
26762
27057
  config,
26763
- nativeDirectory: join8(config.nativeProjectDirectory, "ios"),
27058
+ nativeDirectory: join9(config.nativeProjectDirectory, "ios"),
26764
27059
  profile,
26765
27060
  projectRoot: resolvePath3(projectRoot),
26766
27061
  remote: true,
@@ -26917,8 +27212,8 @@ var installAbsoluteRemoteMacAgent = async (project) => {
26917
27212
  };
26918
27213
  var materializeAbsoluteRemoteMacAgent = async (projectRoot) => {
26919
27214
  const shippedCandidates = [
26920
- join8(import.meta.dir, "remoteMacAgentEntry.js"),
26921
- join8(import.meta.dir, "..", "mobile", "remoteMacAgentEntry.js")
27215
+ join9(import.meta.dir, "remoteMacAgentEntry.js"),
27216
+ join9(import.meta.dir, "..", "mobile", "remoteMacAgentEntry.js")
26922
27217
  ];
26923
27218
  let path;
26924
27219
  for (const candidate of shippedCandidates) {
@@ -26929,14 +27224,14 @@ var materializeAbsoluteRemoteMacAgent = async (projectRoot) => {
26929
27224
  }
26930
27225
  if (!path) {
26931
27226
  const sourceCandidates = [
26932
- join8(import.meta.dir, "remoteMacAgentEntry.ts"),
26933
- join8(import.meta.dir, "..", "..", "src", "mobile", "remoteMacAgentEntry.ts")
27227
+ join9(import.meta.dir, "remoteMacAgentEntry.ts"),
27228
+ join9(import.meta.dir, "..", "..", "src", "mobile", "remoteMacAgentEntry.ts")
26934
27229
  ];
26935
27230
  const source = await sourceCandidates.reduce(async (found, candidate) => await found ?? (await Bun.file(candidate).exists() ? candidate : undefined), Promise.resolve(undefined));
26936
27231
  if (!source)
26937
27232
  throw new Error("The AbsoluteJS installation does not contain its remote Mac agent artifact.");
26938
- const outdir = join8(resolvePath3(projectRoot), ".absolutejs", "mobile", "remote-agent");
26939
- await mkdir6(outdir, { recursive: true });
27233
+ const outdir = join9(resolvePath3(projectRoot), ".absolutejs", "mobile", "remote-agent");
27234
+ await mkdir7(outdir, { recursive: true });
26940
27235
  const result = await Bun.build({
26941
27236
  entrypoints: [source],
26942
27237
  minify: true,
@@ -26945,13 +27240,13 @@ var materializeAbsoluteRemoteMacAgent = async (projectRoot) => {
26945
27240
  });
26946
27241
  if (!result.success)
26947
27242
  throw new AggregateError(result.logs, "Failed to build the AbsoluteJS remote Mac agent.");
26948
- path = join8(outdir, "remoteMacAgentEntry.js");
27243
+ path = join9(outdir, "remoteMacAgentEntry.js");
26949
27244
  }
26950
27245
  const bytes = await Bun.file(path).arrayBuffer();
26951
- const sha256 = createHash7("sha256").update(new Uint8Array(bytes)).digest("hex");
26952
- return { bytes: bytes.byteLength, path, sha256 };
27246
+ const sha2562 = createHash8("sha256").update(new Uint8Array(bytes)).digest("hex");
27247
+ return { bytes: bytes.byteLength, path, sha256: sha2562 };
26953
27248
  };
26954
- var portableRelativePath = (root, path) => relative6(root, path).split(sep5).join(posix.sep);
27249
+ var portableRelativePath = (root, path) => relative7(root, path).split(sep6).join(posix.sep);
26955
27250
  var portableMobileConfig = (project) => ({
26956
27251
  appId: project.config.appId,
26957
27252
  appName: project.config.appName,
@@ -27132,9 +27427,9 @@ var writeRemoteArtifact = async (path, stream) => {
27132
27427
  };
27133
27428
  var retrieveAbsoluteRemoteIosRelease = async (project, metadata, outputDirectory) => {
27134
27429
  const releaseRoot = posix.join(project.remoteProjectRoot, ".absolutejs", "mobile", "releases", "ios", metadata.releaseId);
27135
- const stagingParent = join8(project.projectRoot, ".absolutejs", "mobile");
27136
- await mkdir6(stagingParent, { recursive: true });
27137
- const staging = await mkdtemp4(join8(stagingParent, ".remote-ios-"));
27430
+ const stagingParent = join9(project.projectRoot, ".absolutejs", "mobile");
27431
+ await mkdir7(stagingParent, { recursive: true });
27432
+ const staging = await mkdtemp5(join9(stagingParent, ".remote-ios-"));
27138
27433
  try {
27139
27434
  const remoteMetadata = requireRemoteSuccess(await defaultTransport.capture([
27140
27435
  ...absoluteRemoteMacSshBase(project.profile),
@@ -27144,7 +27439,7 @@ var retrieveAbsoluteRemoteIosRelease = async (project, metadata, outputDirectory
27144
27439
  const downloadedMetadata = JSON.parse(remoteMetadata);
27145
27440
  if (JSON.stringify(requireAbsoluteIosReleaseMetadata(downloadedMetadata)) !== JSON.stringify(metadata))
27146
27441
  throw new TypeError("Remote iOS release metadata changed during retrieval.");
27147
- const artifactPath = join8(staging, "App.ipa");
27442
+ const artifactPath = join9(staging, "App.ipa");
27148
27443
  const download = Bun.spawn([
27149
27444
  ...absoluteRemoteMacSshBase(project.profile),
27150
27445
  "/bin/sh -lc",
@@ -27164,7 +27459,7 @@ var retrieveAbsoluteRemoteIosRelease = async (project, metadata, outputDirectory
27164
27459
  projectRoot: project.projectRoot
27165
27460
  });
27166
27461
  } finally {
27167
- await rm6(staging, { force: true, recursive: true }).catch(() => {
27462
+ await rm7(staging, { force: true, recursive: true }).catch(() => {
27168
27463
  return;
27169
27464
  });
27170
27465
  }
@@ -27406,7 +27701,7 @@ var startAbsoluteRemoteDevSession = async (options) => {
27406
27701
  await syncProject(options.project);
27407
27702
  const syncDuration = performance.now() - syncStartedAt;
27408
27703
  const encodedConfig = Buffer.from(JSON.stringify(portableMobileConfig(options.project))).toString("base64url");
27409
- const encodedCertificateAuthority = options.certificateAuthorityPath ? (await readFile9(options.certificateAuthorityPath)).toString("base64url") : undefined;
27704
+ const encodedCertificateAuthority = options.certificateAuthorityPath ? (await readFile10(options.certificateAuthorityPath)).toString("base64url") : undefined;
27410
27705
  const physicalDevice = options.deviceIdentifier !== undefined;
27411
27706
  const expo = options.project.config.engine === "expo";
27412
27707
  if (expo && options.metroPort === undefined)
@@ -27473,8 +27768,8 @@ var startAbsoluteRemoteDevSession = async (options) => {
27473
27768
  const pending = new Map;
27474
27769
  let resolveReady;
27475
27770
  let rejectReady;
27476
- const readyPromise = new Promise((resolve6, reject) => {
27477
- resolveReady = resolve6;
27771
+ const readyPromise = new Promise((resolve7, reject) => {
27772
+ resolveReady = resolve7;
27478
27773
  rejectReady = reject;
27479
27774
  });
27480
27775
  const handleEvent = (event) => {
@@ -27577,7 +27872,7 @@ var startAbsoluteRemoteDevSession = async (options) => {
27577
27872
  options.log?.(`Remote Mac connected (${options.project.profile.name}); agent ${agent.uploaded ? "uploaded" : "cache hit"}, project synced, and ${expo ? "Expo " : ""}iOS ready in ${totalDuration.toFixed(2)}ms.`);
27578
27873
  const request = (commandName) => {
27579
27874
  const id = randomUUID4();
27580
- const response = new Promise((resolve6, reject) => pending.set(id, { reject, resolve: resolve6 }));
27875
+ const response = new Promise((resolve7, reject) => pending.set(id, { reject, resolve: resolve7 }));
27581
27876
  process2.stdin.write(`${JSON.stringify({ command: commandName, id, v: ABSOLUTE_REMOTE_MAC_PROTOCOL_VERSION })}
27582
27877
  `);
27583
27878
  const flush = async () => {
@@ -27597,7 +27892,7 @@ var startAbsoluteRemoteDevSession = async (options) => {
27597
27892
  if (closed)
27598
27893
  return;
27599
27894
  closed = true;
27600
- const timeout = () => new Promise((resolve6) => setTimeout(() => resolve6("timeout"), REMOTE_SESSION_CLOSE_TIMEOUT_MS));
27895
+ const timeout = () => new Promise((resolve7) => setTimeout(() => resolve7("timeout"), REMOTE_SESSION_CLOSE_TIMEOUT_MS));
27601
27896
  const id = randomUUID4();
27602
27897
  process2.stdin.write(`${JSON.stringify({ command: "close", id, v: ABSOLUTE_REMOTE_MAC_PROTOCOL_VERSION })}
27603
27898
  `);
@@ -27644,11 +27939,11 @@ var startAbsoluteRemoteDevSession = async (options) => {
27644
27939
  screenshot: async (destination) => {
27645
27940
  const result = await request("screenshot");
27646
27941
  const target = resolvePath3(options.project.projectRoot, destination);
27647
- const targetRelative = relative6(options.project.projectRoot, target);
27648
- if (targetRelative.startsWith("..") || isAbsolute5(targetRelative))
27942
+ const targetRelative = relative7(options.project.projectRoot, target);
27943
+ if (targetRelative.startsWith("..") || isAbsolute6(targetRelative))
27649
27944
  throw new Error("iOS screenshot must remain inside the project.");
27650
- await mkdir6(dirname5(target), { recursive: true });
27651
- await writeFile7(target, Buffer.from(result.data, "base64"));
27945
+ await mkdir7(dirname6(target), { recursive: true });
27946
+ await writeFile8(target, Buffer.from(result.data, "base64"));
27652
27947
  return target;
27653
27948
  },
27654
27949
  get state() {
@@ -27675,20 +27970,20 @@ var absoluteIosDeviceAcceptanceCommands = (options) => {
27675
27970
  ]
27676
27971
  };
27677
27972
  };
27678
- var requireSuccess3 = (result, message) => {
27973
+ var requireSuccess4 = (result, message) => {
27679
27974
  if (result.exitCode !== 0)
27680
27975
  throw new Error(message);
27681
27976
  return result;
27682
27977
  };
27683
27978
  var testAbsoluteIosPhysicalDevice = async (options) => {
27684
27979
  const commands = absoluteIosDeviceAcceptanceCommands(options);
27685
- requireSuccess3(await options.capture(commands.details), "The selected physical iOS device is unavailable. Pair it in Xcode Device Hub, trust this Mac, unlock it, and enable Developer Mode.");
27686
- const apps = requireSuccess3(await options.capture(commands.apps), "AbsoluteJS could not inspect installed apps on the physical iOS device.");
27980
+ requireSuccess4(await options.capture(commands.details), "The selected physical iOS device is unavailable. Pair it in Xcode Device Hub, trust this Mac, unlock it, and enable Developer Mode.");
27981
+ const apps = requireSuccess4(await options.capture(commands.apps), "AbsoluteJS could not inspect installed apps on the physical iOS device.");
27687
27982
  if (!apps.stdout.includes(options.appId))
27688
27983
  throw new Error("The AbsoluteJS app is not installed on the selected physical iOS device. Start bun dev with the same --ios-device value first.");
27689
27984
  const now = options.now ?? performance.now.bind(performance);
27690
27985
  const startedAt = now();
27691
- requireSuccess3(await options.capture(commands.launch), "AbsoluteJS could not relaunch the app on the physical iOS device.");
27986
+ requireSuccess4(await options.capture(commands.launch), "AbsoluteJS could not relaunch the app on the physical iOS device.");
27692
27987
  await options.waitForHmr();
27693
27988
  return {
27694
27989
  hmrConnected: true,
@@ -27711,10 +28006,10 @@ var frameworks2 = new Set([
27711
28006
  "svelte",
27712
28007
  "vue"
27713
28008
  ]);
27714
- var isRecord4 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
28009
+ var isRecord5 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
27715
28010
  var isPageFramework2 = (value) => typeof value === "string" && frameworks2.has(value);
27716
28011
  var parseAbsoluteMobileBuildPageMetadata = (value) => {
27717
- if (!isRecord4(value))
28012
+ if (!isRecord5(value))
27718
28013
  return;
27719
28014
  if (typeof value.bundleKey !== "string" || typeof value.contract !== "string" || !isPageFramework2(value.framework) || typeof value.pageId !== "string" || typeof value.propsSchemaHash !== "string") {
27720
28015
  return;
@@ -27728,32 +28023,32 @@ var parseAbsoluteMobileBuildPageMetadata = (value) => {
27728
28023
  };
27729
28024
  };
27730
28025
  // src/mobile/buildPipeline.ts
27731
- import { readFile as readFile15 } from "fs/promises";
27732
- import { join as join18, resolve as resolve13 } from "path";
28026
+ import { readFile as readFile16 } from "fs/promises";
28027
+ import { join as join19, resolve as resolve14 } from "path";
27733
28028
  import { pathToFileURL as pathToFileURL2 } from "url";
27734
28029
 
27735
28030
  // src/mobile/buildRelease.ts
27736
- import { createHash as createHash9 } from "crypto";
27737
- import { mkdir as mkdir8, readFile as readFile11, writeFile as writeFile9 } from "fs/promises";
27738
- import { basename as basename2, dirname as dirname6, extname, join as join9, relative as relative7, resolve as resolve8 } from "path";
28031
+ import { createHash as createHash10 } from "crypto";
28032
+ import { mkdir as mkdir9, readFile as readFile12, writeFile as writeFile10 } from "fs/promises";
28033
+ import { basename as basename3, dirname as dirname7, extname, join as join10, relative as relative8, resolve as resolve9 } from "path";
27739
28034
  init_releaseArtifact();
27740
- var sha256 = (bytes) => createHash9("sha256").update(bytes).digest("hex");
28035
+ var sha2562 = (bytes) => createHash10("sha256").update(bytes).digest("hex");
27741
28036
  var STATIC_SCRIPT_PATTERN = /(<script\b[^>]*?\bsrc\s*=\s*["'])(\/[^"']+\.(?:js|ts))(["'][^>]*>)/giu;
27742
28037
  var rewriteStaticScriptPaths = (source, manifest) => source.replace(STATIC_SCRIPT_PATTERN, (match, prefix, path, suffix) => {
27743
28038
  if (path.endsWith("/htmx.min.js"))
27744
28039
  return match;
27745
- const key = toPascal(basename2(path, extname(path)));
28040
+ const key = toPascal(basename3(path, extname(path)));
27746
28041
  const builtPath = manifest[key];
27747
28042
  return builtPath ? `${prefix}${builtPath}${suffix}` : match;
27748
28043
  });
27749
28044
  var readPageMetadata = (route) => parseAbsoluteMobileBuildPageMetadata(route.hooks?.detail?.[ABSOLUTE_MOBILE_ROUTE_DETAIL]);
27750
28045
  var resolveAssetPath = (buildDirectory, assetPath) => {
27751
- const resolvedBuildDirectory = resolve8(buildDirectory);
27752
- const resolvedAsset = resolve8(assetPath);
28046
+ const resolvedBuildDirectory = resolve9(buildDirectory);
28047
+ const resolvedAsset = resolve9(assetPath);
27753
28048
  if (resolvedAsset.startsWith(`${resolvedBuildDirectory}/`)) {
27754
28049
  return resolvedAsset;
27755
28050
  }
27756
- return join9(buildDirectory, assetPath.replace(/^\/+/, ""));
28051
+ return join10(buildDirectory, assetPath.replace(/^\/+/, ""));
27757
28052
  };
27758
28053
  var pageFor = async (metadata, manifest, buildDirectory) => {
27759
28054
  const assetPath = manifest[metadata.bundleKey];
@@ -27762,12 +28057,12 @@ var pageFor = async (metadata, manifest, buildDirectory) => {
27762
28057
  }
27763
28058
  let resolvedAssetPath = resolveAssetPath(buildDirectory, assetPath);
27764
28059
  if (metadata.framework === "html" || metadata.framework === "htmx") {
27765
- const source = await readFile11(resolvedAssetPath, "utf8");
28060
+ const source = await readFile12(resolvedAssetPath, "utf8");
27766
28061
  const rewritten = rewriteStaticScriptPaths(source, manifest);
27767
- const documentHash = sha256(new TextEncoder().encode(rewritten));
27768
- resolvedAssetPath = join9(buildDirectory, ".absolutejs", "mobile-pages", `${documentHash}.html`);
27769
- await mkdir8(dirname6(resolvedAssetPath), { recursive: true });
27770
- await writeFile9(resolvedAssetPath, rewritten);
28062
+ const documentHash = sha2562(new TextEncoder().encode(rewritten));
28063
+ resolvedAssetPath = join10(buildDirectory, ".absolutejs", "mobile-pages", `${documentHash}.html`);
28064
+ await mkdir9(dirname7(resolvedAssetPath), { recursive: true });
28065
+ await writeFile10(resolvedAssetPath, rewritten);
27771
28066
  }
27772
28067
  const pageAssetKey = metadata.bundleKey.replace(/Index$/u, "");
27773
28068
  const styleAssetPath = [
@@ -27776,20 +28071,20 @@ var pageFor = async (metadata, manifest, buildDirectory) => {
27776
28071
  ].map((key) => manifest[key]).find((path) => typeof path === "string");
27777
28072
  const resolvedStylePath = styleAssetPath ? resolveAssetPath(buildDirectory, styleAssetPath) : undefined;
27778
28073
  const [bytes, styleBytes] = await Promise.all([
27779
- readFile11(resolvedAssetPath),
27780
- resolvedStylePath ? readFile11(resolvedStylePath) : undefined
28074
+ readFile12(resolvedAssetPath),
28075
+ resolvedStylePath ? readFile12(resolvedStylePath) : undefined
27781
28076
  ]);
27782
- const bundlePath = `/${relative7(resolve8(buildDirectory), resolvedAssetPath).replaceAll("\\", "/")}`;
27783
- const styleBundlePath = resolvedStylePath ? `/${relative7(resolve8(buildDirectory), resolvedStylePath).replaceAll("\\", "/")}` : undefined;
28077
+ const bundlePath = `/${relative8(resolve9(buildDirectory), resolvedAssetPath).replaceAll("\\", "/")}`;
28078
+ const styleBundlePath = resolvedStylePath ? `/${relative8(resolve9(buildDirectory), resolvedStylePath).replaceAll("\\", "/")}` : undefined;
27784
28079
  return {
27785
- bundleHash: sha256(bytes),
28080
+ bundleHash: sha2562(bytes),
27786
28081
  bundlePath,
27787
28082
  contract: metadata.contract,
27788
28083
  framework: metadata.framework,
27789
28084
  pageId: metadata.pageId,
27790
28085
  propsSchemaHash: metadata.propsSchemaHash,
27791
28086
  ...styleBytes && styleBundlePath ? {
27792
- styleBundleHash: sha256(styleBytes),
28087
+ styleBundleHash: sha2562(styleBytes),
27793
28088
  styleBundlePath
27794
28089
  } : {}
27795
28090
  };
@@ -27797,7 +28092,7 @@ var pageFor = async (metadata, manifest, buildDirectory) => {
27797
28092
  var buildAbsoluteMobileCompatibilityRelease = async (options) => {
27798
28093
  const [captured, producerBytes] = await Promise.all([
27799
28094
  captureAbsoluteMobileRouteGraph(options.app),
27800
- readFile11(options.producerPath)
28095
+ readFile12(options.producerPath)
27801
28096
  ]);
27802
28097
  if (captured.length === 0) {
27803
28098
  throw new TypeError("No instrumented AbsoluteJS mobile page routes were found in the finalized Elysia route graph.");
@@ -27811,8 +28106,8 @@ var buildAbsoluteMobileCompatibilityRelease = async (options) => {
27811
28106
  metadataByPage.set(metadata.pageId, metadata);
27812
28107
  }
27813
28108
  const pages = await Promise.all([...metadataByPage.values()].map((metadata) => pageFor(metadata, options.manifest, options.buildDirectory)));
27814
- const producerHash = sha256(producerBytes);
27815
- const appBuild = `ambuild_${sha256(new TextEncoder().encode(JSON.stringify({
28109
+ const producerHash = sha2562(producerBytes);
28110
+ const appBuild = `ambuild_${sha2562(new TextEncoder().encode(JSON.stringify({
27816
28111
  pages: pages.map(({
27817
28112
  bundleHash,
27818
28113
  bundlePath,
@@ -27888,15 +28183,15 @@ init_routeMatcher();
27888
28183
  import {
27889
28184
  cp,
27890
28185
  copyFile as copyFile5,
27891
- mkdir as mkdir9,
27892
- mkdtemp as mkdtemp5,
27893
- readFile as readFile12,
27894
- rename as rename9,
27895
- rm as rm8,
27896
- writeFile as writeFile10
28186
+ mkdir as mkdir10,
28187
+ mkdtemp as mkdtemp6,
28188
+ readFile as readFile13,
28189
+ rename as rename10,
28190
+ rm as rm9,
28191
+ writeFile as writeFile11
27897
28192
  } from "fs/promises";
27898
28193
  import { existsSync as existsSync2 } from "fs";
27899
- import { basename as basename3, dirname as dirname7, extname as extname2, join as join10, relative as relative8, resolve as resolve9 } from "path";
28194
+ import { basename as basename4, dirname as dirname8, extname as extname2, join as join11, relative as relative9, resolve as resolve10 } from "path";
27900
28195
 
27901
28196
  // src/mobile/client.ts
27902
28197
  init_pageProtocol();
@@ -27930,14 +28225,14 @@ var upgradeReasons = new Set([
27930
28225
  "protocol",
27931
28226
  "runtime"
27932
28227
  ]);
27933
- var isRecord6 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
28228
+ var isRecord7 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
27934
28229
  var isFramework = (value) => typeof value === "string" && frameworks4.has(value);
27935
28230
  var isUpgradeReason = (value) => typeof value === "string" && upgradeReasons.has(value);
27936
28231
  var parsePageResult = (value) => {
27937
28232
  if (typeof value.contract !== "string" || !isFramework(value.framework) || typeof value.pageId !== "string" || typeof value.status !== "number") {
27938
28233
  throw new AbsoluteMobilePageProtocolError("invalid-envelope", "The mobile page response is missing required page metadata.");
27939
28234
  }
27940
- if (!isRecord6(value.props)) {
28235
+ if (!isRecord7(value.props)) {
27941
28236
  throw new AbsoluteMobilePageProtocolError("invalid-props", "The mobile page response must contain an object props value.");
27942
28237
  }
27943
28238
  return {
@@ -27988,7 +28283,7 @@ var activateAbsoluteMobilePage = async (value, options) => {
27988
28283
  };
27989
28284
  };
27990
28285
  var parseAbsoluteMobilePageEnvelope = (value) => {
27991
- if (!isRecord6(value) || !isRecord6(value.response)) {
28286
+ if (!isRecord7(value) || !isRecord7(value.response)) {
27992
28287
  throw new AbsoluteMobilePageProtocolError("invalid-envelope", "The server did not return an AbsoluteJS mobile page envelope.");
27993
28288
  }
27994
28289
  if (value.protocol !== ABSOLUTE_MOBILE_PAGE_PROTOCOL_VERSION) {
@@ -28107,49 +28402,49 @@ var CAPACITOR_CLIENT_FRAMEWORKS = new Set([
28107
28402
  var CLIENT_ASSET_DIRECTORIES = ["assets", "html", "htmx", "indexes"];
28108
28403
  var errorHasCode2 = (error, code) => typeof error === "object" && error !== null && Reflect.get(error, "code") === code;
28109
28404
  var shellBootstrapModule = () => {
28110
- const candidate = ["js", "ts"].map((extension) => join10(import.meta.dir, `shellBootstrap.${extension}`)).find(existsSync2);
28405
+ const candidate = ["js", "ts"].map((extension) => join11(import.meta.dir, `shellBootstrap.${extension}`)).find(existsSync2);
28111
28406
  if (candidate)
28112
28407
  return candidate;
28113
28408
  throw new TypeError("AbsoluteJS mobile shell bootstrap module is missing.");
28114
28409
  };
28115
28410
  var shellAuthModule = () => {
28116
- const candidate = ["js", "ts"].map((extension) => join10(import.meta.dir, `shellAuth.${extension}`)).find(existsSync2);
28411
+ const candidate = ["js", "ts"].map((extension) => join11(import.meta.dir, `shellAuth.${extension}`)).find(existsSync2);
28117
28412
  if (candidate)
28118
28413
  return candidate;
28119
28414
  throw new TypeError("AbsoluteJS mobile auth shell module is missing.");
28120
28415
  };
28121
28416
  var shellExpoAuthModule = () => {
28122
- const candidate = ["js", "ts"].map((extension) => join10(import.meta.dir, `shellExpoAuth.${extension}`)).find(existsSync2);
28417
+ const candidate = ["js", "ts"].map((extension) => join11(import.meta.dir, `shellExpoAuth.${extension}`)).find(existsSync2);
28123
28418
  if (candidate)
28124
28419
  return candidate;
28125
28420
  throw new TypeError("AbsoluteJS Expo auth bridge module is missing.");
28126
28421
  };
28127
28422
  var shellSyncModule = () => {
28128
- const candidate = ["js", "ts"].map((extension) => join10(import.meta.dir, `shellSync.${extension}`)).find(existsSync2);
28423
+ const candidate = ["js", "ts"].map((extension) => join11(import.meta.dir, `shellSync.${extension}`)).find(existsSync2);
28129
28424
  if (candidate)
28130
28425
  return candidate;
28131
28426
  throw new TypeError("AbsoluteJS mobile Sync shell module is missing.");
28132
28427
  };
28133
28428
  var shellExpoSyncModule = () => {
28134
- const candidate = ["js", "ts"].map((extension) => join10(import.meta.dir, `shellExpoSync.${extension}`)).find(existsSync2);
28429
+ const candidate = ["js", "ts"].map((extension) => join11(import.meta.dir, `shellExpoSync.${extension}`)).find(existsSync2);
28135
28430
  if (candidate)
28136
28431
  return candidate;
28137
28432
  throw new TypeError("AbsoluteJS Expo Sync bridge module is missing.");
28138
28433
  };
28139
28434
  var shellPushModule = () => {
28140
- const candidate = ["js", "ts"].map((extension) => join10(import.meta.dir, `shellPush.${extension}`)).find(existsSync2);
28435
+ const candidate = ["js", "ts"].map((extension) => join11(import.meta.dir, `shellPush.${extension}`)).find(existsSync2);
28141
28436
  if (candidate)
28142
28437
  return candidate;
28143
28438
  throw new TypeError("AbsoluteJS mobile push shell module is missing.");
28144
28439
  };
28145
28440
  var shellExpoDevicesModule = () => {
28146
- const candidate = ["js", "ts"].map((extension) => join10(import.meta.dir, `shellExpoDevices.${extension}`)).find(existsSync2);
28441
+ const candidate = ["js", "ts"].map((extension) => join11(import.meta.dir, `shellExpoDevices.${extension}`)).find(existsSync2);
28147
28442
  if (candidate)
28148
28443
  return candidate;
28149
28444
  throw new TypeError("AbsoluteJS Expo device bridge module is missing.");
28150
28445
  };
28151
28446
  var shellUpdateModule = () => {
28152
- const candidate = ["js", "ts"].map((extension) => join10(import.meta.dir, `shellUpdate.${extension}`)).find(existsSync2);
28447
+ const candidate = ["js", "ts"].map((extension) => join11(import.meta.dir, `shellUpdate.${extension}`)).find(existsSync2);
28153
28448
  if (candidate)
28154
28449
  return candidate;
28155
28450
  throw new TypeError("AbsoluteJS mobile update shell module is missing.");
@@ -28184,8 +28479,8 @@ var indexHtml = (appName, productionOrigin) => `<!doctype html>
28184
28479
  </html>
28185
28480
  `;
28186
28481
  var sourceAssetPath = (buildDirectory, bundlePath) => {
28187
- const root = resolve9(buildDirectory);
28188
- const asset = resolve9(root, bundlePath.replace(/^\/+/, ""));
28482
+ const root = resolve10(buildDirectory);
28483
+ const asset = resolve10(root, bundlePath.replace(/^\/+/, ""));
28189
28484
  if (!asset.startsWith(`${root}/`)) {
28190
28485
  throw new TypeError("Mobile page bundle escaped the build directory.");
28191
28486
  }
@@ -28202,15 +28497,15 @@ var resolveProjectImport = async (projectRoot, specifier) => {
28202
28497
  const segments = specifier.split("/");
28203
28498
  const packageName = specifier.startsWith("@") ? segments.slice(0, 2).join("/") : segments[0] ?? "";
28204
28499
  const subpath = specifier.slice(packageName.length);
28205
- const packageDirectory = join10(resolve9(projectRoot), "node_modules", packageName);
28206
- const manifest = JSON.parse(await readFile12(join10(packageDirectory, "package.json"), "utf8"));
28500
+ const packageDirectory = join11(resolve10(projectRoot), "node_modules", packageName);
28501
+ const manifest = JSON.parse(await readFile13(join11(packageDirectory, "package.json"), "utf8"));
28207
28502
  const exports = typeof manifest === "object" && manifest !== null ? Reflect.get(manifest, "exports") : undefined;
28208
28503
  const entry = typeof exports === "object" && exports !== null ? Reflect.get(exports, subpath ? `.${subpath}` : ".") : undefined;
28209
28504
  const target = importEntryTarget(entry);
28210
28505
  if (typeof target !== "string" || !target.startsWith("./"))
28211
28506
  throw new TypeError(`${specifier} does not publish an import entry.`);
28212
- const resolved = resolve9(packageDirectory, target);
28213
- if (!resolved.startsWith(`${resolve9(packageDirectory)}/`))
28507
+ const resolved = resolve10(packageDirectory, target);
28508
+ if (!resolved.startsWith(`${resolve10(packageDirectory)}/`))
28214
28509
  throw new TypeError(`${specifier} has an unsafe import entry.`);
28215
28510
  return resolved;
28216
28511
  };
@@ -28241,7 +28536,7 @@ var buildShellBootstrap = async (staging, auth, sync, storagePrefix, engine, upd
28241
28536
  const absoluteMobilePushCapability = absoluteDeviceCapability${pushIndex}(absoluteMobilePush.capabilityOptions);
28242
28537
  ` : "";
28243
28538
  const capabilityOptions = shellCapabilities.map((name, index) => `${JSON.stringify(name)}: ${name === "pushNotifications" ? "absoluteMobilePushCapability" : `absoluteDeviceCapability${index}()`}`).join(", ");
28244
- const entryPath = join10(staging, ".absolute-mobile-entry.ts");
28539
+ const entryPath = join11(staging, ".absolute-mobile-entry.ts");
28245
28540
  const baseAdapterModule = capacitor ? await resolveProjectImport(projectRoot, "@absolutejs/devices-capacitor") : shellExpoDevicesModule();
28246
28541
  const adapterImport = capacitor ? `import { installCapacitorDeviceAdapterIfNative } from ${JSON.stringify(baseAdapterModule)};` : `import { createAbsoluteExpoBridgeFetch, installAbsoluteExpoWebDeviceAdapter } from ${JSON.stringify(baseAdapterModule)};`;
28247
28542
  const adapterInstall = capacitor ? `installCapacitorDeviceAdapterIfNative({ storagePrefix: ${JSON.stringify(storagePrefix)}${capabilityOptions ? `, ${capabilityOptions}` : ""} });` : `installAbsoluteExpoWebDeviceAdapter(${JSON.stringify(deviceCapabilities.capabilities)});`;
@@ -28259,7 +28554,7 @@ const absoluteMobilePushCapability = absoluteDeviceCapability${pushIndex}(absolu
28259
28554
  if (updates)
28260
28555
  shellOptionProperties.push("installUpdates: installAbsoluteMobileShellUpdates");
28261
28556
  const shellOptions = `{ ${shellOptionProperties.join(", ")} }`;
28262
- await writeFile10(entryPath, `import { startAbsoluteMobileShell } from ${JSON.stringify(modulePath)};
28557
+ await writeFile11(entryPath, `import { startAbsoluteMobileShell } from ${JSON.stringify(modulePath)};
28263
28558
  ${adapterImport}
28264
28559
  ${authImport}${syncImport}${pushImport}${updateImport}${capabilityImports}
28265
28560
  ${pushSetup}${adapterInstall}
@@ -28275,31 +28570,31 @@ void startAbsoluteMobileShell(${shellOptions});
28275
28570
  if (!build.success || build.outputs.length !== 1) {
28276
28571
  throw new AggregateError(build.logs, "Failed to build the AbsoluteJS Capacitor shell.");
28277
28572
  }
28278
- await rename9(build.outputs[0]?.path ?? "", join10(staging, BOOTSTRAP_FILE));
28279
- await rm8(entryPath, { force: true });
28573
+ await rename10(build.outputs[0]?.path ?? "", join11(staging, BOOTSTRAP_FILE));
28574
+ await rm9(entryPath, { force: true });
28280
28575
  };
28281
28576
  var removePreviousBundle = async (backup, moved) => {
28282
28577
  if (!moved)
28283
28578
  return;
28284
- await rm8(backup, { force: true, recursive: true });
28579
+ await rm9(backup, { force: true, recursive: true });
28285
28580
  };
28286
28581
  var restorePreviousBundle = async (backup, destination, moved) => {
28287
28582
  if (!moved)
28288
28583
  return;
28289
- await rename9(backup, destination);
28584
+ await rename10(backup, destination);
28290
28585
  };
28291
28586
  var installBundle = async (staging, destination) => {
28292
28587
  const backup = `${destination}.previous-${crypto.randomUUID()}`;
28293
28588
  let movedPrevious = false;
28294
28589
  try {
28295
- await rename9(destination, backup);
28590
+ await rename10(destination, backup);
28296
28591
  movedPrevious = true;
28297
28592
  } catch (error) {
28298
28593
  if (!errorHasCode2(error, "ENOENT"))
28299
28594
  throw error;
28300
28595
  }
28301
28596
  try {
28302
- await rename9(staging, destination);
28597
+ await rename10(staging, destination);
28303
28598
  await removePreviousBundle(backup, movedPrevious);
28304
28599
  } catch (error) {
28305
28600
  await restorePreviousBundle(backup, destination, movedPrevious);
@@ -28313,17 +28608,17 @@ var copyClientPage = async (page, buildDirectory, staging, copiedDependencies) =
28313
28608
  const extension = extname2(page.bundlePath) || ".js";
28314
28609
  const localBundlePath = `./pages/${page.bundleHash}${extension}`;
28315
28610
  const source = sourceAssetPath(buildDirectory, page.bundlePath);
28316
- await copyFile5(source, join10(staging, localBundlePath));
28611
+ await copyFile5(source, join11(staging, localBundlePath));
28317
28612
  await copyAbsoluteClientDependencies(source, buildDirectory, staging, copiedDependencies);
28318
28613
  let localStylePath;
28319
28614
  if (page.styleBundlePath && page.styleBundleHash) {
28320
28615
  const styleExtension = extname2(page.styleBundlePath) || ".css";
28321
28616
  localStylePath = `./styles/${page.styleBundleHash}${styleExtension}`;
28322
28617
  const styleSource = sourceAssetPath(buildDirectory, page.styleBundlePath);
28323
- await mkdir9(dirname7(join10(staging, localStylePath)), {
28618
+ await mkdir10(dirname8(join11(staging, localStylePath)), {
28324
28619
  recursive: true
28325
28620
  });
28326
- await copyFile5(styleSource, join10(staging, localStylePath));
28621
+ await copyFile5(styleSource, join11(staging, localStylePath));
28327
28622
  await copyAbsoluteClientDependencies(styleSource, buildDirectory, staging, copiedDependencies);
28328
28623
  }
28329
28624
  return {
@@ -28339,26 +28634,26 @@ var materializeAbsoluteMobileSourcemaps = async (pages, appBuild, projectRoot) =
28339
28634
  return value;
28340
28635
  };
28341
28636
  const release = safeLeaf(appBuild, "Mobile app build");
28342
- const privateRoot = join10(projectRoot, "sourcemaps");
28343
- const releaseRoot = join10(privateRoot, "mobile", release);
28637
+ const privateRoot = join11(projectRoot, "sourcemaps");
28638
+ const releaseRoot = join11(privateRoot, "mobile", release);
28344
28639
  const copied = [];
28345
28640
  const available = pages.flatMap((page) => {
28346
- const source = join10(privateRoot, `${basename3(page.bundlePath)}.map`);
28641
+ const source = join11(privateRoot, `${basename4(page.bundlePath)}.map`);
28347
28642
  return existsSync2(source) ? [{ page, source }] : [];
28348
28643
  });
28349
28644
  if (available.length > 0)
28350
- await mkdir9(releaseRoot, { recursive: true });
28645
+ await mkdir10(releaseRoot, { recursive: true });
28351
28646
  await Promise.all(available.map(async ({ page, source }) => {
28352
28647
  const extension = extname2(page.bundlePath) || ".js";
28353
28648
  if (!/^\.[a-z0-9]+$/iu.test(extension))
28354
28649
  throw new TypeError("Mobile page extension is not a safe source-map key.");
28355
28650
  const bundleHash = safeLeaf(page.bundleHash, "Mobile page bundle hash");
28356
28651
  const file = `${bundleHash}${extension}.map`;
28357
- await copyFile5(source, join10(releaseRoot, file));
28652
+ await copyFile5(source, join11(releaseRoot, file));
28358
28653
  copied.push({ bundleHash, file, pageId: page.pageId });
28359
28654
  }));
28360
28655
  if (copied.length > 0) {
28361
- await writeFile10(join10(releaseRoot, "manifest.json"), `${JSON.stringify({
28656
+ await writeFile11(join11(releaseRoot, "manifest.json"), `${JSON.stringify({
28362
28657
  appBuild,
28363
28658
  format: 1,
28364
28659
  pages: copied.sort((left, right) => left.pageId.localeCompare(right.pageId))
@@ -28368,7 +28663,7 @@ var materializeAbsoluteMobileSourcemaps = async (pages, appBuild, projectRoot) =
28368
28663
  return copied.length;
28369
28664
  };
28370
28665
  var absoluteClientImports = async (sourcePath, buildDirectory) => {
28371
- const source = await readFile12(sourcePath, "utf8");
28666
+ const source = await readFile13(sourcePath, "utf8");
28372
28667
  const extension = extname2(sourcePath).toLowerCase();
28373
28668
  let scriptLoader;
28374
28669
  if (extension === ".tsx")
@@ -28391,9 +28686,9 @@ var absoluteClientImports = async (sourcePath, buildDirectory) => {
28391
28686
  const clean = specifier.split(/[?#]/u, 1)[0] ?? specifier;
28392
28687
  if (clean.startsWith("/"))
28393
28688
  return [clean];
28394
- const resolved = resolve9(dirname7(sourcePath), clean);
28395
- const root = resolve9(buildDirectory);
28396
- const relativePath = relative8(root, resolved).replaceAll("\\", "/");
28689
+ const resolved = resolve10(dirname8(sourcePath), clean);
28690
+ const root = resolve10(buildDirectory);
28691
+ const relativePath = relative9(root, resolved).replaceAll("\\", "/");
28397
28692
  if (relativePath === ".." || relativePath.startsWith("../")) {
28398
28693
  throw new TypeError(`Mobile client dependency escaped the build directory: ${specifier}`);
28399
28694
  }
@@ -28405,8 +28700,8 @@ var copyAbsoluteClientDependency = async (specifier, buildDirectory, staging, co
28405
28700
  return;
28406
28701
  copied.add(specifier);
28407
28702
  const source = sourceAssetPath(buildDirectory, specifier);
28408
- const destination = join10(staging, specifier.replace(/^\/+/, ""));
28409
- await mkdir9(dirname7(destination), { recursive: true });
28703
+ const destination = join11(staging, specifier.replace(/^\/+/, ""));
28704
+ await mkdir10(dirname8(destination), { recursive: true });
28410
28705
  await copyFile5(source, destination);
28411
28706
  await copyAbsoluteClientDependencies(source, buildDirectory, staging, copied);
28412
28707
  };
@@ -28419,14 +28714,14 @@ var materializeAbsoluteCapacitorWebBundle = async (options) => {
28419
28714
  throw new TypeError(`mobile.entry ${options.config.entry} is not a captured mobile page route.`);
28420
28715
  }
28421
28716
  const destination = options.config.bundleDirectory;
28422
- await mkdir9(dirname7(destination), { recursive: true });
28423
- const staging = await mkdtemp5(join10(dirname7(destination), `.${basename3(destination)}.stage-`));
28717
+ await mkdir10(dirname8(destination), { recursive: true });
28718
+ const staging = await mkdtemp6(join11(dirname8(destination), `.${basename4(destination)}.stage-`));
28424
28719
  try {
28425
- const pageDirectory = join10(staging, "pages");
28426
- await mkdir9(pageDirectory, { recursive: true });
28720
+ const pageDirectory = join11(staging, "pages");
28721
+ await mkdir10(pageDirectory, { recursive: true });
28427
28722
  await Promise.all(CLIENT_ASSET_DIRECTORIES.map((directory) => ({
28428
- destination: join10(staging, directory),
28429
- source: join10(options.buildDirectory, directory)
28723
+ destination: join11(staging, directory),
28724
+ source: join11(options.buildDirectory, directory)
28430
28725
  })).filter(({ source }) => existsSync2(source)).map(({ destination: assetDestination, source }) => cp(source, assetDestination, { recursive: true })));
28431
28726
  const copiedDependencies = new Set;
28432
28727
  const pages = await Promise.all(options.artifact.pages.map((page) => copyClientPage(page, options.buildDirectory, staging, copiedDependencies)));
@@ -28463,16 +28758,16 @@ var materializeAbsoluteCapacitorWebBundle = async (options) => {
28463
28758
  } : {}
28464
28759
  };
28465
28760
  await Promise.all([
28466
- writeFile10(join10(staging, MANIFEST_FILE), `${JSON.stringify(manifest, null, "\t")}
28761
+ writeFile11(join11(staging, MANIFEST_FILE), `${JSON.stringify(manifest, null, "\t")}
28467
28762
  `),
28468
- writeFile10(join10(staging, INDEX_FILE), indexHtml(options.config.appName, options.config.productionOrigin)),
28763
+ writeFile11(join11(staging, INDEX_FILE), indexHtml(options.config.appName, options.config.productionOrigin)),
28469
28764
  buildShellBootstrap(staging, options.auth !== undefined, options.auth !== undefined && options.sync === true, `absolutejs.${options.auth?.clientId ?? options.config.appId}.`, options.config.engine, options.config.engine === "capacitor" && options.config.updates !== undefined, options.deviceCapabilities, options.projectRoot)
28470
28765
  ]);
28471
28766
  await installBundle(staging, destination);
28472
28767
  await materializeAbsoluteMobileSourcemaps(options.artifact.pages, options.artifact.appBuild, options.projectRoot);
28473
28768
  return manifest;
28474
28769
  } catch (error) {
28475
- await rm8(staging, { force: true, recursive: true });
28770
+ await rm9(staging, { force: true, recursive: true });
28476
28771
  throw error;
28477
28772
  }
28478
28773
  };
@@ -28489,23 +28784,22 @@ init_nativeAuth();
28489
28784
  init_syncSchema();
28490
28785
  init_deviceCapabilities();
28491
28786
  import {
28492
- access as access10,
28493
- cp as cp2,
28494
- mkdir as mkdir11,
28495
- mkdtemp as mkdtemp7,
28787
+ access as access11,
28788
+ mkdir as mkdir12,
28789
+ mkdtemp as mkdtemp8,
28496
28790
  readdir as readdir4,
28497
- readFile as readFile14,
28498
- rename as rename11,
28499
- rm as rm10,
28500
- writeFile as writeFile12
28791
+ readFile as readFile15,
28792
+ rename as rename12,
28793
+ rm as rm11,
28794
+ writeFile as writeFile13
28501
28795
  } from "fs/promises";
28502
- import { createHash as createHash12 } from "crypto";
28503
- import { basename as basename4, dirname as dirname10, join as join17, relative as relative10, resolve as resolve12, sep as sep6 } from "path";
28796
+ import { createHash as createHash13 } from "crypto";
28797
+ import { basename as basename5, dirname as dirname11, join as join18, relative as relative11, resolve as resolve13, sep as sep7 } from "path";
28504
28798
 
28505
28799
  // src/mobile/updateRuntime.ts
28506
28800
  init_deviceCapabilities();
28507
28801
  init_nativeAuth();
28508
- import { createHash as createHash11 } from "crypto";
28802
+ import { createHash as createHash12 } from "crypto";
28509
28803
 
28510
28804
  // src/mobile/updateProtocol.ts
28511
28805
  var ABSOLUTE_MOBILE_UPDATE_FORMAT = 1;
@@ -28646,7 +28940,7 @@ var createAbsoluteMobileUpdateRuntimeDescriptor = (options) => ({
28646
28940
  syncSchema: options.syncSchema ?? null,
28647
28941
  updates: options.config.updates ?? null
28648
28942
  });
28649
- var fingerprintAbsoluteMobileUpdateRuntime = (descriptor) => createHash11("sha256").update(canonicalizeAbsoluteMobileUpdate(descriptor)).digest("hex");
28943
+ var fingerprintAbsoluteMobileUpdateRuntime = (descriptor) => createHash12("sha256").update(canonicalizeAbsoluteMobileUpdate(descriptor)).digest("hex");
28650
28944
  var resolveAbsoluteMobileUpdateRuntime = (config, projectRoot) => {
28651
28945
  const auth = resolveAbsoluteMobileAuthManifest(projectRoot, config);
28652
28946
  const sync = auth !== undefined && projectUsesAbsoluteSync(projectRoot);
@@ -28669,7 +28963,7 @@ var resolveAbsoluteMobileUpdateRuntime = (config, projectRoot) => {
28669
28963
  };
28670
28964
 
28671
28965
  // src/mobile/expoNativeObservability.ts
28672
- import { join as join15 } from "path";
28966
+ import { join as join16 } from "path";
28673
28967
  var HEADER = `// Generated by AbsoluteJS. Edit absolute.config.ts, then run absolute mobile sync.
28674
28968
  `;
28675
28969
  var XML_HEADER = `<!-- Generated by AbsoluteJS. Edit absolute.config.ts, then run absolute mobile sync. -->
@@ -29111,31 +29405,31 @@ export const enqueueAbsoluteExpoNativeObservabilityForTesting = async (testId: s
29111
29405
  `;
29112
29406
  var absoluteExpoNativeObservabilityFiles = (project) => new Map([
29113
29407
  [
29114
- join15(project, "modules/absolute-mobile-observability/expo-module.config.json"),
29408
+ join16(project, "modules/absolute-mobile-observability/expo-module.config.json"),
29115
29409
  moduleConfig
29116
29410
  ],
29117
29411
  [
29118
- join15(project, "modules/absolute-mobile-observability/ios/AbsoluteMobileObservability.podspec"),
29412
+ join16(project, "modules/absolute-mobile-observability/ios/AbsoluteMobileObservability.podspec"),
29119
29413
  podspec
29120
29414
  ],
29121
29415
  [
29122
- join15(project, "modules/absolute-mobile-observability/ios/AbsoluteMobileObservabilityModule.swift"),
29416
+ join16(project, "modules/absolute-mobile-observability/ios/AbsoluteMobileObservabilityModule.swift"),
29123
29417
  iosModule
29124
29418
  ],
29125
29419
  [
29126
- join15(project, "modules/absolute-mobile-observability/android/build.gradle"),
29420
+ join16(project, "modules/absolute-mobile-observability/android/build.gradle"),
29127
29421
  androidBuild
29128
29422
  ],
29129
29423
  [
29130
- join15(project, "modules/absolute-mobile-observability/android/src/main/AndroidManifest.xml"),
29424
+ join16(project, "modules/absolute-mobile-observability/android/src/main/AndroidManifest.xml"),
29131
29425
  androidManifest
29132
29426
  ],
29133
29427
  [
29134
- join15(project, "modules/absolute-mobile-observability/android/src/main/java/expo/modules/absolutemobileobservability/AbsoluteMobileObservabilityModule.kt"),
29428
+ join16(project, "modules/absolute-mobile-observability/android/src/main/java/expo/modules/absolutemobileobservability/AbsoluteMobileObservabilityModule.kt"),
29135
29429
  androidModule
29136
29430
  ],
29137
29431
  [
29138
- join15(project, "src/generated/AbsoluteNativeObservability.ts"),
29432
+ join16(project, "src/generated/AbsoluteNativeObservability.ts"),
29139
29433
  expoNativeObservabilityRuntimeSource
29140
29434
  ]
29141
29435
  ]);
@@ -29144,7 +29438,7 @@ var absoluteExpoNativeObservabilityPaths = (project) => [
29144
29438
  ];
29145
29439
 
29146
29440
  // src/mobile/expoActivityResultRecovery.ts
29147
- import { join as join16 } from "path";
29441
+ import { join as join17 } from "path";
29148
29442
  var HEADER2 = `// Generated by AbsoluteJS. Edit absolute.config.ts, then run absolute mobile sync.
29149
29443
  `;
29150
29444
  var XML_HEADER2 = `<!-- Generated by AbsoluteJS. Edit absolute.config.ts, then run absolute mobile sync. -->
@@ -29271,6 +29565,15 @@ class AbsoluteActivityResultRecoveryModule : Module() {
29271
29565
  Log.d("AbsoluteJS", "Expo application runtime ready for Android activity results")
29272
29566
  }
29273
29567
 
29568
+ Function("markEmbeddedWebReady") {
29569
+ Log.i("AbsoluteJS", "Expo embedded web content ready")
29570
+ }
29571
+
29572
+ Function("markEmbeddedWebPhase") { phase: String ->
29573
+ val allowed = setOf("assets-start", "assets-ready", "assets-root-failed", "assets-directory-failed", "assets-destination-failed", "assets-module-failed", "assets-source-failed", "assets-download-failed", "assets-copy-failed", "assets-read-failed", "assets-write-failed", "assets-finalize-failed", "assets-unexpected-failed", "devices-start", "devices-ready", "devices-failed")
29574
+ if (allowed.contains(phase)) Log.i("AbsoluteJS", "Expo embedded web phase: " + phase)
29575
+ }
29576
+
29274
29577
  Function("takePendingCancellation") {
29275
29578
  AbsoluteActivityResultRecoveryState.takePendingCancellation()
29276
29579
  }
@@ -29281,6 +29584,8 @@ var runtime = `${HEADER2}import { requireNativeModule } from 'expo-modules-core'
29281
29584
 
29282
29585
  type AbsoluteActivityResultRecoveryNative = {
29283
29586
  markApplicationRuntimeReady(): void;
29587
+ markEmbeddedWebPhase(phase: AbsoluteEmbeddedWebPhase): void;
29588
+ markEmbeddedWebReady(): void;
29284
29589
  takePendingCancellation(): boolean;
29285
29590
  };
29286
29591
 
@@ -29291,28 +29596,52 @@ const native = requireNativeModule<AbsoluteActivityResultRecoveryNative>(
29291
29596
  export const markAbsoluteApplicationRuntimeReady = () =>
29292
29597
  native.markApplicationRuntimeReady();
29293
29598
 
29599
+ export const markAbsoluteEmbeddedWebReady = () =>
29600
+ native.markEmbeddedWebReady();
29601
+
29602
+ export type AbsoluteEmbeddedWebPhase =
29603
+ | 'assets-start'
29604
+ | 'assets-ready'
29605
+ | 'assets-root-failed'
29606
+ | 'assets-directory-failed'
29607
+ | 'assets-destination-failed'
29608
+ | 'assets-module-failed'
29609
+ | 'assets-source-failed'
29610
+ | 'assets-download-failed'
29611
+ | 'assets-copy-failed'
29612
+ | 'assets-read-failed'
29613
+ | 'assets-write-failed'
29614
+ | 'assets-finalize-failed'
29615
+ | 'assets-unexpected-failed'
29616
+ | 'devices-start'
29617
+ | 'devices-ready'
29618
+ | 'devices-failed';
29619
+
29620
+ export const markAbsoluteEmbeddedWebPhase = (phase: AbsoluteEmbeddedWebPhase) =>
29621
+ native.markEmbeddedWebPhase(phase);
29622
+
29294
29623
  export const takeAbsoluteActivityResultCancellation = () =>
29295
29624
  native.takePendingCancellation();
29296
29625
  `;
29297
29626
  var absoluteExpoActivityResultRecoveryFiles = (project) => new Map([
29298
29627
  [
29299
- join16(project, "modules/absolute-activity-result-recovery/expo-module.config.json"),
29628
+ join17(project, "modules/absolute-activity-result-recovery/expo-module.config.json"),
29300
29629
  moduleConfig2
29301
29630
  ],
29302
29631
  [
29303
- join16(project, "modules/absolute-activity-result-recovery/android/build.gradle"),
29632
+ join17(project, "modules/absolute-activity-result-recovery/android/build.gradle"),
29304
29633
  androidBuild2
29305
29634
  ],
29306
29635
  [
29307
- join16(project, "modules/absolute-activity-result-recovery/android/src/main/AndroidManifest.xml"),
29636
+ join17(project, "modules/absolute-activity-result-recovery/android/src/main/AndroidManifest.xml"),
29308
29637
  androidManifest2
29309
29638
  ],
29310
29639
  [
29311
- join16(project, "modules/absolute-activity-result-recovery/android/src/main/java/expo/modules/absoluteactivityresultrecovery/AbsoluteActivityResultRecoveryModule.kt"),
29640
+ join17(project, "modules/absolute-activity-result-recovery/android/src/main/java/expo/modules/absoluteactivityresultrecovery/AbsoluteActivityResultRecoveryModule.kt"),
29312
29641
  androidModule2
29313
29642
  ],
29314
29643
  [
29315
- join16(project, "src/generated/AbsoluteActivityResultRecovery.ts"),
29644
+ join17(project, "src/generated/AbsoluteActivityResultRecovery.ts"),
29316
29645
  runtime
29317
29646
  ]
29318
29647
  ]);
@@ -29322,15 +29651,15 @@ var EXPO_GENERATED_HEADER = `// Generated by AbsoluteJS. Edit absolute.config.ts
29322
29651
  `;
29323
29652
  var EXPO_ASSET_EXTENSION = ".absasset";
29324
29653
  var EXPO_PROJECT_MARKER = ".absolutejs-expo-project";
29325
- var exists3 = async (path) => {
29654
+ var exists4 = async (path) => {
29326
29655
  try {
29327
- await access10(path);
29656
+ await access11(path);
29328
29657
  return true;
29329
29658
  } catch {
29330
29659
  return false;
29331
29660
  }
29332
29661
  };
29333
- var isRecord8 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
29662
+ var isRecord9 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
29334
29663
  var requireManifestString = (value, field2) => {
29335
29664
  if (typeof value !== "string" || !value) {
29336
29665
  throw new TypeError(`AbsoluteJS mobile manifest ${field2} is invalid.`);
@@ -29338,11 +29667,11 @@ var requireManifestString = (value, field2) => {
29338
29667
  return value;
29339
29668
  };
29340
29669
  var expoNativeDataManifest = (value) => {
29341
- if (!isRecord8(value) || !Array.isArray(value.pages) || !Array.isArray(value.routes)) {
29670
+ if (!isRecord9(value) || !Array.isArray(value.pages) || !Array.isArray(value.routes)) {
29342
29671
  throw new TypeError("AbsoluteJS mobile manifest is invalid.");
29343
29672
  }
29344
29673
  const pages = value.pages.map((page) => {
29345
- if (!isRecord8(page))
29674
+ if (!isRecord9(page))
29346
29675
  throw new TypeError("AbsoluteJS mobile manifest page is invalid.");
29347
29676
  return {
29348
29677
  bundleHash: requireManifestString(page.bundleHash, "page.bundleHash"),
@@ -29351,7 +29680,7 @@ var expoNativeDataManifest = (value) => {
29351
29680
  };
29352
29681
  });
29353
29682
  const routes = value.routes.flatMap((route) => {
29354
- if (!isRecord8(route) || typeof route.method !== "string") {
29683
+ if (!isRecord9(route) || typeof route.method !== "string") {
29355
29684
  throw new TypeError("AbsoluteJS mobile manifest route is invalid.");
29356
29685
  }
29357
29686
  if (route.method !== "GET")
@@ -29366,7 +29695,7 @@ var expoNativeDataManifest = (value) => {
29366
29695
  });
29367
29696
  return {
29368
29697
  appBuild: requireManifestString(value.appBuild, "appBuild"),
29369
- ...isRecord8(value.observability) && typeof value.observability.endpoint === "string" && typeof value.observability.project === "string" && typeof value.observability.sampleRate === "number" ? {
29698
+ ...isRecord9(value.observability) && typeof value.observability.endpoint === "string" && typeof value.observability.project === "string" && typeof value.observability.sampleRate === "number" ? {
29370
29699
  observability: {
29371
29700
  endpoint: value.observability.endpoint,
29372
29701
  ...typeof value.observability.environment === "string" ? { environment: value.observability.environment } : {},
@@ -29381,7 +29710,7 @@ var expoNativeDataManifest = (value) => {
29381
29710
  };
29382
29711
  };
29383
29712
  var portableRelative2 = (from, destination) => {
29384
- const value = relative10(from, destination).replaceAll("\\", "/");
29713
+ const value = relative11(from, destination).replaceAll("\\", "/");
29385
29714
  return value.startsWith(".") ? value : `./${value}`;
29386
29715
  };
29387
29716
  var routeSegments = (route) => {
@@ -29397,7 +29726,7 @@ var routeSegments = (route) => {
29397
29726
  return segment;
29398
29727
  });
29399
29728
  };
29400
- var routeFile = (project, route) => join17(project, "app", ...routeSegments(route), "index.tsx");
29729
+ var routeFile = (project, route) => join18(project, "app", ...routeSegments(route), "index.tsx");
29401
29730
  var packageDependencies = (plan) => Object.fromEntries(plan.requiredPackages.map((spec) => {
29402
29731
  const separator = spec.lastIndexOf("@");
29403
29732
  return [spec.slice(0, separator), spec.slice(separator + 1)];
@@ -29951,7 +30280,7 @@ ${push ? `absoluteExpoAuth.onPrincipalChange(principal => {
29951
30280
  `;
29952
30281
  };
29953
30282
  var authRuntimeSource = (auth, appId) => {
29954
- const storageIdentity = createHash12("sha256").update(appId).digest("hex").slice(0, 24);
30283
+ const storageIdentity = createHash13("sha256").update(appId).digest("hex").slice(0, 24);
29955
30284
  return `${EXPO_GENERATED_HEADER}import { createAbsoluteExpoAuthClient } from '@absolutejs/auth-expo';
29956
30285
  import { createMobileAuthTransport, installAuthClientRuntimeTransport } from '@absolutejs/auth/client/mobile';
29957
30286
 
@@ -29983,7 +30312,7 @@ export const startAbsoluteExpoAuth = () => {
29983
30312
  `;
29984
30313
  };
29985
30314
  var syncRuntimeSource = (config, schema) => {
29986
- const storageIdentity = createHash12("sha256").update(config.appId).digest("hex").slice(0, 24);
30315
+ const storageIdentity = createHash13("sha256").update(config.appId).digest("hex").slice(0, 24);
29987
30316
  const backgroundEndpoint = new URL("/__absolute/sync/background", config.productionOrigin).href;
29988
30317
  const backgroundTask = `${config.appId}.absolutejs.sync`;
29989
30318
  return `${EXPO_GENERATED_HEADER}import { runHeadlessSync } from '@absolutejs/sync/client/headless';
@@ -30102,10 +30431,11 @@ var webHostSource = (config, auth, sync) => {
30102
30431
  return `${EXPO_GENERATED_HEADER}import * as Linking from 'expo-linking';
30103
30432
  import { router, usePathname } from 'expo-router';
30104
30433
  import { useEffect, useMemo, useRef, useState } from 'react';
30105
- import { ActivityIndicator, BackHandler, Platform, StyleSheet, View } from 'react-native';
30434
+ import { ActivityIndicator, BackHandler, Platform, Pressable, StyleSheet, Text, View } from 'react-native';
30106
30435
  import { useSafeAreaInsets } from 'react-native-safe-area-context';
30107
30436
  import { WebView, type WebViewMessageEvent } from 'react-native-webview';
30108
30437
  import { materializeAbsoluteWebBundle } from './webAssets';
30438
+ import { markAbsoluteEmbeddedWebPhase, markAbsoluteEmbeddedWebReady } from './AbsoluteActivityResultRecovery';
30109
30439
  import { createExpoDevicesBridgeHost } from '@absolutejs/devices-expo/bridge';
30110
30440
  import { absoluteExpoDevices, beforeAbsoluteExpoDeviceSignOut } from './AbsoluteDevices';
30111
30441
  ${auth ? "import { absoluteExpoAuth, getAbsoluteExpoAuthPrincipal, startAbsoluteExpoAuth } from './AbsoluteAuth';" : ""}
@@ -30269,7 +30599,10 @@ export function AbsoluteWebHost({ path }: AbsoluteWebHostProps = {}) {
30269
30599
  const canGoBack = useRef(false);
30270
30600
  const [runtimeReady, setRuntimeReady] = useState(!AUTH_ENABLED && !SYNC_ENABLED);
30271
30601
  const [devicesReady, setDevicesReady] = useState(false);
30602
+ const [startupError, setStartupError] = useState<'assets' | 'devices'>();
30603
+ const [startupRevision, setStartupRevision] = useState(0);
30272
30604
  const activeWebPath = useRef(pathname);
30605
+ const embeddedReadyReported = useRef(false);
30273
30606
  const webSource = useMemo(() => indexUri ? { uri: indexUri } : undefined, [indexUri]);
30274
30607
 
30275
30608
  useEffect(() => {
@@ -30303,8 +30636,18 @@ export function AbsoluteWebHost({ path }: AbsoluteWebHostProps = {}) {
30303
30636
  setIndexUri(target.href);
30304
30637
  return;
30305
30638
  }
30306
- void materializeAbsoluteWebBundle().then(uri => setIndexUri(uri + '?absolutePath=' + encodeURIComponent(pathname)));
30307
- }, [pathname]);
30639
+ markAbsoluteEmbeddedWebPhase('assets-start');
30640
+ void materializeAbsoluteWebBundle().then(uri => {
30641
+ markAbsoluteEmbeddedWebPhase('assets-ready');
30642
+ setIndexUri(uri + '?absolutePath=' + encodeURIComponent(pathname));
30643
+ }).catch(error => {
30644
+ const phase = error instanceof Error && (error.message === 'assets-root-failed' || error.message === 'assets-directory-failed' || error.message === 'assets-destination-failed' || error.message === 'assets-module-failed' || error.message === 'assets-source-failed' || error.message === 'assets-download-failed' || error.message === 'assets-copy-failed' || error.message === 'assets-read-failed' || error.message === 'assets-write-failed' || error.message === 'assets-finalize-failed')
30645
+ ? error.message
30646
+ : 'assets-unexpected-failed';
30647
+ markAbsoluteEmbeddedWebPhase(phase);
30648
+ setStartupError('assets');
30649
+ });
30650
+ }, [pathname, startupRevision]);
30308
30651
  useEffect(() => {
30309
30652
  webView.current?.injectJavaScript(hostMetricsScript(safeAreaInsets));
30310
30653
  }, [safeAreaInsets.bottom, safeAreaInsets.left, safeAreaInsets.right, safeAreaInsets.top]);
@@ -30324,13 +30667,19 @@ export function AbsoluteWebHost({ path }: AbsoluteWebHostProps = {}) {
30324
30667
  };
30325
30668
  useEffect(() => {
30326
30669
  let active = true;
30670
+ markAbsoluteEmbeddedWebPhase('devices-start');
30327
30671
  void createExpoDevicesBridgeHost(absoluteExpoDevices, (event, payload) => {
30328
30672
  if (!active) return;
30329
30673
  respond({ event, format: BRIDGE_FORMAT, kind: 'event', path: activeWebPath.current, payload });
30330
30674
  }).then(host => {
30331
30675
  if (!active) return void Promise.resolve(host.close()).catch(() => undefined);
30332
30676
  devicesBridge.current = host;
30677
+ markAbsoluteEmbeddedWebPhase('devices-ready');
30333
30678
  setDevicesReady(true);
30679
+ }).catch(() => {
30680
+ if (!active) return;
30681
+ markAbsoluteEmbeddedWebPhase('devices-failed');
30682
+ setStartupError('devices');
30334
30683
  });
30335
30684
  return () => {
30336
30685
  active = false;
@@ -30338,7 +30687,7 @@ export function AbsoluteWebHost({ path }: AbsoluteWebHostProps = {}) {
30338
30687
  devicesBridge.current = undefined;
30339
30688
  if (host) void Promise.resolve(host.close()).catch(() => undefined);
30340
30689
  };
30341
- }, []);
30690
+ }, [startupRevision]);
30342
30691
  const hasOrigin = (source: string, origin: string) => {
30343
30692
  try { return new URL(source).origin === origin; } catch { return false; }
30344
30693
  };
@@ -30351,6 +30700,10 @@ export function AbsoluteWebHost({ path }: AbsoluteWebHostProps = {}) {
30351
30700
  if (message.kind === 'event' && (message.event === 'navigation' || message.event === 'ready')) {
30352
30701
  const target = new URL(message.path, PRODUCTION_ORIGIN);
30353
30702
  if (target.origin !== PRODUCTION_ORIGIN) return;
30703
+ if (message.event === 'ready' && !DEV_ORIGIN && !embeddedReadyReported.current) {
30704
+ embeddedReadyReported.current = true;
30705
+ markAbsoluteEmbeddedWebReady();
30706
+ }
30354
30707
  if (isNativeRoute(target.pathname)) router.push(message.path as never);
30355
30708
  else activeWebPath.current = message.path;
30356
30709
  return;
@@ -30390,6 +30743,15 @@ export function AbsoluteWebHost({ path }: AbsoluteWebHostProps = {}) {
30390
30743
  }
30391
30744
  };
30392
30745
 
30746
+ if (startupError) return <View style={styles.loading}>
30747
+ <Text accessibilityRole="alert" style={styles.error}>Embedded content could not start.</Text>
30748
+ <Pressable accessibilityRole="button" onPress={() => {
30749
+ setStartupError(undefined);
30750
+ setIndexUri(undefined);
30751
+ setDevicesReady(false);
30752
+ setStartupRevision(value => value + 1);
30753
+ }} style={styles.retry}><Text>Try again</Text></Pressable>
30754
+ </View>;
30393
30755
  if (!webSource || !runtimeReady || !devicesReady) return <View style={styles.loading}><ActivityIndicator /></View>;
30394
30756
  return <WebView
30395
30757
  allowFileAccess
@@ -30415,7 +30777,7 @@ export function AbsoluteWebHost({ path }: AbsoluteWebHostProps = {}) {
30415
30777
  />;
30416
30778
  }
30417
30779
 
30418
- const styles = StyleSheet.create({ loading: { alignItems: 'center', flex: 1, justifyContent: 'center' }, web: { flex: 1 } });
30780
+ const styles = StyleSheet.create({ error: { marginBottom: 12 }, loading: { alignItems: 'center', flex: 1, justifyContent: 'center' }, retry: { borderWidth: 1, paddingHorizontal: 16, paddingVertical: 12 }, web: { flex: 1 } });
30419
30781
  `;
30420
30782
  };
30421
30783
  var webRouteSource = `${EXPO_GENERATED_HEADER}import { AbsoluteWebHost } from '../src/generated/AbsoluteWebHost';
@@ -30609,8 +30971,8 @@ const styles = StyleSheet.create({
30609
30971
  error: { color: '#b91c1c', fontSize: 16, textAlign: 'center' }
30610
30972
  });
30611
30973
  `;
30612
- var nativeWrapperSource = (wrapper, module, runtime2, route) => `${EXPO_GENERATED_HEADER}import ApplicationNativeRoute from ${JSON.stringify(portableRelative2(dirname10(wrapper), module).replace(/\.(?:[cm]?[jt]sx?)$/u, ""))};
30613
- import { createAbsoluteNativeRoute, createAbsoluteNativeRouteErrorBoundary } from ${JSON.stringify(portableRelative2(dirname10(wrapper), runtime2).replace(/\.(?:[cm]?[jt]sx?)$/u, ""))};
30974
+ var nativeWrapperSource = (wrapper, module, runtime2, route) => `${EXPO_GENERATED_HEADER}import ApplicationNativeRoute from ${JSON.stringify(portableRelative2(dirname11(wrapper), module).replace(/\.(?:[cm]?[jt]sx?)$/u, ""))};
30975
+ import { createAbsoluteNativeRoute, createAbsoluteNativeRouteErrorBoundary } from ${JSON.stringify(portableRelative2(dirname11(wrapper), runtime2).replace(/\.(?:[cm]?[jt]sx?)$/u, ""))};
30614
30976
 
30615
30977
  export const ErrorBoundary = createAbsoluteNativeRouteErrorBoundary(${JSON.stringify(route)});
30616
30978
  export default createAbsoluteNativeRoute(ApplicationNativeRoute, ${JSON.stringify(route)});
@@ -30652,9 +31014,9 @@ var expoTsConfig = (projectRoot, project, auth, sync) => ({
30652
31014
  extends: "expo/tsconfig.base"
30653
31015
  });
30654
31016
  var writeManagedFile = async (path, source, force) => {
30655
- await mkdir11(dirname10(path), { recursive: true });
30656
- if (await exists3(path)) {
30657
- const current = await readFile14(path, "utf8");
31017
+ await mkdir12(dirname11(path), { recursive: true });
31018
+ if (await exists4(path)) {
31019
+ const current = await readFile15(path, "utf8");
30658
31020
  if (current === source)
30659
31021
  return false;
30660
31022
  if (!force && !current.startsWith(EXPO_GENERATED_HEADER)) {
@@ -30662,32 +31024,32 @@ var writeManagedFile = async (path, source, force) => {
30662
31024
  }
30663
31025
  }
30664
31026
  const temporary = `${path}.${crypto.randomUUID()}.tmp`;
30665
- await writeFile12(temporary, source, { flag: "wx" });
30666
- await rename11(temporary, path);
31027
+ await writeFile13(temporary, source, { flag: "wx" });
31028
+ await rename12(temporary, path);
30667
31029
  return true;
30668
31030
  };
30669
31031
  var pruneManagedFiles = async (paths) => {
30670
31032
  const removed = await Promise.all(paths.map(async (path) => {
30671
- if (!await exists3(path))
31033
+ if (!await exists4(path))
30672
31034
  return false;
30673
- const source = await readFile14(path, "utf8");
31035
+ const source = await readFile15(path, "utf8");
30674
31036
  if (!source.startsWith(EXPO_GENERATED_HEADER) && !path.endsWith("expo-module.config.json"))
30675
31037
  return false;
30676
- await rm10(path, { force: true });
31038
+ await rm11(path, { force: true });
30677
31039
  return true;
30678
31040
  }));
30679
31041
  return removed.filter(Boolean).length;
30680
31042
  };
30681
31043
  var pruneStaleManagedExpoRoutes = async (project, expected) => {
30682
- const appDirectory = join17(project, "app");
30683
- if (!await exists3(appDirectory))
31044
+ const appDirectory = join18(project, "app");
31045
+ if (!await exists4(appDirectory))
30684
31046
  return 0;
30685
31047
  const files = await walkFiles(appDirectory);
30686
31048
  const stale = (await Promise.all(files.map(async (path) => ({
30687
- managed: path.endsWith(".tsx") && (await readFile14(path, "utf8")).startsWith(EXPO_GENERATED_HEADER),
31049
+ managed: path.endsWith(".tsx") && (await readFile15(path, "utf8")).startsWith(EXPO_GENERATED_HEADER),
30688
31050
  path
30689
31051
  })))).filter(({ managed, path }) => managed && !expected.has(path));
30690
- await Promise.all(stale.map(({ path }) => rm10(path, { force: true })));
31052
+ await Promise.all(stale.map(({ path }) => rm11(path, { force: true })));
30691
31053
  return stale.length;
30692
31054
  };
30693
31055
  var jsonSource = (value) => `${JSON.stringify(value, null, "\t")}
@@ -30710,7 +31072,7 @@ export const ABSOLUTE_MOBILE_MANIFEST: AbsoluteMobileManifest | undefined = unde
30710
31072
  var writeAbsoluteExpoProject = async (config, options) => {
30711
31073
  if (config.engine !== "expo")
30712
31074
  throw new TypeError("Expo project generation requires mobile.engine: expo.");
30713
- const projectRoot = resolve12(options.projectRoot);
31075
+ const projectRoot = resolve13(options.projectRoot);
30714
31076
  const project = config.nativeProjectDirectory;
30715
31077
  const auth = resolveAbsoluteMobileAuthManifest(projectRoot, config);
30716
31078
  const devices = resolveAbsoluteDeviceCapabilityPlan(projectRoot, "expo");
@@ -30719,7 +31081,7 @@ var writeAbsoluteExpoProject = async (config, options) => {
30719
31081
  const runtimeFingerprint = resolveAbsoluteMobileUpdateRuntime(config, projectRoot).fingerprint;
30720
31082
  const routeModules = Object.entries(config.expoNativeRoutes);
30721
31083
  const moduleChecks = await Promise.all(routeModules.map(async ([route, module]) => ({
30722
- exists: await exists3(module),
31084
+ exists: await exists4(module),
30723
31085
  module,
30724
31086
  route
30725
31087
  })));
@@ -30727,20 +31089,20 @@ var writeAbsoluteExpoProject = async (config, options) => {
30727
31089
  if (missing) {
30728
31090
  throw new TypeError(`Expo native route ${missing.route} references missing module ${missing.module}.`);
30729
31091
  }
30730
- const marker = join17(project, EXPO_PROJECT_MARKER);
30731
- if (await exists3(project) && !await exists3(marker)) {
31092
+ const marker = join18(project, EXPO_PROJECT_MARKER);
31093
+ if (await exists4(project) && !await exists4(marker)) {
30732
31094
  const entries = await readdir4(project);
30733
31095
  if (entries.length > 0 && !options.force) {
30734
31096
  throw new TypeError(`Expo project directory ${project} is not AbsoluteJS-managed; rerun with --force only after reviewing it.`);
30735
31097
  }
30736
31098
  }
30737
- await mkdir11(project, { recursive: true });
30738
- await writeFile12(marker, `format=1
31099
+ await mkdir12(project, { recursive: true });
31100
+ await writeFile13(marker, `format=1
30739
31101
  `);
30740
31102
  const authEnabled = Boolean(auth);
30741
31103
  const files = new Map([
30742
31104
  [
30743
- join17(project, ".gitignore"),
31105
+ join18(project, ".gitignore"),
30744
31106
  `.expo/
30745
31107
  android/
30746
31108
  ios/
@@ -30748,45 +31110,45 @@ node_modules/
30748
31110
  `
30749
31111
  ],
30750
31112
  [
30751
- join17(project, "app.json"),
31113
+ join18(project, "app.json"),
30752
31114
  jsonSource(expoAppConfig(config, authEnabled, syncEnabled, devices, runtimeFingerprint))
30753
31115
  ],
30754
- [join17(project, "app.config.js"), expoDynamicAppConfig],
31116
+ [join18(project, "app.config.js"), expoDynamicAppConfig],
30755
31117
  [
30756
- join17(project, "package.json"),
31118
+ join18(project, "package.json"),
30757
31119
  jsonSource(expoPackage(authEnabled, syncEnabled, devices, config.updates !== undefined))
30758
31120
  ],
30759
- [join17(project, "metro.config.js"), metroConfig(projectRoot)],
31121
+ [join18(project, "metro.config.js"), metroConfig(projectRoot)],
30760
31122
  [
30761
- join17(project, "plugins", "withAbsoluteDevelopmentCa.js"),
31123
+ join18(project, "plugins", "withAbsoluteDevelopmentCa.js"),
30762
31124
  expoDevelopmentCaPlugin
30763
31125
  ],
30764
31126
  [
30765
- join17(project, "plugins", "withAbsoluteActivityResultRecovery.js"),
31127
+ join18(project, "plugins", "withAbsoluteActivityResultRecovery.js"),
30766
31128
  expoActivityResultRecoveryPlugin
30767
31129
  ],
30768
31130
  [
30769
- join17(project, "tsconfig.json"),
31131
+ join18(project, "tsconfig.json"),
30770
31132
  jsonSource(expoTsConfig(projectRoot, project, authEnabled, syncEnabled))
30771
31133
  ],
30772
31134
  [
30773
- join17(project, "app", "_layout.tsx"),
31135
+ join18(project, "app", "_layout.tsx"),
30774
31136
  layoutSource(authEnabled, syncEnabled, config.updates !== undefined, config.observability !== undefined)
30775
31137
  ],
30776
31138
  [
30777
- join17(project, "app", "__absolute", "native", "index.tsx"),
31139
+ join18(project, "app", "__absolute", "native", "index.tsx"),
30778
31140
  nativeDiagnosticSource
30779
31141
  ],
30780
31142
  [
30781
- join17(project, "src", "generated", "AbsoluteDevices.ts"),
31143
+ join18(project, "src", "generated", "AbsoluteDevices.ts"),
30782
31144
  devicesRuntimeSource(config, devices, authEnabled)
30783
31145
  ],
30784
31146
  [
30785
- join17(project, "src", "generated", "AbsoluteNativeRoute.tsx"),
31147
+ join18(project, "src", "generated", "AbsoluteNativeRoute.tsx"),
30786
31148
  nativeRouteRuntimeSource(authEnabled)
30787
31149
  ],
30788
31150
  [
30789
- join17(project, "src", "generated", "AbsoluteWebHost.tsx"),
31151
+ join18(project, "src", "generated", "AbsoluteWebHost.tsx"),
30790
31152
  webHostSource(config, auth, syncEnabled)
30791
31153
  ]
30792
31154
  ]);
@@ -30797,31 +31159,31 @@ node_modules/
30797
31159
  files.set(path, source);
30798
31160
  }
30799
31161
  if (config.updates) {
30800
- files.set(join17(project, "src", "generated", "AbsoluteUpdates.ts"), updatesRuntimeSource(config));
31162
+ files.set(join18(project, "src", "generated", "AbsoluteUpdates.ts"), updatesRuntimeSource(config));
30801
31163
  }
30802
31164
  const expoCodeSigning = config.updates?.expoCodeSigning;
30803
31165
  if (expoCodeSigning)
30804
- files.set(join17(project, "certs", "absolute-mobile-update.pem"), expoCodeSigning.certificatePem);
31166
+ files.set(join18(project, "certs", "absolute-mobile-update.pem"), expoCodeSigning.certificatePem);
30805
31167
  if (auth) {
30806
- files.set(join17(project, "src", "generated", "AbsoluteAuth.ts"), authRuntimeSource(auth, config.appId));
31168
+ files.set(join18(project, "src", "generated", "AbsoluteAuth.ts"), authRuntimeSource(auth, config.appId));
30807
31169
  }
30808
31170
  if (syncSchema) {
30809
- files.set(join17(project, "src", "generated", "AbsoluteSync.ts"), syncRuntimeSource(config, syncSchema));
31171
+ files.set(join18(project, "src", "generated", "AbsoluteSync.ts"), syncRuntimeSource(config, syncSchema));
30810
31172
  }
30811
- const webAssetsPath = join17(project, "src", "generated", "webAssets.ts");
30812
- if (!await exists3(webAssetsPath)) {
31173
+ const webAssetsPath = join18(project, "src", "generated", "webAssets.ts");
31174
+ if (!await exists4(webAssetsPath)) {
30813
31175
  files.set(webAssetsPath, emptyWebAssetsSource);
30814
31176
  }
30815
31177
  if (!config.expoNativeRoutes["/"]) {
30816
- files.set(join17(project, "app", "index.tsx"), webRouteSource);
31178
+ files.set(join18(project, "app", "index.tsx"), webRouteSource);
30817
31179
  }
30818
- files.set(join17(project, "app", "[...absolute].tsx"), catchAllRouteSource);
30819
- const nativeRouteRuntime = join17(project, "src", "generated", "AbsoluteNativeRoute.tsx");
31180
+ files.set(join18(project, "app", "[...absolute].tsx"), catchAllRouteSource);
31181
+ const nativeRouteRuntime = join18(project, "src", "generated", "AbsoluteNativeRoute.tsx");
30820
31182
  for (const [route, module] of routeModules) {
30821
- const wrapper = route === "/" ? join17(project, "app", "index.tsx") : routeFile(project, route);
31183
+ const wrapper = route === "/" ? join18(project, "app", "index.tsx") : routeFile(project, route);
30822
31184
  files.set(wrapper, nativeWrapperSource(wrapper, module, nativeRouteRuntime, route));
30823
31185
  }
30824
- const removedRoutes = await pruneStaleManagedExpoRoutes(project, new Set([...files.keys()].filter((path) => path.startsWith(`${join17(project, "app")}${sep6}`))));
31186
+ const removedRoutes = await pruneStaleManagedExpoRoutes(project, new Set([...files.keys()].filter((path) => path.startsWith(`${join18(project, "app")}${sep7}`))));
30825
31187
  const removedObservability = config.observability ? 0 : await pruneManagedFiles(absoluteExpoNativeObservabilityPaths(project));
30826
31188
  const changes = await Promise.all([...files].map(([path, source]) => writeManagedFile(path, source, true)));
30827
31189
  const changed = removedRoutes + removedObservability + changes.filter(Boolean).length;
@@ -30830,7 +31192,7 @@ node_modules/
30830
31192
  var walkFiles = async (root, directory = root) => {
30831
31193
  const entries = await readdir4(directory, { withFileTypes: true });
30832
31194
  const nested = await Promise.all(entries.map((entry) => {
30833
- const path = join17(directory, entry.name);
31195
+ const path = join18(directory, entry.name);
30834
31196
  if (entry.isDirectory())
30835
31197
  return walkFiles(root, path);
30836
31198
  if (entry.isFile())
@@ -30841,7 +31203,7 @@ var walkFiles = async (root, directory = root) => {
30841
31203
  };
30842
31204
  var renameIfPresent = async (source, destination) => {
30843
31205
  try {
30844
- await rename11(source, destination);
31206
+ await rename12(source, destination);
30845
31207
  return true;
30846
31208
  } catch (error) {
30847
31209
  if (typeof error === "object" && error !== null && Reflect.get(error, "code") === "ENOENT") {
@@ -30854,87 +31216,130 @@ var installStagedDirectory = async (staging, destination) => {
30854
31216
  const backup = `${destination}.previous-${crypto.randomUUID()}`;
30855
31217
  const moved = await renameIfPresent(destination, backup);
30856
31218
  try {
30857
- await rename11(staging, destination);
31219
+ await rename12(staging, destination);
30858
31220
  if (moved)
30859
- await rm10(backup, { force: true, recursive: true });
31221
+ await rm11(backup, { force: true, recursive: true });
30860
31222
  } catch (error) {
30861
31223
  if (moved)
30862
- await rename11(backup, destination);
31224
+ await rename12(backup, destination);
30863
31225
  throw error;
30864
31226
  }
30865
31227
  };
30866
- var assetModuleSource = (assets, bundleId, manifest) => `${EXPO_GENERATED_HEADER}import { Asset } from 'expo-asset';
31228
+ var assetModuleSource = (assets, archiveAsset, bundleId, manifest) => `${EXPO_GENERATED_HEADER}import { Asset } from 'expo-asset';
30867
31229
  import { Directory, File, Paths } from 'expo-file-system';
31230
+ import { copyAsync as copyLegacyAsync } from 'expo-file-system/legacy';
30868
31231
 
30869
31232
  ${nativeDataManifestTypeSource}
30870
31233
  declare const require: (path: string) => number;
30871
31234
  const BUNDLE_ID = ${JSON.stringify(bundleId)};
30872
31235
  export const ABSOLUTE_MOBILE_MANIFEST: AbsoluteMobileManifest = ${JSON.stringify(manifest)};
31236
+ const ARCHIVE_MODULE = require(${JSON.stringify(archiveAsset)});
30873
31237
  const ASSETS = [
30874
- ${assets.map(({ asset, path }) => ` { module: require(${JSON.stringify(asset)}), path: ${JSON.stringify(path)} }`).join(`,
31238
+ ${assets.map((entry) => ` ${JSON.stringify(entry)}`).join(`,
30875
31239
  `)}
30876
31240
  ] as const;
30877
31241
 
30878
31242
  export const materializeAbsoluteWebBundle = async () => {
30879
- const root = new Directory(Paths.document, 'absolutejs-web', BUNDLE_ID);
30880
- root.create({ idempotent: true, intermediates: true });
31243
+ let root: Directory;
31244
+ try {
31245
+ root = new Directory(Paths.document, 'absolutejs-web', BUNDLE_ID);
31246
+ root.create({ idempotent: true, intermediates: true });
31247
+ } catch { throw new Error('assets-root-failed'); }
31248
+ let archive: File;
31249
+ try { archive = new File(root, '.absolutejs-bundle.absasset'); }
31250
+ catch { throw new Error('assets-destination-failed'); }
31251
+ if (!archive.exists) {
31252
+ let asset: Asset;
31253
+ try { asset = Asset.fromModule(ARCHIVE_MODULE); }
31254
+ catch { throw new Error('assets-module-failed'); }
31255
+ try { if (!asset.localUri) asset = await asset.downloadAsync(); }
31256
+ catch { throw new Error('assets-download-failed'); }
31257
+ if (!asset.localUri) throw new Error('assets-download-failed');
31258
+ let source: File;
31259
+ try { source = new File(asset.localUri); }
31260
+ catch { throw new Error('assets-source-failed'); }
31261
+ try { await source.copy(archive); }
31262
+ catch {
31263
+ try { await copyLegacyAsync({ from: asset.localUri, to: archive.uri }); }
31264
+ catch { throw new Error('assets-copy-failed'); }
31265
+ }
31266
+ }
31267
+ let contents: Uint8Array;
31268
+ try { contents = await archive.bytes(); }
31269
+ catch { throw new Error('assets-read-failed'); }
30881
31270
  for (const entry of ASSETS) {
30882
31271
  const parts = entry.path.split('/');
30883
31272
  const name = parts.pop();
30884
- if (!name) throw new Error('AbsoluteJS embedded asset path is invalid.');
30885
- const directory = new Directory(root, ...parts);
30886
- directory.create({ idempotent: true, intermediates: true });
30887
- const destination = new File(directory, name);
30888
- if (destination.exists) continue;
30889
- const asset = await Asset.fromModule(entry.module).downloadAsync();
30890
- if (!asset.localUri) throw new Error('Expo did not materialize an embedded AbsoluteJS asset.');
30891
- new File(asset.localUri).copy(destination);
31273
+ if (!name) throw new Error('assets-directory-failed');
31274
+ let directory: Directory;
31275
+ try {
31276
+ directory = new Directory(root, ...parts);
31277
+ directory.create({ idempotent: true, intermediates: true });
31278
+ }
31279
+ catch { throw new Error('assets-directory-failed'); }
31280
+ let destination: File;
31281
+ try {
31282
+ destination = new File(directory, name);
31283
+ if (destination.exists && destination.size === entry.length) continue;
31284
+ if (destination.exists) destination.delete();
31285
+ } catch { throw new Error('assets-destination-failed'); }
31286
+ try { destination.write(contents.slice(entry.offset, entry.offset + entry.length)); }
31287
+ catch { throw new Error('assets-write-failed'); }
30892
31288
  }
31289
+ try { archive.delete(); }
31290
+ catch { throw new Error('assets-finalize-failed'); }
30893
31291
 
30894
- return new File(root, 'index.html').uri;
31292
+ try { return new File(root, 'index.html').uri; }
31293
+ catch { throw new Error('assets-finalize-failed'); }
30895
31294
  };
30896
31295
  `;
30897
31296
  var syncAbsoluteExpoWebAssets = async (config) => {
30898
31297
  if (config.engine !== "expo")
30899
31298
  throw new TypeError("Expo asset sync requires mobile.engine: expo.");
30900
- const marker = join17(config.nativeProjectDirectory, EXPO_PROJECT_MARKER);
30901
- if (!await exists3(marker)) {
31299
+ const marker = join18(config.nativeProjectDirectory, EXPO_PROJECT_MARKER);
31300
+ if (!await exists4(marker)) {
30902
31301
  throw new TypeError("Expo asset sync requires an AbsoluteJS-managed Expo project. Run mobile init first.");
30903
31302
  }
30904
- const manifestPath = join17(config.bundleDirectory, "absolute-mobile-manifest.json");
30905
- const manifest = JSON.parse(await readFile14(manifestPath, "utf8"));
31303
+ const manifestPath = join18(config.bundleDirectory, "absolute-mobile-manifest.json");
31304
+ const manifest = JSON.parse(await readFile15(manifestPath, "utf8"));
30906
31305
  const nativeDataManifest = expoNativeDataManifest(manifest);
30907
31306
  const { appBuild } = nativeDataManifest;
30908
31307
  const files = await walkFiles(config.bundleDirectory);
30909
- const bundleHash = createHash12("sha256");
30910
- const filesWithContents = await Promise.all(files.map(async (file) => ({ contents: await readFile14(file), file })));
31308
+ const bundleHash = createHash13("sha256");
31309
+ const filesWithContents = await Promise.all(files.map(async (file) => ({ contents: await readFile15(file), file })));
30911
31310
  filesWithContents.forEach(({ contents, file }) => {
30912
- bundleHash.update(relative10(config.bundleDirectory, file).replaceAll("\\", "/"));
31311
+ bundleHash.update(relative11(config.bundleDirectory, file).replaceAll("\\", "/"));
30913
31312
  bundleHash.update("\x00");
30914
31313
  bundleHash.update(contents);
30915
31314
  bundleHash.update("\x00");
30916
31315
  });
30917
31316
  const bundleId = `amexpo_${bundleHash.digest("hex")}`;
30918
- const destination = join17(config.nativeProjectDirectory, "assets", "absolute");
30919
- await mkdir11(dirname10(destination), { recursive: true });
30920
- const staging = await mkdtemp7(join17(dirname10(destination), `.${basename4(destination)}.stage-`));
31317
+ const destination = join18(config.nativeProjectDirectory, "assets", "absolute");
31318
+ await mkdir12(dirname11(destination), { recursive: true });
31319
+ const staging = await mkdtemp8(join18(dirname11(destination), `.${basename5(destination)}.stage-`));
30921
31320
  let assets;
31321
+ let archiveAsset;
30922
31322
  try {
30923
- assets = await Promise.all(files.map(async (source, index) => {
30924
- const name = `${String(index).padStart(6, "0")}${EXPO_ASSET_EXTENSION}`;
30925
- await cp2(source, join17(staging, name));
30926
- return {
30927
- asset: portableRelative2(join17(config.nativeProjectDirectory, "src", "generated"), join17(destination, name)),
30928
- path: relative10(config.bundleDirectory, source).replaceAll("\\", "/")
31323
+ let offset = 0;
31324
+ assets = filesWithContents.map(({ contents, file }) => {
31325
+ const entry = {
31326
+ length: contents.byteLength,
31327
+ offset,
31328
+ path: relative11(config.bundleDirectory, file).replaceAll("\\", "/")
30929
31329
  };
30930
- }));
31330
+ offset += contents.byteLength;
31331
+ return entry;
31332
+ });
31333
+ const name = `bundle${EXPO_ASSET_EXTENSION}`;
31334
+ await writeFile13(join18(staging, name), Buffer.concat(filesWithContents.map(({ contents }) => contents)));
31335
+ archiveAsset = portableRelative2(join18(config.nativeProjectDirectory, "src", "generated"), join18(destination, name));
30931
31336
  await installStagedDirectory(staging, destination);
30932
31337
  } catch (error) {
30933
- await rm10(staging, { force: true, recursive: true });
31338
+ await rm11(staging, { force: true, recursive: true });
30934
31339
  throw error;
30935
31340
  }
30936
- const generated = join17(config.nativeProjectDirectory, "src", "generated", "webAssets.ts");
30937
- await writeManagedFile(generated, assetModuleSource(assets, bundleId, nativeDataManifest), true);
31341
+ const generated = join18(config.nativeProjectDirectory, "src", "generated", "webAssets.ts");
31342
+ await writeManagedFile(generated, assetModuleSource(assets, archiveAsset, bundleId, nativeDataManifest), true);
30938
31343
  return { appBuild, assets: assets.length, bundleId, path: destination };
30939
31344
  };
30940
31345
 
@@ -30972,11 +31377,11 @@ var loadServerApp = async (producerPath) => {
30972
31377
  return { app, exportName };
30973
31378
  };
30974
31379
  var finalizeAbsoluteMobileCompatibilityBuild = async (options) => {
30975
- const buildDirectory = resolve13(options.buildDirectory);
31380
+ const buildDirectory = resolve14(options.buildDirectory);
30976
31381
  const mobile = normalizeAbsoluteMobileConfig(options.mobile, options.projectRoot);
30977
- const root = join18(buildDirectory, ".absolutejs", "mobile-compatibility");
31382
+ const root = join19(buildDirectory, ".absolutejs", "mobile-compatibility");
30978
31383
  const [manifestSource, previous] = await Promise.all([
30979
- readFile15(join18(buildDirectory, "manifest.json"), "utf8"),
31384
+ readFile16(join19(buildDirectory, "manifest.json"), "utf8"),
30980
31385
  readAbsoluteMobileMaterializedReleases(root)
30981
31386
  ]);
30982
31387
  const manifest = JSON.parse(manifestSource);
@@ -30989,11 +31394,11 @@ var finalizeAbsoluteMobileCompatibilityBuild = async (options) => {
30989
31394
  process.env.ABSOLUTE_BUILD_DIR = buildDirectory;
30990
31395
  process.env.ABSOLUTE_COMPILED_RUNTIME = "1";
30991
31396
  if (options.configPath) {
30992
- process.env.ABSOLUTE_CONFIG = resolve13(options.projectRoot, options.configPath);
31397
+ process.env.ABSOLUTE_CONFIG = resolve14(options.projectRoot, options.configPath);
30993
31398
  }
30994
31399
  let loaded;
30995
31400
  try {
30996
- loaded = await loadServerApp(resolve13(options.producerPath));
31401
+ loaded = await loadServerApp(resolve14(options.producerPath));
30997
31402
  } finally {
30998
31403
  restoreEnvironmentVariable("ABSOLUTE_BUILD_DIR", previousBuildDirectory);
30999
31404
  restoreEnvironmentVariable("ABSOLUTE_COMPILED_RUNTIME", previousCompiledRuntime);
@@ -31006,7 +31411,7 @@ var finalizeAbsoluteMobileCompatibilityBuild = async (options) => {
31006
31411
  manifest,
31007
31412
  previousArtifacts: previous.map(({ artifact }) => artifact),
31008
31413
  producerExport: loaded.exportName,
31009
- producerPath: resolve13(options.producerPath),
31414
+ producerPath: resolve14(options.producerPath),
31010
31415
  runtime: String(ABSOLUTE_MOBILE_PAGE_PROTOCOL_VERSION)
31011
31416
  });
31012
31417
  const {
@@ -31256,7 +31661,7 @@ var ABSOLUTE_EXPO_BRIDGE_METHODS = [
31256
31661
  "sync.socket.open",
31257
31662
  "sync.socket.sendChunk"
31258
31663
  ];
31259
- var isRecord9 = (value) => typeof value === "object" && value !== null && !Array.isArray(value) && (Object.getPrototypeOf(value) === Object.prototype || Object.getPrototypeOf(value) === null);
31664
+ var isRecord10 = (value) => typeof value === "object" && value !== null && !Array.isArray(value) && (Object.getPrototypeOf(value) === Object.prototype || Object.getPrototypeOf(value) === null);
31260
31665
  var validId = (value) => typeof value === "string" && /^[A-Za-z0-9_-]{1,80}$/u.test(value);
31261
31666
  var validPath = (value) => typeof value === "string" && value.startsWith("/") && !value.startsWith("//") && value.length <= 4096;
31262
31667
  var parseRequest = (value) => {
@@ -31266,7 +31671,7 @@ var parseRequest = (value) => {
31266
31671
  if (!method) {
31267
31672
  throw new TypeError("Expo bridge method is not allowed.");
31268
31673
  }
31269
- if (!isRecord9(value.params))
31674
+ if (!isRecord10(value.params))
31270
31675
  throw new TypeError("Expo bridge request params must be an object.");
31271
31676
  if (typeof value.path !== "string" || !validPath(value.path))
31272
31677
  throw new TypeError("Expo bridge request path is invalid.");
@@ -31302,7 +31707,7 @@ var parseRequest = (value) => {
31302
31707
  throw new TypeError("Expo bridge HTTP body exceeds 48 KiB.");
31303
31708
  if ((value.params.method === "GET" || value.params.method === "DELETE") && value.params.body !== undefined)
31304
31709
  throw new TypeError("Expo bridge HTTP method cannot contain a body.");
31305
- if (!isRecord9(value.params.headers))
31710
+ if (!isRecord10(value.params.headers))
31306
31711
  throw new TypeError("Expo bridge HTTP headers must be an object.");
31307
31712
  const headersAllowed = Object.entries(value.params.headers).every(([name, header]) => typeof header === "string" && (name.toLowerCase() === "accept" || name.toLowerCase() === "content-type" || name.toLowerCase().startsWith("x-absolute-mobile-")));
31308
31713
  if (!headersAllowed) {
@@ -31328,13 +31733,13 @@ var parseResponse = (value) => {
31328
31733
  if (typeof value.id !== "string" || !validId(value.id))
31329
31734
  throw new TypeError("Expo bridge response id is invalid.");
31330
31735
  if (value.error !== undefined) {
31331
- if (!isRecord9(value.error) || typeof value.error.code !== "string" || typeof value.error.message !== "string") {
31736
+ if (!isRecord10(value.error) || typeof value.error.code !== "string" || typeof value.error.message !== "string") {
31332
31737
  throw new TypeError("Expo bridge response error is invalid.");
31333
31738
  }
31334
31739
  if (value.result !== undefined)
31335
31740
  throw new TypeError("Expo bridge response cannot contain result and error.");
31336
31741
  }
31337
- if (isRecord9(value.error)) {
31742
+ if (isRecord10(value.error)) {
31338
31743
  return {
31339
31744
  error: {
31340
31745
  code: String(value.error.code),
@@ -31358,7 +31763,7 @@ var parseEvent = (value) => {
31358
31763
  }
31359
31764
  if (typeof value.path !== "string" || !validPath(value.path))
31360
31765
  throw new TypeError("Expo bridge event path is invalid.");
31361
- if (value.payload !== undefined && !isRecord9(value.payload)) {
31766
+ if (value.payload !== undefined && !isRecord10(value.payload)) {
31362
31767
  throw new TypeError("Expo bridge event payload must be an object.");
31363
31768
  }
31364
31769
  return {
@@ -31392,7 +31797,7 @@ var parseAbsoluteExpoBridgeMessage = (source) => {
31392
31797
  cause
31393
31798
  });
31394
31799
  }
31395
- if (!isRecord9(parsed) || parsed.format !== ABSOLUTE_EXPO_BRIDGE_FORMAT) {
31800
+ if (!isRecord10(parsed) || parsed.format !== ABSOLUTE_EXPO_BRIDGE_FORMAT) {
31396
31801
  throw new TypeError("Expo bridge message format is unsupported.");
31397
31802
  }
31398
31803
  if (parsed.kind === "request")
@@ -31405,21 +31810,21 @@ var parseAbsoluteExpoBridgeMessage = (source) => {
31405
31810
  };
31406
31811
  // src/mobile/expoCodeSigning.ts
31407
31812
  var import_code_signing_certificates = __toESM(require_main(), 1);
31408
- import { access as access11, mkdir as mkdir12, writeFile as writeFile13 } from "fs/promises";
31409
- import { dirname as dirname11, isAbsolute as isAbsolute6, relative as relative11, resolve as resolve14, sep as sep7 } from "path";
31410
- var exists4 = async (path) => access11(path).then(() => true).catch(() => false);
31411
- var inside = (root, path) => {
31412
- const location2 = relative11(root, path);
31413
- return location2 === "" || location2 !== ".." && !location2.startsWith(`..${sep7}`) && !isAbsolute6(location2);
31813
+ import { access as access12, mkdir as mkdir13, writeFile as writeFile14 } from "fs/promises";
31814
+ import { dirname as dirname12, isAbsolute as isAbsolute7, relative as relative12, resolve as resolve15, sep as sep8 } from "path";
31815
+ var exists5 = async (path) => access12(path).then(() => true).catch(() => false);
31816
+ var inside2 = (root, path) => {
31817
+ const location2 = relative12(root, path);
31818
+ return location2 === "" || location2 !== ".." && !location2.startsWith(`..${sep8}`) && !isAbsolute7(location2);
31414
31819
  };
31415
31820
  var generateAbsoluteExpoCodeSigning = async (options) => {
31416
- const root = resolve14(options.projectRoot);
31417
- const certificatePath = resolve14(root, options.certificatePath);
31418
- const privateKeyPath = resolve14(root, options.privateKeyPath);
31419
- const publicKeyPath = resolve14(root, options.publicKeyPath ?? resolve14(dirname11(privateKeyPath), "public-key.pem"));
31420
- if (!inside(root, certificatePath))
31821
+ const root = resolve15(options.projectRoot);
31822
+ const certificatePath = resolve15(root, options.certificatePath);
31823
+ const privateKeyPath = resolve15(root, options.privateKeyPath);
31824
+ const publicKeyPath = resolve15(root, options.publicKeyPath ?? resolve15(dirname12(privateKeyPath), "public-key.pem"));
31825
+ if (!inside2(root, certificatePath))
31421
31826
  throw new TypeError("Expo code-signing certificate must be written inside the project so store builds can embed it.");
31422
- if (inside(root, privateKeyPath) || inside(root, publicKeyPath))
31827
+ if (inside2(root, privateKeyPath) || inside2(root, publicKeyPath))
31423
31828
  throw new TypeError("Expo code-signing private/public key output must remain outside the project and source control.");
31424
31829
  const commonName = options.commonName.trim();
31425
31830
  if (!commonName || commonName.length > 64)
@@ -31428,7 +31833,7 @@ var generateAbsoluteExpoCodeSigning = async (options) => {
31428
31833
  if (!Number.isSafeInteger(validityYears) || validityYears < 1 || validityYears > 20)
31429
31834
  throw new TypeError("Expo code-signing validity must be an integer from 1 through 20 years.");
31430
31835
  const collisions = (await Promise.all([certificatePath, privateKeyPath, publicKeyPath].map(async (path) => ({
31431
- exists: await exists4(path),
31836
+ exists: await exists5(path),
31432
31837
  path
31433
31838
  })))).filter((entry) => entry.exists);
31434
31839
  if (collisions.length > 0)
@@ -31446,11 +31851,11 @@ var generateAbsoluteExpoCodeSigning = async (options) => {
31446
31851
  import_code_signing_certificates.validateSelfSignedCertificate(certificate, keyPair);
31447
31852
  const { privateKeyPEM, publicKeyPEM } = import_code_signing_certificates.convertKeyPairToPEM(keyPair);
31448
31853
  const certificatePem = import_code_signing_certificates.convertCertificateToCertificatePEM(certificate);
31449
- await Promise.all([certificatePath, privateKeyPath, publicKeyPath].map((path) => mkdir12(dirname11(path), { recursive: true })));
31854
+ await Promise.all([certificatePath, privateKeyPath, publicKeyPath].map((path) => mkdir13(dirname12(path), { recursive: true })));
31450
31855
  await Promise.all([
31451
- writeFile13(certificatePath, certificatePem, { flag: "wx", mode: 420 }),
31452
- writeFile13(privateKeyPath, privateKeyPEM, { flag: "wx", mode: 384 }),
31453
- writeFile13(publicKeyPath, publicKeyPEM, { flag: "wx", mode: 420 })
31856
+ writeFile14(certificatePath, certificatePem, { flag: "wx", mode: 420 }),
31857
+ writeFile14(privateKeyPath, privateKeyPEM, { flag: "wx", mode: 384 }),
31858
+ writeFile14(publicKeyPath, publicKeyPEM, { flag: "wx", mode: 420 })
31454
31859
  ]);
31455
31860
  return {
31456
31861
  certificatePath,
@@ -31552,9 +31957,9 @@ var parseAbsoluteAndroidAccessibilityHierarchy = (source) => [...source.matchAll
31552
31957
  });
31553
31958
  // src/mobile/expoNativeWatcher.ts
31554
31959
  import { watch as watch2 } from "fs";
31555
- import { access as access12, readdir as readdir5, readFile as readFile16 } from "fs/promises";
31556
- import { basename as basename5, join as join19, relative as relative12 } from "path";
31557
- import { createHash as createHash13 } from "crypto";
31960
+ import { access as access13, readdir as readdir5, readFile as readFile17 } from "fs/promises";
31961
+ import { basename as basename6, join as join20, relative as relative13 } from "path";
31962
+ import { createHash as createHash14 } from "crypto";
31558
31963
  var NATIVE_CHANGE_DEBOUNCE_MS2 = 500;
31559
31964
  var ROOT_NATIVE_INPUTS2 = new Set([
31560
31965
  "absolute.config.js",
@@ -31568,13 +31973,13 @@ var ROOT_NATIVE_INPUTS2 = new Set([
31568
31973
  "package.json"
31569
31974
  ]);
31570
31975
  var EXPO_NATIVE_DIRECTORIES = ["modules", "plugins"];
31571
- var exists5 = async (path) => access12(path).then(() => true, () => false);
31976
+ var exists6 = async (path) => access13(path).then(() => true, () => false);
31572
31977
  var filesIn = async (directory, prefix) => {
31573
- if (!await exists5(directory))
31978
+ if (!await exists6(directory))
31574
31979
  return [];
31575
31980
  const entries = await readdir5(directory, { withFileTypes: true });
31576
31981
  const nested = await Promise.all(entries.map((entry) => {
31577
- const path = join19(directory, entry.name);
31982
+ const path = join20(directory, entry.name);
31578
31983
  const name = `${prefix}/${entry.name}`;
31579
31984
  if (entry.isDirectory())
31580
31985
  return filesIn(path, name);
@@ -31583,21 +31988,21 @@ var filesIn = async (directory, prefix) => {
31583
31988
  return nested.flat().sort((left, right) => left.name.localeCompare(right.name));
31584
31989
  };
31585
31990
  var fingerprintAbsoluteExpoNativeInputs = async (options) => {
31586
- const hash = createHash13("sha256");
31991
+ const hash = createHash14("sha256");
31587
31992
  const rootFiles = await Promise.all([...ROOT_NATIVE_INPUTS2].sort().map(async (name) => {
31588
- const path = join19(options.projectRoot, name);
31589
- return await exists5(path) ? [{ name: `root/${name}`, path }] : [];
31993
+ const path = join20(options.projectRoot, name);
31994
+ return await exists6(path) ? [{ name: `root/${name}`, path }] : [];
31590
31995
  }));
31591
- const nativeFiles = await Promise.all(EXPO_NATIVE_DIRECTORIES.map((name) => filesIn(join19(options.expoProjectDirectory, name), name)));
31996
+ const nativeFiles = await Promise.all(EXPO_NATIVE_DIRECTORIES.map((name) => filesIn(join20(options.expoProjectDirectory, name), name)));
31592
31997
  const files = [...rootFiles.flat(), ...nativeFiles.flat()].sort((left, right) => left.name.localeCompare(right.name));
31593
- const contents = await Promise.all(files.map(({ path }) => readFile16(path)));
31998
+ const contents = await Promise.all(files.map(({ path }) => readFile17(path)));
31594
31999
  files.forEach(({ name }, index) => {
31595
32000
  hash.update(name);
31596
32001
  hash.update(contents[index] ?? Buffer.alloc(0));
31597
32002
  });
31598
32003
  return hash.digest("hex");
31599
32004
  };
31600
- var isAbsoluteExpoNativeRootInput = (path) => ROOT_NATIVE_INPUTS2.has(basename5(path));
32005
+ var isAbsoluteExpoNativeRootInput = (path) => ROOT_NATIVE_INPUTS2.has(basename6(path));
31601
32006
  var createAbsoluteExpoNativeWatcher = async (options) => {
31602
32007
  let fingerprint = await fingerprintAbsoluteExpoNativeInputs(options);
31603
32008
  let closed = false;
@@ -31659,14 +32064,14 @@ var createAbsoluteExpoNativeWatcher = async (options) => {
31659
32064
  }
31660
32065
  };
31661
32066
  const nativeDirectories = (await Promise.all(EXPO_NATIVE_DIRECTORIES.map(async (name) => {
31662
- const directory = join19(options.expoProjectDirectory, name);
31663
- return await exists5(directory) ? [directory] : [];
32067
+ const directory = join20(options.expoProjectDirectory, name);
32068
+ return await exists6(directory) ? [directory] : [];
31664
32069
  }))).flat();
31665
32070
  nativeDirectories.forEach((directory) => {
31666
32071
  watchers.push(watch2(directory, { recursive: true }, (_event, filename) => {
31667
32072
  if (!filename)
31668
32073
  return;
31669
- record(relative12(options.expoProjectDirectory, join19(directory, String(filename))), false);
32074
+ record(relative13(options.expoProjectDirectory, join20(directory, String(filename))), false);
31670
32075
  }));
31671
32076
  });
31672
32077
  watchers.push(watch2(options.projectRoot, (_event, filename) => {
@@ -31681,8 +32086,8 @@ var createAbsoluteExpoNativeWatcher = async (options) => {
31681
32086
  return { close };
31682
32087
  };
31683
32088
  // src/mobile/expoUpdate.ts
31684
- import { access as access13, mkdir as mkdir13, readFile as readFile17, writeFile as writeFile14 } from "fs/promises";
31685
- import { dirname as dirname12, extname as extname4, join as join20 } from "path";
32089
+ import { access as access14, mkdir as mkdir14, readFile as readFile18, writeFile as writeFile15 } from "fs/promises";
32090
+ import { dirname as dirname13, extname as extname4, join as join21 } from "path";
31686
32091
  var ABSOLUTE_EXPO_UPDATE_DESCRIPTOR = "_absolute/expo-update.json";
31687
32092
  var ABSOLUTE_EXPO_UPDATE_FORMAT = 1;
31688
32093
  var object4 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
@@ -31748,7 +32153,7 @@ var parseAbsoluteExpoUpdateDescriptor = (value) => {
31748
32153
  };
31749
32154
  };
31750
32155
  var finalizeAbsoluteExpoUpdateExport = async (options) => {
31751
- const metadata = JSON.parse(await readFile17(join20(options.exportDirectory, "metadata.json"), "utf8"));
32156
+ const metadata = JSON.parse(await readFile18(join21(options.exportDirectory, "metadata.json"), "utf8"));
31752
32157
  if (!object4(metadata) || !object4(metadata.fileMetadata))
31753
32158
  throw new TypeError("Expo export metadata.json is invalid.");
31754
32159
  const descriptor = parseAbsoluteExpoUpdateDescriptor({
@@ -31759,12 +32164,12 @@ var finalizeAbsoluteExpoUpdateExport = async (options) => {
31759
32164
  runtimeVersion: options.runtimeVersion
31760
32165
  });
31761
32166
  const referenced = Object.values(descriptor.platforms).flatMap((entry) => entry ? [entry.launchAsset, ...entry.assets] : []);
31762
- await Promise.all(referenced.map(({ path }) => access13(join20(options.exportDirectory, path)).catch(() => {
32167
+ await Promise.all(referenced.map(({ path }) => access14(join21(options.exportDirectory, path)).catch(() => {
31763
32168
  throw new TypeError(`Expo export metadata references missing asset ${path}.`);
31764
32169
  })));
31765
- const destination = join20(options.exportDirectory, ABSOLUTE_EXPO_UPDATE_DESCRIPTOR);
31766
- await mkdir13(dirname12(destination), { recursive: true });
31767
- await writeFile14(destination, `${JSON.stringify(descriptor, null, "\t")}
32170
+ const destination = join21(options.exportDirectory, ABSOLUTE_EXPO_UPDATE_DESCRIPTOR);
32171
+ await mkdir14(dirname13(destination), { recursive: true });
32172
+ await writeFile15(destination, `${JSON.stringify(descriptor, null, "\t")}
31768
32173
  `);
31769
32174
  return { descriptor, path: destination };
31770
32175
  };
@@ -31774,8 +32179,8 @@ init_config();
31774
32179
 
31775
32180
  // src/mobile/ciWorkflow.ts
31776
32181
  import { existsSync as existsSync4 } from "fs";
31777
- import { access as access14, mkdir as mkdir14, readFile as readFile18, writeFile as writeFile15 } from "fs/promises";
31778
- import { dirname as dirname13, extname as extname5, relative as relative13, resolve as resolve15, sep as sep8 } from "path";
32182
+ import { access as access15, mkdir as mkdir15, readFile as readFile19, writeFile as writeFile16 } from "fs/promises";
32183
+ import { dirname as dirname14, extname as extname5, relative as relative14, resolve as resolve16, sep as sep9 } from "path";
31779
32184
  var ABSOLUTE_MOBILE_CI_WORKFLOW_FORMAT = 1;
31780
32185
  var SECRET_NAME_PATTERN = /^[A-Z][A-Z0-9_]*$/u;
31781
32186
  var CI_ENV_INDENTATION = 6;
@@ -31794,9 +32199,9 @@ var RESERVED_SECRET_NAMES = new Set([
31794
32199
  "APP_STORE_CONNECT_KEY_ID",
31795
32200
  "APP_STORE_CONNECT_PRIVATE_KEY_BASE64"
31796
32201
  ]);
31797
- var exists6 = async (path) => {
32202
+ var exists7 = async (path) => {
31798
32203
  try {
31799
- await access14(path);
32204
+ await access15(path);
31800
32205
  return true;
31801
32206
  } catch {
31802
32207
  return false;
@@ -31804,10 +32209,10 @@ var exists6 = async (path) => {
31804
32209
  };
31805
32210
  var yamlString = (value) => `'${value.replaceAll("'", "''")}'`;
31806
32211
  var projectPath = (projectRoot, value, field2, options = {}) => {
31807
- const root = resolve15(projectRoot);
31808
- const path = resolve15(root, value);
31809
- const portable = relative13(root, path).replaceAll("\\", "/");
31810
- if (portable === ".." || portable.startsWith(`..${sep8}`) || portable.startsWith("../") || portable === "") {
32212
+ const root = resolve16(projectRoot);
32213
+ const path = resolve16(root, value);
32214
+ const portable = relative14(root, path).replaceAll("\\", "/");
32215
+ if (portable === ".." || portable.startsWith(`..${sep9}`) || portable.startsWith("../") || portable === "") {
31811
32216
  throw new TypeError(`${field2} must remain inside the project root.`);
31812
32217
  }
31813
32218
  if (/\r|\n/u.test(portable) || portable.startsWith("-"))
@@ -31817,11 +32222,11 @@ var projectPath = (projectRoot, value, field2, options = {}) => {
31817
32222
  return portable;
31818
32223
  };
31819
32224
  var workflowOutputPath = (projectRoot, value) => {
31820
- const root = resolve15(projectRoot);
31821
- const workflows = resolve15(root, ".github/workflows");
31822
- const path = resolve15(root, value ?? ".github/workflows/absolute-mobile.yml");
31823
- const portable = relative13(workflows, path);
31824
- if (portable === ".." || portable.startsWith(`..${sep8}`) || extname5(path) !== ".yml" && extname5(path) !== ".yaml") {
32225
+ const root = resolve16(projectRoot);
32226
+ const workflows = resolve16(root, ".github/workflows");
32227
+ const path = resolve16(root, value ?? ".github/workflows/absolute-mobile.yml");
32228
+ const portable = relative14(workflows, path);
32229
+ if (portable === ".." || portable.startsWith(`..${sep9}`) || extname5(path) !== ".yml" && extname5(path) !== ".yaml") {
31825
32230
  throw new TypeError("mobile ci github --output must be a .yml or .yaml file inside .github/workflows.");
31826
32231
  }
31827
32232
  return path;
@@ -32250,12 +32655,12 @@ ${bundleAuditSteps}${platforms.includes("android") ? androidJob({ customSecrets,
32250
32655
  var writeAbsoluteMobileGithubWorkflow = async (options) => {
32251
32656
  const path = workflowOutputPath(options.projectRoot, options.outputPath);
32252
32657
  const generated = createAbsoluteMobileGithubWorkflow(options);
32253
- const previous = await exists6(path) ? await readFile18(path, "utf8") : undefined;
32658
+ const previous = await exists7(path) ? await readFile19(path, "utf8") : undefined;
32254
32659
  if (previous !== undefined && previous !== generated.workflow && !options.force)
32255
- throw new TypeError(`${relative13(options.projectRoot, path)} already exists and differs. Rerun with --force to replace the generated workflow.`);
32660
+ throw new TypeError(`${relative14(options.projectRoot, path)} already exists and differs. Rerun with --force to replace the generated workflow.`);
32256
32661
  if (previous !== generated.workflow) {
32257
- await mkdir14(dirname13(path), { recursive: true });
32258
- await writeFile15(path, generated.workflow);
32662
+ await mkdir15(dirname14(path), { recursive: true });
32663
+ await writeFile16(path, generated.workflow);
32259
32664
  }
32260
32665
  return {
32261
32666
  changed: previous !== generated.workflow,
@@ -32273,20 +32678,20 @@ init_materializedBundle();
32273
32678
  init_mobilePreview();
32274
32679
 
32275
32680
  // src/mobile/nativeDeepLinks.ts
32276
- import { readFile as readFile19, rename as rename12, writeFile as writeFile16 } from "fs/promises";
32277
- import { join as join23 } from "path";
32681
+ import { readFile as readFile20, rename as rename13, writeFile as writeFile17 } from "fs/promises";
32682
+ import { join as join24 } from "path";
32278
32683
  var START_MARKER = "<!-- absolutejs:deep-links:start -->";
32279
32684
  var END_MARKER = "<!-- absolutejs:deep-links:end -->";
32280
32685
  var IOS_ENTITLEMENTS = "App/AbsoluteJS.entitlements";
32281
32686
  var NOT_FOUND = -1;
32282
32687
  var escapeXml = (value) => value.replaceAll("&", "&amp;").replaceAll('"', "&quot;").replaceAll("'", "&apos;").replaceAll("<", "&lt;").replaceAll(">", "&gt;");
32283
32688
  var writeChangedFile = async (path, source) => {
32284
- const current = await readFile19(path, "utf8");
32689
+ const current = await readFile20(path, "utf8");
32285
32690
  if (current === source)
32286
32691
  return false;
32287
32692
  const temporary = `${path}.${crypto.randomUUID()}.tmp`;
32288
- await writeFile16(temporary, source, { flag: "wx" });
32289
- await rename12(temporary, path);
32693
+ await writeFile17(temporary, source, { flag: "wx" });
32694
+ await rename13(temporary, path);
32290
32695
  return true;
32291
32696
  };
32292
32697
  var replaceManagedRegion = (source, region, insertAt) => {
@@ -32331,8 +32736,8 @@ ${hosts}
32331
32736
  `;
32332
32737
  };
32333
32738
  var configureAndroid = async (config) => {
32334
- const path = join23(config.nativeProjectDirectory, "android/app/src/main/AndroidManifest.xml");
32335
- const source = await readFile19(path, "utf8");
32739
+ const path = join24(config.nativeProjectDirectory, "android/app/src/main/AndroidManifest.xml");
32740
+ const source = await readFile20(path, "utf8");
32336
32741
  const mainActivity = source.indexOf('android:name=".MainActivity"');
32337
32742
  if (mainActivity === NOT_FOUND) {
32338
32743
  throw new TypeError("Android MainActivity was not found.");
@@ -32357,8 +32762,8 @@ var iosSchemeRegion = (scheme) => ` ${START_MARKER}
32357
32762
  ${END_MARKER}
32358
32763
  `;
32359
32764
  var configureIosInfo = async (config) => {
32360
- const path = join23(config.nativeProjectDirectory, "ios/App/App/Info.plist");
32361
- const source = await readFile19(path, "utf8");
32765
+ const path = join24(config.nativeProjectDirectory, "ios/App/App/Info.plist");
32766
+ const source = await readFile20(path, "utf8");
32362
32767
  const region = config.deepLinkScheme ? iosSchemeRegion(config.deepLinkScheme) : ` ${START_MARKER}
32363
32768
  ${END_MARKER}
32364
32769
  `;
@@ -32381,10 +32786,10 @@ ${domains}
32381
32786
  `;
32382
32787
  };
32383
32788
  var configureIosEntitlements = async (config) => {
32384
- const path = join23(config.nativeProjectDirectory, "ios/App/AbsoluteJS.entitlements");
32789
+ const path = join24(config.nativeProjectDirectory, "ios/App/AbsoluteJS.entitlements");
32385
32790
  let current = "";
32386
32791
  try {
32387
- current = await readFile19(path, "utf8");
32792
+ current = await readFile20(path, "utf8");
32388
32793
  } catch (error) {
32389
32794
  if (!(error instanceof Error) || !("code" in error) || error.code !== "ENOENT") {
32390
32795
  throw error;
@@ -32394,13 +32799,13 @@ var configureIosEntitlements = async (config) => {
32394
32799
  if (current === source)
32395
32800
  return false;
32396
32801
  const temporary = `${path}.${crypto.randomUUID()}.tmp`;
32397
- await writeFile16(temporary, source, { flag: "wx" });
32398
- await rename12(temporary, path);
32802
+ await writeFile17(temporary, source, { flag: "wx" });
32803
+ await rename13(temporary, path);
32399
32804
  return true;
32400
32805
  };
32401
32806
  var configureIosProject = async (config) => {
32402
- const path = join23(config.nativeProjectDirectory, "ios/App/App.xcodeproj/project.pbxproj");
32403
- const source = await readFile19(path, "utf8");
32807
+ const path = join24(config.nativeProjectDirectory, "ios/App/App.xcodeproj/project.pbxproj");
32808
+ const source = await readFile20(path, "utf8");
32404
32809
  const declarations = [
32405
32810
  ...source.matchAll(/CODE_SIGN_ENTITLEMENTS = ([^;]+);/g)
32406
32811
  ].map((match) => match[1]);
@@ -32439,8 +32844,8 @@ var applyAbsoluteNativeDeepLinks = async (config, platforms = config.platforms)
32439
32844
  };
32440
32845
  // src/mobile/nativeDeviceCapabilities.ts
32441
32846
  init_deviceCapabilities();
32442
- import { readFile as readFile20, rename as rename13, writeFile as writeFile17 } from "fs/promises";
32443
- import { join as join24 } from "path";
32847
+ import { readFile as readFile21, rename as rename14, writeFile as writeFile18 } from "fs/promises";
32848
+ import { join as join25 } from "path";
32444
32849
  var START_MARKER2 = "<!-- absolutejs:device-capabilities:start -->";
32445
32850
  var END_MARKER2 = "<!-- absolutejs:device-capabilities:end -->";
32446
32851
  var NOT_FOUND2 = -1;
@@ -32450,12 +32855,12 @@ var PUSH_START_MARKER = "absolutejs:push-notifications:start";
32450
32855
  var PUSH_END_MARKER = "absolutejs:push-notifications:end";
32451
32856
  var escapeXml2 = (value) => value.replaceAll("&", "&amp;").replaceAll('"', "&quot;").replaceAll("'", "&apos;").replaceAll("<", "&lt;").replaceAll(">", "&gt;");
32452
32857
  var writeChangedFile2 = async (path, source) => {
32453
- const current = await readFile20(path, "utf8");
32858
+ const current = await readFile21(path, "utf8");
32454
32859
  if (current === source)
32455
32860
  return false;
32456
32861
  const temporary = `${path}.${crypto.randomUUID()}.tmp`;
32457
- await writeFile17(temporary, source, { flag: "wx" });
32458
- await rename13(temporary, path);
32862
+ await writeFile18(temporary, source, { flag: "wx" });
32863
+ await rename14(temporary, path);
32459
32864
  return true;
32460
32865
  };
32461
32866
  var writeOptionalChangedFile = async (path, source) => {
@@ -32463,14 +32868,14 @@ var writeOptionalChangedFile = async (path, source) => {
32463
32868
  if (current === source)
32464
32869
  return false;
32465
32870
  if (current === null) {
32466
- await writeFile17(path, source, { flag: "wx" });
32871
+ await writeFile18(path, source, { flag: "wx" });
32467
32872
  return true;
32468
32873
  }
32469
32874
  return writeChangedFile2(path, source);
32470
32875
  };
32471
32876
  var optionalSource = async (path) => {
32472
32877
  try {
32473
- return await readFile20(path, "utf8");
32878
+ return await readFile21(path, "utf8");
32474
32879
  } catch (error) {
32475
32880
  if (typeof error === "object" && error !== null && Reflect.get(error, "code") === "ENOENT")
32476
32881
  return null;
@@ -32584,14 +32989,14 @@ var writeIosPrivacyManifest = async (path, current, source) => {
32584
32989
  return false;
32585
32990
  if (current !== null)
32586
32991
  return writeChangedFile2(path, source);
32587
- await writeFile17(path, source, { flag: "wx" });
32992
+ await writeFile18(path, source, { flag: "wx" });
32588
32993
  return true;
32589
32994
  };
32590
32995
  var configureIosPrivacyProject = async (config, requirements) => {
32591
32996
  if (requirements.iosPrivacyAccessedApis.length === 0)
32592
32997
  return false;
32593
- const projectPath2 = join24(config.nativeProjectDirectory, "ios/App/App.xcodeproj/project.pbxproj");
32594
- const project = await readFile20(projectPath2, "utf8");
32998
+ const projectPath2 = join25(config.nativeProjectDirectory, "ios/App/App.xcodeproj/project.pbxproj");
32999
+ const project = await readFile21(projectPath2, "utf8");
32595
33000
  return writeChangedFile2(projectPath2, addIosPrivacyProjectReference(project));
32596
33001
  };
32597
33002
  var addIosPrivacyProjectReference = (source) => {
@@ -32643,8 +33048,8 @@ ${next.slice(index)}`;
32643
33048
  return next;
32644
33049
  };
32645
33050
  var configureIos2 = async (config, plan) => {
32646
- const path = join24(config.nativeProjectDirectory, "ios/App/App/Info.plist");
32647
- const source = await readFile20(path, "utf8");
33051
+ const path = join25(config.nativeProjectDirectory, "ios/App/App/Info.plist");
33052
+ const source = await readFile21(path, "utf8");
32648
33053
  const requirements = absoluteDeviceNativeRequirements(plan);
32649
33054
  const existingSystemBars = source.match(/<key>UIViewControllerBasedStatusBarAppearance<\/key>\s*<(true|false)\s*\/>/u);
32650
33055
  const ownedStart = source.indexOf(START_MARKER2);
@@ -32664,7 +33069,7 @@ ${content}
32664
33069
  ${END_MARKER2}
32665
33070
  ` : "";
32666
33071
  const infoChanged = await writeChangedFile2(path, managed(source, region, source.lastIndexOf("</dict>")));
32667
- const privacyPath = join24(config.nativeProjectDirectory, "ios/App/App/PrivacyInfo.xcprivacy");
33072
+ const privacyPath = join25(config.nativeProjectDirectory, "ios/App/App/PrivacyInfo.xcprivacy");
32668
33073
  const privacyCurrent = await optionalSource(privacyPath);
32669
33074
  const privacySource = privacyManifestSource(privacyCurrent, requirements);
32670
33075
  const [privacyChanged, projectChanged, pushChanged] = await Promise.all([
@@ -32675,7 +33080,7 @@ ${content}
32675
33080
  return infoChanged || privacyChanged || projectChanged || pushChanged;
32676
33081
  };
32677
33082
  var configureIosPushNotifications = async (config, enabled) => {
32678
- const entitlementsPath = join24(config.nativeProjectDirectory, "ios/App/AbsoluteJS.entitlements");
33083
+ const entitlementsPath = join25(config.nativeProjectDirectory, "ios/App/AbsoluteJS.entitlements");
32679
33084
  const entitlements = await optionalSource(entitlementsPath);
32680
33085
  if (entitlements === null && !enabled)
32681
33086
  return false;
@@ -32687,7 +33092,7 @@ var configureIosPushNotifications = async (config, enabled) => {
32687
33092
  <!-- ${PUSH_END_MARKER} -->
32688
33093
  ` : "";
32689
33094
  const nextEntitlements = replacePushRegion(entitlements, entitlementRegion, entitlements.lastIndexOf("</dict>"));
32690
- const delegatePath = join24(config.nativeProjectDirectory, "ios/App/App/AppDelegate.swift");
33095
+ const delegatePath = join25(config.nativeProjectDirectory, "ios/App/App/AppDelegate.swift");
32691
33096
  const delegate = await optionalSource(delegatePath);
32692
33097
  if (delegate === null && !enabled)
32693
33098
  return false;
@@ -32736,8 +33141,8 @@ var replacePushRegion = (source, region, insertion) => {
32736
33141
  return `${source.slice(0, insertion)}${region}${source.slice(insertion)}`;
32737
33142
  };
32738
33143
  var configureAndroid2 = async (config, plan) => {
32739
- const path = join24(config.nativeProjectDirectory, "android/app/src/main/AndroidManifest.xml");
32740
- const source = await readFile20(path, "utf8");
33144
+ const path = join25(config.nativeProjectDirectory, "android/app/src/main/AndroidManifest.xml");
33145
+ const source = await readFile21(path, "utf8");
32741
33146
  const permissions = absoluteDeviceNativeRequirements(plan).androidPermissions;
32742
33147
  const content = permissions.map((permission) => ` <uses-permission android:name="${escapeXml2(permission)}" />`).join(`
32743
33148
  `);
@@ -32772,7 +33177,7 @@ ${content}
32772
33177
  throw new TypeError(`Android google-services.json does not contain package ${config.appId}.`);
32773
33178
  const [manifestChanged, firebaseChanged] = await Promise.all([
32774
33179
  writeChangedFile2(path, nextManifest),
32775
- writeOptionalChangedFile(join24(config.nativeProjectDirectory, "android/app/google-services.json"), firebaseSource)
33180
+ writeOptionalChangedFile(join25(config.nativeProjectDirectory, "android/app/google-services.json"), firebaseSource)
32776
33181
  ]);
32777
33182
  return manifestChanged || firebaseChanged;
32778
33183
  };
@@ -32791,14 +33196,14 @@ init_nativeAuth();
32791
33196
 
32792
33197
  // src/mobile/nativeUpdates.ts
32793
33198
  import {
32794
- mkdir as mkdir15,
32795
- readFile as readFile21,
33199
+ mkdir as mkdir16,
33200
+ readFile as readFile22,
32796
33201
  readdir as readdir6,
32797
- rename as rename14,
32798
- rm as rm11,
32799
- writeFile as writeFile18
33202
+ rename as rename15,
33203
+ rm as rm12,
33204
+ writeFile as writeFile19
32800
33205
  } from "fs/promises";
32801
- import { dirname as dirname15, join as join25 } from "path";
33206
+ import { dirname as dirname16, join as join26 } from "path";
32802
33207
  var START = "// absolutejs:mobile-updates:start";
32803
33208
  var END = "// absolutejs:mobile-updates:end";
32804
33209
  var PLUGIN_START = "// absolutejs:mobile-update-plugin:start";
@@ -32806,32 +33211,32 @@ var PLUGIN_END = "// absolutejs:mobile-update-plugin:end";
32806
33211
  var ANDROID_PLUGIN = "AbsoluteMobileUpdateWatchdogPlugin.java";
32807
33212
  var optionalSource2 = async (path) => {
32808
33213
  try {
32809
- return await readFile21(path, "utf8");
33214
+ return await readFile22(path, "utf8");
32810
33215
  } catch (error) {
32811
33216
  if (typeof error === "object" && error !== null && Reflect.get(error, "code") === "ENOENT")
32812
33217
  return null;
32813
33218
  throw error;
32814
33219
  }
32815
33220
  };
32816
- var isRecord11 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
33221
+ var isRecord12 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
32817
33222
  var writeChanged = async (path, source) => {
32818
33223
  const current = await optionalSource2(path);
32819
33224
  if (current === source)
32820
33225
  return false;
32821
- await mkdir15(dirname15(path), { recursive: true });
33226
+ await mkdir16(dirname16(path), { recursive: true });
32822
33227
  if (current === null) {
32823
- await writeFile18(path, source, { flag: "wx" });
33228
+ await writeFile19(path, source, { flag: "wx" });
32824
33229
  return true;
32825
33230
  }
32826
33231
  const temporary = `${path}.${crypto.randomUUID()}.tmp`;
32827
- await writeFile18(temporary, source, { flag: "wx" });
32828
- await rename14(temporary, path);
33232
+ await writeFile19(temporary, source, { flag: "wx" });
33233
+ await rename15(temporary, path);
32829
33234
  return true;
32830
33235
  };
32831
33236
  var removeOwnedFile = async (path) => {
32832
33237
  if (await optionalSource2(path) === null)
32833
33238
  return false;
32834
- await rm11(path);
33239
+ await rm12(path);
32835
33240
  return true;
32836
33241
  };
32837
33242
  var replaceMarkedRegion = (source, start, end, region, insertion, error) => {
@@ -32968,11 +33373,11 @@ public final class AbsoluteMobileUpdateWatchdogPlugin: CAPPlugin, CAPBridgedPlug
32968
33373
  ${PLUGIN_END}
32969
33374
  `;
32970
33375
  var configureIos3 = async (config, enabled) => {
32971
- const path = join25(config.nativeProjectDirectory, "ios/App/App/AppDelegate.swift");
32972
- const capacitorConfigPath = join25(config.nativeProjectDirectory, "ios/App/App/capacitor.config.json");
32973
- let source = await readFile21(path, "utf8");
32974
- const launch = source.indexOf("didFinishLaunchingWithOptions");
32975
- const brace = launch < 0 ? -1 : source.indexOf("{", launch);
33376
+ const path = join26(config.nativeProjectDirectory, "ios/App/App/AppDelegate.swift");
33377
+ const capacitorConfigPath = join26(config.nativeProjectDirectory, "ios/App/App/capacitor.config.json");
33378
+ let source = await readFile22(path, "utf8");
33379
+ const launch2 = source.indexOf("didFinishLaunchingWithOptions");
33380
+ const brace = launch2 < 0 ? -1 : source.indexOf("{", launch2);
32976
33381
  const launchRegion = enabled ? ` ${START}
32977
33382
  AbsoluteMobileUpdateWatchdogPlugin.recoverInterruptedBoot()
32978
33383
  ${END}
@@ -32981,11 +33386,11 @@ var configureIos3 = async (config, enabled) => {
32981
33386
  `, brace) + 1, "Could not find a safe iOS location for mobile update recovery.");
32982
33387
  const plugin = enabled ? iosPluginRegion(config.updates?.bootTimeoutMs ?? 20000) : "";
32983
33388
  source = replaceMarkedRegion(source, PLUGIN_START, PLUGIN_END, plugin, source.length, "Could not find a safe iOS location for the mobile update watchdog.");
32984
- const capacitorConfigSource2 = await readFile21(capacitorConfigPath, "utf8");
33389
+ const capacitorConfigSource2 = await readFile22(capacitorConfigPath, "utf8");
32985
33390
  let capacitorConfig;
32986
33391
  try {
32987
33392
  const value = JSON.parse(capacitorConfigSource2);
32988
- if (!isRecord11(value))
33393
+ if (!isRecord12(value))
32989
33394
  throw new TypeError;
32990
33395
  capacitorConfig = value;
32991
33396
  } catch {
@@ -33161,12 +33566,12 @@ var androidActivityInRoot = async (root) => {
33161
33566
  throw error;
33162
33567
  }
33163
33568
  const candidate = entries.find((entry) => entry.endsWith("/MainActivity.java") || entry.endsWith("/MainActivity.kt") || entry === "MainActivity.java" || entry === "MainActivity.kt");
33164
- return candidate ? join25(root, candidate) : undefined;
33569
+ return candidate ? join26(root, candidate) : undefined;
33165
33570
  };
33166
33571
  var androidActivity = async (config) => {
33167
33572
  const roots = [
33168
- join25(config.nativeProjectDirectory, "android/app/src/main/java"),
33169
- join25(config.nativeProjectDirectory, "android/app/src/main/kotlin")
33573
+ join26(config.nativeProjectDirectory, "android/app/src/main/java"),
33574
+ join26(config.nativeProjectDirectory, "android/app/src/main/kotlin")
33170
33575
  ];
33171
33576
  const candidates = await Promise.all(roots.map(androidActivityInRoot));
33172
33577
  const candidate = candidates.find((value) => value !== undefined);
@@ -33265,12 +33670,12 @@ var injectAndroidActivity = (source, enabled) => {
33265
33670
  };
33266
33671
  var configureAndroid3 = async (config, enabled) => {
33267
33672
  const activityPath = await androidActivity(config);
33268
- const activity = await readFile21(activityPath, "utf8");
33673
+ const activity = await readFile22(activityPath, "utf8");
33269
33674
  const packageName = activity.match(/^\s*package\s+([A-Za-z0-9_.]+)\s*[;\n]/mu)?.[1];
33270
33675
  if (!packageName)
33271
33676
  throw new TypeError("Android MainActivity package declaration was not found.");
33272
33677
  const packagePath = packageName.replaceAll(".", "/");
33273
- const pluginPath = join25(config.nativeProjectDirectory, "android/app/src/main/java", packagePath, ANDROID_PLUGIN);
33678
+ const pluginPath = join26(config.nativeProjectDirectory, "android/app/src/main/java", packagePath, ANDROID_PLUGIN);
33274
33679
  const changed = await Promise.all([
33275
33680
  writeChanged(activityPath, injectAndroidActivity(activity, enabled)),
33276
33681
  enabled ? writeChanged(pluginPath, androidPluginSource(packageName, config.updates?.bootTimeoutMs ?? 20000)) : removeOwnedFile(pluginPath)
@@ -33290,14 +33695,14 @@ var applyAbsoluteNativeUpdates = async (config, platforms = config.platforms) =>
33290
33695
  };
33291
33696
  // src/mobile/nativeObservability.ts
33292
33697
  import {
33293
- mkdir as mkdir16,
33294
- readFile as readFile22,
33698
+ mkdir as mkdir17,
33699
+ readFile as readFile23,
33295
33700
  readdir as readdir7,
33296
- rename as rename15,
33297
- rm as rm12,
33298
- writeFile as writeFile19
33701
+ rename as rename16,
33702
+ rm as rm13,
33703
+ writeFile as writeFile20
33299
33704
  } from "fs/promises";
33300
- import { dirname as dirname16, join as join26 } from "path";
33705
+ import { dirname as dirname17, join as join27 } from "path";
33301
33706
  var START2 = "// absolutejs:native-observability:start";
33302
33707
  var END2 = "// absolutejs:native-observability:end";
33303
33708
  var PLUGIN_START2 = "// absolutejs:native-observability-plugin:start";
@@ -33305,7 +33710,7 @@ var PLUGIN_END2 = "// absolutejs:native-observability-plugin:end";
33305
33710
  var ANDROID_PLUGIN2 = "AbsoluteMobileObservabilityPlugin.java";
33306
33711
  var optionalSource3 = async (path) => {
33307
33712
  try {
33308
- return await readFile22(path, "utf8");
33713
+ return await readFile23(path, "utf8");
33309
33714
  } catch (error) {
33310
33715
  if (typeof error === "object" && error !== null && Reflect.get(error, "code") === "ENOENT")
33311
33716
  return null;
@@ -33316,23 +33721,23 @@ var writeChanged2 = async (path, source) => {
33316
33721
  const current = await optionalSource3(path);
33317
33722
  if (current === source)
33318
33723
  return false;
33319
- await mkdir16(dirname16(path), { recursive: true });
33724
+ await mkdir17(dirname17(path), { recursive: true });
33320
33725
  if (current === null) {
33321
- await writeFile19(path, source, { flag: "wx" });
33726
+ await writeFile20(path, source, { flag: "wx" });
33322
33727
  return true;
33323
33728
  }
33324
33729
  const temporary = `${path}.${crypto.randomUUID()}.tmp`;
33325
- await writeFile19(temporary, source, { flag: "wx" });
33326
- await rename15(temporary, path);
33730
+ await writeFile20(temporary, source, { flag: "wx" });
33731
+ await rename16(temporary, path);
33327
33732
  return true;
33328
33733
  };
33329
33734
  var removeOwnedFile2 = async (path) => {
33330
33735
  if (await optionalSource3(path) === null)
33331
33736
  return false;
33332
- await rm12(path);
33737
+ await rm13(path);
33333
33738
  return true;
33334
33739
  };
33335
- var isRecord12 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
33740
+ var isRecord13 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
33336
33741
  var replaceMarkedRegion2 = (source, start, end, region, insertion, error) => {
33337
33742
  const existingStart = source.indexOf(start);
33338
33743
  const existingEnd = source.indexOf(end);
@@ -33465,9 +33870,9 @@ public final class AbsoluteMobileObservabilityPlugin: CAPPlugin, CAPBridgedPlugi
33465
33870
  ${PLUGIN_END2}
33466
33871
  `;
33467
33872
  var configureIos4 = async (config, enabled) => {
33468
- const path = join26(config.nativeProjectDirectory, "ios/App/App/AppDelegate.swift");
33469
- const capacitorConfigPath = join26(config.nativeProjectDirectory, "ios/App/App/capacitor.config.json");
33470
- let source = await readFile22(path, "utf8");
33873
+ const path = join27(config.nativeProjectDirectory, "ios/App/App/AppDelegate.swift");
33874
+ const capacitorConfigPath = join27(config.nativeProjectDirectory, "ios/App/App/capacitor.config.json");
33875
+ let source = await readFile23(path, "utf8");
33471
33876
  if (enabled && !source.includes("import MetricKit")) {
33472
33877
  const capacitorImport = source.lastIndexOf("import Capacitor");
33473
33878
  if (capacitorImport < 0)
@@ -33481,11 +33886,11 @@ ${source.slice(newline + 1)}`;
33481
33886
  source = source.replace(`import MetricKit
33482
33887
  `, "");
33483
33888
  source = replaceMarkedRegion2(source, PLUGIN_START2, PLUGIN_END2, enabled ? iosPluginRegion2 : "", source.length, "Could not find a safe iOS location for native observability.");
33484
- const capacitorConfigSource2 = await readFile22(capacitorConfigPath, "utf8");
33889
+ const capacitorConfigSource2 = await readFile23(capacitorConfigPath, "utf8");
33485
33890
  let capacitorConfig;
33486
33891
  try {
33487
33892
  const value = JSON.parse(capacitorConfigSource2);
33488
- if (!isRecord12(value))
33893
+ if (!isRecord13(value))
33489
33894
  throw new TypeError;
33490
33895
  capacitorConfig = value;
33491
33896
  } catch {
@@ -33726,12 +34131,12 @@ var androidActivityInRoot2 = async (root) => {
33726
34131
  throw error;
33727
34132
  }
33728
34133
  const candidate = entries.find((entry) => entry.endsWith("/MainActivity.java") || entry.endsWith("/MainActivity.kt") || entry === "MainActivity.java" || entry === "MainActivity.kt");
33729
- return candidate ? join26(root, candidate) : undefined;
34134
+ return candidate ? join27(root, candidate) : undefined;
33730
34135
  };
33731
34136
  var androidActivity2 = async (config) => {
33732
34137
  const roots = [
33733
- join26(config.nativeProjectDirectory, "android/app/src/main/java"),
33734
- join26(config.nativeProjectDirectory, "android/app/src/main/kotlin")
34138
+ join27(config.nativeProjectDirectory, "android/app/src/main/java"),
34139
+ join27(config.nativeProjectDirectory, "android/app/src/main/kotlin")
33735
34140
  ];
33736
34141
  const candidates = await Promise.all(roots.map(androidActivityInRoot2));
33737
34142
  const candidate = candidates.find((value) => value !== undefined);
@@ -33799,11 +34204,11 @@ var injectAndroidActivity2 = (source, enabled) => {
33799
34204
  };
33800
34205
  var configureAndroid4 = async (config, enabled) => {
33801
34206
  const activityPath = await androidActivity2(config);
33802
- const activity = await readFile22(activityPath, "utf8");
34207
+ const activity = await readFile23(activityPath, "utf8");
33803
34208
  const packageName = activity.match(/^\s*package\s+([A-Za-z0-9_.]+)\s*[;\n]/mu)?.[1];
33804
34209
  if (!packageName)
33805
34210
  throw new TypeError("Android MainActivity package declaration was not found.");
33806
- const pluginPath = join26(config.nativeProjectDirectory, "android/app/src/main/java", packageName.replaceAll(".", "/"), ANDROID_PLUGIN2);
34211
+ const pluginPath = join27(config.nativeProjectDirectory, "android/app/src/main/java", packageName.replaceAll(".", "/"), ANDROID_PLUGIN2);
33807
34212
  const changed = await Promise.all([
33808
34213
  writeChanged2(activityPath, injectAndroidActivity2(activity, enabled)),
33809
34214
  enabled ? writeChanged2(pluginPath, androidPluginSource2(packageName)) : removeOwnedFile2(pluginPath)
@@ -33828,8 +34233,8 @@ init_producerContext();
33828
34233
  init_releaseArtifact();
33829
34234
 
33830
34235
  // src/mobile/releasePublisher.ts
33831
- import { access as access15 } from "fs/promises";
33832
- import { isAbsolute as isAbsolute7, relative as relative14, resolve as resolve16, sep as sep9 } from "path";
34236
+ import { access as access16 } from "fs/promises";
34237
+ import { isAbsolute as isAbsolute8, relative as relative15, resolve as resolve17, sep as sep10 } from "path";
33833
34238
  import { pathToFileURL as pathToFileURL3 } from "url";
33834
34239
  var prepareAbsoluteIosRelease = async (publisher, options) => {
33835
34240
  if (typeof publisher.prepareIosRelease !== "function") {
@@ -33852,24 +34257,24 @@ var prepareAbsoluteAndroidRelease = async (publisher, options) => {
33852
34257
  }
33853
34258
  return versionCode;
33854
34259
  };
33855
- var isRecord13 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
33856
- var isPublisher = (value) => isRecord13(value) && typeof value.publish === "function";
34260
+ var isRecord14 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
34261
+ var isPublisher = (value) => isRecord14(value) && typeof value.publish === "function";
33857
34262
  var publisherModulePath = (projectRoot, requested) => {
33858
- const root = resolve16(projectRoot);
33859
- const path = resolve16(root, requested);
33860
- const projectRelative = relative14(root, path);
33861
- if (projectRelative === ".." || projectRelative.startsWith(`..${sep9}`) || isAbsolute7(projectRelative)) {
34263
+ const root = resolve17(projectRoot);
34264
+ const path = resolve17(root, requested);
34265
+ const projectRelative = relative15(root, path);
34266
+ if (projectRelative === ".." || projectRelative.startsWith(`..${sep10}`) || isAbsolute8(projectRelative)) {
33862
34267
  throw new TypeError("mobile publish --registry must remain inside the project.");
33863
34268
  }
33864
34269
  return path;
33865
34270
  };
33866
34271
  var loadAbsoluteNativeReleasePublisher = async (projectRoot, requestedModulePath) => {
33867
34272
  const modulePath = publisherModulePath(projectRoot, requestedModulePath);
33868
- await access15(modulePath).catch(() => {
34273
+ await access16(modulePath).catch(() => {
33869
34274
  throw new TypeError(`Native release registry module does not exist: ${modulePath}`);
33870
34275
  });
33871
34276
  const loaded = await import(pathToFileURL3(modulePath).href);
33872
- const publisher = isRecord13(loaded) ? loaded.default ?? loaded.registry : undefined;
34277
+ const publisher = isRecord14(loaded) ? loaded.default ?? loaded.registry : undefined;
33873
34278
  if (!isPublisher(publisher)) {
33874
34279
  throw new TypeError("Native release registry module must default-export a registry with publish(options).");
33875
34280
  }
@@ -33929,7 +34334,7 @@ var publishAbsoluteIosRelease = async (options) => {
33929
34334
  init_pageProtocol();
33930
34335
  init_releaseArtifact();
33931
34336
  import { existsSync as existsSync7, readFileSync as readFileSync8 } from "fs";
33932
- import { dirname as dirname17, extname as extname6, relative as relative15, resolve as resolve17 } from "path";
34337
+ import { dirname as dirname18, extname as extname6, relative as relative16, resolve as resolve18 } from "path";
33933
34338
  import ts2 from "typescript";
33934
34339
  var ROUTE_METHODS = new Set(["get", "head"]);
33935
34340
  var SOURCE_FILTER = /\.[cm]?[jt]sx?$/;
@@ -33980,7 +34385,7 @@ var PAGE_HANDLERS = new Map([
33980
34385
  ]
33981
34386
  ]);
33982
34387
  var posixPath = (value) => value.replace(/\\/g, "/");
33983
- var findTsconfig = (entry, projectRoot) => ts2.findConfigFile(dirname17(entry), existsSync7, "tsconfig.json") ?? ts2.findConfigFile(projectRoot, existsSync7, "tsconfig.json");
34388
+ var findTsconfig = (entry, projectRoot) => ts2.findConfigFile(dirname18(entry), existsSync7, "tsconfig.json") ?? ts2.findConfigFile(projectRoot, existsSync7, "tsconfig.json");
33984
34389
  var createProgram = (entry, projectRoot) => {
33985
34390
  const configPath2 = findTsconfig(entry, projectRoot);
33986
34391
  if (!configPath2) {
@@ -33992,7 +34397,7 @@ var createProgram = (entry, projectRoot) => {
33992
34397
  target: ts2.ScriptTarget.ESNext
33993
34398
  });
33994
34399
  }
33995
- const parsed = ts2.parseJsonConfigFileContent(ts2.readConfigFile(configPath2, (path) => readFileSync8(path, "utf8")).config, ts2.sys, dirname17(configPath2));
34400
+ const parsed = ts2.parseJsonConfigFileContent(ts2.readConfigFile(configPath2, (path) => readFileSync8(path, "utf8")).config, ts2.sys, dirname18(configPath2));
33996
34401
  if (!parsed.fileNames.includes(entry))
33997
34402
  parsed.fileNames.push(entry);
33998
34403
  return ts2.createProgram(parsed.fileNames, parsed.options);
@@ -34098,7 +34503,7 @@ var resolvePageIdentity = (expression, sourceFile, checker, projectRoot) => {
34098
34503
  const declaration = symbol?.declarations?.[0];
34099
34504
  const file = declaration?.getSourceFile().fileName ?? sourceFile.fileName;
34100
34505
  const exportedName = symbol?.name ?? expression.getText(sourceFile);
34101
- const source = posixPath(relative15(projectRoot, file));
34506
+ const source = posixPath(relative16(projectRoot, file));
34102
34507
  return `${source}#${exportedName}`;
34103
34508
  };
34104
34509
  var resolveAlias = (symbol, checker) => {
@@ -34337,7 +34742,7 @@ var analyzeProgram = (program, projectRoot) => {
34337
34742
  const checker = program.getTypeChecker();
34338
34743
  const analyzed = new Map;
34339
34744
  for (const sourceFile of program.getSourceFiles()) {
34340
- const resolvedFile = resolve17(sourceFile.fileName);
34745
+ const resolvedFile = resolve18(sourceFile.fileName);
34341
34746
  if (!isProjectSource(sourceFile, resolvedFile, projectRoot))
34342
34747
  continue;
34343
34748
  const analysis = analyzeSourceFile(sourceFile, checker, projectRoot);
@@ -34430,14 +34835,14 @@ var transformFile = (source, fileName, analysis) => {
34430
34835
  };
34431
34836
  var ABSOLUTE_MOBILE_TRANSFORM_PROTOCOL = ABSOLUTE_MOBILE_PAGE_PROTOCOL_VERSION;
34432
34837
  var createAbsoluteMobileRouteMetadataPlugin = (options) => {
34433
- const projectRoot = resolve17(options.projectRoot ?? process.cwd());
34434
- const entry = resolve17(options.entry);
34838
+ const projectRoot = resolve18(options.projectRoot ?? process.cwd());
34839
+ const entry = resolve18(options.entry);
34435
34840
  const analyzed = analyzeProgram(createProgram(entry, projectRoot), projectRoot);
34436
34841
  return {
34437
34842
  name: "absolute-mobile-route-metadata",
34438
34843
  setup(build) {
34439
34844
  build.onLoad({ filter: SOURCE_FILTER }, async ({ path }) => {
34440
- const analysis = analyzed.get(resolve17(path));
34845
+ const analysis = analyzed.get(resolve18(path));
34441
34846
  if (!analysis)
34442
34847
  return;
34443
34848
  const source = await Bun.file(path).text();
@@ -34450,11 +34855,11 @@ var createAbsoluteMobileRouteMetadataPlugin = (options) => {
34450
34855
  };
34451
34856
  };
34452
34857
  var inspectAbsoluteMobileRouteMetadata = (options) => {
34453
- const projectRoot = resolve17(options.projectRoot ?? process.cwd());
34454
- const entry = resolve17(options.entry);
34858
+ const projectRoot = resolve18(options.projectRoot ?? process.cwd());
34859
+ const entry = resolve18(options.entry);
34455
34860
  const analyzed = analyzeProgram(createProgram(entry, projectRoot), projectRoot);
34456
34861
  return [...analyzed.entries()].flatMap(([file, analysis]) => [...analysis.byRouteCall.values()].map(({ metadata }) => ({
34457
- file: posixPath(relative15(projectRoot, file)),
34862
+ file: posixPath(relative16(projectRoot, file)),
34458
34863
  metadata
34459
34864
  })));
34460
34865
  };
@@ -34788,7 +35193,7 @@ var createCapacitor = (win) => {
34788
35193
  callbackId
34789
35194
  }, callback);
34790
35195
  };
34791
- const p = new Promise((resolve18) => call.then(() => resolve18({ remove })));
35196
+ const p = new Promise((resolve19) => call.then(() => resolve19({ remove })));
34792
35197
  p.remove = async () => {
34793
35198
  console.warn(`Using addListener() without 'await' is deprecated.`);
34794
35199
  await remove();
@@ -34993,11 +35398,11 @@ class CapacitorCookiesPluginWeb extends WebPlugin {
34993
35398
  var CapacitorCookies = registerPlugin("CapacitorCookies", {
34994
35399
  web: () => new CapacitorCookiesPluginWeb
34995
35400
  });
34996
- var readBlobAsBase64 = async (blob) => new Promise((resolve18, reject) => {
35401
+ var readBlobAsBase64 = async (blob) => new Promise((resolve19, reject) => {
34997
35402
  const reader = new FileReader;
34998
35403
  reader.onload = () => {
34999
35404
  const base64String = reader.result;
35000
- resolve18(base64String.indexOf(",") >= 0 ? base64String.split(",")[1] : base64String);
35405
+ resolve19(base64String.indexOf(",") >= 0 ? base64String.split(",")[1] : base64String);
35001
35406
  };
35002
35407
  reader.onerror = (error) => reject(error);
35003
35408
  reader.readAsDataURL(blob);
@@ -35173,7 +35578,7 @@ var REPORT_KINDS = new Set([
35173
35578
  "signal"
35174
35579
  ]);
35175
35580
  var nativeObservability = registerPlugin("AbsoluteMobileObservability");
35176
- var isRecord14 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
35581
+ var isRecord15 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
35177
35582
  var redactText = (value) => value.slice(0, MAX_STRING_LENGTH).replace(/\b(Bearer)\s+[A-Za-z0-9._~+/-]+=*/giu, "$1 [REDACTED]").replace(/([?&](?:access_token|api_?key|authorization|code|id_token|password|refresh_token|secret|token)=)[^&#\s]*/giu, "$1[REDACTED]").replace(/\b((?:access_?token|api_?key|authorization|client_?secret|cookie|id_?token|password|passwd|refresh_?token|secret|token)\s*[:=]\s*)[^,\s;]+/giu, "$1[REDACTED]").replace(/\beyJ[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+\b/gu, "[REDACTED]");
35178
35583
  var redactValue = (value, depth = 0) => {
35179
35584
  if (depth >= MAX_REDACTION_DEPTH)
@@ -35184,7 +35589,7 @@ var redactValue = (value, depth = 0) => {
35184
35589
  return value;
35185
35590
  if (Array.isArray(value))
35186
35591
  return value.slice(0, 64).map((entry) => redactValue(entry, depth + 1));
35187
- if (!isRecord14(value))
35592
+ if (!isRecord15(value))
35188
35593
  return String(value).slice(0, MAX_STRING_LENGTH);
35189
35594
  return Object.fromEntries(Object.entries(value).slice(0, 128).map(([key, entry]) => [
35190
35595
  key,
@@ -35192,7 +35597,7 @@ var redactValue = (value, depth = 0) => {
35192
35597
  ]));
35193
35598
  };
35194
35599
  var parseReport = (value) => {
35195
- if (!isRecord14(value) || !isRecord14(value.details))
35600
+ if (!isRecord15(value) || !isRecord15(value.details))
35196
35601
  return;
35197
35602
  if (typeof value.id !== "string" || !REPORT_ID.test(value.id))
35198
35603
  return;
@@ -35203,7 +35608,7 @@ var parseReport = (value) => {
35203
35608
  if (value.platform !== "android" && value.platform !== "ios")
35204
35609
  return;
35205
35610
  const details = redactValue(value.details);
35206
- if (!isRecord14(details))
35611
+ if (!isRecord15(details))
35207
35612
  return;
35208
35613
  if (new TextEncoder().encode(JSON.stringify(details)).byteLength > MAX_DETAIL_BYTES)
35209
35614
  return;
@@ -39657,8 +40062,8 @@ var createBeacon = (options) => {
39657
40062
  if (await fontAvailable(element))
39658
40063
  return;
39659
40064
  if (confirmationMs > 0) {
39660
- await new Promise((resolve18) => {
39661
- const timer2 = window.setTimeout(resolve18, confirmationMs);
40065
+ await new Promise((resolve19) => {
40066
+ const timer2 = window.setTimeout(resolve19, confirmationMs);
39662
40067
  cleanups.push(() => window.clearTimeout(timer2));
39663
40068
  });
39664
40069
  if (document.visibilityState === "hidden")
@@ -40646,51 +41051,51 @@ var createAbsoluteMobileUpdateClient = (options) => {
40646
41051
  };
40647
41052
  };
40648
41053
  // src/mobile/updatePublisher.ts
40649
- import { access as access16 } from "fs/promises";
40650
- import { isAbsolute as isAbsolute8, relative as relative17, resolve as resolve19, sep as sep10 } from "path";
41054
+ import { access as access17 } from "fs/promises";
41055
+ import { isAbsolute as isAbsolute9, relative as relative18, resolve as resolve20, sep as sep11 } from "path";
40651
41056
  import { pathToFileURL as pathToFileURL4 } from "url";
40652
41057
 
40653
41058
  // src/mobile/updateSigning.ts
40654
- import { createHash as createHash14, sign, verify } from "crypto";
41059
+ import { createHash as createHash15, sign, verify } from "crypto";
40655
41060
  import {
40656
- cp as cp3,
40657
- mkdir as mkdir17,
40658
- mkdtemp as mkdtemp8,
41061
+ cp as cp2,
41062
+ mkdir as mkdir18,
41063
+ mkdtemp as mkdtemp9,
40659
41064
  readdir as readdir8,
40660
- readFile as readFile23,
40661
- rename as rename16,
40662
- rm as rm13,
40663
- stat as stat4,
40664
- writeFile as writeFile20
41065
+ readFile as readFile24,
41066
+ rename as rename17,
41067
+ rm as rm14,
41068
+ stat as stat5,
41069
+ writeFile as writeFile21
40665
41070
  } from "fs/promises";
40666
- import { dirname as dirname18, join as join27, relative as relative16, resolve as resolve18 } from "path";
41071
+ import { dirname as dirname19, join as join28, relative as relative17, resolve as resolve19 } from "path";
40667
41072
  var UPDATE_MANIFEST_FILE = "update.json";
40668
41073
  var UPDATE_FILES_DIRECTORY = "files";
40669
- var sha2562 = (value) => createHash14("sha256").update(value).digest("hex");
41074
+ var sha2563 = (value) => createHash15("sha256").update(value).digest("hex");
40670
41075
  var listFiles = async (root, directory = root) => {
40671
41076
  const entries = await readdir8(directory, { withFileTypes: true });
40672
41077
  const paths = await Promise.all(entries.map(async (entry) => {
40673
- const path = join27(directory, entry.name);
41078
+ const path = join28(directory, entry.name);
40674
41079
  if (entry.isDirectory())
40675
41080
  return listFiles(root, path);
40676
41081
  if (!entry.isFile())
40677
41082
  throw new TypeError("Mobile updates cannot contain links or special files.");
40678
- return [relative16(root, path).replaceAll("\\", "/")];
41083
+ return [relative17(root, path).replaceAll("\\", "/")];
40679
41084
  }));
40680
41085
  return paths.flat().sort((left, right) => left.localeCompare(right));
40681
41086
  };
40682
41087
  var inspectFiles = async (root, paths) => Promise.all(paths.map(async (path) => {
40683
- const source = join27(root, path);
41088
+ const source = join28(root, path);
40684
41089
  const [metadata, contents] = await Promise.all([
40685
- stat4(source),
40686
- readFile23(source)
41090
+ stat5(source),
41091
+ readFile24(source)
40687
41092
  ]);
40688
- return { bytes: metadata.size, path, sha256: sha2562(contents) };
41093
+ return { bytes: metadata.size, path, sha256: sha2563(contents) };
40689
41094
  }));
40690
- var releaseIdFor = (value) => `amu_${sha2562(canonicalizeAbsoluteMobileUpdate(value))}`;
41095
+ var releaseIdFor = (value) => `amu_${sha2563(canonicalizeAbsoluteMobileUpdate(value))}`;
40691
41096
  var buildAbsoluteMobileUpdate = async (options) => {
40692
- const bundleDirectory = resolve18(options.bundleDirectory);
40693
- const outputRoot = resolve18(options.outputDirectory);
41097
+ const bundleDirectory = resolve19(options.bundleDirectory);
41098
+ const outputRoot = resolve19(options.outputDirectory);
40694
41099
  if (outputRoot === bundleDirectory || outputRoot.startsWith(`${bundleDirectory}/`))
40695
41100
  throw new TypeError("Mobile update output must be outside the embedded bundle.");
40696
41101
  const paths = await listFiles(bundleDirectory);
@@ -40718,38 +41123,38 @@ var buildAbsoluteMobileUpdate = async (options) => {
40718
41123
  value: signature.toString("base64")
40719
41124
  }
40720
41125
  });
40721
- await mkdir17(outputRoot, { recursive: true });
40722
- const outputDirectory = join27(outputRoot, manifest.releaseId);
40723
- const staging = await mkdtemp8(join27(outputRoot, ".stage-"));
41126
+ await mkdir18(outputRoot, { recursive: true });
41127
+ const outputDirectory = join28(outputRoot, manifest.releaseId);
41128
+ const staging = await mkdtemp9(join28(outputRoot, ".stage-"));
40724
41129
  try {
40725
- await cp3(bundleDirectory, join27(staging, UPDATE_FILES_DIRECTORY), {
41130
+ await cp2(bundleDirectory, join28(staging, UPDATE_FILES_DIRECTORY), {
40726
41131
  force: true,
40727
41132
  recursive: true
40728
41133
  });
40729
- await writeFile20(join27(staging, UPDATE_MANIFEST_FILE), `${JSON.stringify(manifest, null, "\t")}
41134
+ await writeFile21(join28(staging, UPDATE_MANIFEST_FILE), `${JSON.stringify(manifest, null, "\t")}
40730
41135
  `);
40731
- await rename16(staging, outputDirectory);
41136
+ await rename17(staging, outputDirectory);
40732
41137
  } catch (error) {
40733
- await rm13(staging, { force: true, recursive: true });
41138
+ await rm14(staging, { force: true, recursive: true });
40734
41139
  if (typeof error === "object" && error !== null && Reflect.get(error, "code") === "EEXIST")
40735
41140
  throw new TypeError(`Mobile update ${manifest.releaseId} already exists.`, { cause: error });
40736
41141
  throw error;
40737
41142
  }
40738
41143
  return {
40739
41144
  manifest,
40740
- manifestPath: join27(outputDirectory, UPDATE_MANIFEST_FILE),
41145
+ manifestPath: join28(outputDirectory, UPDATE_MANIFEST_FILE),
40741
41146
  outputDirectory
40742
41147
  };
40743
41148
  };
40744
41149
  var copyAbsoluteMobileUpdateFile = async (updateDirectory, path, destination) => {
40745
- const source = resolve18(updateDirectory, UPDATE_FILES_DIRECTORY, path);
40746
- const root = resolve18(updateDirectory, UPDATE_FILES_DIRECTORY);
41150
+ const source = resolve19(updateDirectory, UPDATE_FILES_DIRECTORY, path);
41151
+ const root = resolve19(updateDirectory, UPDATE_FILES_DIRECTORY);
40747
41152
  if (!source.startsWith(`${root}/`))
40748
41153
  throw new TypeError("Update file escaped its release.");
40749
- await mkdir17(dirname18(destination), { recursive: true });
40750
- await cp3(source, destination, { force: true });
41154
+ await mkdir18(dirname19(destination), { recursive: true });
41155
+ await cp2(source, destination, { force: true });
40751
41156
  };
40752
- var readAbsoluteMobileUpdate = async (directory) => parseAbsoluteMobileUpdateManifest(JSON.parse(await readFile23(join27(resolve18(directory), UPDATE_MANIFEST_FILE), "utf8")));
41157
+ var readAbsoluteMobileUpdate = async (directory) => parseAbsoluteMobileUpdateManifest(JSON.parse(await readFile24(join28(resolve19(directory), UPDATE_MANIFEST_FILE), "utf8")));
40753
41158
  var verifyAbsoluteMobileUpdateSignature = (manifestValue, publicKey) => {
40754
41159
  const manifest = parseAbsoluteMobileUpdateManifest(manifestValue);
40755
41160
  const valid = verify("sha256", absoluteMobileUpdateSigningPayload(unsignedAbsoluteMobileUpdate(manifest)), { dsaEncoding: "ieee-p1363", key: publicKey }, Buffer.from(manifest.signature.value, "base64"));
@@ -40866,16 +41271,16 @@ var pruneAbsoluteMobileUpdates = async (options) => {
40866
41271
  var object5 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
40867
41272
  var isPublisher2 = (value) => object5(value) && typeof value.publishUpdate === "function" && typeof value.promoteUpdate === "function" && typeof value.rollbackUpdate === "function";
40868
41273
  var projectPath2 = (projectRoot, requested, label) => {
40869
- const root = resolve19(projectRoot);
40870
- const path = resolve19(root, requested);
40871
- const projectRelative = relative17(root, path);
40872
- if (projectRelative === ".." || projectRelative.startsWith(`..${sep10}`) || isAbsolute8(projectRelative))
41274
+ const root = resolve20(projectRoot);
41275
+ const path = resolve20(root, requested);
41276
+ const projectRelative = relative18(root, path);
41277
+ if (projectRelative === ".." || projectRelative.startsWith(`..${sep11}`) || isAbsolute9(projectRelative))
40873
41278
  throw new TypeError(`${label} must remain inside the project.`);
40874
41279
  return path;
40875
41280
  };
40876
41281
  var loadAbsoluteMobileUpdatePublisher = async (projectRoot, requestedModulePath) => {
40877
41282
  const modulePath = projectPath2(projectRoot, requestedModulePath, "mobile update registry");
40878
- await access16(modulePath).catch(() => {
41283
+ await access17(modulePath).catch(() => {
40879
41284
  throw new TypeError(`Mobile update registry does not exist: ${modulePath}`);
40880
41285
  });
40881
41286
  const loaded = await import(pathToFileURL4(modulePath).href);
@@ -40926,7 +41331,7 @@ var rollbackAbsoluteMobileUpdate = async (options) => {
40926
41331
  return result;
40927
41332
  };
40928
41333
  // src/mobile/updateRollout.ts
40929
- import { createHash as createHash15 } from "crypto";
41334
+ import { createHash as createHash16 } from "crypto";
40930
41335
  var UUID_PATTERN = /^[a-f0-9]{8}-[a-f0-9]{4}-[1-8][a-f0-9]{3}-[89ab][a-f0-9]{3}-[a-f0-9]{12}$/u;
40931
41336
  var requireHeader = (headers, name) => {
40932
41337
  const value = headers.get(name);
@@ -40941,7 +41346,7 @@ var isAbsoluteMobileUpdateRolloutMember = (options) => {
40941
41346
  return false;
40942
41347
  if (options.rollout === 1)
40943
41348
  return true;
40944
- const digest = createHash15("sha256").update(`${options.appId}\x00${options.channel}\x00${options.releaseId}\x00${options.installationId}`).digest();
41349
+ const digest = createHash16("sha256").update(`${options.appId}\x00${options.channel}\x00${options.releaseId}\x00${options.installationId}`).digest();
40945
41350
  const bucket = digest.readUInt32BE(0) / 4294967296;
40946
41351
  return bucket < options.rollout;
40947
41352
  };
@@ -40965,6 +41370,9 @@ init_updateServer();
40965
41370
  export {
40966
41371
  ABSOLUTE_ANDROID_RELEASE_FORMAT,
40967
41372
  ABSOLUTE_AUTH_PACKAGE,
41373
+ ABSOLUTE_BUNDLETOOL_SHA256,
41374
+ ABSOLUTE_BUNDLETOOL_URL,
41375
+ ABSOLUTE_BUNDLETOOL_VERSION,
40968
41376
  ABSOLUTE_EXPO_AUTH_CORE_VERSION,
40969
41377
  ABSOLUTE_EXPO_AUTH_PACKAGE,
40970
41378
  ABSOLUTE_EXPO_AUTH_VERSION,
@@ -41013,6 +41421,7 @@ export {
41013
41421
  MOBILE_PAGE_REQUEST_HEADERS,
41014
41422
  absoluteAndroidNodeLabel,
41015
41423
  absoluteAndroidTouchTargetDp,
41424
+ absoluteBundletoolPath,
41016
41425
  absoluteDeviceNativeRequirements,
41017
41426
  absoluteExpoExecutable,
41018
41427
  absoluteExpoNativeObservabilityFiles,
@@ -41080,6 +41489,7 @@ export {
41080
41489
  discoverAbsoluteSyncSchema,
41081
41490
  disposeAbsoluteMobilePage,
41082
41491
  drainAbsoluteMobileNativeObservability,
41492
+ ensureAbsoluteBundletool,
41083
41493
  expoNativeObservabilityRuntimeSource,
41084
41494
  fetchAbsoluteMobilePage,
41085
41495
  finalizeAbsoluteExpoUpdateExport,
@@ -41096,6 +41506,7 @@ export {
41096
41506
  getCurrentAbsoluteMobileProducerContext,
41097
41507
  hashAbsoluteMobilePropsSchema,
41098
41508
  inspectAbsoluteAndroidInstalledApp,
41509
+ inspectAbsoluteBundletool,
41099
41510
  inspectAbsoluteIosInstalledApp,
41100
41511
  inspectAbsoluteMobileRouteMetadata,
41101
41512
  inspectAbsoluteMobileUpdateHealth,
@@ -41171,6 +41582,7 @@ export {
41171
41582
  publishAbsoluteAndroidRelease,
41172
41583
  publishAbsoluteIosRelease,
41173
41584
  publishAbsoluteMobileUpdate,
41585
+ readAbsoluteAndroidRelease,
41174
41586
  readAbsoluteMobileLinkIntent,
41175
41587
  readAbsoluteMobileMaterializedReleases,
41176
41588
  readAbsoluteMobileUpdate,
@@ -41193,6 +41605,7 @@ export {
41193
41605
  resumeAbsoluteMobileUpdateRollout,
41194
41606
  retainAbsoluteMobileCompatibilityArtifacts,
41195
41607
  rollbackAbsoluteMobileUpdate,
41608
+ runAbsoluteAndroidReleaseAcceptance,
41196
41609
  runAbsoluteAndroidUpgradeConformance,
41197
41610
  runWithAbsoluteMobileProducer,
41198
41611
  serializeAbsoluteMobileAuthEnvironment,
@@ -41219,5 +41632,5 @@ export {
41219
41632
  writeAbsoluteMobileUpdateRegistry
41220
41633
  };
41221
41634
 
41222
- //# debugId=E20E65274897005764756E2164756E21
41635
+ //# debugId=FC8B1849EF68EB6464756E2164756E21
41223
41636
  //# sourceMappingURL=index.js.map