@absolutejs/absolute 0.20.0-beta.42 → 0.20.0-beta.43
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/dist/angular/components/core/streamingSlotRegistrar.js +1 -1
- package/dist/angular/components/core/streamingSlotRegistry.js +2 -2
- package/dist/cli/index.js +320 -95
- package/dist/mobile/index.js +183 -76
- package/dist/mobile/index.js.map +5 -5
- package/dist/mobile/remoteMacAgentEntry.js +335 -14
- package/dist/src/mobile/expoDevController.d.ts +8 -4
- package/dist/src/mobile/remoteMacProtocol.d.ts +27 -0
- package/dist/src/mobile/remoteMacWire.d.ts +1 -1
- package/package.json +1 -1
package/dist/cli/index.js
CHANGED
|
@@ -4488,7 +4488,7 @@ var init_iosSimulatorController = __esm(() => {
|
|
|
4488
4488
|
});
|
|
4489
4489
|
|
|
4490
4490
|
// src/mobile/remoteMacWire.ts
|
|
4491
|
-
var ABSOLUTE_REMOTE_MAC_EVENT_PREFIX = "ABSOLUTE_REMOTE_MAC\t", ABSOLUTE_REMOTE_MAC_PROTOCOL_VERSION =
|
|
4491
|
+
var ABSOLUTE_REMOTE_MAC_EVENT_PREFIX = "ABSOLUTE_REMOTE_MAC\t", ABSOLUTE_REMOTE_MAC_PROTOCOL_VERSION = 2;
|
|
4492
4492
|
|
|
4493
4493
|
// src/mobile/remoteMacProtocol.ts
|
|
4494
4494
|
import { createHash as createHash6, randomUUID as randomUUID4 } from "crypto";
|
|
@@ -4504,7 +4504,7 @@ import {
|
|
|
4504
4504
|
resolve as resolvePath,
|
|
4505
4505
|
sep as sep4
|
|
4506
4506
|
} from "path";
|
|
4507
|
-
var PROFILE_FORMAT = 1, REMOTE_STDIN_FLUSH_ATTEMPTS = 3, PROFILE_NAME, SSH_DESTINATION, defaultProfilePath = () => join13(homedir4(), ".absolutejs", "mobile", "remote-macs.json"), emptyStore = () => ({
|
|
4507
|
+
var PROFILE_FORMAT = 1, REMOTE_STDIN_FLUSH_ATTEMPTS = 3, REMOTE_SESSION_CLOSE_TIMEOUT_MS = 2000, PROFILE_NAME, SSH_DESTINATION, defaultProfilePath = () => join13(homedir4(), ".absolutejs", "mobile", "remote-macs.json"), emptyStore = () => ({
|
|
4508
4508
|
format: PROFILE_FORMAT,
|
|
4509
4509
|
profiles: {}
|
|
4510
4510
|
}), loadStore = async (path = defaultProfilePath()) => {
|
|
@@ -4675,7 +4675,11 @@ var PROFILE_FORMAT = 1, REMOTE_STDIN_FLUSH_ATTEMPTS = 3, PROFILE_NAME, SSH_DESTI
|
|
|
4675
4675
|
}
|
|
4676
4676
|
await saveStore(store, profilePath);
|
|
4677
4677
|
return true;
|
|
4678
|
-
}, projectIdentity = (projectRoot, appId) => createHash6("sha256").update(`${resolvePath(projectRoot)}\x00${appId}`).digest("hex").slice(0, 20),
|
|
4678
|
+
}, projectIdentity = (projectRoot, appId) => createHash6("sha256").update(`${resolvePath(projectRoot)}\x00${appId}`).digest("hex").slice(0, 20), createAbsoluteRemoteExpoIosDevProject = (config, projectRoot, profile) => {
|
|
4679
|
+
if (config.engine !== "expo")
|
|
4680
|
+
throw new TypeError("Remote Expo execution requires mobile.engine: expo.");
|
|
4681
|
+
return createAbsoluteRemoteIosDevProject(config, projectRoot, profile);
|
|
4682
|
+
}, createAbsoluteRemoteIosDevProject = (config, projectRoot, profile) => ({
|
|
4679
4683
|
cap: join13(resolvePath(projectRoot), "node_modules", ".bin", "cap"),
|
|
4680
4684
|
config,
|
|
4681
4685
|
nativeDirectory: join13(config.nativeProjectDirectory, "ios"),
|
|
@@ -4762,6 +4766,7 @@ var PROFILE_FORMAT = 1, REMOTE_STDIN_FLUSH_ATTEMPTS = 3, PROFILE_NAME, SSH_DESTI
|
|
|
4762
4766
|
appId: project.config.appId,
|
|
4763
4767
|
appName: project.config.appName,
|
|
4764
4768
|
bundleDirectory: portableRelativePath(project.projectRoot, project.config.bundleDirectory),
|
|
4769
|
+
engine: project.config.engine,
|
|
4765
4770
|
...project.config.deepLinkScheme || project.config.deepLinkHosts.length > 1 || project.config.appleAppIdPrefix ? {
|
|
4766
4771
|
deepLinks: {
|
|
4767
4772
|
...project.config.deepLinkScheme ? { scheme: project.config.deepLinkScheme } : {},
|
|
@@ -4774,6 +4779,16 @@ var PROFILE_FORMAT = 1, REMOTE_STDIN_FLUSH_ATTEMPTS = 3, PROFILE_NAME, SSH_DESTI
|
|
|
4774
4779
|
}
|
|
4775
4780
|
} : {},
|
|
4776
4781
|
entry: project.config.entry,
|
|
4782
|
+
...project.config.engine === "expo" ? {
|
|
4783
|
+
expo: { sdkVersion: project.config.expoSdkVersion ?? 57 },
|
|
4784
|
+
routes: {
|
|
4785
|
+
default: "web",
|
|
4786
|
+
native: Object.fromEntries(Object.entries(project.config.expoNativeRoutes).map(([route, module]) => [
|
|
4787
|
+
route,
|
|
4788
|
+
portableRelativePath(project.projectRoot, module)
|
|
4789
|
+
]))
|
|
4790
|
+
}
|
|
4791
|
+
} : {},
|
|
4777
4792
|
...project.config.iosVersion ? { ios: { version: project.config.iosVersion } } : {},
|
|
4778
4793
|
nativeProject: {
|
|
4779
4794
|
directory: portableRelativePath(project.projectRoot, project.config.nativeProjectDirectory),
|
|
@@ -4861,7 +4876,30 @@ var PROFILE_FORMAT = 1, REMOTE_STDIN_FLUSH_ATTEMPTS = 3, PROFILE_NAME, SSH_DESTI
|
|
|
4861
4876
|
} finally {
|
|
4862
4877
|
reader.releaseLock();
|
|
4863
4878
|
}
|
|
4864
|
-
},
|
|
4879
|
+
}, startAbsoluteRemoteExpoIosDevSession = async (options) => {
|
|
4880
|
+
const session = await startAbsoluteRemoteDevSession({
|
|
4881
|
+
certificateAuthorityPath: options.certificateAuthorityPath,
|
|
4882
|
+
deviceIdentifier: options.deviceIdentifier,
|
|
4883
|
+
https: options.https,
|
|
4884
|
+
installAgent: options.installAgent,
|
|
4885
|
+
log: options.log,
|
|
4886
|
+
metroPort: options.metroPort,
|
|
4887
|
+
onExpoPhaseTiming: options.onPhaseTiming,
|
|
4888
|
+
onExpoStateChange: options.onStateChange,
|
|
4889
|
+
port: options.port,
|
|
4890
|
+
project: options.project,
|
|
4891
|
+
serverHost: options.serverHost,
|
|
4892
|
+
signal: options.signal,
|
|
4893
|
+
syncProject: options.syncProject,
|
|
4894
|
+
transport: options.transport
|
|
4895
|
+
});
|
|
4896
|
+
return {
|
|
4897
|
+
close: session.close,
|
|
4898
|
+
metroPort: options.metroPort,
|
|
4899
|
+
platforms: ["ios"],
|
|
4900
|
+
timings: session.timings
|
|
4901
|
+
};
|
|
4902
|
+
}, startAbsoluteRemoteIosDevSession = (options) => startAbsoluteRemoteDevSession(options), startAbsoluteRemoteDevSession = async (options) => {
|
|
4865
4903
|
const startedAt = performance.now();
|
|
4866
4904
|
const transport = options.transport ?? defaultTransport;
|
|
4867
4905
|
const installAgent = options.installAgent ?? installAbsoluteRemoteMacAgent;
|
|
@@ -4875,9 +4913,22 @@ var PROFILE_FORMAT = 1, REMOTE_STDIN_FLUSH_ATTEMPTS = 3, PROFILE_NAME, SSH_DESTI
|
|
|
4875
4913
|
const encodedConfig = Buffer.from(JSON.stringify(portableMobileConfig(options.project))).toString("base64url");
|
|
4876
4914
|
const encodedCertificateAuthority = options.certificateAuthorityPath ? (await readFile8(options.certificateAuthorityPath)).toString("base64url") : undefined;
|
|
4877
4915
|
const physicalDevice = options.deviceIdentifier !== undefined;
|
|
4878
|
-
|
|
4879
|
-
if (
|
|
4880
|
-
|
|
4916
|
+
const expo = options.project.config.engine === "expo";
|
|
4917
|
+
if (expo && options.metroPort === undefined)
|
|
4918
|
+
throw new TypeError("Remote Expo execution requires a Metro port.");
|
|
4919
|
+
if (options.metroPort === options.port)
|
|
4920
|
+
throw new TypeError("Expo Metro and AbsoluteJS must use different ports.");
|
|
4921
|
+
const translatedRelayPort = (sourcePort) => sourcePort <= 49151 ? sourcePort + 16384 : sourcePort - 16384;
|
|
4922
|
+
const occupiedRemotePorts = new Set([options.port, options.metroPort].filter((value) => value !== undefined));
|
|
4923
|
+
const reserveRelayPort = (sourcePort) => {
|
|
4924
|
+
let candidate = translatedRelayPort(sourcePort);
|
|
4925
|
+
while (occupiedRemotePorts.has(candidate))
|
|
4926
|
+
candidate = candidate === 65535 ? 1024 : candidate + 1;
|
|
4927
|
+
occupiedRemotePorts.add(candidate);
|
|
4928
|
+
return candidate;
|
|
4929
|
+
};
|
|
4930
|
+
const relayPort = physicalDevice ? reserveRelayPort(options.port) : undefined;
|
|
4931
|
+
const metroRelayPort = physicalDevice && options.metroPort !== undefined ? reserveRelayPort(options.metroPort) : undefined;
|
|
4881
4932
|
if (physicalDevice && !options.serverHost)
|
|
4882
4933
|
throw new Error("Remote physical iOS development requires the Remote Mac LAN host.");
|
|
4883
4934
|
const remoteCommand = [
|
|
@@ -4890,6 +4941,7 @@ var PROFILE_FORMAT = 1, REMOTE_STDIN_FLUSH_ATTEMPTS = 3, PROFILE_NAME, SSH_DESTI
|
|
|
4890
4941
|
String(options.port),
|
|
4891
4942
|
"--mobile-config",
|
|
4892
4943
|
shellQuote(encodedConfig),
|
|
4944
|
+
...expo && options.metroPort !== undefined ? ["--metro-port", String(options.metroPort)] : [],
|
|
4893
4945
|
...encodedCertificateAuthority ? [
|
|
4894
4946
|
"--certificate-authority",
|
|
4895
4947
|
shellQuote(encodedCertificateAuthority)
|
|
@@ -4901,7 +4953,8 @@ var PROFILE_FORMAT = 1, REMOTE_STDIN_FLUSH_ATTEMPTS = 3, PROFILE_NAME, SSH_DESTI
|
|
|
4901
4953
|
"--server-host",
|
|
4902
4954
|
shellQuote(options.serverHost ?? ""),
|
|
4903
4955
|
"--relay-port",
|
|
4904
|
-
String(relayPort)
|
|
4956
|
+
String(relayPort),
|
|
4957
|
+
...expo && metroRelayPort !== undefined ? ["--metro-relay-port", String(metroRelayPort)] : []
|
|
4905
4958
|
] : []
|
|
4906
4959
|
].join(" ");
|
|
4907
4960
|
const command = [
|
|
@@ -4910,6 +4963,10 @@ var PROFILE_FORMAT = 1, REMOTE_STDIN_FLUSH_ATTEMPTS = 3, PROFILE_NAME, SSH_DESTI
|
|
|
4910
4963
|
"ExitOnForwardFailure=yes",
|
|
4911
4964
|
"-R",
|
|
4912
4965
|
physicalDevice ? `127.0.0.1:${relayPort}:127.0.0.1:${options.port}` : `${options.port}:127.0.0.1:${options.port}`,
|
|
4966
|
+
...expo && options.metroPort !== undefined ? [
|
|
4967
|
+
"-R",
|
|
4968
|
+
physicalDevice ? `127.0.0.1:${metroRelayPort}:127.0.0.1:${options.metroPort}` : `${options.metroPort}:127.0.0.1:${options.metroPort}`
|
|
4969
|
+
] : [],
|
|
4913
4970
|
"/bin/sh -lc",
|
|
4914
4971
|
shellQuote(remoteCommand)
|
|
4915
4972
|
];
|
|
@@ -4935,11 +4992,19 @@ var PROFILE_FORMAT = 1, REMOTE_STDIN_FLUSH_ATTEMPTS = 3, PROFILE_NAME, SSH_DESTI
|
|
|
4935
4992
|
if (event.type === "native-log")
|
|
4936
4993
|
options.nativeLog?.(event.entry);
|
|
4937
4994
|
if (event.type === "state") {
|
|
4938
|
-
(
|
|
4939
|
-
|
|
4995
|
+
if (expo)
|
|
4996
|
+
options.onExpoStateChange?.(event.state);
|
|
4997
|
+
else {
|
|
4998
|
+
state = event.state;
|
|
4999
|
+
options.onStateChange?.(state);
|
|
5000
|
+
}
|
|
5001
|
+
}
|
|
5002
|
+
if (event.type === "timing") {
|
|
5003
|
+
if (expo)
|
|
5004
|
+
options.onExpoPhaseTiming?.(event);
|
|
5005
|
+
else
|
|
5006
|
+
options.onPhaseTiming?.(event);
|
|
4940
5007
|
}
|
|
4941
|
-
if (event.type === "timing")
|
|
4942
|
-
options.onPhaseTiming?.(event);
|
|
4943
5008
|
if (event.type === "ready") {
|
|
4944
5009
|
ready = event;
|
|
4945
5010
|
resolveReady();
|
|
@@ -4981,9 +5046,26 @@ var PROFILE_FORMAT = 1, REMOTE_STDIN_FLUSH_ATTEMPTS = 3, PROFILE_NAME, SSH_DESTI
|
|
|
4981
5046
|
pending.clear();
|
|
4982
5047
|
return;
|
|
4983
5048
|
});
|
|
4984
|
-
|
|
5049
|
+
try {
|
|
5050
|
+
await readyPromise;
|
|
5051
|
+
} catch (error) {
|
|
5052
|
+
process2.stdin.end();
|
|
5053
|
+
process2.kill();
|
|
5054
|
+
await process2.exited.catch(() => {
|
|
5055
|
+
return;
|
|
5056
|
+
});
|
|
5057
|
+
throw error;
|
|
5058
|
+
}
|
|
4985
5059
|
if (!ready)
|
|
4986
5060
|
throw fatal ?? new Error("Remote Mac did not become ready.");
|
|
5061
|
+
if (ready.engine !== options.project.config.engine) {
|
|
5062
|
+
process2.stdin.end();
|
|
5063
|
+
process2.kill();
|
|
5064
|
+
await process2.exited.catch(() => {
|
|
5065
|
+
return;
|
|
5066
|
+
});
|
|
5067
|
+
throw new Error("Remote Mac executor returned the wrong mobile engine.");
|
|
5068
|
+
}
|
|
4987
5069
|
const totalDuration = performance.now() - startedAt;
|
|
4988
5070
|
let currentReady = {
|
|
4989
5071
|
...ready,
|
|
@@ -4995,11 +5077,11 @@ var PROFILE_FORMAT = 1, REMOTE_STDIN_FLUSH_ATTEMPTS = 3, PROFILE_NAME, SSH_DESTI
|
|
|
4995
5077
|
total: totalDuration
|
|
4996
5078
|
}
|
|
4997
5079
|
};
|
|
4998
|
-
options.log?.(`Remote Mac connected (${options.project.profile.name}); agent ${agent.uploaded ? "uploaded" : "cache hit"}, project synced, and iOS ready in ${totalDuration.toFixed(2)}ms.`);
|
|
5080
|
+
options.log?.(`Remote Mac connected (${options.project.profile.name}); agent ${agent.uploaded ? "uploaded" : "cache hit"}, project synced, and ${expo ? "Expo " : ""}iOS ready in ${totalDuration.toFixed(2)}ms.`);
|
|
4999
5081
|
const request = (commandName) => {
|
|
5000
5082
|
const id = randomUUID4();
|
|
5001
5083
|
const response = new Promise((resolve9, reject) => pending.set(id, { reject, resolve: resolve9 }));
|
|
5002
|
-
process2.stdin.write(`${JSON.stringify({ command: commandName, id, v:
|
|
5084
|
+
process2.stdin.write(`${JSON.stringify({ command: commandName, id, v: ABSOLUTE_REMOTE_MAC_PROTOCOL_VERSION })}
|
|
5003
5085
|
`);
|
|
5004
5086
|
const flush = async () => {
|
|
5005
5087
|
for (let attempt = 0;attempt < REMOTE_STDIN_FLUSH_ATTEMPTS; attempt++) {
|
|
@@ -5018,13 +5100,24 @@ var PROFILE_FORMAT = 1, REMOTE_STDIN_FLUSH_ATTEMPTS = 3, PROFILE_NAME, SSH_DESTI
|
|
|
5018
5100
|
if (closed)
|
|
5019
5101
|
return;
|
|
5020
5102
|
closed = true;
|
|
5021
|
-
|
|
5022
|
-
|
|
5023
|
-
|
|
5103
|
+
const timeout = () => new Promise((resolve9) => setTimeout(() => resolve9("timeout"), REMOTE_SESSION_CLOSE_TIMEOUT_MS));
|
|
5104
|
+
await Promise.race([
|
|
5105
|
+
request("close").catch(() => {
|
|
5106
|
+
return;
|
|
5107
|
+
}),
|
|
5108
|
+
timeout()
|
|
5109
|
+
]);
|
|
5024
5110
|
process2.stdin.end();
|
|
5025
|
-
await
|
|
5026
|
-
|
|
5027
|
-
|
|
5111
|
+
const exit = await Promise.race([
|
|
5112
|
+
process2.exited.then(() => "exited").catch(() => "exited"),
|
|
5113
|
+
timeout()
|
|
5114
|
+
]);
|
|
5115
|
+
if (exit === "timeout") {
|
|
5116
|
+
process2.kill();
|
|
5117
|
+
await process2.exited.catch(() => {
|
|
5118
|
+
return;
|
|
5119
|
+
});
|
|
5120
|
+
}
|
|
5028
5121
|
};
|
|
5029
5122
|
const makeSession = () => ({
|
|
5030
5123
|
close,
|
|
@@ -23371,7 +23464,8 @@ var commandEnvironment = (options) => ({
|
|
|
23371
23464
|
ABSOLUTE_EXPO_DEVELOPMENT_CA_PATH: options.certificateAuthorityPath
|
|
23372
23465
|
} : {},
|
|
23373
23466
|
...options.androidOrigin ? { EXPO_PUBLIC_ABSOLUTE_DEV_ANDROID_ORIGIN: options.androidOrigin } : {},
|
|
23374
|
-
...options.iosOrigin ? { EXPO_PUBLIC_ABSOLUTE_DEV_IOS_ORIGIN: options.iosOrigin } : {}
|
|
23467
|
+
...options.iosOrigin ? { EXPO_PUBLIC_ABSOLUTE_DEV_IOS_ORIGIN: options.iosOrigin } : {},
|
|
23468
|
+
...options.metroHost ? { REACT_NATIVE_PACKAGER_HOSTNAME: options.metroHost } : {}
|
|
23375
23469
|
});
|
|
23376
23470
|
var absoluteExpoExecutable = async (project) => {
|
|
23377
23471
|
const executable = join6(project, "node_modules", ".bin", "expo");
|
|
@@ -23385,8 +23479,8 @@ var absoluteExpoExecutable = async (project) => {
|
|
|
23385
23479
|
var planAbsoluteExpoDevSession = (config, options) => {
|
|
23386
23480
|
if (config.engine !== "expo")
|
|
23387
23481
|
throw new TypeError("The Expo development controller requires Expo.");
|
|
23388
|
-
if (options.platforms.length === 0)
|
|
23389
|
-
throw new TypeError("Expo
|
|
23482
|
+
if (options.platforms.length === 0 && options.metro === "external")
|
|
23483
|
+
throw new TypeError("External Expo execution requires a target platform.");
|
|
23390
23484
|
const secureOrigin = [options.androidOrigin, options.iosOrigin].some((origin) => origin && new URL(origin).protocol === "https:");
|
|
23391
23485
|
if (secureOrigin && !options.certificateAuthorityPath)
|
|
23392
23486
|
throw new TypeError("Expo HTTPS development requires the AbsoluteJS development CA certificate.");
|
|
@@ -23403,7 +23497,7 @@ var planAbsoluteExpoDevSession = (config, options) => {
|
|
|
23403
23497
|
env,
|
|
23404
23498
|
role: "metro"
|
|
23405
23499
|
};
|
|
23406
|
-
const prepare = {
|
|
23500
|
+
const prepare = options.platforms.length === 0 ? undefined : {
|
|
23407
23501
|
args: [
|
|
23408
23502
|
"prebuild",
|
|
23409
23503
|
"--clean",
|
|
@@ -23431,7 +23525,11 @@ var planAbsoluteExpoDevSession = (config, options) => {
|
|
|
23431
23525
|
return command;
|
|
23432
23526
|
});
|
|
23433
23527
|
return {
|
|
23434
|
-
commands: [
|
|
23528
|
+
commands: [
|
|
23529
|
+
...prepare ? [prepare] : [],
|
|
23530
|
+
...options.metro === "external" ? [] : [metro],
|
|
23531
|
+
...native
|
|
23532
|
+
],
|
|
23435
23533
|
metroPort: options.metroPort,
|
|
23436
23534
|
project: config.nativeProjectDirectory
|
|
23437
23535
|
};
|
|
@@ -23520,47 +23618,48 @@ var startAbsoluteExpoDevSession = async (options) => {
|
|
|
23520
23618
|
const prepareCommand = plan.commands.find((command) => command.role === "native-prepare");
|
|
23521
23619
|
const metroCommand = plan.commands.find((command) => command.role === "metro");
|
|
23522
23620
|
const nativeCommands = plan.commands.filter((command) => command.role === "native-build");
|
|
23523
|
-
|
|
23524
|
-
|
|
23525
|
-
|
|
23526
|
-
|
|
23527
|
-
|
|
23528
|
-
|
|
23529
|
-
|
|
23530
|
-
|
|
23531
|
-
|
|
23532
|
-
|
|
23533
|
-
|
|
23534
|
-
|
|
23535
|
-
|
|
23536
|
-
|
|
23537
|
-
|
|
23538
|
-
|
|
23539
|
-
|
|
23540
|
-
|
|
23541
|
-
|
|
23542
|
-
|
|
23543
|
-
|
|
23544
|
-
|
|
23545
|
-
|
|
23546
|
-
|
|
23547
|
-
|
|
23548
|
-
|
|
23549
|
-
|
|
23550
|
-
|
|
23551
|
-
|
|
23552
|
-
phase: "preparing-native"
|
|
23553
|
-
});
|
|
23554
|
-
setState("starting-metro");
|
|
23621
|
+
const runPrepareCommand = async (command) => {
|
|
23622
|
+
setState("preparing-native");
|
|
23623
|
+
const prepareStarted = performance.now();
|
|
23624
|
+
const prepareProcess = run(executable, command.args, {
|
|
23625
|
+
cwd: plan.project,
|
|
23626
|
+
env: { ...process.env, ...command.env },
|
|
23627
|
+
stdio: ["ignore", "pipe", "pipe"]
|
|
23628
|
+
});
|
|
23629
|
+
forwardLines(prepareProcess, (line) => {
|
|
23630
|
+
if (line)
|
|
23631
|
+
log(`[prebuild] ${line}`);
|
|
23632
|
+
});
|
|
23633
|
+
const abortPrepare = () => void stopProcess(prepareProcess);
|
|
23634
|
+
options.signal?.addEventListener("abort", abortPrepare, { once: true });
|
|
23635
|
+
const prepareExit = await waitForExit(prepareProcess);
|
|
23636
|
+
options.signal?.removeEventListener("abort", abortPrepare);
|
|
23637
|
+
if (options.signal?.aborted)
|
|
23638
|
+
throw abortError();
|
|
23639
|
+
if (prepareExit !== 0) {
|
|
23640
|
+
setState("failed");
|
|
23641
|
+
throw new Error(`Expo native preparation exited with status ${prepareExit}.`);
|
|
23642
|
+
}
|
|
23643
|
+
publishTiming("preparing-native", performance.now() - prepareStarted);
|
|
23644
|
+
};
|
|
23645
|
+
if (prepareCommand)
|
|
23646
|
+
await runPrepareCommand(prepareCommand);
|
|
23647
|
+
const managedMetro = metroCommand !== undefined;
|
|
23648
|
+
if (managedMetro)
|
|
23649
|
+
setState("starting-metro");
|
|
23555
23650
|
const metroStarted = performance.now();
|
|
23556
|
-
const metro = run(executable, metroCommand.args, {
|
|
23651
|
+
const metro = metroCommand ? run(executable, metroCommand.args, {
|
|
23557
23652
|
cwd: plan.project,
|
|
23558
23653
|
env: { ...process.env, ...metroCommand.env },
|
|
23559
23654
|
stdio: ["ignore", "pipe", "pipe"]
|
|
23560
|
-
});
|
|
23655
|
+
}) : undefined;
|
|
23561
23656
|
let metroReady = false;
|
|
23562
23657
|
let resolveMetro;
|
|
23563
23658
|
const metroPromise = new Promise((resolve4, reject) => {
|
|
23659
|
+
if (!metro) {
|
|
23660
|
+
resolve4();
|
|
23661
|
+
return;
|
|
23662
|
+
}
|
|
23564
23663
|
const timeout = setTimeout(() => {
|
|
23565
23664
|
reject(new Error("Expo Metro did not become ready within 60 seconds."));
|
|
23566
23665
|
}, METRO_READY_TIMEOUT_MS);
|
|
@@ -23575,15 +23674,19 @@ var startAbsoluteExpoDevSession = async (options) => {
|
|
|
23575
23674
|
}
|
|
23576
23675
|
});
|
|
23577
23676
|
});
|
|
23578
|
-
|
|
23579
|
-
|
|
23580
|
-
|
|
23581
|
-
|
|
23582
|
-
metroReady
|
|
23583
|
-
|
|
23584
|
-
|
|
23585
|
-
|
|
23586
|
-
|
|
23677
|
+
if (metro)
|
|
23678
|
+
forwardLines(metro, (line) => {
|
|
23679
|
+
if (line)
|
|
23680
|
+
log(`[metro] ${line}`);
|
|
23681
|
+
if (!metroReady && /(?:Waiting on|Metro waiting on|Dev server ready)/iu.test(line)) {
|
|
23682
|
+
metroReady = true;
|
|
23683
|
+
resolveMetro?.();
|
|
23684
|
+
}
|
|
23685
|
+
});
|
|
23686
|
+
const abort = () => {
|
|
23687
|
+
if (metro)
|
|
23688
|
+
stopProcess(metro);
|
|
23689
|
+
};
|
|
23587
23690
|
options.signal?.addEventListener("abort", abort, { once: true });
|
|
23588
23691
|
const runNativeCommand = async (command) => {
|
|
23589
23692
|
if (options.signal?.aborted)
|
|
@@ -23664,12 +23767,8 @@ var startAbsoluteExpoDevSession = async (options) => {
|
|
|
23664
23767
|
try {
|
|
23665
23768
|
await startPhysicalIosEnrollment();
|
|
23666
23769
|
await metroPromise;
|
|
23667
|
-
|
|
23668
|
-
|
|
23669
|
-
options.onPhaseTiming?.({
|
|
23670
|
-
durationMs: metroMs,
|
|
23671
|
-
phase: "starting-metro"
|
|
23672
|
-
});
|
|
23770
|
+
if (managedMetro)
|
|
23771
|
+
publishTiming("starting-metro", performance.now() - metroStarted);
|
|
23673
23772
|
await runNativeCommands(nativeCommands);
|
|
23674
23773
|
setState("ready");
|
|
23675
23774
|
return {
|
|
@@ -23678,14 +23777,16 @@ var startAbsoluteExpoDevSession = async (options) => {
|
|
|
23678
23777
|
timings,
|
|
23679
23778
|
close: async () => {
|
|
23680
23779
|
options.signal?.removeEventListener("abort", abort);
|
|
23681
|
-
|
|
23780
|
+
if (metro)
|
|
23781
|
+
await stopProcess(metro);
|
|
23682
23782
|
await closeEnrollmentServer();
|
|
23683
23783
|
setState("closed");
|
|
23684
23784
|
}
|
|
23685
23785
|
};
|
|
23686
23786
|
} catch (error) {
|
|
23687
23787
|
options.signal?.removeEventListener("abort", abort);
|
|
23688
|
-
|
|
23788
|
+
if (metro)
|
|
23789
|
+
await stopProcess(metro);
|
|
23689
23790
|
await closeEnrollmentServer();
|
|
23690
23791
|
setState("failed");
|
|
23691
23792
|
throw error;
|
|
@@ -24092,9 +24193,6 @@ var dev = async (serverEntry, configPath2, options = {}) => {
|
|
|
24092
24193
|
throw new TypeError("--ios-device requires ios in mobile.platforms.");
|
|
24093
24194
|
}
|
|
24094
24195
|
if (options.iosDevice) {
|
|
24095
|
-
if (mobileConfig?.engine === "expo" && detectAbsoluteMobileHost() !== "macos") {
|
|
24096
|
-
throw new Error("Expo physical iOS development currently requires local macOS; Expo Remote Mac execution is the next adapter milestone.");
|
|
24097
|
-
}
|
|
24098
24196
|
if (detectAbsoluteMobileHost() === "macos")
|
|
24099
24197
|
iosPhysicalServerHost = mobileReachableHost(resolvedDev.host);
|
|
24100
24198
|
else {
|
|
@@ -24138,6 +24236,7 @@ var dev = async (serverEntry, configPath2, options = {}) => {
|
|
|
24138
24236
|
}
|
|
24139
24237
|
}
|
|
24140
24238
|
const platforms = [];
|
|
24239
|
+
let remoteIos;
|
|
24141
24240
|
if (normalized.platforms.includes("android")) {
|
|
24142
24241
|
const target = options.androidDevice ? "device" : "emulator";
|
|
24143
24242
|
let ready = androidToolchainReady(await inspectAbsoluteMobileToolchain(), target);
|
|
@@ -24153,7 +24252,14 @@ var dev = async (serverEntry, configPath2, options = {}) => {
|
|
|
24153
24252
|
}
|
|
24154
24253
|
if (normalized.platforms.includes("ios")) {
|
|
24155
24254
|
if (detectAbsoluteMobileHost() !== "macos") {
|
|
24156
|
-
|
|
24255
|
+
const remote = selectedRemoteMacProfile ?? await getAbsoluteRemoteMacProfile();
|
|
24256
|
+
if (!remote) {
|
|
24257
|
+
console.log(cliTag("\x1B[33m", "Expo iOS target skipped. Pair a Mac with `absolute mobile pair mac <name> <user@host>`."));
|
|
24258
|
+
} else {
|
|
24259
|
+
selectedRemoteMacProfile = remote;
|
|
24260
|
+
remoteIos = createAbsoluteRemoteExpoIosDevProject(normalized, process.cwd(), remote);
|
|
24261
|
+
console.log(cliTag("\x1B[35m", `Using remote Mac ${remote.name} for Expo iOS development.`));
|
|
24262
|
+
}
|
|
24157
24263
|
} else {
|
|
24158
24264
|
const target = options.iosDevice ? "device" : "simulator";
|
|
24159
24265
|
let ready = iosToolchainReady(await inspectAbsoluteMobileToolchain(), target);
|
|
@@ -24168,13 +24274,17 @@ var dev = async (serverEntry, configPath2, options = {}) => {
|
|
|
24168
24274
|
platforms.push("ios");
|
|
24169
24275
|
}
|
|
24170
24276
|
}
|
|
24171
|
-
if (platforms.length > 0) {
|
|
24277
|
+
if (platforms.length > 0 || remoteIos) {
|
|
24172
24278
|
expoDevProject = {
|
|
24173
24279
|
executable: await absoluteExpoExecutable(generated.path),
|
|
24174
24280
|
mobile: normalized,
|
|
24175
|
-
platforms
|
|
24281
|
+
platforms,
|
|
24282
|
+
...remoteIos ? { remoteIos } : {}
|
|
24176
24283
|
};
|
|
24177
|
-
console.log(cliTag("\x1B[35m", `Expo development build queued for ${
|
|
24284
|
+
console.log(cliTag("\x1B[35m", `Expo development build queued for ${[
|
|
24285
|
+
...platforms,
|
|
24286
|
+
...remoteIos ? ["ios (Remote Mac)"] : []
|
|
24287
|
+
].join(" + ")}; Metro and native launch will start with the Bun server.`));
|
|
24178
24288
|
}
|
|
24179
24289
|
} else if (normalized.platforms.includes("android")) {
|
|
24180
24290
|
const androidTarget = options.androidDevice ? "device" : "emulator";
|
|
@@ -24601,54 +24711,166 @@ var dev = async (serverEntry, configPath2, options = {}) => {
|
|
|
24601
24711
|
return;
|
|
24602
24712
|
}
|
|
24603
24713
|
const androidHost = options.androidDevice ? mobileReachableHost(resolvedDev.host) : "10.0.2.2";
|
|
24604
|
-
const iosHost = options.iosDevice ? mobileReachableHost(resolvedDev.host) : "localhost";
|
|
24605
|
-
|
|
24606
|
-
|
|
24607
|
-
|
|
24714
|
+
const iosHost = options.iosDevice ? iosPhysicalServerHost ?? mobileReachableHost(resolvedDev.host) : "localhost";
|
|
24715
|
+
const androidOrigin = project.platforms.includes("android") ? absoluteDevOrigin(androidHost) : undefined;
|
|
24716
|
+
const iosOrigin = project.platforms.includes("ios") || project.remoteIos ? absoluteDevOrigin(iosHost) : undefined;
|
|
24717
|
+
let metroSession;
|
|
24718
|
+
let localNativeSession;
|
|
24719
|
+
let remoteSession;
|
|
24720
|
+
const metroStart = startAbsoluteExpoDevSession({
|
|
24721
|
+
androidOrigin,
|
|
24608
24722
|
certificateAuthorityPath: devCertificateAuthorityPath ?? undefined,
|
|
24609
24723
|
config: project.mobile,
|
|
24610
24724
|
executable: project.executable,
|
|
24611
|
-
|
|
24612
|
-
iosOrigin: project.platforms.includes("ios") ? absoluteDevOrigin(iosHost) : undefined,
|
|
24725
|
+
iosOrigin,
|
|
24613
24726
|
metroPort: expoMetroPort,
|
|
24614
|
-
platforms:
|
|
24727
|
+
platforms: [],
|
|
24615
24728
|
signal: expoDevAbort.signal,
|
|
24616
24729
|
log: (message) => printNativeOutput(cliTag("\x1B[35m", `Expo ${message}`)),
|
|
24617
24730
|
onPhaseTiming: ({ durationMs, phase }) => {
|
|
24618
24731
|
sendTelemetryEvent("mobile:expo-dev-phase", {
|
|
24619
24732
|
durationMs: Math.round(durationMs),
|
|
24733
|
+
host: detectAbsoluteMobileHost(),
|
|
24620
24734
|
phase,
|
|
24621
24735
|
platform: expoTelemetryPlatform(phase),
|
|
24622
24736
|
provider: "expo"
|
|
24623
24737
|
});
|
|
24624
24738
|
},
|
|
24625
24739
|
onStateChange: (state) => {
|
|
24626
|
-
expoDevState = state;
|
|
24627
24740
|
if (state === "ready" || state === "closed")
|
|
24628
24741
|
return;
|
|
24742
|
+
expoDevState = state;
|
|
24629
24743
|
printNativeOutput(cliTag("\x1B[35m", `Expo development: ${state}.`));
|
|
24630
24744
|
}
|
|
24631
|
-
}).then(
|
|
24745
|
+
}).then((session) => {
|
|
24746
|
+
metroSession = session;
|
|
24747
|
+
return session;
|
|
24748
|
+
});
|
|
24749
|
+
const localNativeStart = metroStart.then(async () => {
|
|
24750
|
+
if (project.platforms.length === 0)
|
|
24751
|
+
return;
|
|
24752
|
+
const session = await startAbsoluteExpoDevSession({
|
|
24753
|
+
androidDevice: options.androidDevice,
|
|
24754
|
+
androidOrigin,
|
|
24755
|
+
certificateAuthorityPath: devCertificateAuthorityPath ?? undefined,
|
|
24756
|
+
config: project.mobile,
|
|
24757
|
+
executable: project.executable,
|
|
24758
|
+
iosDevice: options.iosDevice,
|
|
24759
|
+
iosOrigin,
|
|
24760
|
+
metro: "external",
|
|
24761
|
+
metroPort: expoMetroPort,
|
|
24762
|
+
platforms: project.platforms,
|
|
24763
|
+
signal: expoDevAbort.signal,
|
|
24764
|
+
log: (message) => printNativeOutput(cliTag("\x1B[35m", `Expo ${message}`)),
|
|
24765
|
+
onPhaseTiming: ({ durationMs, phase }) => {
|
|
24766
|
+
sendTelemetryEvent("mobile:expo-dev-phase", {
|
|
24767
|
+
durationMs: Math.round(durationMs),
|
|
24768
|
+
host: detectAbsoluteMobileHost(),
|
|
24769
|
+
phase,
|
|
24770
|
+
platform: expoTelemetryPlatform(phase),
|
|
24771
|
+
provider: "expo"
|
|
24772
|
+
});
|
|
24773
|
+
},
|
|
24774
|
+
onStateChange: (state) => {
|
|
24775
|
+
if (state === "ready" || state === "closed")
|
|
24776
|
+
return;
|
|
24777
|
+
expoDevState = state;
|
|
24778
|
+
printNativeOutput(cliTag("\x1B[35m", `Expo development: ${state}.`));
|
|
24779
|
+
}
|
|
24780
|
+
});
|
|
24781
|
+
localNativeSession = session;
|
|
24782
|
+
return session;
|
|
24783
|
+
});
|
|
24784
|
+
const remoteIosProject = project.remoteIos;
|
|
24785
|
+
const remoteStart = remoteIosProject ? metroStart.then(async () => {
|
|
24786
|
+
const session = await startAbsoluteRemoteExpoIosDevSession({
|
|
24787
|
+
certificateAuthorityPath: devCertificateAuthorityPath ?? undefined,
|
|
24788
|
+
deviceIdentifier: options.iosDevice,
|
|
24789
|
+
https: httpsEnabled,
|
|
24790
|
+
metroPort: expoMetroPort,
|
|
24791
|
+
port,
|
|
24792
|
+
project: remoteIosProject,
|
|
24793
|
+
serverHost: options.iosDevice ? iosPhysicalServerHost : undefined,
|
|
24794
|
+
signal: expoDevAbort.signal,
|
|
24795
|
+
log: (message) => printNativeOutput(cliTag("\x1B[35m", `Expo [remote-ios] ${message}`)),
|
|
24796
|
+
onPhaseTiming: ({ durationMs, phase }) => {
|
|
24797
|
+
sendTelemetryEvent("mobile:expo-dev-phase", {
|
|
24798
|
+
durationMs: Math.round(durationMs),
|
|
24799
|
+
host: "remote-macos",
|
|
24800
|
+
phase,
|
|
24801
|
+
platform: expoTelemetryPlatform(phase),
|
|
24802
|
+
provider: "expo"
|
|
24803
|
+
});
|
|
24804
|
+
},
|
|
24805
|
+
onStateChange: (state) => {
|
|
24806
|
+
if (state === "ready" || state === "closed")
|
|
24807
|
+
return;
|
|
24808
|
+
expoDevState = state;
|
|
24809
|
+
printNativeOutput(cliTag("\x1B[35m", `Expo Remote Mac iOS: ${state}.`));
|
|
24810
|
+
}
|
|
24811
|
+
});
|
|
24812
|
+
remoteSession = session;
|
|
24813
|
+
return session;
|
|
24814
|
+
}) : Promise.resolve(undefined);
|
|
24815
|
+
expoDevStart = Promise.all([metroStart, localNativeStart, remoteStart]).then(async ([metro, localNative, remote]) => {
|
|
24816
|
+
const session = {
|
|
24817
|
+
metroPort: metro.metroPort,
|
|
24818
|
+
platforms: [
|
|
24819
|
+
...new Set([
|
|
24820
|
+
...localNative?.platforms ?? [],
|
|
24821
|
+
...remote?.platforms ?? []
|
|
24822
|
+
])
|
|
24823
|
+
],
|
|
24824
|
+
timings: {
|
|
24825
|
+
...metro.timings,
|
|
24826
|
+
...localNative?.timings,
|
|
24827
|
+
...remote?.timings
|
|
24828
|
+
},
|
|
24829
|
+
close: async () => {
|
|
24830
|
+
await Promise.all([
|
|
24831
|
+
metro.close(),
|
|
24832
|
+
localNative?.close(),
|
|
24833
|
+
remote?.close()
|
|
24834
|
+
]);
|
|
24835
|
+
}
|
|
24836
|
+
};
|
|
24632
24837
|
if (cleaning) {
|
|
24633
24838
|
await session.close();
|
|
24634
24839
|
} else {
|
|
24635
24840
|
expoDevSession = session;
|
|
24841
|
+
expoDevState = "ready";
|
|
24636
24842
|
sendTelemetryEvent("mobile:expo-dev-ready", {
|
|
24637
24843
|
metroPort: session.metroPort,
|
|
24638
24844
|
platforms: session.platforms,
|
|
24639
24845
|
provider: "expo",
|
|
24846
|
+
remoteIos: project.remoteIos !== undefined,
|
|
24640
24847
|
timings: session.timings
|
|
24641
24848
|
});
|
|
24642
24849
|
printNativeOutput(cliTag("\x1B[35m", `Expo ${session.platforms.join(" + ")} connected; native Fast Refresh uses Metro on ${session.metroPort}, and AbsoluteJS pages use HMR on ${port}.`));
|
|
24643
24850
|
}
|
|
24644
24851
|
}).catch((error) => {
|
|
24852
|
+
expoDevAbort.abort();
|
|
24853
|
+
Promise.all([
|
|
24854
|
+
metroSession?.close().catch(() => {
|
|
24855
|
+
return;
|
|
24856
|
+
}),
|
|
24857
|
+
localNativeSession?.close().catch(() => {
|
|
24858
|
+
return;
|
|
24859
|
+
}),
|
|
24860
|
+
remoteSession?.close().catch(() => {
|
|
24861
|
+
return;
|
|
24862
|
+
})
|
|
24863
|
+
]);
|
|
24645
24864
|
expoDevState = "failed";
|
|
24646
24865
|
if (cleaning && error instanceof Error && error.name === "AbortError") {
|
|
24647
24866
|
return;
|
|
24648
24867
|
}
|
|
24649
24868
|
sendTelemetryEvent("mobile:expo-dev-failed", {
|
|
24650
24869
|
phase: expoDevState,
|
|
24651
|
-
platforms:
|
|
24870
|
+
platforms: [
|
|
24871
|
+
...project.platforms,
|
|
24872
|
+
...project.remoteIos ? ["ios"] : []
|
|
24873
|
+
],
|
|
24652
24874
|
provider: "expo"
|
|
24653
24875
|
});
|
|
24654
24876
|
console.error(cliTag("\x1B[31m", `Expo development failed: ${error instanceof Error ? error.message : String(error)}`));
|
|
@@ -25186,7 +25408,10 @@ var dev = async (serverEntry, configPath2, options = {}) => {
|
|
|
25186
25408
|
console.log(cliTag("\x1B[35m", `iOS target: ${target}; HMR port ${port}.`));
|
|
25187
25409
|
}
|
|
25188
25410
|
if (expoDevProject) {
|
|
25189
|
-
console.log(cliTag("\x1B[35m", `Expo targets: ${
|
|
25411
|
+
console.log(cliTag("\x1B[35m", `Expo targets: ${[
|
|
25412
|
+
...expoDevProject.platforms,
|
|
25413
|
+
...expoDevProject.remoteIos ? ["ios (Remote Mac)"] : []
|
|
25414
|
+
].join(", ")}; state ${expoDevState}; Metro ${expoMetroPort ?? "not allocated"}; AbsoluteJS HMR ${port}.`));
|
|
25190
25415
|
}
|
|
25191
25416
|
},
|
|
25192
25417
|
relaunchDevice: async () => {
|