rnxsim 0.1.432 → 0.1.434

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 (83) hide show
  1. package/README.md +20 -50
  2. package/cli/auth.ts +33 -3
  3. package/cli/cloud-client.ts +577 -99
  4. package/cli/cloud-dispatch.ts +5 -10
  5. package/cli/cloud-session.ts +5 -5
  6. package/cli/commands/auth.ts +13 -2
  7. package/cli/commands/box.ts +270 -26
  8. package/cli/commands/control.ts +40 -13
  9. package/cli/commands/device.ts +1 -1
  10. package/cli/commands/flow.ts +189 -43
  11. package/cli/commands/inspect/get-layout.ts +1 -1
  12. package/cli/commands/inspect.ts +8 -1
  13. package/cli/commands/login.ts +79 -14
  14. package/cli/commands/maestro-generate.ts +70 -54
  15. package/cli/commands/maestro.ts +69 -20
  16. package/cli/commands/platform.ts +30 -32
  17. package/cli/commands/screenshot.ts +3 -2
  18. package/cli/commands/upload.ts +28 -10
  19. package/cli/help-core.ts +11 -1
  20. package/cli/outbound-endpoints.ts +32 -5
  21. package/cli/parse-args.ts +17 -0
  22. package/cli/send-to-box.ts +112 -0
  23. package/cli/shell-init.ts +4 -4
  24. package/cli/ws-bridge.ts +109 -62
  25. package/dist-lib/agent-daemon-client.cjs +1 -1
  26. package/dist-lib/agent-events.cjs +1 -1
  27. package/dist-lib/agent-identity.cjs +1 -1
  28. package/dist-lib/agent-sessions.cjs +1 -1
  29. package/dist-lib/attached-projects.cjs +1 -1
  30. package/dist-lib/auth/shared-session.cjs +17 -4
  31. package/dist-lib/backend-origin.cjs +1 -1
  32. package/dist-lib/beta.cjs +1 -1
  33. package/dist-lib/beta.mjs +1 -1
  34. package/dist-lib/bridge-constants.cjs +1 -1
  35. package/dist-lib/bridge-contract-input.cjs +1 -1
  36. package/dist-lib/bridge-contract-input.mjs +1 -1
  37. package/dist-lib/bridge-contract.cjs +1 -1
  38. package/dist-lib/bridge-contract.mjs +1 -1
  39. package/dist-lib/capture-contract.cjs +1 -1
  40. package/dist-lib/capture-contract.mjs +1 -1
  41. package/dist-lib/cli-constants.cjs +1 -1
  42. package/dist-lib/cloud-contract.cjs +1 -1
  43. package/dist-lib/cloud-contract.mjs +1 -1
  44. package/dist-lib/cloud.cjs +108 -93
  45. package/dist-lib/cloud.mjs +106 -91
  46. package/dist-lib/config.cjs +1 -1
  47. package/dist-lib/detox/index.cjs +1 -1
  48. package/dist-lib/dev-bundle-resolution.cjs +1 -1
  49. package/dist-lib/home-paths.cjs +1 -1
  50. package/dist-lib/host/bridge-host.cjs +5324 -1371
  51. package/dist-lib/host/fetch-proxy-handler.cjs +1 -1
  52. package/dist-lib/host/fetch-proxy-overrides.cjs +1 -1
  53. package/dist-lib/host/fetch-proxy-overrides.mjs +1 -1
  54. package/dist-lib/host/replacement-module-handler.cjs +298 -91
  55. package/dist-lib/host/websocket-proxy.cjs +1 -1
  56. package/dist-lib/index.cjs +369 -241
  57. package/dist-lib/jump-to-source-babel.cjs +1 -1
  58. package/dist-lib/menu.cjs +7 -1
  59. package/dist-lib/menu.mjs +7 -1
  60. package/dist-lib/metro-fingerprint-registry.cjs +1 -1
  61. package/dist-lib/metro-fingerprint-registry.mjs +1 -1
  62. package/dist-lib/metro-production-bundle.cjs +1 -1
  63. package/dist-lib/metro-production-bundle.mjs +1 -1
  64. package/dist-lib/metro.cjs +327 -299
  65. package/dist-lib/profiles.cjs +1 -1
  66. package/dist-lib/public-brand.cjs +1 -1
  67. package/dist-lib/react-native-host-modules.cjs +1 -1
  68. package/dist-lib/react-native-host-modules.mjs +1 -1
  69. package/dist-lib/render-mode.cjs +1 -1
  70. package/dist-lib/scripts/dev-server-scanner.cjs +1 -1
  71. package/dist-lib/sdk.cjs +1 -1
  72. package/dist-lib/sdk.mjs +1 -1
  73. package/dist-lib/skills.cjs +4849 -1199
  74. package/dist-lib/vite.cjs +298 -91
  75. package/package.json +3 -2
  76. package/src/auth/shared-session.ts +31 -0
  77. package/src/bridge-contract.ts +6 -0
  78. package/src/cloud.ts +83 -113
  79. package/src/host/bridge-host.ts +79 -0
  80. package/src/host/replacement-module-handler.ts +20 -96
  81. package/src/menu.ts +8 -0
  82. package/src/metro-plugin.ts +30 -113
  83. package/src/vite-plugin.ts +11 -2
