@absolutejs/absolute 0.20.0-beta.100 → 0.20.0-beta.102
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +14 -0
- package/changelog.json +25 -0
- package/dist/angular/components/core/streamingSlotRegistrar.js +1 -1
- package/dist/angular/components/core/streamingSlotRegistry.js +2 -2
- package/dist/build.js +5 -5
- package/dist/build.js.map +4 -4
- 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-qfckt3vc.js → mobile-6xe6zysv.js} +851 -233
- package/dist/cli/{start-10dfrjvd.js → start-nmyy64tr.js} +3 -3
- package/dist/index.js +5 -5
- package/dist/index.js.map +4 -4
- package/dist/mobile/index.js +1187 -760
- package/dist/mobile/index.js.map +9 -8
- package/dist/mobile/remoteMacAgentEntry.js +321 -216
- 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/dist/src/mobile/releaseDoctor.d.ts +5 -0
- package/package.json +2 -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",
|
|
@@ -24719,6 +24721,14 @@ var signAab = (artifactPath, capture, jarsigner, signing) => {
|
|
|
24719
24721
|
if (result.exitCode !== 0)
|
|
24720
24722
|
throw new TypeError("jarsigner could not sign the Android App Bundle with the configured CI identity.");
|
|
24721
24723
|
};
|
|
24724
|
+
var windowsJarsignerPath = (path, capture) => {
|
|
24725
|
+
const result = capture(["wslpath", "-w", path]);
|
|
24726
|
+
const translated = result.stdout.trim();
|
|
24727
|
+
if (result.exitCode !== 0 || !translated) {
|
|
24728
|
+
throw new TypeError(`Could not translate an Android signing path for the Windows JDK: ${path}`);
|
|
24729
|
+
}
|
|
24730
|
+
return translated;
|
|
24731
|
+
};
|
|
24722
24732
|
var sha256File = async (path) => createHash4("sha256").update(await readFile5(path)).digest("hex");
|
|
24723
24733
|
var fingerprintExpoAndroidProject = async (nativeDirectory) => {
|
|
24724
24734
|
const root = await realpath2(nativeDirectory);
|
|
@@ -24836,13 +24846,19 @@ var buildAbsoluteAndroidRelease = async (options) => {
|
|
|
24836
24846
|
throw new TypeError(`Android Gradle did not produce the expected App Bundle: ${artifactPath}`);
|
|
24837
24847
|
}
|
|
24838
24848
|
const capture = options.capture ?? defaultCapture;
|
|
24839
|
-
const jarsigner = options.jarsigner === undefined ? Bun.which("jarsigner") : options.jarsigner;
|
|
24840
|
-
|
|
24841
|
-
|
|
24849
|
+
const jarsigner = options.jarsigner === undefined ? Bun.which("jarsigner") ?? (host === "wsl" || host === "windows" ? Bun.which("jarsigner.exe") : null) : options.jarsigner;
|
|
24850
|
+
const usesWindowsJarsigner = host === "wsl" && jarsigner?.toLowerCase().endsWith(".exe");
|
|
24851
|
+
const signerArtifactPath = usesWindowsJarsigner ? windowsJarsignerPath(artifactPath, capture) : artifactPath;
|
|
24852
|
+
const signing = usesWindowsJarsigner && options.signing ? {
|
|
24853
|
+
...options.signing,
|
|
24854
|
+
keystorePath: windowsJarsignerPath(options.signing.keystorePath, capture)
|
|
24855
|
+
} : options.signing;
|
|
24856
|
+
let signed = verifyAabSignature(signerArtifactPath, capture, jarsigner);
|
|
24857
|
+
if (signed === false && signing) {
|
|
24842
24858
|
if (!jarsigner)
|
|
24843
24859
|
throw new TypeError("Could not sign the Android App Bundle because jarsigner is unavailable.");
|
|
24844
|
-
signAab(
|
|
24845
|
-
signed = verifyAabSignature(
|
|
24860
|
+
signAab(signerArtifactPath, capture, jarsigner, signing);
|
|
24861
|
+
signed = verifyAabSignature(signerArtifactPath, capture, jarsigner);
|
|
24846
24862
|
if (!signed)
|
|
24847
24863
|
throw new TypeError("Android App Bundle signature verification failed after CI signing.");
|
|
24848
24864
|
}
|
|
@@ -24873,6 +24889,29 @@ var buildAbsoluteAndroidRelease = async (options) => {
|
|
|
24873
24889
|
};
|
|
24874
24890
|
return installRelease(artifactPath, metadata, safeOutputDirectory(projectRoot, options.outputDirectory));
|
|
24875
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
|
+
|
|
24876
24915
|
// src/mobile/androidUpgradeConformance.ts
|
|
24877
24916
|
import { performance as performance2 } from "perf_hooks";
|
|
24878
24917
|
var captureCommand4 = async (command) => {
|
|
@@ -24966,21 +25005,291 @@ var runAbsoluteAndroidUpgradeConformance = async (options) => {
|
|
|
24966
25005
|
state
|
|
24967
25006
|
};
|
|
24968
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
|
+
};
|
|
24969
25278
|
// src/mobile/iosRelease.ts
|
|
24970
|
-
import { createHash as
|
|
25279
|
+
import { createHash as createHash6 } from "crypto";
|
|
24971
25280
|
import {
|
|
24972
|
-
access as
|
|
25281
|
+
access as access7,
|
|
24973
25282
|
copyFile as copyFile3,
|
|
24974
|
-
mkdir as
|
|
24975
|
-
mkdtemp as
|
|
25283
|
+
mkdir as mkdir5,
|
|
25284
|
+
mkdtemp as mkdtemp4,
|
|
24976
25285
|
readdir as readdir3,
|
|
24977
|
-
readFile as
|
|
24978
|
-
rename as
|
|
24979
|
-
rm as
|
|
24980
|
-
stat as
|
|
24981
|
-
writeFile as
|
|
25286
|
+
readFile as readFile7,
|
|
25287
|
+
rename as rename6,
|
|
25288
|
+
rm as rm5,
|
|
25289
|
+
stat as stat3,
|
|
25290
|
+
writeFile as writeFile6
|
|
24982
25291
|
} from "fs/promises";
|
|
24983
|
-
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";
|
|
24984
25293
|
var ABSOLUTE_IOS_RELEASE_FORMAT = 1;
|
|
24985
25294
|
var developmentTeamArgument = (value) => {
|
|
24986
25295
|
if (value === undefined)
|
|
@@ -24990,9 +25299,9 @@ var developmentTeamArgument = (value) => {
|
|
|
24990
25299
|
throw new TypeError("iOS development team must contain ten letters or digits.");
|
|
24991
25300
|
return `DEVELOPMENT_TEAM=${team}`;
|
|
24992
25301
|
};
|
|
24993
|
-
var
|
|
25302
|
+
var isRecord3 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
24994
25303
|
var requireManifest2 = (value) => {
|
|
24995
|
-
if (!
|
|
25304
|
+
if (!isRecord3(value) || typeof value.appBuild !== "string" || typeof value.appId !== "string" || typeof value.runtime !== "string") {
|
|
24996
25305
|
throw new TypeError("Invalid embedded AbsoluteJS mobile manifest.");
|
|
24997
25306
|
}
|
|
24998
25307
|
return {
|
|
@@ -25003,13 +25312,13 @@ var requireManifest2 = (value) => {
|
|
|
25003
25312
|
};
|
|
25004
25313
|
var pathExists4 = async (path) => {
|
|
25005
25314
|
try {
|
|
25006
|
-
await
|
|
25315
|
+
await access7(path);
|
|
25007
25316
|
return true;
|
|
25008
25317
|
} catch {
|
|
25009
25318
|
return false;
|
|
25010
25319
|
}
|
|
25011
25320
|
};
|
|
25012
|
-
var
|
|
25321
|
+
var defaultRun2 = async (command, options = {}) => {
|
|
25013
25322
|
const process2 = Bun.spawn(command, {
|
|
25014
25323
|
cwd: options.cwd,
|
|
25015
25324
|
env: options.env,
|
|
@@ -25050,8 +25359,8 @@ var ignoredFingerprintDirectories = new Set([
|
|
|
25050
25359
|
var fingerprintFiles = async (root, current = root, options = {}) => {
|
|
25051
25360
|
const entries = await readdir3(current, { withFileTypes: true });
|
|
25052
25361
|
const nested = await Promise.all(entries.sort((left, right) => left.name.localeCompare(right.name)).map(async (entry) => {
|
|
25053
|
-
const path =
|
|
25054
|
-
const projectRelative =
|
|
25362
|
+
const path = join7(current, entry.name);
|
|
25363
|
+
const projectRelative = relative5(root, path).replaceAll("\\", "/");
|
|
25055
25364
|
const ignored = entry.isDirectory() && (ignoredFingerprintDirectories.has(entry.name) || projectRelative === "App/App/public" && options.includePublicBundle !== true);
|
|
25056
25365
|
if (ignored)
|
|
25057
25366
|
return [];
|
|
@@ -25062,11 +25371,11 @@ var fingerprintFiles = async (root, current = root, options = {}) => {
|
|
|
25062
25371
|
return nested.flat();
|
|
25063
25372
|
};
|
|
25064
25373
|
var fingerprintAbsoluteIosNativeProject = async (nativeDirectory, options = {}) => {
|
|
25065
|
-
const hasher =
|
|
25374
|
+
const hasher = createHash6("sha256");
|
|
25066
25375
|
const files = await fingerprintFiles(nativeDirectory, nativeDirectory, options);
|
|
25067
|
-
const contents = await Promise.all(files.map((file) =>
|
|
25376
|
+
const contents = await Promise.all(files.map((file) => readFile7(file)));
|
|
25068
25377
|
files.forEach((file, index) => {
|
|
25069
|
-
hasher.update(
|
|
25378
|
+
hasher.update(relative5(nativeDirectory, file).replaceAll("\\", "/"));
|
|
25070
25379
|
hasher.update("\x00");
|
|
25071
25380
|
hasher.update(contents[index] ?? new Uint8Array);
|
|
25072
25381
|
hasher.update("\x00");
|
|
@@ -25074,21 +25383,21 @@ var fingerprintAbsoluteIosNativeProject = async (nativeDirectory, options = {})
|
|
|
25074
25383
|
return hasher.digest("hex");
|
|
25075
25384
|
};
|
|
25076
25385
|
var safeOutputDirectory2 = (projectRoot, requested) => {
|
|
25077
|
-
const root =
|
|
25078
|
-
const output =
|
|
25079
|
-
const projectRelative =
|
|
25080
|
-
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)) {
|
|
25081
25390
|
throw new TypeError("mobile build --outdir must remain inside the project.");
|
|
25082
25391
|
}
|
|
25083
25392
|
return output;
|
|
25084
25393
|
};
|
|
25085
|
-
var sha256File2 = async (path) =>
|
|
25394
|
+
var sha256File2 = async (path) => createHash6("sha256").update(await readFile7(path)).digest("hex");
|
|
25086
25395
|
var findByExtension = async (root, extension) => {
|
|
25087
25396
|
if (!await pathExists4(root))
|
|
25088
25397
|
return;
|
|
25089
25398
|
const entries = await readdir3(root, { withFileTypes: true });
|
|
25090
25399
|
const matches2 = await Promise.all(entries.map(async (entry) => {
|
|
25091
|
-
const path =
|
|
25400
|
+
const path = join7(root, entry.name);
|
|
25092
25401
|
if (entry.isDirectory() && entry.name.endsWith(extension))
|
|
25093
25402
|
return path;
|
|
25094
25403
|
if (entry.isFile() && entry.name.endsWith(extension))
|
|
@@ -25102,7 +25411,7 @@ var findAllByExtension = async (root, extension, options = {}) => {
|
|
|
25102
25411
|
return [];
|
|
25103
25412
|
const entries = await readdir3(root, { withFileTypes: true });
|
|
25104
25413
|
const matches2 = await Promise.all(entries.map(async (entry) => {
|
|
25105
|
-
const path =
|
|
25414
|
+
const path = join7(root, entry.name);
|
|
25106
25415
|
if (entry.name.endsWith(extension))
|
|
25107
25416
|
return [path];
|
|
25108
25417
|
if (!entry.isDirectory() || options.excludedDirectories?.has(entry.name))
|
|
@@ -25112,17 +25421,17 @@ var findAllByExtension = async (root, extension, options = {}) => {
|
|
|
25112
25421
|
return matches2.flat().sort();
|
|
25113
25422
|
};
|
|
25114
25423
|
var resolveAbsoluteIosXcodeProject = async (nativeDirectory, options = {}) => {
|
|
25115
|
-
const requestedWorkspace = options.workspacePath ?
|
|
25424
|
+
const requestedWorkspace = options.workspacePath ? resolve5(nativeDirectory, options.workspacePath) : undefined;
|
|
25116
25425
|
if (requestedWorkspace) {
|
|
25117
|
-
const requestedRelative =
|
|
25118
|
-
if (requestedRelative === ".." || requestedRelative.startsWith(`..${
|
|
25426
|
+
const requestedRelative = relative5(nativeDirectory, requestedWorkspace);
|
|
25427
|
+
if (requestedRelative === ".." || requestedRelative.startsWith(`..${sep4}`) || isAbsolute4(requestedRelative))
|
|
25119
25428
|
throw new TypeError("iOS release workspacePath must remain inside the native iOS project.");
|
|
25120
25429
|
}
|
|
25121
25430
|
const workspaces = requestedWorkspace ? [requestedWorkspace] : await findAllByExtension(nativeDirectory, ".xcworkspace", {
|
|
25122
25431
|
excludedDirectories: new Set(["Pods", "DerivedData", "build"])
|
|
25123
25432
|
});
|
|
25124
25433
|
if (workspaces.length !== 1)
|
|
25125
|
-
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.");
|
|
25126
25435
|
const [workspacePath] = workspaces;
|
|
25127
25436
|
if (!workspacePath || !await pathExists4(workspacePath))
|
|
25128
25437
|
throw new TypeError("iOS release could not find an Xcode workspace.");
|
|
@@ -25132,7 +25441,7 @@ var resolveAbsoluteIosXcodeProject = async (nativeDirectory, options = {}) => {
|
|
|
25132
25441
|
excludedDirectories: new Set(["Pods", "DerivedData", "build"])
|
|
25133
25442
|
});
|
|
25134
25443
|
const schemes = [
|
|
25135
|
-
...new Set(schemeFiles.map((path) => path.slice(path.lastIndexOf(
|
|
25444
|
+
...new Set(schemeFiles.map((path) => path.slice(path.lastIndexOf(sep4) + 1, -".xcscheme".length)))
|
|
25136
25445
|
];
|
|
25137
25446
|
if (schemes.length !== 1 || !schemes[0])
|
|
25138
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.");
|
|
@@ -25155,7 +25464,7 @@ var requireBuildNumber = (value) => {
|
|
|
25155
25464
|
return value;
|
|
25156
25465
|
};
|
|
25157
25466
|
var requireAbsoluteIosReleaseMetadata = (value) => {
|
|
25158
|
-
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}`) {
|
|
25159
25468
|
throw new TypeError("Invalid AbsoluteJS iOS release metadata.");
|
|
25160
25469
|
}
|
|
25161
25470
|
return {
|
|
@@ -25176,18 +25485,18 @@ var requireAbsoluteIosReleaseMetadata = (value) => {
|
|
|
25176
25485
|
};
|
|
25177
25486
|
};
|
|
25178
25487
|
var installRelease2 = async (artifactPath, metadata, outputRoot) => {
|
|
25179
|
-
const releaseRoot =
|
|
25180
|
-
const destination =
|
|
25488
|
+
const releaseRoot = join7(outputRoot, metadata.releaseId);
|
|
25489
|
+
const destination = join7(releaseRoot, "App.ipa");
|
|
25181
25490
|
if (await pathExists4(releaseRoot)) {
|
|
25182
|
-
const value = JSON.parse(await
|
|
25183
|
-
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)) {
|
|
25184
25493
|
throw new TypeError(`Immutable iOS release ${metadata.releaseId} does not match its content.`);
|
|
25185
25494
|
}
|
|
25186
|
-
const [bytes,
|
|
25187
|
-
|
|
25495
|
+
const [bytes, sha2562] = await Promise.all([
|
|
25496
|
+
stat3(destination).then(({ size }) => size),
|
|
25188
25497
|
sha256File2(destination)
|
|
25189
25498
|
]);
|
|
25190
|
-
if (bytes !== metadata.bytes ||
|
|
25499
|
+
if (bytes !== metadata.bytes || sha2562 !== metadata.sha256)
|
|
25191
25500
|
throw new TypeError(`Immutable iOS release ${metadata.releaseId} artifact is missing or modified.`);
|
|
25192
25501
|
return {
|
|
25193
25502
|
artifactPath: destination,
|
|
@@ -25198,20 +25507,20 @@ var installRelease2 = async (artifactPath, metadata, outputRoot) => {
|
|
|
25198
25507
|
releaseRoot
|
|
25199
25508
|
};
|
|
25200
25509
|
}
|
|
25201
|
-
await
|
|
25202
|
-
const staging = await
|
|
25510
|
+
await mkdir5(dirname4(releaseRoot), { recursive: true });
|
|
25511
|
+
const staging = await mkdtemp4(join7(dirname4(releaseRoot), ".ios-stage-"));
|
|
25203
25512
|
try {
|
|
25204
|
-
await copyFile3(artifactPath,
|
|
25513
|
+
await copyFile3(artifactPath, join7(staging, "App.ipa"));
|
|
25205
25514
|
const complete = {
|
|
25206
25515
|
...metadata,
|
|
25207
25516
|
artifact: "App.ipa"
|
|
25208
25517
|
};
|
|
25209
|
-
await
|
|
25518
|
+
await writeFile6(join7(staging, "release.json"), `${JSON.stringify(complete, null, "\t")}
|
|
25210
25519
|
`, { flag: "wx" });
|
|
25211
|
-
await
|
|
25520
|
+
await rename6(staging, releaseRoot);
|
|
25212
25521
|
return { artifactPath: destination, metadata: complete, releaseRoot };
|
|
25213
25522
|
} finally {
|
|
25214
|
-
await
|
|
25523
|
+
await rm5(staging, { force: true, recursive: true }).catch(() => {
|
|
25215
25524
|
return;
|
|
25216
25525
|
});
|
|
25217
25526
|
}
|
|
@@ -25224,10 +25533,10 @@ var buildAbsoluteIosRelease = async (options) => {
|
|
|
25224
25533
|
const marketingVersion = options.config.iosVersion;
|
|
25225
25534
|
if (!marketingVersion)
|
|
25226
25535
|
throw new TypeError("iOS release builds require mobile.ios.version in absolutejs.config.ts.");
|
|
25227
|
-
const manifest = requireManifest2(JSON.parse(await
|
|
25536
|
+
const manifest = requireManifest2(JSON.parse(await readFile7(join7(options.config.bundleDirectory, "absolute-mobile-manifest.json"), "utf8")));
|
|
25228
25537
|
if (manifest.appId !== options.config.appId)
|
|
25229
25538
|
throw new TypeError("Embedded mobile manifest appId does not match mobile.appId.");
|
|
25230
|
-
const nativeDirectory =
|
|
25539
|
+
const nativeDirectory = join7(options.config.nativeProjectDirectory, "ios");
|
|
25231
25540
|
const xcode = await resolveAbsoluteIosXcodeProject(nativeDirectory, {
|
|
25232
25541
|
scheme: options.scheme,
|
|
25233
25542
|
workspacePath: options.workspacePath
|
|
@@ -25235,18 +25544,18 @@ var buildAbsoluteIosRelease = async (options) => {
|
|
|
25235
25544
|
let buildNumber = requireBuildNumber(options.buildNumber);
|
|
25236
25545
|
if (options.prepareBuildNumber) {
|
|
25237
25546
|
const nativeFingerprint = await fingerprintAbsoluteIosNativeProject(nativeDirectory);
|
|
25238
|
-
const buildIdentity =
|
|
25547
|
+
const buildIdentity = createHash6("sha256").update(`${manifest.appBuild}\x00${nativeFingerprint}\x00${marketingVersion}`).digest("hex");
|
|
25239
25548
|
buildNumber = requireBuildNumber(await options.prepareBuildNumber(buildIdentity));
|
|
25240
25549
|
}
|
|
25241
|
-
const stagingParent =
|
|
25242
|
-
await
|
|
25243
|
-
const staging = await
|
|
25244
|
-
const archivePath =
|
|
25245
|
-
const exportPath =
|
|
25246
|
-
const exportPlist =
|
|
25247
|
-
await
|
|
25248
|
-
await
|
|
25249
|
-
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;
|
|
25250
25559
|
try {
|
|
25251
25560
|
const developmentTeam = developmentTeamArgument(options.developmentTeam);
|
|
25252
25561
|
const versionArguments = [
|
|
@@ -25271,7 +25580,7 @@ var buildAbsoluteIosRelease = async (options) => {
|
|
|
25271
25580
|
], { cwd: nativeDirectory, env: options.env });
|
|
25272
25581
|
if (archiveExit !== 0)
|
|
25273
25582
|
throw new TypeError("Xcode failed to archive the iOS app.");
|
|
25274
|
-
const archivedApp = await findByExtension(
|
|
25583
|
+
const archivedApp = await findByExtension(join7(archivePath, "Products", "Applications"), ".app");
|
|
25275
25584
|
const capture = options.capture ?? defaultCapture2;
|
|
25276
25585
|
const signed = archivedApp ? capture([
|
|
25277
25586
|
"codesign",
|
|
@@ -25297,11 +25606,11 @@ var buildAbsoluteIosRelease = async (options) => {
|
|
|
25297
25606
|
const artifactPath = await findByExtension(exportPath, ".ipa");
|
|
25298
25607
|
if (!artifactPath)
|
|
25299
25608
|
throw new TypeError("Xcode did not produce an exported IPA.");
|
|
25300
|
-
const [bytes,
|
|
25301
|
-
|
|
25609
|
+
const [bytes, sha2562] = await Promise.all([
|
|
25610
|
+
stat3(artifactPath).then(({ size }) => size),
|
|
25302
25611
|
sha256File2(artifactPath)
|
|
25303
25612
|
]);
|
|
25304
|
-
const releaseId = `amobile_ios_${
|
|
25613
|
+
const releaseId = `amobile_ios_${sha2562}`;
|
|
25305
25614
|
return await installRelease2(artifactPath, {
|
|
25306
25615
|
appBuild: manifest.appBuild,
|
|
25307
25616
|
appId: manifest.appId,
|
|
@@ -25313,23 +25622,23 @@ var buildAbsoluteIosRelease = async (options) => {
|
|
|
25313
25622
|
platform: "ios",
|
|
25314
25623
|
releaseId,
|
|
25315
25624
|
runtime: manifest.runtime,
|
|
25316
|
-
sha256,
|
|
25625
|
+
sha256: sha2562,
|
|
25317
25626
|
signed,
|
|
25318
25627
|
type: "ipa"
|
|
25319
25628
|
}, safeOutputDirectory2(options.projectRoot, options.outputDirectory));
|
|
25320
25629
|
} finally {
|
|
25321
|
-
await
|
|
25630
|
+
await rm5(staging, { force: true, recursive: true }).catch(() => {
|
|
25322
25631
|
return;
|
|
25323
25632
|
});
|
|
25324
25633
|
}
|
|
25325
25634
|
};
|
|
25326
25635
|
var installAbsoluteIosRelease = async (options) => {
|
|
25327
25636
|
const metadata = requireAbsoluteIosReleaseMetadata(options.metadata);
|
|
25328
|
-
const [bytes,
|
|
25329
|
-
|
|
25637
|
+
const [bytes, sha2562] = await Promise.all([
|
|
25638
|
+
stat3(options.artifactPath).then(({ size }) => size),
|
|
25330
25639
|
sha256File2(options.artifactPath)
|
|
25331
25640
|
]);
|
|
25332
|
-
if (bytes !== metadata.bytes ||
|
|
25641
|
+
if (bytes !== metadata.bytes || sha2562 !== metadata.sha256)
|
|
25333
25642
|
throw new TypeError("Remote iOS release artifact does not match its signed metadata.");
|
|
25334
25643
|
const { artifact: _artifact, ...releaseMetadata } = metadata;
|
|
25335
25644
|
return installRelease2(options.artifactPath, releaseMetadata, safeOutputDirectory2(options.projectRoot, options.outputDirectory));
|
|
@@ -25405,7 +25714,7 @@ var assertAbsoluteIosInstalledAppUpgrade = (before, after) => {
|
|
|
25405
25714
|
throw new Error(`iOS CFBundleVersion did not increase (${before.buildNumber} -> ${after.buildNumber}).`);
|
|
25406
25715
|
};
|
|
25407
25716
|
// src/mobile/iosConformance.ts
|
|
25408
|
-
import { readFile as
|
|
25717
|
+
import { readFile as readFile8, stat as stat4 } from "fs/promises";
|
|
25409
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");
|
|
25410
25719
|
var parseAbsoluteIosHmrLog = (line) => {
|
|
25411
25720
|
const match = HMR_LINE.exec(line);
|
|
@@ -25437,13 +25746,13 @@ var waitForAbsoluteIosHmrLog = async (options) => {
|
|
|
25437
25746
|
const sleep = options.sleep ?? Bun.sleep;
|
|
25438
25747
|
const timeoutMs = options.timeoutMs ?? 30000;
|
|
25439
25748
|
const deadline = Date.now() + timeoutMs;
|
|
25440
|
-
let offset = options.startOffset ?? await
|
|
25749
|
+
let offset = options.startOffset ?? await stat4(options.logPath).then(({ size }) => size).catch(() => 0);
|
|
25441
25750
|
let buffered = "";
|
|
25442
25751
|
const poll = async () => {
|
|
25443
25752
|
if (Date.now() > deadline)
|
|
25444
25753
|
throw new Error(`No iOS native HMR acknowledgement was observed within ${timeoutMs}ms.`);
|
|
25445
25754
|
options.signal?.throwIfAborted();
|
|
25446
|
-
const contents = await
|
|
25755
|
+
const contents = await readFile8(options.logPath).catch(() => Buffer.alloc(0));
|
|
25447
25756
|
if (contents.byteLength < offset) {
|
|
25448
25757
|
offset = 0;
|
|
25449
25758
|
buffered = "";
|
|
@@ -25463,28 +25772,28 @@ var waitForAbsoluteIosHmrLog = async (options) => {
|
|
|
25463
25772
|
return poll();
|
|
25464
25773
|
};
|
|
25465
25774
|
// src/mobile/iosSimulatorController.ts
|
|
25466
|
-
import { createHash as
|
|
25775
|
+
import { createHash as createHash7, randomUUID as randomUUID3 } from "crypto";
|
|
25467
25776
|
import {
|
|
25468
|
-
access as
|
|
25777
|
+
access as access8,
|
|
25469
25778
|
copyFile as copyFile4,
|
|
25470
|
-
mkdir as
|
|
25471
|
-
readFile as
|
|
25472
|
-
rename as
|
|
25473
|
-
rm as
|
|
25474
|
-
writeFile as
|
|
25779
|
+
mkdir as mkdir6,
|
|
25780
|
+
readFile as readFile9,
|
|
25781
|
+
rename as rename7,
|
|
25782
|
+
rm as rm6,
|
|
25783
|
+
writeFile as writeFile7
|
|
25475
25784
|
} from "fs/promises";
|
|
25476
25785
|
import { isIP as isIP2 } from "net";
|
|
25477
|
-
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";
|
|
25478
25787
|
init_getDurationString();
|
|
25479
25788
|
var ABSOLUTE_IOS_SIMULATOR_NAME = "AbsoluteJS iPhone";
|
|
25480
25789
|
var BOOT_TIMEOUT_MS = 180000;
|
|
25481
25790
|
var BOOT_POLL_MS = 1000;
|
|
25482
25791
|
var DEV_JOURNAL_FORMAT = 1;
|
|
25483
25792
|
var NATIVE_CACHE_FORMAT = 1;
|
|
25484
|
-
var
|
|
25793
|
+
var isRecord4 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
25485
25794
|
var pathExists5 = async (path) => {
|
|
25486
25795
|
try {
|
|
25487
|
-
await
|
|
25796
|
+
await access8(path);
|
|
25488
25797
|
return true;
|
|
25489
25798
|
} catch {
|
|
25490
25799
|
return false;
|
|
@@ -25513,7 +25822,7 @@ var defaultCapture3 = (command, options = {}) => {
|
|
|
25513
25822
|
};
|
|
25514
25823
|
}
|
|
25515
25824
|
};
|
|
25516
|
-
var
|
|
25825
|
+
var defaultRun3 = async (command, options = {}) => {
|
|
25517
25826
|
const process2 = Bun.spawn(command, {
|
|
25518
25827
|
cwd: options.cwd,
|
|
25519
25828
|
env: options.env,
|
|
@@ -25579,7 +25888,7 @@ var defaultStartNativeLogs = (command, options, onLine) => {
|
|
|
25579
25888
|
}
|
|
25580
25889
|
};
|
|
25581
25890
|
};
|
|
25582
|
-
var
|
|
25891
|
+
var requireSuccess3 = async (command, label, run, options) => {
|
|
25583
25892
|
const exitCode = await run(command, options);
|
|
25584
25893
|
if (exitCode !== 0)
|
|
25585
25894
|
throw new Error(`${label} failed with status ${exitCode}.`);
|
|
@@ -25590,7 +25899,7 @@ var trustIosSimulatorDevelopmentCa = async (options, udid, run, log) => {
|
|
|
25590
25899
|
if (!options.certificateAuthorityPath) {
|
|
25591
25900
|
throw new Error("iOS Simulator HTTPS requires the AbsoluteJS development CA certificate.");
|
|
25592
25901
|
}
|
|
25593
|
-
await
|
|
25902
|
+
await requireSuccess3([
|
|
25594
25903
|
options.project.xcrun,
|
|
25595
25904
|
"simctl",
|
|
25596
25905
|
"keychain",
|
|
@@ -25627,7 +25936,7 @@ var requireCapturedSuccess = (result, label) => {
|
|
|
25627
25936
|
var parseJson = (source, label) => {
|
|
25628
25937
|
try {
|
|
25629
25938
|
const parsed = JSON.parse(source);
|
|
25630
|
-
if (
|
|
25939
|
+
if (isRecord4(parsed))
|
|
25631
25940
|
return parsed;
|
|
25632
25941
|
} catch {}
|
|
25633
25942
|
throw new Error(`Invalid ${label} JSON from simctl.`);
|
|
@@ -25638,7 +25947,7 @@ var parseIosDeviceTypes = (source) => {
|
|
|
25638
25947
|
if (!Array.isArray(types))
|
|
25639
25948
|
return [];
|
|
25640
25949
|
return types.flatMap((type) => {
|
|
25641
|
-
if (!
|
|
25950
|
+
if (!isRecord4(type))
|
|
25642
25951
|
return [];
|
|
25643
25952
|
const { identifier } = type;
|
|
25644
25953
|
const { name } = type;
|
|
@@ -25651,7 +25960,7 @@ var parseIosRuntimes = (source) => {
|
|
|
25651
25960
|
if (!Array.isArray(runtimes))
|
|
25652
25961
|
return [];
|
|
25653
25962
|
return runtimes.flatMap((runtime) => {
|
|
25654
|
-
if (!
|
|
25963
|
+
if (!isRecord4(runtime))
|
|
25655
25964
|
return [];
|
|
25656
25965
|
const { identifier } = runtime;
|
|
25657
25966
|
const { name } = runtime;
|
|
@@ -25671,13 +25980,13 @@ var parseIosRuntimes = (source) => {
|
|
|
25671
25980
|
var parseIosSimulators = (source) => {
|
|
25672
25981
|
const parsed = parseJson(source, "device");
|
|
25673
25982
|
const { devices } = parsed;
|
|
25674
|
-
if (!
|
|
25983
|
+
if (!isRecord4(devices))
|
|
25675
25984
|
return [];
|
|
25676
25985
|
return Object.entries(devices).flatMap(([runtime, values]) => {
|
|
25677
25986
|
if (!Array.isArray(values))
|
|
25678
25987
|
return [];
|
|
25679
25988
|
return values.flatMap((device) => {
|
|
25680
|
-
if (!
|
|
25989
|
+
if (!isRecord4(device))
|
|
25681
25990
|
return [];
|
|
25682
25991
|
const { name } = device;
|
|
25683
25992
|
const { state } = device;
|
|
@@ -25719,21 +26028,21 @@ var preferredIphoneType = (types) => types.filter((type) => type.name.startsWith
|
|
|
25719
26028
|
return rightPro - leftPro;
|
|
25720
26029
|
})[0];
|
|
25721
26030
|
var journalPaths = (projectRoot) => {
|
|
25722
|
-
const root =
|
|
26031
|
+
const root = join8(projectRoot, ".absolutejs", "mobile", "ios-dev-session");
|
|
25723
26032
|
return {
|
|
25724
|
-
configBackup:
|
|
25725
|
-
infoBackup:
|
|
25726
|
-
journal:
|
|
26033
|
+
configBackup: join8(root, "capacitor-config.backup"),
|
|
26034
|
+
infoBackup: join8(root, "Info.plist.backup"),
|
|
26035
|
+
journal: join8(root, "journal.json"),
|
|
25727
26036
|
root
|
|
25728
26037
|
};
|
|
25729
26038
|
};
|
|
25730
|
-
var nativeCachePath = (projectRoot) =>
|
|
26039
|
+
var nativeCachePath = (projectRoot) => join8(projectRoot, ".absolutejs", "mobile", "ios-native-cache.json");
|
|
25731
26040
|
var isInside = (root, path) => {
|
|
25732
|
-
const value =
|
|
25733
|
-
return value === "" || !value.startsWith(`..${
|
|
26041
|
+
const value = relative6(resolve6(root), resolve6(path));
|
|
26042
|
+
return value === "" || !value.startsWith(`..${sep5}`) && value !== ".." && !isAbsolute5(value);
|
|
25734
26043
|
};
|
|
25735
26044
|
var parseJournal = (value) => {
|
|
25736
|
-
if (!
|
|
26045
|
+
if (!isRecord4(value) || value.format !== DEV_JOURNAL_FORMAT)
|
|
25737
26046
|
return null;
|
|
25738
26047
|
const { configBackupPath } = value;
|
|
25739
26048
|
const { infoBackupPath } = value;
|
|
@@ -25752,10 +26061,10 @@ var parseJournal = (value) => {
|
|
|
25752
26061
|
var repairAbsoluteIosDevSession = async (projectRoot) => {
|
|
25753
26062
|
const paths = journalPaths(projectRoot);
|
|
25754
26063
|
if (!await pathExists5(paths.journal)) {
|
|
25755
|
-
await
|
|
26064
|
+
await rm6(paths.root, { force: true, recursive: true });
|
|
25756
26065
|
return false;
|
|
25757
26066
|
}
|
|
25758
|
-
const journal = await
|
|
26067
|
+
const journal = await readFile9(paths.journal, "utf8").then((source) => parseJournal(JSON.parse(source))).catch(() => null);
|
|
25759
26068
|
if (!journal || !isInside(projectRoot, journal.nativeConfigPath) || !isInside(projectRoot, journal.infoPath) || !isInside(paths.root, journal.configBackupPath) || !isInside(paths.root, journal.infoBackupPath)) {
|
|
25760
26069
|
throw new Error(`Refusing unsafe or invalid iOS dev journal at ${paths.journal}.`);
|
|
25761
26070
|
}
|
|
@@ -25763,7 +26072,7 @@ var repairAbsoluteIosDevSession = async (projectRoot) => {
|
|
|
25763
26072
|
await copyFile4(journal.configBackupPath, journal.nativeConfigPath);
|
|
25764
26073
|
if (await pathExists5(journal.infoBackupPath))
|
|
25765
26074
|
await copyFile4(journal.infoBackupPath, journal.infoPath);
|
|
25766
|
-
await
|
|
26075
|
+
await rm6(paths.root, { force: true, recursive: true });
|
|
25767
26076
|
return true;
|
|
25768
26077
|
};
|
|
25769
26078
|
var iosDevelopmentInfoPlist = (source, cleartext) => {
|
|
@@ -25789,19 +26098,19 @@ var iosDevelopmentInfoPlist = (source, cleartext) => {
|
|
|
25789
26098
|
var writeDevProjection = async (project, port, https, serverHost = "localhost") => {
|
|
25790
26099
|
const paths = journalPaths(project.projectRoot);
|
|
25791
26100
|
await repairAbsoluteIosDevSession(project.projectRoot);
|
|
25792
|
-
const nativeConfigPath =
|
|
25793
|
-
const infoPath =
|
|
26101
|
+
const nativeConfigPath = join8(project.nativeDirectory, "App", "App", "capacitor.config.json");
|
|
26102
|
+
const infoPath = join8(project.nativeDirectory, "App", "App", "Info.plist");
|
|
25794
26103
|
const [configSource, infoSource] = await Promise.all([
|
|
25795
|
-
|
|
25796
|
-
|
|
26104
|
+
readFile9(nativeConfigPath, "utf8"),
|
|
26105
|
+
readFile9(infoPath, "utf8")
|
|
25797
26106
|
]);
|
|
25798
26107
|
const parsed = JSON.parse(configSource);
|
|
25799
|
-
if (!
|
|
26108
|
+
if (!isRecord4(parsed))
|
|
25800
26109
|
throw new Error(`Invalid Capacitor native config at ${nativeConfigPath}.`);
|
|
25801
|
-
await
|
|
26110
|
+
await mkdir6(paths.root, { recursive: true });
|
|
25802
26111
|
await Promise.all([
|
|
25803
|
-
|
|
25804
|
-
|
|
26112
|
+
writeFile7(paths.configBackup, configSource, { flag: "wx" }),
|
|
26113
|
+
writeFile7(paths.infoBackup, infoSource, { flag: "wx" })
|
|
25805
26114
|
]);
|
|
25806
26115
|
const journal = {
|
|
25807
26116
|
configBackupPath: paths.configBackup,
|
|
@@ -25810,7 +26119,7 @@ var writeDevProjection = async (project, port, https, serverHost = "localhost")
|
|
|
25810
26119
|
infoPath,
|
|
25811
26120
|
nativeConfigPath
|
|
25812
26121
|
};
|
|
25813
|
-
await
|
|
26122
|
+
await writeFile7(paths.journal, `${JSON.stringify(journal, null, "\t")}
|
|
25814
26123
|
`, {
|
|
25815
26124
|
flag: "wx"
|
|
25816
26125
|
});
|
|
@@ -25819,21 +26128,21 @@ var writeDevProjection = async (project, port, https, serverHost = "localhost")
|
|
|
25819
26128
|
developmentUrl.searchParams.set("__absolute_target", "capacitor-ios");
|
|
25820
26129
|
const existingServer = parsed.server;
|
|
25821
26130
|
parsed.server = {
|
|
25822
|
-
...
|
|
26131
|
+
...isRecord4(existingServer) ? existingServer : {},
|
|
25823
26132
|
cleartext: !https,
|
|
25824
26133
|
url: developmentUrl.href
|
|
25825
26134
|
};
|
|
25826
26135
|
await Promise.all([
|
|
25827
|
-
|
|
26136
|
+
writeFile7(nativeConfigPath, `${JSON.stringify(parsed, null, "\t")}
|
|
25828
26137
|
`),
|
|
25829
|
-
|
|
26138
|
+
writeFile7(infoPath, iosDevelopmentInfoPlist(infoSource, !https))
|
|
25830
26139
|
]);
|
|
25831
26140
|
};
|
|
25832
26141
|
var parseNativeCache = (value) => {
|
|
25833
|
-
if (!
|
|
26142
|
+
if (!isRecord4(value))
|
|
25834
26143
|
return null;
|
|
25835
26144
|
const { appId, fingerprint, format, installations } = value;
|
|
25836
|
-
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"))
|
|
25837
26146
|
return null;
|
|
25838
26147
|
return {
|
|
25839
26148
|
appId,
|
|
@@ -25845,19 +26154,19 @@ var parseNativeCache = (value) => {
|
|
|
25845
26154
|
]))
|
|
25846
26155
|
};
|
|
25847
26156
|
};
|
|
25848
|
-
var readNativeCache = (projectRoot) =>
|
|
26157
|
+
var readNativeCache = (projectRoot) => readFile9(nativeCachePath(projectRoot), "utf8").then((source) => parseNativeCache(JSON.parse(source))).catch(() => null);
|
|
25849
26158
|
var writeNativeCache = async (projectRoot, cache) => {
|
|
25850
26159
|
const destination = nativeCachePath(projectRoot);
|
|
25851
26160
|
const temporary = `${destination}.${process.pid}.${randomUUID3()}.tmp`;
|
|
25852
|
-
await
|
|
26161
|
+
await mkdir6(dirname5(destination), { recursive: true });
|
|
25853
26162
|
try {
|
|
25854
|
-
await
|
|
26163
|
+
await writeFile7(temporary, `${JSON.stringify(cache, null, "\t")}
|
|
25855
26164
|
`, {
|
|
25856
26165
|
flag: "wx"
|
|
25857
26166
|
});
|
|
25858
|
-
await
|
|
26167
|
+
await rename7(temporary, destination);
|
|
25859
26168
|
} finally {
|
|
25860
|
-
await
|
|
26169
|
+
await rm6(temporary, { force: true }).catch(() => {
|
|
25861
26170
|
return;
|
|
25862
26171
|
});
|
|
25863
26172
|
}
|
|
@@ -25963,12 +26272,12 @@ var physicalIosAppIsInstalled = (project, identifier, capture) => {
|
|
|
25963
26272
|
return result.exitCode === 0 && result.stdout.includes(project.config.appId);
|
|
25964
26273
|
};
|
|
25965
26274
|
var buildIosDebugApp = async (project, udid, fingerprint, run, signal) => {
|
|
25966
|
-
const derivedDataPath =
|
|
25967
|
-
await
|
|
25968
|
-
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([
|
|
25969
26278
|
project.xcodebuild,
|
|
25970
26279
|
"-workspace",
|
|
25971
|
-
|
|
26280
|
+
join8(project.nativeDirectory, "App", "App.xcworkspace"),
|
|
25972
26281
|
"-scheme",
|
|
25973
26282
|
"App",
|
|
25974
26283
|
"-configuration",
|
|
@@ -25979,18 +26288,18 @@ var buildIosDebugApp = async (project, udid, fingerprint, run, signal) => {
|
|
|
25979
26288
|
derivedDataPath,
|
|
25980
26289
|
"build"
|
|
25981
26290
|
], "iOS simulator build", run, { cwd: project.nativeDirectory, signal });
|
|
25982
|
-
const appPath =
|
|
26291
|
+
const appPath = join8(derivedDataPath, "Build", "Products", "Debug-iphonesimulator", "App.app");
|
|
25983
26292
|
if (!await pathExists5(appPath))
|
|
25984
26293
|
throw new Error(`Xcode did not produce the simulator app at ${appPath}.`);
|
|
25985
26294
|
return appPath;
|
|
25986
26295
|
};
|
|
25987
26296
|
var buildPhysicalIosDebugApp = async (project, identifier, run, signal) => {
|
|
25988
|
-
const derivedDataPath =
|
|
25989
|
-
await
|
|
25990
|
-
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([
|
|
25991
26300
|
project.xcodebuild,
|
|
25992
26301
|
"-workspace",
|
|
25993
|
-
|
|
26302
|
+
join8(project.nativeDirectory, "App", "App.xcworkspace"),
|
|
25994
26303
|
"-scheme",
|
|
25995
26304
|
"App",
|
|
25996
26305
|
"-configuration",
|
|
@@ -26002,7 +26311,7 @@ var buildPhysicalIosDebugApp = async (project, identifier, run, signal) => {
|
|
|
26002
26311
|
"-allowProvisioningUpdates",
|
|
26003
26312
|
"build"
|
|
26004
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 });
|
|
26005
|
-
const appPath =
|
|
26314
|
+
const appPath = join8(derivedDataPath, "Build", "Products", "Debug-iphoneos", "App.app");
|
|
26006
26315
|
if (!await pathExists5(appPath))
|
|
26007
26316
|
throw new Error(`Xcode did not produce the physical-device app at ${appPath}.`);
|
|
26008
26317
|
return appPath;
|
|
@@ -26018,7 +26327,7 @@ var ensurePhysicalIosDebugApp = async (options) => {
|
|
|
26018
26327
|
const appPath = await buildPhysicalIosDebugApp(options.project, options.identifier, options.run, options.signal);
|
|
26019
26328
|
throwIfAborted2(options.signal);
|
|
26020
26329
|
options.transition("installing");
|
|
26021
|
-
await
|
|
26330
|
+
await requireSuccess3([
|
|
26022
26331
|
options.project.xcrun,
|
|
26023
26332
|
"devicectl",
|
|
26024
26333
|
"device",
|
|
@@ -26051,7 +26360,7 @@ var ensureIosDebugApp = async (options) => {
|
|
|
26051
26360
|
const appPath = await buildIosDebugApp(options.project, options.udid, options.fingerprint, options.run, options.signal);
|
|
26052
26361
|
throwIfAborted2(options.signal);
|
|
26053
26362
|
options.transition("installing");
|
|
26054
|
-
await
|
|
26363
|
+
await requireSuccess3([options.project.xcrun, "simctl", "install", options.udid, appPath], "iOS simulator app installation", options.run, { signal: options.signal });
|
|
26055
26364
|
const updated = installedAppIdentity(options.project, options.udid, options.capture);
|
|
26056
26365
|
if (updated) {
|
|
26057
26366
|
await writeNativeCache(options.project.projectRoot, {
|
|
@@ -26137,7 +26446,7 @@ var prepareAbsoluteIosDevProject = async (config, options) => {
|
|
|
26137
26446
|
if (detectAbsoluteMobileHost() !== "macos")
|
|
26138
26447
|
throw new Error("iOS development requires macOS and Xcode.");
|
|
26139
26448
|
const target = options.target ?? "simulator";
|
|
26140
|
-
const projectRoot =
|
|
26449
|
+
const projectRoot = resolve6(options.projectRoot);
|
|
26141
26450
|
const checks = await inspectAbsoluteMobileToolchain({ host: "macos" });
|
|
26142
26451
|
const failed = checks.filter((check) => check.platform === "ios" && !(target === "device" && check.id === "ios.runtime") && (check.status === "fail" || check.status === "warn"));
|
|
26143
26452
|
if (failed.length > 0)
|
|
@@ -26146,20 +26455,20 @@ var prepareAbsoluteIosDevProject = async (config, options) => {
|
|
|
26146
26455
|
const xcodebuild = checks.find((check) => check.id === "ios.xcodebuild")?.path;
|
|
26147
26456
|
if (!xcrun || !xcodebuild)
|
|
26148
26457
|
throw new Error("Xcode tools disappeared after readiness checks.");
|
|
26149
|
-
const cap =
|
|
26458
|
+
const cap = join8(projectRoot, "node_modules", ".bin", "cap");
|
|
26150
26459
|
if (!await pathExists5(cap))
|
|
26151
26460
|
throw new Error("Capacitor CLI is not installed. Run absolute mobile init first.");
|
|
26152
26461
|
await writeAbsoluteCapacitorConfig(config, { projectRoot });
|
|
26153
|
-
await
|
|
26154
|
-
const placeholder =
|
|
26462
|
+
await mkdir6(config.bundleDirectory, { recursive: true });
|
|
26463
|
+
const placeholder = join8(config.bundleDirectory, "index.html");
|
|
26155
26464
|
if (!await pathExists5(placeholder))
|
|
26156
|
-
await
|
|
26465
|
+
await writeFile7(placeholder, `<!doctype html><title>AbsoluteJS mobile development</title>
|
|
26157
26466
|
`);
|
|
26158
|
-
const nativeDirectory =
|
|
26467
|
+
const nativeDirectory = join8(config.nativeProjectDirectory, "ios");
|
|
26159
26468
|
if (!await pathExists5(nativeDirectory)) {
|
|
26160
26469
|
if (!options.createNativeProject)
|
|
26161
26470
|
throw new Error("iOS native project has not been created.");
|
|
26162
|
-
const run = options.run ??
|
|
26471
|
+
const run = options.run ?? defaultRun3;
|
|
26163
26472
|
if (await run([cap, "add", "ios"], { cwd: projectRoot }) !== 0)
|
|
26164
26473
|
throw new Error("Capacitor iOS project creation failed.");
|
|
26165
26474
|
}
|
|
@@ -26212,7 +26521,7 @@ var prepareIosSimulatorTarget = async (options) => {
|
|
|
26212
26521
|
]);
|
|
26213
26522
|
options.transition("connecting");
|
|
26214
26523
|
await waitForBootedSimulator(options.project, device.udid, options.capture, options.sleep, options.startOptions.signal);
|
|
26215
|
-
await
|
|
26524
|
+
await requireSuccess3([options.project.xcrun, "simctl", "bootstatus", device.udid, "-b"], "iOS simulator boot readiness", options.run, { signal: options.startOptions.signal });
|
|
26216
26525
|
await trustIosSimulatorDevelopmentCa(options.startOptions, device.udid, options.run, options.log);
|
|
26217
26526
|
return { caEnrollmentServer: null, startedSimulator, udid: device.udid };
|
|
26218
26527
|
};
|
|
@@ -26222,7 +26531,7 @@ var startAbsoluteIosDevSession = async (options) => {
|
|
|
26222
26531
|
const targetKind = deviceIdentifier ? "device" : "simulator";
|
|
26223
26532
|
const serverHost = deviceIdentifier ? normalizeAbsoluteIosDeviceHost(options.serverHost ?? "") : "localhost";
|
|
26224
26533
|
const capture = options.capture ?? defaultCapture3;
|
|
26225
|
-
const run = options.run ??
|
|
26534
|
+
const run = options.run ?? defaultRun3;
|
|
26226
26535
|
const sleep = options.sleep ?? Bun.sleep;
|
|
26227
26536
|
const spawn2 = options.spawn ?? defaultSpawn;
|
|
26228
26537
|
const log = options.log ?? console.log;
|
|
@@ -26262,13 +26571,13 @@ var startAbsoluteIosDevSession = async (options) => {
|
|
|
26262
26571
|
nativeLogs = attachNativeLogs(project, udid, options);
|
|
26263
26572
|
return;
|
|
26264
26573
|
}
|
|
26265
|
-
await
|
|
26574
|
+
await requireSuccess3(iosLaunchCommand(project, udid, deviceIdentifier !== undefined), "iOS app relaunch", run, { signal: options.signal });
|
|
26266
26575
|
};
|
|
26267
26576
|
try {
|
|
26268
26577
|
await repairAbsoluteIosDevSession(project.projectRoot);
|
|
26269
26578
|
throwIfAborted2(options.signal);
|
|
26270
26579
|
transition("syncing");
|
|
26271
|
-
await
|
|
26580
|
+
await requireSuccess3([project.cap, "sync", "ios"], "Capacitor iOS synchronization", run, { cwd: project.projectRoot, signal: options.signal });
|
|
26272
26581
|
transition("configuring");
|
|
26273
26582
|
if (options.embeddedBundle !== true)
|
|
26274
26583
|
await writeDevProjection(project, options.port, options.https === true, serverHost);
|
|
@@ -26334,7 +26643,7 @@ var startAbsoluteIosDevSession = async (options) => {
|
|
|
26334
26643
|
nativeLogs = attachNativeLogs(project, udid, options);
|
|
26335
26644
|
transition("launching");
|
|
26336
26645
|
if (!deviceIdentifier || !nativeLogs)
|
|
26337
|
-
await
|
|
26646
|
+
await requireSuccess3(iosLaunchCommand(project, udid, deviceIdentifier !== undefined), "iOS app launch", run, { signal: options.signal });
|
|
26338
26647
|
transition("ready");
|
|
26339
26648
|
timings.total = performance.now() - startedAt;
|
|
26340
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"}).`);
|
|
@@ -26383,11 +26692,11 @@ var startAbsoluteIosDevSession = async (options) => {
|
|
|
26383
26692
|
screenshot: async (destination) => {
|
|
26384
26693
|
if (deviceIdentifier)
|
|
26385
26694
|
throw new Error("Physical iOS screenshots are captured in Xcode Device Hub; the CLI never records a device screen automatically.");
|
|
26386
|
-
const resolved =
|
|
26695
|
+
const resolved = resolve6(project.projectRoot, destination);
|
|
26387
26696
|
if (!isInside(project.projectRoot, resolved))
|
|
26388
26697
|
throw new Error("iOS screenshot destination must remain inside the project.");
|
|
26389
|
-
await
|
|
26390
|
-
await
|
|
26698
|
+
await mkdir6(dirname5(resolved), { recursive: true });
|
|
26699
|
+
await requireSuccess3([
|
|
26391
26700
|
project.xcrun,
|
|
26392
26701
|
"simctl",
|
|
26393
26702
|
"io",
|
|
@@ -26413,7 +26722,7 @@ var startAbsoluteIosDevSession = async (options) => {
|
|
|
26413
26722
|
};
|
|
26414
26723
|
// src/mobile/iosNativeWatcher.ts
|
|
26415
26724
|
import { watch } from "fs";
|
|
26416
|
-
import { basename } from "path";
|
|
26725
|
+
import { basename as basename2 } from "path";
|
|
26417
26726
|
var NATIVE_CHANGE_DEBOUNCE_MS = 500;
|
|
26418
26727
|
var ROOT_NATIVE_INPUTS = new Set([
|
|
26419
26728
|
"absolute.config.js",
|
|
@@ -26503,28 +26812,28 @@ var createAbsoluteIosNativeWatcher = async (options) => {
|
|
|
26503
26812
|
options.signal?.addEventListener("abort", close, { once: true });
|
|
26504
26813
|
return { close };
|
|
26505
26814
|
};
|
|
26506
|
-
var isAbsoluteIosNativeRootInput = (path) => ROOT_NATIVE_INPUTS.has(
|
|
26815
|
+
var isAbsoluteIosNativeRootInput = (path) => ROOT_NATIVE_INPUTS.has(basename2(path));
|
|
26507
26816
|
// src/mobile/remoteMacProtocol.ts
|
|
26508
|
-
import { createHash as
|
|
26817
|
+
import { createHash as createHash8, randomUUID as randomUUID4 } from "crypto";
|
|
26509
26818
|
import {
|
|
26510
26819
|
chmod,
|
|
26511
|
-
mkdir as
|
|
26512
|
-
mkdtemp as
|
|
26513
|
-
readFile as
|
|
26514
|
-
rename as
|
|
26515
|
-
rm as
|
|
26516
|
-
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
|
|
26517
26826
|
} from "fs/promises";
|
|
26518
|
-
import { homedir as
|
|
26827
|
+
import { homedir as homedir3 } from "os";
|
|
26519
26828
|
import { isIP as isIP3 } from "net";
|
|
26520
26829
|
import {
|
|
26521
|
-
dirname as
|
|
26522
|
-
isAbsolute as
|
|
26523
|
-
join as
|
|
26830
|
+
dirname as dirname6,
|
|
26831
|
+
isAbsolute as isAbsolute6,
|
|
26832
|
+
join as join9,
|
|
26524
26833
|
posix,
|
|
26525
|
-
relative as
|
|
26834
|
+
relative as relative7,
|
|
26526
26835
|
resolve as resolvePath3,
|
|
26527
|
-
sep as
|
|
26836
|
+
sep as sep6
|
|
26528
26837
|
} from "path";
|
|
26529
26838
|
|
|
26530
26839
|
// src/mobile/remoteMacWire.ts
|
|
@@ -26539,14 +26848,14 @@ var REMOTE_RELEASE_LEASE_HEARTBEAT_MS = 15000;
|
|
|
26539
26848
|
var REMOTE_RELEASE_LEASE_STALE_SECONDS = 120;
|
|
26540
26849
|
var PROFILE_NAME = /^[a-z0-9](?:[a-z0-9._-]{0,62}[a-z0-9])?$/u;
|
|
26541
26850
|
var SSH_DESTINATION = /^(?:[A-Za-z0-9._-]+@)?[A-Za-z0-9._:-]+$/u;
|
|
26542
|
-
var defaultProfilePath = () =>
|
|
26851
|
+
var defaultProfilePath = () => join9(homedir3(), ".absolutejs", "mobile", "remote-macs.json");
|
|
26543
26852
|
var emptyStore = () => ({
|
|
26544
26853
|
format: PROFILE_FORMAT,
|
|
26545
26854
|
profiles: {}
|
|
26546
26855
|
});
|
|
26547
26856
|
var loadStore = async (path = defaultProfilePath()) => {
|
|
26548
26857
|
try {
|
|
26549
|
-
const parsed = JSON.parse(await
|
|
26858
|
+
const parsed = JSON.parse(await readFile10(path, "utf8"));
|
|
26550
26859
|
if (parsed.format !== PROFILE_FORMAT || typeof parsed.profiles !== "object" || parsed.profiles === null || Array.isArray(parsed.profiles))
|
|
26551
26860
|
throw new Error("Unsupported remote Mac profile format.");
|
|
26552
26861
|
for (const [key, profile] of Object.entries(parsed.profiles)) {
|
|
@@ -26563,13 +26872,13 @@ var loadStore = async (path = defaultProfilePath()) => {
|
|
|
26563
26872
|
}
|
|
26564
26873
|
};
|
|
26565
26874
|
var saveStore = async (store, path = defaultProfilePath()) => {
|
|
26566
|
-
await
|
|
26875
|
+
await mkdir7(dirname6(path), { recursive: true });
|
|
26567
26876
|
const temporary = `${path}.${randomUUID4()}.tmp`;
|
|
26568
|
-
await
|
|
26877
|
+
await writeFile8(temporary, `${JSON.stringify(store, null, 2)}
|
|
26569
26878
|
`, {
|
|
26570
26879
|
mode: 384
|
|
26571
26880
|
});
|
|
26572
|
-
await
|
|
26881
|
+
await rename8(temporary, path);
|
|
26573
26882
|
await chmod(path, 384);
|
|
26574
26883
|
};
|
|
26575
26884
|
var validateAbsoluteRemoteMacProfileName = (name) => {
|
|
@@ -26737,16 +27046,16 @@ var removeAbsoluteRemoteMacProfile = async (name, profilePath) => {
|
|
|
26737
27046
|
await saveStore(store, profilePath);
|
|
26738
27047
|
return true;
|
|
26739
27048
|
};
|
|
26740
|
-
var projectIdentity = (projectRoot, appId) =>
|
|
27049
|
+
var projectIdentity = (projectRoot, appId) => createHash8("sha256").update(`${resolvePath3(projectRoot)}\x00${appId}`).digest("hex").slice(0, 20);
|
|
26741
27050
|
var createAbsoluteRemoteExpoIosDevProject = (config, projectRoot, profile) => {
|
|
26742
27051
|
if (config.engine !== "expo")
|
|
26743
27052
|
throw new TypeError("Remote Expo execution requires mobile.engine: expo.");
|
|
26744
27053
|
return createAbsoluteRemoteIosDevProject(config, projectRoot, profile);
|
|
26745
27054
|
};
|
|
26746
27055
|
var createAbsoluteRemoteIosDevProject = (config, projectRoot, profile) => ({
|
|
26747
|
-
cap:
|
|
27056
|
+
cap: join9(resolvePath3(projectRoot), "node_modules", ".bin", "cap"),
|
|
26748
27057
|
config,
|
|
26749
|
-
nativeDirectory:
|
|
27058
|
+
nativeDirectory: join9(config.nativeProjectDirectory, "ios"),
|
|
26750
27059
|
profile,
|
|
26751
27060
|
projectRoot: resolvePath3(projectRoot),
|
|
26752
27061
|
remote: true,
|
|
@@ -26903,8 +27212,8 @@ var installAbsoluteRemoteMacAgent = async (project) => {
|
|
|
26903
27212
|
};
|
|
26904
27213
|
var materializeAbsoluteRemoteMacAgent = async (projectRoot) => {
|
|
26905
27214
|
const shippedCandidates = [
|
|
26906
|
-
|
|
26907
|
-
|
|
27215
|
+
join9(import.meta.dir, "remoteMacAgentEntry.js"),
|
|
27216
|
+
join9(import.meta.dir, "..", "mobile", "remoteMacAgentEntry.js")
|
|
26908
27217
|
];
|
|
26909
27218
|
let path;
|
|
26910
27219
|
for (const candidate of shippedCandidates) {
|
|
@@ -26915,14 +27224,14 @@ var materializeAbsoluteRemoteMacAgent = async (projectRoot) => {
|
|
|
26915
27224
|
}
|
|
26916
27225
|
if (!path) {
|
|
26917
27226
|
const sourceCandidates = [
|
|
26918
|
-
|
|
26919
|
-
|
|
27227
|
+
join9(import.meta.dir, "remoteMacAgentEntry.ts"),
|
|
27228
|
+
join9(import.meta.dir, "..", "..", "src", "mobile", "remoteMacAgentEntry.ts")
|
|
26920
27229
|
];
|
|
26921
27230
|
const source = await sourceCandidates.reduce(async (found, candidate) => await found ?? (await Bun.file(candidate).exists() ? candidate : undefined), Promise.resolve(undefined));
|
|
26922
27231
|
if (!source)
|
|
26923
27232
|
throw new Error("The AbsoluteJS installation does not contain its remote Mac agent artifact.");
|
|
26924
|
-
const outdir =
|
|
26925
|
-
await
|
|
27233
|
+
const outdir = join9(resolvePath3(projectRoot), ".absolutejs", "mobile", "remote-agent");
|
|
27234
|
+
await mkdir7(outdir, { recursive: true });
|
|
26926
27235
|
const result = await Bun.build({
|
|
26927
27236
|
entrypoints: [source],
|
|
26928
27237
|
minify: true,
|
|
@@ -26931,13 +27240,13 @@ var materializeAbsoluteRemoteMacAgent = async (projectRoot) => {
|
|
|
26931
27240
|
});
|
|
26932
27241
|
if (!result.success)
|
|
26933
27242
|
throw new AggregateError(result.logs, "Failed to build the AbsoluteJS remote Mac agent.");
|
|
26934
|
-
path =
|
|
27243
|
+
path = join9(outdir, "remoteMacAgentEntry.js");
|
|
26935
27244
|
}
|
|
26936
27245
|
const bytes = await Bun.file(path).arrayBuffer();
|
|
26937
|
-
const
|
|
26938
|
-
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 };
|
|
26939
27248
|
};
|
|
26940
|
-
var portableRelativePath = (root, path) =>
|
|
27249
|
+
var portableRelativePath = (root, path) => relative7(root, path).split(sep6).join(posix.sep);
|
|
26941
27250
|
var portableMobileConfig = (project) => ({
|
|
26942
27251
|
appId: project.config.appId,
|
|
26943
27252
|
appName: project.config.appName,
|
|
@@ -27118,9 +27427,9 @@ var writeRemoteArtifact = async (path, stream) => {
|
|
|
27118
27427
|
};
|
|
27119
27428
|
var retrieveAbsoluteRemoteIosRelease = async (project, metadata, outputDirectory) => {
|
|
27120
27429
|
const releaseRoot = posix.join(project.remoteProjectRoot, ".absolutejs", "mobile", "releases", "ios", metadata.releaseId);
|
|
27121
|
-
const stagingParent =
|
|
27122
|
-
await
|
|
27123
|
-
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-"));
|
|
27124
27433
|
try {
|
|
27125
27434
|
const remoteMetadata = requireRemoteSuccess(await defaultTransport.capture([
|
|
27126
27435
|
...absoluteRemoteMacSshBase(project.profile),
|
|
@@ -27130,7 +27439,7 @@ var retrieveAbsoluteRemoteIosRelease = async (project, metadata, outputDirectory
|
|
|
27130
27439
|
const downloadedMetadata = JSON.parse(remoteMetadata);
|
|
27131
27440
|
if (JSON.stringify(requireAbsoluteIosReleaseMetadata(downloadedMetadata)) !== JSON.stringify(metadata))
|
|
27132
27441
|
throw new TypeError("Remote iOS release metadata changed during retrieval.");
|
|
27133
|
-
const artifactPath =
|
|
27442
|
+
const artifactPath = join9(staging, "App.ipa");
|
|
27134
27443
|
const download = Bun.spawn([
|
|
27135
27444
|
...absoluteRemoteMacSshBase(project.profile),
|
|
27136
27445
|
"/bin/sh -lc",
|
|
@@ -27150,7 +27459,7 @@ var retrieveAbsoluteRemoteIosRelease = async (project, metadata, outputDirectory
|
|
|
27150
27459
|
projectRoot: project.projectRoot
|
|
27151
27460
|
});
|
|
27152
27461
|
} finally {
|
|
27153
|
-
await
|
|
27462
|
+
await rm7(staging, { force: true, recursive: true }).catch(() => {
|
|
27154
27463
|
return;
|
|
27155
27464
|
});
|
|
27156
27465
|
}
|
|
@@ -27392,7 +27701,7 @@ var startAbsoluteRemoteDevSession = async (options) => {
|
|
|
27392
27701
|
await syncProject(options.project);
|
|
27393
27702
|
const syncDuration = performance.now() - syncStartedAt;
|
|
27394
27703
|
const encodedConfig = Buffer.from(JSON.stringify(portableMobileConfig(options.project))).toString("base64url");
|
|
27395
|
-
const encodedCertificateAuthority = options.certificateAuthorityPath ? (await
|
|
27704
|
+
const encodedCertificateAuthority = options.certificateAuthorityPath ? (await readFile10(options.certificateAuthorityPath)).toString("base64url") : undefined;
|
|
27396
27705
|
const physicalDevice = options.deviceIdentifier !== undefined;
|
|
27397
27706
|
const expo = options.project.config.engine === "expo";
|
|
27398
27707
|
if (expo && options.metroPort === undefined)
|
|
@@ -27459,8 +27768,8 @@ var startAbsoluteRemoteDevSession = async (options) => {
|
|
|
27459
27768
|
const pending = new Map;
|
|
27460
27769
|
let resolveReady;
|
|
27461
27770
|
let rejectReady;
|
|
27462
|
-
const readyPromise = new Promise((
|
|
27463
|
-
resolveReady =
|
|
27771
|
+
const readyPromise = new Promise((resolve7, reject) => {
|
|
27772
|
+
resolveReady = resolve7;
|
|
27464
27773
|
rejectReady = reject;
|
|
27465
27774
|
});
|
|
27466
27775
|
const handleEvent = (event) => {
|
|
@@ -27563,7 +27872,7 @@ var startAbsoluteRemoteDevSession = async (options) => {
|
|
|
27563
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.`);
|
|
27564
27873
|
const request = (commandName) => {
|
|
27565
27874
|
const id = randomUUID4();
|
|
27566
|
-
const response = new Promise((
|
|
27875
|
+
const response = new Promise((resolve7, reject) => pending.set(id, { reject, resolve: resolve7 }));
|
|
27567
27876
|
process2.stdin.write(`${JSON.stringify({ command: commandName, id, v: ABSOLUTE_REMOTE_MAC_PROTOCOL_VERSION })}
|
|
27568
27877
|
`);
|
|
27569
27878
|
const flush = async () => {
|
|
@@ -27583,7 +27892,7 @@ var startAbsoluteRemoteDevSession = async (options) => {
|
|
|
27583
27892
|
if (closed)
|
|
27584
27893
|
return;
|
|
27585
27894
|
closed = true;
|
|
27586
|
-
const timeout = () => new Promise((
|
|
27895
|
+
const timeout = () => new Promise((resolve7) => setTimeout(() => resolve7("timeout"), REMOTE_SESSION_CLOSE_TIMEOUT_MS));
|
|
27587
27896
|
const id = randomUUID4();
|
|
27588
27897
|
process2.stdin.write(`${JSON.stringify({ command: "close", id, v: ABSOLUTE_REMOTE_MAC_PROTOCOL_VERSION })}
|
|
27589
27898
|
`);
|
|
@@ -27630,11 +27939,11 @@ var startAbsoluteRemoteDevSession = async (options) => {
|
|
|
27630
27939
|
screenshot: async (destination) => {
|
|
27631
27940
|
const result = await request("screenshot");
|
|
27632
27941
|
const target = resolvePath3(options.project.projectRoot, destination);
|
|
27633
|
-
const targetRelative =
|
|
27634
|
-
if (targetRelative.startsWith("..") ||
|
|
27942
|
+
const targetRelative = relative7(options.project.projectRoot, target);
|
|
27943
|
+
if (targetRelative.startsWith("..") || isAbsolute6(targetRelative))
|
|
27635
27944
|
throw new Error("iOS screenshot must remain inside the project.");
|
|
27636
|
-
await
|
|
27637
|
-
await
|
|
27945
|
+
await mkdir7(dirname6(target), { recursive: true });
|
|
27946
|
+
await writeFile8(target, Buffer.from(result.data, "base64"));
|
|
27638
27947
|
return target;
|
|
27639
27948
|
},
|
|
27640
27949
|
get state() {
|
|
@@ -27661,20 +27970,20 @@ var absoluteIosDeviceAcceptanceCommands = (options) => {
|
|
|
27661
27970
|
]
|
|
27662
27971
|
};
|
|
27663
27972
|
};
|
|
27664
|
-
var
|
|
27973
|
+
var requireSuccess4 = (result, message) => {
|
|
27665
27974
|
if (result.exitCode !== 0)
|
|
27666
27975
|
throw new Error(message);
|
|
27667
27976
|
return result;
|
|
27668
27977
|
};
|
|
27669
27978
|
var testAbsoluteIosPhysicalDevice = async (options) => {
|
|
27670
27979
|
const commands = absoluteIosDeviceAcceptanceCommands(options);
|
|
27671
|
-
|
|
27672
|
-
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.");
|
|
27673
27982
|
if (!apps.stdout.includes(options.appId))
|
|
27674
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.");
|
|
27675
27984
|
const now = options.now ?? performance.now.bind(performance);
|
|
27676
27985
|
const startedAt = now();
|
|
27677
|
-
|
|
27986
|
+
requireSuccess4(await options.capture(commands.launch), "AbsoluteJS could not relaunch the app on the physical iOS device.");
|
|
27678
27987
|
await options.waitForHmr();
|
|
27679
27988
|
return {
|
|
27680
27989
|
hmrConnected: true,
|
|
@@ -27697,10 +28006,10 @@ var frameworks2 = new Set([
|
|
|
27697
28006
|
"svelte",
|
|
27698
28007
|
"vue"
|
|
27699
28008
|
]);
|
|
27700
|
-
var
|
|
28009
|
+
var isRecord5 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
27701
28010
|
var isPageFramework2 = (value) => typeof value === "string" && frameworks2.has(value);
|
|
27702
28011
|
var parseAbsoluteMobileBuildPageMetadata = (value) => {
|
|
27703
|
-
if (!
|
|
28012
|
+
if (!isRecord5(value))
|
|
27704
28013
|
return;
|
|
27705
28014
|
if (typeof value.bundleKey !== "string" || typeof value.contract !== "string" || !isPageFramework2(value.framework) || typeof value.pageId !== "string" || typeof value.propsSchemaHash !== "string") {
|
|
27706
28015
|
return;
|
|
@@ -27714,32 +28023,32 @@ var parseAbsoluteMobileBuildPageMetadata = (value) => {
|
|
|
27714
28023
|
};
|
|
27715
28024
|
};
|
|
27716
28025
|
// src/mobile/buildPipeline.ts
|
|
27717
|
-
import { readFile as
|
|
27718
|
-
import { join as
|
|
28026
|
+
import { readFile as readFile16 } from "fs/promises";
|
|
28027
|
+
import { join as join19, resolve as resolve14 } from "path";
|
|
27719
28028
|
import { pathToFileURL as pathToFileURL2 } from "url";
|
|
27720
28029
|
|
|
27721
28030
|
// src/mobile/buildRelease.ts
|
|
27722
|
-
import { createHash as
|
|
27723
|
-
import { mkdir as
|
|
27724
|
-
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";
|
|
27725
28034
|
init_releaseArtifact();
|
|
27726
|
-
var
|
|
28035
|
+
var sha2562 = (bytes) => createHash10("sha256").update(bytes).digest("hex");
|
|
27727
28036
|
var STATIC_SCRIPT_PATTERN = /(<script\b[^>]*?\bsrc\s*=\s*["'])(\/[^"']+\.(?:js|ts))(["'][^>]*>)/giu;
|
|
27728
28037
|
var rewriteStaticScriptPaths = (source, manifest) => source.replace(STATIC_SCRIPT_PATTERN, (match, prefix, path, suffix) => {
|
|
27729
28038
|
if (path.endsWith("/htmx.min.js"))
|
|
27730
28039
|
return match;
|
|
27731
|
-
const key = toPascal(
|
|
28040
|
+
const key = toPascal(basename3(path, extname(path)));
|
|
27732
28041
|
const builtPath = manifest[key];
|
|
27733
28042
|
return builtPath ? `${prefix}${builtPath}${suffix}` : match;
|
|
27734
28043
|
});
|
|
27735
28044
|
var readPageMetadata = (route) => parseAbsoluteMobileBuildPageMetadata(route.hooks?.detail?.[ABSOLUTE_MOBILE_ROUTE_DETAIL]);
|
|
27736
28045
|
var resolveAssetPath = (buildDirectory, assetPath) => {
|
|
27737
|
-
const resolvedBuildDirectory =
|
|
27738
|
-
const resolvedAsset =
|
|
28046
|
+
const resolvedBuildDirectory = resolve9(buildDirectory);
|
|
28047
|
+
const resolvedAsset = resolve9(assetPath);
|
|
27739
28048
|
if (resolvedAsset.startsWith(`${resolvedBuildDirectory}/`)) {
|
|
27740
28049
|
return resolvedAsset;
|
|
27741
28050
|
}
|
|
27742
|
-
return
|
|
28051
|
+
return join10(buildDirectory, assetPath.replace(/^\/+/, ""));
|
|
27743
28052
|
};
|
|
27744
28053
|
var pageFor = async (metadata, manifest, buildDirectory) => {
|
|
27745
28054
|
const assetPath = manifest[metadata.bundleKey];
|
|
@@ -27748,12 +28057,12 @@ var pageFor = async (metadata, manifest, buildDirectory) => {
|
|
|
27748
28057
|
}
|
|
27749
28058
|
let resolvedAssetPath = resolveAssetPath(buildDirectory, assetPath);
|
|
27750
28059
|
if (metadata.framework === "html" || metadata.framework === "htmx") {
|
|
27751
|
-
const source = await
|
|
28060
|
+
const source = await readFile12(resolvedAssetPath, "utf8");
|
|
27752
28061
|
const rewritten = rewriteStaticScriptPaths(source, manifest);
|
|
27753
|
-
const documentHash =
|
|
27754
|
-
resolvedAssetPath =
|
|
27755
|
-
await
|
|
27756
|
-
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);
|
|
27757
28066
|
}
|
|
27758
28067
|
const pageAssetKey = metadata.bundleKey.replace(/Index$/u, "");
|
|
27759
28068
|
const styleAssetPath = [
|
|
@@ -27762,20 +28071,20 @@ var pageFor = async (metadata, manifest, buildDirectory) => {
|
|
|
27762
28071
|
].map((key) => manifest[key]).find((path) => typeof path === "string");
|
|
27763
28072
|
const resolvedStylePath = styleAssetPath ? resolveAssetPath(buildDirectory, styleAssetPath) : undefined;
|
|
27764
28073
|
const [bytes, styleBytes] = await Promise.all([
|
|
27765
|
-
|
|
27766
|
-
resolvedStylePath ?
|
|
28074
|
+
readFile12(resolvedAssetPath),
|
|
28075
|
+
resolvedStylePath ? readFile12(resolvedStylePath) : undefined
|
|
27767
28076
|
]);
|
|
27768
|
-
const bundlePath = `/${
|
|
27769
|
-
const styleBundlePath = resolvedStylePath ? `/${
|
|
28077
|
+
const bundlePath = `/${relative8(resolve9(buildDirectory), resolvedAssetPath).replaceAll("\\", "/")}`;
|
|
28078
|
+
const styleBundlePath = resolvedStylePath ? `/${relative8(resolve9(buildDirectory), resolvedStylePath).replaceAll("\\", "/")}` : undefined;
|
|
27770
28079
|
return {
|
|
27771
|
-
bundleHash:
|
|
28080
|
+
bundleHash: sha2562(bytes),
|
|
27772
28081
|
bundlePath,
|
|
27773
28082
|
contract: metadata.contract,
|
|
27774
28083
|
framework: metadata.framework,
|
|
27775
28084
|
pageId: metadata.pageId,
|
|
27776
28085
|
propsSchemaHash: metadata.propsSchemaHash,
|
|
27777
28086
|
...styleBytes && styleBundlePath ? {
|
|
27778
|
-
styleBundleHash:
|
|
28087
|
+
styleBundleHash: sha2562(styleBytes),
|
|
27779
28088
|
styleBundlePath
|
|
27780
28089
|
} : {}
|
|
27781
28090
|
};
|
|
@@ -27783,7 +28092,7 @@ var pageFor = async (metadata, manifest, buildDirectory) => {
|
|
|
27783
28092
|
var buildAbsoluteMobileCompatibilityRelease = async (options) => {
|
|
27784
28093
|
const [captured, producerBytes] = await Promise.all([
|
|
27785
28094
|
captureAbsoluteMobileRouteGraph(options.app),
|
|
27786
|
-
|
|
28095
|
+
readFile12(options.producerPath)
|
|
27787
28096
|
]);
|
|
27788
28097
|
if (captured.length === 0) {
|
|
27789
28098
|
throw new TypeError("No instrumented AbsoluteJS mobile page routes were found in the finalized Elysia route graph.");
|
|
@@ -27797,8 +28106,8 @@ var buildAbsoluteMobileCompatibilityRelease = async (options) => {
|
|
|
27797
28106
|
metadataByPage.set(metadata.pageId, metadata);
|
|
27798
28107
|
}
|
|
27799
28108
|
const pages = await Promise.all([...metadataByPage.values()].map((metadata) => pageFor(metadata, options.manifest, options.buildDirectory)));
|
|
27800
|
-
const producerHash =
|
|
27801
|
-
const appBuild = `ambuild_${
|
|
28109
|
+
const producerHash = sha2562(producerBytes);
|
|
28110
|
+
const appBuild = `ambuild_${sha2562(new TextEncoder().encode(JSON.stringify({
|
|
27802
28111
|
pages: pages.map(({
|
|
27803
28112
|
bundleHash,
|
|
27804
28113
|
bundlePath,
|
|
@@ -27874,15 +28183,15 @@ init_routeMatcher();
|
|
|
27874
28183
|
import {
|
|
27875
28184
|
cp,
|
|
27876
28185
|
copyFile as copyFile5,
|
|
27877
|
-
mkdir as
|
|
27878
|
-
mkdtemp as
|
|
27879
|
-
readFile as
|
|
27880
|
-
rename as
|
|
27881
|
-
rm as
|
|
27882
|
-
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
|
|
27883
28192
|
} from "fs/promises";
|
|
27884
28193
|
import { existsSync as existsSync2 } from "fs";
|
|
27885
|
-
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";
|
|
27886
28195
|
|
|
27887
28196
|
// src/mobile/client.ts
|
|
27888
28197
|
init_pageProtocol();
|
|
@@ -27916,14 +28225,14 @@ var upgradeReasons = new Set([
|
|
|
27916
28225
|
"protocol",
|
|
27917
28226
|
"runtime"
|
|
27918
28227
|
]);
|
|
27919
|
-
var
|
|
28228
|
+
var isRecord7 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
27920
28229
|
var isFramework = (value) => typeof value === "string" && frameworks4.has(value);
|
|
27921
28230
|
var isUpgradeReason = (value) => typeof value === "string" && upgradeReasons.has(value);
|
|
27922
28231
|
var parsePageResult = (value) => {
|
|
27923
28232
|
if (typeof value.contract !== "string" || !isFramework(value.framework) || typeof value.pageId !== "string" || typeof value.status !== "number") {
|
|
27924
28233
|
throw new AbsoluteMobilePageProtocolError("invalid-envelope", "The mobile page response is missing required page metadata.");
|
|
27925
28234
|
}
|
|
27926
|
-
if (!
|
|
28235
|
+
if (!isRecord7(value.props)) {
|
|
27927
28236
|
throw new AbsoluteMobilePageProtocolError("invalid-props", "The mobile page response must contain an object props value.");
|
|
27928
28237
|
}
|
|
27929
28238
|
return {
|
|
@@ -27974,7 +28283,7 @@ var activateAbsoluteMobilePage = async (value, options) => {
|
|
|
27974
28283
|
};
|
|
27975
28284
|
};
|
|
27976
28285
|
var parseAbsoluteMobilePageEnvelope = (value) => {
|
|
27977
|
-
if (!
|
|
28286
|
+
if (!isRecord7(value) || !isRecord7(value.response)) {
|
|
27978
28287
|
throw new AbsoluteMobilePageProtocolError("invalid-envelope", "The server did not return an AbsoluteJS mobile page envelope.");
|
|
27979
28288
|
}
|
|
27980
28289
|
if (value.protocol !== ABSOLUTE_MOBILE_PAGE_PROTOCOL_VERSION) {
|
|
@@ -28093,49 +28402,49 @@ var CAPACITOR_CLIENT_FRAMEWORKS = new Set([
|
|
|
28093
28402
|
var CLIENT_ASSET_DIRECTORIES = ["assets", "html", "htmx", "indexes"];
|
|
28094
28403
|
var errorHasCode2 = (error, code) => typeof error === "object" && error !== null && Reflect.get(error, "code") === code;
|
|
28095
28404
|
var shellBootstrapModule = () => {
|
|
28096
|
-
const candidate = ["js", "ts"].map((extension) =>
|
|
28405
|
+
const candidate = ["js", "ts"].map((extension) => join11(import.meta.dir, `shellBootstrap.${extension}`)).find(existsSync2);
|
|
28097
28406
|
if (candidate)
|
|
28098
28407
|
return candidate;
|
|
28099
28408
|
throw new TypeError("AbsoluteJS mobile shell bootstrap module is missing.");
|
|
28100
28409
|
};
|
|
28101
28410
|
var shellAuthModule = () => {
|
|
28102
|
-
const candidate = ["js", "ts"].map((extension) =>
|
|
28411
|
+
const candidate = ["js", "ts"].map((extension) => join11(import.meta.dir, `shellAuth.${extension}`)).find(existsSync2);
|
|
28103
28412
|
if (candidate)
|
|
28104
28413
|
return candidate;
|
|
28105
28414
|
throw new TypeError("AbsoluteJS mobile auth shell module is missing.");
|
|
28106
28415
|
};
|
|
28107
28416
|
var shellExpoAuthModule = () => {
|
|
28108
|
-
const candidate = ["js", "ts"].map((extension) =>
|
|
28417
|
+
const candidate = ["js", "ts"].map((extension) => join11(import.meta.dir, `shellExpoAuth.${extension}`)).find(existsSync2);
|
|
28109
28418
|
if (candidate)
|
|
28110
28419
|
return candidate;
|
|
28111
28420
|
throw new TypeError("AbsoluteJS Expo auth bridge module is missing.");
|
|
28112
28421
|
};
|
|
28113
28422
|
var shellSyncModule = () => {
|
|
28114
|
-
const candidate = ["js", "ts"].map((extension) =>
|
|
28423
|
+
const candidate = ["js", "ts"].map((extension) => join11(import.meta.dir, `shellSync.${extension}`)).find(existsSync2);
|
|
28115
28424
|
if (candidate)
|
|
28116
28425
|
return candidate;
|
|
28117
28426
|
throw new TypeError("AbsoluteJS mobile Sync shell module is missing.");
|
|
28118
28427
|
};
|
|
28119
28428
|
var shellExpoSyncModule = () => {
|
|
28120
|
-
const candidate = ["js", "ts"].map((extension) =>
|
|
28429
|
+
const candidate = ["js", "ts"].map((extension) => join11(import.meta.dir, `shellExpoSync.${extension}`)).find(existsSync2);
|
|
28121
28430
|
if (candidate)
|
|
28122
28431
|
return candidate;
|
|
28123
28432
|
throw new TypeError("AbsoluteJS Expo Sync bridge module is missing.");
|
|
28124
28433
|
};
|
|
28125
28434
|
var shellPushModule = () => {
|
|
28126
|
-
const candidate = ["js", "ts"].map((extension) =>
|
|
28435
|
+
const candidate = ["js", "ts"].map((extension) => join11(import.meta.dir, `shellPush.${extension}`)).find(existsSync2);
|
|
28127
28436
|
if (candidate)
|
|
28128
28437
|
return candidate;
|
|
28129
28438
|
throw new TypeError("AbsoluteJS mobile push shell module is missing.");
|
|
28130
28439
|
};
|
|
28131
28440
|
var shellExpoDevicesModule = () => {
|
|
28132
|
-
const candidate = ["js", "ts"].map((extension) =>
|
|
28441
|
+
const candidate = ["js", "ts"].map((extension) => join11(import.meta.dir, `shellExpoDevices.${extension}`)).find(existsSync2);
|
|
28133
28442
|
if (candidate)
|
|
28134
28443
|
return candidate;
|
|
28135
28444
|
throw new TypeError("AbsoluteJS Expo device bridge module is missing.");
|
|
28136
28445
|
};
|
|
28137
28446
|
var shellUpdateModule = () => {
|
|
28138
|
-
const candidate = ["js", "ts"].map((extension) =>
|
|
28447
|
+
const candidate = ["js", "ts"].map((extension) => join11(import.meta.dir, `shellUpdate.${extension}`)).find(existsSync2);
|
|
28139
28448
|
if (candidate)
|
|
28140
28449
|
return candidate;
|
|
28141
28450
|
throw new TypeError("AbsoluteJS mobile update shell module is missing.");
|
|
@@ -28170,8 +28479,8 @@ var indexHtml = (appName, productionOrigin) => `<!doctype html>
|
|
|
28170
28479
|
</html>
|
|
28171
28480
|
`;
|
|
28172
28481
|
var sourceAssetPath = (buildDirectory, bundlePath) => {
|
|
28173
|
-
const root =
|
|
28174
|
-
const asset =
|
|
28482
|
+
const root = resolve10(buildDirectory);
|
|
28483
|
+
const asset = resolve10(root, bundlePath.replace(/^\/+/, ""));
|
|
28175
28484
|
if (!asset.startsWith(`${root}/`)) {
|
|
28176
28485
|
throw new TypeError("Mobile page bundle escaped the build directory.");
|
|
28177
28486
|
}
|
|
@@ -28188,15 +28497,15 @@ var resolveProjectImport = async (projectRoot, specifier) => {
|
|
|
28188
28497
|
const segments = specifier.split("/");
|
|
28189
28498
|
const packageName = specifier.startsWith("@") ? segments.slice(0, 2).join("/") : segments[0] ?? "";
|
|
28190
28499
|
const subpath = specifier.slice(packageName.length);
|
|
28191
|
-
const packageDirectory =
|
|
28192
|
-
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"));
|
|
28193
28502
|
const exports = typeof manifest === "object" && manifest !== null ? Reflect.get(manifest, "exports") : undefined;
|
|
28194
28503
|
const entry = typeof exports === "object" && exports !== null ? Reflect.get(exports, subpath ? `.${subpath}` : ".") : undefined;
|
|
28195
28504
|
const target = importEntryTarget(entry);
|
|
28196
28505
|
if (typeof target !== "string" || !target.startsWith("./"))
|
|
28197
28506
|
throw new TypeError(`${specifier} does not publish an import entry.`);
|
|
28198
|
-
const resolved =
|
|
28199
|
-
if (!resolved.startsWith(`${
|
|
28507
|
+
const resolved = resolve10(packageDirectory, target);
|
|
28508
|
+
if (!resolved.startsWith(`${resolve10(packageDirectory)}/`))
|
|
28200
28509
|
throw new TypeError(`${specifier} has an unsafe import entry.`);
|
|
28201
28510
|
return resolved;
|
|
28202
28511
|
};
|
|
@@ -28227,7 +28536,7 @@ var buildShellBootstrap = async (staging, auth, sync, storagePrefix, engine, upd
|
|
|
28227
28536
|
const absoluteMobilePushCapability = absoluteDeviceCapability${pushIndex}(absoluteMobilePush.capabilityOptions);
|
|
28228
28537
|
` : "";
|
|
28229
28538
|
const capabilityOptions = shellCapabilities.map((name, index) => `${JSON.stringify(name)}: ${name === "pushNotifications" ? "absoluteMobilePushCapability" : `absoluteDeviceCapability${index}()`}`).join(", ");
|
|
28230
|
-
const entryPath =
|
|
28539
|
+
const entryPath = join11(staging, ".absolute-mobile-entry.ts");
|
|
28231
28540
|
const baseAdapterModule = capacitor ? await resolveProjectImport(projectRoot, "@absolutejs/devices-capacitor") : shellExpoDevicesModule();
|
|
28232
28541
|
const adapterImport = capacitor ? `import { installCapacitorDeviceAdapterIfNative } from ${JSON.stringify(baseAdapterModule)};` : `import { createAbsoluteExpoBridgeFetch, installAbsoluteExpoWebDeviceAdapter } from ${JSON.stringify(baseAdapterModule)};`;
|
|
28233
28542
|
const adapterInstall = capacitor ? `installCapacitorDeviceAdapterIfNative({ storagePrefix: ${JSON.stringify(storagePrefix)}${capabilityOptions ? `, ${capabilityOptions}` : ""} });` : `installAbsoluteExpoWebDeviceAdapter(${JSON.stringify(deviceCapabilities.capabilities)});`;
|
|
@@ -28245,7 +28554,7 @@ const absoluteMobilePushCapability = absoluteDeviceCapability${pushIndex}(absolu
|
|
|
28245
28554
|
if (updates)
|
|
28246
28555
|
shellOptionProperties.push("installUpdates: installAbsoluteMobileShellUpdates");
|
|
28247
28556
|
const shellOptions = `{ ${shellOptionProperties.join(", ")} }`;
|
|
28248
|
-
await
|
|
28557
|
+
await writeFile11(entryPath, `import { startAbsoluteMobileShell } from ${JSON.stringify(modulePath)};
|
|
28249
28558
|
${adapterImport}
|
|
28250
28559
|
${authImport}${syncImport}${pushImport}${updateImport}${capabilityImports}
|
|
28251
28560
|
${pushSetup}${adapterInstall}
|
|
@@ -28261,31 +28570,31 @@ void startAbsoluteMobileShell(${shellOptions});
|
|
|
28261
28570
|
if (!build.success || build.outputs.length !== 1) {
|
|
28262
28571
|
throw new AggregateError(build.logs, "Failed to build the AbsoluteJS Capacitor shell.");
|
|
28263
28572
|
}
|
|
28264
|
-
await
|
|
28265
|
-
await
|
|
28573
|
+
await rename10(build.outputs[0]?.path ?? "", join11(staging, BOOTSTRAP_FILE));
|
|
28574
|
+
await rm9(entryPath, { force: true });
|
|
28266
28575
|
};
|
|
28267
28576
|
var removePreviousBundle = async (backup, moved) => {
|
|
28268
28577
|
if (!moved)
|
|
28269
28578
|
return;
|
|
28270
|
-
await
|
|
28579
|
+
await rm9(backup, { force: true, recursive: true });
|
|
28271
28580
|
};
|
|
28272
28581
|
var restorePreviousBundle = async (backup, destination, moved) => {
|
|
28273
28582
|
if (!moved)
|
|
28274
28583
|
return;
|
|
28275
|
-
await
|
|
28584
|
+
await rename10(backup, destination);
|
|
28276
28585
|
};
|
|
28277
28586
|
var installBundle = async (staging, destination) => {
|
|
28278
28587
|
const backup = `${destination}.previous-${crypto.randomUUID()}`;
|
|
28279
28588
|
let movedPrevious = false;
|
|
28280
28589
|
try {
|
|
28281
|
-
await
|
|
28590
|
+
await rename10(destination, backup);
|
|
28282
28591
|
movedPrevious = true;
|
|
28283
28592
|
} catch (error) {
|
|
28284
28593
|
if (!errorHasCode2(error, "ENOENT"))
|
|
28285
28594
|
throw error;
|
|
28286
28595
|
}
|
|
28287
28596
|
try {
|
|
28288
|
-
await
|
|
28597
|
+
await rename10(staging, destination);
|
|
28289
28598
|
await removePreviousBundle(backup, movedPrevious);
|
|
28290
28599
|
} catch (error) {
|
|
28291
28600
|
await restorePreviousBundle(backup, destination, movedPrevious);
|
|
@@ -28299,17 +28608,17 @@ var copyClientPage = async (page, buildDirectory, staging, copiedDependencies) =
|
|
|
28299
28608
|
const extension = extname2(page.bundlePath) || ".js";
|
|
28300
28609
|
const localBundlePath = `./pages/${page.bundleHash}${extension}`;
|
|
28301
28610
|
const source = sourceAssetPath(buildDirectory, page.bundlePath);
|
|
28302
|
-
await copyFile5(source,
|
|
28611
|
+
await copyFile5(source, join11(staging, localBundlePath));
|
|
28303
28612
|
await copyAbsoluteClientDependencies(source, buildDirectory, staging, copiedDependencies);
|
|
28304
28613
|
let localStylePath;
|
|
28305
28614
|
if (page.styleBundlePath && page.styleBundleHash) {
|
|
28306
28615
|
const styleExtension = extname2(page.styleBundlePath) || ".css";
|
|
28307
28616
|
localStylePath = `./styles/${page.styleBundleHash}${styleExtension}`;
|
|
28308
28617
|
const styleSource = sourceAssetPath(buildDirectory, page.styleBundlePath);
|
|
28309
|
-
await
|
|
28618
|
+
await mkdir10(dirname8(join11(staging, localStylePath)), {
|
|
28310
28619
|
recursive: true
|
|
28311
28620
|
});
|
|
28312
|
-
await copyFile5(styleSource,
|
|
28621
|
+
await copyFile5(styleSource, join11(staging, localStylePath));
|
|
28313
28622
|
await copyAbsoluteClientDependencies(styleSource, buildDirectory, staging, copiedDependencies);
|
|
28314
28623
|
}
|
|
28315
28624
|
return {
|
|
@@ -28325,26 +28634,26 @@ var materializeAbsoluteMobileSourcemaps = async (pages, appBuild, projectRoot) =
|
|
|
28325
28634
|
return value;
|
|
28326
28635
|
};
|
|
28327
28636
|
const release = safeLeaf(appBuild, "Mobile app build");
|
|
28328
|
-
const privateRoot =
|
|
28329
|
-
const releaseRoot =
|
|
28637
|
+
const privateRoot = join11(projectRoot, "sourcemaps");
|
|
28638
|
+
const releaseRoot = join11(privateRoot, "mobile", release);
|
|
28330
28639
|
const copied = [];
|
|
28331
28640
|
const available = pages.flatMap((page) => {
|
|
28332
|
-
const source =
|
|
28641
|
+
const source = join11(privateRoot, `${basename4(page.bundlePath)}.map`);
|
|
28333
28642
|
return existsSync2(source) ? [{ page, source }] : [];
|
|
28334
28643
|
});
|
|
28335
28644
|
if (available.length > 0)
|
|
28336
|
-
await
|
|
28645
|
+
await mkdir10(releaseRoot, { recursive: true });
|
|
28337
28646
|
await Promise.all(available.map(async ({ page, source }) => {
|
|
28338
28647
|
const extension = extname2(page.bundlePath) || ".js";
|
|
28339
28648
|
if (!/^\.[a-z0-9]+$/iu.test(extension))
|
|
28340
28649
|
throw new TypeError("Mobile page extension is not a safe source-map key.");
|
|
28341
28650
|
const bundleHash = safeLeaf(page.bundleHash, "Mobile page bundle hash");
|
|
28342
28651
|
const file = `${bundleHash}${extension}.map`;
|
|
28343
|
-
await copyFile5(source,
|
|
28652
|
+
await copyFile5(source, join11(releaseRoot, file));
|
|
28344
28653
|
copied.push({ bundleHash, file, pageId: page.pageId });
|
|
28345
28654
|
}));
|
|
28346
28655
|
if (copied.length > 0) {
|
|
28347
|
-
await
|
|
28656
|
+
await writeFile11(join11(releaseRoot, "manifest.json"), `${JSON.stringify({
|
|
28348
28657
|
appBuild,
|
|
28349
28658
|
format: 1,
|
|
28350
28659
|
pages: copied.sort((left, right) => left.pageId.localeCompare(right.pageId))
|
|
@@ -28354,7 +28663,7 @@ var materializeAbsoluteMobileSourcemaps = async (pages, appBuild, projectRoot) =
|
|
|
28354
28663
|
return copied.length;
|
|
28355
28664
|
};
|
|
28356
28665
|
var absoluteClientImports = async (sourcePath, buildDirectory) => {
|
|
28357
|
-
const source = await
|
|
28666
|
+
const source = await readFile13(sourcePath, "utf8");
|
|
28358
28667
|
const extension = extname2(sourcePath).toLowerCase();
|
|
28359
28668
|
let scriptLoader;
|
|
28360
28669
|
if (extension === ".tsx")
|
|
@@ -28377,9 +28686,9 @@ var absoluteClientImports = async (sourcePath, buildDirectory) => {
|
|
|
28377
28686
|
const clean = specifier.split(/[?#]/u, 1)[0] ?? specifier;
|
|
28378
28687
|
if (clean.startsWith("/"))
|
|
28379
28688
|
return [clean];
|
|
28380
|
-
const resolved =
|
|
28381
|
-
const root =
|
|
28382
|
-
const relativePath =
|
|
28689
|
+
const resolved = resolve10(dirname8(sourcePath), clean);
|
|
28690
|
+
const root = resolve10(buildDirectory);
|
|
28691
|
+
const relativePath = relative9(root, resolved).replaceAll("\\", "/");
|
|
28383
28692
|
if (relativePath === ".." || relativePath.startsWith("../")) {
|
|
28384
28693
|
throw new TypeError(`Mobile client dependency escaped the build directory: ${specifier}`);
|
|
28385
28694
|
}
|
|
@@ -28391,8 +28700,8 @@ var copyAbsoluteClientDependency = async (specifier, buildDirectory, staging, co
|
|
|
28391
28700
|
return;
|
|
28392
28701
|
copied.add(specifier);
|
|
28393
28702
|
const source = sourceAssetPath(buildDirectory, specifier);
|
|
28394
|
-
const destination =
|
|
28395
|
-
await
|
|
28703
|
+
const destination = join11(staging, specifier.replace(/^\/+/, ""));
|
|
28704
|
+
await mkdir10(dirname8(destination), { recursive: true });
|
|
28396
28705
|
await copyFile5(source, destination);
|
|
28397
28706
|
await copyAbsoluteClientDependencies(source, buildDirectory, staging, copied);
|
|
28398
28707
|
};
|
|
@@ -28405,14 +28714,14 @@ var materializeAbsoluteCapacitorWebBundle = async (options) => {
|
|
|
28405
28714
|
throw new TypeError(`mobile.entry ${options.config.entry} is not a captured mobile page route.`);
|
|
28406
28715
|
}
|
|
28407
28716
|
const destination = options.config.bundleDirectory;
|
|
28408
|
-
await
|
|
28409
|
-
const staging = await
|
|
28717
|
+
await mkdir10(dirname8(destination), { recursive: true });
|
|
28718
|
+
const staging = await mkdtemp6(join11(dirname8(destination), `.${basename4(destination)}.stage-`));
|
|
28410
28719
|
try {
|
|
28411
|
-
const pageDirectory =
|
|
28412
|
-
await
|
|
28720
|
+
const pageDirectory = join11(staging, "pages");
|
|
28721
|
+
await mkdir10(pageDirectory, { recursive: true });
|
|
28413
28722
|
await Promise.all(CLIENT_ASSET_DIRECTORIES.map((directory) => ({
|
|
28414
|
-
destination:
|
|
28415
|
-
source:
|
|
28723
|
+
destination: join11(staging, directory),
|
|
28724
|
+
source: join11(options.buildDirectory, directory)
|
|
28416
28725
|
})).filter(({ source }) => existsSync2(source)).map(({ destination: assetDestination, source }) => cp(source, assetDestination, { recursive: true })));
|
|
28417
28726
|
const copiedDependencies = new Set;
|
|
28418
28727
|
const pages = await Promise.all(options.artifact.pages.map((page) => copyClientPage(page, options.buildDirectory, staging, copiedDependencies)));
|
|
@@ -28449,16 +28758,16 @@ var materializeAbsoluteCapacitorWebBundle = async (options) => {
|
|
|
28449
28758
|
} : {}
|
|
28450
28759
|
};
|
|
28451
28760
|
await Promise.all([
|
|
28452
|
-
|
|
28761
|
+
writeFile11(join11(staging, MANIFEST_FILE), `${JSON.stringify(manifest, null, "\t")}
|
|
28453
28762
|
`),
|
|
28454
|
-
|
|
28763
|
+
writeFile11(join11(staging, INDEX_FILE), indexHtml(options.config.appName, options.config.productionOrigin)),
|
|
28455
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)
|
|
28456
28765
|
]);
|
|
28457
28766
|
await installBundle(staging, destination);
|
|
28458
28767
|
await materializeAbsoluteMobileSourcemaps(options.artifact.pages, options.artifact.appBuild, options.projectRoot);
|
|
28459
28768
|
return manifest;
|
|
28460
28769
|
} catch (error) {
|
|
28461
|
-
await
|
|
28770
|
+
await rm9(staging, { force: true, recursive: true });
|
|
28462
28771
|
throw error;
|
|
28463
28772
|
}
|
|
28464
28773
|
};
|
|
@@ -28475,23 +28784,22 @@ init_nativeAuth();
|
|
|
28475
28784
|
init_syncSchema();
|
|
28476
28785
|
init_deviceCapabilities();
|
|
28477
28786
|
import {
|
|
28478
|
-
access as
|
|
28479
|
-
|
|
28480
|
-
|
|
28481
|
-
mkdtemp as mkdtemp7,
|
|
28787
|
+
access as access11,
|
|
28788
|
+
mkdir as mkdir12,
|
|
28789
|
+
mkdtemp as mkdtemp8,
|
|
28482
28790
|
readdir as readdir4,
|
|
28483
|
-
readFile as
|
|
28484
|
-
rename as
|
|
28485
|
-
rm as
|
|
28486
|
-
writeFile as
|
|
28791
|
+
readFile as readFile15,
|
|
28792
|
+
rename as rename12,
|
|
28793
|
+
rm as rm11,
|
|
28794
|
+
writeFile as writeFile13
|
|
28487
28795
|
} from "fs/promises";
|
|
28488
|
-
import { createHash as
|
|
28489
|
-
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";
|
|
28490
28798
|
|
|
28491
28799
|
// src/mobile/updateRuntime.ts
|
|
28492
28800
|
init_deviceCapabilities();
|
|
28493
28801
|
init_nativeAuth();
|
|
28494
|
-
import { createHash as
|
|
28802
|
+
import { createHash as createHash12 } from "crypto";
|
|
28495
28803
|
|
|
28496
28804
|
// src/mobile/updateProtocol.ts
|
|
28497
28805
|
var ABSOLUTE_MOBILE_UPDATE_FORMAT = 1;
|
|
@@ -28632,7 +28940,7 @@ var createAbsoluteMobileUpdateRuntimeDescriptor = (options) => ({
|
|
|
28632
28940
|
syncSchema: options.syncSchema ?? null,
|
|
28633
28941
|
updates: options.config.updates ?? null
|
|
28634
28942
|
});
|
|
28635
|
-
var fingerprintAbsoluteMobileUpdateRuntime = (descriptor) =>
|
|
28943
|
+
var fingerprintAbsoluteMobileUpdateRuntime = (descriptor) => createHash12("sha256").update(canonicalizeAbsoluteMobileUpdate(descriptor)).digest("hex");
|
|
28636
28944
|
var resolveAbsoluteMobileUpdateRuntime = (config, projectRoot) => {
|
|
28637
28945
|
const auth = resolveAbsoluteMobileAuthManifest(projectRoot, config);
|
|
28638
28946
|
const sync = auth !== undefined && projectUsesAbsoluteSync(projectRoot);
|
|
@@ -28655,7 +28963,7 @@ var resolveAbsoluteMobileUpdateRuntime = (config, projectRoot) => {
|
|
|
28655
28963
|
};
|
|
28656
28964
|
|
|
28657
28965
|
// src/mobile/expoNativeObservability.ts
|
|
28658
|
-
import { join as
|
|
28966
|
+
import { join as join16 } from "path";
|
|
28659
28967
|
var HEADER = `// Generated by AbsoluteJS. Edit absolute.config.ts, then run absolute mobile sync.
|
|
28660
28968
|
`;
|
|
28661
28969
|
var XML_HEADER = `<!-- Generated by AbsoluteJS. Edit absolute.config.ts, then run absolute mobile sync. -->
|
|
@@ -29097,31 +29405,31 @@ export const enqueueAbsoluteExpoNativeObservabilityForTesting = async (testId: s
|
|
|
29097
29405
|
`;
|
|
29098
29406
|
var absoluteExpoNativeObservabilityFiles = (project) => new Map([
|
|
29099
29407
|
[
|
|
29100
|
-
|
|
29408
|
+
join16(project, "modules/absolute-mobile-observability/expo-module.config.json"),
|
|
29101
29409
|
moduleConfig
|
|
29102
29410
|
],
|
|
29103
29411
|
[
|
|
29104
|
-
|
|
29412
|
+
join16(project, "modules/absolute-mobile-observability/ios/AbsoluteMobileObservability.podspec"),
|
|
29105
29413
|
podspec
|
|
29106
29414
|
],
|
|
29107
29415
|
[
|
|
29108
|
-
|
|
29416
|
+
join16(project, "modules/absolute-mobile-observability/ios/AbsoluteMobileObservabilityModule.swift"),
|
|
29109
29417
|
iosModule
|
|
29110
29418
|
],
|
|
29111
29419
|
[
|
|
29112
|
-
|
|
29420
|
+
join16(project, "modules/absolute-mobile-observability/android/build.gradle"),
|
|
29113
29421
|
androidBuild
|
|
29114
29422
|
],
|
|
29115
29423
|
[
|
|
29116
|
-
|
|
29424
|
+
join16(project, "modules/absolute-mobile-observability/android/src/main/AndroidManifest.xml"),
|
|
29117
29425
|
androidManifest
|
|
29118
29426
|
],
|
|
29119
29427
|
[
|
|
29120
|
-
|
|
29428
|
+
join16(project, "modules/absolute-mobile-observability/android/src/main/java/expo/modules/absolutemobileobservability/AbsoluteMobileObservabilityModule.kt"),
|
|
29121
29429
|
androidModule
|
|
29122
29430
|
],
|
|
29123
29431
|
[
|
|
29124
|
-
|
|
29432
|
+
join16(project, "src/generated/AbsoluteNativeObservability.ts"),
|
|
29125
29433
|
expoNativeObservabilityRuntimeSource
|
|
29126
29434
|
]
|
|
29127
29435
|
]);
|
|
@@ -29130,7 +29438,7 @@ var absoluteExpoNativeObservabilityPaths = (project) => [
|
|
|
29130
29438
|
];
|
|
29131
29439
|
|
|
29132
29440
|
// src/mobile/expoActivityResultRecovery.ts
|
|
29133
|
-
import { join as
|
|
29441
|
+
import { join as join17 } from "path";
|
|
29134
29442
|
var HEADER2 = `// Generated by AbsoluteJS. Edit absolute.config.ts, then run absolute mobile sync.
|
|
29135
29443
|
`;
|
|
29136
29444
|
var XML_HEADER2 = `<!-- Generated by AbsoluteJS. Edit absolute.config.ts, then run absolute mobile sync. -->
|
|
@@ -29257,6 +29565,15 @@ class AbsoluteActivityResultRecoveryModule : Module() {
|
|
|
29257
29565
|
Log.d("AbsoluteJS", "Expo application runtime ready for Android activity results")
|
|
29258
29566
|
}
|
|
29259
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
|
+
|
|
29260
29577
|
Function("takePendingCancellation") {
|
|
29261
29578
|
AbsoluteActivityResultRecoveryState.takePendingCancellation()
|
|
29262
29579
|
}
|
|
@@ -29267,6 +29584,8 @@ var runtime = `${HEADER2}import { requireNativeModule } from 'expo-modules-core'
|
|
|
29267
29584
|
|
|
29268
29585
|
type AbsoluteActivityResultRecoveryNative = {
|
|
29269
29586
|
markApplicationRuntimeReady(): void;
|
|
29587
|
+
markEmbeddedWebPhase(phase: AbsoluteEmbeddedWebPhase): void;
|
|
29588
|
+
markEmbeddedWebReady(): void;
|
|
29270
29589
|
takePendingCancellation(): boolean;
|
|
29271
29590
|
};
|
|
29272
29591
|
|
|
@@ -29277,28 +29596,52 @@ const native = requireNativeModule<AbsoluteActivityResultRecoveryNative>(
|
|
|
29277
29596
|
export const markAbsoluteApplicationRuntimeReady = () =>
|
|
29278
29597
|
native.markApplicationRuntimeReady();
|
|
29279
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
|
+
|
|
29280
29623
|
export const takeAbsoluteActivityResultCancellation = () =>
|
|
29281
29624
|
native.takePendingCancellation();
|
|
29282
29625
|
`;
|
|
29283
29626
|
var absoluteExpoActivityResultRecoveryFiles = (project) => new Map([
|
|
29284
29627
|
[
|
|
29285
|
-
|
|
29628
|
+
join17(project, "modules/absolute-activity-result-recovery/expo-module.config.json"),
|
|
29286
29629
|
moduleConfig2
|
|
29287
29630
|
],
|
|
29288
29631
|
[
|
|
29289
|
-
|
|
29632
|
+
join17(project, "modules/absolute-activity-result-recovery/android/build.gradle"),
|
|
29290
29633
|
androidBuild2
|
|
29291
29634
|
],
|
|
29292
29635
|
[
|
|
29293
|
-
|
|
29636
|
+
join17(project, "modules/absolute-activity-result-recovery/android/src/main/AndroidManifest.xml"),
|
|
29294
29637
|
androidManifest2
|
|
29295
29638
|
],
|
|
29296
29639
|
[
|
|
29297
|
-
|
|
29640
|
+
join17(project, "modules/absolute-activity-result-recovery/android/src/main/java/expo/modules/absoluteactivityresultrecovery/AbsoluteActivityResultRecoveryModule.kt"),
|
|
29298
29641
|
androidModule2
|
|
29299
29642
|
],
|
|
29300
29643
|
[
|
|
29301
|
-
|
|
29644
|
+
join17(project, "src/generated/AbsoluteActivityResultRecovery.ts"),
|
|
29302
29645
|
runtime
|
|
29303
29646
|
]
|
|
29304
29647
|
]);
|
|
@@ -29308,15 +29651,15 @@ var EXPO_GENERATED_HEADER = `// Generated by AbsoluteJS. Edit absolute.config.ts
|
|
|
29308
29651
|
`;
|
|
29309
29652
|
var EXPO_ASSET_EXTENSION = ".absasset";
|
|
29310
29653
|
var EXPO_PROJECT_MARKER = ".absolutejs-expo-project";
|
|
29311
|
-
var
|
|
29654
|
+
var exists4 = async (path) => {
|
|
29312
29655
|
try {
|
|
29313
|
-
await
|
|
29656
|
+
await access11(path);
|
|
29314
29657
|
return true;
|
|
29315
29658
|
} catch {
|
|
29316
29659
|
return false;
|
|
29317
29660
|
}
|
|
29318
29661
|
};
|
|
29319
|
-
var
|
|
29662
|
+
var isRecord9 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
29320
29663
|
var requireManifestString = (value, field2) => {
|
|
29321
29664
|
if (typeof value !== "string" || !value) {
|
|
29322
29665
|
throw new TypeError(`AbsoluteJS mobile manifest ${field2} is invalid.`);
|
|
@@ -29324,11 +29667,11 @@ var requireManifestString = (value, field2) => {
|
|
|
29324
29667
|
return value;
|
|
29325
29668
|
};
|
|
29326
29669
|
var expoNativeDataManifest = (value) => {
|
|
29327
|
-
if (!
|
|
29670
|
+
if (!isRecord9(value) || !Array.isArray(value.pages) || !Array.isArray(value.routes)) {
|
|
29328
29671
|
throw new TypeError("AbsoluteJS mobile manifest is invalid.");
|
|
29329
29672
|
}
|
|
29330
29673
|
const pages = value.pages.map((page) => {
|
|
29331
|
-
if (!
|
|
29674
|
+
if (!isRecord9(page))
|
|
29332
29675
|
throw new TypeError("AbsoluteJS mobile manifest page is invalid.");
|
|
29333
29676
|
return {
|
|
29334
29677
|
bundleHash: requireManifestString(page.bundleHash, "page.bundleHash"),
|
|
@@ -29337,7 +29680,7 @@ var expoNativeDataManifest = (value) => {
|
|
|
29337
29680
|
};
|
|
29338
29681
|
});
|
|
29339
29682
|
const routes = value.routes.flatMap((route) => {
|
|
29340
|
-
if (!
|
|
29683
|
+
if (!isRecord9(route) || typeof route.method !== "string") {
|
|
29341
29684
|
throw new TypeError("AbsoluteJS mobile manifest route is invalid.");
|
|
29342
29685
|
}
|
|
29343
29686
|
if (route.method !== "GET")
|
|
@@ -29352,7 +29695,7 @@ var expoNativeDataManifest = (value) => {
|
|
|
29352
29695
|
});
|
|
29353
29696
|
return {
|
|
29354
29697
|
appBuild: requireManifestString(value.appBuild, "appBuild"),
|
|
29355
|
-
...
|
|
29698
|
+
...isRecord9(value.observability) && typeof value.observability.endpoint === "string" && typeof value.observability.project === "string" && typeof value.observability.sampleRate === "number" ? {
|
|
29356
29699
|
observability: {
|
|
29357
29700
|
endpoint: value.observability.endpoint,
|
|
29358
29701
|
...typeof value.observability.environment === "string" ? { environment: value.observability.environment } : {},
|
|
@@ -29367,7 +29710,7 @@ var expoNativeDataManifest = (value) => {
|
|
|
29367
29710
|
};
|
|
29368
29711
|
};
|
|
29369
29712
|
var portableRelative2 = (from, destination) => {
|
|
29370
|
-
const value =
|
|
29713
|
+
const value = relative11(from, destination).replaceAll("\\", "/");
|
|
29371
29714
|
return value.startsWith(".") ? value : `./${value}`;
|
|
29372
29715
|
};
|
|
29373
29716
|
var routeSegments = (route) => {
|
|
@@ -29383,7 +29726,7 @@ var routeSegments = (route) => {
|
|
|
29383
29726
|
return segment;
|
|
29384
29727
|
});
|
|
29385
29728
|
};
|
|
29386
|
-
var routeFile = (project, route) =>
|
|
29729
|
+
var routeFile = (project, route) => join18(project, "app", ...routeSegments(route), "index.tsx");
|
|
29387
29730
|
var packageDependencies = (plan) => Object.fromEntries(plan.requiredPackages.map((spec) => {
|
|
29388
29731
|
const separator = spec.lastIndexOf("@");
|
|
29389
29732
|
return [spec.slice(0, separator), spec.slice(separator + 1)];
|
|
@@ -29937,7 +30280,7 @@ ${push ? `absoluteExpoAuth.onPrincipalChange(principal => {
|
|
|
29937
30280
|
`;
|
|
29938
30281
|
};
|
|
29939
30282
|
var authRuntimeSource = (auth, appId) => {
|
|
29940
|
-
const storageIdentity =
|
|
30283
|
+
const storageIdentity = createHash13("sha256").update(appId).digest("hex").slice(0, 24);
|
|
29941
30284
|
return `${EXPO_GENERATED_HEADER}import { createAbsoluteExpoAuthClient } from '@absolutejs/auth-expo';
|
|
29942
30285
|
import { createMobileAuthTransport, installAuthClientRuntimeTransport } from '@absolutejs/auth/client/mobile';
|
|
29943
30286
|
|
|
@@ -29969,7 +30312,7 @@ export const startAbsoluteExpoAuth = () => {
|
|
|
29969
30312
|
`;
|
|
29970
30313
|
};
|
|
29971
30314
|
var syncRuntimeSource = (config, schema) => {
|
|
29972
|
-
const storageIdentity =
|
|
30315
|
+
const storageIdentity = createHash13("sha256").update(config.appId).digest("hex").slice(0, 24);
|
|
29973
30316
|
const backgroundEndpoint = new URL("/__absolute/sync/background", config.productionOrigin).href;
|
|
29974
30317
|
const backgroundTask = `${config.appId}.absolutejs.sync`;
|
|
29975
30318
|
return `${EXPO_GENERATED_HEADER}import { runHeadlessSync } from '@absolutejs/sync/client/headless';
|
|
@@ -30088,10 +30431,11 @@ var webHostSource = (config, auth, sync) => {
|
|
|
30088
30431
|
return `${EXPO_GENERATED_HEADER}import * as Linking from 'expo-linking';
|
|
30089
30432
|
import { router, usePathname } from 'expo-router';
|
|
30090
30433
|
import { useEffect, useMemo, useRef, useState } from 'react';
|
|
30091
|
-
import { ActivityIndicator, BackHandler, Platform, StyleSheet, View } from 'react-native';
|
|
30434
|
+
import { ActivityIndicator, BackHandler, Platform, Pressable, StyleSheet, Text, View } from 'react-native';
|
|
30092
30435
|
import { useSafeAreaInsets } from 'react-native-safe-area-context';
|
|
30093
30436
|
import { WebView, type WebViewMessageEvent } from 'react-native-webview';
|
|
30094
30437
|
import { materializeAbsoluteWebBundle } from './webAssets';
|
|
30438
|
+
import { markAbsoluteEmbeddedWebPhase, markAbsoluteEmbeddedWebReady } from './AbsoluteActivityResultRecovery';
|
|
30095
30439
|
import { createExpoDevicesBridgeHost } from '@absolutejs/devices-expo/bridge';
|
|
30096
30440
|
import { absoluteExpoDevices, beforeAbsoluteExpoDeviceSignOut } from './AbsoluteDevices';
|
|
30097
30441
|
${auth ? "import { absoluteExpoAuth, getAbsoluteExpoAuthPrincipal, startAbsoluteExpoAuth } from './AbsoluteAuth';" : ""}
|
|
@@ -30255,7 +30599,10 @@ export function AbsoluteWebHost({ path }: AbsoluteWebHostProps = {}) {
|
|
|
30255
30599
|
const canGoBack = useRef(false);
|
|
30256
30600
|
const [runtimeReady, setRuntimeReady] = useState(!AUTH_ENABLED && !SYNC_ENABLED);
|
|
30257
30601
|
const [devicesReady, setDevicesReady] = useState(false);
|
|
30602
|
+
const [startupError, setStartupError] = useState<'assets' | 'devices'>();
|
|
30603
|
+
const [startupRevision, setStartupRevision] = useState(0);
|
|
30258
30604
|
const activeWebPath = useRef(pathname);
|
|
30605
|
+
const embeddedReadyReported = useRef(false);
|
|
30259
30606
|
const webSource = useMemo(() => indexUri ? { uri: indexUri } : undefined, [indexUri]);
|
|
30260
30607
|
|
|
30261
30608
|
useEffect(() => {
|
|
@@ -30289,8 +30636,18 @@ export function AbsoluteWebHost({ path }: AbsoluteWebHostProps = {}) {
|
|
|
30289
30636
|
setIndexUri(target.href);
|
|
30290
30637
|
return;
|
|
30291
30638
|
}
|
|
30292
|
-
|
|
30293
|
-
|
|
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]);
|
|
30294
30651
|
useEffect(() => {
|
|
30295
30652
|
webView.current?.injectJavaScript(hostMetricsScript(safeAreaInsets));
|
|
30296
30653
|
}, [safeAreaInsets.bottom, safeAreaInsets.left, safeAreaInsets.right, safeAreaInsets.top]);
|
|
@@ -30310,13 +30667,19 @@ export function AbsoluteWebHost({ path }: AbsoluteWebHostProps = {}) {
|
|
|
30310
30667
|
};
|
|
30311
30668
|
useEffect(() => {
|
|
30312
30669
|
let active = true;
|
|
30670
|
+
markAbsoluteEmbeddedWebPhase('devices-start');
|
|
30313
30671
|
void createExpoDevicesBridgeHost(absoluteExpoDevices, (event, payload) => {
|
|
30314
30672
|
if (!active) return;
|
|
30315
30673
|
respond({ event, format: BRIDGE_FORMAT, kind: 'event', path: activeWebPath.current, payload });
|
|
30316
30674
|
}).then(host => {
|
|
30317
30675
|
if (!active) return void Promise.resolve(host.close()).catch(() => undefined);
|
|
30318
30676
|
devicesBridge.current = host;
|
|
30677
|
+
markAbsoluteEmbeddedWebPhase('devices-ready');
|
|
30319
30678
|
setDevicesReady(true);
|
|
30679
|
+
}).catch(() => {
|
|
30680
|
+
if (!active) return;
|
|
30681
|
+
markAbsoluteEmbeddedWebPhase('devices-failed');
|
|
30682
|
+
setStartupError('devices');
|
|
30320
30683
|
});
|
|
30321
30684
|
return () => {
|
|
30322
30685
|
active = false;
|
|
@@ -30324,7 +30687,7 @@ export function AbsoluteWebHost({ path }: AbsoluteWebHostProps = {}) {
|
|
|
30324
30687
|
devicesBridge.current = undefined;
|
|
30325
30688
|
if (host) void Promise.resolve(host.close()).catch(() => undefined);
|
|
30326
30689
|
};
|
|
30327
|
-
}, []);
|
|
30690
|
+
}, [startupRevision]);
|
|
30328
30691
|
const hasOrigin = (source: string, origin: string) => {
|
|
30329
30692
|
try { return new URL(source).origin === origin; } catch { return false; }
|
|
30330
30693
|
};
|
|
@@ -30337,6 +30700,10 @@ export function AbsoluteWebHost({ path }: AbsoluteWebHostProps = {}) {
|
|
|
30337
30700
|
if (message.kind === 'event' && (message.event === 'navigation' || message.event === 'ready')) {
|
|
30338
30701
|
const target = new URL(message.path, PRODUCTION_ORIGIN);
|
|
30339
30702
|
if (target.origin !== PRODUCTION_ORIGIN) return;
|
|
30703
|
+
if (message.event === 'ready' && !DEV_ORIGIN && !embeddedReadyReported.current) {
|
|
30704
|
+
embeddedReadyReported.current = true;
|
|
30705
|
+
markAbsoluteEmbeddedWebReady();
|
|
30706
|
+
}
|
|
30340
30707
|
if (isNativeRoute(target.pathname)) router.push(message.path as never);
|
|
30341
30708
|
else activeWebPath.current = message.path;
|
|
30342
30709
|
return;
|
|
@@ -30376,6 +30743,15 @@ export function AbsoluteWebHost({ path }: AbsoluteWebHostProps = {}) {
|
|
|
30376
30743
|
}
|
|
30377
30744
|
};
|
|
30378
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>;
|
|
30379
30755
|
if (!webSource || !runtimeReady || !devicesReady) return <View style={styles.loading}><ActivityIndicator /></View>;
|
|
30380
30756
|
return <WebView
|
|
30381
30757
|
allowFileAccess
|
|
@@ -30401,7 +30777,7 @@ export function AbsoluteWebHost({ path }: AbsoluteWebHostProps = {}) {
|
|
|
30401
30777
|
/>;
|
|
30402
30778
|
}
|
|
30403
30779
|
|
|
30404
|
-
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 } });
|
|
30405
30781
|
`;
|
|
30406
30782
|
};
|
|
30407
30783
|
var webRouteSource = `${EXPO_GENERATED_HEADER}import { AbsoluteWebHost } from '../src/generated/AbsoluteWebHost';
|
|
@@ -30595,8 +30971,8 @@ const styles = StyleSheet.create({
|
|
|
30595
30971
|
error: { color: '#b91c1c', fontSize: 16, textAlign: 'center' }
|
|
30596
30972
|
});
|
|
30597
30973
|
`;
|
|
30598
|
-
var nativeWrapperSource = (wrapper, module, runtime2, route) => `${EXPO_GENERATED_HEADER}import ApplicationNativeRoute from ${JSON.stringify(portableRelative2(
|
|
30599
|
-
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, ""))};
|
|
30600
30976
|
|
|
30601
30977
|
export const ErrorBoundary = createAbsoluteNativeRouteErrorBoundary(${JSON.stringify(route)});
|
|
30602
30978
|
export default createAbsoluteNativeRoute(ApplicationNativeRoute, ${JSON.stringify(route)});
|
|
@@ -30638,9 +31014,9 @@ var expoTsConfig = (projectRoot, project, auth, sync) => ({
|
|
|
30638
31014
|
extends: "expo/tsconfig.base"
|
|
30639
31015
|
});
|
|
30640
31016
|
var writeManagedFile = async (path, source, force) => {
|
|
30641
|
-
await
|
|
30642
|
-
if (await
|
|
30643
|
-
const current = await
|
|
31017
|
+
await mkdir12(dirname11(path), { recursive: true });
|
|
31018
|
+
if (await exists4(path)) {
|
|
31019
|
+
const current = await readFile15(path, "utf8");
|
|
30644
31020
|
if (current === source)
|
|
30645
31021
|
return false;
|
|
30646
31022
|
if (!force && !current.startsWith(EXPO_GENERATED_HEADER)) {
|
|
@@ -30648,32 +31024,32 @@ var writeManagedFile = async (path, source, force) => {
|
|
|
30648
31024
|
}
|
|
30649
31025
|
}
|
|
30650
31026
|
const temporary = `${path}.${crypto.randomUUID()}.tmp`;
|
|
30651
|
-
await
|
|
30652
|
-
await
|
|
31027
|
+
await writeFile13(temporary, source, { flag: "wx" });
|
|
31028
|
+
await rename12(temporary, path);
|
|
30653
31029
|
return true;
|
|
30654
31030
|
};
|
|
30655
31031
|
var pruneManagedFiles = async (paths) => {
|
|
30656
31032
|
const removed = await Promise.all(paths.map(async (path) => {
|
|
30657
|
-
if (!await
|
|
31033
|
+
if (!await exists4(path))
|
|
30658
31034
|
return false;
|
|
30659
|
-
const source = await
|
|
31035
|
+
const source = await readFile15(path, "utf8");
|
|
30660
31036
|
if (!source.startsWith(EXPO_GENERATED_HEADER) && !path.endsWith("expo-module.config.json"))
|
|
30661
31037
|
return false;
|
|
30662
|
-
await
|
|
31038
|
+
await rm11(path, { force: true });
|
|
30663
31039
|
return true;
|
|
30664
31040
|
}));
|
|
30665
31041
|
return removed.filter(Boolean).length;
|
|
30666
31042
|
};
|
|
30667
31043
|
var pruneStaleManagedExpoRoutes = async (project, expected) => {
|
|
30668
|
-
const appDirectory =
|
|
30669
|
-
if (!await
|
|
31044
|
+
const appDirectory = join18(project, "app");
|
|
31045
|
+
if (!await exists4(appDirectory))
|
|
30670
31046
|
return 0;
|
|
30671
31047
|
const files = await walkFiles(appDirectory);
|
|
30672
31048
|
const stale = (await Promise.all(files.map(async (path) => ({
|
|
30673
|
-
managed: path.endsWith(".tsx") && (await
|
|
31049
|
+
managed: path.endsWith(".tsx") && (await readFile15(path, "utf8")).startsWith(EXPO_GENERATED_HEADER),
|
|
30674
31050
|
path
|
|
30675
31051
|
})))).filter(({ managed, path }) => managed && !expected.has(path));
|
|
30676
|
-
await Promise.all(stale.map(({ path }) =>
|
|
31052
|
+
await Promise.all(stale.map(({ path }) => rm11(path, { force: true })));
|
|
30677
31053
|
return stale.length;
|
|
30678
31054
|
};
|
|
30679
31055
|
var jsonSource = (value) => `${JSON.stringify(value, null, "\t")}
|
|
@@ -30696,7 +31072,7 @@ export const ABSOLUTE_MOBILE_MANIFEST: AbsoluteMobileManifest | undefined = unde
|
|
|
30696
31072
|
var writeAbsoluteExpoProject = async (config, options) => {
|
|
30697
31073
|
if (config.engine !== "expo")
|
|
30698
31074
|
throw new TypeError("Expo project generation requires mobile.engine: expo.");
|
|
30699
|
-
const projectRoot =
|
|
31075
|
+
const projectRoot = resolve13(options.projectRoot);
|
|
30700
31076
|
const project = config.nativeProjectDirectory;
|
|
30701
31077
|
const auth = resolveAbsoluteMobileAuthManifest(projectRoot, config);
|
|
30702
31078
|
const devices = resolveAbsoluteDeviceCapabilityPlan(projectRoot, "expo");
|
|
@@ -30705,7 +31081,7 @@ var writeAbsoluteExpoProject = async (config, options) => {
|
|
|
30705
31081
|
const runtimeFingerprint = resolveAbsoluteMobileUpdateRuntime(config, projectRoot).fingerprint;
|
|
30706
31082
|
const routeModules = Object.entries(config.expoNativeRoutes);
|
|
30707
31083
|
const moduleChecks = await Promise.all(routeModules.map(async ([route, module]) => ({
|
|
30708
|
-
exists: await
|
|
31084
|
+
exists: await exists4(module),
|
|
30709
31085
|
module,
|
|
30710
31086
|
route
|
|
30711
31087
|
})));
|
|
@@ -30713,20 +31089,20 @@ var writeAbsoluteExpoProject = async (config, options) => {
|
|
|
30713
31089
|
if (missing) {
|
|
30714
31090
|
throw new TypeError(`Expo native route ${missing.route} references missing module ${missing.module}.`);
|
|
30715
31091
|
}
|
|
30716
|
-
const marker =
|
|
30717
|
-
if (await
|
|
31092
|
+
const marker = join18(project, EXPO_PROJECT_MARKER);
|
|
31093
|
+
if (await exists4(project) && !await exists4(marker)) {
|
|
30718
31094
|
const entries = await readdir4(project);
|
|
30719
31095
|
if (entries.length > 0 && !options.force) {
|
|
30720
31096
|
throw new TypeError(`Expo project directory ${project} is not AbsoluteJS-managed; rerun with --force only after reviewing it.`);
|
|
30721
31097
|
}
|
|
30722
31098
|
}
|
|
30723
|
-
await
|
|
30724
|
-
await
|
|
31099
|
+
await mkdir12(project, { recursive: true });
|
|
31100
|
+
await writeFile13(marker, `format=1
|
|
30725
31101
|
`);
|
|
30726
31102
|
const authEnabled = Boolean(auth);
|
|
30727
31103
|
const files = new Map([
|
|
30728
31104
|
[
|
|
30729
|
-
|
|
31105
|
+
join18(project, ".gitignore"),
|
|
30730
31106
|
`.expo/
|
|
30731
31107
|
android/
|
|
30732
31108
|
ios/
|
|
@@ -30734,45 +31110,45 @@ node_modules/
|
|
|
30734
31110
|
`
|
|
30735
31111
|
],
|
|
30736
31112
|
[
|
|
30737
|
-
|
|
31113
|
+
join18(project, "app.json"),
|
|
30738
31114
|
jsonSource(expoAppConfig(config, authEnabled, syncEnabled, devices, runtimeFingerprint))
|
|
30739
31115
|
],
|
|
30740
|
-
[
|
|
31116
|
+
[join18(project, "app.config.js"), expoDynamicAppConfig],
|
|
30741
31117
|
[
|
|
30742
|
-
|
|
31118
|
+
join18(project, "package.json"),
|
|
30743
31119
|
jsonSource(expoPackage(authEnabled, syncEnabled, devices, config.updates !== undefined))
|
|
30744
31120
|
],
|
|
30745
|
-
[
|
|
31121
|
+
[join18(project, "metro.config.js"), metroConfig(projectRoot)],
|
|
30746
31122
|
[
|
|
30747
|
-
|
|
31123
|
+
join18(project, "plugins", "withAbsoluteDevelopmentCa.js"),
|
|
30748
31124
|
expoDevelopmentCaPlugin
|
|
30749
31125
|
],
|
|
30750
31126
|
[
|
|
30751
|
-
|
|
31127
|
+
join18(project, "plugins", "withAbsoluteActivityResultRecovery.js"),
|
|
30752
31128
|
expoActivityResultRecoveryPlugin
|
|
30753
31129
|
],
|
|
30754
31130
|
[
|
|
30755
|
-
|
|
31131
|
+
join18(project, "tsconfig.json"),
|
|
30756
31132
|
jsonSource(expoTsConfig(projectRoot, project, authEnabled, syncEnabled))
|
|
30757
31133
|
],
|
|
30758
31134
|
[
|
|
30759
|
-
|
|
31135
|
+
join18(project, "app", "_layout.tsx"),
|
|
30760
31136
|
layoutSource(authEnabled, syncEnabled, config.updates !== undefined, config.observability !== undefined)
|
|
30761
31137
|
],
|
|
30762
31138
|
[
|
|
30763
|
-
|
|
31139
|
+
join18(project, "app", "__absolute", "native", "index.tsx"),
|
|
30764
31140
|
nativeDiagnosticSource
|
|
30765
31141
|
],
|
|
30766
31142
|
[
|
|
30767
|
-
|
|
31143
|
+
join18(project, "src", "generated", "AbsoluteDevices.ts"),
|
|
30768
31144
|
devicesRuntimeSource(config, devices, authEnabled)
|
|
30769
31145
|
],
|
|
30770
31146
|
[
|
|
30771
|
-
|
|
31147
|
+
join18(project, "src", "generated", "AbsoluteNativeRoute.tsx"),
|
|
30772
31148
|
nativeRouteRuntimeSource(authEnabled)
|
|
30773
31149
|
],
|
|
30774
31150
|
[
|
|
30775
|
-
|
|
31151
|
+
join18(project, "src", "generated", "AbsoluteWebHost.tsx"),
|
|
30776
31152
|
webHostSource(config, auth, syncEnabled)
|
|
30777
31153
|
]
|
|
30778
31154
|
]);
|
|
@@ -30783,31 +31159,31 @@ node_modules/
|
|
|
30783
31159
|
files.set(path, source);
|
|
30784
31160
|
}
|
|
30785
31161
|
if (config.updates) {
|
|
30786
|
-
files.set(
|
|
31162
|
+
files.set(join18(project, "src", "generated", "AbsoluteUpdates.ts"), updatesRuntimeSource(config));
|
|
30787
31163
|
}
|
|
30788
31164
|
const expoCodeSigning = config.updates?.expoCodeSigning;
|
|
30789
31165
|
if (expoCodeSigning)
|
|
30790
|
-
files.set(
|
|
31166
|
+
files.set(join18(project, "certs", "absolute-mobile-update.pem"), expoCodeSigning.certificatePem);
|
|
30791
31167
|
if (auth) {
|
|
30792
|
-
files.set(
|
|
31168
|
+
files.set(join18(project, "src", "generated", "AbsoluteAuth.ts"), authRuntimeSource(auth, config.appId));
|
|
30793
31169
|
}
|
|
30794
31170
|
if (syncSchema) {
|
|
30795
|
-
files.set(
|
|
31171
|
+
files.set(join18(project, "src", "generated", "AbsoluteSync.ts"), syncRuntimeSource(config, syncSchema));
|
|
30796
31172
|
}
|
|
30797
|
-
const webAssetsPath =
|
|
30798
|
-
if (!await
|
|
31173
|
+
const webAssetsPath = join18(project, "src", "generated", "webAssets.ts");
|
|
31174
|
+
if (!await exists4(webAssetsPath)) {
|
|
30799
31175
|
files.set(webAssetsPath, emptyWebAssetsSource);
|
|
30800
31176
|
}
|
|
30801
31177
|
if (!config.expoNativeRoutes["/"]) {
|
|
30802
|
-
files.set(
|
|
31178
|
+
files.set(join18(project, "app", "index.tsx"), webRouteSource);
|
|
30803
31179
|
}
|
|
30804
|
-
files.set(
|
|
30805
|
-
const nativeRouteRuntime =
|
|
31180
|
+
files.set(join18(project, "app", "[...absolute].tsx"), catchAllRouteSource);
|
|
31181
|
+
const nativeRouteRuntime = join18(project, "src", "generated", "AbsoluteNativeRoute.tsx");
|
|
30806
31182
|
for (const [route, module] of routeModules) {
|
|
30807
|
-
const wrapper = route === "/" ?
|
|
31183
|
+
const wrapper = route === "/" ? join18(project, "app", "index.tsx") : routeFile(project, route);
|
|
30808
31184
|
files.set(wrapper, nativeWrapperSource(wrapper, module, nativeRouteRuntime, route));
|
|
30809
31185
|
}
|
|
30810
|
-
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}`))));
|
|
30811
31187
|
const removedObservability = config.observability ? 0 : await pruneManagedFiles(absoluteExpoNativeObservabilityPaths(project));
|
|
30812
31188
|
const changes = await Promise.all([...files].map(([path, source]) => writeManagedFile(path, source, true)));
|
|
30813
31189
|
const changed = removedRoutes + removedObservability + changes.filter(Boolean).length;
|
|
@@ -30816,7 +31192,7 @@ node_modules/
|
|
|
30816
31192
|
var walkFiles = async (root, directory = root) => {
|
|
30817
31193
|
const entries = await readdir4(directory, { withFileTypes: true });
|
|
30818
31194
|
const nested = await Promise.all(entries.map((entry) => {
|
|
30819
|
-
const path =
|
|
31195
|
+
const path = join18(directory, entry.name);
|
|
30820
31196
|
if (entry.isDirectory())
|
|
30821
31197
|
return walkFiles(root, path);
|
|
30822
31198
|
if (entry.isFile())
|
|
@@ -30827,7 +31203,7 @@ var walkFiles = async (root, directory = root) => {
|
|
|
30827
31203
|
};
|
|
30828
31204
|
var renameIfPresent = async (source, destination) => {
|
|
30829
31205
|
try {
|
|
30830
|
-
await
|
|
31206
|
+
await rename12(source, destination);
|
|
30831
31207
|
return true;
|
|
30832
31208
|
} catch (error) {
|
|
30833
31209
|
if (typeof error === "object" && error !== null && Reflect.get(error, "code") === "ENOENT") {
|
|
@@ -30840,87 +31216,130 @@ var installStagedDirectory = async (staging, destination) => {
|
|
|
30840
31216
|
const backup = `${destination}.previous-${crypto.randomUUID()}`;
|
|
30841
31217
|
const moved = await renameIfPresent(destination, backup);
|
|
30842
31218
|
try {
|
|
30843
|
-
await
|
|
31219
|
+
await rename12(staging, destination);
|
|
30844
31220
|
if (moved)
|
|
30845
|
-
await
|
|
31221
|
+
await rm11(backup, { force: true, recursive: true });
|
|
30846
31222
|
} catch (error) {
|
|
30847
31223
|
if (moved)
|
|
30848
|
-
await
|
|
31224
|
+
await rename12(backup, destination);
|
|
30849
31225
|
throw error;
|
|
30850
31226
|
}
|
|
30851
31227
|
};
|
|
30852
|
-
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';
|
|
30853
31229
|
import { Directory, File, Paths } from 'expo-file-system';
|
|
31230
|
+
import { copyAsync as copyLegacyAsync } from 'expo-file-system/legacy';
|
|
30854
31231
|
|
|
30855
31232
|
${nativeDataManifestTypeSource}
|
|
30856
31233
|
declare const require: (path: string) => number;
|
|
30857
31234
|
const BUNDLE_ID = ${JSON.stringify(bundleId)};
|
|
30858
31235
|
export const ABSOLUTE_MOBILE_MANIFEST: AbsoluteMobileManifest = ${JSON.stringify(manifest)};
|
|
31236
|
+
const ARCHIVE_MODULE = require(${JSON.stringify(archiveAsset)});
|
|
30859
31237
|
const ASSETS = [
|
|
30860
|
-
${assets.map((
|
|
31238
|
+
${assets.map((entry) => ` ${JSON.stringify(entry)}`).join(`,
|
|
30861
31239
|
`)}
|
|
30862
31240
|
] as const;
|
|
30863
31241
|
|
|
30864
31242
|
export const materializeAbsoluteWebBundle = async () => {
|
|
30865
|
-
|
|
30866
|
-
|
|
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'); }
|
|
30867
31270
|
for (const entry of ASSETS) {
|
|
30868
31271
|
const parts = entry.path.split('/');
|
|
30869
31272
|
const name = parts.pop();
|
|
30870
|
-
if (!name) throw new Error('
|
|
30871
|
-
|
|
30872
|
-
|
|
30873
|
-
|
|
30874
|
-
|
|
30875
|
-
|
|
30876
|
-
|
|
30877
|
-
|
|
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'); }
|
|
30878
31288
|
}
|
|
31289
|
+
try { archive.delete(); }
|
|
31290
|
+
catch { throw new Error('assets-finalize-failed'); }
|
|
30879
31291
|
|
|
30880
|
-
return new File(root, 'index.html').uri;
|
|
31292
|
+
try { return new File(root, 'index.html').uri; }
|
|
31293
|
+
catch { throw new Error('assets-finalize-failed'); }
|
|
30881
31294
|
};
|
|
30882
31295
|
`;
|
|
30883
31296
|
var syncAbsoluteExpoWebAssets = async (config) => {
|
|
30884
31297
|
if (config.engine !== "expo")
|
|
30885
31298
|
throw new TypeError("Expo asset sync requires mobile.engine: expo.");
|
|
30886
|
-
const marker =
|
|
30887
|
-
if (!await
|
|
31299
|
+
const marker = join18(config.nativeProjectDirectory, EXPO_PROJECT_MARKER);
|
|
31300
|
+
if (!await exists4(marker)) {
|
|
30888
31301
|
throw new TypeError("Expo asset sync requires an AbsoluteJS-managed Expo project. Run mobile init first.");
|
|
30889
31302
|
}
|
|
30890
|
-
const manifestPath =
|
|
30891
|
-
const manifest = JSON.parse(await
|
|
31303
|
+
const manifestPath = join18(config.bundleDirectory, "absolute-mobile-manifest.json");
|
|
31304
|
+
const manifest = JSON.parse(await readFile15(manifestPath, "utf8"));
|
|
30892
31305
|
const nativeDataManifest = expoNativeDataManifest(manifest);
|
|
30893
31306
|
const { appBuild } = nativeDataManifest;
|
|
30894
31307
|
const files = await walkFiles(config.bundleDirectory);
|
|
30895
|
-
const bundleHash =
|
|
30896
|
-
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 })));
|
|
30897
31310
|
filesWithContents.forEach(({ contents, file }) => {
|
|
30898
|
-
bundleHash.update(
|
|
31311
|
+
bundleHash.update(relative11(config.bundleDirectory, file).replaceAll("\\", "/"));
|
|
30899
31312
|
bundleHash.update("\x00");
|
|
30900
31313
|
bundleHash.update(contents);
|
|
30901
31314
|
bundleHash.update("\x00");
|
|
30902
31315
|
});
|
|
30903
31316
|
const bundleId = `amexpo_${bundleHash.digest("hex")}`;
|
|
30904
|
-
const destination =
|
|
30905
|
-
await
|
|
30906
|
-
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-`));
|
|
30907
31320
|
let assets;
|
|
31321
|
+
let archiveAsset;
|
|
30908
31322
|
try {
|
|
30909
|
-
|
|
30910
|
-
|
|
30911
|
-
|
|
30912
|
-
|
|
30913
|
-
|
|
30914
|
-
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("\\", "/")
|
|
30915
31329
|
};
|
|
30916
|
-
|
|
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));
|
|
30917
31336
|
await installStagedDirectory(staging, destination);
|
|
30918
31337
|
} catch (error) {
|
|
30919
|
-
await
|
|
31338
|
+
await rm11(staging, { force: true, recursive: true });
|
|
30920
31339
|
throw error;
|
|
30921
31340
|
}
|
|
30922
|
-
const generated =
|
|
30923
|
-
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);
|
|
30924
31343
|
return { appBuild, assets: assets.length, bundleId, path: destination };
|
|
30925
31344
|
};
|
|
30926
31345
|
|
|
@@ -30958,11 +31377,11 @@ var loadServerApp = async (producerPath) => {
|
|
|
30958
31377
|
return { app, exportName };
|
|
30959
31378
|
};
|
|
30960
31379
|
var finalizeAbsoluteMobileCompatibilityBuild = async (options) => {
|
|
30961
|
-
const buildDirectory =
|
|
31380
|
+
const buildDirectory = resolve14(options.buildDirectory);
|
|
30962
31381
|
const mobile = normalizeAbsoluteMobileConfig(options.mobile, options.projectRoot);
|
|
30963
|
-
const root =
|
|
31382
|
+
const root = join19(buildDirectory, ".absolutejs", "mobile-compatibility");
|
|
30964
31383
|
const [manifestSource, previous] = await Promise.all([
|
|
30965
|
-
|
|
31384
|
+
readFile16(join19(buildDirectory, "manifest.json"), "utf8"),
|
|
30966
31385
|
readAbsoluteMobileMaterializedReleases(root)
|
|
30967
31386
|
]);
|
|
30968
31387
|
const manifest = JSON.parse(manifestSource);
|
|
@@ -30975,11 +31394,11 @@ var finalizeAbsoluteMobileCompatibilityBuild = async (options) => {
|
|
|
30975
31394
|
process.env.ABSOLUTE_BUILD_DIR = buildDirectory;
|
|
30976
31395
|
process.env.ABSOLUTE_COMPILED_RUNTIME = "1";
|
|
30977
31396
|
if (options.configPath) {
|
|
30978
|
-
process.env.ABSOLUTE_CONFIG =
|
|
31397
|
+
process.env.ABSOLUTE_CONFIG = resolve14(options.projectRoot, options.configPath);
|
|
30979
31398
|
}
|
|
30980
31399
|
let loaded;
|
|
30981
31400
|
try {
|
|
30982
|
-
loaded = await loadServerApp(
|
|
31401
|
+
loaded = await loadServerApp(resolve14(options.producerPath));
|
|
30983
31402
|
} finally {
|
|
30984
31403
|
restoreEnvironmentVariable("ABSOLUTE_BUILD_DIR", previousBuildDirectory);
|
|
30985
31404
|
restoreEnvironmentVariable("ABSOLUTE_COMPILED_RUNTIME", previousCompiledRuntime);
|
|
@@ -30992,7 +31411,7 @@ var finalizeAbsoluteMobileCompatibilityBuild = async (options) => {
|
|
|
30992
31411
|
manifest,
|
|
30993
31412
|
previousArtifacts: previous.map(({ artifact }) => artifact),
|
|
30994
31413
|
producerExport: loaded.exportName,
|
|
30995
|
-
producerPath:
|
|
31414
|
+
producerPath: resolve14(options.producerPath),
|
|
30996
31415
|
runtime: String(ABSOLUTE_MOBILE_PAGE_PROTOCOL_VERSION)
|
|
30997
31416
|
});
|
|
30998
31417
|
const {
|
|
@@ -31242,7 +31661,7 @@ var ABSOLUTE_EXPO_BRIDGE_METHODS = [
|
|
|
31242
31661
|
"sync.socket.open",
|
|
31243
31662
|
"sync.socket.sendChunk"
|
|
31244
31663
|
];
|
|
31245
|
-
var
|
|
31664
|
+
var isRecord10 = (value) => typeof value === "object" && value !== null && !Array.isArray(value) && (Object.getPrototypeOf(value) === Object.prototype || Object.getPrototypeOf(value) === null);
|
|
31246
31665
|
var validId = (value) => typeof value === "string" && /^[A-Za-z0-9_-]{1,80}$/u.test(value);
|
|
31247
31666
|
var validPath = (value) => typeof value === "string" && value.startsWith("/") && !value.startsWith("//") && value.length <= 4096;
|
|
31248
31667
|
var parseRequest = (value) => {
|
|
@@ -31252,7 +31671,7 @@ var parseRequest = (value) => {
|
|
|
31252
31671
|
if (!method) {
|
|
31253
31672
|
throw new TypeError("Expo bridge method is not allowed.");
|
|
31254
31673
|
}
|
|
31255
|
-
if (!
|
|
31674
|
+
if (!isRecord10(value.params))
|
|
31256
31675
|
throw new TypeError("Expo bridge request params must be an object.");
|
|
31257
31676
|
if (typeof value.path !== "string" || !validPath(value.path))
|
|
31258
31677
|
throw new TypeError("Expo bridge request path is invalid.");
|
|
@@ -31288,7 +31707,7 @@ var parseRequest = (value) => {
|
|
|
31288
31707
|
throw new TypeError("Expo bridge HTTP body exceeds 48 KiB.");
|
|
31289
31708
|
if ((value.params.method === "GET" || value.params.method === "DELETE") && value.params.body !== undefined)
|
|
31290
31709
|
throw new TypeError("Expo bridge HTTP method cannot contain a body.");
|
|
31291
|
-
if (!
|
|
31710
|
+
if (!isRecord10(value.params.headers))
|
|
31292
31711
|
throw new TypeError("Expo bridge HTTP headers must be an object.");
|
|
31293
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-")));
|
|
31294
31713
|
if (!headersAllowed) {
|
|
@@ -31314,13 +31733,13 @@ var parseResponse = (value) => {
|
|
|
31314
31733
|
if (typeof value.id !== "string" || !validId(value.id))
|
|
31315
31734
|
throw new TypeError("Expo bridge response id is invalid.");
|
|
31316
31735
|
if (value.error !== undefined) {
|
|
31317
|
-
if (!
|
|
31736
|
+
if (!isRecord10(value.error) || typeof value.error.code !== "string" || typeof value.error.message !== "string") {
|
|
31318
31737
|
throw new TypeError("Expo bridge response error is invalid.");
|
|
31319
31738
|
}
|
|
31320
31739
|
if (value.result !== undefined)
|
|
31321
31740
|
throw new TypeError("Expo bridge response cannot contain result and error.");
|
|
31322
31741
|
}
|
|
31323
|
-
if (
|
|
31742
|
+
if (isRecord10(value.error)) {
|
|
31324
31743
|
return {
|
|
31325
31744
|
error: {
|
|
31326
31745
|
code: String(value.error.code),
|
|
@@ -31344,7 +31763,7 @@ var parseEvent = (value) => {
|
|
|
31344
31763
|
}
|
|
31345
31764
|
if (typeof value.path !== "string" || !validPath(value.path))
|
|
31346
31765
|
throw new TypeError("Expo bridge event path is invalid.");
|
|
31347
|
-
if (value.payload !== undefined && !
|
|
31766
|
+
if (value.payload !== undefined && !isRecord10(value.payload)) {
|
|
31348
31767
|
throw new TypeError("Expo bridge event payload must be an object.");
|
|
31349
31768
|
}
|
|
31350
31769
|
return {
|
|
@@ -31378,7 +31797,7 @@ var parseAbsoluteExpoBridgeMessage = (source) => {
|
|
|
31378
31797
|
cause
|
|
31379
31798
|
});
|
|
31380
31799
|
}
|
|
31381
|
-
if (!
|
|
31800
|
+
if (!isRecord10(parsed) || parsed.format !== ABSOLUTE_EXPO_BRIDGE_FORMAT) {
|
|
31382
31801
|
throw new TypeError("Expo bridge message format is unsupported.");
|
|
31383
31802
|
}
|
|
31384
31803
|
if (parsed.kind === "request")
|
|
@@ -31391,21 +31810,21 @@ var parseAbsoluteExpoBridgeMessage = (source) => {
|
|
|
31391
31810
|
};
|
|
31392
31811
|
// src/mobile/expoCodeSigning.ts
|
|
31393
31812
|
var import_code_signing_certificates = __toESM(require_main(), 1);
|
|
31394
|
-
import { access as
|
|
31395
|
-
import { dirname as
|
|
31396
|
-
var
|
|
31397
|
-
var
|
|
31398
|
-
const location2 =
|
|
31399
|
-
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);
|
|
31400
31819
|
};
|
|
31401
31820
|
var generateAbsoluteExpoCodeSigning = async (options) => {
|
|
31402
|
-
const root =
|
|
31403
|
-
const certificatePath =
|
|
31404
|
-
const privateKeyPath =
|
|
31405
|
-
const publicKeyPath =
|
|
31406
|
-
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))
|
|
31407
31826
|
throw new TypeError("Expo code-signing certificate must be written inside the project so store builds can embed it.");
|
|
31408
|
-
if (
|
|
31827
|
+
if (inside2(root, privateKeyPath) || inside2(root, publicKeyPath))
|
|
31409
31828
|
throw new TypeError("Expo code-signing private/public key output must remain outside the project and source control.");
|
|
31410
31829
|
const commonName = options.commonName.trim();
|
|
31411
31830
|
if (!commonName || commonName.length > 64)
|
|
@@ -31414,7 +31833,7 @@ var generateAbsoluteExpoCodeSigning = async (options) => {
|
|
|
31414
31833
|
if (!Number.isSafeInteger(validityYears) || validityYears < 1 || validityYears > 20)
|
|
31415
31834
|
throw new TypeError("Expo code-signing validity must be an integer from 1 through 20 years.");
|
|
31416
31835
|
const collisions = (await Promise.all([certificatePath, privateKeyPath, publicKeyPath].map(async (path) => ({
|
|
31417
|
-
exists: await
|
|
31836
|
+
exists: await exists5(path),
|
|
31418
31837
|
path
|
|
31419
31838
|
})))).filter((entry) => entry.exists);
|
|
31420
31839
|
if (collisions.length > 0)
|
|
@@ -31432,11 +31851,11 @@ var generateAbsoluteExpoCodeSigning = async (options) => {
|
|
|
31432
31851
|
import_code_signing_certificates.validateSelfSignedCertificate(certificate, keyPair);
|
|
31433
31852
|
const { privateKeyPEM, publicKeyPEM } = import_code_signing_certificates.convertKeyPairToPEM(keyPair);
|
|
31434
31853
|
const certificatePem = import_code_signing_certificates.convertCertificateToCertificatePEM(certificate);
|
|
31435
|
-
await Promise.all([certificatePath, privateKeyPath, publicKeyPath].map((path) =>
|
|
31854
|
+
await Promise.all([certificatePath, privateKeyPath, publicKeyPath].map((path) => mkdir13(dirname12(path), { recursive: true })));
|
|
31436
31855
|
await Promise.all([
|
|
31437
|
-
|
|
31438
|
-
|
|
31439
|
-
|
|
31856
|
+
writeFile14(certificatePath, certificatePem, { flag: "wx", mode: 420 }),
|
|
31857
|
+
writeFile14(privateKeyPath, privateKeyPEM, { flag: "wx", mode: 384 }),
|
|
31858
|
+
writeFile14(publicKeyPath, publicKeyPEM, { flag: "wx", mode: 420 })
|
|
31440
31859
|
]);
|
|
31441
31860
|
return {
|
|
31442
31861
|
certificatePath,
|
|
@@ -31538,9 +31957,9 @@ var parseAbsoluteAndroidAccessibilityHierarchy = (source) => [...source.matchAll
|
|
|
31538
31957
|
});
|
|
31539
31958
|
// src/mobile/expoNativeWatcher.ts
|
|
31540
31959
|
import { watch as watch2 } from "fs";
|
|
31541
|
-
import { access as
|
|
31542
|
-
import { basename as
|
|
31543
|
-
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";
|
|
31544
31963
|
var NATIVE_CHANGE_DEBOUNCE_MS2 = 500;
|
|
31545
31964
|
var ROOT_NATIVE_INPUTS2 = new Set([
|
|
31546
31965
|
"absolute.config.js",
|
|
@@ -31554,13 +31973,13 @@ var ROOT_NATIVE_INPUTS2 = new Set([
|
|
|
31554
31973
|
"package.json"
|
|
31555
31974
|
]);
|
|
31556
31975
|
var EXPO_NATIVE_DIRECTORIES = ["modules", "plugins"];
|
|
31557
|
-
var
|
|
31976
|
+
var exists6 = async (path) => access13(path).then(() => true, () => false);
|
|
31558
31977
|
var filesIn = async (directory, prefix) => {
|
|
31559
|
-
if (!await
|
|
31978
|
+
if (!await exists6(directory))
|
|
31560
31979
|
return [];
|
|
31561
31980
|
const entries = await readdir5(directory, { withFileTypes: true });
|
|
31562
31981
|
const nested = await Promise.all(entries.map((entry) => {
|
|
31563
|
-
const path =
|
|
31982
|
+
const path = join20(directory, entry.name);
|
|
31564
31983
|
const name = `${prefix}/${entry.name}`;
|
|
31565
31984
|
if (entry.isDirectory())
|
|
31566
31985
|
return filesIn(path, name);
|
|
@@ -31569,21 +31988,21 @@ var filesIn = async (directory, prefix) => {
|
|
|
31569
31988
|
return nested.flat().sort((left, right) => left.name.localeCompare(right.name));
|
|
31570
31989
|
};
|
|
31571
31990
|
var fingerprintAbsoluteExpoNativeInputs = async (options) => {
|
|
31572
|
-
const hash =
|
|
31991
|
+
const hash = createHash14("sha256");
|
|
31573
31992
|
const rootFiles = await Promise.all([...ROOT_NATIVE_INPUTS2].sort().map(async (name) => {
|
|
31574
|
-
const path =
|
|
31575
|
-
return await
|
|
31993
|
+
const path = join20(options.projectRoot, name);
|
|
31994
|
+
return await exists6(path) ? [{ name: `root/${name}`, path }] : [];
|
|
31576
31995
|
}));
|
|
31577
|
-
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)));
|
|
31578
31997
|
const files = [...rootFiles.flat(), ...nativeFiles.flat()].sort((left, right) => left.name.localeCompare(right.name));
|
|
31579
|
-
const contents = await Promise.all(files.map(({ path }) =>
|
|
31998
|
+
const contents = await Promise.all(files.map(({ path }) => readFile17(path)));
|
|
31580
31999
|
files.forEach(({ name }, index) => {
|
|
31581
32000
|
hash.update(name);
|
|
31582
32001
|
hash.update(contents[index] ?? Buffer.alloc(0));
|
|
31583
32002
|
});
|
|
31584
32003
|
return hash.digest("hex");
|
|
31585
32004
|
};
|
|
31586
|
-
var isAbsoluteExpoNativeRootInput = (path) => ROOT_NATIVE_INPUTS2.has(
|
|
32005
|
+
var isAbsoluteExpoNativeRootInput = (path) => ROOT_NATIVE_INPUTS2.has(basename6(path));
|
|
31587
32006
|
var createAbsoluteExpoNativeWatcher = async (options) => {
|
|
31588
32007
|
let fingerprint = await fingerprintAbsoluteExpoNativeInputs(options);
|
|
31589
32008
|
let closed = false;
|
|
@@ -31645,14 +32064,14 @@ var createAbsoluteExpoNativeWatcher = async (options) => {
|
|
|
31645
32064
|
}
|
|
31646
32065
|
};
|
|
31647
32066
|
const nativeDirectories = (await Promise.all(EXPO_NATIVE_DIRECTORIES.map(async (name) => {
|
|
31648
|
-
const directory =
|
|
31649
|
-
return await
|
|
32067
|
+
const directory = join20(options.expoProjectDirectory, name);
|
|
32068
|
+
return await exists6(directory) ? [directory] : [];
|
|
31650
32069
|
}))).flat();
|
|
31651
32070
|
nativeDirectories.forEach((directory) => {
|
|
31652
32071
|
watchers.push(watch2(directory, { recursive: true }, (_event, filename) => {
|
|
31653
32072
|
if (!filename)
|
|
31654
32073
|
return;
|
|
31655
|
-
record(
|
|
32074
|
+
record(relative13(options.expoProjectDirectory, join20(directory, String(filename))), false);
|
|
31656
32075
|
}));
|
|
31657
32076
|
});
|
|
31658
32077
|
watchers.push(watch2(options.projectRoot, (_event, filename) => {
|
|
@@ -31667,8 +32086,8 @@ var createAbsoluteExpoNativeWatcher = async (options) => {
|
|
|
31667
32086
|
return { close };
|
|
31668
32087
|
};
|
|
31669
32088
|
// src/mobile/expoUpdate.ts
|
|
31670
|
-
import { access as
|
|
31671
|
-
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";
|
|
31672
32091
|
var ABSOLUTE_EXPO_UPDATE_DESCRIPTOR = "_absolute/expo-update.json";
|
|
31673
32092
|
var ABSOLUTE_EXPO_UPDATE_FORMAT = 1;
|
|
31674
32093
|
var object4 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
@@ -31734,7 +32153,7 @@ var parseAbsoluteExpoUpdateDescriptor = (value) => {
|
|
|
31734
32153
|
};
|
|
31735
32154
|
};
|
|
31736
32155
|
var finalizeAbsoluteExpoUpdateExport = async (options) => {
|
|
31737
|
-
const metadata = JSON.parse(await
|
|
32156
|
+
const metadata = JSON.parse(await readFile18(join21(options.exportDirectory, "metadata.json"), "utf8"));
|
|
31738
32157
|
if (!object4(metadata) || !object4(metadata.fileMetadata))
|
|
31739
32158
|
throw new TypeError("Expo export metadata.json is invalid.");
|
|
31740
32159
|
const descriptor = parseAbsoluteExpoUpdateDescriptor({
|
|
@@ -31745,12 +32164,12 @@ var finalizeAbsoluteExpoUpdateExport = async (options) => {
|
|
|
31745
32164
|
runtimeVersion: options.runtimeVersion
|
|
31746
32165
|
});
|
|
31747
32166
|
const referenced = Object.values(descriptor.platforms).flatMap((entry) => entry ? [entry.launchAsset, ...entry.assets] : []);
|
|
31748
|
-
await Promise.all(referenced.map(({ path }) =>
|
|
32167
|
+
await Promise.all(referenced.map(({ path }) => access14(join21(options.exportDirectory, path)).catch(() => {
|
|
31749
32168
|
throw new TypeError(`Expo export metadata references missing asset ${path}.`);
|
|
31750
32169
|
})));
|
|
31751
|
-
const destination =
|
|
31752
|
-
await
|
|
31753
|
-
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")}
|
|
31754
32173
|
`);
|
|
31755
32174
|
return { descriptor, path: destination };
|
|
31756
32175
|
};
|
|
@@ -31760,8 +32179,8 @@ init_config();
|
|
|
31760
32179
|
|
|
31761
32180
|
// src/mobile/ciWorkflow.ts
|
|
31762
32181
|
import { existsSync as existsSync4 } from "fs";
|
|
31763
|
-
import { access as
|
|
31764
|
-
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";
|
|
31765
32184
|
var ABSOLUTE_MOBILE_CI_WORKFLOW_FORMAT = 1;
|
|
31766
32185
|
var SECRET_NAME_PATTERN = /^[A-Z][A-Z0-9_]*$/u;
|
|
31767
32186
|
var CI_ENV_INDENTATION = 6;
|
|
@@ -31780,9 +32199,9 @@ var RESERVED_SECRET_NAMES = new Set([
|
|
|
31780
32199
|
"APP_STORE_CONNECT_KEY_ID",
|
|
31781
32200
|
"APP_STORE_CONNECT_PRIVATE_KEY_BASE64"
|
|
31782
32201
|
]);
|
|
31783
|
-
var
|
|
32202
|
+
var exists7 = async (path) => {
|
|
31784
32203
|
try {
|
|
31785
|
-
await
|
|
32204
|
+
await access15(path);
|
|
31786
32205
|
return true;
|
|
31787
32206
|
} catch {
|
|
31788
32207
|
return false;
|
|
@@ -31790,10 +32209,10 @@ var exists6 = async (path) => {
|
|
|
31790
32209
|
};
|
|
31791
32210
|
var yamlString = (value) => `'${value.replaceAll("'", "''")}'`;
|
|
31792
32211
|
var projectPath = (projectRoot, value, field2, options = {}) => {
|
|
31793
|
-
const root =
|
|
31794
|
-
const path =
|
|
31795
|
-
const portable =
|
|
31796
|
-
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 === "") {
|
|
31797
32216
|
throw new TypeError(`${field2} must remain inside the project root.`);
|
|
31798
32217
|
}
|
|
31799
32218
|
if (/\r|\n/u.test(portable) || portable.startsWith("-"))
|
|
@@ -31803,11 +32222,11 @@ var projectPath = (projectRoot, value, field2, options = {}) => {
|
|
|
31803
32222
|
return portable;
|
|
31804
32223
|
};
|
|
31805
32224
|
var workflowOutputPath = (projectRoot, value) => {
|
|
31806
|
-
const root =
|
|
31807
|
-
const workflows =
|
|
31808
|
-
const path =
|
|
31809
|
-
const portable =
|
|
31810
|
-
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") {
|
|
31811
32230
|
throw new TypeError("mobile ci github --output must be a .yml or .yaml file inside .github/workflows.");
|
|
31812
32231
|
}
|
|
31813
32232
|
return path;
|
|
@@ -32236,12 +32655,12 @@ ${bundleAuditSteps}${platforms.includes("android") ? androidJob({ customSecrets,
|
|
|
32236
32655
|
var writeAbsoluteMobileGithubWorkflow = async (options) => {
|
|
32237
32656
|
const path = workflowOutputPath(options.projectRoot, options.outputPath);
|
|
32238
32657
|
const generated = createAbsoluteMobileGithubWorkflow(options);
|
|
32239
|
-
const previous = await
|
|
32658
|
+
const previous = await exists7(path) ? await readFile19(path, "utf8") : undefined;
|
|
32240
32659
|
if (previous !== undefined && previous !== generated.workflow && !options.force)
|
|
32241
|
-
throw new TypeError(`${
|
|
32660
|
+
throw new TypeError(`${relative14(options.projectRoot, path)} already exists and differs. Rerun with --force to replace the generated workflow.`);
|
|
32242
32661
|
if (previous !== generated.workflow) {
|
|
32243
|
-
await
|
|
32244
|
-
await
|
|
32662
|
+
await mkdir15(dirname14(path), { recursive: true });
|
|
32663
|
+
await writeFile16(path, generated.workflow);
|
|
32245
32664
|
}
|
|
32246
32665
|
return {
|
|
32247
32666
|
changed: previous !== generated.workflow,
|
|
@@ -32259,20 +32678,20 @@ init_materializedBundle();
|
|
|
32259
32678
|
init_mobilePreview();
|
|
32260
32679
|
|
|
32261
32680
|
// src/mobile/nativeDeepLinks.ts
|
|
32262
|
-
import { readFile as
|
|
32263
|
-
import { join as
|
|
32681
|
+
import { readFile as readFile20, rename as rename13, writeFile as writeFile17 } from "fs/promises";
|
|
32682
|
+
import { join as join24 } from "path";
|
|
32264
32683
|
var START_MARKER = "<!-- absolutejs:deep-links:start -->";
|
|
32265
32684
|
var END_MARKER = "<!-- absolutejs:deep-links:end -->";
|
|
32266
32685
|
var IOS_ENTITLEMENTS = "App/AbsoluteJS.entitlements";
|
|
32267
32686
|
var NOT_FOUND = -1;
|
|
32268
32687
|
var escapeXml = (value) => value.replaceAll("&", "&").replaceAll('"', """).replaceAll("'", "'").replaceAll("<", "<").replaceAll(">", ">");
|
|
32269
32688
|
var writeChangedFile = async (path, source) => {
|
|
32270
|
-
const current = await
|
|
32689
|
+
const current = await readFile20(path, "utf8");
|
|
32271
32690
|
if (current === source)
|
|
32272
32691
|
return false;
|
|
32273
32692
|
const temporary = `${path}.${crypto.randomUUID()}.tmp`;
|
|
32274
|
-
await
|
|
32275
|
-
await
|
|
32693
|
+
await writeFile17(temporary, source, { flag: "wx" });
|
|
32694
|
+
await rename13(temporary, path);
|
|
32276
32695
|
return true;
|
|
32277
32696
|
};
|
|
32278
32697
|
var replaceManagedRegion = (source, region, insertAt) => {
|
|
@@ -32317,8 +32736,8 @@ ${hosts}
|
|
|
32317
32736
|
`;
|
|
32318
32737
|
};
|
|
32319
32738
|
var configureAndroid = async (config) => {
|
|
32320
|
-
const path =
|
|
32321
|
-
const source = await
|
|
32739
|
+
const path = join24(config.nativeProjectDirectory, "android/app/src/main/AndroidManifest.xml");
|
|
32740
|
+
const source = await readFile20(path, "utf8");
|
|
32322
32741
|
const mainActivity = source.indexOf('android:name=".MainActivity"');
|
|
32323
32742
|
if (mainActivity === NOT_FOUND) {
|
|
32324
32743
|
throw new TypeError("Android MainActivity was not found.");
|
|
@@ -32343,8 +32762,8 @@ var iosSchemeRegion = (scheme) => ` ${START_MARKER}
|
|
|
32343
32762
|
${END_MARKER}
|
|
32344
32763
|
`;
|
|
32345
32764
|
var configureIosInfo = async (config) => {
|
|
32346
|
-
const path =
|
|
32347
|
-
const source = await
|
|
32765
|
+
const path = join24(config.nativeProjectDirectory, "ios/App/App/Info.plist");
|
|
32766
|
+
const source = await readFile20(path, "utf8");
|
|
32348
32767
|
const region = config.deepLinkScheme ? iosSchemeRegion(config.deepLinkScheme) : ` ${START_MARKER}
|
|
32349
32768
|
${END_MARKER}
|
|
32350
32769
|
`;
|
|
@@ -32367,10 +32786,10 @@ ${domains}
|
|
|
32367
32786
|
`;
|
|
32368
32787
|
};
|
|
32369
32788
|
var configureIosEntitlements = async (config) => {
|
|
32370
|
-
const path =
|
|
32789
|
+
const path = join24(config.nativeProjectDirectory, "ios/App/AbsoluteJS.entitlements");
|
|
32371
32790
|
let current = "";
|
|
32372
32791
|
try {
|
|
32373
|
-
current = await
|
|
32792
|
+
current = await readFile20(path, "utf8");
|
|
32374
32793
|
} catch (error) {
|
|
32375
32794
|
if (!(error instanceof Error) || !("code" in error) || error.code !== "ENOENT") {
|
|
32376
32795
|
throw error;
|
|
@@ -32380,13 +32799,13 @@ var configureIosEntitlements = async (config) => {
|
|
|
32380
32799
|
if (current === source)
|
|
32381
32800
|
return false;
|
|
32382
32801
|
const temporary = `${path}.${crypto.randomUUID()}.tmp`;
|
|
32383
|
-
await
|
|
32384
|
-
await
|
|
32802
|
+
await writeFile17(temporary, source, { flag: "wx" });
|
|
32803
|
+
await rename13(temporary, path);
|
|
32385
32804
|
return true;
|
|
32386
32805
|
};
|
|
32387
32806
|
var configureIosProject = async (config) => {
|
|
32388
|
-
const path =
|
|
32389
|
-
const source = await
|
|
32807
|
+
const path = join24(config.nativeProjectDirectory, "ios/App/App.xcodeproj/project.pbxproj");
|
|
32808
|
+
const source = await readFile20(path, "utf8");
|
|
32390
32809
|
const declarations = [
|
|
32391
32810
|
...source.matchAll(/CODE_SIGN_ENTITLEMENTS = ([^;]+);/g)
|
|
32392
32811
|
].map((match) => match[1]);
|
|
@@ -32425,8 +32844,8 @@ var applyAbsoluteNativeDeepLinks = async (config, platforms = config.platforms)
|
|
|
32425
32844
|
};
|
|
32426
32845
|
// src/mobile/nativeDeviceCapabilities.ts
|
|
32427
32846
|
init_deviceCapabilities();
|
|
32428
|
-
import { readFile as
|
|
32429
|
-
import { join as
|
|
32847
|
+
import { readFile as readFile21, rename as rename14, writeFile as writeFile18 } from "fs/promises";
|
|
32848
|
+
import { join as join25 } from "path";
|
|
32430
32849
|
var START_MARKER2 = "<!-- absolutejs:device-capabilities:start -->";
|
|
32431
32850
|
var END_MARKER2 = "<!-- absolutejs:device-capabilities:end -->";
|
|
32432
32851
|
var NOT_FOUND2 = -1;
|
|
@@ -32436,12 +32855,12 @@ var PUSH_START_MARKER = "absolutejs:push-notifications:start";
|
|
|
32436
32855
|
var PUSH_END_MARKER = "absolutejs:push-notifications:end";
|
|
32437
32856
|
var escapeXml2 = (value) => value.replaceAll("&", "&").replaceAll('"', """).replaceAll("'", "'").replaceAll("<", "<").replaceAll(">", ">");
|
|
32438
32857
|
var writeChangedFile2 = async (path, source) => {
|
|
32439
|
-
const current = await
|
|
32858
|
+
const current = await readFile21(path, "utf8");
|
|
32440
32859
|
if (current === source)
|
|
32441
32860
|
return false;
|
|
32442
32861
|
const temporary = `${path}.${crypto.randomUUID()}.tmp`;
|
|
32443
|
-
await
|
|
32444
|
-
await
|
|
32862
|
+
await writeFile18(temporary, source, { flag: "wx" });
|
|
32863
|
+
await rename14(temporary, path);
|
|
32445
32864
|
return true;
|
|
32446
32865
|
};
|
|
32447
32866
|
var writeOptionalChangedFile = async (path, source) => {
|
|
@@ -32449,14 +32868,14 @@ var writeOptionalChangedFile = async (path, source) => {
|
|
|
32449
32868
|
if (current === source)
|
|
32450
32869
|
return false;
|
|
32451
32870
|
if (current === null) {
|
|
32452
|
-
await
|
|
32871
|
+
await writeFile18(path, source, { flag: "wx" });
|
|
32453
32872
|
return true;
|
|
32454
32873
|
}
|
|
32455
32874
|
return writeChangedFile2(path, source);
|
|
32456
32875
|
};
|
|
32457
32876
|
var optionalSource = async (path) => {
|
|
32458
32877
|
try {
|
|
32459
|
-
return await
|
|
32878
|
+
return await readFile21(path, "utf8");
|
|
32460
32879
|
} catch (error) {
|
|
32461
32880
|
if (typeof error === "object" && error !== null && Reflect.get(error, "code") === "ENOENT")
|
|
32462
32881
|
return null;
|
|
@@ -32570,14 +32989,14 @@ var writeIosPrivacyManifest = async (path, current, source) => {
|
|
|
32570
32989
|
return false;
|
|
32571
32990
|
if (current !== null)
|
|
32572
32991
|
return writeChangedFile2(path, source);
|
|
32573
|
-
await
|
|
32992
|
+
await writeFile18(path, source, { flag: "wx" });
|
|
32574
32993
|
return true;
|
|
32575
32994
|
};
|
|
32576
32995
|
var configureIosPrivacyProject = async (config, requirements) => {
|
|
32577
32996
|
if (requirements.iosPrivacyAccessedApis.length === 0)
|
|
32578
32997
|
return false;
|
|
32579
|
-
const projectPath2 =
|
|
32580
|
-
const project = await
|
|
32998
|
+
const projectPath2 = join25(config.nativeProjectDirectory, "ios/App/App.xcodeproj/project.pbxproj");
|
|
32999
|
+
const project = await readFile21(projectPath2, "utf8");
|
|
32581
33000
|
return writeChangedFile2(projectPath2, addIosPrivacyProjectReference(project));
|
|
32582
33001
|
};
|
|
32583
33002
|
var addIosPrivacyProjectReference = (source) => {
|
|
@@ -32629,8 +33048,8 @@ ${next.slice(index)}`;
|
|
|
32629
33048
|
return next;
|
|
32630
33049
|
};
|
|
32631
33050
|
var configureIos2 = async (config, plan) => {
|
|
32632
|
-
const path =
|
|
32633
|
-
const source = await
|
|
33051
|
+
const path = join25(config.nativeProjectDirectory, "ios/App/App/Info.plist");
|
|
33052
|
+
const source = await readFile21(path, "utf8");
|
|
32634
33053
|
const requirements = absoluteDeviceNativeRequirements(plan);
|
|
32635
33054
|
const existingSystemBars = source.match(/<key>UIViewControllerBasedStatusBarAppearance<\/key>\s*<(true|false)\s*\/>/u);
|
|
32636
33055
|
const ownedStart = source.indexOf(START_MARKER2);
|
|
@@ -32650,7 +33069,7 @@ ${content}
|
|
|
32650
33069
|
${END_MARKER2}
|
|
32651
33070
|
` : "";
|
|
32652
33071
|
const infoChanged = await writeChangedFile2(path, managed(source, region, source.lastIndexOf("</dict>")));
|
|
32653
|
-
const privacyPath =
|
|
33072
|
+
const privacyPath = join25(config.nativeProjectDirectory, "ios/App/App/PrivacyInfo.xcprivacy");
|
|
32654
33073
|
const privacyCurrent = await optionalSource(privacyPath);
|
|
32655
33074
|
const privacySource = privacyManifestSource(privacyCurrent, requirements);
|
|
32656
33075
|
const [privacyChanged, projectChanged, pushChanged] = await Promise.all([
|
|
@@ -32661,7 +33080,7 @@ ${content}
|
|
|
32661
33080
|
return infoChanged || privacyChanged || projectChanged || pushChanged;
|
|
32662
33081
|
};
|
|
32663
33082
|
var configureIosPushNotifications = async (config, enabled) => {
|
|
32664
|
-
const entitlementsPath =
|
|
33083
|
+
const entitlementsPath = join25(config.nativeProjectDirectory, "ios/App/AbsoluteJS.entitlements");
|
|
32665
33084
|
const entitlements = await optionalSource(entitlementsPath);
|
|
32666
33085
|
if (entitlements === null && !enabled)
|
|
32667
33086
|
return false;
|
|
@@ -32673,7 +33092,7 @@ var configureIosPushNotifications = async (config, enabled) => {
|
|
|
32673
33092
|
<!-- ${PUSH_END_MARKER} -->
|
|
32674
33093
|
` : "";
|
|
32675
33094
|
const nextEntitlements = replacePushRegion(entitlements, entitlementRegion, entitlements.lastIndexOf("</dict>"));
|
|
32676
|
-
const delegatePath =
|
|
33095
|
+
const delegatePath = join25(config.nativeProjectDirectory, "ios/App/App/AppDelegate.swift");
|
|
32677
33096
|
const delegate = await optionalSource(delegatePath);
|
|
32678
33097
|
if (delegate === null && !enabled)
|
|
32679
33098
|
return false;
|
|
@@ -32722,8 +33141,8 @@ var replacePushRegion = (source, region, insertion) => {
|
|
|
32722
33141
|
return `${source.slice(0, insertion)}${region}${source.slice(insertion)}`;
|
|
32723
33142
|
};
|
|
32724
33143
|
var configureAndroid2 = async (config, plan) => {
|
|
32725
|
-
const path =
|
|
32726
|
-
const source = await
|
|
33144
|
+
const path = join25(config.nativeProjectDirectory, "android/app/src/main/AndroidManifest.xml");
|
|
33145
|
+
const source = await readFile21(path, "utf8");
|
|
32727
33146
|
const permissions = absoluteDeviceNativeRequirements(plan).androidPermissions;
|
|
32728
33147
|
const content = permissions.map((permission) => ` <uses-permission android:name="${escapeXml2(permission)}" />`).join(`
|
|
32729
33148
|
`);
|
|
@@ -32758,7 +33177,7 @@ ${content}
|
|
|
32758
33177
|
throw new TypeError(`Android google-services.json does not contain package ${config.appId}.`);
|
|
32759
33178
|
const [manifestChanged, firebaseChanged] = await Promise.all([
|
|
32760
33179
|
writeChangedFile2(path, nextManifest),
|
|
32761
|
-
writeOptionalChangedFile(
|
|
33180
|
+
writeOptionalChangedFile(join25(config.nativeProjectDirectory, "android/app/google-services.json"), firebaseSource)
|
|
32762
33181
|
]);
|
|
32763
33182
|
return manifestChanged || firebaseChanged;
|
|
32764
33183
|
};
|
|
@@ -32777,14 +33196,14 @@ init_nativeAuth();
|
|
|
32777
33196
|
|
|
32778
33197
|
// src/mobile/nativeUpdates.ts
|
|
32779
33198
|
import {
|
|
32780
|
-
mkdir as
|
|
32781
|
-
readFile as
|
|
33199
|
+
mkdir as mkdir16,
|
|
33200
|
+
readFile as readFile22,
|
|
32782
33201
|
readdir as readdir6,
|
|
32783
|
-
rename as
|
|
32784
|
-
rm as
|
|
32785
|
-
writeFile as
|
|
33202
|
+
rename as rename15,
|
|
33203
|
+
rm as rm12,
|
|
33204
|
+
writeFile as writeFile19
|
|
32786
33205
|
} from "fs/promises";
|
|
32787
|
-
import { dirname as
|
|
33206
|
+
import { dirname as dirname16, join as join26 } from "path";
|
|
32788
33207
|
var START = "// absolutejs:mobile-updates:start";
|
|
32789
33208
|
var END = "// absolutejs:mobile-updates:end";
|
|
32790
33209
|
var PLUGIN_START = "// absolutejs:mobile-update-plugin:start";
|
|
@@ -32792,32 +33211,32 @@ var PLUGIN_END = "// absolutejs:mobile-update-plugin:end";
|
|
|
32792
33211
|
var ANDROID_PLUGIN = "AbsoluteMobileUpdateWatchdogPlugin.java";
|
|
32793
33212
|
var optionalSource2 = async (path) => {
|
|
32794
33213
|
try {
|
|
32795
|
-
return await
|
|
33214
|
+
return await readFile22(path, "utf8");
|
|
32796
33215
|
} catch (error) {
|
|
32797
33216
|
if (typeof error === "object" && error !== null && Reflect.get(error, "code") === "ENOENT")
|
|
32798
33217
|
return null;
|
|
32799
33218
|
throw error;
|
|
32800
33219
|
}
|
|
32801
33220
|
};
|
|
32802
|
-
var
|
|
33221
|
+
var isRecord12 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
32803
33222
|
var writeChanged = async (path, source) => {
|
|
32804
33223
|
const current = await optionalSource2(path);
|
|
32805
33224
|
if (current === source)
|
|
32806
33225
|
return false;
|
|
32807
|
-
await
|
|
33226
|
+
await mkdir16(dirname16(path), { recursive: true });
|
|
32808
33227
|
if (current === null) {
|
|
32809
|
-
await
|
|
33228
|
+
await writeFile19(path, source, { flag: "wx" });
|
|
32810
33229
|
return true;
|
|
32811
33230
|
}
|
|
32812
33231
|
const temporary = `${path}.${crypto.randomUUID()}.tmp`;
|
|
32813
|
-
await
|
|
32814
|
-
await
|
|
33232
|
+
await writeFile19(temporary, source, { flag: "wx" });
|
|
33233
|
+
await rename15(temporary, path);
|
|
32815
33234
|
return true;
|
|
32816
33235
|
};
|
|
32817
33236
|
var removeOwnedFile = async (path) => {
|
|
32818
33237
|
if (await optionalSource2(path) === null)
|
|
32819
33238
|
return false;
|
|
32820
|
-
await
|
|
33239
|
+
await rm12(path);
|
|
32821
33240
|
return true;
|
|
32822
33241
|
};
|
|
32823
33242
|
var replaceMarkedRegion = (source, start, end, region, insertion, error) => {
|
|
@@ -32954,11 +33373,11 @@ public final class AbsoluteMobileUpdateWatchdogPlugin: CAPPlugin, CAPBridgedPlug
|
|
|
32954
33373
|
${PLUGIN_END}
|
|
32955
33374
|
`;
|
|
32956
33375
|
var configureIos3 = async (config, enabled) => {
|
|
32957
|
-
const path =
|
|
32958
|
-
const capacitorConfigPath =
|
|
32959
|
-
let source = await
|
|
32960
|
-
const
|
|
32961
|
-
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);
|
|
32962
33381
|
const launchRegion = enabled ? ` ${START}
|
|
32963
33382
|
AbsoluteMobileUpdateWatchdogPlugin.recoverInterruptedBoot()
|
|
32964
33383
|
${END}
|
|
@@ -32967,11 +33386,11 @@ var configureIos3 = async (config, enabled) => {
|
|
|
32967
33386
|
`, brace) + 1, "Could not find a safe iOS location for mobile update recovery.");
|
|
32968
33387
|
const plugin = enabled ? iosPluginRegion(config.updates?.bootTimeoutMs ?? 20000) : "";
|
|
32969
33388
|
source = replaceMarkedRegion(source, PLUGIN_START, PLUGIN_END, plugin, source.length, "Could not find a safe iOS location for the mobile update watchdog.");
|
|
32970
|
-
const capacitorConfigSource2 = await
|
|
33389
|
+
const capacitorConfigSource2 = await readFile22(capacitorConfigPath, "utf8");
|
|
32971
33390
|
let capacitorConfig;
|
|
32972
33391
|
try {
|
|
32973
33392
|
const value = JSON.parse(capacitorConfigSource2);
|
|
32974
|
-
if (!
|
|
33393
|
+
if (!isRecord12(value))
|
|
32975
33394
|
throw new TypeError;
|
|
32976
33395
|
capacitorConfig = value;
|
|
32977
33396
|
} catch {
|
|
@@ -33147,12 +33566,12 @@ var androidActivityInRoot = async (root) => {
|
|
|
33147
33566
|
throw error;
|
|
33148
33567
|
}
|
|
33149
33568
|
const candidate = entries.find((entry) => entry.endsWith("/MainActivity.java") || entry.endsWith("/MainActivity.kt") || entry === "MainActivity.java" || entry === "MainActivity.kt");
|
|
33150
|
-
return candidate ?
|
|
33569
|
+
return candidate ? join26(root, candidate) : undefined;
|
|
33151
33570
|
};
|
|
33152
33571
|
var androidActivity = async (config) => {
|
|
33153
33572
|
const roots = [
|
|
33154
|
-
|
|
33155
|
-
|
|
33573
|
+
join26(config.nativeProjectDirectory, "android/app/src/main/java"),
|
|
33574
|
+
join26(config.nativeProjectDirectory, "android/app/src/main/kotlin")
|
|
33156
33575
|
];
|
|
33157
33576
|
const candidates = await Promise.all(roots.map(androidActivityInRoot));
|
|
33158
33577
|
const candidate = candidates.find((value) => value !== undefined);
|
|
@@ -33251,12 +33670,12 @@ var injectAndroidActivity = (source, enabled) => {
|
|
|
33251
33670
|
};
|
|
33252
33671
|
var configureAndroid3 = async (config, enabled) => {
|
|
33253
33672
|
const activityPath = await androidActivity(config);
|
|
33254
|
-
const activity = await
|
|
33673
|
+
const activity = await readFile22(activityPath, "utf8");
|
|
33255
33674
|
const packageName = activity.match(/^\s*package\s+([A-Za-z0-9_.]+)\s*[;\n]/mu)?.[1];
|
|
33256
33675
|
if (!packageName)
|
|
33257
33676
|
throw new TypeError("Android MainActivity package declaration was not found.");
|
|
33258
33677
|
const packagePath = packageName.replaceAll(".", "/");
|
|
33259
|
-
const pluginPath =
|
|
33678
|
+
const pluginPath = join26(config.nativeProjectDirectory, "android/app/src/main/java", packagePath, ANDROID_PLUGIN);
|
|
33260
33679
|
const changed = await Promise.all([
|
|
33261
33680
|
writeChanged(activityPath, injectAndroidActivity(activity, enabled)),
|
|
33262
33681
|
enabled ? writeChanged(pluginPath, androidPluginSource(packageName, config.updates?.bootTimeoutMs ?? 20000)) : removeOwnedFile(pluginPath)
|
|
@@ -33276,14 +33695,14 @@ var applyAbsoluteNativeUpdates = async (config, platforms = config.platforms) =>
|
|
|
33276
33695
|
};
|
|
33277
33696
|
// src/mobile/nativeObservability.ts
|
|
33278
33697
|
import {
|
|
33279
|
-
mkdir as
|
|
33280
|
-
readFile as
|
|
33698
|
+
mkdir as mkdir17,
|
|
33699
|
+
readFile as readFile23,
|
|
33281
33700
|
readdir as readdir7,
|
|
33282
|
-
rename as
|
|
33283
|
-
rm as
|
|
33284
|
-
writeFile as
|
|
33701
|
+
rename as rename16,
|
|
33702
|
+
rm as rm13,
|
|
33703
|
+
writeFile as writeFile20
|
|
33285
33704
|
} from "fs/promises";
|
|
33286
|
-
import { dirname as
|
|
33705
|
+
import { dirname as dirname17, join as join27 } from "path";
|
|
33287
33706
|
var START2 = "// absolutejs:native-observability:start";
|
|
33288
33707
|
var END2 = "// absolutejs:native-observability:end";
|
|
33289
33708
|
var PLUGIN_START2 = "// absolutejs:native-observability-plugin:start";
|
|
@@ -33291,7 +33710,7 @@ var PLUGIN_END2 = "// absolutejs:native-observability-plugin:end";
|
|
|
33291
33710
|
var ANDROID_PLUGIN2 = "AbsoluteMobileObservabilityPlugin.java";
|
|
33292
33711
|
var optionalSource3 = async (path) => {
|
|
33293
33712
|
try {
|
|
33294
|
-
return await
|
|
33713
|
+
return await readFile23(path, "utf8");
|
|
33295
33714
|
} catch (error) {
|
|
33296
33715
|
if (typeof error === "object" && error !== null && Reflect.get(error, "code") === "ENOENT")
|
|
33297
33716
|
return null;
|
|
@@ -33302,23 +33721,23 @@ var writeChanged2 = async (path, source) => {
|
|
|
33302
33721
|
const current = await optionalSource3(path);
|
|
33303
33722
|
if (current === source)
|
|
33304
33723
|
return false;
|
|
33305
|
-
await
|
|
33724
|
+
await mkdir17(dirname17(path), { recursive: true });
|
|
33306
33725
|
if (current === null) {
|
|
33307
|
-
await
|
|
33726
|
+
await writeFile20(path, source, { flag: "wx" });
|
|
33308
33727
|
return true;
|
|
33309
33728
|
}
|
|
33310
33729
|
const temporary = `${path}.${crypto.randomUUID()}.tmp`;
|
|
33311
|
-
await
|
|
33312
|
-
await
|
|
33730
|
+
await writeFile20(temporary, source, { flag: "wx" });
|
|
33731
|
+
await rename16(temporary, path);
|
|
33313
33732
|
return true;
|
|
33314
33733
|
};
|
|
33315
33734
|
var removeOwnedFile2 = async (path) => {
|
|
33316
33735
|
if (await optionalSource3(path) === null)
|
|
33317
33736
|
return false;
|
|
33318
|
-
await
|
|
33737
|
+
await rm13(path);
|
|
33319
33738
|
return true;
|
|
33320
33739
|
};
|
|
33321
|
-
var
|
|
33740
|
+
var isRecord13 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
33322
33741
|
var replaceMarkedRegion2 = (source, start, end, region, insertion, error) => {
|
|
33323
33742
|
const existingStart = source.indexOf(start);
|
|
33324
33743
|
const existingEnd = source.indexOf(end);
|
|
@@ -33451,9 +33870,9 @@ public final class AbsoluteMobileObservabilityPlugin: CAPPlugin, CAPBridgedPlugi
|
|
|
33451
33870
|
${PLUGIN_END2}
|
|
33452
33871
|
`;
|
|
33453
33872
|
var configureIos4 = async (config, enabled) => {
|
|
33454
|
-
const path =
|
|
33455
|
-
const capacitorConfigPath =
|
|
33456
|
-
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");
|
|
33457
33876
|
if (enabled && !source.includes("import MetricKit")) {
|
|
33458
33877
|
const capacitorImport = source.lastIndexOf("import Capacitor");
|
|
33459
33878
|
if (capacitorImport < 0)
|
|
@@ -33467,11 +33886,11 @@ ${source.slice(newline + 1)}`;
|
|
|
33467
33886
|
source = source.replace(`import MetricKit
|
|
33468
33887
|
`, "");
|
|
33469
33888
|
source = replaceMarkedRegion2(source, PLUGIN_START2, PLUGIN_END2, enabled ? iosPluginRegion2 : "", source.length, "Could not find a safe iOS location for native observability.");
|
|
33470
|
-
const capacitorConfigSource2 = await
|
|
33889
|
+
const capacitorConfigSource2 = await readFile23(capacitorConfigPath, "utf8");
|
|
33471
33890
|
let capacitorConfig;
|
|
33472
33891
|
try {
|
|
33473
33892
|
const value = JSON.parse(capacitorConfigSource2);
|
|
33474
|
-
if (!
|
|
33893
|
+
if (!isRecord13(value))
|
|
33475
33894
|
throw new TypeError;
|
|
33476
33895
|
capacitorConfig = value;
|
|
33477
33896
|
} catch {
|
|
@@ -33712,12 +34131,12 @@ var androidActivityInRoot2 = async (root) => {
|
|
|
33712
34131
|
throw error;
|
|
33713
34132
|
}
|
|
33714
34133
|
const candidate = entries.find((entry) => entry.endsWith("/MainActivity.java") || entry.endsWith("/MainActivity.kt") || entry === "MainActivity.java" || entry === "MainActivity.kt");
|
|
33715
|
-
return candidate ?
|
|
34134
|
+
return candidate ? join27(root, candidate) : undefined;
|
|
33716
34135
|
};
|
|
33717
34136
|
var androidActivity2 = async (config) => {
|
|
33718
34137
|
const roots = [
|
|
33719
|
-
|
|
33720
|
-
|
|
34138
|
+
join27(config.nativeProjectDirectory, "android/app/src/main/java"),
|
|
34139
|
+
join27(config.nativeProjectDirectory, "android/app/src/main/kotlin")
|
|
33721
34140
|
];
|
|
33722
34141
|
const candidates = await Promise.all(roots.map(androidActivityInRoot2));
|
|
33723
34142
|
const candidate = candidates.find((value) => value !== undefined);
|
|
@@ -33785,11 +34204,11 @@ var injectAndroidActivity2 = (source, enabled) => {
|
|
|
33785
34204
|
};
|
|
33786
34205
|
var configureAndroid4 = async (config, enabled) => {
|
|
33787
34206
|
const activityPath = await androidActivity2(config);
|
|
33788
|
-
const activity = await
|
|
34207
|
+
const activity = await readFile23(activityPath, "utf8");
|
|
33789
34208
|
const packageName = activity.match(/^\s*package\s+([A-Za-z0-9_.]+)\s*[;\n]/mu)?.[1];
|
|
33790
34209
|
if (!packageName)
|
|
33791
34210
|
throw new TypeError("Android MainActivity package declaration was not found.");
|
|
33792
|
-
const pluginPath =
|
|
34211
|
+
const pluginPath = join27(config.nativeProjectDirectory, "android/app/src/main/java", packageName.replaceAll(".", "/"), ANDROID_PLUGIN2);
|
|
33793
34212
|
const changed = await Promise.all([
|
|
33794
34213
|
writeChanged2(activityPath, injectAndroidActivity2(activity, enabled)),
|
|
33795
34214
|
enabled ? writeChanged2(pluginPath, androidPluginSource2(packageName)) : removeOwnedFile2(pluginPath)
|
|
@@ -33814,8 +34233,8 @@ init_producerContext();
|
|
|
33814
34233
|
init_releaseArtifact();
|
|
33815
34234
|
|
|
33816
34235
|
// src/mobile/releasePublisher.ts
|
|
33817
|
-
import { access as
|
|
33818
|
-
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";
|
|
33819
34238
|
import { pathToFileURL as pathToFileURL3 } from "url";
|
|
33820
34239
|
var prepareAbsoluteIosRelease = async (publisher, options) => {
|
|
33821
34240
|
if (typeof publisher.prepareIosRelease !== "function") {
|
|
@@ -33838,24 +34257,24 @@ var prepareAbsoluteAndroidRelease = async (publisher, options) => {
|
|
|
33838
34257
|
}
|
|
33839
34258
|
return versionCode;
|
|
33840
34259
|
};
|
|
33841
|
-
var
|
|
33842
|
-
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";
|
|
33843
34262
|
var publisherModulePath = (projectRoot, requested) => {
|
|
33844
|
-
const root =
|
|
33845
|
-
const path =
|
|
33846
|
-
const projectRelative =
|
|
33847
|
-
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)) {
|
|
33848
34267
|
throw new TypeError("mobile publish --registry must remain inside the project.");
|
|
33849
34268
|
}
|
|
33850
34269
|
return path;
|
|
33851
34270
|
};
|
|
33852
34271
|
var loadAbsoluteNativeReleasePublisher = async (projectRoot, requestedModulePath) => {
|
|
33853
34272
|
const modulePath = publisherModulePath(projectRoot, requestedModulePath);
|
|
33854
|
-
await
|
|
34273
|
+
await access16(modulePath).catch(() => {
|
|
33855
34274
|
throw new TypeError(`Native release registry module does not exist: ${modulePath}`);
|
|
33856
34275
|
});
|
|
33857
34276
|
const loaded = await import(pathToFileURL3(modulePath).href);
|
|
33858
|
-
const publisher =
|
|
34277
|
+
const publisher = isRecord14(loaded) ? loaded.default ?? loaded.registry : undefined;
|
|
33859
34278
|
if (!isPublisher(publisher)) {
|
|
33860
34279
|
throw new TypeError("Native release registry module must default-export a registry with publish(options).");
|
|
33861
34280
|
}
|
|
@@ -33915,7 +34334,7 @@ var publishAbsoluteIosRelease = async (options) => {
|
|
|
33915
34334
|
init_pageProtocol();
|
|
33916
34335
|
init_releaseArtifact();
|
|
33917
34336
|
import { existsSync as existsSync7, readFileSync as readFileSync8 } from "fs";
|
|
33918
|
-
import { dirname as
|
|
34337
|
+
import { dirname as dirname18, extname as extname6, relative as relative16, resolve as resolve18 } from "path";
|
|
33919
34338
|
import ts2 from "typescript";
|
|
33920
34339
|
var ROUTE_METHODS = new Set(["get", "head"]);
|
|
33921
34340
|
var SOURCE_FILTER = /\.[cm]?[jt]sx?$/;
|
|
@@ -33966,7 +34385,7 @@ var PAGE_HANDLERS = new Map([
|
|
|
33966
34385
|
]
|
|
33967
34386
|
]);
|
|
33968
34387
|
var posixPath = (value) => value.replace(/\\/g, "/");
|
|
33969
|
-
var findTsconfig = (entry, projectRoot) => ts2.findConfigFile(
|
|
34388
|
+
var findTsconfig = (entry, projectRoot) => ts2.findConfigFile(dirname18(entry), existsSync7, "tsconfig.json") ?? ts2.findConfigFile(projectRoot, existsSync7, "tsconfig.json");
|
|
33970
34389
|
var createProgram = (entry, projectRoot) => {
|
|
33971
34390
|
const configPath2 = findTsconfig(entry, projectRoot);
|
|
33972
34391
|
if (!configPath2) {
|
|
@@ -33978,7 +34397,7 @@ var createProgram = (entry, projectRoot) => {
|
|
|
33978
34397
|
target: ts2.ScriptTarget.ESNext
|
|
33979
34398
|
});
|
|
33980
34399
|
}
|
|
33981
|
-
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));
|
|
33982
34401
|
if (!parsed.fileNames.includes(entry))
|
|
33983
34402
|
parsed.fileNames.push(entry);
|
|
33984
34403
|
return ts2.createProgram(parsed.fileNames, parsed.options);
|
|
@@ -34084,7 +34503,7 @@ var resolvePageIdentity = (expression, sourceFile, checker, projectRoot) => {
|
|
|
34084
34503
|
const declaration = symbol?.declarations?.[0];
|
|
34085
34504
|
const file = declaration?.getSourceFile().fileName ?? sourceFile.fileName;
|
|
34086
34505
|
const exportedName = symbol?.name ?? expression.getText(sourceFile);
|
|
34087
|
-
const source = posixPath(
|
|
34506
|
+
const source = posixPath(relative16(projectRoot, file));
|
|
34088
34507
|
return `${source}#${exportedName}`;
|
|
34089
34508
|
};
|
|
34090
34509
|
var resolveAlias = (symbol, checker) => {
|
|
@@ -34323,7 +34742,7 @@ var analyzeProgram = (program, projectRoot) => {
|
|
|
34323
34742
|
const checker = program.getTypeChecker();
|
|
34324
34743
|
const analyzed = new Map;
|
|
34325
34744
|
for (const sourceFile of program.getSourceFiles()) {
|
|
34326
|
-
const resolvedFile =
|
|
34745
|
+
const resolvedFile = resolve18(sourceFile.fileName);
|
|
34327
34746
|
if (!isProjectSource(sourceFile, resolvedFile, projectRoot))
|
|
34328
34747
|
continue;
|
|
34329
34748
|
const analysis = analyzeSourceFile(sourceFile, checker, projectRoot);
|
|
@@ -34416,14 +34835,14 @@ var transformFile = (source, fileName, analysis) => {
|
|
|
34416
34835
|
};
|
|
34417
34836
|
var ABSOLUTE_MOBILE_TRANSFORM_PROTOCOL = ABSOLUTE_MOBILE_PAGE_PROTOCOL_VERSION;
|
|
34418
34837
|
var createAbsoluteMobileRouteMetadataPlugin = (options) => {
|
|
34419
|
-
const projectRoot =
|
|
34420
|
-
const entry =
|
|
34838
|
+
const projectRoot = resolve18(options.projectRoot ?? process.cwd());
|
|
34839
|
+
const entry = resolve18(options.entry);
|
|
34421
34840
|
const analyzed = analyzeProgram(createProgram(entry, projectRoot), projectRoot);
|
|
34422
34841
|
return {
|
|
34423
34842
|
name: "absolute-mobile-route-metadata",
|
|
34424
34843
|
setup(build) {
|
|
34425
34844
|
build.onLoad({ filter: SOURCE_FILTER }, async ({ path }) => {
|
|
34426
|
-
const analysis = analyzed.get(
|
|
34845
|
+
const analysis = analyzed.get(resolve18(path));
|
|
34427
34846
|
if (!analysis)
|
|
34428
34847
|
return;
|
|
34429
34848
|
const source = await Bun.file(path).text();
|
|
@@ -34436,11 +34855,11 @@ var createAbsoluteMobileRouteMetadataPlugin = (options) => {
|
|
|
34436
34855
|
};
|
|
34437
34856
|
};
|
|
34438
34857
|
var inspectAbsoluteMobileRouteMetadata = (options) => {
|
|
34439
|
-
const projectRoot =
|
|
34440
|
-
const entry =
|
|
34858
|
+
const projectRoot = resolve18(options.projectRoot ?? process.cwd());
|
|
34859
|
+
const entry = resolve18(options.entry);
|
|
34441
34860
|
const analyzed = analyzeProgram(createProgram(entry, projectRoot), projectRoot);
|
|
34442
34861
|
return [...analyzed.entries()].flatMap(([file, analysis]) => [...analysis.byRouteCall.values()].map(({ metadata }) => ({
|
|
34443
|
-
file: posixPath(
|
|
34862
|
+
file: posixPath(relative16(projectRoot, file)),
|
|
34444
34863
|
metadata
|
|
34445
34864
|
})));
|
|
34446
34865
|
};
|
|
@@ -34774,7 +35193,7 @@ var createCapacitor = (win) => {
|
|
|
34774
35193
|
callbackId
|
|
34775
35194
|
}, callback);
|
|
34776
35195
|
};
|
|
34777
|
-
const p = new Promise((
|
|
35196
|
+
const p = new Promise((resolve19) => call.then(() => resolve19({ remove })));
|
|
34778
35197
|
p.remove = async () => {
|
|
34779
35198
|
console.warn(`Using addListener() without 'await' is deprecated.`);
|
|
34780
35199
|
await remove();
|
|
@@ -34979,11 +35398,11 @@ class CapacitorCookiesPluginWeb extends WebPlugin {
|
|
|
34979
35398
|
var CapacitorCookies = registerPlugin("CapacitorCookies", {
|
|
34980
35399
|
web: () => new CapacitorCookiesPluginWeb
|
|
34981
35400
|
});
|
|
34982
|
-
var readBlobAsBase64 = async (blob) => new Promise((
|
|
35401
|
+
var readBlobAsBase64 = async (blob) => new Promise((resolve19, reject) => {
|
|
34983
35402
|
const reader = new FileReader;
|
|
34984
35403
|
reader.onload = () => {
|
|
34985
35404
|
const base64String = reader.result;
|
|
34986
|
-
|
|
35405
|
+
resolve19(base64String.indexOf(",") >= 0 ? base64String.split(",")[1] : base64String);
|
|
34987
35406
|
};
|
|
34988
35407
|
reader.onerror = (error) => reject(error);
|
|
34989
35408
|
reader.readAsDataURL(blob);
|
|
@@ -35159,7 +35578,7 @@ var REPORT_KINDS = new Set([
|
|
|
35159
35578
|
"signal"
|
|
35160
35579
|
]);
|
|
35161
35580
|
var nativeObservability = registerPlugin("AbsoluteMobileObservability");
|
|
35162
|
-
var
|
|
35581
|
+
var isRecord15 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
35163
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]");
|
|
35164
35583
|
var redactValue = (value, depth = 0) => {
|
|
35165
35584
|
if (depth >= MAX_REDACTION_DEPTH)
|
|
@@ -35170,7 +35589,7 @@ var redactValue = (value, depth = 0) => {
|
|
|
35170
35589
|
return value;
|
|
35171
35590
|
if (Array.isArray(value))
|
|
35172
35591
|
return value.slice(0, 64).map((entry) => redactValue(entry, depth + 1));
|
|
35173
|
-
if (!
|
|
35592
|
+
if (!isRecord15(value))
|
|
35174
35593
|
return String(value).slice(0, MAX_STRING_LENGTH);
|
|
35175
35594
|
return Object.fromEntries(Object.entries(value).slice(0, 128).map(([key, entry]) => [
|
|
35176
35595
|
key,
|
|
@@ -35178,7 +35597,7 @@ var redactValue = (value, depth = 0) => {
|
|
|
35178
35597
|
]));
|
|
35179
35598
|
};
|
|
35180
35599
|
var parseReport = (value) => {
|
|
35181
|
-
if (!
|
|
35600
|
+
if (!isRecord15(value) || !isRecord15(value.details))
|
|
35182
35601
|
return;
|
|
35183
35602
|
if (typeof value.id !== "string" || !REPORT_ID.test(value.id))
|
|
35184
35603
|
return;
|
|
@@ -35189,7 +35608,7 @@ var parseReport = (value) => {
|
|
|
35189
35608
|
if (value.platform !== "android" && value.platform !== "ios")
|
|
35190
35609
|
return;
|
|
35191
35610
|
const details = redactValue(value.details);
|
|
35192
|
-
if (!
|
|
35611
|
+
if (!isRecord15(details))
|
|
35193
35612
|
return;
|
|
35194
35613
|
if (new TextEncoder().encode(JSON.stringify(details)).byteLength > MAX_DETAIL_BYTES)
|
|
35195
35614
|
return;
|
|
@@ -39643,8 +40062,8 @@ var createBeacon = (options) => {
|
|
|
39643
40062
|
if (await fontAvailable(element))
|
|
39644
40063
|
return;
|
|
39645
40064
|
if (confirmationMs > 0) {
|
|
39646
|
-
await new Promise((
|
|
39647
|
-
const timer2 = window.setTimeout(
|
|
40065
|
+
await new Promise((resolve19) => {
|
|
40066
|
+
const timer2 = window.setTimeout(resolve19, confirmationMs);
|
|
39648
40067
|
cleanups.push(() => window.clearTimeout(timer2));
|
|
39649
40068
|
});
|
|
39650
40069
|
if (document.visibilityState === "hidden")
|
|
@@ -40632,51 +41051,51 @@ var createAbsoluteMobileUpdateClient = (options) => {
|
|
|
40632
41051
|
};
|
|
40633
41052
|
};
|
|
40634
41053
|
// src/mobile/updatePublisher.ts
|
|
40635
|
-
import { access as
|
|
40636
|
-
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";
|
|
40637
41056
|
import { pathToFileURL as pathToFileURL4 } from "url";
|
|
40638
41057
|
|
|
40639
41058
|
// src/mobile/updateSigning.ts
|
|
40640
|
-
import { createHash as
|
|
41059
|
+
import { createHash as createHash15, sign, verify } from "crypto";
|
|
40641
41060
|
import {
|
|
40642
|
-
cp as
|
|
40643
|
-
mkdir as
|
|
40644
|
-
mkdtemp as
|
|
41061
|
+
cp as cp2,
|
|
41062
|
+
mkdir as mkdir18,
|
|
41063
|
+
mkdtemp as mkdtemp9,
|
|
40645
41064
|
readdir as readdir8,
|
|
40646
|
-
readFile as
|
|
40647
|
-
rename as
|
|
40648
|
-
rm as
|
|
40649
|
-
stat as
|
|
40650
|
-
writeFile as
|
|
41065
|
+
readFile as readFile24,
|
|
41066
|
+
rename as rename17,
|
|
41067
|
+
rm as rm14,
|
|
41068
|
+
stat as stat5,
|
|
41069
|
+
writeFile as writeFile21
|
|
40651
41070
|
} from "fs/promises";
|
|
40652
|
-
import { dirname as
|
|
41071
|
+
import { dirname as dirname19, join as join28, relative as relative17, resolve as resolve19 } from "path";
|
|
40653
41072
|
var UPDATE_MANIFEST_FILE = "update.json";
|
|
40654
41073
|
var UPDATE_FILES_DIRECTORY = "files";
|
|
40655
|
-
var
|
|
41074
|
+
var sha2563 = (value) => createHash15("sha256").update(value).digest("hex");
|
|
40656
41075
|
var listFiles = async (root, directory = root) => {
|
|
40657
41076
|
const entries = await readdir8(directory, { withFileTypes: true });
|
|
40658
41077
|
const paths = await Promise.all(entries.map(async (entry) => {
|
|
40659
|
-
const path =
|
|
41078
|
+
const path = join28(directory, entry.name);
|
|
40660
41079
|
if (entry.isDirectory())
|
|
40661
41080
|
return listFiles(root, path);
|
|
40662
41081
|
if (!entry.isFile())
|
|
40663
41082
|
throw new TypeError("Mobile updates cannot contain links or special files.");
|
|
40664
|
-
return [
|
|
41083
|
+
return [relative17(root, path).replaceAll("\\", "/")];
|
|
40665
41084
|
}));
|
|
40666
41085
|
return paths.flat().sort((left, right) => left.localeCompare(right));
|
|
40667
41086
|
};
|
|
40668
41087
|
var inspectFiles = async (root, paths) => Promise.all(paths.map(async (path) => {
|
|
40669
|
-
const source =
|
|
41088
|
+
const source = join28(root, path);
|
|
40670
41089
|
const [metadata, contents] = await Promise.all([
|
|
40671
|
-
|
|
40672
|
-
|
|
41090
|
+
stat5(source),
|
|
41091
|
+
readFile24(source)
|
|
40673
41092
|
]);
|
|
40674
|
-
return { bytes: metadata.size, path, sha256:
|
|
41093
|
+
return { bytes: metadata.size, path, sha256: sha2563(contents) };
|
|
40675
41094
|
}));
|
|
40676
|
-
var releaseIdFor = (value) => `amu_${
|
|
41095
|
+
var releaseIdFor = (value) => `amu_${sha2563(canonicalizeAbsoluteMobileUpdate(value))}`;
|
|
40677
41096
|
var buildAbsoluteMobileUpdate = async (options) => {
|
|
40678
|
-
const bundleDirectory =
|
|
40679
|
-
const outputRoot =
|
|
41097
|
+
const bundleDirectory = resolve19(options.bundleDirectory);
|
|
41098
|
+
const outputRoot = resolve19(options.outputDirectory);
|
|
40680
41099
|
if (outputRoot === bundleDirectory || outputRoot.startsWith(`${bundleDirectory}/`))
|
|
40681
41100
|
throw new TypeError("Mobile update output must be outside the embedded bundle.");
|
|
40682
41101
|
const paths = await listFiles(bundleDirectory);
|
|
@@ -40704,38 +41123,38 @@ var buildAbsoluteMobileUpdate = async (options) => {
|
|
|
40704
41123
|
value: signature.toString("base64")
|
|
40705
41124
|
}
|
|
40706
41125
|
});
|
|
40707
|
-
await
|
|
40708
|
-
const outputDirectory =
|
|
40709
|
-
const staging = await
|
|
41126
|
+
await mkdir18(outputRoot, { recursive: true });
|
|
41127
|
+
const outputDirectory = join28(outputRoot, manifest.releaseId);
|
|
41128
|
+
const staging = await mkdtemp9(join28(outputRoot, ".stage-"));
|
|
40710
41129
|
try {
|
|
40711
|
-
await
|
|
41130
|
+
await cp2(bundleDirectory, join28(staging, UPDATE_FILES_DIRECTORY), {
|
|
40712
41131
|
force: true,
|
|
40713
41132
|
recursive: true
|
|
40714
41133
|
});
|
|
40715
|
-
await
|
|
41134
|
+
await writeFile21(join28(staging, UPDATE_MANIFEST_FILE), `${JSON.stringify(manifest, null, "\t")}
|
|
40716
41135
|
`);
|
|
40717
|
-
await
|
|
41136
|
+
await rename17(staging, outputDirectory);
|
|
40718
41137
|
} catch (error) {
|
|
40719
|
-
await
|
|
41138
|
+
await rm14(staging, { force: true, recursive: true });
|
|
40720
41139
|
if (typeof error === "object" && error !== null && Reflect.get(error, "code") === "EEXIST")
|
|
40721
41140
|
throw new TypeError(`Mobile update ${manifest.releaseId} already exists.`, { cause: error });
|
|
40722
41141
|
throw error;
|
|
40723
41142
|
}
|
|
40724
41143
|
return {
|
|
40725
41144
|
manifest,
|
|
40726
|
-
manifestPath:
|
|
41145
|
+
manifestPath: join28(outputDirectory, UPDATE_MANIFEST_FILE),
|
|
40727
41146
|
outputDirectory
|
|
40728
41147
|
};
|
|
40729
41148
|
};
|
|
40730
41149
|
var copyAbsoluteMobileUpdateFile = async (updateDirectory, path, destination) => {
|
|
40731
|
-
const source =
|
|
40732
|
-
const root =
|
|
41150
|
+
const source = resolve19(updateDirectory, UPDATE_FILES_DIRECTORY, path);
|
|
41151
|
+
const root = resolve19(updateDirectory, UPDATE_FILES_DIRECTORY);
|
|
40733
41152
|
if (!source.startsWith(`${root}/`))
|
|
40734
41153
|
throw new TypeError("Update file escaped its release.");
|
|
40735
|
-
await
|
|
40736
|
-
await
|
|
41154
|
+
await mkdir18(dirname19(destination), { recursive: true });
|
|
41155
|
+
await cp2(source, destination, { force: true });
|
|
40737
41156
|
};
|
|
40738
|
-
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")));
|
|
40739
41158
|
var verifyAbsoluteMobileUpdateSignature = (manifestValue, publicKey) => {
|
|
40740
41159
|
const manifest = parseAbsoluteMobileUpdateManifest(manifestValue);
|
|
40741
41160
|
const valid = verify("sha256", absoluteMobileUpdateSigningPayload(unsignedAbsoluteMobileUpdate(manifest)), { dsaEncoding: "ieee-p1363", key: publicKey }, Buffer.from(manifest.signature.value, "base64"));
|
|
@@ -40852,16 +41271,16 @@ var pruneAbsoluteMobileUpdates = async (options) => {
|
|
|
40852
41271
|
var object5 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
40853
41272
|
var isPublisher2 = (value) => object5(value) && typeof value.publishUpdate === "function" && typeof value.promoteUpdate === "function" && typeof value.rollbackUpdate === "function";
|
|
40854
41273
|
var projectPath2 = (projectRoot, requested, label) => {
|
|
40855
|
-
const root =
|
|
40856
|
-
const path =
|
|
40857
|
-
const projectRelative =
|
|
40858
|
-
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))
|
|
40859
41278
|
throw new TypeError(`${label} must remain inside the project.`);
|
|
40860
41279
|
return path;
|
|
40861
41280
|
};
|
|
40862
41281
|
var loadAbsoluteMobileUpdatePublisher = async (projectRoot, requestedModulePath) => {
|
|
40863
41282
|
const modulePath = projectPath2(projectRoot, requestedModulePath, "mobile update registry");
|
|
40864
|
-
await
|
|
41283
|
+
await access17(modulePath).catch(() => {
|
|
40865
41284
|
throw new TypeError(`Mobile update registry does not exist: ${modulePath}`);
|
|
40866
41285
|
});
|
|
40867
41286
|
const loaded = await import(pathToFileURL4(modulePath).href);
|
|
@@ -40912,7 +41331,7 @@ var rollbackAbsoluteMobileUpdate = async (options) => {
|
|
|
40912
41331
|
return result;
|
|
40913
41332
|
};
|
|
40914
41333
|
// src/mobile/updateRollout.ts
|
|
40915
|
-
import { createHash as
|
|
41334
|
+
import { createHash as createHash16 } from "crypto";
|
|
40916
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;
|
|
40917
41336
|
var requireHeader = (headers, name) => {
|
|
40918
41337
|
const value = headers.get(name);
|
|
@@ -40927,7 +41346,7 @@ var isAbsoluteMobileUpdateRolloutMember = (options) => {
|
|
|
40927
41346
|
return false;
|
|
40928
41347
|
if (options.rollout === 1)
|
|
40929
41348
|
return true;
|
|
40930
|
-
const digest =
|
|
41349
|
+
const digest = createHash16("sha256").update(`${options.appId}\x00${options.channel}\x00${options.releaseId}\x00${options.installationId}`).digest();
|
|
40931
41350
|
const bucket = digest.readUInt32BE(0) / 4294967296;
|
|
40932
41351
|
return bucket < options.rollout;
|
|
40933
41352
|
};
|
|
@@ -40951,6 +41370,9 @@ init_updateServer();
|
|
|
40951
41370
|
export {
|
|
40952
41371
|
ABSOLUTE_ANDROID_RELEASE_FORMAT,
|
|
40953
41372
|
ABSOLUTE_AUTH_PACKAGE,
|
|
41373
|
+
ABSOLUTE_BUNDLETOOL_SHA256,
|
|
41374
|
+
ABSOLUTE_BUNDLETOOL_URL,
|
|
41375
|
+
ABSOLUTE_BUNDLETOOL_VERSION,
|
|
40954
41376
|
ABSOLUTE_EXPO_AUTH_CORE_VERSION,
|
|
40955
41377
|
ABSOLUTE_EXPO_AUTH_PACKAGE,
|
|
40956
41378
|
ABSOLUTE_EXPO_AUTH_VERSION,
|
|
@@ -40999,6 +41421,7 @@ export {
|
|
|
40999
41421
|
MOBILE_PAGE_REQUEST_HEADERS,
|
|
41000
41422
|
absoluteAndroidNodeLabel,
|
|
41001
41423
|
absoluteAndroidTouchTargetDp,
|
|
41424
|
+
absoluteBundletoolPath,
|
|
41002
41425
|
absoluteDeviceNativeRequirements,
|
|
41003
41426
|
absoluteExpoExecutable,
|
|
41004
41427
|
absoluteExpoNativeObservabilityFiles,
|
|
@@ -41066,6 +41489,7 @@ export {
|
|
|
41066
41489
|
discoverAbsoluteSyncSchema,
|
|
41067
41490
|
disposeAbsoluteMobilePage,
|
|
41068
41491
|
drainAbsoluteMobileNativeObservability,
|
|
41492
|
+
ensureAbsoluteBundletool,
|
|
41069
41493
|
expoNativeObservabilityRuntimeSource,
|
|
41070
41494
|
fetchAbsoluteMobilePage,
|
|
41071
41495
|
finalizeAbsoluteExpoUpdateExport,
|
|
@@ -41082,6 +41506,7 @@ export {
|
|
|
41082
41506
|
getCurrentAbsoluteMobileProducerContext,
|
|
41083
41507
|
hashAbsoluteMobilePropsSchema,
|
|
41084
41508
|
inspectAbsoluteAndroidInstalledApp,
|
|
41509
|
+
inspectAbsoluteBundletool,
|
|
41085
41510
|
inspectAbsoluteIosInstalledApp,
|
|
41086
41511
|
inspectAbsoluteMobileRouteMetadata,
|
|
41087
41512
|
inspectAbsoluteMobileUpdateHealth,
|
|
@@ -41157,6 +41582,7 @@ export {
|
|
|
41157
41582
|
publishAbsoluteAndroidRelease,
|
|
41158
41583
|
publishAbsoluteIosRelease,
|
|
41159
41584
|
publishAbsoluteMobileUpdate,
|
|
41585
|
+
readAbsoluteAndroidRelease,
|
|
41160
41586
|
readAbsoluteMobileLinkIntent,
|
|
41161
41587
|
readAbsoluteMobileMaterializedReleases,
|
|
41162
41588
|
readAbsoluteMobileUpdate,
|
|
@@ -41179,6 +41605,7 @@ export {
|
|
|
41179
41605
|
resumeAbsoluteMobileUpdateRollout,
|
|
41180
41606
|
retainAbsoluteMobileCompatibilityArtifacts,
|
|
41181
41607
|
rollbackAbsoluteMobileUpdate,
|
|
41608
|
+
runAbsoluteAndroidReleaseAcceptance,
|
|
41182
41609
|
runAbsoluteAndroidUpgradeConformance,
|
|
41183
41610
|
runWithAbsoluteMobileProducer,
|
|
41184
41611
|
serializeAbsoluteMobileAuthEnvironment,
|
|
@@ -41205,5 +41632,5 @@ export {
|
|
|
41205
41632
|
writeAbsoluteMobileUpdateRegistry
|
|
41206
41633
|
};
|
|
41207
41634
|
|
|
41208
|
-
//# debugId=
|
|
41635
|
+
//# debugId=FC8B1849EF68EB6464756E2164756E21
|
|
41209
41636
|
//# sourceMappingURL=index.js.map
|