peachsim 0.1.2229 → 0.1.2231

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 (87) hide show
  1. package/dist-lib/agent-daemon-client.cjs +1 -1
  2. package/dist-lib/agent-events.cjs +1 -1
  3. package/dist-lib/attached-projects.cjs +1 -1
  4. package/dist-lib/auth/shared-session.cjs +1 -1
  5. package/dist-lib/backend-origin.cjs +1 -1
  6. package/dist-lib/beta.cjs +1 -1
  7. package/dist-lib/beta.mjs +1 -1
  8. package/dist-lib/bridge-constants.cjs +1 -1
  9. package/dist-lib/bridge-contract-input.cjs +1 -1
  10. package/dist-lib/bridge-contract-input.mjs +1 -1
  11. package/dist-lib/bridge-contract.cjs +1 -1
  12. package/dist-lib/bridge-contract.mjs +1 -1
  13. package/dist-lib/bundle-channel.cjs +1 -1
  14. package/dist-lib/capture-contract.cjs +1 -1
  15. package/dist-lib/capture-contract.mjs +1 -1
  16. package/dist-lib/cloud-contract.cjs +1 -1
  17. package/dist-lib/cloud-contract.mjs +1 -1
  18. package/dist-lib/cloud-test-args.cjs +1 -1
  19. package/dist-lib/cloud-test-args.mjs +1 -1
  20. package/dist-lib/cloud.cjs +1 -1
  21. package/dist-lib/cloud.mjs +1 -1
  22. package/dist-lib/config.cjs +1 -1
  23. package/dist-lib/config.mjs +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/expo-swift-bundle.cjs +1 -1
  27. package/dist-lib/expo-swift-metadata.cjs +1 -1
  28. package/dist-lib/expo-swift-metadata.mjs +1 -1
  29. package/dist-lib/home-paths.cjs +1 -1
  30. package/dist-lib/host/bridge-host.cjs +42 -3
  31. package/dist-lib/host/fetch-proxy-handler.cjs +1 -1
  32. package/dist-lib/host/fetch-proxy-overrides.cjs +1 -1
  33. package/dist-lib/host/fetch-proxy-overrides.mjs +1 -1
  34. package/dist-lib/host/replacement-module-handler.cjs +1 -1
  35. package/dist-lib/host/websocket-proxy.cjs +1 -1
  36. package/dist-lib/index.cjs +7 -1
  37. package/dist-lib/jump-to-source-babel.cjs +1 -1
  38. package/dist-lib/jump-to-source-native.cjs +1 -1
  39. package/dist-lib/kotlin-host.cjs +1 -1
  40. package/dist-lib/menu.cjs +1 -1
  41. package/dist-lib/menu.mjs +1 -1
  42. package/dist-lib/metro-fingerprint-registry.cjs +1 -1
  43. package/dist-lib/metro-fingerprint-registry.mjs +1 -1
  44. package/dist-lib/metro-production-bundle.cjs +1 -1
  45. package/dist-lib/metro-production-bundle.mjs +1 -1
  46. package/dist-lib/metro.cjs +1 -1
  47. package/dist-lib/native-app-identity-project.cjs +1 -1
  48. package/dist-lib/native-app-identity-project.mjs +1 -1
  49. package/dist-lib/native-app-identity.cjs +1 -1
  50. package/dist-lib/native-app-identity.mjs +1 -1
  51. package/dist-lib/native-firebase-metadata.cjs +1 -1
  52. package/dist-lib/native-firebase-metadata.mjs +1 -1
  53. package/dist-lib/pdfium-raster.cjs +1 -1
  54. package/dist-lib/pdfium-raster.mjs +1 -1
  55. package/dist-lib/plist.cjs +1 -1
  56. package/dist-lib/plist.mjs +1 -1
  57. package/dist-lib/profiles.cjs +1 -1
  58. package/dist-lib/public-brand.cjs +1 -1
  59. package/dist-lib/public-origins-lib-esm.json +24 -24
  60. package/dist-lib/public-origins-lib.json +53 -53
  61. package/dist-lib/react-native-host-modules.cjs +1 -1
  62. package/dist-lib/react-native-host-modules.mjs +1 -1
  63. package/dist-lib/reap-browser.cjs +1 -1
  64. package/dist-lib/scripts/dev-server-scanner.cjs +43 -3
  65. package/dist-lib/sdk.cjs +1 -1
  66. package/dist-lib/sdk.mjs +1 -1
  67. package/dist-lib/skills.cjs +43 -4
  68. package/dist-lib/swift-compile.cjs +1 -1
  69. package/dist-lib/swift-compile.mjs +1 -1
  70. package/dist-lib/swift-package.cjs +1 -1
  71. package/dist-lib/swift-package.mjs +1 -1
  72. package/dist-lib/swift-submit.cjs +1 -1
  73. package/dist-lib/swift-submit.mjs +1 -1
  74. package/dist-lib/swift-toolchain.cjs +1 -1
  75. package/dist-lib/swift.cjs +1 -1
  76. package/dist-lib/vite-swift.cjs +1 -1
  77. package/dist-lib/vite.cjs +7 -1
  78. package/dist-lib/worklet-executable.cjs +1 -1
  79. package/dist-lib/worklet-executable.mjs +1 -1
  80. package/install.sh +12 -2
  81. package/kotlin/sdk.tar.gz +0 -0
  82. package/package.json +1 -1
  83. package/scripts/dev-server-scanner.ts +64 -3
  84. package/src/conformance-pixel-comparison.ts +12 -7
  85. package/src/react-native-coverage/native-typescript-parser.ts +18 -8
  86. package/src/vite-plugin-one.ts +2 -0
  87. package/src/vite-plugin.ts +9 -8
