peachsim 0.1.1635 → 0.1.1641

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 (142) hide show
  1. package/README.md +10 -1
  2. package/cli/app-config.ts +14 -5
  3. package/cli/app-stubs.ts +96 -22
  4. package/cli/bridge-flow-runner.ts +2 -2
  5. package/cli/cloud-client.ts +60 -40
  6. package/cli/cloud-session.ts +16 -0
  7. package/cli/commands/assert.ts +17 -4
  8. package/cli/commands/box.ts +33 -19
  9. package/cli/commands/doctor.ts +37 -20
  10. package/cli/commands/flow.ts +1 -1
  11. package/cli/commands/inspect/actions.ts +3 -2
  12. package/cli/commands/inspect/core.ts +0 -8
  13. package/cli/commands/inspect/shared.ts +9 -4
  14. package/cli/commands/inspect.ts +65 -61
  15. package/cli/commands/platform.ts +2 -1
  16. package/cli/commands/preview.ts +1 -1
  17. package/cli/commands/record.ts +154 -68
  18. package/cli/commands/swift.ts +18 -4
  19. package/cli/commands/three-mode.ts +4 -38
  20. package/cli/commands/upload.ts +55 -49
  21. package/cli/drivers/playwright-sim-host.ts +65 -42
  22. package/cli/flow-live-status.ts +0 -2
  23. package/cli/main.ts +2 -2
  24. package/cli/outbound-endpoints.ts +7 -5
  25. package/cli/pause-aware-timeout.ts +4 -0
  26. package/cli/ws-bridge.ts +19 -16
  27. package/detox/attempt-events.cjs +99 -6
  28. package/detox/attempt-events.d.cts +7 -0
  29. package/detox/expectations.ts +7 -3
  30. package/detox/index.ts +259 -139
  31. package/detox/jest-environment.cjs +5 -1
  32. package/detox/motion-change.cjs +170 -21
  33. package/detox/motion-change.d.cts +32 -0
  34. package/detox/navigation-lifecycle.ts +35 -3
  35. package/dist-lib/agent-daemon-client.cjs +1 -1
  36. package/dist-lib/agent-events.cjs +1 -1
  37. package/dist-lib/attached-projects.cjs +1 -1
  38. package/dist-lib/auth/shared-session.cjs +1 -1
  39. package/dist-lib/backend-origin.cjs +17 -7
  40. package/dist-lib/beta.cjs +1 -1
  41. package/dist-lib/beta.mjs +1 -1
  42. package/dist-lib/bridge-constants.cjs +1 -1
  43. package/dist-lib/bridge-contract-input.cjs +1 -1
  44. package/dist-lib/bridge-contract-input.mjs +1 -1
  45. package/dist-lib/bridge-contract.cjs +1 -1
  46. package/dist-lib/bridge-contract.mjs +1 -1
  47. package/dist-lib/bundle-channel.cjs +5014 -2268
  48. package/dist-lib/capture-contract.cjs +1 -1
  49. package/dist-lib/capture-contract.mjs +1 -1
  50. package/dist-lib/cloud-contract.cjs +1 -1
  51. package/dist-lib/cloud-contract.mjs +1 -1
  52. package/dist-lib/cloud-test-args.cjs +1 -1
  53. package/dist-lib/cloud-test-args.mjs +1 -1
  54. package/dist-lib/cloud.cjs +1 -1
  55. package/dist-lib/cloud.mjs +1 -1
  56. package/dist-lib/config.cjs +1 -1
  57. package/dist-lib/config.mjs +1 -1
  58. package/dist-lib/detox/index.cjs +1036 -166
  59. package/dist-lib/detox/jest-environment.cjs +5 -1
  60. package/dist-lib/dev-bundle-resolution.cjs +1 -1
  61. package/dist-lib/expo-swift-bundle.cjs +4613 -1963
  62. package/dist-lib/expo-swift-metadata.cjs +9 -7
  63. package/dist-lib/expo-swift-metadata.mjs +9 -7
  64. package/dist-lib/home-paths.cjs +1 -1
  65. package/dist-lib/host/bridge-host.cjs +58072 -16400
  66. package/dist-lib/host/fetch-proxy-handler.cjs +1 -1
  67. package/dist-lib/host/fetch-proxy-overrides.cjs +1 -1
  68. package/dist-lib/host/fetch-proxy-overrides.mjs +1 -1
  69. package/dist-lib/host/replacement-module-handler.cjs +1 -1
  70. package/dist-lib/host/websocket-proxy.cjs +1 -1
  71. package/dist-lib/index.cjs +2790 -143
  72. package/dist-lib/jump-to-source-babel.cjs +1 -1
  73. package/dist-lib/jump-to-source-native.cjs +1 -1
  74. package/dist-lib/kotlin-host.cjs +1 -1
  75. package/dist-lib/menu.cjs +1 -1
  76. package/dist-lib/menu.mjs +1 -1
  77. package/dist-lib/metro-fingerprint-registry.cjs +1 -1
  78. package/dist-lib/metro-fingerprint-registry.mjs +1 -1
  79. package/dist-lib/metro-production-bundle.cjs +1 -1
  80. package/dist-lib/metro-production-bundle.mjs +1 -1
  81. package/dist-lib/metro.cjs +2579 -95
  82. package/dist-lib/native-app-identity-project.cjs +243 -53
  83. package/dist-lib/native-app-identity-project.mjs +243 -53
  84. package/dist-lib/native-app-identity.cjs +29 -30
  85. package/dist-lib/native-app-identity.mjs +29 -30
  86. package/dist-lib/native-firebase-metadata.cjs +1 -1
  87. package/dist-lib/native-firebase-metadata.mjs +1 -1
  88. package/dist-lib/plist.cjs +1 -1
  89. package/dist-lib/plist.mjs +1 -1
  90. package/dist-lib/profiles.cjs +1 -1
  91. package/dist-lib/public-brand.cjs +1 -1
  92. package/dist-lib/react-native-host-modules.cjs +2 -2
  93. package/dist-lib/react-native-host-modules.mjs +2 -2
  94. package/dist-lib/scripts/dev-server-scanner.cjs +8 -6
  95. package/dist-lib/sdk.cjs +4 -3
  96. package/dist-lib/sdk.mjs +4 -3
  97. package/dist-lib/skills.cjs +66475 -23097
  98. package/dist-lib/swift-compile.cjs +452 -260
  99. package/dist-lib/swift-compile.mjs +451 -252
  100. package/dist-lib/swift-package.cjs +1 -1
  101. package/dist-lib/swift-package.mjs +1 -1
  102. package/dist-lib/swift-submit.cjs +14 -7
  103. package/dist-lib/swift-submit.mjs +14 -7
  104. package/dist-lib/swift-toolchain.cjs +316 -41
  105. package/dist-lib/swift.cjs +1 -1
  106. package/dist-lib/vite-swift.cjs +8188 -5636
  107. package/dist-lib/vite.cjs +2857 -12
  108. package/dist-lib/worklet-executable.cjs +14 -2
  109. package/dist-lib/worklet-executable.mjs +14 -2
  110. package/package.json +1 -1
  111. package/src/backend-origin.ts +21 -6
  112. package/src/expo-swift-host.ts +5 -2
  113. package/src/expoKotlinContract.ts +4 -7
  114. package/src/expoSwiftContract.ts +4 -6
  115. package/src/host/staged-host-files.ts +9 -0
  116. package/src/native-app-identity-project.ts +1 -4
  117. package/src/native-app-identity.ts +1 -4
  118. package/src/nativeAppIconContract.ts +1 -4
  119. package/src/output-lock-stdio.ts +36 -0
  120. package/src/react-native-bridge-modules.ts +106 -78
  121. package/src/react-native-host-modules.ts +4 -1
  122. package/src/settings-bundle.ts +1 -4
  123. package/src/swift-compile.ts +224 -139
  124. package/src/swift-distribution.lock.json +23 -12
  125. package/src/swift-distribution.ts +103 -4
  126. package/src/swift-host.ts +95 -30
  127. package/src/swift-icu.ts +16 -10
  128. package/src/swift-objc-compile.ts +547 -0
  129. package/src/swift-objc-metadata.ts +204 -0
  130. package/src/swift-objc-sdk.ts +883 -19
  131. package/src/swift-objc-standin.ts +126 -14
  132. package/src/swift-package-manifest.ts +42 -1
  133. package/src/swift-packages.ts +35 -21
  134. package/src/swift-root-lock.ts +153 -0
  135. package/src/swift-standin-emit.ts +40 -7
  136. package/src/swift-standins.ts +404 -138
  137. package/src/swift-submit.ts +18 -7
  138. package/src/swift-toolchain.ts +378 -46
  139. package/src/swiftContract.ts +12 -0
  140. package/src/worker-system-chunks.ts +11 -12
  141. package/src/worklet-executable.ts +19 -1
  142. package/src/xcode-project.ts +280 -33
