rnxsim 0.1.521 → 0.1.523

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/cli/commands/control.ts +31 -15
  2. package/dist-lib/agent-daemon-client.cjs +1 -1
  3. package/dist-lib/agent-events.cjs +1 -1
  4. package/dist-lib/agent-identity.cjs +1 -1
  5. package/dist-lib/agent-sessions.cjs +1 -1
  6. package/dist-lib/attached-projects.cjs +1 -1
  7. package/dist-lib/auth/shared-session.cjs +1 -1
  8. package/dist-lib/backend-origin.cjs +1 -1
  9. package/dist-lib/beta.cjs +1 -1
  10. package/dist-lib/beta.mjs +1 -1
  11. package/dist-lib/bridge-constants.cjs +1 -1
  12. package/dist-lib/bridge-contract-input.cjs +1 -1
  13. package/dist-lib/bridge-contract-input.mjs +1 -1
  14. package/dist-lib/bridge-contract.cjs +1 -1
  15. package/dist-lib/bridge-contract.mjs +1 -1
  16. package/dist-lib/capture-contract.cjs +1 -1
  17. package/dist-lib/capture-contract.mjs +1 -1
  18. package/dist-lib/cli-constants.cjs +1 -1
  19. package/dist-lib/cloud-contract.cjs +1 -1
  20. package/dist-lib/cloud-contract.mjs +1 -1
  21. package/dist-lib/cloud.cjs +1 -1
  22. package/dist-lib/cloud.mjs +1 -1
  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 +7 -3
  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 +1 -1
  34. package/dist-lib/jump-to-source-babel.cjs +1 -1
  35. package/dist-lib/jump-to-source-native.cjs +1 -1
  36. package/dist-lib/menu.cjs +1 -1
  37. package/dist-lib/menu.mjs +1 -1
  38. package/dist-lib/metro-fingerprint-registry.cjs +1 -1
  39. package/dist-lib/metro-fingerprint-registry.mjs +1 -1
  40. package/dist-lib/metro-production-bundle.cjs +1 -1
  41. package/dist-lib/metro-production-bundle.mjs +1 -1
  42. package/dist-lib/metro.cjs +1 -1
  43. package/dist-lib/profiles.cjs +1 -1
  44. package/dist-lib/public-brand.cjs +1 -1
  45. package/dist-lib/react-native-host-modules.cjs +1 -1
  46. package/dist-lib/react-native-host-modules.mjs +1 -1
  47. package/dist-lib/render-mode.cjs +1 -1
  48. package/dist-lib/scripts/dev-server-scanner.cjs +1 -1
  49. package/dist-lib/sdk.cjs +1 -1
  50. package/dist-lib/sdk.mjs +1 -1
  51. package/dist-lib/skills.cjs +32 -14
  52. package/dist-lib/swift.cjs +155 -72
  53. package/dist-lib/vite.cjs +38 -42
  54. package/package.json +1 -1
  55. package/src/swift.ts +2 -3
  56. package/src/vite-plugin-swift.ts +81 -59
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.521 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.523 | (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;
@@ -32,8 +32,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
32
32
  // src/swift.ts
33
33
  var swift_exports = {};
34
34
  __export(swift_exports, {
35
- createSwiftModule: () => createSwiftModule,
36
- createSwiftView: () => createSwiftView
35
+ createSwiftEntry: () => createSwiftEntry
37
36
  });
38
37
  module.exports = __toCommonJS(swift_exports);
39
38
 
@@ -190,20 +189,6 @@ function pointerExport(exports2, name) {
190
189
  return result;
191
190
  };
192
191
  }
