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

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,
@@ -3923,6 +3924,17 @@ var PROFILE_FORMAT = 1, REMOTE_STDIN_FLUSH_ATTEMPTS = 3, PROFILE_NAME, SSH_DESTI
3923
3924
  if (result.exitCode !== 0)
3924
3925
  throw new Error(`${label} failed: ${(result.stderr || result.stdout).trim() || `status ${result.exitCode}`}`);
3925
3926
  return result.stdout.trim();
3927
+ }, captureAbsoluteRemoteMacCommand = async (profile, command, transport) => {
3928
+ if (command.length === 0)
3929
+ throw new TypeError("A Remote Mac command cannot be empty.");
3930
+ if (command.some((argument) => /[\r\n\0]/u.test(argument)))
3931
+ throw new TypeError("Remote Mac command arguments cannot contain controls.");
3932
+ const capture = transport?.capture ?? defaultTransport.capture;
3933
+ return capture([
3934
+ ...absoluteRemoteMacSshBase(profile),
3935
+ "/bin/sh -lc",
3936
+ shellQuote(command.map((argument) => shellQuote(argument)).join(" "))
3937
+ ]);
3926
3938
  }, getAbsoluteRemoteMacProfile = async (name, profilePath) => {
3927
3939
  const store = await loadStore(profilePath);
3928
3940
  const selected = name ?? process.env.ABSOLUTE_IOS_REMOTE ?? store.defaultProfile;
@@ -18432,6 +18444,44 @@ var init_androidRelease = __esm(() => {
18432
18444
  init_androidEmulatorController();
18433
18445
  });
18434
18446
 
18447
+ // src/mobile/iosDeviceAcceptance.ts
18448
+ var absoluteIosDeviceAcceptanceCommands = (options) => {
18449
+ const xcrun = options.xcrun ?? "/usr/bin/xcrun";
18450
+ const prefix = [xcrun, "devicectl", "device"];
18451
+ return {
18452
+ apps: [...prefix, "info", "apps", "--device", options.device],
18453
+ details: [...prefix, "info", "details", "--device", options.device],
18454
+ launch: [
18455
+ ...prefix,
18456
+ "process",
18457
+ "launch",
18458
+ "--terminate-existing",
18459
+ "--device",
18460
+ options.device,
18461
+ options.appId
18462
+ ]
18463
+ };
18464
+ }, requireSuccess3 = (result, message) => {
18465
+ if (result.exitCode !== 0)
18466
+ throw new Error(message);
18467
+ return result;
18468
+ }, testAbsoluteIosPhysicalDevice = async (options) => {
18469
+ const commands = absoluteIosDeviceAcceptanceCommands(options);
18470
+ 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.");
18471
+ const apps = requireSuccess3(await options.capture(commands.apps), "AbsoluteJS could not inspect installed apps on the physical iOS device.");
18472
+ if (!apps.stdout.includes(options.appId))
18473
+ 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.");
18474
+ const now = options.now ?? performance.now.bind(performance);
18475
+ const startedAt = now();
18476
+ requireSuccess3(await options.capture(commands.launch), "AbsoluteJS could not relaunch the app on the physical iOS device.");
18477
+ await options.waitForHmr();
18478
+ return {
18479
+ hmrConnected: true,
18480
+ installed: true,
18481
+ relaunchMs: Math.round(now() - startedAt)
18482
+ };
18483
+ };
18484
+
18435
18485
  // src/mobile/iosConformance.ts
18436
18486
  import { readFile as readFile18, stat as stat3 } from "fs/promises";
18437
18487
  var HMR_LINE, parseAbsoluteIosHmrLog = (line) => {
@@ -18502,6 +18552,15 @@ var secretPattern, bearerPattern, coordinatePattern, nativeCredentialPattern, sa
18502
18552
  if (run.hmr)
18503
18553
  hmrResult = run.hmr.outcome === "failed" ? "FAIL" : "PASS";
18504
18554
  const routeDetails = run.routes?.length ? ` Routes: ${run.routes.join(", ")}.` : "";
18555
+ let artifactDetails = "No target screenshot was captured.";
18556
+ let artifactResult = "FAIL";
18557
+ if (run.screenshot) {
18558
+ artifactDetails = "A target screenshot was captured. Visually review it before sharing this directory.";
18559
+ artifactResult = "PASS";
18560
+ } else if (run.targetKind === "device") {
18561
+ artifactDetails = "Physical-device screen capture was intentionally skipped; use Xcode Device Hub for manual visual evidence.";
18562
+ artifactResult = "SKIPPED";
18563
+ }
18505
18564
  const checks = [
18506
18565
  {
18507
18566
  details: `Captured host, toolchain, Bun, and AbsoluteJS metadata for ${target}.`,
@@ -18520,10 +18579,10 @@ var secretPattern, bearerPattern, coordinatePattern, nativeCredentialPattern, sa
18520
18579
  result: hmrResult
18521
18580
  },
18522
18581
  {
18523
- details: run.screenshot ? "A target screenshot was captured. Visually review it before sharing this directory." : "No target screenshot was captured.",
18582
+ details: artifactDetails,
18524
18583
  ...evidence ? { evidence } : {},
18525
18584
  id: "AUTO-ARTIFACT-01",
18526
- result: run.screenshot ? "PASS" : "FAIL"
18585
+ result: artifactResult
18527
18586
  }
18528
18587
  ];
18529
18588
  if (run.upgrade) {
@@ -18556,15 +18615,30 @@ var secretPattern, bearerPattern, coordinatePattern, nativeCredentialPattern, sa
18556
18615
  result: Object.values(syncMigration.state).every(Boolean) ? "PASS" : "FAIL"
18557
18616
  });
18558
18617
  }