@@ -1,4 +1,4 @@
1
- /*! peach v0.1.1635 | (c) 2026 Tamagui LLC | Proprietary; see LICENSE */
1
+ /*! peach v0.1.1641 | (c) 2026 Tamagui LLC | Proprietary; see LICENSE */
2
2
  let __sootsim_import_meta_url = '', __sootsim_import_meta_dirname = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; __sootsim_import_meta_dirname = __dirname; } catch {}
3
3
  "use strict";
4
4
  var __defProp = Object.defineProperty;
@@ -241,6 +241,11 @@ function isFooterBlockLine(source, line, end) {
241
241
  return line === end || source.startsWith("globalThis.", line) || source.startsWith("//", line);
242
242
  }
243
243
 
244
+ // src/is-record.ts
245
+ function isRecord(value) {
246
+ return typeof value === "object" && value !== null && !Array.isArray(value);
247
+ }
248
+
244
249
  // src/assetCatalogContract.ts
245
250
  function isSwiftImageVariants(value) {
246
251
  return Array.isArray(value) && value.length > 0 && value.every(
@@ -249,9 +254,6 @@ function isSwiftImageVariants(value) {
249
254
  }
250
255
 
251
256
  // src/nativeAppIconContract.ts
252
- function isRecord(value) {
253
- return typeof value === "object" && value !== null && !Array.isArray(value);
254
- }
255
257
  function isNativeAppIconArtwork(value) {
256
258
  return isRecord(value) && (value.primary === void 0 || isSwiftImageVariants(value.primary)) && isRecord(value.alternates) && Object.values(value.alternates).every(isSwiftImageVariants);
257
259
  }
@@ -525,35 +527,32 @@ function visitXcodeTargetMembers(objects, targetId, resolvePath, filesUnder, joi
525
527
  var NATIVE_APP_IDENTITY_PREFIX = "globalThis.__sootsimNativeAppIdentity=";
526
528
  var METRO_MODULE_PATHS_PREFIX = "globalThis.__sootsimModulePaths=";
527
529
  var NATIVE_APP_IDENTITY_HEADER = "Peach-Native-App-Identity";
528
- function isRecord2(value) {
529
- return typeof value === "object" && value !== null && !Array.isArray(value);
530
- }
531
530
  function nonEmptyString(value) {
532
531
  return typeof value === "string" && value.length > 0 ? value : null;
533
532
  }
534
533
  function isNativeAppIdentity(value) {
535
- if (!isRecord2(value)) return false;
534
+ if (!isRecord(value)) return false;
536
535
  for (const key of ["statusBarHidden", "viewControllerBasedStatusBarAppearance"]) {
537
536
  if (value[key] !== void 0 && typeof value[key] !== "boolean") return false;
538
537
  }
539
538
  const oneUpdates = value.oneUpdates;
540
- if (oneUpdates !== void 0 && (!isRecord2(oneUpdates) || typeof oneUpdates.enabled !== "boolean" || oneUpdates.url !== null && typeof oneUpdates.url !== "string" || oneUpdates.runtimeVersion !== null && typeof oneUpdates.runtimeVersion !== "string" || oneUpdates.embeddedManifestJson !== null && typeof oneUpdates.embeddedManifestJson !== "string" || oneUpdates.enabled && (typeof oneUpdates.url !== "string" || oneUpdates.url.length === 0 || typeof oneUpdates.runtimeVersion !== "string" || oneUpdates.runtimeVersion.length === 0))) {
539
+ if (oneUpdates !== void 0 && (!isRecord(oneUpdates) || typeof oneUpdates.enabled !== "boolean" || oneUpdates.url !== null && typeof oneUpdates.url !== "string" || oneUpdates.runtimeVersion !== null && typeof oneUpdates.runtimeVersion !== "string" || oneUpdates.embeddedManifestJson !== null && typeof oneUpdates.embeddedManifestJson !== "string" || oneUpdates.enabled && (typeof oneUpdates.url !== "string" || oneUpdates.url.length === 0 || typeof oneUpdates.runtimeVersion !== "string" || oneUpdates.runtimeVersion.length === 0))) {
541
540
  return false;
542
541
  }
543
542
  if (value.dtPlatformVersion !== void 0 && typeof value.dtPlatformVersion !== "string")
544
543
  return false;
545
544
  if (value.androidManifestPermissions !== void 0 && (!Array.isArray(value.androidManifestPermissions) || !value.androidManifestPermissions.every(
546
- (permission) => isRecord2(permission) && typeof permission.name === "string" && permission.name.length > 0 && Number.isInteger(permission.minSdkVersion) && typeof permission.minSdkVersion === "number" && permission.minSdkVersion > 0 && (permission.maxSdkVersion === void 0 || typeof permission.maxSdkVersion === "number" && Number.isInteger(permission.maxSdkVersion) && permission.maxSdkVersion >= 0)
545
+ (permission) => isRecord(permission) && typeof permission.name === "string" && permission.name.length > 0 && Number.isInteger(permission.minSdkVersion) && typeof permission.minSdkVersion === "number" && permission.minSdkVersion > 0 && (permission.maxSdkVersion === void 0 || typeof permission.maxSdkVersion === "number" && Number.isInteger(permission.maxSdkVersion) && permission.maxSdkVersion >= 0)
547
546
  )))
548
547
  return false;
549
- if (value.googleSignIn !== void 0 && !isRecord2(value.googleSignIn)) return false;
548
+ if (value.googleSignIn !== void 0 && !isRecord(value.googleSignIn)) return false;
550
549
  const descriptions = value.permissionUsageDescriptions;
551
- if (value.reanimatedStaticFeatureFlags !== void 0 && (!isRecord2(value.reanimatedStaticFeatureFlags) || !Object.values(value.reanimatedStaticFeatureFlags).every(
550
+ if (value.reanimatedStaticFeatureFlags !== void 0 && (!isRecord(value.reanimatedStaticFeatureFlags) || !Object.values(value.reanimatedStaticFeatureFlags).every(
552
551
  (flag) => typeof flag === "boolean"
553
552
  )))
554
553
  return false;
555
- if (descriptions !== void 0 && !isRecord2(descriptions)) return false;
556
- if (value.infoPlistStrings !== void 0 && (!isRecord2(value.infoPlistStrings) || !Object.values(value.infoPlistStrings).every((entry) => typeof entry === "string")))
554
+ if (descriptions !== void 0 && !isRecord(descriptions)) return false;
555
+ if (value.infoPlistStrings !== void 0 && (!isRecord(value.infoPlistStrings) || !Object.values(value.infoPlistStrings).every((entry) => typeof entry === "string")))
557
556
  return false;
558
557
  if (value.urlQuerySchemes !== void 0 && !Array.isArray(value.urlQuerySchemes))
559
558
  return false;
@@ -673,7 +672,7 @@ function equalIdentityValues(left, right) {
673
672
  if (Array.isArray(left) && Array.isArray(right)) {
674
673
  return left.length === right.length && left.every((value, index) => equalIdentityValues(value, right[index]));
675
674
  }
676
- if (!isRecord2(left) || !isRecord2(right)) return false;
675
+ if (!isRecord(left) || !isRecord(right)) return false;
677
676
  const keys = Object.keys(left);
678
677
  return keys.length === Object.keys(right).length && keys.every(
679
678
  (key) => Object.hasOwn(right, key) && equalIdentityValues(left[key], right[key])
@@ -763,12 +762,12 @@ function insertNativeAppIdentityFooter(source, identity) {
763
762
  function readGoogleSignInConfiguration(plist, resources) {
764
763
  const clientIds = {};
765
764
  for (const [file, value] of Object.entries(resources)) {
766
- if (isRecord2(value) && typeof value.CLIENT_ID === "string")
765
+ if (isRecord(value) && typeof value.CLIENT_ID === "string")
767
766
  clientIds[file.split("/").pop()?.replace(/\.plist$/, "") ?? file] = value.CLIENT_ID;
768
767
  }
769
768
  const urlSchemes = [];
770
769
  for (const entry of Array.isArray(plist.CFBundleURLTypes) ? plist.CFBundleURLTypes : []) {
771
- if (!isRecord2(entry) || !Array.isArray(entry.CFBundleURLSchemes)) continue;
770
+ if (!isRecord(entry) || !Array.isArray(entry.CFBundleURLSchemes)) continue;
772
771
  for (const scheme of entry.CFBundleURLSchemes)
773
772
  if (typeof scheme === "string") urlSchemes.push(scheme);
774
773
  }
@@ -876,14 +875,14 @@ function nativeAppIdentityFromIos(files, parseInfoPlist, iosTarget, resourceUri)
876
875
  let objects = {};
877
876
  try {
878
877
  const parsed = parseOpenStepPlist(pbxproj);
879
- if (isRecord2(parsed)) {
880
- objects = isRecord2(parsed.objects) ? parsed.objects : parsed;
878
+ if (isRecord(parsed)) {
879
+ objects = isRecord(parsed.objects) ? parsed.objects : parsed;
881
880
  }
882
881
  } catch {
883
882
  }
884
883
  const targets = [];
885
884
  for (const [id, obj] of Object.entries(objects)) {
886
- if (isRecord2(obj) && obj.isa === "PBXNativeTarget" && typeof obj.name === "string") {
885
+ if (isRecord(obj) && obj.isa === "PBXNativeTarget" && typeof obj.name === "string") {
887
886
  targets.push({
888
887
  id,
889
888
  name: obj.name,
@@ -929,13 +928,13 @@ function nativeAppIdentityFromIos(files, parseInfoPlist, iosTarget, resourceUri)
929
928
  PRODUCT_NAME: targetName
930
929
  };
931
930
  for (const obj of Object.values(objects)) {
932
- if (isRecord2(obj) && obj.isa === "PBXProject" && typeof obj.buildConfigurationList === "string") {
931
+ if (isRecord(obj) && obj.isa === "PBXProject" && typeof obj.buildConfigurationList === "string") {
933
932
  const listObj = objects[obj.buildConfigurationList];
934
- if (isRecord2(listObj) && Array.isArray(listObj.buildConfigurations)) {
933
+ if (isRecord(listObj) && Array.isArray(listObj.buildConfigurations)) {
935
934
  for (const configId of listObj.buildConfigurations) {
936
935
  if (typeof configId === "string") {
937
936
  const configObj = objects[configId];
938
- if (isRecord2(configObj) && configObj.name === "Release" && isRecord2(configObj.buildSettings)) {
937
+ if (isRecord(configObj) && configObj.name === "Release" && isRecord(configObj.buildSettings)) {
939
938
  for (const [k, v] of Object.entries(configObj.buildSettings)) {
940
939
  if (typeof v === "string") settings[k] = v;
941
940
  }
@@ -947,11 +946,11 @@ function nativeAppIdentityFromIos(files, parseInfoPlist, iosTarget, resourceUri)
947
946
  }
948
947
  if (selectedTarget?.buildConfigurationList) {
949
948
  const listObj = objects[selectedTarget.buildConfigurationList];
950
- if (isRecord2(listObj) && Array.isArray(listObj.buildConfigurations)) {
949
+ if (isRecord(listObj) && Array.isArray(listObj.buildConfigurations)) {
951
950
  for (const configId of listObj.buildConfigurations) {
952
951
  if (typeof configId === "string") {
953
952
  const configObj = objects[configId];
954
- if (isRecord2(configObj) && configObj.name === "Release" && isRecord2(configObj.buildSettings)) {
953
+ if (isRecord(configObj) && configObj.name === "Release" && isRecord(configObj.buildSettings)) {
955
954
  for (const [k, v] of Object.entries(configObj.buildSettings)) {
956
955
  if (typeof v === "string") settings[k] = v;
957
956
  }
@@ -1002,7 +1001,7 @@ function nativeAppIdentityFromIos(files, parseInfoPlist, iosTarget, resourceUri)
1002
1001
  if (!bundleName) return null;
1003
1002
  const applicationName = identityFieldFrom(settings, plistString(plist, "CFBundleDisplayName"), void 0) ?? bundleName;
1004
1003
  const dictionary = parseInfoPlist(plist);
1005
- if (!isRecord2(dictionary)) throw new Error("native app Info.plist is not a dictionary");
1004
+ if (!isRecord(dictionary)) throw new Error("native app Info.plist is not a dictionary");
1006
1005
  const declaredDisplayName = dictionary.CFBundleDisplayName;
1007
1006
  const applicationDisplayName = typeof declaredDisplayName === "string" ? resolveBuildSetting(declaredDisplayName, settings) : void 0;
1008
1007
  if (applicationDisplayName === null)
@@ -1015,9 +1014,9 @@ function nativeAppIdentityFromIos(files, parseInfoPlist, iosTarget, resourceUri)
1015
1014
  if (dtPlatformVersion === null)
1016
1015
  throw new Error("native app Info.plist DTPlatformVersion is unresolved");
1017
1016
  const icons = dictionary.CFBundleIcons;
1018
- const alternates = isRecord2(icons) ? icons.CFBundleAlternateIcons : void 0;
1017
+ const alternates = isRecord(icons) ? icons.CFBundleAlternateIcons : void 0;
1019
1018
  const alternateIconNames = /* @__PURE__ */ new Set();
1020
- for (const name of isRecord2(alternates) ? Object.keys(alternates) : []) {
1019
+ for (const name of isRecord(alternates) ? Object.keys(alternates) : []) {
1021
1020
  const resolved = resolveBuildSetting(name, settings);
1022
1021
  if (resolved === null) throw new Error("native alternate icon name is unresolved");
1023
1022
  alternateIconNames.add(resolved);
@@ -1121,11 +1120,11 @@ function nativeAppIdentityFromIos(files, parseInfoPlist, iosTarget, resourceUri)
1121
1120
  return `${base.startsWith("/") ? "/" : ""}${segments.join("/")}`;
1122
1121
  };
1123
1122
  const project = Object.values(objects).find(
1124
- (object) => isRecord2(object) && object.isa === "PBXProject"
1123
+ (object) => isRecord(object) && object.isa === "PBXProject"
1125
1124
  );
1126
1125
  const projectDir = join(
1127
1126
  pbxprojPath.replace(/(?:^|\/)[^/]+\.xcodeproj\/project\.pbxproj$/, ""),
1128
- isRecord2(project) && typeof project.projectDirPath === "string" ? project.projectDirPath : ""
1127
+ isRecord(project) && typeof project.projectDirPath === "string" ? project.projectDirPath : ""
1129
1128
  );
1130
1129
  const paths = Object.keys(files);
1131
1130
  visitXcodeTargetMembers(
@@ -1,4 +1,4 @@
1
- /*! peach v0.1.1635 | (c) 2026 Tamagui LLC | Proprietary; see LICENSE */
1
+ /*! peach v0.1.1641 | (c) 2026 Tamagui LLC | Proprietary; see LICENSE */
2
2
 
3
3
  // src/android-string-value.ts
4
4
  function compileAndroidStringValue(text, where) {
@@ -199,6 +199,11 @@ function isFooterBlockLine(source, line, end) {
199
199
  return line === end || source.startsWith("globalThis.", line) || source.startsWith("//", line);
200
200
  }
201
201
 
202
+ // src/is-record.ts
203
+ function isRecord(value) {
204
+ return typeof value === "object" && value !== null && !Array.isArray(value);
205
+ }
206
+
202
207
  // src/assetCatalogContract.ts
203
208
  function isSwiftImageVariants(value) {
204
209
  return Array.isArray(value) && value.length > 0 && value.every(
@@ -207,9 +212,6 @@ function isSwiftImageVariants(value) {
207
212
  }
208
213
 
209
214
  // src/nativeAppIconContract.ts
210
- function isRecord(value) {
211
- return typeof value === "object" && value !== null && !Array.isArray(value);
212
- }
213
215
  function isNativeAppIconArtwork(value) {
214
216
  return isRecord(value) && (value.primary === void 0 || isSwiftImageVariants(value.primary)) && isRecord(value.alternates) && Object.values(value.alternates).every(isSwiftImageVariants);
215
217
  }
@@ -483,35 +485,32 @@ function visitXcodeTargetMembers(objects, targetId, resolvePath, filesUnder, joi
483
485
  var NATIVE_APP_IDENTITY_PREFIX = "globalThis.__sootsimNativeAppIdentity=";
484
486
  var METRO_MODULE_PATHS_PREFIX = "globalThis.__sootsimModulePaths=";
485
487
  var NATIVE_APP_IDENTITY_HEADER = "Peach-Native-App-Identity";
486
- function isRecord2(value) {
487
- return typeof value === "object" && value !== null && !Array.isArray(value);
488
- }
489
488
  function nonEmptyString(value) {
490
489
  return typeof value === "string" && value.length > 0 ? value : null;
491
490
  }
492
491
  function isNativeAppIdentity(value) {
493
- if (!isRecord2(value)) return false;
492
+ if (!isRecord(value)) return false;
494
493
  for (const key of ["statusBarHidden", "viewControllerBasedStatusBarAppearance"]) {
495
494
  if (value[key] !== void 0 && typeof value[key] !== "boolean") return false;
496
495
  }
497
496
  const oneUpdates = value.oneUpdates;
498
- if (oneUpdates !== void 0 && (!isRecord2(oneUpdates) || typeof oneUpdates.enabled !== "boolean" || oneUpdates.url !== null && typeof oneUpdates.url !== "string" || oneUpdates.runtimeVersion !== null && typeof oneUpdates.runtimeVersion !== "string" || oneUpdates.embeddedManifestJson !== null && typeof oneUpdates.embeddedManifestJson !== "string" || oneUpdates.enabled && (typeof oneUpdates.url !== "string" || oneUpdates.url.length === 0 || typeof oneUpdates.runtimeVersion !== "string" || oneUpdates.runtimeVersion.length === 0))) {
497
+ if (oneUpdates !== void 0 && (!isRecord(oneUpdates) || typeof oneUpdates.enabled !== "boolean" || oneUpdates.url !== null && typeof oneUpdates.url !== "string" || oneUpdates.runtimeVersion !== null && typeof oneUpdates.runtimeVersion !== "string" || oneUpdates.embeddedManifestJson !== null && typeof oneUpdates.embeddedManifestJson !== "string" || oneUpdates.enabled && (typeof oneUpdates.url !== "string" || oneUpdates.url.length === 0 || typeof oneUpdates.runtimeVersion !== "string" || oneUpdates.runtimeVersion.length === 0))) {
499
498
  return false;
500
499
  }
501
500
  if (value.dtPlatformVersion !== void 0 && typeof value.dtPlatformVersion !== "string")
502
501
  return false;
503
502
  if (value.androidManifestPermissions !== void 0 && (!Array.isArray(value.androidManifestPermissions) || !value.androidManifestPermissions.every(
504
- (permission) => isRecord2(permission) && typeof permission.name === "string" && permission.name.length > 0 && Number.isInteger(permission.minSdkVersion) && typeof permission.minSdkVersion === "number" && permission.minSdkVersion > 0 && (permission.maxSdkVersion === void 0 || typeof permission.maxSdkVersion === "number" && Number.isInteger(permission.maxSdkVersion) && permission.maxSdkVersion >= 0)
503
+ (permission) => isRecord(permission) && typeof permission.name === "string" && permission.name.length > 0 && Number.isInteger(permission.minSdkVersion) && typeof permission.minSdkVersion === "number" && permission.minSdkVersion > 0 && (permission.maxSdkVersion === void 0 || typeof permission.maxSdkVersion === "number" && Number.isInteger(permission.maxSdkVersion) && permission.maxSdkVersion >= 0)
505
504
  )))
506
505
  return false;
507
- if (value.googleSignIn !== void 0 && !isRecord2(value.googleSignIn)) return false;
506
+ if (value.googleSignIn !== void 0 && !isRecord(value.googleSignIn)) return false;
508
507
  const descriptions = value.permissionUsageDescriptions;
509
- if (value.reanimatedStaticFeatureFlags !== void 0 && (!isRecord2(value.reanimatedStaticFeatureFlags) || !Object.values(value.reanimatedStaticFeatureFlags).every(
508
+ if (value.reanimatedStaticFeatureFlags !== void 0 && (!isRecord(value.reanimatedStaticFeatureFlags) || !Object.values(value.reanimatedStaticFeatureFlags).every(
510
509
  (flag) => typeof flag === "boolean"
511
510
  )))
512
511
  return false;
513
- if (descriptions !== void 0 && !isRecord2(descriptions)) return false;
514
- if (value.infoPlistStrings !== void 0 && (!isRecord2(value.infoPlistStrings) || !Object.values(value.infoPlistStrings).every((entry) => typeof entry === "string")))
512
+ if (descriptions !== void 0 && !isRecord(descriptions)) return false;
513
+ if (value.infoPlistStrings !== void 0 && (!isRecord(value.infoPlistStrings) || !Object.values(value.infoPlistStrings).every((entry) => typeof entry === "string")))
515
514
  return false;
516
515
  if (value.urlQuerySchemes !== void 0 && !Array.isArray(value.urlQuerySchemes))
517
516
  return false;
@@ -631,7 +630,7 @@ function equalIdentityValues(left, right) {
631
630
  if (Array.isArray(left) && Array.isArray(right)) {
632
631
  return left.length === right.length && left.every((value, index) => equalIdentityValues(value, right[index]));
633
632
  }
634
- if (!isRecord2(left) || !isRecord2(right)) return false;
633
+ if (!isRecord(left) || !isRecord(right)) return false;
635
634
  const keys = Object.keys(left);
636
635
  return keys.length === Object.keys(right).length && keys.every(
637
636
  (key) => Object.hasOwn(right, key) && equalIdentityValues(left[key], right[key])
@@ -721,12 +720,12 @@ function insertNativeAppIdentityFooter(source, identity) {
721
720
  function readGoogleSignInConfiguration(plist, resources) {
722
721
  const clientIds = {};
723
722
  for (const [file, value] of Object.entries(resources)) {
724
- if (isRecord2(value) && typeof value.CLIENT_ID === "string")
723
+ if (isRecord(value) && typeof value.CLIENT_ID === "string")
725
724
  clientIds[file.split("/").pop()?.replace(/\.plist$/, "") ?? file] = value.CLIENT_ID;
726
725
  }
727
726
  const urlSchemes = [];
728
727
  for (const entry of Array.isArray(plist.CFBundleURLTypes) ? plist.CFBundleURLTypes : []) {
729
- if (!isRecord2(entry) || !Array.isArray(entry.CFBundleURLSchemes)) continue;
728
+ if (!isRecord(entry) || !Array.isArray(entry.CFBundleURLSchemes)) continue;
730
729
  for (const scheme of entry.CFBundleURLSchemes)
731
730
  if (typeof scheme === "string") urlSchemes.push(scheme);
732
731
  }
@@ -834,14 +833,14 @@ function nativeAppIdentityFromIos(files, parseInfoPlist, iosTarget, resourceUri)
834
833
  let objects = {};
835
834
  try {
836
835
  const parsed = parseOpenStepPlist(pbxproj);
837
- if (isRecord2(parsed)) {
838
- objects = isRecord2(parsed.objects) ? parsed.objects : parsed;
836
+ if (isRecord(parsed)) {
837
+ objects = isRecord(parsed.objects) ? parsed.objects : parsed;
839
838
  }
840
839
  } catch {
841
840
  }
842
841
  const targets = [];
843
842
  for (const [id, obj] of Object.entries(objects)) {
844
- if (isRecord2(obj) && obj.isa === "PBXNativeTarget" && typeof obj.name === "string") {
843
+ if (isRecord(obj) && obj.isa === "PBXNativeTarget" && typeof obj.name === "string") {
845
844
  targets.push({
846
845
  id,
847
846
  name: obj.name,
@@ -887,13 +886,13 @@ function nativeAppIdentityFromIos(files, parseInfoPlist, iosTarget, resourceUri)
887
886
  PRODUCT_NAME: targetName
888
887
  };
889
888
  for (const obj of Object.values(objects)) {
890
- if (isRecord2(obj) && obj.isa === "PBXProject" && typeof obj.buildConfigurationList === "string") {
889
+ if (isRecord(obj) && obj.isa === "PBXProject" && typeof obj.buildConfigurationList === "string") {
891
890
  const listObj = objects[obj.buildConfigurationList];
892
- if (isRecord2(listObj) && Array.isArray(listObj.buildConfigurations)) {
891
+ if (isRecord(listObj) && Array.isArray(listObj.buildConfigurations)) {
893
892
  for (const configId of listObj.buildConfigurations) {
894
893
  if (typeof configId === "string") {
895
894
  const configObj = objects[configId];
896
- if (isRecord2(configObj) && configObj.name === "Release" && isRecord2(configObj.buildSettings)) {
895
+ if (isRecord(configObj) && configObj.name === "Release" && isRecord(configObj.buildSettings)) {
897
896
  for (const [k, v] of Object.entries(configObj.buildSettings)) {
898
897
  if (typeof v === "string") settings[k] = v;
899
898
  }
@@ -905,11 +904,11 @@ function nativeAppIdentityFromIos(files, parseInfoPlist, iosTarget, resourceUri)
905
904
  }
906
905
  if (selectedTarget?.buildConfigurationList) {
907
906
  const listObj = objects[selectedTarget.buildConfigurationList];
908
- if (isRecord2(listObj) && Array.isArray(listObj.buildConfigurations)) {
907
+ if (isRecord(listObj) && Array.isArray(listObj.buildConfigurations)) {
909
908
  for (const configId of listObj.buildConfigurations) {
910
909
  if (typeof configId === "string") {
911
910
  const configObj = objects[configId];
912
- if (isRecord2(configObj) && configObj.name === "Release" && isRecord2(configObj.buildSettings)) {
911
+ if (isRecord(configObj) && configObj.name === "Release" && isRecord(configObj.buildSettings)) {
913
912
  for (const [k, v] of Object.entries(configObj.buildSettings)) {
914
913
  if (typeof v === "string") settings[k] = v;
915
914
  }
@@ -960,7 +959,7 @@ function nativeAppIdentityFromIos(files, parseInfoPlist, iosTarget, resourceUri)
960
959
  if (!bundleName) return null;
961
960
  const applicationName = identityFieldFrom(settings, plistString(plist, "CFBundleDisplayName"), void 0) ?? bundleName;
962
961
  const dictionary = parseInfoPlist(plist);
963
- if (!isRecord2(dictionary)) throw new Error("native app Info.plist is not a dictionary");
962
+ if (!isRecord(dictionary)) throw new Error("native app Info.plist is not a dictionary");
964
963
  const declaredDisplayName = dictionary.CFBundleDisplayName;
965
964
  const applicationDisplayName = typeof declaredDisplayName === "string" ? resolveBuildSetting(declaredDisplayName, settings) : void 0;
966
965
  if (applicationDisplayName === null)
@@ -973,9 +972,9 @@ function nativeAppIdentityFromIos(files, parseInfoPlist, iosTarget, resourceUri)
973
972
  if (dtPlatformVersion === null)
974
973
  throw new Error("native app Info.plist DTPlatformVersion is unresolved");
975
974
  const icons = dictionary.CFBundleIcons;
976
- const alternates = isRecord2(icons) ? icons.CFBundleAlternateIcons : void 0;
975
+ const alternates = isRecord(icons) ? icons.CFBundleAlternateIcons : void 0;
977
976
  const alternateIconNames = /* @__PURE__ */ new Set();
978
- for (const name of isRecord2(alternates) ? Object.keys(alternates) : []) {
977
+ for (const name of isRecord(alternates) ? Object.keys(alternates) : []) {
979
978
  const resolved = resolveBuildSetting(name, settings);
980
979
  if (resolved === null) throw new Error("native alternate icon name is unresolved");
981
980
  alternateIconNames.add(resolved);
@@ -1079,11 +1078,11 @@ function nativeAppIdentityFromIos(files, parseInfoPlist, iosTarget, resourceUri)
1079
1078
  return `${base.startsWith("/") ? "/" : ""}${segments.join("/")}`;
1080
1079
  };
1081
1080
  const project = Object.values(objects).find(
1082
- (object) => isRecord2(object) && object.isa === "PBXProject"
1081
+ (object) => isRecord(object) && object.isa === "PBXProject"
1083
1082
  );
1084
1083
  const projectDir = join(
1085
1084
  pbxprojPath.replace(/(?:^|\/)[^/]+\.xcodeproj\/project\.pbxproj$/, ""),
1086
- isRecord2(project) && typeof project.projectDirPath === "string" ? project.projectDirPath : ""
1085
+ isRecord(project) && typeof project.projectDirPath === "string" ? project.projectDirPath : ""
1087
1086
  );
1088
1087
  const paths = Object.keys(files);
1089
1088
  visitXcodeTargetMembers(
@@ -1,4 +1,4 @@
1
- /*! peach v0.1.1635 | (c) 2026 Tamagui LLC | Proprietary; see LICENSE */
1
+ /*! peach v0.1.1641 | (c) 2026 Tamagui LLC | Proprietary; see LICENSE */
2
2
  let __sootsim_import_meta_url = '', __sootsim_import_meta_dirname = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; __sootsim_import_meta_dirname = __dirname; } catch {}
3
3
  "use strict";
4
4
  var __defProp = Object.defineProperty;
@@ -1,4 +1,4 @@
1
- /*! peach v0.1.1635 | (c) 2026 Tamagui LLC | Proprietary; see LICENSE */
1
+ /*! peach v0.1.1641 | (c) 2026 Tamagui LLC | Proprietary; see LICENSE */
2
2
 
3
3
  // src/bundleGlobalFooter.ts
4
4
  function findBundleFooter(source, prefix) {
@@ -1,4 +1,4 @@
1
- /*! peach v0.1.1635 | (c) 2026 Tamagui LLC | Proprietary; see LICENSE */
1
+ /*! peach v0.1.1641 | (c) 2026 Tamagui LLC | Proprietary; see LICENSE */
2
2
  let __sootsim_import_meta_url = '', __sootsim_import_meta_dirname = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; __sootsim_import_meta_dirname = __dirname; } catch {}
3
3
  "use strict";
4
4
  var __create = Object.create;
@@ -1,4 +1,4 @@
1
- /*! peach v0.1.1635 | (c) 2026 Tamagui LLC | Proprietary; see LICENSE */
1
+ /*! peach v0.1.1641 | (c) 2026 Tamagui LLC | Proprietary; see LICENSE */
2
2
 
3
3
  // src/plist.ts
4
4
  import plist from "plist";
@@ -1,4 +1,4 @@
1
- /*! peach v0.1.1635 | (c) 2026 Tamagui LLC | Proprietary; see LICENSE */
1
+ /*! peach v0.1.1641 | (c) 2026 Tamagui LLC | Proprietary; see LICENSE */
2
2
  let __sootsim_import_meta_url = '', __sootsim_import_meta_dirname = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; __sootsim_import_meta_dirname = __dirname; } catch {}
3
3
  "use strict";
4
4
  var __create = Object.create;
@@ -1,4 +1,4 @@
1
- /*! peach v0.1.1635 | (c) 2026 Tamagui LLC | Proprietary; see LICENSE */
1
+ /*! peach v0.1.1641 | (c) 2026 Tamagui LLC | Proprietary; see LICENSE */
2
2
  let __sootsim_import_meta_url = '', __sootsim_import_meta_dirname = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; __sootsim_import_meta_dirname = __dirname; } catch {}
3
3
  "use strict";
4
4
  var __defProp = Object.defineProperty;
@@ -1,4 +1,4 @@
1
- /*! peach v0.1.1635 | (c) 2026 Tamagui LLC | Proprietary; see LICENSE */
1
+ /*! peach v0.1.1641 | (c) 2026 Tamagui LLC | Proprietary; see LICENSE */
2
2
  let __sootsim_import_meta_url = '', __sootsim_import_meta_dirname = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; __sootsim_import_meta_dirname = __dirname; } catch {}
3
3
  "use strict";
4
4
  var __defProp = Object.defineProperty;
@@ -64,7 +64,7 @@ var REACT_NATIVE_PASSTHROUGH_SPECIFIERS = [
64
64
  ];
65
65
  function isReactNativePassthroughSpecifier(specifier) {
66
66
  return REACT_NATIVE_PASSTHROUGH_SPECIFIERS.some(
67
- (passthrough) => specifier === passthrough || specifier.startsWith(`${passthrough}/`)
67
+ (passthrough) => specifier.startsWith(passthrough) && (specifier.length === passthrough.length || specifier[passthrough.length] === "/")
68
68
  );
69
69
  }
70
70
  // Annotate the CommonJS export names for ESM import in node:
@@ -1,4 +1,4 @@
1
- /*! peach v0.1.1635 | (c) 2026 Tamagui LLC | Proprietary; see LICENSE */
1
+ /*! peach v0.1.1641 | (c) 2026 Tamagui LLC | Proprietary; see LICENSE */
2
2
 
3
3
  // src/react-native-host-modules.ts
4
4
  var REACT_NATIVE_PASSTHROUGH_SPECIFIERS = [
@@ -39,7 +39,7 @@ var REACT_NATIVE_PASSTHROUGH_SPECIFIERS = [
39
39
  ];
40
40
  function isReactNativePassthroughSpecifier(specifier) {
41
41
  return REACT_NATIVE_PASSTHROUGH_SPECIFIERS.some(
42
- (passthrough) => specifier === passthrough || specifier.startsWith(`${passthrough}/`)
42
+ (passthrough) => specifier.startsWith(passthrough) && (specifier.length === passthrough.length || specifier[passthrough.length] === "/")
43
43
  );
44
44
  }
45
45
  export {
@@ -1,4 +1,4 @@
1
- /*! peach v0.1.1635 | (c) 2026 Tamagui LLC | Proprietary; see LICENSE */
1
+ /*! peach v0.1.1641 | (c) 2026 Tamagui LLC | Proprietary; see LICENSE */
2
2
  let __sootsim_import_meta_url = '', __sootsim_import_meta_dirname = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; __sootsim_import_meta_dirname = __dirname; } catch {}
3
3
  "use strict";
4
4
  var __create = Object.create;
@@ -312,6 +312,11 @@ function isLoopbackHost(hostname) {
312
312
  return normalized === "localhost" || normalized.endsWith(".localhost") || normalized === "0.0.0.0" || normalized === "::1" || /^127(?:\.\d{1,3}){3}$/.test(normalized);
313
313
  }
314
314
 
315
+ // src/is-record.ts
316
+ function isRecord(value) {
317
+ return typeof value === "object" && value !== null && !Array.isArray(value);
318
+ }
319
+
315
320
  // src/config.ts
316
321
  var PEACH_CONFIG_QUERY_PARAM = "peachConfig";
317
322
  function hasOwnKeys(value) {
@@ -555,9 +560,6 @@ var MAX_CHILD_DEPTH = 8;
555
560
  var MAX_PLIST_FILES = 32;
556
561
  var MAX_SPECIFIERS = 512;
557
562
  var settingsBundleCache = /* @__PURE__ */ new Map();
558
- function isRecord2(value) {
559
- return typeof value === "object" && value !== null && !Array.isArray(value);
560
- }
561
563
  function optionalString(value) {
562
564
  return typeof value === "string" ? value : void 0;
563
565
  }
@@ -684,7 +686,7 @@ async function parsePlistRecord(path) {
684
686
  if (!metadata.isFile() || metadata.size > MAX_PLIST_BYTES) return null;
685
687
  const source = await (0, import_promises.readFile)(path, "utf8");
686
688
  const parsed = parsePlistSource(source);
687
- return isRecord2(parsed) ? parsed : null;
689
+ return isRecord(parsed) ? parsed : null;
688
690
  } catch {
689
691
  return null;
690
692
  }
@@ -720,7 +722,7 @@ function normalizeMultiValue(raw, key, title) {
720
722
  };
721
723
  }
722
724
  async function normalizeSpecifier(raw, context) {
723
- if (!isRecord2(raw)) return null;
725
+ if (!isRecord(raw)) return null;
724
726
  if (context.budget.specifiers >= MAX_SPECIFIERS) return null;
725
727
  const type = requiredString(raw.Type);
726
728
  if (!type) return null;
package/dist-lib/sdk.cjs CHANGED
@@ -1,4 +1,4 @@
1
- /*! peach v0.1.1635 | (c) 2026 Tamagui LLC | Proprietary; see LICENSE */
1
+ /*! peach v0.1.1641 | (c) 2026 Tamagui LLC | Proprietary; see LICENSE */
2
2
  let __sootsim_import_meta_url = '', __sootsim_import_meta_dirname = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; __sootsim_import_meta_dirname = __dirname; } catch {}
3
3
  "use strict";
4
4
  var __defProp = Object.defineProperty;
@@ -2497,9 +2497,10 @@ async function tapByText(bridge, query, options = {}, opts = {}) {
2497
2497
  });
2498
2498
  }
2499
2499
  async function resolveTextTapTarget(bridge, query, options = {}) {
2500
+ const needle = options.exact ? query : query.trim().toLowerCase();
2501
+ if (!needle) return { matched: 0, total: 0 };
2500
2502
  const { tree } = await inspectTree(bridge, 50);
2501
2503
  if (!Array.isArray(tree)) return { matched: 0, total: 0 };
2502
- const needle = options.exact ? query : query.toLowerCase();
2503
2504
  let candidates = collectTextCandidates(tree).filter(
2504
2505
  ({ node: node2, ancestorTestIDs, role }) => {
2505
2506
  const text = nodeText(node2);
@@ -2523,7 +2524,7 @@ async function resolveTextTapTarget(bridge, query, options = {}) {
2523
2524
  if (actionable.length > 0) candidates = actionable;
2524
2525
  if (!options.exact) {
2525
2526
  const whole = candidates.filter(
2526
- ({ node: node2 }) => nodeText(node2).trim().toLowerCase() === needle.trim()
2527
+ ({ node: node2 }) => nodeText(node2).trim().toLowerCase() === needle
2527
2528
  );
2528
2529
  if (whole.length > 0) candidates = whole;
2529
2530
  }
package/dist-lib/sdk.mjs CHANGED
@@ -1,4 +1,4 @@
1
- /*! peach v0.1.1635 | (c) 2026 Tamagui LLC | Proprietary; see LICENSE */
1
+ /*! peach v0.1.1641 | (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);
@@ -2392,9 +2392,10 @@ async function tapByText(bridge, query, options = {}, opts = {}) {
2392
2392
  });
2393
2393
  }
2394
2394
  async function resolveTextTapTarget(bridge, query, options = {}) {
2395
+ const needle = options.exact ? query : query.trim().toLowerCase();
2396
+ if (!needle) return { matched: 0, total: 0 };
2395
2397
  const { tree } = await inspectTree(bridge, 50);
2396
2398
  if (!Array.isArray(tree)) return { matched: 0, total: 0 };
2397
- const needle = options.exact ? query : query.toLowerCase();
2398
2399
  let candidates = collectTextCandidates(tree).filter(
2399
2400
  ({ node: node2, ancestorTestIDs, role }) => {
2400
2401
  const text = nodeText(node2);
@@ -2418,7 +2419,7 @@ async function resolveTextTapTarget(bridge, query, options = {}) {
2418
2419
  if (actionable.length > 0) candidates = actionable;
2419
2420
  if (!options.exact) {
2420
2421
  const whole = candidates.filter(
2421
- ({ node: node2 }) => nodeText(node2).trim().toLowerCase() === needle.trim()
2422
+ ({ node: node2 }) => nodeText(node2).trim().toLowerCase() === needle
2422
2423
  );
2423
2424
  if (whole.length > 0) candidates = whole;
2424
2425
  }