@@ -1,4 +1,4 @@
1
- /*! peach v0.1.2229 | (c) 2026 Tamagui LLC | Proprietary; see LICENSE */
1
+ /*! peach v0.1.2231 | (c) 2026 Tamagui LLC | Proprietary; see LICENSE */
2
2
  let __sootsim_import_meta_url = '', __sootsim_import_meta_dirname = '', __sootsim_import_meta_filename = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; __sootsim_import_meta_dirname = __dirname; __sootsim_import_meta_filename = __filename; } catch {}
3
3
  "use strict";
4
4
  var __create = Object.create;
@@ -1649,6 +1649,30 @@ async function fetchManifestEnrichment(result, buildIconProxyUrl) {
1649
1649
  }
1650
1650
  var knownNonPatched = /* @__PURE__ */ new Set();
1651
1651
  var knownOne = /* @__PURE__ */ new Set();
1652
+ var oneNativeApps = /* @__PURE__ */ new Map();
1653
+ function oneNativeWidgetFromScan(scan, result, identity) {
1654
+ if (!Array.isArray(scan)) return null;
1655
+ for (const entry of scan) {
1656
+ if (!entry || typeof entry !== "object" || entry.port !== result.port) continue;
1657
+ if (typeof entry.bundleUrl !== "string") continue;
1658
+ let advertised;
1659
+ try {
1660
+ advertised = new URL(entry.bundleUrl);
1661
+ } catch {
1662
+ continue;
1663
+ }
1664
+ if (!isLoopbackHost(advertised.hostname) || advertised.port !== String(result.port))
1665
+ continue;
1666
+ const widget = configuredWidgetFromScan(scan, advertised.href);
1667
+ if (widget?.projectRoot === identity.root && widget.metadata.bundleId === identity.bundleId)
1668
+ return {
1669
+ ...widget,
1670
+ bundleUrl: result.bundleUrl,
1671
+ packageUrl: new URL("/__peach/swift-package/OneWidgets", result.bundleUrl).href
1672
+ };
1673
+ }
1674
+ return null;
1675
+ }
1652
1676
  async function probePort(port, buildIconProxyUrl, listeningProcess, verdict) {
1653
1677
  const demoApps = await loadOptionalDemoApps();
1654
1678
  const probeHostname = await tcpPing(port);
@@ -1675,6 +1699,15 @@ async function probePort(port, buildIconProxyUrl, listeningProcess, verdict) {
1675
1699
  ]);
1676
1700
  const manifestParsed = manifestRes ? safeParseManifest(manifestRes.body) : null;
1677
1701
  const { launchUrl: manifestLaunchUrl, client: manifestClient } = readExpoManifestFields(manifestParsed);
1702
+ const metadata = manifestParsed?.metadata;
1703
+ const extra = manifestParsed?.extra;
1704
+ const expoGo = extra && typeof extra === "object" ? Reflect.get(extra, "expoGo") : null;
1705
+ const developer = expoGo && typeof expoGo === "object" ? Reflect.get(expoGo, "developer") : null;
1706
+ const projectRoot = developer && typeof developer === "object" ? Reflect.get(developer, "projectRoot") : null;
1707
+ const bundleId = manifestClient.ios?.bundleIdentifier;
1708
+ if (metadata && typeof metadata === "object" && Reflect.get(metadata, "oneNativeApp") === true && typeof projectRoot === "string" && typeof bundleId === "string")
1709
+ oneNativeApps.set(port, { root: projectRoot, bundleId });
1710
+ else if (manifestRes) oneNativeApps.delete(port);
1678
1711
  const manifestState = !manifestRes ? "no-answer" : manifestParsed && (manifestLaunchUrl || typeof manifestClient.name === "string") ? "resolved" : "no-manifest";
1679
1712
  const metroPackager = !!statusRes?.body.includes("packager-status:running") && !(manifestState === "resolved" && manifestLaunchUrl?.includes("/one/metro-entry.bundle"));
