peachsim 0.1.527

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 (324) hide show
  1. package/LICENSE +22 -0
  2. package/README.md +640 -0
  3. package/cli/app-config.ts +82 -0
  4. package/cli/app-fonts.ts +388 -0
  5. package/cli/app-project.ts +59 -0
  6. package/cli/app-splash.ts +171 -0
  7. package/cli/app-state-reset.ts +26 -0
  8. package/cli/auth.ts +184 -0
  9. package/cli/bin.ts +59 -0
  10. package/cli/bridge-diagnostics.ts +226 -0
  11. package/cli/bridge-flow-runner.ts +2806 -0
  12. package/cli/browser-backend.ts +44 -0
  13. package/cli/browser-evals.ts +96 -0
  14. package/cli/cli-update.ts +261 -0
  15. package/cli/cloud-client.ts +1530 -0
  16. package/cli/cloud-dispatch.ts +206 -0
  17. package/cli/cloud-session.ts +227 -0
  18. package/cli/command-contract.ts +221 -0
  19. package/cli/command-registry.ts +304 -0
  20. package/cli/commands/agent-wrapper.ts +1048 -0
  21. package/cli/commands/agent.ts +439 -0
  22. package/cli/commands/app-fonts.ts +99 -0
  23. package/cli/commands/assert.ts +542 -0
  24. package/cli/commands/auth.ts +71 -0
  25. package/cli/commands/box/bundle-plane.ts +71 -0
  26. package/cli/commands/box/checkout-plane.ts +256 -0
  27. package/cli/commands/box/plane-share.ts +208 -0
  28. package/cli/commands/box/rnx-command.ts +60 -0
  29. package/cli/commands/box/search-command.ts +157 -0
  30. package/cli/commands/box.ts +925 -0
  31. package/cli/commands/camera.ts +266 -0
  32. package/cli/commands/cleanup.ts +169 -0
  33. package/cli/commands/compat.ts +176 -0
  34. package/cli/commands/config.ts +34 -0
  35. package/cli/commands/control.ts +2154 -0
  36. package/cli/commands/cpu-profile.ts +941 -0
  37. package/cli/commands/daemon-mac-app.ts +165 -0
  38. package/cli/commands/daemon.ts +800 -0
  39. package/cli/commands/debug.ts +751 -0
  40. package/cli/commands/desktop.ts +39 -0
  41. package/cli/commands/detect.ts +201 -0
  42. package/cli/commands/detox.ts +481 -0
  43. package/cli/commands/device.ts +134 -0
  44. package/cli/commands/diagnose.ts +589 -0
  45. package/cli/commands/do-chain.ts +408 -0
  46. package/cli/commands/electron.ts +94 -0
  47. package/cli/commands/film.ts +379 -0
  48. package/cli/commands/flow.ts +1240 -0
  49. package/cli/commands/inspect/actions.ts +516 -0
  50. package/cli/commands/inspect/core.ts +2086 -0
  51. package/cli/commands/inspect/count.ts +17 -0
  52. package/cli/commands/inspect/describe.ts +119 -0
  53. package/cli/commands/inspect/env.ts +25 -0
  54. package/cli/commands/inspect/find.ts +169 -0
  55. package/cli/commands/inspect/get-layout.ts +53 -0
  56. package/cli/commands/inspect/keyboard.ts +54 -0
  57. package/cli/commands/inspect/list.ts +175 -0
  58. package/cli/commands/inspect/memory.ts +215 -0
  59. package/cli/commands/inspect/redaction.ts +39 -0
  60. package/cli/commands/inspect/resolve-target.ts +77 -0
  61. package/cli/commands/inspect/screens.ts +78 -0
  62. package/cli/commands/inspect/settle.ts +32 -0
  63. package/cli/commands/inspect/settling.ts +197 -0
  64. package/cli/commands/inspect/shared.ts +259 -0
  65. package/cli/commands/inspect/sleep.ts +15 -0
  66. package/cli/commands/inspect/tree.ts +23 -0
  67. package/cli/commands/inspect/url.ts +17 -0
  68. package/cli/commands/inspect/wait-event.ts +211 -0
  69. package/cli/commands/inspect/wait-idle.ts +25 -0
  70. package/cli/commands/inspect/wait-ready.ts +87 -0
  71. package/cli/commands/inspect/wait-selector.ts +59 -0
  72. package/cli/commands/inspect/wait.ts +32 -0
  73. package/cli/commands/inspect.ts +4738 -0
  74. package/cli/commands/install-cli.ts +275 -0
  75. package/cli/commands/install-desktop.ts +385 -0
  76. package/cli/commands/login.ts +357 -0
  77. package/cli/commands/logout.ts +24 -0
  78. package/cli/commands/maestro-generate.ts +375 -0
  79. package/cli/commands/maestro.ts +536 -0
  80. package/cli/commands/mode.ts +58 -0
  81. package/cli/commands/no-bridge-hint.ts +80 -0
  82. package/cli/commands/perf.ts +67 -0
  83. package/cli/commands/permissions.ts +203 -0
  84. package/cli/commands/platform.ts +410 -0
  85. package/cli/commands/preview.ts +103 -0
  86. package/cli/commands/profile.ts +106 -0
  87. package/cli/commands/react.ts +353 -0
  88. package/cli/commands/record.ts +1435 -0
  89. package/cli/commands/report-issue.ts +305 -0
  90. package/cli/commands/reset.ts +89 -0
  91. package/cli/commands/runtime.ts +348 -0
  92. package/cli/commands/screenshot-command.ts +106 -0
  93. package/cli/commands/screenshot-layers.ts +144 -0
  94. package/cli/commands/screenshot-mode.ts +38 -0
  95. package/cli/commands/screenshot.ts +492 -0
  96. package/cli/commands/screenshots-capture.ts +608 -0
  97. package/cli/commands/screenshots.ts +127 -0
  98. package/cli/commands/serve.ts +139 -0
  99. package/cli/commands/setup.ts +416 -0
  100. package/cli/commands/shell-boolean-mode.ts +82 -0
  101. package/cli/commands/skills.ts +468 -0
  102. package/cli/commands/slides.ts +357 -0
  103. package/cli/commands/state.ts +94 -0
  104. package/cli/commands/storage.ts +58 -0
  105. package/cli/commands/telemetry.ts +55 -0
  106. package/cli/commands/test.ts +535 -0
  107. package/cli/commands/three-mode.ts +771 -0
  108. package/cli/commands/timeline.ts +121 -0
  109. package/cli/commands/upgrade.ts +167 -0
  110. package/cli/commands/upload.ts +1203 -0
  111. package/cli/commands/version.ts +63 -0
  112. package/cli/commands/welcome.ts +17 -0
  113. package/cli/commands/what-happened.ts +328 -0
  114. package/cli/current-sim.ts +217 -0
  115. package/cli/desktop-companion.ts +315 -0
  116. package/cli/drivers/electron.ts +70 -0
  117. package/cli/drivers/index.ts +20 -0
  118. package/cli/drivers/playwright-provisioning.ts +184 -0
  119. package/cli/drivers/playwright-sim-host.ts +537 -0
  120. package/cli/drivers/playwright.ts +209 -0
  121. package/cli/drivers/registry.ts +65 -0
  122. package/cli/drivers/types.ts +102 -0
  123. package/cli/flow-export.ts +55 -0
  124. package/cli/flow-file.ts +142 -0
  125. package/cli/flow-live-status.ts +126 -0
  126. package/cli/flow-session.ts +140 -0
  127. package/cli/help-core.ts +143 -0
  128. package/cli/help.ts +44 -0
  129. package/cli/hidden-runtime-alias.ts +19 -0
  130. package/cli/hints.ts +214 -0
  131. package/cli/inspect-notice-state.ts +114 -0
  132. package/cli/internal-child.ts +176 -0
  133. package/cli/maestro-js.ts +323 -0
  134. package/cli/main.ts +704 -0
  135. package/cli/open-url.ts +8 -0
  136. package/cli/outbound-endpoints.ts +830 -0
  137. package/cli/parent-pid.ts +204 -0
  138. package/cli/parse-args.ts +189 -0
  139. package/cli/privacy.ts +53 -0
  140. package/cli/prompt.ts +56 -0
  141. package/cli/recording-access.ts +108 -0
  142. package/cli/registry.ts +2 -0
  143. package/cli/resolve-assets.ts +63 -0
  144. package/cli/rnx-in-process.ts +98 -0
  145. package/cli/run-registry.ts +226 -0
  146. package/cli/run-rnx-core.ts +148 -0
  147. package/cli/run-rnx.ts +137 -0
  148. package/cli/runtime-notes.ts +66 -0
  149. package/cli/runtime-summary.ts +25 -0
  150. package/cli/secure-file.ts +31 -0
  151. package/cli/self-invocation.ts +58 -0
  152. package/cli/send-to-box.ts +109 -0
  153. package/cli/setup-repository.ts +191 -0
  154. package/cli/shell-init.ts +98 -0
  155. package/cli/standalone.ts +4 -0
  156. package/cli/telemetry.ts +84 -0
  157. package/cli/ui.ts +68 -0
  158. package/cli/ws-bridge.ts +1020 -0
  159. package/detox/attempt-events.cjs +23 -0
  160. package/detox/colors.ts +54 -0
  161. package/detox/config-loader.ts +135 -0
  162. package/detox/element-types.ts +48 -0
  163. package/detox/expectations.ts +534 -0
  164. package/detox/gestures.ts +501 -0
  165. package/detox/index.ts +2694 -0
  166. package/detox/jest-preset.cjs +29 -0
  167. package/detox/jest-setup-after-env.cjs +22 -0
  168. package/detox/matchers.ts +30 -0
  169. package/detox/motion-change.cjs +109 -0
  170. package/detox/motion-change.d.cts +35 -0
  171. package/detox/navigation-lifecycle.ts +290 -0
  172. package/detox/navigation.ts +43 -0
  173. package/detox/proof-frame.cjs +114 -0
  174. package/detox/record-block-execution.cjs +78 -0
  175. package/detox/screenshots/animated-color-test-rest-norngh.png +0 -0
  176. package/detox/screenshots/color-test-after-drag-norngh.png +0 -0
  177. package/detox/screenshots/color-test-rest-norngh.png +0 -0
  178. package/detox/screenshots/theme-blue-toggle.png +0 -0
  179. package/detox/screenshots/theme-blue.png +0 -0
  180. package/detox/screenshots/theme-red-toggle.png +0 -0
  181. package/detox/screenshots/theme-red.png +0 -0
  182. package/dist-lib/agent-daemon-client.cjs +502 -0
  183. package/dist-lib/agent-events.cjs +48 -0
  184. package/dist-lib/agent-identity.cjs +53 -0
  185. package/dist-lib/agent-sessions.cjs +759 -0
  186. package/dist-lib/attached-projects.cjs +526 -0
  187. package/dist-lib/auth/shared-session.cjs +208 -0
  188. package/dist-lib/backend-origin.cjs +88 -0
  189. package/dist-lib/beta.cjs +41 -0
  190. package/dist-lib/beta.mjs +13 -0
  191. package/dist-lib/bridge-constants.cjs +161 -0
  192. package/dist-lib/bridge-contract-input.cjs +451 -0
  193. package/dist-lib/bridge-contract-input.mjs +414 -0
  194. package/dist-lib/bridge-contract.cjs +130 -0
  195. package/dist-lib/bridge-contract.mjs +94 -0
  196. package/dist-lib/capture-contract.cjs +220 -0
  197. package/dist-lib/capture-contract.mjs +190 -0
  198. package/dist-lib/cli-constants.cjs +32 -0
  199. package/dist-lib/cloud-contract.cjs +194 -0
  200. package/dist-lib/cloud-contract.mjs +145 -0
  201. package/dist-lib/cloud.cjs +670 -0
  202. package/dist-lib/cloud.mjs +639 -0
  203. package/dist-lib/config.cjs +96 -0
  204. package/dist-lib/detox/index.cjs +3789 -0
  205. package/dist-lib/detox/jest-preset.cjs +29 -0
  206. package/dist-lib/dev-bundle-resolution.cjs +290 -0
  207. package/dist-lib/home-paths.cjs +638 -0
  208. package/dist-lib/host/bridge-host.cjs +10903 -0
  209. package/dist-lib/host/fetch-proxy-handler.cjs +421 -0
  210. package/dist-lib/host/fetch-proxy-overrides.cjs +63 -0
  211. package/dist-lib/host/fetch-proxy-overrides.mjs +37 -0
  212. package/dist-lib/host/replacement-module-handler.cjs +469 -0
  213. package/dist-lib/host/websocket-proxy.cjs +298 -0
  214. package/dist-lib/index.cjs +4268 -0
  215. package/dist-lib/jump-to-source-babel.cjs +93 -0
  216. package/dist-lib/jump-to-source-native.cjs +112 -0
  217. package/dist-lib/menu.cjs +646 -0
  218. package/dist-lib/menu.mjs +604 -0
  219. package/dist-lib/metro-fingerprint-registry.cjs +186 -0
  220. package/dist-lib/metro-fingerprint-registry.mjs +156 -0
  221. package/dist-lib/metro-production-bundle.cjs +329 -0
  222. package/dist-lib/metro-production-bundle.mjs +295 -0
  223. package/dist-lib/metro.cjs +904 -0
  224. package/dist-lib/profiles.cjs +246 -0
  225. package/dist-lib/public-brand.cjs +39 -0
  226. package/dist-lib/react-native-host-modules.cjs +51 -0
  227. package/dist-lib/react-native-host-modules.mjs +25 -0
  228. package/dist-lib/render-mode.cjs +54 -0
  229. package/dist-lib/scripts/dev-server-scanner.cjs +1232 -0
  230. package/dist-lib/sdk.cjs +2433 -0
  231. package/dist-lib/sdk.mjs +2336 -0
  232. package/dist-lib/skills.cjs +39132 -0
  233. package/dist-lib/swift-submit.cjs +92 -0
  234. package/dist-lib/swift-submit.mjs +65 -0
  235. package/dist-lib/swift.cjs +1646 -0
  236. package/dist-lib/vite.cjs +1591 -0
  237. package/package.json +290 -0
  238. package/scripts/dev-server-scanner.ts +1291 -0
  239. package/scripts/optional-demo-registry.ts +113 -0
  240. package/skills/contrast/SKILL.md +165 -0
  241. package/skills/rnx-debug/SKILL.md +433 -0
  242. package/skills/rnx-perf/SKILL.md +399 -0
  243. package/skills/rnx-setup/SKILL.md +172 -0
  244. package/skills/rnx-test/SKILL.md +321 -0
  245. package/skills/rnx-visual/SKILL.md +126 -0
  246. package/src/agent-daemon-client.ts +410 -0
  247. package/src/agent-events.ts +71 -0
  248. package/src/agent-identity.ts +23 -0
  249. package/src/agent-prompt.ts +71 -0
  250. package/src/agent-sessions.ts +580 -0
  251. package/src/app-url.ts +39 -0
  252. package/src/attached-projects.ts +539 -0
  253. package/src/auth/shared-session.ts +235 -0
  254. package/src/backend-origin.ts +70 -0
  255. package/src/beta.ts +19 -0
  256. package/src/bridge-constants.ts +175 -0
  257. package/src/bridge-contract-input.ts +502 -0
  258. package/src/bridge-contract.ts +558 -0
  259. package/src/browser-cache.ts +16 -0
  260. package/src/capture-contract.ts +587 -0
  261. package/src/cli-constants.ts +1 -0
  262. package/src/cli-version.ts +40 -0
  263. package/src/cloud-contract.ts +274 -0
  264. package/src/cloud.ts +762 -0
  265. package/src/codex-client.ts +234 -0
  266. package/src/config.ts +132 -0
  267. package/src/connect.ts +101 -0
  268. package/src/dev-bundle-resolution.ts +346 -0
  269. package/src/dev-server-open.ts +198 -0
  270. package/src/disk-cleanup.ts +540 -0
  271. package/src/flow-timeout-scale.ts +15 -0
  272. package/src/home-paths.ts +806 -0
  273. package/src/host/agent-host.ts +666 -0
  274. package/src/host/bridge-host.ts +2788 -0
  275. package/src/host/fetch-proxy-handler.ts +449 -0
  276. package/src/host/fetch-proxy-overrides.ts +51 -0
  277. package/src/host/open-url.ts +89 -0
  278. package/src/host/plane-host.ts +203 -0
  279. package/src/host/replacement-module-handler.ts +158 -0
  280. package/src/host/websocket-proxy.ts +315 -0
  281. package/src/index.ts +71 -0
  282. package/src/jump-to-source-babel.ts +135 -0
  283. package/src/jump-to-source-native.ts +102 -0
  284. package/src/menu.ts +777 -0
  285. package/src/metro-fingerprint-registry.ts +302 -0
  286. package/src/metro-plugin.ts +341 -0
  287. package/src/metro-production-bundle.ts +471 -0
  288. package/src/native-dev-bundle-url.ts +118 -0
  289. package/src/native-seam-manifest.ts +341 -0
  290. package/src/playwright-host-log.ts +16 -0
  291. package/src/plist.ts +27 -0
  292. package/src/poll-until.ts +123 -0
  293. package/src/profiles.ts +179 -0
  294. package/src/public-brand.ts +9 -0
  295. package/src/react-native-host-modules.ts +26 -0
  296. package/src/render-mode.ts +27 -0
  297. package/src/rolldown-plugin-swift.ts +240 -0
  298. package/src/runtime-assets.ts +233 -0
  299. package/src/runtime-delivery.ts +54 -0
  300. package/src/screenshots/compose.ts +422 -0
  301. package/src/screenshots/frame-compose.ts +514 -0
  302. package/src/screenshots/orchestrate.ts +256 -0
  303. package/src/screenshots/org-deck.ts +91 -0
  304. package/src/screenshots/registry.ts +58 -0
  305. package/src/screenshots/schema.ts +364 -0
  306. package/src/sdk.ts +15 -0
  307. package/src/settings-bundle.ts +418 -0
  308. package/src/shell-bridge-identity.ts +15 -0
  309. package/src/sim-client.ts +697 -0
  310. package/src/skills/builtin/a11y-review.ts +132 -0
  311. package/src/skills/builtin/compat-check.ts +71 -0
  312. package/src/skills/builtin/maestro-test.ts +121 -0
  313. package/src/skills/builtin/perf-profile.ts +90 -0
  314. package/src/skills/builtin/screenshot-all.ts +52 -0
  315. package/src/skills/builtin/visual-diff.ts +100 -0
  316. package/src/skills/registry.ts +107 -0
  317. package/src/skills/types.ts +41 -0
  318. package/src/swift-submit.ts +185 -0
  319. package/src/swift.ts +7 -0
  320. package/src/team-machine-prompt.ts +73 -0
  321. package/src/vite-plugin-one.ts +264 -0
  322. package/src/vite-plugin-swift.ts +620 -0
  323. package/src/vite-plugin.ts +1946 -0
  324. package/src/worklets-babel.ts +250 -0
