peachsim 0.1.1481 → 0.1.1619

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 (292) hide show
  1. package/README.md +56 -13
  2. package/cli/app-catalog.ts +7 -5
  3. package/cli/app-config.ts +47 -8
  4. package/cli/app-fonts.ts +84 -49
  5. package/cli/app-stubs.ts +433 -0
  6. package/cli/bin.ts +15 -2
  7. package/cli/bridge-flow-runner.ts +383 -123
  8. package/cli/cloud-client.ts +26 -25
  9. package/cli/cloud-test-tunnel.ts +2 -0
  10. package/cli/command-registry.ts +2 -1
  11. package/cli/commands/agent-indicator-mode.ts +39 -0
  12. package/cli/commands/box/bundle-plane.ts +4 -0
  13. package/cli/commands/box.ts +16 -23
  14. package/cli/commands/control.ts +221 -126
  15. package/cli/commands/daemon.ts +99 -24
  16. package/cli/commands/debug.ts +31 -3
  17. package/cli/commands/detect.ts +1 -1
  18. package/cli/commands/device.ts +6 -8
  19. package/cli/commands/diagnose.ts +2 -0
  20. package/cli/commands/do-chain.ts +2 -2
  21. package/cli/commands/doctor.ts +1030 -0
  22. package/cli/commands/flow.ts +447 -406
  23. package/cli/commands/inspect/actions.ts +2 -0
  24. package/cli/commands/inspect/core.ts +138 -46
  25. package/cli/commands/inspect/env.ts +10 -0
  26. package/cli/commands/inspect/list.ts +25 -8
  27. package/cli/commands/inspect/memory.ts +9 -0
  28. package/cli/commands/inspect/settling.ts +219 -66
  29. package/cli/commands/inspect/shared.ts +53 -12
  30. package/cli/commands/inspect/wait-event.ts +0 -1
  31. package/cli/commands/inspect/wait.ts +2 -2
  32. package/cli/commands/inspect.ts +51 -16
  33. package/cli/commands/install-desktop.ts +3 -2
  34. package/cli/commands/kotlin.ts +81 -22
  35. package/cli/commands/login.ts +1 -1
  36. package/cli/commands/maestro-compare.ts +41 -5
  37. package/cli/commands/maestro-generate.ts +11 -7
  38. package/cli/commands/maestro.ts +43 -15
  39. package/cli/commands/mode.ts +13 -1
  40. package/cli/commands/no-bridge-hint.ts +26 -3
  41. package/cli/commands/perf-record.ts +296 -0
  42. package/cli/commands/perf.ts +6 -1
  43. package/cli/commands/platform.ts +15 -4
  44. package/cli/commands/preview.ts +1 -1
  45. package/cli/commands/record.ts +37 -6
  46. package/cli/commands/report-issue.ts +2 -1
  47. package/cli/commands/runtime.ts +9 -11
  48. package/cli/commands/screenshots.ts +4 -3
  49. package/cli/commands/serve.ts +30 -2
  50. package/cli/commands/setup.ts +32 -7
  51. package/cli/commands/skills.ts +16 -43
  52. package/cli/commands/swift.ts +22 -3
  53. package/cli/commands/upgrade.ts +7 -6
  54. package/cli/commands/upload.ts +118 -69
  55. package/cli/commands/window.ts +449 -0
  56. package/cli/current-sim.ts +1 -2
  57. package/cli/desktop-companion.ts +84 -10
  58. package/cli/device-option.ts +8 -0
  59. package/cli/drivers/desktop.ts +3 -1
  60. package/cli/drivers/playwright-sim-host.ts +30 -11
  61. package/cli/drivers/playwright.ts +1 -4
  62. package/cli/flow-export.ts +2 -2
  63. package/cli/flow-file.ts +19 -18
  64. package/cli/internal-child.ts +7 -6
  65. package/cli/maestro-compare.ts +28 -6
  66. package/cli/maestro-js.ts +2 -1
  67. package/cli/main.ts +25 -4
  68. package/cli/material-symbol-fonts.ts +171 -0
  69. package/cli/outbound-endpoints.ts +132 -54
  70. package/cli/parse-args.ts +7 -0
  71. package/cli/preview-capture.ts +12 -0
  72. package/cli/privacy.ts +1 -1
  73. package/cli/run-registry.ts +5 -2
  74. package/cli/runtime-compat.ts +16 -0
  75. package/cli/telemetry.ts +6 -3
  76. package/cli/ui.ts +5 -0
  77. package/cli/ws-bridge.ts +121 -62
  78. package/detox/attempt-events.cjs +762 -0
  79. package/detox/attempt-events.d.cts +106 -0
  80. package/detox/gestures.ts +115 -2
  81. package/detox/index.ts +762 -426
  82. package/detox/jest-environment.cjs +86 -0
  83. package/detox/jest-preset.cjs +3 -1
  84. package/detox/jest-setup-after-env.cjs +1 -0
  85. package/detox/matchers.ts +3 -6
  86. package/detox/motion-change.cjs +259 -0
  87. package/detox/motion-change.d.cts +73 -0
  88. package/detox/proof-frame.cjs +83 -9
  89. package/dist-lib/agent-daemon-client.cjs +1 -1
  90. package/dist-lib/agent-events.cjs +1 -1
  91. package/dist-lib/attached-projects.cjs +1 -1
  92. package/dist-lib/auth/shared-session.cjs +15 -5
  93. package/dist-lib/backend-origin.cjs +1 -1
  94. package/dist-lib/beta.cjs +1 -1
  95. package/dist-lib/beta.mjs +1 -1
  96. package/dist-lib/bridge-constants.cjs +3 -1
  97. package/dist-lib/bridge-contract-input.cjs +1 -1
  98. package/dist-lib/bridge-contract-input.mjs +1 -1
  99. package/dist-lib/bridge-contract.cjs +1 -1
  100. package/dist-lib/bridge-contract.mjs +1 -1
  101. package/dist-lib/bundle-channel.cjs +5950 -1775
  102. package/dist-lib/capture-contract.cjs +1 -1
  103. package/dist-lib/capture-contract.mjs +1 -1
  104. package/dist-lib/cloud-contract.cjs +6 -1
  105. package/dist-lib/cloud-contract.mjs +5 -1
  106. package/dist-lib/cloud-test-args.cjs +1 -1
  107. package/dist-lib/cloud-test-args.mjs +1 -1
  108. package/dist-lib/cloud.cjs +1 -1
  109. package/dist-lib/cloud.mjs +1 -1
  110. package/dist-lib/config.cjs +34 -3
  111. package/dist-lib/config.mjs +33 -3
  112. package/dist-lib/detox/index.cjs +3443 -564
  113. package/dist-lib/detox/jest-environment.cjs +86 -0
  114. package/dist-lib/detox/jest-preset.cjs +3 -1
  115. package/dist-lib/dev-bundle-resolution.cjs +1 -1
  116. package/dist-lib/expo-swift-bundle.cjs +5518 -1446
  117. package/dist-lib/expo-swift-metadata.cjs +21 -13
  118. package/dist-lib/expo-swift-metadata.mjs +21 -13
  119. package/dist-lib/home-paths.cjs +1 -1
  120. package/dist-lib/host/bridge-host.cjs +21728 -16808
  121. package/dist-lib/host/fetch-proxy-handler.cjs +177 -102
  122. package/dist-lib/host/fetch-proxy-overrides.cjs +84 -4
  123. package/dist-lib/host/fetch-proxy-overrides.mjs +74 -3
  124. package/dist-lib/host/replacement-module-handler.cjs +16 -15
  125. package/dist-lib/host/websocket-proxy.cjs +243 -6
  126. package/dist-lib/index.cjs +6063 -4113
  127. package/dist-lib/jump-to-source-babel.cjs +73 -35
  128. package/dist-lib/jump-to-source-native.cjs +118 -10
  129. package/dist-lib/kotlin-host.cjs +264 -121
  130. package/dist-lib/menu.cjs +1 -1
  131. package/dist-lib/menu.mjs +1 -1
  132. package/dist-lib/metro-fingerprint-registry.cjs +1 -1
  133. package/dist-lib/metro-fingerprint-registry.mjs +1 -1
  134. package/dist-lib/metro-production-bundle.cjs +147 -99
  135. package/dist-lib/metro-production-bundle.mjs +142 -99
  136. package/dist-lib/metro.cjs +4249 -360
  137. package/dist-lib/native-app-identity-project.cjs +318 -131
  138. package/dist-lib/native-app-identity-project.mjs +317 -131
  139. package/dist-lib/native-app-identity.cjs +322 -33
  140. package/dist-lib/native-app-identity.mjs +319 -32
  141. package/dist-lib/native-firebase-metadata.cjs +1 -1
  142. package/dist-lib/native-firebase-metadata.mjs +1 -1
  143. package/dist-lib/plist.cjs +1 -1
  144. package/dist-lib/plist.mjs +1 -1
  145. package/dist-lib/profiles.cjs +1 -1
  146. package/dist-lib/public-brand.cjs +1 -1
  147. package/dist-lib/react-native-host-modules.cjs +11 -1
  148. package/dist-lib/react-native-host-modules.mjs +11 -1
  149. package/dist-lib/scripts/dev-server-scanner.cjs +127 -42
  150. package/dist-lib/sdk.cjs +311 -103
  151. package/dist-lib/sdk.mjs +311 -103
  152. package/dist-lib/skills.cjs +18344 -11121
  153. package/dist-lib/swift-compile.cjs +3291 -544
  154. package/dist-lib/swift-compile.mjs +3227 -478
  155. package/dist-lib/swift-package.cjs +25 -3
  156. package/dist-lib/swift-package.mjs +22 -2
  157. package/dist-lib/swift-submit.cjs +2 -2
  158. package/dist-lib/swift-submit.mjs +2 -2
  159. package/dist-lib/swift-toolchain.cjs +1 -1
  160. package/dist-lib/swift.cjs +1 -1
  161. package/dist-lib/vite-swift.cjs +5523 -1428
  162. package/dist-lib/vite.cjs +251 -60
  163. package/dist-lib/worklet-executable.cjs +18 -4
  164. package/dist-lib/worklet-executable.mjs +18 -4
  165. package/install.sh +8 -3
  166. package/kotlin/AndroidViewSources/android/graphics/Canvas.kt +2 -0
  167. package/kotlin/AndroidViewSources/android/graphics/Paint.kt +18 -0
  168. package/kotlin/AndroidViewSources/dev/peach/app/JavaFormat.kt +16 -8
  169. package/kotlin/AppSources/android/view/Window.kt +4 -1
  170. package/kotlin/AppSources/android/window/BackEvent.kt +24 -0
  171. package/kotlin/AppSources/android/window/OnBackAnimationCallback.kt +7 -0
  172. package/kotlin/AppSources/android/window/OnBackInvokedDispatcher.kt +37 -1
  173. package/kotlin/AppSources/androidx/activity/BackEventCompat.kt +5 -0
  174. package/kotlin/AppSources/androidx/activity/OnBackPressedDispatcher.kt +8 -1
  175. package/kotlin/AppSources/dev/peach/app/PeachApp.kt +14 -0
  176. package/kotlin/CompilerSources/META-INF/services/org.jetbrains.kotlin.compiler.plugin.CompilerPluginRegistrar +1 -0
  177. package/kotlin/CompilerSources/PeachJniIncoming.kt +243 -0
  178. package/kotlin/CompilerSources/PeachJniPlugin.kt +116 -0
  179. package/kotlin/ComposeSources/PeachComposeHost.kt +58 -32
  180. package/kotlin/ComposeSources/PeachMagnifier.kt +185 -0
  181. package/kotlin/ExpoComposeSources/PeachAndroidView.kt +16 -0
  182. package/kotlin/JniPlatformSources/androidx/annotation/CallSuper.kt +5 -0
  183. package/kotlin/JniPlatformSources/com/facebook/proguard/annotations/DoNotStrip.kt +5 -0
  184. package/kotlin/JniPlatformSources/dalvik/annotation/optimization/FastNative.kt +5 -0
  185. package/kotlin/JniPlatformSources/kotlin/Synchronized.kt +6 -0
  186. package/kotlin/JniPlatformSources/kotlin/jvm/JvmField.kt +5 -0
  187. package/kotlin/JniPlatformSources/kotlin/jvm/JvmStatic.kt +5 -0
  188. package/kotlin/JniSources/com/facebook/jni/HybridData.kt +68 -0
  189. package/kotlin/JniSources/dev/peach/jni/IncomingBindings.kt +157 -0
  190. package/kotlin/JniSources/dev/peach/jni/NativeBindings.kt +79 -0
  191. package/kotlin/JniTransportSources/dev/peach/jni/integration/JniTransport.kt +91 -0
  192. package/kotlin/README.md +18 -0
  193. package/kotlin/Sources/java/util/IllegalFormatCodePointException.kt +10 -0
  194. package/kotlin/Sources/java/util/IllegalFormatException.kt +5 -0
  195. package/kotlin/fixtures/counter/CounterApp.native.tsx +30 -3
  196. package/kotlin/fixtures/counter/CounterScreen.d.kt.ts +1 -0
  197. package/kotlin/fixtures/counter/CounterScreen.kt +2 -1
  198. package/kotlin/fixtures/counter/package.json +15 -2
  199. package/kotlin/fixtures/counter/vite.config.ts +11 -1
  200. package/kotlin/fork/NOTICE +1 -0
  201. package/kotlin/fork/README.md +5 -4
  202. package/kotlin/fork/compose-worker-globals.patch +629 -0
  203. package/kotlin/fork/fork.json +1 -1
  204. package/kotlin/toolchain.json +3 -3
  205. package/package.json +1 -1
  206. package/scripts/dev-server-scanner.ts +166 -81
  207. package/skills/contrast/SKILL.md +4 -4
  208. package/skills/peach-debug/SKILL.md +1 -1
  209. package/skills/peach-perf/SKILL.md +25 -0
  210. package/skills/peach-setup/SKILL.md +47 -13
  211. package/skills/peach-test/SKILL.md +2 -3
  212. package/src/agent-identity.ts +18 -0
  213. package/src/assetCatalogContract.ts +31 -3
  214. package/src/auth/shared-session.ts +3 -2
  215. package/src/bridge-constants.ts +1 -1
  216. package/src/bridge-contract.ts +5 -0
  217. package/src/bundle-channel.mjs +38 -7
  218. package/src/bundleGlobalFooter.ts +70 -20
  219. package/src/cloud-contract.ts +11 -0
  220. package/src/config.ts +47 -1
  221. package/src/configured-bundle-producer.ts +4 -1
  222. package/src/desktop-host-delivery.ts +4 -3
  223. package/src/expo-kotlin-host.ts +7 -2
  224. package/src/guest-bundle.ts +15 -8
  225. package/src/host/agent-host.ts +2 -4
  226. package/src/host/bridge-host.ts +260 -119
  227. package/src/host/fetch-proxy-handler.ts +237 -146
  228. package/src/host/fetch-proxy-overrides.ts +118 -0
  229. package/src/host/fetch-proxy-transport.ts +77 -63
  230. package/src/host/lease-owner.test.ts +18 -1
  231. package/src/host/lease-owner.ts +4 -5
  232. package/src/host/loopback-ports.ts +34 -0
  233. package/src/host/replacement-module-handler.ts +24 -15
  234. package/src/host/server-scan-handler.ts +87 -0
  235. package/src/host/staged-host-files.ts +92 -0
  236. package/src/host/websocket-proxy.ts +271 -5
  237. package/src/installed-package-versions.ts +66 -0
  238. package/src/jump-to-source-babel.ts +97 -89
  239. package/src/jump-to-source-native.ts +109 -11
  240. package/src/kotlin-host.ts +144 -27
  241. package/src/kotlin-module.ts +52 -0
  242. package/src/kotlinDiscoveryContract.ts +27 -0
  243. package/src/metro-layout-parser.ts +78 -0
  244. package/src/metro-plugin.ts +129 -39
  245. package/src/metro-production-bundle.ts +140 -139
  246. package/src/native-app-identity-project.ts +103 -5
  247. package/src/native-app-identity.ts +173 -11
  248. package/src/native-firebase-config.ts +83 -80
  249. package/src/native-seam-manifest.ts +0 -44
  250. package/src/nativeAppIconContract.ts +137 -0
  251. package/src/nativeViewSourceContract.ts +49 -0
  252. package/src/nativeViewWebContract.ts +41 -0
  253. package/src/nitro-bundle.ts +43 -0
  254. package/src/nitro-compile.ts +107 -0
  255. package/src/nitro-source.ts +310 -0
  256. package/src/nitroContract.ts +51 -0
  257. package/src/one-widget-metadata.ts +23 -3
  258. package/src/oneWidgetContract.ts +36 -3
  259. package/src/packageVersionsContract.ts +52 -0
  260. package/src/process-group.ts +306 -0
  261. package/src/process-liveness.ts +24 -0
  262. package/src/process-output.ts +21 -2
  263. package/src/react-devtools-frontend-react.ts +45 -0
  264. package/src/react-native-host-modules.ts +10 -0
  265. package/src/serverDiscoveryContract.ts +41 -0
  266. package/src/skills/builtin/maestro-test.ts +2 -4
  267. package/src/swift-compile.ts +3195 -650
  268. package/src/swift-design-time.ts +552 -0
  269. package/src/swift-distribution-contract.ts +11 -0
  270. package/src/swift-distribution.lock.json +46 -11
  271. package/src/swift-host.ts +144 -30
  272. package/src/swift-icu.ts +10 -2
  273. package/src/swift-objc-sdk.ts +726 -0
  274. package/src/swift-objc-standin.ts +441 -0
  275. package/src/swift-package.ts +25 -0
  276. package/src/swift-packages.ts +25 -10
  277. package/src/swift-standin-config.ts +94 -0
  278. package/src/swift-standin-emit.ts +5 -3
  279. package/src/swift-standins.ts +225 -81
  280. package/src/swift-submit.ts +2 -1
  281. package/src/swiftContract.ts +4 -0
  282. package/src/target-matcher.ts +67 -0
  283. package/src/visit-parsed-program.ts +21 -0
  284. package/src/vite-plugin-one.ts +65 -17
  285. package/src/vite-plugin-swift.ts +1 -0
  286. package/src/vite-plugin.ts +168 -70
  287. package/src/worker-system-chunks.ts +89 -10
  288. package/src/worklet-executable.ts +21 -3
  289. package/src/worklets-babel.ts +85 -13
  290. package/src/xcode-project.ts +81 -134
  291. package/src/xcode-target-members.ts +107 -0
  292. package/cli/commands/compat.ts +0 -395
