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

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/cli/index.js CHANGED
@@ -458,6 +458,7 @@ var registeredPids, exitHandlerRegistered = false, instanceFilePath = (pid) => j
458
458
  frameworks: toStringArray(parsed.frameworks),
459
459
  host: typeof parsed.host === "string" ? parsed.host : "localhost",
460
460
  https: parsed.https === true,
461
+ ...typeof parsed.iosRemoteMac === "string" ? { iosRemoteMac: parsed.iosRemoteMac } : {},
461
462
  logFile: typeof parsed.logFile === "string" ? parsed.logFile : null,
462
463
  name: typeof parsed.name === "string" ? parsed.name : "unknown",
463
464
  pid: parsed.pid,
@@ -2634,22 +2635,22 @@ var isRecord2 = (value) => typeof value === "object" && value !== null && !Array
2634
2635
  stdout: ""
2635
2636
  };
2636
2637
  }
2637
- }, ignoredFingerprintDirectories, fingerprintFiles = async (root, current = root) => {
2638
+ }, ignoredFingerprintDirectories, fingerprintFiles = async (root, current = root, options = {}) => {
2638
2639
  const entries = await readdir2(current, { withFileTypes: true });
2639
2640
  const nested = await Promise.all(entries.sort((left, right) => left.name.localeCompare(right.name)).map(async (entry) => {
2640
2641
  const path = join9(current, entry.name);
2641
2642
  const projectRelative = relative3(root, path).replaceAll("\\", "/");
2642
- const ignored = entry.isDirectory() && (ignoredFingerprintDirectories.has(entry.name) || projectRelative === "App/App/public");
2643
+ const ignored = entry.isDirectory() && (ignoredFingerprintDirectories.has(entry.name) || projectRelative === "App/App/public" && options.includePublicBundle !== true);
2643
2644
  if (ignored)
2644
2645
  return [];
2645
2646
  if (entry.isDirectory())
2646
- return fingerprintFiles(root, path);
2647
+ return fingerprintFiles(root, path, options);
2647
2648
  return entry.isFile() ? [path] : [];
2648
2649
  }));
2649
2650
  return nested.flat();
2650
- }, fingerprintAbsoluteIosNativeProject = async (nativeDirectory) => {
2651
+ }, fingerprintAbsoluteIosNativeProject = async (nativeDirectory, options = {}) => {
2651
2652
  const hasher = createHash3("sha256");
2652
- const files = await fingerprintFiles(nativeDirectory);
2653
+ const files = await fingerprintFiles(nativeDirectory, nativeDirectory, options);
2653
2654
  const contents = await Promise.all(files.map((file) => readFile4(file)));
2654
2655
  files.forEach((file, index) => {
2655
2656
  hasher.update(relative3(nativeDirectory, file).replaceAll("\\", "/"));
@@ -3298,7 +3299,7 @@ var ABSOLUTE_IOS_SIMULATOR_NAME = "AbsoluteJS iPhone", BOOT_TIMEOUT_MS = 180000,
3298
3299
  return;
3299
3300
  });
3300
3301
  }
