@absolutejs/absolute 0.20.0-beta.33 → 0.20.0-beta.34

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.
@@ -2580,17 +2580,134 @@ var waitForAbsoluteIosHmrLog = async (options) => {
2580
2580
  return poll();
2581
2581
  };
2582
2582
  // src/mobile/iosSimulatorController.ts
2583
- import { createHash as createHash6, randomUUID as randomUUID2 } from "crypto";
2583
+ import { createHash as createHash6, randomUUID as randomUUID3 } from "crypto";
2584
2584
  import {
2585
2585
  access as access6,
2586
2586
  copyFile as copyFile4,
2587
2587
  mkdir as mkdir5,
2588
- readFile as readFile7,
2588
+ readFile as readFile8,
2589
2589
  rename as rename6,
2590
2590
  rm as rm5,
2591
2591
  writeFile as writeFile6
2592
2592
  } from "fs/promises";
2593
+ import { isIP as isIP2 } from "net";
2593
2594
  import { dirname as dirname4, isAbsolute as isAbsolute4, join as join6, relative as relative5, resolve as resolve5, sep as sep4 } from "path";
2595
+
2596
+ // src/mobile/iosPhysicalDeviceTransport.ts
2597
+ import { randomUUID as randomUUID2, X509Certificate } from "crypto";
2598
+ import { createServer } from "http";
2599
+ import {
2600
+ connect as connectTcp,
2601
+ createServer as createTcpServer,
2602
+ isIP
2603
+ } from "net";
2604
+ import { readFile as readFile7 } from "fs/promises";
2605
+ var closeServer = (server) => new Promise((resolve5, reject) => {
2606
+ server.close((error) => {
2607
+ if (error)
2608
+ reject(error);
2609
+ else
2610
+ resolve5();
2611
+ });
2612
+ });
2613
+ var listen = (server, port) => new Promise((resolve5, reject) => {
2614
+ server.once("error", reject);
2615
+ server.listen(port, "0.0.0.0", () => {
2616
+ server.off("error", reject);
2617
+ const address = server.address();
2618
+ if (!address || typeof address === "string") {
2619
+ reject(new Error("Could not determine the iOS device helper port."));
2620
+ return;
2621
+ }
2622
+ resolve5(address.port);
2623
+ });
2624
+ });
2625
+ var findEphemeralPort = async () => {
2626
+ const probe = createTcpServer();
2627
+ const port = await new Promise((resolve5, reject) => {
2628
+ probe.once("error", reject);
2629
+ probe.listen(0, "127.0.0.1", () => {
2630
+ const address = probe.address();
2631
+ if (!address || typeof address === "string") {
2632
+ reject(new Error("Could not allocate the iOS CA enrollment port."));
2633
+ return;
2634
+ }
2635
+ resolve5(address.port);
2636
+ });
2637
+ });
2638
+ await closeServer(probe);
2639
+ return port;
2640
+ };
2641
+ var normalizeAbsoluteIosDeviceHost = (value) => {
2642
+ const normalized = value.trim();
2643
+ if (!normalized || normalized.length > 253 || /[\0\s/?#]/u.test(normalized))
2644
+ throw new TypeError("Physical iOS development requires a valid LAN host.");
2645
+ return normalized;
2646
+ };
2647
+ var normalizeAbsoluteIosDeviceIdentifier = (value) => {
2648
+ const normalized = value.trim();
2649
+ if (!normalized || normalized.length > 256 || /[\0\r\n]/u.test(normalized))
2650
+ throw new TypeError("--ios-device requires a valid Xcode device identifier or name.");
2651
+ return normalized;
2652
+ };
2653
+ var urlForHost = (protocol, host, port) => {
2654
+ const url = new URL(`${protocol}://localhost:${port}`);
2655
+ const normalizedHost = normalizeAbsoluteIosDeviceHost(host);
2656
+ url.hostname = isIP(normalizedHost) === 6 ? `[${normalizedHost}]` : normalizedHost;
2657
+ return url;
2658
+ };
2659
+ var startAbsoluteIosCaEnrollmentServer = async (options) => {
2660
+ const certificate = new X509Certificate(await readFile7(options.certificateAuthorityPath));
2661
+ const certificateBytes = certificate.raw;
2662
+ const token = randomUUID2().replaceAll("-", "");
2663
+ const certificatePath = `/${token}/absolutejs-development-ca.cer`;
2664
+ const server = createServer((request, response) => {
2665
+ if (request.method !== "GET" || request.url !== certificatePath) {
2666
+ response.writeHead(404, {
2667
+ "Cache-Control": "no-store",
2668
+ "Content-Type": "text/plain; charset=utf-8"
2669
+ });
2670
+ response.end("Not found.");
2671
+ return;
2672
+ }
2673
+ response.writeHead(200, {
2674
+ "Cache-Control": "no-store",
2675
+ "Content-Disposition": 'attachment; filename="absolutejs-development-ca.cer"',
2676
+ "Content-Length": String(certificateBytes.byteLength),
2677
+ "Content-Type": "application/x-x509-ca-cert",
2678
+ "X-Content-Type-Options": "nosniff"
2679
+ });
2680
+ response.end(certificateBytes);
2681
+ });
2682
+ const port = await findEphemeralPort();
2683
+ await listen(server, port);
2684
+ const url = urlForHost("http", options.displayHost, port);
2685
+ url.pathname = certificatePath;
2686
+ return {
2687
+ url: url.href,
2688
+ close: () => closeServer(server)
2689
+ };
2690
+ };
2691
+ var startAbsoluteIosTcpRelay = async (options) => {
2692
+ const server = createTcpServer((downstream) => {
2693
+ const upstream = connectTcp({
2694
+ host: "127.0.0.1",
2695
+ port: options.targetPort
2696
+ });
2697
+ downstream.pipe(upstream);
2698
+ upstream.pipe(downstream);
2699
+ const closePeer = () => {
2700
+ downstream.destroy();
2701
+ upstream.destroy();
2702
+ };
2703
+ downstream.once("error", closePeer);
2704
+ upstream.once("error", closePeer);
2705
+ });
2706
+ await listen(server, options.listenPort);
2707
+ return { close: () => closeServer(server) };
2708
+ };
2709
+
2710
+ // src/mobile/iosSimulatorController.ts
2594
2711
  init_getDurationString();
2595
2712
  var ABSOLUTE_IOS_SIMULATOR_NAME = "AbsoluteJS iPhone";
2596
2713
  var BOOT_TIMEOUT_MS = 180000;
@@ -2716,6 +2833,24 @@ var trustIosSimulatorDevelopmentCa = async (options, udid, run, log) => {
2716
2833
  ], "iOS Simulator development CA trust", run, { signal: options.signal });
2717
2834
  log("Installed the AbsoluteJS development CA into this iOS Simulator trust store.");
2718
2835
  };