18618
+ if (run.deviceAcceptance) {
18619
+ checks.push({
18620
+ details: `The installed physical-device app relaunched and reconnected to native HMR in ${run.deviceAcceptance.relaunchMs}ms.`,
18621
+ id: "AUTO-DEVICE-01",
18622
+ result: "PASS"
18623
+ }, {
18624
+ 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.",
18625
+ id: "AUTO-DEVICE-HTTPS-01",
18626
+ result: run.deviceAcceptance.https ? "PASS" : "FAIL"
18627
+ }, {
18628
+ 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.",
18629
+ id: "AUTO-DEVICE-REMOTE-01",
18630
+ result: run.deviceAcceptance.remote ? "PASS" : "SKIPPED"
18631
+ });
18632
+ }
18559
18633
  return checks;
18560
18634
  }, createAbsoluteNativeTestReport = (options) => ({
18561
18635
  automatedChecks: options.automatedChecks ?? createAbsoluteNativeAutomatedChecks(options.run),
18562
18636
  generatedAt: options.generatedAt ?? new Date().toISOString(),
18563
- manualChecks: options.manualChecks.map(([id, details]) => ({
18637
+ manualChecks: options.manualChecks.map(([id, details]) => options.manualCheckResults?.[id] ?? {
18564
18638
  details,
18565
18639
  id,
18566
18640
  result: "NOT_RUN"
18567
- })),
18641
+ }),
18568
18642
  metadata: options.metadata,
18569
18643
  overallResult: options.run.status === "fail" ? "FAIL" : "INCOMPLETE",
18570
18644
  platform: options.run.platform,
@@ -18626,10 +18700,18 @@ var init_nativeTestReport = __esm(() => {
18626
18700
 
18627
18701
  // src/mobile/iosTestReport.ts
18628
18702
  var MANUAL_CHECKS, readPackageVersionForIosReport, sanitizeIosReportText, writeAbsoluteIosPartnerReport, createAbsoluteIosPartnerReport = (options) => {
18629
- const { udid, ...run } = options.run;
18703
+ const { targetId, targetKind, ...run } = options.run;
18704
+ const physicalResults = targetKind === "device" && run.deviceAcceptance ? {
18705
+ "DEVICEDEV-01": {
18706
+ details: "AbsoluteJS selected a physical target from the running development session without using Simulator.",
18707
+ id: "DEVICEDEV-01",
18708
+ result: "PASS"
18709
+ }
18710
+ } : undefined;
18630
18711
  return createAbsoluteNativeTestReport({
18631
18712
  ...options.generatedAt ? { generatedAt: options.generatedAt } : {},
18632
18713
  manualChecks: MANUAL_CHECKS,
18714
+ ...physicalResults ? { manualCheckResults: physicalResults } : {},
18633
18715
  metadata: {
18634
18716
  absolutejsVersion: options.absolutejsVersion,
18635
18717
  bunVersion: options.bunVersion,
@@ -18640,8 +18722,8 @@ var MANUAL_CHECKS, readPackageVersionForIosReport, sanitizeIosReportText, writeA
18640
18722
  run: {
18641
18723
  ...run,
18642
18724
  platform: "ios",
18643
- targetId: udid,
18644
- targetKind: "simulator"
18725
+ targetId,
18726
+ targetKind
18645
18727
  }
18646
18728
  });
18647
18729
  };
@@ -18658,6 +18740,10 @@ var init_iosTestReport = __esm(() => {
18658
18740
  ["SETUP-05", "Confirm generated iOS project signing and Xcode warnings."],
18659
18741
  ["DEV-01", "Record cold and warm bun dev startup timings."],
18660
18742
  ["DEV-02", "Complete route traversal, HMR, relaunch, and recovery checks."],
18743
+ ...Array.from({ length: 10 }, (_, index) => [
18744
+ `DEVICEDEV-${String(index + 1).padStart(2, "0")}`,
18745
+ `Complete physical-device development runbook check DEVICEDEV-${String(index + 1).padStart(2, "0")}.`
18746
+ ]),
18661
18747
  ["CAP-01", "Complete automatic device-capability provisioning checks."],
18662
18748
  ...Array.from({ length: 8 }, (_, index) => [
18663
18749
  `SYSUI-${String(index + 1).padStart(2, "0")}`,
@@ -19835,7 +19921,7 @@ Emulator setup verification:`);
19835
19921
  if (!instance?.logFile)
19836
19922
  throw new TypeError("The selected dev server has no session log. Run `bun dev` normally before requesting --wait-for-hmr.");
19837
19923
  if (!args.includes("--json"))
19838
- console.log("iOS simulator is ready. Save a source edit now; waiting for a native HMR acknowledgement\u2026");
19924
+ console.log("iOS app is ready. Save a source edit now; waiting for a native HMR acknowledgement\u2026");
19839
19925
  return waitForAbsoluteIosHmrLog({
19840
19926
  logPath: instance.logFile,
19841
19927
  timeoutMs
@@ -19845,7 +19931,7 @@ Emulator setup verification:`);
19845
19931
  console.log(JSON.stringify(report, null, 2));
19846
19932
  return;
19847
19933
  }
19848
- console.log(`\u2713 iOS simulator ${report.udid}: ${report.appId} launched; screenshot ${report.screenshot}.`);
19934
+ 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
19935
  if (!report.hmrApply)
19850
19936
  return;
19851
19937
  const timing = report.hmrApply.serverMs === undefined ? "" : ` (server ${report.hmrApply.serverMs}ms, client ${report.hmrApply.clientMs}ms)`;
@@ -19856,6 +19942,41 @@ Emulator setup verification:`);
19856
19942
  if (!xcrun)
19857
19943
  throw new TypeError("iOS simulator tools are unavailable. Run this command on macOS after `absolute mobile doctor ios --fix`.");
19858
19944
  return xcrun;
19945
+ }, runningIosDevice = (instance) => {
19946
+ if (!instance)
19947
+ return;
19948
+ const index = instance.command.indexOf("--ios-device");
19949
+ return index === NOT_FOUND3 ? undefined : instance.command[index + 1];
19950
+ }, physicalIosCapture = async (options) => {
19951
+ const remoteName = valueAfter(options.args, "--remote");
19952
+ if (remoteName && options.instance.iosRemoteMac && remoteName !== options.instance.iosRemoteMac)
19953
+ throw new TypeError("--remote must match the Remote Mac used by the running bun dev session.");
19954
+ const selectedRemoteName = remoteName ?? options.instance.iosRemoteMac;
19955
+ const remote = process.platform === "darwin" && !selectedRemoteName ? undefined : await getAbsoluteRemoteMacProfile(selectedRemoteName);
19956
+ if (process.platform !== "darwin" && !remote)
19957
+ throw new TypeError("Physical iOS acceptance requires macOS or a paired Remote Mac.");
19958
+ if (remote) {
19959
+ const macos = await captureAbsoluteRemoteMacCommand(remote, [
19960
+ "/usr/bin/sw_vers",
19961
+ "-productVersion"
19962
+ ]);
19963
+ if (macos.exitCode !== 0)
19964
+ throw new Error("Remote Mac version inspection failed.");
19965
+ return {
19966
+ macosVersion: macos.stdout.trim(),
19967
+ remote: true,
19968
+ xcodeVersion: remote.xcodeVersion,
19969
+ xcrun: "/usr/bin/xcrun",
19970
+ capture: (command) => captureAbsoluteRemoteMacCommand(remote, command)
19971
+ };
19972
+ }
19973
+ return {
19974
+ macosVersion: requireCapturedCommand(["/usr/bin/sw_vers", "-productVersion"], "macOS version inspection").stdout.trim(),
19975
+ remote: false,
19976
+ xcodeVersion: requireCapturedCommand(["/usr/bin/xcodebuild", "-version"], "Xcode version inspection").stdout.trim(),
19977
+ xcrun: "/usr/bin/xcrun",
19978
+ capture: async (command) => captureCommand4(command)
19979
+ };
19859
19980
  }, selectIosSimulator = (xcrun, explicitUdid) => {
19860
19981
  const result = captureCommand4([
19861
19982
  xcrun,
@@ -19961,12 +20082,124 @@ Emulator setup verification:`);
19961
20082
  const reportRoot = nativeReportRoot(options.args, options.projectRoot, "ios");
19962
20083
  if (!reportRoot)
19963
20084
  return;
19964
- const metadata = await iosReportMetadata(options.xcrun);
20085
+ const metadata = options.metadata ?? (options.xcrun ? await iosReportMetadata(options.xcrun) : undefined);
20086
+ if (!metadata)
20087
+ throw new Error("iOS report metadata could not be inspected.");
19965
20088
  const paths = await writeAbsoluteIosPartnerReport(reportRoot, createAbsoluteIosPartnerReport({ ...metadata, run: options.run }));
19966
20089
  const print = options.args.includes("--json") ? console.error : console.log;
19967
20090
  print(`iOS partner report: ${paths.markdownPath}`);
19968
20091
  print(`Return this report directory: ${paths.directory}`);
19969
20092
  return paths;
20093
+ }, testPhysicalIos = async (options) => {
20094
+ const {
20095
+ args,
20096
+ device,
20097
+ https,
20098
+ instance,
20099
+ mobile,
20100
+ port,
20101
+ projectRoot,
20102
+ timeoutMs
20103
+ } = options;
20104
+ const transport = await physicalIosCapture({ args, instance });
20105
+ const reportRoot = nativeReportRoot(args, projectRoot, "ios");
20106
+ const startedAt = performance.now();
20107
+ try {
20108
+ const acceptance = await testAbsoluteIosPhysicalDevice({
20109
+ appId: mobile.appId,
20110
+ capture: transport.capture,
20111
+ device,
20112
+ xcrun: transport.xcrun,
20113
+ waitForHmr: () => waitForIosHmrClient({ https, port, timeoutMs })
20114
+ });
20115
+ const hmrApply = await waitForRequestedIosHmr(args, instance, timeoutMs);
20116
+ const report = {
20117
+ appId: mobile.appId,
20118
+ durationMs: Math.round(performance.now() - startedAt),
20119
+ ...hmrApply ? { hmrApply } : {},
20120
+ hmrConnected: true,
20121
+ platform: "ios",
20122
+ port,
20123
+ provider: "capacitor",
20124
+ status: "pass",
20125
+ target: "device",
20126
+ targetId: "physical-device"
20127
+ };
20128
+ sendTelemetryEvent("mobile:ios-device-conformance", {
20129
+ durationMs: report.durationMs,
20130
+ platform: report.platform,
20131
+ provider: report.provider,
20132
+ remote: transport.remote,
20133
+ success: true,
20134
+ waitedForHmr: args.includes("--wait-for-hmr")
20135
+ });
20136
+ printIosTestReport(report, args.includes("--json"));
20137
+ await writeRequestedIosReport({
20138
+ args,
20139
+ metadata: {
20140
+ absolutejsVersion: await absolutejsVersionForReport(),
20141
+ bunVersion: Bun.version,
20142
+ macosVersion: transport.macosVersion,
20143
+ xcodeVersion: transport.xcodeVersion
20144
+ },
20145
+ projectRoot,
20146
+ run: {
20147
+ appId: report.appId,
20148
+ deviceAcceptance: {
20149
+ https: true,
20150
+ relaunchMs: acceptance.relaunchMs,
20151
+ remote: transport.remote
20152
+ },
20153
+ durationMs: report.durationMs,
20154
+ ...hmrApply ? {
20155
+ hmr: {
20156
+ durationMs: hmrApply.duration,
20157
+ outcome: hmrApply.outcome,
20158
+ ...hmrApply.clientMs === undefined ? {} : { clientMs: hmrApply.clientMs },
20159
+ ...hmrApply.serverMs === undefined ? {} : { serverMs: hmrApply.serverMs }
20160
+ }
20161
+ } : {},
20162
+ hmrConnected: true,
20163
+ port,
20164
+ status: "pass",
20165
+ targetId: "physical-device",
20166
+ targetKind: "device"
20167
+ }
20168
+ });
20169
+ return report;
20170
+ } catch (error) {
20171
+ const durationMs = Math.round(performance.now() - startedAt);
20172
+ sendTelemetryEvent("mobile:ios-device-conformance", {
20173
+ durationMs,
20174
+ platform: "ios",
20175
+ provider: "capacitor",
20176
+ remote: transport.remote,
20177
+ success: false,
20178
+ waitedForHmr: args.includes("--wait-for-hmr")
20179
+ });
20180
+ if (reportRoot)
20181
+ await writeRequestedIosReport({
20182
+ args,
20183
+ metadata: {
20184
+ absolutejsVersion: await absolutejsVersionForReport(),
20185
+ bunVersion: Bun.version,
20186
+ macosVersion: transport.macosVersion,
20187
+ xcodeVersion: transport.xcodeVersion
20188
+ },
20189
+ projectRoot,
20190
+ run: {
20191
+ appId: mobile.appId,
20192
+ durationMs,
20193
+ error: sanitizeIosReportText(error instanceof Error ? error.message : String(error)),
20194
+ hmrConnected: false,
20195
+ port,
20196
+ status: "fail",
20197
+ targetId: "physical-device",
20198
+ targetKind: "device"
20199
+ }
20200
+ });
20201
+ throw error;
20202
+ }
19970
20203
  }, testIos = async (args) => {
19971
20204
  const { mobile, projectRoot } = await loadMobile(valueAfter(args, "--config"));
19972
20205
  const { https, instance, port } = requireIosTestContext(args, projectRoot);
@@ -19975,6 +20208,35 @@ Emulator setup verification:`);
19975
20208
  if (args.includes("--route"))
19976
20209
  throw new TypeError("iOS simulator route selection is not exposed through simctl; configure mobile.entry for the native route matrix.");
19977
20210
  const timeoutMs = androidTestTimeout(args);
20211
+ const requestedDevice = valueAfter(args, "--device");
20212
+ if (args.includes("--device") && !requestedDevice)
20213
+ throw new TypeError("mobile test ios --device requires a device identifier or name.");
20214
+ if (requestedDevice && (valueAfter(args, "--udid") || valueAfter(args, "--serial")))
20215
+ throw new TypeError("mobile test ios --device cannot be combined with a simulator selector.");
20216
+ if (!requestedDevice && args.includes("--remote"))
20217
+ throw new TypeError("mobile test ios --remote is available only with --device.");
20218
+ if (requestedDevice) {
20219
+ const device = normalizeAbsoluteIosDeviceIdentifier(requestedDevice);
20220
+ const activeDevice = runningIosDevice(instance);
20221
+ if (!activeDevice)
20222
+ throw new TypeError("The selected dev server is not running a physical iOS session. Start bun dev with --ios-device first.");
20223
+ if (activeDevice !== device)
20224
+ throw new TypeError("--device must match the --ios-device value used by the running bun dev session.");
20225
+ if (!https)
20226
+ throw new TypeError("Physical iOS acceptance requires dev.https: true so the report can prove the native trust path.");
20227
+ if (!instance)
20228
+ throw new TypeError("Physical iOS acceptance requires a registered bun dev session.");
20229
+ return testPhysicalIos({
20230
+ args,
20231
+ device,
20232
+ https,
20233
+ instance,
20234
+ mobile,
20235
+ port,
20236
+ projectRoot,
20237
+ timeoutMs
20238
+ });
20239
+ }
19978
20240
  const xcrun = await requireIosXcrun();
19979
20241
  const simulator = selectIosSimulator(xcrun, valueAfter(args, "--udid") ?? valueAfter(args, "--serial"));
19980
20242
  const reportRoot = nativeReportRoot(args, projectRoot, "ios");
@@ -20012,7 +20274,8 @@ Emulator setup verification:`);
20012
20274
  provider: "capacitor",
20013
20275
  screenshot,
20014
20276
  status: "pass",
20015
- udid: simulator.udid
20277
+ target: "simulator",
20278
+ targetId: simulator.udid
20016
20279
  };
20017
20280
  sendTelemetryEvent("mobile:ios-conformance", {
20018
20281
  durationMs: report.durationMs,
@@ -20040,7 +20303,8 @@ Emulator setup verification:`);
20040
20303
  port: report.port,
20041
20304
  screenshot: report.screenshot,
20042
20305
  status: report.status,
20043
- udid: report.udid
20306
+ targetId: report.targetId,
20307
+ targetKind: report.target
20044
20308
  },
20045
20309
  xcrun
20046
20310
  });
@@ -20073,7 +20337,8 @@ Emulator setup verification:`);
20073
20337
  port,
20074
20338
  ...screenshot ? { screenshot } : {},
20075
20339
  status: "fail",
20076
- udid: simulator.udid
20340
+ targetId: simulator.udid,
20341
+ targetKind: "simulator"
20077
20342
  },
20078
20343
  xcrun
20079
20344
  });
@@ -20133,7 +20398,7 @@ Emulator setup verification:`);
20133
20398
  await publishIos(args.slice(2));
20134
20399
  return;
20135
20400
  }
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]");
20401
+ 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
20402
  };
20138
20403
  var init_mobile = __esm(() => {
20139
20404
  init_dependencies();
@@ -20154,6 +20419,7 @@ var init_mobile = __esm(() => {
20154
20419
  init_androidRelease();
20155
20420
  init_iosRelease();
20156
20421
  init_iosSimulatorController();
20422
+ init_iosPhysicalDeviceTransport();
20157
20423
  init_iosConformance();
20158
20424
  init_iosTestReport();
20159
20425
  init_androidTestReport();
@@ -21683,6 +21949,7 @@ var dev = async (serverEntry, configPath2, options = {}) => {
21683
21949
  frameworks: [],
21684
21950
  host: resolvedDev.host,
21685
21951
  https: httpsEnabled,
21952
+ ...selectedRemoteMacProfile ? { iosRemoteMac: selectedRemoteMacProfile.name } : {},
21686
21953
  logFile: instanceLogFile,
21687
21954
  name: resolveProjectName(process.cwd()),
21688
21955
  pid: instancePid,
package/dist/index.js CHANGED
@@ -16592,7 +16592,15 @@ import { existsSync as existsSync26, readFileSync as readFileSync25, promises as
16592
16592
  import { join as join38, basename as basename12, sep as sep3, dirname as dirname21, resolve as resolve29, relative as relative14 } from "path";
16593
16593
  var {Glob: Glob6 } = globalThis.Bun;
16594
16594
  import ts14 from "typescript";
16595
- var traceAngularPhase = async (name, fn2, metadata2) => {
16595
+ var atomicWriteSequence = 0, writeTextFileAtomically = async (path, content) => {
16596
+ const temporaryPath = `${path}.tmp.${process.pid}.${atomicWriteSequence++}`;
16597
+ try {
16598
+ await fs5.writeFile(temporaryPath, content, "utf-8");
16599
+ await fs5.rename(temporaryPath, path);
16600
+ } finally {
16601
+ await fs5.rm(temporaryPath, { force: true });
16602
+ }
16603
+ }, traceAngularPhase = async (name, fn2, metadata2) => {
16596
16604
  const tracePhase = globalThis.__absoluteBuildTracePhase;
16597
16605
  return tracePhase ? tracePhase(`compile/angular/${name}`, fn2, metadata2) : await fn2();
16598
16606
  }, readTsconfigPathAliases = () => {
@@ -16858,10 +16866,10 @@ var traceAngularPhase = async (name, fn2, metadata2) => {
16858
16866
  }
16859
16867
  }, writeResourceCacheFile = async (cachePath, source) => {
16860
16868
  await fs5.mkdir(dirname21(cachePath), { recursive: true });
16861
- await fs5.writeFile(cachePath, JSON.stringify({
16869
+ await writeTextFileAtomically(cachePath, JSON.stringify({
16862
16870
  source,
16863
16871
  version: 1
16864
- }), "utf-8");
16872
+ }));
16865
16873
  }, resolveResourceTransformCachePath = async (filePath, source, stylePreprocessors) => {
16866
16874
  const resourcePaths = collectAngularResourcePaths(source, dirname21(filePath));
16867
16875
  const resourceContents = await Promise.all(resourcePaths.map(async (resourcePath) => {
@@ -17047,7 +17055,7 @@ var traceAngularPhase = async (name, fn2, metadata2) => {
17047
17055
  });
17048
17056
  await traceAngularPhase("aot/write-output", () => Promise.all(entries.map(async ({ target, content }) => {
17049
17057
  await fs5.mkdir(dirname21(target), { recursive: true });
17050
- await fs5.writeFile(target, content, "utf-8");
17058
+ await writeTextFileAtomically(target, content);
17051
17059
  })), { outputs: entries.length });
17052
17060
  return await traceAngularPhase("aot/collect-output-paths", () => entries.map(({ target }) => target), { outputs: entries.length });
17053
17061
  }, compileAngularFile = async (inputPath, outDir, stylePreprocessors) => compileAngularFiles([inputPath], outDir, stylePreprocessors), jitContentCache, invalidateAngularJitCache = (filePath) => {
@@ -17512,7 +17520,7 @@ ${fields}
17512
17520
  const processedContent = transpileAndRewrite(sourceCode, relativeDir, actualPath, importRewrites);
17513
17521
  const preservedInjection = await readPreservedInjection(targetPath);
17514
17522
  await fs5.mkdir(targetDir, { recursive: true });
17515
- await fs5.writeFile(targetPath, processedContent + preservedInjection, "utf-8");
17523
+ await writeTextFileAtomically(targetPath, processedContent + preservedInjection);
17516
17524
  jitContentCache.set(cacheKey2, contentHash);
17517
17525
  }
17518
17526
  allOutputs.push(targetPath);
@@ -17528,7 +17536,7 @@ ${fields}
17528
17536
  export const __ABSOLUTE_PAGE_USES_LEGACY_ANIMATIONS__ = true;
17529
17537
  ` : withoutLegacyFlag;
17530
17538
  if (nextEntryOutput !== entryOutput) {
17531
- await fs5.writeFile(entryOutputPath, nextEntryOutput, "utf-8");
17539
+ await writeTextFileAtomically(entryOutputPath, nextEntryOutput);
17532
17540
  }
17533
17541
  }
17534
17542
  return allOutputs;
@@ -17698,7 +17706,7 @@ export const providers = [${fragments.join(", ")}];
17698
17706
  `;
17699
17707
  }
17700
17708
  }
17701
- await traceAngularPhase("wrapper/write-server-output", () => fs5.writeFile(rawServerFile, rewritten, "utf-8"), { entry: resolvedEntry });
17709
+ await traceAngularPhase("wrapper/write-server-output", () => writeTextFileAtomically(rawServerFile, rewritten), { entry: resolvedEntry });
17702
17710
  const relativePath = relative14(indexesDir, rawServerFile).replace(/\\/g, "/");
17703
17711
  const normalizedImportPath = relativePath.startsWith(".") ? relativePath : `./${relativePath}`;
17704
17712
  const hmrPreamble = hmr ? `window.__HMR_FRAMEWORK__ = "angular";
@@ -17897,7 +17905,7 @@ window.__ABSOLUTE_PAGE_DISPOSE__ = async function() {
17897
17905
  `.trim();
17898
17906
  const indexHash = Bun.hash(hydration).toString(BASE_36_RADIX);
17899
17907
  const indexUnchanged = cachedWrapper?.indexHash === indexHash;
17900
- await traceAngularPhase("wrapper/write-client-index", () => fs5.writeFile(clientFile, hydration, "utf-8"), { entry: resolvedEntry });
17908
+ await traceAngularPhase("wrapper/write-client-index", () => writeTextFileAtomically(clientFile, hydration), { entry: resolvedEntry });
17901
17909
  wrapperOutputCache.set(resolvedEntry, {
17902
17910
  indexHash,
17903
17911
  serverHash: serverContentHash
@@ -24389,6 +24397,7 @@ var createHMRState = (config) => ({
24389
24397
  lastBroadcastTimestamp: 0,
24390
24398
  manifest: {},
24391
24399
  moduleVersions: createModuleVersionTracker(),
24400
+ pendingBundleRebuilds: new Set,
24392
24401
  rebuildCount: 0,
24393
24402
  rebuildQueue: new Set,
24394
24403
  rebuildTimeout: null,
@@ -24700,7 +24709,7 @@ var safeRemoveFromGraph = (graph, fullPath) => {
24700
24709
  });
24701
24710
  }
24702
24711
  }, ATOMIC_WRITE_TEMP_PATTERNS, shouldSkipFilename = (filename, isStylesDir) => !isStylesDir && (filename === "compiled" || filename === "generated" || filename === "build" || filename === "indexes" || filename === "server" || filename === "client" || filename.includes("/compiled/") || filename.includes("/generated/") || filename.includes("/build/") || filename.includes("/indexes/") || filename.includes("/server/") || filename.includes("/client/") || filename.startsWith("compiled/") || filename.startsWith("generated/") || filename.startsWith("build/") || filename.startsWith("indexes/") || filename.startsWith("server/") || filename.startsWith("client/")) || filename.endsWith("/") || filename.includes(".tmp.") || filename.endsWith(".tmp") || filename.endsWith("~") || filename.startsWith(".#") || filename.startsWith(".absolutejs-hmr-") || ATOMIC_WRITE_TEMP_PATTERNS.some((pattern) => pattern.test(filename)), setupWatcher = (absolutePath, isStylesDir, state, onFileChange) => {
24703
- const ATOMIC_RECOVERY_WINDOW_MS = 5000;
24712
+ const ATOMIC_RECOVERY_WINDOW_MS = 60000;
24704
24713
  const atomicRecoveryScan = (eventDir) => {
24705
24714
  let entries;
24706
24715
  try {
@@ -27352,6 +27361,7 @@ var moduleServerPromise, getModuleServer = () => moduleServerPromise, clearDevSs
27352
27361
  }
27353
27362
  const DEBOUNCE_MS = config.options?.hmr?.debounceMs ?? DEFAULT_DEBOUNCE_MS;
27354
27363
  state.rebuildTimeout = setTimeout(() => {
27364
+ state.rebuildTimeout = null;
27355
27365
  drainQueueAndRebuild(state, config, onRebuildComplete);
27356
27366
  }, DEBOUNCE_MS);
27357
27367
  }, resolveComponentLookupFile = (componentFile, graph) => {
@@ -27755,6 +27765,7 @@ var moduleServerPromise, getModuleServer = () => moduleServerPromise, clearDevSs
27755
27765
  const { invalidateFingerprintCache: invalidateFingerprintCache2 } = await Promise.resolve().then(() => (init_fastHmrCompiler(), exports_fastHmrCompiler));
27756
27766
  invalidateFingerprintCache2();
27757
27767
  }, ANGULAR_BUNDLE_DEBOUNCE_MS = 2000, angularBundleState, scheduleAngularBundleRebuild = (state, pageEntries, angularDir) => {
27768
+ state.pendingBundleRebuilds.add("angular");
27758
27769
  let ctx = angularBundleState.get(state);
27759
27770
  if (!ctx) {
27760
27771
  ctx = {
@@ -27789,6 +27800,8 @@ var moduleServerPromise, getModuleServer = () => moduleServerPromise, clearDevSs
27789
27800
  }
27790
27801
  } finally {
27791
27802
  ctx.inFlight = null;
27803
+ if (!ctx.debounceTimer && !ctx.debouncedPromise && !ctx.pending)
27804
+ state.pendingBundleRebuilds.delete("angular");
27792
27805
  }
27793
27806
  };
27794
27807
  const fire = () => {
@@ -28296,6 +28309,7 @@ var moduleServerPromise, getModuleServer = () => moduleServerPromise, clearDevSs
28296
28309
  type: "svelte-tier-zero-ssr-rebuild-complete"
28297
28310
  });
28298
28311
  }, scheduleSvelteBundleRebuild = (state, svelteFiles, config) => {
28312
+ state.pendingBundleRebuilds.add("svelte");
28299
28313
  const ctx = getOrCreateBundleCtx(svelteBundleState, state);
28300
28314
  for (const file5 of svelteFiles)
28301
28315
  ctx.pendingFiles.add(file5);
@@ -28322,6 +28336,8 @@ var moduleServerPromise, getModuleServer = () => moduleServerPromise, clearDevSs
28322
28336
  }
28323
28337
  } finally {
28324
28338
  ctx.inFlight = null;
28339
+ if (!ctx.debounceTimer && !ctx.debouncedPromise && !ctx.pending && ctx.pendingFiles.size === 0)
28340
+ state.pendingBundleRebuilds.delete("svelte");
28325
28341
  }
28326
28342
  };
28327
28343
  const fire = () => {
@@ -28571,6 +28587,7 @@ var moduleServerPromise, getModuleServer = () => moduleServerPromise, clearDevSs
28571
28587
  type: "vue-tier-zero-ssr-rebuild-complete"
28572
28588
  });
28573
28589
  }, scheduleVueBundleRebuild = (state, vueFiles, config) => {
28590
+ state.pendingBundleRebuilds.add("vue");
28574
28591
  const ctx = getOrCreateBundleCtx(vueBundleState, state);
28575
28592
  for (const file5 of vueFiles)
28576
28593
  ctx.pendingFiles.add(file5);
@@ -28597,6 +28614,8 @@ var moduleServerPromise, getModuleServer = () => moduleServerPromise, clearDevSs
28597
28614
  }
28598
28615
  } finally {
28599
28616
  ctx.inFlight = null;
28617
+ if (!ctx.debounceTimer && !ctx.debouncedPromise && !ctx.pending && ctx.pendingFiles.size === 0)
28618
+ state.pendingBundleRebuilds.delete("vue");
28600
28619
  }
28601
28620
  };
28602
28621
  const fire = () => {
@@ -29459,6 +29478,7 @@ var moduleServerPromise, getModuleServer = () => moduleServerPromise, clearDevSs
29459
29478
  if (state.rebuildTimeout)
29460
29479
  clearTimeout(state.rebuildTimeout);
29461
29480
  state.rebuildTimeout = setTimeout(() => {
29481
+ state.rebuildTimeout = null;
29462
29482
  drainQueueAndRebuild(state, config, onRebuildComplete);
29463
29483
  }, REBUILD_BATCH_DELAY_MS);
29464
29484
  }, STYLE_FILE_EXT_RE, hasAngularOwnedStyleEdit = async (state, angularDir) => {
@@ -30551,8 +30571,11 @@ var STORE_KEY = "__elysiaStore", restoredStores, getGlobalValue = (key) => Refle
30551
30571
  entryWatcherReady: globalThis.__absoluteEntryWatcherReady === true,
30552
30572
  isRebuilding: hmrState2.isRebuilding,
30553
30573
  manifestKeys: Object.keys(manifest),
30574
+ pendingBundleRebuilds: Array.from(hmrState2.pendingBundleRebuilds),
30575
+ pendingFileChanges: Array.from(hmrState2.fileChangeQueue.values()).reduce((total, files) => total + files.length, 0),
30554
30576
  rebuildCount: hmrState2.rebuildCount,
30555
30577
  rebuildQueue: Array.from(hmrState2.rebuildQueue),
30578
+ rebuildScheduled: hmrState2.rebuildTimeout !== null,
30556
30579
  timestamp: Date.now()
30557
30580
  }));
30558
30581
  var init_hmr = __esm(() => {
@@ -40877,5 +40900,5 @@ export {
40877
40900
  ANGULAR_INIT_TIMEOUT_MS
40878
40901
  };
40879
40902
 
40880
- //# debugId=D2060DE03921305264756E2164756E21
40903
+ //# debugId=B33205E04E972F4064756E2164756E21
40881
40904
  //# sourceMappingURL=index.js.map