peachsim 0.1.939 → 0.1.1399

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 (396) hide show
  1. package/README.md +28 -22
  2. package/cli/app-catalog.ts +29 -14
  3. package/cli/app-fonts.ts +5 -3
  4. package/cli/bridge-flow-runner.ts +40 -29
  5. package/cli/cloud-client.ts +57 -21
  6. package/cli/cloud-test-tunnel.ts +12 -18
  7. package/cli/commands/agent.ts +1 -1
  8. package/cli/commands/app-fonts.ts +3 -3
  9. package/cli/commands/assert.ts +8 -8
  10. package/cli/commands/auth.ts +8 -3
  11. package/cli/commands/box/bundle-plane.ts +13 -1
  12. package/cli/commands/box.ts +16 -5
  13. package/cli/commands/compat.ts +1 -1
  14. package/cli/commands/config.ts +2 -2
  15. package/cli/commands/control.ts +125 -71
  16. package/cli/commands/cpu-profile.ts +45 -1
  17. package/cli/commands/daemon.ts +131 -33
  18. package/cli/commands/debug.ts +24 -17
  19. package/cli/commands/desktop.ts +7 -1
  20. package/cli/commands/detect.ts +101 -0
  21. package/cli/commands/detox.ts +6 -6
  22. package/cli/commands/device.ts +12 -12
  23. package/cli/commands/electron.ts +32 -14
  24. package/cli/commands/flow.ts +49 -41
  25. package/cli/commands/guest-host.ts +39 -1
  26. package/cli/commands/inspect/core.ts +14 -8
  27. package/cli/commands/inspect/list.ts +1 -1
  28. package/cli/commands/inspect/settle.ts +5 -3
  29. package/cli/commands/inspect/settling.ts +229 -44
  30. package/cli/commands/inspect/wait-idle.ts +3 -2
  31. package/cli/commands/inspect.ts +105 -93
  32. package/cli/commands/install-cli.ts +36 -15
  33. package/cli/commands/install-desktop.ts +68 -195
  34. package/cli/commands/kotlin.ts +6 -5
  35. package/cli/commands/login.ts +5 -5
  36. package/cli/commands/maestro-compare.ts +554 -0
  37. package/cli/commands/maestro-generate.ts +6 -3
  38. package/cli/commands/maestro.ts +22 -0
  39. package/cli/commands/mode.ts +2 -2
  40. package/cli/commands/no-bridge-hint.ts +6 -2
  41. package/cli/commands/platform.ts +35 -6
  42. package/cli/commands/preview.ts +6 -0
  43. package/cli/commands/project-report.ts +10 -12
  44. package/cli/commands/record.ts +37 -37
  45. package/cli/commands/runtime.ts +9 -9
  46. package/cli/commands/screenshot-layers.ts +4 -4
  47. package/cli/commands/screenshot-mode.ts +2 -2
  48. package/cli/commands/screenshot.ts +8 -8
  49. package/cli/commands/screenshots-capture.ts +2 -2
  50. package/cli/commands/serve.ts +9 -12
  51. package/cli/commands/setup.ts +29 -14
  52. package/cli/commands/shell-boolean-mode.ts +2 -2
  53. package/cli/commands/show-touches-mode.ts +2 -2
  54. package/cli/commands/skills.ts +11 -11
  55. package/cli/commands/swift.ts +29 -11
  56. package/cli/commands/telemetry.ts +2 -2
  57. package/cli/commands/test.ts +5 -0
  58. package/cli/commands/three-mode.ts +3 -3
  59. package/cli/commands/timeline.ts +4 -4
  60. package/cli/commands/upgrade.ts +2 -2
  61. package/cli/commands/upload.ts +15 -15
  62. package/cli/commands/what-happened.ts +2 -2
  63. package/cli/current-sim.ts +6 -3
  64. package/cli/desktop-companion.ts +55 -149
  65. package/cli/dev-build-freshness.ts +2 -2
  66. package/cli/drivers/desktop.ts +17 -9
  67. package/cli/drivers/electron.ts +1 -2
  68. package/cli/drivers/playwright-sim-host.ts +11 -2
  69. package/cli/drivers/playwright.ts +35 -2
  70. package/cli/drivers/types.ts +8 -0
  71. package/cli/maestro-compare.ts +670 -0
  72. package/cli/outbound-endpoints.ts +46 -8
  73. package/cli/recording-access.ts +6 -6
  74. package/cli/run-registry.ts +1 -1
  75. package/cli/runtime-compat.ts +5 -1
  76. package/cli/send-to-box.ts +3 -3
  77. package/cli/shell-init.ts +2 -1
  78. package/cli/ws-bridge.ts +9 -5
  79. package/detox/element-types.ts +1 -0
  80. package/detox/gestures.ts +3 -3
  81. package/detox/index.ts +67 -38
  82. package/detox/navigation-lifecycle.ts +9 -6
  83. package/detox/proof-frame.cjs +6 -4
  84. package/dist-lib/agent-daemon-client.cjs +1 -1
  85. package/dist-lib/agent-events.cjs +1 -1
  86. package/dist-lib/attached-projects.cjs +1 -1
  87. package/dist-lib/auth/shared-session.cjs +1 -1
  88. package/dist-lib/backend-origin.cjs +1 -1
  89. package/dist-lib/beta.cjs +1 -1
  90. package/dist-lib/beta.mjs +1 -1
  91. package/dist-lib/bridge-constants.cjs +1 -1
  92. package/dist-lib/bridge-contract-input.cjs +42 -17
  93. package/dist-lib/bridge-contract-input.mjs +41 -16
  94. package/dist-lib/bridge-contract.cjs +1 -4
  95. package/dist-lib/bridge-contract.mjs +1 -3
  96. package/dist-lib/bundle-channel.cjs +2918 -550
  97. package/dist-lib/capture-contract.cjs +65 -24
  98. package/dist-lib/capture-contract.mjs +63 -24
  99. package/dist-lib/cloud-contract.cjs +2 -2
  100. package/dist-lib/cloud-contract.mjs +2 -2
  101. package/dist-lib/cloud-test-args.cjs +1 -1
  102. package/dist-lib/cloud-test-args.mjs +1 -1
  103. package/dist-lib/cloud.cjs +3 -3
  104. package/dist-lib/cloud.mjs +3 -3
  105. package/dist-lib/config.cjs +15 -5
  106. package/dist-lib/config.mjs +154 -0
  107. package/dist-lib/detox/index.cjs +495 -139
  108. package/dist-lib/dev-bundle-resolution.cjs +1 -1
  109. package/dist-lib/expo-swift-bundle.cjs +1168 -238
  110. package/dist-lib/expo-swift-metadata.cjs +34 -23
  111. package/dist-lib/expo-swift-metadata.mjs +32 -23
  112. package/dist-lib/home-paths.cjs +2 -2
  113. package/dist-lib/host/bridge-host.cjs +2938 -654
  114. package/dist-lib/host/fetch-proxy-handler.cjs +14 -1
  115. package/dist-lib/host/fetch-proxy-overrides.cjs +7 -1
  116. package/dist-lib/host/fetch-proxy-overrides.mjs +5 -1
  117. package/dist-lib/host/replacement-module-handler.cjs +2 -2
  118. package/dist-lib/host/websocket-proxy.cjs +1 -1
  119. package/dist-lib/index.cjs +999 -353
  120. package/dist-lib/jump-to-source-babel.cjs +1 -1
  121. package/dist-lib/jump-to-source-native.cjs +1 -1
  122. package/dist-lib/kotlin-host.cjs +332 -19
  123. package/dist-lib/menu.cjs +1 -1
  124. package/dist-lib/menu.mjs +1 -1
  125. package/dist-lib/metro-fingerprint-registry.cjs +1 -1
  126. package/dist-lib/metro-fingerprint-registry.mjs +1 -1
  127. package/dist-lib/metro-production-bundle.cjs +7 -7
  128. package/dist-lib/metro-production-bundle.mjs +5 -5
  129. package/dist-lib/metro.cjs +688 -250
  130. package/dist-lib/native-app-identity-project.cjs +2647 -0
  131. package/dist-lib/native-app-identity-project.mjs +1257 -0
  132. package/dist-lib/native-app-identity.cjs +325 -25
  133. package/dist-lib/native-app-identity.mjs +323 -25
  134. package/dist-lib/native-firebase-metadata.cjs +1 -1
  135. package/dist-lib/native-firebase-metadata.mjs +1 -1
  136. package/dist-lib/plist.cjs +1 -1
  137. package/dist-lib/plist.mjs +1 -1
  138. package/dist-lib/profiles.cjs +1 -1
  139. package/dist-lib/public-brand.cjs +1 -1
  140. package/dist-lib/react-native-host-modules.cjs +5 -1
  141. package/dist-lib/react-native-host-modules.mjs +5 -1
  142. package/dist-lib/scripts/dev-server-scanner.cjs +57 -32
  143. package/dist-lib/sdk.cjs +231 -51
  144. package/dist-lib/sdk.mjs +231 -51
  145. package/dist-lib/skills.cjs +4107 -1374
  146. package/dist-lib/swift-compile.cjs +290 -30
  147. package/dist-lib/swift-compile.mjs +290 -30
  148. package/dist-lib/swift-package.cjs +143 -12
  149. package/dist-lib/swift-package.mjs +137 -11
  150. package/dist-lib/swift-submit.cjs +47 -5
  151. package/dist-lib/swift-submit.mjs +42 -5
  152. package/dist-lib/swift-toolchain.cjs +7 -2
  153. package/dist-lib/swift.cjs +1 -1
  154. package/dist-lib/vite-swift.cjs +1392 -458
  155. package/dist-lib/vite.cjs +13 -17
  156. package/dist-lib/worklet-executable.cjs +248 -33
  157. package/dist-lib/worklet-executable.mjs +248 -33
  158. package/install.sh +10 -1
  159. package/kotlin/{AppSources → AndroidViewSources}/android/content/res/Resources.kt +9 -9
  160. package/kotlin/AndroidViewSources/android/graphics/Canvas.kt +20 -0
  161. package/kotlin/AndroidViewSources/android/view/View.kt +211 -0
  162. package/kotlin/AndroidViewSources/android/widget/FrameLayout.kt +61 -0
  163. package/kotlin/AndroidViewSources/android/widget/LinearLayout.kt +49 -0
  164. package/kotlin/AppSources/android/view/Window.kt +36 -0
  165. package/kotlin/AppSources/android/view/WindowInsets.kt +9 -0
  166. package/kotlin/AppSources/android/view/WindowInsetsController.kt +5 -0
  167. package/kotlin/AppSources/android/window/OnBackInvokedDispatcher.kt +48 -0
  168. package/kotlin/AppSources/androidx/activity/OnBackPressedDispatcher.kt +20 -5
  169. package/kotlin/AppSources/androidx/compose/foundation/layout/WindowInsets.kt +15 -0
  170. package/kotlin/AppSources/androidx/compose/ui/platform/ComposeView.kt +2 -1
  171. package/kotlin/AppSources/dev/peach/app/PeachApp.kt +42 -50
  172. package/kotlin/ComposeSources/PeachComposeHost.kt +200 -84
  173. package/kotlin/ExpoComposeSources/PeachAndroidView.kt +87 -0
  174. package/kotlin/ExpoComposeSources/PeachExpoViewMount.kt +24 -0
  175. package/kotlin/ExpoComposeSources/dev/peach/expo/PeachExpoCompose.kt +28 -0
  176. package/kotlin/ExpoComposeSources/expo/modules/kotlin/views/ExpoComposeView.kt +70 -0
  177. package/kotlin/ExpoSources/dev/peach/expo/PeachExpoRuntime.kt +513 -0
  178. package/kotlin/ExpoSources/dev/peach/expo/PeachExpoTypes.kt +173 -0
  179. package/kotlin/ExpoSources/expo/modules/kotlin/AppContext.kt +20 -0
  180. package/kotlin/ExpoSources/expo/modules/kotlin/Promise.kt +19 -0
  181. package/kotlin/ExpoSources/expo/modules/kotlin/classcomponent/ClassComponentBuilder.kt +198 -0
  182. package/kotlin/ExpoSources/expo/modules/kotlin/exception/CodedException.kt +126 -0
  183. package/kotlin/ExpoSources/expo/modules/kotlin/functions/Functions.kt +132 -0
  184. package/kotlin/ExpoSources/expo/modules/kotlin/jni/JavaScriptTypedArray.kt +81 -0
  185. package/kotlin/ExpoSources/expo/modules/kotlin/modules/Module.kt +98 -0
  186. package/kotlin/ExpoSources/expo/modules/kotlin/objects/ObjectDefinitionBuilder.kt +236 -0
  187. package/kotlin/ExpoSources/expo/modules/kotlin/records/Record.kt +12 -0
  188. package/kotlin/ExpoSources/expo/modules/kotlin/runtime/Runtime.kt +9 -0
  189. package/kotlin/ExpoSources/expo/modules/kotlin/sharedobjects/SharedObject.kt +50 -0
  190. package/kotlin/ExpoSources/expo/modules/kotlin/sharedobjects/SharedObjectRegistry.kt +57 -0
  191. package/kotlin/ExpoSources/expo/modules/kotlin/sharedobjects/SharedRef.kt +19 -0
  192. package/kotlin/ExpoSources/expo/modules/kotlin/typedarray/ConcreteTypedArrays.kt +158 -0
  193. package/kotlin/ExpoSources/expo/modules/kotlin/typedarray/GenericTypedArray.kt +8 -0
  194. package/kotlin/ExpoSources/expo/modules/kotlin/typedarray/TypedArray.kt +29 -0
  195. package/kotlin/ExpoSources/expo/modules/kotlin/typedarray/TypedArrayIterator.kt +9 -0
  196. package/kotlin/ExpoSources/expo/modules/kotlin/types/AnyType.kt +155 -0
  197. package/kotlin/ExpoSources/expo/modules/kotlin/types/Either.kt +91 -0
  198. package/kotlin/ExpoSources/expo/modules/kotlin/types/Enumerable.kt +6 -0
  199. package/kotlin/ExpoSources/expo/modules/kotlin/viewevent/ViewEvent.kt +54 -0
  200. package/kotlin/ExpoSources/expo/modules/kotlin/views/ExpoView.kt +23 -0
  201. package/kotlin/ExpoSources/expo/modules/kotlin/views/ViewDefinitionBuilder.kt +71 -0
  202. package/kotlin/ExpoSources/expo/modules/kotlin/views/ViewProps.kt +35 -0
  203. package/kotlin/README.md +13 -3
  204. package/kotlin/Sources/android/os/Build.kt +17 -0
  205. package/kotlin/Sources/android/os/Handler.kt +35 -0
  206. package/kotlin/Sources/android/os/Looper.kt +17 -0
  207. package/kotlin/Sources/android/os/MessageQueue.kt +56 -0
  208. package/kotlin/Sources/android/os/SystemClock.kt +14 -0
  209. package/kotlin/Sources/android/util/Log.kt +64 -0
  210. package/kotlin/Sources/java/security/MessageDigest.kt +114 -0
  211. package/kotlin/Sources/kotlin/text/StringFormat.kt +9 -0
  212. package/kotlin/Sources/org/json/JSON.kt +44 -0
  213. package/kotlin/fixtures/counter/Counter.d.kt.ts +1 -0
  214. package/kotlin/fixtures/counter/Counter.kt +10 -3
  215. package/kotlin/fixtures/counter/CounterApp.native.tsx +1 -1
  216. package/kotlin/fixtures/counter/vite.config.ts +2 -2
  217. package/kotlin/fixtures/headless-counter/Headless.kt +7 -6
  218. package/kotlin/fixtures/import-animation/Animation.d.kt.ts +7 -0
  219. package/kotlin/fixtures/import-animation/Animation.kt +80 -0
  220. package/kotlin/fixtures/import-animation/ImportAnimation.native.tsx +13 -0
  221. package/kotlin/fixtures/import-animation/README.md +24 -0
  222. package/kotlin/fixtures/import-animation/app/_layout.tsx +4 -0
  223. package/kotlin/fixtures/import-animation/app/index+spa.tsx +1 -0
  224. package/kotlin/fixtures/import-animation/app/routes.d.ts +18 -0
  225. package/kotlin/fixtures/import-animation/package.json +23 -0
  226. package/kotlin/fixtures/import-animation/tsconfig.json +20 -0
  227. package/kotlin/fixtures/import-animation/vite.config.ts +20 -0
  228. package/kotlin/fixtures/import-editor/Editor.d.kt.ts +7 -0
  229. package/kotlin/fixtures/import-editor/Editor.kt +59 -0
  230. package/kotlin/fixtures/import-editor/ImportEditor.native.tsx +23 -0
  231. package/kotlin/fixtures/import-editor/README.md +27 -0
  232. package/kotlin/fixtures/import-editor/app/_layout.tsx +4 -0
  233. package/kotlin/fixtures/import-editor/app/index+spa.tsx +1 -0
  234. package/kotlin/fixtures/import-editor/package.json +23 -0
  235. package/kotlin/fixtures/import-editor/tsconfig.json +20 -0
  236. package/kotlin/fixtures/import-editor/vite.config.ts +20 -0
  237. package/kotlin/fixtures/import-effects/Effects.d.kt.ts +7 -0
  238. package/kotlin/fixtures/import-effects/Effects.kt +87 -0
  239. package/kotlin/fixtures/import-effects/ImportEffects.native.tsx +13 -0
  240. package/kotlin/fixtures/import-effects/README.md +19 -0
  241. package/kotlin/fixtures/import-effects/app/_layout.tsx +4 -0
  242. package/kotlin/fixtures/import-effects/app/index+spa.tsx +1 -0
  243. package/kotlin/fixtures/import-effects/package.json +23 -0
  244. package/kotlin/fixtures/import-effects/tsconfig.json +20 -0
  245. package/kotlin/fixtures/import-effects/vite.config.ts +20 -0
  246. package/kotlin/fixtures/import-layout/ImportLayout.native.tsx +13 -0
  247. package/kotlin/fixtures/import-layout/Layout.d.kt.ts +7 -0
  248. package/kotlin/fixtures/import-layout/Layout.kt +72 -0
  249. package/kotlin/fixtures/import-layout/README.md +24 -0
  250. package/kotlin/fixtures/import-layout/app/_layout.tsx +4 -0
  251. package/kotlin/fixtures/import-layout/app/index+spa.tsx +1 -0
  252. package/kotlin/fixtures/import-layout/package.json +23 -0
  253. package/kotlin/fixtures/import-layout/tsconfig.json +20 -0
  254. package/kotlin/fixtures/import-layout/vite.config.ts +20 -0
  255. package/kotlin/fixtures/import-navigation/ImportNavigation.native.tsx +18 -0
  256. package/kotlin/fixtures/import-navigation/Navigation.d.kt.ts +7 -0
  257. package/kotlin/fixtures/import-navigation/Navigation.kt +104 -0
  258. package/kotlin/fixtures/import-navigation/README.md +31 -0
  259. package/kotlin/fixtures/import-navigation/app/_layout.tsx +4 -0
  260. package/kotlin/fixtures/import-navigation/app/index+spa.tsx +1 -0
  261. package/kotlin/fixtures/import-navigation/package.json +23 -0
  262. package/kotlin/fixtures/import-navigation/tsconfig.json +20 -0
  263. package/kotlin/fixtures/import-navigation/vite.config.ts +20 -0
  264. package/kotlin/fixtures/import-overlays/ImportOverlays.native.tsx +29 -0
  265. package/kotlin/fixtures/import-overlays/Overlays.d.kt.ts +7 -0
  266. package/kotlin/fixtures/import-overlays/Overlays.kt +93 -0
  267. package/kotlin/fixtures/import-overlays/README.md +34 -0
  268. package/kotlin/fixtures/import-overlays/app/_layout.tsx +4 -0
  269. package/kotlin/fixtures/import-overlays/app/index+spa.tsx +1 -0
  270. package/kotlin/fixtures/import-overlays/package.json +23 -0
  271. package/kotlin/fixtures/import-overlays/tsconfig.json +20 -0
  272. package/kotlin/fixtures/import-overlays/vite.config.ts +20 -0
  273. package/kotlin/fixtures/import-scroll/ImportScroll.native.tsx +13 -0
  274. package/kotlin/fixtures/import-scroll/README.md +23 -0
  275. package/kotlin/fixtures/import-scroll/Scroll.d.kt.ts +7 -0
  276. package/kotlin/fixtures/import-scroll/Scroll.kt +91 -0
  277. package/kotlin/fixtures/import-scroll/app/_layout.tsx +4 -0
  278. package/kotlin/fixtures/import-scroll/app/index+spa.tsx +1 -0
  279. package/kotlin/fixtures/import-scroll/package.json +23 -0
  280. package/kotlin/fixtures/import-scroll/tsconfig.json +20 -0
  281. package/kotlin/fixtures/import-scroll/vite.config.ts +20 -0
  282. package/kotlin/fixtures/import-selection/ImportSelection.native.tsx +44 -0
  283. package/kotlin/fixtures/import-selection/README.md +32 -0
  284. package/kotlin/fixtures/import-selection/Selection.d.kt.ts +8 -0
  285. package/kotlin/fixtures/import-selection/Selection.kt +78 -0
  286. package/kotlin/fixtures/import-selection/app/_layout.tsx +4 -0
  287. package/kotlin/fixtures/import-selection/app/index+spa.tsx +1 -0
  288. package/kotlin/fixtures/import-selection/package.json +23 -0
  289. package/kotlin/fixtures/import-selection/tsconfig.json +20 -0
  290. package/kotlin/fixtures/import-selection/vite.config.ts +20 -0
  291. package/kotlin/fixtures/import-surfaces/ImportSurfaces.native.tsx +13 -0
  292. package/kotlin/fixtures/import-surfaces/README.md +22 -0
  293. package/kotlin/fixtures/import-surfaces/Surfaces.d.kt.ts +7 -0
  294. package/kotlin/fixtures/import-surfaces/Surfaces.kt +64 -0
  295. package/kotlin/fixtures/import-surfaces/app/_layout.tsx +4 -0
  296. package/kotlin/fixtures/import-surfaces/app/index+spa.tsx +1 -0
  297. package/kotlin/fixtures/import-surfaces/package.json +23 -0
  298. package/kotlin/fixtures/import-surfaces/tsconfig.json +20 -0
  299. package/kotlin/fixtures/import-surfaces/vite.config.ts +20 -0
  300. package/kotlin/fixtures/import-values/ImportValues.native.tsx +35 -0
  301. package/kotlin/fixtures/import-values/README.md +23 -0
  302. package/kotlin/fixtures/import-values/Values.d.kt.ts +11 -0
  303. package/kotlin/fixtures/import-values/Values.kt +66 -0
  304. package/kotlin/fixtures/import-values/app/_layout.tsx +4 -0
  305. package/kotlin/fixtures/import-values/app/index+spa.tsx +1 -0
  306. package/kotlin/fixtures/import-values/package.json +23 -0
  307. package/kotlin/fixtures/import-values/tsconfig.json +20 -0
  308. package/kotlin/fixtures/import-values/vite.config.ts +20 -0
  309. package/kotlin/fixtures/kotlin-app-variants/BarBehavior.kt +38 -0
  310. package/kotlin/fixtures/kotlin-app-variants/BarVisibility.kt +36 -0
  311. package/kotlin/fixtures/kotlin-app-variants/Ime.kt +3 -1
  312. package/kotlin/fixtures/kotlin-app-variants/TransientInsets.kt +50 -0
  313. package/kotlin/fork/NOTICE +6 -1
  314. package/kotlin/fork/README.md +15 -7
  315. package/kotlin/fork/build.sh +2 -0
  316. package/kotlin/fork/compose-worker-globals.patch +186 -4
  317. package/kotlin/fork/fork.json +2 -2
  318. package/kotlin/fork/skiko-worker-clock.patch +12 -0
  319. package/kotlin/toolchain.json +12 -12
  320. package/kotlin/tools/expo-types.main.kts +115 -0
  321. package/package.json +17 -23
  322. package/scripts/dev-server-scanner.ts +92 -66
  323. package/skills/contrast/SKILL.md +2 -2
  324. package/skills/peach-debug/SKILL.md +1 -1
  325. package/skills/peach-perf/SKILL.md +1 -1
  326. package/skills/peach-setup/SKILL.md +2 -1
  327. package/skills/peach-test/SKILL.md +8 -0
  328. package/src/assetCatalogContract.ts +43 -1
  329. package/src/bridge-contract-input.ts +46 -19
  330. package/src/bridge-contract.ts +0 -1
  331. package/src/bundle-channel.mjs +197 -84
  332. package/src/bundleGlobalFooter.ts +38 -0
  333. package/src/capture-contract.ts +107 -33
  334. package/src/cloud-contract.ts +5 -1
  335. package/src/cloud.ts +5 -2
  336. package/src/config.ts +22 -3
  337. package/src/configured-bundle-producer.ts +1 -1
  338. package/src/desktop-host-delivery.ts +95 -1
  339. package/src/expo-kotlin-bundle.ts +29 -0
  340. package/src/expo-kotlin-host.ts +201 -0
  341. package/src/expo-swift-host.ts +96 -76
  342. package/src/expoKotlinContract.ts +70 -0
  343. package/src/expoSwiftContract.ts +4 -25
  344. package/src/home-paths.ts +7 -4
  345. package/src/host/bridge-host.ts +23 -3
  346. package/src/host/fetch-proxy-handler.ts +13 -0
  347. package/src/host/fetch-proxy-overrides.ts +11 -0
  348. package/src/host/replacement-module-handler.ts +5 -2
  349. package/src/index.ts +3 -1
  350. package/src/kotlin-host.ts +463 -19
  351. package/src/metro-plugin.ts +56 -28
  352. package/src/metro-production-bundle.ts +2 -2
  353. package/src/native-app-identity-project.ts +190 -0
  354. package/src/native-app-identity.ts +398 -34
  355. package/src/native-firebase-config.ts +69 -15
  356. package/src/native-seam-manifest.ts +6 -0
  357. package/src/one-widget-discovery.ts +2 -1
  358. package/src/openstep-plist.ts +107 -0
  359. package/src/react-native-host-modules.ts +4 -0
  360. package/src/runtime-assets.ts +2 -2
  361. package/src/sim-client.ts +2 -2
  362. package/src/swift-binary-modules.ts +3 -1
  363. package/src/swift-compile.ts +286 -38
  364. package/src/swift-distribution-contract.ts +4 -0
  365. package/src/swift-distribution.lock.json +123 -12
  366. package/src/swift-distribution.ts +7 -3
  367. package/src/swift-host.ts +298 -83
  368. package/src/swift-package-manifest.ts +29 -2
  369. package/src/swift-package.ts +180 -10
  370. package/src/swift-packages.ts +4 -0
  371. package/src/swift-standin-emit.ts +4 -1
  372. package/src/swift-standins.ts +274 -15
  373. package/src/swift-submit.ts +62 -7
  374. package/src/swift-toolchain.ts +6 -1
  375. package/src/swiftContract.ts +126 -3
  376. package/src/vite-plugin-one.ts +13 -16
  377. package/src/vite-plugin-swift.ts +4 -5
  378. package/src/vite-plugin.ts +360 -144
  379. package/src/vite.d.ts +1 -1
  380. package/src/worker-system-chunks.ts +221 -0
  381. package/src/worklet-executable.ts +348 -38
  382. package/src/worklets-babel.ts +1 -1
  383. package/src/xcode-project.ts +243 -127
  384. package/dist-lib/agent-identity.cjs +0 -39
  385. package/dist-lib/agent-sessions.cjs +0 -760
  386. package/dist-lib/cli-constants.cjs +0 -32
  387. package/dist-lib/render-mode.cjs +0 -44
  388. package/kotlin/AppSources/android/view/View.kt +0 -74
  389. package/kotlin/AppSources/android/widget/FrameLayout.kt +0 -6
  390. package/src/render-mode.ts +0 -15
  391. /package/kotlin/{AppSources → AndroidViewSources}/android/content/Context.kt +0 -0
  392. /package/kotlin/{AppSources → AndroidViewSources}/android/content/res/Configuration.kt +0 -0
  393. /package/kotlin/{AppSources → AndroidViewSources}/android/graphics/Color.kt +0 -0
  394. /package/kotlin/{AppSources → AndroidViewSources}/android/util/DisplayMetrics.kt +0 -0
  395. /package/kotlin/{AppSources → AndroidViewSources}/dev/peach/app/JavaFormat.kt +0 -0
  396. /package/kotlin/{AppSources → Sources}/java/lang/Runnable.kt +0 -0
