rnxsim 0.1.444 → 0.1.446

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 (61) hide show
  1. package/cli/auth.ts +2 -2
  2. package/cli/cloud-client.ts +13 -13
  3. package/cli/cloud-session.ts +1 -1
  4. package/cli/commands/detox.ts +18 -0
  5. package/cli/commands/inspect.ts +2 -2
  6. package/cli/outbound-endpoints.ts +0 -2
  7. package/cli/send-to-box.ts +7 -7
  8. package/detox/index.ts +21 -1
  9. package/dist-lib/agent-daemon-client.cjs +1 -1
  10. package/dist-lib/agent-events.cjs +1 -1
  11. package/dist-lib/agent-identity.cjs +1 -1
  12. package/dist-lib/agent-sessions.cjs +1 -1
  13. package/dist-lib/attached-projects.cjs +1 -1
  14. package/dist-lib/auth/shared-session.cjs +1 -1
  15. package/dist-lib/backend-origin.cjs +1 -1
  16. package/dist-lib/beta.cjs +1 -1
  17. package/dist-lib/beta.mjs +1 -1
  18. package/dist-lib/bridge-constants.cjs +1 -1
  19. package/dist-lib/bridge-contract-input.cjs +1 -1
  20. package/dist-lib/bridge-contract-input.mjs +1 -1
  21. package/dist-lib/bridge-contract.cjs +1 -1
  22. package/dist-lib/bridge-contract.mjs +1 -1
  23. package/dist-lib/capture-contract.cjs +1 -1
  24. package/dist-lib/capture-contract.mjs +1 -1
  25. package/dist-lib/cli-constants.cjs +1 -1
  26. package/dist-lib/cloud-contract.cjs +1 -1
  27. package/dist-lib/cloud-contract.mjs +1 -1
  28. package/dist-lib/cloud.cjs +1 -1
  29. package/dist-lib/cloud.mjs +1 -1
  30. package/dist-lib/config.cjs +1 -1
  31. package/dist-lib/detox/index.cjs +16 -1
  32. package/dist-lib/dev-bundle-resolution.cjs +1 -1
  33. package/dist-lib/home-paths.cjs +1 -1
  34. package/dist-lib/host/bridge-host.cjs +178 -178
  35. package/dist-lib/host/fetch-proxy-handler.cjs +1 -1
  36. package/dist-lib/host/fetch-proxy-overrides.cjs +1 -1
  37. package/dist-lib/host/fetch-proxy-overrides.mjs +1 -1
  38. package/dist-lib/host/replacement-module-handler.cjs +1 -1
  39. package/dist-lib/host/websocket-proxy.cjs +1 -1
  40. package/dist-lib/index.cjs +4 -4
  41. package/dist-lib/jump-to-source-babel.cjs +1 -1
  42. package/dist-lib/menu.cjs +1 -1
  43. package/dist-lib/menu.mjs +1 -1
  44. package/dist-lib/metro-fingerprint-registry.cjs +1 -1
  45. package/dist-lib/metro-fingerprint-registry.mjs +1 -1
  46. package/dist-lib/metro-production-bundle.cjs +1 -1
  47. package/dist-lib/metro-production-bundle.mjs +1 -1
  48. package/dist-lib/metro.cjs +1 -1
  49. package/dist-lib/profiles.cjs +1 -1
  50. package/dist-lib/public-brand.cjs +1 -1
  51. package/dist-lib/react-native-host-modules.cjs +1 -1
  52. package/dist-lib/react-native-host-modules.mjs +1 -1
  53. package/dist-lib/render-mode.cjs +1 -1
  54. package/dist-lib/scripts/dev-server-scanner.cjs +1 -1
  55. package/dist-lib/sdk.cjs +1 -1
  56. package/dist-lib/sdk.mjs +1 -1
  57. package/dist-lib/skills.cjs +198 -201
  58. package/dist-lib/vite.cjs +1 -1
  59. package/package.json +1 -1
  60. package/src/auth/shared-session.ts +1 -1
  61. package/src/cloud-contract.ts +1 -1
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.444 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.446 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __create = Object.create;
@@ -1469,10 +1469,11 @@ var init_capability_outcomes2 = __esm({
1469
1469
  });
1470
1470
 
1471
1471
  // ../compat/src/generated/react-native-root-export-coverage.ts
1472
- var REACT_NATIVE_ROOT_EXPORT_STRICT_COVERAGE;
1472
+ var REACT_NATIVE_ROOT_EXPORT_WILL_IT_WORK_COVERAGE, REACT_NATIVE_ROOT_EXPORT_STRICT_COVERAGE;
1473
1473
  var init_react_native_root_export_coverage = __esm({
1474
1474
  "../compat/src/generated/react-native-root-export-coverage.ts"() {
1475
1475
  "use strict";
1476
+ REACT_NATIVE_ROOT_EXPORT_WILL_IT_WORK_COVERAGE = 0.99;
1476
1477
  REACT_NATIVE_ROOT_EXPORT_STRICT_COVERAGE = 0.765;
1477
1478
  }
1478
1479
  });