package/README.md CHANGED
@@ -373,59 +373,29 @@ const { withRNX } = require('rnxsim/metro')
373
373
 
374
374
  const config = getDefaultConfig(__dirname)
375
375
 
376
- module.exports = withRNX(config, { open: { appName: 'My App' } })
376
+ module.exports = withRNX(config)
377
377
  ```
378
378
 
379
- The `open` option serves the RNX shell and opens the app in its own named
380
- Electron window. `open: true` derives the name from `package.json`; use the
381
- object form when the display name differs. Run `rnx desktop install` once before
382
- enabling it. The macOS desktop download is about 109 MiB and the installed app
383
- uses about 267 MiB, so the browser remains the recommended first-run path and
384
- Electron is an opt-in desktop upgrade. The notarized CLI install did not produce
385
- a Gatekeeper prompt on a clean profile. A Mac that previously ran an unsigned
386
- development Electron build against the same user-data directory may ask for
387
- one-time Keychain approval. `RNX_NO_OPEN=1` keeps the server headless. The
388
- Metro wrapper also has three independent non-window opt-ins.
389
- `devServer` serves the RNX shell from the Metro process. `productionBundles`
390
- appends Metro's exact module identity to every production bundle, as a trailing
391
- `globalThis.__sootsimModulePaths = { ... }` assignment. The versioned value
392
- contains the module-ID-to-source-path map and the incoming bare logical
393
- specifiers Metro resolved for each module. Logical specifiers keep identity
394
- exact when a custom resolver maps a host package such as `react` outside
395
- `node_modules`. `developmentBundles` appends the same identity to every
396
- ordinary development bundle while keeping `__DEV__`, verbose module names, and
397
- the source map.
398
-
399
- That footer is the only change. Metro drops the fourth `__d` argument when
400
- `dev` is false, so a production bundle names none of its modules, and RNX needs
401
- those names to recognize React, React Native, and native compatibility seams at
402
- load time. Resolution, transforms, minification, and the source map stay the
403
- app's own, so the annotated bundle is the bundle you ship: the footer assigns
404
- one unused global on a device, and Hermes drops it during bytecode compilation.
405
-
406
- RNX also accepts an ordinary, unannotated Metro production JavaScript bundle.
407
- That path reports identity as `inferred` and matches package graph fingerprints
408
- from a separately updated, integrity-checked registry. It is deliberately less
409
- strong than the plugin path: ambiguous packages stay unknown, every unknown
410
- module receives a nonmatching synthetic name, and React must be identified
411
- exactly or the load stops before app code runs. Hermes bytecode is not a
412
- supported input; pass RNX the JavaScript bundle produced before Hermes
413
- compilation. Use `productionBundles: true` when exact identity is required.
379
+ rnx works directly with regular, unannotated Metro production JavaScript bundles
380
+ out of the box. It identifies modules by matching package graph fingerprints
381
+ against a separately updated, integrity-checked registry. Hermes bytecode is not
382
+ a supported input; pass rnx the JavaScript bundle produced before Hermes
383
+ compilation.
414
384
 
415
- ```js
416
- module.exports = withRNX(config, { productionBundles: true })
417
-
418
- // enable any combination when one Metro process should provide them
419
- module.exports = withRNX(config, {
420
- devServer: true,
421
- productionBundles: true,
422
- developmentBundles: true,
423
- })
424
- ```
385
+ If an app has unusual dependencies or fingerprint inference fails, you can
386
+ optionally wrap your Metro configuration with `withRNX(config)`. It takes no
387
+ options and enables two integrations:
388
+
389
+ 1. **Deterministic module identity:** appends Metro's exact module identity map
390
+ as a trailing `globalThis.__sootsimModulePaths = { ... }` footer to every
391
+ bundle. Resolution, transforms, minification, and source maps stay the app's
392
+ own, so the annotated bundle is the exact bundle you ship: the footer assigns
393
+ one unused global on a device, and Hermes drops it during bytecode compilation.
394
+ 2. **In-browser dev shell:** serves the rnx simulator shell at `/__soot/` on
395
+ the Metro dev server.
425
396
 
426
- Calling `withRNX(config)` changes nothing. The URL helpers request ordinary
427
- Metro graphs: `dev=false&minify=true` for production and
428
- `dev=true&minify=false` for development.
397
+ The URL helpers request ordinary Metro graphs: `dev=false&minify=true` for
398
+ production and `dev=true&minify=false` for development.
429
399
 
430
400
  ```js