@@ -3,15 +3,29 @@
3
3
  // against the Xcode Release build settings, or `android/app/build.gradle`), so
4
4
  // a simulator tenant reports the same identity the native Release build does.
5
5
  //
6
- // the values travel in a bundle footer or a response header bound to unchanged
7
- // artifact bytes. tenant boot validates both before evaluation and clears the
8
- // realm store when neither carries identity.
6
+ // identity travels in a bundle footer or response header. the one updates
7
+ // receipt travels only in the response header so publisher JavaScript stays
8
+ // unchanged. tenant boot validates both before evaluation and clears the realm
9
+ // store when neither carries identity.
10
+
11
+ import { parseOpenStepPlist } from './openstep-plist'
9
12
 
10
13
  export type NativeAppIdentityPlatform = 'ios' | 'android'
11
14
 
15
+ export interface NativeOneUpdatesReceipt {
16
+ enabled: boolean
17
+ url: string | null
18
+ runtimeVersion: string | null
19
+ embeddedManifestJson: string | null
20
+ }
21
+
12
22
  export interface NativeAppIdentity {
13
23
  // the user-facing name (CFBundleDisplayName, else CFBundleName).
14
24
  applicationName: string | null
25
+ // the literal CFBundleDisplayName, without a bundle-name fallback.
26
+ applicationDisplayName?: string
27
+ // the processed ARGB integer from RCTRootViewBackgroundColor.
28
+ rootViewBackgroundColor?: number
15
29
  // CFBundleName, which CFNetwork stamps into the default User-Agent and iOS's
16
30
  // own prompts use (the ASWebAuthenticationSession consent alert); distinct
17
31
  // from the display name. absent in footers built before it was carried.
@@ -23,6 +37,16 @@ export interface NativeAppIdentity {
23
37
  permissionUsageDescriptions?: Readonly<Record<string, unknown>>
24
38
  urlQuerySchemes?: readonly unknown[]
25
39
  appIntentIdentifiers?: readonly string[]
40
+ backgroundTaskIdentifiers?: readonly string[]
41
+ backgroundModes?: readonly string[]
42
+ supportedInterfaceOrientations?: readonly string[]
43
+ ipadSupportedInterfaceOrientations?: readonly string[]
44
+ defaultScreenOrientationMask?: string
45
+ shareIntoAppGroupId?: string
46
+ alternateIconNames?: readonly string[]
47
+ // one updates configuration travels only in response metadata, never in guest
48
+ // code or inferred from JavaScript build flags.
49
+ oneUpdates?: NativeOneUpdatesReceipt
26
50
  }
27
51
 
28
52
  export type NativeAppIdentityFiles = Record<string, string>
@@ -46,6 +70,24 @@ function nonEmptyString(value: unknown): string | null {
46
70
 
47
71
  export function isNativeAppIdentity(value: unknown): value is NativeAppIdentity {
48
72
  if (!isRecord(value)) return false
73
+ const oneUpdates = value.oneUpdates
74
+ if (
75
+ oneUpdates !== undefined &&
76
+ (!isRecord(oneUpdates) ||
77
+ typeof oneUpdates.enabled !== 'boolean' ||
78
+ (oneUpdates.url !== null && typeof oneUpdates.url !== 'string') ||
79
+ (oneUpdates.runtimeVersion !== null &&
80
+ typeof oneUpdates.runtimeVersion !== 'string') ||
81
+ (oneUpdates.embeddedManifestJson !== null &&
82
+ typeof oneUpdates.embeddedManifestJson !== 'string') ||
83
+ (oneUpdates.enabled &&
84
+ (typeof oneUpdates.url !== 'string' ||
85
+ oneUpdates.url.length === 0 ||
86
+ typeof oneUpdates.runtimeVersion !== 'string' ||
87
+ oneUpdates.runtimeVersion.length === 0)))
88
+ ) {
89
+ return false
90
+ }
49
91
  const descriptions = value.permissionUsageDescriptions
50
92
  if (descriptions !== undefined && !isRecord(descriptions)) return false
51
93
  if (value.urlQuerySchemes !== undefined && !Array.isArray(value.urlQuerySchemes))
@@ -56,7 +98,59 @@ export function isNativeAppIdentity(value: unknown): value is NativeAppIdentity
56
98
  !value.appIntentIdentifiers.every((identifier) => typeof identifier === 'string'))
57
99
  )
58
100
  return false
101
+ if (
102
+ value.backgroundTaskIdentifiers !== undefined &&
103
+ (!Array.isArray(value.backgroundTaskIdentifiers) ||
104
+ !value.backgroundTaskIdentifiers.every(
105
+ (identifier) => typeof identifier === 'string',
106
+ ))
107
+ )
108
+ return false
109
+ if (
110
+ value.backgroundModes !== undefined &&
111
+ (!Array.isArray(value.backgroundModes) ||
112
+ !value.backgroundModes.every((mode) => typeof mode === 'string'))
113
+ )
114
+ return false
115
+ if (
116
+ value.shareIntoAppGroupId !== undefined &&
117
+ typeof value.shareIntoAppGroupId !== 'string'
118
+ )
119
+ return false
120
+ if (
121
+ value.applicationDisplayName !== undefined &&
122
+ typeof value.applicationDisplayName !== 'string'
123
+ )
124
+ return false
125
+ if (
126
+ value.rootViewBackgroundColor !== undefined &&
127
+ (typeof value.rootViewBackgroundColor !== 'number' ||
128
+ !Number.isInteger(value.rootViewBackgroundColor))
129
+ )
130
+ return false
131
+ for (const orientations of [
132
+ value.supportedInterfaceOrientations,
133
+ value.ipadSupportedInterfaceOrientations,
134
+ ]) {
135
+ if (
136
+ orientations !== undefined &&
137
+ (!Array.isArray(orientations) ||
138
+ !orientations.every((orientation) => typeof orientation === 'string'))
139
+ )
140
+ return false
141
+ }
142
+ if (
143
+ value.defaultScreenOrientationMask !== undefined &&
144
+ typeof value.defaultScreenOrientationMask !== 'string'
145
+ )
146
+ return false
59
147
  const platform = value.platform
148
+ if (
149
+ value.alternateIconNames !== undefined &&
150
+ (!Array.isArray(value.alternateIconNames) ||
151
+ !value.alternateIconNames.every((name) => typeof name === 'string'))
152
+ )
153
+ return false
60
154
  if (platform !== 'ios' && platform !== 'android') return false
61
155
  const applicationName = value.applicationName
62
156
  if (applicationName !== null && nonEmptyString(applicationName) === null) return false
@@ -79,11 +173,20 @@ export function readNativeAppIdentity(value: unknown): NativeAppIdentity | null
79
173
  }