@@ -1,9 +1,85 @@
1
- /*! peach v0.1.1481 | (c) 2026 Tamagui LLC | Proprietary; see LICENSE */
1
+ /*! peach v0.1.1619 | (c) 2026 Tamagui LLC | Proprietary; see LICENSE */
2
2
 
3
3
  // src/native-app-identity-project.ts
4
4
  import fs2 from "node:fs";
5
+ import { createRequire } from "node:module";
5
6
  import path3 from "node:path";
6
7
 
8
+ // src/nativeAppIconContract.ts
9
+ function isRecord(value) {
10
+ return typeof value === "object" && value !== null && !Array.isArray(value);
11
+ }
12
+ function resolveNativeAppIconArtwork(resources, readText, resourceUri, icons, primaryName, alternateNames, resolveReference) {
13
+ const members = new Set(resources);
14
+ const dictionary = isRecord(icons) ? icons : {};
15
+ const alternates = Object.fromEntries(
16
+ Object.entries(
17
+ isRecord(dictionary.CFBundleAlternateIcons) ? dictionary.CFBundleAlternateIcons : {}
18
+ ).map(([name, declaration]) => [resolveReference(name), declaration])
19
+ );
20
+ const resolve = (declaration, defaultName) => {
21
+ const entry = isRecord(declaration) ? declaration : {};
22
+ const name = typeof entry.CFBundleIconName === "string" ? resolveReference(entry.CFBundleIconName) : resolveReference(defaultName);
23
+ const catalogs = resources.filter(
24
+ (file) => file.endsWith(`/${name}.appiconset/Contents.json`)
25
+ );
26
+ const populatedCatalogs = [];
27
+ for (const catalog of catalogs) {
28
+ const catalogCandidates = [];
29
+ const text2 = readText(catalog);
30
+ const contents = text2 === null ? null : JSON.parse(text2);
31
+ if (isRecord(contents) && Array.isArray(contents.images)) {
32
+ for (const image of contents.images) {
33
+ if (!isRecord(image) || typeof image.filename !== "string" || /[/\\]/.test(image.filename) || !/\.(png|jpe?g|webp)$/i.test(image.filename) || image.appearances !== void 0 || !["iphone", "universal", "ios-marketing"].includes(String(image.idiom)))
34
+ continue;
35
+ const file = catalog.slice(0, -"Contents.json".length) + image.filename;
36
+ const scale = image.scale === "2x" ? 2 : image.scale === "3x" ? 3 : 1;
37
+ const size = typeof image.size === "string" ? parseFloat(image.size) : 1024;
38
+ if (members.has(file) && Number.isFinite(size) && size > 0)
39
+ catalogCandidates.push({ file, scale, size });
40
+ }
41
+ }
42
+ if (catalogCandidates.length > 0) populatedCatalogs.push(catalogCandidates);
43
+ }
44
+ if (populatedCatalogs.length > 1)
45
+ throw new Error(`native app icon catalog ${name} is ambiguous`);
46
+ const candidates = [];
47
+ if (populatedCatalogs.length === 1) {
48
+ candidates.push(...populatedCatalogs[0]);
49
+ const home = candidates.filter((image) => image.size === 60);
50
+ const chosen = home.length ? home : candidates.sort((a, b) => b.size * b.scale - a.size * a.scale).slice(0, 1);
51
+ return chosen.flatMap(({ file, scale }) => {
52
+ const uri = resourceUri(file);
53
+ return uri ? [{ uri, scale }] : [];
54
+ }).sort((a, b) => a.scale - b.scale);
55
+ }
56
+ const files = Array.isArray(entry.CFBundleIconFiles) ? entry.CFBundleIconFiles : [];
57
+ for (const iconFile of files) {
58
+ if (typeof iconFile !== "string" || /[/\\]/.test(iconFile)) continue;
59
+ const base = resolveReference(iconFile).replace(/\.(png|jpe?g|webp)$/i, "");
60
+ for (const file of resources) {
61
+ const match = /(?:^|\/)([^/]+?)(?:@([23])x)?\.(png|jpe?g|webp)$/i.exec(file);
62
+ if (!match || match[1] !== base) continue;
63
+ candidates.push({ file, scale: Number(match[2] ?? 1), size: 60 });
64
+ }
65
+ }
66
+ return candidates.flatMap(({ file, scale }) => {
67
+ const uri = resourceUri(file);
68
+ return uri ? [{ uri, scale }] : [];
69
+ }).sort((a, b) => a.scale - b.scale);
70
+ };
71
+ const primary = resolve(dictionary.CFBundlePrimaryIcon, primaryName);
72
+ return {
73
+ ...primary.length ? { primary } : {},
74
+ alternates: Object.fromEntries(
75
+ alternateNames.flatMap((name) => {
76
+ const images = resolve(alternates[name], name);
77
+ return images.length ? [[name, images]] : [];
78
+ })
79
+ )
80
+ };
81
+ }
82
+
7
83
  // src/openstep-plist.ts
