peachsim 0.1.656 → 0.1.658

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 (111) hide show
  1. package/README.md +22 -3
  2. package/cli/app-config.ts +34 -15
  3. package/cli/app-project.ts +6 -6
  4. package/cli/bridge-flow-runner.ts +10 -23
  5. package/cli/commands/compat.ts +234 -10
  6. package/cli/commands/control.ts +20 -20
  7. package/cli/commands/do-chain.ts +5 -1
  8. package/cli/commands/flow.ts +3 -3
  9. package/cli/commands/inspect/actions.ts +33 -76
  10. package/cli/commands/inspect/resolve-target.ts +67 -2
  11. package/cli/commands/inspect.ts +16 -1
  12. package/cli/drivers/playwright-provisioning.ts +95 -0
  13. package/cli/ws-bridge.ts +7 -7
  14. package/detox/config-loader.ts +1 -1
  15. package/dist-lib/agent-daemon-client.cjs +1 -1
  16. package/dist-lib/agent-events.cjs +1 -1
  17. package/dist-lib/agent-identity.cjs +1 -1
  18. package/dist-lib/agent-sessions.cjs +1 -1
  19. package/dist-lib/attached-projects.cjs +1 -1
  20. package/dist-lib/auth/shared-session.cjs +1 -1
  21. package/dist-lib/backend-origin.cjs +1 -1
  22. package/dist-lib/beta.cjs +1 -1
  23. package/dist-lib/beta.mjs +1 -1
  24. package/dist-lib/bridge-constants.cjs +1 -1
  25. package/dist-lib/bridge-contract-input.cjs +9 -1
  26. package/dist-lib/bridge-contract-input.mjs +9 -1
  27. package/dist-lib/bridge-contract.cjs +1 -1
  28. package/dist-lib/bridge-contract.mjs +1 -1
  29. package/dist-lib/capture-contract.cjs +1 -1
  30. package/dist-lib/capture-contract.mjs +1 -1
  31. package/dist-lib/cli-constants.cjs +1 -1
  32. package/dist-lib/cloud-contract.cjs +1 -1
  33. package/dist-lib/cloud-contract.mjs +1 -1
  34. package/dist-lib/cloud-test-args.cjs +1 -1
  35. package/dist-lib/cloud-test-args.mjs +1 -1
  36. package/dist-lib/cloud.cjs +1 -1
  37. package/dist-lib/cloud.mjs +1 -1
  38. package/dist-lib/config.cjs +27 -26
  39. package/dist-lib/detox/index.cjs +1 -1
  40. package/dist-lib/dev-bundle-resolution.cjs +1 -1
  41. package/dist-lib/home-paths.cjs +1 -1
  42. package/dist-lib/host/bridge-host.cjs +90 -47
  43. package/dist-lib/host/fetch-proxy-handler.cjs +1 -1
  44. package/dist-lib/host/fetch-proxy-overrides.cjs +1 -1
  45. package/dist-lib/host/fetch-proxy-overrides.mjs +1 -1
  46. package/dist-lib/host/replacement-module-handler.cjs +51 -8
  47. package/dist-lib/host/websocket-proxy.cjs +1 -1
  48. package/dist-lib/index.cjs +317 -70
  49. package/dist-lib/jump-to-source-babel.cjs +1 -1
  50. package/dist-lib/jump-to-source-native.cjs +1 -1
  51. package/dist-lib/kotlin-host.cjs +8 -4
  52. package/dist-lib/menu.cjs +1 -1
  53. package/dist-lib/menu.mjs +1 -1
  54. package/dist-lib/metro-fingerprint-registry.cjs +1 -1
  55. package/dist-lib/metro-fingerprint-registry.mjs +1 -1
  56. package/dist-lib/metro-production-bundle.cjs +1 -1
  57. package/dist-lib/metro-production-bundle.mjs +1 -1
  58. package/dist-lib/metro.cjs +300 -29
  59. package/dist-lib/native-app-identity.cjs +58 -25
  60. package/dist-lib/native-app-identity.mjs +57 -25
  61. package/dist-lib/plist.cjs +64 -0
  62. package/dist-lib/plist.mjs +29 -0
  63. package/dist-lib/profiles.cjs +1 -1
  64. package/dist-lib/public-brand.cjs +1 -1
  65. package/dist-lib/react-native-host-modules.cjs +1 -1
  66. package/dist-lib/react-native-host-modules.mjs +1 -1
  67. package/dist-lib/render-mode.cjs +1 -1
  68. package/dist-lib/scripts/dev-server-scanner.cjs +14 -16
  69. package/dist-lib/sdk.cjs +36 -49
  70. package/dist-lib/sdk.mjs +36 -49
  71. package/dist-lib/skills.cjs +341 -198
  72. package/dist-lib/swift-compile.cjs +1 -1
  73. package/dist-lib/swift-compile.mjs +1 -1
  74. package/dist-lib/swift-package.cjs +1 -1
  75. package/dist-lib/swift-package.mjs +1 -1
  76. package/dist-lib/swift-submit.cjs +1 -1
  77. package/dist-lib/swift-submit.mjs +1 -1
  78. package/dist-lib/swift.cjs +1 -1
  79. package/dist-lib/vite-swift.cjs +1 -1
  80. package/dist-lib/vite.cjs +51 -8
  81. package/kotlin/AppSources/android/app/UiModeManager.kt +9 -0
  82. package/kotlin/AppSources/android/content/Context.kt +9 -2
  83. package/kotlin/AppSources/android/content/res/Configuration.kt +16 -0
  84. package/kotlin/AppSources/android/content/res/Resources.kt +7 -0
  85. package/kotlin/AppSources/android/graphics/Color.kt +13 -0
  86. package/kotlin/AppSources/android/view/View.kt +2 -0
  87. package/kotlin/AppSources/android/view/Window.kt +99 -8
  88. package/kotlin/AppSources/android/view/WindowInsetsController.kt +12 -0
  89. package/kotlin/AppSources/android/view/WindowManager.kt +16 -0
  90. package/kotlin/AppSources/androidx/activity/EdgeToEdge.kt +71 -0
  91. package/kotlin/AppSources/androidx/core/view/WindowCompat.kt +32 -0
  92. package/kotlin/AppSources/dev/peach/app/PeachApp.kt +16 -11
  93. package/kotlin/AppSources/dev/peach/app/PeachWindowHost.kt +2 -1
  94. package/kotlin/ComposeSources/PeachComposeHost.kt +11 -1
  95. package/package.json +8 -1
  96. package/scripts/dev-server-scanner.ts +3 -3
  97. package/scripts/optional-demo-registry.ts +1 -1
  98. package/skills/peach-setup/SKILL.md +27 -0
  99. package/src/android-theme.ts +167 -0
  100. package/src/android-xml.ts +70 -0
  101. package/src/bridge-contract-input.ts +10 -1
  102. package/src/bridge-contract.ts +7 -1
  103. package/src/config.ts +34 -26
  104. package/src/generated/android-framework-themes.json +6303 -0
  105. package/src/host/replacement-module-handler.ts +33 -0
  106. package/src/index.ts +1 -0
  107. package/src/kotlin-app.ts +75 -61
  108. package/src/kotlin-host.ts +7 -3
  109. package/src/metro-plugin.ts +46 -3
  110. package/src/native-app-identity.ts +75 -26
  111. package/src/sim-client.ts +2 -4
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.656 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.658 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __create = Object.create;
@@ -4425,6 +4425,8 @@ var init_supported_native_packages = __esm({
4425
4425
  // seam
4426
4426
  "@kesha-antonov/react-native-background-downloader",
4427
4427
  // seam
4428
+ "@livekit/react-native-webrtc",
4429
+ // seam
4428
4430
  "@lodev09/react-native-true-sheet",
4429
4431
  // seam
4430
4432
  "@logicwind/react-native-exit-app",
@@ -4490,7 +4492,7 @@ var init_supported_native_packages = __esm({
4490
4492
  "@react-native-community/image-editor",
4491
4493
  // seam+coverage
4492
4494
  "@react-native-community/masked-view",
4493
- // coverage
4495
+ // seam+coverage
4494
4496
  "@react-native-community/netinfo",
4495
4497
  // seam+coverage
4496
4498
  "@react-native-community/progress-view",
@@ -4509,6 +4511,8 @@ var init_supported_native_packages = __esm({
4509
4511
  // seam+coverage
4510
4512
  "@react-native-firebase/app",
4511
4513
  // seam+coverage
4514
+ "@react-native-firebase/app-check",
4515
+ // seam
4512
4516
  "@react-native-firebase/auth",
4513
4517
  // seam
4514
4518
  "@react-native-firebase/crashlytics",
@@ -4517,16 +4521,20 @@ var init_supported_native_packages = __esm({
4517
4521
  // seam
4518
4522
  "@react-native-firebase/functions",
4519
4523
  // seam
4524
+ "@react-native-firebase/installations",
4525
+ // seam
4520
4526
  "@react-native-firebase/messaging",
4521
4527
  // seam
4522
4528
  "@react-native-firebase/perf",
4523
- // coverage
4529
+ // seam+coverage
4530
+ "@react-native-firebase/remote-config",
4531
+ // seam
4524
4532
  "@react-native-firebase/storage",
4525
4533
  // seam
4526
4534
  "@react-native-google-signin/google-signin",
4527
4535
  // seam
4528
4536
  "@react-native-masked-view/masked-view",
4529
- // coverage
4537
+ // seam+coverage
4530
4538
  "@react-native-menu/menu",
4531
4539
  // coverage
4532
4540
  "@react-native-ml-kit/barcode-scanning",
@@ -4620,21 +4628,21 @@ var init_supported_native_packages = __esm({
4620
4628
  "expo-av",
4621
4629
  // seam+coverage
4622
4630
  "expo-background-fetch",
4623
- // semantic-proof
4631
+ // semantic-proof+seam
4624
4632
  "expo-background-task",
4625
- // semantic-proof
4633
+ // semantic-proof+seam
4626
4634
  "expo-battery",
4627
- // semantic-proof+coverage
4635
+ // semantic-proof+seam+coverage
4628
4636
  "expo-blur",
4629
- // coverage
4637
+ // seam+coverage
4630
4638
  "expo-brightness",
4631
- // semantic-proof
4639
+ // semantic-proof+seam
4632
4640
  "expo-calendar",
4633
4641
  // semantic-proof+seam
4634
4642
  "expo-camera",
4635
4643
  // seam+coverage
4636
4644
  "expo-cellular",
4637
- // semantic-proof
4645
+ // semantic-proof+seam
4638
4646
  "expo-clipboard",
4639
4647
  // seam+coverage
4640
4648
  "expo-constants",
@@ -4663,6 +4671,8 @@ var init_supported_native_packages = __esm({
4663
4671
  // seam+coverage
4664
4672
  "expo-hardware-buttons",
4665
4673
  // seam
4674
+ "expo-iap",
4675
+ // seam
4666
4676
  "expo-ignore-battery-optimizations",
4667
4677
  // coverage
4668
4678
  "expo-image",
@@ -4698,7 +4708,7 @@ var init_supported_native_packages = __esm({
4698
4708
  "expo-mesh-gradient",
4699
4709
  // coverage
4700
4710
  "expo-network",
4701
- // semantic-proof+coverage
4711
+ // semantic-proof+seam+coverage
4702
4712
  "expo-notifications",
4703
4713
  // seam+coverage
4704
4714
  "expo-passkey",
@@ -4712,7 +4722,7 @@ var init_supported_native_packages = __esm({
4712
4722
  "expo-quick-actions",
4713
4723
  // seam
4714
4724
  "expo-screen-capture",
4715
- // semantic-proof
4725
+ // semantic-proof+seam
4716
4726
  "expo-screen-corner-radius",
4717
4727
  // seam+coverage
4718
4728
  "expo-screen-orientation",
@@ -4752,7 +4762,7 @@ var init_supported_native_packages = __esm({
4752
4762
  "expo-video-metadata",
4753
4763
  // seam
4754
4764
  "expo-video-thumbnails",
4755
- // semantic-proof
4765
+ // semantic-proof+seam
4756
4766
  "expo-web-browser",
4757
4767
  // seam
4758
4768
  "expo-widgets",
@@ -4931,6 +4941,8 @@ var init_supported_native_packages = __esm({
4931
4941
  // seam+coverage
4932
4942
  "react-native-get-random-values",
4933
4943
  // seam+coverage
4944
+ "react-native-google-mobile-ads",
4945
+ // seam
4934
4946
  "react-native-google-places",
4935
4947
  // seam
4936
4948
  "react-native-google-play-install-referrer",
@@ -4945,6 +4957,8 @@ var init_supported_native_packages = __esm({
4945
4957
  // seam
4946
4958
  "react-native-http-bridge-refurbished",
4947
4959
  // seam
4960
+ "react-native-iap",
4961
+ // seam
4948
4962
  "react-native-idle-timer",
4949
4963
  // seam+coverage
4950
4964
  "react-native-image-colors",
@@ -5081,6 +5095,8 @@ var init_supported_native_packages = __esm({
5081
5095
  // seam
5082
5096
  "react-native-purchases",
5083
5097
  // preset+seam+coverage
5098
+ "react-native-purchases-ui",
5099
+ // seam
5084
5100
  "react-native-pure-jwt",
5085
5101
  // seam+coverage
5086
5102
  "react-native-quick-actions",
@@ -5239,6 +5255,8 @@ var init_supported_native_packages = __esm({
5239
5255
  // preset
5240
5256
  "react-native-webp-format",
5241
5257
  // coverage
5258
+ "react-native-webrtc",
5259
+ // seam
5242
5260
  "react-native-webview",
5243
5261
  // preset+visual-proof+seam
5244
5262
  "react-native-widget-picker",
@@ -5249,6 +5267,8 @@ var init_supported_native_packages = __esm({
5249
5267
  // seam
5250
5268
  "react-native-worklets",
5251
5269
  // preset+coverage
5270
+ "react-native-worklets-core",
5271
+ // seam
5252
5272
  "react-native-xxhash",
5253
5273
  // seam+coverage
5254
5274
  "react-native-youtube",
@@ -6058,8 +6078,8 @@ var init_registry = __esm({
6058
6078
  }
6059
6079
  ],
6060
6080
  capabilityCoverage: CAPABILITY_INVENTORY_PACKAGE_COVERAGE["@react-native-masked-view/masked-view"],
6061
- note: "engine-level masked-view node with canvaskit saveLayer + BlendMode.DstIn alpha compositing",
6062
- working: "MaskedView component renders sootsim-masked-view host element with __sootsimMaskSlot alpha-mask pipeline (saveLayer + DstIn in canvaskit-renderer), maskElement, children, style, pointerEvents, accessible, accessibilityLabel, nativeID, testID"
6081
+ note: "upstream masked-view JS runs unchanged against an RNCMaskedView native view seam: its first subview is the alpha mask (canvaskit saveLayer + BlendMode.DstIn)",
6082
+ working: "MaskedView, maskElement, children, the invalid-mask warning and unmasked View fallback, style, pointerEvents, accessible, accessibilityLabel, nativeID, testID"
6063
6083
  }
6064
6084
  ]
6065
6085
  },
@@ -6070,7 +6090,7 @@ var init_registry = __esm({
6070
6090
  {
6071
6091
  range: ">=0.1.0 <0.2.0",
6072
6092
  coverage: 0.9,
6073
- note: "the retired package name resolves to the same RNCMaskedView-compatible engine node as its renamed successor",
6093
+ note: "the retired package JS runs unchanged against the same RNCMaskedView native view seam as its renamed successor",
6074
6094
  working: "default MaskedView component, alpha-channel maskElement compositing, children, View props and refs, and the upstream invalid-mask warning plus unmasked View fallback",
6075
6095
  missing: "the retired package publishes a class declaration that TypeScript 5.9 cannot use as JSX with current React 19 types; native iOS and Android compositor timing under animated masks"
6076
6096
  }
@@ -6324,7 +6344,7 @@ var init_registry = __esm({
6324
6344
  {
6325
6345
  range: ">=12.0.0",
6326
6346
  coverage: 0.95,
6327
- note: "CanvasKit blur with measured iOS 27 filter chains for UIKit styles",
6347
+ note: "upstream expo-blur JS runs unchanged against an ExpoBlurView native view seam: CanvasKit blur with measured iOS 27 filter chains for UIKit styles",
6328
6348
  working: "BlurView, BlurTargetView, tint (all 22 BlurTint values; UIKit styles use their iOS 27 blur, curve, saturation, brightness, and tint chain), intensity, blurReductionFactor, experimentalBlurMethod, blurMethod props",
6329
6349
  missing: "native partial-intensity interpolation fidelity, Animated.createAnimatedComponent integration fidelity"
6330
6350
  }
@@ -7293,7 +7313,7 @@ var init_registry = __esm({
7293
7313
  {
7294
7314
  range: ">=18.0.0",
7295
7315
  coverage: 0.95,
7296
- note: "development noop \u2014 performance tracing API is present and records nothing",
7316
+ note: "upstream @react-native-firebase/perf JS runs unchanged against the NativeRNFBTurboPerf (v26) and RNFBPerfModule native seam; traces and http metrics are accepted and nothing is uploaded, collection and instrumentation start enabled as FIRPerformance does",
7297
7317
  working: "trace/newTrace/startTrace, Trace start/stop/attributes/metrics, HttpMetric start/stop/attributes/payload metadata, collection enablement",
7298
7318
  missing: "native app start/network instrumentation, trace persistence, upload to Firebase Performance"
7299
7319
  }
@@ -7306,9 +7326,9 @@ var init_registry = __esm({
7306
7326
  {
7307
7327
  range: ">=18.0.0",
7308
7328
  coverage: 0.8,
7309
- note: "safe defaults \u2014 remote config calls resolve and return static empty values",
7329
+ note: "upstream @react-native-firebase/remote-config JS runs unchanged against the NativeRNFBTurboConfig (v26) and RNFBConfigModule native seam, backed by the firebase js sdk remote config for the same app: fetches reach the project template, values persist, minimum fetch intervals throttle",
7310
7330
  working: "setDefaults, setConfigSettings, fetch, fetchAndActivate, activate, ensureInitialized, getAll, getBoolean, getNumber, getString, getValue, reset",
7311
- missing: "remote fetch/activate against Firebase backend, persisted defaults, realtime config updates"
7331
+ missing: "setDefaultsFromResource (no app bundle plist)"
7312
7332
  }
7313
7333
  ]
7314
7334
  },
@@ -7345,9 +7365,9 @@ var init_registry = __esm({
7345
7365
  {
7346
7366
  range: ">=18.0.0",
7347
7367
  coverage: 0,
7348
- note: "the reference iOS simulator creates real Firebase installation identifiers and tokens when configured. Peach returns fixed placeholder strings, so import safety receives no behavior credit",
7349
- working: "default installations(), getId, getToken, delete",
7350
- missing: "real Firebase installation registration and token lifecycle"
7368
+ note: "upstream @react-native-firebase/installations JS runs unchanged against the NativeRNFBTurboInstallations (v26) and RNFBInstallationsModule native seam, backed by the firebase js sdk installations for the same app",
7369
+ working: "default installations(), modular helpers, getId, getToken, delete",
7370
+ missing: "none known"
7351
7371
  }
7352
7372
  ]
7353
7373
  },
@@ -7356,11 +7376,11 @@ var init_registry = __esm({
7356
7376
  stubType: "native",
7357
7377
  versions: [
7358
7378
  {
7359
- range: ">=18.0.0",
7360
- coverage: 0,
7361
- note: "the reference iOS simulator performs this package's behavior. Peach currently provides only this unsupported shape: development token noop : App Check API shape resolves with stub tokens. imports and API shape receive no behavior credit",
7362
- working: "default appCheck(), activate, setTokenAutoRefreshEnabled, getToken, onTokenChanged",
7363
- missing: "real attestation provider, token refresh, enforcement with Firebase services"
7379
+ range: ">=23.0.0",
7380
+ coverage: 0.8,
7381
+ note: "native-seam only. the published app-check JS runs over NativeRNFBTurboAppCheck, which mirrors RNFBAppCheckModule and a port of AppCheckCore token caching. the debug provider exchanges its token at firebaseappcheck.googleapis.com, so a debug token registered in the Firebase console yields real tokens, and the firebase js sdk services behind the other RNFB seams attach them. DeviceCheck and App Attest report the unsupported-attestation-provider error a device without DCDevice support reports",
7382
+ working: "initializeAppCheck and activate, configureProvider for debug, deviceCheck, appAttest and appAttestWithDeviceCheckFallback, getToken with caching and forced refresh, getLimitedUseToken, token auto-refresh setting, provider-not-ready and token-error rejections, debug token logging and persistence",
7383
+ missing: "Apple-signed DeviceCheck and App Attest attestation"
7364
7384
  }
7365
7385
  ]
7366
7386
  },
@@ -7369,11 +7389,11 @@ var init_registry = __esm({
7369
7389
  stubType: "native",
7370
7390
  versions: [
7371
7391
  {
7372
- range: ">=12.0.0",
7392
+ range: ">=16.0.0 <17.0.0",
7373
7393
  coverage: 0.35,
7374
- note: "partial JS-reimpl stub \u2014 covers ~40% of upstream surface; useIAP hook, withIAPContext, IAPManagerAndroid, getStorefrontIOS etc. missing. should be migrated to native-seam pattern so real package runs against an RNIapIos/RNIapAndroid TurboModule shim",
7375
- working: "initConnection resolves true, purchaseErrorListener/purchaseUpdatedListener return removable subscriptions, endConnection resolves",
7376
- missing: "getProducts/getSubscriptions always [], requestPurchase/requestSubscription always undefined, getAvailablePurchases [], finishTransaction noop, validateReceiptIos/Android return {}, no IAPManagerAndroid/withIAPContext, useIAP hook missing"
7394
+ note: "native seam: published JS and useIAP run against the RnIap Nitro hybrid object, modeling an empty StoreKit catalog and transaction history",
7395
+ working: "connection lifecycle, fetchProducts, purchase error listeners, empty purchase and subscription queries, numeric finishTransaction, invalid verification result, native missing-product and receipt errors",
7396
+ missing: "real purchases, StoreKit UI, AppStore sync, app transactions, introductory offer eligibility, provider verification and Play Billing"
7377
7397
  }
7378
7398
  ]
7379
7399
  },
@@ -8874,7 +8894,14 @@ var init_registry = __esm({
8874
8894
  stubType: "native",
8875
8895
  versions: [
8876
8896
  {
8877
- range: ">=1.0.0",
8897
+ range: ">=2.0.0 <3.0.0",
8898
+ coverage: 0,
8899
+ note: "native seam: published JavaScript loads against the Compressor Nitro hybrid object; native media and filesystem operations reject explicitly",
8900
+ working: "published Image, Video, Audio and utility exports load; transcoding rejects with UNSUPPORTED_OPERATION instead of returning an unchanged asset as a success",
8901
+ missing: "native media transcoding, metadata, thumbnails, cache files, upload/download and background execution"
8902
+ },
8903
+ {
8904
+ range: ">=1.0.0 <2.0.0",
8878
8905
  coverage: 0.78,
8879
8906
  note: "native-seam: real package JS runs from the bundle; the Compressor TurboModule is browser-backed (canvas raster compression, HTMLVideoElement metadata/thumbnail, fetch upload/download)",
8880
8907
  working: "Image.compress loads uri/base64 inputs, preserves aspect ratio, resizes/re-encodes jpg/png, returns uri or base64; getImageMetaData/getVideoMetaData report real dimensions+size; createVideoThumbnail captures the first frame; clearCache resolves (composer onClose); Video.compress passes through and drives progress to completion; backgroundUpload/download use fetch",
@@ -9654,10 +9681,10 @@ var init_registry = __esm({
9654
9681
  versions: [
9655
9682
  {
9656
9683
  range: ">=8.0.0",
9657
- coverage: 0,
9658
- note: "the reference iOS simulator renders configured RevenueCat paywalls. Peach's replacement returns NOT_PRESENTED, rejects customer center, and substitutes async no-ops for view components. the current 10.7 package ships its own visibly labeled Preview API components, but replacing the package prevents that upstream path from running. none of these shapes receive behavior credit",
9659
- working: "RevenueCatUI singleton, presentPaywall (NOT_PRESENTED), presentPaywallIfNeeded (NOT_PRESENTED), presentCustomerCenter (rejects clearly), PAYWALL_RESULT enum (NOT_PRESENTED, ERROR, CANCELLED, PURCHASED, RESTORED)",
9660
- missing: "configured paywall and customer-center UI, Paywall / OriginalTemplatePaywallFooterContainerView / CustomerCenterView components, dismiss and purchase/restore callbacks, purchase logic, custom variables, management events, and the package-owned Preview API path"
9684
+ coverage: 0.7,
9685
+ note: "native-seam only. the published RevenueCatUI JS runs over RNPaywalls, RNCustomerCenter and the PaywallView, RCPaywallFooterView and CustomerCenterView view managers. RevenueCat's dashboard-designed paywall never reaches Peach, so the seam draws a simplified paywall from the RNPurchases offering and buys and restores through that seam, with PaywallProxy's page-sheet presentation, entitlement check, result strings and view event bodies",
9686
+ working: "presentPaywall and presentPaywallIfNeeded (PURCHASED, RESTORED, CANCELLED, NOT_PRESENTED), Paywall and footer components with purchase, restore, cancel, error and dismiss events, purchase-initiated and purchase-logic round trips, presentCustomerCenter and CustomerCenterView with restore and manage-subscriptions events",
9687
+ missing: "dashboard-designed paywall templates, custom variables and fonts beyond fontFamily, customer-center support paths, refunds and promotional offers"
9661
9688
  }
9662
9689
  ]
9663
9690
  },
@@ -9877,8 +9904,8 @@ var init_registry = __esm({
9877
9904
  {
9878
9905
  range: ">=125.0.0",
9879
9906
  coverage: 0.85,
9880
- note: "load-safe noop \u2014 registerGlobals/setupReactNativeWebRTC accept calls; on web the global navigator.mediaDevices / RTCPeerConnection are already present so no patching is required",
9881
- missing: "no native iOS/Android WebRTC bindings. apps that need raw camera capture should use the browser getUserMedia API directly"
9907
+ note: "published JS runs over WebRTCModule backed by browser peers, capture, data channels, stats, RTCView frames and encryption. recording aliases share one pending capture; stop and disposal invalidate it. device playout controls existing and incoming audio receivers",
9908
+ missing: "AVAudioSession categories and hardware audio routing have no browser equivalent"
9882
9909
  }
9883
9910
  ]
9884
9911
  },
@@ -9887,10 +9914,11 @@ var init_registry = __esm({
9887
9914
  stubType: "native",
9888
9915
  versions: [
9889
9916
  {
9890
- range: ">=2.0.0",
9917
+ range: ">=5.0.0 <6.0.0",
9891
9918
  coverage: 0.45,
9892
- note: "load-safe noop \u2014 initConnection=false (apps branch on no-IAP), getProducts/getSubscriptions/getAvailablePurchases return empty arrays, requestPurchase rejects with E_IAP_NOT_AVAILABLE. PurchaseError class + ErrorCode/IAPErrorCode/IapEvent enums exposed for type-checked code",
9893
- missing: "no StoreKit / Play Billing \u2014 same constraint as react-native-purchases. paywall flows take their offline branch"
9919
+ note: "native seam: published JS and useIAP run against ExpoIap, modeling an empty StoreKit catalog and transaction history",
9920
+ working: "connection lifecycle, fetchProducts, native purchase errors and event subscriptions, empty purchase and subscription queries, numeric finishTransaction, missing receipt and invalid verification result",
9921
+ missing: "real purchases, StoreKit UI, AppStore sync, app transactions, introductory offer eligibility, provider verification and Play Billing"
9894
9922
  }
9895
9923
  ]
9896
9924
  },
@@ -9988,9 +10016,9 @@ var init_registry = __esm({
9988
10016
  versions: [
9989
10017
  {
9990
10018
  range: ">=1.0.0",
9991
- coverage: 0.5,
9992
- note: "callbacks run, but every worklet stays on the main JavaScript thread while the reference iOS simulator executes worklets on their dedicated runtime",
9993
- missing: "no off-thread JS execution (matches our react-native-worklets-pkg stub story). complex worklet pipelines that actually need parallelism will see degraded performance, not crashes"
10019
+ coverage: 0.85,
10020
+ note: "published JS over the Worklets TurboModule: contexts run worklets on their own worker runtimes, createRunOnJS and cross-context calls settle promises on the calling thread, and shared values replicate writes and listeners across runtimes",
10021
+ missing: "shared value writes replicate in order instead of under one mutex, so simultaneous writes from two threads can briefly disagree; a worklet a context received and passes to another context loses its captured closure"
9994
10022
  }
9995
10023
  ]
9996
10024
  },
@@ -9999,10 +10027,10 @@ var init_registry = __esm({
9999
10027
  stubType: "native",
10000
10028
  versions: [
10001
10029
  {
10002
- range: ">=125.0.0",
10030
+ range: ">=124.0.0",
10003
10031
  coverage: 0.7,
10004
- note: "load-safe pass-through \u2014 RTCPeerConnection / RTCIceCandidate / RTCSessionDescription / MediaStream / MediaStreamTrack / mediaDevices forwarded from globalThis (browsers have these natively); registerGlobals is a noop; RTCView component renders null since we have no host-side video bridge yet",
10005
- missing: "RTCView visual rendering needs a host bridge that paints a video element into the device frame (deferred). raw audio/video peer connections work via the browser globals"
10032
+ note: "published JS runs over WebRTCModule backed by browser peer connections, capture, native events, data channels, stats and live RTCView frames. audio receivers obey device playout state",
10033
+ missing: "native hardware audio routing has no browser equivalent"
10006
10034
  }
10007
10035
  ]
10008
10036
  },
@@ -19215,14 +19243,14 @@ var init_backend_origin = __esm({
19215
19243
  function hasOwnKeys(value) {
19216
19244
  return !!value && Object.keys(value).length > 0;
19217
19245
  }
19218
- function hasRNXConfig(config) {
19246
+ function hasPeachConfig(config) {
19219
19247
  if (!config) return false;
19220
- return typeof config.runtimeVersion === "string" && config.runtimeVersion.length > 0 || hasOwnKeys(config.modules) || hasOwnKeys(config.turboModules) || hasOwnKeys(config.nativeModules) || hasOwnKeys(config.env) || hasOwnKeys(config.network?.remap) || hasOwnKeys(config.settings) || hasOwnKeys(config.initialState);
19248
+ return typeof config.runtimeVersion === "string" && config.runtimeVersion.length > 0 || hasOwnKeys(config.modules) || hasOwnKeys(config.turboModules) || hasOwnKeys(config.nativeModules) || hasOwnKeys(config.nativeViews) || hasOwnKeys(config.env) || hasOwnKeys(config.network?.remap) || hasOwnKeys(config.settings) || hasOwnKeys(config.initialState);
19221
19249
  }
19222
- function mergeRNXConfig(base, override) {
19223
- if (!hasRNXConfig(base) && !hasRNXConfig(override)) return void 0;
19224
- if (!hasRNXConfig(base)) return override ? { ...override } : void 0;
19225
- if (!hasRNXConfig(override)) return base ? { ...base } : void 0;
19250
+ function mergePeachConfig(base, override) {
19251
+ if (!hasPeachConfig(base) && !hasPeachConfig(override)) return void 0;
19252
+ if (!hasPeachConfig(base)) return override ? { ...override } : void 0;
19253
+ if (!hasPeachConfig(override)) return base ? { ...base } : void 0;
19226
19254
  return {
19227
19255
  runtimeVersion: override.runtimeVersion ?? base.runtimeVersion,
19228
19256
  modules: { ...base.modules || {}, ...override.modules || {} },
@@ -19231,6 +19259,7 @@ function mergeRNXConfig(base, override) {
19231
19259
  ...base.nativeModules || {},
19232
19260
  ...override.nativeModules || {}
19233
19261
  },
19262
+ nativeViews: { ...base.nativeViews || {}, ...override.nativeViews || {} },
19234
19263
  env: { ...base.env || {}, ...override.env || {} },
19235
19264
  network: {
19236
19265
  remap: { ...base.network?.remap || {}, ...override.network?.remap || {} }
@@ -19242,20 +19271,20 @@ function mergeRNXConfig(base, override) {
19242
19271
  initialState: { ...base.initialState || {}, ...override.initialState || {} }
19243
19272
  };
19244
19273
  }
19245
- function applyRNXConfigToUrl(url, config) {
19274
+ function applyPeachConfigToUrl(url, config) {
19246
19275
  const parsed = new URL(url);
19247
- if (hasRNXConfig(config)) {
19248
- parsed.searchParams.set(RNX_CONFIG_QUERY_PARAM, JSON.stringify(config));
19276
+ if (hasPeachConfig(config)) {
19277
+ parsed.searchParams.set(PEACH_CONFIG_QUERY_PARAM, JSON.stringify(config));
19249
19278
  } else {
19250
- parsed.searchParams.delete(RNX_CONFIG_QUERY_PARAM);
19279
+ parsed.searchParams.delete(PEACH_CONFIG_QUERY_PARAM);
19251
19280
  }
19252
19281
  return parsed.toString();
19253
19282
  }
19254
- var RNX_CONFIG_QUERY_PARAM;
19283
+ var PEACH_CONFIG_QUERY_PARAM;
19255
19284
  var init_config = __esm({
19256
19285
  "src/config.ts"() {
19257
19286
  "use strict";
19258
- RNX_CONFIG_QUERY_PARAM = "rnxConfig";
19287
+ PEACH_CONFIG_QUERY_PARAM = "peachConfig";
19259
19288
  }
19260
19289
  });
19261
19290
 
@@ -20028,7 +20057,7 @@ function withRuntimeConfig(port, bundleUrl, projectCwd) {
20028
20057
  }) : [];
20029
20058
  const exactKnownApps = knownApps.filter((app) => app.preferredPort === port);
20030
20059
  const knownApp = exactKnownApps.length === 1 ? exactKnownApps[0] : exactKnownApps.length === 0 && knownApps.length === 1 ? knownApps[0] : void 0;
20031
- const configured = knownApp?.runtimeConfig ? applyRNXConfigToUrl(bundleUrl, knownApp.runtimeConfig) : bundleUrl;
20060
+ const configured = knownApp?.runtimeConfig ? applyPeachConfigToUrl(bundleUrl, knownApp.runtimeConfig) : bundleUrl;
20032
20061
  return normalizeNativeDevBundleUrl(configured);
20033
20062
  }
20034
20063
  function isDirectOneBundleUrl(bundleUrl) {
@@ -20416,12 +20445,12 @@ var init_dev_server_scanner = __esm({
20416
20445
  "scripts/dev-server-scanner.ts"() {
20417
20446
  "use strict";
20418
20447
  import_child_process = require("child_process");
20419
- init_process_group();
20420
20448
  import_promises2 = require("fs/promises");
20421
20449
  import_http = __toESM(require("http"), 1);
20422
20450
  import_net = __toESM(require("net"), 1);
20423
20451
  import_node_fs2 = require("node:fs");
20424
20452
  import_node_path3 = require("node:path");
20453
+ init_process_group();
20425
20454
  init_backend_origin();
20426
20455
  init_config();
20427
20456
  init_native_dev_bundle_url();
@@ -24059,12 +24088,15 @@ function transformsFor(filePath) {
24059
24088
  );
24060
24089
  }
24061
24090
  }
24091
+ function isLocalSpecifier(specifier) {
24092
+ return specifier.startsWith("./") || specifier.startsWith("../");
24093
+ }
24062
24094
  function isContrastKitSpecifier(specifier) {
24063
24095
  return specifier === "contrast-kit" || specifier.startsWith("contrast-kit/");
24064
24096
  }
24065
24097
  function unsupportedSpecifier(specifier) {
24066
24098
  return new Error(
24067
- `replacement modules may only import react, react-native, contrast-kit, and the packages rnx stubs for this app; '${specifier}' is none of those. vendor the code into the replacement file, or add the package to rnx.config so the simulator bridges it.`
24099
+ `replacement modules may only import react, react-native, contrast-kit, the packages rnx stubs for this app, and other project files by relative path; '${specifier}' is none of those. vendor the code into a project file, or add the package to peach.config so the simulator bridges it.`
24068
24100
  );
24069
24101
  }
24070
24102
  function bridgeDeclaration(name2, specifier) {
@@ -24087,11 +24119,9 @@ function compileReplacementModule(input) {
24087
24119
  const transformed = (0, import_dist.transform)(input.source, {
24088
24120
  transforms: transformsFor(input.filePath),
24089
24121
  filePath: input.filePath,
24090
- // classic runtime, matching what the app's own Metro build does for a file
24091
- // that has no automatic-runtime pragma: the file imports React itself.
24092
- jsxRuntime: "classic",
24093
- jsxPragma: "React.createElement",
24094
- jsxFragmentPragma: "React.Fragment",
24122
+ // the automatic runtime, as @react-native/babel-preset and babel-preset-expo
24123
+ // compile the app's own files: jsx needs no React import.
24124
+ jsxRuntime: "automatic",
24095
24125
  production: true,
24096
24126
  sourceMapOptions: { compiledFilename: input.filePath }
24097
24127
  });
@@ -24118,6 +24148,13 @@ function compileReplacementModule(input) {
24118
24148
  return name2;
24119
24149
  };
24120
24150
  const edits = [];
24151
+ const pointAtLocalModule = (specifierToken, specifier) => {
24152
+ edits.push({
24153
+ start: specifierToken.start,
24154
+ end: specifierToken.end,
24155
+ text: JSON.stringify(input.localModuleUrl(specifier))
24156
+ });
24157
+ };
24121
24158
  for (let index = 0; index < tokens.length; index++) {
24122
24159
  const token = tokens[index];
24123
24160
  if (token.type === EXPORT_KEYWORD) {
@@ -24137,6 +24174,10 @@ function compileReplacementModule(input) {
24137
24174
  }
24138
24175
  if (fromAt > 0 && tokens[fromAt] && read(tokens[fromAt]) === "from" && tokens[fromAt + 1]?.type === import_types.TokenType.string) {
24139
24176
  const specifier2 = readSpecifier(tokens[fromAt + 1]);
24177
+ if (isLocalSpecifier(specifier2)) {
24178
+ pointAtLocalModule(tokens[fromAt + 1], specifier2);
24179
+ continue;
24180
+ }
24140
24181
  throw new Error(
24141
24182
  `a replacement module cannot re-export from another module, and this one re-exports from '${specifier2}'. import what you need and export the binding.`
24142
24183
  );
@@ -24189,6 +24230,10 @@ function compileReplacementModule(input) {
24189
24230
  const specifierToken = tokens[cursor];
24190
24231
  if (!specifierToken) throw new Error("replacement module import is unterminated");
24191
24232
  const specifier = readSpecifier(specifierToken);
24233
+ if (isLocalSpecifier(specifier)) {
24234
+ pointAtLocalModule(specifierToken, specifier);
24235
+ continue;
24236
+ }
24192
24237
  if (specifier !== "react" && specifier !== "react-native" && !JSX_RUNTIME_SPECIFIERS.has(specifier) && !isContrastKitSpecifier(specifier) && !input.runtimePackages.has(specifier)) {
24193
24238
  throw unsupportedSpecifier(specifier);
24194
24239
  }
@@ -24254,6 +24299,25 @@ function sendJavaScript(req, res, source) {
24254
24299
  });
24255
24300
  res.end(req.method === "HEAD" ? void 0 : source);
24256
24301
  }
24302
+ function resolveLocalImport(fromFile, specifier) {
24303
+ const base = import_node_path14.default.resolve(import_node_path14.default.dirname(fromFile), specifier);
24304
+ const candidates = [
24305
+ ...REPLACEMENT_MODULE_EXTENSIONS.some(
24306
+ (ext) => ext === import_node_path14.default.extname(base).toLowerCase()
24307
+ ) ? [base] : [],
24308
+ ...REPLACEMENT_MODULE_EXTENSIONS.map((ext) => base + ext),
24309
+ ...REPLACEMENT_MODULE_EXTENSIONS.map((ext) => import_node_path14.default.join(base, `index${ext}`))
24310
+ ];
24311
+ const found = candidates.find(
24312
+ (candidate) => (0, import_node_fs14.statSync)(candidate, { throwIfNoEntry: false })?.isFile()
24313
+ );
24314
+ if (!found) {
24315
+ throw new Error(
24316
+ `'${specifier}' imported by ${fromFile} matches no ${REPLACEMENT_MODULE_EXTENSIONS.join(", ")} file`
24317
+ );
24318
+ }
24319
+ return found;
24320
+ }
24257
24321
  function isReplacementModuleRequestUrl(rawUrl) {
24258
24322
  if (!rawUrl) return false;
24259
24323
  try {
@@ -24344,7 +24408,14 @@ async function handleReplacementModuleRequest(req, res, options = {}) {
24344
24408
  const compiled = compileReplacementModule({
24345
24409
  filePath: resolvedTargetPath,
24346
24410
  source: await import_promises5.default.readFile(resolvedTargetPath, "utf8"),
24347
- runtimePackages
24411
+ runtimePackages,
24412
+ // the imported file's url is this request's with only its path changed,
24413
+ // so the token, cache key and runtime packages carry over.
24414
+ localModuleUrl: (specifier) => {
24415
+ const local = new URL(url.href);
24416
+ local.searchParams.set("path", resolveLocalImport(targetPath, specifier));
24417
+ return `${local.pathname}${local.search}`;
24418
+ }
24348
24419
  });
24349
24420
  const map = Buffer.from(JSON.stringify(compiled.sourceMap), "utf8").toString("base64");
24350
24421
  sendJavaScript(
@@ -24361,10 +24432,11 @@ async function handleReplacementModuleRequest(req, res, options = {}) {
24361
24432
  }
24362
24433
  return true;
24363
24434
  }
24364
- var import_promises5, import_node_path14, REPLACEMENT_MODULE_ROUTE;
24435
+ var import_node_fs14, import_promises5, import_node_path14, REPLACEMENT_MODULE_ROUTE;
24365
24436
  var init_replacement_module_handler = __esm({
24366
24437
  "src/host/replacement-module-handler.ts"() {
24367
24438
  "use strict";
24439
+ import_node_fs14 = require("node:fs");
24368
24440
  import_promises5 = __toESM(require("node:fs/promises"), 1);
24369
24441
  import_node_path14 = __toESM(require("node:path"), 1);
24370
24442
  init_replacementModule();
@@ -24709,25 +24781,25 @@ function normalizeSession(input) {
24709
24781
  }
24710
24782
  function readSharedDesktopAuthSession() {
24711
24783
  const filepath = getSharedDesktopAuthFilePath();
24712
- if (!(0, import_node_fs14.existsSync)(filepath)) return null;
24784
+ if (!(0, import_node_fs15.existsSync)(filepath)) return null;
24713
24785
  try {
24714
- const parsed = JSON.parse((0, import_node_fs14.readFileSync)(filepath, "utf8"));
24786
+ const parsed = JSON.parse((0, import_node_fs15.readFileSync)(filepath, "utf8"));
24715
24787
  const normalized = normalizeSession(parsed);
24716
24788
  if (!normalized) {
24717
- (0, import_node_fs14.rmSync)(filepath, { force: true });
24789
+ (0, import_node_fs15.rmSync)(filepath, { force: true });
24718
24790
  return null;
24719
24791
  }
24720
24792
  return normalized;
24721
24793
  } catch {
24722
- (0, import_node_fs14.rmSync)(filepath, { force: true });
24794
+ (0, import_node_fs15.rmSync)(filepath, { force: true });
24723
24795
  return null;
24724
24796
  }
24725
24797
  }
24726
- var import_node_fs14, import_node_path15, SESSION_VERSION, SESSION_FILE_ENV, DEFAULT_ORIGIN;
24798
+ var import_node_fs15, import_node_path15, SESSION_VERSION, SESSION_FILE_ENV, DEFAULT_ORIGIN;
24727
24799
  var init_shared_session = __esm({
24728
24800
  "src/auth/shared-session.ts"() {
24729
24801
  "use strict";
24730
- import_node_fs14 = require("node:fs");
24802
+ import_node_fs15 = require("node:fs");
24731
24803
  import_node_path15 = require("node:path");
24732
24804
  init_home_paths();
24733
24805
  SESSION_VERSION = 1;
@@ -28198,7 +28270,7 @@ function detectFramework2(deps) {
28198
28270
  }
28199
28271
  function detectProject(dir) {
28200
28272
  const pkgPath = (0, import_node_path16.join)(dir, "package.json");
28201
- if (!(0, import_node_fs15.existsSync)(pkgPath)) return null;
28273
+ if (!(0, import_node_fs16.existsSync)(pkgPath)) return null;
28202
28274
  const pkg = readProjectManifest(dir);
28203
28275
  if (!pkg) return null;
28204
28276
  const deps = { ...pkg.dependencies, ...pkg.devDependencies };
@@ -28216,19 +28288,19 @@ function detectProject(dir) {
28216
28288
  // apps write .cjs as often as .js, and missing one reads as "this project
28217
28289
  // has no bundler config" and sends the user to create a second one.
28218
28290
  hasViteConfig: CONFIG_EXTENSIONS.some(
28219
- (ext) => (0, import_node_fs15.existsSync)((0, import_node_path16.join)(dir, `vite.config.${ext}`))
28291
+ (ext) => (0, import_node_fs16.existsSync)((0, import_node_path16.join)(dir, `vite.config.${ext}`))
28220
28292
  ),
28221
28293
  hasMetroConfig: CONFIG_EXTENSIONS.some(
28222
- (ext) => (0, import_node_fs15.existsSync)((0, import_node_path16.join)(dir, `metro.config.${ext}`))
28294
+ (ext) => (0, import_node_fs16.existsSync)((0, import_node_path16.join)(dir, `metro.config.${ext}`))
28223
28295
  ),
28224
28296
  devCommand: typeof devCommand === "string" ? devCommand : null
28225
28297
  };
28226
28298
  }
28227
28299
  function readProjectMetadata(path23) {
28228
28300
  try {
28229
- const info = (0, import_node_fs15.lstatSync)(path23);
28301
+ const info = (0, import_node_fs16.lstatSync)(path23);
28230
28302
  if (!info.isFile() || info.size > 4 * 1024 * 1024) return null;
28231
- return (0, import_node_fs15.readFileSync)(path23, "utf8");
28303
+ return (0, import_node_fs16.readFileSync)(path23, "utf8");
28232
28304
  } catch {
28233
28305
  return null;
28234
28306
  }
@@ -28265,11 +28337,11 @@ function readProjectManifest(dir) {
28265
28337
  devDependencies: record(metadataValue(parsed, "devDependencies"))
28266
28338
  };
28267
28339
  }
28268
- var import_node_fs15, import_node_path16, import_json5, import_yaml, CONFIG_EXTENSIONS;
28340
+ var import_node_fs16, import_node_path16, import_json5, import_yaml, CONFIG_EXTENSIONS;
28269
28341
  var init_detect = __esm({
28270
28342
  "cli/commands/detect.ts"() {
28271
28343
  "use strict";
28272
- import_node_fs15 = require("node:fs");
28344
+ import_node_fs16 = require("node:fs");
28273
28345
  import_node_path16 = require("node:path");
28274
28346
  import_json5 = __toESM(require("json5"), 1);
28275
28347
  import_yaml = require("yaml");
@@ -28311,17 +28383,17 @@ function readImmutableBundleSource(bundlePath) {
28311
28383
  if ((0, import_node_path17.extname)(filepath) !== ".js") {
28312
28384
  throw new Error(`${REMOTE_COMMAND} requires one local Metro .js bundle`);
28313
28385
  }
28314
- const descriptor = (0, import_node_fs16.openSync)(filepath, "r");
28386
+ const descriptor = (0, import_node_fs17.openSync)(filepath, "r");
28315
28387
  try {
28316
- const before = (0, import_node_fs16.fstatSync)(descriptor, { bigint: true });
28388
+ const before = (0, import_node_fs17.fstatSync)(descriptor, { bigint: true });
28317
28389
  if (!before.isFile()) {
28318
28390
  throw new Error(`${REMOTE_COMMAND} bundle must be a regular local file`);
28319
28391
  }
28320
28392
  if (before.size <= 0n) {
28321
28393
  throw new Error(`${REMOTE_COMMAND} bundle is empty`);
28322
28394
  }
28323
- const bytes = (0, import_node_fs16.readFileSync)(descriptor);
28324
- const after = (0, import_node_fs16.fstatSync)(descriptor, { bigint: true });
28395
+ const bytes = (0, import_node_fs17.readFileSync)(descriptor);
28396
+ const after = (0, import_node_fs17.fstatSync)(descriptor, { bigint: true });
28325
28397
  if (before.dev !== after.dev || before.ino !== after.ino || before.size !== after.size || before.mtimeNs !== after.mtimeNs || bytes.length !== Number(before.size)) {
28326
28398
  throw new Error(`${REMOTE_COMMAND} bundle changed while it was being read`);
28327
28399
  }
@@ -28336,7 +28408,7 @@ function readImmutableBundleSource(bundlePath) {
28336
28408
  }
28337
28409
  return source;
28338
28410
  } finally {
28339
- (0, import_node_fs16.closeSync)(descriptor);
28411
+ (0, import_node_fs17.closeSync)(descriptor);
28340
28412
  }
28341
28413
  }
28342
28414
  async function fetchBundleSource(bundleUrl) {
@@ -28384,14 +28456,14 @@ async function loadBundleSource(bundleInput) {
28384
28456
  }
28385
28457
  function listMetroAssetDest(assetsPath) {
28386
28458
  const directory = (0, import_node_path17.resolve)(assetsPath);
28387
- if (!(0, import_node_fs16.existsSync)(directory)) return { directory, files: [], truncated: false };
28388
- const skipNested = (0, import_node_fs16.existsSync)((0, import_node_path17.join)(directory, "package.json"));
28459
+ if (!(0, import_node_fs17.existsSync)(directory)) return { directory, files: [], truncated: false };
28460
+ const skipNested = (0, import_node_fs17.existsSync)((0, import_node_path17.join)(directory, "package.json"));
28389
28461
  const files = [];
28390
28462
  let truncated = false;
28391
28463
  const walk = (dir, prefix) => {
28392
28464
  let entries;
28393
28465
  try {
28394
- entries = (0, import_node_fs16.readdirSync)(dir, { withFileTypes: true });
28466
+ entries = (0, import_node_fs17.readdirSync)(dir, { withFileTypes: true });
28395
28467
  } catch {
28396
28468
  return;
28397
28469
  }
@@ -28438,7 +28510,7 @@ function distinctByContent(directory, options) {
28438
28510
  for (const relative2 of options) {
28439
28511
  let bytes;
28440
28512
  try {
28441
- bytes = (0, import_node_fs16.readFileSync)((0, import_node_path17.join)(directory, relative2));
28513
+ bytes = (0, import_node_fs17.readFileSync)((0, import_node_path17.join)(directory, relative2));
28442
28514
  } catch {
28443
28515
  continue;
28444
28516
  }
@@ -28470,7 +28542,7 @@ function placeMetroDescriptor(listing, descriptor) {
28470
28542
  let bytes;
28471
28543
  try {
28472
28544
  bytes = combination.map(
28473
- (relative2) => (0, import_node_fs16.readFileSync)((0, import_node_path17.join)(listing.directory, relative2))
28545
+ (relative2) => (0, import_node_fs17.readFileSync)((0, import_node_path17.join)(listing.directory, relative2))
28474
28546
  );
28475
28547
  } catch {
28476
28548
  continue;
@@ -28641,7 +28713,7 @@ async function embedBundleAssets(bundlePath, command, assetPolicy) {
28641
28713
  );
28642
28714
  }
28643
28715
  const relative2 = placement?.files.get(variant.scale);
28644
- if (relative2 && dest) return (0, import_node_fs16.readFileSync)((0, import_node_path17.join)(dest.directory, relative2));
28716
+ if (relative2 && dest) return (0, import_node_fs17.readFileSync)((0, import_node_path17.join)(dest.directory, relative2));
28645
28717
  if (placement && placement.files.size > 0) return null;
28646
28718
  if (placement && placement.ambiguous.length > 0 && dest) {
28647
28719
  throw new Error(
@@ -28856,12 +28928,12 @@ function createCloudBridgeForParsed(parsed) {
28856
28928
  if (!session) return null;
28857
28929
  return session.service === "box" ? new CloudBoxBridge(session) : new CloudBridge(session);
28858
28930
  }
28859
- var import_node_crypto6, import_node_fs16, import_node_path17, DEFAULT_RNX_CLOUD_ORIGIN, MAX_RNX_CLOUD_BUNDLE_BYTES, REMOTE_COMMAND, MAX_ASSET_DEST_FILES, ACCOUNT_CHOICE_REFUSALS, PROJECT_ONLY_DIRECTORIES, MAX_PLACEMENT_COMBINATIONS, CloudBridge, CloudBoxBridge;
28931
+ var import_node_crypto6, import_node_fs17, import_node_path17, DEFAULT_RNX_CLOUD_ORIGIN, MAX_RNX_CLOUD_BUNDLE_BYTES, REMOTE_COMMAND, MAX_ASSET_DEST_FILES, ACCOUNT_CHOICE_REFUSALS, PROJECT_ONLY_DIRECTORIES, MAX_PLACEMENT_COMBINATIONS, CloudBridge, CloudBoxBridge;
28860
28932
  var init_cloud_client = __esm({
28861
28933
  "cli/cloud-client.ts"() {
28862
28934
  "use strict";
28863
28935
  import_node_crypto6 = require("node:crypto");
28864
- import_node_fs16 = require("node:fs");
28936
+ import_node_fs17 = require("node:fs");
28865
28937
  import_node_path17 = require("node:path");
28866
28938
  init_metroAssetArtifact();
28867
28939
  init_metroCloudArtifact();
@@ -31274,30 +31346,30 @@ var init_parent_pid = __esm({
31274
31346
 
31275
31347
  // cli/secure-file.ts
31276
31348
  function writeSecureJsonAtomic(filepath, value) {
31277
- (0, import_node_fs17.mkdirSync)((0, import_node_path18.dirname)(filepath), { recursive: true });
31349
+ (0, import_node_fs18.mkdirSync)((0, import_node_path18.dirname)(filepath), { recursive: true });
31278
31350
  const temporary = `${filepath}.tmp-${process.pid}-${(0, import_node_crypto7.randomUUID)()}`;
31279
31351
  let descriptor = null;
31280
31352
  try {
31281
- descriptor = (0, import_node_fs17.openSync)(temporary, "wx", 384);
31282
- (0, import_node_fs17.fchmodSync)(descriptor, 384);
31283
- (0, import_node_fs17.writeFileSync)(descriptor, `${JSON.stringify(value, null, 2)}
31353
+ descriptor = (0, import_node_fs18.openSync)(temporary, "wx", 384);
31354
+ (0, import_node_fs18.fchmodSync)(descriptor, 384);
31355
+ (0, import_node_fs18.writeFileSync)(descriptor, `${JSON.stringify(value, null, 2)}
31284
31356
  `);
31285
- (0, import_node_fs17.fsyncSync)(descriptor);
31286
- (0, import_node_fs17.closeSync)(descriptor);
31357
+ (0, import_node_fs18.fsyncSync)(descriptor);
31358
+ (0, import_node_fs18.closeSync)(descriptor);
31287
31359
  descriptor = null;
31288
- (0, import_node_fs17.renameSync)(temporary, filepath);
31360
+ (0, import_node_fs18.renameSync)(temporary, filepath);
31289
31361
  } catch (error) {
31290
- if (descriptor !== null) (0, import_node_fs17.closeSync)(descriptor);
31291
- (0, import_node_fs17.rmSync)(temporary, { force: true });
31362
+ if (descriptor !== null) (0, import_node_fs18.closeSync)(descriptor);
31363
+ (0, import_node_fs18.rmSync)(temporary, { force: true });
31292
31364
  throw error;
31293
31365
  }
31294
31366
  }
31295
- var import_node_crypto7, import_node_fs17, import_node_path18;
31367
+ var import_node_crypto7, import_node_fs18, import_node_path18;
31296
31368
  var init_secure_file = __esm({
31297
31369
  "cli/secure-file.ts"() {
31298
31370
  "use strict";
31299
31371
  import_node_crypto7 = require("node:crypto");
31300
- import_node_fs17 = require("node:fs");
31372
+ import_node_fs18 = require("node:fs");
31301
31373
  import_node_path18 = require("node:path");
31302
31374
  }
31303
31375
  });
@@ -31475,7 +31547,7 @@ function liveDevBridgeLockfiles() {
31475
31547
  function checkoutRoot(cwd) {
31476
31548
  let current = import_node_path19.default.resolve(cwd);
31477
31549
  while (true) {
31478
- if (import_node_fs18.default.existsSync(import_node_path19.default.join(current, ".git"))) return current;
31550
+ if (import_node_fs19.default.existsSync(import_node_path19.default.join(current, ".git"))) return current;
31479
31551
  const parent = import_node_path19.default.dirname(current);
31480
31552
  if (parent === current) return null;
31481
31553
  current = parent;
@@ -31870,9 +31942,8 @@ function createBridge(wsPort, opts = {}) {
31870
31942
  );
31871
31943
  return sendOnce(successor);
31872
31944
  }
31873
- clearCurrentSimId();
31874
31945
  throw new Error(
31875
- `saved sim ${sentSimId} is gone${message.slice(missingSimMessage.length)}; run \`peach list\` and \`peach use <sim>\`, or open a fresh sim`
31946
+ `saved sim ${sentSimId} is not connected${message.slice(missingSimMessage.length)}; commands resume when it reconnects, or run \`peach list\` and \`peach use <sim>\`, or open a fresh sim`
31876
31947
  );
31877
31948
  }
31878
31949
  throw error;
@@ -31986,11 +32057,11 @@ async function callInBridge(bridge, path23, ...args) {
31986
32057
  async function callInBridgeWrite(bridge, path23, ...args) {
31987
32058
  return bridge.send({ type: "call", path: path23, args, acquireLock: true });
31988
32059
  }
31989
- var import_node_fs18, import_node_path19, import_ws2, PEACH_PLACEMENT_ENV, resolvedWorld, BridgeSimLockedError, BRIDGE_VALUE_FLAGS_TABLE, BRIDGE_VALUE_FLAGS;
32060
+ var import_node_fs19, import_node_path19, import_ws2, PEACH_PLACEMENT_ENV, resolvedWorld, BridgeSimLockedError, BRIDGE_VALUE_FLAGS_TABLE, BRIDGE_VALUE_FLAGS;
31990
32061
  var init_ws_bridge = __esm({
31991
32062
  "cli/ws-bridge.ts"() {
31992
32063
  "use strict";
31993
- import_node_fs18 = __toESM(require("node:fs"), 1);
32064
+ import_node_fs19 = __toESM(require("node:fs"), 1);
31994
32065
  import_node_path19 = __toESM(require("node:path"), 1);
31995
32066
  import_ws2 = require("ws");
31996
32067
  init_bridge_constants();
@@ -32284,8 +32355,8 @@ var init_dev_bundle_resolution = __esm({
32284
32355
 
32285
32356
  // src/dot-env.ts
32286
32357
  function selectEnvFile(env, notices) {
32287
- if (import_node_fs19.default.existsSync("/tmp/envfile")) {
32288
- return { name: import_node_fs19.default.readFileSync("/tmp/envfile", "utf8").trim(), fromEnvfile: false };
32358
+ if (import_node_fs20.default.existsSync("/tmp/envfile")) {
32359
+ return { name: import_node_fs20.default.readFileSync("/tmp/envfile", "utf8").trim(), fromEnvfile: false };
32289
32360
  }
32290
32361
  const requested = env.ENVFILE;
32291
32362
  if (!requested) return { name: DEFAULT_ENV_FILE, fromEnvfile: false };
@@ -32355,9 +32426,9 @@ function readProjectDotEnv(envsRoot, env = process.env) {
32355
32426
  ...requestedPaths,
32356
32427
  import_node_path20.default.resolve(import_node_path20.default.join(envsRoot, DEFAULT_ENV_FILE))
32357
32428
  ];
32358
- if (!import_node_fs19.default.existsSync(candidates[2])) candidates.push(import_node_path20.default.resolve(DEFAULT_ENV_FILE));
32429
+ if (!import_node_fs20.default.existsSync(candidates[2])) candidates.push(import_node_path20.default.resolve(DEFAULT_ENV_FILE));
32359
32430
  const tried = [...new Set(candidates)];
32360
- const resolved = tried.find((candidate) => import_node_fs19.default.existsSync(candidate));
32431
+ const resolved = tried.find((candidate) => import_node_fs20.default.existsSync(candidate));
32361
32432
  if (!resolved) {
32362
32433
  notices.push(
32363
32434
  "*** Missing .env file ****",
@@ -32377,7 +32448,7 @@ function readProjectDotEnv(envsRoot, env = process.env) {
32377
32448
  );
32378
32449
  }
32379
32450
  const config = {};
32380
- for (const line of import_node_fs19.default.readFileSync(resolved, "utf8").split("\n")) {
32451
+ for (const line of import_node_fs20.default.readFileSync(resolved, "utf8").split("\n")) {
32381
32452
  if (!line.trim()) continue;
32382
32453
  if (/^[ \t\n\v\f\r]*#/.test(line)) continue;
32383
32454
  const match = DOTENV_PATTERN.exec(line);
@@ -32387,11 +32458,11 @@ function readProjectDotEnv(envsRoot, env = process.env) {
32387
32458
  }
32388
32459
  return { config, notices };
32389
32460
  }
32390
- var import_node_fs19, import_node_path20, DEFAULT_ENV_FILE, DOTENV_PATTERN, BUILD_SETTING_PATTERN, INVALID_ENTRY;
32461
+ var import_node_fs20, import_node_path20, DEFAULT_ENV_FILE, DOTENV_PATTERN, BUILD_SETTING_PATTERN, INVALID_ENTRY;
32391
32462
  var init_dot_env = __esm({
32392
32463
  "src/dot-env.ts"() {
32393
32464
  "use strict";
32394
- import_node_fs19 = __toESM(require("node:fs"), 1);
32465
+ import_node_fs20 = __toESM(require("node:fs"), 1);
32395
32466
  import_node_path20 = __toESM(require("node:path"), 1);
32396
32467
  DEFAULT_ENV_FILE = ".env";
32397
32468
  DOTENV_PATTERN = /^(?:export[ \t\n\v\f\r]+|)(?<key>[\p{Alphabetic}\p{Nd}_]+)[ \t\n\v\f\r]*=[ \t\n\v\f\r]*((?<quote>["'])?(?<val>[^\n]*?[^\\\n])\k<quote>?|)$/u;
@@ -32421,7 +32492,7 @@ function readNativeFirebaseConfig(projectRoot) {
32421
32492
  "app.config.ts",
32422
32493
  "app.config.cjs",
32423
32494
  "app.config.mjs"
32424
- ].some((name2) => import_node_fs20.default.existsSync(import_node_path21.default.join(projectRoot, name2))))
32495
+ ].some((name2) => import_node_fs21.default.existsSync(import_node_path21.default.join(projectRoot, name2))))
32425
32496
  return result;
32426
32497
  const require5 = (0, import_node_module.createRequire)(import_node_path21.default.join(projectRoot, "package.json"));
32427
32498
  const configModule = require5("@expo/config");
@@ -32437,7 +32508,7 @@ function readNativeFirebaseConfig(projectRoot) {
32437
32508
  const native = config[platform];
32438
32509
  if (!isRecord(native) || typeof native.googleServicesFile !== "string") continue;
32439
32510
  try {
32440
- const source = import_node_fs20.default.readFileSync(
32511
+ const source = import_node_fs21.default.readFileSync(
32441
32512
  import_node_path21.default.resolve(projectRoot, native.googleServicesFile),
32442
32513
  "utf8"
32443
32514
  );
@@ -32490,11 +32561,11 @@ function readNativeFirebaseConfig(projectRoot) {
32490
32561
  }
32491
32562
  return result;
32492
32563
  }
32493
- var import_node_fs20, import_node_module, import_node_path21;
32564
+ var import_node_fs21, import_node_module, import_node_path21;
32494
32565
  var init_native_firebase_config = __esm({
32495
32566
  "src/native-firebase-config.ts"() {
32496
32567
  "use strict";
32497
- import_node_fs20 = __toESM(require("node:fs"), 1);
32568
+ import_node_fs21 = __toESM(require("node:fs"), 1);
32498
32569
  import_node_module = require("node:module");
32499
32570
  import_node_path21 = __toESM(require("node:path"), 1);
32500
32571
  init_is_record();
@@ -32708,14 +32779,14 @@ var init_bundleAssets = __esm({
32708
32779
  // cli/app-catalog.ts
32709
32780
  function listDir(dir) {
32710
32781
  try {
32711
- return import_node_fs21.default.readdirSync(dir, { withFileTypes: true });
32782
+ return import_node_fs22.default.readdirSync(dir, { withFileTypes: true });
32712
32783
  } catch {
32713
32784
  return [];
32714
32785
  }
32715
32786
  }
32716
32787
  function readText(file) {
32717
32788
  try {
32718
- return import_node_fs21.default.readFileSync(file, "utf8");
32789
+ return import_node_fs22.default.readFileSync(file, "utf8");
32719
32790
  } catch {
32720
32791
  return null;
32721
32792
  }
@@ -32755,11 +32826,11 @@ function discoverAppCatalog(appDir) {
32755
32826
  if (accentName === null && Object.keys(colors).length === 0) return null;
32756
32827
  return { colors, accentName };
32757
32828
  }
32758
- var import_node_fs21, import_node_path22, ACCENT_BUILD_SETTING, PLIST_ACCENT;
32829
+ var import_node_fs22, import_node_path22, ACCENT_BUILD_SETTING, PLIST_ACCENT;
32759
32830
  var init_app_catalog = __esm({
32760
32831
  "cli/app-catalog.ts"() {
32761
32832
  "use strict";
32762
- import_node_fs21 = __toESM(require("node:fs"), 1);
32833
+ import_node_fs22 = __toESM(require("node:fs"), 1);
32763
32834
  import_node_path22 = __toESM(require("node:path"), 1);
32764
32835
  init_bundleAssets();
32765
32836
  ACCENT_BUILD_SETTING = /ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = "?([^";]+)"?;/;
@@ -32772,7 +32843,7 @@ function firstNamedFile(dir, names) {
32772
32843
  for (const name2 of names) {
32773
32844
  const candidate = import_node_path23.default.join(dir, name2);
32774
32845
  try {
32775
- if (import_node_fs22.default.statSync(candidate).isFile()) return candidate;
32846
+ if (import_node_fs23.default.statSync(candidate).isFile()) return candidate;
32776
32847
  } catch {
32777
32848
  }
32778
32849
  }
@@ -32782,26 +32853,26 @@ function findExpoAppConfig(dir) {
32782
32853
  return firstNamedFile(dir, EXPO_APP_CONFIG_NAMES);
32783
32854
  }
32784
32855
  function findRNXAppConfig(dir) {
32785
- return firstNamedFile(dir, RNX_APP_CONFIG_NAMES);
32856
+ return firstNamedFile(dir, PEACH_APP_CONFIG_NAMES);
32786
32857
  }
32787
32858
  function resolveAppProject(projectRoot) {
32788
32859
  const appDir = import_node_path23.default.resolve(projectRoot);
32789
32860
  try {
32790
- if (!import_node_fs22.default.statSync(appDir).isDirectory()) return null;
32861
+ if (!import_node_fs23.default.statSync(appDir).isDirectory()) return null;
32791
32862
  } catch {
32792
32863
  return null;
32793
32864
  }
32794
32865
  const configPath = findRNXAppConfig(appDir);
32795
- if (!configPath && !findExpoAppConfig(appDir) && !import_node_fs22.default.existsSync(import_node_path23.default.join(appDir, "package.json"))) {
32866
+ if (!configPath && !findExpoAppConfig(appDir) && !import_node_fs23.default.existsSync(import_node_path23.default.join(appDir, "package.json"))) {
32796
32867
  return null;
32797
32868
  }
32798
32869
  return { appDir, configPath };
32799
32870
  }
32800
- var import_node_fs22, import_node_path23, EXPO_APP_CONFIG_NAMES, RNX_APP_CONFIG_NAMES;
32871
+ var import_node_fs23, import_node_path23, EXPO_APP_CONFIG_NAMES, PEACH_APP_CONFIG_NAMES;
32801
32872
  var init_app_project = __esm({
32802
32873
  "cli/app-project.ts"() {
32803
32874
  "use strict";
32804
- import_node_fs22 = __toESM(require("node:fs"), 1);
32875
+ import_node_fs23 = __toESM(require("node:fs"), 1);
32805
32876
  import_node_path23 = __toESM(require("node:path"), 1);
32806
32877
  EXPO_APP_CONFIG_NAMES = [
32807
32878
  "app.config.js",
@@ -32810,11 +32881,11 @@ var init_app_project = __esm({
32810
32881
  "app.config.mjs",
32811
32882
  "app.json"
32812
32883
  ];
32813
- RNX_APP_CONFIG_NAMES = [
32814
- "rnx.config.ts",
32815
- "rnx.config.js",
32816
- "rnx.config.mjs",
32817
- "rnx.config.cjs"
32884
+ PEACH_APP_CONFIG_NAMES = [
32885
+ "peach.config.ts",
32886
+ "peach.config.js",
32887
+ "peach.config.mjs",
32888
+ "peach.config.cjs"
32818
32889
  ];
32819
32890
  }
32820
32891
  });
@@ -32823,23 +32894,29 @@ var init_app_project = __esm({
32823
32894
  function isOptionalRecord(value) {
32824
32895
  return value === void 0 || value !== null && typeof value === "object" && !Array.isArray(value);
32825
32896
  }
32826
- function isRNXConfig(value) {
32897
+ function isPeachConfig(value) {
32827
32898
  if (!value || typeof value !== "object" || Array.isArray(value)) return false;
32828
32899
  const runtimeVersion = Reflect.get(value, "runtimeVersion");
32829
32900
  const network = Reflect.get(value, "network");
32830
- return (runtimeVersion === void 0 || typeof runtimeVersion === "string" && runtimeVersion === runtimeVersion.trim() && isValidRuntimeVersion(runtimeVersion)) && isOptionalRecord(Reflect.get(value, "modules")) && isOptionalRecord(Reflect.get(value, "turboModules")) && isOptionalRecord(Reflect.get(value, "nativeModules")) && isOptionalRecord(Reflect.get(value, "env")) && isOptionalRecord(network) && isOptionalRecord(Reflect.get(value, "settings")) && isOptionalRecord(Reflect.get(value, "initialState"));
32901
+ return (runtimeVersion === void 0 || typeof runtimeVersion === "string" && runtimeVersion === runtimeVersion.trim() && isValidRuntimeVersion(runtimeVersion)) && isOptionalRecord(Reflect.get(value, "modules")) && isOptionalRecord(Reflect.get(value, "turboModules")) && isOptionalRecord(Reflect.get(value, "nativeModules")) && isOptionalRecord(Reflect.get(value, "nativeViews")) && isOptionalRecord(Reflect.get(value, "env")) && isOptionalRecord(network) && isOptionalRecord(Reflect.get(value, "settings")) && isOptionalRecord(Reflect.get(value, "initialState"));
32902
+ }
32903
+ function resolveFileEntries(entries, configDir) {
32904
+ if (!entries) return entries;
32905
+ return Object.fromEntries(
32906
+ Object.entries(entries).map(([name2, resolution]) => [
32907
+ name2,
32908
+ resolution && typeof resolution === "object" && "file" in resolution && typeof resolution.file === "string" ? { ...resolution, file: import_node_path24.default.resolve(configDir, resolution.file) } : resolution
32909
+ ])
32910
+ );
32831
32911
  }
32832
32912
  function resolveConfigReplacementFiles(config, configPath) {
32833
- if (!config.modules) return config;
32834
32913
  const configDir = import_node_path24.default.dirname(configPath);
32835
32914
  return {
32836
32915
  ...config,
32837
- modules: Object.fromEntries(
32838
- Object.entries(config.modules).map(([name2, resolution]) => [
32839
- name2,
32840
- resolution && typeof resolution === "object" && "file" in resolution ? { ...resolution, file: import_node_path24.default.resolve(configDir, resolution.file) } : resolution
32841
- ])
32842
- )
32916
+ modules: resolveFileEntries(config.modules, configDir),
32917
+ turboModules: resolveFileEntries(config.turboModules, configDir),
32918
+ nativeModules: resolveFileEntries(config.nativeModules, configDir),
32919
+ nativeViews: resolveFileEntries(config.nativeViews, configDir)
32843
32920
  };
32844
32921
  }
32845
32922
  async function loadRNXAppConfig(project) {
@@ -32854,7 +32931,7 @@ async function loadRNXAppConfig(project) {
32854
32931
  }
32855
32932
  });
32856
32933
  const loaded = await jiti.import(project.configPath, { default: true });
32857
- if (!isRNXConfig(loaded)) {
32934
+ if (!isPeachConfig(loaded)) {
32858
32935
  throw new Error("the default export must be a peach config object");
32859
32936
  }
32860
32937
  return resolveConfigReplacementFiles(loaded, project.configPath);
@@ -32929,7 +33006,7 @@ function discoverNativeLinkedAppFonts(opts) {
32929
33006
  scannedFontDirectories++;
32930
33007
  let entries;
32931
33008
  try {
32932
- entries = import_node_fs23.default.readdirSync(current.dir, { withFileTypes: true });
33009
+ entries = import_node_fs24.default.readdirSync(current.dir, { withFileTypes: true });
32933
33010
  } catch {
32934
33011
  continue;
32935
33012
  }
@@ -32951,7 +33028,7 @@ function discoverNativeLinkedAppFonts(opts) {
32951
33028
  };
32952
33029
  try {
32953
33030
  const packageJson = JSON.parse(
32954
- import_node_fs23.default.readFileSync(import_node_path25.default.join(selectedAppDir, "package.json"), "utf8")
33031
+ import_node_fs24.default.readFileSync(import_node_path25.default.join(selectedAppDir, "package.json"), "utf8")
32955
33032
  );
32956
33033
  const dependencyNames = /* @__PURE__ */ new Set();
32957
33034
  for (const field of ["dependencies", "devDependencies", "optionalDependencies"]) {
@@ -33002,7 +33079,7 @@ function discoverNativeLinkedAppFonts(opts) {
33002
33079
  }
33003
33080
  try {
33004
33081
  const configPath = import_node_path25.default.join(selectedAppDir, "react-native.config.js");
33005
- if (import_node_fs23.default.statSync(configPath).isFile()) {
33082
+ if (import_node_fs24.default.statSync(configPath).isFile()) {
33006
33083
  const appConfigRequire = (0, import_node_module3.createRequire)(import_node_path25.default.join(selectedAppDir, "package.json"));
33007
33084
  const rnConfig = appConfigRequire(configPath);
33008
33085
  const assets = rnConfig && typeof rnConfig === "object" ? Reflect.get(rnConfig, "assets") : null;
@@ -33021,7 +33098,7 @@ function discoverNativeLinkedAppFonts(opts) {
33021
33098
  if (platform === "ios") {
33022
33099
  const iosDir = import_node_path25.default.join(selectedAppDir, "ios");
33023
33100
  try {
33024
- const targetDirs = import_node_fs23.default.readdirSync(iosDir, { withFileTypes: true }).filter(
33101
+ const targetDirs = import_node_fs24.default.readdirSync(iosDir, { withFileTypes: true }).filter(
33025
33102
  (entry) => entry.isDirectory() && !entry.isSymbolicLink() && entry.name !== "Pods" && entry.name !== "build" && !entry.name.startsWith(".")
33026
33103
  ).slice(0, 64);
33027
33104
  const plistPaths = [import_node_path25.default.join(iosDir, "Info.plist")];
@@ -33031,7 +33108,7 @@ function discoverNativeLinkedAppFonts(opts) {
33031
33108
  for (const plistPath of plistPaths) {
33032
33109
  let parsed;
33033
33110
  try {
33034
- parsed = parsePlistSource(import_node_fs23.default.readFileSync(plistPath, "utf8"));
33111
+ parsed = parsePlistSource(import_node_fs24.default.readFileSync(plistPath, "utf8"));
33035
33112
  } catch {
33036
33113
  continue;
33037
33114
  }
@@ -33048,7 +33125,7 @@ function discoverNativeLinkedAppFonts(opts) {
33048
33125
  const relative2 = import_node_path25.default.relative(selectedAppDir, candidate);
33049
33126
  if (relative2.startsWith("..") || import_node_path25.default.isAbsolute(relative2)) return false;
33050
33127
  try {
33051
- return import_node_fs23.default.statSync(candidate).isFile();
33128
+ return import_node_fs24.default.statSync(candidate).isFile();
33052
33129
  } catch {
33053
33130
  return false;
33054
33131
  }
@@ -33094,11 +33171,11 @@ async function resolveMetroProjectRoot(bundleUrl, opts) {
33094
33171
  function encodeAppFontsWire(specs) {
33095
33172
  return specs.map((spec) => `${encodeURIComponent(spec.url)}::${encodeURIComponent(spec.family)}`).join(",");
33096
33173
  }
33097
- var import_node_fs23, import_node_module3, import_node_path25, import_config_plugin_fonts, require3;
33174
+ var import_node_fs24, import_node_module3, import_node_path25, import_config_plugin_fonts, require3;
33098
33175
  var init_app_fonts = __esm({
33099
33176
  "cli/app-fonts.ts"() {
33100
33177
  "use strict";
33101
- import_node_fs23 = __toESM(require("node:fs"), 1);
33178
+ import_node_fs24 = __toESM(require("node:fs"), 1);
33102
33179
  import_node_module3 = require("node:module");
33103
33180
  import_node_path25 = __toESM(require("node:path"), 1);
33104
33181
  import_config_plugin_fonts = require("peach-engine/engine/config-plugin-fonts");
@@ -34368,13 +34445,13 @@ function resolvePlaywright() {
34368
34445
  try {
34369
34446
  const modulePath = requireFromRoot.resolve(spec);
34370
34447
  const packageJsonPath = requireFromRoot.resolve(`${spec}/package.json`);
34371
- const parsed = JSON.parse((0, import_node_fs24.readFileSync)(packageJsonPath, "utf8"));
34448
+ const parsed = JSON.parse((0, import_node_fs25.readFileSync)(packageJsonPath, "utf8"));
34372
34449
  if (!isRecord(parsed) || typeof parsed.version !== "string") continue;
34373
34450
  const corePackagePath = (0, import_node_module5.createRequire)(modulePath).resolve(
34374
34451
  "playwright-core/package.json"
34375
34452
  );
34376
34453
  const cliPath = (0, import_node_path26.join)((0, import_node_path26.dirname)(corePackagePath), "cli.js");
34377
- if (!(0, import_node_fs24.existsSync)(cliPath)) continue;
34454
+ if (!(0, import_node_fs25.existsSync)(cliPath)) continue;
34378
34455
  return {
34379
34456
  spec,
34380
34457
  modulePath,
@@ -34445,7 +34522,7 @@ function probeBrowser(resolved, env) {
34445
34522
  return {
34446
34523
  ok: true,
34447
34524
  executablePath: parsed.executablePath,
34448
- exists: parsed.exists && (0, import_node_fs24.existsSync)(parsed.executablePath)
34525
+ exists: parsed.exists && (0, import_node_fs25.existsSync)(parsed.executablePath)
34449
34526
  };
34450
34527
  } catch (error) {
34451
34528
  return {
@@ -34461,6 +34538,8 @@ function ensurePlaywrightBrowser(resolved, headless, env = process.env) {
34461
34538
  const before = probeBrowser(resolved, probeEnv);
34462
34539
  if (!before.ok) return before;
34463
34540
  if (before.exists) {
34541
+ const missing2 = missingLibrariesMessage(before.executablePath, browser);
34542
+ if (missing2) return { ok: false, message: missing2 };
34464
34543
  return { ok: true, executablePath: before.executablePath, installed: false };
34465
34544
  }
34466
34545
  const installer = rnxSelfInvocation();
@@ -34497,14 +34576,50 @@ ${detail}` : ""}`
34497
34576
  message: `${resolved.spec}@${resolved.version} browser install completed, but its required ${browser} executable is still missing at ${after.executablePath}`
34498
34577
  };
34499
34578
  }
34579
+ const missing = missingLibrariesMessage(after.executablePath, browser);
34580
+ if (missing) return { ok: false, message: missing };
34500
34581
  return { ok: true, executablePath: after.executablePath, installed: true };
34501
34582
  }
34502
- var import_node_child_process6, import_node_fs24, import_node_module5, import_node_path26;
34583
+ function isTime64Distro() {
34584
+ if (!(0, import_node_fs25.existsSync)("/etc/os-release")) return false;
34585
+ const fields = Object.fromEntries(
34586
+ (0, import_node_fs25.readFileSync)("/etc/os-release", "utf8").split("\n").map((line) => line.match(/^(\w+)="?([^"]*)"?$/)).filter((match) => match !== null).map((match) => [match[1], match[2]])
34587
+ );
34588
+ const version = Number.parseFloat(fields.VERSION_ID ?? "");
34589
+ return fields.ID === "ubuntu" && version >= 24.04 || fields.ID === "debian" && version >= 13;
34590
+ }
34591
+ function missingLibrariesMessage(executablePath, browser) {
34592
+ if (process.platform !== "linux") return null;
34593
+ const ldd = (0, import_node_child_process6.spawnSync)("ldd", [executablePath], { encoding: "utf8", timeout: 3e4 });
34594
+ const libraries = [...(ldd.stdout ?? "").matchAll(/^\s*(\S+) => not found$/gm)].map(
34595
+ (match) => match[1]
34596
+ );
34597
+ if (!libraries.length) return null;
34598
+ const time64 = isTime64Distro();
34599
+ const packages = /* @__PURE__ */ new Set();
34600
+ const unknown = [];
34601
+ for (const library of libraries) {
34602
+ const name2 = LIBRARY_PACKAGES[library];
34603
+ if (!name2) unknown.push(library);
34604
+ else packages.add(time64 && TIME64_PACKAGES.has(name2) ? `${name2}t64` : name2);
34605
+ }
34606
+ const sudo = process.getuid?.() === 0 ? "" : "sudo ";
34607
+ return [
34608
+ `${browser} at ${executablePath} cannot start: this system is missing shared libraries it links (${libraries.join(", ")}).`,
34609
+ ...packages.size ? [
34610
+ "On Debian or Ubuntu, install them and run the command again:",
34611
+ "",
34612
+ ` ${sudo}apt-get update && ${sudo}apt-get install -y --no-install-recommends ${[...packages].join(" ")}`
34613
+ ] : [],
34614
+ ...unknown.length ? ["", `No known Debian package provides: ${unknown.join(", ")}`] : []
34615
+ ].join("\n");
34616
+ }
34617
+ var import_node_child_process6, import_node_fs25, import_node_module5, import_node_path26, LIBRARY_PACKAGES, TIME64_PACKAGES;
34503
34618
  var init_playwright_provisioning = __esm({
34504
34619
  "cli/drivers/playwright-provisioning.ts"() {
34505
34620
  "use strict";
34506
34621
  import_node_child_process6 = require("node:child_process");
34507
- import_node_fs24 = require("node:fs");
34622
+ import_node_fs25 = require("node:fs");
34508
34623
  import_node_module5 = require("node:module");
34509
34624
  import_node_path26 = require("node:path");
34510
34625
  init_src();
@@ -34513,6 +34628,42 @@ var init_playwright_provisioning = __esm({
34513
34628
  init_internal_child();
34514
34629
  init_self_invocation();
34515
34630
  init_playwright_core_pin();
34631
+ LIBRARY_PACKAGES = {
34632
+ "libasound.so.2": "libasound2",
34633
+ "libatk-1.0.so.0": "libatk1.0-0",
34634
+ "libatk-bridge-2.0.so.0": "libatk-bridge2.0-0",
34635
+ "libatspi.so.0": "libatspi2.0-0",
34636
+ "libcairo.so.2": "libcairo2",
34637
+ "libcups.so.2": "libcups2",
34638
+ "libdbus-1.so.3": "libdbus-1-3",
34639
+ "libexpat.so.1": "libexpat1",
34640
+ "libgbm.so.1": "libgbm1",
34641
+ "libgio-2.0.so.0": "libglib2.0-0",
34642
+ "libglib-2.0.so.0": "libglib2.0-0",
34643
+ "libgobject-2.0.so.0": "libglib2.0-0",
34644
+ "libnspr4.so": "libnspr4",
34645
+ "libnss3.so": "libnss3",
34646
+ "libnssutil3.so": "libnss3",
34647
+ "libpango-1.0.so.0": "libpango-1.0-0",
34648
+ "libsmime3.so": "libnss3",
34649
+ "libudev.so.1": "libudev1",
34650
+ "libX11.so.6": "libx11-6",
34651
+ "libxcb.so.1": "libxcb1",
34652
+ "libXcomposite.so.1": "libxcomposite1",
34653
+ "libXdamage.so.1": "libxdamage1",
34654
+ "libXext.so.6": "libxext6",
34655
+ "libXfixes.so.3": "libxfixes3",
34656
+ "libxkbcommon.so.0": "libxkbcommon0",
34657
+ "libXrandr.so.2": "libxrandr2"
34658
+ };
34659
+ TIME64_PACKAGES = /* @__PURE__ */ new Set([
34660
+ "libasound2",
34661
+ "libatk1.0-0",
34662
+ "libatk-bridge2.0-0",
34663
+ "libatspi2.0-0",
34664
+ "libcups2",
34665
+ "libglib2.0-0"
34666
+ ]);
34516
34667
  }
34517
34668
  });
34518
34669
 
@@ -35437,7 +35588,7 @@ function assertExplicitBridgeLock(preferredPort, explicitPort, lock) {
35437
35588
  async function ensureRuntimeForOpen() {
35438
35589
  if (resolveDevCheckoutRuntimeRoot()) return;
35439
35590
  const active = readActiveRuntime();
35440
- if (active && import_node_fs25.default.existsSync(runtimeDir(active))) return;
35591
+ if (active && import_node_fs26.default.existsSync(runtimeDir(active))) return;
35441
35592
  console.error(" installing peach engine runtime...");
35442
35593
  const { runRuntime: runRuntime2 } = await Promise.resolve().then(() => (init_runtime(), runtime_exports));
35443
35594
  await runRuntime2(["install"], {});
@@ -35613,7 +35764,7 @@ function parseOpenRuntimeConfig(args) {
35613
35764
  }
35614
35765
  const moduleName = raw.slice(0, eqIndex).trim();
35615
35766
  const filePath = normalizeReplacementPath(raw.slice(eqIndex + 1).trim());
35616
- if (!import_node_fs25.default.existsSync(filePath)) {
35767
+ if (!import_node_fs26.default.existsSync(filePath)) {
35617
35768
  console.error(` peach open: replacement file not found: ${filePath}`);
35618
35769
  rnxExit(1);
35619
35770
  }
@@ -35644,7 +35795,7 @@ async function resolveAppProjectForBundleUrl(bundleUrl) {
35644
35795
  return advertisedRoot ? resolveAppProject(advertisedRoot) : null;
35645
35796
  }
35646
35797
  async function ensureConfiguredRuntime(version) {
35647
- if (import_node_fs25.default.existsSync(import_node_path27.default.join(runtimeDir(version), "index.html"))) return;
35798
+ if (import_node_fs26.default.existsSync(import_node_path27.default.join(runtimeDir(version), "index.html"))) return;
35648
35799
  console.error(` installing configured engine runtime ${version}...`);
35649
35800
  const result = await rnxRuntime.install({
35650
35801
  version,
@@ -35722,9 +35873,9 @@ async function resolveShellUrl(target, baseUrl, opts = {}) {
35722
35873
  if (looksLikeSootsimUrl(target)) {
35723
35874
  const url = new URL(target);
35724
35875
  const base = new URL(baseUrl);
35725
- const baseConfig = base.searchParams.get(RNX_CONFIG_QUERY_PARAM);
35726
- if (baseConfig && !url.searchParams.has(RNX_CONFIG_QUERY_PARAM)) {
35727
- url.searchParams.set(RNX_CONFIG_QUERY_PARAM, baseConfig);
35876
+ const baseConfig = base.searchParams.get(PEACH_CONFIG_QUERY_PARAM);
35877
+ if (baseConfig && !url.searchParams.has(PEACH_CONFIG_QUERY_PARAM)) {
35878
+ url.searchParams.set(PEACH_CONFIG_QUERY_PARAM, baseConfig);
35728
35879
  }
35729
35880
  return url.toString();
35730
35881
  }
@@ -35961,7 +36112,7 @@ function playwrightHostPidForSim(sim) {
35961
36112
  function signalDriverLaunchConnected(result) {
35962
36113
  if (!result.connectAckFile) return false;
35963
36114
  try {
35964
- import_node_fs25.default.writeFileSync(
36115
+ import_node_fs26.default.writeFileSync(
35965
36116
  result.connectAckFile,
35966
36117
  `${JSON.stringify({ connectedAt: Date.now(), pid: result.pid ?? null })}
35967
36118
  `,
@@ -35975,7 +36126,7 @@ function signalDriverLaunchConnected(result) {
35975
36126
  function printDriverDiagnosticLogTail(result) {
35976
36127
  if (!result.diagnosticLogPath) return;
35977
36128
  try {
35978
- const detail = import_node_fs25.default.readFileSync(result.diagnosticLogPath, "utf8").trim();
36129
+ const detail = import_node_fs26.default.readFileSync(result.diagnosticLogPath, "utf8").trim();
35979
36130
  if (!detail) {
35980
36131
  console.error(` ${import_node_path27.default.basename(result.diagnosticLogPath)} was empty`);
35981
36132
  return;
@@ -36071,16 +36222,16 @@ function printOpenedSim(openUrl2, sim, mode, quiet = false) {
36071
36222
  try {
36072
36223
  const parsed = new URL(value);
36073
36224
  let changed = false;
36074
- if (parsed.searchParams.has(RNX_CONFIG_QUERY_PARAM)) {
36075
- parsed.searchParams.set(RNX_CONFIG_QUERY_PARAM, "[redacted]");
36225
+ if (parsed.searchParams.has(PEACH_CONFIG_QUERY_PARAM)) {
36226
+ parsed.searchParams.set(PEACH_CONFIG_QUERY_PARAM, "[redacted]");
36076
36227
  changed = true;
36077
36228
  }
36078
36229
  const bundle = parsed.searchParams.get("bundle");
36079
36230
  if (bundle) {
36080
36231
  try {
36081
36232
  const parsedBundle = new URL(bundle);
36082
- if (parsedBundle.searchParams.has(RNX_CONFIG_QUERY_PARAM)) {
36083
- parsedBundle.searchParams.set(RNX_CONFIG_QUERY_PARAM, "[redacted]");
36233
+ if (parsedBundle.searchParams.has(PEACH_CONFIG_QUERY_PARAM)) {
36234
+ parsedBundle.searchParams.set(PEACH_CONFIG_QUERY_PARAM, "[redacted]");
36084
36235
  parsed.searchParams.set("bundle", parsedBundle.toString());
36085
36236
  changed = true;
36086
36237
  }
@@ -36319,8 +36470,8 @@ async function runOpenCommand(args, opts = {}) {
36319
36470
  const project = await resolveAppProjectForBundleUrl(resolvedBundle?.bundleUrl);
36320
36471
  const appConfig = await loadRNXAppConfig(project);
36321
36472
  const configuredRuntimeVersion = appConfig?.runtimeVersion;
36322
- const runtimeConfig = mergeRNXConfig(
36323
- mergeRNXConfig(
36473
+ const runtimeConfig = mergePeachConfig(
36474
+ mergePeachConfig(
36324
36475
  appConfig ? { ...appConfig, runtimeVersion: void 0 } : void 0,
36325
36476
  opts.runtimeConfig
36326
36477
  ),
@@ -36493,7 +36644,7 @@ async function runOpenCommand(args, opts = {}) {
36493
36644
  if (!targetSim && parsed.simIdSource !== "flag") {
36494
36645
  targetShellUrl = await buildShellUrl(
36495
36646
  target,
36496
- applyRNXConfigToUrl(baseUrl, runtimeConfig),
36647
+ applyPeachConfigToUrl(baseUrl, runtimeConfig),
36497
36648
  buildShellUrlOpts
36498
36649
  );
36499
36650
  const normalizedTarget = new URL(targetShellUrl);
@@ -36522,7 +36673,7 @@ async function runOpenCommand(args, opts = {}) {
36522
36673
  const resolvedBaseUrl = hasExplicitBaseUrl || looksLikeSootsimUrl(target) ? baseUrl : deriveCurrentSimBaseUrl(targetSim, baseUrl);
36523
36674
  navigatedShellUrl = targetShellUrl ?? await buildShellUrl(
36524
36675
  target,
36525
- applyRNXConfigToUrl(resolvedBaseUrl, runtimeConfig),
36676
+ applyPeachConfigToUrl(resolvedBaseUrl, runtimeConfig),
36526
36677
  buildShellUrlOpts
36527
36678
  );
36528
36679
  const navigationUrl = new URL(navigatedShellUrl);
@@ -36597,7 +36748,7 @@ async function runOpenCommand(args, opts = {}) {
36597
36748
  bridge.close();
36598
36749
  }
36599
36750
  }
36600
- const configuredBaseUrl = applyRNXConfigToUrl(baseUrl, runtimeConfig);
36751
+ const configuredBaseUrl = applyPeachConfigToUrl(baseUrl, runtimeConfig);
36601
36752
  const openUrl2 = await buildOpenUrl(target, configuredBaseUrl, token, buildShellUrlOpts);
36602
36753
  const ownerPid = opts.ownerPid ?? getStableOwnerPid();
36603
36754
  if (!ownerPid) {
@@ -36966,12 +37117,12 @@ async function runCloseCommand(args, opts = {}) {
36966
37117
  bridge.close();
36967
37118
  }
36968
37119
  }
36969
- var import_node_child_process7, import_node_fs25, import_node_os4, import_node_path27, import_app_catalog_wire, import_devices2, import_ws4, DEFAULT_DRIVER_CONNECT_TIMEOUT_MS, DRIVER_CONNECT_INTERVAL_MS, DRIVER_CONNECT_HOST_GRACE_MS, OPEN_BRIDGE_SPAWN_TIMEOUT_MS, SHELL_APPS, DEV_BUNDLE_RESOLVE_ATTEMPTS, DEV_BUNDLE_RESOLVE_INTERVAL_MS;
37120
+ var import_node_child_process7, import_node_fs26, import_node_os4, import_node_path27, import_app_catalog_wire, import_devices2, import_ws4, DEFAULT_DRIVER_CONNECT_TIMEOUT_MS, DRIVER_CONNECT_INTERVAL_MS, DRIVER_CONNECT_HOST_GRACE_MS, OPEN_BRIDGE_SPAWN_TIMEOUT_MS, SHELL_APPS, DEV_BUNDLE_RESOLVE_ATTEMPTS, DEV_BUNDLE_RESOLVE_INTERVAL_MS;
36970
37121
  var init_control = __esm({
36971
37122
  "cli/commands/control.ts"() {
36972
37123
  "use strict";
36973
37124
  import_node_child_process7 = require("node:child_process");
36974
- import_node_fs25 = __toESM(require("node:fs"), 1);
37125
+ import_node_fs26 = __toESM(require("node:fs"), 1);
36975
37126
  import_node_os4 = __toESM(require("node:os"), 1);
36976
37127
  import_node_path27 = __toESM(require("node:path"), 1);
36977
37128
  import_app_catalog_wire = require("peach-engine/engine/app-catalog-wire");
@@ -38505,7 +38656,6 @@ var init_bridge_flow_runner = __esm({
38505
38656
  });
38506
38657
  firstLaunchDone = false;
38507
38658
  appStopped = false;
38508
- launchArgumentsActive = false;
38509
38659
  profilingEnabled = false;
38510
38660
  recordingEnabled = false;
38511
38661
  recordingAccessChecked = false;
@@ -39738,17 +39888,6 @@ var init_bridge_flow_runner = __esm({
39738
39888
  }
39739
39889
  throw new Error("extendedWaitUntil timed out");
39740
39890
  }
39741
- async reloadGuestApp() {
39742
- const reloaded = await this.bridge.send({
39743
- type: "call",
39744
- simId: this.opts.simId,
39745
- path: "SootSim.bridges.hotRemount.reloadExternalApp",
39746
- args: []
39747
- });
39748
- if (reloaded) return;
39749
- await this.evaluate("window.location.reload()").catch(() => {
39750
- });
39751
- }
39752
39891
  async resetGuestAppData(launchOptions) {
39753
39892
  const reset = await this.bridge.send(
39754
39893
  {
@@ -39809,6 +39948,7 @@ var init_bridge_flow_runner = __esm({
39809
39948
  }
39810
39949
  const wantsClear = !!(opts && typeof opts === "object" && opts.clearState);
39811
39950
  const wantsResetRuntime = readBooleanKey(opts, "resetRuntime");
39951
+ const wantsForeground = isObjectRecord(opts) && opts.stopApp === false;
39812
39952
  await this.setLaunchPermissions(isObjectRecord(opts) ? opts.permissions : void 0);
39813
39953
  if (!this.firstLaunchDone) {
39814
39954
  this.firstLaunchDone = true;
@@ -39843,7 +39983,14 @@ var init_bridge_flow_runner = __esm({
39843
39983
  await this.waitForTree(12e4);
39844
39984
  await this.waitForTree(3e4);
39845
39985
  } else {
39846
- await this.launchShellAppFromHomeIfNeeded(opts);
39986
+ const launched = await this.launchShellAppFromHomeIfNeeded(opts);
39987
+ if (!launched && !wantsForeground) {
39988
+ await this.waitForTree(12e4);
39989
+ await this.reloadGuestAppRuntime({
39990
+ launchArguments: null,
39991
+ initialUrl: null
39992
+ });
39993
+ }
39847
39994
  await this.waitForTree(12e4);
39848
39995
  await this.waitForTree(3e4);
39849
39996
  }
@@ -39853,13 +40000,11 @@ var init_bridge_flow_runner = __esm({
39853
40000
  launchArguments: hasLaunchArguments ? launchArguments : null,
39854
40001
  initialUrl: null
39855
40002
  });
39856
- } else if (hasLaunchArguments || this.launchArgumentsActive || this.appStopped) {
40003
+ } else if (hasLaunchArguments || this.appStopped || !wantsForeground) {
39857
40004
  await this.reloadGuestAppRuntime({
39858
40005
  launchArguments: hasLaunchArguments ? launchArguments : null,
39859
40006
  initialUrl: null
39860
40007
  });
39861
- } else {
39862
- await this.reloadGuestApp();
39863
40008
  }
39864
40009
  await this.waitForTree(12e4);
39865
40010
  if (this.opts.onAfterLaunch) {
@@ -39873,7 +40018,6 @@ var init_bridge_flow_runner = __esm({
39873
40018
  }
39874
40019
  }
39875
40020
  this.appStopped = false;
39876
- this.launchArgumentsActive = hasLaunchArguments;
39877
40021
  if (this.profilingEnabled) {
39878
40022
  await this.startProfile();
39879
40023
  }
@@ -40085,7 +40229,6 @@ var init_bridge_flow_runner = __esm({
40085
40229
  throw new Error(`openLink failed: ${result?.error || "no test bridge"}`);
40086
40230
  }
40087
40231
  this.appStopped = false;
40088
- this.launchArgumentsActive = false;
40089
40232
  this.firstLaunchDone = true;
40090
40233
  }
40091
40234
  // evaluate a `when:` predicate. returns true if the step should run.