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
@@ -25,6 +25,7 @@ import {
25
25
  } from './swift-compile'
26
26
  import {
27
27
  STANDIN_EMIT_VERSION,
28
+ STANDIN_IMPORTS,
28
29
  emitSwiftStandin,
29
30
  type SymbolGraph,
30
31
  } from './swift-standin-emit'
@@ -134,7 +135,10 @@ function locateXcframework(tree: string): string | null {
134
135
  // remote) keeps its bytes and unpacks again when they change. the digest,
135
136
  // not the path, keys the stand-in cache, so a replaced same-path zip
136
137
  // rebuilds instead of reusing stale output.
137
- function xcframework(binary: SwiftPackageBinary): { dir: string; digest: string } {
138
+ function xcframework(binary: SwiftPackageBinary): {
139
+ dir: string
140
+ digest: string
141
+ } {
138
142
  if (!binary.url && !binary.dir.endsWith('.zip'))
139
143
  return { dir: binary.dir, digest: treeDigest(binary.dir) }
140
144
  if (binary.url && (!binary.checksum || !/^[a-f0-9]{64}$/i.test(binary.checksum)))
@@ -213,6 +217,10 @@ function surfaces(xcframeworkDir: string): Surface[] {
213
217
  .readdirSync(xcframeworkDir)
214
218
  .filter((name) => /^ios-.+-simulator$/.test(name))
215
219
  .sort()[0]
220
+ // a plain .framework vendors one built framework, never xcframework
221
+ // slices; name the shape instead of asking for a layout it cannot have
222
+ if (!slice && xcframeworkDir.endsWith('.framework'))
223
+ throw new Error('a plain .framework has no .xcframework simulator slice')
216
224
  if (!slice) throw new Error('it has no iOS simulator slice')
217
225
  const root = path.join(xcframeworkDir, slice)
218
226
  const found: Surface[] = []
@@ -265,6 +273,11 @@ function peachModuleDirs(toolchain: Toolchain, imports: string[]): string[] {
265
273
  const { moduleRoot, toolchainBin } = toolchain
266
274
  if (swiftDistributionAt(moduleRoot)) return [path.join(moduleRoot, 'modules')]
267
275
  const peach = new Set(swiftPeachModules(moduleRoot))
276
+ // the generated source imports UIKit even when the interface names only
277
+ // sdk modules, so its imports, not the interface's, decide what builds
278
+ const targets = [...new Set([...STANDIN_IMPORTS, ...imports])].filter((name) =>
279
+ peach.has(name),
280
+ )
268
281
  const plugins = swiftMacroPlugins(moduleRoot)
269
282
  if (plugins.stale)
270
283
  exec('sh', [
@@ -272,11 +285,15 @@ function peachModuleDirs(toolchain: Toolchain, imports: string[]): string[] {
272
285
  toolchainBin,
273
286
  plugins.libraries[0]!,
274
287
  ])
275
- for (const target of imports.filter((name) => peach.has(name)))
288
+ for (const target of targets)
276
289
  exec(
277
290
  path.join(toolchainBin, 'swift'),
278
291
  [
279
292
  'build',
293
+ '--build-system',
294
+ 'native',
295
+ '-j',
296
+ '4',
280
297
  '--swift-sdk',
281
298
  swiftModuleSdk(moduleRoot).wasmSdkId,
282
299
  '-c',
@@ -314,8 +331,19 @@ function peachModuleDirs(toolchain: Toolchain, imports: string[]): string[] {
314
331
  // an iOS interface read for wasm: its own flags target wasm, and objective-c
315
332
  // attributes, which need a runtime wasm swift lacks, come off its
316
333
  // declarations; the declarations themselves stay as the vendor wrote them.
334
+ // iOS declares NSObject in its ObjectiveC module, which interfaces name
335
+ // (`ObjectiveC.NSObject`, or `ObjectiveC::NSObject` from swift 6.4); on wasm
336
+ // Foundation declares it, so those references name Foundation.
317
337
  export function swiftInterfaceForWasm(text: string): string {
318
- return text
338
+ const rooted = text.replace(
339
+ /\bObjectiveC(\.|::)(NSObject|NSObjectProtocol)\b/g,
340
+ 'Foundation$1$2',
341
+ )
342
+ const foundation =
343
+ rooted !== text && !/^import[ \t]+Foundation\b/m.test(rooted)
344
+ ? rooted.replace(/^(?=import[ \t])/m, 'import Foundation\n')
345
+ : rooted
346
+ return foundation
319
347
  .replace(/^(\/\/ swift-module-flags:.*)$/m, (flags) =>
320
348
  flags
321
349
  .replace(/-target \S+/, `-target ${TRIPLE}`)
@@ -694,6 +722,229 @@ function cStandin(
694
722
  }
695
723
  }
696
724
 
725
+ const RUST_TARGET = 'wasm32-wasip1'
726
+ // directories a crate search never enters: build output and installed deps
727
+ const UNSEARCHED = new Set([
728
+ 'node_modules',
729
+ 'Pods',
730
+ 'target',
731
+ '.build',
732
+ '.git',
733
+ 'DerivedData',
734
+ ])
735
+
736
+ // the crate whose static library is `lib<name>.a`: its `[lib] name`, or its
737
+ // package name with dashes as underscores, as cargo names the library.
738
+ function crateFor(root: string, name: string): string | null {
739
+ const walk = (dir: string, depth: number): string | null => {
740
+ const manifest = path.join(dir, 'Cargo.toml')
741
+ if (fs.existsSync(manifest)) {
742
+ const text = fs.readFileSync(manifest, 'utf8')
743
+ const section = (title: string) =>
744
+ new RegExp(`^\\[${title}\\]\\s*$([\\s\\S]*?)(?=^\\[|(?![\\s\\S]))`, 'm').exec(
745
+ text,
746
+ )?.[1] ?? ''
747
+ const field = (body: string, key: string) =>
748
+ new RegExp(`^${key}\\s*=\\s*"([^"]+)"`, 'm').exec(body)?.[1]
749
+ const lib = section('lib')
750
+ const crate =
751
+ field(lib, 'name') ?? field(section('package'), 'name')?.replaceAll('-', '_')
752
+ if (crate === name) {
753
+ if (!/crate-type\s*=\s*\[[^\]]*"staticlib"/.test(lib))
754
+ throw new Error(
755
+ `${path.relative(root, manifest)} builds lib${name} without crate-type "staticlib"`,
756
+ )
757
+ return manifest
758
+ }
759
+ }
760
+ if (depth === 0) return null
761
+ for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
762
+ if (
763
+ !entry.isDirectory() ||
764
+ UNSEARCHED.has(entry.name) ||
765
+ entry.name.endsWith('.xcframework')
766
+ )
767
+ continue
768
+ const found = walk(path.join(dir, entry.name), depth - 1)
769
+ if (found) return found
770
+ }
771
+ return null
772
+ }
773
+ return walk(root, 4)
774
+ }
775
+
776
+ /**
777
+ * the WebAssembly static library a c stand-in links in place of its traps,
778
+ * or null when it has none. a build the developer supplies in the
779
+ * xcframework (`wasm32-wasip1/lib<name>.a`) wins; otherwise the crate under
780
+ * `searchRoot` that builds the slice's library compiles with the developer's
781
+ * own cargo. peach ships no rust compiler.
782
+ */
783
+ export function standinLibrary(
784
+ binary: SwiftPackageBinary,
785
+ searchRoot: string,
786
+ ): string | null {
787
+ const dir = xcframework(binary).dir
788
+ const slice = fs
789
+ .readdirSync(dir)
790
+ .filter((name) => /^ios-.+-simulator$/.test(name))
791
+ .sort()[0]
792
+ const library = slice
793
+ ? fs.readdirSync(path.join(dir, slice)).find((name) => /^lib.+\.a$/.test(name))
794
+ : undefined
795
+ const supplied = path.join(dir, RUST_TARGET)
796
+ if (fs.existsSync(supplied)) {
797
+ const found = fs.readdirSync(supplied).filter((name) => name.endsWith('.a'))
798
+ const chosen =
799
+ library && found.includes(library) ? library : found.length === 1 ? found[0] : null
800
+ if (!chosen)
801
+ throw new Error(
802
+ `${path.relative(searchRoot, supplied)} holds no single static library${library ? ` named ${library}` : ''}`,
803
+ )
804
+ return path.join(supplied, chosen)
805
+ }
806
+ if (!library) return null
807
+ const manifest = crateFor(searchRoot, library.slice('lib'.length, -'.a'.length))
808
+ if (!manifest) return null
809
+ const result = spawnSync(
810
+ 'cargo',
811
+ [
812
+ 'build',
813
+ '--release',
814
+ '--target',
815
+ RUST_TARGET,
816
+ '--message-format=json-render-diagnostics',
817
+ '--manifest-path',
818
+ manifest,
819
+ ],
820
+ {
821
+ encoding: 'utf8',
822
+ maxBuffer: 256 * 1024 * 1024,
823
+ stdio: ['ignore', 'pipe', 'pipe'],
824
+ },
825
+ )
826
+ const crate = path.relative(searchRoot, path.dirname(manifest))
827
+ if (result.error)
828
+ throw new Error(
829
+ `${crate} is a rust crate and cargo is not installed; install rust (https://rustup.rs), then run again`,
830
+ )
831
+ if (result.status !== 0) {
832
+ if (
833
+ /target may not be installed|can't find crate for `(core|std)`/.test(result.stderr)
834
+ )
835
+ throw new Error(
836
+ `${crate} builds for ${RUST_TARGET}, which this rust lacks; run \`rustup target add ${RUST_TARGET}\`, then run again`,
837
+ )
838
+ throw new Error(
839
+ `cargo could not build ${crate} for ${RUST_TARGET}: ${failure(result)}`,
840
+ )
841
+ }
842
+ for (const line of result.stdout.split('\n')) {
843
+ if (!line.startsWith('{')) continue
844
+ const message: unknown = JSON.parse(line)
845
+ if (
846
+ !message ||
847
+ typeof message !== 'object' ||
848
+ !('filenames' in message) ||
849
+ !Array.isArray(message.filenames)
850
+ )
851
+ continue
852
+ const archive = message.filenames.find(
853
+ (file): file is string =>
854
+ typeof file === 'string' && path.basename(file) === library,
855
+ )
856
+ if (archive) return archive
857
+ }
858
+ throw new Error(`cargo built ${crate} for ${RUST_TARGET} but reported no ${library}`)
859
+ }
860
+
861
+ // source preflight shares project compilation's portable builder admission.
862
+ // the complete resolved artifact travels as an input, including ignored local frameworks.
863
+ function sourceBinaryStandins(
864
+ binary: SwiftPackageBinary,
865
+ toolchain: Toolchain,
866
+ provided: ReadonlySet<string>,
867
+ ): SwiftStandin[] | string {
868
+ const repo = path.resolve(toolchain.moduleRoot, '../..')
869
+ const work = fs.mkdtempSync(path.join(os.tmpdir(), 'peach-standin-request-'))
870
+ try {
871
+ const artifact = xcframework(binary)
872
+ const local = { ...binary, dir: artifact.dir, url: null, checksum: null }
873
+ const generation = standinGenerationInputs([local], toolchain)
874
+ const request = path.join(work, 'request.json')
875
+ const delivery = path.join(work, 'delivery')
876
+ fs.writeFileSync(
877
+ request,
878
+ JSON.stringify({
879
+ binary: local,
880
+ provided: [...provided],
881
+ generation,
882
+ release: toolchain.release,
883
+ callerToolchainBin: toolchain.toolchainBin,
884
+ }),
885
+ )
886
+ execFileSync(
887
+ 'bash',
888
+ [
889
+ path.join(repo, 'scripts/build/remote.sh'),
890
+ // a deadline makes a busy pool wait for a slot; without one it refuses
891
+ // at once and the app reads as missing a module
892
+ '--timeout',
893
+ '1800',
894
+ '--delivery-dir',
895
+ delivery,
896
+ '--toolchain',
897
+ 'packages/sootsim-swift/toolchain.json',
898
+ '--input',
899
+ request,
900
+ '--input',
901
+ artifact.dir,
902
+ 'bun',
903
+ 'scripts/build/swift-standins.ts',
904
+ '--request',
905
+ '.remote-inputs/request.json',
906
+ '--artifact',
907
+ `.remote-inputs/${path.basename(artifact.dir)}`,
908
+ '--output',
909
+ '.remote-out/standins.json',
910
+ ],
911
+ { cwd: repo, stdio: 'inherit' },
912
+ )
913
+ const receipt: unknown = JSON.parse(
914
+ fs.readFileSync(path.join(delivery, 'standins.json'), 'utf8'),
915
+ )
916
+ if (
917
+ !receipt ||
918
+ typeof receipt !== 'object' ||
919
+ !('generation' in receipt) ||
920
+ receipt.generation !== generation ||
921
+ !('result' in receipt)
922
+ )
923
+ throw new Error('Swift stand-in builder source differs from the caller')
924
+ const result = receipt.result
925
+ if (typeof result === 'string') return result
926
+ if (
927
+ !Array.isArray(result) ||
928
+ !result.every(
929
+ (item) =>
930
+ item &&
931
+ typeof item === 'object' &&
932
+ typeof item.module === 'string' &&
933
+ typeof item.target === 'string' &&
934
+ item.target === binary.target &&
935
+ item.files &&
936
+ typeof item.files === 'object' &&
937
+ !Array.isArray(item.files) &&
938
+ Object.values(item.files).every((text) => typeof text === 'string'),
939
+ )
940
+ )
941
+ throw new Error('invalid Swift stand-in builder result')
942
+ return result
943
+ } finally {
944
+ fs.rmSync(work, { recursive: true, force: true })
945
+ }
946
+ }
947
+
697
948
  const built = new Map<string, SwiftStandin[] | string>()
698
949
 
699
950
  /** what stand-ins are generated from besides the surfaces' files: the
@@ -792,18 +1043,26 @@ function binaryStandins(
792
1043
  const work = fs.mkdtempSync(path.join(os.tmpdir(), 'peach-standin-'))
793
1044
  let result: SwiftStandin[] | string
794
1045
  try {
795
- result = found.map((surface) => {
796
- const dir = path.join(work, surface.module)
797
- try {
798
- return surface.kind === 'swift'
799
- ? swiftStandin(surface, binary, toolchain, dir)
800
- : cStandin(surface, binary, toolchain, dir)
801
- } catch (error) {
802
- throw new Error(
803
- `no stand-in for ${surface.module}: ${error instanceof Error && !('stderr' in error) ? error.message : failure(error)}`,
804
- )
805
- }
806
- })
1046
+ result =
1047
+ process.platform === 'darwin' &&
1048
+ process.env.TM_SESSION &&
1049
+ process.env.CI !== 'true' &&
1050
+ toolchain.moduleRoot === path.resolve(import.meta.dirname, '../../sootsim-swift') &&
1051
+ !swiftDistributionAt(toolchain.moduleRoot)
1052
+ ? sourceBinaryStandins(binary, toolchain, provided)
1053
+ : found.map((surface) => {
1054
+ const dir = path.join(work, surface.module)
1055
+ try {
1056
+ return surface.kind === 'swift'
1057
+ ? swiftStandin(surface, binary, toolchain, dir)
1058
+ : cStandin(surface, binary, toolchain, dir)
1059
+ } catch (error) {
1060
+ throw new Error(
1061
+ `no stand-in for ${surface.module}: ${error instanceof Error && !('stderr' in error) ? error.message : failure(error)}`,
1062
+ )
1063
+ }
1064
+ })
1065
+ if (typeof result === 'string') return result
807
1066
  fs.mkdirSync(path.dirname(cached), { recursive: true })
808
1067
  fs.writeFileSync(cached, JSON.stringify(result))
809
1068
  built.set(id, result)
@@ -20,6 +20,12 @@
20
20
  * Browser-safe: node-only submitters live beside their call sites.
21
21
  */
22
22
 
23
+ import {
24
+ isSwiftMetalLibrarySources,
25
+ type SwiftMetalLibrarySource,
26
+ type SwiftResourceBundle,
27
+ } from './swiftContract'
28
+
23
29
  export const SWIFT_COMPILE_PATH = '/api/swift-compile'
24
30
  export const SWIFT_PACKAGE_PATH = '/__peach/swift-package/'
25
31
  export const SWIFT_HMR_PATH = '/__peach/swift-hmr'
@@ -30,6 +36,9 @@ export const MAX_SWIFT_COMPILE_SOURCE_BYTES = 2 * 1024 * 1024
30
36
  export const MAX_SWIFT_COMPILE_RESOURCES = 128
31
37
  export const MAX_SWIFT_COMPILE_RESOURCE_BYTES = 2 * 1024 * 1024
32
38
  export const MAX_SWIFT_COMPILE_RESOURCE_TOTAL_BYTES = 8 * 1024 * 1024
39
+ export const MAX_SWIFT_COMPILE_METAL_FILES = 128
40
+ export const MAX_SWIFT_COMPILE_METAL_BYTES = 2 * 1024 * 1024
41
+ export const MAX_SWIFT_COMPILE_METAL_TOTAL_BYTES = 8 * 1024 * 1024
33
42
  export const MAX_SWIFT_COMPILE_IMAGES = 128
34
43
  export const MAX_SWIFT_COMPILE_IMAGE_BYTES = 4 * 1024 * 1024
35
44
  export const MAX_SWIFT_COMPILE_IMAGE_TOTAL_BYTES = 16 * 1024 * 1024
@@ -71,8 +80,25 @@ export const MAX_SWIFT_COMPILE_IMAGE_TOTAL_BYTES = 16 * 1024 * 1024
71
80
  * 22: WebKit script messages carry request ids and receive Promise replies.
72
81
  * 23: URLSessionWebSocketTask uses the networking host for real WebSocket transport.
73
82
  * 24: WebKit cookie stores share native jars with isolated store lifetimes.
83
+ * 25: CoreMotion authorization reads motion (4) from the shared permission owner.
74
84
  */
75
- export const SWIFT_HOST_ABI = 24
85
+ // 26: target resource bundles and shader library source assignments.
86
+ // 27: direct Metal requests, asynchronous GPU completion and shared readback.
87
+ // 28: direct render operations and texture readback before completion.
88
+ // 29: original metallib input, native AIR inspection and compute execution.
89
+ // 30: compute texture bytes and immutable sampler bindings at submission.
90
+ // 31: independent vertex/fragment resource snapshots for every render draw.
91
+ // 32: target-owned named images and per-bundle image resource tables.
92
+ // 33: active iOS device identity before Swift native module calls.
93
+ // 34: asynchronous SwiftUI shader prewarm through the compositor device.
94
+ // 35: SwiftUI shader shape fills retain the original shader wire.
95
+ // 36: shader strokes carry width, inset and output-origin geometry.
96
+ // 37: shader foreground and background styles retain their library arguments.
97
+ // 38: typed Swift view exports and package-scoped native descriptors.
98
+ // 39: canvas image draw operations retain their target bundle.
99
+ // 40: implicit animations retain typed value changes through a generation marker.
100
+ // 41: original compiled SwiftUI libraries retain data and deferred URL inputs.
101
+ export const SWIFT_HOST_ABI = 41
76
102
 
77
103
  export interface SwiftImageUpload {
78
104
  /** the raster file picked for the asset (has the extension). */
@@ -108,6 +134,7 @@ export type SwiftCompileOutcome =
108
134
  * when the request packs no images.
109
135
  */
110
136
  imageUrls?: Record<string, string>
137
+ metalSources?: Record<string, SwiftMetalLibrarySource>
111
138
  /** the callable swift modules the sources export; absent when none. */
112
139
  native?: SwiftNativeModules
113
140
  }
@@ -125,7 +152,7 @@ export type SwiftCompileOutcome =
125
152
  const POLL_INTERVAL_MS = 1500
126
153
 
127
154
  /**
128
- * the callable surface of a swift package whose sources declare `RNXModule`
155
+ * the callable surface of a swift package whose sources declare `PeachModule`
129
156
  * classes, as vxrn's native-source contract describes it: `one typegen`
130
157
  * writes it beside a One package, and the compile host derives it for a
131
158
  * project. the dispatch glue compiled into the artifact checks `hash` on every
@@ -138,6 +165,8 @@ export interface SwiftNativeModules {
138
165
  files: Record<string, string[]>
139
166
  /** module name to its method names. */
140
167
  modules: Record<string, string[]>
168
+ /** typed view name to its prop names. */
169
+ views: Record<string, string[]>
141
170
  /** the files that also declare the package's `@main` view. */
142
171
  defaultViewFiles: string[]
143
172
  }
@@ -150,14 +179,18 @@ export function swiftNativeEntry(
150
179
  packageId: string
151
180
  contractHash: string
152
181
  modules: Record<string, string[]>
182
+ views: string[]
153
183
  defaultView: boolean
154
184
  } {
155
185
  return {
156
186
  packageId: native.packageId,
157
187
  contractHash: native.hash,
158
188
  modules: Object.fromEntries(
159
- (native.files[file] ?? []).map((name) => [name, native.modules[name] ?? []]),
189
+ (native.files[file] ?? [])
190
+ .filter((name) => Object.hasOwn(native.modules, name))
191
+ .map((name) => [name, native.modules[name]]),
160
192
  ),
193
+ views: (native.files[file] ?? []).filter((name) => Object.hasOwn(native.views, name)),
161
194
  defaultView: native.defaultViewFiles.includes(file),
162
195
  }
163
196
  }
@@ -187,15 +220,17 @@ export interface SwiftCompileContext {
187
220
 
188
221
  export type SwiftCompileSubmit = (work: {
189
222
  files: Record<string, string>
223
+ metalSources?: Record<string, string>
190
224
  /** the bundle pack; absent means the project packs none. */
191
225
  resources?: Record<string, string>
192
226
  /** project-relative resource paths used to associate implicit resources with targets. */
193
227
  resourcePaths?: string[]
228
+ resourceBundles?: SwiftResourceBundle[]
194
229
  /** the photo rasters to publish; absent means the project packs none. */
195
230
  images?: Record<string, SwiftImageUpload>
196
231
  entry: string
197
- /** the id a One package's native modules register under; absent means `App`. */
198
- packageId?: string
232
+ /** the directory-derived id of the One package. */
233
+ packageId: string
199
234
  }) => Promise<SwiftCompileOutcome>
200
235
 
201
236
  /** the HTTP submitter, shared by the browser worker and the node build. */
@@ -255,7 +290,12 @@ export function isSwiftNativeModules(value: unknown): value is SwiftNativeModule
255
290
  typeof value.hash === 'string' &&
256
291
  isRecord(value.files) &&
257
292
  isRecord(value.modules) &&
258
- [...Object.values(value.files), ...Object.values(value.modules)].every(
293
+ isRecord(value.views) &&
294
+ [
295
+ ...Object.values(value.files),
296
+ ...Object.values(value.modules),
297
+ ...Object.values(value.views),
298
+ ].every(
259
299
  (names) => Array.isArray(names) && names.every((name) => typeof name === 'string'),
260
300
  ) &&
261
301
  Array.isArray(value.defaultViewFiles) &&
@@ -275,6 +315,8 @@ function isSwiftCompileOutcome(value: unknown): value is SwiftCompileOutcome {
275
315
  (value.imageUrls === undefined ||
276
316
  (isRecord(value.imageUrls) &&
277
317
  Object.values(value.imageUrls).every((url) => typeof url === 'string'))) &&
318
+ (value.metalSources === undefined ||
319
+ isSwiftMetalLibrarySources(value.metalSources)) &&
278
320
  (value.native === undefined || isSwiftNativeModules(value.native))
279
321
  )
280
322
  case 'compiling':
@@ -308,6 +350,7 @@ export interface SwiftModuleAddress {
308
350
  icuUrl: string
309
351
  /** bundle asset name to absolute photo url, when the pack publishes any. */
310
352
  imageUrls?: Record<string, string>
353
+ metalSources?: Record<string, SwiftMetalLibrarySource>
311
354
  /** the callable swift modules the artifact links, when the sources declare any. */
312
355
  native?: SwiftNativeModules
313
356
  }
@@ -337,12 +380,14 @@ export async function compileSwiftProject(
337
380
  submit: SwiftCompileSubmit,
338
381
  work: {
339
382
  files: Record<string, string>
383
+ metalSources?: Record<string, string>
340
384
  resources?: Record<string, string>
341
385
  /** project-relative resource paths used to associate implicit resources with targets. */
342
386
  resourcePaths?: string[]
387
+ resourceBundles?: SwiftResourceBundle[]
343
388
  images?: Record<string, SwiftImageUpload>
344
389
  entry: string
345
- packageId?: string
390
+ packageId: string
346
391
  },
347
392
  origin: string,
348
393
  signal?: AbortSignal,
@@ -359,6 +404,16 @@ export async function compileSwiftProject(
359
404
  ...(outcome.imageUrls === undefined
360
405
  ? {}
361
406
  : { imageUrls: resolveImageUrls(outcome.imageUrls, origin) }),
407
+ ...(outcome.metalSources === undefined
408
+ ? {}
409
+ : {
410
+ metalSources: Object.fromEntries(
411
+ Object.entries(outcome.metalSources).map(([file, source]) => [
412
+ file,
413
+ { ...source, url: compileAssetUrl(source.url, origin) },
414
+ ]),
415
+ ),
416
+ }),
362
417
  ...(outcome.native === undefined ? {} : { native: outcome.native }),
363
418
  }
364
419
  case 'compiling':
@@ -10,6 +10,11 @@ import fs from 'node:fs'
10
10
  import os from 'node:os'
11
11
  import path from 'node:path'
12
12
 
13
+ // swift.org's x.y.0 archives report the compiler identity as x.y.
14
+ export function swiftCompilerRelease(release: string): string {
15
+ return release.replace(/^swift-(\d+\.\d+)\.0-RELEASE$/, 'swift-$1-RELEASE')
16
+ }
17
+
13
18
  /**
14
19
  * the bin directory of the toolchain for `release`, unverified. macOS: the
15
20
  * Xcode Toolchains directory, the user's before the system's. Linux: a
@@ -62,7 +67,7 @@ export function swiftToolchain(release: string, sdk: SwiftWasmSdk): string {
62
67
  stdio: ['ignore', 'pipe', 'pipe'],
63
68
  })
64
69
  : ''
65
- if (!version.includes(`(${release})`)) {
70
+ if (!version.includes(`(${swiftCompilerRelease(release)})`)) {
66
71
  const found = version
67
72
  ? `found ${version.split('\n')[0]?.trim()} at ${swift}`
68
73
  : process.platform === 'darwin'