@absolutejs/absolute 0.20.0-beta.92 → 0.20.0-beta.94

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.
Files changed (39) hide show
  1. package/CHANGELOG.md +24 -0
  2. package/changelog.json +48 -0
  3. package/dist/angular/components/core/streamingSlotRegistrar.js +1 -1
  4. package/dist/angular/components/core/streamingSlotRegistry.js +2 -2
  5. package/dist/build/buildWorker.js +10 -1
  6. package/dist/build.js +16 -7
  7. package/dist/build.js.map +9 -8
  8. package/dist/cli/{compile-vf61bv90.js → compile-qg75ewma.js} +5 -5
  9. package/dist/cli/{dev-perzmh2w.js → dev-sm9px53g.js} +83 -11
  10. package/dist/cli/{expoDevController-tr63cg78.js → expoDevController-a0jk8d43.js} +31 -2
  11. package/dist/cli/expoNativeWatcher-rmc95bak.js +138 -0
  12. package/dist/cli/{expoProject-djc0vk7g.js → expoProject-h38entbj.js} +1 -1
  13. package/dist/cli/{index-8zrnvazp.js → index-0t1cxstr.js} +261 -48
  14. package/dist/cli/{index-fn44wefq.js → index-3sdvzrv2.js} +37 -28
  15. package/dist/cli/{index-gxkmg2ss.js → index-51yyq29s.js} +1 -1
  16. package/dist/cli/index-bw4ktfnz.js +11 -0
  17. package/dist/cli/{index-751czk1b.js → index-d8va9b7v.js} +1 -1
  18. package/dist/cli/index.js +5 -5
  19. package/dist/cli/{mobile-yk7qr9qg.js → mobile-dev4mjsa.js} +20 -12
  20. package/dist/cli/{remoteMacProtocol-vw931n0a.js → remoteMacProtocol-kqvkp0qd.js} +2 -1
  21. package/dist/cli/{start-ef7tgbmf.js → start-0ddnh0y4.js} +3 -3
  22. package/dist/dev/client/handlers/svelte.ts +11 -15
  23. package/dist/dev/serverBootstrap.js +10 -1
  24. package/dist/index.js +17 -8
  25. package/dist/index.js.map +11 -10
  26. package/dist/mobile/index.js +599 -208
  27. package/dist/mobile/index.js.map +11 -8
  28. package/dist/mobile/mobilePreviewClient.ts +1 -1
  29. package/dist/mobile/remoteMacAgentEntry.js +354 -188
  30. package/dist/src/dev/clientManager.d.ts +2 -2
  31. package/dist/src/mobile/androidConformance.d.ts +4 -1
  32. package/dist/src/mobile/expoActivityResultRecovery.d.ts +1 -0
  33. package/dist/src/mobile/expoBridge.d.ts +2 -2
  34. package/dist/src/mobile/expoDevController.d.ts +2 -6
  35. package/dist/src/mobile/expoNativeWatcher.d.ts +21 -0
  36. package/dist/src/mobile/index.d.ts +1 -0
  37. package/dist/src/mobile/remoteMacProtocol.d.ts +1 -4
  38. package/dist/src/utils/unrefTimer.d.ts +5 -0
  39. package/package.json +5 -2
@@ -23,7 +23,7 @@ import {
23
23
  writeFile
24
24
  } from "fs/promises";
25
25
  import { createHash as createHash2 } from "crypto";
26
- import { basename, dirname as dirname2, join as join4, relative as relative2, resolve as resolve3, sep } from "path";
26
+ import { basename, dirname as dirname2, join as join5, relative as relative2, resolve as resolve3, sep } from "path";
27
27
 
28
28
  // src/mobile/syncSchema.ts
29
29
  import { readFileSync } from "fs";
@@ -1405,6 +1405,127 @@ var absoluteExpoNativeObservabilityPaths = (project) => [
1405
1405
  ...absoluteExpoNativeObservabilityFiles(project).keys()
1406
1406
  ];
1407
1407
 