1680
1713
  const [sootsimRes, swiftRes, kotlinRes, oneScanRes] = metroPackager ? [null, null, null, null] : await Promise.all([
@@ -1877,6 +1910,7 @@ function __resetScannerCache() {
1877
1910
  portCache.clear();
1878
1911
  knownNonPatched.clear();
1879
1912
  knownOne.clear();
1913
+ oneNativeApps.clear();
1880
1914
  enrichmentCache.clear();
1881
1915
  enrichmentInFlight.clear();
1882
1916
  portCacheInvalidatedAt.clear();
@@ -1911,6 +1945,9 @@ async function scanDevServers(opts = {}) {
1911
1945
  for (const p of [...knownOne]) {
1912
1946
  if (!currentPorts.has(p)) knownOne.delete(p);
1913
1947
  }
1948
+ for (const p of [...oneNativeApps.keys()]) {
1949
+ if (!currentPorts.has(p)) oneNativeApps.delete(p);
1950
+ }
1914
1951
  for (const p of [...enrichmentCache.keys()]) {
1915
1952
  if (!currentPorts.has(p)) enrichmentCache.delete(p);
1916
1953
  }
@@ -1935,6 +1972,7 @@ async function scanDevServers(opts = {}) {
1935
1972
  if (cached2 && cached2.pid !== pid) {
1936
1973
  knownNonPatched.delete(port);
1937
1974
  knownOne.delete(port);
1975
+ oneNativeApps.delete(port);
1938
1976
  enrichmentCache.delete(port);
1939
1977
  localIconPathCache.delete(port);
1940
1978
  }
@@ -1962,7 +2000,8 @@ async function scanDevServers(opts = {}) {
1962
2000
  }
1963
2001
  await Promise.all(
1964
2002
  results.map(async (result) => {
1965
- if (result.framework !== "one" && result.framework !== "vxrn") {
2003
+ const nativeIdentity = oneNativeApps.get(result.port);
2004
+ if (result.framework !== "one" && result.framework !== "vxrn" && !nativeIdentity) {
1966
2005
  result.widget = null;
1967
2006
  return;
1968
2007
  }
@@ -1977,7 +2016,8 @@ async function scanDevServers(opts = {}) {
1977
2016
  result.widget ??= null;
1978
2017
  return;
1979
2018
  }
1980
- result.widget = scanRes.statusCode === 200 && scanRes.contentType?.includes("json") ? configuredWidgetFromScan(safeParseManifest(scanRes.body), result.bundleUrl) : null;
2019
+ const scan2 = scanRes.statusCode === 200 && scanRes.contentType?.includes("json") ? safeParseManifest(scanRes.body) : null;
2020
+ result.widget = nativeIdentity ? oneNativeWidgetFromScan(scan2, result, nativeIdentity) : configuredWidgetFromScan(scan2, result.bundleUrl);
1981
2021
  })
1982
2022
  );
1983
2023
  const pidByPort = /* @__PURE__ */ new Map();
package/dist-lib/sdk.cjs CHANGED
@@ -1,4 +1,4 @@
1
- /*! peach v0.1.2229 | (c) 2026 Tamagui LLC | Proprietary; see LICENSE */
1
+ /*! peach v0.1.2231 | (c) 2026 Tamagui LLC | Proprietary; see LICENSE */
2
2
  let __sootsim_import_meta_url = '', __sootsim_import_meta_dirname = '', __sootsim_import_meta_filename = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; __sootsim_import_meta_dirname = __dirname; __sootsim_import_meta_filename = __filename; } catch {}
3
3
  "use strict";
4
4
  var __defProp = Object.defineProperty;
package/dist-lib/sdk.mjs CHANGED
@@ -1,4 +1,4 @@
1
- /*! peach v0.1.2229 | (c) 2026 Tamagui LLC | Proprietary; see LICENSE */
1
+ /*! peach v0.1.2231 | (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
- /*! peach v0.1.2229 | (c) 2026 Tamagui LLC | Proprietary; see LICENSE */
1
+ /*! peach v0.1.2231 | (c) 2026 Tamagui LLC | Proprietary; see LICENSE */
2
2
  let __sootsim_import_meta_url = '', __sootsim_import_meta_dirname = '', __sootsim_import_meta_filename = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; __sootsim_import_meta_dirname = __dirname; __sootsim_import_meta_filename = __filename; } catch {}
3
3
  "use strict";
4
4
  var __create = Object.create;
@@ -89835,6 +89835,29 @@ async function fetchManifestEnrichment(result, buildIconProxyUrl) {
89835
89835
  });
89836
89836
  invalidatePortCache(result.port);
89837
89837
  }
89838
+ function oneNativeWidgetFromScan(scan2, result, identity2) {
89839
+ if (!Array.isArray(scan2)) return null;
89840
+ for (const entry of scan2) {
89841
+ if (!entry || typeof entry !== "object" || entry.port !== result.port) continue;
89842
+ if (typeof entry.bundleUrl !== "string") continue;
89843
+ let advertised;
89844
+ try {
89845
+ advertised = new URL(entry.bundleUrl);
89846
+ } catch {
89847
+ continue;
89848
+ }
89849
+ if (!isLoopbackHost(advertised.hostname) || advertised.port !== String(result.port))
89850
+ continue;
89851
+ const widget = configuredWidgetFromScan(scan2, advertised.href);
89852
+ if (widget?.projectRoot === identity2.root && widget.metadata.bundleId === identity2.bundleId)
89853
+ return {
89854
+ ...widget,
89855
+ bundleUrl: result.bundleUrl,
89856
+ packageUrl: new URL("/__peach/swift-package/OneWidgets", result.bundleUrl).href
89857
+ };
89858
+ }
89859
+ return null;
89860
+ }
89838
89861
  async function probePort(port, buildIconProxyUrl, listeningProcess, verdict) {
89839
89862
  const demoApps = await loadOptionalDemoApps();
89840
89863
  const probeHostname = await tcpPing(port);
@@ -89861,6 +89884,15 @@ async function probePort(port, buildIconProxyUrl, listeningProcess, verdict) {
89861
89884
  ]);
89862
89885
  const manifestParsed = manifestRes ? safeParseManifest(manifestRes.body) : null;
89863
89886
  const { launchUrl: manifestLaunchUrl, client: manifestClient } = readExpoManifestFields(manifestParsed);
89887
+ const metadata = manifestParsed?.metadata;
89888
+ const extra = manifestParsed?.extra;
89889
+ const expoGo = extra && typeof extra === "object" ? Reflect.get(extra, "expoGo") : null;
89890
+ const developer = expoGo && typeof expoGo === "object" ? Reflect.get(expoGo, "developer") : null;
89891
+ const projectRoot = developer && typeof developer === "object" ? Reflect.get(developer, "projectRoot") : null;
89892
+ const bundleId = manifestClient.ios?.bundleIdentifier;
89893
+ if (metadata && typeof metadata === "object" && Reflect.get(metadata, "oneNativeApp") === true && typeof projectRoot === "string" && typeof bundleId === "string")
89894
+ oneNativeApps.set(port, { root: projectRoot, bundleId });
89895
+ else if (manifestRes) oneNativeApps.delete(port);
89864
89896
  const manifestState = !manifestRes ? "no-answer" : manifestParsed && (manifestLaunchUrl || typeof manifestClient.name === "string") ? "resolved" : "no-manifest";
89865
89897
  const metroPackager = !!statusRes?.body.includes("packager-status:running") && !(manifestState === "resolved" && manifestLaunchUrl?.includes("/one/metro-entry.bundle"));
89866
89898
  const [sootsimRes, swiftRes, kotlinRes, oneScanRes] = metroPackager ? [null, null, null, null] : await Promise.all([
@@ -90081,6 +90113,9 @@ async function scanDevServers(opts = {}) {
90081
90113
  for (const p of [...knownOne]) {
90082
90114
  if (!currentPorts.has(p)) knownOne.delete(p);
90083
90115
  }
90116
+ for (const p of [...oneNativeApps.keys()]) {
90117
+ if (!currentPorts.has(p)) oneNativeApps.delete(p);
90118
+ }
90084
90119
  for (const p of [...enrichmentCache.keys()]) {
90085
90120
  if (!currentPorts.has(p)) enrichmentCache.delete(p);
90086
90121
  }
@@ -90105,6 +90140,7 @@ async function scanDevServers(opts = {}) {
90105
90140
  if (cached4 && cached4.pid !== pid) {
90106
90141
  knownNonPatched.delete(port);
90107
90142
  knownOne.delete(port);
90143
+ oneNativeApps.delete(port);
90108
90144
  enrichmentCache.delete(port);
90109
90145
  localIconPathCache.delete(port);
90110
90146
  }
@@ -90132,7 +90168,8 @@ async function scanDevServers(opts = {}) {
90132
90168
  }
90133
90169
  await Promise.all(
90134
90170
  results.map(async (result) => {
90135
- if (result.framework !== "one" && result.framework !== "vxrn") {
90171
+ const nativeIdentity = oneNativeApps.get(result.port);
90172
+ if (result.framework !== "one" && result.framework !== "vxrn" && !nativeIdentity) {
90136
90173
  result.widget = null;
90137
90174
  return;
90138
90175
  }
@@ -90147,7 +90184,8 @@ async function scanDevServers(opts = {}) {
90147
90184
  result.widget ??= null;
90148
90185
  return;
90149
90186
  }
90150
- result.widget = scanRes.statusCode === 200 && scanRes.contentType?.includes("json") ? configuredWidgetFromScan(safeParseManifest(scanRes.body), result.bundleUrl) : null;
90187
+ const scan3 = scanRes.statusCode === 200 && scanRes.contentType?.includes("json") ? safeParseManifest(scanRes.body) : null;
90188
+ result.widget = nativeIdentity ? oneNativeWidgetFromScan(scan3, result, nativeIdentity) : configuredWidgetFromScan(scan3, result.bundleUrl);
90151
90189
  })
90152
90190
  );
90153
90191
  const pidByPort = /* @__PURE__ */ new Map();
@@ -90171,7 +90209,7 @@ async function scanDevServers(opts = {}) {
90171
90209
  }
90172
90210
  return results.filter((r) => !isSootSimSelfServer(r)).sort((a, b) => a.port - b.port);
90173
90211
  }
90174
- var import_child_process, import_promises11, import_http, import_net, import_node_fs107, import_node_os22, import_node_path108, LISTENER_LOCK_PATH, LISTENER_RESULT_PATH, LISTENER_LOCK_STALE_MS, LISTENER_LOCK_WAIT_MS, TIMEOUT_MS, MANIFEST_TIMEOUT_MS, SERVER_SCAN_PROBE_HEADER, TCP_GATE_MS, BODY_TIMEOUT_MS, FALLBACK_PORTS, SELF_PORT_RANGE_START, SELF_PORT_RANGE_END, DevServerScanUnavailableError, LISTING_TIMEOUT_MS, LISTENER_CACHE_MS, listenerCache, inflightListing, listenerHolds, cwdByPid, cwdQueue, cwdFlushing, localIconPathCache, localIconProbeInFlight, ENRICH_TIMEOUT_MS, enrichmentCache, enrichmentInFlight, knownNonPatched, knownOne, portCache, portCacheInvalidatedAt, NEGATIVE_CACHE_TTL_MS, WEAK_RESULT_CACHE_TTL_MS;
90212
+ var import_child_process, import_promises11, import_http, import_net, import_node_fs107, import_node_os22, import_node_path108, LISTENER_LOCK_PATH, LISTENER_RESULT_PATH, LISTENER_LOCK_STALE_MS, LISTENER_LOCK_WAIT_MS, TIMEOUT_MS, MANIFEST_TIMEOUT_MS, SERVER_SCAN_PROBE_HEADER, TCP_GATE_MS, BODY_TIMEOUT_MS, FALLBACK_PORTS, SELF_PORT_RANGE_START, SELF_PORT_RANGE_END, DevServerScanUnavailableError, LISTING_TIMEOUT_MS, LISTENER_CACHE_MS, listenerCache, inflightListing, listenerHolds, cwdByPid, cwdQueue, cwdFlushing, localIconPathCache, localIconProbeInFlight, ENRICH_TIMEOUT_MS, enrichmentCache, enrichmentInFlight, knownNonPatched, knownOne, oneNativeApps, portCache, portCacheInvalidatedAt, NEGATIVE_CACHE_TTL_MS, WEAK_RESULT_CACHE_TTL_MS;
90175
90213
  var init_dev_server_scanner = __esm({
90176
90214
  "scripts/dev-server-scanner.ts"() {
90177
90215
  "use strict";
@@ -90236,6 +90274,7 @@ var init_dev_server_scanner = __esm({
90236
90274
  enrichmentInFlight = /* @__PURE__ */ new Set();
90237
90275
  knownNonPatched = /* @__PURE__ */ new Set();
90238
90276
  knownOne = /* @__PURE__ */ new Set();
90277
+ oneNativeApps = /* @__PURE__ */ new Map();
90239
90278
  portCache = /* @__PURE__ */ new Map();
90240
90279
  portCacheInvalidatedAt = /* @__PURE__ */ new Map();
90241
90280
  NEGATIVE_CACHE_TTL_MS = 3e4;
@@ -1,4 +1,4 @@
1
- /*! peach v0.1.2229 | (c) 2026 Tamagui LLC | Proprietary; see LICENSE */
1
+ /*! peach v0.1.2231 | (c) 2026 Tamagui LLC | Proprietary; see LICENSE */
2
2
  let __sootsim_import_meta_url = '', __sootsim_import_meta_dirname = '', __sootsim_import_meta_filename = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; __sootsim_import_meta_dirname = __dirname; __sootsim_import_meta_filename = __filename; } catch {}
3
3
  "use strict";
4
4
  var __create = Object.create;
@@ -1,4 +1,4 @@
1
- /*! peach v0.1.2229 | (c) 2026 Tamagui LLC | Proprietary; see LICENSE */
1
+ /*! peach v0.1.2231 | (c) 2026 Tamagui LLC | Proprietary; see LICENSE */
2
2
 
3
3
  // src/swift-compile.ts
4
4
  import {
@@ -1,4 +1,4 @@
1
- /*! peach v0.1.2229 | (c) 2026 Tamagui LLC | Proprietary; see LICENSE */
1
+ /*! peach v0.1.2231 | (c) 2026 Tamagui LLC | Proprietary; see LICENSE */
2
2
  let __sootsim_import_meta_url = '', __sootsim_import_meta_dirname = '', __sootsim_import_meta_filename = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; __sootsim_import_meta_dirname = __dirname; __sootsim_import_meta_filename = __filename; } catch {}
3
3
  "use strict";
4
4
  var __defProp = Object.defineProperty;
@@ -1,4 +1,4 @@
1
- /*! peach v0.1.2229 | (c) 2026 Tamagui LLC | Proprietary; see LICENSE */
1
+ /*! peach v0.1.2231 | (c) 2026 Tamagui LLC | Proprietary; see LICENSE */
2
2
 
3
3
  // src/swift-package.ts
4
4
  function swiftManifestSettings(target) {
@@ -1,4 +1,4 @@
1
- /*! peach v0.1.2229 | (c) 2026 Tamagui LLC | Proprietary; see LICENSE */
1
+ /*! peach v0.1.2231 | (c) 2026 Tamagui LLC | Proprietary; see LICENSE */
2
2
  let __sootsim_import_meta_url = '', __sootsim_import_meta_dirname = '', __sootsim_import_meta_filename = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; __sootsim_import_meta_dirname = __dirname; __sootsim_import_meta_filename = __filename; } catch {}
3
3
  "use strict";
4
4
  var __defProp = Object.defineProperty;
@@ -1,4 +1,4 @@
1
- /*! peach v0.1.2229 | (c) 2026 Tamagui LLC | Proprietary; see LICENSE */
1
+ /*! peach v0.1.2231 | (c) 2026 Tamagui LLC | Proprietary; see LICENSE */
2
2
 
3
3
  // src/is-record.ts
4
4
  function isRecord(value) {
@@ -1,4 +1,4 @@
1
- /*! peach v0.1.2229 | (c) 2026 Tamagui LLC | Proprietary; see LICENSE */
1
+ /*! peach v0.1.2231 | (c) 2026 Tamagui LLC | Proprietary; see LICENSE */
2
2
  let __sootsim_import_meta_url = '', __sootsim_import_meta_dirname = '', __sootsim_import_meta_filename = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; __sootsim_import_meta_dirname = __dirname; __sootsim_import_meta_filename = __filename; } catch {}
3
3
  "use strict";
4
4
  var __create = Object.create;
@@ -1,4 +1,4 @@
1
- /*! peach v0.1.2229 | (c) 2026 Tamagui LLC | Proprietary; see LICENSE */
1
+ /*! peach v0.1.2231 | (c) 2026 Tamagui LLC | Proprietary; see LICENSE */
2
2
  let __sootsim_import_meta_url = '', __sootsim_import_meta_dirname = '', __sootsim_import_meta_filename = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; __sootsim_import_meta_dirname = __dirname; __sootsim_import_meta_filename = __filename; } catch {}
3
3
  "use strict";
4
4
  var __defProp = Object.defineProperty;
@@ -1,4 +1,4 @@
1
- /*! peach v0.1.2229 | (c) 2026 Tamagui LLC | Proprietary; see LICENSE */
1
+ /*! peach v0.1.2231 | (c) 2026 Tamagui LLC | Proprietary; see LICENSE */
2
2
  let __sootsim_import_meta_url = '', __sootsim_import_meta_dirname = '', __sootsim_import_meta_filename = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; __sootsim_import_meta_dirname = __dirname; __sootsim_import_meta_filename = __filename; } catch {}
3
3
  "use strict";
4
4
  var __create = Object.create;
package/dist-lib/vite.cjs CHANGED
@@ -1,4 +1,4 @@
1
- /*! peach v0.1.2229 | (c) 2026 Tamagui LLC | Proprietary; see LICENSE */
1
+ /*! peach v0.1.2231 | (c) 2026 Tamagui LLC | Proprietary; see LICENSE */
2
2
  let __sootsim_import_meta_url = '', __sootsim_import_meta_dirname = '', __sootsim_import_meta_filename = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; __sootsim_import_meta_dirname = __dirname; __sootsim_import_meta_filename = __filename; } catch {}
3
3
  "use strict";
4
4
  var __create = Object.create;
@@ -6355,6 +6355,11 @@ var compilerArchives = {
6355
6355
  }
6356
6356
  }
6357
6357
  };
6358
+ var SWIFT_PRIVATE_DISTRIBUTION_ENV = "PEACH_SWIFT_PRIVATE_DISTRIBUTION";
6359
+ function privateSwiftDistributionRoot() {
6360
+ const root = process.env[SWIFT_PRIVATE_DISTRIBUTION_ENV]?.trim();
6361
+ return root ? import_node_path10.default.resolve(root) : null;
6362
+ }
6358
6363
 
6359
6364
  // src/swift-objc-runtime.ts
6360
6365
  init_define_SWIFT_COVERAGE_SOURCE_DIGESTS();
@@ -12664,6 +12669,7 @@ function peachPlugin(options = {}) {
12664
12669
  let swiftPackages;
12665
12670
  let swiftModuleRoot;
12666
12671
  const moduleRootFor = () => {
12672
+ if (privateSwiftDistributionRoot()) return void 0;
12667
12673
  if (swiftModuleRoot === void 0) {
12668
12674
  const moduleRoot = import_path4.default.resolve(
12669
12675
  import_path4.default.dirname((0, import_node_url2.fileURLToPath)(__sootsim_import_meta_url)),
@@ -1,4 +1,4 @@
1
- /*! peach v0.1.2229 | (c) 2026 Tamagui LLC | Proprietary; see LICENSE */
1
+ /*! peach v0.1.2231 | (c) 2026 Tamagui LLC | Proprietary; see LICENSE */
2
2
  let __sootsim_import_meta_url = '', __sootsim_import_meta_dirname = '', __sootsim_import_meta_filename = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; __sootsim_import_meta_dirname = __dirname; __sootsim_import_meta_filename = __filename; } catch {}
3
3
  "use strict";
4
4
  var __defProp = Object.defineProperty;
@@ -1,4 +1,4 @@
1
- /*! peach v0.1.2229 | (c) 2026 Tamagui LLC | Proprietary; see LICENSE */
1
+ /*! peach v0.1.2231 | (c) 2026 Tamagui LLC | Proprietary; see LICENSE */
2
2
 
3
3
  // src/worklet-executable.ts
4
4
  import { parse } from "acorn";
package/install.sh CHANGED
@@ -38,6 +38,16 @@ command_exists() {
38
38
  command -v "$1" >/dev/null 2>&1
39
39
  }
40
40
 
41
+ # curl's --retry skips a connection reset mid-transfer, so retry the request.
42
+ fetch() {
43
+ attempt=1
44
+ until curl -fsSL "$@"; do
45
+ [ "$attempt" -ge 3 ] && return 1
46
+ attempt=$((attempt + 1))
47
+ sleep 2
48
+ done
49
+ }
50
+
41
51
  command_exists curl || fail "curl is required to install peach"
42
52
 
43
53
  case "$(uname -s)" in
@@ -92,8 +102,8 @@ say " version: $PEACH_VERSION"
92
102
  say " command: $CLI"
93
103
  say ""
94
104
  say "Downloading the standalone peach executable..."
95
- curl -fsSL "$ARTIFACT_URL" -o "$TMP_BIN" || fail "could not download peach"
96
- curl -fsSL "$ARTIFACT_URL.sha256" -o "$TMP_SHA" ||
105
+ fetch "$ARTIFACT_URL" -o "$TMP_BIN" || fail "could not download peach"
106
+ fetch "$ARTIFACT_URL.sha256" -o "$TMP_SHA" ||
97
107
  fail "could not download the peach checksum"
98
108
 
99
109
  EXPECTED_SHA="$(tr -d '[:space:]' <"$TMP_SHA")"
package/kotlin/sdk.tar.gz CHANGED
Binary file
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "peachsim",
3
- "version": "0.1.2229",
3
+ "version": "0.1.2231",
4
4
  "description": "Vite and Metro plugins, testing drivers, and SDK exports for peach.",
5
5
  "author": "Tamagui LLC",
6
6
  "license": "SEE LICENSE IN LICENSE",
@@ -48,6 +48,7 @@ import {
48
48
  parseSwiftHostDiscovery,
49
49
  } from '../src/swiftDiscoveryContract'
50
50
  import { loadOptionalDemoApps, optionalDemoAppsSync } from './optional-demo-registry.ts'
51
+ import type { ConfiguredOneWidget } from '../src/oneWidgetContract'
51
52
  import type { DiscoveredServer } from '../src/serverDiscoveryContract'
52
53
 
53
54
  export type { DiscoveredServer } from '../src/serverDiscoveryContract'
@@ -1187,6 +1188,38 @@ const knownNonPatched = new Set<number>()
1187
1188
  // same invalidation rules as knownNonPatched: cleared on port
1188
1189
  // disappearance, owning-pid change, and __resetScannerCache.
1189
1190
  const knownOne = new Set<number>()
1191
+ const oneNativeApps = new Map<number, { root: string; bundleId: string }>()
1192
+
1193
+ function oneNativeWidgetFromScan(
1194
+ scan: unknown,
1195
+ result: DiscoveredServer,
1196
+ identity: { root: string; bundleId: string },
1197
+ ): ConfiguredOneWidget | null {
1198
+ if (!Array.isArray(scan)) return null
1199
+ for (const entry of scan) {
1200
+ if (!entry || typeof entry !== 'object' || entry.port !== result.port) continue
1201
+ if (typeof entry.bundleUrl !== 'string') continue
1202
+ let advertised: URL
1203
+ try {
1204
+ advertised = new URL(entry.bundleUrl)
1205
+ } catch {
1206
+ continue
1207
+ }
1208
+ if (!isLoopbackHost(advertised.hostname) || advertised.port !== String(result.port))
1209
+ continue
1210
+ const widget = configuredWidgetFromScan(scan, advertised.href)
1211
+ if (
1212
+ widget?.projectRoot === identity.root &&
1213
+ widget.metadata.bundleId === identity.bundleId
1214
+ )
1215
+ return {
1216
+ ...widget,
1217
+ bundleUrl: result.bundleUrl,
1218
+ packageUrl: new URL('/__peach/swift-package/OneWidgets', result.bundleUrl).href,
1219
+ }
1220
+ }
1221
+ return null
1222
+ }
1190
1223
 
1191
1224
  // fire signature probes in waves and pick the best match by precedence:
1192
1225
  // 1. expo manifest (JSON manifest at /)
@@ -1260,6 +1293,25 @@ export async function probePort(
1260
1293
  const manifestParsed = manifestRes ? safeParseManifest(manifestRes.body) : null
1261
1294
  const { launchUrl: manifestLaunchUrl, client: manifestClient } =
1262
1295
  readExpoManifestFields(manifestParsed)
1296
+ const metadata = manifestParsed?.metadata
1297
+ const extra = manifestParsed?.extra
1298
+ const expoGo = extra && typeof extra === 'object' ? Reflect.get(extra, 'expoGo') : null
1299
+ const developer =
1300
+ expoGo && typeof expoGo === 'object' ? Reflect.get(expoGo, 'developer') : null
1301
+ const projectRoot =
1302
+ developer && typeof developer === 'object'
1303
+ ? Reflect.get(developer, 'projectRoot')
1304
+ : null
1305
+ const bundleId = manifestClient.ios?.bundleIdentifier
1306
+ if (
1307
+ metadata &&
1308
+ typeof metadata === 'object' &&
1309
+ Reflect.get(metadata, 'oneNativeApp') === true &&
1310
+ typeof projectRoot === 'string' &&
1311
+ typeof bundleId === 'string'
1312
+ )
1313
+ oneNativeApps.set(port, { root: projectRoot, bundleId })
1314
+ else if (manifestRes) oneNativeApps.delete(port)
1263
1315
  // `manifestRes === null` means the probe got NO answer — it timed out or the
1264
1316
  // connection failed. that is not the same fact as a server that answered and
1265
1317
  // turned out to have no manifest, and only the second one licenses the
@@ -1636,6 +1688,7 @@ export function __resetScannerCache() {
1636
1688
  portCache.clear()
1637
1689
  knownNonPatched.clear()
1638
1690
  knownOne.clear()
1691
+ oneNativeApps.clear()
1639
1692
  enrichmentCache.clear()
1640
1693
  enrichmentInFlight.clear()
1641
1694
  portCacheInvalidatedAt.clear()
@@ -1692,6 +1745,9 @@ export async function scanDevServers(
1692
1745
  for (const p of [...knownOne]) {
1693
1746
  if (!currentPorts.has(p)) knownOne.delete(p)
1694
1747
  }
1748
+ for (const p of [...oneNativeApps.keys()]) {
1749
+ if (!currentPorts.has(p)) oneNativeApps.delete(p)
1750
+ }
1695
1751
  for (const p of [...enrichmentCache.keys()]) {
1696
1752
  if (!currentPorts.has(p)) enrichmentCache.delete(p)
1697
1753
  }
@@ -1726,6 +1782,7 @@ export async function scanDevServers(
1726
1782
  if (cached && cached.pid !== pid) {
1727
1783
  knownNonPatched.delete(port)
1728
1784
  knownOne.delete(port)
1785
+ oneNativeApps.delete(port)
1729
1786
  // a restarted process may be a different app — drop its captured name/icon.
1730
1787
  enrichmentCache.delete(port)
1731
1788
  localIconPathCache.delete(port)
@@ -1765,7 +1822,8 @@ export async function scanDevServers(
1765
1822
  // "no widget".
1766
1823
  await Promise.all(
1767
1824
  results.map(async (result) => {
1768
- if (result.framework !== 'one' && result.framework !== 'vxrn') {
1825
+ const nativeIdentity = oneNativeApps.get(result.port)
1826
+ if (result.framework !== 'one' && result.framework !== 'vxrn' && !nativeIdentity) {
1769
1827
  result.widget = null
1770
1828
  return
1771
1829
  }
@@ -1780,10 +1838,13 @@ export async function scanDevServers(
1780
1838
  result.widget ??= null
1781
1839
  return
1782
1840
  }
1783
- result.widget =
1841
+ const scan =
1784
1842
  scanRes.statusCode === 200 && scanRes.contentType?.includes('json')
1785
- ? configuredWidgetFromScan(safeParseManifest(scanRes.body), result.bundleUrl)
1843
+ ? safeParseManifest(scanRes.body)
1786
1844
  : null
1845
+ result.widget = nativeIdentity
1846
+ ? oneNativeWidgetFromScan(scan, result, nativeIdentity)
1847
+ : configuredWidgetFromScan(scan, result.bundleUrl)
1787
1848
  }),
1788
1849
  )
1789
1850
 
@@ -1,3 +1,4 @@
1
+ import { Buffer } from 'node:buffer'
1
2
  import pixelmatch from 'pixelmatch'
2
3
  import {
3
4
  CONFORMANCE_FLAT_SHADE_FLATNESS,
@@ -123,13 +124,17 @@ export function compareConformancePixels(options: {
123
124
 
124
125
  // identical frames need no shade or neighborhood search, but still use
125
126
  // the same region and rounded-display exclusions for their pixel count.
126
- let identical = true
127
- for (let index = 0; index < options.reference.length; index++) {
128
- if (options.reference[index] !== options.result[index]) {
129
- identical = false
130
- break
131
- }
132
- }
127
+ const identical = Buffer.from(
128
+ options.reference.buffer,
129
+ options.reference.byteOffset,
130
+ options.reference.byteLength,
131
+ ).equals(
132
+ Buffer.from(
133
+ options.result.buffer,
134
+ options.result.byteOffset,
135
+ options.result.byteLength,
136
+ ),
137
+ )
133
138
  if (identical) {
134
139
  options.diff?.fill(0)
135
140
  const columns = Math.ceil(options.width)
@@ -61,14 +61,24 @@ export async function withTypeScriptSourceParser<T>(
61
61
  if (!project) throw new Error('native TypeScript parser found no program')
62
62
  // the program retains every input for resolution; transfer only the ASTs
63
63
  // the caller analyzes across the native compiler's RPC boundary.
64
- for (const path of requestedSources) {
65
- const virtualPath = sourcePaths.get(path)
66
- if (!virtualPath) throw new Error(`requested parser source is missing: ${path}`)
67
- const sourceFile = await project.program.getSourceFile(virtualPath)
68
- if (!sourceFile)
69
- throw new Error(`native TypeScript parser did not return ${path}`)
70
- parsed.set(path, sourceFile)
71
- projects.set(path, project)
64
+ const requestedPaths = Array.from(requestedSources)
65
+ for (let start = 0; start < requestedPaths.length; start += 64) {
66
+ const sources = await Promise.allSettled(
67
+ requestedPaths.slice(start, start + 64).map(async (path) => {
68
+ const virtualPath = sourcePaths.get(path)
69
+ if (!virtualPath)
70
+ throw new Error(`requested parser source is missing: ${path}`)
71
+ const sourceFile = await project.program.getSourceFile(virtualPath)
72
+ if (!sourceFile)
73
+ throw new Error(`native TypeScript parser did not return ${path}`)
74
+ return { path, sourceFile }
75
+ }),
76
+ )
77
+ for (const source of sources) {
78
+ if (source.status === 'rejected') throw source.reason
79
+ parsed.set(source.value.path, source.value.sourceFile)
80
+ projects.set(source.value.path, project)
81
+ }
72
82
  }
73
83
  return await analyze(parsed, projects)
74
84
  } finally {
@@ -46,6 +46,7 @@ import {
46
46
  } from './runtime-assets'
47
47
  import { ensureRuntimePackFor } from './runtime-packs'
48
48
  import { SWIFT_HMR_PATH, SWIFT_PACKAGE_PATH } from './swift-submit'
49
+ import { privateSwiftDistributionRoot } from './swift-toolchain'
49
50
  import { swiftViteLifetime } from './swift-vite-lifetime'
50
51
  import type { OneWidgetPackage } from './oneWidgetContract'
51
52
  import type { PeachPluginOptions } from './vite'
@@ -235,6 +236,7 @@ export function peachPlugin(options: PeachPluginOptions = {}): Plugin {
235
236
  // npm install has none (null), and its packages compile on Contrast.
236
237
  let swiftModuleRoot: string | null | undefined
237
238
  const moduleRootFor = (): string | undefined => {
239
+ if (privateSwiftDistributionRoot()) return undefined
238
240
  if (swiftModuleRoot === undefined) {
239
241
  // src/ or dist-lib/ → .. is peachsim; the module sits beside it
240
242
  const moduleRoot = path.resolve(
@@ -2542,23 +2542,23 @@ function externalAppResolvePlugin(
2542
2542
  // convert require() calls and handle JSX in .js files from external app sources
2543
2543
  function externalAppTransformPlugin(isAppSource: (p: string) => boolean): Plugin {
2544
2544
  const defines: Record<string, string> = {}
2545
+ let isBuild = false
2545
2546
  return {
2546
2547
  name: 'sootsim-external-app-transform',
2547
2548
  enforce: 'pre',
2548
2549
  configResolved(config) {
2550
+ isBuild = config.command === 'build'
2549
2551
  for (const [name, value] of Object.entries(config.define ?? {}))
2550
2552
  defines[name] = typeof value === 'string' ? value : JSON.stringify(value)
2551
2553
  },
2552
2554
  transform: {
2553
2555
  filter: { code: /require\(|</ },
2554
2556
  async handler(code, id) {
2555
- // expo's winter polyfills use Metro-local requires in lazy getters.
2556
- // their module imports must never reach the host's native-package registry.
2557
- if (!isAppSource(id) && !/\/node_modules\/expo\/(?:src|build)\/winter\//.test(id))
2558
- return null
2557
+ const isExpoWinter = /\/node_modules\/expo\/(?:src|build)\/winter\//.test(id)
2558
+ if (!isAppSource(id) && !isExpoWinter) return null
2559
2559
 
2560
- // prune upstream's disabled native branches before lifting module imports.
2561
- let result = /\/node_modules\/expo\/(?:src|build)\/winter\//.test(id)
2560
+ // prune disabled native branches before resolving their requires.
2561
+ let result = isExpoWinter
2562
2562
  ? minifySync(
2563
2563
  stripViteQuery(id),
2564
2564
  transformSync(stripViteQuery(id), code, { define: defines }).code,
@@ -2567,9 +2567,10 @@ function externalAppTransformPlugin(isAppSource: (p: string) => boolean): Plugin
2567
2567
  : code
2568
2568
  let imports = ''
2569
2569
  let importCounter = 0
2570
- let hasChanges = false
2570
+ let hasChanges = isExpoWinter
2571
2571
 
2572
- if (code.includes('require(')) {
2572
+ // rolldown keeps winter's lazy requires at their call sites in builds.
2573
+ if (code.includes('require(') && !(isBuild && isExpoWinter)) {
2573
2574
  const replacements: Array<{ start: number; end: number; varName: string }> = []
2574
2575
  const seenPaths = new Map<string, string>()
2575
2576
  const pending: unknown[] = [parseSync(stripViteQuery(id), result).program]