rnxsim 0.1.401 → 0.1.403

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 (56) hide show
  1. package/README.md +16 -7
  2. package/cli/commands/box.ts +10 -3
  3. package/cli/outbound-endpoints.ts +2 -2
  4. package/dist-lib/agent-daemon-client.cjs +1 -1
  5. package/dist-lib/agent-events.cjs +1 -1
  6. package/dist-lib/agent-identity.cjs +1 -1
  7. package/dist-lib/agent-sessions.cjs +1 -1
  8. package/dist-lib/attached-projects.cjs +1 -1
  9. package/dist-lib/auth/shared-session.cjs +1 -1
  10. package/dist-lib/backend-origin.cjs +1 -1
  11. package/dist-lib/beta.cjs +1 -1
  12. package/dist-lib/beta.mjs +1 -1
  13. package/dist-lib/bridge-constants.cjs +1 -1
  14. package/dist-lib/bridge-contract-input.cjs +1 -1
  15. package/dist-lib/bridge-contract-input.mjs +1 -1
  16. package/dist-lib/bridge-contract.cjs +1 -1
  17. package/dist-lib/bridge-contract.mjs +1 -1
  18. package/dist-lib/capture-contract.cjs +5 -2
  19. package/dist-lib/capture-contract.mjs +5 -2
  20. package/dist-lib/cli-constants.cjs +1 -1
  21. package/dist-lib/cloud-contract.cjs +3 -2
  22. package/dist-lib/cloud-contract.mjs +3 -2
  23. package/dist-lib/config.cjs +1 -1
  24. package/dist-lib/detox/index.cjs +1 -1
  25. package/dist-lib/dev-bundle-resolution.cjs +1 -1
  26. package/dist-lib/home-paths.cjs +1 -1
  27. package/dist-lib/host/bridge-host.cjs +1 -1
  28. package/dist-lib/host/fetch-proxy-handler.cjs +1 -1
  29. package/dist-lib/host/fetch-proxy-overrides.cjs +1 -1
  30. package/dist-lib/host/fetch-proxy-overrides.mjs +1 -1
  31. package/dist-lib/host/replacement-module-handler.cjs +1 -1
  32. package/dist-lib/host/websocket-proxy.cjs +1 -1
  33. package/dist-lib/index.cjs +37 -12
  34. package/dist-lib/jump-to-source-babel.cjs +1 -1
  35. package/dist-lib/menu.cjs +1 -1
  36. package/dist-lib/menu.mjs +1 -1
  37. package/dist-lib/metro-production-bundle.cjs +72 -7
  38. package/dist-lib/metro-production-bundle.mjs +69 -7
  39. package/dist-lib/metro.cjs +41 -10
  40. package/dist-lib/profiles.cjs +1 -1
  41. package/dist-lib/public-brand.cjs +1 -1
  42. package/dist-lib/react-native-host-modules.cjs +1 -1
  43. package/dist-lib/react-native-host-modules.mjs +1 -1
  44. package/dist-lib/render-mode.cjs +1 -1
  45. package/dist-lib/scripts/dev-server-scanner.cjs +1 -1
  46. package/dist-lib/sdk.cjs +1 -1
  47. package/dist-lib/sdk.mjs +1 -1
  48. package/dist-lib/skills.cjs +3 -2
  49. package/dist-lib/vite.cjs +6 -1
  50. package/package.json +1 -1
  51. package/src/bridge-contract.ts +20 -0
  52. package/src/capture-contract.ts +8 -0
  53. package/src/cloud-contract.ts +1 -0
  54. package/src/metro-plugin.ts +29 -23
  55. package/src/metro-production-bundle.ts +124 -8
  56. package/src/runtime-assets.ts +5 -0
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.401 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.403 | (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 __defProp = Object.defineProperty;
@@ -22,9 +22,12 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
22
22
  // src/metro-production-bundle.ts
23
23
  var metro_production_bundle_exports = {};
24
24
  __export(metro_production_bundle_exports, {
25
+ appendRNXMetroModulePathsFooter: () => appendRNXMetroModulePathsFooter,
25
26
  createRNXMetroModulePathsFooter: () => createRNXMetroModulePathsFooter,
27
+ detachRNXMetroSourceMapUrl: () => detachRNXMetroSourceMapUrl,
26
28
  readRNXMetroBundleLayout: () => readRNXMetroBundleLayout,
27
29
  readRNXMetroModuleIdentity: () => readRNXMetroModuleIdentity,
30
+ toRNXDevelopmentBundleUrl: () => toRNXDevelopmentBundleUrl,
28
31
  toRNXProductionBundleUrl: () => toRNXProductionBundleUrl,
29
32
  validateRNXMetroModulePaths: () => validateRNXMetroModulePaths
30
33
  });
@@ -38,18 +41,44 @@ function toRNXProductionBundleUrl(bundleUrl) {
38
41
  url.searchParams.set("minify", "true");
39
42
  return relative ? `${url.pathname}${url.search}${url.hash}` : url.toString();
40
43
  }
44
+ function toRNXDevelopmentBundleUrl(bundleUrl) {
45
+ const relative = bundleUrl.startsWith("/");
46
+ const url = new URL(bundleUrl, "http://rnxsim.local");
47
+ url.searchParams.set("dev", "true");
48
+ url.searchParams.set("hot", "false");
49
+ url.searchParams.set("minify", "false");
50
+ return relative ? `${url.pathname}${url.search}${url.hash}` : url.toString();
51
+ }
52
+ var RNXSIM_METRO_SOURCE_MAP_COMMENT = "//# sourceMappingURL=";
53
+ function detachRNXMetroSourceMapUrl(bundleText) {
54
+ const trimmedEnd = bundleText.replace(/\s+$/, "");
55
+ const commentStart = trimmedEnd.lastIndexOf(`
56
+ ${RNXSIM_METRO_SOURCE_MAP_COMMENT}`);
57
+ if (commentStart < 0) return { source: bundleText, sourceMappingUrl: null };
58
+ const url = trimmedEnd.slice(commentStart + 1 + RNXSIM_METRO_SOURCE_MAP_COMMENT.length);
59
+ if (url.includes("\n")) return { source: bundleText, sourceMappingUrl: null };
60
+ return { source: trimmedEnd.slice(0, commentStart), sourceMappingUrl: url };
61
+ }
41
62
  function createRNXMetroModulePathsFooter(modulePaths) {
42
63
  const payload = JSON.stringify(modulePaths).replace(/\u2028/g, "\\u2028").replace(/\u2029/g, "\\u2029").replace(/<\//g, "<\\/");
43
64
  return `
44
65
  ${RNXSIM_METRO_MODULE_PATHS_PREFIX}${payload};`;
45
66
  }
67
+ function appendRNXMetroModulePathsFooter(bundleText, modulePaths) {
68
+ const footer = createRNXMetroModulePathsFooter(modulePaths);
69
+ const detached = detachRNXMetroSourceMapUrl(bundleText);
70
+ return detached.sourceMappingUrl === null ? bundleText + footer : `${detached.source}${footer}
71
+ ${RNXSIM_METRO_SOURCE_MAP_COMMENT}${detached.sourceMappingUrl}`;
72
+ }
46
73
  function readRNXMetroModuleIdentity(bundleText) {
74
+ const detached = detachRNXMetroSourceMapUrl(bundleText);
75
+ const withoutMap = detached.source;
47
76
  const footerPrefix = `
48
77
  ${RNXSIM_METRO_MODULE_PATHS_PREFIX}`;
49
- const footerStart = bundleText.lastIndexOf(footerPrefix);
50
- if (footerStart < 0 || !bundleText.endsWith(";")) return null;
78
+ const footerStart = withoutMap.lastIndexOf(footerPrefix);
79
+ if (footerStart < 0 || !withoutMap.endsWith(";")) return null;
51
80
  const parsed = JSON.parse(
52
- bundleText.slice(footerStart + footerPrefix.length, -1)
81
+ withoutMap.slice(footerStart + footerPrefix.length, -1)
53
82
  );
54
83
  if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
55
84
  return null;
@@ -59,7 +88,24 @@ ${RNXSIM_METRO_MODULE_PATHS_PREFIX}`;
59
88
  if (typeof modulePath !== "string") return null;
60
89
  modulePaths[moduleId] = modulePath;
61
90
  }
62
- return { source: bundleText.slice(0, footerStart), modulePaths };
91
+ return {
92
+ source: withoutMap.slice(0, footerStart),
93
+ modulePaths,
94
+ sourceMappingUrl: detached.sourceMappingUrl
95
+ };
96
+ }
97
+ function readStringLiteralStart(source, start, end) {
98
+ const quote = source[end];
99
+ if (quote !== '"' && quote !== "'") return -1;
100
+ for (let index = end - 1; index > start; index--) {
101
+ if (source[index] !== quote) continue;
102
+ let backslashes = 0;
103
+ while (index - 1 - backslashes > start && source[index - 1 - backslashes] === "\\") {
104
+ backslashes++;
105
+ }
106
+ if (backslashes % 2 === 0) return index;
107
+ }
108
+ return -1;
63
109
  }
64
110
  function readDefineTail(source, start, end) {
65
111
  let cursor = end;
@@ -69,6 +115,19 @@ function readDefineTail(source, start, end) {
69
115
  if (source[cursor] !== ")") return null;
70
116
  cursor--;
71
117
  while (cursor > start && /\s/.test(source[cursor])) cursor--;
118
+ let verboseNameStart;
119
+ let verboseNameEnd;
120
+ if (source[cursor] === '"' || source[cursor] === "'") {
121
+ const literalStart = readStringLiteralStart(source, start, cursor);
122
+ if (literalStart < 0) return null;
123
+ verboseNameStart = literalStart;
124
+ verboseNameEnd = cursor + 1;
125
+ cursor = literalStart - 1;
126
+ while (cursor > start && /\s/.test(source[cursor])) cursor--;
127
+ if (source[cursor] !== ",") return null;
128
+ cursor--;
129
+ while (cursor > start && /\s/.test(source[cursor])) cursor--;
130
+ }
72
131
  if (source[cursor] !== "]") return null;
73
132
  const dependenciesEnd = cursor + 1;
74
133
  let depth = 1;
@@ -100,7 +159,9 @@ function readDefineTail(source, start, end) {
100
159
  moduleId,
101
160
  factoryEnd,
102
161
  dependenciesStart,
103
- dependenciesEnd
162
+ dependenciesEnd,
163
+ verboseNameStart,
164
+ verboseNameEnd
104
165
  };
105
166
  }
106
167
  function readRNXMetroBundleLayout(source) {
@@ -140,7 +201,8 @@ function readRNXMetroBundleLayout(source) {
140
201
  lineIndex,
141
202
  endLineIndex,
142
203
  factory: { start: start + "__d(".length, end: tail.factoryEnd },
143
- dependencies: { start: tail.dependenciesStart, end: tail.dependenciesEnd }
204
+ dependencies: { start: tail.dependenciesStart, end: tail.dependenciesEnd },
205
+ ...tail.verboseNameStart !== void 0 && tail.verboseNameEnd !== void 0 ? { verboseName: { start: tail.verboseNameStart, end: tail.verboseNameEnd } } : {}
144
206
  });
145
207
  }
146
208
  return {
@@ -188,9 +250,12 @@ function validateRNXMetroModulePaths(source, modulePaths) {
188
250
  }
189
251
  // Annotate the CommonJS export names for ESM import in node:
190
252
  0 && (module.exports = {
253
+ appendRNXMetroModulePathsFooter,
191
254
  createRNXMetroModulePathsFooter,
255
+ detachRNXMetroSourceMapUrl,
192
256
  readRNXMetroBundleLayout,
193
257
  readRNXMetroModuleIdentity,
258
+ toRNXDevelopmentBundleUrl,
194
259
  toRNXProductionBundleUrl,
195
260
  validateRNXMetroModulePaths
196
261
  });
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.401 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.403 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
 
3
3
  // src/metro-production-bundle.ts
4
4
  var RNXSIM_METRO_MODULE_PATHS_PREFIX = "globalThis.__sootsimModulePaths=";
@@ -10,18 +10,44 @@ function toRNXProductionBundleUrl(bundleUrl) {
10
10
  url.searchParams.set("minify", "true");
11
11
  return relative ? `${url.pathname}${url.search}${url.hash}` : url.toString();
12
12
  }
13
+ function toRNXDevelopmentBundleUrl(bundleUrl) {
14
+ const relative = bundleUrl.startsWith("/");
15
+ const url = new URL(bundleUrl, "http://rnxsim.local");
16
+ url.searchParams.set("dev", "true");
17
+ url.searchParams.set("hot", "false");
18
+ url.searchParams.set("minify", "false");
19
+ return relative ? `${url.pathname}${url.search}${url.hash}` : url.toString();
20
+ }
21
+ var RNXSIM_METRO_SOURCE_MAP_COMMENT = "//# sourceMappingURL=";
22
+ function detachRNXMetroSourceMapUrl(bundleText) {
23
+ const trimmedEnd = bundleText.replace(/\s+$/, "");
24
+ const commentStart = trimmedEnd.lastIndexOf(`
25
+ ${RNXSIM_METRO_SOURCE_MAP_COMMENT}`);
26
+ if (commentStart < 0) return { source: bundleText, sourceMappingUrl: null };
27
+ const url = trimmedEnd.slice(commentStart + 1 + RNXSIM_METRO_SOURCE_MAP_COMMENT.length);
28
+ if (url.includes("\n")) return { source: bundleText, sourceMappingUrl: null };
29
+ return { source: trimmedEnd.slice(0, commentStart), sourceMappingUrl: url };
30
+ }
13
31
  function createRNXMetroModulePathsFooter(modulePaths) {
14
32
  const payload = JSON.stringify(modulePaths).replace(/\u2028/g, "\\u2028").replace(/\u2029/g, "\\u2029").replace(/<\//g, "<\\/");
15
33
  return `
16
34
  ${RNXSIM_METRO_MODULE_PATHS_PREFIX}${payload};`;
17
35
  }
36
+ function appendRNXMetroModulePathsFooter(bundleText, modulePaths) {
37
+ const footer = createRNXMetroModulePathsFooter(modulePaths);
38
+ const detached = detachRNXMetroSourceMapUrl(bundleText);
39
+ return detached.sourceMappingUrl === null ? bundleText + footer : `${detached.source}${footer}
40
+ ${RNXSIM_METRO_SOURCE_MAP_COMMENT}${detached.sourceMappingUrl}`;
41
+ }
18
42
  function readRNXMetroModuleIdentity(bundleText) {
43
+ const detached = detachRNXMetroSourceMapUrl(bundleText);
44
+ const withoutMap = detached.source;
19
45
  const footerPrefix = `
20
46
  ${RNXSIM_METRO_MODULE_PATHS_PREFIX}`;
21
- const footerStart = bundleText.lastIndexOf(footerPrefix);
22
- if (footerStart < 0 || !bundleText.endsWith(";")) return null;
47
+ const footerStart = withoutMap.lastIndexOf(footerPrefix);
48
+ if (footerStart < 0 || !withoutMap.endsWith(";")) return null;
23
49
  const parsed = JSON.parse(
24
- bundleText.slice(footerStart + footerPrefix.length, -1)
50
+ withoutMap.slice(footerStart + footerPrefix.length, -1)
25
51
  );
26
52
  if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
27
53
  return null;
@@ -31,7 +57,24 @@ ${RNXSIM_METRO_MODULE_PATHS_PREFIX}`;
31
57
  if (typeof modulePath !== "string") return null;
32
58
  modulePaths[moduleId] = modulePath;
33
59
  }
34
- return { source: bundleText.slice(0, footerStart), modulePaths };
60
+ return {
61
+ source: withoutMap.slice(0, footerStart),
62
+ modulePaths,
63
+ sourceMappingUrl: detached.sourceMappingUrl
64
+ };
65
+ }
66
+ function readStringLiteralStart(source, start, end) {
67
+ const quote = source[end];
68
+ if (quote !== '"' && quote !== "'") return -1;
69
+ for (let index = end - 1; index > start; index--) {
70
+ if (source[index] !== quote) continue;
71
+ let backslashes = 0;
72
+ while (index - 1 - backslashes > start && source[index - 1 - backslashes] === "\\") {
73
+ backslashes++;
74
+ }
75
+ if (backslashes % 2 === 0) return index;
76
+ }
77
+ return -1;
35
78
  }
36
79
  function readDefineTail(source, start, end) {
37
80
  let cursor = end;
@@ -41,6 +84,19 @@ function readDefineTail(source, start, end) {
41
84
  if (source[cursor] !== ")") return null;
42
85
  cursor--;
43
86
  while (cursor > start && /\s/.test(source[cursor])) cursor--;
87
+ let verboseNameStart;
88
+ let verboseNameEnd;
89
+ if (source[cursor] === '"' || source[cursor] === "'") {
90
+ const literalStart = readStringLiteralStart(source, start, cursor);
91
+ if (literalStart < 0) return null;
92
+ verboseNameStart = literalStart;
93
+ verboseNameEnd = cursor + 1;
94
+ cursor = literalStart - 1;
95
+ while (cursor > start && /\s/.test(source[cursor])) cursor--;
96
+ if (source[cursor] !== ",") return null;
97
+ cursor--;
98
+ while (cursor > start && /\s/.test(source[cursor])) cursor--;
99
+ }
44
100
  if (source[cursor] !== "]") return null;
45
101
  const dependenciesEnd = cursor + 1;
46
102
  let depth = 1;
@@ -72,7 +128,9 @@ function readDefineTail(source, start, end) {
72
128
  moduleId,
73
129
  factoryEnd,
74
130
  dependenciesStart,
75
- dependenciesEnd
131
+ dependenciesEnd,
132
+ verboseNameStart,
133
+ verboseNameEnd
76
134
  };
77
135
  }
78
136
  function readRNXMetroBundleLayout(source) {
@@ -112,7 +170,8 @@ function readRNXMetroBundleLayout(source) {
112
170
  lineIndex,
113
171
  endLineIndex,
114
172
  factory: { start: start + "__d(".length, end: tail.factoryEnd },
115
- dependencies: { start: tail.dependenciesStart, end: tail.dependenciesEnd }
173
+ dependencies: { start: tail.dependenciesStart, end: tail.dependenciesEnd },
174
+ ...tail.verboseNameStart !== void 0 && tail.verboseNameEnd !== void 0 ? { verboseName: { start: tail.verboseNameStart, end: tail.verboseNameEnd } } : {}
116
175
  });
117
176
  }
118
177
  return {
@@ -159,9 +218,12 @@ function validateRNXMetroModulePaths(source, modulePaths) {
159
218
  }
160
219
  }
161
220
  export {
221
+ appendRNXMetroModulePathsFooter,
162
222
  createRNXMetroModulePathsFooter,
223
+ detachRNXMetroSourceMapUrl,
163
224
  readRNXMetroBundleLayout,
164
225
  readRNXMetroModuleIdentity,
226
+ toRNXDevelopmentBundleUrl,
165
227
  toRNXProductionBundleUrl,
166
228
  validateRNXMetroModulePaths
167
229
  };
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.401 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.403 | (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;
@@ -33,6 +33,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
33
33
  var metro_plugin_exports = {};
34
34
  __export(metro_plugin_exports, {
35
35
  default: () => metro_plugin_default,
36
+ toRNXDevelopmentBundleUrl: () => toRNXDevelopmentBundleUrl,
36
37
  toRNXProductionBundleUrl: () => toRNXProductionBundleUrl,
37
38
  withRNX: () => withRNX
38
39
  });
@@ -419,11 +420,35 @@ function toRNXProductionBundleUrl(bundleUrl) {
419
420
  url.searchParams.set("minify", "true");
420
421
  return relative ? `${url.pathname}${url.search}${url.hash}` : url.toString();
421
422
  }
423
+ function toRNXDevelopmentBundleUrl(bundleUrl) {
424
+ const relative = bundleUrl.startsWith("/");
425
+ const url = new URL(bundleUrl, "http://rnxsim.local");
426
+ url.searchParams.set("dev", "true");
427
+ url.searchParams.set("hot", "false");
428
+ url.searchParams.set("minify", "false");
429
+ return relative ? `${url.pathname}${url.search}${url.hash}` : url.toString();
430
+ }
431
+ var RNXSIM_METRO_SOURCE_MAP_COMMENT = "//# sourceMappingURL=";
432
+ function detachRNXMetroSourceMapUrl(bundleText) {
433
+ const trimmedEnd = bundleText.replace(/\s+$/, "");
434
+ const commentStart = trimmedEnd.lastIndexOf(`
435
+ ${RNXSIM_METRO_SOURCE_MAP_COMMENT}`);
436
+ if (commentStart < 0) return { source: bundleText, sourceMappingUrl: null };
437
+ const url = trimmedEnd.slice(commentStart + 1 + RNXSIM_METRO_SOURCE_MAP_COMMENT.length);
438
+ if (url.includes("\n")) return { source: bundleText, sourceMappingUrl: null };
439
+ return { source: trimmedEnd.slice(0, commentStart), sourceMappingUrl: url };
440
+ }
422
441
  function createRNXMetroModulePathsFooter(modulePaths) {
423
442
  const payload = JSON.stringify(modulePaths).replace(/\u2028/g, "\\u2028").replace(/\u2029/g, "\\u2029").replace(/<\//g, "<\\/");
424
443
  return `
425
444
  ${RNXSIM_METRO_MODULE_PATHS_PREFIX}${payload};`;
426
445
  }
446
+ function appendRNXMetroModulePathsFooter(bundleText, modulePaths) {
447
+ const footer = createRNXMetroModulePathsFooter(modulePaths);
448
+ const detached = detachRNXMetroSourceMapUrl(bundleText);
449
+ return detached.sourceMappingUrl === null ? bundleText + footer : `${detached.source}${footer}
450
+ ${RNXSIM_METRO_SOURCE_MAP_COMMENT}${detached.sourceMappingUrl}`;
451
+ }
427
452
 
428
453
  // src/runtime-assets.ts
429
454
  var import_fs = __toESM(require("fs"), 1);
@@ -591,6 +616,11 @@ function serveRuntimeFile(req, res, fullPath) {
591
616
  const stat = import_fs.default.statSync(fullPath);
592
617
  const lastModified = stat.mtime.toUTCString();
593
618
  res.setHeader("content-type", MIME_TYPES[ext] || "application/octet-stream");
619
+ if (/^canvaskit-graphite-pipelines-[0-9a-f]{8}\.bin$/.test(import_path.default.basename(fullPath))) {
620
+ res.setHeader("cache-control", "public, max-age=31536000, immutable");
621
+ import_fs.default.createReadStream(fullPath).pipe(res);
622
+ return;
623
+ }
594
624
  res.setHeader("cache-control", "no-cache");
595
625
  res.setHeader("last-modified", lastModified);
596
626
  if (req?.headers?.["if-modified-since"] === lastModified) {
@@ -636,22 +666,21 @@ function appendRNXModulePaths(result, graph, options, projectRoot) {
636
666
  const dependencies = graph.dependencies;
637
667
  const createModuleId = options.createModuleId;
638
668
  if (!dependencies || !createModuleId) {
639
- throw new Error(
640
- "rnxsim: Metro did not provide the production module graph and createModuleId"
641
- );
669
+ throw new Error("rnxsim: Metro did not provide the module graph and createModuleId");
642
670
  }
643
671
  const modulePaths = {};
644
672
  for (const module2 of dependencies.values()) {
645
673
  modulePaths[String(createModuleId(module2.path))] = import_path2.default.relative(projectRoot, module2.path).replaceAll(import_path2.default.sep, "/");
646
674
  }
647
675
  if (Object.keys(modulePaths).length !== dependencies.size) {
648
- throw new Error("rnxsim: production module IDs were not unique");
676
+ throw new Error("rnxsim: bundle module IDs were not unique");
649
677
  }
650
- const footer = createRNXMetroModulePathsFooter(modulePaths);
651
- return typeof result === "string" ? result + footer : { ...result, code: result.code + footer };
678
+ return typeof result === "string" ? appendRNXMetroModulePathsFooter(result, modulePaths) : { ...result, code: appendRNXMetroModulePathsFooter(result.code, modulePaths) };
652
679
  }
653
680
  function withRNX(config, options = {}) {
654
- if (!options.devServer && !options.open && !options.productionBundles) return config;
681
+ if (!options.devServer && !options.open && !options.productionBundles && !options.developmentBundles) {
682
+ return config;
683
+ }
655
684
  const cfgProjectRoot = config.projectRoot || process.cwd();
656
685
  const appName = resolveRnxDesktopAppName(options.open, cfgProjectRoot);
657
686
  const configuredBundleUrl = options.bundleUrl || "/index.bundle?platform=ios&dev=true&hot=true&minify=false";
@@ -669,7 +698,7 @@ function withRNX(config, options = {}) {
669
698
  const existingEnhance = cfgServer?.enhanceMiddleware;
670
699
  const existingSerializer = cfgSerializer?.customSerializer;
671
700
  let productionConfig = {};
672
- if (options.productionBundles) {
701
+ if (options.productionBundles || options.developmentBundles) {
673
702
  let defaultSerializer;
674
703
  productionConfig = {
675
704
  serializer: {
@@ -682,7 +711,8 @@ function withRNX(config, options = {}) {
682
711
  graph,
683
712
  serializerOptions
684
713
  );
685
- return graph.transformOptions?.dev === false ? appendRNXModulePaths(result, graph, serializerOptions, cfgProjectRoot) : result;
714
+ const dev = serializerOptions.dev;
715
+ return dev === false && options.productionBundles === true || dev === true && options.developmentBundles === true ? appendRNXModulePaths(result, graph, serializerOptions, cfgProjectRoot) : result;
686
716
  }
687
717
  }
688
718
  };
@@ -809,6 +839,7 @@ function resolveMetroPort(server) {
809
839
  var metro_plugin_default = withRNX;
810
840
  // Annotate the CommonJS export names for ESM import in node:
811
841
  0 && (module.exports = {
842
+ toRNXDevelopmentBundleUrl,
812
843
  toRNXProductionBundleUrl,
813
844
  withRNX
814
845
  });
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.401 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.403 | (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;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.401 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.403 | (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 __defProp = Object.defineProperty;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.401 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.403 | (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 __defProp = Object.defineProperty;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.401 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.403 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
 
3
3
  // src/react-native-host-modules.ts
4
4
  var REACT_NATIVE_PASSTHROUGH_SPECIFIERS = [
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.401 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.403 | (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 __defProp = Object.defineProperty;
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.401 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.403 | (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/dist-lib/sdk.cjs CHANGED
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.401 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.403 | (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 __defProp = Object.defineProperty;
package/dist-lib/sdk.mjs CHANGED
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.401 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.403 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  var __defProp = Object.defineProperty;
3
3
  var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
4
4
  var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.401 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.403 | (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;
@@ -21421,7 +21421,8 @@ var init_cloud_contract = __esm({
21421
21421
  "tree",
21422
21422
  "tap",
21423
21423
  "longPress",
21424
- "memory"
21424
+ "memory",
21425
+ "diagnostics"
21425
21426
  ]);
21426
21427
  RNX_CLOUD_COMMAND_TYPE_SET = new Set(RNX_CLOUD_COMMAND_TYPES);
21427
21428
  }
package/dist-lib/vite.cjs CHANGED
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.401 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.403 | (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;
@@ -526,6 +526,11 @@ function serveRuntimeFile(req, res, fullPath) {
526
526
  const stat = import_fs.default.statSync(fullPath);
527
527
  const lastModified = stat.mtime.toUTCString();
528
528
  res.setHeader("content-type", MIME_TYPES[ext] || "application/octet-stream");
529
+ if (/^canvaskit-graphite-pipelines-[0-9a-f]{8}\.bin$/.test(import_path.default.basename(fullPath))) {
530
+ res.setHeader("cache-control", "public, max-age=31536000, immutable");
531
+ import_fs.default.createReadStream(fullPath).pipe(res);
532
+ return;
533
+ }
529
534
  res.setHeader("cache-control", "no-cache");
530
535
  res.setHeader("last-modified", lastModified);
531
536
  if (req?.headers?.["if-modified-since"] === lastModified) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rnxsim",
3
- "version": "0.1.401",
3
+ "version": "0.1.403",
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",
@@ -37,6 +37,7 @@ export type BridgeCommandType =
37
37
  | 'resolve'
38
38
  | 'reset'
39
39
  | 'camera'
40
+ | 'diagnostics'
40
41
 
41
42
  export interface WsCommand {
42
43
  id: string | number
@@ -86,6 +87,9 @@ export interface WsCommand {
86
87
  resetOptions?: ResetOptions
87
88
  // camera — fixture injection into the host camera pipeline
88
89
  camera?: CameraCommand
90
+ // diagnostics — read-only engine debug state: channel recording, the sheet /
91
+ // portal / boundary finders, and the recent event ring.
92
+ diagnostics?: DiagnosticsOptions
89
93
  }
90
94
 
91
95
  // ---------------------------------------------------------------------------
@@ -258,6 +262,22 @@ export interface SemanticWaitResult {
258
262
  // state — one round-trip situational awareness
259
263
  // ---------------------------------------------------------------------------
260
264
 
265
+ export interface DiagnosticsOptions {
266
+ // debug channels to record from this point on. omitted leaves recording as
267
+ // it is; an empty list stops recording.
268
+ channels?: readonly string[]
269
+ find?: 'sheets' | 'portals' | 'boundaries'
270
+ recentChannel?: string
271
+ recentLimit?: number
272
+ }
273
+
274
+ export interface DiagnosticsResult {
275
+ channels: string[]
276
+ runtime: unknown
277
+ found: unknown[] | null
278
+ events: unknown[]
279
+ }
280
+
261
281
  export interface SimStateOptions {
262
282
  // omit a section an agent does not need this turn
263
283
  screenshot?: boolean
@@ -162,6 +162,7 @@ export interface RnxRasterRegionTree {
162
162
  nodeId: number
163
163
  parentNodeId: number | null
164
164
  type: string
165
+ text?: string | null
165
166
  style: Record<string, unknown>
166
167
  layout: RnxCaptureRect
167
168
  frame: RnxCaptureRect | null
@@ -178,6 +179,12 @@ export function selectRnxRasterNodeIds(tree: RnxRasterRegionTree): Set<number> {
178
179
  if (!visibleFrame || visibleFrame.width <= 0 || visibleFrame.height <= 0) continue
179
180
  if (
180
181
  node.type === 'masked-view' ||
182
+ (node.type === 'text' &&
183
+ typeof node.text === 'string' &&
184
+ (/\p{Emoji_Presentation}/u.test(node.text) ||
185
+ /\uFE0F|\u200D|\u20E3|\p{Emoji_Modifier}|\p{Regional_Indicator}/u.test(
186
+ node.text,
187
+ ))) ||
181
188
  node.style._liquidGlass !== undefined ||
182
189
  node.style._liquidGlassEdge !== undefined
183
190
  ) {
@@ -293,6 +300,7 @@ export function rnxCaptureRasterRegions(
293
300
  nodeId: node.nodeId,
294
301
  parentNodeId: node.parentNodeId,
295
302
  type: node.type,
303
+ text: node.text,
296
304
  style: node.style.resolved,
297
305
  layout: node.layout.local,
298
306
  frame: node.layout.frame,
@@ -22,6 +22,7 @@ export const RNX_CLOUD_COMMAND_TYPES = Object.freeze([
22
22
  'tap',
23
23
  'longPress',
24
24
  'memory',
25
+ 'diagnostics',
25
26
  ]) satisfies readonly BridgeCommandType[]
26
27
 
27
28
  const RNX_CLOUD_COMMAND_TYPE_SET = new Set<string>(RNX_CLOUD_COMMAND_TYPES)