@absolutejs/absolute 0.20.0-beta.79 → 0.20.0-beta.80

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.
@@ -26447,7 +26447,7 @@ var expoAppConfig = (config, auth, sync, devices, runtimeFingerprint) => {
26447
26447
  slug: config.appId.toLowerCase().replaceAll(".", "-"),
26448
26448
  ...config.updates ? {
26449
26449
  updates: {
26450
- checkAutomatically: "NEVER",
26450
+ checkAutomatically: "ON_ERROR_RECOVERY",
26451
26451
  fallbackToCacheTimeout: config.updates.bootTimeoutMs,
26452
26452
  requestHeaders: {
26453
26453
  "x-absolute-mobile-app": config.appId,
@@ -26527,7 +26527,7 @@ var metroConfig = (projectRoot) => `${EXPO_GENERATED_HEADER}const { getDefaultCo
26527
26527
  const path = require('node:path');
26528
26528
 
26529
26529
  const projectRoot = __dirname;
26530
- const appRoot = ${JSON.stringify(projectRoot)};
26530
+ const appRoot = process.env.ABSOLUTE_EXPO_APP_ROOT || ${JSON.stringify(projectRoot)};
26531
26531
  const config = getDefaultConfig(projectRoot);
26532
26532
  config.resolver.assetExts.push('absasset');
26533
26533
  config.resolver.nodeModulesPaths = [
@@ -26561,15 +26561,11 @@ export default function AbsoluteLayout() {
26561
26561
  return <Stack screenOptions={{ headerShown: false }} />;
26562
26562
  }
26563
26563
  `;
26564
- var updatesRuntimeSource = (config) => `${EXPO_GENERATED_HEADER}import { randomUUID } from 'expo-crypto';
26564
+ var updatesRuntimeSource = () => `${EXPO_GENERATED_HEADER}import { randomUUID } from 'expo-crypto';
26565
26565
  import * as SecureStore from 'expo-secure-store';
26566
26566
  import * as Updates from 'expo-updates';
26567
26567
 
26568
26568
  const INSTALLATION_KEY = 'absolutejs.mobile.update.installation.v1';
26569
- const REQUEST_HEADERS = ${JSON.stringify({
26570
- "x-absolute-mobile-app": config.appId,
26571
- "x-absolute-mobile-channel": config.updates?.channel
26572
- })};
26573
26569
 
26574
26570
  let startPromise: Promise<void> | undefined;
26575
26571
  export const startAbsoluteExpoUpdates = () => {
@@ -26580,13 +26576,13 @@ export const startAbsoluteExpoUpdates = () => {
26580
26576
  installationId = randomUUID();
26581
26577
  await SecureStore.setItemAsync(INSTALLATION_KEY, installationId);
26582
26578
  }
26583
- await Updates.setUpdateRequestHeadersOverride({
26584
- ...REQUEST_HEADERS,
26585
- 'x-absolute-mobile-installation': installationId
26586
- });
26579
+ await Updates.setExtraParamAsync('absolute-installation', installationId);
26587
26580
  const result = await Updates.checkForUpdateAsync();
26588
26581
  if (result.isAvailable || result.isRollBackToEmbedded) {
26589
26582
  await Updates.fetchUpdateAsync();
26583
+ if (result.isRollBackToEmbedded) {
26584
+ await Updates.reloadAsync();
26585
+ }
26590
26586
  }
26591
26587
  })().catch(error => {
26592
26588
  console.warn('[absolute:mobile-update] Expo update check failed', error instanceof Error ? error.message : 'unknown error');
@@ -27528,7 +27524,7 @@ node_modules/
27528
27524
  files.set(path, source);
27529
27525
  }
27530
27526
  if (config.updates) {
27531
- files.set(join15(project, "src", "generated", "AbsoluteUpdates.ts"), updatesRuntimeSource(config));
27527
+ files.set(join15(project, "src", "generated", "AbsoluteUpdates.ts"), updatesRuntimeSource());
27532
27528
  }
27533
27529
  const expoCodeSigning = config.updates?.expoCodeSigning;
27534
27530
  if (expoCodeSigning)
@@ -28227,8 +28223,10 @@ var expoDevelopmentClientScheme = (appId) => `exp+${appId.toLowerCase().replaceA
28227
28223
  var expoDevelopmentClientUrl = (appId, host3, port) => `${expoDevelopmentClientScheme(appId)}://expo-development-client/?url=${encodeURIComponent(`http://${host3}:${port}`)}`;
28228
28224
  var captureCommand4 = (command) => {
28229
28225
  const result = Bun.spawnSync(command, {
28226
+ killSignal: "SIGKILL",
28230
28227
  stderr: "ignore",
28231
- stdout: "pipe"
28228
+ stdout: "pipe",
28229
+ timeout: 30000
28232
28230
  });
28233
28231
  return { exitCode: result.exitCode, stdout: result.stdout.toString() };
28234
28232
  };
@@ -28271,7 +28269,35 @@ var connectLocalExpoAndroid = (adb, appId, metroPort, capture, preferredDevice)
28271
28269
  openDevelopmentClient();
28272
28270
  return serial;
28273
28271
  };
28274
- var encodedWindowsExpoAndroidCommand = (project, androidRoot, appId, args, capture, metroPort, preferredDevice) => {
28272
+ var launchLocalExpoAndroidRelease = (adb, appId, forwardedPort, capture, preferredDevice) => {
28273
+ const devices = capture([adb, "devices"]);
28274
+ if (devices.exitCode !== 0)
28275
+ throw new Error("Could not inspect devices after the Expo release build.");
28276
+ const ready = devices.stdout.split(/\r?\n/u).flatMap((line) => {
28277
+ const match = /^(\S+)\s+device$/u.exec(line.trim());
28278
+ return match?.[1] ? [match[1]] : [];
28279
+ });
28280
+ const serial = preferredDevice ? ready.find((value) => value === preferredDevice) : ready.find((value) => value.startsWith("emulator-")) ?? ready[0];
28281
+ if (!serial)
28282
+ throw new Error("Expo release build completed but no ready device was found.");
28283
+ const run = (args, message) => {
28284
+ if (capture([adb, "-s", serial, ...args]).exitCode !== 0)
28285
+ throw new Error(message);
28286
+ };
28287
+ run(["reverse", `tcp:${forwardedPort}`, `tcp:${forwardedPort}`], "Expo Android release forwarding failed.");
28288
+ run(["shell", "am", "force-stop", appId], "Expo Android release reset failed.");
28289
+ run([
28290
+ "shell",
28291
+ "monkey",
28292
+ "-p",
28293
+ appId,
28294
+ "-c",
28295
+ "android.intent.category.LAUNCHER",
28296
+ "1"
28297
+ ], "Expo Android release launch failed.");
28298
+ return serial;
28299
+ };
28300
+ var encodedWindowsExpoAndroidCommand = (project, androidRoot, appId, args, capture, forwardedPort, preferredDevice, mode = "development") => {
28275
28301
  const windowsSource = windowsPathFromWsl2(project, capture);
28276
28302
  const buildId = Bun.hash(resolvePath4(project)).toString(16);
28277
28303
  const buildDirectory = resolvePath4(androidRoot, "..", "..", "ExpoBuilds", buildId.slice(0, 10));
@@ -28287,15 +28313,24 @@ var encodedWindowsExpoAndroidCommand = (project, androidRoot, appId, args, captu
28287
28313
  `[IO.File]::WriteAllText($hook, [Text.Encoding]::UTF8.GetString([Convert]::FromBase64String('${realpathHook}')))`,
28288
28314
  "$env:ABSOLUTE_EXPO_PHYSICAL_ROOT = $directory",
28289
28315
  "$env:ABSOLUTE_EXPO_MAPPED_ROOT = $mappedProject",
28316
+ "$env:ABSOLUTE_EXPO_APP_ROOT = $mappedProject",
28290
28317
  '$env:NODE_OPTIONS = "--require=$hook"',
28291
28318
  "$env:GRADLE_OPTS = (($env:GRADLE_OPTS + ' -Dorg.gradle.daemon=false').Trim())",
28292
28319
  "$autolinkingCache = Join-Path $mappedProject 'android\\build\\generated\\autolinking'",
28293
28320
  "if ([IO.Directory]::Exists($autolinkingCache)) { [IO.Directory]::Delete($autolinkingCache, $true) }",
28294
- "$expo = Join-Path $mappedProject 'node_modules\\.bin\\expo.exe'",
28295
- "& $expo @expoArguments",
28296
- "if ($LASTEXITCODE -ne 0) { throw 'Expo Android native build failed.' }",
28321
+ ...mode === "development" ? [
28322
+ "$expo = Join-Path $mappedProject 'node_modules\\.bin\\expo.exe'",
28323
+ "& $expo @expoArguments",
28324
+ "if ($LASTEXITCODE -ne 0) { throw 'Expo Android native build failed.' }"
28325
+ ] : [
28326
+ "$gradle = Join-Path $mappedProject 'android\\gradlew.bat'",
28327
+ "$androidProject = Join-Path $mappedProject 'android'",
28328
+ "& $gradle --no-daemon --console=plain -p $androidProject assembleRelease",
28329
+ "if ($LASTEXITCODE -ne 0) { throw 'Expo Android release compilation failed.' }"
28330
+ ],
28297
28331
  "$adb = Join-Path $androidHome 'platform-tools\\adb.exe'",
28298
- "$readyDevices = @(& $adb devices) | Where-Object { $_ -match '\\tdevice$' } | ForEach-Object { ($_ -split '\\s+')[0] }",
28332
+ "$deviceDeadline = [DateTime]::UtcNow.AddSeconds(60)",
28333
+ "do { $readyDevices = @(& $adb devices) | Where-Object { $_ -match '\\tdevice$' } | ForEach-Object { ($_ -split '\\s+')[0] }; if (-not $readyDevices) { Start-Sleep -Milliseconds 500 } } while (-not $readyDevices -and [DateTime]::UtcNow -lt $deviceDeadline)",
28299
28334
  ...preferredDevice ? [
28300
28335
  `$serial = [Text.Encoding]::UTF8.GetString([Convert]::FromBase64String('${encode(preferredDevice)}'))`,
28301
28336
  "if ($readyDevices -notcontains $serial) { throw 'The selected Expo Android device is not connected after build.' }"
@@ -28304,16 +28339,35 @@ var encodedWindowsExpoAndroidCommand = (project, androidRoot, appId, args, captu
28304
28339
  "if (-not $serial) { $serial = $readyDevices | Select-Object -First 1 }"
28305
28340
  ],
28306
28341
  "if (-not $serial) { throw 'Expo Android build completed but no ready device was found.' }",
28307
- `& $adb -s $serial reverse 'tcp:${metroPort}' 'tcp:${metroPort}'`,
28308
- "if ($LASTEXITCODE -ne 0) { throw 'Expo Android Metro forwarding failed.' }",
28342
+ ...mode === "release" ? [
28343
+ "$apk = Join-Path $mappedProject 'android\\app\\build\\outputs\\apk\\release\\app-release.apk'",
28344
+ "$installOutput = Join-Path $env:TEMP ('absolutejs-adb-install-' + [Guid]::NewGuid().ToString('N') + '.out')",
28345
+ "$installError = $installOutput + '.err'",
28346
+ "$install = Start-Process -FilePath $adb -ArgumentList @('-s', $serial, 'install', '-r', $apk) -NoNewWindow -PassThru -RedirectStandardOutput $installOutput -RedirectStandardError $installError",
28347
+ "if (-not $install.WaitForExit(900000)) { $install.Kill(); throw 'Expo Android release installation timed out after 15 minutes.' }",
28348
+ "$install.WaitForExit()",
28349
+ "$installText = ((Get-Content $installOutput -Raw -ErrorAction SilentlyContinue) + (Get-Content $installError -Raw -ErrorAction SilentlyContinue))",
28350
+ "if ($installText) { Write-Output $installText.Trim() }",
28351
+ "Remove-Item $installOutput, $installError -Force -ErrorAction SilentlyContinue",
28352
+ "if ($install.ExitCode -ne 0 -and $installText -notmatch '(?m)^Success\\r?$') { throw 'Expo Android release installation failed.' }",
28353
+ "$installedPackage = @(& $adb -s $serial shell pm path " + `'${appId}')`,
28354
+ "if ($LASTEXITCODE -ne 0 -or $installedPackage -notmatch '^package:') { throw 'Expo Android release package verification failed.' }"
28355
+ ] : [],
28356
+ `& $adb -s $serial reverse 'tcp:${forwardedPort}' 'tcp:${forwardedPort}'`,
28357
+ "if ($LASTEXITCODE -ne 0) { throw 'Expo Android port forwarding failed.' }",
28309
28358
  `& $adb -s $serial shell am force-stop '${appId}'`,
28310
- "if ($LASTEXITCODE -ne 0) { throw 'Expo Android development-client reset failed.' }",
28311
- `$developmentUrl = '${developmentScheme}://expo-development-client/?url=' + [Uri]::EscapeDataString('http://localhost:${metroPort}')`,
28312
- `& $adb -s $serial shell am start -a android.intent.action.VIEW -d $developmentUrl '${appId}'`,
28313
- "if ($LASTEXITCODE -ne 0) { throw 'Expo Android development-client launch failed.' }",
28314
- "Start-Sleep -Milliseconds 1000",
28315
- `& $adb -s $serial shell am start -a android.intent.action.VIEW -d $developmentUrl '${appId}'`,
28316
- "if ($LASTEXITCODE -ne 0) { throw 'Expo Android development-client retry failed.' }"
28359
+ "if ($LASTEXITCODE -ne 0) { throw 'Expo Android application reset failed.' }",
28360
+ ...mode === "development" ? [
28361
+ `$developmentUrl = '${developmentScheme}://expo-development-client/?url=' + [Uri]::EscapeDataString('http://localhost:${forwardedPort}')`,
28362
+ `& $adb -s $serial shell am start -a android.intent.action.VIEW -d $developmentUrl '${appId}'`,
28363
+ "if ($LASTEXITCODE -ne 0) { throw 'Expo Android development-client launch failed.' }",
28364
+ "Start-Sleep -Milliseconds 1000",
28365
+ `& $adb -s $serial shell am start -a android.intent.action.VIEW -d $developmentUrl '${appId}'`,
28366
+ "if ($LASTEXITCODE -ne 0) { throw 'Expo Android development-client retry failed.' }"
28367
+ ] : [
28368
+ `& $adb -s $serial shell monkey -p '${appId}' -c android.intent.category.LAUNCHER 1 | Out-Null`,
28369
+ "if ($LASTEXITCODE -ne 0) { throw 'Expo Android release launch failed.' }"
28370
+ ]
28317
28371
  ].join("; ");
28318
28372
  const source = [
28319
28373
  "$ErrorActionPreference = 'Stop'",
@@ -28324,7 +28378,7 @@ var encodedWindowsExpoAndroidCommand = (project, androidRoot, appId, args, captu
28324
28378
  `$expoArguments = @([Text.Encoding]::UTF8.GetString([Convert]::FromBase64String('${encode(JSON.stringify(args))}')) | ConvertFrom-Json)`,
28325
28379
  "$env:ANDROID_HOME = $androidHome",
28326
28380
  "$env:ANDROID_SDK_ROOT = $androidHome",
28327
- "$env:NODE_ENV = 'development'",
28381
+ `$env:NODE_ENV = '${mode === "development" ? "development" : "production"}'`,
28328
28382
  ...preferredDevice ? [] : ["$env:ORG_GRADLE_PROJECT_reactNativeArchitectures = 'x86_64'"],
28329
28383
  "New-Item -ItemType Directory -Force -Path $directory | Out-Null",
28330
28384
  "& robocopy.exe $source $directory /MIR /XD node_modules .expo .git .gradle .cxx .kotlin build /XF bun.lock bun.lockb .absolutejs-preserve-subst.cjs /NFL /NDL /NJH /NJS /NP",
@@ -28334,9 +28388,11 @@ var encodedWindowsExpoAndroidCommand = (project, androidRoot, appId, args, captu
28334
28388
  "$bun = (Get-Command bun.exe -ErrorAction Stop).Source",
28335
28389
  "& $bun install",
28336
28390
  "if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE }",
28391
+ "$mirrorRoot = Split-Path -Parent $directory",
28392
+ "$staleDrives = @(& subst.exe) | ForEach-Object { if ($_ -match '^([A-Z]:)\\\\: => (.+)$' -and [String]::Equals($Matches[2].TrimEnd('\\'), $mirrorRoot.TrimEnd('\\'), [StringComparison]::OrdinalIgnoreCase)) { $Matches[1] } }",
28393
+ "foreach ($staleDrive in $staleDrives) { & subst.exe $staleDrive /D | Out-Null }",
28337
28394
  "$drive = @('Z:', 'Y:', 'X:', 'W:', 'V:', 'U:', 'T:') | Where-Object { -not (Test-Path ($_ + '\\')) } | Select-Object -First 1",
28338
28395
  "if (-not $drive) { throw 'AbsoluteJS could not reserve a temporary drive letter for the Expo Android build.' }",
28339
- "$mirrorRoot = Split-Path -Parent $directory",
28340
28396
  "& subst.exe $drive $mirrorRoot",
28341
28397
  "if ($LASTEXITCODE -ne 0) { throw 'AbsoluteJS could not create the short Expo Android build path.' }",
28342
28398
  `try { ${mappedBuild} } finally { Set-Location ($env:SystemDrive + '\\'); & subst.exe $drive /D | Out-Null }`,
@@ -28470,7 +28526,7 @@ var waitForExit = (process2) => new Promise((resolve15) => {
28470
28526
  var runUtilityCommand = async (run, command, args, options) => {
28471
28527
  const child = run(command, args, {
28472
28528
  cwd: options.cwd,
28473
- env: process.env,
28529
+ env: options.env ?? process.env,
28474
28530
  stdio: ["ignore", "pipe", "pipe"]
28475
28531
  });
28476
28532
  forwardLines(child, options.log);
@@ -28482,6 +28538,56 @@ var runUtilityCommand = async (run, command, args, options) => {
28482
28538
  throw abortError();
28483
28539
  return exitCode;
28484
28540
  };
28541
+ var installAbsoluteExpoAndroidRelease = async (options) => {
28542
+ if (options.config.engine !== "expo")
28543
+ throw new TypeError("The Expo Android release installer requires Expo.");
28544
+ if (!options.config.platforms.includes("android"))
28545
+ throw new TypeError("The Expo Android release installer requires the android platform.");
28546
+ const host3 = options.host ?? detectAbsoluteMobileHost();
28547
+ const project = options.config.nativeProjectDirectory;
28548
+ const executable = options.executable ?? await absoluteExpoExecutable(project);
28549
+ const capture = options.capture ?? captureCommand4;
28550
+ const run = options.spawnProcess ?? spawn;
28551
+ const log = options.log ?? (() => {
28552
+ return;
28553
+ });
28554
+ const env = { ...process.env, NODE_ENV: "production" };
28555
+ const utilityOptions = {
28556
+ cwd: project,
28557
+ env,
28558
+ log,
28559
+ signal: options.signal
28560
+ };
28561
+ const started = performance.now();
28562
+ const prebuildExit = await runUtilityCommand(run, executable, ["prebuild", "--clean", "--no-install", "--platform", "android"], utilityOptions);
28563
+ if (prebuildExit !== 0)
28564
+ throw new Error(`Expo Android production preparation exited with status ${prebuildExit}.`);
28565
+ const androidRoot = options.androidRoot ?? process.env.ANDROID_HOME ?? process.env.ANDROID_SDK_ROOT ?? absoluteManagedAndroidSdkRoot(host3);
28566
+ const args = [
28567
+ "run:android",
28568
+ "--variant",
28569
+ "release",
28570
+ "--no-bundler",
28571
+ ...options.androidDevice ? ["--device", options.androidDevice] : []
28572
+ ];
28573
+ const invocation = host3 === "wsl" ? encodedWindowsExpoAndroidCommand(project, androidRoot, options.config.appId, args, capture, options.forwardedPort, options.androidDevice, "release") : [executable, ...args];
28574
+ if (host3 === "wsl")
28575
+ log("[android] Mirroring native inputs to the Windows host for an installable Expo release build.");
28576
+ const [releaseExecutable, ...releaseArguments] = invocation;
28577
+ if (!releaseExecutable)
28578
+ throw new Error("Expo Android release build command is empty.");
28579
+ const releaseExit = await runUtilityCommand(run, releaseExecutable, releaseArguments, utilityOptions);
28580
+ if (releaseExit !== 0)
28581
+ throw new Error(`Expo Android release build exited with status ${releaseExit}.`);
28582
+ const adb = options.androidAdb ?? join17(androidRoot, "platform-tools", host3 === "windows" || host3 === "wsl" ? "adb.exe" : "adb");
28583
+ const serial = host3 === "wsl" ? options.androidDevice ?? capture([adb, "devices"]).stdout.split(/\r?\n/u).flatMap((line) => {
28584
+ const match = /^(\S+)\s+device$/u.exec(line.trim());
28585
+ return match?.[1] ? [match[1]] : [];
28586
+ }).find((value) => value.startsWith("emulator-")) : launchLocalExpoAndroidRelease(adb, options.config.appId, options.forwardedPort, capture, options.androidDevice);
28587
+ if (!serial)
28588
+ throw new Error("Expo Android release build completed but its device could not be identified.");
28589
+ return { durationMs: performance.now() - started, serial };
28590
+ };
28485
28591
  var startAbsoluteExpoDevSession = async (options) => {
28486
28592
  const plan = planAbsoluteExpoDevSession(options.config, options);
28487
28593
  const executable = options.executable ?? await absoluteExpoExecutable(plan.project);
@@ -37807,6 +37913,7 @@ export {
37807
37913
  inspectAbsoluteRemoteMac,
37808
37914
  inspectAbsoluteRemoteMacLanHost,
37809
37915
  inspectAbsoluteRemoteMacWorkspace,
37916
+ installAbsoluteExpoAndroidRelease,
37810
37917
  installAbsoluteIosRelease,
37811
37918
  installAbsoluteMobileAdaptiveShell,
37812
37919
  installAbsoluteMobileAuthEnvironment,
@@ -37905,5 +38012,5 @@ export {
37905
38012
  writeAbsoluteMobileGithubWorkflow
37906
38013
  };
37907
38014
 
37908
- //# debugId=16567FBADD9BB3F164756E2164756E21
38015
+ //# debugId=7510C0F4F58DE47064756E2164756E21
37909
38016
  //# sourceMappingURL=index.js.map