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