@absolutejs/absolute 0.20.0-beta.115 → 0.20.0-beta.117
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 +18 -0
- package/changelog.json +38 -1
- package/dist/angular/components/core/streamingSlotRegistrar.js +1 -1
- package/dist/angular/components/core/streamingSlotRegistry.js +2 -2
- package/dist/build.js +9 -4
- package/dist/build.js.map +5 -4
- package/dist/cli/{androidEmulatorController-nybhzc6c.js → androidEmulatorController-v6chbhem.js} +2 -2
- package/dist/cli/{androidNativeWatcher-2930tb8c.js → androidNativeWatcher-mgqws6ag.js} +2 -2
- package/dist/cli/{compile-ya4kd2sg.js → compile-5m830csy.js} +2 -2
- package/dist/cli/{dev-5cqmf7za.js → dev-ww30tdrv.js} +10 -7
- package/dist/cli/{expoProject-f5j20xms.js → expoProject-w2pzjwnx.js} +1 -1
- package/dist/cli/{index-28pbrd3q.js → index-18q9qc7f.js} +15 -2
- package/dist/cli/{index-5fmgn0nx.js → index-5268nwjx.js} +1 -1
- package/dist/cli/{index-5skbydh0.js → index-hneb973j.js} +1 -1
- package/dist/cli/{index-6mbm4n3g.js → index-k8r00xh9.js} +1 -1
- package/dist/cli/{index-dr21p6ae.js → index-nxcwg9ma.js} +590 -152
- package/dist/cli/{index-qr0pc777.js → index-wtyg9cy0.js} +1 -1
- package/dist/cli/index.js +5 -5
- package/dist/cli/{iosNativeWatcher-t6gv0p1w.js → iosNativeWatcher-8w1gawg4.js} +2 -2
- package/dist/cli/{iosSimulatorController-5n2a9fxv.js → iosSimulatorController-5vhqvhg6.js} +2 -2
- package/dist/cli/{mobile-fg2226vv.js → mobile-21vsmrjd.js} +47 -56
- package/dist/cli/{start-jt61f40d.js → start-3bhf56tj.js} +3 -3
- package/dist/index.js +12 -6
- package/dist/index.js.map +6 -5
- package/dist/mobile/index.js +692 -274
- package/dist/mobile/index.js.map +8 -6
- package/dist/mobile/remoteMacAgentEntry.js +564 -231
- package/dist/mobile/shellBootstrap.js +6 -1
- package/dist/react/hooks/index.js.map +2 -2
- package/dist/src/dev/serverEntryCopies.d.ts +2 -0
- package/dist/src/mobile/capacitorProject.d.ts +4 -0
- package/dist/src/mobile/expoEmbeddedAssets.d.ts +1 -0
- package/dist/src/mobile/nativePackages.d.ts +10 -0
- package/dist/src/mobile/updateRuntime.d.ts +1 -0
- package/package.json +6 -2
package/dist/mobile/index.js
CHANGED
|
@@ -1120,7 +1120,7 @@ __export(exports_associationFiles, {
|
|
|
1120
1120
|
});
|
|
1121
1121
|
import {
|
|
1122
1122
|
access as access11,
|
|
1123
|
-
mkdir as
|
|
1123
|
+
mkdir as mkdir11,
|
|
1124
1124
|
readFile as readFile13,
|
|
1125
1125
|
rename as rename10,
|
|
1126
1126
|
rm as rm10,
|
|
@@ -1241,7 +1241,7 @@ var JSON_HEADERS, OWNERSHIP_FILE = ".absolutejs-mobile-associations.json", HTTP_
|
|
|
1241
1241
|
await rm10(backup, { force: true, recursive: true });
|
|
1242
1242
|
}, materializeHost = async (root, host, files) => {
|
|
1243
1243
|
const directory = resolve10(root, host, ".well-known");
|
|
1244
|
-
await
|
|
1244
|
+
await mkdir11(directory, { recursive: true });
|
|
1245
1245
|
return Promise.all(files.map(async ([name, document2]) => {
|
|
1246
1246
|
const path = resolve10(directory, name);
|
|
1247
1247
|
await writeAtomic(path, `${JSON.stringify(document2, null, 2)}
|
|
@@ -1277,7 +1277,7 @@ var JSON_HEADERS, OWNERSHIP_FILE = ".absolutejs-mobile-associations.json", HTTP_
|
|
|
1277
1277
|
if (documents.apple) {
|
|
1278
1278
|
files.push(["apple-app-site-association", documents.apple]);
|
|
1279
1279
|
}
|
|
1280
|
-
await
|
|
1280
|
+
await mkdir11(temporary, { recursive: true });
|
|
1281
1281
|
try {
|
|
1282
1282
|
const temporaryPaths = (await Promise.all(config.deepLinkHosts.map((host) => materializeHost(temporary, host, files)))).flat();
|
|
1283
1283
|
await writeAtomic(resolve10(temporary, OWNERSHIP_FILE), `${JSON.stringify({ format: 1, hosts: config.deepLinkHosts }, null, 2)}
|
|
@@ -1712,7 +1712,7 @@ __export(exports_materializedBundle, {
|
|
|
1712
1712
|
import { createHash as createHash13 } from "crypto";
|
|
1713
1713
|
import {
|
|
1714
1714
|
access as access12,
|
|
1715
|
-
mkdir as
|
|
1715
|
+
mkdir as mkdir14,
|
|
1716
1716
|
mkdtemp as mkdtemp8,
|
|
1717
1717
|
readFile as readFile16,
|
|
1718
1718
|
rename as rename12,
|
|
@@ -1752,7 +1752,7 @@ var ABSOLUTE_MOBILE_MATERIALIZED_BUNDLE_FORMAT = 1, CURRENT_BUNDLE_FILE = "curre
|
|
|
1752
1752
|
}, writeRelease = async (root, release) => {
|
|
1753
1753
|
const directory = join14(root, release.artifact.releaseId);
|
|
1754
1754
|
const producerPath = join14(directory, release.artifact.producer.module);
|
|
1755
|
-
await
|
|
1755
|
+
await mkdir14(dirname11(producerPath), { recursive: true });
|
|
1756
1756
|
await Promise.all([
|
|
1757
1757
|
writeFile13(join14(directory, ARTIFACT_FILE2), `${JSON.stringify(release.artifact, null, "\t")}
|
|
1758
1758
|
`),
|
|
@@ -1833,7 +1833,7 @@ var ABSOLUTE_MOBILE_MATERIALIZED_BUNDLE_FORMAT = 1, CURRENT_BUNDLE_FILE = "curre
|
|
|
1833
1833
|
});
|
|
1834
1834
|
const root = resolvePath4(input.root);
|
|
1835
1835
|
const bundlesRoot = join14(root, BUNDLES_DIRECTORY);
|
|
1836
|
-
await
|
|
1836
|
+
await mkdir14(bundlesRoot, { recursive: true });
|
|
1837
1837
|
const bundleId = bundleIdFor(input.currentReleaseId, artifacts);
|
|
1838
1838
|
await installImmutableBundle(bundlesRoot, bundleId, orderedReleases);
|
|
1839
1839
|
const index = {
|
|
@@ -6439,24 +6439,24 @@ var require_pem = __commonJS(function(exports, module) {
|
|
|
6439
6439
|
options = options || {};
|
|
6440
6440
|
var rval = "-----BEGIN " + msg.type + `-----\r
|
|
6441
6441
|
`;
|
|
6442
|
-
var
|
|
6442
|
+
var header2;
|
|
6443
6443
|
if (msg.procType) {
|
|
6444
|
-
|
|
6444
|
+
header2 = {
|
|
6445
6445
|
name: "Proc-Type",
|
|
6446
6446
|
values: [String(msg.procType.version), msg.procType.type]
|
|
6447
6447
|
};
|
|
6448
|
-
rval += foldHeader(
|
|
6448
|
+
rval += foldHeader(header2);
|
|
6449
6449
|
}
|
|
6450
6450
|
if (msg.contentDomain) {
|
|
6451
|
-
|
|
6452
|
-
rval += foldHeader(
|
|
6451
|
+
header2 = { name: "Content-Domain", values: [msg.contentDomain] };
|
|
6452
|
+
rval += foldHeader(header2);
|
|
6453
6453
|
}
|
|
6454
6454
|
if (msg.dekInfo) {
|
|
6455
|
-
|
|
6455
|
+
header2 = { name: "DEK-Info", values: [msg.dekInfo.algorithm] };
|
|
6456
6456
|
if (msg.dekInfo.parameters) {
|
|
6457
|
-
|
|
6457
|
+
header2.values.push(msg.dekInfo.parameters);
|
|
6458
6458
|
}
|
|
6459
|
-
rval += foldHeader(
|
|
6459
|
+
rval += foldHeader(header2);
|
|
6460
6460
|
}
|
|
6461
6461
|
if (msg.headers) {
|
|
6462
6462
|
for (var i = 0;i < msg.headers.length; ++i) {
|
|
@@ -6514,27 +6514,27 @@ var require_pem = __commonJS(function(exports, module) {
|
|
|
6514
6514
|
}
|
|
6515
6515
|
match = line.match(rHeader);
|
|
6516
6516
|
if (match) {
|
|
6517
|
-
var
|
|
6517
|
+
var header2 = { name: match[1], values: [] };
|
|
6518
6518
|
var values = match[2].split(",");
|
|
6519
6519
|
for (var vi = 0;vi < values.length; ++vi) {
|
|
6520
|
-
|
|
6520
|
+
header2.values.push(ltrim(values[vi]));
|
|
6521
6521
|
}
|
|
6522
6522
|
if (!msg.procType) {
|
|
6523
|
-
if (
|
|
6523
|
+
if (header2.name !== "Proc-Type") {
|
|
6524
6524
|
throw new Error("Invalid PEM formatted message. The first " + 'encapsulated header must be "Proc-Type".');
|
|
6525
|
-
} else if (
|
|
6525
|
+
} else if (header2.values.length !== 2) {
|
|
6526
6526
|
throw new Error('Invalid PEM formatted message. The "Proc-Type" ' + "header must have two subfields.");
|
|
6527
6527
|
}
|
|
6528
6528
|
msg.procType = { version: values[0], type: values[1] };
|
|
6529
|
-
} else if (!msg.contentDomain &&
|
|
6529
|
+
} else if (!msg.contentDomain && header2.name === "Content-Domain") {
|
|
6530
6530
|
msg.contentDomain = values[0] || "";
|
|
6531
|
-
} else if (!msg.dekInfo &&
|
|
6532
|
-
if (
|
|
6531
|
+
} else if (!msg.dekInfo && header2.name === "DEK-Info") {
|
|
6532
|
+
if (header2.values.length === 0) {
|
|
6533
6533
|
throw new Error('Invalid PEM formatted message. The "DEK-Info" ' + "header must have at least one subfield.");
|
|
6534
6534
|
}
|
|
6535
6535
|
msg.dekInfo = { algorithm: values[0], parameters: values[1] || null };
|
|
6536
6536
|
} else {
|
|
6537
|
-
msg.headers.push(
|
|
6537
|
+
msg.headers.push(header2);
|
|
6538
6538
|
}
|
|
6539
6539
|
}
|
|
6540
6540
|
++li;
|
|
@@ -6548,14 +6548,14 @@ var require_pem = __commonJS(function(exports, module) {
|
|
|
6548
6548
|
}
|
|
6549
6549
|
return rval;
|
|
6550
6550
|
};
|
|
6551
|
-
function foldHeader(
|
|
6552
|
-
var rval =
|
|
6551
|
+
function foldHeader(header2) {
|
|
6552
|
+
var rval = header2.name + ": ";
|
|
6553
6553
|
var values = [];
|
|
6554
6554
|
var insertSpace = function(match, $1) {
|
|
6555
6555
|
return " " + $1;
|
|
6556
6556
|
};
|
|
6557
|
-
for (var i = 0;i <
|
|
6558
|
-
values.push(
|
|
6557
|
+
for (var i = 0;i < header2.values.length; ++i) {
|
|
6558
|
+
values.push(header2.values[i].replace(/^(\S+\r\n)/, insertSpace));
|
|
6559
6559
|
}
|
|
6560
6560
|
rval += values.join(",") + `\r
|
|
6561
6561
|
`;
|
|
@@ -7172,9 +7172,9 @@ var require_prng = __commonJS(function(exports, module) {
|
|
|
7172
7172
|
_crypto = __require("crypto");
|
|
7173
7173
|
}
|
|
7174
7174
|
var prng = module.exports = forge.prng = forge.prng || {};
|
|
7175
|
-
prng.create = function(
|
|
7175
|
+
prng.create = function(plugin2) {
|
|
7176
7176
|
var ctx = {
|
|
7177
|
-
plugin,
|
|
7177
|
+
plugin: plugin2,
|
|
7178
7178
|
key: null,
|
|
7179
7179
|
seed: null,
|
|
7180
7180
|
time: null,
|
|
@@ -7182,7 +7182,7 @@ var require_prng = __commonJS(function(exports, module) {
|
|
|
7182
7182
|
generated: 0,
|
|
7183
7183
|
keyBytes: ""
|
|
7184
7184
|
};
|
|
7185
|
-
var md =
|
|
7185
|
+
var md = plugin2.md;
|
|
7186
7186
|
var pools2 = new Array(32);
|
|
7187
7187
|
for (var i = 0;i < 32; ++i) {
|
|
7188
7188
|
pools2[i] = md.create();
|
|
@@ -19453,7 +19453,7 @@ var init_compatibilityDispatcher = __esm(() => {
|
|
|
19453
19453
|
// src/cli/scripts/telemetry.ts
|
|
19454
19454
|
import { existsSync as existsSync5, mkdirSync, readFileSync as readFileSync6, writeFileSync } from "fs";
|
|
19455
19455
|
import { homedir as homedir4 } from "os";
|
|
19456
|
-
import { join as
|
|
19456
|
+
import { join as join28 } from "path";
|
|
19457
19457
|
var configDir, configPath, getTelemetryConfig = () => {
|
|
19458
19458
|
try {
|
|
19459
19459
|
if (!existsSync5(configPath))
|
|
@@ -19466,14 +19466,14 @@ var configDir, configPath, getTelemetryConfig = () => {
|
|
|
19466
19466
|
}
|
|
19467
19467
|
};
|
|
19468
19468
|
var init_telemetry = __esm(() => {
|
|
19469
|
-
configDir =
|
|
19470
|
-
configPath =
|
|
19469
|
+
configDir = join28(homedir4(), ".absolutejs");
|
|
19470
|
+
configPath = join28(configDir, "telemetry.json");
|
|
19471
19471
|
});
|
|
19472
19472
|
|
|
19473
19473
|
// src/cli/telemetryEvent.ts
|
|
19474
19474
|
import { existsSync as existsSync6, readFileSync as readFileSync7 } from "fs";
|
|
19475
19475
|
import { arch, platform as platform3 } from "os";
|
|
19476
|
-
import { dirname as dirname20, join as
|
|
19476
|
+
import { dirname as dirname20, join as join29, parse } from "path";
|
|
19477
19477
|
var checkCandidate = (candidate) => {
|
|
19478
19478
|
if (!existsSync6(candidate)) {
|
|
19479
19479
|
return null;
|
|
@@ -19493,7 +19493,7 @@ var checkCandidate = (candidate) => {
|
|
|
19493
19493
|
}, findPackageVersion = () => {
|
|
19494
19494
|
let { dir } = import.meta;
|
|
19495
19495
|
while (dir !== parse(dir).root) {
|
|
19496
|
-
const candidate =
|
|
19496
|
+
const candidate = join29(dir, "package.json");
|
|
19497
19497
|
const version = checkCandidate(candidate);
|
|
19498
19498
|
if (version) {
|
|
19499
19499
|
return version;
|
|
@@ -21718,7 +21718,7 @@ import {
|
|
|
21718
21718
|
createPublicKey as createPublicKey3,
|
|
21719
21719
|
X509Certificate as X509Certificate4
|
|
21720
21720
|
} from "crypto";
|
|
21721
|
-
import { access as access24, mkdir as
|
|
21721
|
+
import { access as access24, mkdir as mkdir27 } from "fs/promises";
|
|
21722
21722
|
import { dirname as dirname26, isAbsolute as isAbsolute15, relative as relative25, resolve as resolve27, sep as sep17 } from "path";
|
|
21723
21723
|
import { pathToFileURL as pathToFileURL5 } from "url";
|
|
21724
21724
|
import { Elysia as Elysia4 } from "elysia";
|
|
@@ -21944,7 +21944,7 @@ ${generated}`);
|
|
|
21944
21944
|
return;
|
|
21945
21945
|
});
|
|
21946
21946
|
}
|
|
21947
|
-
await
|
|
21947
|
+
await mkdir27(dirname26(path2), { recursive: true });
|
|
21948
21948
|
await Bun.write(path2, renderAbsoluteMobileUpdateRegistry({
|
|
21949
21949
|
...options.health ? { health: options.health } : {},
|
|
21950
21950
|
...options.rollout ? { rollout: options.rollout } : {},
|
|
@@ -23686,7 +23686,7 @@ import { createHash as createHash5 } from "crypto";
|
|
|
23686
23686
|
import {
|
|
23687
23687
|
access as access6,
|
|
23688
23688
|
copyFile as copyFile3,
|
|
23689
|
-
mkdir as
|
|
23689
|
+
mkdir as mkdir5,
|
|
23690
23690
|
mkdtemp as mkdtemp2,
|
|
23691
23691
|
readFile as readFile6,
|
|
23692
23692
|
realpath as realpath2,
|
|
@@ -23939,7 +23939,7 @@ import {
|
|
|
23939
23939
|
access as access4,
|
|
23940
23940
|
copyFile as copyFile2,
|
|
23941
23941
|
lstat,
|
|
23942
|
-
mkdir as
|
|
23942
|
+
mkdir as mkdir4,
|
|
23943
23943
|
readFile as readFile4,
|
|
23944
23944
|
readdir as readdir2,
|
|
23945
23945
|
readlink,
|
|
@@ -23960,7 +23960,7 @@ import {
|
|
|
23960
23960
|
} from "path";
|
|
23961
23961
|
|
|
23962
23962
|
// src/mobile/capacitorProject.ts
|
|
23963
|
-
import { access as access3, readFile as readFile3, rename as rename3, writeFile as writeFile3 } from "fs/promises";
|
|
23963
|
+
import { access as access3, mkdir as mkdir3, readFile as readFile3, rename as rename3, writeFile as writeFile3 } from "fs/promises";
|
|
23964
23964
|
import { relative as relative2, resolve as resolve2 } from "path";
|
|
23965
23965
|
var CONFIG_FILE = "capacitor.config.ts";
|
|
23966
23966
|
var portableRelative2 = (root, path) => relative2(root, path).replaceAll("\\", "/");
|
|
@@ -23988,6 +23988,19 @@ var exists2 = async (path) => {
|
|
|
23988
23988
|
return false;
|
|
23989
23989
|
}
|
|
23990
23990
|
};
|
|
23991
|
+
var prepareAbsoluteCapacitorInitialization = async (config) => {
|
|
23992
|
+
await mkdir3(config.bundleDirectory, { recursive: true });
|
|
23993
|
+
try {
|
|
23994
|
+
await writeFile3(resolve2(config.bundleDirectory, "index.html"), '<!doctype html><html lang="en"><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><title>App preparation</title><body><main><h1>Your native project is ready</h1><p>Build your AbsoluteJS mobile bundle before running this app.</p></main></body></html>', { flag: "wx" });
|
|
23995
|
+
} catch (error) {
|
|
23996
|
+
if (!(error instanceof Error && ("code" in error) && error.code === "EEXIST"))
|
|
23997
|
+
throw error;
|
|
23998
|
+
}
|
|
23999
|
+
return Promise.all(config.platforms.map(async (platform2) => ({
|
|
24000
|
+
command: await exists2(resolve2(config.nativeProjectDirectory, platform2)) ? "sync" : "add",
|
|
24001
|
+
platform: platform2
|
|
24002
|
+
})));
|
|
24003
|
+
};
|
|
23991
24004
|
var writeAbsoluteCapacitorConfig = async (config, options) => {
|
|
23992
24005
|
const projectRoot = resolve2(options.projectRoot);
|
|
23993
24006
|
const destination = resolve2(projectRoot, CONFIG_FILE);
|
|
@@ -25343,7 +25356,7 @@ var installRelease = async (artifactPath, metadata, outputRoot) => {
|
|
|
25343
25356
|
}
|
|
25344
25357
|
return { artifactPath: destination, metadata: existing, releaseRoot };
|
|
25345
25358
|
}
|
|
25346
|
-
await
|
|
25359
|
+
await mkdir5(dirname3(releaseRoot), { recursive: true });
|
|
25347
25360
|
const staging = await mkdtemp2(join6(dirname3(releaseRoot), ".android-stage-"));
|
|
25348
25361
|
try {
|
|
25349
25362
|
await copyFile3(artifactPath, join6(staging, artifactName));
|
|
@@ -25504,7 +25517,7 @@ var waitForAbsoluteAndroidNetworkServices = async (options) => {
|
|
|
25504
25517
|
// src/mobile/androidReleaseAcceptance.ts
|
|
25505
25518
|
import {
|
|
25506
25519
|
access as access7,
|
|
25507
|
-
mkdir as
|
|
25520
|
+
mkdir as mkdir6,
|
|
25508
25521
|
mkdtemp as mkdtemp3,
|
|
25509
25522
|
readFile as readFile7,
|
|
25510
25523
|
rename as rename6,
|
|
@@ -25723,7 +25736,7 @@ var ensureAbsoluteBundletool = async (options) => {
|
|
|
25723
25736
|
const digest = createHash6("sha256").update(bytes).digest("hex");
|
|
25724
25737
|
if (digest !== ABSOLUTE_BUNDLETOOL_SHA256)
|
|
25725
25738
|
throw new TypeError("Downloaded Bundletool failed checksum verification.");
|
|
25726
|
-
await
|
|
25739
|
+
await mkdir6(dirname4(inspected.path), { recursive: true });
|
|
25727
25740
|
const staging = await mkdtemp3(join7(dirname4(inspected.path), ".install-"));
|
|
25728
25741
|
const candidate = join7(staging, "bundletool.jar");
|
|
25729
25742
|
try {
|
|
@@ -25800,7 +25813,7 @@ var runAbsoluteAndroidReleaseAcceptance = async (options) => {
|
|
|
25800
25813
|
throw new TypeError("Installed release acceptance changes network state and therefore requires an Android emulator.");
|
|
25801
25814
|
const run = options.run ?? defaultRun;
|
|
25802
25815
|
const startedAt = performance.now();
|
|
25803
|
-
await
|
|
25816
|
+
await mkdir6(options.artifactDirectory, { recursive: true });
|
|
25804
25817
|
const apksPath = join7(options.artifactDirectory, "release.apks");
|
|
25805
25818
|
const windowsJava = (options.host ?? detectAbsoluteMobileHost()) === "wsl" && options.java.toLowerCase().endsWith(".exe");
|
|
25806
25819
|
const toolPath = async (path) => {
|
|
@@ -25897,7 +25910,7 @@ import { createHash as createHash7 } from "crypto";
|
|
|
25897
25910
|
import {
|
|
25898
25911
|
access as access8,
|
|
25899
25912
|
copyFile as copyFile4,
|
|
25900
|
-
mkdir as
|
|
25913
|
+
mkdir as mkdir7,
|
|
25901
25914
|
mkdtemp as mkdtemp4,
|
|
25902
25915
|
readdir as readdir3,
|
|
25903
25916
|
readFile as readFile8,
|
|
@@ -26159,7 +26172,7 @@ var installRelease2 = async (artifactPath, metadata, outputRoot, registeredArtif
|
|
|
26159
26172
|
releaseRoot
|
|
26160
26173
|
};
|
|
26161
26174
|
}
|
|
26162
|
-
await
|
|
26175
|
+
await mkdir7(dirname5(releaseRoot), { recursive: true });
|
|
26163
26176
|
const staging = await mkdtemp4(join8(dirname5(releaseRoot), ".ios-stage-"));
|
|
26164
26177
|
try {
|
|
26165
26178
|
await copyFile4(artifactPath, join8(staging, "App.ipa"));
|
|
@@ -26188,7 +26201,7 @@ var installRelease2 = async (artifactPath, metadata, outputRoot, registeredArtif
|
|
|
26188
26201
|
var exportRegisteredDeviceArtifact = async (options) => {
|
|
26189
26202
|
const exportPath = join8(options.staging, "registered-export");
|
|
26190
26203
|
const exportPlist = join8(options.staging, "RegisteredExportOptions.plist");
|
|
26191
|
-
await
|
|
26204
|
+
await mkdir7(exportPath, { recursive: true });
|
|
26192
26205
|
await writeFile7(exportPlist, exportOptions("debugging"));
|
|
26193
26206
|
const exitCode = await options.run([
|
|
26194
26207
|
"xcodebuild",
|
|
@@ -26238,12 +26251,12 @@ var buildAbsoluteIosRelease = async (options) => {
|
|
|
26238
26251
|
buildNumber = requireBuildNumber(await options.prepareBuildNumber(buildIdentity));
|
|
26239
26252
|
}
|
|
26240
26253
|
const stagingParent = resolve6(options.projectRoot, ".absolutejs/mobile");
|
|
26241
|
-
await
|
|
26254
|
+
await mkdir7(stagingParent, { recursive: true });
|
|
26242
26255
|
const staging = await mkdtemp4(join8(stagingParent, ".ios-build-"));
|
|
26243
26256
|
const archivePath = join8(staging, "App.xcarchive");
|
|
26244
26257
|
const exportPath = join8(staging, "export");
|
|
26245
26258
|
const exportPlist = join8(staging, "ExportOptions.plist");
|
|
26246
|
-
await
|
|
26259
|
+
await mkdir7(exportPath, { recursive: true });
|
|
26247
26260
|
await writeFile7(exportPlist, exportOptions("app-store-connect"));
|
|
26248
26261
|
const run = options.run ?? defaultRun2;
|
|
26249
26262
|
try {
|
|
@@ -26355,7 +26368,7 @@ var installAbsoluteIosRelease = async (options) => {
|
|
|
26355
26368
|
import { createHash as createHash8 } from "crypto";
|
|
26356
26369
|
import {
|
|
26357
26370
|
access as access9,
|
|
26358
|
-
mkdir as
|
|
26371
|
+
mkdir as mkdir8,
|
|
26359
26372
|
mkdtemp as mkdtemp5,
|
|
26360
26373
|
readFile as readFile9,
|
|
26361
26374
|
readdir as readdir4,
|
|
@@ -26593,7 +26606,7 @@ var runAbsoluteIosSimulatorReleaseAcceptance = async (options) => {
|
|
|
26593
26606
|
const iosRoot = join9(options.config.nativeProjectDirectory, "ios");
|
|
26594
26607
|
const xcode = await resolveAbsoluteIosXcodeProject(iosRoot);
|
|
26595
26608
|
const derivedData = join9(options.artifactDirectory, "DerivedData");
|
|
26596
|
-
await
|
|
26609
|
+
await mkdir8(options.artifactDirectory, { recursive: true });
|
|
26597
26610
|
await requireSuccess3(run, [
|
|
26598
26611
|
xcodebuild,
|
|
26599
26612
|
"-workspace",
|
|
@@ -26899,7 +26912,7 @@ import { createHash as createHash9, randomUUID as randomUUID3 } from "crypto";
|
|
|
26899
26912
|
import {
|
|
26900
26913
|
access as access10,
|
|
26901
26914
|
copyFile as copyFile5,
|
|
26902
|
-
mkdir as
|
|
26915
|
+
mkdir as mkdir9,
|
|
26903
26916
|
readFile as readFile11,
|
|
26904
26917
|
rename as rename8,
|
|
26905
26918
|
rm as rm8,
|
|
@@ -27230,7 +27243,7 @@ var writeDevProjection = async (project, port, https, serverHost = "localhost")
|
|
|
27230
27243
|
const parsed = JSON.parse(configSource);
|
|
27231
27244
|
if (!isRecord4(parsed))
|
|
27232
27245
|
throw new Error(`Invalid Capacitor native config at ${nativeConfigPath}.`);
|
|
27233
|
-
await
|
|
27246
|
+
await mkdir9(paths.root, { recursive: true });
|
|
27234
27247
|
await Promise.all([
|
|
27235
27248
|
writeFile8(paths.configBackup, configSource, { flag: "wx" }),
|
|
27236
27249
|
writeFile8(paths.infoBackup, infoSource, { flag: "wx" })
|
|
@@ -27281,7 +27294,7 @@ var readNativeCache = (projectRoot) => readFile11(nativeCachePath(projectRoot),
|
|
|
27281
27294
|
var writeNativeCache = async (projectRoot, cache) => {
|
|
27282
27295
|
const destination = nativeCachePath(projectRoot);
|
|
27283
27296
|
const temporary = `${destination}.${process.pid}.${randomUUID3()}.tmp`;
|
|
27284
|
-
await
|
|
27297
|
+
await mkdir9(dirname7(destination), { recursive: true });
|
|
27285
27298
|
try {
|
|
27286
27299
|
await writeFile8(temporary, `${JSON.stringify(cache, null, "\t")}
|
|
27287
27300
|
`, {
|
|
@@ -27396,7 +27409,7 @@ var physicalIosAppIsInstalled = (project, identifier, capture) => {
|
|
|
27396
27409
|
};
|
|
27397
27410
|
var buildIosDebugApp = async (project, udid, fingerprint, run, signal) => {
|
|
27398
27411
|
const derivedDataPath = join10(project.projectRoot, ".absolutejs", "mobile", "ios-derived-data", createHash9("sha256").update(project.config.appId).digest("hex").slice(0, 16));
|
|
27399
|
-
await
|
|
27412
|
+
await mkdir9(derivedDataPath, { recursive: true });
|
|
27400
27413
|
await requireSuccess4([
|
|
27401
27414
|
project.xcodebuild,
|
|
27402
27415
|
"-workspace",
|
|
@@ -27418,7 +27431,7 @@ var buildIosDebugApp = async (project, udid, fingerprint, run, signal) => {
|
|
|
27418
27431
|
};
|
|
27419
27432
|
var buildPhysicalIosDebugApp = async (project, identifier, run, signal) => {
|
|
27420
27433
|
const derivedDataPath = join10(project.projectRoot, ".absolutejs", "mobile", "ios-derived-data", createHash9("sha256").update(project.config.appId).digest("hex").slice(0, 16));
|
|
27421
|
-
await
|
|
27434
|
+
await mkdir9(derivedDataPath, { recursive: true });
|
|
27422
27435
|
await requireSuccess4([
|
|
27423
27436
|
project.xcodebuild,
|
|
27424
27437
|
"-workspace",
|
|
@@ -27582,7 +27595,7 @@ var prepareAbsoluteIosDevProject = async (config, options) => {
|
|
|
27582
27595
|
if (!await pathExists5(cap))
|
|
27583
27596
|
throw new Error("Capacitor CLI is not installed. Run absolute mobile init first.");
|
|
27584
27597
|
await writeAbsoluteCapacitorConfig(config, { projectRoot });
|
|
27585
|
-
await
|
|
27598
|
+
await mkdir9(config.bundleDirectory, { recursive: true });
|
|
27586
27599
|
const placeholder = join10(config.bundleDirectory, "index.html");
|
|
27587
27600
|
if (!await pathExists5(placeholder))
|
|
27588
27601
|
await writeFile8(placeholder, `<!doctype html><title>AbsoluteJS mobile development</title>
|
|
@@ -27818,7 +27831,7 @@ var startAbsoluteIosDevSession = async (options) => {
|
|
|
27818
27831
|
const resolved = resolve8(project.projectRoot, destination);
|
|
27819
27832
|
if (!isInside(project.projectRoot, resolved))
|
|
27820
27833
|
throw new Error("iOS screenshot destination must remain inside the project.");
|
|
27821
|
-
await
|
|
27834
|
+
await mkdir9(dirname7(resolved), { recursive: true });
|
|
27822
27835
|
await requireSuccess4([
|
|
27823
27836
|
project.xcrun,
|
|
27824
27837
|
"simctl",
|
|
@@ -27940,7 +27953,7 @@ var isAbsoluteIosNativeRootInput = (path) => ROOT_NATIVE_INPUTS.has(basename3(pa
|
|
|
27940
27953
|
import { createHash as createHash10, randomUUID as randomUUID4 } from "crypto";
|
|
27941
27954
|
import {
|
|
27942
27955
|
chmod,
|
|
27943
|
-
mkdir as
|
|
27956
|
+
mkdir as mkdir10,
|
|
27944
27957
|
mkdtemp as mkdtemp6,
|
|
27945
27958
|
readFile as readFile12,
|
|
27946
27959
|
rename as rename9,
|
|
@@ -27995,7 +28008,7 @@ var loadStore = async (path = defaultProfilePath()) => {
|
|
|
27995
28008
|
}
|
|
27996
28009
|
};
|
|
27997
28010
|
var saveStore = async (store, path = defaultProfilePath()) => {
|
|
27998
|
-
await
|
|
28011
|
+
await mkdir10(dirname8(path), { recursive: true });
|
|
27999
28012
|
const temporary = `${path}.${randomUUID4()}.tmp`;
|
|
28000
28013
|
await writeFile9(temporary, `${JSON.stringify(store, null, 2)}
|
|
28001
28014
|
`, {
|
|
@@ -28354,7 +28367,7 @@ var materializeAbsoluteRemoteMacAgent = async (projectRoot) => {
|
|
|
28354
28367
|
if (!source)
|
|
28355
28368
|
throw new Error("The AbsoluteJS installation does not contain its remote Mac agent artifact.");
|
|
28356
28369
|
const outdir = join11(resolvePath3(projectRoot), ".absolutejs", "mobile", "remote-agent");
|
|
28357
|
-
await
|
|
28370
|
+
await mkdir10(outdir, { recursive: true });
|
|
28358
28371
|
const result = await Bun.build({
|
|
28359
28372
|
entrypoints: [source],
|
|
28360
28373
|
minify: true,
|
|
@@ -28590,7 +28603,7 @@ var writeRemoteArtifact = async (path, stream) => {
|
|
|
28590
28603
|
var retrieveAbsoluteRemoteIosRelease = async (project, metadata, outputDirectory) => {
|
|
28591
28604
|
const releaseRoot = posix.join(project.remoteProjectRoot, ".absolutejs", "mobile", "releases", "ios", metadata.releaseId);
|
|
28592
28605
|
const stagingParent = join11(project.projectRoot, ".absolutejs", "mobile");
|
|
28593
|
-
await
|
|
28606
|
+
await mkdir10(stagingParent, { recursive: true });
|
|
28594
28607
|
const staging = await mkdtemp6(join11(stagingParent, ".remote-ios-"));
|
|
28595
28608
|
try {
|
|
28596
28609
|
const remoteMetadata = requireRemoteSuccess(await defaultTransport.capture([
|
|
@@ -29294,7 +29307,7 @@ var startAbsoluteRemoteDevSession = async (options) => {
|
|
|
29294
29307
|
const targetRelative = relative9(options.project.projectRoot, target);
|
|
29295
29308
|
if (targetRelative.startsWith("..") || isAbsolute7(targetRelative))
|
|
29296
29309
|
throw new Error("iOS screenshot must remain inside the project.");
|
|
29297
|
-
await
|
|
29310
|
+
await mkdir10(dirname8(target), { recursive: true });
|
|
29298
29311
|
await writeFile9(target, Buffer.from(result.data, "base64"));
|
|
29299
29312
|
return target;
|
|
29300
29313
|
},
|
|
@@ -29376,12 +29389,12 @@ var parseAbsoluteMobileBuildPageMetadata = (value) => {
|
|
|
29376
29389
|
};
|
|
29377
29390
|
// src/mobile/buildPipeline.ts
|
|
29378
29391
|
import { readFile as readFile18 } from "fs/promises";
|
|
29379
|
-
import { join as
|
|
29392
|
+
import { join as join22, resolve as resolve16 } from "path";
|
|
29380
29393
|
import { pathToFileURL as pathToFileURL2 } from "url";
|
|
29381
29394
|
|
|
29382
29395
|
// src/mobile/buildRelease.ts
|
|
29383
29396
|
import { createHash as createHash12 } from "crypto";
|
|
29384
|
-
import { mkdir as
|
|
29397
|
+
import { mkdir as mkdir12, readFile as readFile14, writeFile as writeFile11 } from "fs/promises";
|
|
29385
29398
|
import { basename as basename4, dirname as dirname9, extname, join as join12, relative as relative10, resolve as resolve11 } from "path";
|
|
29386
29399
|
init_releaseArtifact();
|
|
29387
29400
|
var sha2563 = (bytes) => createHash12("sha256").update(bytes).digest("hex");
|
|
@@ -29413,7 +29426,7 @@ var pageFor = async (metadata, manifest, buildDirectory) => {
|
|
|
29413
29426
|
const rewritten = rewriteStaticScriptPaths(source, manifest);
|
|
29414
29427
|
const documentHash = sha2563(new TextEncoder().encode(rewritten));
|
|
29415
29428
|
resolvedAssetPath = join12(buildDirectory, ".absolutejs", "mobile-pages", `${documentHash}.html`);
|
|
29416
|
-
await
|
|
29429
|
+
await mkdir12(dirname9(resolvedAssetPath), { recursive: true });
|
|
29417
29430
|
await writeFile11(resolvedAssetPath, rewritten);
|
|
29418
29431
|
}
|
|
29419
29432
|
const pageAssetKey = metadata.bundleKey.replace(/Index$/u, "");
|
|
@@ -29535,7 +29548,7 @@ init_routeMatcher();
|
|
|
29535
29548
|
import {
|
|
29536
29549
|
cp,
|
|
29537
29550
|
copyFile as copyFile6,
|
|
29538
|
-
mkdir as
|
|
29551
|
+
mkdir as mkdir13,
|
|
29539
29552
|
mkdtemp as mkdtemp7,
|
|
29540
29553
|
readFile as readFile15,
|
|
29541
29554
|
rename as rename11,
|
|
@@ -29975,7 +29988,7 @@ var copyClientPage = async (page, buildDirectory, staging, copiedDependencies) =
|
|
|
29975
29988
|
const styleExtension = extname2(page.styleBundlePath) || ".css";
|
|
29976
29989
|
localStylePath = `./styles/${page.styleBundleHash}${styleExtension}`;
|
|
29977
29990
|
const styleSource = sourceAssetPath(buildDirectory, page.styleBundlePath);
|
|
29978
|
-
await
|
|
29991
|
+
await mkdir13(dirname10(join13(staging, localStylePath)), {
|
|
29979
29992
|
recursive: true
|
|
29980
29993
|
});
|
|
29981
29994
|
await copyFile6(styleSource, join13(staging, localStylePath));
|
|
@@ -30002,7 +30015,7 @@ var materializeAbsoluteMobileSourcemaps = async (pages, appBuild, projectRoot) =
|
|
|
30002
30015
|
return existsSync2(source) ? [{ page, source }] : [];
|
|
30003
30016
|
});
|
|
30004
30017
|
if (available.length > 0)
|
|
30005
|
-
await
|
|
30018
|
+
await mkdir13(releaseRoot, { recursive: true });
|
|
30006
30019
|
await Promise.all(available.map(async ({ page, source }) => {
|
|
30007
30020
|
const extension = extname2(page.bundlePath) || ".js";
|
|
30008
30021
|
if (!/^\.[a-z0-9]+$/iu.test(extension))
|
|
@@ -30061,7 +30074,7 @@ var copyAbsoluteClientDependency = async (specifier, buildDirectory, staging, co
|
|
|
30061
30074
|
copied.add(specifier);
|
|
30062
30075
|
const source = sourceAssetPath(buildDirectory, specifier);
|
|
30063
30076
|
const destination = join13(staging, specifier.replace(/^\/+/, ""));
|
|
30064
|
-
await
|
|
30077
|
+
await mkdir13(dirname10(destination), { recursive: true });
|
|
30065
30078
|
await copyFile6(source, destination);
|
|
30066
30079
|
await copyAbsoluteClientDependencies(source, buildDirectory, staging, copied);
|
|
30067
30080
|
};
|
|
@@ -30074,11 +30087,11 @@ var materializeAbsoluteCapacitorWebBundle = async (options) => {
|
|
|
30074
30087
|
throw new TypeError(`mobile.entry ${options.config.entry} is not a captured mobile page route.`);
|
|
30075
30088
|
}
|
|
30076
30089
|
const destination = options.config.bundleDirectory;
|
|
30077
|
-
await
|
|
30090
|
+
await mkdir13(dirname10(destination), { recursive: true });
|
|
30078
30091
|
const staging = await mkdtemp7(join13(dirname10(destination), `.${basename5(destination)}.stage-`));
|
|
30079
30092
|
try {
|
|
30080
30093
|
const pageDirectory = join13(staging, "pages");
|
|
30081
|
-
await
|
|
30094
|
+
await mkdir13(pageDirectory, { recursive: true });
|
|
30082
30095
|
await Promise.all(CLIENT_ASSET_DIRECTORIES.map((directory) => ({
|
|
30083
30096
|
destination: join13(staging, directory),
|
|
30084
30097
|
source: join13(options.buildDirectory, directory)
|
|
@@ -30140,12 +30153,9 @@ init_releaseArtifact();
|
|
|
30140
30153
|
init_deviceCapabilities();
|
|
30141
30154
|
|
|
30142
30155
|
// src/mobile/expoProject.ts
|
|
30143
|
-
init_nativeAuth();
|
|
30144
|
-
init_syncSchema();
|
|
30145
|
-
init_deviceCapabilities();
|
|
30146
30156
|
import {
|
|
30147
30157
|
access as access13,
|
|
30148
|
-
mkdir as
|
|
30158
|
+
mkdir as mkdir15,
|
|
30149
30159
|
mkdtemp as mkdtemp9,
|
|
30150
30160
|
readdir as readdir5,
|
|
30151
30161
|
readFile as readFile17,
|
|
@@ -30154,7 +30164,39 @@ import {
|
|
|
30154
30164
|
writeFile as writeFile14
|
|
30155
30165
|
} from "fs/promises";
|
|
30156
30166
|
import { createHash as createHash15 } from "crypto";
|
|
30157
|
-
import { basename as basename6, dirname as dirname13, join as
|
|
30167
|
+
import { basename as basename6, dirname as dirname13, join as join21, relative as relative13, resolve as resolve15, sep as sep8 } from "path";
|
|
30168
|
+
|
|
30169
|
+
// src/mobile/nativePackages.ts
|
|
30170
|
+
var ABSOLUTE_CAPACITOR_DEVICES_VERSION = "0.8.0";
|
|
30171
|
+
var ABSOLUTE_CAPACITOR_SYNC_VERSION = "0.9.3";
|
|
30172
|
+
var ABSOLUTE_DEVICES_VERSION = "0.7.0";
|
|
30173
|
+
var ABSOLUTE_EXPO_DEVICES_VERSION = "0.0.11";
|
|
30174
|
+
var ABSOLUTE_NATIVE_EXACT_PACKAGES = new Set([
|
|
30175
|
+
"@absolutejs/devices",
|
|
30176
|
+
"@absolutejs/devices-capacitor",
|
|
30177
|
+
"@absolutejs/sync-capacitor"
|
|
30178
|
+
]);
|
|
30179
|
+
var CAPACITOR_PACKAGE_SPECS = [
|
|
30180
|
+
"@capacitor/core@8.5.0",
|
|
30181
|
+
"@capacitor/app@8.1.1",
|
|
30182
|
+
"@capacitor/browser@8.0.4",
|
|
30183
|
+
"@capacitor/network@8.0.1",
|
|
30184
|
+
"@capacitor/preferences@8.0.1",
|
|
30185
|
+
"@capacitor/cli@8.5.0",
|
|
30186
|
+
"@capacitor/android@8.5.0",
|
|
30187
|
+
"@capacitor/ios@8.5.0",
|
|
30188
|
+
`@absolutejs/devices@${ABSOLUTE_DEVICES_VERSION}`,
|
|
30189
|
+
`@absolutejs/devices-capacitor@${ABSOLUTE_CAPACITOR_DEVICES_VERSION}`
|
|
30190
|
+
];
|
|
30191
|
+
var CAPACITOR_SYNC_PACKAGE_SPECS = [
|
|
30192
|
+
`@absolutejs/sync-capacitor@${ABSOLUTE_CAPACITOR_SYNC_VERSION}`,
|
|
30193
|
+
"@capacitor-community/sqlite@8.1.1"
|
|
30194
|
+
];
|
|
30195
|
+
|
|
30196
|
+
// src/mobile/expoProject.ts
|
|
30197
|
+
init_nativeAuth();
|
|
30198
|
+
init_syncSchema();
|
|
30199
|
+
init_deviceCapabilities();
|
|
30158
30200
|
|
|
30159
30201
|
// src/mobile/updateRuntime.ts
|
|
30160
30202
|
init_deviceCapabilities();
|
|
@@ -30295,6 +30337,7 @@ var createAbsoluteMobileUpdateRuntimeDescriptor = (options) => ({
|
|
|
30295
30337
|
},
|
|
30296
30338
|
deviceCapabilities: options.deviceCapabilities,
|
|
30297
30339
|
engine: options.config.engine,
|
|
30340
|
+
...options.config.engine === "expo" ? { expoEmbeddedAssetsAbi: 1 } : {},
|
|
30298
30341
|
format: ABSOLUTE_MOBILE_UPDATE_RUNTIME_FORMAT,
|
|
30299
30342
|
shellAbi: ABSOLUTE_MOBILE_SHELL_ABI,
|
|
30300
30343
|
syncSchema: options.syncSchema ?? null,
|
|
@@ -31064,6 +31107,265 @@ var absoluteExpoActivityResultRecoveryFiles = (project) => new Map([
|
|
|
31064
31107
|
]
|
|
31065
31108
|
]);
|
|
31066
31109
|
|
|
31110
|
+
// src/mobile/expoEmbeddedAssets.ts
|
|
31111
|
+
import { join as join20 } from "path";
|
|
31112
|
+
var header = `// Generated by AbsoluteJS. Edit absolute.config.ts, then run absolute mobile sync.
|
|
31113
|
+
`;
|
|
31114
|
+
var android = `${header}package expo.modules.absoluteembeddedassets
|
|
31115
|
+
|
|
31116
|
+
import android.content.Context
|
|
31117
|
+
import android.graphics.Bitmap
|
|
31118
|
+
import android.net.Uri
|
|
31119
|
+
import android.util.Log
|
|
31120
|
+
import android.webkit.WebResourceRequest
|
|
31121
|
+
import android.webkit.WebResourceResponse
|
|
31122
|
+
import android.webkit.WebView
|
|
31123
|
+
import androidx.webkit.WebViewAssetLoader
|
|
31124
|
+
import androidx.webkit.WebViewCompat
|
|
31125
|
+
import androidx.webkit.WebViewFeature
|
|
31126
|
+
import androidx.webkit.ScriptHandler
|
|
31127
|
+
import androidx.webkit.WebMessageCompat
|
|
31128
|
+
import com.facebook.react.ReactPackage
|
|
31129
|
+
import com.facebook.react.bridge.NativeModule
|
|
31130
|
+
import com.facebook.react.bridge.ReactApplicationContext
|
|
31131
|
+
import com.facebook.react.bridge.ReadableMap
|
|
31132
|
+
import com.facebook.react.uimanager.ThemedReactContext
|
|
31133
|
+
import com.facebook.react.uimanager.ViewManager
|
|
31134
|
+
import com.reactnativecommunity.webview.RNCWebViewClient
|
|
31135
|
+
import com.reactnativecommunity.webview.RNCWebViewManager
|
|
31136
|
+
import com.reactnativecommunity.webview.RNCWebViewWrapper
|
|
31137
|
+
import expo.modules.kotlin.modules.Module
|
|
31138
|
+
import expo.modules.kotlin.modules.ModuleDefinition
|
|
31139
|
+
import java.io.ByteArrayInputStream
|
|
31140
|
+
import java.io.File
|
|
31141
|
+
import java.util.concurrent.ConcurrentHashMap
|
|
31142
|
+
import java.util.WeakHashMap
|
|
31143
|
+
|
|
31144
|
+
private const val HOST = "appassets.androidplatform.net"
|
|
31145
|
+
private const val PREFIX = "/absolutejs/"
|
|
31146
|
+
|
|
31147
|
+
internal object AbsoluteEmbeddedAssets {
|
|
31148
|
+
private val bundles = ConcurrentHashMap<String, Map<String, File>>()
|
|
31149
|
+
|
|
31150
|
+
fun register(context: Context, rootUri: String, paths: List<String>): String {
|
|
31151
|
+
check(WebViewFeature.isFeatureSupported(WebViewFeature.DOCUMENT_START_SCRIPT) &&
|
|
31152
|
+
WebViewFeature.isFeatureSupported(WebViewFeature.WEB_MESSAGE_LISTENER)) {
|
|
31153
|
+
"Update Android System WebView to load this application."
|
|
31154
|
+
}
|
|
31155
|
+
val uri = Uri.parse(rootUri)
|
|
31156
|
+
require(uri.scheme == "file" && uri.authority.isNullOrEmpty() && uri.query == null && uri.fragment == null)
|
|
31157
|
+
val root = File(requireNotNull(uri.path)).canonicalFile
|
|
31158
|
+
val parent = File(context.filesDir, "absolutejs-web").canonicalFile
|
|
31159
|
+
require(root.parentFile == parent && root.name.matches(Regex("amexpo_[a-f0-9]{64}")))
|
|
31160
|
+
require(paths.isNotEmpty() && paths.size <= 100000 && paths.distinct().size == paths.size)
|
|
31161
|
+
val files = paths.associateWith { path ->
|
|
31162
|
+
require(path.isNotEmpty() && !path.contains('\\\\') && !path.contains('%') &&
|
|
31163
|
+
!path.contains('?') && !path.contains('#') && path.indexOf(0.toChar()) < 0 &&
|
|
31164
|
+
path.split('/').all { it.isNotEmpty() && it != "." && it != ".." })
|
|
31165
|
+
val file = File(root, path).canonicalFile
|
|
31166
|
+
require(file.path.startsWith(root.path + File.separator) && file.isFile)
|
|
31167
|
+
file
|
|
31168
|
+
}
|
|
31169
|
+
require(files.containsKey("index.html") && files.containsKey("absolute-mobile-manifest.json"))
|
|
31170
|
+
bundles[root.name] = files
|
|
31171
|
+
Log.i("AbsoluteJS", "Expo embedded web phase: asset-host-registered")
|
|
31172
|
+
return "https://" + HOST + PREFIX + root.name + "/index.html"
|
|
31173
|
+
}
|
|
31174
|
+
|
|
31175
|
+
private fun empty(status: Int, reason: String) = WebResourceResponse(
|
|
31176
|
+
"text/plain", "UTF-8", status, reason,
|
|
31177
|
+
mapOf("Cache-Control" to "no-store", "X-Content-Type-Options" to "nosniff"),
|
|
31178
|
+
ByteArrayInputStream(ByteArray(0))
|
|
31179
|
+
)
|
|
31180
|
+
|
|
31181
|
+
private fun resource(path: String): WebResourceResponse {
|
|
31182
|
+
val bundle = path.substringBefore('/')
|
|
31183
|
+
val name = path.substringAfter('/', "")
|
|
31184
|
+
val file = bundles[bundle]?.get(name) ?: return empty(404, "Not Found")
|
|
31185
|
+
// Recheck canonical location at read time. Never follow a replaced symlink.
|
|
31186
|
+
if (file.canonicalFile != file || !file.isFile) return empty(404, "Not Found")
|
|
31187
|
+
val mime = when (file.extension.lowercase()) {
|
|
31188
|
+
"html", "htm" -> "text/html"
|
|
31189
|
+
"js", "mjs" -> "text/javascript"
|
|
31190
|
+
"json", "map" -> "application/json"
|
|
31191
|
+
"css" -> "text/css"
|
|
31192
|
+
"svg" -> "image/svg+xml"
|
|
31193
|
+
"wasm" -> "application/wasm"
|
|
31194
|
+
else -> android.webkit.MimeTypeMap.getSingleton().getMimeTypeFromExtension(file.extension.lowercase()) ?: "application/octet-stream"
|
|
31195
|
+
}
|
|
31196
|
+
return try {
|
|
31197
|
+
WebResourceResponse(mime, "UTF-8", 200, "OK",
|
|
31198
|
+
mapOf("Cache-Control" to "no-store", "X-Content-Type-Options" to "nosniff"), file.inputStream())
|
|
31199
|
+
} catch (_: Exception) { empty(404, "Not Found") }
|
|
31200
|
+
}
|
|
31201
|
+
|
|
31202
|
+
private val loader = WebViewAssetLoader.Builder()
|
|
31203
|
+
.setDomain(HOST).setHttpAllowed(false)
|
|
31204
|
+
.addPathHandler(PREFIX) { path -> resource(path) }.build()
|
|
31205
|
+
|
|
31206
|
+
fun intercept(request: WebResourceRequest, activeBundle: String?): WebResourceResponse? {
|
|
31207
|
+
val uri = request.url
|
|
31208
|
+
if (uri.host != HOST) return null
|
|
31209
|
+
if (uri.path.orEmpty().endsWith("/index.html")) Log.i("AbsoluteJS", "Expo embedded web phase: document-request")
|
|
31210
|
+
if (uri.path.orEmpty().endsWith("/absolute-mobile-bootstrap.js")) Log.i("AbsoluteJS", "Expo embedded web phase: bootstrap-request")
|
|
31211
|
+
// A reserved asset host must never fall through to DNS/network, even for
|
|
31212
|
+
// unknown bundles, wrong ports/schemes, methods, or malformed paths.
|
|
31213
|
+
if (uri.scheme != "https" || uri.port != -1 || uri.userInfo != null ||
|
|
31214
|
+
request.method != "GET") return empty(403, "Forbidden")
|
|
31215
|
+
// Root-relative image/font/CSS URLs retain their web meaning. Scope them
|
|
31216
|
+
// to this WebView's bundle, not the last bundle registered by another view.
|
|
31217
|
+
if (!uri.path.orEmpty().startsWith(PREFIX)) {
|
|
31218
|
+
if (request.isForMainFrame || activeBundle == null) return empty(404, "Not Found")
|
|
31219
|
+
return resource(activeBundle + "/" + uri.path.orEmpty().removePrefix("/"))
|
|
31220
|
+
}
|
|
31221
|
+
return loader.shouldInterceptRequest(uri) ?: empty(404, "Not Found")
|
|
31222
|
+
}
|
|
31223
|
+
}
|
|
31224
|
+
|
|
31225
|
+
class AbsoluteEmbeddedAssetsModule : Module() {
|
|
31226
|
+
override fun definition() = ModuleDefinition {
|
|
31227
|
+
Name("AbsoluteEmbeddedAssets")
|
|
31228
|
+
AsyncFunction("registerBundle") { root: String, paths: List<String> ->
|
|
31229
|
+
AbsoluteEmbeddedAssets.register(requireNotNull(appContext.reactContext), root, paths)
|
|
31230
|
+
}
|
|
31231
|
+
}
|
|
31232
|
+
}
|
|
31233
|
+
|
|
31234
|
+
class AbsoluteEmbeddedWebViewManager : RNCWebViewManager() {
|
|
31235
|
+
private val scripts = WeakHashMap<RNCWebViewWrapper, ScriptHandler>()
|
|
31236
|
+
override fun getName() = "AbsoluteEmbeddedWebView"
|
|
31237
|
+
override fun setNewSource(view: RNCWebViewWrapper, value: ReadableMap?) {
|
|
31238
|
+
Log.i("AbsoluteJS", "Expo embedded web phase: source-assigned")
|
|
31239
|
+
super.setNewSource(view, value)
|
|
31240
|
+
}
|
|
31241
|
+
override fun setMessagingEnabled(view: RNCWebViewWrapper, value: Boolean) {
|
|
31242
|
+
super.setMessagingEnabled(view, value)
|
|
31243
|
+
// Upstream reports sourceOrigin as event.url and accepts subframe messages.
|
|
31244
|
+
// Retain its event dispatch, but bind this bridge to our main-frame origin
|
|
31245
|
+
// and attach the native-observed document URL, never a JS-supplied URL.
|
|
31246
|
+
if (!WebViewFeature.isFeatureSupported(WebViewFeature.WEB_MESSAGE_LISTENER)) return
|
|
31247
|
+
WebViewCompat.removeWebMessageListener(view.webView, "ReactNativeWebView")
|
|
31248
|
+
if (!value) return
|
|
31249
|
+
WebViewCompat.addWebMessageListener(view.webView, "ReactNativeWebView", setOf("https://" + HOST)) {
|
|
31250
|
+
webView, message, sourceOrigin, isMainFrame, _ ->
|
|
31251
|
+
if (isMainFrame && sourceOrigin.scheme == "https" && sourceOrigin.host == HOST &&
|
|
31252
|
+
message.type == WebMessageCompat.TYPE_STRING) {
|
|
31253
|
+
val url = webView.url
|
|
31254
|
+
val data = message.data
|
|
31255
|
+
if (url != null && data != null) view.webView.onMessage(data, url)
|
|
31256
|
+
}
|
|
31257
|
+
}
|
|
31258
|
+
}
|
|
31259
|
+
override fun setInjectedJavaScriptBeforeContentLoaded(view: RNCWebViewWrapper, value: String?) {
|
|
31260
|
+
scripts.remove(view)?.remove()
|
|
31261
|
+
if (value == null) return
|
|
31262
|
+
// onPageStarted injection races module execution on Android. Register with
|
|
31263
|
+
// Chromium before navigation, scoped to our virtual asset origin only.
|
|
31264
|
+
check(WebViewFeature.isFeatureSupported(WebViewFeature.DOCUMENT_START_SCRIPT)) {
|
|
31265
|
+
"AbsoluteJS requires an Android System WebView with document-start script support."
|
|
31266
|
+
}
|
|
31267
|
+
scripts[view] = WebViewCompat.addDocumentStartJavaScript(view.webView, value, setOf("https://" + HOST))
|
|
31268
|
+
}
|
|
31269
|
+
override fun onDropViewInstance(view: RNCWebViewWrapper) {
|
|
31270
|
+
scripts.remove(view)?.remove()
|
|
31271
|
+
if (WebViewFeature.isFeatureSupported(WebViewFeature.WEB_MESSAGE_LISTENER))
|
|
31272
|
+
WebViewCompat.removeWebMessageListener(view.webView, "ReactNativeWebView")
|
|
31273
|
+
super.onDropViewInstance(view)
|
|
31274
|
+
}
|
|
31275
|
+
override fun addEventEmitters(context: ThemedReactContext, view: RNCWebViewWrapper) {
|
|
31276
|
+
Log.i("AbsoluteJS", "Expo embedded web phase: asset-host-view-created")
|
|
31277
|
+
view.webView.webViewClient = object : RNCWebViewClient() {
|
|
31278
|
+
@Volatile private var activeBundle: String? = null
|
|
31279
|
+
override fun onPageStarted(view: WebView, url: String, favicon: Bitmap?) {
|
|
31280
|
+
Log.i("AbsoluteJS", "Expo embedded web phase: document-started")
|
|
31281
|
+
val uri = Uri.parse(url)
|
|
31282
|
+
activeBundle = if (uri.scheme == "https" && uri.host == HOST && uri.path.orEmpty().startsWith(PREFIX))
|
|
31283
|
+
uri.path!!.removePrefix(PREFIX).substringBefore('/') else null
|
|
31284
|
+
super.onPageStarted(view, url, favicon)
|
|
31285
|
+
}
|
|
31286
|
+
override fun shouldInterceptRequest(view: WebView, request: WebResourceRequest): WebResourceResponse? =
|
|
31287
|
+
AbsoluteEmbeddedAssets.intercept(request, activeBundle) ?: super.shouldInterceptRequest(view, request)
|
|
31288
|
+
}
|
|
31289
|
+
}
|
|
31290
|
+
}
|
|
31291
|
+
|
|
31292
|
+
class AbsoluteEmbeddedWebViewPackage : ReactPackage {
|
|
31293
|
+
override fun createNativeModules(context: ReactApplicationContext): List<NativeModule> = emptyList()
|
|
31294
|
+
override fun createViewManagers(context: ReactApplicationContext): List<ViewManager<*, *>> = listOf(AbsoluteEmbeddedWebViewManager())
|
|
31295
|
+
}
|
|
31296
|
+
`;
|
|
31297
|
+
var plugin = `${header}const { withMainApplication } = require('expo/config-plugins');
|
|
31298
|
+
module.exports = config => withMainApplication(config, value => {
|
|
31299
|
+
if (value.modResults.language !== 'kt') throw new Error('AbsoluteJS embedded assets require the managed Kotlin application.');
|
|
31300
|
+
const name = 'expo.modules.absoluteembeddedassets.AbsoluteEmbeddedWebViewPackage';
|
|
31301
|
+
const registration = 'add(' + name + '())';
|
|
31302
|
+
const source = value.modResults.contents;
|
|
31303
|
+
if (!source.includes(registration)) {
|
|
31304
|
+
const anchor = 'PackageList(this).packages.apply {';
|
|
31305
|
+
if (source.split(anchor).length !== 2) throw new Error('Cannot safely register AbsoluteJS embedded WebView in MainApplication.');
|
|
31306
|
+
value.modResults.contents = source.replace(anchor, anchor + '\\n ' + registration);
|
|
31307
|
+
}
|
|
31308
|
+
return value;
|
|
31309
|
+
});
|
|
31310
|
+
`;
|
|
31311
|
+
var runtime2 = `${header}import { requireNativeModule } from 'expo-modules-core';
|
|
31312
|
+
import { Platform, requireNativeComponent } from 'react-native';
|
|
31313
|
+
|
|
31314
|
+
export const absoluteEmbeddedNativeConfig = Platform.OS === 'android'
|
|
31315
|
+
? { component: requireNativeComponent('AbsoluteEmbeddedWebView') }
|
|
31316
|
+
: undefined;
|
|
31317
|
+
|
|
31318
|
+
export const registerAbsoluteEmbeddedBundle = async (rootUri: string, paths: string[], indexUri: string): Promise<string> => {
|
|
31319
|
+
if (Platform.OS !== 'android') return indexUri;
|
|
31320
|
+
const native = requireNativeModule<{ registerBundle(root: string, paths: string[]): Promise<string> }>('AbsoluteEmbeddedAssets');
|
|
31321
|
+
return native.registerBundle(rootUri, paths);
|
|
31322
|
+
};
|
|
31323
|
+
`;
|
|
31324
|
+
var absoluteExpoEmbeddedAssetsFiles = (project) => {
|
|
31325
|
+
const root = join20(project, "modules/absolute-embedded-assets");
|
|
31326
|
+
return new Map([
|
|
31327
|
+
[
|
|
31328
|
+
join20(root, "expo-module.config.json"),
|
|
31329
|
+
`${JSON.stringify({
|
|
31330
|
+
android: {
|
|
31331
|
+
modules: [
|
|
31332
|
+
"expo.modules.absoluteembeddedassets.AbsoluteEmbeddedAssetsModule"
|
|
31333
|
+
]
|
|
31334
|
+
},
|
|
31335
|
+
platforms: ["android"]
|
|
31336
|
+
}, null, 2)}
|
|
31337
|
+
`
|
|
31338
|
+
],
|
|
31339
|
+
[
|
|
31340
|
+
join20(root, "android/build.gradle"),
|
|
31341
|
+
`${header}plugins { id 'com.android.library'; id 'expo-module-gradle-plugin' }
|
|
31342
|
+
group = 'expo.modules.absoluteembeddedassets'
|
|
31343
|
+
version = '0.0.1'
|
|
31344
|
+
android {
|
|
31345
|
+
namespace 'expo.modules.absoluteembeddedassets'
|
|
31346
|
+
defaultConfig { versionCode 1; versionName '0.0.1' }
|
|
31347
|
+
}
|
|
31348
|
+
dependencies {
|
|
31349
|
+
implementation 'com.facebook.react:react-android'
|
|
31350
|
+
implementation project(':react-native-webview')
|
|
31351
|
+
implementation 'androidx.webkit:webkit:1.14.0'
|
|
31352
|
+
}
|
|
31353
|
+
`
|
|
31354
|
+
],
|
|
31355
|
+
[
|
|
31356
|
+
join20(root, "android/src/main/AndroidManifest.xml"),
|
|
31357
|
+
`<manifest xmlns:android="http://schemas.android.com/apk/res/android" />
|
|
31358
|
+
`
|
|
31359
|
+
],
|
|
31360
|
+
[
|
|
31361
|
+
join20(root, "android/src/main/java/expo/modules/absoluteembeddedassets/AbsoluteEmbeddedAssetsModule.kt"),
|
|
31362
|
+
android
|
|
31363
|
+
],
|
|
31364
|
+
[join20(project, "plugins/withAbsoluteEmbeddedAssets.js"), plugin],
|
|
31365
|
+
[join20(project, "src/generated/AbsoluteEmbeddedAssets.ts"), runtime2]
|
|
31366
|
+
]);
|
|
31367
|
+
};
|
|
31368
|
+
|
|
31067
31369
|
// src/mobile/expoProject.ts
|
|
31068
31370
|
var EXPO_GENERATED_HEADER = `// Generated by AbsoluteJS. Edit absolute.config.ts, then run absolute mobile sync.
|
|
31069
31371
|
`;
|
|
@@ -31144,15 +31446,15 @@ var routeSegments = (route) => {
|
|
|
31144
31446
|
return segment;
|
|
31145
31447
|
});
|
|
31146
31448
|
};
|
|
31147
|
-
var routeFile = (project, route) =>
|
|
31449
|
+
var routeFile = (project, route) => join21(project, "app", ...routeSegments(route), "index.tsx");
|
|
31148
31450
|
var packageDependencies = (plan) => Object.fromEntries(plan.requiredPackages.map((spec) => {
|
|
31149
31451
|
const separator = spec.lastIndexOf("@");
|
|
31150
31452
|
return [spec.slice(0, separator), spec.slice(separator + 1)];
|
|
31151
31453
|
}));
|
|
31152
31454
|
var expoPackage = (auth, branding, sync, devices, updates) => ({
|
|
31153
31455
|
dependencies: {
|
|
31154
|
-
"@absolutejs/devices":
|
|
31155
|
-
"@absolutejs/devices-expo":
|
|
31456
|
+
"@absolutejs/devices": ABSOLUTE_DEVICES_VERSION,
|
|
31457
|
+
"@absolutejs/devices-expo": ABSOLUTE_EXPO_DEVICES_VERSION,
|
|
31156
31458
|
...auth ? {
|
|
31157
31459
|
"@absolutejs/auth": ABSOLUTE_EXPO_AUTH_CORE_VERSION,
|
|
31158
31460
|
[ABSOLUTE_EXPO_AUTH_PACKAGE]: ABSOLUTE_EXPO_AUTH_VERSION
|
|
@@ -31233,24 +31535,24 @@ var expoAppConfig = (config, auth, sync, devices, runtimeFingerprint) => {
|
|
|
31233
31535
|
const devicePlugins = [
|
|
31234
31536
|
...new Set(devices.capabilities.flatMap((name) => devices.providers[name]?.plugins ?? []))
|
|
31235
31537
|
];
|
|
31236
|
-
const configuredPlugins = devicePlugins.map((
|
|
31237
|
-
if (
|
|
31538
|
+
const configuredPlugins = devicePlugins.map((plugin2) => {
|
|
31539
|
+
if (plugin2 === "expo-image-picker")
|
|
31238
31540
|
return [
|
|
31239
|
-
|
|
31541
|
+
plugin2,
|
|
31240
31542
|
{
|
|
31241
31543
|
cameraPermission: descriptions.NSCameraUsageDescription,
|
|
31242
31544
|
microphonePermission: false,
|
|
31243
31545
|
photosPermission: descriptions.NSPhotoLibraryUsageDescription
|
|
31244
31546
|
}
|
|
31245
31547
|
];
|
|
31246
|
-
if (
|
|
31548
|
+
if (plugin2 === "expo-location")
|
|
31247
31549
|
return [
|
|
31248
|
-
|
|
31550
|
+
plugin2,
|
|
31249
31551
|
{
|
|
31250
31552
|
locationWhenInUsePermission: descriptions.NSLocationWhenInUseUsageDescription
|
|
31251
31553
|
}
|
|
31252
31554
|
];
|
|
31253
|
-
return
|
|
31555
|
+
return plugin2;
|
|
31254
31556
|
});
|
|
31255
31557
|
return {
|
|
31256
31558
|
expo: {
|
|
@@ -31272,7 +31574,7 @@ var expoAppConfig = (config, auth, sync, devices, runtimeFingerprint) => {
|
|
|
31272
31574
|
package: config.appId,
|
|
31273
31575
|
permissions: requirements.androidPermissions
|
|
31274
31576
|
},
|
|
31275
|
-
experiments: { typedRoutes: true },
|
|
31577
|
+
experiments: { tsconfigPaths: false, typedRoutes: true },
|
|
31276
31578
|
ios: {
|
|
31277
31579
|
...branding?.ios ?? {},
|
|
31278
31580
|
associatedDomains: config.deepLinkHosts.map((host2) => `applinks:${host2}`),
|
|
@@ -31295,6 +31597,7 @@ var expoAppConfig = (config, auth, sync, devices, runtimeFingerprint) => {
|
|
|
31295
31597
|
["expo-dev-client", { launchMode: "most-recent" }],
|
|
31296
31598
|
...branding ? [branding.splashPlugin] : [],
|
|
31297
31599
|
"./plugins/withAbsoluteActivityResultRecovery",
|
|
31600
|
+
"./plugins/withAbsoluteEmbeddedAssets",
|
|
31298
31601
|
...auth || config.updates ? ["expo-secure-store"] : [],
|
|
31299
31602
|
...sync ? [
|
|
31300
31603
|
"expo-sqlite",
|
|
@@ -31752,7 +32055,7 @@ import {
|
|
|
31752
32055
|
installExpoSyncLifecycle,
|
|
31753
32056
|
registerExpoSyncBackgroundTask
|
|
31754
32057
|
} from '@absolutejs/sync-expo';
|
|
31755
|
-
import
|
|
32058
|
+
import { reloadAppAsync } from 'expo';
|
|
31756
32059
|
import { absoluteExpoAuth, startAbsoluteExpoAuth } from './AbsoluteAuth';
|
|
31757
32060
|
|
|
31758
32061
|
const BACKGROUND_TASK = ${JSON.stringify(backgroundTask)};
|
|
@@ -31811,37 +32114,98 @@ absoluteExpoAuth.onPrincipalChange(principal => {
|
|
|
31811
32114
|
if (!started || principal?.namespace === activeNamespace) return;
|
|
31812
32115
|
const previousNamespace = activeNamespace;
|
|
31813
32116
|
installRuntimeTransport(principal);
|
|
31814
|
-
if (previousNamespace !== undefined) void
|
|
32117
|
+
if (previousNamespace !== undefined) void reloadAppAsync('absolutejs-auth-principal-changed').catch(() => {
|
|
32118
|
+
console.warn('AbsoluteJS could not reset the account runtime. Restart the app before continuing.');
|
|
32119
|
+
});
|
|
31815
32120
|
});
|
|
31816
32121
|
|
|
31817
32122
|
export const createAbsoluteExpoSyncBridge = async (
|
|
31818
32123
|
emit: (event: 'sync.socket' | 'sync.wake', payload: Record<string, unknown>) => void
|
|
31819
32124
|
) => {
|
|
31820
32125
|
await startAbsoluteExpoSync();
|
|
31821
|
-
const
|
|
31822
|
-
|
|
31823
|
-
|
|
31824
|
-
|
|
32126
|
+
const bind = (namespace: string, generation: number) => {
|
|
32127
|
+
const emitCurrent = (event: 'sync.socket' | 'sync.wake', payload: Record<string, unknown>) => {
|
|
32128
|
+
if (!closed && generation === revision) emit(event, payload);
|
|
32129
|
+
};
|
|
32130
|
+
const transactions = createExpoSyncBridgeHost({ createId: expoSyncRandomId, namespace, store });
|
|
32131
|
+
const sockets = createExpoSyncSocketBridgeHost({
|
|
32132
|
+
allowedOrigin: PRODUCTION_ORIGIN,
|
|
32133
|
+
emit: payload => emitCurrent('sync.socket', payload),
|
|
32134
|
+
socketTicket: async audience => {
|
|
32135
|
+
if (closed || generation !== revision) throw new Error('Expo Sync principal changed.');
|
|
32136
|
+
const ticket = await absoluteExpoAuth.socketTicket(audience);
|
|
32137
|
+
if (closed || generation !== revision) throw new Error('Expo Sync principal changed.');
|
|
32138
|
+
return ticket;
|
|
32139
|
+
}
|
|
32140
|
+
});
|
|
32141
|
+
const removeLifecycle = installExpoSyncLifecycle({
|
|
32142
|
+
client: { reconnect: () => emitCurrent('sync.wake', {}) }
|
|
32143
|
+
});
|
|
32144
|
+
return {
|
|
32145
|
+
close: async () => {
|
|
32146
|
+
removeLifecycle();
|
|
32147
|
+
await Promise.all([transactions.close(), sockets.close()]);
|
|
32148
|
+
},
|
|
32149
|
+
request: (method: string, params: Record<string, unknown>) =>
|
|
32150
|
+
method.startsWith('sync.socket.') ? sockets.request(method, params) : transactions.request(method, params)
|
|
32151
|
+
};
|
|
31825
32152
|
};
|
|
31826
|
-
|
|
31827
|
-
|
|
31828
|
-
|
|
31829
|
-
|
|
31830
|
-
|
|
31831
|
-
|
|
31832
|
-
const
|
|
31833
|
-
|
|
31834
|
-
|
|
32153
|
+
let closed = false;
|
|
32154
|
+
let revoked = false;
|
|
32155
|
+
let boundNamespace: string | undefined;
|
|
32156
|
+
let revision = 0;
|
|
32157
|
+
let bridge: ReturnType<typeof bind> | undefined;
|
|
32158
|
+
let ready = Promise.resolve();
|
|
32159
|
+
const replace = (principal: Awaited<ReturnType<typeof absoluteExpoAuth.principal>>) => {
|
|
32160
|
+
if (closed) return;
|
|
32161
|
+
// A mounted page may bind its first login, but must never inherit another
|
|
32162
|
+
// account's authority. Account changes require the existing runtime reload.
|
|
32163
|
+
if (boundNamespace !== undefined && principal?.namespace !== boundNamespace) revoked = true;
|
|
32164
|
+
const generation = ++revision;
|
|
32165
|
+
const previous = bridge;
|
|
32166
|
+
bridge = undefined;
|
|
32167
|
+
ready = ready.then(async () => {
|
|
32168
|
+
await previous?.close();
|
|
32169
|
+
if (!closed && !revoked && generation === revision && principal) {
|
|
32170
|
+
boundNamespace = principal.namespace;
|
|
32171
|
+
bridge = bind(principal.namespace, generation);
|
|
32172
|
+
}
|
|
32173
|
+
});
|
|
32174
|
+
// Keep background transitions handled; requests still observe setup failures.
|
|
32175
|
+
void ready.catch(() => undefined);
|
|
32176
|
+
};
|
|
32177
|
+
const stop = absoluteExpoAuth.onPrincipalChange(replace);
|
|
32178
|
+
try {
|
|
32179
|
+
const initialRevision = revision;
|
|
32180
|
+
const principal = await absoluteExpoAuth.principal();
|
|
32181
|
+
if (revision === initialRevision) replace(principal);
|
|
32182
|
+
await ready;
|
|
32183
|
+
} catch (error) {
|
|
32184
|
+
stop();
|
|
32185
|
+
closed = true;
|
|
32186
|
+
await bridge?.close();
|
|
32187
|
+
throw error;
|
|
32188
|
+
}
|
|
31835
32189
|
|
|
31836
32190
|
return {
|
|
31837
32191
|
close: async () => {
|
|
31838
|
-
|
|
31839
|
-
|
|
32192
|
+
if (closed) return;
|
|
32193
|
+
closed = true;
|
|
32194
|
+
++revision;
|
|
32195
|
+
stop();
|
|
32196
|
+
const previous = bridge;
|
|
32197
|
+
bridge = undefined;
|
|
32198
|
+
await Promise.all([ready, previous?.close()]);
|
|
31840
32199
|
},
|
|
31841
|
-
request: (method: string, params: Record<string, unknown>) =>
|
|
31842
|
-
|
|
31843
|
-
|
|
31844
|
-
|
|
32200
|
+
request: async (method: string, params: Record<string, unknown>) => {
|
|
32201
|
+
const generation = revision;
|
|
32202
|
+
await ready;
|
|
32203
|
+
if (closed || revoked || generation !== revision) throw new Error('Expo Sync principal changed.');
|
|
32204
|
+
if (!bridge) throw new Error('Expo Sync requires an authenticated principal.');
|
|
32205
|
+
const result = await bridge.request(method, params);
|
|
32206
|
+
if (closed || revoked || generation !== revision) throw new Error('Expo Sync principal changed.');
|
|
32207
|
+
return result;
|
|
32208
|
+
}
|
|
31845
32209
|
};
|
|
31846
32210
|
};
|
|
31847
32211
|
`;
|
|
@@ -31859,6 +32223,7 @@ import { ActivityIndicator, BackHandler, Platform, Pressable, StyleSheet, Text,
|
|
|
31859
32223
|
import { useSafeAreaInsets } from 'react-native-safe-area-context';
|
|
31860
32224
|
import { WebView, type WebViewMessageEvent } from 'react-native-webview';
|
|
31861
32225
|
import { materializeAbsoluteWebBundle } from './webAssets';
|
|
32226
|
+
import { absoluteEmbeddedNativeConfig } from './AbsoluteEmbeddedAssets';
|
|
31862
32227
|
import { markAbsoluteEmbeddedWebPhase, markAbsoluteEmbeddedWebReady } from './AbsoluteActivityResultRecovery';
|
|
31863
32228
|
import { createExpoDevicesBridgeHost } from '@absolutejs/devices-expo/bridge';
|
|
31864
32229
|
import { absoluteExpoDevices, beforeAbsoluteExpoDeviceSignOut } from './AbsoluteDevices';
|
|
@@ -31978,7 +32343,16 @@ const bridgeBootstrap = (path: string, safeAreaInsets: { bottom: number; left: n
|
|
|
31978
32343
|
event.preventDefault();
|
|
31979
32344
|
send({ format: 3, kind: 'event', event: 'navigation', path: url.pathname + url.search + url.hash });
|
|
31980
32345
|
}, true);
|
|
31981
|
-
|
|
32346
|
+
let shellRendered = false;
|
|
32347
|
+
addEventListener('absolute:shell-rendered', () => {
|
|
32348
|
+
shellRendered = true;
|
|
32349
|
+
send({ format: 3, kind: 'event', event: 'shell-rendered', path: currentPath });
|
|
32350
|
+
});
|
|
32351
|
+
const startupFailed = () => {
|
|
32352
|
+
if (!shellRendered) send({ format: 3, kind: 'event', event: 'startup-failed', path: currentPath });
|
|
32353
|
+
};
|
|
32354
|
+
addEventListener('error', startupFailed);
|
|
32355
|
+
addEventListener('unhandledrejection', startupFailed);
|
|
31982
32356
|
})(); true;\`;
|
|
31983
32357
|
};
|
|
31984
32358
|
|
|
@@ -32023,11 +32397,18 @@ export function AbsoluteWebHost({ path }: AbsoluteWebHostProps = {}) {
|
|
|
32023
32397
|
const canGoBack = useRef(false);
|
|
32024
32398
|
const [runtimeReady, setRuntimeReady] = useState(!AUTH_ENABLED && !SYNC_ENABLED);
|
|
32025
32399
|
const [devicesReady, setDevicesReady] = useState(false);
|
|
32026
|
-
const [startupError, setStartupError] = useState<'assets' | 'devices'>();
|
|
32400
|
+
const [startupError, setStartupError] = useState<'assets' | 'devices' | 'content'>();
|
|
32027
32401
|
const [startupRevision, setStartupRevision] = useState(0);
|
|
32028
32402
|
const activeWebPath = useRef(pathname);
|
|
32029
32403
|
const embeddedReadyReported = useRef(false);
|
|
32030
32404
|
const webSource = useMemo(() => indexUri ? { uri: indexUri } : undefined, [indexUri]);
|
|
32405
|
+
useEffect(() => {
|
|
32406
|
+
if (!indexUri || DEV_ORIGIN) return;
|
|
32407
|
+
const timeout = setTimeout(() => {
|
|
32408
|
+
if (!embeddedReadyReported.current) setStartupError('content');
|
|
32409
|
+
}, 60000);
|
|
32410
|
+
return () => clearTimeout(timeout);
|
|
32411
|
+
}, [indexUri]);
|
|
32031
32412
|
|
|
32032
32413
|
useEffect(() => {
|
|
32033
32414
|
if (!AUTH_ENABLED && !SYNC_ENABLED) return;
|
|
@@ -32038,10 +32419,13 @@ export function AbsoluteWebHost({ path }: AbsoluteWebHostProps = {}) {
|
|
|
32038
32419
|
webView.current?.injectJavaScript(\`globalThis.__absoluteExpoReceive(\${JSON.stringify(source)}); true;\`);
|
|
32039
32420
|
});
|
|
32040
32421
|
void ${sync ? "startAbsoluteExpoSync" : "startAbsoluteExpoAuth"}().then(async () => {
|
|
32041
|
-
${sync ? `
|
|
32422
|
+
${sync ? `const bridge = await createAbsoluteExpoSyncBridge((event, payload) => {
|
|
32423
|
+
if (!active) return;
|
|
32042
32424
|
const source = JSON.stringify({ event, format: BRIDGE_FORMAT, kind: 'event', path: activeWebPath.current, payload });
|
|
32043
32425
|
webView.current?.injectJavaScript(\`globalThis.__absoluteExpoReceive(\${JSON.stringify(source)}); true;\`);
|
|
32044
|
-
})
|
|
32426
|
+
});
|
|
32427
|
+
if (!active) { await bridge.close(); return; }
|
|
32428
|
+
syncBridge.current = bridge;` : ""}
|
|
32045
32429
|
if (active) setRuntimeReady(true);
|
|
32046
32430
|
});
|
|
32047
32431
|
return () => {
|
|
@@ -32063,6 +32447,7 @@ export function AbsoluteWebHost({ path }: AbsoluteWebHostProps = {}) {
|
|
|
32063
32447
|
markAbsoluteEmbeddedWebPhase('assets-start');
|
|
32064
32448
|
void materializeAbsoluteWebBundle().then(uri => {
|
|
32065
32449
|
markAbsoluteEmbeddedWebPhase('assets-ready');
|
|
32450
|
+
embeddedReadyReported.current = false;
|
|
32066
32451
|
setIndexUri(uri + '?absolutePath=' + encodeURIComponent(pathname));
|
|
32067
32452
|
}).catch(error => {
|
|
32068
32453
|
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')
|
|
@@ -32116,15 +32501,23 @@ export function AbsoluteWebHost({ path }: AbsoluteWebHostProps = {}) {
|
|
|
32116
32501
|
try { return new URL(source).origin === origin; } catch { return false; }
|
|
32117
32502
|
};
|
|
32118
32503
|
const onMessage = async (event: WebViewMessageEvent) => {
|
|
32504
|
+
// Bridge authority belongs only to the currently loaded embedded bundle
|
|
32505
|
+
// (or the explicitly configured development origin), never remote pages.
|
|
32506
|
+
const sourceUrl = event.nativeEvent.url;
|
|
32507
|
+
if (!indexUri || typeof sourceUrl !== 'string' || (DEV_ORIGIN ? !hasOrigin(sourceUrl, DEV_ORIGIN) : !sourceUrl.startsWith(indexUri.slice(0, indexUri.lastIndexOf('/') + 1)))) return;
|
|
32119
32508
|
const source = event.nativeEvent.data;
|
|
32120
32509
|
if (new TextEncoder().encode(source).byteLength > MAX_MESSAGE_BYTES) return;
|
|
32121
32510
|
let message: Record<string, unknown>;
|
|
32122
32511
|
try { message = JSON.parse(source); } catch { return; }
|
|
32123
32512
|
if (message.format !== BRIDGE_FORMAT || typeof message.path !== 'string' || !message.path.startsWith('/') || message.path.startsWith('//')) return;
|
|
32124
|
-
if (message.kind === 'event' &&
|
|
32513
|
+
if (message.kind === 'event' && message.event === 'startup-failed') {
|
|
32514
|
+
if (!embeddedReadyReported.current) setStartupError('content');
|
|
32515
|
+
return;
|
|
32516
|
+
}
|
|
32517
|
+
if (message.kind === 'event' && (message.event === 'navigation' || message.event === 'shell-rendered')) {
|
|
32125
32518
|
const target = new URL(message.path, PRODUCTION_ORIGIN);
|
|
32126
32519
|
if (target.origin !== PRODUCTION_ORIGIN) return;
|
|
32127
|
-
if (message.event === '
|
|
32520
|
+
if (message.event === 'shell-rendered' && !DEV_ORIGIN && !embeddedReadyReported.current) {
|
|
32128
32521
|
embeddedReadyReported.current = true;
|
|
32129
32522
|
markAbsoluteEmbeddedWebReady();
|
|
32130
32523
|
}
|
|
@@ -32178,12 +32571,17 @@ export function AbsoluteWebHost({ path }: AbsoluteWebHostProps = {}) {
|
|
|
32178
32571
|
</View>;
|
|
32179
32572
|
if (!webSource || !runtimeReady || !devicesReady) return <View style={styles.loading}><ActivityIndicator /></View>;
|
|
32180
32573
|
return <WebView
|
|
32181
|
-
|
|
32182
|
-
|
|
32574
|
+
nativeConfig={!DEV_ORIGIN ? absoluteEmbeddedNativeConfig : undefined}
|
|
32575
|
+
allowFileAccess={Platform.OS !== 'android'}
|
|
32576
|
+
allowFileAccessFromFileURLs={Platform.OS !== 'android'}
|
|
32183
32577
|
allowUniversalAccessFromFileURLs={false}
|
|
32578
|
+
originWhitelist={DEV_ORIGIN ? [DEV_ORIGIN] : [Platform.OS === 'android' ? 'https://appassets.androidplatform.net' : 'file://*']}
|
|
32184
32579
|
allowingReadAccessToURL={webSource.uri.slice(0, webSource.uri.lastIndexOf('/') + 1)}
|
|
32185
32580
|
injectedJavaScriptBeforeContentLoaded={bridgeBootstrap(pathname, safeAreaInsets)}
|
|
32186
32581
|
onMessage={onMessage}
|
|
32582
|
+
onError={() => setStartupError('content')}
|
|
32583
|
+
onRenderProcessGone={() => setStartupError('content')}
|
|
32584
|
+
onContentProcessDidTerminate={() => setStartupError('content')}
|
|
32187
32585
|
onNavigationStateChange={state => {
|
|
32188
32586
|
canGoBack.current = state.canGoBack;
|
|
32189
32587
|
if (!DEV_ORIGIN || !hasOrigin(state.url, DEV_ORIGIN)) return;
|
|
@@ -32191,8 +32589,8 @@ export function AbsoluteWebHost({ path }: AbsoluteWebHostProps = {}) {
|
|
|
32191
32589
|
activeWebPath.current = route.pathname + route.search + route.hash;
|
|
32192
32590
|
}}
|
|
32193
32591
|
onShouldStartLoadWithRequest={request => {
|
|
32194
|
-
if (
|
|
32195
|
-
void Linking.openURL(request.url);
|
|
32592
|
+
if (DEV_ORIGIN ? hasOrigin(request.url, DEV_ORIGIN) : request.url.startsWith(webSource.uri.slice(0, webSource.uri.lastIndexOf('/') + 1))) return true;
|
|
32593
|
+
if (/^https?:/.test(request.url)) void Linking.openURL(request.url);
|
|
32196
32594
|
return false;
|
|
32197
32595
|
}}
|
|
32198
32596
|
ref={webView}
|
|
@@ -32395,8 +32793,8 @@ const styles = StyleSheet.create({
|
|
|
32395
32793
|
error: { color: '#b91c1c', fontSize: 16, textAlign: 'center' }
|
|
32396
32794
|
});
|
|
32397
32795
|
`;
|
|
32398
|
-
var nativeWrapperSource = (wrapper, module,
|
|
32399
|
-
import { createAbsoluteNativeRoute, createAbsoluteNativeRouteErrorBoundary } from ${JSON.stringify(portableRelative3(dirname13(wrapper),
|
|
32796
|
+
var nativeWrapperSource = (wrapper, module, runtime3, route) => `${EXPO_GENERATED_HEADER}import ApplicationNativeRoute from ${JSON.stringify(portableRelative3(dirname13(wrapper), module).replace(/\.(?:[cm]?[jt]sx?)$/u, ""))};
|
|
32797
|
+
import { createAbsoluteNativeRoute, createAbsoluteNativeRouteErrorBoundary } from ${JSON.stringify(portableRelative3(dirname13(wrapper), runtime3).replace(/\.(?:[cm]?[jt]sx?)$/u, ""))};
|
|
32400
32798
|
|
|
32401
32799
|
export const ErrorBoundary = createAbsoluteNativeRouteErrorBoundary(${JSON.stringify(route)});
|
|
32402
32800
|
export default createAbsoluteNativeRoute(ApplicationNativeRoute, ${JSON.stringify(route)});
|
|
@@ -32438,7 +32836,7 @@ var expoTsConfig = (projectRoot, project, auth, sync) => ({
|
|
|
32438
32836
|
extends: "expo/tsconfig.base"
|
|
32439
32837
|
});
|
|
32440
32838
|
var writeManagedFile = async (path, source, force) => {
|
|
32441
|
-
await
|
|
32839
|
+
await mkdir15(dirname13(path), { recursive: true });
|
|
32442
32840
|
if (await exists6(path)) {
|
|
32443
32841
|
const current = await readFile17(path, "utf8");
|
|
32444
32842
|
if (current === source)
|
|
@@ -32465,7 +32863,7 @@ var pruneManagedFiles = async (paths) => {
|
|
|
32465
32863
|
return removed.filter(Boolean).length;
|
|
32466
32864
|
};
|
|
32467
32865
|
var pruneStaleManagedExpoRoutes = async (project, expected) => {
|
|
32468
|
-
const appDirectory =
|
|
32866
|
+
const appDirectory = join21(project, "app");
|
|
32469
32867
|
if (!await exists6(appDirectory))
|
|
32470
32868
|
return 0;
|
|
32471
32869
|
const files = await walkFiles(appDirectory);
|
|
@@ -32513,20 +32911,20 @@ var writeAbsoluteExpoProject = async (config, options) => {
|
|
|
32513
32911
|
if (missing) {
|
|
32514
32912
|
throw new TypeError(`Expo native route ${missing.route} references missing module ${missing.module}.`);
|
|
32515
32913
|
}
|
|
32516
|
-
const marker =
|
|
32914
|
+
const marker = join21(project, EXPO_PROJECT_MARKER);
|
|
32517
32915
|
if (await exists6(project) && !await exists6(marker)) {
|
|
32518
32916
|
const entries = await readdir5(project);
|
|
32519
32917
|
if (entries.length > 0 && !options.force) {
|
|
32520
32918
|
throw new TypeError(`Expo project directory ${project} is not AbsoluteJS-managed; rerun with --force only after reviewing it.`);
|
|
32521
32919
|
}
|
|
32522
32920
|
}
|
|
32523
|
-
await
|
|
32921
|
+
await mkdir15(project, { recursive: true });
|
|
32524
32922
|
await writeFile14(marker, `format=1
|
|
32525
32923
|
`);
|
|
32526
32924
|
const authEnabled = Boolean(auth);
|
|
32527
32925
|
const files = new Map([
|
|
32528
32926
|
[
|
|
32529
|
-
|
|
32927
|
+
join21(project, ".gitignore"),
|
|
32530
32928
|
`.expo/
|
|
32531
32929
|
android/
|
|
32532
32930
|
ios/
|
|
@@ -32534,80 +32932,82 @@ node_modules/
|
|
|
32534
32932
|
`
|
|
32535
32933
|
],
|
|
32536
32934
|
[
|
|
32537
|
-
|
|
32935
|
+
join21(project, "app.json"),
|
|
32538
32936
|
jsonSource(expoAppConfig(config, authEnabled, syncEnabled, devices, runtimeFingerprint))
|
|
32539
32937
|
],
|
|
32540
|
-
[
|
|
32938
|
+
[join21(project, "app.config.js"), expoDynamicAppConfig],
|
|
32541
32939
|
[
|
|
32542
|
-
|
|
32940
|
+
join21(project, "package.json"),
|
|
32543
32941
|
jsonSource(expoPackage(authEnabled, config.branding !== undefined, syncEnabled, devices, config.updates !== undefined))
|
|
32544
32942
|
],
|
|
32545
|
-
[
|
|
32943
|
+
[join21(project, "metro.config.js"), metroConfig(projectRoot)],
|
|
32546
32944
|
[
|
|
32547
|
-
|
|
32945
|
+
join21(project, "plugins", "withAbsoluteDevelopmentCa.js"),
|
|
32548
32946
|
expoDevelopmentCaPlugin
|
|
32549
32947
|
],
|
|
32550
32948
|
[
|
|
32551
|
-
|
|
32949
|
+
join21(project, "plugins", "withAbsoluteActivityResultRecovery.js"),
|
|
32552
32950
|
expoActivityResultRecoveryPlugin
|
|
32553
32951
|
],
|
|
32554
32952
|
[
|
|
32555
|
-
|
|
32953
|
+
join21(project, "tsconfig.json"),
|
|
32556
32954
|
jsonSource(expoTsConfig(projectRoot, project, authEnabled, syncEnabled))
|
|
32557
32955
|
],
|
|
32558
32956
|
[
|
|
32559
|
-
|
|
32957
|
+
join21(project, "app", "_layout.tsx"),
|
|
32560
32958
|
layoutSource(authEnabled, syncEnabled, config.updates !== undefined, config.observability !== undefined)
|
|
32561
32959
|
],
|
|
32562
32960
|
[
|
|
32563
|
-
|
|
32961
|
+
join21(project, "app", "__absolute", "native", "index.tsx"),
|
|
32564
32962
|
nativeDiagnosticSource
|
|
32565
32963
|
],
|
|
32566
32964
|
[
|
|
32567
|
-
|
|
32965
|
+
join21(project, "src", "generated", "AbsoluteDevices.ts"),
|
|
32568
32966
|
devicesRuntimeSource(config, devices, authEnabled)
|
|
32569
32967
|
],
|
|
32570
32968
|
[
|
|
32571
|
-
|
|
32969
|
+
join21(project, "src", "generated", "AbsoluteNativeRoute.tsx"),
|
|
32572
32970
|
nativeRouteRuntimeSource(authEnabled)
|
|
32573
32971
|
],
|
|
32574
32972
|
[
|
|
32575
|
-
|
|
32973
|
+
join21(project, "src", "generated", "AbsoluteWebHost.tsx"),
|
|
32576
32974
|
webHostSource(config, auth, syncEnabled)
|
|
32577
32975
|
]
|
|
32578
32976
|
]);
|
|
32579
32977
|
for (const [path, source] of absoluteExpoActivityResultRecoveryFiles(project))
|
|
32580
32978
|
files.set(path, source);
|
|
32979
|
+
for (const [path, source] of absoluteExpoEmbeddedAssetsFiles(project))
|
|
32980
|
+
files.set(path, source);
|
|
32581
32981
|
if (config.observability) {
|
|
32582
32982
|
for (const [path, source] of absoluteExpoNativeObservabilityFiles(project))
|
|
32583
32983
|
files.set(path, source);
|
|
32584
32984
|
}
|
|
32585
32985
|
if (config.updates) {
|
|
32586
|
-
files.set(
|
|
32986
|
+
files.set(join21(project, "src", "generated", "AbsoluteUpdates.ts"), updatesRuntimeSource(config));
|
|
32587
32987
|
}
|
|
32588
32988
|
const expoCodeSigning = config.updates?.expoCodeSigning;
|
|
32589
32989
|
if (expoCodeSigning)
|
|
32590
|
-
files.set(
|
|
32990
|
+
files.set(join21(project, "certs", "absolute-mobile-update.pem"), expoCodeSigning.certificatePem);
|
|
32591
32991
|
if (auth) {
|
|
32592
|
-
files.set(
|
|
32992
|
+
files.set(join21(project, "src", "generated", "AbsoluteAuth.ts"), authRuntimeSource(auth, config.appId));
|
|
32593
32993
|
}
|
|
32594
32994
|
if (syncSchema) {
|
|
32595
|
-
files.set(
|
|
32995
|
+
files.set(join21(project, "src", "generated", "AbsoluteSync.ts"), syncRuntimeSource(config, syncSchema));
|
|
32596
32996
|
}
|
|
32597
|
-
const webAssetsPath =
|
|
32997
|
+
const webAssetsPath = join21(project, "src", "generated", "webAssets.ts");
|
|
32598
32998
|
if (!await exists6(webAssetsPath)) {
|
|
32599
32999
|
files.set(webAssetsPath, emptyWebAssetsSource);
|
|
32600
33000
|
}
|
|
32601
33001
|
if (!config.expoNativeRoutes["/"]) {
|
|
32602
|
-
files.set(
|
|
33002
|
+
files.set(join21(project, "app", "index.tsx"), webRouteSource);
|
|
32603
33003
|
}
|
|
32604
|
-
files.set(
|
|
32605
|
-
const nativeRouteRuntime =
|
|
33004
|
+
files.set(join21(project, "app", "[...absolute].tsx"), catchAllRouteSource);
|
|
33005
|
+
const nativeRouteRuntime = join21(project, "src", "generated", "AbsoluteNativeRoute.tsx");
|
|
32606
33006
|
for (const [route, module] of routeModules) {
|
|
32607
|
-
const wrapper = route === "/" ?
|
|
33007
|
+
const wrapper = route === "/" ? join21(project, "app", "index.tsx") : routeFile(project, route);
|
|
32608
33008
|
files.set(wrapper, nativeWrapperSource(wrapper, module, nativeRouteRuntime, route));
|
|
32609
33009
|
}
|
|
32610
|
-
const removedRoutes = await pruneStaleManagedExpoRoutes(project, new Set([...files.keys()].filter((path) => path.startsWith(`${
|
|
33010
|
+
const removedRoutes = await pruneStaleManagedExpoRoutes(project, new Set([...files.keys()].filter((path) => path.startsWith(`${join21(project, "app")}${sep8}`))));
|
|
32611
33011
|
const removedObservability = config.observability ? 0 : await pruneManagedFiles(absoluteExpoNativeObservabilityPaths(project));
|
|
32612
33012
|
const changes = await Promise.all([...files].map(([path, source]) => writeManagedFile(path, source, true)));
|
|
32613
33013
|
await writeAbsoluteExpoBrandingInputs(config, projectRoot);
|
|
@@ -32617,7 +33017,7 @@ node_modules/
|
|
|
32617
33017
|
var walkFiles = async (root, directory = root) => {
|
|
32618
33018
|
const entries = await readdir5(directory, { withFileTypes: true });
|
|
32619
33019
|
const nested = await Promise.all(entries.map((entry) => {
|
|
32620
|
-
const path =
|
|
33020
|
+
const path = join21(directory, entry.name);
|
|
32621
33021
|
if (entry.isDirectory())
|
|
32622
33022
|
return walkFiles(root, path);
|
|
32623
33023
|
if (entry.isFile())
|
|
@@ -32650,13 +33050,16 @@ var installStagedDirectory = async (staging, destination) => {
|
|
|
32650
33050
|
throw error;
|
|
32651
33051
|
}
|
|
32652
33052
|
};
|
|
32653
|
-
var assetModuleSource = (assets, archiveAsset, bundleId, manifest) => `${EXPO_GENERATED_HEADER}import { Asset } from 'expo-asset';
|
|
33053
|
+
var assetModuleSource = (assets, archiveAsset, bundleId, archiveMd5, manifest) => `${EXPO_GENERATED_HEADER}import { Asset } from 'expo-asset';
|
|
32654
33054
|
import { Directory, File, Paths } from 'expo-file-system';
|
|
32655
33055
|
import { copyAsync as copyLegacyAsync } from 'expo-file-system/legacy';
|
|
33056
|
+
import { registerAbsoluteEmbeddedBundle } from './AbsoluteEmbeddedAssets';
|
|
32656
33057
|
|
|
32657
33058
|
${nativeDataManifestTypeSource}
|
|
32658
33059
|
declare const require: (path: string) => number;
|
|
32659
33060
|
const BUNDLE_ID = ${JSON.stringify(bundleId)};
|
|
33061
|
+
const ARCHIVE_MD5 = ${JSON.stringify(archiveMd5)};
|
|
33062
|
+
const ARCHIVE_LENGTH = ${assets.reduce((sum, entry) => sum + entry.length, 0)};
|
|
32660
33063
|
export const ABSOLUTE_MOBILE_MANIFEST: AbsoluteMobileManifest = ${JSON.stringify(manifest)};
|
|
32661
33064
|
const ARCHIVE_MODULE = require(${JSON.stringify(archiveAsset)});
|
|
32662
33065
|
const ASSETS = [
|
|
@@ -32673,10 +33076,12 @@ export const materializeAbsoluteWebBundle = async () => {
|
|
|
32673
33076
|
let archive: File;
|
|
32674
33077
|
try { archive = new File(root, '.absolutejs-bundle.absasset'); }
|
|
32675
33078
|
catch { throw new Error('assets-destination-failed'); }
|
|
33079
|
+
if (archive.exists && (archive.size !== ARCHIVE_LENGTH || archive.md5 !== ARCHIVE_MD5)) archive.delete();
|
|
32676
33080
|
if (!archive.exists) {
|
|
32677
33081
|
let asset: Asset;
|
|
32678
33082
|
try { asset = Asset.fromModule(ARCHIVE_MODULE); }
|
|
32679
33083
|
catch { throw new Error('assets-module-failed'); }
|
|
33084
|
+
if (asset.type !== 'absasset' || asset.hash !== ARCHIVE_MD5) throw new Error('assets-identity-failed');
|
|
32680
33085
|
try { if (!asset.localUri) asset = await asset.downloadAsync(); }
|
|
32681
33086
|
catch { throw new Error('assets-download-failed'); }
|
|
32682
33087
|
if (!asset.localUri) throw new Error('assets-download-failed');
|
|
@@ -32689,9 +33094,16 @@ export const materializeAbsoluteWebBundle = async () => {
|
|
|
32689
33094
|
catch { throw new Error('assets-copy-failed'); }
|
|
32690
33095
|
}
|
|
32691
33096
|
}
|
|
33097
|
+
// Checksums detect accidental corruption/registry mismatches, not authenticity;
|
|
33098
|
+
// authenticity comes from the signed application/update containing this table.
|
|
33099
|
+
if (archive.size !== ARCHIVE_LENGTH || archive.md5 !== ARCHIVE_MD5) {
|
|
33100
|
+
archive.delete();
|
|
33101
|
+
throw new Error('assets-integrity-failed');
|
|
33102
|
+
}
|
|
32692
33103
|
let contents: Uint8Array;
|
|
32693
33104
|
try { contents = await archive.bytes(); }
|
|
32694
33105
|
catch { throw new Error('assets-read-failed'); }
|
|
33106
|
+
if (contents.byteLength !== ARCHIVE_LENGTH) throw new Error('assets-integrity-failed');
|
|
32695
33107
|
for (const entry of ASSETS) {
|
|
32696
33108
|
const parts = entry.path.split('/');
|
|
32697
33109
|
const name = parts.pop();
|
|
@@ -32705,27 +33117,28 @@ export const materializeAbsoluteWebBundle = async () => {
|
|
|
32705
33117
|
let destination: File;
|
|
32706
33118
|
try {
|
|
32707
33119
|
destination = new File(directory, name);
|
|
32708
|
-
if (destination.exists && destination.size === entry.length) continue;
|
|
33120
|
+
if (destination.exists && destination.size === entry.length && destination.md5 === entry.md5) continue;
|
|
32709
33121
|
if (destination.exists) destination.delete();
|
|
32710
33122
|
} catch { throw new Error('assets-destination-failed'); }
|
|
32711
33123
|
try { destination.write(contents.slice(entry.offset, entry.offset + entry.length)); }
|
|
32712
33124
|
catch { throw new Error('assets-write-failed'); }
|
|
33125
|
+
if (destination.size !== entry.length || destination.md5 !== entry.md5) throw new Error('assets-integrity-failed');
|
|
32713
33126
|
}
|
|
32714
33127
|
try { archive.delete(); }
|
|
32715
33128
|
catch { throw new Error('assets-finalize-failed'); }
|
|
32716
33129
|
|
|
32717
|
-
try { return new File(root, 'index.html').uri; }
|
|
33130
|
+
try { return await registerAbsoluteEmbeddedBundle(root.uri, ASSETS.map(entry => entry.path), new File(root, 'index.html').uri); }
|
|
32718
33131
|
catch { throw new Error('assets-finalize-failed'); }
|
|
32719
33132
|
};
|
|
32720
33133
|
`;
|
|
32721
33134
|
var syncAbsoluteExpoWebAssets = async (config) => {
|
|
32722
33135
|
if (config.engine !== "expo")
|
|
32723
33136
|
throw new TypeError("Expo asset sync requires mobile.engine: expo.");
|
|
32724
|
-
const marker =
|
|
33137
|
+
const marker = join21(config.nativeProjectDirectory, EXPO_PROJECT_MARKER);
|
|
32725
33138
|
if (!await exists6(marker)) {
|
|
32726
33139
|
throw new TypeError("Expo asset sync requires an AbsoluteJS-managed Expo project. Run mobile init first.");
|
|
32727
33140
|
}
|
|
32728
|
-
const manifestPath =
|
|
33141
|
+
const manifestPath = join21(config.bundleDirectory, "absolute-mobile-manifest.json");
|
|
32729
33142
|
const manifest = JSON.parse(await readFile17(manifestPath, "utf8"));
|
|
32730
33143
|
const nativeDataManifest = expoNativeDataManifest(manifest);
|
|
32731
33144
|
const { appBuild } = nativeDataManifest;
|
|
@@ -32739,16 +33152,18 @@ var syncAbsoluteExpoWebAssets = async (config) => {
|
|
|
32739
33152
|
bundleHash.update("\x00");
|
|
32740
33153
|
});
|
|
32741
33154
|
const bundleId = `amexpo_${bundleHash.digest("hex")}`;
|
|
32742
|
-
const destination =
|
|
32743
|
-
await
|
|
32744
|
-
const staging = await mkdtemp9(
|
|
33155
|
+
const destination = join21(config.nativeProjectDirectory, "assets", "absolute");
|
|
33156
|
+
await mkdir15(dirname13(destination), { recursive: true });
|
|
33157
|
+
const staging = await mkdtemp9(join21(dirname13(destination), `.${basename6(destination)}.stage-`));
|
|
32745
33158
|
let assets;
|
|
32746
33159
|
let archiveAsset;
|
|
33160
|
+
let archiveMd5;
|
|
32747
33161
|
try {
|
|
32748
33162
|
let offset = 0;
|
|
32749
33163
|
assets = filesWithContents.map(({ contents, file }) => {
|
|
32750
33164
|
const entry = {
|
|
32751
33165
|
length: contents.byteLength,
|
|
33166
|
+
md5: createHash15("md5").update(contents).digest("hex"),
|
|
32752
33167
|
offset,
|
|
32753
33168
|
path: relative13(config.bundleDirectory, file).replaceAll("\\", "/")
|
|
32754
33169
|
};
|
|
@@ -32756,15 +33171,17 @@ var syncAbsoluteExpoWebAssets = async (config) => {
|
|
|
32756
33171
|
return entry;
|
|
32757
33172
|
});
|
|
32758
33173
|
const name = `bundle${EXPO_ASSET_EXTENSION}`;
|
|
32759
|
-
|
|
32760
|
-
|
|
33174
|
+
const archiveContents = Buffer.concat(filesWithContents.map(({ contents }) => contents));
|
|
33175
|
+
archiveMd5 = createHash15("md5").update(archiveContents).digest("hex");
|
|
33176
|
+
await writeFile14(join21(staging, name), archiveContents);
|
|
33177
|
+
archiveAsset = portableRelative3(join21(config.nativeProjectDirectory, "src", "generated"), join21(destination, name));
|
|
32761
33178
|
await installStagedDirectory(staging, destination);
|
|
32762
33179
|
} catch (error) {
|
|
32763
33180
|
await rm13(staging, { force: true, recursive: true });
|
|
32764
33181
|
throw error;
|
|
32765
33182
|
}
|
|
32766
|
-
const generated =
|
|
32767
|
-
await writeManagedFile(generated, assetModuleSource(assets, archiveAsset, bundleId, nativeDataManifest), true);
|
|
33183
|
+
const generated = join21(config.nativeProjectDirectory, "src", "generated", "webAssets.ts");
|
|
33184
|
+
await writeManagedFile(generated, assetModuleSource(assets, archiveAsset, bundleId, archiveMd5, nativeDataManifest), true);
|
|
32768
33185
|
return { appBuild, assets: assets.length, bundleId, path: destination };
|
|
32769
33186
|
};
|
|
32770
33187
|
|
|
@@ -32804,9 +33221,9 @@ var loadServerApp = async (producerPath) => {
|
|
|
32804
33221
|
var finalizeAbsoluteMobileCompatibilityBuild = async (options) => {
|
|
32805
33222
|
const buildDirectory = resolve16(options.buildDirectory);
|
|
32806
33223
|
const mobile = normalizeAbsoluteMobileConfig(options.mobile, options.projectRoot);
|
|
32807
|
-
const root =
|
|
33224
|
+
const root = join22(buildDirectory, ".absolutejs", "mobile-compatibility");
|
|
32808
33225
|
const [manifestSource, previous] = await Promise.all([
|
|
32809
|
-
readFile18(
|
|
33226
|
+
readFile18(join22(buildDirectory, "manifest.json"), "utf8"),
|
|
32810
33227
|
readAbsoluteMobileMaterializedReleases(root)
|
|
32811
33228
|
]);
|
|
32812
33229
|
const manifest = JSON.parse(manifestSource);
|
|
@@ -33134,7 +33551,7 @@ var parseRequest = (value) => {
|
|
|
33134
33551
|
throw new TypeError("Expo bridge HTTP method cannot contain a body.");
|
|
33135
33552
|
if (!isRecord10(value.params.headers))
|
|
33136
33553
|
throw new TypeError("Expo bridge HTTP headers must be an object.");
|
|
33137
|
-
const headersAllowed = Object.entries(value.params.headers).every(([name,
|
|
33554
|
+
const headersAllowed = Object.entries(value.params.headers).every(([name, header2]) => typeof header2 === "string" && (name.toLowerCase() === "accept" || name.toLowerCase() === "content-type" || name.toLowerCase().startsWith("x-absolute-mobile-")));
|
|
33138
33555
|
if (!headersAllowed) {
|
|
33139
33556
|
throw new TypeError("Expo bridge HTTP header is not allowed.");
|
|
33140
33557
|
}
|
|
@@ -33235,7 +33652,7 @@ var parseAbsoluteExpoBridgeMessage = (source) => {
|
|
|
33235
33652
|
};
|
|
33236
33653
|
// src/mobile/expoCodeSigning.ts
|
|
33237
33654
|
var import_code_signing_certificates = __toESM(require_main(), 1);
|
|
33238
|
-
import { access as access14, mkdir as
|
|
33655
|
+
import { access as access14, mkdir as mkdir16, writeFile as writeFile15 } from "fs/promises";
|
|
33239
33656
|
import { dirname as dirname14, isAbsolute as isAbsolute8, relative as relative14, resolve as resolve17, sep as sep9 } from "path";
|
|
33240
33657
|
var exists7 = async (path) => access14(path).then(() => true).catch(() => false);
|
|
33241
33658
|
var inside3 = (root, path) => {
|
|
@@ -33276,7 +33693,7 @@ var generateAbsoluteExpoCodeSigning = async (options) => {
|
|
|
33276
33693
|
import_code_signing_certificates.validateSelfSignedCertificate(certificate, keyPair);
|
|
33277
33694
|
const { privateKeyPEM, publicKeyPEM } = import_code_signing_certificates.convertKeyPairToPEM(keyPair);
|
|
33278
33695
|
const certificatePem = import_code_signing_certificates.convertCertificateToCertificatePEM(certificate);
|
|
33279
|
-
await Promise.all([certificatePath, privateKeyPath, publicKeyPath].map((path) =>
|
|
33696
|
+
await Promise.all([certificatePath, privateKeyPath, publicKeyPath].map((path) => mkdir16(dirname14(path), { recursive: true })));
|
|
33280
33697
|
await Promise.all([
|
|
33281
33698
|
writeFile15(certificatePath, certificatePem, { flag: "wx", mode: 420 }),
|
|
33282
33699
|
writeFile15(privateKeyPath, privateKeyPEM, { flag: "wx", mode: 384 }),
|
|
@@ -33383,7 +33800,7 @@ var parseAbsoluteAndroidAccessibilityHierarchy = (source) => [...source.matchAll
|
|
|
33383
33800
|
// src/mobile/expoNativeWatcher.ts
|
|
33384
33801
|
import { watch as watch2 } from "fs";
|
|
33385
33802
|
import { access as access15, readdir as readdir6, readFile as readFile19 } from "fs/promises";
|
|
33386
|
-
import { basename as basename7, join as
|
|
33803
|
+
import { basename as basename7, join as join23, relative as relative15 } from "path";
|
|
33387
33804
|
import { createHash as createHash16 } from "crypto";
|
|
33388
33805
|
var NATIVE_CHANGE_DEBOUNCE_MS2 = 500;
|
|
33389
33806
|
var ROOT_NATIVE_INPUTS2 = new Set([
|
|
@@ -33404,7 +33821,7 @@ var filesIn = async (directory, prefix) => {
|
|
|
33404
33821
|
return [];
|
|
33405
33822
|
const entries = await readdir6(directory, { withFileTypes: true });
|
|
33406
33823
|
const nested = await Promise.all(entries.map((entry) => {
|
|
33407
|
-
const path =
|
|
33824
|
+
const path = join23(directory, entry.name);
|
|
33408
33825
|
const name = `${prefix}/${entry.name}`;
|
|
33409
33826
|
if (entry.isDirectory())
|
|
33410
33827
|
return filesIn(path, name);
|
|
@@ -33415,10 +33832,10 @@ var filesIn = async (directory, prefix) => {
|
|
|
33415
33832
|
var fingerprintAbsoluteExpoNativeInputs = async (options) => {
|
|
33416
33833
|
const hash = createHash16("sha256");
|
|
33417
33834
|
const rootFiles = await Promise.all([...ROOT_NATIVE_INPUTS2].sort().map(async (name) => {
|
|
33418
|
-
const path =
|
|
33835
|
+
const path = join23(options.projectRoot, name);
|
|
33419
33836
|
return await exists8(path) ? [{ name: `root/${name}`, path }] : [];
|
|
33420
33837
|
}));
|
|
33421
|
-
const nativeFiles = await Promise.all(EXPO_NATIVE_DIRECTORIES.map((name) => filesIn(
|
|
33838
|
+
const nativeFiles = await Promise.all(EXPO_NATIVE_DIRECTORIES.map((name) => filesIn(join23(options.expoProjectDirectory, name), name)));
|
|
33422
33839
|
const files = [...rootFiles.flat(), ...nativeFiles.flat()].sort((left, right) => left.name.localeCompare(right.name));
|
|
33423
33840
|
const contents = await Promise.all(files.map(({ path }) => readFile19(path)));
|
|
33424
33841
|
files.forEach(({ name }, index) => {
|
|
@@ -33489,14 +33906,14 @@ var createAbsoluteExpoNativeWatcher = async (options) => {
|
|
|
33489
33906
|
}
|
|
33490
33907
|
};
|
|
33491
33908
|
const nativeDirectories = (await Promise.all(EXPO_NATIVE_DIRECTORIES.map(async (name) => {
|
|
33492
|
-
const directory =
|
|
33909
|
+
const directory = join23(options.expoProjectDirectory, name);
|
|
33493
33910
|
return await exists8(directory) ? [directory] : [];
|
|
33494
33911
|
}))).flat();
|
|
33495
33912
|
nativeDirectories.forEach((directory) => {
|
|
33496
33913
|
watchers.push(watch2(directory, { recursive: true }, (_event, filename) => {
|
|
33497
33914
|
if (!filename)
|
|
33498
33915
|
return;
|
|
33499
|
-
record(relative15(options.expoProjectDirectory,
|
|
33916
|
+
record(relative15(options.expoProjectDirectory, join23(directory, String(filename))), false);
|
|
33500
33917
|
}));
|
|
33501
33918
|
});
|
|
33502
33919
|
watchers.push(watch2(options.projectRoot, (_event, filename) => {
|
|
@@ -33511,8 +33928,8 @@ var createAbsoluteExpoNativeWatcher = async (options) => {
|
|
|
33511
33928
|
return { close };
|
|
33512
33929
|
};
|
|
33513
33930
|
// src/mobile/expoUpdate.ts
|
|
33514
|
-
import { access as access16, mkdir as
|
|
33515
|
-
import { dirname as dirname15, extname as extname4, join as
|
|
33931
|
+
import { access as access16, mkdir as mkdir17, readFile as readFile20, writeFile as writeFile16 } from "fs/promises";
|
|
33932
|
+
import { dirname as dirname15, extname as extname4, join as join24 } from "path";
|
|
33516
33933
|
var ABSOLUTE_EXPO_UPDATE_DESCRIPTOR = "_absolute/expo-update.json";
|
|
33517
33934
|
var ABSOLUTE_EXPO_UPDATE_FORMAT = 1;
|
|
33518
33935
|
var object4 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
@@ -33578,7 +33995,7 @@ var parseAbsoluteExpoUpdateDescriptor = (value) => {
|
|
|
33578
33995
|
};
|
|
33579
33996
|
};
|
|
33580
33997
|
var finalizeAbsoluteExpoUpdateExport = async (options) => {
|
|
33581
|
-
const metadata = JSON.parse(await readFile20(
|
|
33998
|
+
const metadata = JSON.parse(await readFile20(join24(options.exportDirectory, "metadata.json"), "utf8"));
|
|
33582
33999
|
if (!object4(metadata) || !object4(metadata.fileMetadata))
|
|
33583
34000
|
throw new TypeError("Expo export metadata.json is invalid.");
|
|
33584
34001
|
const descriptor = parseAbsoluteExpoUpdateDescriptor({
|
|
@@ -33589,11 +34006,11 @@ var finalizeAbsoluteExpoUpdateExport = async (options) => {
|
|
|
33589
34006
|
runtimeVersion: options.runtimeVersion
|
|
33590
34007
|
});
|
|
33591
34008
|
const referenced = Object.values(descriptor.platforms).flatMap((entry) => entry ? [entry.launchAsset, ...entry.assets] : []);
|
|
33592
|
-
await Promise.all(referenced.map(({ path }) => access16(
|
|
34009
|
+
await Promise.all(referenced.map(({ path }) => access16(join24(options.exportDirectory, path)).catch(() => {
|
|
33593
34010
|
throw new TypeError(`Expo export metadata references missing asset ${path}.`);
|
|
33594
34011
|
})));
|
|
33595
|
-
const destination =
|
|
33596
|
-
await
|
|
34012
|
+
const destination = join24(options.exportDirectory, ABSOLUTE_EXPO_UPDATE_DESCRIPTOR);
|
|
34013
|
+
await mkdir17(dirname15(destination), { recursive: true });
|
|
33597
34014
|
await writeFile16(destination, `${JSON.stringify(descriptor, null, "\t")}
|
|
33598
34015
|
`);
|
|
33599
34016
|
return { descriptor, path: destination };
|
|
@@ -33605,7 +34022,7 @@ init_config();
|
|
|
33605
34022
|
// src/mobile/ciPromotionAudit.ts
|
|
33606
34023
|
import {
|
|
33607
34024
|
access as access19,
|
|
33608
|
-
mkdir as
|
|
34025
|
+
mkdir as mkdir20,
|
|
33609
34026
|
mkdtemp as mkdtemp11,
|
|
33610
34027
|
readFile as readFile23,
|
|
33611
34028
|
readdir as readdir7,
|
|
@@ -33614,10 +34031,10 @@ import {
|
|
|
33614
34031
|
stat as stat7,
|
|
33615
34032
|
writeFile as writeFile19
|
|
33616
34033
|
} from "fs/promises";
|
|
33617
|
-
import { dirname as dirname17, isAbsolute as isAbsolute11, join as
|
|
34034
|
+
import { dirname as dirname17, isAbsolute as isAbsolute11, join as join26, relative as relative18, resolve as resolve20, sep as sep12 } from "path";
|
|
33618
34035
|
|
|
33619
34036
|
// src/mobile/certificationVerification.ts
|
|
33620
|
-
import { access as access17, mkdir as
|
|
34037
|
+
import { access as access17, mkdir as mkdir18, readFile as readFile21, stat as stat6, writeFile as writeFile17 } from "fs/promises";
|
|
33621
34038
|
import { dirname as dirname16, isAbsolute as isAbsolute9, relative as relative16, resolve as resolve18, sep as sep10 } from "path";
|
|
33622
34039
|
var ABSOLUTE_MOBILE_CERTIFICATION_VERIFICATION_FORMAT = 1;
|
|
33623
34040
|
var MAX_VERIFICATION_BYTES = 1048576;
|
|
@@ -33710,7 +34127,7 @@ var readAbsoluteSigstoreBundle = async (projectRoot, requested) => {
|
|
|
33710
34127
|
var writeAbsoluteMobileCertificationVerification = async (projectRoot, requested, verification) => {
|
|
33711
34128
|
const path = projectFile(projectRoot, requested);
|
|
33712
34129
|
const parsed = parseAbsoluteMobileCertificationVerification(verification);
|
|
33713
|
-
await
|
|
34130
|
+
await mkdir18(dirname16(path), { recursive: true });
|
|
33714
34131
|
await writeFile17(path, `${JSON.stringify(parsed, null, 2)}
|
|
33715
34132
|
`, {
|
|
33716
34133
|
mode: 384
|
|
@@ -33722,14 +34139,14 @@ var writeAbsoluteMobileCertificationVerification = async (projectRoot, requested
|
|
|
33722
34139
|
import { createHash as createHash17 } from "crypto";
|
|
33723
34140
|
import {
|
|
33724
34141
|
access as access18,
|
|
33725
|
-
mkdir as
|
|
34142
|
+
mkdir as mkdir19,
|
|
33726
34143
|
mkdtemp as mkdtemp10,
|
|
33727
34144
|
readFile as readFile22,
|
|
33728
34145
|
rename as rename14,
|
|
33729
34146
|
rm as rm14,
|
|
33730
34147
|
writeFile as writeFile18
|
|
33731
34148
|
} from "fs/promises";
|
|
33732
|
-
import { basename as basename8, isAbsolute as isAbsolute10, join as
|
|
34149
|
+
import { basename as basename8, isAbsolute as isAbsolute10, join as join25, relative as relative17, resolve as resolve19, sep as sep11 } from "path";
|
|
33733
34150
|
var ABSOLUTE_MOBILE_RELEASE_CERTIFICATION_FORMAT = 1;
|
|
33734
34151
|
var CERTIFICATION_PREFIX = "amobile_cert_";
|
|
33735
34152
|
var SHA256 = /^[a-f0-9]{64}$/u;
|
|
@@ -33773,7 +34190,7 @@ var resolveEvidencePath = async (projectRoot, requested) => {
|
|
|
33773
34190
|
throw new TypeError("Mobile certification evidence must remain inside the project.");
|
|
33774
34191
|
if (basename8(selected) === "report.json")
|
|
33775
34192
|
return selected;
|
|
33776
|
-
const report =
|
|
34193
|
+
const report = join25(selected, "report.json");
|
|
33777
34194
|
if (!await exists9(report))
|
|
33778
34195
|
throw new TypeError(`Mobile certification evidence does not contain report.json: ${requested}`);
|
|
33779
34196
|
return report;
|
|
@@ -34038,7 +34455,7 @@ var readAbsoluteMobileReleaseCertification = async (projectRoot, requested) => {
|
|
|
34038
34455
|
const selected = resolve19(projectRoot, requested);
|
|
34039
34456
|
if (!inside4(projectRoot, selected))
|
|
34040
34457
|
throw new TypeError("Mobile release certification must remain inside the project.");
|
|
34041
|
-
const path = basename8(selected) === "certification.json" ? selected :
|
|
34458
|
+
const path = basename8(selected) === "certification.json" ? selected : join25(selected, "certification.json");
|
|
34042
34459
|
const value = JSON.parse(await readFile22(path, "utf8"));
|
|
34043
34460
|
return { certification: parseCertification(value), path };
|
|
34044
34461
|
};
|
|
@@ -34085,15 +34502,15 @@ var verifyAbsoluteMobileReleaseCertification = (certification, release, requirem
|
|
|
34085
34502
|
};
|
|
34086
34503
|
var writeAbsoluteMobileReleaseCertification = async (projectRoot, certification, outputDirectory) => {
|
|
34087
34504
|
const root = resolve19(projectRoot);
|
|
34088
|
-
const parent = resolve19(root, outputDirectory ??
|
|
34505
|
+
const parent = resolve19(root, outputDirectory ?? join25(".absolutejs", "mobile", "certifications", certification.release.platform, certification.release.releaseId));
|
|
34089
34506
|
if (!inside4(root, parent))
|
|
34090
34507
|
throw new TypeError("Mobile certification output must remain inside the project.");
|
|
34091
|
-
await
|
|
34092
|
-
const destination =
|
|
34508
|
+
await mkdir19(parent, { recursive: true });
|
|
34509
|
+
const destination = join25(parent, certification.certificationId);
|
|
34093
34510
|
const paths = {
|
|
34094
34511
|
directory: destination,
|
|
34095
|
-
jsonPath:
|
|
34096
|
-
markdownPath:
|
|
34512
|
+
jsonPath: join25(destination, "certification.json"),
|
|
34513
|
+
markdownPath: join25(destination, "certification.md")
|
|
34097
34514
|
};
|
|
34098
34515
|
const json = serializeAbsoluteMobileReleaseCertification(certification);
|
|
34099
34516
|
const markdown = renderAbsoluteMobileReleaseCertification(certification);
|
|
@@ -34109,13 +34526,13 @@ var writeAbsoluteMobileReleaseCertification = async (projectRoot, certification,
|
|
|
34109
34526
|
await verifyExisting();
|
|
34110
34527
|
return paths;
|
|
34111
34528
|
}
|
|
34112
|
-
const staging = await mkdtemp10(
|
|
34529
|
+
const staging = await mkdtemp10(join25(parent, ".certification-"));
|
|
34113
34530
|
try {
|
|
34114
34531
|
await Promise.all([
|
|
34115
|
-
writeFile18(
|
|
34532
|
+
writeFile18(join25(staging, "certification.json"), json, {
|
|
34116
34533
|
flag: "wx"
|
|
34117
34534
|
}),
|
|
34118
|
-
writeFile18(
|
|
34535
|
+
writeFile18(join25(staging, "certification.md"), markdown, {
|
|
34119
34536
|
flag: "wx"
|
|
34120
34537
|
})
|
|
34121
34538
|
]);
|
|
@@ -34347,7 +34764,7 @@ var findFiles = async (root, name) => {
|
|
|
34347
34764
|
visited += 1;
|
|
34348
34765
|
if (visited > MAX_SEARCH_FILES)
|
|
34349
34766
|
throw new TypeError("Downloaded GitHub artifact contains too many files.");
|
|
34350
|
-
const path =
|
|
34767
|
+
const path = join26(directory, entry.name);
|
|
34351
34768
|
if (entry.isDirectory()) {
|
|
34352
34769
|
await walk(path);
|
|
34353
34770
|
return;
|
|
@@ -34461,11 +34878,11 @@ var auditAbsoluteMobileCiPromotion = async (options) => {
|
|
|
34461
34878
|
const output = projectPath(options.projectRoot, options.outputDirectory ?? `.absolutejs/mobile-ci/audits/${promotionRunId}`);
|
|
34462
34879
|
if (await access19(output).then(() => true).catch(() => false))
|
|
34463
34880
|
throw new TypeError(`Mobile CI audit output already exists: ${output}`);
|
|
34464
|
-
await
|
|
34465
|
-
const staging = await mkdtemp11(
|
|
34881
|
+
await mkdir20(dirname17(output), { recursive: true });
|
|
34882
|
+
const staging = await mkdtemp11(join26(dirname17(output), ".promotion-audit-"));
|
|
34466
34883
|
try {
|
|
34467
|
-
const evidenceRoot =
|
|
34468
|
-
await
|
|
34884
|
+
const evidenceRoot = join26(staging, "promotion-evidence");
|
|
34885
|
+
await mkdir20(evidenceRoot);
|
|
34469
34886
|
await requireCommand(runner, [
|
|
34470
34887
|
"gh",
|
|
34471
34888
|
"run",
|
|
@@ -34495,8 +34912,8 @@ var auditAbsoluteMobileCiPromotion = async (options) => {
|
|
|
34495
34912
|
if (context && options.sourceRunId && context.sourceRunId !== sourceRunId)
|
|
34496
34913
|
throw new TypeError("Requested source run does not match promotion context.");
|
|
34497
34914
|
const sourceArtifact = context?.sourceArtifact ?? `absolute-mobile-${platform3}`;
|
|
34498
|
-
const sourceRoot =
|
|
34499
|
-
await
|
|
34915
|
+
const sourceRoot = join26(staging, "source-release");
|
|
34916
|
+
await mkdir20(sourceRoot);
|
|
34500
34917
|
await requireCommand(runner, [
|
|
34501
34918
|
"gh",
|
|
34502
34919
|
"run",
|
|
@@ -34579,9 +34996,9 @@ var auditAbsoluteMobileCiPromotion = async (options) => {
|
|
|
34579
34996
|
verifiedAt: new Date().toISOString()
|
|
34580
34997
|
};
|
|
34581
34998
|
await Promise.all([
|
|
34582
|
-
writeFile19(
|
|
34999
|
+
writeFile19(join26(staging, "audit.json"), `${JSON.stringify(audit, null, 2)}
|
|
34583
35000
|
`, { mode: 384 }),
|
|
34584
|
-
writeFile19(
|
|
35001
|
+
writeFile19(join26(staging, "audit.md"), renderAuditMarkdown(audit), {
|
|
34585
35002
|
mode: 384
|
|
34586
35003
|
})
|
|
34587
35004
|
]);
|
|
@@ -34597,14 +35014,14 @@ import {
|
|
|
34597
35014
|
access as access20,
|
|
34598
35015
|
link,
|
|
34599
35016
|
lstat as lstat2,
|
|
34600
|
-
mkdir as
|
|
35017
|
+
mkdir as mkdir21,
|
|
34601
35018
|
open,
|
|
34602
35019
|
readFile as readFile24,
|
|
34603
35020
|
readdir as readdir8,
|
|
34604
35021
|
rename as rename16,
|
|
34605
35022
|
rm as rm16
|
|
34606
35023
|
} from "fs/promises";
|
|
34607
|
-
import { dirname as dirname18, isAbsolute as isAbsolute12, join as
|
|
35024
|
+
import { dirname as dirname18, isAbsolute as isAbsolute12, join as join27, relative as relative19, resolve as resolve21, sep as sep13 } from "path";
|
|
34608
35025
|
import { randomUUID as randomUUID5 } from "crypto";
|
|
34609
35026
|
var ABSOLUTE_MOBILE_CI_PROMOTION_OPERATION_FORMAT = 1;
|
|
34610
35027
|
var MAX_OPERATION_BYTES = 65536;
|
|
@@ -34670,8 +35087,8 @@ var runId2 = (value, label) => {
|
|
|
34670
35087
|
return parsed;
|
|
34671
35088
|
};
|
|
34672
35089
|
var nullableRunId = (value, label) => value === null ? null : runId2(value, label);
|
|
34673
|
-
var operationRoot = (projectRoot) =>
|
|
34674
|
-
var absoluteMobilePromotionOperationPath = (projectRoot, requestedDispatchId) =>
|
|
35090
|
+
var operationRoot = (projectRoot) => join27(resolve21(projectRoot), ".absolutejs", "mobile-ci", "promotions");
|
|
35091
|
+
var absoluteMobilePromotionOperationPath = (projectRoot, requestedDispatchId) => join27(operationRoot(projectRoot), dispatchId2(requestedDispatchId), "operation.json");
|
|
34675
35092
|
var operationPhase = (value) => {
|
|
34676
35093
|
const phase = PHASES.find((candidate) => candidate === value);
|
|
34677
35094
|
if (!phase)
|
|
@@ -34741,8 +35158,8 @@ var writeSynced = async (path, source) => {
|
|
|
34741
35158
|
}
|
|
34742
35159
|
};
|
|
34743
35160
|
var atomicWrite = async (path, source, exclusive) => {
|
|
34744
|
-
await
|
|
34745
|
-
const temporary =
|
|
35161
|
+
await mkdir21(dirname18(path), { recursive: true });
|
|
35162
|
+
const temporary = join27(dirname18(path), `.operation-${randomUUID5()}.tmp`);
|
|
34746
35163
|
try {
|
|
34747
35164
|
await writeSynced(temporary, source);
|
|
34748
35165
|
if (exclusive)
|
|
@@ -34812,7 +35229,7 @@ var readAbsoluteMobilePromotionOperation = async (projectRoot, requestedDispatch
|
|
|
34812
35229
|
var relativeAbsoluteMobilePromotionOperationPath = (projectRoot, dispatchIdValue) => relative19(resolve21(projectRoot), absoluteMobilePromotionOperationPath(projectRoot, dispatchIdValue)).replaceAll("\\", "/");
|
|
34813
35230
|
// src/mobile/ciWorkflow.ts
|
|
34814
35231
|
import { existsSync as existsSync4 } from "fs";
|
|
34815
|
-
import { access as access21, mkdir as
|
|
35232
|
+
import { access as access21, mkdir as mkdir22, readFile as readFile25, writeFile as writeFile20 } from "fs/promises";
|
|
34816
35233
|
import { dirname as dirname19, extname as extname5, relative as relative20, resolve as resolve22, sep as sep14 } from "path";
|
|
34817
35234
|
var ABSOLUTE_MOBILE_CI_WORKFLOW_FORMAT = 4;
|
|
34818
35235
|
var SECRET_NAME_PATTERN = /^[A-Z][A-Z0-9_]*$/u;
|
|
@@ -35624,7 +36041,7 @@ var writeAbsoluteMobileGithubWorkflow = async (options) => {
|
|
|
35624
36041
|
if (previous !== undefined && previous !== generated.workflow && !options.force)
|
|
35625
36042
|
throw new TypeError(`${relative20(options.projectRoot, path)} already exists and differs. Rerun with --force to replace the generated workflow.`);
|
|
35626
36043
|
if (previous !== generated.workflow) {
|
|
35627
|
-
await
|
|
36044
|
+
await mkdir22(dirname19(path), { recursive: true });
|
|
35628
36045
|
await writeFile20(path, generated.workflow);
|
|
35629
36046
|
}
|
|
35630
36047
|
return {
|
|
@@ -35644,7 +36061,7 @@ init_mobilePreview();
|
|
|
35644
36061
|
|
|
35645
36062
|
// src/mobile/nativeDeepLinks.ts
|
|
35646
36063
|
import { readFile as readFile26, rename as rename17, writeFile as writeFile21 } from "fs/promises";
|
|
35647
|
-
import { join as
|
|
36064
|
+
import { join as join30 } from "path";
|
|
35648
36065
|
var START_MARKER = "<!-- absolutejs:deep-links:start -->";
|
|
35649
36066
|
var END_MARKER = "<!-- absolutejs:deep-links:end -->";
|
|
35650
36067
|
var IOS_ENTITLEMENTS = "App/AbsoluteJS.entitlements";
|
|
@@ -35701,7 +36118,7 @@ ${hosts}
|
|
|
35701
36118
|
`;
|
|
35702
36119
|
};
|
|
35703
36120
|
var configureAndroid = async (config) => {
|
|
35704
|
-
const path =
|
|
36121
|
+
const path = join30(config.nativeProjectDirectory, "android/app/src/main/AndroidManifest.xml");
|
|
35705
36122
|
const source = await readFile26(path, "utf8");
|
|
35706
36123
|
const mainActivity = source.indexOf('android:name=".MainActivity"');
|
|
35707
36124
|
if (mainActivity === NOT_FOUND) {
|
|
@@ -35727,7 +36144,7 @@ var iosSchemeRegion = (scheme) => ` ${START_MARKER}
|
|
|
35727
36144
|
${END_MARKER}
|
|
35728
36145
|
`;
|
|
35729
36146
|
var configureIosInfo = async (config) => {
|
|
35730
|
-
const path =
|
|
36147
|
+
const path = join30(config.nativeProjectDirectory, "ios/App/App/Info.plist");
|
|
35731
36148
|
const source = await readFile26(path, "utf8");
|
|
35732
36149
|
const region = config.deepLinkScheme ? iosSchemeRegion(config.deepLinkScheme) : ` ${START_MARKER}
|
|
35733
36150
|
${END_MARKER}
|
|
@@ -35751,7 +36168,7 @@ ${domains}
|
|
|
35751
36168
|
`;
|
|
35752
36169
|
};
|
|
35753
36170
|
var configureIosEntitlements = async (config) => {
|
|
35754
|
-
const path =
|
|
36171
|
+
const path = join30(config.nativeProjectDirectory, "ios/App/AbsoluteJS.entitlements");
|
|
35755
36172
|
let current = "";
|
|
35756
36173
|
try {
|
|
35757
36174
|
current = await readFile26(path, "utf8");
|
|
@@ -35769,7 +36186,7 @@ var configureIosEntitlements = async (config) => {
|
|
|
35769
36186
|
return true;
|
|
35770
36187
|
};
|
|
35771
36188
|
var configureIosProject = async (config) => {
|
|
35772
|
-
const path =
|
|
36189
|
+
const path = join30(config.nativeProjectDirectory, "ios/App/App.xcodeproj/project.pbxproj");
|
|
35773
36190
|
const source = await readFile26(path, "utf8");
|
|
35774
36191
|
const declarations = [
|
|
35775
36192
|
...source.matchAll(/CODE_SIGN_ENTITLEMENTS = ([^;]+);/g)
|
|
@@ -35810,7 +36227,7 @@ var applyAbsoluteNativeDeepLinks = async (config, platforms = config.platforms)
|
|
|
35810
36227
|
// src/mobile/nativeDeviceCapabilities.ts
|
|
35811
36228
|
init_deviceCapabilities();
|
|
35812
36229
|
import { readFile as readFile27, rename as rename18, writeFile as writeFile22 } from "fs/promises";
|
|
35813
|
-
import { join as
|
|
36230
|
+
import { join as join31 } from "path";
|
|
35814
36231
|
var START_MARKER2 = "<!-- absolutejs:device-capabilities:start -->";
|
|
35815
36232
|
var END_MARKER2 = "<!-- absolutejs:device-capabilities:end -->";
|
|
35816
36233
|
var NOT_FOUND2 = -1;
|
|
@@ -35960,7 +36377,7 @@ var writeIosPrivacyManifest = async (path, current, source) => {
|
|
|
35960
36377
|
var configureIosPrivacyProject = async (config, requirements) => {
|
|
35961
36378
|
if (requirements.iosPrivacyAccessedApis.length === 0)
|
|
35962
36379
|
return false;
|
|
35963
|
-
const projectPath3 =
|
|
36380
|
+
const projectPath3 = join31(config.nativeProjectDirectory, "ios/App/App.xcodeproj/project.pbxproj");
|
|
35964
36381
|
const project = await readFile27(projectPath3, "utf8");
|
|
35965
36382
|
return writeChangedFile2(projectPath3, addIosPrivacyProjectReference(project));
|
|
35966
36383
|
};
|
|
@@ -36013,7 +36430,7 @@ ${next.slice(index)}`;
|
|
|
36013
36430
|
return next;
|
|
36014
36431
|
};
|
|
36015
36432
|
var configureIos2 = async (config, plan) => {
|
|
36016
|
-
const path =
|
|
36433
|
+
const path = join31(config.nativeProjectDirectory, "ios/App/App/Info.plist");
|
|
36017
36434
|
const source = await readFile27(path, "utf8");
|
|
36018
36435
|
const requirements = absoluteDeviceNativeRequirements(plan);
|
|
36019
36436
|
const existingSystemBars = source.match(/<key>UIViewControllerBasedStatusBarAppearance<\/key>\s*<(true|false)\s*\/>/u);
|
|
@@ -36034,7 +36451,7 @@ ${content}
|
|
|
36034
36451
|
${END_MARKER2}
|
|
36035
36452
|
` : "";
|
|
36036
36453
|
const infoChanged = await writeChangedFile2(path, managed(source, region, source.lastIndexOf("</dict>")));
|
|
36037
|
-
const privacyPath =
|
|
36454
|
+
const privacyPath = join31(config.nativeProjectDirectory, "ios/App/App/PrivacyInfo.xcprivacy");
|
|
36038
36455
|
const privacyCurrent = await optionalSource(privacyPath);
|
|
36039
36456
|
const privacySource = privacyManifestSource(privacyCurrent, requirements);
|
|
36040
36457
|
const [privacyChanged, projectChanged, pushChanged] = await Promise.all([
|
|
@@ -36045,7 +36462,7 @@ ${content}
|
|
|
36045
36462
|
return infoChanged || privacyChanged || projectChanged || pushChanged;
|
|
36046
36463
|
};
|
|
36047
36464
|
var configureIosPushNotifications = async (config, enabled) => {
|
|
36048
|
-
const entitlementsPath =
|
|
36465
|
+
const entitlementsPath = join31(config.nativeProjectDirectory, "ios/App/AbsoluteJS.entitlements");
|
|
36049
36466
|
const entitlements = await optionalSource(entitlementsPath);
|
|
36050
36467
|
if (entitlements === null && !enabled)
|
|
36051
36468
|
return false;
|
|
@@ -36057,7 +36474,7 @@ var configureIosPushNotifications = async (config, enabled) => {
|
|
|
36057
36474
|
<!-- ${PUSH_END_MARKER} -->
|
|
36058
36475
|
` : "";
|
|
36059
36476
|
const nextEntitlements = replacePushRegion(entitlements, entitlementRegion, entitlements.lastIndexOf("</dict>"));
|
|
36060
|
-
const delegatePath =
|
|
36477
|
+
const delegatePath = join31(config.nativeProjectDirectory, "ios/App/App/AppDelegate.swift");
|
|
36061
36478
|
const delegate = await optionalSource(delegatePath);
|
|
36062
36479
|
if (delegate === null && !enabled)
|
|
36063
36480
|
return false;
|
|
@@ -36106,7 +36523,7 @@ var replacePushRegion = (source, region, insertion) => {
|
|
|
36106
36523
|
return `${source.slice(0, insertion)}${region}${source.slice(insertion)}`;
|
|
36107
36524
|
};
|
|
36108
36525
|
var configureAndroid2 = async (config, plan) => {
|
|
36109
|
-
const path =
|
|
36526
|
+
const path = join31(config.nativeProjectDirectory, "android/app/src/main/AndroidManifest.xml");
|
|
36110
36527
|
const source = await readFile27(path, "utf8");
|
|
36111
36528
|
const permissions = absoluteDeviceNativeRequirements(plan).androidPermissions;
|
|
36112
36529
|
const content = permissions.map((permission) => ` <uses-permission android:name="${escapeXml2(permission)}" />`).join(`
|
|
@@ -36135,14 +36552,14 @@ ${content}
|
|
|
36135
36552
|
const clients = typeof firebase === "object" && firebase !== null ? Reflect.get(firebase, "client") : undefined;
|
|
36136
36553
|
const matchesApp = Array.isArray(clients) && clients.some((client) => {
|
|
36137
36554
|
const info = typeof client === "object" && client !== null ? Reflect.get(client, "client_info") : undefined;
|
|
36138
|
-
const
|
|
36139
|
-
return typeof
|
|
36555
|
+
const android2 = typeof info === "object" && info !== null ? Reflect.get(info, "android_client_info") : undefined;
|
|
36556
|
+
return typeof android2 === "object" && android2 !== null && Reflect.get(android2, "package_name") === config.appId;
|
|
36140
36557
|
});
|
|
36141
36558
|
if (!matchesApp)
|
|
36142
36559
|
throw new TypeError(`Android google-services.json does not contain package ${config.appId}.`);
|
|
36143
36560
|
const [manifestChanged, firebaseChanged] = await Promise.all([
|
|
36144
36561
|
writeChangedFile2(path, nextManifest),
|
|
36145
|
-
writeOptionalChangedFile(
|
|
36562
|
+
writeOptionalChangedFile(join31(config.nativeProjectDirectory, "android/app/google-services.json"), firebaseSource)
|
|
36146
36563
|
]);
|
|
36147
36564
|
return manifestChanged || firebaseChanged;
|
|
36148
36565
|
};
|
|
@@ -36161,14 +36578,14 @@ init_nativeAuth();
|
|
|
36161
36578
|
|
|
36162
36579
|
// src/mobile/nativeUpdates.ts
|
|
36163
36580
|
import {
|
|
36164
|
-
mkdir as
|
|
36581
|
+
mkdir as mkdir23,
|
|
36165
36582
|
readFile as readFile28,
|
|
36166
36583
|
readdir as readdir9,
|
|
36167
36584
|
rename as rename19,
|
|
36168
36585
|
rm as rm17,
|
|
36169
36586
|
writeFile as writeFile23
|
|
36170
36587
|
} from "fs/promises";
|
|
36171
|
-
import { dirname as dirname21, join as
|
|
36588
|
+
import { dirname as dirname21, join as join32 } from "path";
|
|
36172
36589
|
var START = "// absolutejs:mobile-updates:start";
|
|
36173
36590
|
var END = "// absolutejs:mobile-updates:end";
|
|
36174
36591
|
var PLUGIN_START = "// absolutejs:mobile-update-plugin:start";
|
|
@@ -36188,7 +36605,7 @@ var writeChanged = async (path, source) => {
|
|
|
36188
36605
|
const current = await optionalSource2(path);
|
|
36189
36606
|
if (current === source)
|
|
36190
36607
|
return false;
|
|
36191
|
-
await
|
|
36608
|
+
await mkdir23(dirname21(path), { recursive: true });
|
|
36192
36609
|
if (current === null) {
|
|
36193
36610
|
await writeFile23(path, source, { flag: "wx" });
|
|
36194
36611
|
return true;
|
|
@@ -36338,8 +36755,8 @@ public final class AbsoluteMobileUpdateWatchdogPlugin: CAPPlugin, CAPBridgedPlug
|
|
|
36338
36755
|
${PLUGIN_END}
|
|
36339
36756
|
`;
|
|
36340
36757
|
var configureIos3 = async (config, enabled) => {
|
|
36341
|
-
const path =
|
|
36342
|
-
const capacitorConfigPath =
|
|
36758
|
+
const path = join32(config.nativeProjectDirectory, "ios/App/App/AppDelegate.swift");
|
|
36759
|
+
const capacitorConfigPath = join32(config.nativeProjectDirectory, "ios/App/App/capacitor.config.json");
|
|
36343
36760
|
let source = await readFile28(path, "utf8");
|
|
36344
36761
|
const launch2 = source.indexOf("didFinishLaunchingWithOptions");
|
|
36345
36762
|
const brace = launch2 < 0 ? -1 : source.indexOf("{", launch2);
|
|
@@ -36349,8 +36766,8 @@ var configureIos3 = async (config, enabled) => {
|
|
|
36349
36766
|
` : "";
|
|
36350
36767
|
source = replaceMarkedRegion(source, START, END, launchRegion, brace < 0 ? -1 : source.indexOf(`
|
|
36351
36768
|
`, brace) + 1, "Could not find a safe iOS location for mobile update recovery.");
|
|
36352
|
-
const
|
|
36353
|
-
source = replaceMarkedRegion(source, PLUGIN_START, PLUGIN_END,
|
|
36769
|
+
const plugin2 = enabled ? iosPluginRegion(config.updates?.bootTimeoutMs ?? 20000) : "";
|
|
36770
|
+
source = replaceMarkedRegion(source, PLUGIN_START, PLUGIN_END, plugin2, source.length, "Could not find a safe iOS location for the mobile update watchdog.");
|
|
36354
36771
|
const capacitorConfigSource2 = await readFile28(capacitorConfigPath, "utf8");
|
|
36355
36772
|
let capacitorConfig;
|
|
36356
36773
|
try {
|
|
@@ -36531,12 +36948,12 @@ var androidActivityInRoot = async (root) => {
|
|
|
36531
36948
|
throw error;
|
|
36532
36949
|
}
|
|
36533
36950
|
const candidate = entries.find((entry) => entry.endsWith("/MainActivity.java") || entry.endsWith("/MainActivity.kt") || entry === "MainActivity.java" || entry === "MainActivity.kt");
|
|
36534
|
-
return candidate ?
|
|
36951
|
+
return candidate ? join32(root, candidate) : undefined;
|
|
36535
36952
|
};
|
|
36536
36953
|
var androidActivity = async (config) => {
|
|
36537
36954
|
const roots = [
|
|
36538
|
-
|
|
36539
|
-
|
|
36955
|
+
join32(config.nativeProjectDirectory, "android/app/src/main/java"),
|
|
36956
|
+
join32(config.nativeProjectDirectory, "android/app/src/main/kotlin")
|
|
36540
36957
|
];
|
|
36541
36958
|
const candidates = await Promise.all(roots.map(androidActivityInRoot));
|
|
36542
36959
|
const candidate = candidates.find((value) => value !== undefined);
|
|
@@ -36640,7 +37057,7 @@ var configureAndroid3 = async (config, enabled) => {
|
|
|
36640
37057
|
if (!packageName)
|
|
36641
37058
|
throw new TypeError("Android MainActivity package declaration was not found.");
|
|
36642
37059
|
const packagePath = packageName.replaceAll(".", "/");
|
|
36643
|
-
const pluginPath =
|
|
37060
|
+
const pluginPath = join32(config.nativeProjectDirectory, "android/app/src/main/java", packagePath, ANDROID_PLUGIN);
|
|
36644
37061
|
const changed = await Promise.all([
|
|
36645
37062
|
writeChanged(activityPath, injectAndroidActivity(activity, enabled)),
|
|
36646
37063
|
enabled ? writeChanged(pluginPath, androidPluginSource(packageName, config.updates?.bootTimeoutMs ?? 20000)) : removeOwnedFile(pluginPath)
|
|
@@ -36660,14 +37077,14 @@ var applyAbsoluteNativeUpdates = async (config, platforms = config.platforms) =>
|
|
|
36660
37077
|
};
|
|
36661
37078
|
// src/mobile/nativeObservability.ts
|
|
36662
37079
|
import {
|
|
36663
|
-
mkdir as
|
|
37080
|
+
mkdir as mkdir24,
|
|
36664
37081
|
readFile as readFile29,
|
|
36665
37082
|
readdir as readdir10,
|
|
36666
37083
|
rename as rename20,
|
|
36667
37084
|
rm as rm18,
|
|
36668
37085
|
writeFile as writeFile24
|
|
36669
37086
|
} from "fs/promises";
|
|
36670
|
-
import { dirname as dirname22, join as
|
|
37087
|
+
import { dirname as dirname22, join as join33 } from "path";
|
|
36671
37088
|
var START2 = "// absolutejs:native-observability:start";
|
|
36672
37089
|
var END2 = "// absolutejs:native-observability:end";
|
|
36673
37090
|
var PLUGIN_START2 = "// absolutejs:native-observability-plugin:start";
|
|
@@ -36686,7 +37103,7 @@ var writeChanged2 = async (path, source) => {
|
|
|
36686
37103
|
const current = await optionalSource3(path);
|
|
36687
37104
|
if (current === source)
|
|
36688
37105
|
return false;
|
|
36689
|
-
await
|
|
37106
|
+
await mkdir24(dirname22(path), { recursive: true });
|
|
36690
37107
|
if (current === null) {
|
|
36691
37108
|
await writeFile24(path, source, { flag: "wx" });
|
|
36692
37109
|
return true;
|
|
@@ -36835,8 +37252,8 @@ public final class AbsoluteMobileObservabilityPlugin: CAPPlugin, CAPBridgedPlugi
|
|
|
36835
37252
|
${PLUGIN_END2}
|
|
36836
37253
|
`;
|
|
36837
37254
|
var configureIos4 = async (config, enabled) => {
|
|
36838
|
-
const path =
|
|
36839
|
-
const capacitorConfigPath =
|
|
37255
|
+
const path = join33(config.nativeProjectDirectory, "ios/App/App/AppDelegate.swift");
|
|
37256
|
+
const capacitorConfigPath = join33(config.nativeProjectDirectory, "ios/App/App/capacitor.config.json");
|
|
36840
37257
|
let source = await readFile29(path, "utf8");
|
|
36841
37258
|
if (enabled && !source.includes("import MetricKit")) {
|
|
36842
37259
|
const capacitorImport = source.lastIndexOf("import Capacitor");
|
|
@@ -37096,12 +37513,12 @@ var androidActivityInRoot2 = async (root) => {
|
|
|
37096
37513
|
throw error;
|
|
37097
37514
|
}
|
|
37098
37515
|
const candidate = entries.find((entry) => entry.endsWith("/MainActivity.java") || entry.endsWith("/MainActivity.kt") || entry === "MainActivity.java" || entry === "MainActivity.kt");
|
|
37099
|
-
return candidate ?
|
|
37516
|
+
return candidate ? join33(root, candidate) : undefined;
|
|
37100
37517
|
};
|
|
37101
37518
|
var androidActivity2 = async (config) => {
|
|
37102
37519
|
const roots = [
|
|
37103
|
-
|
|
37104
|
-
|
|
37520
|
+
join33(config.nativeProjectDirectory, "android/app/src/main/java"),
|
|
37521
|
+
join33(config.nativeProjectDirectory, "android/app/src/main/kotlin")
|
|
37105
37522
|
];
|
|
37106
37523
|
const candidates = await Promise.all(roots.map(androidActivityInRoot2));
|
|
37107
37524
|
const candidate = candidates.find((value) => value !== undefined);
|
|
@@ -37173,7 +37590,7 @@ var configureAndroid4 = async (config, enabled) => {
|
|
|
37173
37590
|
const packageName = activity.match(/^\s*package\s+([A-Za-z0-9_.]+)\s*[;\n]/mu)?.[1];
|
|
37174
37591
|
if (!packageName)
|
|
37175
37592
|
throw new TypeError("Android MainActivity package declaration was not found.");
|
|
37176
|
-
const pluginPath =
|
|
37593
|
+
const pluginPath = join33(config.nativeProjectDirectory, "android/app/src/main/java", packageName.replaceAll(".", "/"), ANDROID_PLUGIN2);
|
|
37177
37594
|
const changed = await Promise.all([
|
|
37178
37595
|
writeChanged2(activityPath, injectAndroidActivity2(activity, enabled)),
|
|
37179
37596
|
enabled ? writeChanged2(pluginPath, androidPluginSource2(packageName)) : removeOwnedFile2(pluginPath)
|
|
@@ -37192,8 +37609,8 @@ var applyAbsoluteNativeObservability = async (config, platforms = config.platfor
|
|
|
37192
37609
|
return { changed: changed.some(Boolean) };
|
|
37193
37610
|
};
|
|
37194
37611
|
// src/mobile/nativeReleaseReadiness.ts
|
|
37195
|
-
import { mkdir as
|
|
37196
|
-
import { dirname as dirname23, join as
|
|
37612
|
+
import { mkdir as mkdir25, readFile as readFile30, readdir as readdir11, rename as rename21, writeFile as writeFile25 } from "fs/promises";
|
|
37613
|
+
import { dirname as dirname23, join as join34 } from "path";
|
|
37197
37614
|
var START3 = "// absolutejs:release-readiness:start";
|
|
37198
37615
|
var END3 = "// absolutejs:release-readiness:end";
|
|
37199
37616
|
var IOS_PLUGIN_START = "// absolutejs:release-readiness-plugin:start";
|
|
@@ -37212,7 +37629,7 @@ var writeChanged3 = async (path, source) => {
|
|
|
37212
37629
|
const current = await optionalSource4(path);
|
|
37213
37630
|
if (current === source)
|
|
37214
37631
|
return false;
|
|
37215
|
-
await
|
|
37632
|
+
await mkdir25(dirname23(path), { recursive: true });
|
|
37216
37633
|
if (current === null) {
|
|
37217
37634
|
await writeFile25(path, source, { flag: "wx" });
|
|
37218
37635
|
return true;
|
|
@@ -37232,12 +37649,12 @@ var activityInRoot = async (root) => {
|
|
|
37232
37649
|
throw error;
|
|
37233
37650
|
}
|
|
37234
37651
|
const candidate = entries.find((entry) => entry.endsWith("/MainActivity.java") || entry.endsWith("/MainActivity.kt") || entry === "MainActivity.java" || entry === "MainActivity.kt");
|
|
37235
|
-
return candidate ?
|
|
37652
|
+
return candidate ? join34(root, candidate) : undefined;
|
|
37236
37653
|
};
|
|
37237
37654
|
var activityPath = async (config) => {
|
|
37238
37655
|
const roots = [
|
|
37239
|
-
|
|
37240
|
-
|
|
37656
|
+
join34(config.nativeProjectDirectory, "android/app/src/main/java"),
|
|
37657
|
+
join34(config.nativeProjectDirectory, "android/app/src/main/kotlin")
|
|
37241
37658
|
];
|
|
37242
37659
|
const candidates = await Promise.all(roots.map(activityInRoot));
|
|
37243
37660
|
const candidate = candidates.find((value) => value !== undefined);
|
|
@@ -37347,8 +37764,8 @@ var replaceIosPluginRegion = (appDelegate, existingStart, existingEnd) => {
|
|
|
37347
37764
|
return `${appDelegate.slice(0, from)}${iosPluginRegion3}${appDelegate.slice(through)}`;
|
|
37348
37765
|
};
|
|
37349
37766
|
var configureIos5 = async (config) => {
|
|
37350
|
-
const appDelegatePath =
|
|
37351
|
-
const capacitorConfigPath =
|
|
37767
|
+
const appDelegatePath = join34(config.nativeProjectDirectory, "ios/App/App/AppDelegate.swift");
|
|
37768
|
+
const capacitorConfigPath = join34(config.nativeProjectDirectory, "ios/App/App/capacitor.config.json");
|
|
37352
37769
|
const appDelegate = await readFile30(appDelegatePath, "utf8");
|
|
37353
37770
|
const existingStart = appDelegate.indexOf(IOS_PLUGIN_START);
|
|
37354
37771
|
const existingEnd = appDelegate.indexOf(IOS_PLUGIN_END);
|
|
@@ -37388,7 +37805,7 @@ var configureAndroid5 = async (config) => {
|
|
|
37388
37805
|
const packageName = activity.match(/^\s*package\s+([A-Za-z0-9_.]+)\s*[;\n]/mu)?.[1];
|
|
37389
37806
|
if (!packageName)
|
|
37390
37807
|
throw new TypeError("Android MainActivity package declaration was not found.");
|
|
37391
|
-
const pluginPath =
|
|
37808
|
+
const pluginPath = join34(config.nativeProjectDirectory, "android/app/src/main/java", packageName.replaceAll(".", "/"), ANDROID_PLUGIN3);
|
|
37392
37809
|
const changed = await Promise.all([
|
|
37393
37810
|
writeChanged3(mainActivityPath, injectRegistration(activity)),
|
|
37394
37811
|
writeChanged3(pluginPath, pluginSource(packageName))
|
|
@@ -38129,11 +38546,11 @@ var resolveAbsoluteHttpUrl = (target, origin) => {
|
|
|
38129
38546
|
var createAbsoluteHttpTransport = ({
|
|
38130
38547
|
fetch: fetchImpl = globalThis.fetch,
|
|
38131
38548
|
origin,
|
|
38132
|
-
runtime:
|
|
38549
|
+
runtime: runtime3
|
|
38133
38550
|
}) => ({
|
|
38134
38551
|
fetch: fetchImpl,
|
|
38135
38552
|
origin: normalizeAbsoluteHttpOrigin(origin),
|
|
38136
|
-
runtime:
|
|
38553
|
+
runtime: runtime3
|
|
38137
38554
|
});
|
|
38138
38555
|
var createWebHttpTransport = (options = {}) => {
|
|
38139
38556
|
const origin = options.origin ?? globalThis.location?.origin;
|
|
@@ -38316,8 +38733,8 @@ var createCapacitor = (win) => {
|
|
|
38316
38733
|
};
|
|
38317
38734
|
const isNativePlatform = () => getPlatform() !== "web";
|
|
38318
38735
|
const isPluginAvailable = (pluginName) => {
|
|
38319
|
-
const
|
|
38320
|
-
if (
|
|
38736
|
+
const plugin2 = registeredPlugins.get(pluginName);
|
|
38737
|
+
if (plugin2 === null || plugin2 === undefined ? undefined : plugin2.platforms.has(getPlatform())) {
|
|
38321
38738
|
return true;
|
|
38322
38739
|
}
|
|
38323
38740
|
if (getPluginHeader(pluginName)) {
|
|
@@ -38872,12 +39289,12 @@ var drainAbsoluteMobileNativeObservability = async (manifest, fetch2, options =
|
|
|
38872
39289
|
const config = manifest.observability;
|
|
38873
39290
|
if (!config || !(options.native ?? Capacitor.isNativePlatform()))
|
|
38874
39291
|
return 0;
|
|
38875
|
-
const
|
|
38876
|
-
const pending = await
|
|
39292
|
+
const plugin2 = options.plugin ?? nativeObservability;
|
|
39293
|
+
const pending = await plugin2.pending();
|
|
38877
39294
|
const reports = pending.reports.slice(0, MAX_REPORTS).map(parseReport).filter((report) => report !== undefined);
|
|
38878
39295
|
const discarded = reports.filter((report) => !sampled(report.id, config.sampleRate));
|
|
38879
39296
|
if (discarded.length > 0)
|
|
38880
|
-
await
|
|
39297
|
+
await plugin2.acknowledge({
|
|
38881
39298
|
ids: discarded.map(({ id }) => id)
|
|
38882
39299
|
});
|
|
38883
39300
|
const selected = reports.filter((report) => sampled(report.id, config.sampleRate));
|
|
@@ -38897,7 +39314,7 @@ var drainAbsoluteMobileNativeObservability = async (manifest, fetch2, options =
|
|
|
38897
39314
|
});
|
|
38898
39315
|
if (!response.ok)
|
|
38899
39316
|
return 0;
|
|
38900
|
-
await
|
|
39317
|
+
await plugin2.acknowledge({
|
|
38901
39318
|
ids: selected.map(({ id }) => id)
|
|
38902
39319
|
});
|
|
38903
39320
|
return selected.length;
|
|
@@ -44270,7 +44687,7 @@ import { pathToFileURL as pathToFileURL4 } from "url";
|
|
|
44270
44687
|
import { createHash as createHash18, sign, verify } from "crypto";
|
|
44271
44688
|
import {
|
|
44272
44689
|
cp as cp2,
|
|
44273
|
-
mkdir as
|
|
44690
|
+
mkdir as mkdir26,
|
|
44274
44691
|
mkdtemp as mkdtemp12,
|
|
44275
44692
|
readdir as readdir12,
|
|
44276
44693
|
readFile as readFile31,
|
|
@@ -44279,14 +44696,14 @@ import {
|
|
|
44279
44696
|
stat as stat8,
|
|
44280
44697
|
writeFile as writeFile26
|
|
44281
44698
|
} from "fs/promises";
|
|
44282
|
-
import { dirname as dirname25, join as
|
|
44699
|
+
import { dirname as dirname25, join as join35, relative as relative23, resolve as resolve25 } from "path";
|
|
44283
44700
|
var UPDATE_MANIFEST_FILE = "update.json";
|
|
44284
44701
|
var UPDATE_FILES_DIRECTORY = "files";
|
|
44285
44702
|
var sha2565 = (value) => createHash18("sha256").update(value).digest("hex");
|
|
44286
44703
|
var listFiles = async (root, directory = root) => {
|
|
44287
44704
|
const entries = await readdir12(directory, { withFileTypes: true });
|
|
44288
44705
|
const paths = await Promise.all(entries.map(async (entry) => {
|
|
44289
|
-
const path =
|
|
44706
|
+
const path = join35(directory, entry.name);
|
|
44290
44707
|
if (entry.isDirectory())
|
|
44291
44708
|
return listFiles(root, path);
|
|
44292
44709
|
if (!entry.isFile())
|
|
@@ -44296,7 +44713,7 @@ var listFiles = async (root, directory = root) => {
|
|
|
44296
44713
|
return paths.flat().sort((left, right) => left.localeCompare(right));
|
|
44297
44714
|
};
|
|
44298
44715
|
var inspectFiles = async (root, paths) => Promise.all(paths.map(async (path) => {
|
|
44299
|
-
const source =
|
|
44716
|
+
const source = join35(root, path);
|
|
44300
44717
|
const [metadata, contents] = await Promise.all([
|
|
44301
44718
|
stat8(source),
|
|
44302
44719
|
readFile31(source)
|
|
@@ -44334,15 +44751,15 @@ var buildAbsoluteMobileUpdate = async (options) => {
|
|
|
44334
44751
|
value: signature.toString("base64")
|
|
44335
44752
|
}
|
|
44336
44753
|
});
|
|
44337
|
-
await
|
|
44338
|
-
const outputDirectory =
|
|
44339
|
-
const staging = await mkdtemp12(
|
|
44754
|
+
await mkdir26(outputRoot, { recursive: true });
|
|
44755
|
+
const outputDirectory = join35(outputRoot, manifest.releaseId);
|
|
44756
|
+
const staging = await mkdtemp12(join35(outputRoot, ".stage-"));
|
|
44340
44757
|
try {
|
|
44341
|
-
await cp2(bundleDirectory,
|
|
44758
|
+
await cp2(bundleDirectory, join35(staging, UPDATE_FILES_DIRECTORY), {
|
|
44342
44759
|
force: true,
|
|
44343
44760
|
recursive: true
|
|
44344
44761
|
});
|
|
44345
|
-
await writeFile26(
|
|
44762
|
+
await writeFile26(join35(staging, UPDATE_MANIFEST_FILE), `${JSON.stringify(manifest, null, "\t")}
|
|
44346
44763
|
`);
|
|
44347
44764
|
await rename22(staging, outputDirectory);
|
|
44348
44765
|
} catch (error) {
|
|
@@ -44353,7 +44770,7 @@ var buildAbsoluteMobileUpdate = async (options) => {
|
|
|
44353
44770
|
}
|
|
44354
44771
|
return {
|
|
44355
44772
|
manifest,
|
|
44356
|
-
manifestPath:
|
|
44773
|
+
manifestPath: join35(outputDirectory, UPDATE_MANIFEST_FILE),
|
|
44357
44774
|
outputDirectory
|
|
44358
44775
|
};
|
|
44359
44776
|
};
|
|
@@ -44362,10 +44779,10 @@ var copyAbsoluteMobileUpdateFile = async (updateDirectory, path, destination) =>
|
|
|
44362
44779
|
const root = resolve25(updateDirectory, UPDATE_FILES_DIRECTORY);
|
|
44363
44780
|
if (!source.startsWith(`${root}/`))
|
|
44364
44781
|
throw new TypeError("Update file escaped its release.");
|
|
44365
|
-
await
|
|
44782
|
+
await mkdir26(dirname25(destination), { recursive: true });
|
|
44366
44783
|
await cp2(source, destination, { force: true });
|
|
44367
44784
|
};
|
|
44368
|
-
var readAbsoluteMobileUpdate = async (directory) => parseAbsoluteMobileUpdateManifest(JSON.parse(await readFile31(
|
|
44785
|
+
var readAbsoluteMobileUpdate = async (directory) => parseAbsoluteMobileUpdateManifest(JSON.parse(await readFile31(join35(resolve25(directory), UPDATE_MANIFEST_FILE), "utf8")));
|
|
44369
44786
|
var verifyAbsoluteMobileUpdateSignature = (manifestValue, publicKey) => {
|
|
44370
44787
|
const manifest = parseAbsoluteMobileUpdateManifest(manifestValue);
|
|
44371
44788
|
const valid = verify("sha256", absoluteMobileUpdateSigningPayload(unsignedAbsoluteMobileUpdate(manifest)), { dsaEncoding: "ieee-p1363", key: publicKey }, Buffer.from(manifest.signature.value, "base64"));
|
|
@@ -44811,6 +45228,7 @@ export {
|
|
|
44811
45228
|
pauseAbsoluteMobileUpdateRollout,
|
|
44812
45229
|
planAbsoluteExpoDevSession,
|
|
44813
45230
|
prepareAbsoluteAndroidRelease,
|
|
45231
|
+
prepareAbsoluteCapacitorInitialization,
|
|
44814
45232
|
prepareAbsoluteIosDevProject,
|
|
44815
45233
|
prepareAbsoluteIosRelease,
|
|
44816
45234
|
projectImportsAbsoluteDeviceCapability,
|
|
@@ -44890,5 +45308,5 @@ export {
|
|
|
44890
45308
|
writeAbsoluteMobileUpdateRegistry
|
|
44891
45309
|
};
|
|
44892
45310
|
|
|
44893
|
-
//# debugId=
|
|
45311
|
+
//# debugId=0FE744BA265F0CF164756E2164756E21
|
|
44894
45312
|
//# sourceMappingURL=index.js.map
|