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,904 @@
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 __create = Object.create;
5
+ var __defProp = Object.defineProperty;
6
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
7
+ var __getOwnPropNames = Object.getOwnPropertyNames;
8
+ var __getProtoOf = Object.getPrototypeOf;
9
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
10
+ var __export = (target, all) => {
11
+ for (var name in all)
12
+ __defProp(target, name, { get: all[name], enumerable: true });
13
+ };
14
+ var __copyProps = (to, from, except, desc) => {
15
+ if (from && typeof from === "object" || typeof from === "function") {
16
+ for (let key of __getOwnPropNames(from))
17
+ if (!__hasOwnProp.call(to, key) && key !== except)
18
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
19
+ }
20
+ return to;
21
+ };
22
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
23
+ // If the importer is in node compatibility mode or this is not an ESM
24
+ // file that has been converted to a CommonJS file using a Babel-
25
+ // compatible transform (i.e. "__esModule" has not been set), then set
26
+ // "default" to the CommonJS "module.exports" for node compatibility.
27
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
28
+ mod
29
+ ));
30
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
31
+
32
+ // src/metro-plugin.ts
33
+ var metro_plugin_exports = {};
34
+ __export(metro_plugin_exports, {
35
+ default: () => metro_plugin_default,
36
+ toRNXDevelopmentBundleUrl: () => toRNXDevelopmentBundleUrl,
37
+ toRNXProductionBundleUrl: () => toRNXProductionBundleUrl,
38
+ withRNX: () => withRNX
39
+ });
40
+ module.exports = __toCommonJS(metro_plugin_exports);
41
+ var import_fs2 = __toESM(require("fs"), 1);
42
+ var import_module = require("module");
43
+ var import_node_crypto2 = require("node:crypto");
44
+ var import_path2 = __toESM(require("path"), 1);
45
+
46
+ // src/dev-server-open.ts
47
+ var import_node_crypto = require("node:crypto");
48
+ var import_node_fs = __toESM(require("node:fs"), 1);
49
+ function tagRnxBundleForPlugin(bundleUrl, replacementOrigin, replacementToken, projectRoot, appName) {
50
+ const absolute = /^[a-z][a-z\d+.-]*:\/\//i.test(bundleUrl);
51
+ const url = new URL(bundleUrl, absolute ? void 0 : "http://rnx.local");
52
+ if (appName) {
53
+ url.searchParams.set("rnxAppName", appName);
54
+ url.searchParams.set(
55
+ "rnxProjectId",
56
+ (0, import_node_crypto.createHash)("sha256").update(import_node_fs.default.realpathSync(projectRoot)).digest("hex").slice(0, 32)
57
+ );
58
+ }
59
+ url.searchParams.set("rnxReplacementOrigin", replacementOrigin);
60
+ url.searchParams.set("rnxReplacementToken", replacementToken);
61
+ return absolute ? url.toString() : `${url.pathname}${url.search}${url.hash}`;
62
+ }
63
+
64
+ // src/host/replacement-module-handler.ts
65
+ var import_promises = __toESM(require("node:fs/promises"), 1);
66
+ var import_node_path = __toESM(require("node:path"), 1);
67
+
68
+ // ../contrast-bundler/src/replacementModule.ts
69
+ var import_dist = require("sucrase/dist/index.js");
70
+ var import_parser = require("sucrase/dist/parser/index.js");
71
+ var import_types = require("sucrase/dist/parser/tokenizer/types.js");
72
+
73
+ // ../contrast-bundler/src/posixPath.ts
74
+ var sep = "/";
75
+ var delimiter = ":";
76
+ function isAbsolute(p) {
77
+ return p.charCodeAt(0) === 47;
78
+ }
79
+ function normalizeSegments(parts, allowAboveRoot) {
80
+ const out = [];
81
+ for (const part of parts) {
82
+ if (part === "" || part === ".") continue;
83
+ if (part === "..") {
84
+ if (out.length > 0 && out[out.length - 1] !== "..") out.pop();
85
+ else if (allowAboveRoot) out.push("..");
86
+ continue;
87
+ }
88
+ out.push(part);
89
+ }
90
+ return out;
91
+ }
92
+ function normalize(p) {
93
+ if (p.length === 0) return ".";
94
+ const absolute = isAbsolute(p);
95
+ const trailingSlash = p.charCodeAt(p.length - 1) === 47;
96
+ const segments = normalizeSegments(p.split("/"), !absolute);
97
+ let joined = segments.join("/");
98
+ if (joined.length === 0) {
99
+ if (absolute) return "/";
100
+ return trailingSlash ? "./" : ".";
101
+ }
102
+ if (trailingSlash) joined += "/";
103
+ return absolute ? "/" + joined : joined;
104
+ }
105
+ function join(...parts) {
106
+ const present = parts.filter((part) => part.length > 0);
107
+ if (present.length === 0) return ".";
108
+ return normalize(present.join("/"));
109
+ }
110
+ function resolve(...parts) {
111
+ let resolved = "";
112
+ let absolute = false;
113
+ for (let i = parts.length - 1; i >= 0 && !absolute; i--) {
114
+ const part = parts[i];
115
+ if (part.length === 0) continue;
116
+ resolved = resolved.length > 0 ? `${part}/${resolved}` : part;
117
+ absolute = isAbsolute(part);
118
+ }
119
+ if (!absolute)
120
+ throw new Error(
121
+ `posixPath.resolve needs an absolute segment, got: ${parts.join(", ")}`
122
+ );
123
+ const normalized = normalizeSegments(resolved.split("/"), false).join("/");
124
+ return normalized.length > 0 ? "/" + normalized : "/";
125
+ }
126
+ function dirname(p) {
127
+ const idx = p.lastIndexOf("/");
128
+ if (idx < 0) return ".";
129
+ if (idx === 0) return "/";
130
+ return p.slice(0, idx);
131
+ }
132
+ function basename(p, ext) {
133
+ const idx = p.lastIndexOf("/");
134
+ const base = idx < 0 ? p : p.slice(idx + 1);
135
+ if (ext != null && ext.length < base.length && base.endsWith(ext)) {
136
+ return base.slice(0, base.length - ext.length);
137
+ }
138
+ return base;
139
+ }
140
+ function extname(p) {
141
+ const base = basename(p);
142
+ const idx = base.lastIndexOf(".");
143
+ if (idx <= 0) return "";
144
+ return base.slice(idx);
145
+ }
146
+ function relative(from, to) {
147
+ if (from === to) return "";
148
+ const fromParts = normalizeSegments(from.split("/"), false);
149
+ const toParts = normalizeSegments(to.split("/"), false);
150
+ let shared = 0;
151
+ while (shared < fromParts.length && shared < toParts.length && fromParts[shared] === toParts[shared]) {
152
+ shared++;
153
+ }
154
+ const up = new Array(fromParts.length - shared).fill("..");
155
+ return [...up, ...toParts.slice(shared)].join("/");
156
+ }
157
+ var posix = {
158
+ sep,
159
+ delimiter,
160
+ isAbsolute,
161
+ normalize,
162
+ join,
163
+ resolve,
164
+ dirname,
165
+ basename,
166
+ extname,
167
+ relative
168
+ };
169
+ var posixPath_default = { ...posix, posix };
170
+
171
+ // ../contrast-bundler/src/replacementModule.ts
172
+ var REPLACEMENT_MODULE_EXTENSIONS = [".js", ".jsx", ".ts", ".tsx"];
173
+ var IMPORT_KEYWORD = import_types.TokenType["_import"];
174
+ var EXPORT_KEYWORD = import_types.TokenType["_export"];
175
+ var REACT_BRIDGE = "globalThis.__sootsim_react_bridge";
176
+ var REACT_NATIVE_BRIDGE = "globalThis.__sootsim_components__";
177
+ var PACKAGE_BRIDGES = "globalThis.__sootsim_config_package_modules";
178
+ var JSX_RUNTIME_SPECIFIERS = /* @__PURE__ */ new Set(["react/jsx-runtime", "react/jsx-dev-runtime"]);
179
+ function transformsFor(filePath) {
180
+ switch (extname(filePath).toLowerCase()) {
181
+ case ".ts":
182
+ return ["typescript"];
183
+ case ".tsx":
184
+ return ["typescript", "jsx"];
185
+ case ".js":
186
+ case ".jsx":
187
+ return ["jsx"];
188
+ default:
189
+ throw new Error(
190
+ `replacement files must be ${REPLACEMENT_MODULE_EXTENSIONS.join(", ")}`
191
+ );
192
+ }
193
+ }
194
+ function isContrastKitSpecifier(specifier) {
195
+ return specifier === "contrast-kit" || specifier.startsWith("contrast-kit/");
196
+ }
197
+ function unsupportedSpecifier(specifier) {
198
+ return new Error(
199
+ `replacement modules may only import react, react-native, contrast-kit, and the packages rnx stubs for this app; '${specifier}' is none of those. vendor the code into the replacement file, or add the package to rnx.config so the simulator bridges it.`
200
+ );
201
+ }
202
+ function bridgeDeclaration(name, specifier) {
203
+ const notReady = (what) => JSON.stringify(`[rnx] replacement ${what} bridge is not ready`);
204
+ if (specifier === "react") {
205
+ return `const ${name} = ${REACT_BRIDGE}; if (!${name}) throw new Error(${notReady("React")});`;
206
+ }
207
+ if (specifier === "react-native") {
208
+ return `const ${name} = ${REACT_NATIVE_BRIDGE}; if (!${name}) throw new Error(${notReady("React Native")});`;
209
+ }
210
+ if (isContrastKitSpecifier(specifier)) {
211
+ return `const ${name} = (globalThis.__contrast_kit_modules && globalThis.__contrast_kit_modules[${JSON.stringify(specifier)}]) || (${PACKAGE_BRIDGES} || {})[${JSON.stringify(specifier)}]; if (!${name}) throw new Error(${JSON.stringify(`[rnx] replacement package bridge ${specifier} is not ready`)});`;
212
+ }
213
+ if (JSX_RUNTIME_SPECIFIERS.has(specifier)) {
214
+ return `const ${name} = (() => { const react = ${REACT_BRIDGE}; if (!react) throw new Error(${notReady("React")}); const jsx = (type, props, key) => react.createElement(type, key === undefined ? props : { ...props, key }); return { Fragment: react.Fragment, jsx, jsxs: jsx, jsxDEV: jsx }; })();`;
215
+ }
216
+ return `const ${name} = (${PACKAGE_BRIDGES} || {})[${JSON.stringify(specifier)}]; if (!${name}) throw new Error(${JSON.stringify(`[rnx] replacement package bridge ${specifier} is not ready`)});`;
217
+ }
218
+ var DEFAULT_INTEROP = "__rnxReplacementDefault";
219
+ var DEFAULT_INTEROP_DECLARATION = `const ${DEFAULT_INTEROP} = (bridge) => (bridge && bridge.__esModule ? bridge.default : bridge);`;
220
+ function compileReplacementModule(input) {
221
+ const transformed = (0, import_dist.transform)(input.source, {
222
+ transforms: transformsFor(input.filePath),
223
+ filePath: input.filePath,
224
+ // classic runtime, matching what the app's own Metro build does for a file
225
+ // that has no automatic-runtime pragma: the file imports React itself.
226
+ jsxRuntime: "classic",
227
+ jsxPragma: "React.createElement",
228
+ jsxFragmentPragma: "React.Fragment",
229
+ production: true,
230
+ sourceMapOptions: { compiledFilename: input.filePath }
231
+ });
232
+ const code = transformed.code;
233
+ const sourceMap = transformed.sourceMap;
234
+ if (!sourceMap) throw new Error("sucrase compiled the replacement with no source map");
235
+ const { tokens } = (0, import_parser.parse)(code, false, false, false);
236
+ const read = (token) => code.slice(token.start, token.end);
237
+ const readSpecifier = (token) => {
238
+ if (token.type !== import_types.TokenType.string) {
239
+ throw new Error("replacement module import has no string specifier");
240
+ }
241
+ return code.slice(token.start + 1, token.end - 1);
242
+ };
243
+ const bridgeNames = /* @__PURE__ */ new Map();
244
+ const declarations = [];
245
+ let needsDefaultInterop = false;
246
+ const bridgeFor = (specifier) => {
247
+ const existing = bridgeNames.get(specifier);
248
+ if (existing) return existing;
249
+ const name = `__rnxReplacementBridge${bridgeNames.size}`;
250
+ bridgeNames.set(specifier, name);
251
+ declarations.push(bridgeDeclaration(name, specifier));
252
+ return name;
253
+ };
254
+ const edits = [];
255
+ for (let index = 0; index < tokens.length; index++) {
256
+ const token = tokens[index];
257
+ if (token.type === EXPORT_KEYWORD) {
258
+ const after2 = tokens[index + 1];
259
+ let fromAt = -1;
260
+ if (after2?.type === import_types.TokenType.star) {
261
+ fromAt = read(tokens[index + 2]) === "from" ? index + 2 : index + 4;
262
+ } else if (after2?.type === import_types.TokenType.braceL) {
263
+ let depth = 1;
264
+ let cursor2 = index + 2;
265
+ while (cursor2 < tokens.length && depth > 0) {
266
+ if (tokens[cursor2].type === import_types.TokenType.braceL) depth++;
267
+ else if (tokens[cursor2].type === import_types.TokenType.braceR) depth--;
268
+ cursor2++;
269
+ }
270
+ fromAt = cursor2;
271
+ }
272
+ if (fromAt > 0 && tokens[fromAt] && read(tokens[fromAt]) === "from" && tokens[fromAt + 1]?.type === import_types.TokenType.string) {
273
+ const specifier2 = readSpecifier(tokens[fromAt + 1]);
274
+ throw new Error(
275
+ `a replacement module cannot re-export from another module, and this one re-exports from '${specifier2}'. import what you need and export the binding.`
276
+ );
277
+ }
278
+ continue;
279
+ }
280
+ if (token.type !== IMPORT_KEYWORD) continue;
281
+ const after = tokens[index + 1];
282
+ if (!after || after.type === import_types.TokenType.parenL || after.type === import_types.TokenType.dot) continue;
283
+ const bindings = [];
284
+ let cursor = index + 1;
285
+ if (after.type !== import_types.TokenType.string) {
286
+ while (cursor < tokens.length) {
287
+ const clause = tokens[cursor];
288
+ if (clause.type === import_types.TokenType.name && read(clause) === "from") break;
289
+ if (clause.type === import_types.TokenType.comma) {
290
+ cursor++;
291
+ continue;
292
+ }
293
+ if (clause.type === import_types.TokenType.star) {
294
+ bindings.push({ local: read(tokens[cursor + 2]), imported: null });
295
+ cursor += 3;
296
+ continue;
297
+ }
298
+ if (clause.type === import_types.TokenType.braceL) {
299
+ cursor++;
300
+ while (cursor < tokens.length && tokens[cursor].type !== import_types.TokenType.braceR) {
301
+ if (tokens[cursor].type === import_types.TokenType.comma) {
302
+ cursor++;
303
+ continue;
304
+ }
305
+ const nameToken = tokens[cursor];
306
+ const imported = nameToken.type === import_types.TokenType.string ? readSpecifier(nameToken) : read(nameToken);
307
+ let local = imported;
308
+ if (tokens[cursor + 1] && read(tokens[cursor + 1]) === "as") {
309
+ local = read(tokens[cursor + 2]);
310
+ cursor += 2;
311
+ }
312
+ bindings.push({ local, imported });
313
+ cursor++;
314
+ }
315
+ cursor++;
316
+ continue;
317
+ }
318
+ bindings.push({ local: read(clause), imported: "default" });
319
+ cursor++;
320
+ }
321
+ cursor++;
322
+ }
323
+ const specifierToken = tokens[cursor];
324
+ if (!specifierToken) throw new Error("replacement module import is unterminated");
325
+ const specifier = readSpecifier(specifierToken);
326
+ if (specifier !== "react" && specifier !== "react-native" && !JSX_RUNTIME_SPECIFIERS.has(specifier) && !isContrastKitSpecifier(specifier) && !input.runtimePackages.has(specifier)) {
327
+ throw unsupportedSpecifier(specifier);
328
+ }
329
+ const bridge = bindings.length > 0 ? bridgeFor(specifier) : null;
330
+ const replacement = bindings.map((binding) => {
331
+ if (binding.imported === null) return `const ${binding.local} = ${bridge};`;
332
+ if (binding.imported === "default") {
333
+ needsDefaultInterop = true;
334
+ return `const ${binding.local} = ${DEFAULT_INTEROP}(${bridge});`;
335
+ }
336
+ return `const ${binding.local} = ${bridge}[${JSON.stringify(binding.imported)}];`;
337
+ }).join(" ");
338
+ const start = token.start;
339
+ const end = specifierToken.end;
340
+ const newlines = code.slice(start, end).split("\n").length - 1;
341
+ edits.push({ start, end, text: replacement + "\n".repeat(newlines) });
342
+ }
343
+ let out = code;
344
+ for (const edit of edits.reverse()) {
345
+ out = out.slice(0, edit.start) + edit.text + out.slice(edit.end);
346
+ }
347
+ if (needsDefaultInterop) declarations.unshift(DEFAULT_INTEROP_DECLARATION);
348
+ const preamble = declarations.join(" ");
349
+ return {
350
+ code: preamble ? `${preamble} ${out}` : out,
351
+ sourceMap: { ...sourceMap, sourcesContent: [input.source] }
352
+ };
353
+ }
354
+
355
+ // src/backend-origin.ts
356
+ function normalizeHostname(hostname) {
357
+ return hostname.replace(/^\[|\]$/g, "").toLowerCase();
358
+ }
359
+ function isLoopbackHost(hostname) {
360
+ const normalized = normalizeHostname(hostname);
361
+ return normalized === "localhost" || normalized.endsWith(".localhost") || normalized === "0.0.0.0" || normalized === "::1" || /^127(?:\.\d{1,3}){3}$/.test(normalized);
362
+ }
363
+
364
+ // src/host/replacement-module-handler.ts
365
+ var REPLACEMENT_MODULE_ROUTE = "/__sootsim-replacement-module";
366
+ function sendJavaScript(req, res, source) {
367
+ const origin = req.headers.origin;
368
+ let allowedOrigin;
369
+ if (origin) {
370
+ try {
371
+ if (isLoopbackHost(new URL(origin).hostname)) allowedOrigin = origin;
372
+ } catch {
373
+ }
374
+ }
375
+ res.writeHead(200, {
376
+ "Content-Type": "application/javascript; charset=utf-8",
377
+ "Cache-Control": "no-cache",
378
+ ...allowedOrigin ? { "Access-Control-Allow-Origin": allowedOrigin, Vary: "Origin" } : {}
379
+ });
380
+ res.end(req.method === "HEAD" ? void 0 : source);
381
+ }
382
+ function isReplacementModuleRequestUrl(rawUrl) {
383
+ if (!rawUrl) return false;
384
+ try {
385
+ const pathname = new URL(rawUrl, "http://rnx.local").pathname;
386
+ return pathname === REPLACEMENT_MODULE_ROUTE;
387
+ } catch {
388
+ return false;
389
+ }
390
+ }
391
+ async function handleReplacementModuleRequest(req, res, options = {}) {
392
+ const rawUrl = req.url || "";
393
+ let url;
394
+ try {
395
+ url = new URL(rawUrl, "http://rnx.local");
396
+ } catch {
397
+ return false;
398
+ }
399
+ if (options.requireLoopbackOrigin) {
400
+ const origin = req.headers.origin;
401
+ const remoteAddress = req.socket.remoteAddress?.replace(/^::ffff:/, "");
402
+ let allowed = Boolean(remoteAddress && isLoopbackHost(remoteAddress));
403
+ if (allowed && origin) {
404
+ try {
405
+ allowed = isLoopbackHost(new URL(origin).hostname);
406
+ } catch {
407
+ allowed = false;
408
+ }
409
+ }
410
+ if (!allowed) {
411
+ res.writeHead(403, { "Content-Type": "text/plain; charset=utf-8" });
412
+ res.end("replacement modules are available only to loopback origins");
413
+ return true;
414
+ }
415
+ }
416
+ if (url.pathname !== REPLACEMENT_MODULE_ROUTE) return false;
417
+ if (options.requestToken && url.searchParams.get("token") !== options.requestToken) {
418
+ res.writeHead(403, { "Content-Type": "text/plain; charset=utf-8" });
419
+ res.end("replacement module request token is invalid");
420
+ return true;
421
+ }
422
+ const targetPath = url.searchParams.get("path");
423
+ if (!targetPath) {
424
+ res.writeHead(400, { "Content-Type": "text/plain; charset=utf-8" });
425
+ res.end("missing path param");
426
+ return true;
427
+ }
428
+ const extension = import_node_path.default.extname(targetPath).toLowerCase();
429
+ if (!REPLACEMENT_MODULE_EXTENSIONS.some((allowed) => allowed === extension)) {
430
+ res.writeHead(400, { "Content-Type": "text/plain; charset=utf-8" });
431
+ res.end(`replacement files must be ${REPLACEMENT_MODULE_EXTENSIONS.join(", ")}`);
432
+ return true;
433
+ }
434
+ if (!import_node_path.default.isAbsolute(targetPath)) {
435
+ res.writeHead(400, { "Content-Type": "text/plain; charset=utf-8" });
436
+ res.end("replacement file path must be absolute");
437
+ return true;
438
+ }
439
+ const runtimePackages = new Set(url.searchParams.getAll("runtimePackage"));
440
+ let resolvedProjectRoot;
441
+ if (options.projectRoot) {
442
+ const lexicalProjectRoot = import_node_path.default.resolve(options.projectRoot);
443
+ resolvedProjectRoot = await import_promises.default.realpath(options.projectRoot);
444
+ const lexicalTarget = import_node_path.default.relative(lexicalProjectRoot, targetPath);
445
+ if (lexicalTarget.startsWith("..") || import_node_path.default.isAbsolute(lexicalTarget)) {
446
+ res.writeHead(403, { "Content-Type": "text/plain; charset=utf-8" });
447
+ res.end("replacement file must be inside the project root");
448
+ return true;
449
+ }
450
+ }
451
+ let resolvedTargetPath;
452
+ try {
453
+ resolvedTargetPath = await import_promises.default.realpath(targetPath);
454
+ } catch (error) {
455
+ const message = error instanceof Error ? error.message : String(error);
456
+ res.writeHead(404, { "Content-Type": "text/plain; charset=utf-8" });
457
+ res.end(`replacement file not found: ${message}`);
458
+ return true;
459
+ }
460
+ if (resolvedProjectRoot) {
461
+ const relativeTarget = import_node_path.default.relative(resolvedProjectRoot, resolvedTargetPath);
462
+ if (relativeTarget.startsWith("..") || import_node_path.default.isAbsolute(relativeTarget)) {
463
+ res.writeHead(403, { "Content-Type": "text/plain; charset=utf-8" });
464
+ res.end("replacement file must be inside the project root");
465
+ return true;
466
+ }
467
+ }
468
+ try {
469
+ const compiled = compileReplacementModule({
470
+ filePath: resolvedTargetPath,
471
+ source: await import_promises.default.readFile(resolvedTargetPath, "utf8"),
472
+ runtimePackages
473
+ });
474
+ const map = Buffer.from(JSON.stringify(compiled.sourceMap), "utf8").toString("base64");
475
+ sendJavaScript(
476
+ req,
477
+ res,
478
+ `${compiled.code}
479
+ //# sourceMappingURL=data:application/json;base64,${map}
480
+ `
481
+ );
482
+ } catch (error) {
483
+ const message = error instanceof Error ? error.message : String(error);
484
+ res.writeHead(500, { "Content-Type": "text/plain; charset=utf-8" });
485
+ res.end(`replacement compile failed: ${message}`);
486
+ }
487
+ return true;
488
+ }
489
+
490
+ // src/metro-production-bundle.ts
491
+ var RNXSIM_METRO_MODULE_PATHS_PREFIX = "globalThis.__sootsimModulePaths=";
492
+ var RNX_METRO_MODULE_IDENTITY_VERSION = 2;
493
+ function toRNXProductionBundleUrl(bundleUrl) {
494
+ const relative2 = bundleUrl.startsWith("/");
495
+ const url = new URL(bundleUrl, "http://rnxsim.local");
496
+ url.searchParams.set("dev", "false");
497
+ url.searchParams.set("hot", "false");
498
+ url.searchParams.set("minify", "true");
499
+ return relative2 ? `${url.pathname}${url.search}${url.hash}` : url.toString();
500
+ }
501
+ function toRNXDevelopmentBundleUrl(bundleUrl) {
502
+ const relative2 = bundleUrl.startsWith("/");
503
+ const url = new URL(bundleUrl, "http://rnxsim.local");
504
+ url.searchParams.set("dev", "true");
505
+ url.searchParams.set("hot", "false");
506
+ url.searchParams.set("minify", "false");
507
+ return relative2 ? `${url.pathname}${url.search}${url.hash}` : url.toString();
508
+ }
509
+ var RNXSIM_METRO_SOURCE_MAP_COMMENT = "//# sourceMappingURL=";
510
+ function detachRNXMetroSourceMapUrl(bundleText) {
511
+ const trimmedEnd = bundleText.replace(/\s+$/, "");
512
+ const commentStart = trimmedEnd.lastIndexOf(`
513
+ ${RNXSIM_METRO_SOURCE_MAP_COMMENT}`);
514
+ if (commentStart < 0) return { source: bundleText, sourceMappingUrl: null };
515
+ const url = trimmedEnd.slice(commentStart + 1 + RNXSIM_METRO_SOURCE_MAP_COMMENT.length);
516
+ if (url.includes("\n")) return { source: bundleText, sourceMappingUrl: null };
517
+ return { source: trimmedEnd.slice(0, commentStart), sourceMappingUrl: url };
518
+ }
519
+ function createRNXMetroModuleIdentityFooter(identity) {
520
+ const payload = JSON.stringify(identity).replace(/\u2028/g, "\\u2028").replace(/\u2029/g, "\\u2029").replace(/<\//g, "<\\/");
521
+ return `
522
+ ${RNXSIM_METRO_MODULE_PATHS_PREFIX}${payload};`;
523
+ }
524
+ function appendRNXMetroModuleIdentityFooter(bundleText, identity) {
525
+ const footer = createRNXMetroModuleIdentityFooter(identity);
526
+ const detached = detachRNXMetroSourceMapUrl(bundleText);
527
+ return detached.sourceMappingUrl === null ? bundleText + footer : `${detached.source}${footer}
528
+ ${RNXSIM_METRO_SOURCE_MAP_COMMENT}${detached.sourceMappingUrl}`;
529
+ }
530
+
531
+ // src/runtime-assets.ts
532
+ var import_fs = __toESM(require("fs"), 1);
533
+ var import_path = __toESM(require("path"), 1);
534
+ var import_url = require("url");
535
+
536
+ // ../contrast-runtime-delivery/src/product.ts
537
+ function isValidRuntimeVersion(value) {
538
+ return value.length <= 100 && /^[0-9A-Za-z][0-9A-Za-z._+-]*$/.test(value);
539
+ }
540
+
541
+ // src/home-paths.ts
542
+ var import_node_fs2 = __toESM(require("node:fs"), 1);
543
+ var import_node_os = require("node:os");
544
+ var import_node_path2 = __toESM(require("node:path"), 1);
545
+ var RNX_HOME_ENV = "RNX_HOME";
546
+ var ACTIVE_RUNTIME_FILE = "active";
547
+ function rnxHomeDir() {
548
+ const override = process.env[RNX_HOME_ENV];
549
+ if (override && override.length > 0) return import_node_path2.default.resolve(override);
550
+ return import_node_path2.default.join((0, import_node_os.homedir)(), ".rnx");
551
+ }
552
+ function runtimesDir() {
553
+ return import_node_path2.default.join(rnxHomeDir(), "runtimes");
554
+ }
555
+ function runtimeDir(version) {
556
+ return import_node_path2.default.join(runtimesDir(), version);
557
+ }
558
+ function activeRuntimeFile() {
559
+ return import_node_path2.default.join(runtimesDir(), ACTIVE_RUNTIME_FILE);
560
+ }
561
+ function readActiveRuntime() {
562
+ try {
563
+ const value = import_node_fs2.default.readFileSync(activeRuntimeFile(), "utf8").trim();
564
+ return value.length > 0 ? value : null;
565
+ } catch {
566
+ return null;
567
+ }
568
+ }
569
+ var DAEMON_LOCKFILE_MAX_BYTES = 16 * 1024;
570
+
571
+ // src/runtime-assets.ts
572
+ var SOOTSIM_RUNTIME_MISSING_MESSAGE = "[rnx] no engine runtime installed. run `rnx runtime install`";
573
+ var _monorepoRootCache;
574
+ function findMonorepoRoot() {
575
+ if (_monorepoRootCache !== void 0) return _monorepoRootCache;
576
+ let dir = import_path.default.dirname((0, import_url.fileURLToPath)(__sootsim_import_meta_url));
577
+ for (let i = 0; i < 12 && dir !== import_path.default.dirname(dir); i++) {
578
+ if (import_fs.default.existsSync(import_path.default.join(dir, "packages/sootsim-engine/package.json")) && import_fs.default.existsSync(import_path.default.join(dir, "public/sootsim"))) {
579
+ _monorepoRootCache = dir;
580
+ return dir;
581
+ }
582
+ dir = import_path.default.dirname(dir);
583
+ }
584
+ _monorepoRootCache = null;
585
+ return null;
586
+ }
587
+ function resolveDevCheckoutRuntimeRoot() {
588
+ if (process.env.RNX_HOME && readActiveRuntime()) return null;
589
+ const root = findMonorepoRoot();
590
+ if (!root) return null;
591
+ const devBuild = import_path.default.join(root, "public/sootsim");
592
+ if (import_fs.default.existsSync(import_path.default.join(devBuild, "index.html")) && import_fs.default.existsSync(import_path.default.join(devBuild, "engine/index.html")) && import_fs.default.existsSync(import_path.default.join(devBuild, "engine-tenant/worker.js"))) {
593
+ return devBuild;
594
+ }
595
+ return null;
596
+ }
597
+ var MIME_TYPES = {
598
+ ".js": "application/javascript",
599
+ ".mjs": "application/javascript",
600
+ ".css": "text/css",
601
+ ".html": "text/html",
602
+ ".wasm": "application/wasm",
603
+ ".json": "application/json",
604
+ ".jpg": "image/jpeg",
605
+ ".jpeg": "image/jpeg",
606
+ ".png": "image/png",
607
+ ".svg": "image/svg+xml",
608
+ ".webp": "image/webp",
609
+ ".glb": "model/gltf-binary",
610
+ ".ttf": "font/ttf",
611
+ ".otf": "font/otf",
612
+ ".woff": "font/woff",
613
+ ".woff2": "font/woff2",
614
+ ".mp3": "audio/mpeg",
615
+ ".wav": "audio/wav"
616
+ };
617
+ var ROOT_RUNTIME_PATHS = [
618
+ "/assets/",
619
+ "/engine/",
620
+ "/engine-tenant/",
621
+ "/photos/",
622
+ "/three-mode/",
623
+ "/fonts/",
624
+ "/icons/",
625
+ "/sounds/",
626
+ "/spike/",
627
+ "/test-wallpaper.jpg",
628
+ "/preview-sw.js",
629
+ "/sootsim.svg"
630
+ ];
631
+ function resolveActiveRuntimeRoot() {
632
+ const devRoot = resolveDevCheckoutRuntimeRoot();
633
+ if (devRoot) return devRoot;
634
+ const active = readActiveRuntime();
635
+ if (!active) return null;
636
+ const dir = runtimeDir(active);
637
+ if (!import_fs.default.existsSync(import_path.default.join(dir, "index.html"))) return null;
638
+ return dir;
639
+ }
640
+ var RUNTIME_VERSION_HOSTNAME_SUFFIX = ".runtime.localhost";
641
+ function isRuntimeVersionHostname(hostname) {
642
+ return hostname.toLowerCase().endsWith(RUNTIME_VERSION_HOSTNAME_SUFFIX);
643
+ }
644
+ function runtimeVersionFromHostname(hostname) {
645
+ if (!isRuntimeVersionHostname(hostname)) return null;
646
+ const labels = hostname.slice(0, -RUNTIME_VERSION_HOSTNAME_SUFFIX.length).split(".");
647
+ if (labels.length === 0 || labels.some((label) => !/^[0-9a-f]{1,60}$/i.test(label))) {
648
+ return null;
649
+ }
650
+ const encoded = labels.join("");
651
+ if (encoded.length % 2 !== 0) return null;
652
+ try {
653
+ const version = Buffer.from(encoded, "hex").toString("utf8");
654
+ return isValidRuntimeVersion(version) ? version : null;
655
+ } catch {
656
+ return null;
657
+ }
658
+ }
659
+ function resolveInstalledRuntimeRoot(version) {
660
+ const dir = runtimeDir(version);
661
+ if (!import_fs.default.existsSync(import_path.default.join(dir, "index.html"))) return null;
662
+ return dir;
663
+ }
664
+ function resolveRuntimeRootForHostname(hostname) {
665
+ if (!isRuntimeVersionHostname(hostname)) return resolveActiveRuntimeRoot();
666
+ const version = runtimeVersionFromHostname(hostname);
667
+ return version ? resolveInstalledRuntimeRoot(version) : null;
668
+ }
669
+ function resolveRuntimeRootForRequestHost(host) {
670
+ if (!host) return resolveActiveRuntimeRoot();
671
+ try {
672
+ return resolveRuntimeRootForHostname(new URL(`http://${host}`).hostname);
673
+ } catch {
674
+ return null;
675
+ }
676
+ }
677
+ function isRootRuntimeAssetPath(pathname) {
678
+ return ROOT_RUNTIME_PATHS.some((p) => pathname === p || pathname.startsWith(p));
679
+ }
680
+ function resolveRuntimeFilePath(runtimeRoot, pathname) {
681
+ if (!pathname.startsWith("/")) return null;
682
+ if (pathname.includes("\0") || pathname.includes("\\")) return null;
683
+ for (const segment of pathname.split("/")) {
684
+ if (segment === "..") return null;
685
+ }
686
+ const fullPath = import_path.default.resolve(runtimeRoot, pathname.replace(/^\/+/, ""));
687
+ const rootWithSep = runtimeRoot.endsWith(import_path.default.sep) ? runtimeRoot : runtimeRoot + import_path.default.sep;
688
+ if (!fullPath.startsWith(rootWithSep) && fullPath !== runtimeRoot) return null;
689
+ if (!import_fs.default.existsSync(fullPath) || !import_fs.default.statSync(fullPath).isFile()) return null;
690
+ return fullPath;
691
+ }
692
+ function serveRuntimeFile(req, res, fullPath) {
693
+ const ext = import_path.default.extname(fullPath);
694
+ const stat = import_fs.default.statSync(fullPath);
695
+ const lastModified = stat.mtime.toUTCString();
696
+ res.setHeader("content-type", MIME_TYPES[ext] || "application/octet-stream");
697
+ if (/^canvaskit-graphite-pipelines-[0-9a-f]{8}\.bin$/.test(import_path.default.basename(fullPath))) {
698
+ res.setHeader("cache-control", "public, max-age=31536000, immutable");
699
+ import_fs.default.createReadStream(fullPath).pipe(res);
700
+ return;
701
+ }
702
+ res.setHeader("cache-control", "no-cache");
703
+ res.setHeader("last-modified", lastModified);
704
+ if (req?.headers?.["if-modified-since"] === lastModified) {
705
+ res.statusCode = 304;
706
+ res.end();
707
+ return;
708
+ }
709
+ import_fs.default.createReadStream(fullPath).pipe(res);
710
+ }
711
+
712
+ // src/metro-plugin.ts
713
+ var prefix = "/__soot";
714
+ function readCallableMetroExport(moduleValue, label) {
715
+ const callable = typeof moduleValue === "function" ? moduleValue : typeof moduleValue === "object" && moduleValue !== null ? Reflect.get(moduleValue, "default") : void 0;
716
+ if (typeof callable !== "function") {
717
+ throw new Error(`rnxsim: Metro ${label} module did not export a function`);
718
+ }
719
+ return (...args) => Reflect.apply(callable, void 0, args);
720
+ }
721
+ function createMetroDefaultSerializer(projectRoot) {
722
+ const projectRequire = (0, import_module.createRequire)(import_path2.default.join(projectRoot, "package.json"));
723
+ const metroRoot = import_path2.default.dirname(projectRequire.resolve("metro/package.json"));
724
+ const baseJSBundle = readCallableMetroExport(
725
+ projectRequire(import_path2.default.join(metroRoot, "src/DeltaBundler/Serializers/baseJSBundle.js")),
726
+ "baseJSBundle"
727
+ );
728
+ const bundleToString = readCallableMetroExport(
729
+ projectRequire(import_path2.default.join(metroRoot, "src/lib/bundleToString.js")),
730
+ "bundleToString"
731
+ );
732
+ return (entryPoint, preModules, graph, options) => {
733
+ const serialized = bundleToString(
734
+ baseJSBundle(entryPoint, preModules, graph, options)
735
+ );
736
+ const code = typeof serialized === "object" && serialized !== null ? Reflect.get(serialized, "code") : void 0;
737
+ if (typeof code !== "string") {
738
+ throw new Error("rnxsim: Metro bundleToString did not return bundle code");
739
+ }
740
+ return code;
741
+ };
742
+ }
743
+ function appendRNXModulePaths(result, graph, options, projectRoot) {
744
+ const dependencies = graph.dependencies;
745
+ const createModuleId = options.createModuleId;
746
+ if (!dependencies || !createModuleId) {
747
+ return result;
748
+ }
749
+ const modulePaths = {};
750
+ for (const module2 of dependencies.values()) {
751
+ modulePaths[String(createModuleId(module2.path))] = import_path2.default.relative(projectRoot, module2.path).replaceAll(import_path2.default.sep, "/");
752
+ }
753
+ if (Object.keys(modulePaths).length !== dependencies.size) {
754
+ throw new Error("rnxsim: bundle module IDs were not unique");
755
+ }
756
+ const specifiersByModuleId = /* @__PURE__ */ new Map();
757
+ for (const module2 of dependencies.values()) {
758
+ for (const [dependencyKey, dependency] of module2.dependencies ?? []) {
759
+ const specifier = dependency.data?.name ?? dependencyKey;
760
+ if (specifier.length === 0 || specifier.startsWith(".") || specifier.startsWith("/") || typeof dependency.absolutePath !== "string") {
761
+ continue;
762
+ }
763
+ const moduleId = String(createModuleId(dependency.absolutePath));
764
+ if (!Object.prototype.hasOwnProperty.call(modulePaths, moduleId)) continue;
765
+ const found = specifiersByModuleId.get(moduleId);
766
+ if (found) found.add(specifier);
767
+ else specifiersByModuleId.set(moduleId, /* @__PURE__ */ new Set([specifier]));
768
+ }
769
+ }
770
+ const logicalSpecifiers = Object.fromEntries(
771
+ [...specifiersByModuleId].sort(([left], [right]) => Number(left) - Number(right)).map(([moduleId, specifiers]) => [moduleId, [...specifiers].sort()])
772
+ );
773
+ const identity = {
774
+ version: RNX_METRO_MODULE_IDENTITY_VERSION,
775
+ identitySource: "rnx-plugin",
776
+ modulePaths,
777
+ logicalSpecifiers
778
+ };
779
+ return typeof result === "string" ? appendRNXMetroModuleIdentityFooter(result, identity) : { ...result, code: appendRNXMetroModuleIdentityFooter(result.code, identity) };
780
+ }
781
+ function withRNX(config) {
782
+ const cfgProjectRoot = config.projectRoot || process.cwd();
783
+ const configuredBundleUrl = "/index.bundle?platform=ios&dev=true&hot=true&minify=false";
784
+ const cfgServer = config.server;
785
+ const port = resolveMetroPort(cfgServer);
786
+ const metroServerId = (0, import_node_crypto2.randomUUID)();
787
+ const bundleUrl = tagRnxBundleForPlugin(
788
+ configuredBundleUrl,
789
+ `http://localhost:${port}`,
790
+ metroServerId,
791
+ cfgProjectRoot
792
+ );
793
+ const cfgSerializer = config.serializer;
794
+ const existingEnhance = cfgServer?.enhanceMiddleware;
795
+ const existingSerializer = cfgSerializer?.customSerializer;
796
+ let defaultSerializer;
797
+ const serializerConfig = {
798
+ serializer: {
799
+ ...cfgSerializer,
800
+ customSerializer: async (entryPoint, preModules, graph, serializerOptions) => {
801
+ const serializer = existingSerializer || (defaultSerializer ||= createMetroDefaultSerializer(cfgProjectRoot));
802
+ const result = await serializer(entryPoint, preModules, graph, serializerOptions);
803
+ return appendRNXModulePaths(result, graph, serializerOptions, cfgProjectRoot);
804
+ }
805
+ }
806
+ };
807
+ const serverConfig = {
808
+ ...cfgServer,
809
+ enhanceMiddleware: (metroMiddleware, metroServer) => {
810
+ let middleware = metroMiddleware;
811
+ if (existingEnhance) {
812
+ middleware = existingEnhance(metroMiddleware, metroServer);
813
+ }
814
+ let connect;
815
+ try {
816
+ connect = require("connect");
817
+ } catch {
818
+ console.warn("[rnx] connect not available");
819
+ return middleware;
820
+ }
821
+ const server = connect();
822
+ server.use((req, res, next) => {
823
+ if (isReplacementModuleRequestUrl(req.url)) {
824
+ void handleReplacementModuleRequest(req, res, {
825
+ projectRoot: cfgProjectRoot,
826
+ requestToken: metroServerId,
827
+ requireLoopbackOrigin: true
828
+ }).then((handled) => {
829
+ if (!handled) next();
830
+ });
831
+ return;
832
+ }
833
+ const url = req.url || "";
834
+ const pathname = url.split("?")[0];
835
+ const runtimeRoot = resolveRuntimeRootForRequestHost(req.headers?.host);
836
+ if (!runtimeRoot) {
837
+ if (pathname === prefix || pathname === prefix + "/") {
838
+ res.statusCode = 500;
839
+ res.end(SOOTSIM_RUNTIME_MISSING_MESSAGE);
840
+ return;
841
+ }
842
+ next();
843
+ return;
844
+ }
845
+ if (isRootRuntimeAssetPath(pathname)) {
846
+ const fullPath = resolveRuntimeFilePath(runtimeRoot, pathname);
847
+ if (fullPath) {
848
+ serveRuntimeFile(req, res, fullPath);
849
+ return;
850
+ }
851
+ }
852
+ if (pathname.startsWith(prefix + "/")) {
853
+ const fullPath = resolveRuntimeFilePath(
854
+ runtimeRoot,
855
+ pathname.slice(prefix.length)
856
+ );
857
+ if (fullPath) {
858
+ serveRuntimeFile(req, res, fullPath);
859
+ return;
860
+ }
861
+ }
862
+ if (pathname === prefix || pathname === prefix + "/" || pathname.startsWith(prefix + "/")) {
863
+ const ext = import_path2.default.extname(pathname);
864
+ if (!ext) {
865
+ const htmlPath = import_path2.default.join(runtimeRoot, "index.html");
866
+ let html = import_fs2.default.readFileSync(htmlPath, "utf8");
867
+ const script = `<script>(function(){var u=new URL(location.href);if(!u.searchParams.has('bundle'))u.searchParams.set('bundle',${JSON.stringify(bundleUrl)});history.replaceState(null,'','${prefix}/'+u.search)})()</script>`;
868
+ html = html.includes("</head>") ? html.replace("</head>", `${script}</head>`) : `${html}${script}`;
869
+ res.setHeader("content-type", "text/html");
870
+ res.end(html);
871
+ return;
872
+ }
873
+ }
874
+ next();
875
+ });
876
+ server.use(middleware);
877
+ console.log(`[rnx] serving at ${prefix}/`);
878
+ return server;
879
+ }
880
+ };
881
+ return {
882
+ ...config,
883
+ ...serializerConfig,
884
+ server: serverConfig
885
+ };
886
+ }
887
+ function resolveMetroPort(server) {
888
+ const inlinePort = process.argv.find((arg) => arg.startsWith("--port="))?.slice(7);
889
+ const portIndex = process.argv.indexOf("--port");
890
+ const splitPort = portIndex >= 0 ? process.argv[portIndex + 1] : void 0;
891
+ const rawPort = inlinePort || splitPort || process.env.RCT_METRO_PORT || server?.port || 8081;
892
+ const port = Number(rawPort);
893
+ if (!Number.isInteger(port) || port <= 0) {
894
+ throw new Error(`rnx: Metro port must be a positive integer, got ${rawPort}`);
895
+ }
896
+ return port;
897
+ }
898
+ var metro_plugin_default = withRNX;
899
+ // Annotate the CommonJS export names for ESM import in node:
900
+ 0 && (module.exports = {
901
+ toRNXDevelopmentBundleUrl,
902
+ toRNXProductionBundleUrl,
903
+ withRNX
904
+ });