2836
+ var iosLaunchCommand = (project, udid, physical) => physical ? [
2837
+ project.xcrun,
2838
+ "devicectl",
2839
+ "device",
2840
+ "process",
2841
+ "launch",
2842
+ "--terminate-existing",
2843
+ "--device",
2844
+ udid,
2845
+ project.config.appId
2846
+ ] : [
2847
+ project.xcrun,
2848
+ "simctl",
2849
+ "launch",
2850
+ "--terminate-running-process",
2851
+ udid,
2852
+ project.config.appId
2853
+ ];
2719
2854
  var requireCapturedSuccess = (result, label) => {
2720
2855
  if (result.exitCode !== 0) {
2721
2856
  throw new Error(`${label} failed: ${result.stderr.trim() || result.stdout.trim() || `status ${result.exitCode}`}`);
@@ -2853,7 +2988,7 @@ var repairAbsoluteIosDevSession = async (projectRoot) => {
2853
2988
  await rm5(paths.root, { force: true, recursive: true });
2854
2989
  return false;
2855
2990
  }
2856
- const journal = await readFile7(paths.journal, "utf8").then((source) => parseJournal(JSON.parse(source))).catch(() => null);
2991
+ const journal = await readFile8(paths.journal, "utf8").then((source) => parseJournal(JSON.parse(source))).catch(() => null);
2857
2992
  if (!journal || !isInside(projectRoot, journal.nativeConfigPath) || !isInside(projectRoot, journal.infoPath) || !isInside(paths.root, journal.configBackupPath) || !isInside(paths.root, journal.infoBackupPath)) {
2858
2993
  throw new Error(`Refusing unsafe or invalid iOS dev journal at ${paths.journal}.`);
2859
2994
  }
@@ -2884,14 +3019,14 @@ var iosDevelopmentInfoPlist = (source, cleartext) => {
2884
3019
  <true/>
2885
3020
  </dict>`);
2886
3021
  };
2887
- var writeDevProjection = async (project, port, https) => {
3022
+ var writeDevProjection = async (project, port, https, serverHost = "localhost") => {
2888
3023
  const paths = journalPaths(project.projectRoot);
2889
3024
  await repairAbsoluteIosDevSession(project.projectRoot);
2890
3025
  const nativeConfigPath = join6(project.nativeDirectory, "App", "App", "capacitor.config.json");
2891
3026
  const infoPath = join6(project.nativeDirectory, "App", "App", "Info.plist");
2892
3027
  const [configSource, infoSource] = await Promise.all([
2893
- readFile7(nativeConfigPath, "utf8"),
2894
- readFile7(infoPath, "utf8")
3028
+ readFile8(nativeConfigPath, "utf8"),
3029
+ readFile8(infoPath, "utf8")
2895
3030
  ]);
2896
3031
  const parsed = JSON.parse(configSource);
2897
3032
  if (!isRecord3(parsed))
@@ -2913,6 +3048,7 @@ var writeDevProjection = async (project, port, https) => {
2913
3048
  flag: "wx"
2914
3049
  });
2915
3050
  const developmentUrl = new URL(`${https ? "https" : "http"}://localhost:${port}${project.config.entry}`);
3051
+ developmentUrl.hostname = isIP2(serverHost) === 6 ? `[${serverHost}]` : serverHost;
2916
3052
  developmentUrl.searchParams.set("__absolute_target", "capacitor-ios");
2917
3053
  const existingServer = parsed.server;
2918
3054
  parsed.server = {
@@ -2942,10 +3078,10 @@ var parseNativeCache = (value) => {
2942
3078
  ]))
2943
3079
  };
2944
3080
  };