193
- function maybePointerExport(exports2, name) {
194
- const value = exports2[name];
195
- if (value === void 0) return void 0;
196
- if (typeof value !== "function") {
197
- throw new Error(`swift export ${name} is not a function`);
198
- }
199
- return (...args) => {
200
- const result = Reflect.apply(value, void 0, args);
201
- if (typeof result !== "number") {
202
- throw new Error(`swift export ${name} returned ${typeof result}`);
203
- }
204
- return result;
205
- };
206
- }
207
192
  function voidExport(exports2, name) {
208
193
  const fn = rawExport(exports2, name);
209
194
  return (...args) => {
@@ -236,13 +221,35 @@ function instantiate(module2) {
236
221
  const initialize = voidExport(instance.exports, "_initialize");
237
222
  const mainArgv = voidExport(instance.exports, "__main_argc_argv");
238
223
  const mount = pointerExport(instance.exports, "rnx_mount");
239
- const mountViewExport = maybePointerExport(instance.exports, "rnx_mount_view");
240
- const hasViewExport = maybePointerExport(instance.exports, "rnx_has_view");
224
+ const mountViewExport = pointerExport(instance.exports, "rnx_mount_view");
225
+ const hasViewExport = pointerExport(instance.exports, "rnx_has_view");
241
226
  const event = pointerExport(instance.exports, "rnx_event");
242
227
  const stateExport = pointerExport(instance.exports, "rnx_state_export");
243
228
  const stateImport = voidExport(instance.exports, "rnx_state_import");
244
229
  const alloc = pointerExport(instance.exports, "rnx_alloc");
245
230
  const free = voidExport(instance.exports, "rnx_free");
231
+ const openURLDrain = typeof instance.exports.rnx_open_url_drain === "function" ? pointerExport(instance.exports, "rnx_open_url_drain") : null;
232
+ const drainOpenURLs = () => {
233
+ if (!openURLDrain) return;
234
+ let urls;
235
+ try {
236
+ urls = JSON.parse(readBuffer(openURLDrain()));
237
+ } catch {
238
+ return;
239
+ }
240
+ if (!Array.isArray(urls)) return;
241
+ for (const url of urls) {
242
+ if (typeof url !== "string") continue;
243
+ import_react_native.Linking.canOpenURL(url).then(
244
+ (open) => {
245
+ if (open) import_react_native.Linking.openURL(url).catch(() => {
246
+ });
247
+ },
248
+ () => {
249
+ }
250
+ );
251
+ }
252
+ };
246
253
  const readBuffer = (ptr) => {
247
254
  const view = new DataView(requireMemory().buffer);
248
255
  const length = view.getUint32(ptr, true);
@@ -262,41 +269,44 @@ function instantiate(module2) {
262
269
  mainArgv(0, 0);
263
270
  return {
264
271
  mount: () => {
265
- if ((hasViewExport?.() ?? 0) === 1) {
272
+ if (hasViewExport() === 1) {
266
273
  throw new Error(
267
274
  "swift package has an RNXPackage entry, not an App entry; mount it as a view or make its @main type conform to App"
268
275
  );
269
276
  }
270
- return readTree(readBuffer(mount()));
277
+ const tree = readTree(readBuffer(mount()));
278
+ drainOpenURLs();
279
+ return tree;
271
280
  },
272
281
  mountView: (props) => {
273
- if (!mountViewExport) {
274
- throw new Error(
275
- "swift artifact has no rnx_mount_view export; rebuild the swift package"
276
- );
277
- }
278
- if ((hasViewExport?.() ?? 0) !== 1) {
282
+ if (hasViewExport() !== 1) {
279
283
  throw new Error(
280
284
  "swift package has no RNXPackage entry; its @main type must conform to RNXPackage to mount as a view"
281
285
  );
282
286
  }
283
- return readTree(
287
+ const tree = readTree(
284
288
  readBuffer(withPayload(props, (ptr, length) => mountViewExport(ptr, length)))
285
289
  );
290
+ drainOpenURLs();
291
+ return tree;
286
292
  },
287
- hasView: () => (hasViewExport?.() ?? 0) === 1,
288
- deliver: (handlerId2, payload) => readTree(
289
- readBuffer(
290
- withPayload(
291
- payload,
292
- (ptr, length) => (
293
- // handler ids are opaque to the tenant: they come from the tree
294
- // this instance just returned and they are only meaningful to it
295
- event(handlerId2, ptr, length)
293
+ hasView: () => hasViewExport() === 1,
294
+ deliver: (handlerId2, payload) => {
295
+ const tree = readTree(
296
+ readBuffer(
297
+ withPayload(
298
+ payload,
299
+ (ptr, length) => (
300
+ // handler ids are opaque to the tenant: they come from the tree
301
+ // this instance just returned and they are only meaningful to it
302
+ event(handlerId2, ptr, length)
303
+ )
296
304
  )
297
305
  )
298
- )
299
- ),
306
+ );
307
+ drainOpenURLs();
308
+ return tree;
309
+ },
300
310
  exportState: () => readBuffer(stateExport()),
301
311
  importState: (state) => {
302
312
  withPayload(JSON.parse(state), (ptr, length) => {
@@ -378,6 +388,16 @@ function resolveModifier(modifier) {
378
388
  }
379
389
  return { ...modifier, color: resolveColor(color) };
380
390
  }
391
+ var SwiftResourcesContext = (0, import_react.createContext)(void 0);
392
+ function SwiftImage(props) {
393
+ const table = (0, import_react.useContext)(SwiftResourcesContext);
394
+ const { source, ...rest } = props ?? {};
395
+ const url = typeof source === "string" ? table?.[source] : void 0;
396
+ return (0, import_react.createElement)(import_ui.Image, {
397
+ ...rest,
398
+ ...source === void 0 ? {} : { source: typeof url === "string" ? { uri: url } : source }
399
+ });
400
+ }
381
401
  var NODE_COMPONENTS = {
382
402
  Alert: SwiftAlert,
383
403
  BottomSheet: import_ui.BottomSheet,
@@ -390,14 +410,17 @@ var NODE_COMPONENTS = {
390
410
  Divider: import_ui.Divider,
391
411
  Ellipse: import_ui.Ellipse,
392
412
  Form: import_ui.Form,
413
+ GeometryReader: import_ui.GeometryReader,
393
414
  GlassEffectContainer: import_ui.GlassEffectContainer,
394
415
  Group: import_ui.Group,
395
416
  HStack: import_ui.HStack,
396
- Image: import_ui.Image,
417
+ Image: SwiftImage,
397
418
  Label: import_ui.Label,
398
419
  LazyVStack: import_ui.LazyVStack,
420
+ LinearGradient: import_ui.LinearGradient,
399
421
  List: import_ui.List,
400
422
  Menu: import_ui.Menu,
423
+ Path: import_ui.Path,
401
424
  Picker: import_ui.Picker,
402
425
  ProgressView: import_ui.ProgressView,
403
426
  Rectangle: import_ui.Rectangle,
@@ -613,6 +636,12 @@ function nodeProps(node, deliver) {
613
636
  const size = typeof font?.size === "number" ? font.size : void 0;
614
637
  return {
615
638
  ...typeof props.systemName === "string" ? { systemName: props.systemName } : {},
639
+ // a bundle asset name rides as the kit image source; the kit paints
640
+ // its placeholder until its named-source lane lands (contrast-kit,
641
+ // not this mount row).
642
+ ...typeof props.name === "string" ? { source: props.name } : {},
643
+ ...props.resizable === true ? { resizable: true } : {},
644
+ ...typeof props.renderingMode === "string" ? { renderingMode: props.renderingMode } : {},
616
645
  ...size === void 0 ? {} : { size },
617
646
  ...pressProps(node, deliver)
618
647
  };
@@ -1075,10 +1104,46 @@ function NavigationStackHost({ node, deliver }) {
1075
1104
  screen.id
1076
1105
  )) });
1077
1106
  }
1107
+ var REGULAR_WIDTH = 768;
1108
+ function SplitViewHost({
1109
+ node,
1110
+ deliver,
1111
+ cache
1112
+ }) {
1113
+ const { width } = (0, import_react_native.useWindowDimensions)();
1114
+ const screens = (node.c ?? []).filter((child) => child.t === "NavigationScreen");
1115
+ if (width < REGULAR_WIDTH) {
1116
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native.View, { style: NAVIGATOR_FILL, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(NavigationStackHost, { node, deliver }) });
1117
+ }
1118
+ const sidebar = screens[0];
1119
+ const pushed = screens.slice(1);
1120
+ const detailProp = node.p?.detail;
1121
+ const detail = isRecord(detailProp) && detailProp.t === "SplitDetail" ? readNodes(detailProp.c) : [];
1122
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react_native.View, { style: { flex: 1, flexDirection: "row", alignSelf: "stretch" }, children: [
1123
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native.View, { style: { width: 320 }, children: sidebar ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(NavigationStackHost, { node: { ...node, c: [sidebar] }, deliver }) : null }),
1124
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native.View, { style: { flex: 1 }, children: pushed.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(NavigationStackHost, { node: { ...node, c: pushed }, deliver }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_jsx_runtime.Fragment, { children: detail.map((child) => renderNode(child, deliver, cache)) }) })
1125
+ ] });
1126
+ }
1127
+ function SwiftAppear({
1128
+ node,
1129
+ deliver,
1130
+ children
1131
+ }) {
1132
+ const onAppear = handlerId(node, "onAppear");
1133
+ const onDisappear = handlerId(node, "onDisappear");
1134
+ (0, import_react.useEffect)(() => {
1135
+ if (onAppear !== void 0) deliver(onAppear, null);
1136
+ return () => {
1137
+ if (onDisappear !== void 0) deliver(onDisappear, null);
1138
+ };
1139
+ }, []);
1140
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_jsx_runtime.Fragment, { children });
1141
+ }
1078
1142
  function renderNode(node, deliver, cache) {
1079
1143
  const cached = cache?.entries.get(node.id);
1080
1144
  if (cached && sameNode(cached.node, node)) return cached.element;
1081
- const element = buildNode(node, deliver, cache);
1145
+ const built = buildNode(node, deliver, cache);
1146
+ const element = node.h?.onAppear !== void 0 || node.h?.onDisappear !== void 0 ? (0, import_react.createElement)(SwiftAppear, { key: node.id, node, deliver }, built) : built;
1082
1147
  cache?.entries.set(node.id, { node, element });
1083
1148
  return element;
1084
1149
  }
@@ -1090,6 +1155,9 @@ function buildNode(node, deliver, cache) {
1090
1155
  if (node.t === "NavigationStack") {
1091
1156
  return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native.View, { style: NAVIGATOR_FILL, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(NavigationStackHost, { node, deliver }) }, node.id);
1092
1157
  }
1158
+ if (node.t === "NavigationSplitView") {
1159
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SplitViewHost, { node, deliver, cache }, node.id);
1160
+ }
1093
1161
  if (node.t === "NavigationLink") {
1094
1162
  return (0, import_react.createElement)(
1095
1163
  import_ui.Button,
@@ -1117,7 +1185,8 @@ function buildNode(node, deliver, cache) {
1117
1185
  function SwiftTree({
1118
1186
  tree,
1119
1187
  deliver,
1120
- cache
1188
+ cache,
1189
+ resources
1121
1190
  }) {
1122
1191
  return (
1123
1192
  // a navigation stack at the root lays its own bar out under the status
@@ -1127,8 +1196,10 @@ function SwiftTree({
1127
1196
  import_ui.Host,
1128
1197
  {
1129
1198
  style: { flex: 1 },
1130
- ignoreSafeArea: tree.some((node) => node.t === "NavigationStack"),
1131
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_native.NavigationIndependentTree, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_native.NavigationContainer, { children: tree.map((node) => renderNode(node, deliver, cache)) }) })
1199
+ ignoreSafeArea: tree.some(
1200
+ (node) => node.t === "NavigationStack" || node.t === "NavigationSplitView"
1201
+ ),
1202
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_native.NavigationIndependentTree, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_native.NavigationContainer, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SwiftResourcesContext.Provider, { value: resources, children: tree.map((node) => renderNode(node, deliver, cache)) }) }) })
1132
1203
  }
1133
1204
  )
1134
1205
  );
@@ -1141,19 +1212,19 @@ function rootRegistry() {
1141
1212
  Reflect.set(globalThis, ROOT_KEY, created);
1142
1213
  return created;
1143
1214
  }
1144
- function slotFor(rootId, mountTree, props) {
1215
+ function slotFor(rootId, mountTree) {
1145
1216
  const registry = rootRegistry();
1146
1217
  const existing = registry.get(rootId);
1147
1218
  if (existing) return existing;
1148
- const created = { root: createRoot(mountTree, props), props };
1219
+ const created = { root: createRoot(mountTree) };
1149
1220
  registry.set(rootId, created);
1150
1221
  return created;
1151
1222
  }
1152
- function createRoot(mountTree, props) {
1223
+ function createRoot(mountTree) {
1153
1224
  let instance = null;
1154
1225
  let source = null;
1155
1226
  let refresh;
1156
- let state = { tree: null, error: null };
1227
+ let state = { tree: null, isView: false, error: null };
1157
1228
  let swap = Promise.resolve();
1158
1229
  const listeners = /* @__PURE__ */ new Set();
1159
1230
  const cache = { entries: /* @__PURE__ */ new Map() };
@@ -1161,13 +1232,14 @@ function createRoot(mountTree, props) {
1161
1232
  state = next;
1162
1233
  for (const listener of listeners) listener();
1163
1234
  };
1164
- const apply = async (options) => {
1235
+ const apply = async (options, props) => {
1165
1236
  const carried = instance?.exportState() ?? null;
1166
1237
  const created = instantiate(await compile(options.url));
1167
1238
  if (carried !== null) created.importState(carried);
1168
1239
  if (source !== options) return;
1169
1240
  instance = created;
1170
- publish({ tree: mountTree(created, props.current), error: null });
1241
+ const mounted = mountTree(created, props);
1242
+ publish({ tree: mounted.tree, isView: mounted.isView, error: null });
1171
1243
  };
1172
1244
  const component = function SwiftRoot() {
1173
1245
  const rendered = (0, import_react.useSyncExternalStore)(
@@ -1181,24 +1253,41 @@ function createRoot(mountTree, props) {
1181
1253
  if (!rendered.tree) return null;
1182
1254
  const deliver = (handlerId2, payload) => {
1183
1255
  if (!instance) throw new Error("swift app received an event before it mounted");
1184
- publish({ tree: instance.deliver(handlerId2, payload), error: null });
1256
+ publish({
1257
+ tree: instance.deliver(handlerId2, payload),
1258
+ isView: rendered.isView,
1259
+ error: null
1260
+ });
1185
1261
  };
1186
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SwiftTree, { tree: rendered.tree, deliver, cache });
1262
+ const resources = source?.resources;
1263
+ if (rendered.isView)
1264
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SwiftResourcesContext.Provider, { value: resources, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_jsx_runtime.Fragment, { children: rendered.tree.map((node) => renderNode(node, deliver, cache)) }) });
1265
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1266
+ SwiftTree,
1267
+ {
1268
+ tree: rendered.tree,
1269
+ deliver,
1270
+ cache,
1271
+ resources
1272
+ }
1273
+ );
1187
1274
  };
1188
1275
  return {
1189
1276
  component,
1190
- use(options, refreshKey) {
1191
- const changed = source === null || source.hash !== options.hash || source.url !== options.url || refreshKey !== void 0 && refreshKey !== refresh;
1277
+ use(options, refreshKey, props) {
1278
+ const changed = source === null || source.hash !== options.hash || source.url !== options.url || JSON.stringify(source.resources ?? null) !== JSON.stringify(options.resources ?? null) || refreshKey !== void 0 && refreshKey !== refresh;
1192
1279
  if (changed) {
1193
1280
  source = options;
1194
1281
  refresh = refreshKey;
1282
+ const next = props ?? {};
1195
1283
  swap = swap.then(
1196
- () => apply(options),
1197
- () => apply(options)
1284
+ () => apply(options, next),
1285
+ () => apply(options, next)
1198
1286
  );
1199
1287
  swap.catch((error) => {
1200
1288
  publish({
1201
1289
  tree: null,
1290
+ isView: false,
1202
1291
  error: error instanceof Error ? error : new Error(String(error))
1203
1292
  });
1204
1293
  });
@@ -1207,11 +1296,6 @@ function createRoot(mountTree, props) {
1207
1296
  }
1208
1297
  };
1209
1298
  }
1210
- function createSwiftModule(options) {
1211
- const rootId = options.rootId ?? "root";
1212
- const slot = slotFor(rootId, (instance) => instance.mount(), { current: {} });
1213
- return slot.root.use(options);
1214
- }
1215
1299
  function propsSignature(props) {
1216
1300
  try {
1217
1301
  return JSON.stringify(props, (_key, value) => {
@@ -1228,22 +1312,21 @@ function propsSignature(props) {
1228
1312
  );
1229
1313
  }
1230
1314
  }
1231
- function createSwiftView(options) {
1232
- const rootId = options.rootId ?? "view";
1233
- const slot = slotFor(rootId, (instance, props) => instance.mountView(props), {
1234
- current: {}
1235
- });
1236
- return function SwiftView(props) {
1315
+ function createSwiftEntry(options) {
1316
+ const rootId = options.rootId ?? "root";
1317
+ const slot = slotFor(
1318
+ rootId,
1319
+ (instance, props) => instance.hasView() ? { tree: instance.mountView(props), isView: true } : { tree: instance.mount(), isView: false }
1320
+ );
1321
+ return function SwiftEntry(props) {
1237
1322
  if (props.children !== void 0) {
1238
- throw new Error("swift views take data props, not children");
1323
+ throw new Error("swift entries take data props, not children");
1239
1324
  }
1240
- slot.props.current = props;
1241
- const component = slot.root.use(options, propsSignature(props));
1325
+ const component = slot.root.use(options, propsSignature(props), props);
1242
1326
  return (0, import_react.createElement)(component);
1243
1327
  };
1244
1328
  }
1245
1329
  // Annotate the CommonJS export names for ESM import in node:
1246
1330
  0 && (module.exports = {
1247
- createSwiftModule,
1248
- createSwiftView
1331
+ createSwiftEntry
1249
1332
  });
package/dist-lib/vite.cjs CHANGED
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.521 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.523 | (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;
@@ -829,8 +829,9 @@ function sourceStamp(packagePath) {
829
829
  }
830
830
  return hash.digest("hex").slice(0, 16);
831
831
  }
832
- function viewRootId(packagePath, file) {
833
- return import_node_path4.default.join(packagePath, import_node_path4.default.relative(packagePath, file));
832
+ function entryRootId(packagePath, file) {
833
+ const relative2 = import_node_path4.default.relative(packagePath, file).split(import_node_path4.default.sep).join(import_node_path4.default.posix.sep);
834
+ return `${import_node_path4.default.basename(packagePath)}${import_node_path4.default.posix.sep}${relative2}`;
834
835
  }
835
836
  function artifactUrl(project, artifact) {
836
837
  const address = devServer?.httpServer?.address();
@@ -848,6 +849,11 @@ function builtArtifact(packagePath) {
848
849
  }
849
850
  return import_node_path4.default.join(binDir, artifacts[0]);
850
851
  }
852
+ function streamText(value) {
853
+ if (typeof value === "string") return value.trim();
854
+ if (Buffer.isBuffer(value)) return value.toString("utf8").trim();
855
+ return "";
856
+ }
851
857
  async function compile(packagePath, stamp) {
852
858
  const swift = import_node_path4.default.join(TOOLCHAIN_BIN, "swift");
853
859
  if (!import_node_fs3.default.existsSync(swift)) {
@@ -872,10 +878,13 @@ async function compile(packagePath, stamp) {
872
878
  { maxBuffer: 64 * 1024 * 1024 }
873
879
  );
874
880
  } catch (error) {
875
- throw new Error(
876
- `swift build failed for ${packagePath}
877
- ${error instanceof Error ? error.message : String(error)}`
878
- );
881
+ const streams = error && typeof error === "object" ? [
882
+ streamText(Reflect.get(error, "stdout")),
883
+ streamText(Reflect.get(error, "stderr"))
884
+ ].filter(Boolean) : [];
885
+ const detail = streams.length > 0 ? streams.join("\n") : error instanceof Error ? error.message : String(error);
886
+ throw new Error(`swift build failed for ${packagePath}
887
+ ${detail}`);
879
888
  }
880
889
  const bytes = import_node_fs3.default.readFileSync(builtArtifact(packagePath));
881
890
  return {
@@ -887,7 +896,13 @@ ${error instanceof Error ? error.message : String(error)}`
887
896
  function artifactFor(project) {
888
897
  const stamp = sourceStamp(project.packagePath);
889
898
  if (project.artifact?.stamp === stamp) return Promise.resolve(project.artifact);
890
- project.building ??= compile(project.packagePath, stamp).then(
899
+ if (project.building) {
900
+ const running = project.building;
901
+ if (running.stamp === stamp) return running.promise;
902
+ const again = () => artifactFor(project);
903
+ return running.promise.then(again, again);
904
+ }
905
+ const promise = compile(project.packagePath, stamp).then(
891
906
  (artifact) => {
892
907
  project.artifact = artifact;
893
908
  project.building = null;
@@ -898,7 +913,8 @@ function artifactFor(project) {
898
913
  throw error;
899
914
  }
900
915
  );
901
- return project.building;
916
+ project.building = { stamp, promise };
917
+ return promise;
902
918
  }
903
919
  function packageFor(file) {
904
920
  let dir = import_node_path4.default.dirname(file);
@@ -912,14 +928,6 @@ function packageFor(file) {
912
928
  `no Package.swift above ${file}${stop === void 0 ? "" : ` (searched up to ${stop})`}; a .swift import needs a swiftpm package like the one in packages/sootsim-swift/example`
913
929
  );
914
930
  }
915
- function isViewPackage(packagePath) {
916
- const main = /@main\s+(?:\w+\s+)*(?:struct|class|enum|actor)\s+\w+[^{]*:\s*[^{]*\bRNXPackage\b/;
917
- for (const file of sourceFiles(packagePath)) {
918
- const text = import_node_fs3.default.readFileSync(file, "utf8").replace(/^\s*\/\/.*$/gm, "");
919
- if (main.test(text)) return true;
920
- }
921
- return false;
922
- }
923
931
  function swiftPlugin(options = {}) {
924
932
  return {
925
933
  name: "rnx-swift",
@@ -938,6 +946,7 @@ function swiftPlugin(options = {}) {
938
946
  async load(id) {
939
947
  if (!id.startsWith(VIRTUAL_PREFIX)) return null;
940
948
  const file = id.slice(VIRTUAL_PREFIX.length);
949
+ if (!import_node_fs3.default.existsSync(file)) throw new Error(`swift source ${file} no longer exists`);
941
950
  const packagePath = options.packagePath ?? packageFor(file);
942
951
  const project = projectFor(packagePath);
943
952
  for (const source of sourceFiles(packagePath)) this.addWatchFile(source);
@@ -952,17 +961,9 @@ function swiftPlugin(options = {}) {
952
961
  this.warn(error instanceof Error ? error.message : String(error));
953
962
  artifact = project.artifact;
954
963
  }
955
- if (isViewPackage(packagePath)) {
956
- const rootId = viewRootId(packagePath, file);
957
- return [
958
- `import { createSwiftView } from 'rnxsim/swift'`,
959
- `export default createSwiftView({ url: ${JSON.stringify(artifactUrl(project, artifact))}, hash: ${JSON.stringify(artifact.hash)}, rootId: ${JSON.stringify(rootId)} })`,
960
- ""
961
- ].join("\n");
962
- }
963
964
  return [
964
- `import { createSwiftModule } from 'rnxsim/swift'`,
965
- `export default createSwiftModule({ url: ${JSON.stringify(artifactUrl(project, artifact))}, hash: ${JSON.stringify(artifact.hash)} })`,
965
+ `import { createSwiftEntry } from 'rnxsim/swift'`,
966
+ `export default createSwiftEntry({ url: ${JSON.stringify(artifactUrl(project, artifact))}, hash: ${JSON.stringify(artifact.hash)}, rootId: ${JSON.stringify(entryRootId(packagePath, file))} })`,
966
967
  ""
967
968
  ].join("\n");
968
969
  },
@@ -974,22 +975,17 @@ function swiftPlugin(options = {}) {
974
975
  next();
975
976
  return;
976
977
  }
977
- void (async () => {
978
- for (const project of projects.values()) {
979
- const artifact = await artifactFor(project);
980
- if (url === `${ARTIFACT_PATH}${artifact.hash}.wasm`) {
981
- res.setHeader("access-control-allow-origin", "*");
982
- res.setHeader("content-type", "application/wasm");
983
- res.end(artifact.bytes);
984
- return;
985
- }
978
+ for (const project of projects.values()) {
979
+ const artifact = project.artifact;
980
+ if (artifact && url === `${ARTIFACT_PATH}${artifact.hash}.wasm`) {
981
+ res.setHeader("access-control-allow-origin", "*");
982
+ res.setHeader("content-type", "application/wasm");
983
+ res.end(artifact.bytes);
984
+ return;
986
985
  }
987
- res.statusCode = 404;
988
- res.end("swift artifact is stale");
989
- })().catch((error) => {
990
- res.statusCode = 500;
991
- res.end(error instanceof Error ? error.message : String(error));
992
- });
986
+ }
987
+ res.statusCode = 404;
988
+ res.end("swift artifact is stale");
993
989
  });
994
990
  }
995
991
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rnxsim",
3
- "version": "0.1.521",
3
+ "version": "0.1.523",
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",
package/src/swift.ts CHANGED
@@ -1,8 +1,7 @@
1
1
  // the runtime the `.swift` vite transform emits its module against. the
2
2
  // implementation lives beside the toolchain it drives, in sootsim-swift.
3
3
  export {
4
- createSwiftModule,
5
- createSwiftView,
4
+ createSwiftEntry,
5
+ type SwiftEntryOptions,
6
6
  type SwiftModuleOptions,
7
- type SwiftViewOptions,
8
7
  } from '../../sootsim-swift/src/mount.tsx'