rnxsim 0.1.335 → 0.1.337

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 (272) hide show
  1. package/README.md +104 -76
  2. package/cli/auth.ts +2 -2
  3. package/cli/bin.ts +7 -3
  4. package/cli/bridge-flow-runner.ts +2 -2
  5. package/cli/commands/agent-wrapper.ts +1 -1
  6. package/cli/commands/agent.ts +12 -12
  7. package/cli/commands/app-fonts.ts +1 -1
  8. package/cli/commands/assert.ts +7 -7
  9. package/cli/commands/auth.ts +4 -4
  10. package/cli/commands/camera.ts +13 -13
  11. package/cli/commands/cleanup.ts +6 -6
  12. package/cli/commands/compat.ts +4 -4
  13. package/cli/commands/config.ts +2 -2
  14. package/cli/commands/control.ts +37 -43
  15. package/cli/commands/cpu-profile.ts +2 -2
  16. package/cli/commands/daemon-mac-app.ts +2 -2
  17. package/cli/commands/daemon.ts +12 -12
  18. package/cli/commands/debug.ts +22 -22
  19. package/cli/commands/desktop.ts +3 -3
  20. package/cli/commands/detox.ts +17 -17
  21. package/cli/commands/device.ts +9 -9
  22. package/cli/commands/diagnose.ts +11 -11
  23. package/cli/commands/electron.ts +7 -7
  24. package/cli/commands/film.ts +6 -6
  25. package/cli/commands/inspect/core.ts +6 -7
  26. package/cli/commands/inspect/find.ts +2 -2
  27. package/cli/commands/inspect.ts +36 -36
  28. package/cli/commands/install-desktop.ts +8 -8
  29. package/cli/commands/login.ts +6 -6
  30. package/cli/commands/maestro-generate.ts +2 -2
  31. package/cli/commands/maestro.ts +23 -23
  32. package/cli/commands/mode.ts +4 -4
  33. package/cli/commands/no-bridge-hint.ts +9 -9
  34. package/cli/commands/perf.ts +11 -11
  35. package/cli/commands/permissions.ts +5 -5
  36. package/cli/commands/profile.ts +11 -11
  37. package/cli/commands/react.ts +15 -15
  38. package/cli/commands/record.ts +15 -15
  39. package/cli/commands/report-issue.ts +2 -2
  40. package/cli/commands/reset.ts +2 -2
  41. package/cli/commands/runtime.ts +18 -18
  42. package/cli/commands/screenshot-mode.ts +5 -5
  43. package/cli/commands/screenshot.ts +12 -12
  44. package/cli/commands/screenshots-capture.ts +7 -7
  45. package/cli/commands/screenshots.ts +6 -6
  46. package/cli/commands/serve.ts +6 -6
  47. package/cli/commands/setup.ts +13 -15
  48. package/cli/commands/skills.ts +14 -14
  49. package/cli/commands/slides.ts +19 -23
  50. package/cli/commands/state.ts +2 -2
  51. package/cli/commands/storage.ts +3 -3
  52. package/cli/commands/telemetry.ts +1 -1
  53. package/cli/commands/three-mode.ts +16 -16
  54. package/cli/commands/timeline.ts +4 -4
  55. package/cli/commands/upgrade.ts +1 -1
  56. package/cli/commands/upload.ts +11 -11
  57. package/cli/commands/version.ts +3 -5
  58. package/cli/commands/what-happened.ts +11 -11
  59. package/cli/drivers/electron.ts +3 -3
  60. package/cli/hints.ts +8 -8
  61. package/cli/recording-access.ts +1 -1
  62. package/cli/ws-bridge.ts +5 -5
  63. package/dist-cli/bin.js +5 -5
  64. package/dist-cli/chunks/{agent-XSJMAFVA.js → agent-QQ3RJNRY.js} +14 -14
  65. package/dist-cli/chunks/{agent-wrapper-NFLJ5K64.js → agent-wrapper-M6SQSMRY.js} +3 -3
  66. package/dist-cli/chunks/app-fonts-F6NDV3XC.js +4 -0
  67. package/dist-cli/chunks/{assert-ILAXIYB5.js → assert-5VB3KQNK.js} +12 -12
  68. package/dist-cli/chunks/auth-PFXODKFN.js +12 -0
  69. package/dist-cli/chunks/{beta-TDR6UKJU.js → beta-WUWYHT4F.js} +2 -2
  70. package/dist-cli/chunks/camera-V3MMTKP7.js +33 -0
  71. package/dist-cli/chunks/{chunk-INBPUR4T.js → chunk-2ANFH72P.js} +11 -11
  72. package/dist-cli/chunks/chunk-2GIA5T6B.js +74 -0
  73. package/dist-cli/chunks/{chunk-GP6QEBZA.js → chunk-4FRSEZ7Z.js} +1 -1
  74. package/dist-cli/chunks/{chunk-USGOQ3YJ.js → chunk-4GXBZHNA.js} +2 -2
  75. package/dist-cli/chunks/{chunk-R3CMECGC.js → chunk-4HESY5E7.js} +4 -4
  76. package/dist-cli/chunks/{chunk-WKT7YM5Q.js → chunk-4VJEXQGD.js} +1 -1
  77. package/dist-cli/chunks/{chunk-FE6ZHPKD.js → chunk-5LJNNHZH.js} +1 -1
  78. package/dist-cli/chunks/{chunk-I2HQB5NN.js → chunk-5QXGSTYI.js} +2 -2
  79. package/dist-cli/chunks/{chunk-FJSHIWAM.js → chunk-5SHAOQHJ.js} +2 -2
  80. package/dist-cli/chunks/{chunk-CGZWLSYD.js → chunk-5UPRBMIG.js} +1 -1
  81. package/dist-cli/chunks/{chunk-ZTM2MKNI.js → chunk-5ZEFRPCC.js} +1 -1
  82. package/dist-cli/chunks/{chunk-RTD3CPDQ.js → chunk-6ART4XVJ.js} +23 -23
  83. package/dist-cli/chunks/{chunk-MTD6IAEA.js → chunk-6CAUT2LH.js} +1 -1
  84. package/dist-cli/chunks/{chunk-ZYHCWCMM.js → chunk-7ATIH7OU.js} +1 -1
  85. package/dist-cli/chunks/{chunk-RVUGKXJD.js → chunk-7Q4QKHMA.js} +1 -1
  86. package/dist-cli/chunks/{chunk-MTNIDSOA.js → chunk-ABK2V2PR.js} +1 -1
  87. package/dist-cli/chunks/{chunk-TL4DNDDY.js → chunk-B53ILAHI.js} +2 -2
  88. package/dist-cli/chunks/{chunk-POC3QTA6.js → chunk-BSSVLFZR.js} +2 -2
  89. package/dist-cli/chunks/chunk-BVOBXTPN.js +30 -0
  90. package/dist-cli/chunks/{chunk-4KC35DMK.js → chunk-CPDEUWL5.js} +2 -2
  91. package/dist-cli/chunks/{chunk-HNQLZZJA.js → chunk-DINU267S.js} +2 -2
  92. package/dist-cli/chunks/{chunk-DCDKJ4NC.js → chunk-DQQ4CZVC.js} +2 -2
  93. package/dist-cli/chunks/{chunk-JWAY6DIH.js → chunk-EDWN2HOO.js} +18 -18
  94. package/dist-cli/chunks/{chunk-3CS4EUMG.js → chunk-EWVG4A3B.js} +2 -2
  95. package/dist-cli/chunks/{chunk-RTEJXUXN.js → chunk-F3NKCQHM.js} +6 -6
  96. package/dist-cli/chunks/{chunk-M7CBQ5I4.js → chunk-GEAGFYKP.js} +1 -1
  97. package/dist-cli/chunks/chunk-GGNH44PZ.js +5 -0
  98. package/dist-cli/chunks/{chunk-YSUIYK6B.js → chunk-HAHJJJUC.js} +2 -2
  99. package/dist-cli/chunks/chunk-HPJ5EKIZ.js +4 -0
  100. package/dist-cli/chunks/{chunk-IN2PZBQD.js → chunk-IBTHGFKE.js} +2 -2
  101. package/dist-cli/chunks/{chunk-ZZWO6Y7X.js → chunk-J6BYRRZQ.js} +2 -2
  102. package/dist-cli/chunks/{chunk-6Y3PVPTF.js → chunk-JK4OZ2TQ.js} +5 -5
  103. package/dist-cli/chunks/{chunk-PO3TOAED.js → chunk-KGQAO25M.js} +2 -2
  104. package/dist-cli/chunks/{chunk-J7XFINJG.js → chunk-L6UUIQE7.js} +2 -2
  105. package/dist-cli/chunks/{chunk-35XNGT5C.js → chunk-LXYLCETR.js} +1 -1
  106. package/dist-cli/chunks/{chunk-JWK5WD44.js → chunk-LZAL3DMP.js} +2 -2
  107. package/dist-cli/chunks/{chunk-3ZDOPKHE.js → chunk-M43UU7UG.js} +4 -4
  108. package/dist-cli/chunks/{chunk-ROPHZJ6P.js → chunk-M4LGUVBM.js} +2 -2
  109. package/dist-cli/chunks/{chunk-RELRA5VW.js → chunk-NCG6C5AH.js} +2 -2
  110. package/dist-cli/chunks/{chunk-42KDXJUD.js → chunk-NR5TSR2Y.js} +2 -2
  111. package/dist-cli/chunks/{chunk-R2UL5VFY.js → chunk-OCPWXT73.js} +3 -3
  112. package/dist-cli/chunks/{chunk-VV4MXLFR.js → chunk-ODKS6JUJ.js} +1 -1
  113. package/dist-cli/chunks/{chunk-F33DUJGG.js → chunk-R2WBREGQ.js} +1 -1
  114. package/dist-cli/chunks/chunk-RKY3ZNTA.js +5 -0
  115. package/dist-cli/chunks/{chunk-MGGRL2Z2.js → chunk-SW7BHOMO.js} +9 -9
  116. package/dist-cli/chunks/{chunk-GVKISFQ3.js → chunk-TJTLXG3R.js} +1 -1
  117. package/dist-cli/chunks/chunk-TNI4PW75.js +124 -0
  118. package/dist-cli/chunks/{chunk-CL3PREIE.js → chunk-UWEDNDND.js} +2 -2
  119. package/dist-cli/chunks/{chunk-IV36DY6M.js → chunk-WRID5SBV.js} +1 -1
  120. package/dist-cli/chunks/{chunk-42ALI64M.js → chunk-WUYI3XJ5.js} +2 -2
  121. package/dist-cli/chunks/{chunk-6VN5ULGQ.js → chunk-X7MHCEGG.js} +2 -2
  122. package/dist-cli/chunks/chunk-XIQFYLWD.js +15 -0
  123. package/dist-cli/chunks/{chunk-LCVUJCRJ.js → chunk-ZUK5ZQU7.js} +1 -1
  124. package/dist-cli/chunks/{cleanup-X6ZRPFDV.js → cleanup-6WBS3MUO.js} +10 -10
  125. package/dist-cli/chunks/cli-version-HUQCDGMA.js +4 -0
  126. package/dist-cli/chunks/{compat-VRXJ5J56.js → compat-2WOPKJYK.js} +9 -9
  127. package/dist-cli/chunks/{config-LHPPE4EP.js → config-FPD7WUYB.js} +5 -5
  128. package/dist-cli/chunks/{control-TVTNGSSF.js → control-B3XNER7I.js} +2 -2
  129. package/dist-cli/chunks/daemon-T4D4X2P5.js +4 -0
  130. package/dist-cli/chunks/{debug-EUHBBPGM.js → debug-LKV5CEAV.js} +17 -17
  131. package/dist-cli/chunks/desktop-EMDPOYQT.js +31 -0
  132. package/dist-cli/chunks/detox-4J4UTZE7.js +52 -0
  133. package/dist-cli/chunks/{device-PONITUZJ.js → device-PMZ7RPXQ.js} +11 -11
  134. package/dist-cli/chunks/{diagnose-2PN4K4L2.js → diagnose-MLEP727D.js} +12 -12
  135. package/dist-cli/chunks/{disk-cleanup-U2PQLOEW.js → disk-cleanup-CVEDIPEE.js} +2 -2
  136. package/dist-cli/chunks/drivers-NTUKJEL6.js +4 -0
  137. package/dist-cli/chunks/{film-XGZCFTQL.js → film-4RNECABF.js} +9 -9
  138. package/dist-cli/chunks/flow-5IOCAHVO.js +4 -0
  139. package/dist-cli/chunks/help-NUJUYEWP.js +4 -0
  140. package/dist-cli/chunks/{hidden-runtime-alias-I4MYF5CO.js → hidden-runtime-alias-YIF25W4F.js} +2 -2
  141. package/dist-cli/chunks/{home-paths-YRAPZ5LE.js → home-paths-WNJCCCCZ.js} +2 -2
  142. package/dist-cli/chunks/inspect-MFEIYUCN.js +4 -0
  143. package/dist-cli/chunks/install-desktop-NB65KI4D.js +4 -0
  144. package/dist-cli/chunks/{login-ZMAIAQ6F.js → login-VEHHGN42.js} +6 -6
  145. package/dist-cli/chunks/{logout-UQZ5JBJU.js → logout-VE7PNXL2.js} +2 -2
  146. package/dist-cli/chunks/{maestro-BQYKDUC4.js → maestro-ZXHTDEOI.js} +25 -25
  147. package/dist-cli/chunks/{maestro-generate-VQYMMQJ5.js → maestro-generate-TK33E2Z6.js} +3 -3
  148. package/dist-cli/chunks/mode-ZDKJ56NT.js +26 -0
  149. package/dist-cli/chunks/{optional-demo-registry-DUWHCLGD.js → optional-demo-registry-GBZ3WVDW.js} +2 -2
  150. package/dist-cli/chunks/{perf-7RAU7WRZ.js → perf-JXNZOUKW.js} +28 -28
  151. package/dist-cli/chunks/permissions-WQ62PW7Y.js +13 -0
  152. package/dist-cli/chunks/record-4S3ZMDIO.js +72 -0
  153. package/dist-cli/chunks/{report-issue-P376KFFU.js → report-issue-KKBADTWO.js} +4 -4
  154. package/dist-cli/chunks/reset-H5XIISJE.js +4 -0
  155. package/dist-cli/chunks/runtime-FK7EEMWA.js +4 -0
  156. package/dist-cli/chunks/{screenshot-command-NE7BKTQ2.js → screenshot-command-42U5MVQL.js} +34 -34
  157. package/dist-cli/chunks/{screenshot-layers-UE4R64PZ.js → screenshot-layers-4G42AHOX.js} +2 -2
  158. package/dist-cli/chunks/{screenshots-capture-ULXPLXMC.js → screenshots-capture-HMQ2OO3I.js} +11 -11
  159. package/dist-cli/chunks/{serve-P7BT4XHR.js → serve-S4V5EDW2.js} +16 -16
  160. package/dist-cli/chunks/setup-T43V7GA6.js +32 -0
  161. package/dist-cli/chunks/{skills-NTRYKJSF.js → skills-O426K26J.js} +16 -16
  162. package/dist-cli/chunks/{state-4D5YAM47.js → state-ZEEPDKJG.js} +5 -5
  163. package/dist-cli/chunks/storage-4GQLOFGG.js +37 -0
  164. package/dist-cli/chunks/store-RFMSNWLJ.js +4 -0
  165. package/dist-cli/chunks/telemetry-NFAAPSMN.js +4 -0
  166. package/dist-cli/chunks/{timeline-GZNFGD3Q.js → timeline-ONCYX7KW.js} +6 -6
  167. package/dist-cli/chunks/{upgrade-A46D6PEY.js → upgrade-A36T52AM.js} +2 -2
  168. package/dist-cli/chunks/upload-36O32DII.js +4 -0
  169. package/dist-cli/chunks/version-67HA253N.js +6 -0
  170. package/dist-cli/chunks/{web-H2IXO5SC.js → web-PWXQHQIE.js} +2 -2
  171. package/dist-cli/chunks/{what-happened-Z7UII5GH.js → what-happened-WNXE622R.js} +16 -16
  172. package/dist-lib/agent-daemon-client.cjs +5 -5
  173. package/dist-lib/agent-events.cjs +1 -1
  174. package/dist-lib/agent-identity.cjs +1 -1
  175. package/dist-lib/agent-sessions.cjs +4 -4
  176. package/dist-lib/attached-projects.cjs +1 -1
  177. package/dist-lib/auth/shared-session.cjs +1 -1
  178. package/dist-lib/backend-origin.cjs +1 -1
  179. package/dist-lib/beta.cjs +1 -1
  180. package/dist-lib/beta.mjs +1 -1
  181. package/dist-lib/bridge-constants.cjs +1 -1
  182. package/dist-lib/bridge-contract.cjs +1 -1
  183. package/dist-lib/cli-constants.cjs +1 -1
  184. package/dist-lib/config.cjs +1 -1
  185. package/dist-lib/detox/index.cjs +1 -1
  186. package/dist-lib/dev-bundle-resolution.cjs +1 -1
  187. package/dist-lib/home-paths.cjs +1 -1
  188. package/dist-lib/host/bridge-host.cjs +7 -7
  189. package/dist-lib/host/fetch-proxy-handler.cjs +1 -1
  190. package/dist-lib/host/fetch-proxy-overrides.cjs +1 -1
  191. package/dist-lib/host/fetch-proxy-overrides.mjs +1 -1
  192. package/dist-lib/host/websocket-proxy.cjs +1 -1
  193. package/dist-lib/index.cjs +248 -98
  194. package/dist-lib/jump-to-source-babel.cjs +1 -1
  195. package/dist-lib/menu.cjs +2 -2
  196. package/dist-lib/menu.mjs +2 -2
  197. package/dist-lib/metro-host-modules/react-dom.js +6 -0
  198. package/dist-lib/metro-host-modules/react-native-web.js +6 -0
  199. package/dist-lib/metro-host-modules/react-native.js +6 -0
  200. package/dist-lib/metro-host-modules/react.js +6 -0
  201. package/dist-lib/metro-host-modules/react__jsx-dev-runtime.js +6 -0
  202. package/dist-lib/metro-host-modules/react__jsx-runtime.js +6 -0
  203. package/dist-lib/metro-production-bundle.cjs +72 -0
  204. package/dist-lib/metro-production-bundle.mjs +44 -0
  205. package/dist-lib/metro.cjs +152 -8
  206. package/dist-lib/profiles.cjs +1 -1
  207. package/dist-lib/public-brand.cjs +2 -2
  208. package/dist-lib/react-native-host-modules.cjs +50 -0
  209. package/dist-lib/render-mode.cjs +1 -1
  210. package/dist-lib/scripts/dev-server-scanner.cjs +1 -1
  211. package/dist-lib/sdk.cjs +6 -7
  212. package/dist-lib/sdk.mjs +6 -7
  213. package/dist-lib/skills.cjs +71 -77
  214. package/dist-lib/vite.cjs +104 -85
  215. package/package.json +15 -2
  216. package/scripts/preuninstall.cjs +1 -1
  217. package/skills/contrast/SKILL.md +67 -75
  218. package/skills/rnx-debug/SKILL.md +84 -84
  219. package/skills/rnx-perf/SKILL.md +8 -8
  220. package/skills/rnx-setup/SKILL.md +54 -54
  221. package/skills/rnx-test/SKILL.md +35 -35
  222. package/skills/rnx-visual/SKILL.md +18 -18
  223. package/src/agent-daemon-client.ts +2 -2
  224. package/src/agent-sessions.ts +2 -2
  225. package/src/connect.ts +6 -6
  226. package/src/disk-cleanup.ts +1 -1
  227. package/src/home-paths.ts +1 -1
  228. package/src/host/bridge-host.ts +6 -6
  229. package/src/index.ts +1 -1
  230. package/src/metro-host-modules/react-dom.js +6 -0
  231. package/src/metro-host-modules/react-native-web.js +6 -0
  232. package/src/metro-host-modules/react-native.js +6 -0
  233. package/src/metro-host-modules/react.js +6 -0
  234. package/src/metro-host-modules/react__jsx-dev-runtime.js +6 -0
  235. package/src/metro-host-modules/react__jsx-runtime.js +6 -0
  236. package/src/metro-plugin.ts +249 -10
  237. package/src/metro-production-bundle.ts +51 -0
  238. package/src/public-brand.ts +1 -1
  239. package/src/react-native-host-modules.ts +25 -0
  240. package/src/runtime-assets.ts +1 -1
  241. package/src/sim-client.ts +1 -1
  242. package/src/vite-plugin-one.ts +171 -145
  243. package/dist-cli/chunks/app-fonts-L3UXFYVE.js +0 -4
  244. package/dist-cli/chunks/auth-ISX2EUQL.js +0 -12
  245. package/dist-cli/chunks/camera-4SWTNJUA.js +0 -33
  246. package/dist-cli/chunks/chunk-BRHZEZKN.js +0 -124
  247. package/dist-cli/chunks/chunk-EJPYPJWP.js +0 -5
  248. package/dist-cli/chunks/chunk-KWCD5MOK.js +0 -15
  249. package/dist-cli/chunks/chunk-MJ7QGY7Z.js +0 -4
  250. package/dist-cli/chunks/chunk-RSA4XWHN.js +0 -5
  251. package/dist-cli/chunks/chunk-S3EIOAWZ.js +0 -74
  252. package/dist-cli/chunks/chunk-TYANJQLO.js +0 -30
  253. package/dist-cli/chunks/cli-version-NZUSWKZR.js +0 -4
  254. package/dist-cli/chunks/daemon-XUEC47EC.js +0 -4
  255. package/dist-cli/chunks/desktop-LLHMP4A3.js +0 -31
  256. package/dist-cli/chunks/detox-QLNWLXA4.js +0 -52
  257. package/dist-cli/chunks/drivers-7IU37M2E.js +0 -4
  258. package/dist-cli/chunks/flow-NZZLR4BN.js +0 -4
  259. package/dist-cli/chunks/help-D7URIJRD.js +0 -4
  260. package/dist-cli/chunks/inspect-TJYWKY56.js +0 -4
  261. package/dist-cli/chunks/install-desktop-LD3W5RS7.js +0 -4
  262. package/dist-cli/chunks/mode-ZQ6H7KWM.js +0 -26
  263. package/dist-cli/chunks/permissions-DRZ3HCFL.js +0 -13
  264. package/dist-cli/chunks/record-J5JAYW4Y.js +0 -72
  265. package/dist-cli/chunks/reset-KXYRDEFU.js +0 -4
  266. package/dist-cli/chunks/runtime-66CEPOG6.js +0 -4
  267. package/dist-cli/chunks/setup-QO5KZAX3.js +0 -32
  268. package/dist-cli/chunks/storage-X2K2MDPX.js +0 -37
  269. package/dist-cli/chunks/store-TUJPIRTT.js +0 -4
  270. package/dist-cli/chunks/telemetry-CF5DVEKI.js +0 -4
  271. package/dist-cli/chunks/upload-UIQJIBEZ.js +0 -4
  272. package/dist-cli/chunks/version-CMBB3FXL.js +0 -6
