@absolutejs/absolute 0.20.0-beta.50 → 0.20.0-beta.52

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.
@@ -1,7 +1,7 @@
1
1
  // @bun
2
2
  var __require = import.meta.require;
3
3
 
4
- // .angular-partial-tmp-fjProX/src/core/streamingSlotRegistrar.ts
4
+ // .angular-partial-tmp-x73pOK/src/core/streamingSlotRegistrar.ts
5
5
  var STREAMING_SLOT_REGISTRAR_KEY = Symbol.for("absolutejs.streamingSlotRegistrar");
6
6
  var STREAMING_SLOT_WARNING_STORAGE_KEY = Symbol.for("absolutejs.streamingSlotWarningController");
7
7
  var STREAMING_SLOT_COLLECTION_STORAGE_KEY = Symbol.for("absolutejs.streamingSlotCollectionController");
@@ -1,7 +1,7 @@
1
1
  // @bun
2
2
  var __require = import.meta.require;
3
3
 
4
- // .angular-partial-tmp-fjProX/src/core/streamingSlotRegistrar.ts
4
+ // .angular-partial-tmp-x73pOK/src/core/streamingSlotRegistrar.ts
5
5
  var STREAMING_SLOT_REGISTRAR_KEY = Symbol.for("absolutejs.streamingSlotRegistrar");
6
6
  var STREAMING_SLOT_WARNING_STORAGE_KEY = Symbol.for("absolutejs.streamingSlotWarningController");
7
7
  var STREAMING_SLOT_COLLECTION_STORAGE_KEY = Symbol.for("absolutejs.streamingSlotCollectionController");
@@ -48,7 +48,7 @@ var warnMissingStreamingSlotCollector = (primitiveName) => {
48
48
  getWarningController()?.maybeWarn(primitiveName);
49
49
  };
50
50
 
51
- // .angular-partial-tmp-fjProX/src/core/streamingSlotRegistry.ts
51
+ // .angular-partial-tmp-x73pOK/src/core/streamingSlotRegistry.ts
52
52
  var STREAMING_SLOT_STORAGE_KEY = Symbol.for("absolutejs.streamingSlotAsyncLocalStorage");
53
53
  var isObjectRecord2 = (value) => Boolean(value) && typeof value === "object";
54
54
  var isAsyncLocalStorage = (value) => isObjectRecord2(value) && ("getStore" in value) && typeof value.getStore === "function" && ("run" in value) && typeof value.run === "function";
package/dist/cli/index.js CHANGED
@@ -4693,7 +4693,7 @@ import {
4693
4693
  writeFile as writeFile4
4694
4694
  } from "fs/promises";
4695
4695
  import { dirname as dirname6, isAbsolute as isAbsolute2, join as join13, relative as relative5, resolve as resolve9, sep as sep3 } from "path";
4696
- var developmentTeamArgument = (value) => {
4696
+ var ABSOLUTE_IOS_RELEASE_FORMAT = 1, developmentTeamArgument = (value) => {
4697
4697
  if (value === undefined)
4698
4698
  return;
4699
4699
  const team = value.trim().toUpperCase();
@@ -4844,6 +4844,26 @@ var developmentTeamArgument = (value) => {
4844
4844
  if (value !== undefined && (!Number.isSafeInteger(value) || value < 1))
4845
4845
  throw new TypeError("iOS build number must be a positive integer.");
4846
4846
  return value;
4847
+ }, requireAbsoluteIosReleaseMetadata = (value) => {
4848
+ if (!isRecord3(value) || value.artifact !== "App.ipa" || typeof value.appBuild !== "string" || typeof value.appId !== "string" || typeof value.bytes !== "number" || !Number.isSafeInteger(value.bytes) || value.bytes < 1 || value.engine !== "capacitor" && value.engine !== "expo" || value.format !== ABSOLUTE_IOS_RELEASE_FORMAT || typeof value.marketingVersion !== "string" || value.platform !== "ios" || typeof value.releaseId !== "string" || typeof value.runtime !== "string" || typeof value.sha256 !== "string" || typeof value.signed !== "boolean" || value.type !== "ipa" || value.buildNumber !== undefined && (typeof value.buildNumber !== "number" || !Number.isSafeInteger(value.buildNumber) || value.buildNumber < 1) || !/^amobile_ios_[a-f0-9]{64}$/u.test(value.releaseId) || !/^[a-f0-9]{64}$/u.test(value.sha256) || value.releaseId !== `amobile_ios_${value.sha256}`) {
4849
+ throw new TypeError("Invalid AbsoluteJS iOS release metadata.");
4850
+ }
4851
+ return {
4852
+ appBuild: value.appBuild,
4853
+ appId: value.appId,
4854
+ artifact: value.artifact,
4855
+ ...typeof value.buildNumber === "number" ? { buildNumber: value.buildNumber } : {},
4856
+ bytes: value.bytes,
4857
+ engine: value.engine,
4858
+ format: value.format,
4859
+ marketingVersion: value.marketingVersion,
4860
+ platform: value.platform,
4861
+ releaseId: value.releaseId,
4862
+ runtime: value.runtime,
4863
+ sha256: value.sha256,
4864
+ signed: value.signed,
4865
+ type: value.type
4866
+ };
4847
4867
  }, installRelease = async (artifactPath, metadata, outputRoot) => {
4848
4868
  const releaseRoot = join13(outputRoot, metadata.releaseId);
4849
4869
  const destination = join13(releaseRoot, "App.ipa");
@@ -4990,6 +5010,16 @@ var developmentTeamArgument = (value) => {
4990
5010
  return;
4991
5011
  });
4992
5012
  }
5013
+ }, installAbsoluteIosRelease = async (options) => {
5014
+ const metadata = requireAbsoluteIosReleaseMetadata(options.metadata);
5015
+ const [bytes, sha256] = await Promise.all([
5016
+ stat(options.artifactPath).then(({ size }) => size),
5017
+ sha256File(options.artifactPath)
5018
+ ]);
5019
+ if (bytes !== metadata.bytes || sha256 !== metadata.sha256)
5020
+ throw new TypeError("Remote iOS release artifact does not match its signed metadata.");
5021
+ const { artifact: _artifact, ...releaseMetadata } = metadata;
5022
+ return installRelease(options.artifactPath, releaseMetadata, safeOutputDirectory(options.projectRoot, options.outputDirectory));
4993
5023
  };