1408
+ // src/mobile/expoActivityResultRecovery.ts
1409
+ import { join as join4 } from "path";
1410
+ var HEADER2 = `// Generated by AbsoluteJS. Edit absolute.config.ts, then run absolute mobile sync.
1411
+ `;
1412
+ var XML_HEADER2 = `<!-- Generated by AbsoluteJS. Edit absolute.config.ts, then run absolute mobile sync. -->
1413
+ `;
1414
+ var moduleConfig2 = `${JSON.stringify({
1415
+ android: {
1416
+ modules: [
1417
+ "expo.modules.absoluteactivityresultrecovery.AbsoluteActivityResultRecoveryModule"
1418
+ ]
1419
+ },
1420
+ platforms: ["android"]
1421
+ }, null, 2)}
1422
+ `;
1423
+ var androidBuild2 = `${HEADER2}plugins {
1424
+ id 'com.android.library'
1425
+ id 'expo-module-gradle-plugin'
1426
+ }
1427
+
1428
+ group = 'expo.modules.absoluteactivityresultrecovery'
1429
+ version = '0.0.1'
1430
+
1431
+ android {
1432
+ namespace 'expo.modules.absoluteactivityresultrecovery'
1433
+ defaultConfig {
1434
+ versionCode 1
1435
+ versionName '0.0.1'
1436
+ }
1437
+ lintOptions { abortOnError false }
1438
+ }
1439
+ `;
1440
+ var androidManifest2 = `${XML_HEADER2}<manifest xmlns:android="http://schemas.android.com/apk/res/android" />
1441
+ `;
1442
+ var androidModule2 = `${HEADER2}package expo.modules.absoluteactivityresultrecovery
1443
+
1444
+ import android.content.Intent
1445
+ import android.util.Log
1446
+ import expo.modules.kotlin.modules.Module
1447
+ import expo.modules.kotlin.modules.ModuleDefinition
1448
+
1449
+ data class AbsolutePendingActivityResult(
1450
+ val requestCode: Int,
1451
+ val resultCode: Int,
1452
+ val data: Intent?
1453
+ )
1454
+
1455
+ object AbsoluteActivityResultRecoveryState {
1456
+ @Volatile
1457
+ var applicationRuntimeReady = false
1458
+
1459
+ private val pendingActivityResults = ArrayDeque<AbsolutePendingActivityResult>()
1460
+
1461
+ @Synchronized
1462
+ fun enqueueActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
1463
+ if (pendingActivityResults.size == 8) pendingActivityResults.removeFirst()
1464
+ pendingActivityResults.addLast(
1465
+ AbsolutePendingActivityResult(requestCode, resultCode, data?.let(::Intent))
1466
+ )
1467
+ Log.d("AbsoluteJS", "Queued early Android activity result; pending=" + pendingActivityResults.size)
1468
+ }
1469
+
1470
+ @Synchronized
1471
+ fun hasPendingActivityResults() = pendingActivityResults.isNotEmpty()
1472
+
1473
+ @Synchronized
1474
+ fun drainActivityResults(): List<AbsolutePendingActivityResult> {
1475
+ val drained = pendingActivityResults.toList()
1476
+ pendingActivityResults.clear()
1477
+ Log.d("AbsoluteJS", "Replaying queued Android activity results; count=" + drained.size)
1478
+ return drained
1479
+ }
1480
+ }
1481
+
1482
+ class AbsoluteActivityResultRecoveryModule : Module() {
1483
+ override fun definition() = ModuleDefinition {
1484
+ Name("AbsoluteActivityResultRecovery")
1485
+
1486
+ Function("markApplicationRuntimeReady") {
1487
+ AbsoluteActivityResultRecoveryState.applicationRuntimeReady = true
1488
+ Log.d("AbsoluteJS", "Expo application runtime ready for Android activity results")
1489
+ }
1490
+ }
1491
+ }
1492
+ `;
1493
+ var runtime = `${HEADER2}import { requireNativeModule } from 'expo-modules-core';
1494
+
1495
+ type AbsoluteActivityResultRecoveryNative = {
1496
+ markApplicationRuntimeReady(): void;
1497
+ };
1498
+
1499
+ const native = requireNativeModule<AbsoluteActivityResultRecoveryNative>(
1500
+ 'AbsoluteActivityResultRecovery'
1501
+ );
1502
+
1503
+ export const markAbsoluteApplicationRuntimeReady = () =>
1504
+ native.markApplicationRuntimeReady();
1505
+ `;
1506
+ var absoluteExpoActivityResultRecoveryFiles = (project) => new Map([
1507
+ [
1508
+ join4(project, "modules/absolute-activity-result-recovery/expo-module.config.json"),
1509
+ moduleConfig2
1510
+ ],
1511
+ [
1512
+ join4(project, "modules/absolute-activity-result-recovery/android/build.gradle"),
1513
+ androidBuild2
1514
+ ],
1515
+ [
1516
+ join4(project, "modules/absolute-activity-result-recovery/android/src/main/AndroidManifest.xml"),
1517
+ androidManifest2
1518
+ ],
1519
+ [
1520
+ join4(project, "modules/absolute-activity-result-recovery/android/src/main/java/expo/modules/absoluteactivityresultrecovery/AbsoluteActivityResultRecoveryModule.kt"),
1521
+ androidModule2
1522
+ ],
1523
+ [
1524
+ join4(project, "src/generated/AbsoluteActivityResultRecovery.ts"),
1525
+ runtime
1526
+ ]
1527
+ ]);
1528
+
1408
1529
  // src/mobile/expoProject.ts
1409
1530
  var EXPO_GENERATED_HEADER = `// Generated by AbsoluteJS. Edit absolute.config.ts, then run absolute mobile sync.
1410
1531
  `;
@@ -1485,7 +1606,7 @@ var routeSegments = (route) => {
1485
1606
  return segment;
1486
1607
  });
1487
1608
  };