@@ -1,15 +1,21 @@
1
- // sootsim metro plugin serves the sootsim shell at /__soot/ on metro's server.
1
+ // rnx metro plugin for opt-in dev shell and production bundle integration.
2
2
  // shell assets come from an engine runtime under ~/.sootsim/runtimes/, fetched
3
3
  // by `sootsim runtime install` / `sootsim setup`. ordinary localhost requests
4
4
  // follow active; a version-owned localhost origin stays on its exact directory
5
5
  // when active changes, so one loaded shell cannot mix runtime chunk trees.
6
6
  //
7
7
  // usage in metro.config.js:
8
- // const { withSootsim } = require('sootsim/metro')
9
- // module.exports = withSootsim(getDefaultConfig(__dirname))
8
+ // const { withRNX } = require('rnxsim/metro')
9
+ // module.exports = withRNX(getDefaultConfig(__dirname), { devServer: true })
10
10
 
11
11
  import fs from 'fs'
12
+ import { createRequire } from 'module'
12
13
  import path from 'path'
14
+ import {
15
+ RNXSIM_METRO_PRODUCTION_BUNDLE_OPTION,
16
+ createRNXMetroModulePathsFooter,
17
+ toRNXProductionBundleUrl,
18
+ } from './metro-production-bundle'
13
19
  import {
14
20
  isRootRuntimeAssetPath,
15
21
  resolveRuntimeFilePath,
@@ -19,32 +25,260 @@ import {
19
25
  } from './runtime-assets'
20
26
 
21
27
  const prefix = '/__soot'
28
+ export { toRNXProductionBundleUrl }
29
+
30
+ const hostModuleSpecifiers = [
31
+ 'react',
32
+ 'react-dom',
33
+ 'react/jsx-runtime',
34
+ 'react/jsx-dev-runtime',
35
+ 'react-native',
36
+ 'react-native-web',
37
+ ] as const
38
+
39
+ type MetroResolverContext = {
40
+ customResolverOptions?: Record<string, unknown>
41
+ resolveRequest: MetroResolver
42
+ }
43
+
44
+ type MetroResolution = {
45
+ type: string
46
+ filePath?: string
47
+ [key: string]: unknown
48
+ }
49
+
50
+ type MetroResolver = (
51
+ context: MetroResolverContext,
52
+ moduleName: string,
53
+ platform: string | null,
54
+ ) => MetroResolution
55
+
56
+ type MetroSerializerGraph = {
57
+ dependencies?: ReadonlyMap<unknown, { path: string }>
58
+ transformOptions?: {
59
+ dev?: boolean
60
+ customTransformOptions?: Record<string, unknown>
61
+ }
62
+ }
63
+
64
+ type MetroSerializerOptions = {
65
+ createModuleId?: (modulePath: string) => number
66
+ dev?: boolean
67
+ [key: string]: unknown
68
+ }
69
+
70
+ type MetroSerializerResult = string | { code: string; map: string }
22
71
 
23
- export interface SootsimMetroOptions {
72
+ type MetroSerializer = (
73
+ entryPoint: string,
74
+ preModules: readonly unknown[],
75
+ graph: MetroSerializerGraph,
76
+ options: MetroSerializerOptions,
77
+ ) => MetroSerializerResult | Promise<MetroSerializerResult>
78
+
79
+ export interface RNXMetroOptions {
24
80
  bundleUrl?: string
25
- enabled?: boolean
81
+ devServer?: boolean
82
+ productionBundles?: boolean
26
83
  }
27
84
 
28
85
  // the slice of metro's config we touch — keeps `T` open for whatever
29
86
  // shape consumers pass while letting us extend `server.enhanceMiddleware`.
30
87
  type MetroConfigWithServer = {
88
+ projectRoot?: string
89
+ watchFolders?: readonly string[]
90
+ resolver?: {
91
+ resolveRequest?: MetroResolver
92
+ [key: string]: unknown
93
+ }
94
+ serializer?: {
95
+ customSerializer?: MetroSerializer
96
+ [key: string]: unknown
97
+ }
31
98
  server?: {
32
99
  enhanceMiddleware?: (middleware: unknown, server: unknown) => unknown
33
100
  [key: string]: unknown
34
101
  }
35
102
  }
36
103
 
37
- export function withSootsim<T extends Record<string, unknown>>(
104
+ function isRNXProductionBundle(graph: MetroSerializerGraph): boolean {
105
+ return (
106
+ graph.transformOptions?.dev === false &&
107
+ graph.transformOptions.customTransformOptions?.[
108
+ RNXSIM_METRO_PRODUCTION_BUNDLE_OPTION
109
+ ] === 'true'
110
+ )
111
+ }
112
+
113
+ function assertProductionEnvironment(): void {
114
+ if (process.env.NODE_ENV === 'production') return
115
+ throw new Error(
116
+ 'rnxsim: production bundle requests require NODE_ENV=production; restart Metro with NODE_ENV=production',
117
+ )
118
+ }
119
+
120
+ function hostModuleFileName(specifier: (typeof hostModuleSpecifiers)[number]): string {
121
+ return `${specifier.replaceAll('/', '__')}.js`
122
+ }
123
+
124
+ function resolveHostModules(): { root: string; files: ReadonlyMap<string, string> } {
125
+ const root = path.join(__dirname, 'metro-host-modules')
126
+ const files = new Map<string, string>()
127
+
128
+ for (const specifier of hostModuleSpecifiers) {
129
+ const filePath = path.join(root, hostModuleFileName(specifier))
130
+ files.set(specifier, filePath)
131
+ }
132
+
133
+ return { root, files }
134
+ }
135
+
136
+ function readCallableMetroExport(
137
+ moduleValue: unknown,
138
+ label: string,
139
+ ): (...args: readonly unknown[]) => unknown {
140
+ const callable =
141
+ typeof moduleValue === 'function'
142
+ ? moduleValue
143
+ : typeof moduleValue === 'object' && moduleValue !== null
144
+ ? Reflect.get(moduleValue, 'default')
145
+ : undefined
146
+ if (typeof callable !== 'function') {
147
+ throw new Error(`rnxsim: Metro ${label} module did not export a function`)
148
+ }
149
+ return (...args) => Reflect.apply(callable, undefined, args)
150
+ }
151
+
152
+ function createMetroDefaultSerializer(projectRoot: string): MetroSerializer {
153
+ const projectRequire = createRequire(path.join(projectRoot, 'package.json'))
154
+ const metroRoot = path.dirname(projectRequire.resolve('metro/package.json'))
155
+ const baseJSBundle = readCallableMetroExport(
156
+ projectRequire(path.join(metroRoot, 'src/DeltaBundler/Serializers/baseJSBundle.js')),
157
+ 'baseJSBundle',
158
+ )
159
+ const bundleToString = readCallableMetroExport(
160
+ projectRequire(path.join(metroRoot, 'src/lib/bundleToString.js')),
161
+ 'bundleToString',
162
+ )
163
+
164
+ return (entryPoint, preModules, graph, options) => {
165
+ const serialized = bundleToString(
166
+ baseJSBundle(entryPoint, preModules, graph, options),
167
+ )
168
+ const code =
169
+ typeof serialized === 'object' && serialized !== null
170
+ ? Reflect.get(serialized, 'code')
171
+ : undefined
172
+ if (typeof code !== 'string') {
173
+ throw new Error('rnxsim: Metro bundleToString did not return bundle code')
174
+ }
175
+ return code
176
+ }
177
+ }
178
+
179
+ function prependRNXModulePaths(
180
+ result: MetroSerializerResult,
181
+ graph: MetroSerializerGraph,
182
+ options: MetroSerializerOptions,
183
+ projectRoot: string,
184
+ ): MetroSerializerResult {
185
+ const dependencies = graph.dependencies
186
+ const createModuleId = options.createModuleId
187
+ if (!dependencies || !createModuleId) {
188
+ throw new Error(
189
+ 'rnxsim: Metro did not provide the production module graph and createModuleId',
190
+ )
191
+ }
192
+
193
+ const modulePaths: Record<string, string> = {}
194
+ for (const module of dependencies.values()) {
195
+ modulePaths[String(createModuleId(module.path))] = path
196
+ .relative(projectRoot, module.path)
197
+ .replaceAll(path.sep, '/')
198
+ }
199
+ if (Object.keys(modulePaths).length !== dependencies.size) {
200
+ throw new Error('rnxsim: production module IDs were not unique')
201
+ }
202
+
203
+ const footer = createRNXMetroModulePathsFooter(modulePaths)
204
+ return typeof result === 'string'
205
+ ? result + footer
206
+ : { ...result, code: result.code + footer }
207
+ }
208
+
209
+ export function withRNX<T extends Record<string, unknown>>(
38
210
  config: T,
39
- options: SootsimMetroOptions = {},
211
+ options: RNXMetroOptions = {},
40
212
  ): T {
41
- if (options.enabled === false) return config
213
+ if (!options.devServer && !options.productionBundles) return config
42
214
 
43
215
  const bundleUrl =
44
216
  options.bundleUrl || '/index.bundle?platform=ios&dev=true&hot=true&minify=false'
45
217
 
46
218
  const cfgServer = (config as MetroConfigWithServer).server
219
+ const cfgResolver = (config as MetroConfigWithServer).resolver
220
+ const cfgSerializer = (config as MetroConfigWithServer).serializer
221
+ const cfgProjectRoot = (config as MetroConfigWithServer).projectRoot || process.cwd()
47
222
  const existingEnhance = cfgServer?.enhanceMiddleware
223
+ const existingResolveRequest = cfgResolver?.resolveRequest
224
+ const existingSerializer = cfgSerializer?.customSerializer
225
+ let productionConfig: Partial<MetroConfigWithServer> = {}
226
+
227
+ if (options.productionBundles) {
228
+ const hostModules = resolveHostModules()
229
+ let defaultSerializer: MetroSerializer | undefined
230
+
231
+ productionConfig = {
232
+ watchFolders: [
233
+ ...((config as MetroConfigWithServer).watchFolders || []),
234
+ hostModules.root,
235
+ ],
236
+ resolver: {
237
+ ...cfgResolver,
238
+ resolveRequest: (
239
+ context: MetroResolverContext,
240
+ moduleName: string,
241
+ platform: string | null,
242
+ ) => {
243
+ if (
244
+ context.customResolverOptions?.[RNXSIM_METRO_PRODUCTION_BUNDLE_OPTION] ===
245
+ 'true'
246
+ ) {
247
+ assertProductionEnvironment()
248
+ const hostModule = hostModules.files.get(moduleName)
249
+ if (hostModule) return { type: 'sourceFile', filePath: hostModule }
250
+ }
251
+ return existingResolveRequest
252
+ ? existingResolveRequest(context, moduleName, platform)
253
+ : context.resolveRequest(context, moduleName, platform)
254
+ },
255
+ },
256
+ serializer: {
257
+ ...cfgSerializer,
258
+ customSerializer: async (
259
+ entryPoint: string,
260
+ preModules: readonly unknown[],
261
+ graph: MetroSerializerGraph,
262
+ serializerOptions: MetroSerializerOptions,
263
+ ) => {
264
+ const serializer =
265
+ existingSerializer ||
266
+ (defaultSerializer ||= createMetroDefaultSerializer(cfgProjectRoot))
267
+ const productionBundle = isRNXProductionBundle(graph)
268
+ if (productionBundle) assertProductionEnvironment()
269
+ const result = await serializer(
270
+ entryPoint,
271
+ preModules,
272
+ graph,
273
+ serializerOptions,
274
+ )
275
+ return productionBundle
276
+ ? prependRNXModulePaths(result, graph, serializerOptions, cfgProjectRoot)
277
+ : result
278
+ },
279
+ },
280
+ }
281
+ }
48
282
 
49
283
  const serverConfig = {
50
284
  ...cfgServer,
@@ -67,6 +301,7 @@ export function withSootsim<T extends Record<string, unknown>>(
67
301
  server.use((req: any, res: any, next: any) => {
68
302
  const url = req.url || ''
69
303
  const pathname = url.split('?')[0]
304
+
70
305
  const runtimeRoot = resolveRuntimeRootForRequestHost(req.headers?.host)
71
306
 
72
307
  if (!runtimeRoot) {
@@ -133,7 +368,11 @@ export function withSootsim<T extends Record<string, unknown>>(
133
368
  },
134
369
  }
135
370
 
136
- return { ...config, server: serverConfig } as T
371
+ return {
372
+ ...config,
373
+ ...productionConfig,
374
+ ...(options.devServer ? { server: serverConfig } : {}),
375
+ } as T
137
376
  }
138
377
 
139
- export default withSootsim
378
+ export default withRNX
@@ -0,0 +1,51 @@
1
+ export const RNXSIM_METRO_PRODUCTION_BUNDLE_OPTION = 'rnxsim'
2
+ const RNXSIM_METRO_MODULE_PATHS_PREFIX = 'globalThis.__sootsimModulePaths='
3
+
4
+ export type RNXMetroModulePathMap = Record<string, string>
5
+ export interface RNXMetroModuleIdentity {
6
+ source: string
7
+ modulePaths: RNXMetroModulePathMap
8
+ }
9
+
10
+ export function toRNXProductionBundleUrl(bundleUrl: string): string {
11
+ const relative = bundleUrl.startsWith('/')
12
+ const url = new URL(bundleUrl, 'http://rnxsim.local')
13
+ url.searchParams.set('dev', 'false')
14
+ url.searchParams.set('hot', 'false')
15
+ url.searchParams.set('minify', 'true')
16
+ url.searchParams.set(`resolver.${RNXSIM_METRO_PRODUCTION_BUNDLE_OPTION}`, 'true')
17
+ url.searchParams.set(`transform.${RNXSIM_METRO_PRODUCTION_BUNDLE_OPTION}`, 'true')
18
+ return relative ? `${url.pathname}${url.search}${url.hash}` : url.toString()
19
+ }
20
+
21
+ export function createRNXMetroModulePathsFooter(
22
+ modulePaths: RNXMetroModulePathMap,
23
+ ): string {
24
+ const payload = JSON.stringify(modulePaths)
25
+ .replace(/\u2028/g, '\\u2028')
26
+ .replace(/\u2029/g, '\\u2029')
27
+ .replace(/<\//g, '<\\/')
28
+ return `\n${RNXSIM_METRO_MODULE_PATHS_PREFIX}${payload};`
29
+ }
30
+
31
+ export function readRNXMetroModuleIdentity(
32
+ bundleText: string,
33
+ ): RNXMetroModuleIdentity | null {
34
+ const footerPrefix = `\n${RNXSIM_METRO_MODULE_PATHS_PREFIX}`
35
+ const footerStart = bundleText.lastIndexOf(footerPrefix)
36
+ if (footerStart < 0 || !bundleText.endsWith(';')) return null
37
+
38
+ const parsed: unknown = JSON.parse(
39
+ bundleText.slice(footerStart + footerPrefix.length, -1),
40
+ )
41
+ if (typeof parsed !== 'object' || parsed === null || Array.isArray(parsed)) {
42
+ return null
43
+ }
44
+
45
+ const modulePaths: RNXMetroModulePathMap = {}
46
+ for (const [moduleId, modulePath] of Object.entries(parsed)) {
47
+ if (typeof modulePath !== 'string') return null
48
+ modulePaths[moduleId] = modulePath
49
+ }
50
+ return { source: bundleText.slice(0, footerStart), modulePaths }
51
+ }
@@ -3,7 +3,7 @@ const name = 'rnx'
3
3
  export const rnxPublicBrand = Object.freeze({
4
4
  name,
5
5
  packageName: 'rnxsim',
6
- commandName: 'rnxsim',
6
+ commandName: 'rnx',
7
7
  domain: 'rnxsim.com',
8
8
  origin: 'https://rnxsim.com',
9
9
  })
@@ -0,0 +1,25 @@
1
+ /**
2
+ * react-native specifiers whose upstream JavaScript must stay in a guest bundle.
3
+ *
4
+ * rnx owns the rest of the react-native package through its host-module registry.
5
+ * these modules instead run against globals installed by the simulator, which
6
+ * preserves upstream platform, style, event-emitter, and TurboModule behavior.
7
+ */
8
+ export const REACT_NATIVE_PASSTHROUGH_SPECIFIERS: readonly string[] = [
9
+ 'react-native/Libraries/vendor/emitter',
10
+ 'react-native/Libraries/Components/View/ReactNativeStyleAttributes',
11
+ 'react-native/Libraries/StyleSheet',
12
+ 'react-native/Libraries/Utilities/differ',
13
+ 'react-native/Libraries/Utilities/stringifySafe',
14
+ 'react-native/src/private/featureflags',
15
+ 'react-native/Libraries/TurboModule/TurboModuleRegistry',
16
+ 'react-native/Libraries/Utilities/Platform',
17
+ 'react-native/Libraries/Utilities/NativePlatformConstants',
18
+ 'react-native/src/private/specs_DEPRECATED/modules/NativePlatformConstants',
19
+ ]
20
+
21
+ export function isReactNativePassthroughSpecifier(specifier: string): boolean {
22
+ return REACT_NATIVE_PASSTHROUGH_SPECIFIERS.some(
23
+ (passthrough) => specifier === passthrough || specifier.startsWith(`${passthrough}/`),
24
+ )
25
+ }
@@ -9,7 +9,7 @@ import { isValidRuntimeVersion } from '@contrast/runtime-delivery'
9
9
  import { readActiveRuntime, runtimeDir } from './home-paths.ts'
10
10
 
11
11
  export const SOOTSIM_RUNTIME_MISSING_MESSAGE =
12
- '[rnx] no engine runtime installed — run `rnxsim setup`, or `rnxsim runtime install`'
12
+ '[rnx] no engine runtime installed — run `rnx setup`, or `rnx runtime install`'
13
13
 
14
14
  // --- dev-checkout mode boundary --------------------------------------------
15
15
  //
package/src/sim-client.ts CHANGED
@@ -1,4 +1,4 @@
1
- // SimClient — the typed, promise-based client every rnxsim frontend drives a
1
+ // SimClient — the typed, promise-based client every rnx frontend drives a
2
2
  // sim through. it wraps a bridge transport (the CLI's ws bridge, or any
3
3
  // InspectBridge-shaped channel) and reuses the existing inspect verbs as its
4
4
  // implementation; it never re-implements tap resolution, find, settling, or