4994
5024
  var init_iosRelease = __esm(() => {
4995
5025
  init_emulatorDoctor();
@@ -5903,11 +5933,19 @@ var init_iosSimulatorController = __esm(() => {
5903
5933
  });
5904
5934
 
5905
5935
  // src/mobile/remoteMacWire.ts
5906
- var ABSOLUTE_REMOTE_MAC_EVENT_PREFIX = "ABSOLUTE_REMOTE_MAC\t", ABSOLUTE_REMOTE_MAC_PROTOCOL_VERSION = 2;
5936
+ var ABSOLUTE_REMOTE_MAC_EVENT_PREFIX = "ABSOLUTE_REMOTE_MAC\t", ABSOLUTE_REMOTE_MAC_PROTOCOL_VERSION = 3;
5907
5937
 
5908
5938
  // src/mobile/remoteMacProtocol.ts
5909
5939
  import { createHash as createHash6, randomUUID as randomUUID4 } from "crypto";
5910
- import { chmod, mkdir as mkdir6, readFile as readFile8, rename as rename6, writeFile as writeFile6 } from "fs/promises";
5940
+ import {
5941
+ chmod,
5942
+ mkdir as mkdir6,
5943
+ mkdtemp as mkdtemp4,
5944
+ readFile as readFile8,
5945
+ rename as rename6,
5946
+ rm as rm6,
5947
+ writeFile as writeFile6
5948
+ } from "fs/promises";
5911
5949
  import { homedir as homedir4 } from "os";
5912
5950
  import { isIP as isIP3 } from "net";
5913
5951
  import {
@@ -6236,6 +6274,13 @@ var PROFILE_FORMAT = 1, REMOTE_STDIN_FLUSH_ATTEMPTS = 3, REMOTE_SESSION_CLOSE_TI
6236
6274
  tar: [
6237
6275
  "tar",
6238
6276
  "--exclude=.git",
6277
+ "--exclude=.env",
6278
+ "--exclude=.env.*",
6279
+ "--exclude=*.jks",
6280
+ "--exclude=*.keystore",
6281
+ "--exclude=*.mobileprovision",
6282
+ "--exclude=*.p12",
6283
+ "--exclude=*.p8",
6239
6284
  "--exclude=node_modules",
6240
6285
  "--exclude=build",
6241
6286
  "--exclude=.absolutejs",
@@ -6271,6 +6316,108 @@ var PROFILE_FORMAT = 1, REMOTE_STDIN_FLUSH_ATTEMPTS = 3, REMOTE_SESSION_CLOSE_TI
6271
6316
  shellQuote(`cd ${shellQuote(project.remoteProjectRoot)} && ${shellQuote(project.profile.bunPath)} install --frozen-lockfile`)
6272
6317
  ]);
6273
6318
  requireRemoteSuccess(install, "Remote Mac dependency installation");
6319
+ }, requireRemoteProjectRelativePath = (project, path) => {
6320
+ const value = portableRelativePath(project.projectRoot, path);
6321
+ if (!value || value === ".." || value.startsWith("../") || posix.isAbsolute(value))
6322
+ throw new TypeError("Remote iOS release inputs must remain inside the project.");
6323
+ return value;
6324
+ }, absoluteRemoteReleaseInputSyncCommands = (project) => {
6325
+ const relativeBundle = requireRemoteProjectRelativePath(project, project.config.bundleDirectory);
6326
+ const destination = posix.join(project.remoteProjectRoot, relativeBundle);
6327
+ const staging = `${destination}.incoming-${randomUUID4()}`;
6328
+ const script = [
6329
+ "set -eu",
6330
+ `rm -rf ${shellQuote(staging)}`,
6331
+ `mkdir -p ${shellQuote(staging)}`,
6332
+ `tar -xf - -C ${shellQuote(staging)}`,
6333
+ `rm -rf ${shellQuote(destination)}`,
6334
+ `mkdir -p ${shellQuote(posix.dirname(destination))}`,
6335
+ `mv ${shellQuote(staging)} ${shellQuote(destination)}`
6336
+ ].join("; ");
6337
+ return {
6338
+ remote: [
6339
+ ...absoluteRemoteMacSshBase(project.profile),
6340
+ "/bin/sh -lc",
6341
+ shellQuote(script)
6342
+ ],
6343
+ tar: ["tar", "-cf", "-", "-C", project.config.bundleDirectory, "."]
6344
+ };
6345
+ }, syncAbsoluteRemoteMacReleaseInputs = async (project) => {
6346
+ const commands = absoluteRemoteReleaseInputSyncCommands(project);
6347
+ const archive = Bun.spawn(commands.tar, {
6348
+ stderr: "pipe",
6349
+ stdout: "pipe"
6350
+ });
6351
+ const upload = Bun.spawn(commands.remote, {
6352
+ stderr: "pipe",
6353
+ stdin: archive.stdout,
6354
+ stdout: "pipe"
6355
+ });
6356
+ const [archiveExit, uploadExit, archiveError, uploadError] = await Promise.all([
6357
+ archive.exited,
6358
+ upload.exited,
6359
+ new Response(archive.stderr).text(),
6360
+ new Response(upload.stderr).text()
6361
+ ]);
6362
+ if (archiveExit !== 0 || uploadExit !== 0)
6363
+ throw new Error(`Remote iOS release input synchronization failed: ${(archiveError || uploadError).trim()}`);
6364
+ }, writeRemoteArtifact = async (path, stream) => {
6365
+ const sink = Bun.file(path).writer();
6366
+ const reader = stream.getReader();
6367
+ try {
6368
+ while (true) {
6369
+ const { done, value } = await reader.read();
6370
+ if (done)
6371
+ break;
6372
+ sink.write(value);
6373
+ }
6374
+ await sink.end();
6375
+ } catch (error) {
6376
+ await Promise.resolve(sink.end()).catch(() => {
6377
+ return;
6378
+ });
6379
+ throw error;
6380
+ } finally {
6381
+ reader.releaseLock();
6382
+ }
6383
+ }, retrieveAbsoluteRemoteIosRelease = async (project, metadata, outputDirectory) => {
6384
+ const releaseRoot = posix.join(project.remoteProjectRoot, ".absolutejs", "mobile", "releases", "ios", metadata.releaseId);
6385
+ const stagingParent = join15(project.projectRoot, ".absolutejs", "mobile");
6386
+ await mkdir6(stagingParent, { recursive: true });
6387
+ const staging = await mkdtemp4(join15(stagingParent, ".remote-ios-"));
6388
+ try {
6389
+ const remoteMetadata = requireRemoteSuccess(await defaultTransport.capture([
6390
+ ...absoluteRemoteMacSshBase(project.profile),
6391
+ "/bin/sh -lc",
6392
+ shellQuote(`cat ${shellQuote(posix.join(releaseRoot, "release.json"))}`)
6393
+ ]), "Remote iOS release metadata retrieval");
6394
+ const downloadedMetadata = JSON.parse(remoteMetadata);
6395
+ if (JSON.stringify(requireAbsoluteIosReleaseMetadata(downloadedMetadata)) !== JSON.stringify(metadata))
6396
+ throw new TypeError("Remote iOS release metadata changed during retrieval.");
6397
+ const artifactPath = join15(staging, "App.ipa");
6398
+ const download = Bun.spawn([
6399
+ ...absoluteRemoteMacSshBase(project.profile),
6400
+ "/bin/sh -lc",
6401
+ shellQuote(`cat ${shellQuote(posix.join(releaseRoot, "App.ipa"))}`)
6402
+ ], { stderr: "pipe", stdout: "pipe" });
6403
+ const [downloadExit, downloadError] = await Promise.all([
6404
+ download.exited,
6405
+ new Response(download.stderr).text(),
6406
+ writeRemoteArtifact(artifactPath, download.stdout)
6407
+ ]);
6408
+ if (downloadExit !== 0)
6409
+ throw new Error(`Remote iOS release retrieval failed: ${downloadError.trim()}`);
6410
+ return await installAbsoluteIosRelease({
6411
+ artifactPath,
6412
+ metadata,
6413
+ outputDirectory,
6414
+ projectRoot: project.projectRoot
6415
+ });
6416
+ } finally {
6417
+ await rm6(staging, { force: true, recursive: true }).catch(() => {
6418
+ return;
6419
+ });
6420
+ }
6274
6421
  }, consumeLines2 = async (stream, onLine) => {
6275
6422
  const reader = stream.getReader();
6276
6423
  const decoder = new TextDecoder;
@@ -6291,6 +6438,116 @@ var PROFILE_FORMAT = 1, REMOTE_STDIN_FLUSH_ATTEMPTS = 3, REMOTE_SESSION_CLOSE_TI
6291
6438
  } finally {
6292
6439
  reader.releaseLock();
6293
6440
  }
6441
+ }, buildAbsoluteRemoteIosRelease = async (options) => {
6442
+ const startedAt = performance.now();
6443
+ const syncStartedAt = performance.now();
6444
+ await (options.syncProject ?? syncAbsoluteRemoteMacProject)(options.project);
6445
+ await (options.syncReleaseInputs ?? syncAbsoluteRemoteMacReleaseInputs)(options.project);
6446
+ const syncDuration = performance.now() - syncStartedAt;
6447
+ options.onPhaseTiming?.({
6448
+ durationMs: syncDuration,
6449
+ phase: "remote-release-sync"
6450
+ });
6451
+ const agentStartedAt = performance.now();
6452
+ const agent = await (options.installAgent ?? installAbsoluteRemoteMacAgent)(options.project);
6453
+ const agentDuration = performance.now() - agentStartedAt;
6454
+ const encodedConfig = Buffer.from(JSON.stringify(portableMobileConfig(options.project))).toString("base64url");
6455
+ const remoteCommand = [
6456
+ `cd ${shellQuote(options.project.remoteProjectRoot)}`,
6457
+ "&&",
6458
+ "exec",
6459
+ shellQuote(options.project.profile.bunPath),
6460
+ shellQuote(agent.remotePath),
6461
+ "--release-ios",
6462
+ "--mobile-config",
6463
+ shellQuote(encodedConfig),
6464
+ ...options.allowUnsigned ? ["--unsigned"] : [],
6465
+ ...options.prepareBuildNumber ? ["--request-build-number"] : [],
6466
+ ...options.developmentTeam ? ["--development-team", shellQuote(options.developmentTeam)] : []
6467
+ ].join(" ");
6468
+ const process2 = (options.transport?.spawn ?? defaultTransport.spawn)([
6469
+ ...absoluteRemoteMacSshBase(options.project.profile),
6470
+ "/bin/sh -lc",
6471
+ shellQuote(remoteCommand)
6472
+ ], {});
6473
+ let failure;
6474
+ let metadata;
6475
+ const responses = [];
6476
+ const stdoutDone = consumeLines2(process2.stdout, (line) => {
6477
+ if (!line.startsWith(ABSOLUTE_REMOTE_MAC_EVENT_PREFIX))
6478
+ return;
6479
+ try {
6480
+ const event = JSON.parse(line.slice(ABSOLUTE_REMOTE_MAC_EVENT_PREFIX.length));
6481
+ if (event.v !== ABSOLUTE_REMOTE_MAC_PROTOCOL_VERSION)
6482
+ throw new Error("Remote Mac protocol version mismatch.");
6483
+ if (event.type === "log")
6484
+ options.log?.(event.message);
6485
+ if (event.type === "timing") {
6486
+ const durationMs = Reflect.get(event, "durationMs");
6487
+ const phase = Reflect.get(event, "phase");
6488
+ if (typeof durationMs === "number" && typeof phase === "string")
6489
+ options.onPhaseTiming?.({ durationMs, phase });
6490
+ }
6491
+ if (event.type === "fatal")
6492
+ failure = new Error(event.error);
6493
+ if (event.type === "release")
6494
+ metadata = requireAbsoluteIosReleaseMetadata(event.metadata);
6495
+ if (event.type === "build-number-request") {
6496
+ if (!options.prepareBuildNumber || !/^[a-f0-9]{64}$/u.test(event.buildIdentity) || !event.id)
6497
+ throw new TypeError("Remote Mac requested an invalid iOS build number.");
6498
+ responses.push(options.prepareBuildNumber(event.buildIdentity).then(async (buildNumber) => {
6499
+ if (!Number.isSafeInteger(buildNumber) || buildNumber < 1)
6500
+ throw new TypeError("iOS release publisher returned an invalid build number.");
6501
+ process2.stdin.write(`${JSON.stringify({ buildNumber, command: "build-number", id: event.id, v: ABSOLUTE_REMOTE_MAC_PROTOCOL_VERSION })}
6502
+ `);
6503
+ for (let attempt = 0;attempt < REMOTE_STDIN_FLUSH_ATTEMPTS; attempt++) {
6504
+ try {
6505
+ await process2.stdin.flush();
6506
+ break;
6507
+ } catch {
6508
+ await Promise.resolve();
6509
+ }
6510
+ }
6511
+ }).catch((error) => {
6512
+ failure = error instanceof Error ? error : new Error("Failed to allocate an iOS build number.");
6513
+ process2.kill();
6514
+ return;
6515
+ }));
6516
+ }
6517
+ } catch (error) {
6518
+ failure = error instanceof Error ? error : new Error("Remote Mac emitted an invalid release event.");
6519
+ process2.kill();
6520
+ }
6521
+ });
6522
+ const stderrDone = consumeLines2(process2.stderr, (line) => options.log?.(`[remote] ${line}`));
6523
+ const exitCode = await process2.exited;
6524
+ try {
6525
+ process2.stdin.end();
6526
+ } catch {}
6527
+ await Promise.all([stdoutDone, stderrDone, ...responses]);
6528
+ if (failure)
6529
+ throw failure;
6530
+ if (exitCode !== 0)
6531
+ throw new Error(`Remote iOS release agent exited with status ${exitCode}.`);
6532
+ if (!metadata)
6533
+ throw new Error("Remote iOS release agent did not return an IPA.");
6534
+ const downloadStartedAt = performance.now();
6535
+ const release = await (options.retrieveRelease ?? retrieveAbsoluteRemoteIosRelease)(options.project, metadata, options.outputDirectory);
6536
+ const downloadDuration = performance.now() - downloadStartedAt;
6537
+ options.onPhaseTiming?.({
6538
+ durationMs: downloadDuration,
6539
+ phase: "remote-release-download"
6540
+ });
6541
+ options.log?.(`Remote Mac ${options.project.profile.name} built and verified iOS release ${metadata.releaseId} in ${(performance.now() - startedAt).toFixed(2)}ms (agent ${agent.uploaded ? "uploaded" : "cache hit"}).`);
6542
+ return {
6543
+ ...release,
6544
+ timings: {
6545
+ "remote-agent": agentDuration,
6546
+ "remote-release-download": downloadDuration,
6547
+ "remote-release-sync": syncDuration,
6548
+ total: performance.now() - startedAt
6549
+ }
6550
+ };
6294
6551
  }, startAbsoluteRemoteExpoIosDevSession = async (options) => {
6295
6552
  const session = await startAbsoluteRemoteDevSession({
6296
6553
  certificateAuthorityPath: options.certificateAuthorityPath,
@@ -6464,7 +6721,9 @@ var PROFILE_FORMAT = 1, REMOTE_STDIN_FLUSH_ATTEMPTS = 3, REMOTE_SESSION_CLOSE_TI
6464
6721
  try {
6465
6722
  await readyPromise;
6466
6723
  } catch (error) {
6467
- process2.stdin.end();
6724
+ try {
6725
+ process2.stdin.end();
6726
+ } catch {}
6468
6727
  process2.kill();
6469
6728
  await process2.exited.catch(() => {
6470
6729
  return;
@@ -6516,13 +6775,12 @@ var PROFILE_FORMAT = 1, REMOTE_STDIN_FLUSH_ATTEMPTS = 3, REMOTE_SESSION_CLOSE_TI
6516
6775
  return;
6517
6776
  closed = true;
6518
6777
  const timeout = () => new Promise((resolve11) => setTimeout(() => resolve11("timeout"), REMOTE_SESSION_CLOSE_TIMEOUT_MS));
6519
- await Promise.race([
6520
- request("close").catch(() => {
6521
- return;
6522
- }),
6523
- timeout()
6524
- ]);
6525
- process2.stdin.end();
6778
+ const id = randomUUID4();
6779
+ process2.stdin.write(`${JSON.stringify({ command: "close", id, v: ABSOLUTE_REMOTE_MAC_PROTOCOL_VERSION })}
6780
+ `);
6781
+ try {
6782
+ process2.stdin.end();
6783
+ } catch {}
6526
6784
  const exit = await Promise.race([
6527
6785
  process2.exited.then(() => "exited").catch(() => "exited"),
6528
6786
  timeout()
@@ -6577,6 +6835,7 @@ var PROFILE_FORMAT = 1, REMOTE_STDIN_FLUSH_ATTEMPTS = 3, REMOTE_SESSION_CLOSE_TI
6577
6835
  return makeSession();
6578
6836
  };
6579
6837
  var init_remoteMacProtocol = __esm(() => {
6838
+ init_iosRelease();
6580
6839
  PROFILE_NAME = /^[a-z0-9](?:[a-z0-9._-]{0,62}[a-z0-9])?$/u;
6581
6840
  SSH_DESTINATION = /^(?:[A-Za-z0-9._-]+@)?[A-Za-z0-9._:-]+$/u;
6582
6841
  defaultTransport = {
@@ -8541,10 +8800,10 @@ import {
8541
8800
  cp as cp3,
8542
8801
  copyFile as copyFile4,
8543
8802
  mkdir as mkdir9,
8544
- mkdtemp as mkdtemp4,
8803
+ mkdtemp as mkdtemp5,
8545
8804
  readFile as readFile10,
8546
8805
  rename as rename7,
8547
- rm as rm6,
8806
+ rm as rm7,
8548
8807
  writeFile as writeFile8
8549
8808
  } from "fs/promises";
8550
8809
  import { existsSync as existsSync10 } from "fs";
@@ -8690,11 +8949,11 @@ void startAbsoluteMobileShell(${shellOptions});
8690
8949
  throw new AggregateError(build.logs, "Failed to build the AbsoluteJS Capacitor shell.");
8691
8950
  }
8692
8951
  await rename7(build.outputs[0]?.path ?? "", join21(staging, BOOTSTRAP_FILE));
8693
- await rm6(entryPath, { force: true });
8952
+ await rm7(entryPath, { force: true });
8694
8953
  }, removePreviousBundle = async (backup, moved) => {
8695
8954
  if (!moved)
8696
8955
  return;
8697
- await rm6(backup, { force: true, recursive: true });
8956
+ await rm7(backup, { force: true, recursive: true });
8698
8957
  }, restorePreviousBundle = async (backup, destination, moved) => {
8699
8958
  if (!moved)
8700
8959
  return;
@@ -8791,7 +9050,7 @@ void startAbsoluteMobileShell(${shellOptions});
8791
9050
  }
8792
9051
  const destination = options.config.bundleDirectory;
8793
9052
  await mkdir9(dirname12(destination), { recursive: true });
8794
- const staging = await mkdtemp4(join21(dirname12(destination), `.${basename8(destination)}.stage-`));
9053
+ const staging = await mkdtemp5(join21(dirname12(destination), `.${basename8(destination)}.stage-`));
8795
9054
  try {
8796
9055
  const pageDirectory = join21(staging, "pages");
8797
9056
  await mkdir9(pageDirectory, { recursive: true });
@@ -8839,7 +9098,7 @@ void startAbsoluteMobileShell(${shellOptions});
8839
9098
  await installBundle(staging, destination);
8840
9099
  return manifest;
8841
9100
  } catch (error) {
8842
- await rm6(staging, { force: true, recursive: true });
9101
+ await rm7(staging, { force: true, recursive: true });
8843
9102
  throw error;
8844
9103
  }
8845
9104
  };
@@ -8883,10 +9142,10 @@ import { createHash as createHash11 } from "crypto";
8883
9142
  import {
8884
9143
  access as access8,
8885
9144
  mkdir as mkdir10,
8886
- mkdtemp as mkdtemp5,
9145
+ mkdtemp as mkdtemp6,
8887
9146
  readFile as readFile11,
8888
9147
  rename as rename8,
8889
- rm as rm7,
9148
+ rm as rm8,
8890
9149
  writeFile as writeFile9
8891
9150
  } from "fs/promises";
8892
9151
  import { dirname as dirname13, join as join22, resolve as resolvePath3 } from "path";
@@ -8936,12 +9195,12 @@ var ABSOLUTE_MOBILE_MATERIALIZED_BUNDLE_FORMAT = 1, CURRENT_BUNDLE_FILE = "curre
8936
9195
  if (!errorHasCode2(error, "ENOENT"))
8937
9196
  throw error;
8938
9197
  }
8939
- const staging = await mkdtemp5(join22(bundlesRoot, ".stage-"));
9198
+ const staging = await mkdtemp6(join22(bundlesRoot, ".stage-"));
8940
9199
  try {
8941
9200
  await Promise.all(releases.map((release) => writeRelease(staging, release)));
8942
9201
  await rename8(staging, destination);
8943
9202
  } catch (error) {
8944
- await rm7(staging, { force: true, recursive: true });
9203
+ await rm8(staging, { force: true, recursive: true });
8945
9204
  if (errorHasCode2(error, "EEXIST") || errorHasCode2(error, "ENOTEMPTY")) {
8946
9205
  return destination;
8947
9206
  }
@@ -18144,6 +18403,10 @@ console.log(\`
18144
18403
  const resolvedOutdir = resolve36(outdir ?? "dist");
18145
18404
  await withBuildDirectoryLock(resolvedOutdir, () => compileUnlocked(serverEntry, resolvedOutdir, outfile, configPath2));
18146
18405
  }, compileUnlocked = async (serverEntry, resolvedOutdir, outfile, configPath2) => {
18406
+ rmSync7(join47(resolvedOutdir, "node_modules"), {
18407
+ force: true,
18408
+ recursive: true
18409
+ });
18147
18410
  const configuredPrerenderPort = env5.COMPILE_PORT === undefined ? Number(env5.PORT) : Number(env5.COMPILE_PORT);
18148
18411
  const prerenderPort = configuredPrerenderPort > 0 ? configuredPrerenderPort : await findFreePort();
18149
18412
  killStaleProcesses(prerenderPort);
@@ -18987,7 +19250,7 @@ import {
18987
19250
  mkdir as mkdir11,
18988
19251
  readFile as readFile16,
18989
19252
  rename as rename12,
18990
- rm as rm8,
19253
+ rm as rm9,
18991
19254
  writeFile as writeFile13
18992
19255
  } from "fs/promises";
18993
19256
  import { resolve as resolve37 } from "path";
@@ -19088,7 +19351,7 @@ var OWNERSHIP_FILE = ".absolutejs-mobile-associations.json", HTTP_OK = 200, VERI
19088
19351
  throw error;
19089
19352
  }
19090
19353
  if (hasCurrent)
19091
- await rm8(backup, { force: true, recursive: true });
19354
+ await rm9(backup, { force: true, recursive: true });
19092
19355
  }, materializeHost = async (root, host2, files) => {
19093
19356
  const directory = resolve37(root, host2, ".well-known");
19094
19357
  await mkdir11(directory, { recursive: true });
@@ -19136,7 +19399,7 @@ var OWNERSHIP_FILE = ".absolutejs-mobile-associations.json", HTTP_OK = 200, VERI
19136
19399
  const written = temporaryPaths.map((path) => resolve37(root, path.slice(temporary.length + 1)));
19137
19400
  return { root, written };
19138
19401
  } catch (error) {
19139
- await rm8(temporary, { force: true, recursive: true });
19402
+ await rm9(temporary, { force: true, recursive: true });
19140
19403
  throw error;
19141
19404
  }
19142
19405
  }, verifyAbsoluteMobileAssociationFiles = async (config, request = globalThis.fetch) => {
@@ -20398,11 +20661,11 @@ import {
20398
20661
  access as access12,
20399
20662
  copyFile as copyFile5,
20400
20663
  mkdir as mkdir13,
20401
- mkdtemp as mkdtemp6,
20664
+ mkdtemp as mkdtemp7,
20402
20665
  readFile as readFile19,
20403
20666
  realpath as realpath2,
20404
20667
  rename as rename13,
20405
- rm as rm9,
20668
+ rm as rm10,
20406
20669
  stat as stat3,
20407
20670
  writeFile as writeFile15
20408
20671
  } from "fs/promises";
@@ -20505,7 +20768,7 @@ var ABSOLUTE_ANDROID_RELEASE_FORMAT = 1, isRecord15 = (value) => typeof value ==
20505
20768
  return { artifactPath: destination, metadata: existing, releaseRoot };
20506
20769
  }
20507
20770
  await mkdir13(dirname31(releaseRoot), { recursive: true });
20508
- const staging = await mkdtemp6(join53(dirname31(releaseRoot), ".android-stage-"));
20771
+ const staging = await mkdtemp7(join53(dirname31(releaseRoot), ".android-stage-"));
20509
20772
  try {
20510
20773
  await copyFile5(artifactPath, join53(staging, artifactName));
20511
20774
  const complete = {
@@ -20517,7 +20780,7 @@ var ABSOLUTE_ANDROID_RELEASE_FORMAT = 1, isRecord15 = (value) => typeof value ==
20517
20780
  await rename13(staging, releaseRoot);
20518
20781
  return { artifactPath: destination, metadata: complete, releaseRoot };
20519
20782
  } finally {
20520
- await rm9(staging, { force: true, recursive: true }).catch(() => {
20783
+ await rm10(staging, { force: true, recursive: true }).catch(() => {
20521
20784
  return;
20522
20785
  });
20523
20786
  }
@@ -22197,6 +22460,7 @@ Mobile release security and compliance checks failed.`);
22197
22460
  "--play-track",
22198
22461
  "--play-update-priority",
22199
22462
  "--registry",
22463
+ "--remote",
22200
22464
  "--testflight-group",
22201
22465
  "--testflight-notes",
22202
22466
  "--web-outdir"
@@ -22357,7 +22621,7 @@ Mobile release security and compliance checks failed.`);
22357
22621
  await writeAbsoluteExpoProject(mobile, { projectRoot });
22358
22622
  await ensureExpoPackages(mobile.nativeProjectDirectory, [...args, "--yes"]);
22359
22623
  await syncAbsoluteExpoWebAssets(mobile);
22360
- await runExpo(mobile.nativeProjectDirectory, ["prebuild", "--clean", "--no-install", "--platform", "ios"], { production: true });
22624
+ await runExpo(mobile.nativeProjectDirectory, ["prebuild", "--clean", "--platform", "ios"], { production: true });
22361
22625
  }, prepareCapacitorIosReleaseProject = async (mobile, projectRoot) => {
22362
22626
  await writeAbsoluteCapacitorConfig(mobile, { projectRoot });
22363
22627
  await runCapacitorForPlatforms(projectRoot, "sync", ["ios"]);
@@ -22472,6 +22736,18 @@ Mobile release security and compliance checks failed.`);
22472
22736
  status: check2.status
22473
22737
  })));
22474
22738
  throw new TypeError("iOS release validation failed before Xcode signing.");
22739
+ }, buildLocalIosRelease = async (options) => {
22740
+ await prepareIosReleaseProject(options.mobile, options.projectRoot, options.args);
22741
+ await requireIosReleaseReady(options.mobile, options.projectRoot);
22742
+ return buildAbsoluteIosRelease({
22743
+ allowUnsigned: options.args.includes("--unsigned"),
22744
+ config: options.mobile,
22745
+ developmentTeam: process.env.ABSOLUTE_IOS_DEVELOPMENT_TEAM,
22746
+ ...options.mobile.engine === "expo" ? { env: expoProductionEnvironment() } : {},
22747
+ outputDirectory: valueAfter(options.args, "--outdir"),
22748
+ ...options.prepareBuildNumber === undefined ? {} : { prepareBuildNumber: options.prepareBuildNumber },
22749
+ projectRoot: options.projectRoot
22750
+ });
22475
22751
  }, buildIos = async (args, prepareBuildNumber) => {
22476
22752
  const configPath2 = valueAfter(args, "--config");
22477
22753
  const { mobile, projectRoot } = await loadMobile(configPath2);
@@ -22479,19 +22755,37 @@ Mobile release security and compliance checks failed.`);
22479
22755
  throw new TypeError("mobile build ios requires ios in mobile.platforms.");
22480
22756
  }
22481
22757
  const startedAt = performance.now();
22758
+ const requestedRemote = valueAfter(args, "--remote");
22759
+ if (args.includes("--remote") && (!requestedRemote || requestedRemote.startsWith("-")))
22760
+ throw new TypeError("mobile build ios requires --remote <name>.");
22761
+ const remoteProfile = requestedRemote !== undefined || process.platform !== "darwin" ? await getAbsoluteRemoteMacProfile(requestedRemote, remoteProfilePath()) : undefined;
22762
+ if (process.platform !== "darwin" && !remoteProfile)
22763
+ throw new TypeError("iOS release builds require macOS or a paired Remote Mac. Run `absolute mobile pair mac <name> <user@host>`.");
22482
22764
  let success = false;
22483
22765
  try {
22484
- if (mobile.engine === "capacitor")
22766
+ if (!remoteProfile && mobile.engine === "capacitor")
22485
22767
  await repairAbsoluteIosDevSession(projectRoot);
22486
22768
  await start(mobileBuildServerEntry(args), valueAfter(args, "--web-outdir"), configPath2, { prepareOnly: true });
22487
- await prepareIosReleaseProject(mobile, projectRoot, args);
22488
- await requireIosReleaseReady(mobile, projectRoot);
22489
- const release = await buildAbsoluteIosRelease({
22769
+ const release = remoteProfile ? await buildAbsoluteRemoteIosRelease({
22490
22770
  allowUnsigned: args.includes("--unsigned"),
22491
- config: mobile,
22492
22771
  developmentTeam: process.env.ABSOLUTE_IOS_DEVELOPMENT_TEAM,
22493
- ...mobile.engine === "expo" ? { env: expoProductionEnvironment() } : {},
22494
22772
  outputDirectory: valueAfter(args, "--outdir"),
22773
+ log: (message) => console.log(`[remote] ${message}`),
22774
+ onPhaseTiming: ({ durationMs: durationMs2, phase }) => {
22775
+ console.log(`[mobile:ios-release] ${phase} ${getDurationString(durationMs2)}`);
22776
+ sendTelemetryEvent("mobile:ios-release-phase", {
22777
+ durationMs: Math.round(durationMs2),
22778
+ engine: mobile.engine,
22779
+ phase,
22780
+ platform: "ios",
22781
+ provider: "remote-mac"
22782
+ });
22783
+ },
22784
+ ...prepareBuildNumber === undefined ? {} : { prepareBuildNumber },
22785
+ project: createAbsoluteRemoteIosDevProject(mobile, projectRoot, remoteProfile)
22786
+ }) : await buildLocalIosRelease({
22787
+ args,
22788
+ mobile,
22495
22789
  ...prepareBuildNumber === undefined ? {} : { prepareBuildNumber },
22496
22790
  projectRoot
22497
22791
  });
@@ -22506,6 +22800,7 @@ Mobile release security and compliance checks failed.`);
22506
22800
  durationMs: Math.round(performance.now() - startedAt),
22507
22801
  engine: mobile.engine,
22508
22802
  platform: "ios",
22803
+ remote: remoteProfile !== undefined,
22509
22804
  success,
22510
22805
  type: "ipa",
22511
22806
  unsignedAllowed: args.includes("--unsigned")
@@ -23427,7 +23722,7 @@ Emulator setup verification:`);
23427
23722
  await publishIos(args.slice(2));
23428
23723
  return;
23429
23724
  }
23430
- 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] | inspect [--json] [--require-bundle] | associations [--outdir dir] [--verify] | ci github [server-entry] [--publish] [--registry module] [--secret-env NAME] [--output path] [--force] [--json] | doctor [ios|android|release [ios|android]] [--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]");
23725
+ 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] | inspect [--json] [--require-bundle] | associations [--outdir dir] [--verify] | ci github [server-entry] [--publish] [--registry module] [--secret-env NAME] [--output path] [--force] [--json] | doctor [ios|android|release [ios|android]] [--remote name] [--json|--fix [--yes]] | build <android|ios> [server-entry] [--remote name] [--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] [--remote name] [--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]");
23431
23726
  };
23432
23727
  var init_mobile = __esm(() => {
23433
23728
  init_dependencies();