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 __create = Object.create;
@@ -1578,10 +1578,12 @@ function androidMergedResourceValuesDirectory(manifestFile) {
1578
1578
  return `${intermediates}incremental/${variant}/merge${taskVariant}Resources/merged.dir`;
1579
1579
  }
1580
1580
 
1581
- // src/nativeAppIconContract.ts
1581
+ // src/is-record.ts
1582
1582
  function isRecord(value) {
1583
1583
  return typeof value === "object" && value !== null && !Array.isArray(value);
1584
1584
  }
1585
+
1586
+ // src/nativeAppIconContract.ts
1585
1587
  function resolveNativeAppIconArtwork(resources, readText, resourceUri, icons, primaryName, alternateNames, resolveReference) {
1586
1588
  const members = new Set(resources);
1587
1589
  const dictionary = isRecord(icons) ? icons : {};
@@ -1835,12 +1837,30 @@ function visitXcodeTargetMembers(objects, targetId, resolvePath, filesUnder, joi
1835
1837
  }
1836
1838
 
1837
1839
  // src/native-app-identity.ts
1838
- function isRecord2(value) {
1839
- return typeof value === "object" && value !== null && !Array.isArray(value);
1840
- }
1841
1840
  function nonEmptyString(value) {
1842
1841
  return typeof value === "string" && value.length > 0 ? value : null;
1843
1842
  }
1843
+ function readGoogleSignInConfiguration(plist3, resources) {
1844
+ const clientIds = {};
1845
+ for (const [file, value] of Object.entries(resources)) {
1846
+ if (isRecord(value) && typeof value.CLIENT_ID === "string")
1847
+ clientIds[file.split("/").pop()?.replace(/\.plist$/, "") ?? file] = value.CLIENT_ID;
1848
+ }
1849
+ const urlSchemes = [];
1850
+ for (const entry of Array.isArray(plist3.CFBundleURLTypes) ? plist3.CFBundleURLTypes : []) {
1851
+ if (!isRecord(entry) || !Array.isArray(entry.CFBundleURLSchemes)) continue;
1852
+ for (const scheme of entry.CFBundleURLSchemes)
1853
+ if (typeof scheme === "string") urlSchemes.push(scheme);
1854
+ }
1855
+ return {
1856
+ clientId: plist3.GIDClientID,
1857
+ serverClientId: plist3.GIDServerClientID,
1858
+ hostedDomain: plist3.GIDHostedDomain,
1859
+ openIDRealm: plist3.GIDOpenIDRealm,
1860
+ urlSchemes,
1861
+ clientIds
1862
+ };
1863
+ }
1844
1864
  function plistString(plist3, key) {
1845
1865
  const match = plist3.match(new RegExp(`<key>${key}</key>\\s*<string>([^<]*)</string>`));
1846
1866
  return match ? match[1].trim() : null;
@@ -1936,14 +1956,14 @@ function nativeAppIdentityFromIos(files, parseInfoPlist, iosTarget, resourceUri)
1936
1956
  let objects = {};
1937
1957
  try {
1938
1958
  const parsed = parseOpenStepPlist(pbxproj);
1939
- if (isRecord2(parsed)) {
1940
- objects = isRecord2(parsed.objects) ? parsed.objects : parsed;
1959
+ if (isRecord(parsed)) {
1960
+ objects = isRecord(parsed.objects) ? parsed.objects : parsed;
1941
1961
  }
1942
1962
  } catch {
1943
1963
  }
1944
1964
  const targets = [];
1945
1965
  for (const [id, obj] of Object.entries(objects)) {
1946
- if (isRecord2(obj) && obj.isa === "PBXNativeTarget" && typeof obj.name === "string") {
1966
+ if (isRecord(obj) && obj.isa === "PBXNativeTarget" && typeof obj.name === "string") {
1947
1967
  targets.push({
1948
1968
  id,
1949
1969
  name: obj.name,
@@ -1989,13 +2009,13 @@ function nativeAppIdentityFromIos(files, parseInfoPlist, iosTarget, resourceUri)
1989
2009
  PRODUCT_NAME: targetName
1990
2010
  };
1991
2011
  for (const obj of Object.values(objects)) {
1992
- if (isRecord2(obj) && obj.isa === "PBXProject" && typeof obj.buildConfigurationList === "string") {
2012
+ if (isRecord(obj) && obj.isa === "PBXProject" && typeof obj.buildConfigurationList === "string") {
1993
2013
  const listObj = objects[obj.buildConfigurationList];
1994
- if (isRecord2(listObj) && Array.isArray(listObj.buildConfigurations)) {
2014
+ if (isRecord(listObj) && Array.isArray(listObj.buildConfigurations)) {
1995
2015
  for (const configId of listObj.buildConfigurations) {
1996
2016
  if (typeof configId === "string") {
1997
2017
  const configObj = objects[configId];
1998
- if (isRecord2(configObj) && configObj.name === "Release" && isRecord2(configObj.buildSettings)) {
2018
+ if (isRecord(configObj) && configObj.name === "Release" && isRecord(configObj.buildSettings)) {
1999
2019
  for (const [k, v] of Object.entries(configObj.buildSettings)) {
2000
2020
  if (typeof v === "string") settings[k] = v;
2001
2021
  }
@@ -2007,11 +2027,11 @@ function nativeAppIdentityFromIos(files, parseInfoPlist, iosTarget, resourceUri)
2007
2027
  }
2008
2028
  if (selectedTarget?.buildConfigurationList) {
2009
2029
  const listObj = objects[selectedTarget.buildConfigurationList];
2010
- if (isRecord2(listObj) && Array.isArray(listObj.buildConfigurations)) {
2030
+ if (isRecord(listObj) && Array.isArray(listObj.buildConfigurations)) {
2011
2031
  for (const configId of listObj.buildConfigurations) {
2012
2032
  if (typeof configId === "string") {
2013
2033
  const configObj = objects[configId];
2014
- if (isRecord2(configObj) && configObj.name === "Release" && isRecord2(configObj.buildSettings)) {
2034
+ if (isRecord(configObj) && configObj.name === "Release" && isRecord(configObj.buildSettings)) {
2015
2035
  for (const [k, v] of Object.entries(configObj.buildSettings)) {
2016
2036
  if (typeof v === "string") settings[k] = v;
2017
2037
  }
@@ -2062,7 +2082,7 @@ function nativeAppIdentityFromIos(files, parseInfoPlist, iosTarget, resourceUri)
2062
2082
  if (!bundleName) return null;
2063
2083
  const applicationName = identityFieldFrom(settings, plistString(plist3, "CFBundleDisplayName"), void 0) ?? bundleName;
2064
2084
  const dictionary = parseInfoPlist(plist3);
2065
- if (!isRecord2(dictionary)) throw new Error("native app Info.plist is not a dictionary");
2085
+ if (!isRecord(dictionary)) throw new Error("native app Info.plist is not a dictionary");
2066
2086
  const declaredDisplayName = dictionary.CFBundleDisplayName;
2067
2087
  const applicationDisplayName = typeof declaredDisplayName === "string" ? resolveBuildSetting(declaredDisplayName, settings) : void 0;
2068
2088
  if (applicationDisplayName === null)
@@ -2075,9 +2095,9 @@ function nativeAppIdentityFromIos(files, parseInfoPlist, iosTarget, resourceUri)
2075
2095
  if (dtPlatformVersion === null)
2076
2096
  throw new Error("native app Info.plist DTPlatformVersion is unresolved");
2077
2097
  const icons = dictionary.CFBundleIcons;
2078
- const alternates = isRecord2(icons) ? icons.CFBundleAlternateIcons : void 0;
2098
+ const alternates = isRecord(icons) ? icons.CFBundleAlternateIcons : void 0;
2079
2099
  const alternateIconNames = /* @__PURE__ */ new Set();
2080
- for (const name of isRecord2(alternates) ? Object.keys(alternates) : []) {
2100
+ for (const name of isRecord(alternates) ? Object.keys(alternates) : []) {
2081
2101
  const resolved = resolveBuildSetting(name, settings);
2082
2102
  if (resolved === null) throw new Error("native alternate icon name is unresolved");
2083
2103
  alternateIconNames.add(resolved);
@@ -2150,6 +2170,12 @@ function nativeAppIdentityFromIos(files, parseInfoPlist, iosTarget, resourceUri)
2150
2170
  if (resolved === null) throw new Error(`native app Info.plist ${key} is unresolved`);
2151
2171
  permissionUsageDescriptions[key] = resolved;
2152
2172
  }
2173
+ const infoPlistStrings = {};
2174
+ for (const [key, value] of Object.entries(dictionary)) {
2175
+ if (typeof value !== "string") continue;
2176
+ const resolved = resolveBuildSetting(value, settings);
2177
+ if (resolved !== null) infoPlistStrings[key] = resolved;
2178
+ }
2153
2179
  if (settings.GENERATE_INFOPLIST_FILE === "YES") {
2154
2180
  for (const [setting, value] of Object.entries(settings)) {
2155
2181
  if (!/^INFOPLIST_KEY_NS.*UsageDescription$/.test(setting)) continue;
@@ -2175,11 +2201,11 @@ function nativeAppIdentityFromIos(files, parseInfoPlist, iosTarget, resourceUri)
2175
2201
  return `${base.startsWith("/") ? "/" : ""}${segments.join("/")}`;
2176
2202
  };
2177
2203
  const project = Object.values(objects).find(
2178
- (object) => isRecord2(object) && object.isa === "PBXProject"
2204
+ (object) => isRecord(object) && object.isa === "PBXProject"
2179
2205
  );
2180
2206
  const projectDir = join(
2181
2207
  pbxprojPath.replace(/(?:^|\/)[^/]+\.xcodeproj\/project\.pbxproj$/, ""),
2182
- isRecord2(project) && typeof project.projectDirPath === "string" ? project.projectDirPath : ""
2208
+ isRecord(project) && typeof project.projectDirPath === "string" ? project.projectDirPath : ""
2183
2209
  );
2184
2210
  const paths = Object.keys(files);
2185
2211
  visitXcodeTargetMembers(
@@ -2210,12 +2236,22 @@ function nativeAppIdentityFromIos(files, parseInfoPlist, iosTarget, resourceUri)
2210
2236
  ...rootModuleName === void 0 ? {} : { rootModuleName },
2211
2237
  ...rootViewBackgroundColor === void 0 ? {} : { rootViewBackgroundColor },
2212
2238
  ...designRequiresCompatibility ? { designRequiresCompatibility } : {},
2239
+ ...typeof dictionary.UIStatusBarHidden === "boolean" ? { statusBarHidden: dictionary.UIStatusBarHidden } : {},
2240
+ ...typeof dictionary.UIViewControllerBasedStatusBarAppearance === "boolean" ? {
2241
+ viewControllerBasedStatusBarAppearance: dictionary.UIViewControllerBasedStatusBarAppearance
2242
+ } : {},
2213
2243
  ...dtPlatformVersion === void 0 ? {} : { dtPlatformVersion },
2214
2244
  bundleName,
2215
2245
  appVersion,
2216
2246
  buildVersion,
2217
2247
  bundleIdentifier,
2218
2248
  platform: "ios",
2249
+ googleSignIn: readGoogleSignInConfiguration(
2250
+ dictionary,
2251
+ Object.fromEntries(
2252
+ [...resources].filter((file) => file.endsWith(".plist") && files[file]).map((file) => [file, parseInfoPlist(files[file])])
2253
+ )
2254
+ ),
2219
2255
  supportedInterfaceOrientations,
2220
2256
  ipadSupportedInterfaceOrientations,
2221
2257
  ...defaultScreenOrientationMask === void 0 ? {} : { defaultScreenOrientationMask },
@@ -2237,6 +2273,7 @@ function nativeAppIdentityFromIos(files, parseInfoPlist, iosTarget, resourceUri)
2237
2273
  )
2238
2274
  } : {},
2239
2275
  permissionUsageDescriptions,
2276
+ infoPlistStrings,
2240
2277
  urlQuerySchemes,
2241
2278
  ...shareIntoAppGroupId === void 0 ? {} : { shareIntoAppGroupId },
2242
2279
  ...rtcAppGroupIdentifier === void 0 ? {} : { rtcAppGroupIdentifier },
@@ -2281,6 +2318,8 @@ function parsePlistSource(source) {
2281
2318
  }
2282
2319
 
2283
2320
  // src/xcode-project.ts
2321
+ var import_node_child_process = require("node:child_process");
2322
+ var import_node_crypto = require("node:crypto");
2284
2323
  var import_node_fs = __toESM(require("node:fs"), 1);
2285
2324
  var import_node_path2 = __toESM(require("node:path"), 1);
2286
2325
  var import_plist2 = __toESM(require_plist(), 1);
@@ -2888,33 +2927,131 @@ function expand(value, lookup) {
2888
2927
  }
2889
2928
  );
2890
2929
  }
2891
- function targetMembers(ref, settings, options = {}) {
2930
+ var preparedSourcePhases = /* @__PURE__ */ new Map();
2931
+ function targetMembers(ref, settings, options, settingKeys, projectInputs) {
2892
2932
  const { project, target, id: targetId } = ref;
2893
2933
  const targetName = str(target.name) ?? targetId;
2894
2934
  const sources = /* @__PURE__ */ new Set();
2895
2935
  const allSources = /* @__PURE__ */ new Set();
2896
2936
  const resources = /* @__PURE__ */ new Set();
2897
2937
  const scriptForOutput = /* @__PURE__ */ new Map();
2898
- const noteScriptOutput = (raw, script) => {
2899
- const expanded = expand(raw, settings);
2900
- if (!expanded.endsWith(".swift")) return;
2901
- const absolute = import_node_path2.default.isAbsolute(expanded) ? import_node_path2.default.normalize(expanded) : import_node_path2.default.resolve(project.projectDir, expanded);
2902
- if (!scriptForOutput.has(absolute)) scriptForOutput.set(absolute, script);
2903
- };
2904
2938
  for (const phaseId of list(target.buildPhases)) {
2905
2939
  const phase = project.object(phaseId);
2906
2940
  if (phase?.isa !== "PBXShellScriptBuildPhase") continue;
2907
2941
  const script = str(phase.name) ?? phaseId;
2908
- for (const raw of list(phase.outputPaths)) noteScriptOutput(raw, script);
2909
- for (const listPath of list(phase.outputFileListPaths)) {
2910
- const expandedList = expand(listPath, settings);
2911
- const absoluteList = import_node_path2.default.isAbsolute(expandedList) ? expandedList : import_node_path2.default.resolve(project.projectDir, expandedList);
2912
- if (!import_node_fs.default.existsSync(absoluteList)) continue;
2913
- for (const line of import_node_fs.default.readFileSync(absoluteList, "utf8").split("\n")) {
2914
- const trimmed = line.trim();
2915
- if (trimmed === "" || trimmed.startsWith("#")) continue;
2916
- noteScriptOutput(trimmed, script);
2942
+ const absolute = (raw) => import_node_path2.default.resolve(project.projectDir, expand(raw, settings));
2943
+ const inputs = list(phase.inputPaths).map(absolute);
2944
+ const outputs = list(phase.outputPaths).map(absolute);
2945
+ const fileLists = /* @__PURE__ */ new Map();
2946
+ for (const kind of ["INPUT", "OUTPUT"]) {
2947
+ const lists = list(
2948
+ kind === "INPUT" ? phase.inputFileListPaths : phase.outputFileListPaths
2949
+ ).map((raw) => {
2950
+ const file = absolute(raw);
2951
+ if (!import_node_fs.default.existsSync(file)) {
2952
+ return { file, entries: [] };
2953
+ }
2954
+ const entries = import_node_fs.default.readFileSync(file, "utf8").split(/\r?\n/).map((line) => line.trim()).filter((line) => line !== "" && !line.startsWith("#")).map(absolute);
2955
+ return { file, entries };
2956
+ });
2957
+ fileLists.set(kind, lists);
2958
+ }
2959
+ const allOutputs = [
2960
+ ...outputs,
2961
+ ...fileLists.get("OUTPUT").flatMap((item) => item.entries)
2962
+ ];
2963
+ for (const output of allOutputs)
2964
+ if (output.endsWith(".swift") && !scriptForOutput.has(output))
2965
+ scriptForOutput.set(output, script);
2966
+ const inputFiles = [
2967
+ ...inputs,
2968
+ ...fileLists.get("INPUT").flatMap((item) => [item.file, ...item.entries]),
2969
+ ...fileLists.get("OUTPUT").map((item) => item.file)
2970
+ ];
2971
+ if (allOutputs.some((file) => file.endsWith(".swift"))) {
2972
+ for (const file of inputFiles) if (import_node_fs.default.existsSync(file)) projectInputs.add(file);
2973
+ }
2974
+ if (options.prepareGeneratedSources && options.requireSources !== false && allOutputs.some((file) => file.endsWith(".swift"))) {
2975
+ const phaseDir = import_node_path2.default.join(settings("TARGET_TEMP_DIR"), `Script-${phaseId}`);
2976
+ for (const lists of fileLists.values())
2977
+ for (const { file } of lists)
2978
+ if (!import_node_fs.default.existsSync(file))
2979
+ throw new Error(
2980
+ `${targetName}: Run Script "${script}" missing file list ${file}`
2981
+ );
2982
+ const env = {
2983
+ ...process.env,
2984
+ ...Object.fromEntries(
2985
+ [...settingKeys].filter((key2) => /^[A-Za-z_][A-Za-z0-9_]*$/.test(key2)).map((key2) => [key2, settings(key2)])
2986
+ )
2987
+ };
2988
+ const declared = { INPUT: inputs, OUTPUT: outputs };
2989
+ for (const kind of ["INPUT", "OUTPUT"]) {
2990
+ env[`SCRIPT_${kind}_FILE_COUNT`] = String(declared[kind].length);
2991
+ declared[kind].forEach((file, index) => {
2992
+ env[`SCRIPT_${kind}_FILE_${index}`] = file;
2993
+ });
2994
+ const lists = fileLists.get(kind);
2995
+ env[`SCRIPT_${kind}_FILE_LIST_COUNT`] = String(lists.length);
2996
+ lists.forEach((_item, index) => {
2997
+ env[`SCRIPT_${kind}_FILE_LIST_${index}`] = import_node_path2.default.join(
2998
+ phaseDir,
2999
+ `${kind}-${index}.xcfilelist`
3000
+ );
3001
+ });
2917
3002
  }
3003
+ const signature = (0, import_node_crypto.createHash)("sha256").update(
3004
+ JSON.stringify([phase, [...settingKeys].map((key2) => [key2, settings(key2)])])
3005
+ );
3006
+ for (const file of inputFiles) {
3007
+ signature.update(file);
3008
+ if (import_node_fs.default.existsSync(file)) {
3009
+ const stat = import_node_fs.default.statSync(file);
3010
+ signature.update(`${stat.mtimeMs}:${stat.ctimeMs}:${stat.size}`);
3011
+ } else signature.update("missing");
3012
+ }
3013
+ const stamp = signature.digest("hex");
3014
+ const key = `${project.projectFile}:${targetId}:${phaseId}:${settings("CONFIGURATION")}`;
3015
+ if (preparedSourcePhases.get(key) === stamp && allOutputs.every((file) => import_node_fs.default.existsSync(file)))
3016
+ continue;
3017
+ import_node_fs.default.mkdirSync(phaseDir, { recursive: true });
3018
+ import_node_fs.default.mkdirSync(settings("BUILT_PRODUCTS_DIR"), { recursive: true });
3019
+ import_node_fs.default.mkdirSync(settings("DERIVED_FILE_DIR"), { recursive: true });
3020
+ for (const [kind, lists] of fileLists)
3021
+ lists.forEach((item, index) => {
3022
+ import_node_fs.default.writeFileSync(
3023
+ env[`SCRIPT_${kind}_FILE_LIST_${index}`],
3024
+ `${item.entries.join("\n")}
3025
+ `
3026
+ );
3027
+ });
3028
+ try {
3029
+ (0, import_node_child_process.execFileSync)(
3030
+ str(phase.shellPath) ?? "/bin/sh",
3031
+ ["-c", str(phase.shellScript) ?? ""],
3032
+ {
3033
+ cwd: project.projectDir,
3034
+ env,
3035
+ stdio: ["ignore", "pipe", "pipe"],
3036
+ timeout: 12e4
3037
+ }
3038
+ );
3039
+ } catch (error) {
3040
+ const output = error instanceof Error ? `${error.message}
3041
+ ${"stdout" in error ? String(error.stdout) : ""}${"stderr" in error ? String(error.stderr) : ""}` : String(error);
3042
+ throw new Error(
3043
+ `${targetName}: Run Script "${script}" failed preparing generated Swift sources:
3044
+ ${output}`
3045
+ );
3046
+ }
3047
+ const missing = allOutputs.filter(
3048
+ (file) => file.endsWith(".swift") && !import_node_fs.default.existsSync(file)
3049
+ );
3050
+ if (missing.length > 0)
3051
+ throw new Error(
3052
+ `${targetName}: Run Script "${script}" did not produce ${missing.join(", ")}`
3053
+ );
3054
+ preparedSourcePhases.set(key, stamp);
2918
3055
  }
2919
3056
  }
2920
3057
  visitXcodeTargetMembers(
@@ -3104,22 +3241,95 @@ function readXcodeAppTarget(input, targetName, configurationName, options = {})
3104
3241
  SRCROOT: ref.project.projectDir,
3105
3242
  SOURCE_ROOT: ref.project.projectDir,
3106
3243
  PROJECT_DIR: ref.project.projectDir,
3244
+ SYMROOT: import_node_path2.default.join(ref.project.projectDir, ".build/peach-xcode/Build/Products"),
3245
+ BUILD_DIR: "$(SYMROOT)",
3246
+ OBJROOT: import_node_path2.default.join(
3247
+ ref.project.projectDir,
3248
+ ".build/peach-xcode/Build/Intermediates.noindex"
3249
+ ),
3250
+ CONFIGURATION_BUILD_DIR: "$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)",
3251
+ BUILT_PRODUCTS_DIR: "$(CONFIGURATION_BUILD_DIR)",
3252
+ TARGET_BUILD_DIR: "$(CONFIGURATION_BUILD_DIR)",
3253
+ PROJECT_TEMP_DIR: "$(OBJROOT)/$(PROJECT_NAME).build",
3254
+ CONFIGURATION_TEMP_DIR: "$(PROJECT_TEMP_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)",
3255
+ TARGET_TEMP_DIR: "$(CONFIGURATION_TEMP_DIR)/$(TARGET_NAME).build",
3256
+ DERIVED_FILE_DIR: "$(TARGET_TEMP_DIR)/DerivedSources",
3257
+ DERIVED_FILES_DIR: "$(DERIVED_FILE_DIR)",
3258
+ PLATFORM_NAME: "iphonesimulator",
3259
+ EFFECTIVE_PLATFORM_NAME: "-iphonesimulator",
3260
+ CURRENT_ARCH: "arm64",
3261
+ ARCHS: "arm64",
3262
+ ACTION: "build",
3107
3263
  DEVELOPMENT_LANGUAGE: str(ref.project.project.developmentRegion) ?? "en"
3108
3264
  },
3109
3265
  options
3110
3266
  );
3111
3267
  for (const file of read) xcconfigs.add(file);
3112
3268
  const swiftVersion = Number.parseFloat(settings2("SWIFT_VERSION") || "5");
3269
+ const members = targetMembers(ref, settings2, options, keys, xcconfigs);
3270
+ const implementations = members.allSources.filter(
3271
+ (file) => /\.(c|cc|cpp|cxx|m|mm)$/.test(file)
3272
+ );
3273
+ const absolute = (file) => import_node_path2.default.resolve(ref.project.projectDir, file);
3274
+ const fileFlags = {};
3275
+ for (const phaseId of list(ref.target.buildPhases)) {
3276
+ const phase = ref.project.object(phaseId);
3277
+ if (phase?.isa !== "PBXSourcesBuildPhase") continue;
3278
+ for (const id of list(phase.files)) {
3279
+ const file = ref.project.object(id);
3280
+ const resolved = ref.project.resolvePath(str(file?.fileRef) ?? "");
3281
+ if (resolved && implementations.includes(resolved))
3282
+ fileFlags[resolved] = settingList(
3283
+ expand(
3284
+ str(isDict(file?.settings) ? file.settings.COMPILER_FLAGS : void 0) ?? "",
3285
+ settings2
3286
+ )
3287
+ );
3288
+ }
3289
+ }
3113
3290
  return {
3114
3291
  settings: settings2,
3115
3292
  keys,
3116
3293
  module: {
3117
3294
  name,
3118
3295
  moduleName: applyOperator(settings2("PRODUCT_MODULE_NAME"), "c99extidentifier"),
3119
- ...targetMembers(ref, settings2, options),
3296
+ ...members,
3120
3297
  languageMode: swiftVersion >= 6 ? 6 : 5,
3121
3298
  mainActorIsolation: settings2("SWIFT_DEFAULT_ACTOR_ISOLATION") === "MainActor",
3122
- defines: compilationConditions(settings2)
3299
+ defines: compilationConditions(settings2),
3300
+ iosDeploymentTarget: settings2("IPHONEOS_DEPLOYMENT_TARGET") || null,
3301
+ ...implementations.some((file) => /\.mm?$/.test(file)) ? {
3302
+ objc: {
3303
+ headers: Object.keys(ref.project.objects).flatMap((id) => {
3304
+ const file = ref.project.resolvePath(id);
3305
+ return file && /\.(h|hh|hpp|hxx|pch)$/.test(file) && import_node_fs.default.existsSync(file) ? [file] : [];
3306
+ }),
3307
+ prefixHeader: settings2("GCC_PREFIX_HEADER") ? absolute(settings2("GCC_PREFIX_HEADER")) : null,
3308
+ bridgingHeader: settings2("SWIFT_OBJC_BRIDGING_HEADER") ? absolute(settings2("SWIFT_OBJC_BRIDGING_HEADER")) : null,
3309
+ headerSearchPaths: [
3310
+ ...settingList(settings2("HEADER_SEARCH_PATHS")),
3311
+ ...settingList(settings2("USER_HEADER_SEARCH_PATHS"))
3312
+ ].map(absolute),
3313
+ frameworkSearchPaths: settingList(settings2("FRAMEWORK_SEARCH_PATHS")).map(
3314
+ absolute
3315
+ ),
3316
+ flags: [
3317
+ ...settings2("CLANG_ENABLE_OBJC_ARC") === "YES" ? ["-fobjc-arc"] : [],
3318
+ ...settings2("CLANG_ENABLE_OBJC_WEAK") === "YES" ? ["-fobjc-weak"] : [],
3319
+ ...settings2("CLANG_ENABLE_MODULES") === "YES" ? ["-fmodules"] : [],
3320
+ ...settings2("GCC_C_LANGUAGE_STANDARD") ? [`-std=${settings2("GCC_C_LANGUAGE_STANDARD")}`] : [],
3321
+ ...settingList(settings2("GCC_PREPROCESSOR_DEFINITIONS")).map(
3322
+ (value) => `-D${value}`
3323
+ ),
3324
+ ...settingList(settings2("OTHER_CFLAGS"))
3325
+ ],
3326
+ cxxFlags: [
3327
+ ...settings2("CLANG_CXX_LANGUAGE_STANDARD") ? [`-std=${settings2("CLANG_CXX_LANGUAGE_STANDARD")}`] : [],
3328
+ ...settingList(settings2("OTHER_CPLUSPLUSFLAGS"))
3329
+ ],
3330
+ fileFlags
3331
+ }
3332
+ } : {}
3123
3333
  }
3124
3334
  };
3125
3335
  };
@@ -3168,6 +3378,23 @@ function readXcodeAppTarget(input, targetName, configurationName, options = {})
3168
3378
  ...projects.flatMap(
3169
3379
  (project) => Object.entries(project.objects).flatMap(([id, entry]) => {
3170
3380
  if (!isDict(entry)) return [];
3381
+ if (entry.isa === "PBXFileSystemSynchronizedRootGroup") {
3382
+ const folder = project.resolvePath(id);
3383
+ const pending = folder ? [folder] : [];
3384
+ const packages = [];
3385
+ while (pending.length > 0) {
3386
+ const dir = pending.pop();
3387
+ if (import_node_fs.default.existsSync(import_node_path2.default.join(dir, "Package.swift"))) {
3388
+ packages.push(dir);
3389
+ continue;
3390
+ }
3391
+ if (!isDirectory(dir)) continue;
3392
+ for (const child of import_node_fs.default.readdirSync(dir, { withFileTypes: true }))
3393
+ if (child.isDirectory() && !child.name.startsWith("."))
3394
+ pending.push(import_node_path2.default.join(dir, child.name));
3395
+ }
3396
+ return packages;
3397
+ }
3171
3398
  const candidate = entry.isa === "XCLocalSwiftPackageReference" ? import_node_path2.default.resolve(project.projectDir, str(entry.relativePath) ?? "") : entry.isa === "PBXFileReference" ? project.resolvePath(id) : null;
3172
3399
  return candidate && import_node_fs.default.existsSync(import_node_path2.default.join(candidate, "Package.swift")) ? [candidate] : [];
3173
3400
  })
@@ -3222,6 +3449,7 @@ function readXcodeAppTarget(input, targetName, configurationName, options = {})
3222
3449
  "swiftpm",
3223
3450
  "Package.resolved"
3224
3451
  );
3452
+ const packageResolved = import_node_fs.default.existsSync(resolvedFile) ? [import_node_fs.default.realpathSync(resolvedFile)] : [...new Set(localPackageDirs.map((dir) => import_node_path2.default.join(dir, "Package.resolved")))].filter((file) => import_node_fs.default.existsSync(file)).map((file) => import_node_fs.default.realpathSync(file)).sort();
3225
3453
  const used = order.map((ref) => ref.project);
3226
3454
  return {
3227
3455
  ...module2,
@@ -3247,7 +3475,7 @@ function readXcodeAppTarget(input, targetName, configurationName, options = {})
3247
3475
  ...new Set(localPackageDirs.map((dir) => import_node_fs.default.realpathSync(dir)))
3248
3476
  ].sort(),
3249
3477
  binaryFrameworks: [...binaryFrameworks].map(([name, file]) => ({ name, path: file })).sort((left, right) => left.name.localeCompare(right.name)),
3250
- packageResolved: import_node_fs.default.existsSync(resolvedFile) ? resolvedFile : null,
3478
+ packageResolved,
3251
3479
  appTargets: appTargetNames,
3252
3480
  configuration,
3253
3481
  settings
@@ -3255,15 +3483,12 @@ function readXcodeAppTarget(input, targetName, configurationName, options = {})
3255
3483
  }
3256
3484
 
3257
3485
  // src/native-app-identity-project.ts
3258
- function isRecord3(value) {
3259
- return typeof value === "object" && value !== null && !Array.isArray(value);
3260
- }
3261
3486
  function nonEmptyString2(value) {
3262
3487
  return typeof value === "string" && value.length > 0 ? value : void 0;
3263
3488
  }
3264
3489
  function readNativeAppIdentityFromXcodeTarget(app, parseInfoPlist = parsePlistSource) {
3265
3490
  const dictionary = parseInfoPlist(app.infoPlist);
3266
- if (!isRecord3(dictionary)) throw new Error("native app Info.plist is not a dictionary");
3491
+ if (!isRecord(dictionary)) throw new Error("native app Info.plist is not a dictionary");
3267
3492
  const settings = app.settings;
3268
3493
  const bundleIdentifier = nonEmptyString2(dictionary.CFBundleIdentifier) ?? nonEmptyString2(settings?.("PRODUCT_BUNDLE_IDENTIFIER"));
3269
3494
  if (!bundleIdentifier) throw new Error("native app has no bundle identifier");
@@ -3280,8 +3505,8 @@ function readNativeAppIdentityFromXcodeTarget(app, parseInfoPlist = parsePlistSo
3280
3505
  const designRequiresCompatibility = dictionary.UIDesignRequiresCompatibility === true;
3281
3506
  const alternateIconNames = /* @__PURE__ */ new Set();
3282
3507
  const icons = dictionary.CFBundleIcons;
3283
- const alternates = isRecord3(icons) ? icons.CFBundleAlternateIcons : void 0;
3284
- if (isRecord3(alternates)) {
3508
+ const alternates = isRecord(icons) ? icons.CFBundleAlternateIcons : void 0;
3509
+ if (isRecord(alternates)) {
3285
3510
  for (const name of Object.keys(alternates)) {
3286
3511
  if (name) alternateIconNames.add(name);
3287
3512
  }
@@ -3298,6 +3523,10 @@ function readNativeAppIdentityFromXcodeTarget(app, parseInfoPlist = parsePlistSo
3298
3523
  }
3299
3524
  permissionUsageDescriptions[key] = value;
3300
3525
  }
3526
+ const infoPlistStrings = {};
3527
+ for (const [key, value] of Object.entries(dictionary)) {
3528
+ if (typeof value === "string") infoPlistStrings[key] = value;
3529
+ }
3301
3530
  const querySchemes = dictionary.LSApplicationQueriesSchemes;
3302
3531
  const urlQuerySchemes = Array.isArray(querySchemes) ? querySchemes : [];
3303
3532
  const intentIds = dictionary.OneAppIntentIdentifiers;
@@ -3325,12 +3554,22 @@ function readNativeAppIdentityFromXcodeTarget(app, parseInfoPlist = parsePlistSo
3325
3554
  ...rootModuleName ? { rootModuleName } : {},
3326
3555
  ...rootViewBackgroundColor !== void 0 ? { rootViewBackgroundColor } : {},
3327
3556
  ...designRequiresCompatibility ? { designRequiresCompatibility } : {},
3557
+ ...typeof dictionary.UIStatusBarHidden === "boolean" ? { statusBarHidden: dictionary.UIStatusBarHidden } : {},
3558
+ ...typeof dictionary.UIViewControllerBasedStatusBarAppearance === "boolean" ? {
3559
+ viewControllerBasedStatusBarAppearance: dictionary.UIViewControllerBasedStatusBarAppearance
3560
+ } : {},
3328
3561
  ...typeof dictionary.DTPlatformVersion === "string" ? { dtPlatformVersion: dictionary.DTPlatformVersion } : {},
3329
3562
  bundleName,
3330
3563
  appVersion,
3331
3564
  buildVersion,
3332
3565
  bundleIdentifier,
3333
3566
  platform: "ios",
3567
+ googleSignIn: readGoogleSignInConfiguration(
3568
+ dictionary,
3569
+ Object.fromEntries(
3570
+ app.resources.filter((file) => file.endsWith(".plist")).map((file) => [file, parseInfoPlist(import_node_fs2.default.readFileSync(file, "utf8"))])
3571
+ )
3572
+ ),
3334
3573
  supportedInterfaceOrientations,
3335
3574
  ipadSupportedInterfaceOrientations,
3336
3575
  ...defaultScreenOrientationMask ? { defaultScreenOrientationMask } : {},
@@ -3349,6 +3588,7 @@ function readNativeAppIdentityFromXcodeTarget(app, parseInfoPlist = parsePlistSo
3349
3588
  (value) => value
3350
3589
  ),
3351
3590
  permissionUsageDescriptions,
3591
+ infoPlistStrings,
3352
3592
  urlQuerySchemes,
3353
3593
  ...shareIntoAppGroupId ? { shareIntoAppGroupId } : {},
3354
3594
  ...rtcAppGroupIdentifier ? { rtcAppGroupIdentifier } : {},
@@ -3498,9 +3738,9 @@ function readIosNativeAppIdentity(projectRoot, parseInfoPlist, iosTarget) {
3498
3738
  const installedManifest = JSON.parse(
3499
3739
  import_node_fs2.default.readFileSync(reanimatedManifestPath, "utf8")
3500
3740
  );
3501
- const installedVersion = isRecord3(installedManifest) ? nonEmptyString2(installedManifest.version) : void 0;
3741
+ const installedVersion = isRecord(installedManifest) ? nonEmptyString2(installedManifest.version) : void 0;
3502
3742
  if (!installedVersion) throw new Error("Reanimated package version is malformed");
3503
- if (installedVersion.startsWith("3.")) return identity;
3743
+ if (Number.parseInt(installedVersion, 10) < 4) return identity;
3504
3744
  const defaults = JSON.parse(
3505
3745
  import_node_fs2.default.readFileSync(
3506
3746
  import_node_path3.default.join(
@@ -3510,11 +3750,11 @@ function readIosNativeAppIdentity(projectRoot, parseInfoPlist, iosTarget) {
3510
3750
  "utf8"
3511
3751
  )
3512
3752
  );
3513
- if (!isRecord3(defaults)) throw new Error("Reanimated static flags are malformed");
3753
+ if (!isRecord(defaults)) throw new Error("Reanimated static flags are malformed");
3514
3754
  const manifest = JSON.parse(import_node_fs2.default.readFileSync(projectManifestPath, "utf8"));
3515
- const reanimated = isRecord3(manifest) ? manifest.reanimated : void 0;
3516
- const overrides = isRecord3(reanimated) ? reanimated.staticFeatureFlags : void 0;
3517
- if (overrides !== void 0 && !isRecord3(overrides)) {
3755
+ const reanimated = isRecord(manifest) ? manifest.reanimated : void 0;
3756
+ const overrides = isRecord(reanimated) ? reanimated.staticFeatureFlags : void 0;
3757
+ if (overrides !== void 0 && !isRecord(overrides)) {
3518
3758
  throw new Error("Reanimated static flag overrides are malformed");
3519
3759
  }
3520
3760
  const flags = {};