3301
- }, fingerprintAbsoluteIosDevProject = async (project) => fingerprintAbsoluteIosNativeProject(project.nativeDirectory), simulatorInventory = (xcrun, capture) => {
3302
+ }, fingerprintAbsoluteIosDevProject = async (project, options = {}) => fingerprintAbsoluteIosNativeProject(project.nativeDirectory, options), simulatorInventory = (xcrun, capture) => {
3302
3303
  const result = capture([
3303
3304
  xcrun,
3304
3305
  "simctl",
@@ -3670,10 +3671,13 @@ var ABSOLUTE_IOS_SIMULATOR_NAME = "AbsoluteJS iPhone", BOOT_TIMEOUT_MS = 180000,
3670
3671
  transition("syncing");
3671
3672
  await requireSuccess2([project.cap, "sync", "ios"], "Capacitor iOS synchronization", run, { cwd: project.projectRoot, signal: options.signal });
3672
3673
  transition("configuring");
3673
- await writeDevProjection(project, options.port, options.https === true, serverHost);
3674
+ if (options.embeddedBundle !== true)
3675
+ await writeDevProjection(project, options.port, options.https === true, serverHost);
3674
3676
  throwIfAborted2(options.signal);
3675
3677
  const fingerprintStartedAt = performance.now();
3676
- const fingerprintPromise = fingerprintAbsoluteIosDevProject(project).then((fingerprint2) => {
3678
+ const fingerprintPromise = fingerprintAbsoluteIosDevProject(project, {
3679
+ includePublicBundle: options.embeddedBundle === true
3680
+ }).then((fingerprint2) => {
3677
3681
  timings.fingerprinting = performance.now() - fingerprintStartedAt;
3678
3682
  return fingerprint2;
3679
3683
  });
@@ -3734,7 +3738,7 @@ var ABSOLUTE_IOS_SIMULATOR_NAME = "AbsoluteJS iPhone", BOOT_TIMEOUT_MS = 180000,
3734
3738
  await requireSuccess2(iosLaunchCommand(project, udid, deviceIdentifier !== undefined), "iOS app launch", run, { signal: options.signal });
3735
3739
  transition("ready");
3736
3740
  timings.total = performance.now() - startedAt;
3737
- log(`iOS ${targetKind} connected with HMR on port ${options.port} in ${getDurationString(timings.total)} (${nativeCacheHit ? "native cache hit" : "native build installed"}).`);
3741
+ log(options.embeddedBundle === true ? `iOS ${targetKind} connected with the embedded bundle and backend on port ${options.port} in ${getDurationString(timings.total)} (${nativeCacheHit ? "native cache hit" : "native build installed"}).` : `iOS ${targetKind} connected with HMR on port ${options.port} in ${getDurationString(timings.total)} (${nativeCacheHit ? "native cache hit" : "native build installed"}).`);
3738
3742
  log(`iOS startup: ${timingSummary(timings)}.`);
3739
3743
  let closed = false;
3740
3744
  const close = async () => {
@@ -3923,6 +3927,17 @@ var PROFILE_FORMAT = 1, REMOTE_STDIN_FLUSH_ATTEMPTS = 3, PROFILE_NAME, SSH_DESTI
3923
3927
  if (result.exitCode !== 0)
3924
3928
  throw new Error(`${label} failed: ${(result.stderr || result.stdout).trim() || `status ${result.exitCode}`}`);
3925
3929
  return result.stdout.trim();
3930
+ }, captureAbsoluteRemoteMacCommand = async (profile, command, transport) => {
3931
+ if (command.length === 0)
3932
+ throw new TypeError("A Remote Mac command cannot be empty.");
3933
+ if (command.some((argument) => /[\r\n\0]/u.test(argument)))
3934
+ throw new TypeError("Remote Mac command arguments cannot contain controls.");
3935
+ const capture = transport?.capture ?? defaultTransport.capture;
3936
+ return capture([
3937
+ ...absoluteRemoteMacSshBase(profile),
3938
+ "/bin/sh -lc",
3939
+ shellQuote(command.map((argument) => shellQuote(argument)).join(" "))
3940
+ ]);
3926
3941
  }, getAbsoluteRemoteMacProfile = async (name, profilePath) => {
3927
3942
  const store = await loadStore(profilePath);
3928
3943
  const selected = name ?? process.env.ABSOLUTE_IOS_REMOTE ?? store.defaultProfile;
@@ -18432,6 +18447,44 @@ var init_androidRelease = __esm(() => {
18432
18447
  init_androidEmulatorController();
18433
18448
  });
18434
18449
 
18450
+ // src/mobile/iosDeviceAcceptance.ts
18451
+ var absoluteIosDeviceAcceptanceCommands = (options) => {
18452
+ const xcrun = options.xcrun ?? "/usr/bin/xcrun";
18453
+ const prefix = [xcrun, "devicectl", "device"];
18454
+ return {
18455
+ apps: [...prefix, "info", "apps", "--device", options.device],
18456
+ details: [...prefix, "info", "details", "--device", options.device],
18457
+ launch: [
18458
+ ...prefix,
18459
+ "process",
18460
+ "launch",
18461
+ "--terminate-existing",
18462
+ "--device",
18463
+ options.device,
18464
+ options.appId
18465
+ ]
18466
+ };
18467
+ }, requireSuccess3 = (result, message) => {
18468
+ if (result.exitCode !== 0)
18469
+ throw new Error(message);
18470
+ return result;
18471
+ }, testAbsoluteIosPhysicalDevice = async (options) => {
18472
+ const commands = absoluteIosDeviceAcceptanceCommands(options);
18473
+ requireSuccess3(await options.capture(commands.details), "The selected physical iOS device is unavailable. Pair it in Xcode Device Hub, trust this Mac, unlock it, and enable Developer Mode.");
18474
+ const apps = requireSuccess3(await options.capture(commands.apps), "AbsoluteJS could not inspect installed apps on the physical iOS device.");
18475
+ if (!apps.stdout.includes(options.appId))
18476
+ throw new Error("The AbsoluteJS app is not installed on the selected physical iOS device. Start bun dev with the same --ios-device value first.");
18477
+ const now = options.now ?? performance.now.bind(performance);
18478
+ const startedAt = now();
18479
+ requireSuccess3(await options.capture(commands.launch), "AbsoluteJS could not relaunch the app on the physical iOS device.");
18480
+ await options.waitForHmr();
18481
+ return {
18482
+ hmrConnected: true,
18483
+ installed: true,
18484
+ relaunchMs: Math.round(now() - startedAt)
18485
+ };
18486
+ };
18487
+
18435
18488
  // src/mobile/iosConformance.ts
18436
18489
  import { readFile as readFile18, stat as stat3 } from "fs/promises";
18437
18490
  var HMR_LINE, parseAbsoluteIosHmrLog = (line) => {
@@ -18502,6 +18555,15 @@ var secretPattern, bearerPattern, coordinatePattern, nativeCredentialPattern, sa
18502
18555
  if (run.hmr)
18503
18556
  hmrResult = run.hmr.outcome === "failed" ? "FAIL" : "PASS";
18504
18557
  const routeDetails = run.routes?.length ? ` Routes: ${run.routes.join(", ")}.` : "";
18558
+ let artifactDetails = "No target screenshot was captured.";
18559
+ let artifactResult = "FAIL";
18560
+ if (run.screenshot) {
18561
+ artifactDetails = "A target screenshot was captured. Visually review it before sharing this directory.";
18562
+ artifactResult = "PASS";
18563
+ } else if (run.targetKind === "device") {
18564
+ artifactDetails = "Physical-device screen capture was intentionally skipped; use Xcode Device Hub for manual visual evidence.";
18565
+ artifactResult = "SKIPPED";
18566
+ }
18505
18567
  const checks = [
18506
18568
  {
18507
18569
  details: `Captured host, toolchain, Bun, and AbsoluteJS metadata for ${target}.`,
@@ -18520,10 +18582,10 @@ var secretPattern, bearerPattern, coordinatePattern, nativeCredentialPattern, sa
18520
18582
  result: hmrResult
18521
18583
  },
18522
18584
  {
18523
- details: run.screenshot ? "A target screenshot was captured. Visually review it before sharing this directory." : "No target screenshot was captured.",
18585
+ details: artifactDetails,
18524
18586
  ...evidence ? { evidence } : {},
18525
18587
  id: "AUTO-ARTIFACT-01",
18526
- result: run.screenshot ? "PASS" : "FAIL"
18588
+ result: artifactResult
18527
18589
  }
18528
18590
  ];
18529
18591
  if (run.upgrade) {
@@ -18556,15 +18618,30 @@ var secretPattern, bearerPattern, coordinatePattern, nativeCredentialPattern, sa
18556
18618
  result: Object.values(syncMigration.state).every(Boolean) ? "PASS" : "FAIL"
18557
18619
  });
18558
18620
  }
18621
+ if (run.deviceAcceptance) {
18622
+ checks.push({
18623
+ details: `The installed physical-device app relaunched and reconnected to native HMR in ${run.deviceAcceptance.relaunchMs}ms.`,
18624
+ id: "AUTO-DEVICE-01",
18625
+ result: "PASS"
18626
+ }, {
18627
+ details: run.deviceAcceptance.https ? "The physical app reached the HTTPS development server and established native HMR; this proves the active app session accepted the development trust path." : "Physical-device acceptance did not use HTTPS.",
18628
+ id: "AUTO-DEVICE-HTTPS-01",
18629
+ result: run.deviceAcceptance.https ? "PASS" : "FAIL"
18630
+ }, {
18631
+ details: run.deviceAcceptance.remote ? "The lifecycle commands ran on the paired Remote Mac and HMR returned through the active relay." : "The acceptance run used the local Mac.",
18632
+ id: "AUTO-DEVICE-REMOTE-01",
18633
+ result: run.deviceAcceptance.remote ? "PASS" : "SKIPPED"
18634
+ });
18635
+ }
18559
18636
  return checks;
18560
18637
  }, createAbsoluteNativeTestReport = (options) => ({
18561
18638
  automatedChecks: options.automatedChecks ?? createAbsoluteNativeAutomatedChecks(options.run),
18562
18639
  generatedAt: options.generatedAt ?? new Date().toISOString(),
18563
- manualChecks: options.manualChecks.map(([id, details]) => ({
18640
+ manualChecks: options.manualChecks.map(([id, details]) => options.manualCheckResults?.[id] ?? {
18564
18641
  details,
18565
18642
  id,
18566
18643
  result: "NOT_RUN"
18567
- })),
18644
+ }),
18568
18645
  metadata: options.metadata,
18569
18646
  overallResult: options.run.status === "fail" ? "FAIL" : "INCOMPLETE",
18570
18647
  platform: options.run.platform,
@@ -18626,10 +18703,18 @@ var init_nativeTestReport = __esm(() => {
18626
18703
 
18627
18704
  // src/mobile/iosTestReport.ts
18628
18705
  var MANUAL_CHECKS, readPackageVersionForIosReport, sanitizeIosReportText, writeAbsoluteIosPartnerReport, createAbsoluteIosPartnerReport = (options) => {
18629
- const { udid, ...run } = options.run;
18706
+ const { targetId, targetKind, ...run } = options.run;
18707
+ const physicalResults = targetKind === "device" && run.deviceAcceptance ? {
18708
+ "DEVICEDEV-01": {
18709
+ details: "AbsoluteJS selected a physical target from the running development session without using Simulator.",
18710
+ id: "DEVICEDEV-01",
18711
+ result: "PASS"
18712
+ }
18713
+ } : undefined;
18630
18714
  return createAbsoluteNativeTestReport({
18631
18715
  ...options.generatedAt ? { generatedAt: options.generatedAt } : {},
18632
18716
  manualChecks: MANUAL_CHECKS,
18717
+ ...physicalResults ? { manualCheckResults: physicalResults } : {},
18633
18718
  metadata: {
18634
18719
  absolutejsVersion: options.absolutejsVersion,
18635
18720
  bunVersion: options.bunVersion,
@@ -18640,8 +18725,8 @@ var MANUAL_CHECKS, readPackageVersionForIosReport, sanitizeIosReportText, writeA
18640
18725
  run: {
18641
18726
  ...run,
18642
18727
  platform: "ios",
18643
- targetId: udid,
18644
- targetKind: "simulator"
18728
+ targetId,
18729
+ targetKind
18645
18730
  }
18646
18731
  });
18647
18732
  };
@@ -18658,6 +18743,10 @@ var init_iosTestReport = __esm(() => {
18658
18743
  ["SETUP-05", "Confirm generated iOS project signing and Xcode warnings."],
18659
18744
  ["DEV-01", "Record cold and warm bun dev startup timings."],
18660
18745
  ["DEV-02", "Complete route traversal, HMR, relaunch, and recovery checks."],
18746
+ ...Array.from({ length: 10 }, (_, index) => [
18747
+ `DEVICEDEV-${String(index + 1).padStart(2, "0")}`,
18748
+ `Complete physical-device development runbook check DEVICEDEV-${String(index + 1).padStart(2, "0")}.`
18749
+ ]),
18661
18750
  ["CAP-01", "Complete automatic device-capability provisioning checks."],
18662
18751
  ...Array.from({ length: 8 }, (_, index) => [
18663
18752
  `SYSUI-${String(index + 1).padStart(2, "0")}`,
@@ -19835,7 +19924,7 @@ Emulator setup verification:`);
19835
19924
  if (!instance?.logFile)
19836
19925
  throw new TypeError("The selected dev server has no session log. Run `bun dev` normally before requesting --wait-for-hmr.");
19837
19926
  if (!args.includes("--json"))
19838
- console.log("iOS simulator is ready. Save a source edit now; waiting for a native HMR acknowledgement\u2026");
19927
+ console.log("iOS app is ready. Save a source edit now; waiting for a native HMR acknowledgement\u2026");
19839
19928
  return waitForAbsoluteIosHmrLog({
19840
19929
  logPath: instance.logFile,
19841
19930
  timeoutMs
@@ -19845,7 +19934,7 @@ Emulator setup verification:`);
19845
19934
  console.log(JSON.stringify(report, null, 2));
19846
19935
  return;
19847
19936
  }
19848
- console.log(`\u2713 iOS simulator ${report.udid}: ${report.appId} launched; screenshot ${report.screenshot}.`);
19937
+ console.log(report.target === "device" ? `\u2713 Physical iOS app ${report.appId} relaunched and reconnected to HMR; no device identifier or screenshot was recorded.` : `\u2713 iOS simulator ${report.targetId}: ${report.appId} launched; screenshot ${report.screenshot}.`);
19849
19938
  if (!report.hmrApply)
19850
19939
  return;
19851
19940
  const timing = report.hmrApply.serverMs === undefined ? "" : ` (server ${report.hmrApply.serverMs}ms, client ${report.hmrApply.clientMs}ms)`;
@@ -19856,6 +19945,41 @@ Emulator setup verification:`);
19856
19945
  if (!xcrun)
19857
19946
  throw new TypeError("iOS simulator tools are unavailable. Run this command on macOS after `absolute mobile doctor ios --fix`.");
19858
19947
  return xcrun;
19948
+ }, runningIosDevice = (instance) => {
19949
+ if (!instance)
19950
+ return;
19951
+ const index = instance.command.indexOf("--ios-device");
19952
+ return index === NOT_FOUND3 ? undefined : instance.command[index + 1];
19953
+ }, physicalIosCapture = async (options) => {
19954
+ const remoteName = valueAfter(options.args, "--remote");
19955
+ if (remoteName && options.instance.iosRemoteMac && remoteName !== options.instance.iosRemoteMac)
19956
+ throw new TypeError("--remote must match the Remote Mac used by the running bun dev session.");
19957
+ const selectedRemoteName = remoteName ?? options.instance.iosRemoteMac;
19958
+ const remote = process.platform === "darwin" && !selectedRemoteName ? undefined : await getAbsoluteRemoteMacProfile(selectedRemoteName);
19959
+ if (process.platform !== "darwin" && !remote)
19960
+ throw new TypeError("Physical iOS acceptance requires macOS or a paired Remote Mac.");
19961
+ if (remote) {
19962
+ const macos = await captureAbsoluteRemoteMacCommand(remote, [
19963
+ "/usr/bin/sw_vers",
19964
+ "-productVersion"
19965
+ ]);
19966
+ if (macos.exitCode !== 0)
19967
+ throw new Error("Remote Mac version inspection failed.");
19968
+ return {
19969
+ macosVersion: macos.stdout.trim(),
19970
+ remote: true,
19971
+ xcodeVersion: remote.xcodeVersion,
19972
+ xcrun: "/usr/bin/xcrun",
19973
+ capture: (command) => captureAbsoluteRemoteMacCommand(remote, command)
19974
+ };
19975
+ }
19976
+ return {
19977
+ macosVersion: requireCapturedCommand(["/usr/bin/sw_vers", "-productVersion"], "macOS version inspection").stdout.trim(),
19978
+ remote: false,
19979
+ xcodeVersion: requireCapturedCommand(["/usr/bin/xcodebuild", "-version"], "Xcode version inspection").stdout.trim(),
19980
+ xcrun: "/usr/bin/xcrun",
19981
+ capture: async (command) => captureCommand4(command)
19982
+ };
19859
19983
  }, selectIosSimulator = (xcrun, explicitUdid) => {
19860
19984
  const result = captureCommand4([
19861
19985
  xcrun,
@@ -19961,12 +20085,124 @@ Emulator setup verification:`);
19961
20085
  const reportRoot = nativeReportRoot(options.args, options.projectRoot, "ios");
19962
20086
  if (!reportRoot)
19963
20087
  return;
19964
- const metadata = await iosReportMetadata(options.xcrun);
20088
+ const metadata = options.metadata ?? (options.xcrun ? await iosReportMetadata(options.xcrun) : undefined);
20089
+ if (!metadata)
20090
+ throw new Error("iOS report metadata could not be inspected.");
19965
20091
  const paths = await writeAbsoluteIosPartnerReport(reportRoot, createAbsoluteIosPartnerReport({ ...metadata, run: options.run }));
19966
20092
  const print = options.args.includes("--json") ? console.error : console.log;
19967
20093
  print(`iOS partner report: ${paths.markdownPath}`);
19968
20094
  print(`Return this report directory: ${paths.directory}`);
19969
20095
  return paths;
20096
+ }, testPhysicalIos = async (options) => {
20097
+ const {
20098
+ args,
20099
+ device,
20100
+ https,
20101
+ instance,
20102
+ mobile,
20103
+ port,
20104
+ projectRoot,
20105
+ timeoutMs
20106
+ } = options;
20107
+ const transport = await physicalIosCapture({ args, instance });
20108
+ const reportRoot = nativeReportRoot(args, projectRoot, "ios");
20109
+ const startedAt = performance.now();
20110
+ try {
20111
+ const acceptance = await testAbsoluteIosPhysicalDevice({
20112
+ appId: mobile.appId,
20113
+ capture: transport.capture,
20114
+ device,
20115
+ xcrun: transport.xcrun,
20116
+ waitForHmr: () => waitForIosHmrClient({ https, port, timeoutMs })
20117
+ });
20118
+ const hmrApply = await waitForRequestedIosHmr(args, instance, timeoutMs);
20119
+ const report = {
20120
+ appId: mobile.appId,
20121
+ durationMs: Math.round(performance.now() - startedAt),
20122
+ ...hmrApply ? { hmrApply } : {},
20123
+ hmrConnected: true,
20124
+ platform: "ios",
20125
+ port,
20126
+ provider: "capacitor",
20127
+ status: "pass",
20128
+ target: "device",
20129
+ targetId: "physical-device"
20130
+ };
20131
+ sendTelemetryEvent("mobile:ios-device-conformance", {
20132
+ durationMs: report.durationMs,
20133
+ platform: report.platform,
20134
+ provider: report.provider,
20135
+ remote: transport.remote,
20136
+ success: true,
20137
+ waitedForHmr: args.includes("--wait-for-hmr")
20138
+ });
20139
+ printIosTestReport(report, args.includes("--json"));
20140
+ await writeRequestedIosReport({
20141
+ args,
20142
+ metadata: {
20143
+ absolutejsVersion: await absolutejsVersionForReport(),
20144
+ bunVersion: Bun.version,
20145
+ macosVersion: transport.macosVersion,
20146
+ xcodeVersion: transport.xcodeVersion
20147
+ },
20148
+ projectRoot,
20149
+ run: {
20150
+ appId: report.appId,
20151
+ deviceAcceptance: {
20152
+ https: true,
20153
+ relaunchMs: acceptance.relaunchMs,
20154
+ remote: transport.remote
20155
+ },
20156
+ durationMs: report.durationMs,
20157
+ ...hmrApply ? {
20158
+ hmr: {
20159
+ durationMs: hmrApply.duration,
20160
+ outcome: hmrApply.outcome,
20161
+ ...hmrApply.clientMs === undefined ? {} : { clientMs: hmrApply.clientMs },
20162
+ ...hmrApply.serverMs === undefined ? {} : { serverMs: hmrApply.serverMs }
20163
+ }
20164
+ } : {},
20165
+ hmrConnected: true,
20166
+ port,
20167
+ status: "pass",
20168
+ targetId: "physical-device",
20169
+ targetKind: "device"
20170
+ }
20171
+ });
20172
+ return report;
20173
+ } catch (error) {
20174
+ const durationMs = Math.round(performance.now() - startedAt);
20175
+ sendTelemetryEvent("mobile:ios-device-conformance", {
20176
+ durationMs,
20177
+ platform: "ios",
20178
+ provider: "capacitor",
20179
+ remote: transport.remote,
20180
+ success: false,
20181
+ waitedForHmr: args.includes("--wait-for-hmr")
20182
+ });
20183
+ if (reportRoot)
20184
+ await writeRequestedIosReport({
20185
+ args,
20186
+ metadata: {
20187
+ absolutejsVersion: await absolutejsVersionForReport(),
20188
+ bunVersion: Bun.version,
20189
+ macosVersion: transport.macosVersion,
20190
+ xcodeVersion: transport.xcodeVersion
20191
+ },
20192
+ projectRoot,
20193
+ run: {
20194
+ appId: mobile.appId,
20195
+ durationMs,
20196
+ error: sanitizeIosReportText(error instanceof Error ? error.message : String(error)),
20197
+ hmrConnected: false,
20198
+ port,
20199
+ status: "fail",
20200
+ targetId: "physical-device",
20201
+ targetKind: "device"
20202
+ }
20203
+ });
20204
+ throw error;
20205
+ }
19970
20206
  }, testIos = async (args) => {
19971
20207
  const { mobile, projectRoot } = await loadMobile(valueAfter(args, "--config"));
19972
20208
  const { https, instance, port } = requireIosTestContext(args, projectRoot);
@@ -19975,6 +20211,35 @@ Emulator setup verification:`);
19975
20211
  if (args.includes("--route"))
19976
20212
  throw new TypeError("iOS simulator route selection is not exposed through simctl; configure mobile.entry for the native route matrix.");
19977
20213
  const timeoutMs = androidTestTimeout(args);
20214
+ const requestedDevice = valueAfter(args, "--device");
20215
+ if (args.includes("--device") && !requestedDevice)
20216
+ throw new TypeError("mobile test ios --device requires a device identifier or name.");
20217
+ if (requestedDevice && (valueAfter(args, "--udid") || valueAfter(args, "--serial")))
20218
+ throw new TypeError("mobile test ios --device cannot be combined with a simulator selector.");
20219
+ if (!requestedDevice && args.includes("--remote"))
20220
+ throw new TypeError("mobile test ios --remote is available only with --device.");
20221
+ if (requestedDevice) {
20222
+ const device = normalizeAbsoluteIosDeviceIdentifier(requestedDevice);
20223
+ const activeDevice = runningIosDevice(instance);
20224
+ if (!activeDevice)
20225
+ throw new TypeError("The selected dev server is not running a physical iOS session. Start bun dev with --ios-device first.");
20226
+ if (activeDevice !== device)
20227
+ throw new TypeError("--device must match the --ios-device value used by the running bun dev session.");
20228
+ if (!https)
20229
+ throw new TypeError("Physical iOS acceptance requires dev.https: true so the report can prove the native trust path.");
20230
+ if (!instance)
20231
+ throw new TypeError("Physical iOS acceptance requires a registered bun dev session.");
20232
+ return testPhysicalIos({
20233
+ args,
20234
+ device,
20235
+ https,
20236
+ instance,
20237
+ mobile,
20238
+ port,
20239
+ projectRoot,
20240
+ timeoutMs
20241
+ });
20242
+ }
19978
20243
  const xcrun = await requireIosXcrun();
19979
20244
  const simulator = selectIosSimulator(xcrun, valueAfter(args, "--udid") ?? valueAfter(args, "--serial"));
19980
20245
  const reportRoot = nativeReportRoot(args, projectRoot, "ios");
@@ -20012,7 +20277,8 @@ Emulator setup verification:`);
20012
20277
  provider: "capacitor",
20013
20278
  screenshot,
20014
20279
  status: "pass",
20015
- udid: simulator.udid
20280
+ target: "simulator",
20281
+ targetId: simulator.udid
20016
20282
  };
20017
20283
  sendTelemetryEvent("mobile:ios-conformance", {
20018
20284
  durationMs: report.durationMs,
@@ -20040,7 +20306,8 @@ Emulator setup verification:`);
20040
20306
  port: report.port,
20041
20307
  screenshot: report.screenshot,
20042
20308
  status: report.status,
20043
- udid: report.udid
20309
+ targetId: report.targetId,
20310
+ targetKind: report.target
20044
20311
  },
20045
20312
  xcrun
20046
20313
  });
@@ -20073,7 +20340,8 @@ Emulator setup verification:`);
20073
20340
  port,
20074
20341
  ...screenshot ? { screenshot } : {},
20075
20342
  status: "fail",
20076
- udid: simulator.udid
20343
+ targetId: simulator.udid,
20344
+ targetKind: "simulator"
20077
20345
  },
20078
20346
  xcrun
20079
20347
  });
@@ -20133,7 +20401,7 @@ Emulator setup verification:`);
20133
20401
  await publishIos(args.slice(2));
20134
20402
  return;
20135
20403
  }
20136
- throw new TypeError("Usage: absolute mobile <pair mac <name> <user@host> [--port n] [--workspace path] | remotes [--json] | unpair mac <name> | init [--no-native] [--force] | sync [ios|android] | associations [--outdir dir] [--verify] | doctor [ios|android|release] [--remote name] [--json|--fix [--yes]] | build <android|ios> [server-entry] [--outdir dir] [--web-outdir dir] [--unsigned] | publish android [server-entry] [--registry module] [--channel name] [--play-track track] [--play-status completed|draft|halted|in-progress] [--play-rollout fraction] [--play-name name] [--play-notes language=text] [--play-update-priority 0..5] [--play-hold-review] [--play-cancel-existing-review] [--outdir dir] [--web-outdir dir] [--unsigned] | publish ios [server-entry] [--registry module] [--channel name] [--testflight-group name-or-id] [--testflight-notes locale=text] [--testflight-submit-review] [--outdir dir] [--web-outdir dir] [--unsigned] | test android [--route path] [--wait-for-hmr] [--report [dir]] [--timeout ms] [--port n] [--serial id] [--artifacts dir] [--json] | test ios [--wait-for-hmr] [--report [dir]] [--timeout ms] [--port n] [--udid id] [--artifacts dir] [--json]> [--config path]");
20404
+ throw new TypeError("Usage: absolute mobile <pair mac <name> <user@host> [--port n] [--workspace path] | remotes [--json] | unpair mac <name> | init [--no-native] [--force] | sync [ios|android] | associations [--outdir dir] [--verify] | doctor [ios|android|release] [--remote name] [--json|--fix [--yes]] | build <android|ios> [server-entry] [--outdir dir] [--web-outdir dir] [--unsigned] | publish android [server-entry] [--registry module] [--channel name] [--play-track track] [--play-status completed|draft|halted|in-progress] [--play-rollout fraction] [--play-name name] [--play-notes language=text] [--play-update-priority 0..5] [--play-hold-review] [--play-cancel-existing-review] [--outdir dir] [--web-outdir dir] [--unsigned] | publish ios [server-entry] [--registry module] [--channel name] [--testflight-group name-or-id] [--testflight-notes locale=text] [--testflight-submit-review] [--outdir dir] [--web-outdir dir] [--unsigned] | test android [--route path] [--wait-for-hmr] [--report [dir]] [--timeout ms] [--port n] [--serial id] [--artifacts dir] [--json] | test ios [--device identifier [--remote name] | --udid id] [--wait-for-hmr] [--report [dir]] [--timeout ms] [--port n] [--artifacts dir] [--json]> [--config path]");
20137
20405
  };
20138
20406
  var init_mobile = __esm(() => {
20139
20407
  init_dependencies();
@@ -20154,6 +20422,7 @@ var init_mobile = __esm(() => {
20154
20422
  init_androidRelease();
20155
20423
  init_iosRelease();
20156
20424
  init_iosSimulatorController();
20425
+ init_iosPhysicalDeviceTransport();
20157
20426
  init_iosConformance();
20158
20427
  init_iosTestReport();
20159
20428
  init_androidTestReport();
@@ -21683,6 +21952,7 @@ var dev = async (serverEntry, configPath2, options = {}) => {
21683
21952
  frameworks: [],
21684
21953
  host: resolvedDev.host,
21685
21954
  https: httpsEnabled,
21955
+ ...selectedRemoteMacProfile ? { iosRemoteMac: selectedRemoteMacProfile.name } : {},
21686
21956
  logFile: instanceLogFile,
21687
21957
  name: resolveProjectName(process.cwd()),
21688
21958
  pid: instancePid,