2945
- var readNativeCache = (projectRoot) => readFile7(nativeCachePath(projectRoot), "utf8").then((source) => parseNativeCache(JSON.parse(source))).catch(() => null);
3081
+ var readNativeCache = (projectRoot) => readFile8(nativeCachePath(projectRoot), "utf8").then((source) => parseNativeCache(JSON.parse(source))).catch(() => null);
2946
3082
  var writeNativeCache = async (projectRoot, cache) => {
2947
3083
  const destination = nativeCachePath(projectRoot);
2948
- const temporary = `${destination}.${process.pid}.${randomUUID2()}.tmp`;
3084
+ const temporary = `${destination}.${process.pid}.${randomUUID3()}.tmp`;
2949
3085
  await mkdir5(dirname4(destination), { recursive: true });
2950
3086
  try {
2951
3087
  await writeFile6(temporary, `${JSON.stringify(cache, null, "\t")}
@@ -3034,6 +3170,31 @@ var installedAppIdentity = (project, udid, capture) => {
3034
3170
  ]);
3035
3171
  return result.exitCode === 0 && result.stdout.trim() ? result.stdout.trim() : undefined;
3036
3172
  };
3173
+ var validatePhysicalIosDevice = (project, identifier, capture) => {
3174
+ const result = capture([
3175
+ project.xcrun,
3176
+ "devicectl",
3177
+ "device",
3178
+ "info",
3179
+ "details",
3180
+ "--device",
3181
+ identifier
3182
+ ]);
3183
+ if (result.exitCode !== 0)
3184
+ throw new Error(`Physical iOS device ${JSON.stringify(identifier)} is unavailable: ${result.stderr.trim() || result.stdout.trim() || "pair it in Xcode Device Hub, trust this Mac, unlock it, and enable Developer Mode."}`);
3185
+ };
3186
+ var physicalIosAppIsInstalled = (project, identifier, capture) => {
3187
+ const result = capture([
3188
+ project.xcrun,
3189
+ "devicectl",
3190
+ "device",
3191
+ "info",
3192
+ "apps",
3193
+ "--device",
3194
+ identifier
3195
+ ]);
3196
+ return result.exitCode === 0 && result.stdout.includes(project.config.appId);
3197
+ };
3037
3198
  var buildIosDebugApp = async (project, udid, fingerprint, run, signal) => {
3038
3199
  const derivedDataPath = join6(project.projectRoot, ".absolutejs", "mobile", "ios-derived-data", createHash6("sha256").update(project.config.appId).digest("hex").slice(0, 16));
3039
3200
  await mkdir5(derivedDataPath, { recursive: true });
@@ -3056,6 +3217,61 @@ var buildIosDebugApp = async (project, udid, fingerprint, run, signal) => {
3056
3217
  throw new Error(`Xcode did not produce the simulator app at ${appPath}.`);
3057
3218
  return appPath;
3058
3219
  };
3220
+ var buildPhysicalIosDebugApp = async (project, identifier, run, signal) => {
3221
+ const derivedDataPath = join6(project.projectRoot, ".absolutejs", "mobile", "ios-derived-data", createHash6("sha256").update(project.config.appId).digest("hex").slice(0, 16));
3222
+ await mkdir5(derivedDataPath, { recursive: true });
3223
+ await requireSuccess2([
3224
+ project.xcodebuild,
3225
+ "-workspace",
3226
+ join6(project.nativeDirectory, "App", "App.xcworkspace"),
3227
+ "-scheme",
3228
+ "App",
3229
+ "-configuration",
3230
+ "Debug",
3231
+ "-destination",
3232
+ `platform=iOS,id=${identifier}`,
3233
+ "-derivedDataPath",
3234
+ derivedDataPath,
3235
+ "-allowProvisioningUpdates",
3236
+ "build"
3237
+ ], "iOS physical-device build (configure automatic signing and a Development Team in Xcode if this is the first run)", run, { cwd: project.nativeDirectory, signal });
3238
+ const appPath = join6(derivedDataPath, "Build", "Products", "Debug-iphoneos", "App.app");
3239
+ if (!await pathExists5(appPath))
3240
+ throw new Error(`Xcode did not produce the physical-device app at ${appPath}.`);
3241
+ return appPath;
3242
+ };
3243
+ var ensurePhysicalIosDebugApp = async (options) => {
3244
+ const cacheHit = options.cache?.appId === options.project.config.appId && options.cache.fingerprint === options.fingerprint && options.cache.installations[options.identifier] === options.fingerprint && physicalIosAppIsInstalled(options.project, options.identifier, options.capture);
3245
+ if (cacheHit) {
3246
+ options.log(`iOS native app is unchanged on the selected physical device; skipped Xcode build and install.`);
3247
+ return true;
3248
+ }
3249
+ options.log("iOS native inputs changed or the physical-device install is stale; rebuilding.");
3250
+ options.transition("building");
3251
+ const appPath = await buildPhysicalIosDebugApp(options.project, options.identifier, options.run, options.signal);
3252
+ throwIfAborted2(options.signal);
3253
+ options.transition("installing");
3254
+ await requireSuccess2([
3255
+ options.project.xcrun,
3256
+ "devicectl",
3257
+ "device",
3258
+ "install",
3259
+ "app",
3260
+ "--device",
3261
+ options.identifier,
3262
+ appPath
3263
+ ], "iOS physical-device app installation", options.run, { signal: options.signal });
3264
+ await writeNativeCache(options.project.projectRoot, {
3265
+ appId: options.project.config.appId,
3266
+ fingerprint: options.fingerprint,
3267
+ format: NATIVE_CACHE_FORMAT,
3268
+ installations: {
3269
+ ...options.cache?.appId === options.project.config.appId ? options.cache.installations : {},
3270
+ [options.identifier]: options.fingerprint
3271
+ }
3272
+ }).catch((error) => options.log(`iOS native cache could not be saved: ${error instanceof Error ? error.message : String(error)}`));
3273
+ return false;
3274
+ };
3059
3275
  var ensureIosDebugApp = async (options) => {
3060
3276
  const installed = installedAppIdentity(options.project, options.udid, options.capture);
3061
3277
  const cacheHit = options.cache?.appId === options.project.config.appId && options.cache.fingerprint === options.fingerprint && installed !== undefined && options.cache.installations[options.udid] === installed;
@@ -3102,7 +3318,18 @@ var attachNativeLogs = (project, udid, options) => {
3102
3318
  if (!options.nativeLog)
3103
3319
  return null;
3104
3320
  const start = options.startNativeLogs ?? defaultStartNativeLogs;
3105
- return start([
3321
+ const command = options.deviceIdentifier ? [
3322
+ project.xcrun,
3323
+ "devicectl",
3324
+ "device",
3325
+ "process",
3326
+ "launch",
3327
+ "--console",
3328
+ "--terminate-existing",
3329
+ "--device",
3330
+ udid,
3331
+ project.config.appId
3332
+ ] : [
3106
3333
  project.xcrun,
3107
3334
  "simctl",
3108
3335
  "spawn",
@@ -3115,7 +3342,8 @@ var attachNativeLogs = (project, udid, options) => {
3115
3342
  "debug",
3116
3343
  "--predicate",
3117
3344
  'process == "App"'
3118
- ], { signal: options.signal }, (line) => {
3345
+ ];
3346
+ return start(command, { signal: options.signal }, (line) => {
3119
3347
  const entry = parseAbsoluteIosLogLine(line);
3120
3348
  if (entry)
3121
3349
  options.nativeLog?.(entry);
@@ -3127,6 +3355,7 @@ var IOS_TIMING_PHASES = [
3127
3355
  ["fingerprinting", "fingerprint"],
3128
3356
  ["booting", "simulator"],
3129
3357
  ["connecting", "device ready"],
3358
+ ["enrolling-trust", "HTTPS trust"],
3130
3359
  ["checking-native", "app check"],
3131
3360
  ["building", "Xcode"],
3132
3361
  ["installing", "install"],
@@ -3139,12 +3368,13 @@ var timingSummary = (timings) => IOS_TIMING_PHASES.map(([phase, label]) => {
3139
3368
  }).filter((value) => value !== null).join(", ");
3140
3369
  var prepareAbsoluteIosDevProject = async (config, options) => {
3141
3370
  if (detectAbsoluteMobileHost() !== "macos")
3142
- throw new Error("iOS simulation requires macOS and Xcode.");
3371
+ throw new Error("iOS development requires macOS and Xcode.");
3372
+ const target = options.target ?? "simulator";
3143
3373
  const projectRoot = resolve5(options.projectRoot);
3144
3374
  const checks = await inspectAbsoluteMobileToolchain({ host: "macos" });
3145
- const failed = checks.filter((check) => check.platform === "ios" && (check.status === "fail" || check.status === "warn"));
3375
+ const failed = checks.filter((check) => check.platform === "ios" && !(target === "device" && check.id === "ios.runtime") && (check.status === "fail" || check.status === "warn"));
3146
3376
  if (failed.length > 0)
3147
- throw new Error(`iOS simulation is not ready: ${failed.map(({ label }) => label).join(", ")}.`);
3377
+ throw new Error(`iOS ${target} development is not ready: ${failed.map(({ label }) => label).join(", ")}.`);
3148
3378
  const xcrun = checks.find((check) => check.id === "ios.xcrun")?.path;
3149
3379
  const xcodebuild = checks.find((check) => check.id === "ios.xcodebuild")?.path;
3150
3380
  if (!xcrun || !xcodebuild)
@@ -3175,8 +3405,55 @@ var prepareAbsoluteIosDevProject = async (config, options) => {
3175
3405
  xcrun
3176
3406
  };
3177
3407
  };
3408
+ var preparePhysicalIosTarget = async (options) => {
3409
+ options.transition("connecting");
3410
+ validatePhysicalIosDevice(options.project, options.deviceIdentifier, options.capture);
3411
+ if (!options.startOptions.https)
3412
+ return {
3413
+ caEnrollmentServer: null,
3414
+ startedSimulator: false,
3415
+ udid: options.deviceIdentifier
3416
+ };
3417
+ if (!options.startOptions.certificateAuthorityPath)
3418
+ throw new Error("Physical iOS HTTPS development requires the AbsoluteJS development CA certificate.");
3419
+ options.transition("enrolling-trust");
3420
+ const startEnrollment = options.startOptions.startCaEnrollmentServer ?? startAbsoluteIosCaEnrollmentServer;
3421
+ const caEnrollmentServer = await startEnrollment({
3422
+ certificateAuthorityPath: options.startOptions.certificateAuthorityPath,
3423
+ displayHost: options.serverHost
3424
+ });
3425
+ options.log(`On the iOS device, open ${caEnrollmentServer.url}, install the AbsoluteJS development CA profile, then enable it under Settings > General > About > Certificate Trust Settings. This public CA endpoint exists only for this dev session.`);
3426
+ return {
3427
+ caEnrollmentServer,
3428
+ startedSimulator: false,
3429
+ udid: options.deviceIdentifier
3430
+ };
3431
+ };
3432
+ var prepareIosSimulatorTarget = async (options) => {
3433
+ options.transition("booting");
3434
+ const managed = await ensureManagedSimulator(options.project, options.capture);
3435
+ const { device } = managed;
3436
+ const startedSimulator = managed.created || device.state !== "Booted";
3437
+ bootSimulator(options.project, device, options.capture);
3438
+ options.spawn([
3439
+ "open",
3440
+ "-a",
3441
+ "Simulator",
3442
+ "--args",
3443
+ "-CurrentDeviceUDID",
3444
+ device.udid
3445
+ ]);
3446
+ options.transition("connecting");
3447
+ await waitForBootedSimulator(options.project, device.udid, options.capture, options.sleep, options.startOptions.signal);
3448
+ await requireSuccess2([options.project.xcrun, "simctl", "bootstatus", device.udid, "-b"], "iOS simulator boot readiness", options.run, { signal: options.startOptions.signal });
3449
+ await trustIosSimulatorDevelopmentCa(options.startOptions, device.udid, options.run, options.log);
3450
+ return { caEnrollmentServer: null, startedSimulator, udid: device.udid };
3451
+ };
3178
3452
  var startAbsoluteIosDevSession = async (options) => {
3179
3453
  const { project } = options;
3454
+ const deviceIdentifier = options.deviceIdentifier ? normalizeAbsoluteIosDeviceIdentifier(options.deviceIdentifier) : undefined;
3455
+ const targetKind = deviceIdentifier ? "device" : "simulator";
3456
+ const serverHost = deviceIdentifier ? normalizeAbsoluteIosDeviceHost(options.serverHost ?? "") : "localhost";
3180
3457
  const capture = options.capture ?? defaultCapture3;
3181
3458
  const run = options.run ?? defaultRun2;
3182
3459
  const sleep = options.sleep ?? Bun.sleep;
@@ -3204,6 +3481,7 @@ var startAbsoluteIosDevSession = async (options) => {
3204
3481
  options.onStateChange?.(next);
3205
3482
  };
3206
3483
  let nativeLogs = null;
3484
+ let caEnrollmentServer = null;
3207
3485
  const closeLogs = async () => {
3208
3486
  const stream = nativeLogs;
3209
3487
  nativeLogs = null;
@@ -3211,39 +3489,66 @@ var startAbsoluteIosDevSession = async (options) => {
3211
3489
  return;
3212
3490
  });
3213
3491
  };
3492
+ const relaunchTarget = async (udid) => {
3493
+ if (deviceIdentifier && options.nativeLog) {
3494
+ await closeLogs();
3495
+ nativeLogs = attachNativeLogs(project, udid, options);
3496
+ return;
3497
+ }
3498
+ await requireSuccess2(iosLaunchCommand(project, udid, deviceIdentifier !== undefined), "iOS app relaunch", run, { signal: options.signal });
3499
+ };
3214
3500
  try {
3215
3501
  await repairAbsoluteIosDevSession(project.projectRoot);
3216
3502
  throwIfAborted2(options.signal);
3217
3503
  transition("syncing");
3218
3504
  await requireSuccess2([project.cap, "sync", "ios"], "Capacitor iOS synchronization", run, { cwd: project.projectRoot, signal: options.signal });
3219
3505
  transition("configuring");
3220
- await writeDevProjection(project, options.port, options.https === true);
3506
+ await writeDevProjection(project, options.port, options.https === true, serverHost);
3221
3507
  throwIfAborted2(options.signal);
3222
3508
  const fingerprintStartedAt = performance.now();
3223
3509
  const fingerprintPromise = fingerprintAbsoluteIosDevProject(project).then((fingerprint2) => {
3224
3510
  timings.fingerprinting = performance.now() - fingerprintStartedAt;
3225
3511
  return fingerprint2;
3226
3512
  });
3227
- transition("booting");
3228
- const { created, device } = await ensureManagedSimulator(project, capture);
3229
- const startedSimulator = created || device.state !== "Booted";
3230
- bootSimulator(project, device, capture);
3231
- spawn([
3232
- "open",
3233
- "-a",
3234
- "Simulator",
3235
- "--args",
3236
- "-CurrentDeviceUDID",
3237
- device.udid
3238
- ]);
3239
- transition("connecting");
3240
- await waitForBootedSimulator(project, device.udid, capture, sleep, options.signal);
3241
- await requireSuccess2([project.xcrun, "simctl", "bootstatus", device.udid, "-b"], "iOS simulator boot readiness", run, { signal: options.signal });
3242
- await trustIosSimulatorDevelopmentCa(options, device.udid, run, log);
3513
+ const target = deviceIdentifier ? await preparePhysicalIosTarget({
3514
+ capture,
3515
+ deviceIdentifier,
3516
+ log,
3517
+ project,
3518
+ serverHost,
3519
+ startOptions: options,
3520
+ transition
3521
+ }) : await prepareIosSimulatorTarget({
3522
+ capture,
3523
+ log,
3524
+ project,
3525
+ run,
3526
+ sleep,
3527
+ spawn,
3528
+ startOptions: options,
3529
+ transition
3530
+ });
3531
+ const {
3532
+ caEnrollmentServer: targetCaEnrollmentServer,
3533
+ startedSimulator,
3534
+ udid
3535
+ } = target;
3536
+ caEnrollmentServer = targetCaEnrollmentServer;
3243
3537
  const fingerprint = await fingerprintPromise;
3244
3538
  transition("checking-native");
3245
- const nativeCacheHit = await ensureIosDebugApp({
3246
- cache: await readNativeCache(project.projectRoot),
3539
+ const cache = await readNativeCache(project.projectRoot);
3540
+ const nativeCacheHit = deviceIdentifier ? await ensurePhysicalIosDebugApp({
3541
+ cache,
3542
+ capture,
3543
+ fingerprint,
3544
+ identifier: deviceIdentifier,
3545
+ log,
3546
+ project,
3547
+ run,
3548
+ signal: options.signal,
3549
+ transition
3550
+ }) : await ensureIosDebugApp({
3551
+ cache,
3247
3552
  capture,
3248
3553
  fingerprint,
3249
3554
  log,
@@ -3251,24 +3556,18 @@ var startAbsoluteIosDevSession = async (options) => {
3251
3556
  run,
3252
3557
  signal: options.signal,
3253
3558
  transition,
3254
- udid: device.udid
3559
+ udid
3255
3560
  });
3256
3561
  throwIfAborted2(options.signal);
3257
3562
  if (options.nativeLog)
3258
3563
  transition("streaming-logs");
3259
- nativeLogs = attachNativeLogs(project, device.udid, options);
3564
+ nativeLogs = attachNativeLogs(project, udid, options);
3260
3565
  transition("launching");
3261
- await requireSuccess2([
3262
- project.xcrun,
3263
- "simctl",
3264
- "launch",
3265
- "--terminate-running-process",
3266
- device.udid,
3267
- project.config.appId
3268
- ], "iOS app launch", run, { signal: options.signal });
3566
+ if (!deviceIdentifier || !nativeLogs)
3567
+ await requireSuccess2(iosLaunchCommand(project, udid, deviceIdentifier !== undefined), "iOS app launch", run, { signal: options.signal });
3269
3568
  transition("ready");
3270
3569
  timings.total = performance.now() - startedAt;
3271
- log(`iOS simulator connected (${device.udid}) with HMR on port ${options.port} in ${getDurationString(timings.total)} (${nativeCacheHit ? "native cache hit" : "native build installed"}).`);
3570
+ log(`iOS ${targetKind} connected with HMR on port ${options.port} in ${getDurationString(timings.total)} (${nativeCacheHit ? "native cache hit" : "native build installed"}).`);
3272
3571
  log(`iOS startup: ${timingSummary(timings)}.`);
3273
3572
  let closed = false;
3274
3573
  const close = async () => {
@@ -3277,6 +3576,10 @@ var startAbsoluteIosDevSession = async (options) => {
3277
3576
  closed = true;
3278
3577
  transition("closing");
3279
3578
  await closeLogs();
3579
+ await caEnrollmentServer?.close().catch(() => {
3580
+ return;
3581
+ });
3582
+ caEnrollmentServer = null;
3280
3583
  await repairAbsoluteIosDevSession(project.projectRoot);
3281
3584
  transition("closed");
3282
3585
  };
@@ -3284,8 +3587,9 @@ var startAbsoluteIosDevSession = async (options) => {
3284
3587
  close,
3285
3588
  nativeCacheHit,
3286
3589
  startedSimulator,
3590
+ targetKind,
3287
3591
  timings: { ...timings },
3288
- udid: device.udid,
3592
+ udid,
3289
3593
  rebuild: async () => {
3290
3594
  if (closed)
3291
3595
  throw new Error("iOS development session is closed.");
@@ -3298,22 +3602,17 @@ var startAbsoluteIosDevSession = async (options) => {
3298
3602
  throw new Error("iOS development session is closed.");
3299
3603
  transition("launching");
3300
3604
  try {
3301
- await requireSuccess2([
3302
- project.xcrun,
3303
- "simctl",
3304
- "launch",
3305
- "--terminate-running-process",
3306
- device.udid,
3307
- project.config.appId
3308
- ], "iOS app relaunch", run, { signal: options.signal });
3605
+ await relaunchTarget(udid);
3309
3606
  transition("ready");
3310
- log(`iOS app relaunched on ${device.udid}.`);
3607
+ log(`iOS app relaunched on the selected ${targetKind}.`);
3311
3608
  } catch (error) {
3312
3609
  transition("failed");
3313
3610
  throw error;
3314
3611
  }
3315
3612
  },
3316
3613
  screenshot: async (destination) => {
3614
+ if (deviceIdentifier)
3615
+ throw new Error("Physical iOS screenshots are captured in Xcode Device Hub; the CLI never records a device screen automatically.");
3317
3616
  const resolved = resolve5(project.projectRoot, destination);
3318
3617
  if (!isInside(project.projectRoot, resolved))
3319
3618
  throw new Error("iOS screenshot destination must remain inside the project.");
@@ -3322,7 +3621,7 @@ var startAbsoluteIosDevSession = async (options) => {
3322
3621
  project.xcrun,
3323
3622
  "simctl",
3324
3623
  "io",
3325
- device.udid,
3624
+ udid,
3326
3625
  "screenshot",
3327
3626
  resolved
3328
3627
  ], "iOS simulator screenshot", run, { signal: options.signal });
@@ -3335,6 +3634,9 @@ var startAbsoluteIosDevSession = async (options) => {
3335
3634
  } catch (error) {
3336
3635
  transition("failed");
3337
3636
  await closeLogs();
3637
+ await caEnrollmentServer?.close().catch(() => {
3638
+ return;
3639
+ });
3338
3640
  await repairAbsoluteIosDevSession(project.projectRoot);
3339
3641
  throw error;
3340
3642
  }
@@ -3433,9 +3735,10 @@ var createAbsoluteIosNativeWatcher = async (options) => {
3433
3735
  };
3434
3736
  var isAbsoluteIosNativeRootInput = (path) => ROOT_NATIVE_INPUTS.has(basename(path));
3435
3737
  // src/mobile/remoteMacProtocol.ts
3436
- import { createHash as createHash7, randomUUID as randomUUID3 } from "crypto";
3437
- import { chmod, mkdir as mkdir6, readFile as readFile8, rename as rename7, writeFile as writeFile7 } from "fs/promises";
3738
+ import { createHash as createHash7, randomUUID as randomUUID4 } from "crypto";
3739
+ import { chmod, mkdir as mkdir6, readFile as readFile9, rename as rename7, writeFile as writeFile7 } from "fs/promises";
3438
3740
  import { homedir as homedir2 } from "os";
3741
+ import { isIP as isIP3 } from "net";
3439
3742
  import {
3440
3743
  dirname as dirname5,
3441
3744
  isAbsolute as isAbsolute5,
@@ -3462,7 +3765,7 @@ var emptyStore = () => ({
3462
3765
  });
3463
3766
  var loadStore = async (path = defaultProfilePath()) => {
3464
3767
  try {
3465
- const parsed = JSON.parse(await readFile8(path, "utf8"));
3768
+ const parsed = JSON.parse(await readFile9(path, "utf8"));
3466
3769
  if (parsed.format !== PROFILE_FORMAT || typeof parsed.profiles !== "object" || parsed.profiles === null || Array.isArray(parsed.profiles))
3467
3770
  throw new Error("Unsupported remote Mac profile format.");
3468
3771
  for (const [key, profile] of Object.entries(parsed.profiles)) {
@@ -3480,7 +3783,7 @@ var loadStore = async (path = defaultProfilePath()) => {
3480
3783
  };
3481
3784
  var saveStore = async (store, path = defaultProfilePath()) => {
3482
3785
  await mkdir6(dirname5(path), { recursive: true });
3483
- const temporary = `${path}.${randomUUID3()}.tmp`;
3786
+ const temporary = `${path}.${randomUUID4()}.tmp`;
3484
3787
  await writeFile7(temporary, `${JSON.stringify(store, null, 2)}
3485
3788
  `, {
3486
3789
  mode: 384
@@ -3581,6 +3884,19 @@ var inspectAbsoluteRemoteMac = async (destination, options = {}) => {
3581
3884
  throw new Error("The remote Mac must have full Xcode installed and selected.");
3582
3885
  return { bunPath, home, os: operatingSystem, xcodeVersion };
3583
3886
  };
3887
+ var inspectAbsoluteRemoteMacLanHost = async (profile, transport) => {
3888
+ const capture = transport?.capture ?? defaultTransport.capture;
3889
+ const script = `default_interface="$(/sbin/route -n get default 2>/dev/null | /usr/bin/awk '/interface:/{print $2; exit}')"; for interface in "$default_interface" en0 en1; do [ -n "$interface" ] || continue; address="$(/usr/sbin/ipconfig getifaddr "$interface" 2>/dev/null || true)"; if [ -n "$address" ]; then printf '%s\\n' "$address"; exit 0; fi; done; exit 1`;
3890
+ const result = await capture([
3891
+ ...absoluteRemoteMacSshBase(profile),
3892
+ "/bin/sh -lc",
3893
+ shellQuote(script)
3894
+ ]);
3895
+ const host = requireRemoteSuccess(result, "Remote Mac LAN address discovery").trim();
3896
+ if (isIP3(host) === 0)
3897
+ throw new Error("The Remote Mac did not report a device-reachable LAN address.");
3898
+ return host;
3899
+ };
3584
3900
  var listAbsoluteRemoteMacProfiles = async (profilePath) => {
3585
3901
  const store = await loadStore(profilePath);
3586
3902
  return {
@@ -3652,7 +3968,7 @@ var installAbsoluteRemoteMacAgent = async (project) => {
3652
3968
  ]);
3653
3969
  if (verified.exitCode === 0)
3654
3970
  return { ...artifact, remotePath, uploaded: false };
3655
- const temporary = posix.join(directory, `.agent-${randomUUID3()}.tmp`);
3971
+ const temporary = posix.join(directory, `.agent-${randomUUID4()}.tmp`);
3656
3972
  const installScript = [
3657
3973
  "set -eu",
3658
3974
  "umask 077",
@@ -3743,7 +4059,7 @@ var portableMobileConfig = (project) => ({
3743
4059
  var absoluteRemoteProjectSyncCommands = (project) => {
3744
4060
  const current = project.remoteProjectRoot;
3745
4061
  const parent = posix.dirname(current);
3746
- const staging = posix.join(parent, `.incoming-${randomUUID3()}`);
4062
+ const staging = posix.join(parent, `.incoming-${randomUUID4()}`);
3747
4063
  const previous = posix.join(parent, ".previous");
3748
4064
  const script = [
3749
4065
  "set -eu",
@@ -3835,7 +4151,13 @@ var startAbsoluteRemoteIosDevSession = async (options) => {
3835
4151
  await syncProject(options.project);
3836
4152
  const syncDuration = performance.now() - syncStartedAt;
3837
4153
  const encodedConfig = Buffer.from(JSON.stringify(portableMobileConfig(options.project))).toString("base64url");
3838
- const encodedCertificateAuthority = options.certificateAuthorityPath ? (await readFile8(options.certificateAuthorityPath)).toString("base64url") : undefined;
4154
+ const encodedCertificateAuthority = options.certificateAuthorityPath ? (await readFile9(options.certificateAuthorityPath)).toString("base64url") : undefined;
4155
+ const physicalDevice = options.deviceIdentifier !== undefined;
4156
+ let relayPort;
4157
+ if (physicalDevice)
4158
+ relayPort = options.port <= 49151 ? options.port + 16384 : options.port - 16384;
4159
+ if (physicalDevice && !options.serverHost)
4160
+ throw new Error("Remote physical iOS development requires the Remote Mac LAN host.");
3839
4161
  const remoteCommand = [
3840
4162
  `cd ${shellQuote(options.project.remoteProjectRoot)}`,
3841
4163
  "&&",
@@ -3850,14 +4172,22 @@ var startAbsoluteRemoteIosDevSession = async (options) => {
3850
4172
  "--certificate-authority",
3851
4173
  shellQuote(encodedCertificateAuthority)
3852
4174
  ] : [],
3853
- ...options.https ? ["--https"] : []
4175
+ ...options.https ? ["--https"] : [],
4176
+ ...options.deviceIdentifier ? [
4177
+ "--ios-device",
4178
+ shellQuote(options.deviceIdentifier),
4179
+ "--server-host",
4180
+ shellQuote(options.serverHost ?? ""),
4181
+ "--relay-port",
4182
+ String(relayPort)
4183
+ ] : []
3854
4184
  ].join(" ");
3855
4185
  const command = [
3856
4186
  ...absoluteRemoteMacSshBase(options.project.profile),
3857
4187
  "-o",
3858
4188
  "ExitOnForwardFailure=yes",
3859
4189
  "-R",
3860
- `${options.port}:127.0.0.1:${options.port}`,
4190
+ physicalDevice ? `127.0.0.1:${relayPort}:127.0.0.1:${options.port}` : `${options.port}:127.0.0.1:${options.port}`,
3861
4191
  "/bin/sh -lc",
3862
4192
  shellQuote(remoteCommand)
3863
4193
  ];
@@ -3945,7 +4275,7 @@ var startAbsoluteRemoteIosDevSession = async (options) => {
3945
4275
  };
3946
4276
  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.`);
3947
4277
  const request = (commandName) => {
3948
- const id = randomUUID3();
4278
+ const id = randomUUID4();
3949
4279
  const response = new Promise((resolve6, reject) => pending.set(id, { reject, resolve: resolve6 }));
3950
4280
  process2.stdin.write(`${JSON.stringify({ command: commandName, id, v: 1 })}
3951
4281
  `);
@@ -3978,6 +4308,7 @@ var startAbsoluteRemoteIosDevSession = async (options) => {
3978
4308
  close,
3979
4309
  nativeCacheHit: currentReady.nativeCacheHit,
3980
4310
  startedSimulator: currentReady.startedSimulator,
4311
+ targetKind: currentReady.targetKind,
3981
4312
  timings: currentReady.timings,
3982
4313
  udid: currentReady.udid,
3983
4314
  rebuild: async () => {
@@ -4019,7 +4350,7 @@ var startAbsoluteRemoteIosDevSession = async (options) => {
4019
4350
  import {
4020
4351
  access as access7,
4021
4352
  mkdir as mkdir7,
4022
- readFile as readFile9,
4353
+ readFile as readFile10,
4023
4354
  rename as rename8,
4024
4355
  rm as rm6,
4025
4356
  writeFile as writeFile8
@@ -4225,7 +4556,7 @@ var createAbsoluteMobileAssociationPlugin = (mobile, projectRoot, options = {})
4225
4556
  var writeAtomic = async (path, source) => {
4226
4557
  let current;
4227
4558
  try {
4228
- current = await readFile9(path, "utf8");
4559
+ current = await readFile10(path, "utf8");
4229
4560
  } catch (error) {
4230
4561
  if (!(error instanceof Error) || !("code" in error) || error.code !== "ENOENT") {
4231
4562
  throw error;
@@ -4250,7 +4581,7 @@ var assertOwnedOutput = async (root) => {
4250
4581
  const path = resolve7(root, OWNERSHIP_FILE);
4251
4582
  let ownership;
4252
4583
  try {
4253
- ownership = JSON.parse(await readFile9(path, "utf8"));
4584
+ ownership = JSON.parse(await readFile10(path, "utf8"));
4254
4585
  } catch {
4255
4586
  throw new TypeError(`Association output ${root} already exists and is not owned by AbsoluteJS.`);
4256
4587
  }
@@ -4386,13 +4717,13 @@ var parseAbsoluteMobileBuildPageMetadata = (value) => {
4386
4717
  };
4387
4718
  };
4388
4719
  // src/mobile/buildPipeline.ts
4389
- import { readFile as readFile13 } from "fs/promises";
4720
+ import { readFile as readFile14 } from "fs/promises";
4390
4721
  import { join as join14, resolve as resolve12 } from "path";
4391
4722
  import { pathToFileURL as pathToFileURL2 } from "url";
4392
4723
 
4393
4724
  // src/mobile/buildRelease.ts
4394
4725
  import { createHash as createHash8 } from "crypto";
4395
- import { mkdir as mkdir8, readFile as readFile10, writeFile as writeFile9 } from "fs/promises";
4726
+ import { mkdir as mkdir8, readFile as readFile11, writeFile as writeFile9 } from "fs/promises";
4396
4727
  import { basename as basename2, dirname as dirname6, extname, join as join8, relative as relative7, resolve as resolve8 } from "path";
4397
4728
  var sha256 = (bytes) => createHash8("sha256").update(bytes).digest("hex");
4398
4729
  var STATIC_SCRIPT_PATTERN = /(<script\b[^>]*?\bsrc\s*=\s*["'])(\/[^"']+\.(?:js|ts))(["'][^>]*>)/giu;
@@ -4419,7 +4750,7 @@ var pageFor = async (metadata, manifest, buildDirectory) => {
4419
4750
  }
4420
4751
  let resolvedAssetPath = resolveAssetPath(buildDirectory, assetPath);
4421
4752
  if (metadata.framework === "html" || metadata.framework === "htmx") {
4422
- const source = await readFile10(resolvedAssetPath, "utf8");
4753
+ const source = await readFile11(resolvedAssetPath, "utf8");
4423
4754
  const rewritten = rewriteStaticScriptPaths(source, manifest);
4424
4755
  const documentHash = sha256(new TextEncoder().encode(rewritten));
4425
4756
  resolvedAssetPath = join8(buildDirectory, ".absolutejs", "mobile-pages", `${documentHash}.html`);
@@ -4433,8 +4764,8 @@ var pageFor = async (metadata, manifest, buildDirectory) => {
4433
4764
  ].map((key) => manifest[key]).find((path) => typeof path === "string");
4434
4765
  const resolvedStylePath = styleAssetPath ? resolveAssetPath(buildDirectory, styleAssetPath) : undefined;
4435
4766
  const [bytes, styleBytes] = await Promise.all([
4436
- readFile10(resolvedAssetPath),
4437
- resolvedStylePath ? readFile10(resolvedStylePath) : undefined
4767
+ readFile11(resolvedAssetPath),
4768
+ resolvedStylePath ? readFile11(resolvedStylePath) : undefined
4438
4769
  ]);
4439
4770
  const bundlePath = `/${relative7(resolve8(buildDirectory), resolvedAssetPath).replaceAll("\\", "/")}`;
4440
4771
  const styleBundlePath = resolvedStylePath ? `/${relative7(resolve8(buildDirectory), resolvedStylePath).replaceAll("\\", "/")}` : undefined;
@@ -4454,7 +4785,7 @@ var pageFor = async (metadata, manifest, buildDirectory) => {
4454
4785
  var buildAbsoluteMobileCompatibilityRelease = async (options) => {
4455
4786
  const [captured, producerBytes] = await Promise.all([
4456
4787
  captureAbsoluteMobileRouteGraph(options.app),
4457
- readFile10(options.producerPath)
4788
+ readFile11(options.producerPath)
4458
4789
  ]);
4459
4790
  if (captured.length === 0) {
4460
4791
  throw new TypeError("No instrumented AbsoluteJS mobile page routes were found in the finalized Elysia route graph.");
@@ -4546,7 +4877,7 @@ import {
4546
4877
  copyFile as copyFile5,
4547
4878
  mkdir as mkdir9,
4548
4879
  mkdtemp as mkdtemp4,
4549
- readFile as readFile11,
4880
+ readFile as readFile12,
4550
4881
  rename as rename9,
4551
4882
  rm as rm7,
4552
4883
  writeFile as writeFile10
@@ -5076,7 +5407,7 @@ var resolveProjectImport = async (projectRoot, specifier) => {
5076
5407
  const packageName = specifier.startsWith("@") ? segments.slice(0, 2).join("/") : segments[0] ?? "";
5077
5408
  const subpath = specifier.slice(packageName.length);
5078
5409
  const packageDirectory = join9(resolve9(projectRoot), "node_modules", packageName);
5079
- const manifest = JSON.parse(await readFile11(join9(packageDirectory, "package.json"), "utf8"));
5410
+ const manifest = JSON.parse(await readFile12(join9(packageDirectory, "package.json"), "utf8"));
5080
5411
  const exports = typeof manifest === "object" && manifest !== null ? Reflect.get(manifest, "exports") : undefined;
5081
5412
  const entry = typeof exports === "object" && exports !== null ? Reflect.get(exports, subpath ? `.${subpath}` : ".") : undefined;
5082
5413
  const target = importEntryTarget(entry);
@@ -5184,7 +5515,7 @@ var copyClientPage = async (page, buildDirectory, staging, copiedDependencies) =
5184
5515
  };
5185
5516
  };
5186
5517
  var absoluteClientImports = async (sourcePath, buildDirectory) => {
5187
- const source = await readFile11(sourcePath, "utf8");
5518
+ const source = await readFile12(sourcePath, "utf8");
5188
5519
  const extension = extname2(sourcePath).toLowerCase();
5189
5520
  let scriptLoader;
5190
5521
  if (extension === ".tsx")
@@ -5295,7 +5626,7 @@ import {
5295
5626
  access as access8,
5296
5627
  mkdir as mkdir10,
5297
5628
  mkdtemp as mkdtemp5,
5298
- readFile as readFile12,
5629
+ readFile as readFile13,
5299
5630
  rename as rename10,
5300
5631
  rm as rm8,
5301
5632
  writeFile as writeFile11
@@ -5392,7 +5723,7 @@ var resolveProducerHandler = (loaded, exportName) => {
5392
5723
  };
5393
5724
  var loadAbsoluteMobileMaterializedBundle = async (root) => {
5394
5725
  const resolvedRoot = resolvePath3(root);
5395
- const serialized = await readFile12(join10(resolvedRoot, CURRENT_BUNDLE_FILE), "utf8");
5726
+ const serialized = await readFile13(join10(resolvedRoot, CURRENT_BUNDLE_FILE), "utf8");
5396
5727
  const parsed = JSON.parse(serialized);
5397
5728
  const index = parseBundleIndex(parsed);
5398
5729
  const bundleRoot = join10(resolvedRoot, BUNDLES_DIRECTORY, index.bundleId);
@@ -5447,7 +5778,7 @@ var materializeAbsoluteMobileCompatibilityBundle = async (input) => {
5447
5778
  var readAbsoluteMobileMaterializedReleases = async (root) => {
5448
5779
  const resolvedRoot = resolvePath3(root);
5449
5780
  try {
5450
- const serialized = await readFile12(join10(resolvedRoot, CURRENT_BUNDLE_FILE), "utf8");
5781
+ const serialized = await readFile13(join10(resolvedRoot, CURRENT_BUNDLE_FILE), "utf8");
5451
5782
  const parsed = JSON.parse(serialized);
5452
5783
  const index = parseBundleIndex(parsed);
5453
5784
  const bundleRoot = join10(resolvedRoot, BUNDLES_DIRECTORY, index.bundleId);
@@ -5558,7 +5889,7 @@ var finalizeAbsoluteMobileCompatibilityBuild = async (options) => {
5558
5889
  const mobile = normalizeAbsoluteMobileConfig(options.mobile, options.projectRoot);
5559
5890
  const root = join14(buildDirectory, ".absolutejs", "mobile-compatibility");
5560
5891
  const [manifestSource, previous] = await Promise.all([
5561
- readFile13(join14(buildDirectory, "manifest.json"), "utf8"),
5892
+ readFile14(join14(buildDirectory, "manifest.json"), "utf8"),
5562
5893
  readAbsoluteMobileMaterializedReleases(root)
5563
5894
  ]);
5564
5895
  const manifest = JSON.parse(manifestSource);
@@ -5957,7 +6288,7 @@ var createAbsoluteMobilePreviewPlugin = (mobile) => {
5957
6288
  });
5958
6289
  };
5959
6290
  // src/mobile/nativeDeepLinks.ts
5960
- import { readFile as readFile14, rename as rename11, writeFile as writeFile12 } from "fs/promises";
6291
+ import { readFile as readFile15, rename as rename11, writeFile as writeFile12 } from "fs/promises";
5961
6292
  import { join as join17 } from "path";
5962
6293
  var START_MARKER = "<!-- absolutejs:deep-links:start -->";
5963
6294
  var END_MARKER = "<!-- absolutejs:deep-links:end -->";
@@ -5965,7 +6296,7 @@ var IOS_ENTITLEMENTS = "App/AbsoluteJS.entitlements";
5965
6296
  var NOT_FOUND = -1;
5966
6297
  var escapeXml = (value) => value.replaceAll("&", "&amp;").replaceAll('"', "&quot;").replaceAll("'", "&apos;").replaceAll("<", "&lt;").replaceAll(">", "&gt;");
5967
6298
  var writeChangedFile = async (path, source) => {
5968
- const current = await readFile14(path, "utf8");
6299
+ const current = await readFile15(path, "utf8");
5969
6300
  if (current === source)
5970
6301
  return false;
5971
6302
  const temporary = `${path}.${crypto.randomUUID()}.tmp`;
@@ -6016,7 +6347,7 @@ ${hosts}
6016
6347
  };
6017
6348
  var configureAndroid = async (config) => {
6018
6349
  const path = join17(config.nativeProjectDirectory, "android/app/src/main/AndroidManifest.xml");
6019
- const source = await readFile14(path, "utf8");
6350
+ const source = await readFile15(path, "utf8");
6020
6351
  const mainActivity = source.indexOf('android:name=".MainActivity"');
6021
6352
  if (mainActivity === NOT_FOUND) {
6022
6353
  throw new TypeError("Android MainActivity was not found.");
@@ -6042,7 +6373,7 @@ var iosSchemeRegion = (scheme) => ` ${START_MARKER}
6042
6373
  `;
6043
6374
  var configureIosInfo = async (config) => {
6044
6375
  const path = join17(config.nativeProjectDirectory, "ios/App/App/Info.plist");
6045
- const source = await readFile14(path, "utf8");
6376
+ const source = await readFile15(path, "utf8");
6046
6377
  const region = config.deepLinkScheme ? iosSchemeRegion(config.deepLinkScheme) : ` ${START_MARKER}
6047
6378
  ${END_MARKER}
6048
6379
  `;
@@ -6068,7 +6399,7 @@ var configureIosEntitlements = async (config) => {
6068
6399
  const path = join17(config.nativeProjectDirectory, "ios/App/AbsoluteJS.entitlements");
6069
6400
  let current = "";
6070
6401
  try {
6071
- current = await readFile14(path, "utf8");
6402
+ current = await readFile15(path, "utf8");
6072
6403
  } catch (error) {
6073
6404
  if (!(error instanceof Error) || !("code" in error) || error.code !== "ENOENT") {
6074
6405
  throw error;
@@ -6084,7 +6415,7 @@ var configureIosEntitlements = async (config) => {
6084
6415
  };
6085
6416
  var configureIosProject = async (config) => {
6086
6417
  const path = join17(config.nativeProjectDirectory, "ios/App/App.xcodeproj/project.pbxproj");
6087
- const source = await readFile14(path, "utf8");
6418
+ const source = await readFile15(path, "utf8");
6088
6419
  const declarations = [
6089
6420
  ...source.matchAll(/CODE_SIGN_ENTITLEMENTS = ([^;]+);/g)
6090
6421
  ].map((match) => match[1]);
@@ -6123,7 +6454,7 @@ var applyAbsoluteNativeDeepLinks = async (config, platforms = config.platforms)
6123
6454
  };
6124
6455
  // src/mobile/nativeDeviceCapabilities.ts
6125
6456
  init_deviceCapabilities();
6126
- import { readFile as readFile15, rename as rename12, writeFile as writeFile13 } from "fs/promises";
6457
+ import { readFile as readFile16, rename as rename12, writeFile as writeFile13 } from "fs/promises";
6127
6458
  import { join as join18 } from "path";
6128
6459
  var START_MARKER2 = "<!-- absolutejs:device-capabilities:start -->";
6129
6460
  var END_MARKER2 = "<!-- absolutejs:device-capabilities:end -->";
@@ -6134,7 +6465,7 @@ var PUSH_START_MARKER = "absolutejs:push-notifications:start";
6134
6465
  var PUSH_END_MARKER = "absolutejs:push-notifications:end";
6135
6466
  var escapeXml2 = (value) => value.replaceAll("&", "&amp;").replaceAll('"', "&quot;").replaceAll("'", "&apos;").replaceAll("<", "&lt;").replaceAll(">", "&gt;");
6136
6467
  var writeChangedFile2 = async (path, source) => {
6137
- const current = await readFile15(path, "utf8");
6468
+ const current = await readFile16(path, "utf8");
6138
6469
  if (current === source)
6139
6470
  return false;
6140
6471
  const temporary = `${path}.${crypto.randomUUID()}.tmp`;
@@ -6154,7 +6485,7 @@ var writeOptionalChangedFile = async (path, source) => {
6154
6485
  };
6155
6486
  var optionalSource = async (path) => {
6156
6487
  try {
6157
- return await readFile15(path, "utf8");
6488
+ return await readFile16(path, "utf8");
6158
6489
  } catch (error) {
6159
6490
  if (typeof error === "object" && error !== null && Reflect.get(error, "code") === "ENOENT")
6160
6491
  return null;
@@ -6275,7 +6606,7 @@ var configureIosPrivacyProject = async (config, requirements) => {
6275
6606
  if (requirements.iosPrivacyAccessedApis.length === 0)
6276
6607
  return false;
6277
6608
  const projectPath = join18(config.nativeProjectDirectory, "ios/App/App.xcodeproj/project.pbxproj");
6278
- const project = await readFile15(projectPath, "utf8");
6609
+ const project = await readFile16(projectPath, "utf8");
6279
6610
  return writeChangedFile2(projectPath, addIosPrivacyProjectReference(project));
6280
6611
  };
6281
6612
  var addIosPrivacyProjectReference = (source) => {
@@ -6328,7 +6659,7 @@ ${next.slice(index)}`;
6328
6659
  };
6329
6660
  var configureIos2 = async (config, plan) => {
6330
6661
  const path = join18(config.nativeProjectDirectory, "ios/App/App/Info.plist");
6331
- const source = await readFile15(path, "utf8");
6662
+ const source = await readFile16(path, "utf8");
6332
6663
  const requirements = absoluteDeviceNativeRequirements(plan);
6333
6664
  const existingSystemBars = source.match(/<key>UIViewControllerBasedStatusBarAppearance<\/key>\s*<(true|false)\s*\/>/u);
6334
6665
  const ownedStart = source.indexOf(START_MARKER2);
@@ -6421,7 +6752,7 @@ var replacePushRegion = (source, region, insertion) => {
6421
6752
  };
6422
6753
  var configureAndroid2 = async (config, plan) => {
6423
6754
  const path = join18(config.nativeProjectDirectory, "android/app/src/main/AndroidManifest.xml");
6424
- const source = await readFile15(path, "utf8");
6755
+ const source = await readFile16(path, "utf8");
6425
6756
  const permissions = absoluteDeviceNativeRequirements(plan).androidPermissions;
6426
6757
  const content = permissions.map((permission) => ` <uses-permission android:name="${escapeXml2(permission)}" />`).join(`
6427
6758
  `);
@@ -7310,7 +7641,9 @@ export {
7310
7641
  validateAbsoluteRemoteMacProfileName,
7311
7642
  syncAbsoluteRemoteMacProject,
7312
7643
  startAbsoluteRemoteIosDevSession,
7644
+ startAbsoluteIosTcpRelay,
7313
7645
  startAbsoluteIosDevSession,
7646
+ startAbsoluteIosCaEnrollmentServer,
7314
7647
  serializeAbsoluteMobileAuthEnvironment,
7315
7648
  runWithAbsoluteMobileProducer,
7316
7649
  runAbsoluteAndroidUpgradeConformance,
@@ -7345,6 +7678,8 @@ export {
7345
7678
  parseAbsoluteAndroidInstalledApp,
7346
7679
  pairAbsoluteRemoteMac,
7347
7680
  normalizeAbsoluteMobileConfig,
7681
+ normalizeAbsoluteIosDeviceIdentifier,
7682
+ normalizeAbsoluteIosDeviceHost,
7348
7683
  navigateAbsoluteMobilePage,
7349
7684
  missingAbsoluteDeviceCapabilityPackages,
7350
7685
  materializeAbsoluteRemoteMacAgent,
@@ -7361,6 +7696,7 @@ export {
7361
7696
  installAbsoluteMobileSyncRemediation,
7362
7697
  installAbsoluteMobileShellHttp,
7363
7698
  installAbsoluteMobileAuthEnvironment,
7699
+ inspectAbsoluteRemoteMacLanHost,
7364
7700
  inspectAbsoluteRemoteMac,
7365
7701
  inspectAbsoluteMobileRouteMetadata,
7366
7702
  inspectAbsoluteAndroidInstalledApp,
@@ -7430,5 +7766,5 @@ export {
7430
7766
  ABSOLUTE_ANDROID_RELEASE_FORMAT
7431
7767
  };
7432
7768
 
7433
- //# debugId=558FB72C0F151C5864756E2164756E21
7769
+ //# debugId=ED7CBBBE08CD962364756E2164756E21
7434
7770
  //# sourceMappingURL=index.js.map