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.
- package/README.md +104 -76
- package/cli/auth.ts +2 -2
- package/cli/bin.ts +7 -3
- package/cli/bridge-flow-runner.ts +2 -2
- package/cli/commands/agent-wrapper.ts +1 -1
- package/cli/commands/agent.ts +12 -12
- package/cli/commands/app-fonts.ts +1 -1
- package/cli/commands/assert.ts +7 -7
- package/cli/commands/auth.ts +4 -4
- package/cli/commands/camera.ts +13 -13
- package/cli/commands/cleanup.ts +6 -6
- package/cli/commands/compat.ts +4 -4
- package/cli/commands/config.ts +2 -2
- package/cli/commands/control.ts +37 -43
- package/cli/commands/cpu-profile.ts +2 -2
- package/cli/commands/daemon-mac-app.ts +2 -2
- package/cli/commands/daemon.ts +12 -12
- package/cli/commands/debug.ts +22 -22
- package/cli/commands/desktop.ts +3 -3
- package/cli/commands/detox.ts +17 -17
- package/cli/commands/device.ts +9 -9
- package/cli/commands/diagnose.ts +11 -11
- package/cli/commands/electron.ts +7 -7
- package/cli/commands/film.ts +6 -6
- package/cli/commands/inspect/core.ts +6 -7
- package/cli/commands/inspect/find.ts +2 -2
- package/cli/commands/inspect.ts +36 -36
- package/cli/commands/install-desktop.ts +8 -8
- package/cli/commands/login.ts +6 -6
- package/cli/commands/maestro-generate.ts +2 -2
- package/cli/commands/maestro.ts +23 -23
- package/cli/commands/mode.ts +4 -4
- package/cli/commands/no-bridge-hint.ts +9 -9
- package/cli/commands/perf.ts +11 -11
- package/cli/commands/permissions.ts +5 -5
- package/cli/commands/profile.ts +11 -11
- package/cli/commands/react.ts +15 -15
- package/cli/commands/record.ts +15 -15
- package/cli/commands/report-issue.ts +2 -2
- package/cli/commands/reset.ts +2 -2
- package/cli/commands/runtime.ts +18 -18
- package/cli/commands/screenshot-mode.ts +5 -5
- package/cli/commands/screenshot.ts +12 -12
- package/cli/commands/screenshots-capture.ts +7 -7
- package/cli/commands/screenshots.ts +6 -6
- package/cli/commands/serve.ts +6 -6
- package/cli/commands/setup.ts +13 -15
- package/cli/commands/skills.ts +14 -14
- package/cli/commands/slides.ts +19 -23
- package/cli/commands/state.ts +2 -2
- package/cli/commands/storage.ts +3 -3
- package/cli/commands/telemetry.ts +1 -1
- package/cli/commands/three-mode.ts +16 -16
- package/cli/commands/timeline.ts +4 -4
- package/cli/commands/upgrade.ts +1 -1
- package/cli/commands/upload.ts +11 -11
- package/cli/commands/version.ts +3 -5
- package/cli/commands/what-happened.ts +11 -11
- package/cli/drivers/electron.ts +3 -3
- package/cli/hints.ts +8 -8
- package/cli/recording-access.ts +1 -1
- package/cli/ws-bridge.ts +5 -5
- package/dist-cli/bin.js +5 -5
- package/dist-cli/chunks/{agent-XSJMAFVA.js → agent-QQ3RJNRY.js} +14 -14
- package/dist-cli/chunks/{agent-wrapper-NFLJ5K64.js → agent-wrapper-M6SQSMRY.js} +3 -3
- package/dist-cli/chunks/app-fonts-F6NDV3XC.js +4 -0
- package/dist-cli/chunks/{assert-ILAXIYB5.js → assert-5VB3KQNK.js} +12 -12
- package/dist-cli/chunks/auth-PFXODKFN.js +12 -0
- package/dist-cli/chunks/{beta-TDR6UKJU.js → beta-WUWYHT4F.js} +2 -2
- package/dist-cli/chunks/camera-V3MMTKP7.js +33 -0
- package/dist-cli/chunks/{chunk-INBPUR4T.js → chunk-2ANFH72P.js} +11 -11
- package/dist-cli/chunks/chunk-2GIA5T6B.js +74 -0
- package/dist-cli/chunks/{chunk-GP6QEBZA.js → chunk-4FRSEZ7Z.js} +1 -1
- package/dist-cli/chunks/{chunk-USGOQ3YJ.js → chunk-4GXBZHNA.js} +2 -2
- package/dist-cli/chunks/{chunk-R3CMECGC.js → chunk-4HESY5E7.js} +4 -4
- package/dist-cli/chunks/{chunk-WKT7YM5Q.js → chunk-4VJEXQGD.js} +1 -1
- package/dist-cli/chunks/{chunk-FE6ZHPKD.js → chunk-5LJNNHZH.js} +1 -1
- package/dist-cli/chunks/{chunk-I2HQB5NN.js → chunk-5QXGSTYI.js} +2 -2
- package/dist-cli/chunks/{chunk-FJSHIWAM.js → chunk-5SHAOQHJ.js} +2 -2
- package/dist-cli/chunks/{chunk-CGZWLSYD.js → chunk-5UPRBMIG.js} +1 -1
- package/dist-cli/chunks/{chunk-ZTM2MKNI.js → chunk-5ZEFRPCC.js} +1 -1
- package/dist-cli/chunks/{chunk-RTD3CPDQ.js → chunk-6ART4XVJ.js} +23 -23
- package/dist-cli/chunks/{chunk-MTD6IAEA.js → chunk-6CAUT2LH.js} +1 -1
- package/dist-cli/chunks/{chunk-ZYHCWCMM.js → chunk-7ATIH7OU.js} +1 -1
- package/dist-cli/chunks/{chunk-RVUGKXJD.js → chunk-7Q4QKHMA.js} +1 -1
- package/dist-cli/chunks/{chunk-MTNIDSOA.js → chunk-ABK2V2PR.js} +1 -1
- package/dist-cli/chunks/{chunk-TL4DNDDY.js → chunk-B53ILAHI.js} +2 -2
- package/dist-cli/chunks/{chunk-POC3QTA6.js → chunk-BSSVLFZR.js} +2 -2
- package/dist-cli/chunks/chunk-BVOBXTPN.js +30 -0
- package/dist-cli/chunks/{chunk-4KC35DMK.js → chunk-CPDEUWL5.js} +2 -2
- package/dist-cli/chunks/{chunk-HNQLZZJA.js → chunk-DINU267S.js} +2 -2
- package/dist-cli/chunks/{chunk-DCDKJ4NC.js → chunk-DQQ4CZVC.js} +2 -2
- package/dist-cli/chunks/{chunk-JWAY6DIH.js → chunk-EDWN2HOO.js} +18 -18
- package/dist-cli/chunks/{chunk-3CS4EUMG.js → chunk-EWVG4A3B.js} +2 -2
- package/dist-cli/chunks/{chunk-RTEJXUXN.js → chunk-F3NKCQHM.js} +6 -6
- package/dist-cli/chunks/{chunk-M7CBQ5I4.js → chunk-GEAGFYKP.js} +1 -1
- package/dist-cli/chunks/chunk-GGNH44PZ.js +5 -0
- package/dist-cli/chunks/{chunk-YSUIYK6B.js → chunk-HAHJJJUC.js} +2 -2
- package/dist-cli/chunks/chunk-HPJ5EKIZ.js +4 -0
- package/dist-cli/chunks/{chunk-IN2PZBQD.js → chunk-IBTHGFKE.js} +2 -2
- package/dist-cli/chunks/{chunk-ZZWO6Y7X.js → chunk-J6BYRRZQ.js} +2 -2
- package/dist-cli/chunks/{chunk-6Y3PVPTF.js → chunk-JK4OZ2TQ.js} +5 -5
- package/dist-cli/chunks/{chunk-PO3TOAED.js → chunk-KGQAO25M.js} +2 -2
- package/dist-cli/chunks/{chunk-J7XFINJG.js → chunk-L6UUIQE7.js} +2 -2
- package/dist-cli/chunks/{chunk-35XNGT5C.js → chunk-LXYLCETR.js} +1 -1
- package/dist-cli/chunks/{chunk-JWK5WD44.js → chunk-LZAL3DMP.js} +2 -2
- package/dist-cli/chunks/{chunk-3ZDOPKHE.js → chunk-M43UU7UG.js} +4 -4
- package/dist-cli/chunks/{chunk-ROPHZJ6P.js → chunk-M4LGUVBM.js} +2 -2
- package/dist-cli/chunks/{chunk-RELRA5VW.js → chunk-NCG6C5AH.js} +2 -2
- package/dist-cli/chunks/{chunk-42KDXJUD.js → chunk-NR5TSR2Y.js} +2 -2
- package/dist-cli/chunks/{chunk-R2UL5VFY.js → chunk-OCPWXT73.js} +3 -3
- package/dist-cli/chunks/{chunk-VV4MXLFR.js → chunk-ODKS6JUJ.js} +1 -1
- package/dist-cli/chunks/{chunk-F33DUJGG.js → chunk-R2WBREGQ.js} +1 -1
- package/dist-cli/chunks/chunk-RKY3ZNTA.js +5 -0
- package/dist-cli/chunks/{chunk-MGGRL2Z2.js → chunk-SW7BHOMO.js} +9 -9
- package/dist-cli/chunks/{chunk-GVKISFQ3.js → chunk-TJTLXG3R.js} +1 -1
- package/dist-cli/chunks/chunk-TNI4PW75.js +124 -0
- package/dist-cli/chunks/{chunk-CL3PREIE.js → chunk-UWEDNDND.js} +2 -2
- package/dist-cli/chunks/{chunk-IV36DY6M.js → chunk-WRID5SBV.js} +1 -1
- package/dist-cli/chunks/{chunk-42ALI64M.js → chunk-WUYI3XJ5.js} +2 -2
- package/dist-cli/chunks/{chunk-6VN5ULGQ.js → chunk-X7MHCEGG.js} +2 -2
- package/dist-cli/chunks/chunk-XIQFYLWD.js +15 -0
- package/dist-cli/chunks/{chunk-LCVUJCRJ.js → chunk-ZUK5ZQU7.js} +1 -1
- package/dist-cli/chunks/{cleanup-X6ZRPFDV.js → cleanup-6WBS3MUO.js} +10 -10
- package/dist-cli/chunks/cli-version-HUQCDGMA.js +4 -0
- package/dist-cli/chunks/{compat-VRXJ5J56.js → compat-2WOPKJYK.js} +9 -9
- package/dist-cli/chunks/{config-LHPPE4EP.js → config-FPD7WUYB.js} +5 -5
- package/dist-cli/chunks/{control-TVTNGSSF.js → control-B3XNER7I.js} +2 -2
- package/dist-cli/chunks/daemon-T4D4X2P5.js +4 -0
- package/dist-cli/chunks/{debug-EUHBBPGM.js → debug-LKV5CEAV.js} +17 -17
- package/dist-cli/chunks/desktop-EMDPOYQT.js +31 -0
- package/dist-cli/chunks/detox-4J4UTZE7.js +52 -0
- package/dist-cli/chunks/{device-PONITUZJ.js → device-PMZ7RPXQ.js} +11 -11
- package/dist-cli/chunks/{diagnose-2PN4K4L2.js → diagnose-MLEP727D.js} +12 -12
- package/dist-cli/chunks/{disk-cleanup-U2PQLOEW.js → disk-cleanup-CVEDIPEE.js} +2 -2
- package/dist-cli/chunks/drivers-NTUKJEL6.js +4 -0
- package/dist-cli/chunks/{film-XGZCFTQL.js → film-4RNECABF.js} +9 -9
- package/dist-cli/chunks/flow-5IOCAHVO.js +4 -0
- package/dist-cli/chunks/help-NUJUYEWP.js +4 -0
- package/dist-cli/chunks/{hidden-runtime-alias-I4MYF5CO.js → hidden-runtime-alias-YIF25W4F.js} +2 -2
- package/dist-cli/chunks/{home-paths-YRAPZ5LE.js → home-paths-WNJCCCCZ.js} +2 -2
- package/dist-cli/chunks/inspect-MFEIYUCN.js +4 -0
- package/dist-cli/chunks/install-desktop-NB65KI4D.js +4 -0
- package/dist-cli/chunks/{login-ZMAIAQ6F.js → login-VEHHGN42.js} +6 -6
- package/dist-cli/chunks/{logout-UQZ5JBJU.js → logout-VE7PNXL2.js} +2 -2
- package/dist-cli/chunks/{maestro-BQYKDUC4.js → maestro-ZXHTDEOI.js} +25 -25
- package/dist-cli/chunks/{maestro-generate-VQYMMQJ5.js → maestro-generate-TK33E2Z6.js} +3 -3
- package/dist-cli/chunks/mode-ZDKJ56NT.js +26 -0
- package/dist-cli/chunks/{optional-demo-registry-DUWHCLGD.js → optional-demo-registry-GBZ3WVDW.js} +2 -2
- package/dist-cli/chunks/{perf-7RAU7WRZ.js → perf-JXNZOUKW.js} +28 -28
- package/dist-cli/chunks/permissions-WQ62PW7Y.js +13 -0
- package/dist-cli/chunks/record-4S3ZMDIO.js +72 -0
- package/dist-cli/chunks/{report-issue-P376KFFU.js → report-issue-KKBADTWO.js} +4 -4
- package/dist-cli/chunks/reset-H5XIISJE.js +4 -0
- package/dist-cli/chunks/runtime-FK7EEMWA.js +4 -0
- package/dist-cli/chunks/{screenshot-command-NE7BKTQ2.js → screenshot-command-42U5MVQL.js} +34 -34
- package/dist-cli/chunks/{screenshot-layers-UE4R64PZ.js → screenshot-layers-4G42AHOX.js} +2 -2
- package/dist-cli/chunks/{screenshots-capture-ULXPLXMC.js → screenshots-capture-HMQ2OO3I.js} +11 -11
- package/dist-cli/chunks/{serve-P7BT4XHR.js → serve-S4V5EDW2.js} +16 -16
- package/dist-cli/chunks/setup-T43V7GA6.js +32 -0
- package/dist-cli/chunks/{skills-NTRYKJSF.js → skills-O426K26J.js} +16 -16
- package/dist-cli/chunks/{state-4D5YAM47.js → state-ZEEPDKJG.js} +5 -5
- package/dist-cli/chunks/storage-4GQLOFGG.js +37 -0
- package/dist-cli/chunks/store-RFMSNWLJ.js +4 -0
- package/dist-cli/chunks/telemetry-NFAAPSMN.js +4 -0
- package/dist-cli/chunks/{timeline-GZNFGD3Q.js → timeline-ONCYX7KW.js} +6 -6
- package/dist-cli/chunks/{upgrade-A46D6PEY.js → upgrade-A36T52AM.js} +2 -2
- package/dist-cli/chunks/upload-36O32DII.js +4 -0
- package/dist-cli/chunks/version-67HA253N.js +6 -0
- package/dist-cli/chunks/{web-H2IXO5SC.js → web-PWXQHQIE.js} +2 -2
- package/dist-cli/chunks/{what-happened-Z7UII5GH.js → what-happened-WNXE622R.js} +16 -16
- package/dist-lib/agent-daemon-client.cjs +5 -5
- package/dist-lib/agent-events.cjs +1 -1
- package/dist-lib/agent-identity.cjs +1 -1
- package/dist-lib/agent-sessions.cjs +4 -4
- package/dist-lib/attached-projects.cjs +1 -1
- package/dist-lib/auth/shared-session.cjs +1 -1
- package/dist-lib/backend-origin.cjs +1 -1
- package/dist-lib/beta.cjs +1 -1
- package/dist-lib/beta.mjs +1 -1
- package/dist-lib/bridge-constants.cjs +1 -1
- package/dist-lib/bridge-contract.cjs +1 -1
- package/dist-lib/cli-constants.cjs +1 -1
- package/dist-lib/config.cjs +1 -1
- package/dist-lib/detox/index.cjs +1 -1
- package/dist-lib/dev-bundle-resolution.cjs +1 -1
- package/dist-lib/home-paths.cjs +1 -1
- package/dist-lib/host/bridge-host.cjs +7 -7
- package/dist-lib/host/fetch-proxy-handler.cjs +1 -1
- package/dist-lib/host/fetch-proxy-overrides.cjs +1 -1
- package/dist-lib/host/fetch-proxy-overrides.mjs +1 -1
- package/dist-lib/host/websocket-proxy.cjs +1 -1
- package/dist-lib/index.cjs +248 -98
- package/dist-lib/jump-to-source-babel.cjs +1 -1
- package/dist-lib/menu.cjs +2 -2
- package/dist-lib/menu.mjs +2 -2
- package/dist-lib/metro-host-modules/react-dom.js +6 -0
- package/dist-lib/metro-host-modules/react-native-web.js +6 -0
- package/dist-lib/metro-host-modules/react-native.js +6 -0
- package/dist-lib/metro-host-modules/react.js +6 -0
- package/dist-lib/metro-host-modules/react__jsx-dev-runtime.js +6 -0
- package/dist-lib/metro-host-modules/react__jsx-runtime.js +6 -0
- package/dist-lib/metro-production-bundle.cjs +72 -0
- package/dist-lib/metro-production-bundle.mjs +44 -0
- package/dist-lib/metro.cjs +152 -8
- package/dist-lib/profiles.cjs +1 -1
- package/dist-lib/public-brand.cjs +2 -2
- package/dist-lib/react-native-host-modules.cjs +50 -0
- package/dist-lib/render-mode.cjs +1 -1
- package/dist-lib/scripts/dev-server-scanner.cjs +1 -1
- package/dist-lib/sdk.cjs +6 -7
- package/dist-lib/sdk.mjs +6 -7
- package/dist-lib/skills.cjs +71 -77
- package/dist-lib/vite.cjs +104 -85
- package/package.json +15 -2
- package/scripts/preuninstall.cjs +1 -1
- package/skills/contrast/SKILL.md +67 -75
- package/skills/rnx-debug/SKILL.md +84 -84
- package/skills/rnx-perf/SKILL.md +8 -8
- package/skills/rnx-setup/SKILL.md +54 -54
- package/skills/rnx-test/SKILL.md +35 -35
- package/skills/rnx-visual/SKILL.md +18 -18
- package/src/agent-daemon-client.ts +2 -2
- package/src/agent-sessions.ts +2 -2
- package/src/connect.ts +6 -6
- package/src/disk-cleanup.ts +1 -1
- package/src/home-paths.ts +1 -1
- package/src/host/bridge-host.ts +6 -6
- package/src/index.ts +1 -1
- package/src/metro-host-modules/react-dom.js +6 -0
- package/src/metro-host-modules/react-native-web.js +6 -0
- package/src/metro-host-modules/react-native.js +6 -0
- package/src/metro-host-modules/react.js +6 -0
- package/src/metro-host-modules/react__jsx-dev-runtime.js +6 -0
- package/src/metro-host-modules/react__jsx-runtime.js +6 -0
- package/src/metro-plugin.ts +249 -10
- package/src/metro-production-bundle.ts +51 -0
- package/src/public-brand.ts +1 -1
- package/src/react-native-host-modules.ts +25 -0
- package/src/runtime-assets.ts +1 -1
- package/src/sim-client.ts +1 -1
- package/src/vite-plugin-one.ts +171 -145
- package/dist-cli/chunks/app-fonts-L3UXFYVE.js +0 -4
- package/dist-cli/chunks/auth-ISX2EUQL.js +0 -12
- package/dist-cli/chunks/camera-4SWTNJUA.js +0 -33
- package/dist-cli/chunks/chunk-BRHZEZKN.js +0 -124
- package/dist-cli/chunks/chunk-EJPYPJWP.js +0 -5
- package/dist-cli/chunks/chunk-KWCD5MOK.js +0 -15
- package/dist-cli/chunks/chunk-MJ7QGY7Z.js +0 -4
- package/dist-cli/chunks/chunk-RSA4XWHN.js +0 -5
- package/dist-cli/chunks/chunk-S3EIOAWZ.js +0 -74
- package/dist-cli/chunks/chunk-TYANJQLO.js +0 -30
- package/dist-cli/chunks/cli-version-NZUSWKZR.js +0 -4
- package/dist-cli/chunks/daemon-XUEC47EC.js +0 -4
- package/dist-cli/chunks/desktop-LLHMP4A3.js +0 -31
- package/dist-cli/chunks/detox-QLNWLXA4.js +0 -52
- package/dist-cli/chunks/drivers-7IU37M2E.js +0 -4
- package/dist-cli/chunks/flow-NZZLR4BN.js +0 -4
- package/dist-cli/chunks/help-D7URIJRD.js +0 -4
- package/dist-cli/chunks/inspect-TJYWKY56.js +0 -4
- package/dist-cli/chunks/install-desktop-LD3W5RS7.js +0 -4
- package/dist-cli/chunks/mode-ZQ6H7KWM.js +0 -26
- package/dist-cli/chunks/permissions-DRZ3HCFL.js +0 -13
- package/dist-cli/chunks/record-J5JAYW4Y.js +0 -72
- package/dist-cli/chunks/reset-KXYRDEFU.js +0 -4
- package/dist-cli/chunks/runtime-66CEPOG6.js +0 -4
- package/dist-cli/chunks/setup-QO5KZAX3.js +0 -32
- package/dist-cli/chunks/storage-X2K2MDPX.js +0 -37
- package/dist-cli/chunks/store-TUJPIRTT.js +0 -4
- package/dist-cli/chunks/telemetry-CF5DVEKI.js +0 -4
- package/dist-cli/chunks/upload-UIQJIBEZ.js +0 -4
- package/dist-cli/chunks/version-CMBB3FXL.js +0 -6
package/src/metro-plugin.ts
CHANGED
|
@@ -1,15 +1,21 @@
|
|
|
1
|
-
//
|
|
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 {
|
|
9
|
-
// module.exports =
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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:
|
|
211
|
+
options: RNXMetroOptions = {},
|
|
40
212
|
): T {
|
|
41
|
-
if (options.
|
|
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 {
|
|
371
|
+
return {
|
|
372
|
+
...config,
|
|
373
|
+
...productionConfig,
|
|
374
|
+
...(options.devServer ? { server: serverConfig } : {}),
|
|
375
|
+
} as T
|
|
137
376
|
}
|
|
138
377
|
|
|
139
|
-
export default
|
|
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
|
+
}
|
package/src/public-brand.ts
CHANGED
|
@@ -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
|
+
}
|
package/src/runtime-assets.ts
CHANGED
|
@@ -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 `
|
|
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
|
|
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
|