431
401
  const {
@@ -514,7 +484,7 @@ For plan-driven app-store exports, use `rnx screenshot appstore`:
514
484
 
515
485
  ```yaml
516
486
  app: 8081
517
- device: iphone-14
487
+ device: iphone-16
518
488
 
519
489
  capture:
520
490
  flow: .maestro/capture-app-store-screenshots.yaml
package/cli/auth.ts CHANGED
@@ -8,7 +8,10 @@
8
8
  //
9
9
  // callers wanting an auth header: `authHeaderOrExit('upload')`.
10
10
 
11
- import { readSharedDesktopAuthSession } from '../src/auth/shared-session'
11
+ import {
12
+ readSharedDesktopAuthSession,
13
+ sharedDesktopAuthAccounts,
14
+ } from '../src/auth/shared-session'
12
15
  import { rnxExit } from './run-rnx'
13
16
 
14
17
  export type CliApiKeyEnvName = 'RNX_API_KEY'
@@ -27,7 +30,15 @@ export type CliAuth =
27
30
  installationId: string | null
28
31
  source: 'contrast-runner' | 'github-actions'
29
32
  }
30
- | { kind: 'session'; token: string; origin: string }
33
+ | {
34
+ kind: 'session'
35
+ token: string
36
+ origin: string
37
+ // the account this sign-in bills cloud sessions to. null when the person
38
+ // belongs to several accounts and has not chosen one with `rnx login
39
+ // --account`; a person with exactly one account never has to choose.
40
+ accountId: string | null
41
+ }
31
42
 
32
43
  export type GitHubUploadIdentity = {
33
44
  repoId: string
@@ -116,11 +127,30 @@ export function resolveCliAuth(): CliAuth | null {
116
127
  if (githubAuth) return githubAuth
117
128
  const session = readSharedDesktopAuthSession()
118
129
  if (session?.token) {
119
- return { kind: 'session', token: session.token, origin: session.origin }
130
+ const accounts = sharedDesktopAuthAccounts(session.user)
131
+ return {
132
+ kind: 'session',
133
+ token: session.token,
134
+ origin: session.origin,
135
+ accountId:
136
+ session.accountId ?? (accounts.length === 1 ? (accounts[0]?.id ?? null) : null),
137
+ }
120
138
  }
121
139
  return null
122
140
  }
123
141
 
142
+ export const CHOOSE_ACCOUNT_HINT =
143
+ 'this sign-in belongs to several accounts; run `rnx login --account <name>` to choose the one to bill'
144
+
145
+ // the account a request that opens a paid cloud session names. an api key
146
+ // names its own account, so it sends none; a session token has to say.
147
+ export function cloudAccountIdOrExit(auth: CliAuth): string | null {
148
+ if (auth.kind !== 'session') return null
149
+ if (auth.accountId) return auth.accountId
150
+ process.stderr.write(`\n ${CHOOSE_ACCOUNT_HINT}\n\n`)
151
+ rnxExit(1)
152
+ }
153
+
124
154
  export function authHeaderValue(auth: CliAuth): string {
125
155
  return auth.kind === 'api-key' ? `Bearer ${auth.secret}` : `Bearer ${auth.token}`
126
156
  }