80
174
  return {
81
175
  applicationName: value.applicationName,
176
+ ...(value.applicationDisplayName === undefined
177
+ ? {}
178
+ : { applicationDisplayName: value.applicationDisplayName }),
179
+ ...(value.rootViewBackgroundColor === undefined
180
+ ? {}
181
+ : { rootViewBackgroundColor: value.rootViewBackgroundColor }),
82
182
  ...(value.bundleName === undefined ? {} : { bundleName: value.bundleName }),
83
183
  appVersion: value.appVersion,
84
184
  buildVersion: value.buildVersion,
85
185
  bundleIdentifier: value.bundleIdentifier,
86
186
  platform: value.platform,
187
+ ...(value.alternateIconNames === undefined
188
+ ? {}
189
+ : { alternateIconNames: [...value.alternateIconNames] }),
87
190
  ...(value.permissionUsageDescriptions === undefined
88
191
  ? {}
89
192
  : {
@@ -92,9 +195,43 @@ export function readNativeAppIdentity(value: unknown): NativeAppIdentity | null
92
195
  ...(value.appIntentIdentifiers === undefined
93
196
  ? {}
94
197
  : { appIntentIdentifiers: [...value.appIntentIdentifiers] }),
198
+ ...(value.backgroundTaskIdentifiers === undefined
199
+ ? {}
200
+ : { backgroundTaskIdentifiers: [...value.backgroundTaskIdentifiers] }),
201
+ ...(value.supportedInterfaceOrientations === undefined
202
+ ? {}
203
+ : {
204
+ supportedInterfaceOrientations: [...value.supportedInterfaceOrientations],
205
+ }),
206
+ ...(value.ipadSupportedInterfaceOrientations === undefined
207
+ ? {}
208
+ : {
209
+ ipadSupportedInterfaceOrientations: [
210
+ ...value.ipadSupportedInterfaceOrientations,
211
+ ],
212
+ }),
213
+ ...(value.defaultScreenOrientationMask === undefined
214
+ ? {}
215
+ : { defaultScreenOrientationMask: value.defaultScreenOrientationMask }),
216
+ ...(value.backgroundModes === undefined
217
+ ? {}
218
+ : { backgroundModes: [...value.backgroundModes] }),
219
+ ...(value.shareIntoAppGroupId === undefined
220
+ ? {}
221
+ : { shareIntoAppGroupId: value.shareIntoAppGroupId }),
95
222
  ...(value.urlQuerySchemes === undefined
96
223
  ? {}
97
224
  : { urlQuerySchemes: [...value.urlQuerySchemes] }),
225
+ ...(value.oneUpdates === undefined
226
+ ? {}
227
+ : {
228
+ oneUpdates: {
229
+ enabled: value.oneUpdates.enabled,
230
+ url: value.oneUpdates.url,
231
+ runtimeVersion: value.oneUpdates.runtimeVersion,
232
+ embeddedManifestJson: value.oneUpdates.embeddedManifestJson,
233
+ },
234
+ }),
98
235
  }
99
236
  }
100
237
 
@@ -135,7 +272,10 @@ export function readNativeAppIdentityFromBundle(
135
272
  }
136
273
  const identity = readNativeAppIdentity(value)
137
274
  if (!identity) throw new Error('native app identity response header is malformed')
138
- if (footer && !equalIdentityValues(identity, readNativeAppIdentity(footer))) {
275
+ const footerIdentity = footer ? readNativeAppIdentity(footer) : null
276
+ const headerBase = { ...identity, oneUpdates: undefined }
277
+ const footerBase = footerIdentity && { ...footerIdentity, oneUpdates: undefined }
278
+ if (footerIdentity && !equalIdentityValues(headerBase, footerBase)) {
139
279
  throw new Error('native app identity response header conflicts with bundle footer')
140
280
  }
141
281
  return identity
@@ -158,7 +298,10 @@ export function getAppliedNativeAppIdentity(): NativeAppIdentity | null {
158
298
  // one line, so the footer survives a bundle whose last statement is the Metro
159
299
  // module identity footer and can be found again by reading the text.
160
300
  export function createNativeAppIdentityFooter(identity: NativeAppIdentity): string {
161
- const payload = JSON.stringify(identity)
301
+ const footerIdentity = { ...identity }
302
+ // native update configuration belongs to response metadata, never guest code.
303
+ delete footerIdentity.oneUpdates
304
+ const payload = JSON.stringify(footerIdentity)
162
305
  .replace(/\u2028/g, '\\u2028')
163
306
  .replace(/\u2029/g, '\\u2029')
164
307
  .replace(/<\//g, '<\\/')
@@ -186,6 +329,9 @@ export function readNativeAppIdentityFooter(source: string): NativeAppIdentity |
186
329
  if (!isNativeAppIdentity(parsed)) {
187
330
  throw new Error('native app identity footer is malformed')
188
331
  }
332
+ if (parsed.oneUpdates !== undefined) {
333
+ throw new Error('native app identity footer cannot contain one updates receipt')
334
+ }
189
335
  return parsed
190
336
  }
191
337
 
@@ -362,39 +508,162 @@ function appTargetReleaseSettings(
362
508
  function nativeAppIdentityFromIos(
363
509
  files: NativeAppIdentityFiles,
364
510
  parseInfoPlist: (source: string) => unknown,
511
+ iosTarget?: string,
365
512
  ): NativeAppIdentity | null {
366
- const pbxprojPath = Object.keys(files).find((path) =>
367
- /(?:^|\/)ios\/[^/]+\.xcodeproj\/project\.pbxproj$/.test(path),
368
- )
513
+ const pbxprojPath =
514
+ Object.keys(files).find((path) =>
515
+ /(?:^|\/)ios\/[^/]+\.xcodeproj\/project\.pbxproj$/.test(path),
516
+ ) ??
517
+ Object.keys(files).find((path) =>
518
+ /(?:^|\/)[^/]+\.xcodeproj\/project\.pbxproj$/.test(path),
519
+ ) ??
520
+ Object.keys(files).find((path) => /(?:^|\/)project\.pbxproj$/.test(path))
369
521
  if (!pbxprojPath) return null
370
522
  const pbxproj = files[pbxprojPath]
371
- // the installed app is the target Xcode builds as an application. an App
372
- // Clip or extension carries its own AppDelegate and Info.plist, so a target
373
- // directory alone cannot say which binary is the app.
374
- const applicationTargets = new Set(
375
- [
376
- ...pbxproj.matchAll(
377
- /isa = PBXNativeTarget;[^}]*?name = "?([^";]+)"?;[^}]*?productType = "com\.apple\.product-type\.application";/g,
378
- ),
379
- ].map((match) => match[1]),
523
+
524
+ let objects: Record<string, unknown> = {}
525
+ try {
526
+ const parsed = parseOpenStepPlist(pbxproj)
527
+ if (isRecord(parsed)) {
528
+ objects = isRecord(parsed.objects) ? parsed.objects : parsed
529
+ }
530
+ } catch {
531
+ // fallback if unparseable
532
+ }
533
+
534
+ interface NativeTargetSummary {
535
+ id: string
536
+ name: string
537
+ productType?: string
538
+ buildConfigurationList?: string
539
+ }
540
+ const targets: NativeTargetSummary[] = []
541
+ for (const [id, obj] of Object.entries(objects)) {
542
+ if (isRecord(obj) && obj.isa === 'PBXNativeTarget' && typeof obj.name === 'string') {
543
+ targets.push({
544
+ id,
545
+ name: obj.name,
546
+ productType: typeof obj.productType === 'string' ? obj.productType : undefined,
547
+ buildConfigurationList:
548
+ typeof obj.buildConfigurationList === 'string'
549
+ ? obj.buildConfigurationList
550
+ : undefined,
551
+ })
552
+ }
553
+ }
554
+ const applicationTargetNames = new Set(
555
+ targets
556
+ .filter((t) => t.productType === 'com.apple.product-type.application')
557
+ .map((t) => t.name),
380
558
  )
381
- const appDelegatePattern = /(?:^|\/)ios\/([^/]+)\/AppDelegate\.(?:swift|mm|m)$/
382
- const targetName =
383
- Object.keys(files)
559
+ if (applicationTargetNames.size === 0) {
560
+ for (const match of pbxproj.matchAll(
561
+ /isa = PBXNativeTarget;[^}]*?name = "?([^";]+)"?;[^}]*?productType = "com\.apple\.product-type\.application";/g,
562
+ )) {
563
+ applicationTargetNames.add(match[1])
564
+ }
565
+ }
566
+
567
+ let targetName: string | null = null
568
+ if (iosTarget) {
569
+ if (applicationTargetNames.has(iosTarget)) {
570
+ targetName = iosTarget
571
+ } else {
572
+ return null
573
+ }
574
+ } else if (applicationTargetNames.size === 1) {
575
+ targetName = [...applicationTargetNames][0]!
576
+ } else if (applicationTargetNames.size > 1) {
577
+ const appDelegatePattern = /(?:^|\/)ios\/([^/]+)\/AppDelegate\.(?:swift|mm|m)$/
578
+ const delegateTargets = Object.keys(files)
384
579
  .filter((path) => !path.includes('/Pods/'))
385
580
  .map((path) => path.match(appDelegatePattern)?.[1])
386
- .find((name) => name !== undefined && applicationTargets.has(name)) ?? null
387
- if (!targetName) return null
581
+ .filter(
582
+ (name): name is string =>
583
+ typeof name === 'string' && applicationTargetNames.has(name),
584
+ )
585
+ if (delegateTargets.length === 1) {
586
+ targetName = delegateTargets[0]!
587
+ } else {
588
+ return null
589
+ }
590
+ } else {
591
+ return null
592
+ }
388
593
 
389
- const plist = files[`ios/${targetName}/Info.plist`]
390
- if (!plist) return null
594
+ const selectedTarget = targets.find((t) => t.name === targetName)
595
+ const settings: Record<string, string> = {
596
+ TARGET_NAME: targetName,
597
+ PRODUCT_NAME: targetName,
598
+ }
599
+ for (const obj of Object.values(objects)) {
600
+ if (
601
+ isRecord(obj) &&
602
+ obj.isa === 'PBXProject' &&
603
+ typeof obj.buildConfigurationList === 'string'
604
+ ) {
605
+ const listObj = objects[obj.buildConfigurationList]
606
+ if (isRecord(listObj) && Array.isArray(listObj.buildConfigurations)) {
607
+ for (const configId of listObj.buildConfigurations) {
608
+ if (typeof configId === 'string') {
609
+ const configObj = objects[configId]
610
+ if (
611
+ isRecord(configObj) &&
612
+ configObj.name === 'Release' &&
613
+ isRecord(configObj.buildSettings)
614
+ ) {
615
+ for (const [k, v] of Object.entries(configObj.buildSettings)) {
616
+ if (typeof v === 'string') settings[k] = v
617
+ }
618
+ }
619
+ }
620
+ }
621
+ }
622
+ }
623
+ }
624
+ if (selectedTarget?.buildConfigurationList) {
625
+ const listObj = objects[selectedTarget.buildConfigurationList]
626
+ if (isRecord(listObj) && Array.isArray(listObj.buildConfigurations)) {
627
+ for (const configId of listObj.buildConfigurations) {
628
+ if (typeof configId === 'string') {
629
+ const configObj = objects[configId]
630
+ if (
631
+ isRecord(configObj) &&
632
+ configObj.name === 'Release' &&
633
+ isRecord(configObj.buildSettings)
634
+ ) {
635
+ for (const [k, v] of Object.entries(configObj.buildSettings)) {
636
+ if (typeof v === 'string') settings[k] = v
637
+ }
638
+ }
639
+ }
640
+ }
641
+ }
642
+ } else {
643
+ const legacy = appTargetReleaseSettings(
644
+ pbxproj,
645
+ targetName,
646
+ `${targetName}/Info.plist`,
647
+ )
648
+ if (legacy) Object.assign(settings, legacy)
649
+ }
391
650
 
392
- const settings = appTargetReleaseSettings(
393
- pbxproj,
394
- targetName,
395
- `${targetName}/Info.plist`,
396
- )
397
- if (!settings) return null
651
+ let plist: string | undefined
652
+ const infoPlistPath = settings.INFOPLIST_FILE
653
+ if (infoPlistPath) {
654
+ const normalized = infoPlistPath.replace(/^"|"$/g, '')
655
+ plist =
656
+ files[`ios/${normalized}`] ??
657
+ files[normalized] ??
658
+ Object.entries(files).find(([k]) => k.endsWith(`/${normalized}`))?.[1]
659
+ }
660
+ if (!plist) {
661
+ plist =
662
+ files[`ios/${targetName}/Info.plist`] ??
663
+ files[`${targetName}/Info.plist`] ??
664
+ Object.entries(files).find(([k]) => k.endsWith(`/${targetName}/Info.plist`))?.[1]
665
+ }
666
+ if (!plist) return null
398
667
 
399
668
  const bundleIdentifier = identityFieldFrom(
400
669
  settings,
@@ -434,12 +703,87 @@ function nativeAppIdentityFromIos(
434
703
  // with the build-side parser; the browser transport has no XML dependency.
435
704
  const dictionary = parseInfoPlist(plist)
436
705
  if (!isRecord(dictionary)) throw new Error('native app Info.plist is not a dictionary')
706
+ const declaredDisplayName = dictionary.CFBundleDisplayName
707
+ const applicationDisplayName =
708
+ typeof declaredDisplayName === 'string'
709
+ ? resolveBuildSetting(declaredDisplayName, settings)
710
+ : undefined
711
+ if (applicationDisplayName === null)
712
+ throw new Error('native app Info.plist CFBundleDisplayName is unresolved')
713
+ const declaredBackgroundColor = dictionary.RCTRootViewBackgroundColor
714
+ const rootViewBackgroundColor =
715
+ typeof declaredBackgroundColor === 'number' &&
716
+ Number.isInteger(declaredBackgroundColor)
717
+ ? declaredBackgroundColor
718
+ : undefined
719
+ const icons = dictionary.CFBundleIcons
720
+ const alternates = isRecord(icons) ? icons.CFBundleAlternateIcons : undefined
721
+ const alternateIconNames = new Set<string>()
722
+ for (const name of isRecord(alternates) ? Object.keys(alternates) : []) {
723
+ const resolved = resolveBuildSetting(name, settings)
724
+ if (resolved === null) throw new Error('native alternate icon name is unresolved')
725
+ alternateIconNames.add(resolved)
726
+ }
727
+ // xcode writes the declared asset catalog names into the compiled plist.
728
+ const alternateSetting = resolveBuildSetting(
729
+ settings.ASSETCATALOG_COMPILER_ALTERNATE_APPICON_NAMES ?? '',
730
+ settings,
731
+ )
732
+ if (alternateSetting === null)
733
+ throw new Error('native alternate icon setting is unresolved')
734
+ for (const match of alternateSetting
735
+ .replace(/\\"/g, '"')
736
+ .matchAll(/"([^"]*)"|([^\s(),]+)/g)) {
737
+ alternateIconNames.add(match[1] ?? match[2])
738
+ }
437
739
  // swift casts the whole configured value to [String]; a mixed array grants none.
438
740
  const intentIds = dictionary.OneAppIntentIdentifiers
439
741
  const appIntentIdentifiers =
440
742
  Array.isArray(intentIds) && intentIds.every((value) => typeof value === 'string')
441
743
  ? intentIds.map((value: string) => resolveBuildSetting(value, settings))
442
744
  : []
745
+ const backgroundIds = dictionary.BGTaskSchedulerPermittedIdentifiers
746
+ const backgroundTaskIdentifiers =
747
+ Array.isArray(backgroundIds) &&
748
+ backgroundIds.every((value) => typeof value === 'string')
749
+ ? backgroundIds.map((value: string) => resolveBuildSetting(value, settings))
750
+ : []
751
+ const declaredModes = dictionary.UIBackgroundModes
752
+ const backgroundModes =
753
+ Array.isArray(declaredModes) &&
754
+ declaredModes.every((value) => typeof value === 'string')
755
+ ? declaredModes.map((value: string) => resolveBuildSetting(value, settings))
756
+ : []
757
+ // the root orientation controller casts each plist list as a whole [String].
758
+ const screenOrientationLists = [
759
+ 'UISupportedInterfaceOrientations',
760
+ 'UISupportedInterfaceOrientations~ipad',
761
+ ].map((key) => {
762
+ const list = dictionary[key]
763
+ if (!Array.isArray(list) || !list.every((value) => typeof value === 'string'))
764
+ return []
765
+ return list.map((value: string) => {
766
+ const resolved = resolveBuildSetting(value, settings)
767
+ if (resolved === null) throw new Error(`native app Info.plist ${key} is unresolved`)
768
+ return resolved
769
+ })
770
+ })
771
+ const [supportedInterfaceOrientations, ipadSupportedInterfaceOrientations] =
772
+ screenOrientationLists
773
+ const declaredDefaultOrientationMask = dictionary.EXDefaultScreenOrientationMask
774
+ const defaultScreenOrientationMask =
775
+ typeof declaredDefaultOrientationMask === 'string'
776
+ ? resolveBuildSetting(declaredDefaultOrientationMask, settings)
777
+ : undefined
778
+ if (defaultScreenOrientationMask === null)
779
+ throw new Error('native app Info.plist EXDefaultScreenOrientationMask is unresolved')
780
+ const declaredShareGroup = dictionary.ExpoShareIntoAppGroupId
781
+ const shareIntoAppGroupId =
782
+ typeof declaredShareGroup === 'string'
783
+ ? resolveBuildSetting(declaredShareGroup, settings)
784
+ : undefined
785
+ if (shareIntoAppGroupId === null)
786
+ throw new Error('native app Info.plist ExpoShareIntoAppGroupId is unresolved')
443
787
  const querySchemes = dictionary.LSApplicationQueriesSchemes
444
788
  if (querySchemes !== undefined && !Array.isArray(querySchemes)) {
445
789
  throw new Error('native app Info.plist LSApplicationQueriesSchemes is not an array')
@@ -453,7 +797,11 @@ function nativeAppIdentityFromIos(
453
797
  })
454
798
  const permissionUsageDescriptions: Record<string, unknown> = {}
455
799
  for (const [key, value] of Object.entries(dictionary)) {
456
- if (!/^NS.*UsageDescription$/.test(key)) continue
800
+ if (
801
+ !/^NS.*UsageDescription$/.test(key) &&
802
+ key !== 'NSLocationTemporaryUsageDescriptionDictionary'
803
+ )
804
+ continue
457
805
  // retain non-string plist values: the native factory checks key presence.
458
806
  if (typeof value !== 'string') {
459
807
  permissionUsageDescriptions[key] = value
@@ -479,13 +827,28 @@ function nativeAppIdentityFromIos(
479
827
 
480
828
  return {
481
829
  applicationName,
830
+ ...(applicationDisplayName === undefined ? {} : { applicationDisplayName }),
831
+ ...(rootViewBackgroundColor === undefined ? {} : { rootViewBackgroundColor }),
482
832
  bundleName,
483
833
  appVersion,
484
834
  buildVersion,
485
835
  bundleIdentifier,
486
836
  platform: 'ios',
837
+ supportedInterfaceOrientations,
838
+ ipadSupportedInterfaceOrientations,
839
+ ...(defaultScreenOrientationMask === undefined
840
+ ? {}
841
+ : { defaultScreenOrientationMask }),
842
+ alternateIconNames: [...alternateIconNames],
487
843
  permissionUsageDescriptions,
488
844
  urlQuerySchemes,
845
+ ...(shareIntoAppGroupId === undefined ? {} : { shareIntoAppGroupId }),
846
+ backgroundTaskIdentifiers: backgroundTaskIdentifiers.every((value) => value !== null)
847
+ ? backgroundTaskIdentifiers
848
+ : [],
849
+ backgroundModes: backgroundModes.every((value) => value !== null)
850
+ ? backgroundModes
851
+ : [],
489
852
  appIntentIdentifiers: appIntentIdentifiers.every((value) => value !== null)
490
853
  ? appIntentIdentifiers
491
854
  : [],
@@ -504,13 +867,14 @@ export function canExtractNativeAppIdentity(platform: unknown): platform is 'ios
504
867
  // read the identity a bundle builder transports. files are project-relative
505
868
  // paths to their text, so both a checked-out app directory and a stored
506
869
  // project file map resolve identically. null when the project carries no
507
- // resolvable native config — the builder then ships no footer.
870
+ // resolvable native config.
508
871
  export function extractNativeAppIdentityFromFiles(
509
872
  files: NativeAppIdentityFiles,
510
- platform: NativeAppIdentityPlatform,
873
+ platform: unknown,
511
874
  parseInfoPlist: (source: string) => unknown,
875
+ iosTarget?: string,
512
876
  ): NativeAppIdentity | null {
513
877
  return canExtractNativeAppIdentity(platform)
514
- ? nativeAppIdentityFromIos(files, parseInfoPlist)
878
+ ? nativeAppIdentityFromIos(files, parseInfoPlist, iosTarget)
515
879
  : null
516
880
  }