8
84
  var isDict = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
9
85
  var str = (value) => typeof value === "string" ? value : void 0;
@@ -99,7 +175,101 @@ function parseOpenStepPlist(text2) {
99
175
  return root;
100
176
  }
101
177
 
178
+ // src/xcode-target-members.ts
179
+ var NEVER_MEMBER = /(?:^|\/)(?:Info\.plist|[^/]+\.entitlements|[^/]+\.xcconfig|\.DS_Store)$/;
180
+ var BUNDLE_DIR = /\.(xcassets|bundle|lproj|xcdatamodeld|scnassets|spriteatlas|rcproject|storyboardc|icon)$/;
181
+ function xcodePathResolver(objects, projectDir, join) {
182
+ const parents = /* @__PURE__ */ new Map();
183
+ for (const [id, entry] of Object.entries(objects)) {
184
+ if (!isDict(entry)) continue;
185
+ if (entry.isa === "PBXGroup" || entry.isa === "PBXVariantGroup") {
186
+ for (const child of list(entry.children)) parents.set(child, id);
187
+ }
188
+ }
189
+ const paths = /* @__PURE__ */ new Map();
190
+ const resolve = (id) => {
191
+ if (paths.has(id)) return paths.get(id);
192
+ paths.set(id, null);
193
+ const entry = objects[id];
194
+ let result = null;
195
+ if (isDict(entry)) {
196
+ const own = str(entry.path) ?? "";
197
+ const tree = str(entry.sourceTree) ?? "<group>";
198
+ if (tree === "<absolute>") result = own;
199
+ else if (tree === "SOURCE_ROOT") result = join(projectDir, own);
200
+ else if (tree === "<group>") {
201
+ const parent = parents.get(id);
202
+ const base = parent ? resolve(parent) : projectDir;
203
+ if (base !== null) result = join(base, own);
204
+ }
205
+ }
206
+ paths.set(id, result);
207
+ return result;
208
+ };
209
+ return resolve;
210
+ }
211
+ function visitXcodeTargetMembers(objects, targetId, resolvePath, filesUnder, join, visit) {
212
+ const target = objects[targetId];
213
+ if (!isDict(target)) return;
214
+ for (const phaseId of list(target.buildPhases)) {
215
+ const phase = objects[phaseId];
216
+ if (!isDict(phase)) continue;
217
+ if (phase.isa !== "PBXSourcesBuildPhase" && phase.isa !== "PBXResourcesBuildPhase")
218
+ continue;
219
+ for (const buildFileId of list(phase.files)) {
220
+ const buildFile = objects[buildFileId];
221
+ if (!isDict(buildFile)) continue;
222
+ const refId = str(buildFile.fileRef);
223
+ if (!refId) continue;
224
+ const entry = objects[refId];
225
+ const refs = isDict(entry) && entry.isa === "PBXVariantGroup" ? list(entry.children) : [refId];
226
+ for (const id of refs) {
227
+ const file = resolvePath(id);
228
+ if (file === null) continue;
229
+ if (phase.isa === "PBXSourcesBuildPhase") visit(file, "source");
230
+ else for (const inner of filesUnder(file)) visit(inner, "resource");
231
+ }
232
+ }
233
+ }
234
+ const owned = new Set(list(target.fileSystemSynchronizedGroups));
235
+ for (const [groupId, group] of Object.entries(objects)) {
236
+ if (!isDict(group) || group.isa !== "PBXFileSystemSynchronizedRootGroup") continue;
237
+ const folder = resolvePath(groupId);
238
+ if (folder === null) continue;
239
+ const prefix = folder === "" ? "" : `${folder.replace(/\/$/, "")}/`;
240
+ const exceptions = /* @__PURE__ */ new Set();
241
+ for (const exceptionId of list(group.exceptions)) {
242
+ const exception = objects[exceptionId];
243
+ if (!isDict(exception) || exception.target !== targetId) continue;
244
+ for (const relative of list(exception.membershipExceptions))
245
+ exceptions.add(relative);
246
+ }
247
+ const members = owned.has(groupId) ? filesUnder(folder) : [...exceptions].flatMap((relative) => filesUnder(join(folder, relative)));
248
+ for (const file of members) {
249
+ const relative = file.slice(prefix.length);
250
+ const excepted = [...exceptions].some(
251
+ (exception) => relative === exception || relative.startsWith(`${exception}/`)
252
+ );
253
+ if (owned.has(groupId) === excepted || NEVER_MEMBER.test(relative)) continue;
254
+ if (file.endsWith(".swift")) {
255
+ if (!relative.split("/").some((segment) => BUNDLE_DIR.test(segment)))
256
+ visit(file, "source");
257
+ } else if (/\.(h|m|mm|c|cpp|metal)$/.test(file)) {
258
+ if (!file.endsWith(".h")) visit(file, "source");
259
+ } else visit(file, "resource");
260
+ }
261
+ }
262
+ }
263
+
102
264
  // src/native-app-identity.ts
