peachsim 0.1.1625 → 0.1.1640

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 (169) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +15 -2
  3. package/cli/app-config.ts +18 -6
  4. package/cli/app-fonts.ts +37 -17
  5. package/cli/app-stubs.ts +284 -20
  6. package/cli/bridge-flow-runner.ts +66 -45
  7. package/cli/cloud-client.ts +60 -40
  8. package/cli/command-registry.ts +1 -0
  9. package/cli/commands/control.ts +283 -49
  10. package/cli/commands/doctor.ts +30 -189
  11. package/cli/commands/flow.ts +79 -11
  12. package/cli/commands/inspect/core.ts +10 -5
  13. package/cli/commands/inspect/settling.ts +14 -2
  14. package/cli/commands/inspect/shared.ts +9 -4
  15. package/cli/commands/inspect/wait-ready.ts +12 -0
  16. package/cli/commands/inspect.ts +91 -50
  17. package/cli/commands/install-desktop.ts +1 -0
  18. package/cli/commands/maestro-compare.ts +97 -38
  19. package/cli/commands/maestro.ts +9 -1
  20. package/cli/commands/preview.ts +1 -1
  21. package/cli/commands/record.ts +118 -48
  22. package/cli/commands/screenshot.ts +23 -1
  23. package/cli/commands/serve.ts +7 -2
  24. package/cli/commands/setup.ts +19 -42
  25. package/cli/commands/swift.ts +14 -3
  26. package/cli/commands/upload.ts +93 -48
  27. package/cli/desktop-companion.ts +102 -17
  28. package/cli/drivers/desktop.ts +14 -1
  29. package/cli/drivers/playwright-sim-host.ts +103 -45
  30. package/cli/drivers/playwright.ts +9 -8
  31. package/cli/drivers/types.ts +5 -0
  32. package/cli/maestro-accessibility.ts +1 -1
  33. package/cli/maestro-compare.ts +84 -12
  34. package/cli/main.ts +3 -2
  35. package/cli/outbound-endpoints.ts +20 -6
  36. package/cli/pause-aware-timeout.ts +106 -0
  37. package/cli/scene-video.ts +89 -0
  38. package/cli/ws-bridge.ts +37 -19
  39. package/detox/attempt-events.cjs +66 -5
  40. package/detox/attempt-events.d.cts +7 -0
  41. package/detox/expectations.ts +7 -3
  42. package/detox/index.ts +269 -170
  43. package/detox/motion-change.cjs +206 -21
  44. package/detox/motion-change.d.cts +39 -2
  45. package/detox/navigation-lifecycle.ts +35 -3
  46. package/dist-lib/agent-daemon-client.cjs +1 -1
  47. package/dist-lib/agent-events.cjs +1 -1
  48. package/dist-lib/attached-projects.cjs +1 -1
  49. package/dist-lib/auth/shared-session.cjs +1 -1
  50. package/dist-lib/backend-origin.cjs +8 -7
  51. package/dist-lib/beta.cjs +1 -1
  52. package/dist-lib/beta.mjs +1 -1
  53. package/dist-lib/bridge-constants.cjs +13 -1
  54. package/dist-lib/bridge-contract-input.cjs +1 -1
  55. package/dist-lib/bridge-contract-input.mjs +1 -1
  56. package/dist-lib/bridge-contract.cjs +14 -8
  57. package/dist-lib/bridge-contract.mjs +13 -7
  58. package/dist-lib/bundle-channel.cjs +11887 -7900
  59. package/dist-lib/capture-contract.cjs +1 -1
  60. package/dist-lib/capture-contract.mjs +1 -1
  61. package/dist-lib/cloud-contract.cjs +1 -1
  62. package/dist-lib/cloud-contract.mjs +1 -1
  63. package/dist-lib/cloud-test-args.cjs +1 -1
  64. package/dist-lib/cloud-test-args.mjs +1 -1
  65. package/dist-lib/cloud.cjs +1 -1
  66. package/dist-lib/cloud.mjs +1 -1
  67. package/dist-lib/config.cjs +6 -3
  68. package/dist-lib/config.mjs +6 -3
  69. package/dist-lib/detox/index.cjs +1379 -725
  70. package/dist-lib/dev-bundle-resolution.cjs +14 -2
  71. package/dist-lib/expo-swift-bundle.cjs +9341 -5462
  72. package/dist-lib/expo-swift-metadata.cjs +11 -7
  73. package/dist-lib/expo-swift-metadata.mjs +11 -7
  74. package/dist-lib/home-paths.cjs +32 -3
  75. package/dist-lib/host/bridge-host.cjs +50204 -7258
  76. package/dist-lib/host/fetch-proxy-handler.cjs +1 -1
  77. package/dist-lib/host/fetch-proxy-overrides.cjs +1 -1
  78. package/dist-lib/host/fetch-proxy-overrides.mjs +1 -1
  79. package/dist-lib/host/replacement-module-handler.cjs +1 -1
  80. package/dist-lib/host/websocket-proxy.cjs +1 -1
  81. package/dist-lib/index.cjs +3541 -448
  82. package/dist-lib/jump-to-source-babel.cjs +1 -1
  83. package/dist-lib/jump-to-source-native.cjs +1 -1
  84. package/dist-lib/kotlin-host.cjs +1 -1
  85. package/dist-lib/menu.cjs +1 -1
  86. package/dist-lib/menu.mjs +1 -1
  87. package/dist-lib/metro-fingerprint-registry.cjs +1 -1
  88. package/dist-lib/metro-fingerprint-registry.mjs +1 -1
  89. package/dist-lib/metro-production-bundle.cjs +1 -1
  90. package/dist-lib/metro-production-bundle.mjs +1 -1
  91. package/dist-lib/metro.cjs +2931 -104
  92. package/dist-lib/native-app-identity-project.cjs +289 -49
  93. package/dist-lib/native-app-identity-project.mjs +289 -49
  94. package/dist-lib/native-app-identity.cjs +77 -26
  95. package/dist-lib/native-app-identity.mjs +76 -26
  96. package/dist-lib/native-firebase-metadata.cjs +1 -1
  97. package/dist-lib/native-firebase-metadata.mjs +1 -1
  98. package/dist-lib/plist.cjs +1 -1
  99. package/dist-lib/plist.mjs +1 -1
  100. package/dist-lib/profiles.cjs +1 -1
  101. package/dist-lib/public-brand.cjs +1 -1
  102. package/dist-lib/react-native-host-modules.cjs +6 -2
  103. package/dist-lib/react-native-host-modules.mjs +6 -2
  104. package/dist-lib/scripts/dev-server-scanner.cjs +22 -8
  105. package/dist-lib/sdk.cjs +27 -11
  106. package/dist-lib/sdk.mjs +27 -10
  107. package/dist-lib/skills.cjs +72201 -26208
  108. package/dist-lib/swift-compile.cjs +1007 -140
  109. package/dist-lib/swift-compile.mjs +1049 -174
  110. package/dist-lib/swift-package.cjs +12 -3
  111. package/dist-lib/swift-package.mjs +12 -3
  112. package/dist-lib/swift-submit.cjs +13 -5
  113. package/dist-lib/swift-submit.mjs +11 -5
  114. package/dist-lib/swift-toolchain.cjs +423 -33
  115. package/dist-lib/swift.cjs +1 -1
  116. package/dist-lib/vite-swift.cjs +8628 -5268
  117. package/dist-lib/vite.cjs +2859 -12
  118. package/dist-lib/worklet-executable.cjs +14 -2
  119. package/dist-lib/worklet-executable.mjs +14 -2
  120. package/kotlin/AppSources/dev/peach/app/PeachDrawable.kt +21 -14
  121. package/kotlin/Sources/androidx/annotation/DrawableRes.kt +14 -0
  122. package/package.json +1 -1
  123. package/scripts/dev-server-scanner.ts +2 -1
  124. package/skills/peach-perf/SKILL.md +11 -5
  125. package/skills/peach-setup/SKILL.md +16 -19
  126. package/src/backend-origin.ts +13 -6
  127. package/src/bridge-constants.ts +11 -0
  128. package/src/bridge-contract.ts +22 -34
  129. package/src/config.ts +15 -0
  130. package/src/desktop-host-delivery.ts +5 -1
  131. package/src/dev-bundle-resolution.ts +2 -1
  132. package/src/expo-manifest-body.ts +13 -0
  133. package/src/expo-swift-host.ts +196 -49
  134. package/src/expo-swift-ready.ts +78 -0
  135. package/src/expoKotlinContract.ts +4 -7
  136. package/src/expoSwiftContract.ts +17 -6
  137. package/src/home-paths.ts +48 -2
  138. package/src/host/bridge-host.ts +5 -2
  139. package/src/host/staged-host-files.ts +9 -0
  140. package/src/native-app-identity-project.ts +27 -6
  141. package/src/native-app-identity.ts +91 -4
  142. package/src/native-firebase-config.ts +209 -13
  143. package/src/nativeAppIconContract.ts +1 -4
  144. package/src/output-lock-stdio.ts +36 -0
  145. package/src/process-group.ts +25 -2
  146. package/src/react-native-bridge-modules.ts +431 -0
  147. package/src/react-native-host-modules.ts +8 -1
  148. package/src/settings-bundle.ts +1 -4
  149. package/src/swift-binary-modules.ts +2 -2
  150. package/src/swift-compile.ts +918 -109
  151. package/src/swift-compiler-digest.ts +14 -0
  152. package/src/swift-distribution.lock.json +24 -12
  153. package/src/swift-distribution.ts +103 -4
  154. package/src/swift-host.ts +180 -55
  155. package/src/swift-icu.ts +27 -13
  156. package/src/swift-objc-compile.ts +355 -0
  157. package/src/swift-objc-sdk.ts +821 -27
  158. package/src/swift-objc-standin.ts +148 -14
  159. package/src/swift-package-manifest.ts +60 -7
  160. package/src/swift-package.ts +15 -1
  161. package/src/swift-packages.ts +154 -81
  162. package/src/swift-standin-emit.ts +96 -15
  163. package/src/swift-standins.ts +530 -116
  164. package/src/swift-submit.ts +13 -5
  165. package/src/swift-toolchain.ts +500 -42
  166. package/src/vite-plugin.ts +12 -1
  167. package/src/worker-system-chunks.ts +11 -12
  168. package/src/worklet-executable.ts +19 -1
  169. package/src/xcode-project.ts +270 -30