@@ -1748,7 +1749,7 @@ var init_supported_native_packages = __esm({
1748
1749
  "posthog-react-native-session-replay",
1749
1750
  // preset+coverage
1750
1751
  "react-native",
1751
- // preset+visual-proof
1752
+ // preset+visual-proof+coverage
1752
1753
  "react-native-actions-shortcuts",
1753
1754
  // coverage
1754
1755
  "react-native-adjust",
@@ -1794,7 +1795,7 @@ var init_supported_native_packages = __esm({
1794
1795
  "react-native-fs",
1795
1796
  // coverage
1796
1797
  "react-native-gesture-handler",
1797
- // preset
1798
+ // preset+coverage
1798
1799
  "react-native-get-device-locale",
1799
1800
  // coverage
1800
1801
  "react-native-get-location",
@@ -1872,7 +1873,7 @@ var init_supported_native_packages = __esm({
1872
1873
  "react-native-randombytes",
1873
1874
  // coverage
1874
1875
  "react-native-reanimated",
1875
- // preset+visual-proof
1876
+ // preset+visual-proof+coverage
1876
1877
  "react-native-restart",
1877
1878
  // coverage
1878
1879
  "react-native-restart-newarch",
@@ -1884,7 +1885,7 @@ var init_supported_native_packages = __esm({
1884
1885
  "react-native-screen-corner-radius",
1885
1886
  // coverage
1886
1887
  "react-native-screens",
1887
- // preset+visual-proof
1888
+ // preset+visual-proof+coverage
1888
1889
  "react-native-securerandom",
1889
1890
  // coverage
1890
1891
  "react-native-settings",
@@ -1993,6 +1994,13 @@ var init_unsupported_packages = __esm({
1993
1994
  });
1994
1995
 
1995
1996
  // ../compat/src/registry.ts
1997
+ function scoredCoverage(packageName, estimate) {
1998
+ const outcomes = CAPABILITY_PACKAGE_OUTCOMES[packageName];
1999
+ const measured = outcomes.byPlatform.ios.compatibility;
2000
+ if (measured === null)
2001
+ return { coverage: estimate, estimate, coverageSource: "estimated" };
2002
+ return { coverage: measured, estimate, coverageSource: "measured", outcomes };
2003
+ }
1996
2004
  var COMPAT_CATEGORIES, POLYFILL_REGISTRY;
1997
2005
  var init_registry = __esm({
1998
2006
  "../compat/src/registry.ts"() {
@@ -2035,10 +2043,8 @@ var init_registry = __esm({
2035
2043
  range: ">=0.86.0 <0.87.0",
2036
2044
  // outcomes measure declared scenarios; strictCoverage remains an
2037
2045
  // independent equal-export implementation estimate.
2038
- coverage: CAPABILITY_PACKAGE_OUTCOMES["react-native"].byPlatform.ios.compatibility,
2046
+ ...scoredCoverage("react-native", REACT_NATIVE_ROOT_EXPORT_WILL_IT_WORK_COVERAGE),
2039
2047
  strictCoverage: REACT_NATIVE_ROOT_EXPORT_STRICT_COVERAGE,
2040
- coverageSource: "measured",
2041
- outcomes: CAPABILITY_PACKAGE_OUTCOMES["react-native"],
2042
2048
  capabilityCoverage: CAPABILITY_INVENTORY_PACKAGE_COVERAGE["react-native"],
2043
2049
  note: "React Native 0.86 root surface with useful core rendering, input, scrolling, animation, list, platform, and native-module behavior",
2044
2050
  working: "all 99 React Native 0.86.2 public runtime root export names; flex and absolute layout, text shaping and wrapping, image loading and resize modes, touch and responder routing, controlled text input and keyboard presentation, vertical and horizontal scrolling with paging/snapping/sticky and maintained content, windowed/inverted/horizontal lists, common Animated graphs and composition, core LayoutAnimation create/update/delete geometry, alerts and action sheets, live platform/dimension/appearance state, and explicit native-module lookup",
@@ -2059,9 +2065,7 @@ var init_registry = __esm({
2059
2065
  },
2060
2066
  {
2061
2067
  range: ">=4.0.0 <5.0.0",
2062
- coverage: CAPABILITY_PACKAGE_OUTCOMES["react-native-reanimated"].byPlatform.ios.compatibility,
2063
- coverageSource: "measured",
2064
- outcomes: CAPABILITY_PACKAGE_OUTCOMES["react-native-reanimated"],
2068
+ ...scoredCoverage("react-native-reanimated", 0.97),
2065
2069
  capabilityCoverage: CAPABILITY_INVENTORY_PACKAGE_COVERAGE["react-native-reanimated"],
2066
2070
  note: "core animations, gestures, scroll, layout transitions, common CSS opacity, transform, and processed-color transitions and keyframes, keyboard, sensors, reduced motion, native view property reads, and direct static style snapshots",
2067
2071
  working: "useSharedValue, useAnimatedStyle/Props/Reaction, useDerivedValue, useAnimatedScrollHandler, useScrollViewOffset, useFrameCallback, useAnimatedRef, useAnimatedKeyboard, useAnimatedSensor, useReducedMotion, entering/exiting/layout transitions, css/createCSSAnimatedComponent with cubicBezier/linear/steps timing for common opacity and transform transitions, opacity and transform keyframes with retained forwards fill, withTiming/Spring/Decay/Delay/Sequence/Repeat/Clamp, interpolate, interpolateColor, runOnJS/UI, measure, scrollTo, getViewProp (layout, opacity, zIndex, backgroundColor, boxShadow), direct setViewStyle snapshots, Easing, createAnimatedComponent, Animated.View/Text/Image/ScrollView/FlatList",
@@ -2077,9 +2081,7 @@ var init_registry = __esm({
2077
2081
  { range: ">=2.0.0 <2.30.0", coverage: 0.7, note: "tap, pan, long press" },
2078
2082
  {
2079
2083
  range: ">=2.30.0 <3.0.0",
2080
- coverage: CAPABILITY_PACKAGE_OUTCOMES["react-native-gesture-handler"].byPlatform.ios.compatibility,
2081
- coverageSource: "measured",
2082
- outcomes: CAPABILITY_PACKAGE_OUTCOMES["react-native-gesture-handler"],
2084
+ ...scoredCoverage("react-native-gesture-handler", 0.9),
2083
2085
  capabilityCoverage: CAPABILITY_INVENTORY_PACKAGE_COVERAGE["react-native-gesture-handler"],
2084
2086
  note: "tap, pan, pinch, rotation, fling, long press, race, manual, simultaneous, force touch unavailable-hardware parity",
2085
2087
  working: "GestureDetector, Gesture.Tap/Pan/Pinch/Rotation/Fling/LongPress/ForceTouch/Manual/Race/Simultaneous/Exclusive/Hover, ForceTouchGestureHandler unavailable-hardware fallback (children render, forceTouchAvailable false, no force events), simultaneousWithExternalGesture/requireExternalGestureToFail/blocksExternalGesture, ScrollView/FlatList, Switch/RefreshControl, Pressable/Text, Touchables, BaseButton/RawButton/RectButton/BorderlessButton/PureNativeButton, Swipeable, ReanimatedSwipeable, DrawerLayout (the upstream component running on this seam: renderNavigationView, drawerPosition/drawerType/drawerWidth/edgeWidth, openDrawer/closeDrawer, edge-swipe drag, onDrawerOpen/onDrawerClose/onDrawerStateChanged), GestureHandlerRootView, createNativeWrapper, gestureHandlerRootHOC, PointerType/MouseButton/HoverEffect exports, velocity tracking, activeOffsets, multi-tap"
@@ -2094,9 +2096,7 @@ var init_registry = __esm({
2094
2096
  { range: ">=3.0.0 <4.0.0", coverage: 0.6, note: "basic screen container" },
2095
2097
  {
2096
2098
  range: ">=4.0.0",
2097
- coverage: CAPABILITY_PACKAGE_OUTCOMES["react-native-screens"].byPlatform.ios.compatibility,
2098
- coverageSource: "measured",
2099
- outcomes: CAPABILITY_PACKAGE_OUTCOMES["react-native-screens"],
2099
+ ...scoredCoverage("react-native-screens", 0.95),
2100
2100
  capabilityCoverage: CAPABILITY_INVENTORY_PACKAGE_COVERAGE["react-native-screens"],
2101
2101
  note: "screen container, stack, header config, search bar, navigation props",
2102
2102
  working: "Screen, ScreenContainer, ScreenStack, enableFreeze/freezeEnabled with delayed React freeze, Android modal/pageSheet push fallback, Android statusBarHidden/statusBarStyle/navigationBarHidden traits, push/pop slide, replaceAnimation push/pop direction, zoom/fade/fade_from_bottom transitions, edge swipe-back, parallax behind-screen, large title collapse, header (back button, inline/large title, custom left/center/right/search bar subviews, native header bar buttons/menus/badges, crossfade), formSheet custom initial detents/corner radius/grabber/undimmed range and stacked sheets, useHeaderHeight, useTransitionProgress, FullWindowOverlay, SearchBar with stacked and iOS 26 automatic/inline/integrated/integratedCentered/integratedButton toolbar placement, Tabs.Host/Screen, lifecycle callbacks (onAppear/onDisappear/onWillAppear/onWillDisappear), onDismissed",
@@ -2125,9 +2125,7 @@ var init_registry = __esm({
2125
2125
  versions: [
2126
2126
  {
2127
2127
  range: ">=13.0.0",
2128
- coverage: CAPABILITY_PACKAGE_OUTCOMES["react-native-svg"].byPlatform.ios.compatibility,
2129
- coverageSource: "measured",
2130
- outcomes: CAPABILITY_PACKAGE_OUTCOMES["react-native-svg"],
2128
+ ...scoredCoverage("react-native-svg", 0.85),
2131
2129
  capabilityCoverage: CAPABILITY_INVENTORY_PACKAGE_COVERAGE["react-native-svg"],
2132
2130
  note: "full CanvasKit rendering for shapes, text, XML, gradients, references, masks, clipping, and images; SVG filter elements skipped",
2133
2131
  working: "Svg, Path, Circle, Rect, Line, Ellipse, Polygon, Polyline, G, Text, TSpan, Defs, LinearGradient and RadialGradient with objectBoundingBox/userSpaceOnUse coordinates, focal points and gradientTransform, Stop, Mask, ClipPath, Image, Use and Symbol references, SvgXml, SvgUri, SvgAst, SvgFromXml, SvgCss, parse, fetchText, camelCase, shape transforms, fill/stroke/opacity/dasharray, currentColor, viewBox scaling",
@@ -2243,9 +2241,7 @@ var init_registry = __esm({
2243
2241
  versions: [
2244
2242
  {
2245
2243
  range: ">=1.0.0",
2246
- coverage: CAPABILITY_PACKAGE_OUTCOMES["react-native-keyboard-controller"].byPlatform.ios.compatibility,
2247
- coverageSource: "measured",
2248
- outcomes: CAPABILITY_PACKAGE_OUTCOMES["react-native-keyboard-controller"],
2244
+ ...scoredCoverage("react-native-keyboard-controller", 0.88),
2249
2245
  capabilityCoverage: CAPABILITY_INVENTORY_PACKAGE_COVERAGE["react-native-keyboard-controller"],
2250
2246
  note: "native bindings stubbed (KeyboardControllerNative, KeyboardEvents, FocusedInputEvents, WindowDimensionsEvents, KeyboardControllerView + sibling native views); upstream pure-JS components, hooks, animated module, and KeyboardAvoidingView resolve from node_modules unchanged",
2251
2247
  working: "every upstream JS export runs through reanimated worklets; Android KeyboardGestureArea drives the existing keyboard owner through drag progress, velocity/distance settling, cancellation, focus retention, and cleanup; supported exports include KeyboardProvider, KeyboardAvoidingView, KeyboardStickyView, KeyboardAwareScrollView, KeyboardToolbar, KeyboardGestureArea, useReanimatedKeyboardAnimation, useKeyboardAnimation, useKeyboardHandler, useGenericKeyboardHandler, useKeyboardController, useKeyboardState, useKeyboardContext, useReanimatedFocusedInput, useFocusedInputHandler, useResizeMode, useWindowDimensions, KeyboardEvents, FocusedInputEvents, WindowDimensionsEvents resize events, KeyboardController (dismiss/setFocusTo/isVisible/state/preload/setInputMode/setDefaultMode), KeyboardControllerView, OverKeyboardView, KeyboardBackgroundView, KeyboardExtender, ClippingScrollView, KeyboardToolbarGroupView, and AndroidSoftInputModes",
@@ -14302,6 +14298,7 @@ function matchCompatVersion(entry, declaredVersion) {
14302
14298
  return {
14303
14299
  ...resolution,
14304
14300
  coverage: selected.coverage,
14301
+ ...selected.estimate !== void 0 ? { estimate: selected.estimate } : {},
14305
14302
  coverageSource: selected.coverageSource ?? "estimated",
14306
14303
  ...selected.outcomes ? { outcomes: selected.outcomes } : {},
14307
14304
  note: selected.note,
@@ -22036,6 +22033,180 @@ var init_metroCloudArtifact = __esm({
22036
22033
  }
22037
22034
  });
22038
22035
 
22036
+ // ../sootsim-engine/src/metro-fingerprint-registry-client.ts
22037
+ function pointerUrl(options) {
22038
+ return options.pointerUrl ?? new URL(import_metro_fingerprint_registry.RNX_METRO_FINGERPRINT_POINTER_PATH, DEFAULT_REGISTRY_ORIGIN).toString();
22039
+ }
22040
+ async function sha256Hex(bytes) {
22041
+ const input = new Uint8Array(bytes.byteLength);
22042
+ input.set(bytes);
22043
+ const digest = new Uint8Array(await crypto.subtle.digest("SHA-256", input.buffer));
22044
+ return [...digest].map((byte) => byte.toString(16).padStart(2, "0")).join("");
22045
+ }
22046
+ async function openRegistryCache() {
22047
+ if (typeof globalThis.caches?.open !== "function") return null;
22048
+ try {
22049
+ return await globalThis.caches.open(REGISTRY_CACHE_NAME);
22050
+ } catch {
22051
+ return null;
22052
+ }
22053
+ }
22054
+ function cacheKey(baseUrl, suffix) {
22055
+ const url = new URL(baseUrl);
22056
+ url.pathname = `${url.pathname.replace(/\/[^/]*$/, "")}/.rnx-fingerprint-cache/${suffix}`;
22057
+ url.search = "";
22058
+ url.hash = "";
22059
+ return new Request(url.toString());
22060
+ }
22061
+ async function parseRegistryBytes(args) {
22062
+ if (args.bytes.byteLength > import_metro_fingerprint_registry.RNX_METRO_FINGERPRINT_MAX_PAYLOAD_BYTES) {
22063
+ throw new Error(
22064
+ `RNX Metro fingerprint registry exceeds ${import_metro_fingerprint_registry.RNX_METRO_FINGERPRINT_MAX_PAYLOAD_BYTES} bytes`
22065
+ );
22066
+ }
22067
+ const integrity = await sha256Hex(args.bytes);
22068
+ if (integrity !== args.expectedIntegrity) {
22069
+ throw new Error("RNX Metro fingerprint registry integrity mismatch");
22070
+ }
22071
+ let parsed;
22072
+ try {
22073
+ parsed = JSON.parse(new TextDecoder().decode(args.bytes));
22074
+ } catch {
22075
+ throw new Error("RNX Metro fingerprint registry is not valid JSON");
22076
+ }
22077
+ const registry = (0, import_metro_fingerprint_registry.parseRNXMetroFingerprintRegistry)(parsed);
22078
+ if (!registry) throw new Error("RNX Metro fingerprint registry is malformed");
22079
+ if (args.expectedRevision && registry.revision !== args.expectedRevision) {
22080
+ throw new Error("RNX Metro fingerprint registry revision does not match its pointer");
22081
+ }
22082
+ return { registry, integrity, source: args.source };
22083
+ }
22084
+ async function readCachedRegistry(cache, baseUrl, integrity, expectedRevision) {
22085
+ const response = await cache.match(cacheKey(baseUrl, integrity));
22086
+ if (!response?.ok) return null;
22087
+ try {
22088
+ return await parseRegistryBytes({
22089
+ bytes: new Uint8Array(await response.arrayBuffer()),
22090
+ expectedIntegrity: integrity,
22091
+ expectedRevision,
22092
+ source: "cache"
22093
+ });
22094
+ } catch {
22095
+ return null;
22096
+ }
22097
+ }
22098
+ async function readLastCachedRegistry(cache, baseUrl) {
22099
+ const memoryReceipt = memoryReceipts.get(baseUrl);
22100
+ if (!cache) return memoryReceipt ? { ...memoryReceipt, source: "cache" } : null;
22101
+ const latest = await cache.match(cacheKey(baseUrl, "latest"));
22102
+ if (!latest?.ok) return memoryReceipt ? { ...memoryReceipt, source: "cache" } : null;
22103
+ const integrity = latest.headers.get("x-rnx-registry-integrity");
22104
+ if (!integrity || !/^[a-f0-9]{64}$/.test(integrity)) {
22105
+ return memoryReceipt ? { ...memoryReceipt, source: "cache" } : null;
22106
+ }
22107
+ return await readCachedRegistry(cache, baseUrl, integrity) ?? (memoryReceipt ? { ...memoryReceipt, source: "cache" } : null);
22108
+ }
22109
+ async function writeCachedRegistry(cache, baseUrl, bytes, receipt) {
22110
+ memoryReceipts.set(baseUrl, receipt);
22111
+ if (!cache) return;
22112
+ const headers = {
22113
+ "content-type": "application/json",
22114
+ "x-rnx-registry-integrity": receipt.integrity
22115
+ };
22116
+ try {
22117
+ await cache.put(
22118
+ cacheKey(baseUrl, receipt.integrity),
22119
+ new Response(bytes.slice(), { headers })
22120
+ );
22121
+ await cache.put(cacheKey(baseUrl, "latest"), new Response("", { headers }));
22122
+ } catch {
22123
+ }
22124
+ }
22125
+ async function readPointer(response) {
22126
+ const bytes = new Uint8Array(await response.arrayBuffer());
22127
+ if (bytes.byteLength > import_metro_fingerprint_registry.RNX_METRO_FINGERPRINT_MAX_POINTER_BYTES) {
22128
+ throw new Error(
22129
+ `RNX Metro fingerprint pointer exceeds ${import_metro_fingerprint_registry.RNX_METRO_FINGERPRINT_MAX_POINTER_BYTES} bytes`
22130
+ );
22131
+ }
22132
+ let parsed;
22133
+ try {
22134
+ parsed = JSON.parse(new TextDecoder().decode(bytes));
22135
+ } catch {
22136
+ throw new Error("RNX Metro fingerprint pointer is not valid JSON");
22137
+ }
22138
+ const pointer = (0, import_metro_fingerprint_registry.parseRNXMetroFingerprintPointer)(parsed);
22139
+ if (!pointer) throw new Error("RNX Metro fingerprint pointer is malformed");
22140
+ return pointer;
22141
+ }
22142
+ async function loadMetroFingerprintRegistry(options = {}) {
22143
+ const baseUrl = pointerUrl(options);
22144
+ const request = options.fetch ?? globalThis.fetch;
22145
+ const cache = await openRegistryCache();
22146
+ let pointer;
22147
+ try {
22148
+ const response = await request(baseUrl, { cache: "no-store" });
22149
+ if (!response.ok) {
22150
+ throw new Error(`RNX Metro fingerprint pointer answered ${response.status}`);
22151
+ }
22152
+ pointer = await readPointer(response);
22153
+ } catch (error) {
22154
+ const fallback = await readLastCachedRegistry(cache, baseUrl);
22155
+ if (fallback) return fallback;
22156
+ throw error;
22157
+ }
22158
+ const memoryReceipt = memoryReceipts.get(baseUrl);
22159
+ if (memoryReceipt?.integrity === pointer.integrity && memoryReceipt.registry.revision === pointer.revision) {
22160
+ return { ...memoryReceipt, source: "cache" };
22161
+ }
22162
+ const cached4 = cache ? await readCachedRegistry(cache, baseUrl, pointer.integrity, pointer.revision) : null;
22163
+ if (cached4) {
22164
+ memoryReceipts.set(baseUrl, cached4);
22165
+ return cached4;
22166
+ }
22167
+ try {
22168
+ const payloadUrl = new URL(pointer.payloadUrl, baseUrl).toString();
22169
+ const response = await request(payloadUrl, { cache: "force-cache" });
22170
+ if (!response.ok) {
22171
+ throw new Error(`RNX Metro fingerprint registry answered ${response.status}`);
22172
+ }
22173
+ const declaredLength = Number(response.headers.get("content-length"));
22174
+ if (Number.isFinite(declaredLength) && declaredLength > import_metro_fingerprint_registry.RNX_METRO_FINGERPRINT_MAX_PAYLOAD_BYTES) {
22175
+ throw new Error(
22176
+ `RNX Metro fingerprint registry exceeds ${import_metro_fingerprint_registry.RNX_METRO_FINGERPRINT_MAX_PAYLOAD_BYTES} bytes`
22177
+ );
22178
+ }
22179
+ const bytes = new Uint8Array(await response.arrayBuffer());
22180
+ if (bytes.byteLength !== pointer.bytes) {
22181
+ throw new Error(
22182
+ "RNX Metro fingerprint registry byte length does not match its pointer"
22183
+ );
22184
+ }
22185
+ const receipt = await parseRegistryBytes({
22186
+ bytes,
22187
+ expectedIntegrity: pointer.integrity,
22188
+ expectedRevision: pointer.revision,
22189
+ source: "network"
22190
+ });
22191
+ await writeCachedRegistry(cache, baseUrl, bytes, receipt);
22192
+ return receipt;
22193
+ } catch (error) {
22194
+ const fallback = await readLastCachedRegistry(cache, baseUrl);
22195
+ if (fallback) return fallback;
22196
+ throw error;
22197
+ }
22198
+ }
22199
+ var import_metro_fingerprint_registry, REGISTRY_CACHE_NAME, DEFAULT_REGISTRY_ORIGIN, memoryReceipts;
22200
+ var init_metro_fingerprint_registry_client = __esm({
22201
+ "../sootsim-engine/src/metro-fingerprint-registry-client.ts"() {
22202
+ "use strict";
22203
+ import_metro_fingerprint_registry = require("rnxsim/metro-fingerprint-registry");
22204
+ REGISTRY_CACHE_NAME = "rnx-metro-fingerprints-v1";
22205
+ DEFAULT_REGISTRY_ORIGIN = "https://contrast.dev";
22206
+ memoryReceipts = /* @__PURE__ */ new Map();
22207
+ }
22208
+ });
22209
+
22039
22210
  // ../compat/src/stub-manifest.ts
22040
22211
  var COMPAT_REACT_NATIVE_DEEP_STUBS;
22041
22212
  var init_stub_manifest = __esm({
@@ -22376,7 +22547,7 @@ function metroFingerprintDiscriminators(input) {
22376
22547
  return { key: `${kind}:${fnv1a64(encoded)}`, cost: encoded.length };
22377
22548
  });
22378
22549
  }
22379
- async function sha256Hex(value) {
22550
+ async function sha256Hex2(value) {
22380
22551
  const bytes = new TextEncoder().encode(value);
22381
22552
  const digest = new Uint8Array(await crypto.subtle.digest("SHA-256", bytes));
22382
22553
  return [...digest].map((byte) => byte.toString(16).padStart(2, "0")).join("");
@@ -22428,7 +22599,7 @@ async function fingerprintBlindMetroBundle(source) {
22428
22599
  exports: exports2,
22429
22600
  literals,
22430
22601
  dependencyArity,
22431
- factoryDigest: await sha256Hex(canonicalFactoryForDigest(factory, literalTokens))
22602
+ factoryDigest: await sha256Hex2(canonicalFactoryForDigest(factory, literalTokens))
22432
22603
  };
22433
22604
  })
22434
22605
  );
@@ -22803,180 +22974,6 @@ var init_metro_fingerprint = __esm({
22803
22974
  }
22804
22975
  });
22805
22976
 
22806
- // ../sootsim-engine/src/metro-fingerprint-registry-client.ts
22807
- function pointerUrl(options) {
22808
- return options.pointerUrl ?? new URL(import_metro_fingerprint_registry.RNX_METRO_FINGERPRINT_POINTER_PATH, DEFAULT_REGISTRY_ORIGIN).toString();
22809
- }
22810
- async function sha256Hex2(bytes) {
22811
- const input = new Uint8Array(bytes.byteLength);
22812
- input.set(bytes);
22813
- const digest = new Uint8Array(await crypto.subtle.digest("SHA-256", input.buffer));
22814
- return [...digest].map((byte) => byte.toString(16).padStart(2, "0")).join("");
22815
- }
22816
- async function openRegistryCache() {
22817
- if (typeof globalThis.caches?.open !== "function") return null;
22818
- try {
22819
- return await globalThis.caches.open(REGISTRY_CACHE_NAME);
22820
- } catch {
22821
- return null;
22822
- }
22823
- }
22824
- function cacheKey(baseUrl, suffix) {
22825
- const url = new URL(baseUrl);
22826
- url.pathname = `${url.pathname.replace(/\/[^/]*$/, "")}/.rnx-fingerprint-cache/${suffix}`;
22827
- url.search = "";
22828
- url.hash = "";
22829
- return new Request(url.toString());
22830
- }
22831
- async function parseRegistryBytes(args) {
22832
- if (args.bytes.byteLength > import_metro_fingerprint_registry.RNX_METRO_FINGERPRINT_MAX_PAYLOAD_BYTES) {
22833
- throw new Error(
22834
- `RNX Metro fingerprint registry exceeds ${import_metro_fingerprint_registry.RNX_METRO_FINGERPRINT_MAX_PAYLOAD_BYTES} bytes`
22835
- );
22836
- }
22837
- const integrity = await sha256Hex2(args.bytes);
22838
- if (integrity !== args.expectedIntegrity) {
22839
- throw new Error("RNX Metro fingerprint registry integrity mismatch");
22840
- }
22841
- let parsed;
22842
- try {
22843
- parsed = JSON.parse(new TextDecoder().decode(args.bytes));
22844
- } catch {
22845
- throw new Error("RNX Metro fingerprint registry is not valid JSON");
22846
- }
22847
- const registry = (0, import_metro_fingerprint_registry.parseRNXMetroFingerprintRegistry)(parsed);
22848
- if (!registry) throw new Error("RNX Metro fingerprint registry is malformed");
22849
- if (args.expectedRevision && registry.revision !== args.expectedRevision) {
22850
- throw new Error("RNX Metro fingerprint registry revision does not match its pointer");
22851
- }
22852
- return { registry, integrity, source: args.source };
22853
- }
22854
- async function readCachedRegistry(cache, baseUrl, integrity, expectedRevision) {
22855
- const response = await cache.match(cacheKey(baseUrl, integrity));
22856
- if (!response?.ok) return null;
22857
- try {
22858
- return await parseRegistryBytes({
22859
- bytes: new Uint8Array(await response.arrayBuffer()),
22860
- expectedIntegrity: integrity,
22861
- expectedRevision,
22862
- source: "cache"
22863
- });
22864
- } catch {
22865
- return null;
22866
- }
22867
- }
22868
- async function readLastCachedRegistry(cache, baseUrl) {
22869
- const memoryReceipt = memoryReceipts.get(baseUrl);
22870
- if (!cache) return memoryReceipt ? { ...memoryReceipt, source: "cache" } : null;
22871
- const latest = await cache.match(cacheKey(baseUrl, "latest"));
22872
- if (!latest?.ok) return memoryReceipt ? { ...memoryReceipt, source: "cache" } : null;
22873
- const integrity = latest.headers.get("x-rnx-registry-integrity");
22874
- if (!integrity || !/^[a-f0-9]{64}$/.test(integrity)) {
22875
- return memoryReceipt ? { ...memoryReceipt, source: "cache" } : null;
22876
- }
22877
- return await readCachedRegistry(cache, baseUrl, integrity) ?? (memoryReceipt ? { ...memoryReceipt, source: "cache" } : null);
22878
- }
22879
- async function writeCachedRegistry(cache, baseUrl, bytes, receipt) {
22880
- memoryReceipts.set(baseUrl, receipt);
22881
- if (!cache) return;
22882
- const headers = {
22883
- "content-type": "application/json",
22884
- "x-rnx-registry-integrity": receipt.integrity
22885
- };
22886
- try {
22887
- await cache.put(
22888
- cacheKey(baseUrl, receipt.integrity),
22889
- new Response(bytes.slice(), { headers })
22890
- );
22891
- await cache.put(cacheKey(baseUrl, "latest"), new Response("", { headers }));
22892
- } catch {
22893
- }
22894
- }
22895
- async function readPointer(response) {
22896
- const bytes = new Uint8Array(await response.arrayBuffer());
22897
- if (bytes.byteLength > import_metro_fingerprint_registry.RNX_METRO_FINGERPRINT_MAX_POINTER_BYTES) {
22898
- throw new Error(
22899
- `RNX Metro fingerprint pointer exceeds ${import_metro_fingerprint_registry.RNX_METRO_FINGERPRINT_MAX_POINTER_BYTES} bytes`
22900
- );
22901
- }
22902
- let parsed;
22903
- try {
22904
- parsed = JSON.parse(new TextDecoder().decode(bytes));
22905
- } catch {
22906
- throw new Error("RNX Metro fingerprint pointer is not valid JSON");
22907
- }
22908
- const pointer = (0, import_metro_fingerprint_registry.parseRNXMetroFingerprintPointer)(parsed);
22909
- if (!pointer) throw new Error("RNX Metro fingerprint pointer is malformed");
22910
- return pointer;
22911
- }
22912
- async function loadMetroFingerprintRegistry(options = {}) {
22913
- const baseUrl = pointerUrl(options);
22914
- const request = options.fetch ?? globalThis.fetch;
22915
- const cache = await openRegistryCache();
22916
- let pointer;
22917
- try {
22918
- const response = await request(baseUrl, { cache: "no-store" });
22919
- if (!response.ok) {
22920
- throw new Error(`RNX Metro fingerprint pointer answered ${response.status}`);
22921
- }
22922
- pointer = await readPointer(response);
22923
- } catch (error) {
22924
- const fallback = await readLastCachedRegistry(cache, baseUrl);
22925
- if (fallback) return fallback;
22926
- throw error;
22927
- }
22928
- const memoryReceipt = memoryReceipts.get(baseUrl);
22929
- if (memoryReceipt?.integrity === pointer.integrity && memoryReceipt.registry.revision === pointer.revision) {
22930
- return { ...memoryReceipt, source: "cache" };
22931
- }
22932
- const cached4 = cache ? await readCachedRegistry(cache, baseUrl, pointer.integrity, pointer.revision) : null;
22933
- if (cached4) {
22934
- memoryReceipts.set(baseUrl, cached4);
22935
- return cached4;
22936
- }
22937
- try {
22938
- const payloadUrl = new URL(pointer.payloadUrl, baseUrl).toString();
22939
- const response = await request(payloadUrl, { cache: "force-cache" });
22940
- if (!response.ok) {
22941
- throw new Error(`RNX Metro fingerprint registry answered ${response.status}`);
22942
- }
22943
- const declaredLength = Number(response.headers.get("content-length"));
22944
- if (Number.isFinite(declaredLength) && declaredLength > import_metro_fingerprint_registry.RNX_METRO_FINGERPRINT_MAX_PAYLOAD_BYTES) {
22945
- throw new Error(
22946
- `RNX Metro fingerprint registry exceeds ${import_metro_fingerprint_registry.RNX_METRO_FINGERPRINT_MAX_PAYLOAD_BYTES} bytes`
22947
- );
22948
- }
22949
- const bytes = new Uint8Array(await response.arrayBuffer());
22950
- if (bytes.byteLength !== pointer.bytes) {
22951
- throw new Error(
22952
- "RNX Metro fingerprint registry byte length does not match its pointer"
22953
- );
22954
- }
22955
- const receipt = await parseRegistryBytes({
22956
- bytes,
22957
- expectedIntegrity: pointer.integrity,
22958
- expectedRevision: pointer.revision,
22959
- source: "network"
22960
- });
22961
- await writeCachedRegistry(cache, baseUrl, bytes, receipt);
22962
- return receipt;
22963
- } catch (error) {
22964
- const fallback = await readLastCachedRegistry(cache, baseUrl);
22965
- if (fallback) return fallback;
22966
- throw error;
22967
- }
22968
- }
22969
- var import_metro_fingerprint_registry, REGISTRY_CACHE_NAME, DEFAULT_REGISTRY_ORIGIN, memoryReceipts;
22970
- var init_metro_fingerprint_registry_client = __esm({
22971
- "../sootsim-engine/src/metro-fingerprint-registry-client.ts"() {
22972
- "use strict";
22973
- import_metro_fingerprint_registry = require("rnxsim/metro-fingerprint-registry");
22974
- REGISTRY_CACHE_NAME = "rnx-metro-fingerprints-v1";
22975
- DEFAULT_REGISTRY_ORIGIN = "https://contrast.dev";
22976
- memoryReceipts = /* @__PURE__ */ new Map();
22977
- }
22978
- });
22979
-
22980
22977
  // src/cloud-contract.ts
22981
22978
  function isRnxCloudCommandType(value) {
22982
22979
  return RNX_CLOUD_COMMAND_TYPE_SET.has(value);
@@ -23724,8 +23721,8 @@ var init_cloud_client = __esm({
23724
23721
  import_node_path15 = require("node:path");
23725
23722
  init_metroAssetArtifact();
23726
23723
  init_metroCloudArtifact();
23727
- init_metro_fingerprint();
23728
23724
  init_metro_fingerprint_registry_client();
23725
+ init_metro_fingerprint();
23729
23726
  init_backend_origin();
23730
23727
  init_cloud_contract();
23731
23728
  init_metro_production_bundle();
package/dist-lib/vite.cjs CHANGED
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.444 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.446 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __create = Object.create;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rnxsim",
3
- "version": "0.1.444",
3
+ "version": "0.1.446",
4
4
  "description": "Vite and Metro plugins, testing drivers, and SDK exports for rnx.",
5
5
  "author": "Tamagui LLC",
6
6
  "license": "SEE LICENSE IN LICENSE",
@@ -7,7 +7,7 @@ import {
7
7
  writeFileSync,
8
8
  } from 'node:fs'
9
9
  import { dirname, join, resolve } from 'node:path'
10
- import { electronUserDataDir } from '../home-paths'
10
+ import { electronUserDataDir } from '../home-paths.ts'
11
11
 
12
12
  export type SharedDesktopAuthTeamSummary = {
13
13
  id: string
@@ -1,4 +1,4 @@
1
- import type { BridgeCommandType } from './bridge-contract'
1
+ import type { BridgeCommandType } from './bridge-contract.ts'
2
2
 
3
3
  export const RNX_CLOUD_MAX_ARTIFACT_BYTES = 20 * 1024 * 1024
4
4
  export const RNX_CLOUD_DESIGN_MAX_STORAGE_ENTRIES = 256