265
+ var ROOT_MODULE_NAME_RE = /(?:\bm|M)oduleName\s*[:=]\s*@?"([^"\\]+)"/g;
266
+ function readRootModuleName(sources) {
267
+ const names = /* @__PURE__ */ new Set();
268
+ for (const source of sources) {
269
+ for (const match of source.matchAll(ROOT_MODULE_NAME_RE)) names.add(match[1]);
270
+ }
271
+ return names.size === 1 ? [...names][0] : void 0;
272
+ }
103
273
  function canExtractNativeAppIdentity(platform) {
104
274
  return platform === "ios";
105
275
  }
@@ -456,8 +626,6 @@ var MODULE_PRODUCTS = /* @__PURE__ */ new Set([
456
626
  "com.apple.product-type.library.static",
457
627
  "com.apple.product-type.library.dynamic"
458
628
  ]);
459
- var NEVER_MEMBER = /(?:^|\/)(?:Info\.plist|[^/]+\.entitlements|[^/]+\.xcconfig|\.DS_Store)$/;
460
- var BUNDLE_DIR = /\.(xcassets|bundle|lproj|xcdatamodeld|scnassets|spriteatlas|rcproject|storyboardc|icon)$/;
461
629
  var CONDITIONS = {
462
630
  sdk: "iphonesimulator",
463
631
  arch: "arm64",
@@ -595,32 +763,7 @@ function loadProject(xcodeproj) {
595
763
  const projectDir = fs.realpathSync(
596
764
  path2.resolve(path2.dirname(xcodeproj), str(project.projectDirPath) ?? "")
597
765
  );
598
- const parent = /* @__PURE__ */ new Map();
599
- for (const [id, entry] of Object.entries(objects)) {
600
- if (!isDict(entry)) continue;
601
- if (entry.isa === "PBXGroup" || entry.isa === "PBXVariantGroup") {
602
- for (const child of list(entry.children)) parent.set(child, id);
603
- }
604
- }
605
- const resolvedPaths = /* @__PURE__ */ new Map();
606
- const resolvePath = (id) => {
607
- if (resolvedPaths.has(id)) return resolvedPaths.get(id);
608
- const entry = object(id);
609
- let result2 = null;
610
- if (entry) {
611
- const own = str(entry.path) ?? "";
612
- const tree = str(entry.sourceTree) ?? "<group>";
613
- if (tree === "<absolute>") result2 = own;
614
- else if (tree === "SOURCE_ROOT") result2 = path2.join(projectDir, own);
615
- else if (tree === "<group>") {
616
- const up = parent.get(id);
617
- const base = up ? resolvePath(up) : projectDir;
618
- result2 = base === null ? null : path2.join(base, own);
619
- }
620
- }
621
- resolvedPaths.set(id, result2);
622
- return result2;
623
- };
766
+ const resolvePath = xcodePathResolver(objects, projectDir, path2.join);
624
767
  const result = {
625
768
  xcodeproj,
626
769
  projectFile,
@@ -640,7 +783,7 @@ function defaultConfiguration(project) {
640
783
  );
641
784
  return names.includes("Debug") ? "Debug" : str(configList?.defaultConfigurationName) ?? names[0] ?? "Debug";
642
785
  }
643
- function targetSettings(ref, configuration, builtins) {
786
+ function targetSettings(ref, configuration, builtins, options = {}) {
644
787
  const { project, target } = ref;
645
788
  const xcconfigs = [];
646
789
  const level = (listId) => {
@@ -652,6 +795,10 @@ function targetSettings(ref, configuration, builtins) {
652
795
  const base = str(config.baseConfigurationReference);
653
796
  const own = isDict(config.buildSettings) ? config.buildSettings : {};
654
797
  const baseFile = base ? project.resolvePath(base) : null;
798
+ if (options.requireSources !== false && base && (!baseFile || !fs.existsSync(baseFile)))
799
+ throw new Error(
800
+ `Unable to open base configuration reference file '${baseFile ?? base}'`
801
+ );
655
802
  const read = [];
656
803
  const fromFile = baseFile ? readXcconfig(baseFile, read) : {};
657
804
  xcconfigs.push(...read);
@@ -747,23 +894,6 @@ function targetMembers(ref, settings, options = {}) {
747
894
  const sources = /* @__PURE__ */ new Set();
748
895
  const allSources = /* @__PURE__ */ new Set();
749
896
  const resources = /* @__PURE__ */ new Set();
750
- const addResource = (file) => {
751
- if (isDirectory(file)) {
752
- for (const inner of walkFiles(file)) resources.add(inner);
753
- } else if (fs.existsSync(file)) resources.add(file);
754
- };
755
- const fileRefPaths = (refId) => {
756
- const entry = project.object(refId);
757
- if (!entry) return [];
758
- if (entry.isa === "PBXVariantGroup") {
759
- return list(entry.children).flatMap((child) => {
760
- const resolved2 = project.resolvePath(child);
761
- return resolved2 ? [resolved2] : [];
762
- });
763
- }
764
- const resolved = project.resolvePath(refId);
765
- return resolved ? [resolved] : [];
766
- };
767
897
  const scriptForOutput = /* @__PURE__ */ new Map();
768
898
  const noteScriptOutput = (raw, script) => {
769
899
  const expanded = expand(raw, settings);
@@ -787,26 +917,28 @@ function targetMembers(ref, settings, options = {}) {
787
917
  }
788
918
  }
789
919
  }
790
- for (const phaseId of list(target.buildPhases)) {
791
- const phase = project.object(phaseId);
792
- if (phase?.isa !== "PBXSourcesBuildPhase" && phase?.isa !== "PBXResourcesBuildPhase")
793
- continue;
794
- for (const buildFileId of list(phase.files)) {
795
- for (const file of fileRefPaths(str(project.object(buildFileId)?.fileRef) ?? "")) {
796
- if (phase.isa === "PBXSourcesBuildPhase") {
797
- if (!fs.existsSync(file)) {
798
- if (options.requireSources === false) continue;
799
- const script = scriptForOutput.get(path2.normalize(file));
800
- throw new Error(
801
- script ? `${targetName}: missing generated source ${file} (Run Script "${script}" declares it in outputPaths; run the script or check in its output)` : `${targetName}: missing source ${file}`
802
- );
803
- }
804
- allSources.add(file);
805
- if (file.endsWith(".swift")) sources.add(file);
806
- } else if (phase.isa === "PBXResourcesBuildPhase") addResource(file);
920
+ visitXcodeTargetMembers(
921
+ project.objects,
922
+ targetId,
923
+ project.resolvePath,
924
+ (file) => isDirectory(file) ? walkFiles(file) : fs.existsSync(file) ? [file] : [],
925
+ path2.join,
926
+ (file, kind) => {
927
+ if (kind === "resource") {
928
+ resources.add(file);
929
+ return;
807
930
  }
931
+ if (!fs.existsSync(file)) {
932
+ if (options.requireSources === false) return;
933
+ const script = scriptForOutput.get(path2.normalize(file));
934
+ throw new Error(
935
+ script ? `${targetName}: missing generated source ${file} (Run Script "${script}" declares it in outputPaths; run the script or check in its output)` : `${targetName}: missing source ${file}`
936
+ );
937
+ }
938
+ allSources.add(file);
939
+ if (file.endsWith(".swift")) sources.add(file);
808
940
  }
809
- }
941
+ );
810
942
  for (const [file, script] of scriptForOutput) {
811
943
  if (sources.has(file) || allSources.has(file)) continue;
812
944
  if (!fs.existsSync(file)) {
@@ -818,52 +950,6 @@ function targetMembers(ref, settings, options = {}) {
818
950
  allSources.add(file);
819
951
  sources.add(file);
820
952
  }
821
- const addSynchronized = (folder, relative) => {
822
- const file = path2.join(folder, relative);
823
- if (NEVER_MEMBER.test(relative)) return;
824
- if (file.endsWith(".swift")) {
825
- if (!relative.split("/").some((segment) => BUNDLE_DIR.test(segment))) {
826
- sources.add(file);
827
- allSources.add(file);
828
- }
829
- } else if (/\.(h|m|mm|c|cpp|metal)$/.test(file)) {
830
- if (!file.endsWith(".h")) allSources.add(file);
831
- } else resources.add(file);
832
- };
833
- const owned = new Set(list(target.fileSystemSynchronizedGroups));
834
- for (const [groupId, group] of Object.entries(project.objects)) {
835
- if (!isDict(group) || group.isa !== "PBXFileSystemSynchronizedRootGroup") continue;
836
- const folder = project.resolvePath(groupId);
837
- if (!folder) continue;
838
- const exceptions = /* @__PURE__ */ new Set();
839
- for (const exceptionId of list(group.exceptions)) {
840
- const exception = project.object(exceptionId);
841
- if (exception?.target !== targetId) continue;
842
- for (const relative of list(exception.membershipExceptions))
843
- exceptions.add(relative);
844
- }
845
- if (owned.has(groupId)) {
846
- for (const file of walkFiles(folder)) {
847
- const relative = path2.relative(folder, file).split(path2.sep).join("/");
848
- if ([...exceptions].some(
849
- (exception) => relative === exception || relative.startsWith(`${exception}/`)
850
- ))
851
- continue;
852
- addSynchronized(folder, relative);
853
- }
854
- } else {
855
- for (const relative of exceptions) {
856
- const file = path2.join(folder, relative);
857
- if (isDirectory(file)) {
858
- for (const inner of walkFiles(file))
859
- addSynchronized(
860
- folder,
861
- path2.relative(folder, inner).split(path2.sep).join("/")
862
- );
863
- } else if (fs.existsSync(file)) addSynchronized(folder, relative);
864
- }
865
- }
866
- }
867
953
  return {
868
954
  sources: [...sources].sort(),
869
955
  resources: [...resources].sort(),
@@ -917,15 +1003,31 @@ function nativeTargets(project) {
917
1003
  }
918
1004
  return refs;
919
1005
  }
920
- function listXcodeAppTargets(xcodeprojOrWorkspace) {
921
- return workspaceProjects(xcodeprojOrWorkspace).projects.flatMap(nativeTargets).filter((ref) => ref.target.productType === APPLICATION).map((ref) => str(ref.target.name) ?? ref.id);
1006
+ function isIosAppTarget(ref, options = {}) {
1007
+ if (ref.target.productType !== APPLICATION) return false;
1008
+ const { get } = targetSettings(
1009
+ ref,
1010
+ defaultConfiguration(ref.project),
1011
+ {
1012
+ TARGET_NAME: str(ref.target.name) ?? ref.id
1013
+ },
1014
+ options
1015
+ );
1016
+ const sdk = get("SDKROOT");
1017
+ return sdk === "auto" ? settingList(get("SUPPORTED_PLATFORMS")).some(isIosPlatform) : sdk === "" || isIosPlatform(sdk);
1018
+ }
1019
+ function isIosPlatform(name) {
1020
+ return name.startsWith("iphoneos") || name.startsWith("iphonesimulator");
1021
+ }
1022
+ function listXcodeAppTargets(xcodeprojOrWorkspace, options = {}) {
1023
+ return workspaceProjects(xcodeprojOrWorkspace).projects.flatMap(nativeTargets).filter((ref) => isIosAppTarget(ref, options)).map((ref) => str(ref.target.name) ?? ref.id);
922
1024
  }
923
1025
  function readXcodeAppTarget(input, targetName, configurationName, options = {}) {
924
1026
  const xcodeprojOrWorkspace = fs.realpathSync(input);
925
1027
  const workspace = xcodeprojOrWorkspace.endsWith(".xcworkspace") ? xcodeprojOrWorkspace : null;
926
1028
  const { listed, projects, projectAt } = workspaceProjects(xcodeprojOrWorkspace);
927
1029
  const allTargets = projects.flatMap(nativeTargets);
928
- const appTargets = allTargets.filter((ref) => ref.target.productType === APPLICATION);
1030
+ const appTargets = allTargets.filter((ref) => isIosAppTarget(ref, options));
929
1031
  const appTargetNames = appTargets.map((ref) => str(ref.target.name) ?? ref.id);
930
1032
  const container = path2.basename(xcodeprojOrWorkspace);
931
1033
  const named = targetName ? appTargets.filter((ref) => ref.target.name === targetName) : appTargets;
@@ -993,14 +1095,19 @@ function readXcodeAppTarget(input, targetName, configurationName, options = {})
993
1095
  get: settings2,
994
1096
  keys,
995
1097
  xcconfigs: read
996
- } = targetSettings(ref, configuration, {
997
- TARGET_NAME: name,
998
- PROJECT_NAME: path2.basename(ref.project.xcodeproj, ".xcodeproj"),
999
- SRCROOT: ref.project.projectDir,
1000
- SOURCE_ROOT: ref.project.projectDir,
1001
- PROJECT_DIR: ref.project.projectDir,
1002
- DEVELOPMENT_LANGUAGE: str(ref.project.project.developmentRegion) ?? "en"
1003
- });
1098
+ } = targetSettings(
1099
+ ref,
1100
+ configuration,
1101
+ {
1102
+ TARGET_NAME: name,
1103
+ PROJECT_NAME: path2.basename(ref.project.xcodeproj, ".xcodeproj"),
1104
+ SRCROOT: ref.project.projectDir,
1105
+ SOURCE_ROOT: ref.project.projectDir,
1106
+ PROJECT_DIR: ref.project.projectDir,
1107
+ DEVELOPMENT_LANGUAGE: str(ref.project.project.developmentRegion) ?? "en"
1108
+ },
1109
+ options
1110
+ );
1004
1111
  for (const file of read) xcconfigs.add(file);
1005
1112
  const swiftVersion = Number.parseFloat(settings2("SWIFT_VERSION") || "5");
1006
1113
  return {
@@ -1138,7 +1245,7 @@ function readXcodeAppTarget(input, targetName, configurationName, options = {})
1138
1245
  }
1139
1246
 
1140
1247
  // src/native-app-identity-project.ts
1141
- function isRecord(value) {
1248
+ function isRecord2(value) {
1142
1249
  return typeof value === "object" && value !== null && !Array.isArray(value);
1143
1250
  }
1144
1251
  function nonEmptyString(value) {
@@ -1146,7 +1253,7 @@ function nonEmptyString(value) {
1146
1253
  }
1147
1254
  function readNativeAppIdentityFromXcodeTarget(app, parseInfoPlist = parsePlistSource) {
1148
1255
  const dictionary = parseInfoPlist(app.infoPlist);
1149
- if (!isRecord(dictionary)) throw new Error("native app Info.plist is not a dictionary");
1256
+ if (!isRecord2(dictionary)) throw new Error("native app Info.plist is not a dictionary");
1150
1257
  const settings = app.settings;
1151
1258
  const bundleIdentifier = nonEmptyString(dictionary.CFBundleIdentifier) ?? nonEmptyString(settings?.("PRODUCT_BUNDLE_IDENTIFIER"));
1152
1259
  if (!bundleIdentifier) throw new Error("native app has no bundle identifier");
@@ -1160,10 +1267,11 @@ function readNativeAppIdentityFromXcodeTarget(app, parseInfoPlist = parsePlistSo
1160
1267
  const applicationName = applicationDisplayName ?? bundleName;
1161
1268
  const declaredBackgroundColor = dictionary.RCTRootViewBackgroundColor;
1162
1269
  const rootViewBackgroundColor = typeof declaredBackgroundColor === "number" && Number.isInteger(declaredBackgroundColor) ? declaredBackgroundColor : void 0;
1270
+ const designRequiresCompatibility = dictionary.UIDesignRequiresCompatibility === true;
1163
1271
  const alternateIconNames = /* @__PURE__ */ new Set();
1164
1272
  const icons = dictionary.CFBundleIcons;
1165
- const alternates = isRecord(icons) ? icons.CFBundleAlternateIcons : void 0;
1166
- if (isRecord(alternates)) {
1273
+ const alternates = isRecord2(icons) ? icons.CFBundleAlternateIcons : void 0;
1274
+ if (isRecord2(alternates)) {
1167
1275
  for (const name of Object.keys(alternates)) {
1168
1276
  if (name) alternateIconNames.add(name);
1169
1277
  }
@@ -1196,10 +1304,16 @@ function readNativeAppIdentityFromXcodeTarget(app, parseInfoPlist = parsePlistSo
1196
1304
  dictionary.EXDefaultScreenOrientationMask
1197
1305
  );
1198
1306
  const shareIntoAppGroupId = nonEmptyString(dictionary.ExpoShareIntoAppGroupId);
1307
+ const rootModuleName = readRootModuleName(
1308
+ app.allSources.filter((file) => /\.(?:swift|mm|m)$/.test(file) && fs2.existsSync(file)).map((file) => fs2.readFileSync(file, "utf8"))
1309
+ );
1199
1310
  return {
1200
1311
  applicationName,
1201
1312
  ...applicationDisplayName ? { applicationDisplayName } : {},
1313
+ ...rootModuleName ? { rootModuleName } : {},
1202
1314
  ...rootViewBackgroundColor !== void 0 ? { rootViewBackgroundColor } : {},
1315
+ ...designRequiresCompatibility ? { designRequiresCompatibility } : {},
1316
+ ...typeof dictionary.DTPlatformVersion === "string" ? { dtPlatformVersion: dictionary.DTPlatformVersion } : {},
1203
1317
  bundleName,
1204
1318
  appVersion,
1205
1319
  buildVersion,
@@ -1209,6 +1323,19 @@ function readNativeAppIdentityFromXcodeTarget(app, parseInfoPlist = parsePlistSo
1209
1323
  ipadSupportedInterfaceOrientations,
1210
1324
  ...defaultScreenOrientationMask ? { defaultScreenOrientationMask } : {},
1211
1325
  alternateIconNames: [...alternateIconNames],
1326
+ appIconArtwork: resolveNativeAppIconArtwork(
1327
+ app.resources,
1328
+ (file) => fs2.readFileSync(file, "utf8"),
1329
+ (file) => {
1330
+ const extension = path3.extname(file).toLowerCase();
1331
+ const contentType = extension === ".jpg" || extension === ".jpeg" ? "image/jpeg" : extension === ".webp" ? "image/webp" : "image/png";
1332
+ return `data:${contentType};base64,${fs2.readFileSync(file).toString("base64")}`;
1333
+ },
1334
+ icons,
1335
+ app.appIconName,
1336
+ [...alternateIconNames],
1337
+ (value) => value
1338
+ ),
1212
1339
  permissionUsageDescriptions,
1213
1340
  urlQuerySchemes,
1214
1341
  ...shareIntoAppGroupId ? { shareIntoAppGroupId } : {},
@@ -1217,6 +1344,8 @@ function readNativeAppIdentityFromXcodeTarget(app, parseInfoPlist = parsePlistSo
1217
1344
  appIntentIdentifiers
1218
1345
  };
1219
1346
  }
1347
+ var NativeAppTargetSelectionError = class extends Error {
1348
+ };
1220
1349
  function readNativeAppIdentityFromProject(projectRoot, platform, parseInfoPlist = parsePlistSource, iosTarget) {
1221
1350
  if (!canExtractNativeAppIdentity(platform)) return null;
1222
1351
  const iosRoot = path3.join(projectRoot, "ios");
@@ -1224,12 +1353,16 @@ function readNativeAppIdentityFromProject(projectRoot, platform, parseInfoPlist
1224
1353
  const projects = fs2.readdirSync(iosRoot, { withFileTypes: true }).filter((entry) => entry.isDirectory() && entry.name.endsWith(".xcodeproj"));
1225
1354
  if (projects.length === 0) return null;
1226
1355
  if (projects.length > 1 && !iosTarget) {
1227
- throw new Error("native app identity requires a selected Xcode project");
1356
+ throw new NativeAppTargetSelectionError(
1357
+ `native app identity requires a selected Xcode project; set withPeach's iosTarget to an app target in one of: ${projects.map((entry) => entry.name).join(", ")}`
1358
+ );
1228
1359
  }
1229
1360
  let project = projects[0];
1230
1361
  if (iosTarget && projects.length > 1) {
1231
1362
  const matches = projects.filter(
1232
- (entry) => listXcodeAppTargets(path3.join(iosRoot, entry.name)).includes(iosTarget)
1363
+ (entry) => listXcodeAppTargets(path3.join(iosRoot, entry.name), {
1364
+ requireSources: false
1365
+ }).includes(iosTarget)
1233
1366
  );
1234
1367
  if (matches.length === 0) {
1235
1368
  throw new Error(`native app identity has no application target ${iosTarget}`);
@@ -1242,16 +1375,69 @@ function readNativeAppIdentityFromProject(projectRoot, platform, parseInfoPlist
1242
1375
  project = matches[0];
1243
1376
  }
1244
1377
  const xcodeproj = path3.join(iosRoot, project.name);
1245
- const appTargets = listXcodeAppTargets(xcodeproj);
1378
+ const appTargets = listXcodeAppTargets(xcodeproj, { requireSources: false });
1246
1379
  if (!iosTarget && appTargets.length > 1) {
1247
- throw new Error("native app identity requires a selected app target");
1380
+ throw new NativeAppTargetSelectionError(
1381
+ `native app identity requires a selected app target; set withPeach's iosTarget to one of: ${appTargets.join(", ")}`
1382
+ );
1248
1383
  }
1249
1384
  const app = readXcodeAppTarget(xcodeproj, iosTarget ?? appTargets[0], "Release", {
1250
1385
  requireSources: false
1251
1386
  });
1252
- return readNativeAppIdentityFromXcodeTarget(app, parseInfoPlist);
1387
+ const identity = readNativeAppIdentityFromXcodeTarget(app, parseInfoPlist);
1388
+ const projectManifestPath = path3.join(projectRoot, "package.json");
1389
+ const projectRequire = createRequire(projectManifestPath);
1390
+ let reanimatedManifestPath;
1391
+ try {
1392
+ reanimatedManifestPath = projectRequire.resolve(
1393
+ "react-native-reanimated/package.json"
1394
+ );
1395
+ } catch (error) {
1396
+ if (error instanceof Error && "code" in error && error.code === "MODULE_NOT_FOUND") {
1397
+ return identity;
1398
+ }
1399
+ throw error;
1400
+ }
1401
+ const installedManifest = JSON.parse(
1402
+ fs2.readFileSync(reanimatedManifestPath, "utf8")
1403
+ );
1404
+ const installedVersion = isRecord2(installedManifest) ? nonEmptyString(installedManifest.version) : void 0;
1405
+ if (!installedVersion) throw new Error("Reanimated package version is malformed");
1406
+ if (installedVersion.startsWith("3.")) return identity;
1407
+ const defaults = JSON.parse(
1408
+ fs2.readFileSync(
1409
+ path3.join(
1410
+ path3.dirname(reanimatedManifestPath),
1411
+ "src/featureFlags/staticFlags.json"
1412
+ ),
1413
+ "utf8"
1414
+ )
1415
+ );
1416
+ if (!isRecord2(defaults)) throw new Error("Reanimated static flags are malformed");
1417
+ const manifest = JSON.parse(fs2.readFileSync(projectManifestPath, "utf8"));
1418
+ const reanimated = isRecord2(manifest) ? manifest.reanimated : void 0;
1419
+ const overrides = isRecord2(reanimated) ? reanimated.staticFeatureFlags : void 0;
1420
+ if (overrides !== void 0 && !isRecord2(overrides)) {
1421
+ throw new Error("Reanimated static flag overrides are malformed");
1422
+ }
1423
+ const flags = {};
1424
+ for (const [name, value] of Object.entries({ ...defaults, ...overrides })) {
1425
+ flags[name] = String(value) === "true";
1426
+ }
1427
+ if (flags.USE_LEGACY_LAYOUT_ANIMATIONS_PROXY && flags.ENABLE_SHARED_ELEMENT_TRANSITIONS) {
1428
+ throw new Error(
1429
+ "Reanimated legacy layout animations cannot enable shared element transitions"
1430
+ );
1431
+ }
1432
+ if (flags.USE_ANIMATION_BACKEND && flags.FORCE_REACT_RENDER_FOR_SETTLED_ANIMATIONS) {
1433
+ throw new Error(
1434
+ "Reanimated animation backend requires settled React renders to be disabled"
1435
+ );
1436
+ }
1437
+ return { ...identity, reanimatedStaticFeatureFlags: flags };
1253
1438
  }
1254
1439
  export {
1440
+ NativeAppTargetSelectionError,
1255
1441
  readNativeAppIdentityFromProject,
1256
1442
  readNativeAppIdentityFromXcodeTarget
1257
1443
  };