@@ -1,4 +1,4 @@
1
- /*! peach v0.1.1625 | (c) 2026 Tamagui LLC | Proprietary; see LICENSE */
1
+ /*! peach v0.1.1640 | (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;
@@ -32,6 +32,7 @@ __export(native_app_identity_exports, {
32
32
  getAppliedNativeAppIdentity: () => getAppliedNativeAppIdentity,
33
33
  insertNativeAppIdentityFooter: () => insertNativeAppIdentityFooter,
34
34
  isNativeAppIdentity: () => isNativeAppIdentity,
35
+ readGoogleSignInConfiguration: () => readGoogleSignInConfiguration,
35
36
  readNativeAppIdentity: () => readNativeAppIdentity,
36
37
  readNativeAppIdentityFooter: () => readNativeAppIdentityFooter,
37
38
  readNativeAppIdentityFromBundle: () => readNativeAppIdentityFromBundle,
@@ -240,6 +241,11 @@ function isFooterBlockLine(source, line, end) {
240
241
  return line === end || source.startsWith("globalThis.", line) || source.startsWith("//", line);
241
242
  }
242
243
 
244
+ // src/is-record.ts
245
+ function isRecord(value) {
246
+ return typeof value === "object" && value !== null && !Array.isArray(value);
247
+ }
248
+
243
249
  // src/assetCatalogContract.ts
244
250
  function isSwiftImageVariants(value) {
245
251
  return Array.isArray(value) && value.length > 0 && value.every(
@@ -248,9 +254,6 @@ function isSwiftImageVariants(value) {
248
254
  }
249
255
 
250
256
  // src/nativeAppIconContract.ts
251
- function isRecord(value) {
252
- return typeof value === "object" && value !== null && !Array.isArray(value);
253
- }
254
257
  function isNativeAppIconArtwork(value) {
255
258
  return isRecord(value) && (value.primary === void 0 || isSwiftImageVariants(value.primary)) && isRecord(value.alternates) && Object.values(value.alternates).every(isSwiftImageVariants);
256
259
  }
@@ -524,30 +527,33 @@ function visitXcodeTargetMembers(objects, targetId, resolvePath, filesUnder, joi
524
527
  var NATIVE_APP_IDENTITY_PREFIX = "globalThis.__sootsimNativeAppIdentity=";
525
528
  var METRO_MODULE_PATHS_PREFIX = "globalThis.__sootsimModulePaths=";
526
529
  var NATIVE_APP_IDENTITY_HEADER = "Peach-Native-App-Identity";
527
- function isRecord2(value) {
528
- return typeof value === "object" && value !== null && !Array.isArray(value);
529
- }
530
530
  function nonEmptyString(value) {
531
531
  return typeof value === "string" && value.length > 0 ? value : null;
532
532
  }
533
533
  function isNativeAppIdentity(value) {
534
- if (!isRecord2(value)) return false;
534
+ if (!isRecord(value)) return false;
535
+ for (const key of ["statusBarHidden", "viewControllerBasedStatusBarAppearance"]) {
536
+ if (value[key] !== void 0 && typeof value[key] !== "boolean") return false;
537
+ }
535
538
  const oneUpdates = value.oneUpdates;
536
- 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))) {
537
540
  return false;
538
541
  }
539
542
  if (value.dtPlatformVersion !== void 0 && typeof value.dtPlatformVersion !== "string")
540
543
  return false;
541
544
  if (value.androidManifestPermissions !== void 0 && (!Array.isArray(value.androidManifestPermissions) || !value.androidManifestPermissions.every(
542
- (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)
543
546
  )))
544
547
  return false;
548
+ if (value.googleSignIn !== void 0 && !isRecord(value.googleSignIn)) return false;
545
549
  const descriptions = value.permissionUsageDescriptions;
546
- 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(
547
551
  (flag) => typeof flag === "boolean"
548
552
  )))
549
553
  return false;
550
- if (descriptions !== void 0 && !isRecord2(descriptions)) return false;
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")))
556
+ return false;
551
557
  if (value.urlQuerySchemes !== void 0 && !Array.isArray(value.urlQuerySchemes))
552
558
  return false;
553
559
  if (value.appIntentIdentifiers !== void 0 && (!Array.isArray(value.appIntentIdentifiers) || !value.appIntentIdentifiers.every((identifier) => typeof identifier === "string")))
@@ -609,6 +615,10 @@ function readNativeAppIdentity(value) {
609
615
  ...value.rootModuleName === void 0 ? {} : { rootModuleName: value.rootModuleName },
610
616
  ...value.rootViewBackgroundColor === void 0 ? {} : { rootViewBackgroundColor: value.rootViewBackgroundColor },
611
617
  ...value.designRequiresCompatibility === void 0 ? {} : { designRequiresCompatibility: value.designRequiresCompatibility },
618
+ ...value.statusBarHidden === void 0 ? {} : { statusBarHidden: value.statusBarHidden },
619
+ ...value.viewControllerBasedStatusBarAppearance === void 0 ? {} : {
620
+ viewControllerBasedStatusBarAppearance: value.viewControllerBasedStatusBarAppearance
621
+ },
612
622
  ...value.dtPlatformVersion === void 0 ? {} : { dtPlatformVersion: value.dtPlatformVersion },
613
623
  ...value.bundleName === void 0 ? {} : { bundleName: value.bundleName },
614
624
  appVersion: value.appVersion,
@@ -623,9 +633,11 @@ function readNativeAppIdentity(value) {
623
633
  (permission) => ({ ...permission })
624
634
  )
625
635
  },
636
+ ...value.googleSignIn === void 0 ? {} : { googleSignIn: structuredClone(value.googleSignIn) },
626
637
  ...value.permissionUsageDescriptions === void 0 ? {} : {
627
638
  permissionUsageDescriptions: { ...value.permissionUsageDescriptions }
628
639
  },
640
+ ...value.infoPlistStrings === void 0 ? {} : { infoPlistStrings: { ...value.infoPlistStrings } },
629
641
  ...value.appIntentIdentifiers === void 0 ? {} : { appIntentIdentifiers: [...value.appIntentIdentifiers] },
630
642
  ...value.backgroundTaskIdentifiers === void 0 ? {} : { backgroundTaskIdentifiers: [...value.backgroundTaskIdentifiers] },
631
643
  ...value.supportedInterfaceOrientations === void 0 ? {} : {
@@ -660,7 +672,7 @@ function equalIdentityValues(left, right) {
660
672
  if (Array.isArray(left) && Array.isArray(right)) {
661
673
  return left.length === right.length && left.every((value, index) => equalIdentityValues(value, right[index]));
662
674
  }
663
- if (!isRecord2(left) || !isRecord2(right)) return false;
675
+ if (!isRecord(left) || !isRecord(right)) return false;
664
676
  const keys = Object.keys(left);
665
677
  return keys.length === Object.keys(right).length && keys.every(
666
678
  (key) => Object.hasOwn(right, key) && equalIdentityValues(left[key], right[key])
@@ -747,6 +759,27 @@ function insertNativeAppIdentityFooter(source, identity) {
747
759
  if (moduleFooter < 0) return withoutExisting + footer;
748
760
  return withoutExisting.slice(0, moduleFooter) + footer + withoutExisting.slice(moduleFooter);
749
761
  }
762
+ function readGoogleSignInConfiguration(plist, resources) {
763
+ const clientIds = {};
764
+ for (const [file, value] of Object.entries(resources)) {
765
+ if (isRecord(value) && typeof value.CLIENT_ID === "string")
766
+ clientIds[file.split("/").pop()?.replace(/\.plist$/, "") ?? file] = value.CLIENT_ID;
767
+ }
768
+ const urlSchemes = [];
769
+ for (const entry of Array.isArray(plist.CFBundleURLTypes) ? plist.CFBundleURLTypes : []) {
770
+ if (!isRecord(entry) || !Array.isArray(entry.CFBundleURLSchemes)) continue;
771
+ for (const scheme of entry.CFBundleURLSchemes)
772
+ if (typeof scheme === "string") urlSchemes.push(scheme);
773
+ }
774
+ return {
775
+ clientId: plist.GIDClientID,
776
+ serverClientId: plist.GIDServerClientID,
777
+ hostedDomain: plist.GIDHostedDomain,
778
+ openIDRealm: plist.GIDOpenIDRealm,
779
+ urlSchemes,
780
+ clientIds
781
+ };
782
+ }
750
783
  function plistString(plist, key) {
751
784
  const match = plist.match(new RegExp(`<key>${key}</key>\\s*<string>([^<]*)</string>`));
752
785
  return match ? match[1].trim() : null;
@@ -842,14 +875,14 @@ function nativeAppIdentityFromIos(files, parseInfoPlist, iosTarget, resourceUri)
842
875
  let objects = {};
843
876
  try {
844
877
  const parsed = parseOpenStepPlist(pbxproj);
845
- if (isRecord2(parsed)) {
846
- objects = isRecord2(parsed.objects) ? parsed.objects : parsed;
878
+ if (isRecord(parsed)) {
879
+ objects = isRecord(parsed.objects) ? parsed.objects : parsed;
847
880
  }
848
881
  } catch {
849
882
  }
850
883
  const targets = [];
851
884
  for (const [id, obj] of Object.entries(objects)) {
852
- if (isRecord2(obj) && obj.isa === "PBXNativeTarget" && typeof obj.name === "string") {
885
+ if (isRecord(obj) && obj.isa === "PBXNativeTarget" && typeof obj.name === "string") {
853
886
  targets.push({
854
887
  id,
855
888
  name: obj.name,
@@ -895,13 +928,13 @@ function nativeAppIdentityFromIos(files, parseInfoPlist, iosTarget, resourceUri)
895
928
  PRODUCT_NAME: targetName
896
929
  };
897
930
  for (const obj of Object.values(objects)) {
898
- if (isRecord2(obj) && obj.isa === "PBXProject" && typeof obj.buildConfigurationList === "string") {
931
+ if (isRecord(obj) && obj.isa === "PBXProject" && typeof obj.buildConfigurationList === "string") {
899
932
  const listObj = objects[obj.buildConfigurationList];
900
- if (isRecord2(listObj) && Array.isArray(listObj.buildConfigurations)) {
933
+ if (isRecord(listObj) && Array.isArray(listObj.buildConfigurations)) {
901
934
  for (const configId of listObj.buildConfigurations) {
902
935
  if (typeof configId === "string") {
903
936
  const configObj = objects[configId];
904
- if (isRecord2(configObj) && configObj.name === "Release" && isRecord2(configObj.buildSettings)) {
937
+ if (isRecord(configObj) && configObj.name === "Release" && isRecord(configObj.buildSettings)) {
905
938
  for (const [k, v] of Object.entries(configObj.buildSettings)) {
906
939
  if (typeof v === "string") settings[k] = v;
907
940
  }
@@ -913,11 +946,11 @@ function nativeAppIdentityFromIos(files, parseInfoPlist, iosTarget, resourceUri)
913
946
  }
914
947
  if (selectedTarget?.buildConfigurationList) {
915
948
  const listObj = objects[selectedTarget.buildConfigurationList];
916
- if (isRecord2(listObj) && Array.isArray(listObj.buildConfigurations)) {
949
+ if (isRecord(listObj) && Array.isArray(listObj.buildConfigurations)) {
917
950
  for (const configId of listObj.buildConfigurations) {
918
951
  if (typeof configId === "string") {
919
952
  const configObj = objects[configId];
920
- if (isRecord2(configObj) && configObj.name === "Release" && isRecord2(configObj.buildSettings)) {
953
+ if (isRecord(configObj) && configObj.name === "Release" && isRecord(configObj.buildSettings)) {
921
954
  for (const [k, v] of Object.entries(configObj.buildSettings)) {
922
955
  if (typeof v === "string") settings[k] = v;
923
956
  }
@@ -968,7 +1001,7 @@ function nativeAppIdentityFromIos(files, parseInfoPlist, iosTarget, resourceUri)
968
1001
  if (!bundleName) return null;
969
1002
  const applicationName = identityFieldFrom(settings, plistString(plist, "CFBundleDisplayName"), void 0) ?? bundleName;
970
1003
  const dictionary = parseInfoPlist(plist);
971
- 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");
972
1005
  const declaredDisplayName = dictionary.CFBundleDisplayName;
973
1006
  const applicationDisplayName = typeof declaredDisplayName === "string" ? resolveBuildSetting(declaredDisplayName, settings) : void 0;
974
1007
  if (applicationDisplayName === null)
@@ -981,9 +1014,9 @@ function nativeAppIdentityFromIos(files, parseInfoPlist, iosTarget, resourceUri)
981
1014
  if (dtPlatformVersion === null)
982
1015
  throw new Error("native app Info.plist DTPlatformVersion is unresolved");
983
1016
  const icons = dictionary.CFBundleIcons;
984
- const alternates = isRecord2(icons) ? icons.CFBundleAlternateIcons : void 0;
1017
+ const alternates = isRecord(icons) ? icons.CFBundleAlternateIcons : void 0;
985
1018
  const alternateIconNames = /* @__PURE__ */ new Set();
