@absolutejs/absolute 0.20.0-beta.104 → 0.20.0-beta.106
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +14 -0
- package/changelog.json +45 -0
- package/dist/angular/components/core/streamingSlotRegistrar.js +1 -1
- package/dist/angular/components/core/streamingSlotRegistry.js +2 -2
- package/dist/cli/{compile-g8vmvr0w.js → compile-hsbs1xf6.js} +2 -2
- package/dist/cli/{dev-m4r4zs2k.js → dev-f6b6hkke.js} +4 -4
- package/dist/cli/{expoProject-780thyfd.js → expoProject-zkprmjjz.js} +1 -1
- package/dist/cli/{index-d5fr1xp3.js → index-0zcebhm4.js} +59 -1
- package/dist/cli/{index-wpfvpsk7.js → index-5skbydh0.js} +1 -1
- package/dist/cli/{index-67kedtn7.js → index-hrzd7e5x.js} +1 -1
- package/dist/cli/{index-3sdvzrv2.js → index-jf1f6npt.js} +233 -4
- package/dist/cli/{index-27hhdgtg.js → index-mazxtfh4.js} +1 -1
- package/dist/cli/{index-qxnptvwn.js → index-q1d4ns4n.js} +100 -9
- package/dist/cli/index.js +5 -5
- package/dist/cli/{iosNativeWatcher-3k715hq0.js → iosNativeWatcher-t6gv0p1w.js} +2 -2
- package/dist/cli/{iosSimulatorController-dr98a0p9.js → iosSimulatorController-5n2a9fxv.js} +2 -2
- package/dist/cli/{mobile-njmnd7vc.js → mobile-w4my2dc7.js} +1008 -173
- package/dist/cli/{remoteMacProtocol-kqvkp0qd.js → remoteMacProtocol-dybpgazw.js} +6 -2
- package/dist/cli/{start-39aqmr5n.js → start-5grq7nfr.js} +3 -3
- package/dist/mobile/index.js +1445 -575
- package/dist/mobile/index.js.map +10 -9
- package/dist/mobile/remoteMacAgentEntry.js +341 -294
- package/dist/src/mobile/index.d.ts +1 -0
- package/dist/src/mobile/iosRelease.d.ts +31 -7
- package/dist/src/mobile/iosReleaseAcceptance.d.ts +66 -0
- package/dist/src/mobile/iosTestReport.d.ts +1 -0
- package/dist/src/mobile/nativeReleaseReadiness.d.ts +1 -1
- package/dist/src/mobile/nativeTestReport.d.ts +16 -0
- package/dist/src/mobile/remoteMacProtocol.d.ts +51 -4
- package/dist/src/mobile/remoteMacWire.d.ts +1 -1
- package/dist/src/mobile/shellReleaseReadiness.d.ts +1 -1
- package/package.json +1 -1
package/dist/mobile/index.js
CHANGED
|
@@ -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
|
|
615
|
-
import { createHash as
|
|
614
|
+
import { resolve as resolve8 } from "path";
|
|
615
|
+
import { createHash as createHash10, 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 =
|
|
618
|
-
const path =
|
|
617
|
+
const root = resolve8(projectRoot);
|
|
618
|
+
const path = resolve8(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:
|
|
790
|
+
certificateSha256: createHash10("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
|
|
1021
|
-
mkdir as
|
|
1022
|
-
readFile as
|
|
1020
|
+
access as access10,
|
|
1021
|
+
mkdir as mkdir9,
|
|
1022
|
+
readFile as readFile12,
|
|
1023
1023
|
rename as rename9,
|
|
1024
|
-
rm as
|
|
1024
|
+
rm as rm9,
|
|
1025
1025
|
writeFile as writeFile9
|
|
1026
1026
|
} from "fs/promises";
|
|
1027
|
-
import { resolve as
|
|
1027
|
+
import { resolve as resolve9 } 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
|
|
1094
|
+
current = await readFile12(path, "utf8");
|
|
1095
1095
|
} catch (error) {
|
|
1096
1096
|
if (!(error instanceof Error) || !("code" in error) || error.code !== "ENOENT") {
|
|
1097
1097
|
throw error;
|
|
@@ -1103,18 +1103,18 @@ var JSON_HEADERS, OWNERSHIP_FILE = ".absolutejs-mobile-associations.json", HTTP_
|
|
|
1103
1103
|
await writeFile9(temporary, source, { flag: "wx" });
|
|
1104
1104
|
await rename9(temporary, path);
|
|
1105
1105
|
return true;
|
|
1106
|
-
},
|
|
1106
|
+
}, exists4 = async (path) => {
|
|
1107
1107
|
try {
|
|
1108
|
-
await
|
|
1108
|
+
await access10(path);
|
|
1109
1109
|
return true;
|
|
1110
1110
|
} catch {
|
|
1111
1111
|
return false;
|
|
1112
1112
|
}
|
|
1113
1113
|
}, assertOwnedOutput = async (root) => {
|
|
1114
|
-
const path =
|
|
1114
|
+
const path = resolve9(root, OWNERSHIP_FILE);
|
|
1115
1115
|
let ownership;
|
|
1116
1116
|
try {
|
|
1117
|
-
ownership = JSON.parse(await
|
|
1117
|
+
ownership = JSON.parse(await readFile12(path, "utf8"));
|
|
1118
1118
|
} catch {
|
|
1119
1119
|
throw new TypeError(`Association output ${root} already exists and is not owned by AbsoluteJS.`);
|
|
1120
1120
|
}
|
|
@@ -1122,7 +1122,7 @@ 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
|
|
1125
|
+
const hasCurrent = await exists4(root);
|
|
1126
1126
|
if (hasCurrent)
|
|
1127
1127
|
await assertOwnedOutput(root);
|
|
1128
1128
|
const backup = `${root}.${crypto.randomUUID()}.previous`;
|
|
@@ -1136,12 +1136,12 @@ var JSON_HEADERS, OWNERSHIP_FILE = ".absolutejs-mobile-associations.json", HTTP_
|
|
|
1136
1136
|
throw error;
|
|
1137
1137
|
}
|
|
1138
1138
|
if (hasCurrent)
|
|
1139
|
-
await
|
|
1139
|
+
await rm9(backup, { force: true, recursive: true });
|
|
1140
1140
|
}, materializeHost = async (root, host, files) => {
|
|
1141
|
-
const directory =
|
|
1142
|
-
await
|
|
1141
|
+
const directory = resolve9(root, host, ".well-known");
|
|
1142
|
+
await mkdir9(directory, { recursive: true });
|
|
1143
1143
|
return Promise.all(files.map(async ([name, document2]) => {
|
|
1144
|
-
const path =
|
|
1144
|
+
const path = resolve9(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 =
|
|
1167
|
+
const root = resolve9(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
|
|
1178
|
+
await mkdir9(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(
|
|
1181
|
+
await writeAtomic(resolve9(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) =>
|
|
1184
|
+
const written = temporaryPaths.map((path) => resolve9(root, path.slice(temporary.length + 1)));
|
|
1185
1185
|
return { root, written };
|
|
1186
1186
|
} catch (error) {
|
|
1187
|
-
await
|
|
1187
|
+
await rm9(temporary, { force: true, recursive: true });
|
|
1188
1188
|
throw error;
|
|
1189
1189
|
}
|
|
1190
1190
|
}, verifyAbsoluteMobileAssociationFiles = async (config, request = globalThis.fetch) => {
|
|
@@ -1607,24 +1607,24 @@ __export(exports_materializedBundle, {
|
|
|
1607
1607
|
materializeAbsoluteMobileCompatibilityBundle: () => materializeAbsoluteMobileCompatibilityBundle,
|
|
1608
1608
|
readAbsoluteMobileMaterializedReleases: () => readAbsoluteMobileMaterializedReleases
|
|
1609
1609
|
});
|
|
1610
|
-
import { createHash as
|
|
1610
|
+
import { createHash as createHash12 } from "crypto";
|
|
1611
1611
|
import {
|
|
1612
|
-
access as
|
|
1613
|
-
mkdir as
|
|
1614
|
-
mkdtemp as
|
|
1615
|
-
readFile as
|
|
1612
|
+
access as access11,
|
|
1613
|
+
mkdir as mkdir12,
|
|
1614
|
+
mkdtemp as mkdtemp8,
|
|
1615
|
+
readFile as readFile15,
|
|
1616
1616
|
rename as rename11,
|
|
1617
|
-
rm as
|
|
1617
|
+
rm as rm11,
|
|
1618
1618
|
writeFile as writeFile12
|
|
1619
1619
|
} from "fs/promises";
|
|
1620
|
-
import { dirname as
|
|
1620
|
+
import { dirname as dirname10, join as join13, resolve as resolvePath4 } from "path";
|
|
1621
1621
|
import { pathToFileURL } from "url";
|
|
1622
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_${
|
|
1627
|
+
return `amb_${createHash12("sha256").update(identity).digest("hex")}`;
|
|
1628
1628
|
}, parseBundleIndex = (value) => {
|
|
1629
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.");
|
|
@@ -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 =
|
|
1652
|
-
const producerPath =
|
|
1653
|
-
await
|
|
1651
|
+
const directory = join13(root, release.artifact.releaseId);
|
|
1652
|
+
const producerPath = join13(directory, release.artifact.producer.module);
|
|
1653
|
+
await mkdir12(dirname10(producerPath), { recursive: true });
|
|
1654
1654
|
await Promise.all([
|
|
1655
|
-
writeFile12(
|
|
1655
|
+
writeFile12(join13(directory, ARTIFACT_FILE2), `${JSON.stringify(release.artifact, null, "\t")}
|
|
1656
1656
|
`),
|
|
1657
1657
|
writeFile12(producerPath, new Uint8Array(await release.producer.arrayBuffer()))
|
|
1658
1658
|
]);
|
|
1659
1659
|
}, installImmutableBundle = async (bundlesRoot, bundleId, releases) => {
|
|
1660
|
-
const destination =
|
|
1660
|
+
const destination = join13(bundlesRoot, bundleId);
|
|
1661
1661
|
try {
|
|
1662
|
-
await
|
|
1662
|
+
await access11(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
|
|
1668
|
+
const staging = await mkdtemp8(join13(bundlesRoot, ".stage-"));
|
|
1669
1669
|
try {
|
|
1670
1670
|
await Promise.all(releases.map((release) => writeRelease(staging, release)));
|
|
1671
1671
|
await rename11(staging, destination);
|
|
1672
1672
|
} catch (error) {
|
|
1673
|
-
await
|
|
1673
|
+
await rm11(staging, { force: true, recursive: true });
|
|
1674
1674
|
if (errorHasCode3(error, "EEXIST") || errorHasCode3(error, "ENOTEMPTY")) {
|
|
1675
1675
|
return destination;
|
|
1676
1676
|
}
|
|
@@ -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
|
|
1699
|
+
const serialized = await readFile15(join13(resolvedRoot, CURRENT_BUNDLE_FILE), "utf8");
|
|
1700
1700
|
const parsed = JSON.parse(serialized);
|
|
1701
1701
|
const index = parseBundleIndex(parsed);
|
|
1702
|
-
const bundleRoot =
|
|
1702
|
+
const bundleRoot = join13(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 =
|
|
1707
|
+
const modulePath = join13(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 =
|
|
1734
|
-
await
|
|
1733
|
+
const bundlesRoot = join13(root, BUNDLES_DIRECTORY);
|
|
1734
|
+
await mkdir12(bundlesRoot, { recursive: true });
|
|
1735
1735
|
const bundleId = bundleIdFor(input.currentReleaseId, artifacts);
|
|
1736
1736
|
await installImmutableBundle(bundlesRoot, bundleId, orderedReleases);
|
|
1737
1737
|
const index = {
|
|
@@ -1740,8 +1740,8 @@ 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 =
|
|
1744
|
-
const temporaryPointerPath =
|
|
1743
|
+
const pointerPath = join13(root, CURRENT_BUNDLE_FILE);
|
|
1744
|
+
const temporaryPointerPath = join13(root, `.current-${crypto.randomUUID()}.json`);
|
|
1745
1745
|
await writeFile12(temporaryPointerPath, `${JSON.stringify(index, null, "\t")}
|
|
1746
1746
|
`, { flag: "wx" });
|
|
1747
1747
|
await rename11(temporaryPointerPath, pointerPath);
|
|
@@ -1749,12 +1749,12 @@ var ABSOLUTE_MOBILE_MATERIALIZED_BUNDLE_FORMAT = 1, CURRENT_BUNDLE_FILE = "curre
|
|
|
1749
1749
|
}, readAbsoluteMobileMaterializedReleases = async (root) => {
|
|
1750
1750
|
const resolvedRoot = resolvePath4(root);
|
|
1751
1751
|
try {
|
|
1752
|
-
const serialized = await
|
|
1752
|
+
const serialized = await readFile15(join13(resolvedRoot, CURRENT_BUNDLE_FILE), "utf8");
|
|
1753
1753
|
const parsed = JSON.parse(serialized);
|
|
1754
1754
|
const index = parseBundleIndex(parsed);
|
|
1755
|
-
const bundleRoot =
|
|
1755
|
+
const bundleRoot = join13(resolvedRoot, BUNDLES_DIRECTORY, index.bundleId);
|
|
1756
1756
|
return Promise.all(index.releases.map(async (artifact) => {
|
|
1757
|
-
const producer = Bun.file(
|
|
1757
|
+
const producer = Bun.file(join13(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
|
|
1778
|
+
import { extname as extname3, join as join14, relative as relative11, resolve as resolve12 } 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 =
|
|
1906
|
+
let path = join14(resolve12(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(
|
|
1961
|
+
return readJson(join14(resolve12(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(
|
|
1970
|
+
const manifest = readJson(join14(resolve12(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 =
|
|
1980
|
+
const root = resolve12(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 =
|
|
1986
|
+
const portable = relative11(root, resolve12(root, path)).replaceAll("\\", "/");
|
|
1987
1987
|
if (isIgnored(portable))
|
|
1988
1988
|
continue;
|
|
1989
|
-
const source = readFileSync3(
|
|
1989
|
+
const source = readFileSync3(resolve12(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 =
|
|
1999
|
+
const root = resolve12(projectRoot);
|
|
2000
2000
|
for (const path of SOURCE_GLOB.scanSync({ cwd: root })) {
|
|
2001
|
-
const portable =
|
|
2001
|
+
const portable = relative11(root, resolve12(root, path)).replaceAll("\\", "/");
|
|
2002
2002
|
if (isIgnored(portable))
|
|
2003
2003
|
continue;
|
|
2004
|
-
const source = readFileSync3(
|
|
2004
|
+
const source = readFileSync3(resolve12(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
|
|
2071
|
+
import { join as join15 } 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(
|
|
2074
|
+
return JSON.parse(readFileSync4(join15(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
|
|
2244
|
+
import { dirname as dirname11, join as join16, resolve as resolve13 } 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 =
|
|
2261
|
+
let directory = resolve13(projectRoot);
|
|
2262
2262
|
while (true) {
|
|
2263
|
-
const candidate =
|
|
2263
|
+
const candidate = join16(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 =
|
|
2267
|
+
const parent = dirname11(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 =
|
|
2494
|
+
const appManifestPath = join16(resolve13(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
|
|
6842
|
-
forge.md.sha256 = forge.md.algorithms.sha256 =
|
|
6843
|
-
|
|
6841
|
+
var sha2564 = module.exports = forge.sha256 = forge.sha256 || {};
|
|
6842
|
+
forge.md.sha256 = forge.md.algorithms.sha256 = sha2564;
|
|
6843
|
+
sha2564.create = function() {
|
|
6844
6844
|
if (!_initialized) {
|
|
6845
6845
|
_init();
|
|
6846
6846
|
}
|
|
@@ -19351,7 +19351,7 @@ var init_compatibilityDispatcher = __esm(() => {
|
|
|
19351
19351
|
// src/cli/scripts/telemetry.ts
|
|
19352
19352
|
import { existsSync as existsSync5, mkdirSync, readFileSync as readFileSync6, writeFileSync } from "fs";
|
|
19353
19353
|
import { homedir as homedir4 } from "os";
|
|
19354
|
-
import { join as
|
|
19354
|
+
import { join as join23 } 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 =
|
|
19368
|
-
configPath =
|
|
19367
|
+
configDir = join23(homedir4(), ".absolutejs");
|
|
19368
|
+
configPath = join23(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
|
|
19374
|
+
import { dirname as dirname16, join as join24, 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 =
|
|
19394
|
+
const candidate = join24(dir, "package.json");
|
|
19395
19395
|
const version = checkCandidate(candidate);
|
|
19396
19396
|
if (version) {
|
|
19397
19397
|
return version;
|
|
19398
19398
|
}
|
|
19399
|
-
dir =
|
|
19399
|
+
dir = dirname16(dir);
|
|
19400
19400
|
}
|
|
19401
19401
|
return "unknown";
|
|
19402
19402
|
}, sendTelemetryEvent = (event, payload) => {
|
|
@@ -20032,7 +20032,7 @@ __export(exports_mobileUpdate, {
|
|
|
20032
20032
|
parseMobileUpdateManifest: () => parseMobileUpdateManifest
|
|
20033
20033
|
});
|
|
20034
20034
|
import {
|
|
20035
|
-
createHash as
|
|
20035
|
+
createHash as createHash18,
|
|
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
|
|
20045
|
+
import { readFile as readFile27, stat as stat7 } 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) =>
|
|
20195
|
+
}, appHash = (appId) => createHash18("sha256").update(appId).digest("hex"), digest = (bytes) => createHash18("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 =
|
|
20206
|
+
const value = createHash18("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,
|
|
20246
|
+
const contentBlobKey = (appId, sha2565) => `${root(appId)}/blobs/${sha2565}`;
|
|
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
|
|
20868
|
-
if (HASH.test(
|
|
20869
|
-
objectKeysByDigest.set(
|
|
20870
|
-
objectBytesByDigest.set(
|
|
20867
|
+
const sha2565 = blobObject.key.slice(blobPrefix.length);
|
|
20868
|
+
if (HASH.test(sha2565)) {
|
|
20869
|
+
objectKeysByDigest.set(sha2565, blobObject.key);
|
|
20870
|
+
objectBytesByDigest.set(sha2565, 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(([
|
|
20953
|
+
const reclaimableContentBytes = [...objectBytesByDigest].filter(([sha2565]) => !protectedDigests.has(sha2565)).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 [
|
|
21051
|
-
if (referencedDigests.has(
|
|
21050
|
+
for (const [sha2565, key] of afterReleaseSweep.objectKeysByDigest) {
|
|
21051
|
+
if (referencedDigests.has(sha2565))
|
|
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(
|
|
21056
|
+
result.sweptContentBlobs.push(sha2565);
|
|
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
|
|
21078
|
+
const localManifest = parseMobileUpdateManifest(JSON.parse(await readFile27(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
|
|
21096
|
+
const metadata = await stat7(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,7 +21208,7 @@ 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) :
|
|
21211
|
+
const hash = RELEASE.test(releaseId) ? releaseId.slice("amu_".length, "amu_".length + 32) : createHash18("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
21213
|
}, expoContentType = (extension2, launch2) => {
|
|
21214
21214
|
if (launch2)
|
|
@@ -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
|
|
21365
|
-
if (request.method === "POST" &&
|
|
21364
|
+
const relative20 = pathname.startsWith(`${route}/`) ? pathname.slice(route.length + 1) : "";
|
|
21365
|
+
if (request.method === "POST" && relative20 === "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 (
|
|
21408
|
+
if (relative20 === "update.json") {
|
|
21409
21409
|
const expoProtocolVersion = request.headers.get("expo-protocol-version");
|
|
21410
21410
|
const expoProtocol = expoProtocolVersion !== null;
|
|
21411
21411
|
if (expoProtocol && expoProtocolVersion !== "1")
|
|
@@ -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(
|
|
21526
|
+
const match = /^(amu_[a-f0-9]{64})\/files\/(.+)$/.exec(relative20);
|
|
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
|
|
21620
|
-
import { dirname as
|
|
21619
|
+
import { access as access19, mkdir as mkdir21 } from "fs/promises";
|
|
21620
|
+
import { dirname as dirname22, isAbsolute as isAbsolute11, relative as relative20, resolve as resolve22, sep as sep13 } 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 =
|
|
21625
|
-
const path2 =
|
|
21626
|
-
const projectRelative =
|
|
21627
|
-
if (projectRelative === ".." || projectRelative.startsWith(`..${
|
|
21624
|
+
const root = resolve22(projectRoot);
|
|
21625
|
+
const path2 = resolve22(root, requested);
|
|
21626
|
+
const projectRelative = relative20(root, path2);
|
|
21627
|
+
if (projectRelative === ".." || projectRelative.startsWith(`..${sep13}`) || isAbsolute11(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
|
|
21650
|
+
await access19(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
|
|
21839
|
+
await access19(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
|
|
21845
|
+
await mkdir21(dirname22(path2), { recursive: true });
|
|
21846
21846
|
await Bun.write(path2, renderAbsoluteMobileUpdateRegistry({
|
|
21847
21847
|
...options.health ? { health: options.health } : {},
|
|
21848
21848
|
...options.rollout ? { rollout: options.rollout } : {},
|
|
@@ -25393,6 +25393,25 @@ var safeOutputDirectory2 = (projectRoot, requested) => {
|
|
|
25393
25393
|
return output;
|
|
25394
25394
|
};
|
|
25395
25395
|
var sha256File2 = async (path) => createHash6("sha256").update(await readFile7(path)).digest("hex");
|
|
25396
|
+
var verifyRegisteredReleaseArtifact = async (releaseRoot, metadata) => {
|
|
25397
|
+
if (!metadata.registeredDevice)
|
|
25398
|
+
return;
|
|
25399
|
+
const destination = join7(releaseRoot, metadata.registeredDevice.artifact);
|
|
25400
|
+
const [bytes, sha2562] = await Promise.all([
|
|
25401
|
+
stat3(destination).then(({ size }) => size),
|
|
25402
|
+
sha256File2(destination)
|
|
25403
|
+
]);
|
|
25404
|
+
if (bytes !== metadata.registeredDevice.bytes || sha2562 !== metadata.registeredDevice.sha256)
|
|
25405
|
+
throw new TypeError(`Immutable iOS release ${metadata.releaseId} registered-device artifact is missing or modified.`);
|
|
25406
|
+
return destination;
|
|
25407
|
+
};
|
|
25408
|
+
var copyRegisteredReleaseArtifact = async (staging, metadata, registeredArtifactPath) => {
|
|
25409
|
+
if (!metadata.registeredDevice)
|
|
25410
|
+
return;
|
|
25411
|
+
if (!registeredArtifactPath)
|
|
25412
|
+
throw new TypeError("iOS release metadata requires a registered-device artifact.");
|
|
25413
|
+
await copyFile3(registeredArtifactPath, join7(staging, metadata.registeredDevice.artifact));
|
|
25414
|
+
};
|
|
25396
25415
|
var findByExtension = async (root, extension) => {
|
|
25397
25416
|
if (!await pathExists4(root))
|
|
25398
25417
|
return;
|
|
@@ -25448,12 +25467,12 @@ var resolveAbsoluteIosXcodeProject = async (nativeDirectory, options = {}) => {
|
|
|
25448
25467
|
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.");
|
|
25449
25468
|
return { scheme: schemes[0], workspacePath };
|
|
25450
25469
|
};
|
|
25451
|
-
var exportOptions = () => `<?xml version="1.0" encoding="UTF-8"?>
|
|
25470
|
+
var exportOptions = (method) => `<?xml version="1.0" encoding="UTF-8"?>
|
|
25452
25471
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
25453
25472
|
<plist version="1.0"><dict>
|
|
25454
25473
|
<key>destination</key><string>export</string>
|
|
25455
25474
|
<key>manageAppVersionAndBuildNumber</key><false/>
|
|
25456
|
-
<key>method</key><string
|
|
25475
|
+
<key>method</key><string>${method}</string>
|
|
25457
25476
|
<key>signingStyle</key><string>automatic</string>
|
|
25458
25477
|
<key>stripSwiftSymbols</key><true/>
|
|
25459
25478
|
<key>uploadSymbols</key><true/>
|
|
@@ -25464,7 +25483,19 @@ var requireBuildNumber = (value) => {
|
|
|
25464
25483
|
throw new TypeError("iOS build number must be a positive integer.");
|
|
25465
25484
|
return value;
|
|
25466
25485
|
};
|
|
25486
|
+
var normalizeRegisteredDevice = (value) => {
|
|
25487
|
+
if (value === undefined)
|
|
25488
|
+
return;
|
|
25489
|
+
if (!isRecord3(value) || value.artifact !== "App.registered.ipa" || typeof value.bytes !== "number" || !Number.isSafeInteger(value.bytes) || value.bytes < 1 || typeof value.sha256 !== "string" || !/^[a-f0-9]{64}$/u.test(value.sha256))
|
|
25490
|
+
throw new TypeError("Invalid AbsoluteJS iOS release metadata.");
|
|
25491
|
+
return {
|
|
25492
|
+
artifact: "App.registered.ipa",
|
|
25493
|
+
bytes: value.bytes,
|
|
25494
|
+
sha256: value.sha256
|
|
25495
|
+
};
|
|
25496
|
+
};
|
|
25467
25497
|
var requireAbsoluteIosReleaseMetadata = (value) => {
|
|
25498
|
+
const registeredDevice = normalizeRegisteredDevice(isRecord3(value) ? value.registeredDevice : undefined);
|
|
25468
25499
|
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}`) {
|
|
25469
25500
|
throw new TypeError("Invalid AbsoluteJS iOS release metadata.");
|
|
25470
25501
|
}
|
|
@@ -25478,6 +25509,7 @@ var requireAbsoluteIosReleaseMetadata = (value) => {
|
|
|
25478
25509
|
format: value.format,
|
|
25479
25510
|
marketingVersion: value.marketingVersion,
|
|
25480
25511
|
platform: value.platform,
|
|
25512
|
+
...registeredDevice ? { registeredDevice } : {},
|
|
25481
25513
|
releaseId: value.releaseId,
|
|
25482
25514
|
runtime: value.runtime,
|
|
25483
25515
|
sha256: value.sha256,
|
|
@@ -25485,12 +25517,13 @@ var requireAbsoluteIosReleaseMetadata = (value) => {
|
|
|
25485
25517
|
type: value.type
|
|
25486
25518
|
};
|
|
25487
25519
|
};
|
|
25488
|
-
var installRelease2 = async (artifactPath, metadata, outputRoot) => {
|
|
25520
|
+
var installRelease2 = async (artifactPath, metadata, outputRoot, registeredArtifactPath) => {
|
|
25489
25521
|
const releaseRoot = join7(outputRoot, metadata.releaseId);
|
|
25490
25522
|
const destination = join7(releaseRoot, "App.ipa");
|
|
25491
25523
|
if (await pathExists4(releaseRoot)) {
|
|
25492
25524
|
const value = JSON.parse(await readFile7(join7(releaseRoot, "release.json"), "utf8"));
|
|
25493
|
-
|
|
25525
|
+
const existing = requireAbsoluteIosReleaseMetadata(value);
|
|
25526
|
+
if (JSON.stringify(existing) !== JSON.stringify({ ...metadata, artifact: "App.ipa" })) {
|
|
25494
25527
|
throw new TypeError(`Immutable iOS release ${metadata.releaseId} does not match its content.`);
|
|
25495
25528
|
}
|
|
25496
25529
|
const [bytes, sha2562] = await Promise.all([
|
|
@@ -25499,12 +25532,14 @@ var installRelease2 = async (artifactPath, metadata, outputRoot) => {
|
|
|
25499
25532
|
]);
|
|
25500
25533
|
if (bytes !== metadata.bytes || sha2562 !== metadata.sha256)
|
|
25501
25534
|
throw new TypeError(`Immutable iOS release ${metadata.releaseId} artifact is missing or modified.`);
|
|
25535
|
+
const registeredDestination = await verifyRegisteredReleaseArtifact(releaseRoot, metadata);
|
|
25502
25536
|
return {
|
|
25503
25537
|
artifactPath: destination,
|
|
25504
25538
|
metadata: {
|
|
25505
25539
|
...metadata,
|
|
25506
25540
|
artifact: "App.ipa"
|
|
25507
25541
|
},
|
|
25542
|
+
...registeredDestination ? { registeredArtifactPath: registeredDestination } : {},
|
|
25508
25543
|
releaseRoot
|
|
25509
25544
|
};
|
|
25510
25545
|
}
|
|
@@ -25512,6 +25547,7 @@ var installRelease2 = async (artifactPath, metadata, outputRoot) => {
|
|
|
25512
25547
|
const staging = await mkdtemp4(join7(dirname4(releaseRoot), ".ios-stage-"));
|
|
25513
25548
|
try {
|
|
25514
25549
|
await copyFile3(artifactPath, join7(staging, "App.ipa"));
|
|
25550
|
+
await copyRegisteredReleaseArtifact(staging, metadata, registeredArtifactPath);
|
|
25515
25551
|
const complete = {
|
|
25516
25552
|
...metadata,
|
|
25517
25553
|
artifact: "App.ipa"
|
|
@@ -25519,13 +25555,50 @@ var installRelease2 = async (artifactPath, metadata, outputRoot) => {
|
|
|
25519
25555
|
await writeFile6(join7(staging, "release.json"), `${JSON.stringify(complete, null, "\t")}
|
|
25520
25556
|
`, { flag: "wx" });
|
|
25521
25557
|
await rename6(staging, releaseRoot);
|
|
25522
|
-
return {
|
|
25558
|
+
return {
|
|
25559
|
+
artifactPath: destination,
|
|
25560
|
+
metadata: complete,
|
|
25561
|
+
...metadata.registeredDevice ? {
|
|
25562
|
+
registeredArtifactPath: join7(releaseRoot, metadata.registeredDevice.artifact)
|
|
25563
|
+
} : {},
|
|
25564
|
+
releaseRoot
|
|
25565
|
+
};
|
|
25523
25566
|
} finally {
|
|
25524
25567
|
await rm5(staging, { force: true, recursive: true }).catch(() => {
|
|
25525
25568
|
return;
|
|
25526
25569
|
});
|
|
25527
25570
|
}
|
|
25528
25571
|
};
|
|
25572
|
+
var exportRegisteredDeviceArtifact = async (options) => {
|
|
25573
|
+
const exportPath = join7(options.staging, "registered-export");
|
|
25574
|
+
const exportPlist = join7(options.staging, "RegisteredExportOptions.plist");
|
|
25575
|
+
await mkdir5(exportPath, { recursive: true });
|
|
25576
|
+
await writeFile6(exportPlist, exportOptions("debugging"));
|
|
25577
|
+
const exitCode = await options.run([
|
|
25578
|
+
"xcodebuild",
|
|
25579
|
+
"-exportArchive",
|
|
25580
|
+
"-archivePath",
|
|
25581
|
+
options.archivePath,
|
|
25582
|
+
"-exportPath",
|
|
25583
|
+
exportPath,
|
|
25584
|
+
"-exportOptionsPlist",
|
|
25585
|
+
exportPlist
|
|
25586
|
+
], { cwd: options.nativeDirectory, env: options.env });
|
|
25587
|
+
if (exitCode !== 0)
|
|
25588
|
+
throw new TypeError("Xcode failed to export the registered-device IPA. Confirm the selected development team includes the test device.");
|
|
25589
|
+
const artifactPath = await findByExtension(exportPath, ".ipa");
|
|
25590
|
+
if (!artifactPath)
|
|
25591
|
+
throw new TypeError("Xcode did not produce a registered-device IPA.");
|
|
25592
|
+
const [bytes, sha2562] = await Promise.all([
|
|
25593
|
+
stat3(artifactPath).then(({ size }) => size),
|
|
25594
|
+
sha256File2(artifactPath)
|
|
25595
|
+
]);
|
|
25596
|
+
const metadata = { artifact: "App.registered.ipa", bytes, sha256: sha2562 };
|
|
25597
|
+
return {
|
|
25598
|
+
artifactPath,
|
|
25599
|
+
metadata
|
|
25600
|
+
};
|
|
25601
|
+
};
|
|
25529
25602
|
var buildAbsoluteIosRelease = async (options) => {
|
|
25530
25603
|
if (options.buildNumber !== undefined && options.prepareBuildNumber)
|
|
25531
25604
|
throw new TypeError("iOS release buildNumber and prepareBuildNumber cannot be combined.");
|
|
@@ -25555,7 +25628,7 @@ var buildAbsoluteIosRelease = async (options) => {
|
|
|
25555
25628
|
const exportPath = join7(staging, "export");
|
|
25556
25629
|
const exportPlist = join7(staging, "ExportOptions.plist");
|
|
25557
25630
|
await mkdir5(exportPath, { recursive: true });
|
|
25558
|
-
await writeFile6(exportPlist, exportOptions());
|
|
25631
|
+
await writeFile6(exportPlist, exportOptions("app-store-connect"));
|
|
25559
25632
|
const run = options.run ?? defaultRun2;
|
|
25560
25633
|
try {
|
|
25561
25634
|
const developmentTeam = developmentTeamArgument(options.developmentTeam);
|
|
@@ -25612,6 +25685,13 @@ var buildAbsoluteIosRelease = async (options) => {
|
|
|
25612
25685
|
sha256File2(artifactPath)
|
|
25613
25686
|
]);
|
|
25614
25687
|
const releaseId = `amobile_ios_${sha2562}`;
|
|
25688
|
+
const registered = options.registeredDeviceArtifact ? await exportRegisteredDeviceArtifact({
|
|
25689
|
+
archivePath,
|
|
25690
|
+
...options.env ? { env: options.env } : {},
|
|
25691
|
+
nativeDirectory,
|
|
25692
|
+
run,
|
|
25693
|
+
staging
|
|
25694
|
+
}) : undefined;
|
|
25615
25695
|
return await installRelease2(artifactPath, {
|
|
25616
25696
|
appBuild: manifest.appBuild,
|
|
25617
25697
|
appId: manifest.appId,
|
|
@@ -25621,12 +25701,13 @@ var buildAbsoluteIosRelease = async (options) => {
|
|
|
25621
25701
|
format: 1,
|
|
25622
25702
|
marketingVersion,
|
|
25623
25703
|
platform: "ios",
|
|
25704
|
+
...registered ? { registeredDevice: registered.metadata } : {},
|
|
25624
25705
|
releaseId,
|
|
25625
25706
|
runtime: manifest.runtime,
|
|
25626
25707
|
sha256: sha2562,
|
|
25627
25708
|
signed,
|
|
25628
25709
|
type: "ipa"
|
|
25629
|
-
}, safeOutputDirectory2(options.projectRoot, options.outputDirectory));
|
|
25710
|
+
}, safeOutputDirectory2(options.projectRoot, options.outputDirectory), registered?.artifactPath);
|
|
25630
25711
|
} finally {
|
|
25631
25712
|
await rm5(staging, { force: true, recursive: true }).catch(() => {
|
|
25632
25713
|
return;
|
|
@@ -25641,9 +25722,40 @@ var installAbsoluteIosRelease = async (options) => {
|
|
|
25641
25722
|
]);
|
|
25642
25723
|
if (bytes !== metadata.bytes || sha2562 !== metadata.sha256)
|
|
25643
25724
|
throw new TypeError("Remote iOS release artifact does not match its signed metadata.");
|
|
25725
|
+
if (metadata.registeredDevice) {
|
|
25726
|
+
if (!options.registeredArtifactPath)
|
|
25727
|
+
throw new TypeError("Remote iOS release metadata requires its registered-device artifact.");
|
|
25728
|
+
const [registeredBytes, registeredSha256] = await Promise.all([
|
|
25729
|
+
stat3(options.registeredArtifactPath).then(({ size }) => size),
|
|
25730
|
+
sha256File2(options.registeredArtifactPath)
|
|
25731
|
+
]);
|
|
25732
|
+
if (registeredBytes !== metadata.registeredDevice.bytes || registeredSha256 !== metadata.registeredDevice.sha256)
|
|
25733
|
+
throw new TypeError("Remote iOS registered-device artifact does not match its signed metadata.");
|
|
25734
|
+
}
|
|
25644
25735
|
const { artifact: _artifact, ...releaseMetadata } = metadata;
|
|
25645
|
-
return installRelease2(options.artifactPath, releaseMetadata, safeOutputDirectory2(options.projectRoot, options.outputDirectory));
|
|
25736
|
+
return installRelease2(options.artifactPath, releaseMetadata, safeOutputDirectory2(options.projectRoot, options.outputDirectory), options.registeredArtifactPath);
|
|
25646
25737
|
};
|
|
25738
|
+
// src/mobile/iosReleaseAcceptance.ts
|
|
25739
|
+
import { createHash as createHash7 } from "crypto";
|
|
25740
|
+
import {
|
|
25741
|
+
access as access8,
|
|
25742
|
+
mkdir as mkdir6,
|
|
25743
|
+
mkdtemp as mkdtemp5,
|
|
25744
|
+
readFile as readFile8,
|
|
25745
|
+
readdir as readdir4,
|
|
25746
|
+
rm as rm6,
|
|
25747
|
+
stat as stat4
|
|
25748
|
+
} from "fs/promises";
|
|
25749
|
+
import {
|
|
25750
|
+
basename as basename2,
|
|
25751
|
+
dirname as dirname5,
|
|
25752
|
+
isAbsolute as isAbsolute5,
|
|
25753
|
+
join as join8,
|
|
25754
|
+
relative as relative6,
|
|
25755
|
+
resolve as resolve6,
|
|
25756
|
+
sep as sep5
|
|
25757
|
+
} from "path";
|
|
25758
|
+
|
|
25647
25759
|
// src/mobile/iosUpgradeConformance.ts
|
|
25648
25760
|
var captureCommand5 = async (command) => {
|
|
25649
25761
|
const process2 = Bun.spawn(command, { stderr: "pipe", stdout: "pipe" });
|
|
@@ -25714,8 +25826,402 @@ var assertAbsoluteIosInstalledAppUpgrade = (before, after) => {
|
|
|
25714
25826
|
if (afterBuild <= beforeBuild)
|
|
25715
25827
|
throw new Error(`iOS CFBundleVersion did not increase (${before.buildNumber} -> ${after.buildNumber}).`);
|
|
25716
25828
|
};
|
|
25829
|
+
|
|
25830
|
+
// src/mobile/iosReleaseAcceptance.ts
|
|
25831
|
+
var READY_MARKERS = {
|
|
25832
|
+
capacitor: "Capacitor embedded web content ready",
|
|
25833
|
+
expo: "Expo embedded web content ready"
|
|
25834
|
+
};
|
|
25835
|
+
var READY_TIMEOUT_MS = 30000;
|
|
25836
|
+
var READY_POLL_MS = 250;
|
|
25837
|
+
var defaultRun3 = async (command, options = {}) => {
|
|
25838
|
+
const process2 = Bun.spawn(command, {
|
|
25839
|
+
cwd: options.cwd,
|
|
25840
|
+
env: options.env,
|
|
25841
|
+
signal: options.signal,
|
|
25842
|
+
stderr: "pipe",
|
|
25843
|
+
stdin: "ignore",
|
|
25844
|
+
stdout: "pipe"
|
|
25845
|
+
});
|
|
25846
|
+
const [exitCode, stderr, stdout] = await Promise.all([
|
|
25847
|
+
process2.exited,
|
|
25848
|
+
new Response(process2.stderr).text(),
|
|
25849
|
+
new Response(process2.stdout).text()
|
|
25850
|
+
]);
|
|
25851
|
+
return { exitCode, stderr, stdout };
|
|
25852
|
+
};
|
|
25853
|
+
var exists3 = async (path) => {
|
|
25854
|
+
try {
|
|
25855
|
+
await access8(path);
|
|
25856
|
+
return true;
|
|
25857
|
+
} catch {
|
|
25858
|
+
return false;
|
|
25859
|
+
}
|
|
25860
|
+
};
|
|
25861
|
+
var sha2562 = async (path) => createHash7("sha256").update(await readFile8(path)).digest("hex");
|
|
25862
|
+
var inside2 = (root, candidate) => {
|
|
25863
|
+
const path = relative6(resolve6(root), resolve6(candidate));
|
|
25864
|
+
return path === "" || !isAbsolute5(path) && path !== ".." && !path.startsWith(`..${sep5}`);
|
|
25865
|
+
};
|
|
25866
|
+
var requireSuccess3 = async (run, command, label, options) => {
|
|
25867
|
+
const result = await run(command, options);
|
|
25868
|
+
if (result.exitCode !== 0)
|
|
25869
|
+
throw new Error(`${label} failed: ${result.stderr.trim() || result.stdout.trim() || `status ${result.exitCode}`}`);
|
|
25870
|
+
return result;
|
|
25871
|
+
};
|
|
25872
|
+
var findByExtension2 = async (root, extension) => {
|
|
25873
|
+
if (!await exists3(root))
|
|
25874
|
+
return;
|
|
25875
|
+
const entries = await readdir4(root, { withFileTypes: true });
|
|
25876
|
+
const matches2 = await Promise.all(entries.map(async (entry) => {
|
|
25877
|
+
const path = join8(root, entry.name);
|
|
25878
|
+
if (entry.name.endsWith(extension))
|
|
25879
|
+
return path;
|
|
25880
|
+
return entry.isDirectory() ? findByExtension2(path, extension) : undefined;
|
|
25881
|
+
}));
|
|
25882
|
+
return matches2.find((match) => match !== undefined);
|
|
25883
|
+
};
|
|
25884
|
+
var readAbsoluteIosRelease = async (projectRoot, requested) => {
|
|
25885
|
+
const root = resolve6(projectRoot);
|
|
25886
|
+
const selected = resolve6(root, requested);
|
|
25887
|
+
if (!inside2(root, selected))
|
|
25888
|
+
throw new TypeError("mobile test ios --release must remain inside the project.");
|
|
25889
|
+
const metadataPath = basename2(selected) === "release.json" ? selected : join8(selected, "release.json");
|
|
25890
|
+
const releaseRoot = dirname5(metadataPath);
|
|
25891
|
+
const metadata = requireAbsoluteIosReleaseMetadata(JSON.parse(await readFile8(metadataPath, "utf8")));
|
|
25892
|
+
const artifactPath = resolve6(releaseRoot, metadata.artifact);
|
|
25893
|
+
if (!inside2(releaseRoot, artifactPath))
|
|
25894
|
+
throw new TypeError("iOS release artifact path is invalid.");
|
|
25895
|
+
const [artifactStat, artifactSha256] = await Promise.all([
|
|
25896
|
+
stat4(artifactPath),
|
|
25897
|
+
sha2562(artifactPath)
|
|
25898
|
+
]);
|
|
25899
|
+
if (artifactStat.size !== metadata.bytes || artifactSha256 !== metadata.sha256)
|
|
25900
|
+
throw new TypeError(`Immutable iOS release ${metadata.releaseId} is missing or modified.`);
|
|
25901
|
+
const registered = metadata.registeredDevice;
|
|
25902
|
+
let registeredArtifactPath;
|
|
25903
|
+
if (registered) {
|
|
25904
|
+
registeredArtifactPath = resolve6(releaseRoot, registered.artifact);
|
|
25905
|
+
if (!inside2(releaseRoot, registeredArtifactPath))
|
|
25906
|
+
throw new TypeError("iOS registered-device artifact path is invalid.");
|
|
25907
|
+
const [registeredStat, registeredSha256] = await Promise.all([
|
|
25908
|
+
stat4(registeredArtifactPath),
|
|
25909
|
+
sha2562(registeredArtifactPath)
|
|
25910
|
+
]);
|
|
25911
|
+
if (registeredStat.size !== registered.bytes || registeredSha256 !== registered.sha256)
|
|
25912
|
+
throw new TypeError(`Registered-device export for ${metadata.releaseId} is missing or modified.`);
|
|
25913
|
+
}
|
|
25914
|
+
return {
|
|
25915
|
+
artifactPath,
|
|
25916
|
+
metadata,
|
|
25917
|
+
metadataPath,
|
|
25918
|
+
registeredArtifactPath,
|
|
25919
|
+
releaseRoot
|
|
25920
|
+
};
|
|
25921
|
+
};
|
|
25922
|
+
var releaseMarker = (release) => {
|
|
25923
|
+
const marker = READY_MARKERS[release.metadata.engine];
|
|
25924
|
+
return release.metadata.buildNumber === undefined ? marker : `${marker}; version=${release.metadata.marketingVersion}; build=${release.metadata.buildNumber}`;
|
|
25925
|
+
};
|
|
25926
|
+
var waitForSimulatorMarker = async (options) => {
|
|
25927
|
+
const startedAt = performance.now();
|
|
25928
|
+
const poll = async () => {
|
|
25929
|
+
options.signal?.throwIfAborted();
|
|
25930
|
+
if (performance.now() - startedAt >= READY_TIMEOUT_MS)
|
|
25931
|
+
throw new Error("The installed iOS Release app launched but its embedded content did not become ready.");
|
|
25932
|
+
const logs = await options.run([
|
|
25933
|
+
options.xcrun,
|
|
25934
|
+
"simctl",
|
|
25935
|
+
"spawn",
|
|
25936
|
+
options.udid,
|
|
25937
|
+
"log",
|
|
25938
|
+
"show",
|
|
25939
|
+
"--style",
|
|
25940
|
+
"compact",
|
|
25941
|
+
"--start",
|
|
25942
|
+
options.startedAt.toISOString(),
|
|
25943
|
+
"--predicate",
|
|
25944
|
+
`eventMessage CONTAINS "${releaseMarker(options.release)}"`
|
|
25945
|
+
]);
|
|
25946
|
+
if (logs.exitCode === 0 && logs.stdout.includes(releaseMarker(options.release)))
|
|
25947
|
+
return;
|
|
25948
|
+
await Bun.sleep(READY_POLL_MS);
|
|
25949
|
+
await poll();
|
|
25950
|
+
};
|
|
25951
|
+
await poll();
|
|
25952
|
+
};
|
|
25953
|
+
var launchSimulator = async (options) => {
|
|
25954
|
+
const startedAt = performance.now();
|
|
25955
|
+
const logStartedAt = new Date;
|
|
25956
|
+
await requireSuccess3(options.run, [
|
|
25957
|
+
options.xcrun,
|
|
25958
|
+
"simctl",
|
|
25959
|
+
"launch",
|
|
25960
|
+
"--terminate-running-process",
|
|
25961
|
+
options.udid,
|
|
25962
|
+
options.release.metadata.appId
|
|
25963
|
+
], "iOS Simulator Release launch");
|
|
25964
|
+
await waitForSimulatorMarker({ ...options, startedAt: logStartedAt });
|
|
25965
|
+
return Math.round(performance.now() - startedAt);
|
|
25966
|
+
};
|
|
25967
|
+
var runAbsoluteIosSimulatorReleaseAcceptance = async (options) => {
|
|
25968
|
+
const baseRun = options.run ?? defaultRun3;
|
|
25969
|
+
const run = (command, commandOptions = {}) => baseRun(command, {
|
|
25970
|
+
...commandOptions,
|
|
25971
|
+
...options.signal ? { signal: options.signal } : {}
|
|
25972
|
+
});
|
|
25973
|
+
options.signal?.throwIfAborted();
|
|
25974
|
+
const xcodebuild = options.xcodebuild ?? "/usr/bin/xcodebuild";
|
|
25975
|
+
const xcrun = options.xcrun ?? "/usr/bin/xcrun";
|
|
25976
|
+
const startedAt = performance.now();
|
|
25977
|
+
const iosRoot = join8(options.config.nativeProjectDirectory, "ios");
|
|
25978
|
+
const xcode = await resolveAbsoluteIosXcodeProject(iosRoot);
|
|
25979
|
+
const derivedData = join8(options.artifactDirectory, "DerivedData");
|
|
25980
|
+
await mkdir6(options.artifactDirectory, { recursive: true });
|
|
25981
|
+
await requireSuccess3(run, [
|
|
25982
|
+
xcodebuild,
|
|
25983
|
+
"-workspace",
|
|
25984
|
+
xcode.workspacePath,
|
|
25985
|
+
"-scheme",
|
|
25986
|
+
xcode.scheme,
|
|
25987
|
+
"-configuration",
|
|
25988
|
+
"Release",
|
|
25989
|
+
"-destination",
|
|
25990
|
+
`platform=iOS Simulator,id=${options.udid}`,
|
|
25991
|
+
"-derivedDataPath",
|
|
25992
|
+
derivedData,
|
|
25993
|
+
`MARKETING_VERSION=${options.release.metadata.marketingVersion}`,
|
|
25994
|
+
...options.release.metadata.buildNumber === undefined ? [] : [
|
|
25995
|
+
`CURRENT_PROJECT_VERSION=${options.release.metadata.buildNumber}`
|
|
25996
|
+
],
|
|
25997
|
+
"build"
|
|
25998
|
+
], "iOS Simulator Release build", { cwd: iosRoot });
|
|
25999
|
+
const app = await findByExtension2(join8(derivedData, "Build", "Products"), ".app");
|
|
26000
|
+
if (!app)
|
|
26001
|
+
throw new Error("Xcode did not produce a Simulator Release app.");
|
|
26002
|
+
const installStartedAt = performance.now();
|
|
26003
|
+
await requireSuccess3(run, [xcrun, "simctl", "install", options.udid, app], "iOS Simulator Release installation");
|
|
26004
|
+
const installMs = Math.round(performance.now() - installStartedAt);
|
|
26005
|
+
const installed = await inspectAbsoluteIosInstalledApp(xcrun, options.udid, options.release.metadata.appId, (command) => run(command));
|
|
26006
|
+
if (installed.version !== options.release.metadata.marketingVersion)
|
|
26007
|
+
throw new Error(`Installed iOS version ${installed.version ?? "unknown"} does not match release ${options.release.metadata.marketingVersion}.`);
|
|
26008
|
+
if (options.release.metadata.buildNumber !== undefined && installed.buildNumber !== String(options.release.metadata.buildNumber))
|
|
26009
|
+
throw new Error(`Installed iOS build ${installed.buildNumber ?? "unknown"} does not match release ${options.release.metadata.buildNumber}.`);
|
|
26010
|
+
const launchMs = await launchSimulator({
|
|
26011
|
+
release: options.release,
|
|
26012
|
+
run,
|
|
26013
|
+
udid: options.udid,
|
|
26014
|
+
xcrun
|
|
26015
|
+
});
|
|
26016
|
+
await requireSuccess3(run, [
|
|
26017
|
+
xcrun,
|
|
26018
|
+
"simctl",
|
|
26019
|
+
"terminate",
|
|
26020
|
+
options.udid,
|
|
26021
|
+
options.release.metadata.appId
|
|
26022
|
+
], "iOS Simulator Release termination");
|
|
26023
|
+
const relaunchMs = await launchSimulator({
|
|
26024
|
+
release: options.release,
|
|
26025
|
+
run,
|
|
26026
|
+
udid: options.udid,
|
|
26027
|
+
xcrun
|
|
26028
|
+
});
|
|
26029
|
+
return {
|
|
26030
|
+
artifactBytes: options.release.metadata.bytes,
|
|
26031
|
+
artifactExactness: "source-equivalent",
|
|
26032
|
+
artifactSha256: options.release.metadata.sha256,
|
|
26033
|
+
...options.release.metadata.buildNumber === undefined ? {} : { buildNumber: options.release.metadata.buildNumber },
|
|
26034
|
+
distribution: "simulator-release",
|
|
26035
|
+
durationMs: Math.round(performance.now() - startedAt),
|
|
26036
|
+
embeddedLocal: true,
|
|
26037
|
+
engine: options.release.metadata.engine,
|
|
26038
|
+
installMs,
|
|
26039
|
+
launchMs,
|
|
26040
|
+
marketingVersion: options.release.metadata.marketingVersion,
|
|
26041
|
+
networkUnavailable: "not-proven",
|
|
26042
|
+
relaunchMs,
|
|
26043
|
+
releaseId: options.release.metadata.releaseId,
|
|
26044
|
+
signed: options.release.metadata.signed,
|
|
26045
|
+
status: "pass",
|
|
26046
|
+
target: "simulator"
|
|
26047
|
+
};
|
|
26048
|
+
};
|
|
26049
|
+
var readUntilMarker = async (reader, marker, output = "") => {
|
|
26050
|
+
const { done, value } = await reader.read();
|
|
26051
|
+
if (done)
|
|
26052
|
+
return { found: false, output };
|
|
26053
|
+
const next = `${output}${new TextDecoder().decode(value)}`;
|
|
26054
|
+
if (next.includes(marker))
|
|
26055
|
+
return { found: true, output: next };
|
|
26056
|
+
return readUntilMarker(reader, marker, next);
|
|
26057
|
+
};
|
|
26058
|
+
var observeDeviceLaunch = async (options) => {
|
|
26059
|
+
const startedAt = performance.now();
|
|
26060
|
+
const process2 = Bun.spawn([
|
|
26061
|
+
options.xcrun,
|
|
26062
|
+
"devicectl",
|
|
26063
|
+
"device",
|
|
26064
|
+
"process",
|
|
26065
|
+
"launch",
|
|
26066
|
+
"--console",
|
|
26067
|
+
"--terminate-existing",
|
|
26068
|
+
"--device",
|
|
26069
|
+
options.device,
|
|
26070
|
+
options.appId
|
|
26071
|
+
], {
|
|
26072
|
+
signal: options.signal,
|
|
26073
|
+
stderr: "pipe",
|
|
26074
|
+
stdin: "ignore",
|
|
26075
|
+
stdout: "pipe"
|
|
26076
|
+
});
|
|
26077
|
+
const stdoutReader = process2.stdout.getReader();
|
|
26078
|
+
const stderrReader = process2.stderr.getReader();
|
|
26079
|
+
const requireMarker = async (reader) => {
|
|
26080
|
+
const result = await readUntilMarker(reader, options.marker);
|
|
26081
|
+
if (!result.found)
|
|
26082
|
+
throw new Error(`Console stream closed before readiness.${result.output.trim() ? ` Output: ${result.output.trim()}` : ""}`);
|
|
26083
|
+
return result;
|
|
26084
|
+
};
|
|
26085
|
+
const observed = Promise.any([
|
|
26086
|
+
requireMarker(stdoutReader),
|
|
26087
|
+
requireMarker(stderrReader)
|
|
26088
|
+
]);
|
|
26089
|
+
try {
|
|
26090
|
+
const result = await Promise.race([
|
|
26091
|
+
observed.then((value) => ({ type: "output", value })).catch(() => ({ type: "closed" })),
|
|
26092
|
+
Bun.sleep(options.timeoutMs ?? READY_TIMEOUT_MS).then(() => ({
|
|
26093
|
+
type: "timeout"
|
|
26094
|
+
}))
|
|
26095
|
+
]);
|
|
26096
|
+
if (result.type === "output" && result.value.found)
|
|
26097
|
+
return Math.round(performance.now() - startedAt);
|
|
26098
|
+
if (result.type === "closed")
|
|
26099
|
+
throw new Error("The physical iOS app exited before embedded content became ready.");
|
|
26100
|
+
throw new Error("The physical iOS app did not report embedded readiness before the timeout.");
|
|
26101
|
+
} finally {
|
|
26102
|
+
process2.kill();
|
|
26103
|
+
await Promise.all([
|
|
26104
|
+
stdoutReader.cancel().catch(() => {
|
|
26105
|
+
return;
|
|
26106
|
+
}),
|
|
26107
|
+
stderrReader.cancel().catch(() => {
|
|
26108
|
+
return;
|
|
26109
|
+
})
|
|
26110
|
+
]);
|
|
26111
|
+
stdoutReader.releaseLock();
|
|
26112
|
+
stderrReader.releaseLock();
|
|
26113
|
+
}
|
|
26114
|
+
};
|
|
26115
|
+
var installRegisteredDeviceRelease = async (options) => {
|
|
26116
|
+
if (!options.release.registeredArtifactPath)
|
|
26117
|
+
throw new TypeError("This release has no same-archive registered-device IPA. Rebuild with `absolute mobile build ios --registered-device-artifact`.");
|
|
26118
|
+
const staging = await mkdtemp5(join8(dirname5(options.release.releaseRoot), ".ios-device-"));
|
|
26119
|
+
try {
|
|
26120
|
+
await requireSuccess3(options.run, [
|
|
26121
|
+
"/usr/bin/ditto",
|
|
26122
|
+
"-x",
|
|
26123
|
+
"-k",
|
|
26124
|
+
options.release.registeredArtifactPath,
|
|
26125
|
+
staging
|
|
26126
|
+
], "iOS registered-device IPA extraction");
|
|
26127
|
+
const app = await findByExtension2(staging, ".app");
|
|
26128
|
+
if (!app)
|
|
26129
|
+
throw new Error("The registered-device IPA contains no installable app.");
|
|
26130
|
+
const startedAt = performance.now();
|
|
26131
|
+
await requireSuccess3(options.run, [
|
|
26132
|
+
options.xcrun,
|
|
26133
|
+
"devicectl",
|
|
26134
|
+
"device",
|
|
26135
|
+
"install",
|
|
26136
|
+
"app",
|
|
26137
|
+
"--device",
|
|
26138
|
+
options.device,
|
|
26139
|
+
app
|
|
26140
|
+
], "iOS registered-device Release installation");
|
|
26141
|
+
return Math.round(performance.now() - startedAt);
|
|
26142
|
+
} finally {
|
|
26143
|
+
await rm6(staging, { force: true, recursive: true });
|
|
26144
|
+
}
|
|
26145
|
+
};
|
|
26146
|
+
var inspectTestFlightInstallation = async (options) => {
|
|
26147
|
+
const apps = await requireSuccess3(options.run, [
|
|
26148
|
+
options.xcrun,
|
|
26149
|
+
"devicectl",
|
|
26150
|
+
"device",
|
|
26151
|
+
"info",
|
|
26152
|
+
"apps",
|
|
26153
|
+
"--device",
|
|
26154
|
+
options.device
|
|
26155
|
+
], "TestFlight installation inspection");
|
|
26156
|
+
if (!apps.stdout.includes(options.release.metadata.appId))
|
|
26157
|
+
throw new Error("The selected device does not have the requested TestFlight app installed.");
|
|
26158
|
+
return 0;
|
|
26159
|
+
};
|
|
26160
|
+
var runAbsoluteIosDeviceReleaseAcceptance = async (options) => {
|
|
26161
|
+
if (!options.networkUnavailableConfirmed)
|
|
26162
|
+
throw new TypeError("Physical iOS offline acceptance requires explicit confirmation that Airplane Mode is enabled and Wi-Fi is disabled in Settings.");
|
|
26163
|
+
const baseRun = options.run ?? defaultRun3;
|
|
26164
|
+
const run = (command, commandOptions = {}) => baseRun(command, {
|
|
26165
|
+
...commandOptions,
|
|
26166
|
+
...options.signal ? { signal: options.signal } : {}
|
|
26167
|
+
});
|
|
26168
|
+
options.signal?.throwIfAborted();
|
|
26169
|
+
const xcrun = options.xcrun ?? "/usr/bin/xcrun";
|
|
26170
|
+
const startedAt = performance.now();
|
|
26171
|
+
await requireSuccess3(run, [
|
|
26172
|
+
xcrun,
|
|
26173
|
+
"devicectl",
|
|
26174
|
+
"device",
|
|
26175
|
+
"info",
|
|
26176
|
+
"details",
|
|
26177
|
+
"--device",
|
|
26178
|
+
options.device
|
|
26179
|
+
], "iOS physical-device availability inspection");
|
|
26180
|
+
const installation = {
|
|
26181
|
+
device: options.device,
|
|
26182
|
+
release: options.release,
|
|
26183
|
+
run,
|
|
26184
|
+
xcrun
|
|
26185
|
+
};
|
|
26186
|
+
const installMs = options.distribution === "registered-device" ? await installRegisteredDeviceRelease(installation) : await inspectTestFlightInstallation(installation);
|
|
26187
|
+
const observe = options.observeLaunch ?? ((launch2) => observeDeviceLaunch({
|
|
26188
|
+
...launch2,
|
|
26189
|
+
...options.signal ? { signal: options.signal } : {},
|
|
26190
|
+
xcrun
|
|
26191
|
+
}));
|
|
26192
|
+
const marker = releaseMarker(options.release);
|
|
26193
|
+
const launchMs = await observe({
|
|
26194
|
+
appId: options.release.metadata.appId,
|
|
26195
|
+
device: options.device,
|
|
26196
|
+
marker
|
|
26197
|
+
});
|
|
26198
|
+
const relaunchMs = await observe({
|
|
26199
|
+
appId: options.release.metadata.appId,
|
|
26200
|
+
device: options.device,
|
|
26201
|
+
marker
|
|
26202
|
+
});
|
|
26203
|
+
return {
|
|
26204
|
+
artifactBytes: options.release.metadata.bytes,
|
|
26205
|
+
artifactExactness: options.distribution === "testflight" ? "store-delivered" : "archive-equivalent",
|
|
26206
|
+
artifactSha256: options.release.metadata.sha256,
|
|
26207
|
+
...options.release.metadata.buildNumber === undefined ? {} : { buildNumber: options.release.metadata.buildNumber },
|
|
26208
|
+
distribution: options.distribution === "testflight" ? "apple-processed" : "registered-device",
|
|
26209
|
+
durationMs: Math.round(performance.now() - startedAt),
|
|
26210
|
+
embeddedLocal: true,
|
|
26211
|
+
engine: options.release.metadata.engine,
|
|
26212
|
+
installMs,
|
|
26213
|
+
launchMs,
|
|
26214
|
+
marketingVersion: options.release.metadata.marketingVersion,
|
|
26215
|
+
networkUnavailable: "user-confirmed",
|
|
26216
|
+
relaunchMs,
|
|
26217
|
+
releaseId: options.release.metadata.releaseId,
|
|
26218
|
+
signed: options.release.metadata.signed,
|
|
26219
|
+
status: "pass",
|
|
26220
|
+
target: "device"
|
|
26221
|
+
};
|
|
26222
|
+
};
|
|
25717
26223
|
// src/mobile/iosConformance.ts
|
|
25718
|
-
import { readFile as
|
|
26224
|
+
import { readFile as readFile9, stat as stat5 } from "fs/promises";
|
|
25719
26225
|
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");
|
|
25720
26226
|
var parseAbsoluteIosHmrLog = (line) => {
|
|
25721
26227
|
const match = HMR_LINE.exec(line);
|
|
@@ -25747,13 +26253,13 @@ var waitForAbsoluteIosHmrLog = async (options) => {
|
|
|
25747
26253
|
const sleep = options.sleep ?? Bun.sleep;
|
|
25748
26254
|
const timeoutMs = options.timeoutMs ?? 30000;
|
|
25749
26255
|
const deadline = Date.now() + timeoutMs;
|
|
25750
|
-
let offset = options.startOffset ?? await
|
|
26256
|
+
let offset = options.startOffset ?? await stat5(options.logPath).then(({ size }) => size).catch(() => 0);
|
|
25751
26257
|
let buffered = "";
|
|
25752
26258
|
const poll = async () => {
|
|
25753
26259
|
if (Date.now() > deadline)
|
|
25754
26260
|
throw new Error(`No iOS native HMR acknowledgement was observed within ${timeoutMs}ms.`);
|
|
25755
26261
|
options.signal?.throwIfAborted();
|
|
25756
|
-
const contents = await
|
|
26262
|
+
const contents = await readFile9(options.logPath).catch(() => Buffer.alloc(0));
|
|
25757
26263
|
if (contents.byteLength < offset) {
|
|
25758
26264
|
offset = 0;
|
|
25759
26265
|
buffered = "";
|
|
@@ -25773,18 +26279,18 @@ var waitForAbsoluteIosHmrLog = async (options) => {
|
|
|
25773
26279
|
return poll();
|
|
25774
26280
|
};
|
|
25775
26281
|
// src/mobile/iosSimulatorController.ts
|
|
25776
|
-
import { createHash as
|
|
26282
|
+
import { createHash as createHash8, randomUUID as randomUUID3 } from "crypto";
|
|
25777
26283
|
import {
|
|
25778
|
-
access as
|
|
26284
|
+
access as access9,
|
|
25779
26285
|
copyFile as copyFile4,
|
|
25780
|
-
mkdir as
|
|
25781
|
-
readFile as
|
|
26286
|
+
mkdir as mkdir7,
|
|
26287
|
+
readFile as readFile10,
|
|
25782
26288
|
rename as rename7,
|
|
25783
|
-
rm as
|
|
26289
|
+
rm as rm7,
|
|
25784
26290
|
writeFile as writeFile7
|
|
25785
26291
|
} from "fs/promises";
|
|
25786
26292
|
import { isIP as isIP2 } from "net";
|
|
25787
|
-
import { dirname as
|
|
26293
|
+
import { dirname as dirname6, isAbsolute as isAbsolute6, join as join9, relative as relative7, resolve as resolve7, sep as sep6 } from "path";
|
|
25788
26294
|
init_getDurationString();
|
|
25789
26295
|
var ABSOLUTE_IOS_SIMULATOR_NAME = "AbsoluteJS iPhone";
|
|
25790
26296
|
var BOOT_TIMEOUT_MS = 180000;
|
|
@@ -25794,7 +26300,7 @@ var NATIVE_CACHE_FORMAT = 1;
|
|
|
25794
26300
|
var isRecord4 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
25795
26301
|
var pathExists5 = async (path) => {
|
|
25796
26302
|
try {
|
|
25797
|
-
await
|
|
26303
|
+
await access9(path);
|
|
25798
26304
|
return true;
|
|
25799
26305
|
} catch {
|
|
25800
26306
|
return false;
|
|
@@ -25823,7 +26329,7 @@ var defaultCapture3 = (command, options = {}) => {
|
|
|
25823
26329
|
};
|
|
25824
26330
|
}
|
|
25825
26331
|
};
|
|
25826
|
-
var
|
|
26332
|
+
var defaultRun4 = async (command, options = {}) => {
|
|
25827
26333
|
const process2 = Bun.spawn(command, {
|
|
25828
26334
|
cwd: options.cwd,
|
|
25829
26335
|
env: options.env,
|
|
@@ -25889,7 +26395,7 @@ var defaultStartNativeLogs = (command, options, onLine) => {
|
|
|
25889
26395
|
}
|
|
25890
26396
|
};
|
|
25891
26397
|
};
|
|
25892
|
-
var
|
|
26398
|
+
var requireSuccess4 = async (command, label, run, options) => {
|
|
25893
26399
|
const exitCode = await run(command, options);
|
|
25894
26400
|
if (exitCode !== 0)
|
|
25895
26401
|
throw new Error(`${label} failed with status ${exitCode}.`);
|
|
@@ -25900,7 +26406,7 @@ var trustIosSimulatorDevelopmentCa = async (options, udid, run, log) => {
|
|
|
25900
26406
|
if (!options.certificateAuthorityPath) {
|
|
25901
26407
|
throw new Error("iOS Simulator HTTPS requires the AbsoluteJS development CA certificate.");
|
|
25902
26408
|
}
|
|
25903
|
-
await
|
|
26409
|
+
await requireSuccess4([
|
|
25904
26410
|
options.project.xcrun,
|
|
25905
26411
|
"simctl",
|
|
25906
26412
|
"keychain",
|
|
@@ -26029,18 +26535,18 @@ var preferredIphoneType = (types) => types.filter((type) => type.name.startsWith
|
|
|
26029
26535
|
return rightPro - leftPro;
|
|
26030
26536
|
})[0];
|
|
26031
26537
|
var journalPaths = (projectRoot) => {
|
|
26032
|
-
const root =
|
|
26538
|
+
const root = join9(projectRoot, ".absolutejs", "mobile", "ios-dev-session");
|
|
26033
26539
|
return {
|
|
26034
|
-
configBackup:
|
|
26035
|
-
infoBackup:
|
|
26036
|
-
journal:
|
|
26540
|
+
configBackup: join9(root, "capacitor-config.backup"),
|
|
26541
|
+
infoBackup: join9(root, "Info.plist.backup"),
|
|
26542
|
+
journal: join9(root, "journal.json"),
|
|
26037
26543
|
root
|
|
26038
26544
|
};
|
|
26039
26545
|
};
|
|
26040
|
-
var nativeCachePath = (projectRoot) =>
|
|
26546
|
+
var nativeCachePath = (projectRoot) => join9(projectRoot, ".absolutejs", "mobile", "ios-native-cache.json");
|
|
26041
26547
|
var isInside = (root, path) => {
|
|
26042
|
-
const value =
|
|
26043
|
-
return value === "" || !value.startsWith(`..${
|
|
26548
|
+
const value = relative7(resolve7(root), resolve7(path));
|
|
26549
|
+
return value === "" || !value.startsWith(`..${sep6}`) && value !== ".." && !isAbsolute6(value);
|
|
26044
26550
|
};
|
|
26045
26551
|
var parseJournal = (value) => {
|
|
26046
26552
|
if (!isRecord4(value) || value.format !== DEV_JOURNAL_FORMAT)
|
|
@@ -26062,10 +26568,10 @@ var parseJournal = (value) => {
|
|
|
26062
26568
|
var repairAbsoluteIosDevSession = async (projectRoot) => {
|
|
26063
26569
|
const paths = journalPaths(projectRoot);
|
|
26064
26570
|
if (!await pathExists5(paths.journal)) {
|
|
26065
|
-
await
|
|
26571
|
+
await rm7(paths.root, { force: true, recursive: true });
|
|
26066
26572
|
return false;
|
|
26067
26573
|
}
|
|
26068
|
-
const journal = await
|
|
26574
|
+
const journal = await readFile10(paths.journal, "utf8").then((source) => parseJournal(JSON.parse(source))).catch(() => null);
|
|
26069
26575
|
if (!journal || !isInside(projectRoot, journal.nativeConfigPath) || !isInside(projectRoot, journal.infoPath) || !isInside(paths.root, journal.configBackupPath) || !isInside(paths.root, journal.infoBackupPath)) {
|
|
26070
26576
|
throw new Error(`Refusing unsafe or invalid iOS dev journal at ${paths.journal}.`);
|
|
26071
26577
|
}
|
|
@@ -26073,7 +26579,7 @@ var repairAbsoluteIosDevSession = async (projectRoot) => {
|
|
|
26073
26579
|
await copyFile4(journal.configBackupPath, journal.nativeConfigPath);
|
|
26074
26580
|
if (await pathExists5(journal.infoBackupPath))
|
|
26075
26581
|
await copyFile4(journal.infoBackupPath, journal.infoPath);
|
|
26076
|
-
await
|
|
26582
|
+
await rm7(paths.root, { force: true, recursive: true });
|
|
26077
26583
|
return true;
|
|
26078
26584
|
};
|
|
26079
26585
|
var iosDevelopmentInfoPlist = (source, cleartext) => {
|
|
@@ -26099,16 +26605,16 @@ var iosDevelopmentInfoPlist = (source, cleartext) => {
|
|
|
26099
26605
|
var writeDevProjection = async (project, port, https, serverHost = "localhost") => {
|
|
26100
26606
|
const paths = journalPaths(project.projectRoot);
|
|
26101
26607
|
await repairAbsoluteIosDevSession(project.projectRoot);
|
|
26102
|
-
const nativeConfigPath =
|
|
26103
|
-
const infoPath =
|
|
26608
|
+
const nativeConfigPath = join9(project.nativeDirectory, "App", "App", "capacitor.config.json");
|
|
26609
|
+
const infoPath = join9(project.nativeDirectory, "App", "App", "Info.plist");
|
|
26104
26610
|
const [configSource, infoSource] = await Promise.all([
|
|
26105
|
-
|
|
26106
|
-
|
|
26611
|
+
readFile10(nativeConfigPath, "utf8"),
|
|
26612
|
+
readFile10(infoPath, "utf8")
|
|
26107
26613
|
]);
|
|
26108
26614
|
const parsed = JSON.parse(configSource);
|
|
26109
26615
|
if (!isRecord4(parsed))
|
|
26110
26616
|
throw new Error(`Invalid Capacitor native config at ${nativeConfigPath}.`);
|
|
26111
|
-
await
|
|
26617
|
+
await mkdir7(paths.root, { recursive: true });
|
|
26112
26618
|
await Promise.all([
|
|
26113
26619
|
writeFile7(paths.configBackup, configSource, { flag: "wx" }),
|
|
26114
26620
|
writeFile7(paths.infoBackup, infoSource, { flag: "wx" })
|
|
@@ -26155,11 +26661,11 @@ var parseNativeCache = (value) => {
|
|
|
26155
26661
|
]))
|
|
26156
26662
|
};
|
|
26157
26663
|
};
|
|
26158
|
-
var readNativeCache = (projectRoot) =>
|
|
26664
|
+
var readNativeCache = (projectRoot) => readFile10(nativeCachePath(projectRoot), "utf8").then((source) => parseNativeCache(JSON.parse(source))).catch(() => null);
|
|
26159
26665
|
var writeNativeCache = async (projectRoot, cache) => {
|
|
26160
26666
|
const destination = nativeCachePath(projectRoot);
|
|
26161
26667
|
const temporary = `${destination}.${process.pid}.${randomUUID3()}.tmp`;
|
|
26162
|
-
await
|
|
26668
|
+
await mkdir7(dirname6(destination), { recursive: true });
|
|
26163
26669
|
try {
|
|
26164
26670
|
await writeFile7(temporary, `${JSON.stringify(cache, null, "\t")}
|
|
26165
26671
|
`, {
|
|
@@ -26167,7 +26673,7 @@ var writeNativeCache = async (projectRoot, cache) => {
|
|
|
26167
26673
|
});
|
|
26168
26674
|
await rename7(temporary, destination);
|
|
26169
26675
|
} finally {
|
|
26170
|
-
await
|
|
26676
|
+
await rm7(temporary, { force: true }).catch(() => {
|
|
26171
26677
|
return;
|
|
26172
26678
|
});
|
|
26173
26679
|
}
|
|
@@ -26273,12 +26779,12 @@ var physicalIosAppIsInstalled = (project, identifier, capture) => {
|
|
|
26273
26779
|
return result.exitCode === 0 && result.stdout.includes(project.config.appId);
|
|
26274
26780
|
};
|
|
26275
26781
|
var buildIosDebugApp = async (project, udid, fingerprint, run, signal) => {
|
|
26276
|
-
const derivedDataPath =
|
|
26277
|
-
await
|
|
26278
|
-
await
|
|
26782
|
+
const derivedDataPath = join9(project.projectRoot, ".absolutejs", "mobile", "ios-derived-data", createHash8("sha256").update(project.config.appId).digest("hex").slice(0, 16));
|
|
26783
|
+
await mkdir7(derivedDataPath, { recursive: true });
|
|
26784
|
+
await requireSuccess4([
|
|
26279
26785
|
project.xcodebuild,
|
|
26280
26786
|
"-workspace",
|
|
26281
|
-
|
|
26787
|
+
join9(project.nativeDirectory, "App", "App.xcworkspace"),
|
|
26282
26788
|
"-scheme",
|
|
26283
26789
|
"App",
|
|
26284
26790
|
"-configuration",
|
|
@@ -26289,18 +26795,18 @@ var buildIosDebugApp = async (project, udid, fingerprint, run, signal) => {
|
|
|
26289
26795
|
derivedDataPath,
|
|
26290
26796
|
"build"
|
|
26291
26797
|
], "iOS simulator build", run, { cwd: project.nativeDirectory, signal });
|
|
26292
|
-
const appPath =
|
|
26798
|
+
const appPath = join9(derivedDataPath, "Build", "Products", "Debug-iphonesimulator", "App.app");
|
|
26293
26799
|
if (!await pathExists5(appPath))
|
|
26294
26800
|
throw new Error(`Xcode did not produce the simulator app at ${appPath}.`);
|
|
26295
26801
|
return appPath;
|
|
26296
26802
|
};
|
|
26297
26803
|
var buildPhysicalIosDebugApp = async (project, identifier, run, signal) => {
|
|
26298
|
-
const derivedDataPath =
|
|
26299
|
-
await
|
|
26300
|
-
await
|
|
26804
|
+
const derivedDataPath = join9(project.projectRoot, ".absolutejs", "mobile", "ios-derived-data", createHash8("sha256").update(project.config.appId).digest("hex").slice(0, 16));
|
|
26805
|
+
await mkdir7(derivedDataPath, { recursive: true });
|
|
26806
|
+
await requireSuccess4([
|
|
26301
26807
|
project.xcodebuild,
|
|
26302
26808
|
"-workspace",
|
|
26303
|
-
|
|
26809
|
+
join9(project.nativeDirectory, "App", "App.xcworkspace"),
|
|
26304
26810
|
"-scheme",
|
|
26305
26811
|
"App",
|
|
26306
26812
|
"-configuration",
|
|
@@ -26312,7 +26818,7 @@ var buildPhysicalIosDebugApp = async (project, identifier, run, signal) => {
|
|
|
26312
26818
|
"-allowProvisioningUpdates",
|
|
26313
26819
|
"build"
|
|
26314
26820
|
], "iOS physical-device build (configure automatic signing and a Development Team in Xcode if this is the first run)", run, { cwd: project.nativeDirectory, signal });
|
|
26315
|
-
const appPath =
|
|
26821
|
+
const appPath = join9(derivedDataPath, "Build", "Products", "Debug-iphoneos", "App.app");
|
|
26316
26822
|
if (!await pathExists5(appPath))
|
|
26317
26823
|
throw new Error(`Xcode did not produce the physical-device app at ${appPath}.`);
|
|
26318
26824
|
return appPath;
|
|
@@ -26328,7 +26834,7 @@ var ensurePhysicalIosDebugApp = async (options) => {
|
|
|
26328
26834
|
const appPath = await buildPhysicalIosDebugApp(options.project, options.identifier, options.run, options.signal);
|
|
26329
26835
|
throwIfAborted2(options.signal);
|
|
26330
26836
|
options.transition("installing");
|
|
26331
|
-
await
|
|
26837
|
+
await requireSuccess4([
|
|
26332
26838
|
options.project.xcrun,
|
|
26333
26839
|
"devicectl",
|
|
26334
26840
|
"device",
|
|
@@ -26361,7 +26867,7 @@ var ensureIosDebugApp = async (options) => {
|
|
|
26361
26867
|
const appPath = await buildIosDebugApp(options.project, options.udid, options.fingerprint, options.run, options.signal);
|
|
26362
26868
|
throwIfAborted2(options.signal);
|
|
26363
26869
|
options.transition("installing");
|
|
26364
|
-
await
|
|
26870
|
+
await requireSuccess4([options.project.xcrun, "simctl", "install", options.udid, appPath], "iOS simulator app installation", options.run, { signal: options.signal });
|
|
26365
26871
|
const updated = installedAppIdentity(options.project, options.udid, options.capture);
|
|
26366
26872
|
if (updated) {
|
|
26367
26873
|
await writeNativeCache(options.project.projectRoot, {
|
|
@@ -26447,7 +26953,7 @@ var prepareAbsoluteIosDevProject = async (config, options) => {
|
|
|
26447
26953
|
if (detectAbsoluteMobileHost() !== "macos")
|
|
26448
26954
|
throw new Error("iOS development requires macOS and Xcode.");
|
|
26449
26955
|
const target = options.target ?? "simulator";
|
|
26450
|
-
const projectRoot =
|
|
26956
|
+
const projectRoot = resolve7(options.projectRoot);
|
|
26451
26957
|
const checks = await inspectAbsoluteMobileToolchain({ host: "macos" });
|
|
26452
26958
|
const failed = checks.filter((check) => check.platform === "ios" && !(target === "device" && check.id === "ios.runtime") && (check.status === "fail" || check.status === "warn"));
|
|
26453
26959
|
if (failed.length > 0)
|
|
@@ -26456,20 +26962,20 @@ var prepareAbsoluteIosDevProject = async (config, options) => {
|
|
|
26456
26962
|
const xcodebuild = checks.find((check) => check.id === "ios.xcodebuild")?.path;
|
|
26457
26963
|
if (!xcrun || !xcodebuild)
|
|
26458
26964
|
throw new Error("Xcode tools disappeared after readiness checks.");
|
|
26459
|
-
const cap =
|
|
26965
|
+
const cap = join9(projectRoot, "node_modules", ".bin", "cap");
|
|
26460
26966
|
if (!await pathExists5(cap))
|
|
26461
26967
|
throw new Error("Capacitor CLI is not installed. Run absolute mobile init first.");
|
|
26462
26968
|
await writeAbsoluteCapacitorConfig(config, { projectRoot });
|
|
26463
|
-
await
|
|
26464
|
-
const placeholder =
|
|
26969
|
+
await mkdir7(config.bundleDirectory, { recursive: true });
|
|
26970
|
+
const placeholder = join9(config.bundleDirectory, "index.html");
|
|
26465
26971
|
if (!await pathExists5(placeholder))
|
|
26466
26972
|
await writeFile7(placeholder, `<!doctype html><title>AbsoluteJS mobile development</title>
|
|
26467
26973
|
`);
|
|
26468
|
-
const nativeDirectory =
|
|
26974
|
+
const nativeDirectory = join9(config.nativeProjectDirectory, "ios");
|
|
26469
26975
|
if (!await pathExists5(nativeDirectory)) {
|
|
26470
26976
|
if (!options.createNativeProject)
|
|
26471
26977
|
throw new Error("iOS native project has not been created.");
|
|
26472
|
-
const run = options.run ??
|
|
26978
|
+
const run = options.run ?? defaultRun4;
|
|
26473
26979
|
if (await run([cap, "add", "ios"], { cwd: projectRoot }) !== 0)
|
|
26474
26980
|
throw new Error("Capacitor iOS project creation failed.");
|
|
26475
26981
|
}
|
|
@@ -26522,7 +27028,7 @@ var prepareIosSimulatorTarget = async (options) => {
|
|
|
26522
27028
|
]);
|
|
26523
27029
|
options.transition("connecting");
|
|
26524
27030
|
await waitForBootedSimulator(options.project, device.udid, options.capture, options.sleep, options.startOptions.signal);
|
|
26525
|
-
await
|
|
27031
|
+
await requireSuccess4([options.project.xcrun, "simctl", "bootstatus", device.udid, "-b"], "iOS simulator boot readiness", options.run, { signal: options.startOptions.signal });
|
|
26526
27032
|
await trustIosSimulatorDevelopmentCa(options.startOptions, device.udid, options.run, options.log);
|
|
26527
27033
|
return { caEnrollmentServer: null, startedSimulator, udid: device.udid };
|
|
26528
27034
|
};
|
|
@@ -26532,7 +27038,7 @@ var startAbsoluteIosDevSession = async (options) => {
|
|
|
26532
27038
|
const targetKind = deviceIdentifier ? "device" : "simulator";
|
|
26533
27039
|
const serverHost = deviceIdentifier ? normalizeAbsoluteIosDeviceHost(options.serverHost ?? "") : "localhost";
|
|
26534
27040
|
const capture = options.capture ?? defaultCapture3;
|
|
26535
|
-
const run = options.run ??
|
|
27041
|
+
const run = options.run ?? defaultRun4;
|
|
26536
27042
|
const sleep = options.sleep ?? Bun.sleep;
|
|
26537
27043
|
const spawn2 = options.spawn ?? defaultSpawn;
|
|
26538
27044
|
const log = options.log ?? console.log;
|
|
@@ -26572,13 +27078,13 @@ var startAbsoluteIosDevSession = async (options) => {
|
|
|
26572
27078
|
nativeLogs = attachNativeLogs(project, udid, options);
|
|
26573
27079
|
return;
|
|
26574
27080
|
}
|
|
26575
|
-
await
|
|
27081
|
+
await requireSuccess4(iosLaunchCommand(project, udid, deviceIdentifier !== undefined), "iOS app relaunch", run, { signal: options.signal });
|
|
26576
27082
|
};
|
|
26577
27083
|
try {
|
|
26578
27084
|
await repairAbsoluteIosDevSession(project.projectRoot);
|
|
26579
27085
|
throwIfAborted2(options.signal);
|
|
26580
27086
|
transition("syncing");
|
|
26581
|
-
await
|
|
27087
|
+
await requireSuccess4([project.cap, "sync", "ios"], "Capacitor iOS synchronization", run, { cwd: project.projectRoot, signal: options.signal });
|
|
26582
27088
|
transition("configuring");
|
|
26583
27089
|
if (options.embeddedBundle !== true)
|
|
26584
27090
|
await writeDevProjection(project, options.port, options.https === true, serverHost);
|
|
@@ -26644,7 +27150,7 @@ var startAbsoluteIosDevSession = async (options) => {
|
|
|
26644
27150
|
nativeLogs = attachNativeLogs(project, udid, options);
|
|
26645
27151
|
transition("launching");
|
|
26646
27152
|
if (!deviceIdentifier || !nativeLogs)
|
|
26647
|
-
await
|
|
27153
|
+
await requireSuccess4(iosLaunchCommand(project, udid, deviceIdentifier !== undefined), "iOS app launch", run, { signal: options.signal });
|
|
26648
27154
|
transition("ready");
|
|
26649
27155
|
timings.total = performance.now() - startedAt;
|
|
26650
27156
|
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"}).`);
|
|
@@ -26693,11 +27199,11 @@ var startAbsoluteIosDevSession = async (options) => {
|
|
|
26693
27199
|
screenshot: async (destination) => {
|
|
26694
27200
|
if (deviceIdentifier)
|
|
26695
27201
|
throw new Error("Physical iOS screenshots are captured in Xcode Device Hub; the CLI never records a device screen automatically.");
|
|
26696
|
-
const resolved =
|
|
27202
|
+
const resolved = resolve7(project.projectRoot, destination);
|
|
26697
27203
|
if (!isInside(project.projectRoot, resolved))
|
|
26698
27204
|
throw new Error("iOS screenshot destination must remain inside the project.");
|
|
26699
|
-
await
|
|
26700
|
-
await
|
|
27205
|
+
await mkdir7(dirname6(resolved), { recursive: true });
|
|
27206
|
+
await requireSuccess4([
|
|
26701
27207
|
project.xcrun,
|
|
26702
27208
|
"simctl",
|
|
26703
27209
|
"io",
|
|
@@ -26723,7 +27229,7 @@ var startAbsoluteIosDevSession = async (options) => {
|
|
|
26723
27229
|
};
|
|
26724
27230
|
// src/mobile/iosNativeWatcher.ts
|
|
26725
27231
|
import { watch } from "fs";
|
|
26726
|
-
import { basename as
|
|
27232
|
+
import { basename as basename3 } from "path";
|
|
26727
27233
|
var NATIVE_CHANGE_DEBOUNCE_MS = 500;
|
|
26728
27234
|
var ROOT_NATIVE_INPUTS = new Set([
|
|
26729
27235
|
"absolute.config.js",
|
|
@@ -26813,33 +27319,33 @@ var createAbsoluteIosNativeWatcher = async (options) => {
|
|
|
26813
27319
|
options.signal?.addEventListener("abort", close, { once: true });
|
|
26814
27320
|
return { close };
|
|
26815
27321
|
};
|
|
26816
|
-
var isAbsoluteIosNativeRootInput = (path) => ROOT_NATIVE_INPUTS.has(
|
|
27322
|
+
var isAbsoluteIosNativeRootInput = (path) => ROOT_NATIVE_INPUTS.has(basename3(path));
|
|
26817
27323
|
// src/mobile/remoteMacProtocol.ts
|
|
26818
|
-
import { createHash as
|
|
27324
|
+
import { createHash as createHash9, randomUUID as randomUUID4 } from "crypto";
|
|
26819
27325
|
import {
|
|
26820
27326
|
chmod,
|
|
26821
|
-
mkdir as
|
|
26822
|
-
mkdtemp as
|
|
26823
|
-
readFile as
|
|
27327
|
+
mkdir as mkdir8,
|
|
27328
|
+
mkdtemp as mkdtemp6,
|
|
27329
|
+
readFile as readFile11,
|
|
26824
27330
|
rename as rename8,
|
|
26825
|
-
rm as
|
|
27331
|
+
rm as rm8,
|
|
26826
27332
|
writeFile as writeFile8
|
|
26827
27333
|
} from "fs/promises";
|
|
26828
27334
|
import { homedir as homedir3 } from "os";
|
|
26829
27335
|
import { isIP as isIP3 } from "net";
|
|
26830
27336
|
import {
|
|
26831
|
-
dirname as
|
|
26832
|
-
isAbsolute as
|
|
26833
|
-
join as
|
|
27337
|
+
dirname as dirname7,
|
|
27338
|
+
isAbsolute as isAbsolute7,
|
|
27339
|
+
join as join10,
|
|
26834
27340
|
posix,
|
|
26835
|
-
relative as
|
|
27341
|
+
relative as relative8,
|
|
26836
27342
|
resolve as resolvePath3,
|
|
26837
|
-
sep as
|
|
27343
|
+
sep as sep7
|
|
26838
27344
|
} from "path";
|
|
26839
27345
|
|
|
26840
27346
|
// src/mobile/remoteMacWire.ts
|
|
26841
27347
|
var ABSOLUTE_REMOTE_MAC_EVENT_PREFIX = "ABSOLUTE_REMOTE_MAC\t";
|
|
26842
|
-
var ABSOLUTE_REMOTE_MAC_PROTOCOL_VERSION =
|
|
27348
|
+
var ABSOLUTE_REMOTE_MAC_PROTOCOL_VERSION = 4;
|
|
26843
27349
|
|
|
26844
27350
|
// src/mobile/remoteMacProtocol.ts
|
|
26845
27351
|
var PROFILE_FORMAT = 1;
|
|
@@ -26849,14 +27355,14 @@ var REMOTE_RELEASE_LEASE_HEARTBEAT_MS = 15000;
|
|
|
26849
27355
|
var REMOTE_RELEASE_LEASE_STALE_SECONDS = 120;
|
|
26850
27356
|
var PROFILE_NAME = /^[a-z0-9](?:[a-z0-9._-]{0,62}[a-z0-9])?$/u;
|
|
26851
27357
|
var SSH_DESTINATION = /^(?:[A-Za-z0-9._-]+@)?[A-Za-z0-9._:-]+$/u;
|
|
26852
|
-
var defaultProfilePath = () =>
|
|
27358
|
+
var defaultProfilePath = () => join10(homedir3(), ".absolutejs", "mobile", "remote-macs.json");
|
|
26853
27359
|
var emptyStore = () => ({
|
|
26854
27360
|
format: PROFILE_FORMAT,
|
|
26855
27361
|
profiles: {}
|
|
26856
27362
|
});
|
|
26857
27363
|
var loadStore = async (path = defaultProfilePath()) => {
|
|
26858
27364
|
try {
|
|
26859
|
-
const parsed = JSON.parse(await
|
|
27365
|
+
const parsed = JSON.parse(await readFile11(path, "utf8"));
|
|
26860
27366
|
if (parsed.format !== PROFILE_FORMAT || typeof parsed.profiles !== "object" || parsed.profiles === null || Array.isArray(parsed.profiles))
|
|
26861
27367
|
throw new Error("Unsupported remote Mac profile format.");
|
|
26862
27368
|
for (const [key, profile] of Object.entries(parsed.profiles)) {
|
|
@@ -26873,7 +27379,7 @@ var loadStore = async (path = defaultProfilePath()) => {
|
|
|
26873
27379
|
}
|
|
26874
27380
|
};
|
|
26875
27381
|
var saveStore = async (store, path = defaultProfilePath()) => {
|
|
26876
|
-
await
|
|
27382
|
+
await mkdir8(dirname7(path), { recursive: true });
|
|
26877
27383
|
const temporary = `${path}.${randomUUID4()}.tmp`;
|
|
26878
27384
|
await writeFile8(temporary, `${JSON.stringify(store, null, 2)}
|
|
26879
27385
|
`, {
|
|
@@ -27047,16 +27553,16 @@ var removeAbsoluteRemoteMacProfile = async (name, profilePath) => {
|
|
|
27047
27553
|
await saveStore(store, profilePath);
|
|
27048
27554
|
return true;
|
|
27049
27555
|
};
|
|
27050
|
-
var projectIdentity = (projectRoot, appId) =>
|
|
27556
|
+
var projectIdentity = (projectRoot, appId) => createHash9("sha256").update(`${resolvePath3(projectRoot)}\x00${appId}`).digest("hex").slice(0, 20);
|
|
27051
27557
|
var createAbsoluteRemoteExpoIosDevProject = (config, projectRoot, profile) => {
|
|
27052
27558
|
if (config.engine !== "expo")
|
|
27053
27559
|
throw new TypeError("Remote Expo execution requires mobile.engine: expo.");
|
|
27054
27560
|
return createAbsoluteRemoteIosDevProject(config, projectRoot, profile);
|
|
27055
27561
|
};
|
|
27056
27562
|
var createAbsoluteRemoteIosDevProject = (config, projectRoot, profile) => ({
|
|
27057
|
-
cap:
|
|
27563
|
+
cap: join10(resolvePath3(projectRoot), "node_modules", ".bin", "cap"),
|
|
27058
27564
|
config,
|
|
27059
|
-
nativeDirectory:
|
|
27565
|
+
nativeDirectory: join10(config.nativeProjectDirectory, "ios"),
|
|
27060
27566
|
profile,
|
|
27061
27567
|
projectRoot: resolvePath3(projectRoot),
|
|
27062
27568
|
remote: true,
|
|
@@ -27213,8 +27719,8 @@ var installAbsoluteRemoteMacAgent = async (project) => {
|
|
|
27213
27719
|
};
|
|
27214
27720
|
var materializeAbsoluteRemoteMacAgent = async (projectRoot) => {
|
|
27215
27721
|
const shippedCandidates = [
|
|
27216
|
-
|
|
27217
|
-
|
|
27722
|
+
join10(import.meta.dir, "remoteMacAgentEntry.js"),
|
|
27723
|
+
join10(import.meta.dir, "..", "mobile", "remoteMacAgentEntry.js")
|
|
27218
27724
|
];
|
|
27219
27725
|
let path;
|
|
27220
27726
|
for (const candidate of shippedCandidates) {
|
|
@@ -27225,14 +27731,14 @@ var materializeAbsoluteRemoteMacAgent = async (projectRoot) => {
|
|
|
27225
27731
|
}
|
|
27226
27732
|
if (!path) {
|
|
27227
27733
|
const sourceCandidates = [
|
|
27228
|
-
|
|
27229
|
-
|
|
27734
|
+
join10(import.meta.dir, "remoteMacAgentEntry.ts"),
|
|
27735
|
+
join10(import.meta.dir, "..", "..", "src", "mobile", "remoteMacAgentEntry.ts")
|
|
27230
27736
|
];
|
|
27231
27737
|
const source = await sourceCandidates.reduce(async (found, candidate) => await found ?? (await Bun.file(candidate).exists() ? candidate : undefined), Promise.resolve(undefined));
|
|
27232
27738
|
if (!source)
|
|
27233
27739
|
throw new Error("The AbsoluteJS installation does not contain its remote Mac agent artifact.");
|
|
27234
|
-
const outdir =
|
|
27235
|
-
await
|
|
27740
|
+
const outdir = join10(resolvePath3(projectRoot), ".absolutejs", "mobile", "remote-agent");
|
|
27741
|
+
await mkdir8(outdir, { recursive: true });
|
|
27236
27742
|
const result = await Bun.build({
|
|
27237
27743
|
entrypoints: [source],
|
|
27238
27744
|
minify: true,
|
|
@@ -27241,13 +27747,13 @@ var materializeAbsoluteRemoteMacAgent = async (projectRoot) => {
|
|
|
27241
27747
|
});
|
|
27242
27748
|
if (!result.success)
|
|
27243
27749
|
throw new AggregateError(result.logs, "Failed to build the AbsoluteJS remote Mac agent.");
|
|
27244
|
-
path =
|
|
27750
|
+
path = join10(outdir, "remoteMacAgentEntry.js");
|
|
27245
27751
|
}
|
|
27246
27752
|
const bytes = await Bun.file(path).arrayBuffer();
|
|
27247
|
-
const
|
|
27248
|
-
return { bytes: bytes.byteLength, path, sha256:
|
|
27753
|
+
const sha2563 = createHash9("sha256").update(new Uint8Array(bytes)).digest("hex");
|
|
27754
|
+
return { bytes: bytes.byteLength, path, sha256: sha2563 };
|
|
27249
27755
|
};
|
|
27250
|
-
var portableRelativePath = (root, path) =>
|
|
27756
|
+
var portableRelativePath = (root, path) => relative8(root, path).split(sep7).join(posix.sep);
|
|
27251
27757
|
var portableMobileConfig = (project) => ({
|
|
27252
27758
|
appId: project.config.appId,
|
|
27253
27759
|
appName: project.config.appName,
|
|
@@ -27383,6 +27889,45 @@ var absoluteRemoteReleaseInputSyncCommands = (project) => {
|
|
|
27383
27889
|
tar: ["tar", "-cf", "-", "-C", project.config.bundleDirectory, "."]
|
|
27384
27890
|
};
|
|
27385
27891
|
};
|
|
27892
|
+
var syncAbsoluteRemoteMacAcceptanceRelease = async (project, release, options = {}) => {
|
|
27893
|
+
options.signal?.throwIfAborted();
|
|
27894
|
+
const destination = posix.join(project.remoteProjectRoot, ".absolutejs", "mobile", "acceptance", "ios", release.metadata.releaseId);
|
|
27895
|
+
const staging = `${destination}.incoming-${randomUUID4()}`;
|
|
27896
|
+
const script = [
|
|
27897
|
+
"set -eu",
|
|
27898
|
+
"umask 077",
|
|
27899
|
+
`rm -rf ${shellQuote(staging)}`,
|
|
27900
|
+
`mkdir -p ${shellQuote(staging)}`,
|
|
27901
|
+
`tar -xf - -C ${shellQuote(staging)}`,
|
|
27902
|
+
`test -f ${shellQuote(posix.join(staging, "release.json"))}`,
|
|
27903
|
+
`rm -rf ${shellQuote(destination)}`,
|
|
27904
|
+
`mkdir -p ${shellQuote(posix.dirname(destination))}`,
|
|
27905
|
+
`mv ${shellQuote(staging)} ${shellQuote(destination)}`
|
|
27906
|
+
].join("; ");
|
|
27907
|
+
const archive = Bun.spawn(["tar", "-cf", "-", "-C", release.releaseRoot, "."], {
|
|
27908
|
+
signal: options.signal,
|
|
27909
|
+
stderr: "pipe",
|
|
27910
|
+
stdout: "pipe"
|
|
27911
|
+
});
|
|
27912
|
+
const upload = Bun.spawn([
|
|
27913
|
+
...absoluteRemoteMacSshBase(project.profile),
|
|
27914
|
+
"/bin/sh -lc",
|
|
27915
|
+
shellQuote(script)
|
|
27916
|
+
], {
|
|
27917
|
+
signal: options.signal,
|
|
27918
|
+
stderr: "pipe",
|
|
27919
|
+
stdin: archive.stdout,
|
|
27920
|
+
stdout: "pipe"
|
|
27921
|
+
});
|
|
27922
|
+
const [archiveExit, uploadExit, archiveError, uploadError] = await Promise.all([
|
|
27923
|
+
archive.exited,
|
|
27924
|
+
upload.exited,
|
|
27925
|
+
new Response(archive.stderr).text(),
|
|
27926
|
+
new Response(upload.stderr).text()
|
|
27927
|
+
]);
|
|
27928
|
+
if (archiveExit !== 0 || uploadExit !== 0)
|
|
27929
|
+
throw new Error(`Remote iOS acceptance artifact synchronization failed: ${(archiveError || uploadError).trim()}`);
|
|
27930
|
+
};
|
|
27386
27931
|
var syncAbsoluteRemoteMacReleaseInputs = async (project, options = {}) => {
|
|
27387
27932
|
options.signal?.throwIfAborted();
|
|
27388
27933
|
const commands = absoluteRemoteReleaseInputSyncCommands(project);
|
|
@@ -27428,9 +27973,9 @@ var writeRemoteArtifact = async (path, stream) => {
|
|
|
27428
27973
|
};
|
|
27429
27974
|
var retrieveAbsoluteRemoteIosRelease = async (project, metadata, outputDirectory) => {
|
|
27430
27975
|
const releaseRoot = posix.join(project.remoteProjectRoot, ".absolutejs", "mobile", "releases", "ios", metadata.releaseId);
|
|
27431
|
-
const stagingParent =
|
|
27432
|
-
await
|
|
27433
|
-
const staging = await
|
|
27976
|
+
const stagingParent = join10(project.projectRoot, ".absolutejs", "mobile");
|
|
27977
|
+
await mkdir8(stagingParent, { recursive: true });
|
|
27978
|
+
const staging = await mkdtemp6(join10(stagingParent, ".remote-ios-"));
|
|
27434
27979
|
try {
|
|
27435
27980
|
const remoteMetadata = requireRemoteSuccess(await defaultTransport.capture([
|
|
27436
27981
|
...absoluteRemoteMacSshBase(project.profile),
|
|
@@ -27440,7 +27985,7 @@ var retrieveAbsoluteRemoteIosRelease = async (project, metadata, outputDirectory
|
|
|
27440
27985
|
const downloadedMetadata = JSON.parse(remoteMetadata);
|
|
27441
27986
|
if (JSON.stringify(requireAbsoluteIosReleaseMetadata(downloadedMetadata)) !== JSON.stringify(metadata))
|
|
27442
27987
|
throw new TypeError("Remote iOS release metadata changed during retrieval.");
|
|
27443
|
-
const artifactPath =
|
|
27988
|
+
const artifactPath = join10(staging, "App.ipa");
|
|
27444
27989
|
const download = Bun.spawn([
|
|
27445
27990
|
...absoluteRemoteMacSshBase(project.profile),
|
|
27446
27991
|
"/bin/sh -lc",
|
|
@@ -27453,14 +27998,31 @@ var retrieveAbsoluteRemoteIosRelease = async (project, metadata, outputDirectory
|
|
|
27453
27998
|
]);
|
|
27454
27999
|
if (downloadExit !== 0)
|
|
27455
28000
|
throw new Error(`Remote iOS release retrieval failed: ${downloadError.trim()}`);
|
|
28001
|
+
let registeredArtifactPath;
|
|
28002
|
+
if (metadata.registeredDevice) {
|
|
28003
|
+
registeredArtifactPath = join10(staging, "App.registered-device.ipa");
|
|
28004
|
+
const registeredDownload = Bun.spawn([
|
|
28005
|
+
...absoluteRemoteMacSshBase(project.profile),
|
|
28006
|
+
"/bin/sh -lc",
|
|
28007
|
+
shellQuote(`cat ${shellQuote(posix.join(releaseRoot, metadata.registeredDevice.artifact))}`)
|
|
28008
|
+
], { stderr: "pipe", stdout: "pipe" });
|
|
28009
|
+
const [registeredExit, registeredError] = await Promise.all([
|
|
28010
|
+
registeredDownload.exited,
|
|
28011
|
+
new Response(registeredDownload.stderr).text(),
|
|
28012
|
+
writeRemoteArtifact(registeredArtifactPath, registeredDownload.stdout)
|
|
28013
|
+
]);
|
|
28014
|
+
if (registeredExit !== 0)
|
|
28015
|
+
throw new Error(`Remote iOS registered-device artifact retrieval failed: ${registeredError.trim()}`);
|
|
28016
|
+
}
|
|
27456
28017
|
return await installAbsoluteIosRelease({
|
|
27457
28018
|
artifactPath,
|
|
27458
28019
|
metadata,
|
|
27459
28020
|
outputDirectory,
|
|
27460
|
-
projectRoot: project.projectRoot
|
|
28021
|
+
projectRoot: project.projectRoot,
|
|
28022
|
+
...registeredArtifactPath ? { registeredArtifactPath } : {}
|
|
27461
28023
|
});
|
|
27462
28024
|
} finally {
|
|
27463
|
-
await
|
|
28025
|
+
await rm8(staging, { force: true, recursive: true }).catch(() => {
|
|
27464
28026
|
return;
|
|
27465
28027
|
});
|
|
27466
28028
|
}
|
|
@@ -27555,6 +28117,7 @@ var buildAbsoluteRemoteIosRelease = async (options) => {
|
|
|
27555
28117
|
shellQuote(encodedConfig),
|
|
27556
28118
|
...options.allowUnsigned ? ["--unsigned"] : [],
|
|
27557
28119
|
...options.prepareBuildNumber ? ["--request-build-number"] : [],
|
|
28120
|
+
...options.registeredDeviceArtifact ? ["--registered-device-artifact"] : [],
|
|
27558
28121
|
...options.developmentTeam ? ["--development-team", shellQuote(options.developmentTeam)] : []
|
|
27559
28122
|
].join(" ");
|
|
27560
28123
|
const process2 = (options.transport?.spawn ?? defaultTransport.spawn)([
|
|
@@ -27659,6 +28222,178 @@ var buildAbsoluteRemoteIosRelease = async (options) => {
|
|
|
27659
28222
|
}
|
|
27660
28223
|
}
|
|
27661
28224
|
};
|
|
28225
|
+
var requireRemoteIosReleaseAcceptance = (value, release, distribution) => {
|
|
28226
|
+
if (typeof value !== "object" || value === null)
|
|
28227
|
+
throw new TypeError("Remote Mac returned invalid iOS release evidence.");
|
|
28228
|
+
const result = value;
|
|
28229
|
+
let expectedExactness = "archive-equivalent";
|
|
28230
|
+
if (distribution === "simulator-release")
|
|
28231
|
+
expectedExactness = "source-equivalent";
|
|
28232
|
+
if (distribution === "testflight")
|
|
28233
|
+
expectedExactness = "store-delivered";
|
|
28234
|
+
const expectedDistribution = distribution === "testflight" ? "apple-processed" : distribution;
|
|
28235
|
+
const expectedTarget = distribution === "simulator-release" ? "simulator" : "device";
|
|
28236
|
+
if (result.status !== "pass" || result.embeddedLocal !== true || result.releaseId !== release.metadata.releaseId || result.engine !== release.metadata.engine || result.marketingVersion !== release.metadata.marketingVersion || result.artifactSha256 !== release.metadata.sha256 || result.artifactBytes !== release.metadata.bytes || result.signed !== release.metadata.signed || result.artifactExactness !== expectedExactness || result.distribution !== expectedDistribution || result.target !== expectedTarget || (distribution === "simulator-release" ? result.networkUnavailable !== "not-proven" : result.networkUnavailable !== "user-confirmed") || (release.metadata.buildNumber === undefined ? result.buildNumber !== undefined : result.buildNumber !== release.metadata.buildNumber) || !["durationMs", "installMs", "launchMs", "relaunchMs"].every((field2) => typeof result[field2] === "number" && Number.isFinite(result[field2]) && result[field2] >= 0))
|
|
28237
|
+
throw new TypeError("Remote Mac iOS release evidence does not match the immutable release or requested lane.");
|
|
28238
|
+
return value;
|
|
28239
|
+
};
|
|
28240
|
+
var runAbsoluteRemoteIosReleaseAcceptance = async (options) => {
|
|
28241
|
+
options.signal?.throwIfAborted();
|
|
28242
|
+
if (options.distribution !== "simulator-release" && !options.deviceIdentifier)
|
|
28243
|
+
throw new TypeError("Remote physical iOS release acceptance requires a device identifier.");
|
|
28244
|
+
if (options.distribution !== "simulator-release" && !options.networkUnavailableConfirmed)
|
|
28245
|
+
throw new TypeError("Remote physical iOS release acceptance requires explicit network-unavailable confirmation.");
|
|
28246
|
+
const operation = new AbortController;
|
|
28247
|
+
const abort = () => operation.abort(options.signal?.reason ?? new Error("Remote iOS release acceptance cancelled."));
|
|
28248
|
+
options.signal?.addEventListener("abort", abort, { once: true });
|
|
28249
|
+
const startedAt = performance.now();
|
|
28250
|
+
const leaseStartedAt = performance.now();
|
|
28251
|
+
let lease;
|
|
28252
|
+
try {
|
|
28253
|
+
lease = await (options.acquireLease ?? ((project, signal) => acquireAbsoluteRemoteMacReleaseLease(project, {
|
|
28254
|
+
signal,
|
|
28255
|
+
transport: options.transport
|
|
28256
|
+
})))(options.project, operation.signal);
|
|
28257
|
+
} catch (error) {
|
|
28258
|
+
options.signal?.removeEventListener("abort", abort);
|
|
28259
|
+
throw error;
|
|
28260
|
+
}
|
|
28261
|
+
const leaseDuration = performance.now() - leaseStartedAt;
|
|
28262
|
+
options.onPhaseTiming?.({
|
|
28263
|
+
durationMs: leaseDuration,
|
|
28264
|
+
phase: "remote-release-acceptance-lease"
|
|
28265
|
+
});
|
|
28266
|
+
let heartbeat;
|
|
28267
|
+
const heartbeatTimer = setInterval(() => {
|
|
28268
|
+
if (heartbeat)
|
|
28269
|
+
return;
|
|
28270
|
+
heartbeat = lease.heartbeat().catch((error) => operation.abort(error)).finally(() => {
|
|
28271
|
+
heartbeat = undefined;
|
|
28272
|
+
});
|
|
28273
|
+
}, REMOTE_RELEASE_LEASE_HEARTBEAT_MS);
|
|
28274
|
+
unrefTimer(heartbeatTimer);
|
|
28275
|
+
try {
|
|
28276
|
+
const syncStartedAt = performance.now();
|
|
28277
|
+
if (options.syncProject)
|
|
28278
|
+
await options.syncProject(options.project);
|
|
28279
|
+
else
|
|
28280
|
+
await syncAbsoluteRemoteMacProject(options.project, {
|
|
28281
|
+
signal: operation.signal
|
|
28282
|
+
});
|
|
28283
|
+
operation.signal.throwIfAborted();
|
|
28284
|
+
if (options.syncReleaseInputs)
|
|
28285
|
+
await options.syncReleaseInputs(options.project);
|
|
28286
|
+
else
|
|
28287
|
+
await syncAbsoluteRemoteMacReleaseInputs(options.project, {
|
|
28288
|
+
signal: operation.signal
|
|
28289
|
+
});
|
|
28290
|
+
operation.signal.throwIfAborted();
|
|
28291
|
+
if (options.syncRelease)
|
|
28292
|
+
await options.syncRelease(options.project, options.release);
|
|
28293
|
+
else
|
|
28294
|
+
await syncAbsoluteRemoteMacAcceptanceRelease(options.project, options.release, { signal: operation.signal });
|
|
28295
|
+
operation.signal.throwIfAborted();
|
|
28296
|
+
const syncDuration = performance.now() - syncStartedAt;
|
|
28297
|
+
options.onPhaseTiming?.({
|
|
28298
|
+
durationMs: syncDuration,
|
|
28299
|
+
phase: "remote-release-acceptance-sync"
|
|
28300
|
+
});
|
|
28301
|
+
const agent = await (options.installAgent ?? installAbsoluteRemoteMacAgent)(options.project);
|
|
28302
|
+
const encodedConfig = Buffer.from(JSON.stringify(portableMobileConfig(options.project))).toString("base64url");
|
|
28303
|
+
const remoteCommand = [
|
|
28304
|
+
`cd ${shellQuote(options.project.remoteProjectRoot)}`,
|
|
28305
|
+
"&&",
|
|
28306
|
+
"exec",
|
|
28307
|
+
shellQuote(options.project.profile.bunPath),
|
|
28308
|
+
shellQuote(agent.remotePath),
|
|
28309
|
+
"--test-ios-release",
|
|
28310
|
+
"--mobile-config",
|
|
28311
|
+
shellQuote(encodedConfig),
|
|
28312
|
+
"--release-id",
|
|
28313
|
+
shellQuote(options.release.metadata.releaseId),
|
|
28314
|
+
"--distribution",
|
|
28315
|
+
shellQuote(options.distribution),
|
|
28316
|
+
...options.deviceIdentifier ? ["--device", shellQuote(options.deviceIdentifier)] : [],
|
|
28317
|
+
...options.simulatorUdid ? ["--simulator-udid", shellQuote(options.simulatorUdid)] : [],
|
|
28318
|
+
...options.networkUnavailableConfirmed ? ["--network-unavailable-confirmed"] : []
|
|
28319
|
+
].join(" ");
|
|
28320
|
+
const process2 = (options.transport?.spawn ?? defaultTransport.spawn)([
|
|
28321
|
+
...absoluteRemoteMacSshBase(options.project.profile),
|
|
28322
|
+
"/bin/sh -lc",
|
|
28323
|
+
shellQuote(remoteCommand)
|
|
28324
|
+
], { signal: operation.signal });
|
|
28325
|
+
const killOnAbort = () => process2.kill();
|
|
28326
|
+
operation.signal.addEventListener("abort", killOnAbort, { once: true });
|
|
28327
|
+
let failure;
|
|
28328
|
+
let accepted;
|
|
28329
|
+
const stdoutDone = consumeLines2(process2.stdout, (line) => {
|
|
28330
|
+
if (!line.startsWith(ABSOLUTE_REMOTE_MAC_EVENT_PREFIX))
|
|
28331
|
+
return;
|
|
28332
|
+
try {
|
|
28333
|
+
const event = JSON.parse(line.slice(ABSOLUTE_REMOTE_MAC_EVENT_PREFIX.length));
|
|
28334
|
+
if (event.v !== ABSOLUTE_REMOTE_MAC_PROTOCOL_VERSION)
|
|
28335
|
+
throw new Error("Remote Mac protocol version mismatch.");
|
|
28336
|
+
if (event.type === "log")
|
|
28337
|
+
options.log?.(event.message);
|
|
28338
|
+
if (event.type === "timing") {
|
|
28339
|
+
const durationMs = Reflect.get(event, "durationMs");
|
|
28340
|
+
const phase = Reflect.get(event, "phase");
|
|
28341
|
+
if (typeof durationMs === "number" && typeof phase === "string")
|
|
28342
|
+
options.onPhaseTiming?.({ durationMs, phase });
|
|
28343
|
+
}
|
|
28344
|
+
if (event.type === "fatal")
|
|
28345
|
+
failure = new Error(event.error);
|
|
28346
|
+
if (event.type === "release-acceptance") {
|
|
28347
|
+
if (!event.targetId || typeof event.targetId !== "string")
|
|
28348
|
+
throw new TypeError("Remote Mac returned an invalid iOS acceptance target.");
|
|
28349
|
+
accepted = {
|
|
28350
|
+
result: requireRemoteIosReleaseAcceptance(event.result, options.release, options.distribution),
|
|
28351
|
+
targetId: event.targetId
|
|
28352
|
+
};
|
|
28353
|
+
}
|
|
28354
|
+
} catch (error) {
|
|
28355
|
+
failure = error instanceof Error ? error : new Error("Remote Mac emitted invalid iOS release evidence.");
|
|
28356
|
+
process2.kill();
|
|
28357
|
+
}
|
|
28358
|
+
});
|
|
28359
|
+
const stderrDone = consumeLines2(process2.stderr, (line) => options.log?.(`[remote] ${line}`));
|
|
28360
|
+
const exitCode = await process2.exited;
|
|
28361
|
+
operation.signal.removeEventListener("abort", killOnAbort);
|
|
28362
|
+
try {
|
|
28363
|
+
process2.stdin.end();
|
|
28364
|
+
} catch {}
|
|
28365
|
+
await Promise.all([stdoutDone, stderrDone]);
|
|
28366
|
+
operation.signal.throwIfAborted();
|
|
28367
|
+
if (failure)
|
|
28368
|
+
throw failure;
|
|
28369
|
+
if (exitCode !== 0)
|
|
28370
|
+
throw new Error(`Remote iOS release acceptance agent exited with status ${exitCode}.`);
|
|
28371
|
+
if (!accepted)
|
|
28372
|
+
throw new Error("Remote iOS release acceptance agent returned no evidence.");
|
|
28373
|
+
const total = performance.now() - startedAt;
|
|
28374
|
+
options.log?.(`Remote Mac ${options.project.profile.name} completed ${options.distribution} acceptance for ${options.release.metadata.releaseId} in ${total.toFixed(2)}ms (agent ${agent.uploaded ? "uploaded" : "cache hit"}).`);
|
|
28375
|
+
return {
|
|
28376
|
+
...accepted,
|
|
28377
|
+
timings: {
|
|
28378
|
+
"remote-release-acceptance-lease": leaseDuration,
|
|
28379
|
+
"remote-release-acceptance-sync": syncDuration,
|
|
28380
|
+
total
|
|
28381
|
+
}
|
|
28382
|
+
};
|
|
28383
|
+
} finally {
|
|
28384
|
+
clearInterval(heartbeatTimer);
|
|
28385
|
+
await heartbeat?.catch(() => {
|
|
28386
|
+
return;
|
|
28387
|
+
});
|
|
28388
|
+
options.signal?.removeEventListener("abort", abort);
|
|
28389
|
+
try {
|
|
28390
|
+
await lease.release();
|
|
28391
|
+
options.log?.("Released Remote Mac release acceptance lease.");
|
|
28392
|
+
} catch (error) {
|
|
28393
|
+
options.log?.(`Remote Mac acceptance lease cleanup failed and will recover after expiry: ${error instanceof Error ? error.message : String(error)}`);
|
|
28394
|
+
}
|
|
28395
|
+
}
|
|
28396
|
+
};
|
|
27662
28397
|
var startAbsoluteRemoteExpoIosDevSession = async (options) => {
|
|
27663
28398
|
let session = await startAbsoluteRemoteDevSession({
|
|
27664
28399
|
certificateAuthorityPath: options.certificateAuthorityPath,
|
|
@@ -27702,7 +28437,7 @@ var startAbsoluteRemoteDevSession = async (options) => {
|
|
|
27702
28437
|
await syncProject(options.project);
|
|
27703
28438
|
const syncDuration = performance.now() - syncStartedAt;
|
|
27704
28439
|
const encodedConfig = Buffer.from(JSON.stringify(portableMobileConfig(options.project))).toString("base64url");
|
|
27705
|
-
const encodedCertificateAuthority = options.certificateAuthorityPath ? (await
|
|
28440
|
+
const encodedCertificateAuthority = options.certificateAuthorityPath ? (await readFile11(options.certificateAuthorityPath)).toString("base64url") : undefined;
|
|
27706
28441
|
const physicalDevice = options.deviceIdentifier !== undefined;
|
|
27707
28442
|
const expo = options.project.config.engine === "expo";
|
|
27708
28443
|
if (expo && options.metroPort === undefined)
|
|
@@ -27769,8 +28504,8 @@ var startAbsoluteRemoteDevSession = async (options) => {
|
|
|
27769
28504
|
const pending = new Map;
|
|
27770
28505
|
let resolveReady;
|
|
27771
28506
|
let rejectReady;
|
|
27772
|
-
const readyPromise = new Promise((
|
|
27773
|
-
resolveReady =
|
|
28507
|
+
const readyPromise = new Promise((resolve8, reject) => {
|
|
28508
|
+
resolveReady = resolve8;
|
|
27774
28509
|
rejectReady = reject;
|
|
27775
28510
|
});
|
|
27776
28511
|
const handleEvent = (event) => {
|
|
@@ -27873,7 +28608,7 @@ var startAbsoluteRemoteDevSession = async (options) => {
|
|
|
27873
28608
|
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.`);
|
|
27874
28609
|
const request = (commandName) => {
|
|
27875
28610
|
const id = randomUUID4();
|
|
27876
|
-
const response = new Promise((
|
|
28611
|
+
const response = new Promise((resolve8, reject) => pending.set(id, { reject, resolve: resolve8 }));
|
|
27877
28612
|
process2.stdin.write(`${JSON.stringify({ command: commandName, id, v: ABSOLUTE_REMOTE_MAC_PROTOCOL_VERSION })}
|
|
27878
28613
|
`);
|
|
27879
28614
|
const flush = async () => {
|
|
@@ -27893,7 +28628,7 @@ var startAbsoluteRemoteDevSession = async (options) => {
|
|
|
27893
28628
|
if (closed)
|
|
27894
28629
|
return;
|
|
27895
28630
|
closed = true;
|
|
27896
|
-
const timeout = () => new Promise((
|
|
28631
|
+
const timeout = () => new Promise((resolve8) => setTimeout(() => resolve8("timeout"), REMOTE_SESSION_CLOSE_TIMEOUT_MS));
|
|
27897
28632
|
const id = randomUUID4();
|
|
27898
28633
|
process2.stdin.write(`${JSON.stringify({ command: "close", id, v: ABSOLUTE_REMOTE_MAC_PROTOCOL_VERSION })}
|
|
27899
28634
|
`);
|
|
@@ -27940,10 +28675,10 @@ var startAbsoluteRemoteDevSession = async (options) => {
|
|
|
27940
28675
|
screenshot: async (destination) => {
|
|
27941
28676
|
const result = await request("screenshot");
|
|
27942
28677
|
const target = resolvePath3(options.project.projectRoot, destination);
|
|
27943
|
-
const targetRelative =
|
|
27944
|
-
if (targetRelative.startsWith("..") ||
|
|
28678
|
+
const targetRelative = relative8(options.project.projectRoot, target);
|
|
28679
|
+
if (targetRelative.startsWith("..") || isAbsolute7(targetRelative))
|
|
27945
28680
|
throw new Error("iOS screenshot must remain inside the project.");
|
|
27946
|
-
await
|
|
28681
|
+
await mkdir8(dirname7(target), { recursive: true });
|
|
27947
28682
|
await writeFile8(target, Buffer.from(result.data, "base64"));
|
|
27948
28683
|
return target;
|
|
27949
28684
|
},
|
|
@@ -27971,20 +28706,20 @@ var absoluteIosDeviceAcceptanceCommands = (options) => {
|
|
|
27971
28706
|
]
|
|
27972
28707
|
};
|
|
27973
28708
|
};
|
|
27974
|
-
var
|
|
28709
|
+
var requireSuccess5 = (result, message) => {
|
|
27975
28710
|
if (result.exitCode !== 0)
|
|
27976
28711
|
throw new Error(message);
|
|
27977
28712
|
return result;
|
|
27978
28713
|
};
|
|
27979
28714
|
var testAbsoluteIosPhysicalDevice = async (options) => {
|
|
27980
28715
|
const commands = absoluteIosDeviceAcceptanceCommands(options);
|
|
27981
|
-
|
|
27982
|
-
const apps =
|
|
28716
|
+
requireSuccess5(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.");
|
|
28717
|
+
const apps = requireSuccess5(await options.capture(commands.apps), "AbsoluteJS could not inspect installed apps on the physical iOS device.");
|
|
27983
28718
|
if (!apps.stdout.includes(options.appId))
|
|
27984
28719
|
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.");
|
|
27985
28720
|
const now = options.now ?? performance.now.bind(performance);
|
|
27986
28721
|
const startedAt = now();
|
|
27987
|
-
|
|
28722
|
+
requireSuccess5(await options.capture(commands.launch), "AbsoluteJS could not relaunch the app on the physical iOS device.");
|
|
27988
28723
|
await options.waitForHmr();
|
|
27989
28724
|
return {
|
|
27990
28725
|
hmrConnected: true,
|
|
@@ -28024,32 +28759,32 @@ var parseAbsoluteMobileBuildPageMetadata = (value) => {
|
|
|
28024
28759
|
};
|
|
28025
28760
|
};
|
|
28026
28761
|
// src/mobile/buildPipeline.ts
|
|
28027
|
-
import { readFile as
|
|
28028
|
-
import { join as
|
|
28762
|
+
import { readFile as readFile17 } from "fs/promises";
|
|
28763
|
+
import { join as join20, resolve as resolve15 } from "path";
|
|
28029
28764
|
import { pathToFileURL as pathToFileURL2 } from "url";
|
|
28030
28765
|
|
|
28031
28766
|
// src/mobile/buildRelease.ts
|
|
28032
|
-
import { createHash as
|
|
28033
|
-
import { mkdir as
|
|
28034
|
-
import { basename as
|
|
28767
|
+
import { createHash as createHash11 } from "crypto";
|
|
28768
|
+
import { mkdir as mkdir10, readFile as readFile13, writeFile as writeFile10 } from "fs/promises";
|
|
28769
|
+
import { basename as basename4, dirname as dirname8, extname, join as join11, relative as relative9, resolve as resolve10 } from "path";
|
|
28035
28770
|
init_releaseArtifact();
|
|
28036
|
-
var
|
|
28771
|
+
var sha2563 = (bytes) => createHash11("sha256").update(bytes).digest("hex");
|
|
28037
28772
|
var STATIC_SCRIPT_PATTERN = /(<script\b[^>]*?\bsrc\s*=\s*["'])(\/[^"']+\.(?:js|ts))(["'][^>]*>)/giu;
|
|
28038
28773
|
var rewriteStaticScriptPaths = (source, manifest) => source.replace(STATIC_SCRIPT_PATTERN, (match, prefix, path, suffix) => {
|
|
28039
28774
|
if (path.endsWith("/htmx.min.js"))
|
|
28040
28775
|
return match;
|
|
28041
|
-
const key = toPascal(
|
|
28776
|
+
const key = toPascal(basename4(path, extname(path)));
|
|
28042
28777
|
const builtPath = manifest[key];
|
|
28043
28778
|
return builtPath ? `${prefix}${builtPath}${suffix}` : match;
|
|
28044
28779
|
});
|
|
28045
28780
|
var readPageMetadata = (route) => parseAbsoluteMobileBuildPageMetadata(route.hooks?.detail?.[ABSOLUTE_MOBILE_ROUTE_DETAIL]);
|
|
28046
28781
|
var resolveAssetPath = (buildDirectory, assetPath) => {
|
|
28047
|
-
const resolvedBuildDirectory =
|
|
28048
|
-
const resolvedAsset =
|
|
28782
|
+
const resolvedBuildDirectory = resolve10(buildDirectory);
|
|
28783
|
+
const resolvedAsset = resolve10(assetPath);
|
|
28049
28784
|
if (resolvedAsset.startsWith(`${resolvedBuildDirectory}/`)) {
|
|
28050
28785
|
return resolvedAsset;
|
|
28051
28786
|
}
|
|
28052
|
-
return
|
|
28787
|
+
return join11(buildDirectory, assetPath.replace(/^\/+/, ""));
|
|
28053
28788
|
};
|
|
28054
28789
|
var pageFor = async (metadata, manifest, buildDirectory) => {
|
|
28055
28790
|
const assetPath = manifest[metadata.bundleKey];
|
|
@@ -28058,11 +28793,11 @@ var pageFor = async (metadata, manifest, buildDirectory) => {
|
|
|
28058
28793
|
}
|
|
28059
28794
|
let resolvedAssetPath = resolveAssetPath(buildDirectory, assetPath);
|
|
28060
28795
|
if (metadata.framework === "html" || metadata.framework === "htmx") {
|
|
28061
|
-
const source = await
|
|
28796
|
+
const source = await readFile13(resolvedAssetPath, "utf8");
|
|
28062
28797
|
const rewritten = rewriteStaticScriptPaths(source, manifest);
|
|
28063
|
-
const documentHash =
|
|
28064
|
-
resolvedAssetPath =
|
|
28065
|
-
await
|
|
28798
|
+
const documentHash = sha2563(new TextEncoder().encode(rewritten));
|
|
28799
|
+
resolvedAssetPath = join11(buildDirectory, ".absolutejs", "mobile-pages", `${documentHash}.html`);
|
|
28800
|
+
await mkdir10(dirname8(resolvedAssetPath), { recursive: true });
|
|
28066
28801
|
await writeFile10(resolvedAssetPath, rewritten);
|
|
28067
28802
|
}
|
|
28068
28803
|
const pageAssetKey = metadata.bundleKey.replace(/Index$/u, "");
|
|
@@ -28072,20 +28807,20 @@ var pageFor = async (metadata, manifest, buildDirectory) => {
|
|
|
28072
28807
|
].map((key) => manifest[key]).find((path) => typeof path === "string");
|
|
28073
28808
|
const resolvedStylePath = styleAssetPath ? resolveAssetPath(buildDirectory, styleAssetPath) : undefined;
|
|
28074
28809
|
const [bytes, styleBytes] = await Promise.all([
|
|
28075
|
-
|
|
28076
|
-
resolvedStylePath ?
|
|
28810
|
+
readFile13(resolvedAssetPath),
|
|
28811
|
+
resolvedStylePath ? readFile13(resolvedStylePath) : undefined
|
|
28077
28812
|
]);
|
|
28078
|
-
const bundlePath = `/${
|
|
28079
|
-
const styleBundlePath = resolvedStylePath ? `/${
|
|
28813
|
+
const bundlePath = `/${relative9(resolve10(buildDirectory), resolvedAssetPath).replaceAll("\\", "/")}`;
|
|
28814
|
+
const styleBundlePath = resolvedStylePath ? `/${relative9(resolve10(buildDirectory), resolvedStylePath).replaceAll("\\", "/")}` : undefined;
|
|
28080
28815
|
return {
|
|
28081
|
-
bundleHash:
|
|
28816
|
+
bundleHash: sha2563(bytes),
|
|
28082
28817
|
bundlePath,
|
|
28083
28818
|
contract: metadata.contract,
|
|
28084
28819
|
framework: metadata.framework,
|
|
28085
28820
|
pageId: metadata.pageId,
|
|
28086
28821
|
propsSchemaHash: metadata.propsSchemaHash,
|
|
28087
28822
|
...styleBytes && styleBundlePath ? {
|
|
28088
|
-
styleBundleHash:
|
|
28823
|
+
styleBundleHash: sha2563(styleBytes),
|
|
28089
28824
|
styleBundlePath
|
|
28090
28825
|
} : {}
|
|
28091
28826
|
};
|
|
@@ -28093,7 +28828,7 @@ var pageFor = async (metadata, manifest, buildDirectory) => {
|
|
|
28093
28828
|
var buildAbsoluteMobileCompatibilityRelease = async (options) => {
|
|
28094
28829
|
const [captured, producerBytes] = await Promise.all([
|
|
28095
28830
|
captureAbsoluteMobileRouteGraph(options.app),
|
|
28096
|
-
|
|
28831
|
+
readFile13(options.producerPath)
|
|
28097
28832
|
]);
|
|
28098
28833
|
if (captured.length === 0) {
|
|
28099
28834
|
throw new TypeError("No instrumented AbsoluteJS mobile page routes were found in the finalized Elysia route graph.");
|
|
@@ -28107,8 +28842,8 @@ var buildAbsoluteMobileCompatibilityRelease = async (options) => {
|
|
|
28107
28842
|
metadataByPage.set(metadata.pageId, metadata);
|
|
28108
28843
|
}
|
|
28109
28844
|
const pages = await Promise.all([...metadataByPage.values()].map((metadata) => pageFor(metadata, options.manifest, options.buildDirectory)));
|
|
28110
|
-
const producerHash =
|
|
28111
|
-
const appBuild = `ambuild_${
|
|
28845
|
+
const producerHash = sha2563(producerBytes);
|
|
28846
|
+
const appBuild = `ambuild_${sha2563(new TextEncoder().encode(JSON.stringify({
|
|
28112
28847
|
pages: pages.map(({
|
|
28113
28848
|
bundleHash,
|
|
28114
28849
|
bundlePath,
|
|
@@ -28184,15 +28919,15 @@ init_routeMatcher();
|
|
|
28184
28919
|
import {
|
|
28185
28920
|
cp,
|
|
28186
28921
|
copyFile as copyFile5,
|
|
28187
|
-
mkdir as
|
|
28188
|
-
mkdtemp as
|
|
28189
|
-
readFile as
|
|
28922
|
+
mkdir as mkdir11,
|
|
28923
|
+
mkdtemp as mkdtemp7,
|
|
28924
|
+
readFile as readFile14,
|
|
28190
28925
|
rename as rename10,
|
|
28191
|
-
rm as
|
|
28926
|
+
rm as rm10,
|
|
28192
28927
|
writeFile as writeFile11
|
|
28193
28928
|
} from "fs/promises";
|
|
28194
28929
|
import { existsSync as existsSync2 } from "fs";
|
|
28195
|
-
import { basename as
|
|
28930
|
+
import { basename as basename5, dirname as dirname9, extname as extname2, join as join12, relative as relative10, resolve as resolve11 } from "path";
|
|
28196
28931
|
|
|
28197
28932
|
// src/mobile/client.ts
|
|
28198
28933
|
init_pageProtocol();
|
|
@@ -28403,55 +29138,55 @@ var CAPACITOR_CLIENT_FRAMEWORKS = new Set([
|
|
|
28403
29138
|
var CLIENT_ASSET_DIRECTORIES = ["assets", "html", "htmx", "indexes"];
|
|
28404
29139
|
var errorHasCode2 = (error, code) => typeof error === "object" && error !== null && Reflect.get(error, "code") === code;
|
|
28405
29140
|
var shellBootstrapModule = () => {
|
|
28406
|
-
const candidate = ["js", "ts"].map((extension) =>
|
|
29141
|
+
const candidate = ["js", "ts"].map((extension) => join12(import.meta.dir, `shellBootstrap.${extension}`)).find(existsSync2);
|
|
28407
29142
|
if (candidate)
|
|
28408
29143
|
return candidate;
|
|
28409
29144
|
throw new TypeError("AbsoluteJS mobile shell bootstrap module is missing.");
|
|
28410
29145
|
};
|
|
28411
29146
|
var shellAuthModule = () => {
|
|
28412
|
-
const candidate = ["js", "ts"].map((extension) =>
|
|
29147
|
+
const candidate = ["js", "ts"].map((extension) => join12(import.meta.dir, `shellAuth.${extension}`)).find(existsSync2);
|
|
28413
29148
|
if (candidate)
|
|
28414
29149
|
return candidate;
|
|
28415
29150
|
throw new TypeError("AbsoluteJS mobile auth shell module is missing.");
|
|
28416
29151
|
};
|
|
28417
29152
|
var shellExpoAuthModule = () => {
|
|
28418
|
-
const candidate = ["js", "ts"].map((extension) =>
|
|
29153
|
+
const candidate = ["js", "ts"].map((extension) => join12(import.meta.dir, `shellExpoAuth.${extension}`)).find(existsSync2);
|
|
28419
29154
|
if (candidate)
|
|
28420
29155
|
return candidate;
|
|
28421
29156
|
throw new TypeError("AbsoluteJS Expo auth bridge module is missing.");
|
|
28422
29157
|
};
|
|
28423
29158
|
var shellSyncModule = () => {
|
|
28424
|
-
const candidate = ["js", "ts"].map((extension) =>
|
|
29159
|
+
const candidate = ["js", "ts"].map((extension) => join12(import.meta.dir, `shellSync.${extension}`)).find(existsSync2);
|
|
28425
29160
|
if (candidate)
|
|
28426
29161
|
return candidate;
|
|
28427
29162
|
throw new TypeError("AbsoluteJS mobile Sync shell module is missing.");
|
|
28428
29163
|
};
|
|
28429
29164
|
var shellExpoSyncModule = () => {
|
|
28430
|
-
const candidate = ["js", "ts"].map((extension) =>
|
|
29165
|
+
const candidate = ["js", "ts"].map((extension) => join12(import.meta.dir, `shellExpoSync.${extension}`)).find(existsSync2);
|
|
28431
29166
|
if (candidate)
|
|
28432
29167
|
return candidate;
|
|
28433
29168
|
throw new TypeError("AbsoluteJS Expo Sync bridge module is missing.");
|
|
28434
29169
|
};
|
|
28435
29170
|
var shellPushModule = () => {
|
|
28436
|
-
const candidate = ["js", "ts"].map((extension) =>
|
|
29171
|
+
const candidate = ["js", "ts"].map((extension) => join12(import.meta.dir, `shellPush.${extension}`)).find(existsSync2);
|
|
28437
29172
|
if (candidate)
|
|
28438
29173
|
return candidate;
|
|
28439
29174
|
throw new TypeError("AbsoluteJS mobile push shell module is missing.");
|
|
28440
29175
|
};
|
|
28441
29176
|
var shellExpoDevicesModule = () => {
|
|
28442
|
-
const candidate = ["js", "ts"].map((extension) =>
|
|
29177
|
+
const candidate = ["js", "ts"].map((extension) => join12(import.meta.dir, `shellExpoDevices.${extension}`)).find(existsSync2);
|
|
28443
29178
|
if (candidate)
|
|
28444
29179
|
return candidate;
|
|
28445
29180
|
throw new TypeError("AbsoluteJS Expo device bridge module is missing.");
|
|
28446
29181
|
};
|
|
28447
29182
|
var shellUpdateModule = () => {
|
|
28448
|
-
const candidate = ["js", "ts"].map((extension) =>
|
|
29183
|
+
const candidate = ["js", "ts"].map((extension) => join12(import.meta.dir, `shellUpdate.${extension}`)).find(existsSync2);
|
|
28449
29184
|
if (candidate)
|
|
28450
29185
|
return candidate;
|
|
28451
29186
|
throw new TypeError("AbsoluteJS mobile update shell module is missing.");
|
|
28452
29187
|
};
|
|
28453
29188
|
var shellReleaseReadinessModule = () => {
|
|
28454
|
-
const candidate = ["js", "ts"].map((extension) =>
|
|
29189
|
+
const candidate = ["js", "ts"].map((extension) => join12(import.meta.dir, `shellReleaseReadiness.${extension}`)).find(existsSync2);
|
|
28455
29190
|
if (candidate)
|
|
28456
29191
|
return candidate;
|
|
28457
29192
|
throw new TypeError("AbsoluteJS mobile release-readiness module is missing.");
|
|
@@ -28486,8 +29221,8 @@ var indexHtml = (appName, productionOrigin) => `<!doctype html>
|
|
|
28486
29221
|
</html>
|
|
28487
29222
|
`;
|
|
28488
29223
|
var sourceAssetPath = (buildDirectory, bundlePath) => {
|
|
28489
|
-
const root =
|
|
28490
|
-
const asset =
|
|
29224
|
+
const root = resolve11(buildDirectory);
|
|
29225
|
+
const asset = resolve11(root, bundlePath.replace(/^\/+/, ""));
|
|
28491
29226
|
if (!asset.startsWith(`${root}/`)) {
|
|
28492
29227
|
throw new TypeError("Mobile page bundle escaped the build directory.");
|
|
28493
29228
|
}
|
|
@@ -28504,15 +29239,15 @@ var resolveProjectImport = async (projectRoot, specifier) => {
|
|
|
28504
29239
|
const segments = specifier.split("/");
|
|
28505
29240
|
const packageName = specifier.startsWith("@") ? segments.slice(0, 2).join("/") : segments[0] ?? "";
|
|
28506
29241
|
const subpath = specifier.slice(packageName.length);
|
|
28507
|
-
const packageDirectory =
|
|
28508
|
-
const manifest = JSON.parse(await
|
|
29242
|
+
const packageDirectory = join12(resolve11(projectRoot), "node_modules", packageName);
|
|
29243
|
+
const manifest = JSON.parse(await readFile14(join12(packageDirectory, "package.json"), "utf8"));
|
|
28509
29244
|
const exports = typeof manifest === "object" && manifest !== null ? Reflect.get(manifest, "exports") : undefined;
|
|
28510
29245
|
const entry = typeof exports === "object" && exports !== null ? Reflect.get(exports, subpath ? `.${subpath}` : ".") : undefined;
|
|
28511
29246
|
const target = importEntryTarget(entry);
|
|
28512
29247
|
if (typeof target !== "string" || !target.startsWith("./"))
|
|
28513
29248
|
throw new TypeError(`${specifier} does not publish an import entry.`);
|
|
28514
|
-
const resolved =
|
|
28515
|
-
if (!resolved.startsWith(`${
|
|
29249
|
+
const resolved = resolve11(packageDirectory, target);
|
|
29250
|
+
if (!resolved.startsWith(`${resolve11(packageDirectory)}/`))
|
|
28516
29251
|
throw new TypeError(`${specifier} has an unsafe import entry.`);
|
|
28517
29252
|
return resolved;
|
|
28518
29253
|
};
|
|
@@ -28543,7 +29278,7 @@ var buildShellBootstrap = async (staging, auth, sync, storagePrefix, engine, upd
|
|
|
28543
29278
|
const absoluteMobilePushCapability = absoluteDeviceCapability${pushIndex}(absoluteMobilePush.capabilityOptions);
|
|
28544
29279
|
` : "";
|
|
28545
29280
|
const capabilityOptions = shellCapabilities.map((name, index) => `${JSON.stringify(name)}: ${name === "pushNotifications" ? "absoluteMobilePushCapability" : `absoluteDeviceCapability${index}()`}`).join(", ");
|
|
28546
|
-
const entryPath =
|
|
29281
|
+
const entryPath = join12(staging, ".absolute-mobile-entry.ts");
|
|
28547
29282
|
const baseAdapterModule = capacitor ? await resolveProjectImport(projectRoot, "@absolutejs/devices-capacitor") : shellExpoDevicesModule();
|
|
28548
29283
|
const adapterImport = capacitor ? `import { installCapacitorDeviceAdapterIfNative } from ${JSON.stringify(baseAdapterModule)};` : `import { createAbsoluteExpoBridgeFetch, installAbsoluteExpoWebDeviceAdapter } from ${JSON.stringify(baseAdapterModule)};`;
|
|
28549
29284
|
const readinessImport = capacitor ? `import { markAbsoluteMobileShellReady } from ${JSON.stringify(shellReleaseReadinessModule())};` : "";
|
|
@@ -28579,13 +29314,13 @@ void startAbsoluteMobileShell(${shellOptions})${capacitor ? ".then(markAbsoluteM
|
|
|
28579
29314
|
if (!build.success || build.outputs.length !== 1) {
|
|
28580
29315
|
throw new AggregateError(build.logs, "Failed to build the AbsoluteJS Capacitor shell.");
|
|
28581
29316
|
}
|
|
28582
|
-
await rename10(build.outputs[0]?.path ?? "",
|
|
28583
|
-
await
|
|
29317
|
+
await rename10(build.outputs[0]?.path ?? "", join12(staging, BOOTSTRAP_FILE));
|
|
29318
|
+
await rm10(entryPath, { force: true });
|
|
28584
29319
|
};
|
|
28585
29320
|
var removePreviousBundle = async (backup, moved) => {
|
|
28586
29321
|
if (!moved)
|
|
28587
29322
|
return;
|
|
28588
|
-
await
|
|
29323
|
+
await rm10(backup, { force: true, recursive: true });
|
|
28589
29324
|
};
|
|
28590
29325
|
var restorePreviousBundle = async (backup, destination, moved) => {
|
|
28591
29326
|
if (!moved)
|
|
@@ -28617,17 +29352,17 @@ var copyClientPage = async (page, buildDirectory, staging, copiedDependencies) =
|
|
|
28617
29352
|
const extension = extname2(page.bundlePath) || ".js";
|
|
28618
29353
|
const localBundlePath = `./pages/${page.bundleHash}${extension}`;
|
|
28619
29354
|
const source = sourceAssetPath(buildDirectory, page.bundlePath);
|
|
28620
|
-
await copyFile5(source,
|
|
29355
|
+
await copyFile5(source, join12(staging, localBundlePath));
|
|
28621
29356
|
await copyAbsoluteClientDependencies(source, buildDirectory, staging, copiedDependencies);
|
|
28622
29357
|
let localStylePath;
|
|
28623
29358
|
if (page.styleBundlePath && page.styleBundleHash) {
|
|
28624
29359
|
const styleExtension = extname2(page.styleBundlePath) || ".css";
|
|
28625
29360
|
localStylePath = `./styles/${page.styleBundleHash}${styleExtension}`;
|
|
28626
29361
|
const styleSource = sourceAssetPath(buildDirectory, page.styleBundlePath);
|
|
28627
|
-
await
|
|
29362
|
+
await mkdir11(dirname9(join12(staging, localStylePath)), {
|
|
28628
29363
|
recursive: true
|
|
28629
29364
|
});
|
|
28630
|
-
await copyFile5(styleSource,
|
|
29365
|
+
await copyFile5(styleSource, join12(staging, localStylePath));
|
|
28631
29366
|
await copyAbsoluteClientDependencies(styleSource, buildDirectory, staging, copiedDependencies);
|
|
28632
29367
|
}
|
|
28633
29368
|
return {
|
|
@@ -28643,26 +29378,26 @@ var materializeAbsoluteMobileSourcemaps = async (pages, appBuild, projectRoot) =
|
|
|
28643
29378
|
return value;
|
|
28644
29379
|
};
|
|
28645
29380
|
const release = safeLeaf(appBuild, "Mobile app build");
|
|
28646
|
-
const privateRoot =
|
|
28647
|
-
const releaseRoot =
|
|
29381
|
+
const privateRoot = join12(projectRoot, "sourcemaps");
|
|
29382
|
+
const releaseRoot = join12(privateRoot, "mobile", release);
|
|
28648
29383
|
const copied = [];
|
|
28649
29384
|
const available = pages.flatMap((page) => {
|
|
28650
|
-
const source =
|
|
29385
|
+
const source = join12(privateRoot, `${basename5(page.bundlePath)}.map`);
|
|
28651
29386
|
return existsSync2(source) ? [{ page, source }] : [];
|
|
28652
29387
|
});
|
|
28653
29388
|
if (available.length > 0)
|
|
28654
|
-
await
|
|
29389
|
+
await mkdir11(releaseRoot, { recursive: true });
|
|
28655
29390
|
await Promise.all(available.map(async ({ page, source }) => {
|
|
28656
29391
|
const extension = extname2(page.bundlePath) || ".js";
|
|
28657
29392
|
if (!/^\.[a-z0-9]+$/iu.test(extension))
|
|
28658
29393
|
throw new TypeError("Mobile page extension is not a safe source-map key.");
|
|
28659
29394
|
const bundleHash = safeLeaf(page.bundleHash, "Mobile page bundle hash");
|
|
28660
29395
|
const file = `${bundleHash}${extension}.map`;
|
|
28661
|
-
await copyFile5(source,
|
|
29396
|
+
await copyFile5(source, join12(releaseRoot, file));
|
|
28662
29397
|
copied.push({ bundleHash, file, pageId: page.pageId });
|
|
28663
29398
|
}));
|
|
28664
29399
|
if (copied.length > 0) {
|
|
28665
|
-
await writeFile11(
|
|
29400
|
+
await writeFile11(join12(releaseRoot, "manifest.json"), `${JSON.stringify({
|
|
28666
29401
|
appBuild,
|
|
28667
29402
|
format: 1,
|
|
28668
29403
|
pages: copied.sort((left, right) => left.pageId.localeCompare(right.pageId))
|
|
@@ -28672,7 +29407,7 @@ var materializeAbsoluteMobileSourcemaps = async (pages, appBuild, projectRoot) =
|
|
|
28672
29407
|
return copied.length;
|
|
28673
29408
|
};
|
|
28674
29409
|
var absoluteClientImports = async (sourcePath, buildDirectory) => {
|
|
28675
|
-
const source = await
|
|
29410
|
+
const source = await readFile14(sourcePath, "utf8");
|
|
28676
29411
|
const extension = extname2(sourcePath).toLowerCase();
|
|
28677
29412
|
let scriptLoader;
|
|
28678
29413
|
if (extension === ".tsx")
|
|
@@ -28695,9 +29430,9 @@ var absoluteClientImports = async (sourcePath, buildDirectory) => {
|
|
|
28695
29430
|
const clean = specifier.split(/[?#]/u, 1)[0] ?? specifier;
|
|
28696
29431
|
if (clean.startsWith("/"))
|
|
28697
29432
|
return [clean];
|
|
28698
|
-
const resolved =
|
|
28699
|
-
const root =
|
|
28700
|
-
const relativePath =
|
|
29433
|
+
const resolved = resolve11(dirname9(sourcePath), clean);
|
|
29434
|
+
const root = resolve11(buildDirectory);
|
|
29435
|
+
const relativePath = relative10(root, resolved).replaceAll("\\", "/");
|
|
28701
29436
|
if (relativePath === ".." || relativePath.startsWith("../")) {
|
|
28702
29437
|
throw new TypeError(`Mobile client dependency escaped the build directory: ${specifier}`);
|
|
28703
29438
|
}
|
|
@@ -28709,8 +29444,8 @@ var copyAbsoluteClientDependency = async (specifier, buildDirectory, staging, co
|
|
|
28709
29444
|
return;
|
|
28710
29445
|
copied.add(specifier);
|
|
28711
29446
|
const source = sourceAssetPath(buildDirectory, specifier);
|
|
28712
|
-
const destination =
|
|
28713
|
-
await
|
|
29447
|
+
const destination = join12(staging, specifier.replace(/^\/+/, ""));
|
|
29448
|
+
await mkdir11(dirname9(destination), { recursive: true });
|
|
28714
29449
|
await copyFile5(source, destination);
|
|
28715
29450
|
await copyAbsoluteClientDependencies(source, buildDirectory, staging, copied);
|
|
28716
29451
|
};
|
|
@@ -28723,14 +29458,14 @@ var materializeAbsoluteCapacitorWebBundle = async (options) => {
|
|
|
28723
29458
|
throw new TypeError(`mobile.entry ${options.config.entry} is not a captured mobile page route.`);
|
|
28724
29459
|
}
|
|
28725
29460
|
const destination = options.config.bundleDirectory;
|
|
28726
|
-
await
|
|
28727
|
-
const staging = await
|
|
29461
|
+
await mkdir11(dirname9(destination), { recursive: true });
|
|
29462
|
+
const staging = await mkdtemp7(join12(dirname9(destination), `.${basename5(destination)}.stage-`));
|
|
28728
29463
|
try {
|
|
28729
|
-
const pageDirectory =
|
|
28730
|
-
await
|
|
29464
|
+
const pageDirectory = join12(staging, "pages");
|
|
29465
|
+
await mkdir11(pageDirectory, { recursive: true });
|
|
28731
29466
|
await Promise.all(CLIENT_ASSET_DIRECTORIES.map((directory) => ({
|
|
28732
|
-
destination:
|
|
28733
|
-
source:
|
|
29467
|
+
destination: join12(staging, directory),
|
|
29468
|
+
source: join12(options.buildDirectory, directory)
|
|
28734
29469
|
})).filter(({ source }) => existsSync2(source)).map(({ destination: assetDestination, source }) => cp(source, assetDestination, { recursive: true })));
|
|
28735
29470
|
const copiedDependencies = new Set;
|
|
28736
29471
|
const pages = await Promise.all(options.artifact.pages.map((page) => copyClientPage(page, options.buildDirectory, staging, copiedDependencies)));
|
|
@@ -28767,16 +29502,16 @@ var materializeAbsoluteCapacitorWebBundle = async (options) => {
|
|
|
28767
29502
|
} : {}
|
|
28768
29503
|
};
|
|
28769
29504
|
await Promise.all([
|
|
28770
|
-
writeFile11(
|
|
29505
|
+
writeFile11(join12(staging, MANIFEST_FILE), `${JSON.stringify(manifest, null, "\t")}
|
|
28771
29506
|
`),
|
|
28772
|
-
writeFile11(
|
|
29507
|
+
writeFile11(join12(staging, INDEX_FILE), indexHtml(options.config.appName, options.config.productionOrigin)),
|
|
28773
29508
|
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)
|
|
28774
29509
|
]);
|
|
28775
29510
|
await installBundle(staging, destination);
|
|
28776
29511
|
await materializeAbsoluteMobileSourcemaps(options.artifact.pages, options.artifact.appBuild, options.projectRoot);
|
|
28777
29512
|
return manifest;
|
|
28778
29513
|
} catch (error) {
|
|
28779
|
-
await
|
|
29514
|
+
await rm10(staging, { force: true, recursive: true });
|
|
28780
29515
|
throw error;
|
|
28781
29516
|
}
|
|
28782
29517
|
};
|
|
@@ -28793,22 +29528,22 @@ init_nativeAuth();
|
|
|
28793
29528
|
init_syncSchema();
|
|
28794
29529
|
init_deviceCapabilities();
|
|
28795
29530
|
import {
|
|
28796
|
-
access as
|
|
28797
|
-
mkdir as
|
|
28798
|
-
mkdtemp as
|
|
28799
|
-
readdir as
|
|
28800
|
-
readFile as
|
|
29531
|
+
access as access12,
|
|
29532
|
+
mkdir as mkdir13,
|
|
29533
|
+
mkdtemp as mkdtemp9,
|
|
29534
|
+
readdir as readdir5,
|
|
29535
|
+
readFile as readFile16,
|
|
28801
29536
|
rename as rename12,
|
|
28802
|
-
rm as
|
|
29537
|
+
rm as rm12,
|
|
28803
29538
|
writeFile as writeFile13
|
|
28804
29539
|
} from "fs/promises";
|
|
28805
|
-
import { createHash as
|
|
28806
|
-
import { basename as
|
|
29540
|
+
import { createHash as createHash14 } from "crypto";
|
|
29541
|
+
import { basename as basename6, dirname as dirname12, join as join19, relative as relative12, resolve as resolve14, sep as sep8 } from "path";
|
|
28807
29542
|
|
|
28808
29543
|
// src/mobile/updateRuntime.ts
|
|
28809
29544
|
init_deviceCapabilities();
|
|
28810
29545
|
init_nativeAuth();
|
|
28811
|
-
import { createHash as
|
|
29546
|
+
import { createHash as createHash13 } from "crypto";
|
|
28812
29547
|
|
|
28813
29548
|
// src/mobile/updateProtocol.ts
|
|
28814
29549
|
var ABSOLUTE_MOBILE_UPDATE_FORMAT = 1;
|
|
@@ -28949,7 +29684,7 @@ var createAbsoluteMobileUpdateRuntimeDescriptor = (options) => ({
|
|
|
28949
29684
|
syncSchema: options.syncSchema ?? null,
|
|
28950
29685
|
updates: options.config.updates ?? null
|
|
28951
29686
|
});
|
|
28952
|
-
var fingerprintAbsoluteMobileUpdateRuntime = (descriptor) =>
|
|
29687
|
+
var fingerprintAbsoluteMobileUpdateRuntime = (descriptor) => createHash13("sha256").update(canonicalizeAbsoluteMobileUpdate(descriptor)).digest("hex");
|
|
28953
29688
|
var resolveAbsoluteMobileUpdateRuntime = (config, projectRoot) => {
|
|
28954
29689
|
const auth = resolveAbsoluteMobileAuthManifest(projectRoot, config);
|
|
28955
29690
|
const sync = auth !== undefined && projectUsesAbsoluteSync(projectRoot);
|
|
@@ -28972,7 +29707,7 @@ var resolveAbsoluteMobileUpdateRuntime = (config, projectRoot) => {
|
|
|
28972
29707
|
};
|
|
28973
29708
|
|
|
28974
29709
|
// src/mobile/expoNativeObservability.ts
|
|
28975
|
-
import { join as
|
|
29710
|
+
import { join as join17 } from "path";
|
|
28976
29711
|
var HEADER = `// Generated by AbsoluteJS. Edit absolute.config.ts, then run absolute mobile sync.
|
|
28977
29712
|
`;
|
|
28978
29713
|
var XML_HEADER = `<!-- Generated by AbsoluteJS. Edit absolute.config.ts, then run absolute mobile sync. -->
|
|
@@ -29414,31 +30149,31 @@ export const enqueueAbsoluteExpoNativeObservabilityForTesting = async (testId: s
|
|
|
29414
30149
|
`;
|
|
29415
30150
|
var absoluteExpoNativeObservabilityFiles = (project) => new Map([
|
|
29416
30151
|
[
|
|
29417
|
-
|
|
30152
|
+
join17(project, "modules/absolute-mobile-observability/expo-module.config.json"),
|
|
29418
30153
|
moduleConfig
|
|
29419
30154
|
],
|
|
29420
30155
|
[
|
|
29421
|
-
|
|
30156
|
+
join17(project, "modules/absolute-mobile-observability/ios/AbsoluteMobileObservability.podspec"),
|
|
29422
30157
|
podspec
|
|
29423
30158
|
],
|
|
29424
30159
|
[
|
|
29425
|
-
|
|
30160
|
+
join17(project, "modules/absolute-mobile-observability/ios/AbsoluteMobileObservabilityModule.swift"),
|
|
29426
30161
|
iosModule
|
|
29427
30162
|
],
|
|
29428
30163
|
[
|
|
29429
|
-
|
|
30164
|
+
join17(project, "modules/absolute-mobile-observability/android/build.gradle"),
|
|
29430
30165
|
androidBuild
|
|
29431
30166
|
],
|
|
29432
30167
|
[
|
|
29433
|
-
|
|
30168
|
+
join17(project, "modules/absolute-mobile-observability/android/src/main/AndroidManifest.xml"),
|
|
29434
30169
|
androidManifest
|
|
29435
30170
|
],
|
|
29436
30171
|
[
|
|
29437
|
-
|
|
30172
|
+
join17(project, "modules/absolute-mobile-observability/android/src/main/java/expo/modules/absolutemobileobservability/AbsoluteMobileObservabilityModule.kt"),
|
|
29438
30173
|
androidModule
|
|
29439
30174
|
],
|
|
29440
30175
|
[
|
|
29441
|
-
|
|
30176
|
+
join17(project, "src/generated/AbsoluteNativeObservability.ts"),
|
|
29442
30177
|
expoNativeObservabilityRuntimeSource
|
|
29443
30178
|
]
|
|
29444
30179
|
]);
|
|
@@ -29447,7 +30182,7 @@ var absoluteExpoNativeObservabilityPaths = (project) => [
|
|
|
29447
30182
|
];
|
|
29448
30183
|
|
|
29449
30184
|
// src/mobile/expoActivityResultRecovery.ts
|
|
29450
|
-
import { join as
|
|
30185
|
+
import { join as join18 } from "path";
|
|
29451
30186
|
var HEADER2 = `// Generated by AbsoluteJS. Edit absolute.config.ts, then run absolute mobile sync.
|
|
29452
30187
|
`;
|
|
29453
30188
|
var XML_HEADER2 = `<!-- Generated by AbsoluteJS. Edit absolute.config.ts, then run absolute mobile sync. -->
|
|
@@ -29458,9 +30193,59 @@ var moduleConfig2 = `${JSON.stringify({
|
|
|
29458
30193
|
"expo.modules.absoluteactivityresultrecovery.AbsoluteActivityResultRecoveryModule"
|
|
29459
30194
|
]
|
|
29460
30195
|
},
|
|
29461
|
-
|
|
30196
|
+
apple: { modules: ["AbsoluteActivityResultRecoveryModule"] },
|
|
30197
|
+
platforms: ["apple", "android"]
|
|
29462
30198
|
}, null, 2)}
|
|
29463
30199
|
`;
|
|
30200
|
+
var podspec2 = `${HEADER2}Pod::Spec.new do |s|
|
|
30201
|
+
s.name = 'AbsoluteActivityResultRecovery'
|
|
30202
|
+
s.version = '0.0.1'
|
|
30203
|
+
s.summary = 'AbsoluteJS native runtime readiness bridge'
|
|
30204
|
+
s.description = 'Generated lifecycle and embedded-content readiness bridge for an AbsoluteJS Expo application.'
|
|
30205
|
+
s.author = 'AbsoluteJS'
|
|
30206
|
+
s.homepage = 'https://absolutejs.com'
|
|
30207
|
+
s.platforms = { :ios => '16.4' }
|
|
30208
|
+
s.source = { git: '' }
|
|
30209
|
+
s.static_framework = true
|
|
30210
|
+
s.dependency 'ExpoModulesCore'
|
|
30211
|
+
s.pod_target_xcconfig = { 'DEFINES_MODULE' => 'YES' }
|
|
30212
|
+
s.source_files = '**/*.{h,m,mm,swift,hpp,cpp}'
|
|
30213
|
+
end
|
|
30214
|
+
`;
|
|
30215
|
+
var iosModule2 = `${HEADER2}import ExpoModulesCore
|
|
30216
|
+
|
|
30217
|
+
public final class AbsoluteActivityResultRecoveryModule: Module {
|
|
30218
|
+
public func definition() -> ModuleDefinition {
|
|
30219
|
+
Name("AbsoluteActivityResultRecovery")
|
|
30220
|
+
|
|
30221
|
+
Function("markApplicationRuntimeReady") { }
|
|
30222
|
+
|
|
30223
|
+
Function("markEmbeddedWebReady") {
|
|
30224
|
+
let info = Bundle.main.infoDictionary ?? [:]
|
|
30225
|
+
let version = info["CFBundleShortVersionString"] as? String ?? "unknown"
|
|
30226
|
+
let build = info["CFBundleVersion"] as? String ?? "unknown"
|
|
30227
|
+
NSLog("AbsoluteJS: Expo embedded web content ready; version=%@; build=%@", version, build)
|
|
30228
|
+
}
|
|
30229
|
+
|
|
30230
|
+
Function("markEmbeddedWebPhase") { (phase: String) in
|
|
30231
|
+
let allowed = [
|
|
30232
|
+
"assets-start", "assets-ready", "assets-root-failed",
|
|
30233
|
+
"assets-directory-failed", "assets-destination-failed",
|
|
30234
|
+
"assets-module-failed", "assets-source-failed",
|
|
30235
|
+
"assets-download-failed", "assets-copy-failed",
|
|
30236
|
+
"assets-read-failed", "assets-write-failed",
|
|
30237
|
+
"assets-finalize-failed", "assets-unexpected-failed",
|
|
30238
|
+
"devices-start", "devices-ready", "devices-failed"
|
|
30239
|
+
]
|
|
30240
|
+
if allowed.contains(phase) {
|
|
30241
|
+
NSLog("AbsoluteJS: Expo embedded web phase: %@", phase)
|
|
30242
|
+
}
|
|
30243
|
+
}
|
|
30244
|
+
|
|
30245
|
+
Function("takePendingCancellation") { false }
|
|
30246
|
+
}
|
|
30247
|
+
}
|
|
30248
|
+
`;
|
|
29464
30249
|
var androidBuild2 = `${HEADER2}plugins {
|
|
29465
30250
|
id 'com.android.library'
|
|
29466
30251
|
id 'expo-module-gradle-plugin'
|
|
@@ -29634,23 +30419,31 @@ export const takeAbsoluteActivityResultCancellation = () =>
|
|
|
29634
30419
|
`;
|
|
29635
30420
|
var absoluteExpoActivityResultRecoveryFiles = (project) => new Map([
|
|
29636
30421
|
[
|
|
29637
|
-
|
|
30422
|
+
join18(project, "modules/absolute-activity-result-recovery/expo-module.config.json"),
|
|
29638
30423
|
moduleConfig2
|
|
29639
30424
|
],
|
|
29640
30425
|
[
|
|
29641
|
-
|
|
30426
|
+
join18(project, "modules/absolute-activity-result-recovery/ios/AbsoluteActivityResultRecovery.podspec"),
|
|
30427
|
+
podspec2
|
|
30428
|
+
],
|
|
30429
|
+
[
|
|
30430
|
+
join18(project, "modules/absolute-activity-result-recovery/ios/AbsoluteActivityResultRecoveryModule.swift"),
|
|
30431
|
+
iosModule2
|
|
30432
|
+
],
|
|
30433
|
+
[
|
|
30434
|
+
join18(project, "modules/absolute-activity-result-recovery/android/build.gradle"),
|
|
29642
30435
|
androidBuild2
|
|
29643
30436
|
],
|
|
29644
30437
|
[
|
|
29645
|
-
|
|
30438
|
+
join18(project, "modules/absolute-activity-result-recovery/android/src/main/AndroidManifest.xml"),
|
|
29646
30439
|
androidManifest2
|
|
29647
30440
|
],
|
|
29648
30441
|
[
|
|
29649
|
-
|
|
30442
|
+
join18(project, "modules/absolute-activity-result-recovery/android/src/main/java/expo/modules/absoluteactivityresultrecovery/AbsoluteActivityResultRecoveryModule.kt"),
|
|
29650
30443
|
androidModule2
|
|
29651
30444
|
],
|
|
29652
30445
|
[
|
|
29653
|
-
|
|
30446
|
+
join18(project, "src/generated/AbsoluteActivityResultRecovery.ts"),
|
|
29654
30447
|
runtime
|
|
29655
30448
|
]
|
|
29656
30449
|
]);
|
|
@@ -29660,9 +30453,9 @@ var EXPO_GENERATED_HEADER = `// Generated by AbsoluteJS. Edit absolute.config.ts
|
|
|
29660
30453
|
`;
|
|
29661
30454
|
var EXPO_ASSET_EXTENSION = ".absasset";
|
|
29662
30455
|
var EXPO_PROJECT_MARKER = ".absolutejs-expo-project";
|
|
29663
|
-
var
|
|
30456
|
+
var exists5 = async (path) => {
|
|
29664
30457
|
try {
|
|
29665
|
-
await
|
|
30458
|
+
await access12(path);
|
|
29666
30459
|
return true;
|
|
29667
30460
|
} catch {
|
|
29668
30461
|
return false;
|
|
@@ -29719,7 +30512,7 @@ var expoNativeDataManifest = (value) => {
|
|
|
29719
30512
|
};
|
|
29720
30513
|
};
|
|
29721
30514
|
var portableRelative2 = (from, destination) => {
|
|
29722
|
-
const value =
|
|
30515
|
+
const value = relative12(from, destination).replaceAll("\\", "/");
|
|
29723
30516
|
return value.startsWith(".") ? value : `./${value}`;
|
|
29724
30517
|
};
|
|
29725
30518
|
var routeSegments = (route) => {
|
|
@@ -29735,7 +30528,7 @@ var routeSegments = (route) => {
|
|
|
29735
30528
|
return segment;
|
|
29736
30529
|
});
|
|
29737
30530
|
};
|
|
29738
|
-
var routeFile = (project, route) =>
|
|
30531
|
+
var routeFile = (project, route) => join19(project, "app", ...routeSegments(route), "index.tsx");
|
|
29739
30532
|
var packageDependencies = (plan) => Object.fromEntries(plan.requiredPackages.map((spec) => {
|
|
29740
30533
|
const separator = spec.lastIndexOf("@");
|
|
29741
30534
|
return [spec.slice(0, separator), spec.slice(separator + 1)];
|
|
@@ -30289,7 +31082,7 @@ ${push ? `absoluteExpoAuth.onPrincipalChange(principal => {
|
|
|
30289
31082
|
`;
|
|
30290
31083
|
};
|
|
30291
31084
|
var authRuntimeSource = (auth, appId) => {
|
|
30292
|
-
const storageIdentity =
|
|
31085
|
+
const storageIdentity = createHash14("sha256").update(appId).digest("hex").slice(0, 24);
|
|
30293
31086
|
return `${EXPO_GENERATED_HEADER}import { createAbsoluteExpoAuthClient } from '@absolutejs/auth-expo';
|
|
30294
31087
|
import { createMobileAuthTransport, installAuthClientRuntimeTransport } from '@absolutejs/auth/client/mobile';
|
|
30295
31088
|
|
|
@@ -30321,7 +31114,7 @@ export const startAbsoluteExpoAuth = () => {
|
|
|
30321
31114
|
`;
|
|
30322
31115
|
};
|
|
30323
31116
|
var syncRuntimeSource = (config, schema) => {
|
|
30324
|
-
const storageIdentity =
|
|
31117
|
+
const storageIdentity = createHash14("sha256").update(config.appId).digest("hex").slice(0, 24);
|
|
30325
31118
|
const backgroundEndpoint = new URL("/__absolute/sync/background", config.productionOrigin).href;
|
|
30326
31119
|
const backgroundTask = `${config.appId}.absolutejs.sync`;
|
|
30327
31120
|
return `${EXPO_GENERATED_HEADER}import { runHeadlessSync } from '@absolutejs/sync/client/headless';
|
|
@@ -30980,8 +31773,8 @@ const styles = StyleSheet.create({
|
|
|
30980
31773
|
error: { color: '#b91c1c', fontSize: 16, textAlign: 'center' }
|
|
30981
31774
|
});
|
|
30982
31775
|
`;
|
|
30983
|
-
var nativeWrapperSource = (wrapper, module, runtime2, route) => `${EXPO_GENERATED_HEADER}import ApplicationNativeRoute from ${JSON.stringify(portableRelative2(
|
|
30984
|
-
import { createAbsoluteNativeRoute, createAbsoluteNativeRouteErrorBoundary } from ${JSON.stringify(portableRelative2(
|
|
31776
|
+
var nativeWrapperSource = (wrapper, module, runtime2, route) => `${EXPO_GENERATED_HEADER}import ApplicationNativeRoute from ${JSON.stringify(portableRelative2(dirname12(wrapper), module).replace(/\.(?:[cm]?[jt]sx?)$/u, ""))};
|
|
31777
|
+
import { createAbsoluteNativeRoute, createAbsoluteNativeRouteErrorBoundary } from ${JSON.stringify(portableRelative2(dirname12(wrapper), runtime2).replace(/\.(?:[cm]?[jt]sx?)$/u, ""))};
|
|
30985
31778
|
|
|
30986
31779
|
export const ErrorBoundary = createAbsoluteNativeRouteErrorBoundary(${JSON.stringify(route)});
|
|
30987
31780
|
export default createAbsoluteNativeRoute(ApplicationNativeRoute, ${JSON.stringify(route)});
|
|
@@ -31023,9 +31816,9 @@ var expoTsConfig = (projectRoot, project, auth, sync) => ({
|
|
|
31023
31816
|
extends: "expo/tsconfig.base"
|
|
31024
31817
|
});
|
|
31025
31818
|
var writeManagedFile = async (path, source, force) => {
|
|
31026
|
-
await
|
|
31027
|
-
if (await
|
|
31028
|
-
const current = await
|
|
31819
|
+
await mkdir13(dirname12(path), { recursive: true });
|
|
31820
|
+
if (await exists5(path)) {
|
|
31821
|
+
const current = await readFile16(path, "utf8");
|
|
31029
31822
|
if (current === source)
|
|
31030
31823
|
return false;
|
|
31031
31824
|
if (!force && !current.startsWith(EXPO_GENERATED_HEADER)) {
|
|
@@ -31039,26 +31832,26 @@ var writeManagedFile = async (path, source, force) => {
|
|
|
31039
31832
|
};
|
|
31040
31833
|
var pruneManagedFiles = async (paths) => {
|
|
31041
31834
|
const removed = await Promise.all(paths.map(async (path) => {
|
|
31042
|
-
if (!await
|
|
31835
|
+
if (!await exists5(path))
|
|
31043
31836
|
return false;
|
|
31044
|
-
const source = await
|
|
31837
|
+
const source = await readFile16(path, "utf8");
|
|
31045
31838
|
if (!source.startsWith(EXPO_GENERATED_HEADER) && !path.endsWith("expo-module.config.json"))
|
|
31046
31839
|
return false;
|
|
31047
|
-
await
|
|
31840
|
+
await rm12(path, { force: true });
|
|
31048
31841
|
return true;
|
|
31049
31842
|
}));
|
|
31050
31843
|
return removed.filter(Boolean).length;
|
|
31051
31844
|
};
|
|
31052
31845
|
var pruneStaleManagedExpoRoutes = async (project, expected) => {
|
|
31053
|
-
const appDirectory =
|
|
31054
|
-
if (!await
|
|
31846
|
+
const appDirectory = join19(project, "app");
|
|
31847
|
+
if (!await exists5(appDirectory))
|
|
31055
31848
|
return 0;
|
|
31056
31849
|
const files = await walkFiles(appDirectory);
|
|
31057
31850
|
const stale = (await Promise.all(files.map(async (path) => ({
|
|
31058
|
-
managed: path.endsWith(".tsx") && (await
|
|
31851
|
+
managed: path.endsWith(".tsx") && (await readFile16(path, "utf8")).startsWith(EXPO_GENERATED_HEADER),
|
|
31059
31852
|
path
|
|
31060
31853
|
})))).filter(({ managed, path }) => managed && !expected.has(path));
|
|
31061
|
-
await Promise.all(stale.map(({ path }) =>
|
|
31854
|
+
await Promise.all(stale.map(({ path }) => rm12(path, { force: true })));
|
|
31062
31855
|
return stale.length;
|
|
31063
31856
|
};
|
|
31064
31857
|
var jsonSource = (value) => `${JSON.stringify(value, null, "\t")}
|
|
@@ -31081,7 +31874,7 @@ export const ABSOLUTE_MOBILE_MANIFEST: AbsoluteMobileManifest | undefined = unde
|
|
|
31081
31874
|
var writeAbsoluteExpoProject = async (config, options) => {
|
|
31082
31875
|
if (config.engine !== "expo")
|
|
31083
31876
|
throw new TypeError("Expo project generation requires mobile.engine: expo.");
|
|
31084
|
-
const projectRoot =
|
|
31877
|
+
const projectRoot = resolve14(options.projectRoot);
|
|
31085
31878
|
const project = config.nativeProjectDirectory;
|
|
31086
31879
|
const auth = resolveAbsoluteMobileAuthManifest(projectRoot, config);
|
|
31087
31880
|
const devices = resolveAbsoluteDeviceCapabilityPlan(projectRoot, "expo");
|
|
@@ -31090,7 +31883,7 @@ var writeAbsoluteExpoProject = async (config, options) => {
|
|
|
31090
31883
|
const runtimeFingerprint = resolveAbsoluteMobileUpdateRuntime(config, projectRoot).fingerprint;
|
|
31091
31884
|
const routeModules = Object.entries(config.expoNativeRoutes);
|
|
31092
31885
|
const moduleChecks = await Promise.all(routeModules.map(async ([route, module]) => ({
|
|
31093
|
-
exists: await
|
|
31886
|
+
exists: await exists5(module),
|
|
31094
31887
|
module,
|
|
31095
31888
|
route
|
|
31096
31889
|
})));
|
|
@@ -31098,20 +31891,20 @@ var writeAbsoluteExpoProject = async (config, options) => {
|
|
|
31098
31891
|
if (missing) {
|
|
31099
31892
|
throw new TypeError(`Expo native route ${missing.route} references missing module ${missing.module}.`);
|
|
31100
31893
|
}
|
|
31101
|
-
const marker =
|
|
31102
|
-
if (await
|
|
31103
|
-
const entries = await
|
|
31894
|
+
const marker = join19(project, EXPO_PROJECT_MARKER);
|
|
31895
|
+
if (await exists5(project) && !await exists5(marker)) {
|
|
31896
|
+
const entries = await readdir5(project);
|
|
31104
31897
|
if (entries.length > 0 && !options.force) {
|
|
31105
31898
|
throw new TypeError(`Expo project directory ${project} is not AbsoluteJS-managed; rerun with --force only after reviewing it.`);
|
|
31106
31899
|
}
|
|
31107
31900
|
}
|
|
31108
|
-
await
|
|
31901
|
+
await mkdir13(project, { recursive: true });
|
|
31109
31902
|
await writeFile13(marker, `format=1
|
|
31110
31903
|
`);
|
|
31111
31904
|
const authEnabled = Boolean(auth);
|
|
31112
31905
|
const files = new Map([
|
|
31113
31906
|
[
|
|
31114
|
-
|
|
31907
|
+
join19(project, ".gitignore"),
|
|
31115
31908
|
`.expo/
|
|
31116
31909
|
android/
|
|
31117
31910
|
ios/
|
|
@@ -31119,45 +31912,45 @@ node_modules/
|
|
|
31119
31912
|
`
|
|
31120
31913
|
],
|
|
31121
31914
|
[
|
|
31122
|
-
|
|
31915
|
+
join19(project, "app.json"),
|
|
31123
31916
|
jsonSource(expoAppConfig(config, authEnabled, syncEnabled, devices, runtimeFingerprint))
|
|
31124
31917
|
],
|
|
31125
|
-
[
|
|
31918
|
+
[join19(project, "app.config.js"), expoDynamicAppConfig],
|
|
31126
31919
|
[
|
|
31127
|
-
|
|
31920
|
+
join19(project, "package.json"),
|
|
31128
31921
|
jsonSource(expoPackage(authEnabled, syncEnabled, devices, config.updates !== undefined))
|
|
31129
31922
|
],
|
|
31130
|
-
[
|
|
31923
|
+
[join19(project, "metro.config.js"), metroConfig(projectRoot)],
|
|
31131
31924
|
[
|
|
31132
|
-
|
|
31925
|
+
join19(project, "plugins", "withAbsoluteDevelopmentCa.js"),
|
|
31133
31926
|
expoDevelopmentCaPlugin
|
|
31134
31927
|
],
|
|
31135
31928
|
[
|
|
31136
|
-
|
|
31929
|
+
join19(project, "plugins", "withAbsoluteActivityResultRecovery.js"),
|
|
31137
31930
|
expoActivityResultRecoveryPlugin
|
|
31138
31931
|
],
|
|
31139
31932
|
[
|
|
31140
|
-
|
|
31933
|
+
join19(project, "tsconfig.json"),
|
|
31141
31934
|
jsonSource(expoTsConfig(projectRoot, project, authEnabled, syncEnabled))
|
|
31142
31935
|
],
|
|
31143
31936
|
[
|
|
31144
|
-
|
|
31937
|
+
join19(project, "app", "_layout.tsx"),
|
|
31145
31938
|
layoutSource(authEnabled, syncEnabled, config.updates !== undefined, config.observability !== undefined)
|
|
31146
31939
|
],
|
|
31147
31940
|
[
|
|
31148
|
-
|
|
31941
|
+
join19(project, "app", "__absolute", "native", "index.tsx"),
|
|
31149
31942
|
nativeDiagnosticSource
|
|
31150
31943
|
],
|
|
31151
31944
|
[
|
|
31152
|
-
|
|
31945
|
+
join19(project, "src", "generated", "AbsoluteDevices.ts"),
|
|
31153
31946
|
devicesRuntimeSource(config, devices, authEnabled)
|
|
31154
31947
|
],
|
|
31155
31948
|
[
|
|
31156
|
-
|
|
31949
|
+
join19(project, "src", "generated", "AbsoluteNativeRoute.tsx"),
|
|
31157
31950
|
nativeRouteRuntimeSource(authEnabled)
|
|
31158
31951
|
],
|
|
31159
31952
|
[
|
|
31160
|
-
|
|
31953
|
+
join19(project, "src", "generated", "AbsoluteWebHost.tsx"),
|
|
31161
31954
|
webHostSource(config, auth, syncEnabled)
|
|
31162
31955
|
]
|
|
31163
31956
|
]);
|
|
@@ -31168,40 +31961,40 @@ node_modules/
|
|
|
31168
31961
|
files.set(path, source);
|
|
31169
31962
|
}
|
|
31170
31963
|
if (config.updates) {
|
|
31171
|
-
files.set(
|
|
31964
|
+
files.set(join19(project, "src", "generated", "AbsoluteUpdates.ts"), updatesRuntimeSource(config));
|
|
31172
31965
|
}
|
|
31173
31966
|
const expoCodeSigning = config.updates?.expoCodeSigning;
|
|
31174
31967
|
if (expoCodeSigning)
|
|
31175
|
-
files.set(
|
|
31968
|
+
files.set(join19(project, "certs", "absolute-mobile-update.pem"), expoCodeSigning.certificatePem);
|
|
31176
31969
|
if (auth) {
|
|
31177
|
-
files.set(
|
|
31970
|
+
files.set(join19(project, "src", "generated", "AbsoluteAuth.ts"), authRuntimeSource(auth, config.appId));
|
|
31178
31971
|
}
|
|
31179
31972
|
if (syncSchema) {
|
|
31180
|
-
files.set(
|
|
31973
|
+
files.set(join19(project, "src", "generated", "AbsoluteSync.ts"), syncRuntimeSource(config, syncSchema));
|
|
31181
31974
|
}
|
|
31182
|
-
const webAssetsPath =
|
|
31183
|
-
if (!await
|
|
31975
|
+
const webAssetsPath = join19(project, "src", "generated", "webAssets.ts");
|
|
31976
|
+
if (!await exists5(webAssetsPath)) {
|
|
31184
31977
|
files.set(webAssetsPath, emptyWebAssetsSource);
|
|
31185
31978
|
}
|
|
31186
31979
|
if (!config.expoNativeRoutes["/"]) {
|
|
31187
|
-
files.set(
|
|
31980
|
+
files.set(join19(project, "app", "index.tsx"), webRouteSource);
|
|
31188
31981
|
}
|
|
31189
|
-
files.set(
|
|
31190
|
-
const nativeRouteRuntime =
|
|
31982
|
+
files.set(join19(project, "app", "[...absolute].tsx"), catchAllRouteSource);
|
|
31983
|
+
const nativeRouteRuntime = join19(project, "src", "generated", "AbsoluteNativeRoute.tsx");
|
|
31191
31984
|
for (const [route, module] of routeModules) {
|
|
31192
|
-
const wrapper = route === "/" ?
|
|
31985
|
+
const wrapper = route === "/" ? join19(project, "app", "index.tsx") : routeFile(project, route);
|
|
31193
31986
|
files.set(wrapper, nativeWrapperSource(wrapper, module, nativeRouteRuntime, route));
|
|
31194
31987
|
}
|
|
31195
|
-
const removedRoutes = await pruneStaleManagedExpoRoutes(project, new Set([...files.keys()].filter((path) => path.startsWith(`${
|
|
31988
|
+
const removedRoutes = await pruneStaleManagedExpoRoutes(project, new Set([...files.keys()].filter((path) => path.startsWith(`${join19(project, "app")}${sep8}`))));
|
|
31196
31989
|
const removedObservability = config.observability ? 0 : await pruneManagedFiles(absoluteExpoNativeObservabilityPaths(project));
|
|
31197
31990
|
const changes = await Promise.all([...files].map(([path, source]) => writeManagedFile(path, source, true)));
|
|
31198
31991
|
const changed = removedRoutes + removedObservability + changes.filter(Boolean).length;
|
|
31199
31992
|
return { changed, path: project, written: [...files.keys()] };
|
|
31200
31993
|
};
|
|
31201
31994
|
var walkFiles = async (root, directory = root) => {
|
|
31202
|
-
const entries = await
|
|
31995
|
+
const entries = await readdir5(directory, { withFileTypes: true });
|
|
31203
31996
|
const nested = await Promise.all(entries.map((entry) => {
|
|
31204
|
-
const path =
|
|
31997
|
+
const path = join19(directory, entry.name);
|
|
31205
31998
|
if (entry.isDirectory())
|
|
31206
31999
|
return walkFiles(root, path);
|
|
31207
32000
|
if (entry.isFile())
|
|
@@ -31227,7 +32020,7 @@ var installStagedDirectory = async (staging, destination) => {
|
|
|
31227
32020
|
try {
|
|
31228
32021
|
await rename12(staging, destination);
|
|
31229
32022
|
if (moved)
|
|
31230
|
-
await
|
|
32023
|
+
await rm12(backup, { force: true, recursive: true });
|
|
31231
32024
|
} catch (error) {
|
|
31232
32025
|
if (moved)
|
|
31233
32026
|
await rename12(backup, destination);
|
|
@@ -31305,27 +32098,27 @@ export const materializeAbsoluteWebBundle = async () => {
|
|
|
31305
32098
|
var syncAbsoluteExpoWebAssets = async (config) => {
|
|
31306
32099
|
if (config.engine !== "expo")
|
|
31307
32100
|
throw new TypeError("Expo asset sync requires mobile.engine: expo.");
|
|
31308
|
-
const marker =
|
|
31309
|
-
if (!await
|
|
32101
|
+
const marker = join19(config.nativeProjectDirectory, EXPO_PROJECT_MARKER);
|
|
32102
|
+
if (!await exists5(marker)) {
|
|
31310
32103
|
throw new TypeError("Expo asset sync requires an AbsoluteJS-managed Expo project. Run mobile init first.");
|
|
31311
32104
|
}
|
|
31312
|
-
const manifestPath =
|
|
31313
|
-
const manifest = JSON.parse(await
|
|
32105
|
+
const manifestPath = join19(config.bundleDirectory, "absolute-mobile-manifest.json");
|
|
32106
|
+
const manifest = JSON.parse(await readFile16(manifestPath, "utf8"));
|
|
31314
32107
|
const nativeDataManifest = expoNativeDataManifest(manifest);
|
|
31315
32108
|
const { appBuild } = nativeDataManifest;
|
|
31316
32109
|
const files = await walkFiles(config.bundleDirectory);
|
|
31317
|
-
const bundleHash =
|
|
31318
|
-
const filesWithContents = await Promise.all(files.map(async (file) => ({ contents: await
|
|
32110
|
+
const bundleHash = createHash14("sha256");
|
|
32111
|
+
const filesWithContents = await Promise.all(files.map(async (file) => ({ contents: await readFile16(file), file })));
|
|
31319
32112
|
filesWithContents.forEach(({ contents, file }) => {
|
|
31320
|
-
bundleHash.update(
|
|
32113
|
+
bundleHash.update(relative12(config.bundleDirectory, file).replaceAll("\\", "/"));
|
|
31321
32114
|
bundleHash.update("\x00");
|
|
31322
32115
|
bundleHash.update(contents);
|
|
31323
32116
|
bundleHash.update("\x00");
|
|
31324
32117
|
});
|
|
31325
32118
|
const bundleId = `amexpo_${bundleHash.digest("hex")}`;
|
|
31326
|
-
const destination =
|
|
31327
|
-
await
|
|
31328
|
-
const staging = await
|
|
32119
|
+
const destination = join19(config.nativeProjectDirectory, "assets", "absolute");
|
|
32120
|
+
await mkdir13(dirname12(destination), { recursive: true });
|
|
32121
|
+
const staging = await mkdtemp9(join19(dirname12(destination), `.${basename6(destination)}.stage-`));
|
|
31329
32122
|
let assets;
|
|
31330
32123
|
let archiveAsset;
|
|
31331
32124
|
try {
|
|
@@ -31334,20 +32127,20 @@ var syncAbsoluteExpoWebAssets = async (config) => {
|
|
|
31334
32127
|
const entry = {
|
|
31335
32128
|
length: contents.byteLength,
|
|
31336
32129
|
offset,
|
|
31337
|
-
path:
|
|
32130
|
+
path: relative12(config.bundleDirectory, file).replaceAll("\\", "/")
|
|
31338
32131
|
};
|
|
31339
32132
|
offset += contents.byteLength;
|
|
31340
32133
|
return entry;
|
|
31341
32134
|
});
|
|
31342
32135
|
const name = `bundle${EXPO_ASSET_EXTENSION}`;
|
|
31343
|
-
await writeFile13(
|
|
31344
|
-
archiveAsset = portableRelative2(
|
|
32136
|
+
await writeFile13(join19(staging, name), Buffer.concat(filesWithContents.map(({ contents }) => contents)));
|
|
32137
|
+
archiveAsset = portableRelative2(join19(config.nativeProjectDirectory, "src", "generated"), join19(destination, name));
|
|
31345
32138
|
await installStagedDirectory(staging, destination);
|
|
31346
32139
|
} catch (error) {
|
|
31347
|
-
await
|
|
32140
|
+
await rm12(staging, { force: true, recursive: true });
|
|
31348
32141
|
throw error;
|
|
31349
32142
|
}
|
|
31350
|
-
const generated =
|
|
32143
|
+
const generated = join19(config.nativeProjectDirectory, "src", "generated", "webAssets.ts");
|
|
31351
32144
|
await writeManagedFile(generated, assetModuleSource(assets, archiveAsset, bundleId, nativeDataManifest), true);
|
|
31352
32145
|
return { appBuild, assets: assets.length, bundleId, path: destination };
|
|
31353
32146
|
};
|
|
@@ -31386,11 +32179,11 @@ var loadServerApp = async (producerPath) => {
|
|
|
31386
32179
|
return { app, exportName };
|
|
31387
32180
|
};
|
|
31388
32181
|
var finalizeAbsoluteMobileCompatibilityBuild = async (options) => {
|
|
31389
|
-
const buildDirectory =
|
|
32182
|
+
const buildDirectory = resolve15(options.buildDirectory);
|
|
31390
32183
|
const mobile = normalizeAbsoluteMobileConfig(options.mobile, options.projectRoot);
|
|
31391
|
-
const root =
|
|
32184
|
+
const root = join20(buildDirectory, ".absolutejs", "mobile-compatibility");
|
|
31392
32185
|
const [manifestSource, previous] = await Promise.all([
|
|
31393
|
-
|
|
32186
|
+
readFile17(join20(buildDirectory, "manifest.json"), "utf8"),
|
|
31394
32187
|
readAbsoluteMobileMaterializedReleases(root)
|
|
31395
32188
|
]);
|
|
31396
32189
|
const manifest = JSON.parse(manifestSource);
|
|
@@ -31403,11 +32196,11 @@ var finalizeAbsoluteMobileCompatibilityBuild = async (options) => {
|
|
|
31403
32196
|
process.env.ABSOLUTE_BUILD_DIR = buildDirectory;
|
|
31404
32197
|
process.env.ABSOLUTE_COMPILED_RUNTIME = "1";
|
|
31405
32198
|
if (options.configPath) {
|
|
31406
|
-
process.env.ABSOLUTE_CONFIG =
|
|
32199
|
+
process.env.ABSOLUTE_CONFIG = resolve15(options.projectRoot, options.configPath);
|
|
31407
32200
|
}
|
|
31408
32201
|
let loaded;
|
|
31409
32202
|
try {
|
|
31410
|
-
loaded = await loadServerApp(
|
|
32203
|
+
loaded = await loadServerApp(resolve15(options.producerPath));
|
|
31411
32204
|
} finally {
|
|
31412
32205
|
restoreEnvironmentVariable("ABSOLUTE_BUILD_DIR", previousBuildDirectory);
|
|
31413
32206
|
restoreEnvironmentVariable("ABSOLUTE_COMPILED_RUNTIME", previousCompiledRuntime);
|
|
@@ -31420,7 +32213,7 @@ var finalizeAbsoluteMobileCompatibilityBuild = async (options) => {
|
|
|
31420
32213
|
manifest,
|
|
31421
32214
|
previousArtifacts: previous.map(({ artifact }) => artifact),
|
|
31422
32215
|
producerExport: loaded.exportName,
|
|
31423
|
-
producerPath:
|
|
32216
|
+
producerPath: resolve15(options.producerPath),
|
|
31424
32217
|
runtime: String(ABSOLUTE_MOBILE_PAGE_PROTOCOL_VERSION)
|
|
31425
32218
|
});
|
|
31426
32219
|
const {
|
|
@@ -31819,21 +32612,21 @@ var parseAbsoluteExpoBridgeMessage = (source) => {
|
|
|
31819
32612
|
};
|
|
31820
32613
|
// src/mobile/expoCodeSigning.ts
|
|
31821
32614
|
var import_code_signing_certificates = __toESM(require_main(), 1);
|
|
31822
|
-
import { access as
|
|
31823
|
-
import { dirname as
|
|
31824
|
-
var
|
|
31825
|
-
var
|
|
31826
|
-
const location2 =
|
|
31827
|
-
return location2 === "" || location2 !== ".." && !location2.startsWith(`..${
|
|
32615
|
+
import { access as access13, mkdir as mkdir14, writeFile as writeFile14 } from "fs/promises";
|
|
32616
|
+
import { dirname as dirname13, isAbsolute as isAbsolute8, relative as relative13, resolve as resolve16, sep as sep9 } from "path";
|
|
32617
|
+
var exists6 = async (path) => access13(path).then(() => true).catch(() => false);
|
|
32618
|
+
var inside3 = (root, path) => {
|
|
32619
|
+
const location2 = relative13(root, path);
|
|
32620
|
+
return location2 === "" || location2 !== ".." && !location2.startsWith(`..${sep9}`) && !isAbsolute8(location2);
|
|
31828
32621
|
};
|
|
31829
32622
|
var generateAbsoluteExpoCodeSigning = async (options) => {
|
|
31830
|
-
const root =
|
|
31831
|
-
const certificatePath =
|
|
31832
|
-
const privateKeyPath =
|
|
31833
|
-
const publicKeyPath =
|
|
31834
|
-
if (!
|
|
32623
|
+
const root = resolve16(options.projectRoot);
|
|
32624
|
+
const certificatePath = resolve16(root, options.certificatePath);
|
|
32625
|
+
const privateKeyPath = resolve16(root, options.privateKeyPath);
|
|
32626
|
+
const publicKeyPath = resolve16(root, options.publicKeyPath ?? resolve16(dirname13(privateKeyPath), "public-key.pem"));
|
|
32627
|
+
if (!inside3(root, certificatePath))
|
|
31835
32628
|
throw new TypeError("Expo code-signing certificate must be written inside the project so store builds can embed it.");
|
|
31836
|
-
if (
|
|
32629
|
+
if (inside3(root, privateKeyPath) || inside3(root, publicKeyPath))
|
|
31837
32630
|
throw new TypeError("Expo code-signing private/public key output must remain outside the project and source control.");
|
|
31838
32631
|
const commonName = options.commonName.trim();
|
|
31839
32632
|
if (!commonName || commonName.length > 64)
|
|
@@ -31842,7 +32635,7 @@ var generateAbsoluteExpoCodeSigning = async (options) => {
|
|
|
31842
32635
|
if (!Number.isSafeInteger(validityYears) || validityYears < 1 || validityYears > 20)
|
|
31843
32636
|
throw new TypeError("Expo code-signing validity must be an integer from 1 through 20 years.");
|
|
31844
32637
|
const collisions = (await Promise.all([certificatePath, privateKeyPath, publicKeyPath].map(async (path) => ({
|
|
31845
|
-
exists: await
|
|
32638
|
+
exists: await exists6(path),
|
|
31846
32639
|
path
|
|
31847
32640
|
})))).filter((entry) => entry.exists);
|
|
31848
32641
|
if (collisions.length > 0)
|
|
@@ -31860,7 +32653,7 @@ var generateAbsoluteExpoCodeSigning = async (options) => {
|
|
|
31860
32653
|
import_code_signing_certificates.validateSelfSignedCertificate(certificate, keyPair);
|
|
31861
32654
|
const { privateKeyPEM, publicKeyPEM } = import_code_signing_certificates.convertKeyPairToPEM(keyPair);
|
|
31862
32655
|
const certificatePem = import_code_signing_certificates.convertCertificateToCertificatePEM(certificate);
|
|
31863
|
-
await Promise.all([certificatePath, privateKeyPath, publicKeyPath].map((path) =>
|
|
32656
|
+
await Promise.all([certificatePath, privateKeyPath, publicKeyPath].map((path) => mkdir14(dirname13(path), { recursive: true })));
|
|
31864
32657
|
await Promise.all([
|
|
31865
32658
|
writeFile14(certificatePath, certificatePem, { flag: "wx", mode: 420 }),
|
|
31866
32659
|
writeFile14(privateKeyPath, privateKeyPEM, { flag: "wx", mode: 384 }),
|
|
@@ -31966,9 +32759,9 @@ var parseAbsoluteAndroidAccessibilityHierarchy = (source) => [...source.matchAll
|
|
|
31966
32759
|
});
|
|
31967
32760
|
// src/mobile/expoNativeWatcher.ts
|
|
31968
32761
|
import { watch as watch2 } from "fs";
|
|
31969
|
-
import { access as
|
|
31970
|
-
import { basename as
|
|
31971
|
-
import { createHash as
|
|
32762
|
+
import { access as access14, readdir as readdir6, readFile as readFile18 } from "fs/promises";
|
|
32763
|
+
import { basename as basename7, join as join21, relative as relative14 } from "path";
|
|
32764
|
+
import { createHash as createHash15 } from "crypto";
|
|
31972
32765
|
var NATIVE_CHANGE_DEBOUNCE_MS2 = 500;
|
|
31973
32766
|
var ROOT_NATIVE_INPUTS2 = new Set([
|
|
31974
32767
|
"absolute.config.js",
|
|
@@ -31982,13 +32775,13 @@ var ROOT_NATIVE_INPUTS2 = new Set([
|
|
|
31982
32775
|
"package.json"
|
|
31983
32776
|
]);
|
|
31984
32777
|
var EXPO_NATIVE_DIRECTORIES = ["modules", "plugins"];
|
|
31985
|
-
var
|
|
32778
|
+
var exists7 = async (path) => access14(path).then(() => true, () => false);
|
|
31986
32779
|
var filesIn = async (directory, prefix) => {
|
|
31987
|
-
if (!await
|
|
32780
|
+
if (!await exists7(directory))
|
|
31988
32781
|
return [];
|
|
31989
|
-
const entries = await
|
|
32782
|
+
const entries = await readdir6(directory, { withFileTypes: true });
|
|
31990
32783
|
const nested = await Promise.all(entries.map((entry) => {
|
|
31991
|
-
const path =
|
|
32784
|
+
const path = join21(directory, entry.name);
|
|
31992
32785
|
const name = `${prefix}/${entry.name}`;
|
|
31993
32786
|
if (entry.isDirectory())
|
|
31994
32787
|
return filesIn(path, name);
|
|
@@ -31997,21 +32790,21 @@ var filesIn = async (directory, prefix) => {
|
|
|
31997
32790
|
return nested.flat().sort((left, right) => left.name.localeCompare(right.name));
|
|
31998
32791
|
};
|
|
31999
32792
|
var fingerprintAbsoluteExpoNativeInputs = async (options) => {
|
|
32000
|
-
const hash =
|
|
32793
|
+
const hash = createHash15("sha256");
|
|
32001
32794
|
const rootFiles = await Promise.all([...ROOT_NATIVE_INPUTS2].sort().map(async (name) => {
|
|
32002
|
-
const path =
|
|
32003
|
-
return await
|
|
32795
|
+
const path = join21(options.projectRoot, name);
|
|
32796
|
+
return await exists7(path) ? [{ name: `root/${name}`, path }] : [];
|
|
32004
32797
|
}));
|
|
32005
|
-
const nativeFiles = await Promise.all(EXPO_NATIVE_DIRECTORIES.map((name) => filesIn(
|
|
32798
|
+
const nativeFiles = await Promise.all(EXPO_NATIVE_DIRECTORIES.map((name) => filesIn(join21(options.expoProjectDirectory, name), name)));
|
|
32006
32799
|
const files = [...rootFiles.flat(), ...nativeFiles.flat()].sort((left, right) => left.name.localeCompare(right.name));
|
|
32007
|
-
const contents = await Promise.all(files.map(({ path }) =>
|
|
32800
|
+
const contents = await Promise.all(files.map(({ path }) => readFile18(path)));
|
|
32008
32801
|
files.forEach(({ name }, index) => {
|
|
32009
32802
|
hash.update(name);
|
|
32010
32803
|
hash.update(contents[index] ?? Buffer.alloc(0));
|
|
32011
32804
|
});
|
|
32012
32805
|
return hash.digest("hex");
|
|
32013
32806
|
};
|
|
32014
|
-
var isAbsoluteExpoNativeRootInput = (path) => ROOT_NATIVE_INPUTS2.has(
|
|
32807
|
+
var isAbsoluteExpoNativeRootInput = (path) => ROOT_NATIVE_INPUTS2.has(basename7(path));
|
|
32015
32808
|
var createAbsoluteExpoNativeWatcher = async (options) => {
|
|
32016
32809
|
let fingerprint = await fingerprintAbsoluteExpoNativeInputs(options);
|
|
32017
32810
|
let closed = false;
|
|
@@ -32073,14 +32866,14 @@ var createAbsoluteExpoNativeWatcher = async (options) => {
|
|
|
32073
32866
|
}
|
|
32074
32867
|
};
|
|
32075
32868
|
const nativeDirectories = (await Promise.all(EXPO_NATIVE_DIRECTORIES.map(async (name) => {
|
|
32076
|
-
const directory =
|
|
32077
|
-
return await
|
|
32869
|
+
const directory = join21(options.expoProjectDirectory, name);
|
|
32870
|
+
return await exists7(directory) ? [directory] : [];
|
|
32078
32871
|
}))).flat();
|
|
32079
32872
|
nativeDirectories.forEach((directory) => {
|
|
32080
32873
|
watchers.push(watch2(directory, { recursive: true }, (_event, filename) => {
|
|
32081
32874
|
if (!filename)
|
|
32082
32875
|
return;
|
|
32083
|
-
record(
|
|
32876
|
+
record(relative14(options.expoProjectDirectory, join21(directory, String(filename))), false);
|
|
32084
32877
|
}));
|
|
32085
32878
|
});
|
|
32086
32879
|
watchers.push(watch2(options.projectRoot, (_event, filename) => {
|
|
@@ -32095,8 +32888,8 @@ var createAbsoluteExpoNativeWatcher = async (options) => {
|
|
|
32095
32888
|
return { close };
|
|
32096
32889
|
};
|
|
32097
32890
|
// src/mobile/expoUpdate.ts
|
|
32098
|
-
import { access as
|
|
32099
|
-
import { dirname as
|
|
32891
|
+
import { access as access15, mkdir as mkdir15, readFile as readFile19, writeFile as writeFile15 } from "fs/promises";
|
|
32892
|
+
import { dirname as dirname14, extname as extname4, join as join22 } from "path";
|
|
32100
32893
|
var ABSOLUTE_EXPO_UPDATE_DESCRIPTOR = "_absolute/expo-update.json";
|
|
32101
32894
|
var ABSOLUTE_EXPO_UPDATE_FORMAT = 1;
|
|
32102
32895
|
var object4 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
@@ -32162,7 +32955,7 @@ var parseAbsoluteExpoUpdateDescriptor = (value) => {
|
|
|
32162
32955
|
};
|
|
32163
32956
|
};
|
|
32164
32957
|
var finalizeAbsoluteExpoUpdateExport = async (options) => {
|
|
32165
|
-
const metadata = JSON.parse(await
|
|
32958
|
+
const metadata = JSON.parse(await readFile19(join22(options.exportDirectory, "metadata.json"), "utf8"));
|
|
32166
32959
|
if (!object4(metadata) || !object4(metadata.fileMetadata))
|
|
32167
32960
|
throw new TypeError("Expo export metadata.json is invalid.");
|
|
32168
32961
|
const descriptor = parseAbsoluteExpoUpdateDescriptor({
|
|
@@ -32173,11 +32966,11 @@ var finalizeAbsoluteExpoUpdateExport = async (options) => {
|
|
|
32173
32966
|
runtimeVersion: options.runtimeVersion
|
|
32174
32967
|
});
|
|
32175
32968
|
const referenced = Object.values(descriptor.platforms).flatMap((entry) => entry ? [entry.launchAsset, ...entry.assets] : []);
|
|
32176
|
-
await Promise.all(referenced.map(({ path }) =>
|
|
32969
|
+
await Promise.all(referenced.map(({ path }) => access15(join22(options.exportDirectory, path)).catch(() => {
|
|
32177
32970
|
throw new TypeError(`Expo export metadata references missing asset ${path}.`);
|
|
32178
32971
|
})));
|
|
32179
|
-
const destination =
|
|
32180
|
-
await
|
|
32972
|
+
const destination = join22(options.exportDirectory, ABSOLUTE_EXPO_UPDATE_DESCRIPTOR);
|
|
32973
|
+
await mkdir15(dirname14(destination), { recursive: true });
|
|
32181
32974
|
await writeFile15(destination, `${JSON.stringify(descriptor, null, "\t")}
|
|
32182
32975
|
`);
|
|
32183
32976
|
return { descriptor, path: destination };
|
|
@@ -32188,8 +32981,8 @@ init_config();
|
|
|
32188
32981
|
|
|
32189
32982
|
// src/mobile/ciWorkflow.ts
|
|
32190
32983
|
import { existsSync as existsSync4 } from "fs";
|
|
32191
|
-
import { access as
|
|
32192
|
-
import { dirname as
|
|
32984
|
+
import { access as access16, mkdir as mkdir16, readFile as readFile20, writeFile as writeFile16 } from "fs/promises";
|
|
32985
|
+
import { dirname as dirname15, extname as extname5, relative as relative15, resolve as resolve17, sep as sep10 } from "path";
|
|
32193
32986
|
var ABSOLUTE_MOBILE_CI_WORKFLOW_FORMAT = 1;
|
|
32194
32987
|
var SECRET_NAME_PATTERN = /^[A-Z][A-Z0-9_]*$/u;
|
|
32195
32988
|
var CI_ENV_INDENTATION = 6;
|
|
@@ -32208,9 +33001,9 @@ var RESERVED_SECRET_NAMES = new Set([
|
|
|
32208
33001
|
"APP_STORE_CONNECT_KEY_ID",
|
|
32209
33002
|
"APP_STORE_CONNECT_PRIVATE_KEY_BASE64"
|
|
32210
33003
|
]);
|
|
32211
|
-
var
|
|
33004
|
+
var exists8 = async (path) => {
|
|
32212
33005
|
try {
|
|
32213
|
-
await
|
|
33006
|
+
await access16(path);
|
|
32214
33007
|
return true;
|
|
32215
33008
|
} catch {
|
|
32216
33009
|
return false;
|
|
@@ -32218,10 +33011,10 @@ var exists7 = async (path) => {
|
|
|
32218
33011
|
};
|
|
32219
33012
|
var yamlString = (value) => `'${value.replaceAll("'", "''")}'`;
|
|
32220
33013
|
var projectPath = (projectRoot, value, field2, options = {}) => {
|
|
32221
|
-
const root =
|
|
32222
|
-
const path =
|
|
32223
|
-
const portable =
|
|
32224
|
-
if (portable === ".." || portable.startsWith(`..${
|
|
33014
|
+
const root = resolve17(projectRoot);
|
|
33015
|
+
const path = resolve17(root, value);
|
|
33016
|
+
const portable = relative15(root, path).replaceAll("\\", "/");
|
|
33017
|
+
if (portable === ".." || portable.startsWith(`..${sep10}`) || portable.startsWith("../") || portable === "") {
|
|
32225
33018
|
throw new TypeError(`${field2} must remain inside the project root.`);
|
|
32226
33019
|
}
|
|
32227
33020
|
if (/\r|\n/u.test(portable) || portable.startsWith("-"))
|
|
@@ -32231,11 +33024,11 @@ var projectPath = (projectRoot, value, field2, options = {}) => {
|
|
|
32231
33024
|
return portable;
|
|
32232
33025
|
};
|
|
32233
33026
|
var workflowOutputPath = (projectRoot, value) => {
|
|
32234
|
-
const root =
|
|
32235
|
-
const workflows =
|
|
32236
|
-
const path =
|
|
32237
|
-
const portable =
|
|
32238
|
-
if (portable === ".." || portable.startsWith(`..${
|
|
33027
|
+
const root = resolve17(projectRoot);
|
|
33028
|
+
const workflows = resolve17(root, ".github/workflows");
|
|
33029
|
+
const path = resolve17(root, value ?? ".github/workflows/absolute-mobile.yml");
|
|
33030
|
+
const portable = relative15(workflows, path);
|
|
33031
|
+
if (portable === ".." || portable.startsWith(`..${sep10}`) || extname5(path) !== ".yml" && extname5(path) !== ".yaml") {
|
|
32239
33032
|
throw new TypeError("mobile ci github --output must be a .yml or .yaml file inside .github/workflows.");
|
|
32240
33033
|
}
|
|
32241
33034
|
return path;
|
|
@@ -32664,11 +33457,11 @@ ${bundleAuditSteps}${platforms.includes("android") ? androidJob({ customSecrets,
|
|
|
32664
33457
|
var writeAbsoluteMobileGithubWorkflow = async (options) => {
|
|
32665
33458
|
const path = workflowOutputPath(options.projectRoot, options.outputPath);
|
|
32666
33459
|
const generated = createAbsoluteMobileGithubWorkflow(options);
|
|
32667
|
-
const previous = await
|
|
33460
|
+
const previous = await exists8(path) ? await readFile20(path, "utf8") : undefined;
|
|
32668
33461
|
if (previous !== undefined && previous !== generated.workflow && !options.force)
|
|
32669
|
-
throw new TypeError(`${
|
|
33462
|
+
throw new TypeError(`${relative15(options.projectRoot, path)} already exists and differs. Rerun with --force to replace the generated workflow.`);
|
|
32670
33463
|
if (previous !== generated.workflow) {
|
|
32671
|
-
await
|
|
33464
|
+
await mkdir16(dirname15(path), { recursive: true });
|
|
32672
33465
|
await writeFile16(path, generated.workflow);
|
|
32673
33466
|
}
|
|
32674
33467
|
return {
|
|
@@ -32687,15 +33480,15 @@ init_materializedBundle();
|
|
|
32687
33480
|
init_mobilePreview();
|
|
32688
33481
|
|
|
32689
33482
|
// src/mobile/nativeDeepLinks.ts
|
|
32690
|
-
import { readFile as
|
|
32691
|
-
import { join as
|
|
33483
|
+
import { readFile as readFile21, rename as rename13, writeFile as writeFile17 } from "fs/promises";
|
|
33484
|
+
import { join as join25 } from "path";
|
|
32692
33485
|
var START_MARKER = "<!-- absolutejs:deep-links:start -->";
|
|
32693
33486
|
var END_MARKER = "<!-- absolutejs:deep-links:end -->";
|
|
32694
33487
|
var IOS_ENTITLEMENTS = "App/AbsoluteJS.entitlements";
|
|
32695
33488
|
var NOT_FOUND = -1;
|
|
32696
33489
|
var escapeXml = (value) => value.replaceAll("&", "&").replaceAll('"', """).replaceAll("'", "'").replaceAll("<", "<").replaceAll(">", ">");
|
|
32697
33490
|
var writeChangedFile = async (path, source) => {
|
|
32698
|
-
const current = await
|
|
33491
|
+
const current = await readFile21(path, "utf8");
|
|
32699
33492
|
if (current === source)
|
|
32700
33493
|
return false;
|
|
32701
33494
|
const temporary = `${path}.${crypto.randomUUID()}.tmp`;
|
|
@@ -32745,8 +33538,8 @@ ${hosts}
|
|
|
32745
33538
|
`;
|
|
32746
33539
|
};
|
|
32747
33540
|
var configureAndroid = async (config) => {
|
|
32748
|
-
const path =
|
|
32749
|
-
const source = await
|
|
33541
|
+
const path = join25(config.nativeProjectDirectory, "android/app/src/main/AndroidManifest.xml");
|
|
33542
|
+
const source = await readFile21(path, "utf8");
|
|
32750
33543
|
const mainActivity = source.indexOf('android:name=".MainActivity"');
|
|
32751
33544
|
if (mainActivity === NOT_FOUND) {
|
|
32752
33545
|
throw new TypeError("Android MainActivity was not found.");
|
|
@@ -32771,8 +33564,8 @@ var iosSchemeRegion = (scheme) => ` ${START_MARKER}
|
|
|
32771
33564
|
${END_MARKER}
|
|
32772
33565
|
`;
|
|
32773
33566
|
var configureIosInfo = async (config) => {
|
|
32774
|
-
const path =
|
|
32775
|
-
const source = await
|
|
33567
|
+
const path = join25(config.nativeProjectDirectory, "ios/App/App/Info.plist");
|
|
33568
|
+
const source = await readFile21(path, "utf8");
|
|
32776
33569
|
const region = config.deepLinkScheme ? iosSchemeRegion(config.deepLinkScheme) : ` ${START_MARKER}
|
|
32777
33570
|
${END_MARKER}
|
|
32778
33571
|
`;
|
|
@@ -32795,10 +33588,10 @@ ${domains}
|
|
|
32795
33588
|
`;
|
|
32796
33589
|
};
|
|
32797
33590
|
var configureIosEntitlements = async (config) => {
|
|
32798
|
-
const path =
|
|
33591
|
+
const path = join25(config.nativeProjectDirectory, "ios/App/AbsoluteJS.entitlements");
|
|
32799
33592
|
let current = "";
|
|
32800
33593
|
try {
|
|
32801
|
-
current = await
|
|
33594
|
+
current = await readFile21(path, "utf8");
|
|
32802
33595
|
} catch (error) {
|
|
32803
33596
|
if (!(error instanceof Error) || !("code" in error) || error.code !== "ENOENT") {
|
|
32804
33597
|
throw error;
|
|
@@ -32813,8 +33606,8 @@ var configureIosEntitlements = async (config) => {
|
|
|
32813
33606
|
return true;
|
|
32814
33607
|
};
|
|
32815
33608
|
var configureIosProject = async (config) => {
|
|
32816
|
-
const path =
|
|
32817
|
-
const source = await
|
|
33609
|
+
const path = join25(config.nativeProjectDirectory, "ios/App/App.xcodeproj/project.pbxproj");
|
|
33610
|
+
const source = await readFile21(path, "utf8");
|
|
32818
33611
|
const declarations = [
|
|
32819
33612
|
...source.matchAll(/CODE_SIGN_ENTITLEMENTS = ([^;]+);/g)
|
|
32820
33613
|
].map((match) => match[1]);
|
|
@@ -32853,8 +33646,8 @@ var applyAbsoluteNativeDeepLinks = async (config, platforms = config.platforms)
|
|
|
32853
33646
|
};
|
|
32854
33647
|
// src/mobile/nativeDeviceCapabilities.ts
|
|
32855
33648
|
init_deviceCapabilities();
|
|
32856
|
-
import { readFile as
|
|
32857
|
-
import { join as
|
|
33649
|
+
import { readFile as readFile22, rename as rename14, writeFile as writeFile18 } from "fs/promises";
|
|
33650
|
+
import { join as join26 } from "path";
|
|
32858
33651
|
var START_MARKER2 = "<!-- absolutejs:device-capabilities:start -->";
|
|
32859
33652
|
var END_MARKER2 = "<!-- absolutejs:device-capabilities:end -->";
|
|
32860
33653
|
var NOT_FOUND2 = -1;
|
|
@@ -32864,7 +33657,7 @@ var PUSH_START_MARKER = "absolutejs:push-notifications:start";
|
|
|
32864
33657
|
var PUSH_END_MARKER = "absolutejs:push-notifications:end";
|
|
32865
33658
|
var escapeXml2 = (value) => value.replaceAll("&", "&").replaceAll('"', """).replaceAll("'", "'").replaceAll("<", "<").replaceAll(">", ">");
|
|
32866
33659
|
var writeChangedFile2 = async (path, source) => {
|
|
32867
|
-
const current = await
|
|
33660
|
+
const current = await readFile22(path, "utf8");
|
|
32868
33661
|
if (current === source)
|
|
32869
33662
|
return false;
|
|
32870
33663
|
const temporary = `${path}.${crypto.randomUUID()}.tmp`;
|
|
@@ -32884,7 +33677,7 @@ var writeOptionalChangedFile = async (path, source) => {
|
|
|
32884
33677
|
};
|
|
32885
33678
|
var optionalSource = async (path) => {
|
|
32886
33679
|
try {
|
|
32887
|
-
return await
|
|
33680
|
+
return await readFile22(path, "utf8");
|
|
32888
33681
|
} catch (error) {
|
|
32889
33682
|
if (typeof error === "object" && error !== null && Reflect.get(error, "code") === "ENOENT")
|
|
32890
33683
|
return null;
|
|
@@ -33004,8 +33797,8 @@ var writeIosPrivacyManifest = async (path, current, source) => {
|
|
|
33004
33797
|
var configureIosPrivacyProject = async (config, requirements) => {
|
|
33005
33798
|
if (requirements.iosPrivacyAccessedApis.length === 0)
|
|
33006
33799
|
return false;
|
|
33007
|
-
const projectPath2 =
|
|
33008
|
-
const project = await
|
|
33800
|
+
const projectPath2 = join26(config.nativeProjectDirectory, "ios/App/App.xcodeproj/project.pbxproj");
|
|
33801
|
+
const project = await readFile22(projectPath2, "utf8");
|
|
33009
33802
|
return writeChangedFile2(projectPath2, addIosPrivacyProjectReference(project));
|
|
33010
33803
|
};
|
|
33011
33804
|
var addIosPrivacyProjectReference = (source) => {
|
|
@@ -33057,8 +33850,8 @@ ${next.slice(index)}`;
|
|
|
33057
33850
|
return next;
|
|
33058
33851
|
};
|
|
33059
33852
|
var configureIos2 = async (config, plan) => {
|
|
33060
|
-
const path =
|
|
33061
|
-
const source = await
|
|
33853
|
+
const path = join26(config.nativeProjectDirectory, "ios/App/App/Info.plist");
|
|
33854
|
+
const source = await readFile22(path, "utf8");
|
|
33062
33855
|
const requirements = absoluteDeviceNativeRequirements(plan);
|
|
33063
33856
|
const existingSystemBars = source.match(/<key>UIViewControllerBasedStatusBarAppearance<\/key>\s*<(true|false)\s*\/>/u);
|
|
33064
33857
|
const ownedStart = source.indexOf(START_MARKER2);
|
|
@@ -33078,7 +33871,7 @@ ${content}
|
|
|
33078
33871
|
${END_MARKER2}
|
|
33079
33872
|
` : "";
|
|
33080
33873
|
const infoChanged = await writeChangedFile2(path, managed(source, region, source.lastIndexOf("</dict>")));
|
|
33081
|
-
const privacyPath =
|
|
33874
|
+
const privacyPath = join26(config.nativeProjectDirectory, "ios/App/App/PrivacyInfo.xcprivacy");
|
|
33082
33875
|
const privacyCurrent = await optionalSource(privacyPath);
|
|
33083
33876
|
const privacySource = privacyManifestSource(privacyCurrent, requirements);
|
|
33084
33877
|
const [privacyChanged, projectChanged, pushChanged] = await Promise.all([
|
|
@@ -33089,7 +33882,7 @@ ${content}
|
|
|
33089
33882
|
return infoChanged || privacyChanged || projectChanged || pushChanged;
|
|
33090
33883
|
};
|
|
33091
33884
|
var configureIosPushNotifications = async (config, enabled) => {
|
|
33092
|
-
const entitlementsPath =
|
|
33885
|
+
const entitlementsPath = join26(config.nativeProjectDirectory, "ios/App/AbsoluteJS.entitlements");
|
|
33093
33886
|
const entitlements = await optionalSource(entitlementsPath);
|
|
33094
33887
|
if (entitlements === null && !enabled)
|
|
33095
33888
|
return false;
|
|
@@ -33101,7 +33894,7 @@ var configureIosPushNotifications = async (config, enabled) => {
|
|
|
33101
33894
|
<!-- ${PUSH_END_MARKER} -->
|
|
33102
33895
|
` : "";
|
|
33103
33896
|
const nextEntitlements = replacePushRegion(entitlements, entitlementRegion, entitlements.lastIndexOf("</dict>"));
|
|
33104
|
-
const delegatePath =
|
|
33897
|
+
const delegatePath = join26(config.nativeProjectDirectory, "ios/App/App/AppDelegate.swift");
|
|
33105
33898
|
const delegate = await optionalSource(delegatePath);
|
|
33106
33899
|
if (delegate === null && !enabled)
|
|
33107
33900
|
return false;
|
|
@@ -33150,8 +33943,8 @@ var replacePushRegion = (source, region, insertion) => {
|
|
|
33150
33943
|
return `${source.slice(0, insertion)}${region}${source.slice(insertion)}`;
|
|
33151
33944
|
};
|
|
33152
33945
|
var configureAndroid2 = async (config, plan) => {
|
|
33153
|
-
const path =
|
|
33154
|
-
const source = await
|
|
33946
|
+
const path = join26(config.nativeProjectDirectory, "android/app/src/main/AndroidManifest.xml");
|
|
33947
|
+
const source = await readFile22(path, "utf8");
|
|
33155
33948
|
const permissions = absoluteDeviceNativeRequirements(plan).androidPermissions;
|
|
33156
33949
|
const content = permissions.map((permission) => ` <uses-permission android:name="${escapeXml2(permission)}" />`).join(`
|
|
33157
33950
|
`);
|
|
@@ -33186,7 +33979,7 @@ ${content}
|
|
|
33186
33979
|
throw new TypeError(`Android google-services.json does not contain package ${config.appId}.`);
|
|
33187
33980
|
const [manifestChanged, firebaseChanged] = await Promise.all([
|
|
33188
33981
|
writeChangedFile2(path, nextManifest),
|
|
33189
|
-
writeOptionalChangedFile(
|
|
33982
|
+
writeOptionalChangedFile(join26(config.nativeProjectDirectory, "android/app/google-services.json"), firebaseSource)
|
|
33190
33983
|
]);
|
|
33191
33984
|
return manifestChanged || firebaseChanged;
|
|
33192
33985
|
};
|
|
@@ -33205,14 +33998,14 @@ init_nativeAuth();
|
|
|
33205
33998
|
|
|
33206
33999
|
// src/mobile/nativeUpdates.ts
|
|
33207
34000
|
import {
|
|
33208
|
-
mkdir as
|
|
33209
|
-
readFile as
|
|
33210
|
-
readdir as
|
|
34001
|
+
mkdir as mkdir17,
|
|
34002
|
+
readFile as readFile23,
|
|
34003
|
+
readdir as readdir7,
|
|
33211
34004
|
rename as rename15,
|
|
33212
|
-
rm as
|
|
34005
|
+
rm as rm13,
|
|
33213
34006
|
writeFile as writeFile19
|
|
33214
34007
|
} from "fs/promises";
|
|
33215
|
-
import { dirname as
|
|
34008
|
+
import { dirname as dirname17, join as join27 } from "path";
|
|
33216
34009
|
var START = "// absolutejs:mobile-updates:start";
|
|
33217
34010
|
var END = "// absolutejs:mobile-updates:end";
|
|
33218
34011
|
var PLUGIN_START = "// absolutejs:mobile-update-plugin:start";
|
|
@@ -33220,7 +34013,7 @@ var PLUGIN_END = "// absolutejs:mobile-update-plugin:end";
|
|
|
33220
34013
|
var ANDROID_PLUGIN = "AbsoluteMobileUpdateWatchdogPlugin.java";
|
|
33221
34014
|
var optionalSource2 = async (path) => {
|
|
33222
34015
|
try {
|
|
33223
|
-
return await
|
|
34016
|
+
return await readFile23(path, "utf8");
|
|
33224
34017
|
} catch (error) {
|
|
33225
34018
|
if (typeof error === "object" && error !== null && Reflect.get(error, "code") === "ENOENT")
|
|
33226
34019
|
return null;
|
|
@@ -33232,7 +34025,7 @@ var writeChanged = async (path, source) => {
|
|
|
33232
34025
|
const current = await optionalSource2(path);
|
|
33233
34026
|
if (current === source)
|
|
33234
34027
|
return false;
|
|
33235
|
-
await
|
|
34028
|
+
await mkdir17(dirname17(path), { recursive: true });
|
|
33236
34029
|
if (current === null) {
|
|
33237
34030
|
await writeFile19(path, source, { flag: "wx" });
|
|
33238
34031
|
return true;
|
|
@@ -33245,7 +34038,7 @@ var writeChanged = async (path, source) => {
|
|
|
33245
34038
|
var removeOwnedFile = async (path) => {
|
|
33246
34039
|
if (await optionalSource2(path) === null)
|
|
33247
34040
|
return false;
|
|
33248
|
-
await
|
|
34041
|
+
await rm13(path);
|
|
33249
34042
|
return true;
|
|
33250
34043
|
};
|
|
33251
34044
|
var replaceMarkedRegion = (source, start, end, region, insertion, error) => {
|
|
@@ -33382,9 +34175,9 @@ public final class AbsoluteMobileUpdateWatchdogPlugin: CAPPlugin, CAPBridgedPlug
|
|
|
33382
34175
|
${PLUGIN_END}
|
|
33383
34176
|
`;
|
|
33384
34177
|
var configureIos3 = async (config, enabled) => {
|
|
33385
|
-
const path =
|
|
33386
|
-
const capacitorConfigPath =
|
|
33387
|
-
let source = await
|
|
34178
|
+
const path = join27(config.nativeProjectDirectory, "ios/App/App/AppDelegate.swift");
|
|
34179
|
+
const capacitorConfigPath = join27(config.nativeProjectDirectory, "ios/App/App/capacitor.config.json");
|
|
34180
|
+
let source = await readFile23(path, "utf8");
|
|
33388
34181
|
const launch2 = source.indexOf("didFinishLaunchingWithOptions");
|
|
33389
34182
|
const brace = launch2 < 0 ? -1 : source.indexOf("{", launch2);
|
|
33390
34183
|
const launchRegion = enabled ? ` ${START}
|
|
@@ -33395,7 +34188,7 @@ var configureIos3 = async (config, enabled) => {
|
|
|
33395
34188
|
`, brace) + 1, "Could not find a safe iOS location for mobile update recovery.");
|
|
33396
34189
|
const plugin = enabled ? iosPluginRegion(config.updates?.bootTimeoutMs ?? 20000) : "";
|
|
33397
34190
|
source = replaceMarkedRegion(source, PLUGIN_START, PLUGIN_END, plugin, source.length, "Could not find a safe iOS location for the mobile update watchdog.");
|
|
33398
|
-
const capacitorConfigSource2 = await
|
|
34191
|
+
const capacitorConfigSource2 = await readFile23(capacitorConfigPath, "utf8");
|
|
33399
34192
|
let capacitorConfig;
|
|
33400
34193
|
try {
|
|
33401
34194
|
const value = JSON.parse(capacitorConfigSource2);
|
|
@@ -33568,19 +34361,19 @@ public final class AbsoluteMobileUpdateWatchdogPlugin extends Plugin {
|
|
|
33568
34361
|
var androidActivityInRoot = async (root) => {
|
|
33569
34362
|
let entries;
|
|
33570
34363
|
try {
|
|
33571
|
-
entries = await
|
|
34364
|
+
entries = await readdir7(root, { recursive: true });
|
|
33572
34365
|
} catch (error) {
|
|
33573
34366
|
if (typeof error === "object" && error !== null && Reflect.get(error, "code") === "ENOENT")
|
|
33574
34367
|
return;
|
|
33575
34368
|
throw error;
|
|
33576
34369
|
}
|
|
33577
34370
|
const candidate = entries.find((entry) => entry.endsWith("/MainActivity.java") || entry.endsWith("/MainActivity.kt") || entry === "MainActivity.java" || entry === "MainActivity.kt");
|
|
33578
|
-
return candidate ?
|
|
34371
|
+
return candidate ? join27(root, candidate) : undefined;
|
|
33579
34372
|
};
|
|
33580
34373
|
var androidActivity = async (config) => {
|
|
33581
34374
|
const roots = [
|
|
33582
|
-
|
|
33583
|
-
|
|
34375
|
+
join27(config.nativeProjectDirectory, "android/app/src/main/java"),
|
|
34376
|
+
join27(config.nativeProjectDirectory, "android/app/src/main/kotlin")
|
|
33584
34377
|
];
|
|
33585
34378
|
const candidates = await Promise.all(roots.map(androidActivityInRoot));
|
|
33586
34379
|
const candidate = candidates.find((value) => value !== undefined);
|
|
@@ -33679,12 +34472,12 @@ var injectAndroidActivity = (source, enabled) => {
|
|
|
33679
34472
|
};
|
|
33680
34473
|
var configureAndroid3 = async (config, enabled) => {
|
|
33681
34474
|
const activityPath = await androidActivity(config);
|
|
33682
|
-
const activity = await
|
|
34475
|
+
const activity = await readFile23(activityPath, "utf8");
|
|
33683
34476
|
const packageName = activity.match(/^\s*package\s+([A-Za-z0-9_.]+)\s*[;\n]/mu)?.[1];
|
|
33684
34477
|
if (!packageName)
|
|
33685
34478
|
throw new TypeError("Android MainActivity package declaration was not found.");
|
|
33686
34479
|
const packagePath = packageName.replaceAll(".", "/");
|
|
33687
|
-
const pluginPath =
|
|
34480
|
+
const pluginPath = join27(config.nativeProjectDirectory, "android/app/src/main/java", packagePath, ANDROID_PLUGIN);
|
|
33688
34481
|
const changed = await Promise.all([
|
|
33689
34482
|
writeChanged(activityPath, injectAndroidActivity(activity, enabled)),
|
|
33690
34483
|
enabled ? writeChanged(pluginPath, androidPluginSource(packageName, config.updates?.bootTimeoutMs ?? 20000)) : removeOwnedFile(pluginPath)
|
|
@@ -33704,14 +34497,14 @@ var applyAbsoluteNativeUpdates = async (config, platforms = config.platforms) =>
|
|
|
33704
34497
|
};
|
|
33705
34498
|
// src/mobile/nativeObservability.ts
|
|
33706
34499
|
import {
|
|
33707
|
-
mkdir as
|
|
33708
|
-
readFile as
|
|
33709
|
-
readdir as
|
|
34500
|
+
mkdir as mkdir18,
|
|
34501
|
+
readFile as readFile24,
|
|
34502
|
+
readdir as readdir8,
|
|
33710
34503
|
rename as rename16,
|
|
33711
|
-
rm as
|
|
34504
|
+
rm as rm14,
|
|
33712
34505
|
writeFile as writeFile20
|
|
33713
34506
|
} from "fs/promises";
|
|
33714
|
-
import { dirname as
|
|
34507
|
+
import { dirname as dirname18, join as join28 } from "path";
|
|
33715
34508
|
var START2 = "// absolutejs:native-observability:start";
|
|
33716
34509
|
var END2 = "// absolutejs:native-observability:end";
|
|
33717
34510
|
var PLUGIN_START2 = "// absolutejs:native-observability-plugin:start";
|
|
@@ -33719,7 +34512,7 @@ var PLUGIN_END2 = "// absolutejs:native-observability-plugin:end";
|
|
|
33719
34512
|
var ANDROID_PLUGIN2 = "AbsoluteMobileObservabilityPlugin.java";
|
|
33720
34513
|
var optionalSource3 = async (path) => {
|
|
33721
34514
|
try {
|
|
33722
|
-
return await
|
|
34515
|
+
return await readFile24(path, "utf8");
|
|
33723
34516
|
} catch (error) {
|
|
33724
34517
|
if (typeof error === "object" && error !== null && Reflect.get(error, "code") === "ENOENT")
|
|
33725
34518
|
return null;
|
|
@@ -33730,7 +34523,7 @@ var writeChanged2 = async (path, source) => {
|
|
|
33730
34523
|
const current = await optionalSource3(path);
|
|
33731
34524
|
if (current === source)
|
|
33732
34525
|
return false;
|
|
33733
|
-
await
|
|
34526
|
+
await mkdir18(dirname18(path), { recursive: true });
|
|
33734
34527
|
if (current === null) {
|
|
33735
34528
|
await writeFile20(path, source, { flag: "wx" });
|
|
33736
34529
|
return true;
|
|
@@ -33743,7 +34536,7 @@ var writeChanged2 = async (path, source) => {
|
|
|
33743
34536
|
var removeOwnedFile2 = async (path) => {
|
|
33744
34537
|
if (await optionalSource3(path) === null)
|
|
33745
34538
|
return false;
|
|
33746
|
-
await
|
|
34539
|
+
await rm14(path);
|
|
33747
34540
|
return true;
|
|
33748
34541
|
};
|
|
33749
34542
|
var isRecord13 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
@@ -33879,9 +34672,9 @@ public final class AbsoluteMobileObservabilityPlugin: CAPPlugin, CAPBridgedPlugi
|
|
|
33879
34672
|
${PLUGIN_END2}
|
|
33880
34673
|
`;
|
|
33881
34674
|
var configureIos4 = async (config, enabled) => {
|
|
33882
|
-
const path =
|
|
33883
|
-
const capacitorConfigPath =
|
|
33884
|
-
let source = await
|
|
34675
|
+
const path = join28(config.nativeProjectDirectory, "ios/App/App/AppDelegate.swift");
|
|
34676
|
+
const capacitorConfigPath = join28(config.nativeProjectDirectory, "ios/App/App/capacitor.config.json");
|
|
34677
|
+
let source = await readFile24(path, "utf8");
|
|
33885
34678
|
if (enabled && !source.includes("import MetricKit")) {
|
|
33886
34679
|
const capacitorImport = source.lastIndexOf("import Capacitor");
|
|
33887
34680
|
if (capacitorImport < 0)
|
|
@@ -33895,7 +34688,7 @@ ${source.slice(newline + 1)}`;
|
|
|
33895
34688
|
source = source.replace(`import MetricKit
|
|
33896
34689
|
`, "");
|
|
33897
34690
|
source = replaceMarkedRegion2(source, PLUGIN_START2, PLUGIN_END2, enabled ? iosPluginRegion2 : "", source.length, "Could not find a safe iOS location for native observability.");
|
|
33898
|
-
const capacitorConfigSource2 = await
|
|
34691
|
+
const capacitorConfigSource2 = await readFile24(capacitorConfigPath, "utf8");
|
|
33899
34692
|
let capacitorConfig;
|
|
33900
34693
|
try {
|
|
33901
34694
|
const value = JSON.parse(capacitorConfigSource2);
|
|
@@ -34133,19 +34926,19 @@ public final class AbsoluteMobileObservabilityPlugin extends Plugin {
|
|
|
34133
34926
|
var androidActivityInRoot2 = async (root) => {
|
|
34134
34927
|
let entries;
|
|
34135
34928
|
try {
|
|
34136
|
-
entries = await
|
|
34929
|
+
entries = await readdir8(root, { recursive: true });
|
|
34137
34930
|
} catch (error) {
|
|
34138
34931
|
if (typeof error === "object" && error !== null && Reflect.get(error, "code") === "ENOENT")
|
|
34139
34932
|
return;
|
|
34140
34933
|
throw error;
|
|
34141
34934
|
}
|
|
34142
34935
|
const candidate = entries.find((entry) => entry.endsWith("/MainActivity.java") || entry.endsWith("/MainActivity.kt") || entry === "MainActivity.java" || entry === "MainActivity.kt");
|
|
34143
|
-
return candidate ?
|
|
34936
|
+
return candidate ? join28(root, candidate) : undefined;
|
|
34144
34937
|
};
|
|
34145
34938
|
var androidActivity2 = async (config) => {
|
|
34146
34939
|
const roots = [
|
|
34147
|
-
|
|
34148
|
-
|
|
34940
|
+
join28(config.nativeProjectDirectory, "android/app/src/main/java"),
|
|
34941
|
+
join28(config.nativeProjectDirectory, "android/app/src/main/kotlin")
|
|
34149
34942
|
];
|
|
34150
34943
|
const candidates = await Promise.all(roots.map(androidActivityInRoot2));
|
|
34151
34944
|
const candidate = candidates.find((value) => value !== undefined);
|
|
@@ -34213,11 +35006,11 @@ var injectAndroidActivity2 = (source, enabled) => {
|
|
|
34213
35006
|
};
|
|
34214
35007
|
var configureAndroid4 = async (config, enabled) => {
|
|
34215
35008
|
const activityPath = await androidActivity2(config);
|
|
34216
|
-
const activity = await
|
|
35009
|
+
const activity = await readFile24(activityPath, "utf8");
|
|
34217
35010
|
const packageName = activity.match(/^\s*package\s+([A-Za-z0-9_.]+)\s*[;\n]/mu)?.[1];
|
|
34218
35011
|
if (!packageName)
|
|
34219
35012
|
throw new TypeError("Android MainActivity package declaration was not found.");
|
|
34220
|
-
const pluginPath =
|
|
35013
|
+
const pluginPath = join28(config.nativeProjectDirectory, "android/app/src/main/java", packageName.replaceAll(".", "/"), ANDROID_PLUGIN2);
|
|
34221
35014
|
const changed = await Promise.all([
|
|
34222
35015
|
writeChanged2(activityPath, injectAndroidActivity2(activity, enabled)),
|
|
34223
35016
|
enabled ? writeChanged2(pluginPath, androidPluginSource2(packageName)) : removeOwnedFile2(pluginPath)
|
|
@@ -34236,14 +35029,16 @@ var applyAbsoluteNativeObservability = async (config, platforms = config.platfor
|
|
|
34236
35029
|
return { changed: changed.some(Boolean) };
|
|
34237
35030
|
};
|
|
34238
35031
|
// src/mobile/nativeReleaseReadiness.ts
|
|
34239
|
-
import { mkdir as
|
|
34240
|
-
import { dirname as
|
|
35032
|
+
import { mkdir as mkdir19, readFile as readFile25, readdir as readdir9, rename as rename17, writeFile as writeFile21 } from "fs/promises";
|
|
35033
|
+
import { dirname as dirname19, join as join29 } from "path";
|
|
34241
35034
|
var START3 = "// absolutejs:release-readiness:start";
|
|
34242
35035
|
var END3 = "// absolutejs:release-readiness:end";
|
|
35036
|
+
var IOS_PLUGIN_START = "// absolutejs:release-readiness-plugin:start";
|
|
35037
|
+
var IOS_PLUGIN_END = "// absolutejs:release-readiness-plugin:end";
|
|
34243
35038
|
var ANDROID_PLUGIN3 = "AbsoluteReleaseReadinessPlugin.java";
|
|
34244
35039
|
var optionalSource4 = async (path) => {
|
|
34245
35040
|
try {
|
|
34246
|
-
return await
|
|
35041
|
+
return await readFile25(path, "utf8");
|
|
34247
35042
|
} catch (error) {
|
|
34248
35043
|
if (typeof error === "object" && error !== null && Reflect.get(error, "code") === "ENOENT")
|
|
34249
35044
|
return null;
|
|
@@ -34254,7 +35049,7 @@ var writeChanged3 = async (path, source) => {
|
|
|
34254
35049
|
const current = await optionalSource4(path);
|
|
34255
35050
|
if (current === source)
|
|
34256
35051
|
return false;
|
|
34257
|
-
await
|
|
35052
|
+
await mkdir19(dirname19(path), { recursive: true });
|
|
34258
35053
|
if (current === null) {
|
|
34259
35054
|
await writeFile21(path, source, { flag: "wx" });
|
|
34260
35055
|
return true;
|
|
@@ -34267,19 +35062,19 @@ var writeChanged3 = async (path, source) => {
|
|
|
34267
35062
|
var activityInRoot = async (root) => {
|
|
34268
35063
|
let entries;
|
|
34269
35064
|
try {
|
|
34270
|
-
entries = await
|
|
35065
|
+
entries = await readdir9(root, { recursive: true });
|
|
34271
35066
|
} catch (error) {
|
|
34272
35067
|
if (typeof error === "object" && error !== null && Reflect.get(error, "code") === "ENOENT")
|
|
34273
35068
|
return;
|
|
34274
35069
|
throw error;
|
|
34275
35070
|
}
|
|
34276
35071
|
const candidate = entries.find((entry) => entry.endsWith("/MainActivity.java") || entry.endsWith("/MainActivity.kt") || entry === "MainActivity.java" || entry === "MainActivity.kt");
|
|
34277
|
-
return candidate ?
|
|
35072
|
+
return candidate ? join29(root, candidate) : undefined;
|
|
34278
35073
|
};
|
|
34279
35074
|
var activityPath = async (config) => {
|
|
34280
35075
|
const roots = [
|
|
34281
|
-
|
|
34282
|
-
|
|
35076
|
+
join29(config.nativeProjectDirectory, "android/app/src/main/java"),
|
|
35077
|
+
join29(config.nativeProjectDirectory, "android/app/src/main/kotlin")
|
|
34283
35078
|
];
|
|
34284
35079
|
const candidates = await Promise.all(roots.map(activityInRoot));
|
|
34285
35080
|
const candidate = candidates.find((value) => value !== undefined);
|
|
@@ -34361,19 +35156,89 @@ public final class AbsoluteReleaseReadinessPlugin extends Plugin {
|
|
|
34361
35156
|
}
|
|
34362
35157
|
}
|
|
34363
35158
|
`;
|
|
34364
|
-
var
|
|
34365
|
-
|
|
34366
|
-
|
|
35159
|
+
var iosPluginRegion3 = `${IOS_PLUGIN_START}
|
|
35160
|
+
@objc(AbsoluteReleaseReadinessPlugin)
|
|
35161
|
+
public final class AbsoluteReleaseReadinessPlugin: CAPPlugin, CAPBridgedPlugin {
|
|
35162
|
+
public let identifier = "AbsoluteReleaseReadinessPlugin"
|
|
35163
|
+
public let jsName = "AbsoluteReleaseReadiness"
|
|
35164
|
+
public let pluginMethods: [CAPPluginMethod] = [
|
|
35165
|
+
CAPPluginMethod(name: "ready", returnType: CAPPluginReturnPromise)
|
|
35166
|
+
]
|
|
35167
|
+
|
|
35168
|
+
@objc public func ready(_ call: CAPPluginCall) {
|
|
35169
|
+
let info = Bundle.main.infoDictionary ?? [:]
|
|
35170
|
+
let version = info["CFBundleShortVersionString"] as? String ?? "unknown"
|
|
35171
|
+
let build = info["CFBundleVersion"] as? String ?? "unknown"
|
|
35172
|
+
NSLog("AbsoluteJS: Capacitor embedded web content ready; version=%@; build=%@", version, build)
|
|
35173
|
+
call.resolve(["ready": true])
|
|
35174
|
+
}
|
|
35175
|
+
}
|
|
35176
|
+
${IOS_PLUGIN_END}
|
|
35177
|
+
`;
|
|
35178
|
+
var replaceIosPluginRegion = (appDelegate, existingStart, existingEnd) => {
|
|
35179
|
+
const from = appDelegate.lastIndexOf(`
|
|
35180
|
+
`, existingStart) + 1;
|
|
35181
|
+
const newline = appDelegate.indexOf(`
|
|
35182
|
+
`, existingEnd + IOS_PLUGIN_END.length);
|
|
35183
|
+
const through = newline < 0 ? appDelegate.length : newline + 1;
|
|
35184
|
+
return `${appDelegate.slice(0, from)}${iosPluginRegion3}${appDelegate.slice(through)}`;
|
|
35185
|
+
};
|
|
35186
|
+
var configureIos5 = async (config) => {
|
|
35187
|
+
const appDelegatePath = join29(config.nativeProjectDirectory, "ios/App/App/AppDelegate.swift");
|
|
35188
|
+
const capacitorConfigPath = join29(config.nativeProjectDirectory, "ios/App/App/capacitor.config.json");
|
|
35189
|
+
const appDelegate = await readFile25(appDelegatePath, "utf8");
|
|
35190
|
+
const existingStart = appDelegate.indexOf(IOS_PLUGIN_START);
|
|
35191
|
+
const existingEnd = appDelegate.indexOf(IOS_PLUGIN_END);
|
|
35192
|
+
if (existingStart < 0 !== existingEnd < 0 || existingStart >= 0 && existingEnd < existingStart)
|
|
35193
|
+
throw new TypeError("AbsoluteJS iOS release-readiness markers are malformed.");
|
|
35194
|
+
const source = existingStart < 0 ? `${appDelegate.trimEnd()}
|
|
35195
|
+
|
|
35196
|
+
${iosPluginRegion3}` : replaceIosPluginRegion(appDelegate, existingStart, existingEnd);
|
|
35197
|
+
let capacitorConfig;
|
|
35198
|
+
try {
|
|
35199
|
+
capacitorConfig = JSON.parse(await readFile25(capacitorConfigPath, "utf8"));
|
|
35200
|
+
} catch {
|
|
35201
|
+
throw new TypeError("iOS capacitor.config.json is invalid; run Capacitor sync before projecting release readiness.");
|
|
35202
|
+
}
|
|
35203
|
+
if (typeof capacitorConfig !== "object" || capacitorConfig === null)
|
|
35204
|
+
throw new TypeError("iOS capacitor.config.json must contain an object.");
|
|
35205
|
+
const packageClassList = Reflect.get(capacitorConfig, "packageClassList");
|
|
35206
|
+
if (!Array.isArray(packageClassList))
|
|
35207
|
+
throw new TypeError("iOS capacitor.config.json has no packageClassList; run Capacitor sync before projecting release readiness.");
|
|
35208
|
+
const classes = packageClassList.filter((value) => typeof value === "string");
|
|
35209
|
+
const nextConfig = `${JSON.stringify({
|
|
35210
|
+
...capacitorConfig,
|
|
35211
|
+
packageClassList: [
|
|
35212
|
+
...new Set([...classes, "AbsoluteReleaseReadinessPlugin"])
|
|
35213
|
+
]
|
|
35214
|
+
}, null, "\t")}
|
|
35215
|
+
`;
|
|
35216
|
+
const changed = await Promise.all([
|
|
35217
|
+
writeChanged3(appDelegatePath, source),
|
|
35218
|
+
writeChanged3(capacitorConfigPath, nextConfig)
|
|
35219
|
+
]);
|
|
35220
|
+
return changed.some(Boolean);
|
|
35221
|
+
};
|
|
35222
|
+
var configureAndroid5 = async (config) => {
|
|
34367
35223
|
const mainActivityPath = await activityPath(config);
|
|
34368
|
-
const activity = await
|
|
35224
|
+
const activity = await readFile25(mainActivityPath, "utf8");
|
|
34369
35225
|
const packageName = activity.match(/^\s*package\s+([A-Za-z0-9_.]+)\s*[;\n]/mu)?.[1];
|
|
34370
35226
|
if (!packageName)
|
|
34371
35227
|
throw new TypeError("Android MainActivity package declaration was not found.");
|
|
34372
|
-
const pluginPath =
|
|
35228
|
+
const pluginPath = join29(config.nativeProjectDirectory, "android/app/src/main/java", packageName.replaceAll(".", "/"), ANDROID_PLUGIN3);
|
|
34373
35229
|
const changed = await Promise.all([
|
|
34374
35230
|
writeChanged3(mainActivityPath, injectRegistration(activity)),
|
|
34375
35231
|
writeChanged3(pluginPath, pluginSource(packageName))
|
|
34376
35232
|
]);
|
|
35233
|
+
return changed.some(Boolean);
|
|
35234
|
+
};
|
|
35235
|
+
var applyAbsoluteNativeReleaseReadiness = async (config, platforms = config.platforms) => {
|
|
35236
|
+
if (config.engine !== "capacitor")
|
|
35237
|
+
return { changed: false };
|
|
35238
|
+
const changed = await Promise.all([
|
|
35239
|
+
platforms.includes("android") ? configureAndroid5(config) : false,
|
|
35240
|
+
platforms.includes("ios") ? configureIos5(config) : false
|
|
35241
|
+
]);
|
|
34377
35242
|
return { changed: changed.some(Boolean) };
|
|
34378
35243
|
};
|
|
34379
35244
|
|
|
@@ -34383,8 +35248,8 @@ init_producerContext();
|
|
|
34383
35248
|
init_releaseArtifact();
|
|
34384
35249
|
|
|
34385
35250
|
// src/mobile/releasePublisher.ts
|
|
34386
|
-
import { access as
|
|
34387
|
-
import { isAbsolute as
|
|
35251
|
+
import { access as access17 } from "fs/promises";
|
|
35252
|
+
import { isAbsolute as isAbsolute9, relative as relative16, resolve as resolve18, sep as sep11 } from "path";
|
|
34388
35253
|
import { pathToFileURL as pathToFileURL3 } from "url";
|
|
34389
35254
|
var prepareAbsoluteIosRelease = async (publisher, options) => {
|
|
34390
35255
|
if (typeof publisher.prepareIosRelease !== "function") {
|
|
@@ -34410,17 +35275,17 @@ var prepareAbsoluteAndroidRelease = async (publisher, options) => {
|
|
|
34410
35275
|
var isRecord14 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
34411
35276
|
var isPublisher = (value) => isRecord14(value) && typeof value.publish === "function";
|
|
34412
35277
|
var publisherModulePath = (projectRoot, requested) => {
|
|
34413
|
-
const root =
|
|
34414
|
-
const path =
|
|
34415
|
-
const projectRelative =
|
|
34416
|
-
if (projectRelative === ".." || projectRelative.startsWith(`..${
|
|
35278
|
+
const root = resolve18(projectRoot);
|
|
35279
|
+
const path = resolve18(root, requested);
|
|
35280
|
+
const projectRelative = relative16(root, path);
|
|
35281
|
+
if (projectRelative === ".." || projectRelative.startsWith(`..${sep11}`) || isAbsolute9(projectRelative)) {
|
|
34417
35282
|
throw new TypeError("mobile publish --registry must remain inside the project.");
|
|
34418
35283
|
}
|
|
34419
35284
|
return path;
|
|
34420
35285
|
};
|
|
34421
35286
|
var loadAbsoluteNativeReleasePublisher = async (projectRoot, requestedModulePath) => {
|
|
34422
35287
|
const modulePath = publisherModulePath(projectRoot, requestedModulePath);
|
|
34423
|
-
await
|
|
35288
|
+
await access17(modulePath).catch(() => {
|
|
34424
35289
|
throw new TypeError(`Native release registry module does not exist: ${modulePath}`);
|
|
34425
35290
|
});
|
|
34426
35291
|
const loaded = await import(pathToFileURL3(modulePath).href);
|
|
@@ -34484,7 +35349,7 @@ var publishAbsoluteIosRelease = async (options) => {
|
|
|
34484
35349
|
init_pageProtocol();
|
|
34485
35350
|
init_releaseArtifact();
|
|
34486
35351
|
import { existsSync as existsSync7, readFileSync as readFileSync8 } from "fs";
|
|
34487
|
-
import { dirname as
|
|
35352
|
+
import { dirname as dirname20, extname as extname6, relative as relative17, resolve as resolve19 } from "path";
|
|
34488
35353
|
import ts2 from "typescript";
|
|
34489
35354
|
var ROUTE_METHODS = new Set(["get", "head"]);
|
|
34490
35355
|
var SOURCE_FILTER = /\.[cm]?[jt]sx?$/;
|
|
@@ -34535,7 +35400,7 @@ var PAGE_HANDLERS = new Map([
|
|
|
34535
35400
|
]
|
|
34536
35401
|
]);
|
|
34537
35402
|
var posixPath = (value) => value.replace(/\\/g, "/");
|
|
34538
|
-
var findTsconfig = (entry, projectRoot) => ts2.findConfigFile(
|
|
35403
|
+
var findTsconfig = (entry, projectRoot) => ts2.findConfigFile(dirname20(entry), existsSync7, "tsconfig.json") ?? ts2.findConfigFile(projectRoot, existsSync7, "tsconfig.json");
|
|
34539
35404
|
var createProgram = (entry, projectRoot) => {
|
|
34540
35405
|
const configPath2 = findTsconfig(entry, projectRoot);
|
|
34541
35406
|
if (!configPath2) {
|
|
@@ -34547,7 +35412,7 @@ var createProgram = (entry, projectRoot) => {
|
|
|
34547
35412
|
target: ts2.ScriptTarget.ESNext
|
|
34548
35413
|
});
|
|
34549
35414
|
}
|
|
34550
|
-
const parsed = ts2.parseJsonConfigFileContent(ts2.readConfigFile(configPath2, (path) => readFileSync8(path, "utf8")).config, ts2.sys,
|
|
35415
|
+
const parsed = ts2.parseJsonConfigFileContent(ts2.readConfigFile(configPath2, (path) => readFileSync8(path, "utf8")).config, ts2.sys, dirname20(configPath2));
|
|
34551
35416
|
if (!parsed.fileNames.includes(entry))
|
|
34552
35417
|
parsed.fileNames.push(entry);
|
|
34553
35418
|
return ts2.createProgram(parsed.fileNames, parsed.options);
|
|
@@ -34653,7 +35518,7 @@ var resolvePageIdentity = (expression, sourceFile, checker, projectRoot) => {
|
|
|
34653
35518
|
const declaration = symbol?.declarations?.[0];
|
|
34654
35519
|
const file = declaration?.getSourceFile().fileName ?? sourceFile.fileName;
|
|
34655
35520
|
const exportedName = symbol?.name ?? expression.getText(sourceFile);
|
|
34656
|
-
const source = posixPath(
|
|
35521
|
+
const source = posixPath(relative17(projectRoot, file));
|
|
34657
35522
|
return `${source}#${exportedName}`;
|
|
34658
35523
|
};
|
|
34659
35524
|
var resolveAlias = (symbol, checker) => {
|
|
@@ -34892,7 +35757,7 @@ var analyzeProgram = (program, projectRoot) => {
|
|
|
34892
35757
|
const checker = program.getTypeChecker();
|
|
34893
35758
|
const analyzed = new Map;
|
|
34894
35759
|
for (const sourceFile of program.getSourceFiles()) {
|
|
34895
|
-
const resolvedFile =
|
|
35760
|
+
const resolvedFile = resolve19(sourceFile.fileName);
|
|
34896
35761
|
if (!isProjectSource(sourceFile, resolvedFile, projectRoot))
|
|
34897
35762
|
continue;
|
|
34898
35763
|
const analysis = analyzeSourceFile(sourceFile, checker, projectRoot);
|
|
@@ -34985,14 +35850,14 @@ var transformFile = (source, fileName, analysis) => {
|
|
|
34985
35850
|
};
|
|
34986
35851
|
var ABSOLUTE_MOBILE_TRANSFORM_PROTOCOL = ABSOLUTE_MOBILE_PAGE_PROTOCOL_VERSION;
|
|
34987
35852
|
var createAbsoluteMobileRouteMetadataPlugin = (options) => {
|
|
34988
|
-
const projectRoot =
|
|
34989
|
-
const entry =
|
|
35853
|
+
const projectRoot = resolve19(options.projectRoot ?? process.cwd());
|
|
35854
|
+
const entry = resolve19(options.entry);
|
|
34990
35855
|
const analyzed = analyzeProgram(createProgram(entry, projectRoot), projectRoot);
|
|
34991
35856
|
return {
|
|
34992
35857
|
name: "absolute-mobile-route-metadata",
|
|
34993
35858
|
setup(build) {
|
|
34994
35859
|
build.onLoad({ filter: SOURCE_FILTER }, async ({ path }) => {
|
|
34995
|
-
const analysis = analyzed.get(
|
|
35860
|
+
const analysis = analyzed.get(resolve19(path));
|
|
34996
35861
|
if (!analysis)
|
|
34997
35862
|
return;
|
|
34998
35863
|
const source = await Bun.file(path).text();
|
|
@@ -35005,11 +35870,11 @@ var createAbsoluteMobileRouteMetadataPlugin = (options) => {
|
|
|
35005
35870
|
};
|
|
35006
35871
|
};
|
|
35007
35872
|
var inspectAbsoluteMobileRouteMetadata = (options) => {
|
|
35008
|
-
const projectRoot =
|
|
35009
|
-
const entry =
|
|
35873
|
+
const projectRoot = resolve19(options.projectRoot ?? process.cwd());
|
|
35874
|
+
const entry = resolve19(options.entry);
|
|
35010
35875
|
const analyzed = analyzeProgram(createProgram(entry, projectRoot), projectRoot);
|
|
35011
35876
|
return [...analyzed.entries()].flatMap(([file, analysis]) => [...analysis.byRouteCall.values()].map(({ metadata }) => ({
|
|
35012
|
-
file: posixPath(
|
|
35877
|
+
file: posixPath(relative17(projectRoot, file)),
|
|
35013
35878
|
metadata
|
|
35014
35879
|
})));
|
|
35015
35880
|
};
|
|
@@ -35343,7 +36208,7 @@ var createCapacitor = (win) => {
|
|
|
35343
36208
|
callbackId
|
|
35344
36209
|
}, callback);
|
|
35345
36210
|
};
|
|
35346
|
-
const p = new Promise((
|
|
36211
|
+
const p = new Promise((resolve20) => call.then(() => resolve20({ remove })));
|
|
35347
36212
|
p.remove = async () => {
|
|
35348
36213
|
console.warn(`Using addListener() without 'await' is deprecated.`);
|
|
35349
36214
|
await remove();
|
|
@@ -35548,11 +36413,11 @@ class CapacitorCookiesPluginWeb extends WebPlugin {
|
|
|
35548
36413
|
var CapacitorCookies = registerPlugin("CapacitorCookies", {
|
|
35549
36414
|
web: () => new CapacitorCookiesPluginWeb
|
|
35550
36415
|
});
|
|
35551
|
-
var readBlobAsBase64 = async (blob) => new Promise((
|
|
36416
|
+
var readBlobAsBase64 = async (blob) => new Promise((resolve20, reject) => {
|
|
35552
36417
|
const reader = new FileReader;
|
|
35553
36418
|
reader.onload = () => {
|
|
35554
36419
|
const base64String = reader.result;
|
|
35555
|
-
|
|
36420
|
+
resolve20(base64String.indexOf(",") >= 0 ? base64String.split(",")[1] : base64String);
|
|
35556
36421
|
};
|
|
35557
36422
|
reader.onerror = (error) => reject(error);
|
|
35558
36423
|
reader.readAsDataURL(blob);
|
|
@@ -40212,8 +41077,8 @@ var createBeacon = (options) => {
|
|
|
40212
41077
|
if (await fontAvailable(element))
|
|
40213
41078
|
return;
|
|
40214
41079
|
if (confirmationMs > 0) {
|
|
40215
|
-
await new Promise((
|
|
40216
|
-
const timer2 = window.setTimeout(
|
|
41080
|
+
await new Promise((resolve20) => {
|
|
41081
|
+
const timer2 = window.setTimeout(resolve20, confirmationMs);
|
|
40217
41082
|
cleanups.push(() => window.clearTimeout(timer2));
|
|
40218
41083
|
});
|
|
40219
41084
|
if (document.visibilityState === "hidden")
|
|
@@ -41201,51 +42066,51 @@ var createAbsoluteMobileUpdateClient = (options) => {
|
|
|
41201
42066
|
};
|
|
41202
42067
|
};
|
|
41203
42068
|
// src/mobile/updatePublisher.ts
|
|
41204
|
-
import { access as
|
|
41205
|
-
import { isAbsolute as
|
|
42069
|
+
import { access as access18 } from "fs/promises";
|
|
42070
|
+
import { isAbsolute as isAbsolute10, relative as relative19, resolve as resolve21, sep as sep12 } from "path";
|
|
41206
42071
|
import { pathToFileURL as pathToFileURL4 } from "url";
|
|
41207
42072
|
|
|
41208
42073
|
// src/mobile/updateSigning.ts
|
|
41209
|
-
import { createHash as
|
|
42074
|
+
import { createHash as createHash16, sign, verify } from "crypto";
|
|
41210
42075
|
import {
|
|
41211
42076
|
cp as cp2,
|
|
41212
|
-
mkdir as
|
|
41213
|
-
mkdtemp as
|
|
41214
|
-
readdir as
|
|
41215
|
-
readFile as
|
|
42077
|
+
mkdir as mkdir20,
|
|
42078
|
+
mkdtemp as mkdtemp10,
|
|
42079
|
+
readdir as readdir10,
|
|
42080
|
+
readFile as readFile26,
|
|
41216
42081
|
rename as rename18,
|
|
41217
|
-
rm as
|
|
41218
|
-
stat as
|
|
42082
|
+
rm as rm15,
|
|
42083
|
+
stat as stat6,
|
|
41219
42084
|
writeFile as writeFile22
|
|
41220
42085
|
} from "fs/promises";
|
|
41221
|
-
import { dirname as
|
|
42086
|
+
import { dirname as dirname21, join as join30, relative as relative18, resolve as resolve20 } from "path";
|
|
41222
42087
|
var UPDATE_MANIFEST_FILE = "update.json";
|
|
41223
42088
|
var UPDATE_FILES_DIRECTORY = "files";
|
|
41224
|
-
var
|
|
42089
|
+
var sha2564 = (value) => createHash16("sha256").update(value).digest("hex");
|
|
41225
42090
|
var listFiles = async (root, directory = root) => {
|
|
41226
|
-
const entries = await
|
|
42091
|
+
const entries = await readdir10(directory, { withFileTypes: true });
|
|
41227
42092
|
const paths = await Promise.all(entries.map(async (entry) => {
|
|
41228
|
-
const path =
|
|
42093
|
+
const path = join30(directory, entry.name);
|
|
41229
42094
|
if (entry.isDirectory())
|
|
41230
42095
|
return listFiles(root, path);
|
|
41231
42096
|
if (!entry.isFile())
|
|
41232
42097
|
throw new TypeError("Mobile updates cannot contain links or special files.");
|
|
41233
|
-
return [
|
|
42098
|
+
return [relative18(root, path).replaceAll("\\", "/")];
|
|
41234
42099
|
}));
|
|
41235
42100
|
return paths.flat().sort((left, right) => left.localeCompare(right));
|
|
41236
42101
|
};
|
|
41237
42102
|
var inspectFiles = async (root, paths) => Promise.all(paths.map(async (path) => {
|
|
41238
|
-
const source =
|
|
42103
|
+
const source = join30(root, path);
|
|
41239
42104
|
const [metadata, contents] = await Promise.all([
|
|
41240
|
-
|
|
41241
|
-
|
|
42105
|
+
stat6(source),
|
|
42106
|
+
readFile26(source)
|
|
41242
42107
|
]);
|
|
41243
|
-
return { bytes: metadata.size, path, sha256:
|
|
42108
|
+
return { bytes: metadata.size, path, sha256: sha2564(contents) };
|
|
41244
42109
|
}));
|
|
41245
|
-
var releaseIdFor = (value) => `amu_${
|
|
42110
|
+
var releaseIdFor = (value) => `amu_${sha2564(canonicalizeAbsoluteMobileUpdate(value))}`;
|
|
41246
42111
|
var buildAbsoluteMobileUpdate = async (options) => {
|
|
41247
|
-
const bundleDirectory =
|
|
41248
|
-
const outputRoot =
|
|
42112
|
+
const bundleDirectory = resolve20(options.bundleDirectory);
|
|
42113
|
+
const outputRoot = resolve20(options.outputDirectory);
|
|
41249
42114
|
if (outputRoot === bundleDirectory || outputRoot.startsWith(`${bundleDirectory}/`))
|
|
41250
42115
|
throw new TypeError("Mobile update output must be outside the embedded bundle.");
|
|
41251
42116
|
const paths = await listFiles(bundleDirectory);
|
|
@@ -41273,38 +42138,38 @@ var buildAbsoluteMobileUpdate = async (options) => {
|
|
|
41273
42138
|
value: signature.toString("base64")
|
|
41274
42139
|
}
|
|
41275
42140
|
});
|
|
41276
|
-
await
|
|
41277
|
-
const outputDirectory =
|
|
41278
|
-
const staging = await
|
|
42141
|
+
await mkdir20(outputRoot, { recursive: true });
|
|
42142
|
+
const outputDirectory = join30(outputRoot, manifest.releaseId);
|
|
42143
|
+
const staging = await mkdtemp10(join30(outputRoot, ".stage-"));
|
|
41279
42144
|
try {
|
|
41280
|
-
await cp2(bundleDirectory,
|
|
42145
|
+
await cp2(bundleDirectory, join30(staging, UPDATE_FILES_DIRECTORY), {
|
|
41281
42146
|
force: true,
|
|
41282
42147
|
recursive: true
|
|
41283
42148
|
});
|
|
41284
|
-
await writeFile22(
|
|
42149
|
+
await writeFile22(join30(staging, UPDATE_MANIFEST_FILE), `${JSON.stringify(manifest, null, "\t")}
|
|
41285
42150
|
`);
|
|
41286
42151
|
await rename18(staging, outputDirectory);
|
|
41287
42152
|
} catch (error) {
|
|
41288
|
-
await
|
|
42153
|
+
await rm15(staging, { force: true, recursive: true });
|
|
41289
42154
|
if (typeof error === "object" && error !== null && Reflect.get(error, "code") === "EEXIST")
|
|
41290
42155
|
throw new TypeError(`Mobile update ${manifest.releaseId} already exists.`, { cause: error });
|
|
41291
42156
|
throw error;
|
|
41292
42157
|
}
|
|
41293
42158
|
return {
|
|
41294
42159
|
manifest,
|
|
41295
|
-
manifestPath:
|
|
42160
|
+
manifestPath: join30(outputDirectory, UPDATE_MANIFEST_FILE),
|
|
41296
42161
|
outputDirectory
|
|
41297
42162
|
};
|
|
41298
42163
|
};
|
|
41299
42164
|
var copyAbsoluteMobileUpdateFile = async (updateDirectory, path, destination) => {
|
|
41300
|
-
const source =
|
|
41301
|
-
const root =
|
|
42165
|
+
const source = resolve20(updateDirectory, UPDATE_FILES_DIRECTORY, path);
|
|
42166
|
+
const root = resolve20(updateDirectory, UPDATE_FILES_DIRECTORY);
|
|
41302
42167
|
if (!source.startsWith(`${root}/`))
|
|
41303
42168
|
throw new TypeError("Update file escaped its release.");
|
|
41304
|
-
await
|
|
42169
|
+
await mkdir20(dirname21(destination), { recursive: true });
|
|
41305
42170
|
await cp2(source, destination, { force: true });
|
|
41306
42171
|
};
|
|
41307
|
-
var readAbsoluteMobileUpdate = async (directory) => parseAbsoluteMobileUpdateManifest(JSON.parse(await
|
|
42172
|
+
var readAbsoluteMobileUpdate = async (directory) => parseAbsoluteMobileUpdateManifest(JSON.parse(await readFile26(join30(resolve20(directory), UPDATE_MANIFEST_FILE), "utf8")));
|
|
41308
42173
|
var verifyAbsoluteMobileUpdateSignature = (manifestValue, publicKey) => {
|
|
41309
42174
|
const manifest = parseAbsoluteMobileUpdateManifest(manifestValue);
|
|
41310
42175
|
const valid = verify("sha256", absoluteMobileUpdateSigningPayload(unsignedAbsoluteMobileUpdate(manifest)), { dsaEncoding: "ieee-p1363", key: publicKey }, Buffer.from(manifest.signature.value, "base64"));
|
|
@@ -41421,16 +42286,16 @@ var pruneAbsoluteMobileUpdates = async (options) => {
|
|
|
41421
42286
|
var object5 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
41422
42287
|
var isPublisher2 = (value) => object5(value) && typeof value.publishUpdate === "function" && typeof value.promoteUpdate === "function" && typeof value.rollbackUpdate === "function";
|
|
41423
42288
|
var projectPath2 = (projectRoot, requested, label) => {
|
|
41424
|
-
const root =
|
|
41425
|
-
const path =
|
|
41426
|
-
const projectRelative =
|
|
41427
|
-
if (projectRelative === ".." || projectRelative.startsWith(`..${
|
|
42289
|
+
const root = resolve21(projectRoot);
|
|
42290
|
+
const path = resolve21(root, requested);
|
|
42291
|
+
const projectRelative = relative19(root, path);
|
|
42292
|
+
if (projectRelative === ".." || projectRelative.startsWith(`..${sep12}`) || isAbsolute10(projectRelative))
|
|
41428
42293
|
throw new TypeError(`${label} must remain inside the project.`);
|
|
41429
42294
|
return path;
|
|
41430
42295
|
};
|
|
41431
42296
|
var loadAbsoluteMobileUpdatePublisher = async (projectRoot, requestedModulePath) => {
|
|
41432
42297
|
const modulePath = projectPath2(projectRoot, requestedModulePath, "mobile update registry");
|
|
41433
|
-
await
|
|
42298
|
+
await access18(modulePath).catch(() => {
|
|
41434
42299
|
throw new TypeError(`Mobile update registry does not exist: ${modulePath}`);
|
|
41435
42300
|
});
|
|
41436
42301
|
const loaded = await import(pathToFileURL4(modulePath).href);
|
|
@@ -41481,7 +42346,7 @@ var rollbackAbsoluteMobileUpdate = async (options) => {
|
|
|
41481
42346
|
return result;
|
|
41482
42347
|
};
|
|
41483
42348
|
// src/mobile/updateRollout.ts
|
|
41484
|
-
import { createHash as
|
|
42349
|
+
import { createHash as createHash17 } from "crypto";
|
|
41485
42350
|
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;
|
|
41486
42351
|
var requireHeader = (headers, name) => {
|
|
41487
42352
|
const value = headers.get(name);
|
|
@@ -41496,7 +42361,7 @@ var isAbsoluteMobileUpdateRolloutMember = (options) => {
|
|
|
41496
42361
|
return false;
|
|
41497
42362
|
if (options.rollout === 1)
|
|
41498
42363
|
return true;
|
|
41499
|
-
const digest =
|
|
42364
|
+
const digest = createHash17("sha256").update(`${options.appId}\x00${options.channel}\x00${options.releaseId}\x00${options.installationId}`).digest();
|
|
41500
42365
|
const bucket = digest.readUInt32BE(0) / 4294967296;
|
|
41501
42366
|
return bucket < options.rollout;
|
|
41502
42367
|
};
|
|
@@ -41734,6 +42599,7 @@ export {
|
|
|
41734
42599
|
publishAbsoluteIosRelease,
|
|
41735
42600
|
publishAbsoluteMobileUpdate,
|
|
41736
42601
|
readAbsoluteAndroidRelease,
|
|
42602
|
+
readAbsoluteIosRelease,
|
|
41737
42603
|
readAbsoluteMobileLinkIntent,
|
|
41738
42604
|
readAbsoluteMobileMaterializedReleases,
|
|
41739
42605
|
readAbsoluteMobileUpdate,
|
|
@@ -41758,6 +42624,9 @@ export {
|
|
|
41758
42624
|
rollbackAbsoluteMobileUpdate,
|
|
41759
42625
|
runAbsoluteAndroidReleaseAcceptance,
|
|
41760
42626
|
runAbsoluteAndroidUpgradeConformance,
|
|
42627
|
+
runAbsoluteIosDeviceReleaseAcceptance,
|
|
42628
|
+
runAbsoluteIosSimulatorReleaseAcceptance,
|
|
42629
|
+
runAbsoluteRemoteIosReleaseAcceptance,
|
|
41761
42630
|
runWithAbsoluteMobileProducer,
|
|
41762
42631
|
serializeAbsoluteMobileAuthEnvironment,
|
|
41763
42632
|
startAbsoluteExpoDevSession,
|
|
@@ -41767,6 +42636,7 @@ export {
|
|
|
41767
42636
|
startAbsoluteRemoteExpoIosDevSession,
|
|
41768
42637
|
startAbsoluteRemoteIosDevSession,
|
|
41769
42638
|
syncAbsoluteExpoWebAssets,
|
|
42639
|
+
syncAbsoluteRemoteMacAcceptanceRelease,
|
|
41770
42640
|
syncAbsoluteRemoteMacProject,
|
|
41771
42641
|
syncAbsoluteRemoteMacReleaseInputs,
|
|
41772
42642
|
testAbsoluteIosPhysicalDevice,
|
|
@@ -41783,5 +42653,5 @@ export {
|
|
|
41783
42653
|
writeAbsoluteMobileUpdateRegistry
|
|
41784
42654
|
};
|
|
41785
42655
|
|
|
41786
|
-
//# debugId=
|
|
42656
|
+
//# debugId=45962AF96688DC1364756E2164756E21
|
|
41787
42657
|
//# sourceMappingURL=index.js.map
|