@@ -0,0 +1,670 @@
1
+ /*! rnx v0.1.527 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
+ let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
+ "use strict";
4
+ var __defProp = Object.defineProperty;
5
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
6
+ var __getOwnPropNames = Object.getOwnPropertyNames;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name2 in all)
10
+ __defProp(target, name2, { get: all[name2], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
21
+
22
+ // src/cloud.ts
23
+ var cloud_exports = {};
24
+ __export(cloud_exports, {
25
+ RNX_CLOUD_COMMAND_TYPES: () => RNX_CLOUD_COMMAND_TYPES,
26
+ RNX_CLOUD_MAX_ARTIFACT_BYTES: () => RNX_CLOUD_MAX_ARTIFACT_BYTES,
27
+ RNX_CLOUD_SCOPED_TOKEN_PREFIX: () => RNX_CLOUD_SCOPED_TOKEN_PREFIX,
28
+ RemoteSimulator: () => RemoteSimulator,
29
+ connect: () => connect,
30
+ createRemoteSimulator: () => createRemoteSimulator,
31
+ isRnxCloudCommandScope: () => isRnxCloudCommandScope,
32
+ isRnxCloudCommandType: () => isRnxCloudCommandType
33
+ });
34
+ module.exports = __toCommonJS(cloud_exports);
35
+
36
+ // src/backend-origin.ts
37
+ function normalizeHostname(hostname) {
38
+ return hostname.replace(/^\[|\]$/g, "").toLowerCase();
39
+ }
40
+ function isLoopbackHost(hostname) {
41
+ const normalized = normalizeHostname(hostname);
42
+ return normalized === "localhost" || normalized.endsWith(".localhost") || normalized === "0.0.0.0" || normalized === "::1" || /^127(?:\.\d{1,3}){3}$/.test(normalized);
43
+ }
44
+
45
+ // src/capture-contract.ts
46
+ var RNX_SCREEN_CAPTURE_VERSION = 1;
47
+ function captureRecord(value) {
48
+ return value !== null && typeof value === "object" && !Array.isArray(value);
49
+ }
50
+ function captureInteger(value) {
51
+ return typeof value === "number" && Number.isSafeInteger(value);
52
+ }
53
+ function captureNumber(value) {
54
+ return typeof value === "number" && Number.isFinite(value);
55
+ }
56
+ function captureNullableString(value) {
57
+ return value === null || typeof value === "string";
58
+ }
59
+ function captureRect(value) {
60
+ return captureRecord(value) && captureNumber(value.x) && captureNumber(value.y) && captureNumber(value.width) && captureNumber(value.height);
61
+ }
62
+ function captureOptionalString(value) {
63
+ return value === void 0 || typeof value === "string";
64
+ }
65
+ function captureOptionalNullableString(value) {
66
+ return value === void 0 || captureNullableString(value);
67
+ }
68
+ function captureFontRegistration(value) {
69
+ return captureRecord(value) && typeof value.family === "string" && value.family.length > 0 && captureOptionalString(value.url) && captureOptionalString(value.sourceLabel) && captureOptionalNullableString(value.parsedFamily) && captureOptionalNullableString(value.parsedPostScript) && captureOptionalNullableString(value.fullName);
70
+ }
71
+ function capturePoint(value) {
72
+ return captureRecord(value) && captureNumber(value.x) && captureNumber(value.y);
73
+ }
74
+ function captureNode(value) {
75
+ if (!captureRecord(value) || !captureInteger(value.nodeId) || !(value.parentNodeId === null || captureInteger(value.parentNodeId)) || !Array.isArray(value.childNodeIds) || !value.childNodeIds.every(captureInteger) || !captureInteger(value.paintIndex) || typeof value.type !== "string" || !captureNullableString(value.id) || !captureNullableString(value.testID) || !captureNullableString(value.text) || !captureInteger(value.childCount) || !captureRecord(value.accessibility) || !captureRecord(value.interaction) || !captureRecord(value.layout) || !captureRecord(value.style) || !captureRecord(value.source) || !captureRecord(value.props) || !captureRecord(value.inspection)) {
76
+ return false;
77
+ }
78
+ const accessibility = value.accessibility;
79
+ if (typeof accessibility.accessible !== "boolean" || !captureNullableString(accessibility.label) || !captureNullableString(accessibility.role) || !captureNullableString(accessibility.hint) || !(accessibility.liveRegion === null || accessibility.liveRegion === "none" || accessibility.liveRegion === "polite" || accessibility.liveRegion === "assertive") || !(accessibility.state === null || captureRecord(accessibility.state)) || !(accessibility.value === null || captureRecord(accessibility.value))) {
80
+ return false;
81
+ }
82
+ const interaction = value.interaction;
83
+ if (typeof interaction.pressed !== "boolean" || typeof interaction.pressable !== "boolean" || typeof interaction.textInput !== "boolean" || !(interaction.textSelection === null || captureRecord(interaction.textSelection)) || typeof interaction.secureTextEntry !== "boolean" || !captureNullableString(interaction.placeholder) || !capturePoint(interaction.scrollOffset) || !(interaction.zoomScale === null || captureNumber(interaction.zoomScale)) || typeof interaction.nativePinchEnabled !== "boolean" || !(interaction.contentOffsetProp === null || captureRecord(interaction.contentOffsetProp)) || !(interaction.strokeDashoffsetProp === null || captureNumber(interaction.strokeDashoffsetProp))) {
84
+ return false;
85
+ }
86
+ const layout = value.layout;
87
+ if (!captureRect(layout.local) || !(layout.frame === null || captureRect(layout.frame)) || !capturePoint(layout.absolutePosition) || !(layout.visibleFrame === null || captureRect(layout.visibleFrame))) {
88
+ return false;
89
+ }
90
+ const style = value.style;
91
+ return captureRecord(style.resolved) && captureRecord(style.authored) && captureRecord(style.computed) && captureRecord(style.tokenBindings) && (value.textLines === void 0 || Array.isArray(value.textLines));
92
+ }
93
+ function isRnxScreenCapture(value) {
94
+ if (!captureRecord(value) || value.contractVersion !== RNX_SCREEN_CAPTURE_VERSION || !captureInteger(value.capturedAt) || !captureRecord(value.tree) || !(value.fonts === void 0 || Array.isArray(value.fonts) && value.fonts.length <= 200 && value.fonts.every(captureFontRegistration)) || !(value.visual === void 0 || captureRecord(value.visual))) {
95
+ return false;
96
+ }
97
+ const tree = value.tree;
98
+ const visual = value.visual;
99
+ return captureRecord(tree.viewport) && captureInteger(tree.viewport.width) && tree.viewport.width > 0 && captureInteger(tree.viewport.height) && tree.viewport.height > 0 && captureInteger(tree.rootNodeId) && (tree.commitRevision === void 0 || captureInteger(tree.commitRevision)) && Array.isArray(tree.nodes) && tree.nodes.every(captureNode) && (visual === void 0 || visual.kind === "png" && (visual.producer === "headless-cpu-app-surface" || visual.producer === "browser-compositor-app-surface") && typeof visual.dataUri === "string" && visual.dataUri.startsWith("data:image/png;base64,") && captureInteger(visual.pixelWidth) && visual.pixelWidth > 0 && captureInteger(visual.pixelHeight) && visual.pixelHeight > 0);
100
+ }
101
+
102
+ // src/cloud-contract.ts
103
+ var RNX_CLOUD_MAX_ARTIFACT_BYTES = 20 * 1024 * 1024;
104
+ var RNX_CLOUD_DESIGN_MAX_STORAGE_BYTES = 1024 * 1024;
105
+ var RNX_CLOUD_COMMAND_SCOPE_SET = /* @__PURE__ */ new Set([
106
+ "read",
107
+ "drive",
108
+ "reset",
109
+ "media",
110
+ "debug",
111
+ "watch"
112
+ ]);
113
+ function isRnxCloudCommandScope(value) {
114
+ return RNX_CLOUD_COMMAND_SCOPE_SET.has(value);
115
+ }
116
+ var RNX_CLOUD_SCOPED_TOKEN_PREFIX = "sk_rnx_sim_";
117
+ var RNX_CLOUD_COMMAND_SCOPES = {
118
+ state: "read",
119
+ tree: "read",
120
+ query: "read",
121
+ resolve: "read",
122
+ screenshot: "read",
123
+ capture: "read",
124
+ captureRegions: "read",
125
+ memory: "read",
126
+ diagnostics: "read",
127
+ storageSnapshot: "read",
128
+ perform: "drive",
129
+ waitFor: "drive",
130
+ tap: "drive",
131
+ longPress: "drive",
132
+ settle: "drive",
133
+ openUrl: "drive",
134
+ setAppearance: "drive",
135
+ keyboard: "drive",
136
+ focus: "drive",
137
+ flowStatus: "drive",
138
+ reset: "reset",
139
+ camera: "media",
140
+ // string evaluation and arbitrary bridge calls are maestro's boundary: the
141
+ // customer sdk never carries this scope, and the service grants it only to
142
+ // the account api key caller. close rides along, since ending the page ends
143
+ // the sim and belongs to the sim's owner rather than any driver.
144
+ evaluate: "debug",
145
+ call: "debug",
146
+ close: "debug"
147
+ };
148
+ function scopeTableKeys() {
149
+ return Object.keys(RNX_CLOUD_COMMAND_SCOPES).filter(
150
+ (key) => Object.prototype.hasOwnProperty.call(RNX_CLOUD_COMMAND_SCOPES, key)
151
+ );
152
+ }
153
+ var RNX_CLOUD_COMMAND_TYPES = Object.freeze(scopeTableKeys());
154
+ var RNX_CLOUD_COMMAND_TYPE_SET = new Set(RNX_CLOUD_COMMAND_TYPES);
155
+ function isRnxCloudCommandType(value) {
156
+ return RNX_CLOUD_COMMAND_TYPE_SET.has(value);
157
+ }
158
+ function rnxCloudCommandScope(type) {
159
+ return RNX_CLOUD_COMMAND_SCOPES[type];
160
+ }
161
+ var RNX_CLOUD_TOKEN_SCOPES = Object.freeze([
162
+ "read",
163
+ "drive",
164
+ "reset",
165
+ "media"
166
+ ]);
167
+ var RNX_CLOUD_ALL_COMMAND_SCOPES = Object.freeze(["read", "drive", "reset", "media", "debug"]);
168
+ function rnxCloudScopesAllowCommand(scopes, type) {
169
+ return scopes.includes(RNX_CLOUD_COMMAND_SCOPES[type]);
170
+ }
171
+
172
+ // src/public-brand.ts
173
+ var name = "rnx";
174
+ var rnxPublicBrand = Object.freeze({
175
+ name,
176
+ packageName: "rnxsim",
177
+ commandName: "rnx",
178
+ domain: "rnxsim.com",
179
+ origin: "https://rnxsim.com"
180
+ });
181
+
182
+ // src/cloud.ts
183
+ var DEFAULT_DEVICE = "iphone-16";
184
+ var DEFAULT_WAIT_READY_MS = 2e4;
185
+ var CLOUD_MAX_RETRIES = 2;
186
+ var CLOUD_NEVER_RETRY_CODES = /* @__PURE__ */ new Set(["concurrency_limit", "early_access"]);
187
+ function isRecord(value) {
188
+ return value !== null && typeof value === "object" && !Array.isArray(value);
189
+ }
190
+ function normalizeCloudOrigin(source) {
191
+ let parsed;
192
+ try {
193
+ parsed = new URL(source);
194
+ } catch {
195
+ throw new Error(`invalid RNX Cloud origin: ${source}`);
196
+ }
197
+ if (parsed.protocol !== "https:" && parsed.protocol !== "http:" || parsed.username || parsed.password || parsed.pathname !== "/" || parsed.search || parsed.hash) {
198
+ throw new Error(`RNX Cloud origin must be an HTTP(S) origin: ${source}`);
199
+ }
200
+ if (parsed.protocol === "http:" && !isLoopbackHost(parsed.hostname)) {
201
+ throw new Error(`RNX Cloud origin requires HTTPS outside loopback: ${source}`);
202
+ }
203
+ return parsed.origin;
204
+ }
205
+ function resolveOrigin(value) {
206
+ const configured = value?.trim() || process.env.RNX_CLOUD_ORIGIN?.trim();
207
+ return normalizeCloudOrigin(configured || rnxPublicBrand.origin);
208
+ }
209
+ function responseError(status, text) {
210
+ if (text) {
211
+ try {
212
+ const parsed = JSON.parse(text);
213
+ const error = isRecord(parsed) ? parsed.error : null;
214
+ if (isRecord(error) && typeof error.message === "string") {
215
+ return new Error(`RNX Cloud request failed (${status}): ${error.message}`);
216
+ }
217
+ } catch {
218
+ }
219
+ }
220
+ return new Error(
221
+ `RNX Cloud request failed (${status})${text.trim() ? `: ${text.trim()}` : ""}`
222
+ );
223
+ }
224
+ function readCloudErrorCode(text) {
225
+ let parsed;
226
+ try {
227
+ parsed = JSON.parse(text);
228
+ } catch {
229
+ return null;
230
+ }
231
+ if (!isRecord(parsed)) return null;
232
+ if (typeof parsed.error === "string") return parsed.error;
233
+ if (isRecord(parsed.error) && typeof parsed.error.code === "string") {
234
+ return parsed.error.code;
235
+ }
236
+ return null;
237
+ }
238
+ function readRetryAfterMs(response, text) {
239
+ const header = response.headers.get("retry-after");
240
+ if (header !== null) {
241
+ const seconds = Number(header.trim());
242
+ if (Number.isFinite(seconds) && seconds >= 0) return seconds * 1e3;
243
+ }
244
+ let parsed;
245
+ try {
246
+ parsed = JSON.parse(text);
247
+ } catch {
248
+ return null;
249
+ }
250
+ if (isRecord(parsed) && typeof parsed.retryAfterMs === "number" && Number.isFinite(parsed.retryAfterMs) && parsed.retryAfterMs >= 0) {
251
+ return parsed.retryAfterMs;
252
+ }
253
+ return null;
254
+ }
255
+ function sleep(ms) {
256
+ return new Promise((resolve) => setTimeout(resolve, ms));
257
+ }
258
+ async function fetchWithCloudRetry(url, init, options) {
259
+ let attempt = 0;
260
+ for (; ; ) {
261
+ const response = await fetch(
262
+ url,
263
+ options?.timeoutMs === void 0 ? init : { ...init, signal: AbortSignal.timeout(options.timeoutMs) }
264
+ );
265
+ if (response.ok) return response;
266
+ const retryableStatus = response.status === 429 || response.status >= 500;
267
+ if (!retryableStatus || attempt >= CLOUD_MAX_RETRIES) return response;
268
+ const text = await response.text();
269
+ const code = readCloudErrorCode(text);
270
+ const retryable = response.status >= 500 ? !(code !== null && CLOUD_NEVER_RETRY_CODES.has(code)) : code === "rate_limited";
271
+ if (!retryable) {
272
+ return new Response(text, { status: response.status, headers: response.headers });
273
+ }
274
+ if (response.status === 429) {
275
+ await sleep(readRetryAfterMs(response, text) ?? 1e3);
276
+ }
277
+ attempt += 1;
278
+ }
279
+ }
280
+ function copyArrayBuffer(bytes) {
281
+ const copy = new ArrayBuffer(bytes.byteLength);
282
+ new Uint8Array(copy).set(bytes);
283
+ return copy;
284
+ }
285
+ async function sha256Hex(bytes) {
286
+ const digest = await globalThis.crypto.subtle.digest("SHA-256", copyArrayBuffer(bytes));
287
+ const view = new Uint8Array(digest);
288
+ let hex = "";
289
+ for (const byte of view) hex += byte.toString(16).padStart(2, "0");
290
+ return hex;
291
+ }
292
+ function readJsArtifact(bytes) {
293
+ let source;
294
+ try {
295
+ source = new TextDecoder("utf-8", { fatal: true }).decode(bytes);
296
+ } catch {
297
+ throw new Error("rnx Cloud artifact must be valid UTF-8 JavaScript, not bytecode");
298
+ }
299
+ if (source.includes("\0") || !source.includes("__d(") || !source.includes("__r(")) {
300
+ throw new Error("rnx Cloud artifact must be a Metro JavaScript bundle");
301
+ }
302
+ return source;
303
+ }
304
+ function readClaim(value) {
305
+ if (!isRecord(value) || typeof value.id !== "string" || !value.id || typeof value.expiresAt !== "number") {
306
+ throw new Error("RNX Cloud returned an invalid claim");
307
+ }
308
+ return { id: value.id, expiresAt: value.expiresAt };
309
+ }
310
+ function artifactDigestId(sha256) {
311
+ return `sha256:${sha256}`;
312
+ }
313
+ function readArtifact(value, expectedId, expectedBytes) {
314
+ if (!isRecord(value) || value.id !== expectedId || typeof value.bytes !== "number" || !Number.isInteger(value.bytes) || value.bytes !== expectedBytes) {
315
+ throw new Error("RNX Cloud returned an invalid artifact receipt");
316
+ }
317
+ return { id: expectedId, bytes: expectedBytes };
318
+ }
319
+ function readSimulatorCreate(value, expectedId, expectedBytes) {
320
+ if (!isRecord(value)) throw new Error("RNX Cloud create returned an invalid simulator");
321
+ const claim = readClaim(value.claim);
322
+ if (typeof value.simId !== "string" || !value.simId || typeof value.token !== "string") {
323
+ throw new Error("RNX Cloud create returned an invalid simulator");
324
+ }
325
+ return {
326
+ simId: value.simId,
327
+ token: value.token,
328
+ claim,
329
+ artifact: readArtifact(value.artifact, expectedId, expectedBytes)
330
+ };
331
+ }
332
+ function readBoxCreate(value, expectedBytes, expectedSha256) {
333
+ const artifactId = artifactDigestId(expectedSha256);
334
+ if (!isRecord(value)) throw new Error("RNX Cloud create returned invalid JSON");
335
+ const simulator = readSimulatorCreate(value.simulator, artifactId, expectedBytes);
336
+ if (typeof value.boxId !== "string" || !value.boxId || value.size !== "nano" || typeof value.token !== "string" || !value.token) {
337
+ throw new Error("RNX Cloud create returned an invalid box receipt");
338
+ }
339
+ return {
340
+ receipt: {
341
+ boxId: value.boxId,
342
+ size: "nano",
343
+ artifact: readArtifact(value.artifact, artifactId, expectedBytes),
344
+ simulator: {
345
+ simId: simulator.simId,
346
+ artifact: simulator.artifact,
347
+ claim: simulator.claim
348
+ }
349
+ },
350
+ boxToken: value.token,
351
+ simulatorToken: simulator.token
352
+ };
353
+ }
354
+ function cloudCommand(command, scopes) {
355
+ const clean = {};
356
+ for (const [key, value] of Object.entries(command)) {
357
+ if (key !== "id" && key !== "simId") clean[key] = value;
358
+ }
359
+ if (!isRnxCloudCommandType(command.type)) {
360
+ throw new Error(`RNX Cloud does not support bridge command type ${command.type}`);
361
+ }
362
+ if (!rnxCloudScopesAllowCommand(scopes, command.type)) {
363
+ throw new Error(
364
+ `RNX Cloud command ${command.type} requires the ${rnxCloudCommandScope(command.type)} scope`
365
+ );
366
+ }
367
+ return { ...clean, type: command.type };
368
+ }
369
+ var RemoteSimulator = class {
370
+ session;
371
+ // driving verbs live here so the client reads the way the CLI does. bound to
372
+ // this simulator at construction, and every verb reads the session live, so a
373
+ // confirmed claim reaches commands issued after it.
374
+ rnx;
375
+ constructor(session) {
376
+ this.session = session;
377
+ this.rnx = {
378
+ command: (command, options) => this.sendCommand(command, options),
379
+ describe: () => this.sendCommand({ type: "tree" }),
380
+ do: (command) => this.sendCommand(command),
381
+ wait: (condition, options) => {
382
+ const timeoutMs = options?.maxMs ?? DEFAULT_WAIT_READY_MS;
383
+ const waitCondition = condition === "ready" ? { type: "ready" } : condition;
384
+ return this.sendCommand(
385
+ {
386
+ type: "waitFor",
387
+ waitForOptions: { condition: waitCondition, timeoutMs }
388
+ },
389
+ { timeoutMs: timeoutMs + 1e3 }
390
+ );
391
+ },
392
+ screenshot: async (options) => {
393
+ const result = await this.sendCommand({
394
+ type: "screenshot",
395
+ layers: options?.layers ?? "tenant"
396
+ });
397
+ if (typeof result !== "string" || !result.startsWith("data:image/")) {
398
+ throw new Error("RNX Cloud screenshot did not return an image data url");
399
+ }
400
+ return result;
401
+ },
402
+ capture: async () => {
403
+ const result = await this.sendCommand({ type: "capture" });
404
+ if (!isRnxScreenCapture(result)) {
405
+ throw new Error("RNX Cloud capture returned an invalid screen capture");
406
+ }
407
+ return result;
408
+ },
409
+ reset: (options) => {
410
+ if (options?.strategy !== void 0 && options.strategy !== "data" && options.strategy !== "full") {
411
+ throw new Error("RNX Cloud reset strategy must be data or full");
412
+ }
413
+ if (options?.from !== void 0 && (typeof options.from !== "string" || options.from.length === 0)) {
414
+ throw new Error("RNX Cloud reset from must name a simulator");
415
+ }
416
+ return this.sendCommand(
417
+ options === void 0 ? { type: "reset" } : {
418
+ type: "reset",
419
+ resetOptions: {
420
+ ...options.strategy === void 0 ? {} : { strategy: options.strategy },
421
+ ...options.from === void 0 ? {} : { from: options.from }
422
+ }
423
+ }
424
+ );
425
+ },
426
+ state: (options) => this.sendCommand(
427
+ options === void 0 ? { type: "state" } : { type: "state", stateOptions: options }
428
+ )
429
+ };
430
+ }
431
+ get simId() {
432
+ return this.session.simId;
433
+ }
434
+ get claim() {
435
+ return this.session.claim;
436
+ }
437
+ get scopes() {
438
+ return this.session.scopes;
439
+ }
440
+ get receipt() {
441
+ if (!this.session.claim) {
442
+ throw new Error("this simulator was attached with connect() and holds no claim");
443
+ }
444
+ return {
445
+ simId: this.session.simId,
446
+ artifact: this.session.artifact,
447
+ claim: this.session.claim
448
+ };
449
+ }
450
+ async sendCommand(command, options) {
451
+ const body = {
452
+ id: globalThis.crypto.randomUUID(),
453
+ // a scoped token drives without a claim: the service checks the token
454
+ // instead. a full token still joins the claim it names here.
455
+ claimId: this.session.claim?.id ?? "",
456
+ command: cloudCommand(command, this.session.scopes)
457
+ };
458
+ let response;
459
+ try {
460
+ response = await fetchWithCloudRetry(
461
+ `${this.session.origin}/v1/sims/${encodeURIComponent(this.session.simId)}/commands`,
462
+ {
463
+ method: "POST",
464
+ headers: {
465
+ authorization: `Bearer ${this.session.simulatorToken}`,
466
+ "content-type": "application/json"
467
+ },
468
+ body: JSON.stringify(body)
469
+ },
470
+ options?.timeoutMs === void 0 ? void 0 : { timeoutMs: options.timeoutMs }
471
+ );
472
+ } catch (error) {
473
+ throw new Error(
474
+ `could not reach RNX Cloud at ${this.session.origin}: ${error instanceof Error ? error.message : String(error)}`
475
+ );
476
+ }
477
+ const text = await response.text();
478
+ if (!response.ok) throw responseError(response.status, text);
479
+ let parsed;
480
+ try {
481
+ parsed = JSON.parse(text);
482
+ } catch {
483
+ throw new Error("RNX Cloud command returned unreadable JSON");
484
+ }
485
+ if (!isRecord(parsed) || parsed.id !== body.id) {
486
+ throw new Error("RNX Cloud command returned an invalid command receipt");
487
+ }
488
+ if (typeof parsed.error === "string" && parsed.error) throw new Error(parsed.error);
489
+ if (!Object.hasOwn(parsed, "result")) {
490
+ throw new Error("RNX Cloud command receipt has no result");
491
+ }
492
+ return parsed.result;
493
+ }
494
+ async confirm() {
495
+ if (!this.session.claim) {
496
+ throw new Error("this simulator was attached with connect() and holds no claim");
497
+ }
498
+ const claimId = this.session.claim.id;
499
+ const response = await fetchWithCloudRetry(
500
+ `${this.session.origin}/v1/sims/${encodeURIComponent(this.session.simId)}/claim`,
501
+ {
502
+ method: "POST",
503
+ headers: {
504
+ authorization: `Bearer ${this.session.simulatorToken}`,
505
+ "content-type": "application/json"
506
+ },
507
+ body: JSON.stringify({ claimId })
508
+ }
509
+ );
510
+ const text = await response.text();
511
+ if (!response.ok) throw responseError(response.status, text);
512
+ let parsed;
513
+ try {
514
+ parsed = JSON.parse(text);
515
+ } catch {
516
+ throw new Error("RNX Cloud claim returned unreadable JSON");
517
+ }
518
+ const claim = readClaim(isRecord(parsed) ? parsed.claim : null);
519
+ if (claim.id !== claimId) {
520
+ throw new Error("RNX Cloud confirmation replaced the initial claim");
521
+ }
522
+ this.session = { ...this.session, claim };
523
+ return claim;
524
+ }
525
+ async close() {
526
+ const target = this.session.boxId !== null && this.session.boxToken !== null ? {
527
+ url: `${this.session.origin}/v1/boxes/${encodeURIComponent(this.session.boxId)}`,
528
+ authorization: `Bearer ${this.session.boxToken}`
529
+ } : {
530
+ url: `${this.session.origin}/v1/sims/${encodeURIComponent(this.session.simId)}`,
531
+ authorization: `Bearer ${this.session.simulatorToken}`
532
+ };
533
+ const response = await fetchWithCloudRetry(target.url, {
534
+ method: "DELETE",
535
+ headers: { authorization: target.authorization }
536
+ });
537
+ const text = await response.text();
538
+ if (!response.ok && response.status !== 404) {
539
+ throw responseError(response.status, text);
540
+ }
541
+ }
542
+ };
543
+ async function createRemoteSimulator(input) {
544
+ if (input.artifact.byteLength > RNX_CLOUD_MAX_ARTIFACT_BYTES) {
545
+ throw new Error(
546
+ `rnx Cloud artifact is ${input.artifact.byteLength} bytes and exceeds the ${RNX_CLOUD_MAX_ARTIFACT_BYTES}-byte limit`
547
+ );
548
+ }
549
+ if (input.artifact.byteLength <= 0) {
550
+ throw new Error("rnx Cloud artifact is empty");
551
+ }
552
+ readJsArtifact(input.artifact);
553
+ const origin = resolveOrigin(input.origin);
554
+ const sha256 = await sha256Hex(input.artifact);
555
+ if (input.sha256 && input.sha256 !== sha256) {
556
+ throw new Error("rnx Cloud artifact sha256 does not match the provided digest");
557
+ }
558
+ const device = input.device?.trim() || DEFAULT_DEVICE;
559
+ let response;
560
+ try {
561
+ response = await fetchWithCloudRetry(`${origin}/v1/boxes`, {
562
+ method: "POST",
563
+ headers: {
564
+ authorization: input.authorization,
565
+ "content-type": "application/javascript",
566
+ "x-rnx-box-size": "nano",
567
+ "x-rnx-artifact-sha256": sha256,
568
+ "x-rnx-platform": "ios",
569
+ "x-rnx-device": device
570
+ },
571
+ body: copyArrayBuffer(input.artifact)
572
+ });
573
+ } catch (error) {
574
+ throw new Error(
575
+ `could not reach RNX Cloud at ${origin}: ${error instanceof Error ? error.message : String(error)}`
576
+ );
577
+ }
578
+ const responseText = await response.text();
579
+ if (!response.ok) throw responseError(response.status, responseText);
580
+ let parsed;
581
+ try {
582
+ parsed = JSON.parse(responseText);
583
+ } catch {
584
+ throw new Error("RNX Cloud create returned unreadable JSON");
585
+ }
586
+ const created = readBoxCreate(parsed, input.artifact.byteLength, sha256);
587
+ const simulator = new RemoteSimulator({
588
+ origin,
589
+ boxId: created.receipt.boxId,
590
+ boxToken: created.boxToken,
591
+ simId: created.receipt.simulator.simId,
592
+ simulatorToken: created.simulatorToken,
593
+ claim: created.receipt.simulator.claim,
594
+ artifact: created.receipt.artifact,
595
+ scopes: RNX_CLOUD_TOKEN_SCOPES
596
+ });
597
+ await simulator.confirm();
598
+ return simulator;
599
+ }
600
+ function readSimArtifact(value) {
601
+ if (!isRecord(value) || typeof value.sha256 !== "string" || !/^[a-f0-9]{64}$/.test(value.sha256) || typeof value.bytes !== "number" || !Number.isInteger(value.bytes) || value.bytes <= 0) {
602
+ throw new Error("RNX Cloud returned an invalid simulator artifact");
603
+ }
604
+ return { id: `sha256:${value.sha256}`, bytes: value.bytes };
605
+ }
606
+ function readConnectClaim(value) {
607
+ if (value === null) return null;
608
+ return readClaim(value);
609
+ }
610
+ function readConnectScopes(value, token) {
611
+ if (!token.startsWith(RNX_CLOUD_SCOPED_TOKEN_PREFIX)) return RNX_CLOUD_TOKEN_SCOPES;
612
+ if (!isRecord(value) || typeof value.id !== "string" || !value.id || !Array.isArray(value.scopes) || value.scopes.length === 0 || !value.scopes.every(
613
+ (scope) => typeof scope === "string" && isRnxCloudCommandScope(scope)
614
+ ) || typeof value.expiresAt !== "number") {
615
+ throw new Error("RNX Cloud returned an invalid scoped token");
616
+ }
617
+ return Object.freeze([...value.scopes]);
618
+ }
619
+ async function connect(input) {
620
+ if (!input.id) throw new Error("RNX Cloud connect needs a simulator id");
621
+ if (!input.token) throw new Error("RNX Cloud connect needs a token");
622
+ const origin = resolveOrigin(input.origin);
623
+ let response;
624
+ try {
625
+ response = await fetchWithCloudRetry(
626
+ `${origin}/v1/sims/${encodeURIComponent(input.id)}`,
627
+ { headers: { authorization: `Bearer ${input.token}` } }
628
+ );
629
+ } catch (error) {
630
+ throw new Error(
631
+ `could not reach RNX Cloud at ${origin}: ${error instanceof Error ? error.message : String(error)}`
632
+ );
633
+ }
634
+ const text = await response.text();
635
+ if (!response.ok) throw responseError(response.status, text);
636
+ let parsed;
637
+ try {
638
+ parsed = JSON.parse(text);
639
+ } catch {
640
+ throw new Error("RNX Cloud connect returned unreadable JSON");
641
+ }
642
+ if (!isRecord(parsed) || !isRecord(parsed.sim)) {
643
+ throw new Error("RNX Cloud connect returned an invalid simulator");
644
+ }
645
+ const sim = parsed.sim;
646
+ if (typeof sim.simId !== "string" || !sim.simId) {
647
+ throw new Error("RNX Cloud connect returned an invalid simulator");
648
+ }
649
+ return new RemoteSimulator({
650
+ origin,
651
+ boxId: null,
652
+ boxToken: null,
653
+ simId: sim.simId,
654
+ simulatorToken: input.token,
655
+ claim: readConnectClaim(sim.claim ?? null),
656
+ artifact: readSimArtifact(sim.artifact),
657
+ scopes: readConnectScopes(isRecord(parsed) ? parsed.token : null, input.token)
658
+ });
659
+ }
660
+ // Annotate the CommonJS export names for ESM import in node:
661
+ 0 && (module.exports = {
662
+ RNX_CLOUD_COMMAND_TYPES,
663
+ RNX_CLOUD_MAX_ARTIFACT_BYTES,
664
+ RNX_CLOUD_SCOPED_TOKEN_PREFIX,
665
+ RemoteSimulator,
666
+ connect,
667
+ createRemoteSimulator,
668
+ isRnxCloudCommandScope,
669
+ isRnxCloudCommandType
670
+ });