986
- for (const name of isRecord2(alternates) ? Object.keys(alternates) : []) {
1019
+ for (const name of isRecord(alternates) ? Object.keys(alternates) : []) {
987
1020
  const resolved = resolveBuildSetting(name, settings);
988
1021
  if (resolved === null) throw new Error("native alternate icon name is unresolved");
989
1022
  alternateIconNames.add(resolved);
@@ -1056,6 +1089,12 @@ function nativeAppIdentityFromIos(files, parseInfoPlist, iosTarget, resourceUri)
1056
1089
  if (resolved === null) throw new Error(`native app Info.plist ${key} is unresolved`);
1057
1090
  permissionUsageDescriptions[key] = resolved;
1058
1091
  }
1092
+ const infoPlistStrings = {};
1093
+ for (const [key, value] of Object.entries(dictionary)) {
1094
+ if (typeof value !== "string") continue;
1095
+ const resolved = resolveBuildSetting(value, settings);
1096
+ if (resolved !== null) infoPlistStrings[key] = resolved;
1097
+ }
1059
1098
  if (settings.GENERATE_INFOPLIST_FILE === "YES") {
1060
1099
  for (const [setting, value] of Object.entries(settings)) {
1061
1100
  if (!/^INFOPLIST_KEY_NS.*UsageDescription$/.test(setting)) continue;
@@ -1081,11 +1120,11 @@ function nativeAppIdentityFromIos(files, parseInfoPlist, iosTarget, resourceUri)
1081
1120
  return `${base.startsWith("/") ? "/" : ""}${segments.join("/")}`;
1082
1121
  };
1083
1122
  const project = Object.values(objects).find(
1084
- (object) => isRecord2(object) && object.isa === "PBXProject"
1123
+ (object) => isRecord(object) && object.isa === "PBXProject"
1085
1124
  );
1086
1125
  const projectDir = join(
1087
1126
  pbxprojPath.replace(/(?:^|\/)[^/]+\.xcodeproj\/project\.pbxproj$/, ""),
1088
- isRecord2(project) && typeof project.projectDirPath === "string" ? project.projectDirPath : ""
1127
+ isRecord(project) && typeof project.projectDirPath === "string" ? project.projectDirPath : ""
1089
1128
  );
1090
1129
  const paths = Object.keys(files);
1091
1130
  visitXcodeTargetMembers(
@@ -1116,12 +1155,22 @@ function nativeAppIdentityFromIos(files, parseInfoPlist, iosTarget, resourceUri)
1116
1155
  ...rootModuleName === void 0 ? {} : { rootModuleName },
1117
1156
  ...rootViewBackgroundColor === void 0 ? {} : { rootViewBackgroundColor },
1118
1157
  ...designRequiresCompatibility ? { designRequiresCompatibility } : {},
1158
+ ...typeof dictionary.UIStatusBarHidden === "boolean" ? { statusBarHidden: dictionary.UIStatusBarHidden } : {},
1159
+ ...typeof dictionary.UIViewControllerBasedStatusBarAppearance === "boolean" ? {
1160
+ viewControllerBasedStatusBarAppearance: dictionary.UIViewControllerBasedStatusBarAppearance
1161
+ } : {},
1119
1162
  ...dtPlatformVersion === void 0 ? {} : { dtPlatformVersion },
1120
1163
  bundleName,
1121
1164
  appVersion,
1122
1165
  buildVersion,
1123
1166
  bundleIdentifier,
1124
1167
  platform: "ios",
1168
+ googleSignIn: readGoogleSignInConfiguration(
1169
+ dictionary,
1170
+ Object.fromEntries(
1171
+ [...resources].filter((file) => file.endsWith(".plist") && files[file]).map((file) => [file, parseInfoPlist(files[file])])
1172
+ )
1173
+ ),
1125
1174
  supportedInterfaceOrientations,
1126
1175
  ipadSupportedInterfaceOrientations,
1127
1176
  ...defaultScreenOrientationMask === void 0 ? {} : { defaultScreenOrientationMask },
@@ -1143,6 +1192,7 @@ function nativeAppIdentityFromIos(files, parseInfoPlist, iosTarget, resourceUri)
1143
1192
  )
1144
1193
  } : {},
1145
1194
  permissionUsageDescriptions,
1195
+ infoPlistStrings,
1146
1196
  urlQuerySchemes,
1147
1197
  ...shareIntoAppGroupId === void 0 ? {} : { shareIntoAppGroupId },
1148
1198
  ...rtcAppGroupIdentifier === void 0 ? {} : { rtcAppGroupIdentifier },
@@ -1191,6 +1241,7 @@ function extractNativeAppIdentityFromFiles(files, platform, parseInfoPlist, iosT
1191
1241
  getAppliedNativeAppIdentity,
1192
1242
  insertNativeAppIdentityFooter,
1193
1243
  isNativeAppIdentity,
1244
+ readGoogleSignInConfiguration,
1194
1245
  readNativeAppIdentity,
1195
1246
  readNativeAppIdentityFooter,
1196
1247
  readNativeAppIdentityFromBundle,
@@ -1,4 +1,4 @@
1
- /*! peach v0.1.1625 | (c) 2026 Tamagui LLC | Proprietary; see LICENSE */
1
+ /*! peach v0.1.1640 | (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,30 +485,33 @@ 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;
493
+ for (const key of ["statusBarHidden", "viewControllerBasedStatusBarAppearance"]) {
494
+ if (value[key] !== void 0 && typeof value[key] !== "boolean") return false;
495
+ }
494
496
  const oneUpdates = value.oneUpdates;
495
- 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))) {
496
498
  return false;
497
499
  }
498
500
  if (value.dtPlatformVersion !== void 0 && typeof value.dtPlatformVersion !== "string")
499
501
  return false;
500
502
  if (value.androidManifestPermissions !== void 0 && (!Array.isArray(value.androidManifestPermissions) || !value.androidManifestPermissions.every(
501
- (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)
502
504
  )))
503
505
  return false;
506
+ if (value.googleSignIn !== void 0 && !isRecord(value.googleSignIn)) return false;
504
507
  const descriptions = value.permissionUsageDescriptions;
505
- 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(
506
509
  (flag) => typeof flag === "boolean"
507
510
  )))
508
511
  return false;
509
- if (descriptions !== void 0 && !isRecord2(descriptions)) return false;
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")))
514
+ return false;
510
515
  if (value.urlQuerySchemes !== void 0 && !Array.isArray(value.urlQuerySchemes))
511
516
  return false;
512
517
  if (value.appIntentIdentifiers !== void 0 && (!Array.isArray(value.appIntentIdentifiers) || !value.appIntentIdentifiers.every((identifier) => typeof identifier === "string")))
@@ -568,6 +573,10 @@ function readNativeAppIdentity(value) {
568
573
  ...value.rootModuleName === void 0 ? {} : { rootModuleName: value.rootModuleName },
569
574
  ...value.rootViewBackgroundColor === void 0 ? {} : { rootViewBackgroundColor: value.rootViewBackgroundColor },
570
575
  ...value.designRequiresCompatibility === void 0 ? {} : { designRequiresCompatibility: value.designRequiresCompatibility },
576
+ ...value.statusBarHidden === void 0 ? {} : { statusBarHidden: value.statusBarHidden },
577
+ ...value.viewControllerBasedStatusBarAppearance === void 0 ? {} : {
578
+ viewControllerBasedStatusBarAppearance: value.viewControllerBasedStatusBarAppearance
579
+ },
571
580
  ...value.dtPlatformVersion === void 0 ? {} : { dtPlatformVersion: value.dtPlatformVersion },
572
581
  ...value.bundleName === void 0 ? {} : { bundleName: value.bundleName },
573
582
  appVersion: value.appVersion,
@@ -582,9 +591,11 @@ function readNativeAppIdentity(value) {
582
591
  (permission) => ({ ...permission })
583
592
  )
584
593
  },
594
+ ...value.googleSignIn === void 0 ? {} : { googleSignIn: structuredClone(value.googleSignIn) },
585
595
  ...value.permissionUsageDescriptions === void 0 ? {} : {
586
596
  permissionUsageDescriptions: { ...value.permissionUsageDescriptions }
587
597
  },
598
+ ...value.infoPlistStrings === void 0 ? {} : { infoPlistStrings: { ...value.infoPlistStrings } },
588
599
  ...value.appIntentIdentifiers === void 0 ? {} : { appIntentIdentifiers: [...value.appIntentIdentifiers] },
589
600
  ...value.backgroundTaskIdentifiers === void 0 ? {} : { backgroundTaskIdentifiers: [...value.backgroundTaskIdentifiers] },
590
601
  ...value.supportedInterfaceOrientations === void 0 ? {} : {
@@ -619,7 +630,7 @@ function equalIdentityValues(left, right) {
619
630
  if (Array.isArray(left) && Array.isArray(right)) {
620
631
  return left.length === right.length && left.every((value, index) => equalIdentityValues(value, right[index]));
621
632
  }
622
- if (!isRecord2(left) || !isRecord2(right)) return false;
633
+ if (!isRecord(left) || !isRecord(right)) return false;
623
634
  const keys = Object.keys(left);
624
635
  return keys.length === Object.keys(right).length && keys.every(
625
636
  (key) => Object.hasOwn(right, key) && equalIdentityValues(left[key], right[key])
@@ -706,6 +717,27 @@ function insertNativeAppIdentityFooter(source, identity) {
706
717
  if (moduleFooter < 0) return withoutExisting + footer;
707
718
  return withoutExisting.slice(0, moduleFooter) + footer + withoutExisting.slice(moduleFooter);
708
719
  }
720
+ function readGoogleSignInConfiguration(plist, resources) {
721
+ const clientIds = {};
722
+ for (const [file, value] of Object.entries(resources)) {
723
+ if (isRecord(value) && typeof value.CLIENT_ID === "string")
724
+ clientIds[file.split("/").pop()?.replace(/\.plist$/, "") ?? file] = value.CLIENT_ID;
725
+ }
726
+ const urlSchemes = [];
727
+ for (const entry of Array.isArray(plist.CFBundleURLTypes) ? plist.CFBundleURLTypes : []) {
728
+ if (!isRecord(entry) || !Array.isArray(entry.CFBundleURLSchemes)) continue;
729
+ for (const scheme of entry.CFBundleURLSchemes)
730
+ if (typeof scheme === "string") urlSchemes.push(scheme);
731
+ }
732
+ return {
733
+ clientId: plist.GIDClientID,
734
+ serverClientId: plist.GIDServerClientID,
735
+ hostedDomain: plist.GIDHostedDomain,
736
+ openIDRealm: plist.GIDOpenIDRealm,
737
+ urlSchemes,
738
+ clientIds
739
+ };
740
+ }
709
741
  function plistString(plist, key) {
710
742
  const match = plist.match(new RegExp(`<key>${key}</key>\\s*<string>([^<]*)</string>`));
711
743
  return match ? match[1].trim() : null;
@@ -801,14 +833,14 @@ function nativeAppIdentityFromIos(files, parseInfoPlist, iosTarget, resourceUri)
801
833
  let objects = {};
802
834
  try {
803
835
  const parsed = parseOpenStepPlist(pbxproj);
804
- if (isRecord2(parsed)) {
805
- objects = isRecord2(parsed.objects) ? parsed.objects : parsed;
836
+ if (isRecord(parsed)) {
837
+ objects = isRecord(parsed.objects) ? parsed.objects : parsed;
806
838
  }
807
839
  } catch {
808
840
  }
809
841
  const targets = [];
810
842
  for (const [id, obj] of Object.entries(objects)) {
811
- if (isRecord2(obj) && obj.isa === "PBXNativeTarget" && typeof obj.name === "string") {
843
+ if (isRecord(obj) && obj.isa === "PBXNativeTarget" && typeof obj.name === "string") {
812
844
  targets.push({
813
845
  id,
814
846
  name: obj.name,
@@ -854,13 +886,13 @@ function nativeAppIdentityFromIos(files, parseInfoPlist, iosTarget, resourceUri)
854
886
  PRODUCT_NAME: targetName
855
887
  };
856
888
  for (const obj of Object.values(objects)) {
857
- if (isRecord2(obj) && obj.isa === "PBXProject" && typeof obj.buildConfigurationList === "string") {
889
+ if (isRecord(obj) && obj.isa === "PBXProject" && typeof obj.buildConfigurationList === "string") {
858
890
  const listObj = objects[obj.buildConfigurationList];
859
- if (isRecord2(listObj) && Array.isArray(listObj.buildConfigurations)) {
891
+ if (isRecord(listObj) && Array.isArray(listObj.buildConfigurations)) {
860
892
  for (const configId of listObj.buildConfigurations) {
861
893
  if (typeof configId === "string") {
862
894
  const configObj = objects[configId];
863
- if (isRecord2(configObj) && configObj.name === "Release" && isRecord2(configObj.buildSettings)) {
895
+ if (isRecord(configObj) && configObj.name === "Release" && isRecord(configObj.buildSettings)) {
864
896
  for (const [k, v] of Object.entries(configObj.buildSettings)) {
865
897
  if (typeof v === "string") settings[k] = v;
866
898
  }
@@ -872,11 +904,11 @@ function nativeAppIdentityFromIos(files, parseInfoPlist, iosTarget, resourceUri)
872
904
  }
873
905
  if (selectedTarget?.buildConfigurationList) {
874
906
  const listObj = objects[selectedTarget.buildConfigurationList];
875
- if (isRecord2(listObj) && Array.isArray(listObj.buildConfigurations)) {
907
+ if (isRecord(listObj) && Array.isArray(listObj.buildConfigurations)) {
876
908
  for (const configId of listObj.buildConfigurations) {
877
909
  if (typeof configId === "string") {
878
910
  const configObj = objects[configId];
879
- if (isRecord2(configObj) && configObj.name === "Release" && isRecord2(configObj.buildSettings)) {
911
+ if (isRecord(configObj) && configObj.name === "Release" && isRecord(configObj.buildSettings)) {
880
912
  for (const [k, v] of Object.entries(configObj.buildSettings)) {
881
913
  if (typeof v === "string") settings[k] = v;
882
914
  }
@@ -927,7 +959,7 @@ function nativeAppIdentityFromIos(files, parseInfoPlist, iosTarget, resourceUri)
927
959
  if (!bundleName) return null;
928
960
  const applicationName = identityFieldFrom(settings, plistString(plist, "CFBundleDisplayName"), void 0) ?? bundleName;
929
961
  const dictionary = parseInfoPlist(plist);
930
- 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");
931
963
  const declaredDisplayName = dictionary.CFBundleDisplayName;
932
964
  const applicationDisplayName = typeof declaredDisplayName === "string" ? resolveBuildSetting(declaredDisplayName, settings) : void 0;
933
965
  if (applicationDisplayName === null)
@@ -940,9 +972,9 @@ function nativeAppIdentityFromIos(files, parseInfoPlist, iosTarget, resourceUri)
940
972
  if (dtPlatformVersion === null)
941
973
  throw new Error("native app Info.plist DTPlatformVersion is unresolved");
942
974
  const icons = dictionary.CFBundleIcons;
943
- const alternates = isRecord2(icons) ? icons.CFBundleAlternateIcons : void 0;
975
+ const alternates = isRecord(icons) ? icons.CFBundleAlternateIcons : void 0;
944
976
  const alternateIconNames = /* @__PURE__ */ new Set();
945
- for (const name of isRecord2(alternates) ? Object.keys(alternates) : []) {
977
+ for (const name of isRecord(alternates) ? Object.keys(alternates) : []) {
946
978
  const resolved = resolveBuildSetting(name, settings);
947
979
  if (resolved === null) throw new Error("native alternate icon name is unresolved");
948
980
  alternateIconNames.add(resolved);
@@ -1015,6 +1047,12 @@ function nativeAppIdentityFromIos(files, parseInfoPlist, iosTarget, resourceUri)
1015
1047
  if (resolved === null) throw new Error(`native app Info.plist ${key} is unresolved`);
1016
1048
  permissionUsageDescriptions[key] = resolved;
1017
1049
  }
1050
+ const infoPlistStrings = {};
1051
+ for (const [key, value] of Object.entries(dictionary)) {
1052
+ if (typeof value !== "string") continue;
1053
+ const resolved = resolveBuildSetting(value, settings);
1054
+ if (resolved !== null) infoPlistStrings[key] = resolved;
1055
+ }
1018
1056
  if (settings.GENERATE_INFOPLIST_FILE === "YES") {
1019
1057
  for (const [setting, value] of Object.entries(settings)) {
1020
1058
  if (!/^INFOPLIST_KEY_NS.*UsageDescription$/.test(setting)) continue;
@@ -1040,11 +1078,11 @@ function nativeAppIdentityFromIos(files, parseInfoPlist, iosTarget, resourceUri)
1040
1078
  return `${base.startsWith("/") ? "/" : ""}${segments.join("/")}`;
1041
1079
  };
1042
1080
  const project = Object.values(objects).find(
1043
- (object) => isRecord2(object) && object.isa === "PBXProject"
1081
+ (object) => isRecord(object) && object.isa === "PBXProject"
1044
1082
  );
1045
1083
  const projectDir = join(
1046
1084
  pbxprojPath.replace(/(?:^|\/)[^/]+\.xcodeproj\/project\.pbxproj$/, ""),
1047
- isRecord2(project) && typeof project.projectDirPath === "string" ? project.projectDirPath : ""
1085
+ isRecord(project) && typeof project.projectDirPath === "string" ? project.projectDirPath : ""
1048
1086
  );
1049
1087
  const paths = Object.keys(files);
1050
1088
  visitXcodeTargetMembers(
@@ -1075,12 +1113,22 @@ function nativeAppIdentityFromIos(files, parseInfoPlist, iosTarget, resourceUri)
1075
1113
  ...rootModuleName === void 0 ? {} : { rootModuleName },
1076
1114
  ...rootViewBackgroundColor === void 0 ? {} : { rootViewBackgroundColor },
1077
1115
  ...designRequiresCompatibility ? { designRequiresCompatibility } : {},
1116
+ ...typeof dictionary.UIStatusBarHidden === "boolean" ? { statusBarHidden: dictionary.UIStatusBarHidden } : {},
1117
+ ...typeof dictionary.UIViewControllerBasedStatusBarAppearance === "boolean" ? {
1118
+ viewControllerBasedStatusBarAppearance: dictionary.UIViewControllerBasedStatusBarAppearance
1119
+ } : {},
1078
1120
  ...dtPlatformVersion === void 0 ? {} : { dtPlatformVersion },
1079
1121
  bundleName,
1080
1122
  appVersion,
1081
1123
  buildVersion,
1082
1124
  bundleIdentifier,
1083
1125
  platform: "ios",
1126
+ googleSignIn: readGoogleSignInConfiguration(
1127
+ dictionary,
1128
+ Object.fromEntries(
1129
+ [...resources].filter((file) => file.endsWith(".plist") && files[file]).map((file) => [file, parseInfoPlist(files[file])])
1130
+ )
1131
+ ),
1084
1132
  supportedInterfaceOrientations,
1085
1133
  ipadSupportedInterfaceOrientations,
1086
1134
  ...defaultScreenOrientationMask === void 0 ? {} : { defaultScreenOrientationMask },
@@ -1102,6 +1150,7 @@ function nativeAppIdentityFromIos(files, parseInfoPlist, iosTarget, resourceUri)
1102
1150
  )
1103
1151
  } : {},
1104
1152
  permissionUsageDescriptions,
1153
+ infoPlistStrings,
1105
1154
  urlQuerySchemes,
1106
1155
  ...shareIntoAppGroupId === void 0 ? {} : { shareIntoAppGroupId },
1107
1156
  ...rtcAppGroupIdentifier === void 0 ? {} : { rtcAppGroupIdentifier },
@@ -1149,6 +1198,7 @@ export {
1149
1198
  getAppliedNativeAppIdentity,
1150
1199
  insertNativeAppIdentityFooter,
1151
1200
  isNativeAppIdentity,
1201
+ readGoogleSignInConfiguration,
1152
1202
  readNativeAppIdentity,
1153
1203
  readNativeAppIdentityFooter,
1154
1204
  readNativeAppIdentityFromBundle,
@@ -1,4 +1,4 @@
1
- /*! peach v0.1.1625 | (c) 2026 Tamagui LLC | Proprietary; see LICENSE */
1
+ /*! peach v0.1.1640 | (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.1625 | (c) 2026 Tamagui LLC | Proprietary; see LICENSE */
1
+ /*! peach v0.1.1640 | (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.1625 | (c) 2026 Tamagui LLC | Proprietary; see LICENSE */
1
+ /*! peach v0.1.1640 | (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.1625 | (c) 2026 Tamagui LLC | Proprietary; see LICENSE */
1
+ /*! peach v0.1.1640 | (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.1625 | (c) 2026 Tamagui LLC | Proprietary; see LICENSE */
1
+ /*! peach v0.1.1640 | (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.1625 | (c) 2026 Tamagui LLC | Proprietary; see LICENSE */
1
+ /*! peach v0.1.1640 | (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.1625 | (c) 2026 Tamagui LLC | Proprietary; see LICENSE */
1
+ /*! peach v0.1.1640 | (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;
@@ -39,6 +39,10 @@ var REACT_NATIVE_PASSTHROUGH_SPECIFIERS = [
39
39
  // expo's metro-runtime dials metro's message socket with this WebSocket,
40
40
  // which runs against the engine's WebSocketModule and BlobModule.
41
41
  "react-native/Libraries/WebSocket",
42
+ // that WebSocket extends upstream's EventTarget and builds its MessageEvent
43
+ // and CloseEvent from the same dom event classes; a stubbed class there is
44
+ // not a constructor to extend.
45
+ "react-native/src/private/webapis",
42
46
  "react-native/Libraries/Blob/Blob",
43
47
  "react-native/Libraries/Blob/BlobManager",
44
48
  "react-native/Libraries/Blob/BlobRegistry",
@@ -60,7 +64,7 @@ var REACT_NATIVE_PASSTHROUGH_SPECIFIERS = [
60
64
  ];
61
65
  function isReactNativePassthroughSpecifier(specifier) {
62
66
  return REACT_NATIVE_PASSTHROUGH_SPECIFIERS.some(
63
- (passthrough) => specifier === passthrough || specifier.startsWith(`${passthrough}/`)
67
+ (passthrough) => specifier.startsWith(passthrough) && (specifier.length === passthrough.length || specifier[passthrough.length] === "/")
64
68
  );
65
69
  }
66
70
  // Annotate the CommonJS export names for ESM import in node:
@@ -1,4 +1,4 @@
1
- /*! peach v0.1.1625 | (c) 2026 Tamagui LLC | Proprietary; see LICENSE */
1
+ /*! peach v0.1.1640 | (c) 2026 Tamagui LLC | Proprietary; see LICENSE */
2
2
 
3
3
  // src/react-native-host-modules.ts
4
4
  var REACT_NATIVE_PASSTHROUGH_SPECIFIERS = [
@@ -14,6 +14,10 @@ var REACT_NATIVE_PASSTHROUGH_SPECIFIERS = [
14
14
  // expo's metro-runtime dials metro's message socket with this WebSocket,
15
15
  // which runs against the engine's WebSocketModule and BlobModule.
16
16
  "react-native/Libraries/WebSocket",
17
+ // that WebSocket extends upstream's EventTarget and builds its MessageEvent
18
+ // and CloseEvent from the same dom event classes; a stubbed class there is
19
+ // not a constructor to extend.
20
+ "react-native/src/private/webapis",
17
21
  "react-native/Libraries/Blob/Blob",
18
22
  "react-native/Libraries/Blob/BlobManager",
19
23
  "react-native/Libraries/Blob/BlobRegistry",
@@ -35,7 +39,7 @@ var REACT_NATIVE_PASSTHROUGH_SPECIFIERS = [
35
39
  ];
36
40
  function isReactNativePassthroughSpecifier(specifier) {
37
41
  return REACT_NATIVE_PASSTHROUGH_SPECIFIERS.some(
38
- (passthrough) => specifier === passthrough || specifier.startsWith(`${passthrough}/`)
42
+ (passthrough) => specifier.startsWith(passthrough) && (specifier.length === passthrough.length || specifier[passthrough.length] === "/")
39
43
  );
40
44
  }
41
45
  export {