1488
- var routeFile = (project, route) => join4(project, "app", ...routeSegments(route), "index.tsx");
1609
+ var routeFile = (project, route) => join5(project, "app", ...routeSegments(route), "index.tsx");
1489
1610
  var packageDependencies = (plan) => Object.fromEntries(plan.requiredPackages.map((spec) => {
1490
1611
  const separator = spec.lastIndexOf("@");
1491
1612
  return [spec.slice(0, separator), spec.slice(separator + 1)];
@@ -1493,7 +1614,7 @@ var packageDependencies = (plan) => Object.fromEntries(plan.requiredPackages.map
1493
1614
  var expoPackage = (auth, sync, devices, updates) => ({
1494
1615
  dependencies: {
1495
1616
  "@absolutejs/devices": "0.7.0",
1496
- "@absolutejs/devices-expo": "0.0.2",
1617
+ "@absolutejs/devices-expo": "0.0.9",
1497
1618
  ...auth ? {
1498
1619
  "@absolutejs/auth": ABSOLUTE_EXPO_AUTH_CORE_VERSION,
1499
1620
  [ABSOLUTE_EXPO_AUTH_PACKAGE]: ABSOLUTE_EXPO_AUTH_VERSION
@@ -1629,6 +1750,7 @@ var expoAppConfig = (config, auth, sync, devices, runtimeFingerprint) => {
1629
1750
  plugins: [
1630
1751
  "expo-router",
1631
1752
  ["expo-dev-client", { launchMode: "most-recent" }],
1753
+ "./plugins/withAbsoluteActivityResultRecovery",
1632
1754
  ...auth || config.updates ? ["expo-secure-store"] : [],
1633
1755
  ...sync ? [
1634
1756
  "expo-sqlite",
@@ -1718,6 +1840,77 @@ const withAbsoluteDevelopmentCa = config => {
1718
1840
 
1719
1841
  module.exports = withAbsoluteDevelopmentCa;
1720
1842
  `;
1843
+ var expoActivityResultRecoveryPlugin = `${EXPO_GENERATED_HEADER}const { withMainActivity } = require('expo/config-plugins');
1844
+
1845
+ const IMPORT_ANCHOR = 'import android.os.Bundle';
1846
+ const CLASS_ANCHOR = 'class MainActivity : ReactActivity() {';
1847
+ const RECOVERY_MARKER = 'absolutePendingActivityResults';
1848
+
1849
+ const withAbsoluteActivityResultRecovery = config => withMainActivity(config, value => {
1850
+ if (value.modResults.language !== 'kt') {
1851
+ throw new Error('AbsoluteJS Expo activity-result recovery requires a Kotlin MainActivity.');
1852
+ }
1853
+ let source = value.modResults.contents;
1854
+ if (source.includes(RECOVERY_MARKER)) return value;
1855
+ if (!source.includes(IMPORT_ANCHOR) || !source.includes(CLASS_ANCHOR)) {
1856
+ throw new Error('AbsoluteJS could not locate the Expo MainActivity integration points.');
1857
+ }
1858
+ source = source.replace(IMPORT_ANCHOR, [
1859
+ 'import android.content.Intent',
1860
+ 'import android.os.Bundle',
1861
+ 'import android.os.Handler',
1862
+ 'import android.os.Looper',
1863
+ 'import expo.modules.absoluteactivityresultrecovery.AbsoluteActivityResultRecoveryState'
1864
+ ].join('\\n'));
1865
+ source = source.replace(CLASS_ANCHOR, \`\${CLASS_ANCHOR}
1866
+ private val absoluteActivityResultHandler = Handler(Looper.getMainLooper())
1867
+ private var absoluteActivityResultAttempts = 0
1868
+ private val absoluteReplayActivityResults = object : Runnable {
1869
+ override fun run() {
1870
+ if (isFinishing || isDestroyed || !AbsoluteActivityResultRecoveryState.hasPendingActivityResults()) return
1871
+ if (!AbsoluteActivityResultRecoveryState.applicationRuntimeReady) {
1872
+ if (absoluteActivityResultAttempts++ < 240) {
1873
+ absoluteActivityResultHandler.postDelayed(this, 250)
1874
+ }
1875
+ return
1876
+ }
1877
+ absoluteActivityResultAttempts = 0
1878
+ AbsoluteActivityResultRecoveryState.drainActivityResults().forEach { result ->
1879
+ super@MainActivity.onActivityResult(result.requestCode, result.resultCode, result.data)
1880
+ }
1881
+ }
1882
+ }
1883
+
1884
+ override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
1885
+ if (AbsoluteActivityResultRecoveryState.applicationRuntimeReady) {
1886
+ super.onActivityResult(requestCode, resultCode, data)
1887
+ return
1888
+ }
1889
+ AbsoluteActivityResultRecoveryState.enqueueActivityResult(requestCode, resultCode, data)
1890
+ absoluteActivityResultHandler.removeCallbacks(absoluteReplayActivityResults)
1891
+ absoluteActivityResultHandler.postDelayed(absoluteReplayActivityResults, 250)
1892
+ }
1893
+
1894
+ override fun onResume() {
1895
+ super.onResume()
1896
+ if (AbsoluteActivityResultRecoveryState.hasPendingActivityResults()) {
1897
+ absoluteActivityResultAttempts = 0
1898
+ absoluteActivityResultHandler.removeCallbacks(absoluteReplayActivityResults)
1899
+ absoluteActivityResultHandler.post(absoluteReplayActivityResults)
1900
+ }
1901
+ }
1902
+
1903
+ override fun onDestroy() {
1904
+ absoluteActivityResultHandler.removeCallbacks(absoluteReplayActivityResults)
1905
+ super.onDestroy()
1906
+ }
1907
+ \`);
1908
+ value.modResults.contents = source;
1909
+ return value;
1910
+ });
1911
+
1912
+ module.exports = withAbsoluteActivityResultRecovery;
1913
+ `;
1721
1914
  var metroConfig = (projectRoot) => `${EXPO_GENERATED_HEADER}const { getDefaultConfig } = require('expo/metro-config');
1722
1915
  const path = require('node:path');
1723
1916
 
@@ -1735,6 +1928,8 @@ module.exports = config;
1735
1928
  `;
1736
1929
  var layoutSource = (auth, sync, updates, observability) => `${EXPO_GENERATED_HEADER}import { Stack } from 'expo-router';
1737
1930
  import '../src/generated/AbsoluteDevices';
1931
+ import { useEffect as useActivityResultRecoveryEffect } from 'react';
1932
+ import { markAbsoluteApplicationRuntimeReady } from '../src/generated/AbsoluteActivityResultRecovery';
1738
1933
  ${auth ? `import { useEffect, useState } from 'react';
1739
1934
  import { startAbsoluteExpoAuth } from '../src/generated/AbsoluteAuth';` : ""}
1740
1935
  ${sync ? "import { startAbsoluteExpoSync } from '../src/generated/AbsoluteSync';" : ""}
@@ -1744,6 +1939,9 @@ ${observability ? `import { useEffect as useNativeObservabilityEffect } from 're
1744
1939
  import { startAbsoluteExpoNativeObservability } from '../src/generated/AbsoluteNativeObservability';` : ""}
1745
1940
 
1746
1941
  export default function AbsoluteLayout() {
1942
+ useActivityResultRecoveryEffect(() => {
1943
+ markAbsoluteApplicationRuntimeReady();
1944
+ }, []);
1747
1945
  ${updates ? "useUpdateEffect(() => { void startAbsoluteExpoUpdates(); }, []);" : ""}
1748
1946
  ${observability ? "useNativeObservabilityEffect(() => { void startAbsoluteExpoNativeObservability(); }, []);" : ""}
1749
1947
  ${auth ? `const [ready, setReady] = useState(false);
@@ -2100,7 +2298,7 @@ var webHostSource = (config, auth, sync) => {
2100
2298
  const nativeRoutePatterns = nativeRoutes.map((route) => route.split("/").filter(Boolean));
2101
2299
  return `${EXPO_GENERATED_HEADER}import * as Linking from 'expo-linking';
2102
2300
  import { router, usePathname } from 'expo-router';
2103
- import { useEffect, useRef, useState } from 'react';
2301
+ import { useEffect, useMemo, useRef, useState } from 'react';
2104
2302
  import { ActivityIndicator, BackHandler, Platform, StyleSheet, View } from 'react-native';
2105
2303
  import { useSafeAreaInsets } from 'react-native-safe-area-context';
2106
2304
  import { WebView, type WebViewMessageEvent } from 'react-native-webview';
@@ -2255,17 +2453,21 @@ const authStatus = async () => {
2255
2453
  return { principal: principal ? { namespace: principal.namespace } : null, user };` : "throw new Error('Expo Auth is not configured.');"}
2256
2454
  };
2257
2455
 
2258
- export function AbsoluteWebHost() {
2259
- const pathname = usePathname() || '/';
2456
+ export type AbsoluteWebHostProps = { path?: string };
2457
+
2458
+ export function AbsoluteWebHost({ path }: AbsoluteWebHostProps = {}) {
2459
+ const routerPathname = usePathname() || '/';
2460
+ const pathname = path?.startsWith('/') && !path.startsWith('//') ? path : routerPathname;
2260
2461
  const safeAreaInsets = useSafeAreaInsets();
2261
2462
  const webView = useRef<WebView>(null);
2262
2463
  const devicesBridge = useRef<{ close(): void | Promise<void>; request(method: string, params: Record<string, unknown>): Promise<unknown> } | undefined>(undefined);
2263
2464
  const syncBridge = useRef<{ close(): void | Promise<void>; request(method: string, params: Record<string, unknown>): Promise<unknown> } | undefined>(undefined);
2264
2465
  const [indexUri, setIndexUri] = useState<string>();
2265
- const [canGoBack, setCanGoBack] = useState(false);
2466
+ const canGoBack = useRef(false);
2266
2467
  const [runtimeReady, setRuntimeReady] = useState(!AUTH_ENABLED && !SYNC_ENABLED);
2267
2468
  const [devicesReady, setDevicesReady] = useState(false);
2268
2469
  const activeWebPath = useRef(pathname);
2470
+ const webSource = useMemo(() => indexUri ? { uri: indexUri } : undefined, [indexUri]);
2269
2471
 
2270
2472
  useEffect(() => {
2271
2473
  if (!AUTH_ENABLED && !SYNC_ENABLED) return;
@@ -2323,7 +2525,7 @@ export function AbsoluteWebHost() {
2323
2525
  if (!active) return;
2324
2526
  respond({ event, format: BRIDGE_FORMAT, kind: 'event', path: activeWebPath.current, payload });
2325
2527
  }).then(host => {
2326
- if (!active) return void host.close();
2528
+ if (!active) return void Promise.resolve(host.close()).catch(() => undefined);
2327
2529
  devicesBridge.current = host;
2328
2530
  setDevicesReady(true);
2329
2531
  });
@@ -2331,7 +2533,7 @@ export function AbsoluteWebHost() {
2331
2533
  active = false;
2332
2534
  const host = devicesBridge.current;
2333
2535
  devicesBridge.current = undefined;
2334
- void host?.close();
2536
+ if (host) void Promise.resolve(host.close()).catch(() => undefined);
2335
2537
  };
2336
2538
  }, []);
2337
2539
  const hasOrigin = (source: string, origin: string) => {
@@ -2351,7 +2553,7 @@ export function AbsoluteWebHost() {
2351
2553
  return;
2352
2554
  }
2353
2555
  if (message.kind === 'event' && message.event === 'back-unhandled') {
2354
- if (canGoBack) webView.current?.goBack();
2556
+ if (canGoBack.current) webView.current?.goBack();
2355
2557
  else BackHandler.exitApp();
2356
2558
  return;
2357
2559
  }
@@ -2385,22 +2587,27 @@ export function AbsoluteWebHost() {
2385
2587
  }
2386
2588
  };
2387
2589
 
2388
- if (!indexUri || !runtimeReady || !devicesReady) return <View style={styles.loading}><ActivityIndicator /></View>;
2590
+ if (!webSource || !runtimeReady || !devicesReady) return <View style={styles.loading}><ActivityIndicator /></View>;
2389
2591
  return <WebView
2390
2592
  allowFileAccess
2391
2593
  allowFileAccessFromFileURLs
2392
2594
  allowUniversalAccessFromFileURLs={false}
2393
- allowingReadAccessToURL={indexUri.slice(0, indexUri.lastIndexOf('/') + 1)}
2595
+ allowingReadAccessToURL={webSource.uri.slice(0, webSource.uri.lastIndexOf('/') + 1)}
2394
2596
  injectedJavaScriptBeforeContentLoaded={bridgeBootstrap(pathname, safeAreaInsets)}
2395
2597
  onMessage={onMessage}
2396
- onNavigationStateChange={state => setCanGoBack(state.canGoBack)}
2598
+ onNavigationStateChange={state => {
2599
+ canGoBack.current = state.canGoBack;
2600
+ if (!DEV_ORIGIN || !hasOrigin(state.url, DEV_ORIGIN)) return;
2601
+ const route = new URL(state.url);
2602
+ activeWebPath.current = route.pathname + route.search + route.hash;
2603
+ }}
2397
2604
  onShouldStartLoadWithRequest={request => {
2398
2605
  if (request.url.startsWith('file:') || hasOrigin(request.url, PRODUCTION_ORIGIN) || DEV_ORIGIN && hasOrigin(request.url, DEV_ORIGIN)) return true;
2399
2606
  void Linking.openURL(request.url);
2400
2607
  return false;
2401
2608
  }}
2402
2609
  ref={webView}
2403
- source={{ uri: indexUri }}
2610
+ source={webSource}
2404
2611
  style={styles.web}
2405
2612
  />;
2406
2613
  }
@@ -2599,8 +2806,8 @@ const styles = StyleSheet.create({
2599
2806
  error: { color: '#b91c1c', fontSize: 16, textAlign: 'center' }
2600
2807
  });
2601
2808
  `;
2602
- var nativeWrapperSource = (wrapper, module, runtime, route) => `${EXPO_GENERATED_HEADER}import ApplicationNativeRoute from ${JSON.stringify(portableRelative(dirname2(wrapper), module).replace(/\.(?:[cm]?[jt]sx?)$/u, ""))};
2603
- import { createAbsoluteNativeRoute, createAbsoluteNativeRouteErrorBoundary } from ${JSON.stringify(portableRelative(dirname2(wrapper), runtime).replace(/\.(?:[cm]?[jt]sx?)$/u, ""))};
2809
+ var nativeWrapperSource = (wrapper, module, runtime2, route) => `${EXPO_GENERATED_HEADER}import ApplicationNativeRoute from ${JSON.stringify(portableRelative(dirname2(wrapper), module).replace(/\.(?:[cm]?[jt]sx?)$/u, ""))};
2810
+ import { createAbsoluteNativeRoute, createAbsoluteNativeRouteErrorBoundary } from ${JSON.stringify(portableRelative(dirname2(wrapper), runtime2).replace(/\.(?:[cm]?[jt]sx?)$/u, ""))};
2604
2811
 
2605
2812
  export const ErrorBoundary = createAbsoluteNativeRouteErrorBoundary(${JSON.stringify(route)});
2606
2813
  export default createAbsoluteNativeRoute(ApplicationNativeRoute, ${JSON.stringify(route)});
@@ -2669,7 +2876,7 @@ var pruneManagedFiles = async (paths) => {
2669
2876
  return removed.filter(Boolean).length;
2670
2877
  };
2671
2878
  var pruneStaleManagedExpoRoutes = async (project, expected) => {
2672
- const appDirectory = join4(project, "app");
2879
+ const appDirectory = join5(project, "app");
2673
2880
  if (!await exists(appDirectory))
2674
2881
  return 0;
2675
2882
  const files = await walkFiles(appDirectory);
@@ -2717,7 +2924,7 @@ var writeAbsoluteExpoProject = async (config, options) => {
2717
2924
  if (missing) {
2718
2925
  throw new TypeError(`Expo native route ${missing.route} references missing module ${missing.module}.`);
2719
2926
  }
2720
- const marker = join4(project, EXPO_PROJECT_MARKER);
2927
+ const marker = join5(project, EXPO_PROJECT_MARKER);
2721
2928
  if (await exists(project) && !await exists(marker)) {
2722
2929
  const entries = await readdir(project);
2723
2930
  if (entries.length > 0 && !options.force) {
@@ -2730,7 +2937,7 @@ var writeAbsoluteExpoProject = async (config, options) => {
2730
2937
  const authEnabled = Boolean(auth);
2731
2938
  const files = new Map([
2732
2939
  [
2733
- join4(project, ".gitignore"),
2940
+ join5(project, ".gitignore"),
2734
2941
  `.expo/
2735
2942
  android/
2736
2943
  ios/
@@ -2738,74 +2945,80 @@ node_modules/
2738
2945
  `
2739
2946
  ],
2740
2947
  [
2741
- join4(project, "app.json"),
2948
+ join5(project, "app.json"),
2742
2949
  jsonSource(expoAppConfig(config, authEnabled, syncEnabled, devices, runtimeFingerprint))
2743
2950
  ],
2744
- [join4(project, "app.config.js"), expoDynamicAppConfig],
2951
+ [join5(project, "app.config.js"), expoDynamicAppConfig],
2745
2952
  [
2746
- join4(project, "package.json"),
2953
+ join5(project, "package.json"),
2747
2954
  jsonSource(expoPackage(authEnabled, syncEnabled, devices, config.updates !== undefined))
2748
2955
  ],
2749
- [join4(project, "metro.config.js"), metroConfig(projectRoot)],
2956
+ [join5(project, "metro.config.js"), metroConfig(projectRoot)],
2750
2957
  [
2751
- join4(project, "plugins", "withAbsoluteDevelopmentCa.js"),
2958
+ join5(project, "plugins", "withAbsoluteDevelopmentCa.js"),
2752
2959
  expoDevelopmentCaPlugin
2753
2960
  ],
2754
2961
  [
2755
- join4(project, "tsconfig.json"),
2962
+ join5(project, "plugins", "withAbsoluteActivityResultRecovery.js"),
2963
+ expoActivityResultRecoveryPlugin
2964
+ ],
2965
+ [
2966
+ join5(project, "tsconfig.json"),
2756
2967
  jsonSource(expoTsConfig(projectRoot, project, authEnabled, syncEnabled))
2757
2968
  ],
2758
2969
  [
2759
- join4(project, "app", "_layout.tsx"),
2970
+ join5(project, "app", "_layout.tsx"),
2760
2971
  layoutSource(authEnabled, syncEnabled, config.updates !== undefined, config.observability !== undefined)
2761
2972
  ],
2762
2973
  [
2763
- join4(project, "app", "__absolute", "native", "index.tsx"),
2974
+ join5(project, "app", "__absolute", "native", "index.tsx"),
2764
2975
  nativeDiagnosticSource
2765
2976
  ],
2766
2977
  [
2767
- join4(project, "src", "generated", "AbsoluteDevices.ts"),
2978
+ join5(project, "src", "generated", "AbsoluteDevices.ts"),
2768
2979
  devicesRuntimeSource(config, devices, authEnabled)
2769
2980
  ],
2770
2981
  [
2771
- join4(project, "src", "generated", "AbsoluteNativeRoute.tsx"),
2982
+ join5(project, "src", "generated", "AbsoluteNativeRoute.tsx"),
2772
2983
  nativeRouteRuntimeSource(authEnabled)
2773
2984
  ],
2774
2985
  [
2775
- join4(project, "src", "generated", "AbsoluteWebHost.tsx"),
2986
+ join5(project, "src", "generated", "AbsoluteWebHost.tsx"),
2776
2987
  webHostSource(config, auth, syncEnabled)
2777
2988
  ]
2778
2989
  ]);
2990
+ for (const [path, source] of absoluteExpoActivityResultRecoveryFiles(project))
2991
+ files.set(path, source);
2779
2992
  if (config.observability) {
2780
2993
  for (const [path, source] of absoluteExpoNativeObservabilityFiles(project))
2781
2994
  files.set(path, source);
2782
2995
  }
2783
2996
  if (config.updates) {
2784
- files.set(join4(project, "src", "generated", "AbsoluteUpdates.ts"), updatesRuntimeSource(config));
2997
+ files.set(join5(project, "src", "generated", "AbsoluteUpdates.ts"), updatesRuntimeSource(config));
2785
2998
  }
2786
2999
  const expoCodeSigning = config.updates?.expoCodeSigning;
2787
3000
  if (expoCodeSigning)
2788
- files.set(join4(project, "certs", "absolute-mobile-update.pem"), expoCodeSigning.certificatePem);
3001
+ files.set(join5(project, "certs", "absolute-mobile-update.pem"), expoCodeSigning.certificatePem);
2789
3002
  if (auth) {
2790
- files.set(join4(project, "src", "generated", "AbsoluteAuth.ts"), authRuntimeSource(auth, config.appId));
3003
+ files.set(join5(project, "src", "generated", "AbsoluteAuth.ts"), authRuntimeSource(auth, config.appId));
2791
3004
  }
2792
3005
  if (syncSchema) {
2793
- files.set(join4(project, "src", "generated", "AbsoluteSync.ts"), syncRuntimeSource(config, syncSchema));
3006
+ files.set(join5(project, "src", "generated", "AbsoluteSync.ts"), syncRuntimeSource(config, syncSchema));
2794
3007
  }
2795
- const webAssetsPath = join4(project, "src", "generated", "webAssets.ts");
3008
+ const webAssetsPath = join5(project, "src", "generated", "webAssets.ts");
2796
3009
  if (!await exists(webAssetsPath)) {
2797
3010
  files.set(webAssetsPath, emptyWebAssetsSource);
2798
3011
  }
2799
3012
  if (!config.expoNativeRoutes["/"]) {
2800
- files.set(join4(project, "app", "index.tsx"), webRouteSource);
3013
+ files.set(join5(project, "app", "index.tsx"), webRouteSource);
2801
3014
  }
2802
- files.set(join4(project, "app", "[...absolute].tsx"), catchAllRouteSource);
2803
- const nativeRouteRuntime = join4(project, "src", "generated", "AbsoluteNativeRoute.tsx");
3015
+ files.set(join5(project, "app", "[...absolute].tsx"), catchAllRouteSource);
3016
+ const nativeRouteRuntime = join5(project, "src", "generated", "AbsoluteNativeRoute.tsx");
2804
3017
  for (const [route, module] of routeModules) {
2805
- const wrapper = route === "/" ? join4(project, "app", "index.tsx") : routeFile(project, route);
3018
+ const wrapper = route === "/" ? join5(project, "app", "index.tsx") : routeFile(project, route);
2806
3019
  files.set(wrapper, nativeWrapperSource(wrapper, module, nativeRouteRuntime, route));
2807
3020
  }
2808
- const removedRoutes = await pruneStaleManagedExpoRoutes(project, new Set([...files.keys()].filter((path) => path.startsWith(`${join4(project, "app")}${sep}`))));
3021
+ const removedRoutes = await pruneStaleManagedExpoRoutes(project, new Set([...files.keys()].filter((path) => path.startsWith(`${join5(project, "app")}${sep}`))));
2809
3022
  const removedObservability = config.observability ? 0 : await pruneManagedFiles(absoluteExpoNativeObservabilityPaths(project));
2810
3023
  const changes = await Promise.all([...files].map(([path, source]) => writeManagedFile(path, source, true)));
2811
3024
  const changed = removedRoutes + removedObservability + changes.filter(Boolean).length;
@@ -2814,7 +3027,7 @@ node_modules/
2814
3027
  var walkFiles = async (root, directory = root) => {
2815
3028
  const entries = await readdir(directory, { withFileTypes: true });
2816
3029
  const nested = await Promise.all(entries.map((entry) => {
2817
- const path = join4(directory, entry.name);
3030
+ const path = join5(directory, entry.name);
2818
3031
  if (entry.isDirectory())
2819
3032
  return walkFiles(root, path);
2820
3033
  if (entry.isFile())
@@ -2881,11 +3094,11 @@ export const materializeAbsoluteWebBundle = async () => {
2881
3094
  var syncAbsoluteExpoWebAssets = async (config) => {
2882
3095
  if (config.engine !== "expo")
2883
3096
  throw new TypeError("Expo asset sync requires mobile.engine: expo.");
2884
- const marker = join4(config.nativeProjectDirectory, EXPO_PROJECT_MARKER);
3097
+ const marker = join5(config.nativeProjectDirectory, EXPO_PROJECT_MARKER);
2885
3098
  if (!await exists(marker)) {
2886
3099
  throw new TypeError("Expo asset sync requires an AbsoluteJS-managed Expo project. Run mobile init first.");
2887
3100
  }
2888
- const manifestPath = join4(config.bundleDirectory, "absolute-mobile-manifest.json");
3101
+ const manifestPath = join5(config.bundleDirectory, "absolute-mobile-manifest.json");
2889
3102
  const manifest = JSON.parse(await readFile(manifestPath, "utf8"));
2890
3103
  const nativeDataManifest = expoNativeDataManifest(manifest);
2891
3104
  const { appBuild } = nativeDataManifest;
@@ -2899,16 +3112,16 @@ var syncAbsoluteExpoWebAssets = async (config) => {
2899
3112
  bundleHash.update("\x00");
2900
3113
  });
2901
3114
  const bundleId = `amexpo_${bundleHash.digest("hex")}`;
2902
- const destination = join4(config.nativeProjectDirectory, "assets", "absolute");
3115
+ const destination = join5(config.nativeProjectDirectory, "assets", "absolute");
2903
3116
  await mkdir(dirname2(destination), { recursive: true });
2904
- const staging = await mkdtemp(join4(dirname2(destination), `.${basename(destination)}.stage-`));
3117
+ const staging = await mkdtemp(join5(dirname2(destination), `.${basename(destination)}.stage-`));
2905
3118
  let assets;
2906
3119
  try {
2907
3120
  assets = await Promise.all(files.map(async (source, index) => {
2908
3121
  const name = `${String(index).padStart(6, "0")}${EXPO_ASSET_EXTENSION}`;
2909
- await cp(source, join4(staging, name));
3122
+ await cp(source, join5(staging, name));
2910
3123
  return {
2911
- asset: portableRelative(join4(config.nativeProjectDirectory, "src", "generated"), join4(destination, name)),
3124
+ asset: portableRelative(join5(config.nativeProjectDirectory, "src", "generated"), join5(destination, name)),
2912
3125
  path: relative2(config.bundleDirectory, source).replaceAll("\\", "/")
2913
3126
  };
2914
3127
  }));
@@ -2917,7 +3130,7 @@ var syncAbsoluteExpoWebAssets = async (config) => {
2917
3130
  await rm(staging, { force: true, recursive: true });
2918
3131
  throw error;
2919
3132
  }
2920
- const generated = join4(config.nativeProjectDirectory, "src", "generated", "webAssets.ts");
3133
+ const generated = join5(config.nativeProjectDirectory, "src", "generated", "webAssets.ts");
2921
3134
  await writeManagedFile(generated, assetModuleSource(assets, bundleId, nativeDataManifest), true);
2922
3135
  return { appBuild, assets: assets.length, bundleId, path: destination };
2923
3136
  };
@@ -3,6 +3,9 @@ import {
3
3
  installAbsoluteIosRelease,
4
4
  requireAbsoluteIosReleaseMetadata
5
5
  } from "./index-qxnptvwn.js";
6
+ import {
7
+ unrefTimer
8
+ } from "./index-bw4ktfnz.js";
6
9
 
7
10
  // src/mobile/remoteMacProtocol.ts
8
11
  import { createHash, randomUUID } from "crypto";
@@ -311,6 +314,29 @@ var acquireAbsoluteRemoteMacReleaseLease = async (project, options = {}) => {
311
314
  release: () => runOwned(`rm -rf ${shellQuote(path)}`)
312
315
  };
313
316
  };
317
+ var cleanAbsoluteRemoteMacWorkspace = async (profile, transport) => {
318
+ const root = profile.workspaceRoot;
319
+ const projects = posix.join(root, "projects");
320
+ const script = [
321
+ "set -eu",
322
+ `mkdir -p ${shellQuote(root)}`,
323
+ `project_staging=$(find ${shellQuote(projects)} -mindepth 2 -maxdepth 2 -type d \\( -name '.incoming-*' -o -name '.previous' -o -name '.release-lease.stale-*' \\) -mtime +0 -prune -print 2>/dev/null | wc -l | tr -d ' ')`,
324
+ `mobile_staging=$(find ${shellQuote(projects)} -type d \\( -path '*/current/.absolutejs/mobile/.ios-build-*' -o -path '*/current/.absolutejs/mobile/.ios-stage-*' -o -path '*/current/.absolutejs/mobile/*.incoming-*' \\) -mtime +0 -prune -print 2>/dev/null | wc -l | tr -d ' ')`,
325
+ `count=$((project_staging+mobile_staging))`,
326
+ `find ${shellQuote(projects)} -mindepth 2 -maxdepth 2 -type d \\( -name '.incoming-*' -o -name '.previous' -o -name '.release-lease.stale-*' \\) -mtime +0 -prune -exec rm -rf {} + 2>/dev/null || true`,
327
+ `find ${shellQuote(projects)} -type d \\( -path '*/current/.absolutejs/mobile/.ios-build-*' -o -path '*/current/.absolutejs/mobile/.ios-stage-*' -o -path '*/current/.absolutejs/mobile/*.incoming-*' \\) -mtime +0 -prune -exec rm -rf {} + 2>/dev/null || true`,
328
+ `printf '%s\\n' "$count"`
329
+ ].join("; ");
330
+ const result = await (transport?.capture ?? defaultTransport.capture)([
331
+ ...absoluteRemoteMacSshBase(profile),
332
+ "/bin/sh -lc",
333
+ shellQuote(script)
334
+ ]);
335
+ const removed = Number(requireRemoteSuccess(result, "Remote Mac workspace cleanup"));
336
+ if (!Number.isSafeInteger(removed) || removed < 0)
337
+ throw new TypeError("Remote Mac returned an invalid cleanup result.");
338
+ return { profile: profile.name, removed, workspaceRoot: root };
339
+ };
314
340
  var inspectAbsoluteRemoteMacWorkspace = async (profile, transport) => {
315
341
  const root = profile.workspaceRoot;
316
342
  const script = [
@@ -339,29 +365,6 @@ var inspectAbsoluteRemoteMacWorkspace = async (profile, transport) => {
339
365
  workspaceRoot: root
340
366
  };
341
367
  };
342
- var cleanAbsoluteRemoteMacWorkspace = async (profile, transport) => {
343
- const root = profile.workspaceRoot;
344
- const projects = posix.join(root, "projects");
345
- const script = [
346
- "set -eu",
347
- `mkdir -p ${shellQuote(root)}`,
348
- `project_staging=$(find ${shellQuote(projects)} -mindepth 2 -maxdepth 2 -type d \\( -name '.incoming-*' -o -name '.previous' -o -name '.release-lease.stale-*' \\) -mtime +0 -prune -print 2>/dev/null | wc -l | tr -d ' ')`,
349
- `mobile_staging=$(find ${shellQuote(projects)} -type d \\( -path '*/current/.absolutejs/mobile/.ios-build-*' -o -path '*/current/.absolutejs/mobile/.ios-stage-*' -o -path '*/current/.absolutejs/mobile/*.incoming-*' \\) -mtime +0 -prune -print 2>/dev/null | wc -l | tr -d ' ')`,
350
- `count=$((project_staging+mobile_staging))`,
351
- `find ${shellQuote(projects)} -mindepth 2 -maxdepth 2 -type d \\( -name '.incoming-*' -o -name '.previous' -o -name '.release-lease.stale-*' \\) -mtime +0 -prune -exec rm -rf {} + 2>/dev/null || true`,
352
- `find ${shellQuote(projects)} -type d \\( -path '*/current/.absolutejs/mobile/.ios-build-*' -o -path '*/current/.absolutejs/mobile/.ios-stage-*' -o -path '*/current/.absolutejs/mobile/*.incoming-*' \\) -mtime +0 -prune -exec rm -rf {} + 2>/dev/null || true`,
353
- `printf '%s\\n' "$count"`
354
- ].join("; ");
355
- const result = await (transport?.capture ?? defaultTransport.capture)([
356
- ...absoluteRemoteMacSshBase(profile),
357
- "/bin/sh -lc",
358
- shellQuote(script)
359
- ]);
360
- const removed = Number(requireRemoteSuccess(result, "Remote Mac workspace cleanup"));
361
- if (!Number.isSafeInteger(removed) || removed < 0)
362
- throw new TypeError("Remote Mac returned an invalid cleanup result.");
363
- return { profile: profile.name, removed, workspaceRoot: root };
364
- };
365
368
  var installAbsoluteRemoteMacAgent = async (project) => {
366
369
  const artifact = await materializeAbsoluteRemoteMacAgent(project.projectRoot);
367
370
  const directory = posix.join(project.profile.workspaceRoot, "agents", `protocol-${ABSOLUTE_REMOTE_MAC_PROTOCOL_VERSION}`, artifact.sha256);
@@ -707,7 +710,7 @@ var buildAbsoluteRemoteIosRelease = async (options) => {
707
710
  heartbeat = undefined;
708
711
  });
709
712
  }, REMOTE_RELEASE_LEASE_HEARTBEAT_MS);
710
- heartbeatTimer.unref();
713
+ unrefTimer(heartbeatTimer);
711
714
  try {
712
715
  const syncStartedAt = performance.now();
713
716
  if (options.syncProject)
@@ -850,7 +853,7 @@ var buildAbsoluteRemoteIosRelease = async (options) => {
850
853
  }
851
854
  };
852
855
  var startAbsoluteRemoteExpoIosDevSession = async (options) => {
853
- const session = await startAbsoluteRemoteDevSession({
856
+ let session = await startAbsoluteRemoteDevSession({
854
857
  certificateAuthorityPath: options.certificateAuthorityPath,
855
858
  deviceIdentifier: options.deviceIdentifier,
856
859
  https: options.https,
@@ -866,12 +869,18 @@ var startAbsoluteRemoteExpoIosDevSession = async (options) => {
866
869
  syncProject: options.syncProject,
867
870
  transport: options.transport
868
871
  });
869
- return {
872
+ const expoSession = {
870
873
  close: session.close,
871
874
  metroPort: options.metroPort,
872
875
  platforms: ["ios"],
873
- timings: session.timings
876
+ timings: session.timings,
877
+ rebuild: async () => {
878
+ session = await session.rebuild();
879
+ expoSession.timings = session.timings;
880
+ return expoSession;
881
+ }
874
882
  };
883
+ return expoSession;
875
884
  };
876
885
  var startAbsoluteRemoteIosDevSession = (options) => startAbsoluteRemoteDevSession(options);
877
886
  var startAbsoluteRemoteDevSession = async (options) => {
@@ -1138,4 +1147,4 @@ var startAbsoluteRemoteDevSession = async (options) => {
1138
1147
  return makeSession();
1139
1148
  };
1140
1149
 
1141
- export { ABSOLUTE_REMOTE_MAC_EVENT_PREFIX, ABSOLUTE_REMOTE_MAC_PROTOCOL_VERSION, validateAbsoluteRemoteMacProfileName, validateAbsoluteSshDestination, absoluteRemoteMacSshBase, captureAbsoluteRemoteMacCommand, getAbsoluteRemoteMacProfile, inspectAbsoluteRemoteMac, inspectAbsoluteRemoteMacLanHost, listAbsoluteRemoteMacProfiles, pairAbsoluteRemoteMac, removeAbsoluteRemoteMacProfile, createAbsoluteRemoteExpoIosDevProject, createAbsoluteRemoteIosDevProject, acquireAbsoluteRemoteMacReleaseLease, inspectAbsoluteRemoteMacWorkspace, cleanAbsoluteRemoteMacWorkspace, installAbsoluteRemoteMacAgent, materializeAbsoluteRemoteMacAgent, absoluteRemoteProjectSyncCommands, syncAbsoluteRemoteMacProject, absoluteRemoteReleaseInputSyncCommands, syncAbsoluteRemoteMacReleaseInputs, buildAbsoluteRemoteIosRelease, startAbsoluteRemoteExpoIosDevSession, startAbsoluteRemoteIosDevSession };
1150
+ export { ABSOLUTE_REMOTE_MAC_EVENT_PREFIX, ABSOLUTE_REMOTE_MAC_PROTOCOL_VERSION, validateAbsoluteRemoteMacProfileName, validateAbsoluteSshDestination, absoluteRemoteMacSshBase, captureAbsoluteRemoteMacCommand, getAbsoluteRemoteMacProfile, inspectAbsoluteRemoteMac, inspectAbsoluteRemoteMacLanHost, listAbsoluteRemoteMacProfiles, pairAbsoluteRemoteMac, removeAbsoluteRemoteMacProfile, createAbsoluteRemoteExpoIosDevProject, createAbsoluteRemoteIosDevProject, acquireAbsoluteRemoteMacReleaseLease, cleanAbsoluteRemoteMacWorkspace, inspectAbsoluteRemoteMacWorkspace, installAbsoluteRemoteMacAgent, materializeAbsoluteRemoteMacAgent, absoluteRemoteProjectSyncCommands, syncAbsoluteRemoteMacProject, absoluteRemoteReleaseInputSyncCommands, syncAbsoluteRemoteMacReleaseInputs, buildAbsoluteRemoteIosRelease, startAbsoluteRemoteExpoIosDevSession, startAbsoluteRemoteIosDevSession };
@@ -6,7 +6,7 @@ import {
6
6
  createIslandRegistryDefinitionPlugin,
7
7
  finalizeAbsoluteMobileCompatibilityBuild,
8
8
  resolveServerBundleExternals
9
- } from "./index-751czk1b.js";
9
+ } from "./index-d8va9b7v.js";
10
10
  import {
11
11
  loadIslandRegistryBuildInfo
12
12
  } from "./index-bzs19w3r.js";