peachsim 0.1.1635 → 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 (129) hide show
  1. package/README.md +5 -1
  2. package/cli/app-config.ts +14 -5
  3. package/cli/app-stubs.ts +62 -13
  4. package/cli/bridge-flow-runner.ts +2 -2
  5. package/cli/cloud-client.ts +60 -40
  6. package/cli/commands/doctor.ts +13 -5
  7. package/cli/commands/flow.ts +1 -1
  8. package/cli/commands/inspect/shared.ts +9 -4
  9. package/cli/commands/inspect.ts +65 -47
  10. package/cli/commands/preview.ts +1 -1
  11. package/cli/commands/record.ts +97 -47
  12. package/cli/commands/swift.ts +9 -3
  13. package/cli/commands/upload.ts +48 -42
  14. package/cli/drivers/playwright-sim-host.ts +65 -42
  15. package/cli/main.ts +1 -1
  16. package/cli/outbound-endpoints.ts +7 -5
  17. package/cli/pause-aware-timeout.ts +4 -0
  18. package/cli/ws-bridge.ts +19 -10
  19. package/detox/attempt-events.cjs +62 -5
  20. package/detox/attempt-events.d.cts +7 -0
  21. package/detox/expectations.ts +7 -3
  22. package/detox/index.ts +121 -47
  23. package/detox/motion-change.cjs +170 -21
  24. package/detox/motion-change.d.cts +32 -0
  25. package/detox/navigation-lifecycle.ts +35 -3
  26. package/dist-lib/agent-daemon-client.cjs +1 -1
  27. package/dist-lib/agent-events.cjs +1 -1
  28. package/dist-lib/attached-projects.cjs +1 -1
  29. package/dist-lib/auth/shared-session.cjs +1 -1
  30. package/dist-lib/backend-origin.cjs +8 -7
  31. package/dist-lib/beta.cjs +1 -1
  32. package/dist-lib/beta.mjs +1 -1
  33. package/dist-lib/bridge-constants.cjs +1 -1
  34. package/dist-lib/bridge-contract-input.cjs +1 -1
  35. package/dist-lib/bridge-contract-input.mjs +1 -1
  36. package/dist-lib/bridge-contract.cjs +1 -1
  37. package/dist-lib/bridge-contract.mjs +1 -1
  38. package/dist-lib/bundle-channel.cjs +4038 -1983
  39. package/dist-lib/capture-contract.cjs +1 -1
  40. package/dist-lib/capture-contract.mjs +1 -1
  41. package/dist-lib/cloud-contract.cjs +1 -1
  42. package/dist-lib/cloud-contract.mjs +1 -1
  43. package/dist-lib/cloud-test-args.cjs +1 -1
  44. package/dist-lib/cloud-test-args.mjs +1 -1
  45. package/dist-lib/cloud.cjs +1 -1
  46. package/dist-lib/cloud.mjs +1 -1
  47. package/dist-lib/config.cjs +1 -1
  48. package/dist-lib/config.mjs +1 -1
  49. package/dist-lib/detox/index.cjs +509 -86
  50. package/dist-lib/dev-bundle-resolution.cjs +1 -1
  51. package/dist-lib/expo-swift-bundle.cjs +3551 -1574
  52. package/dist-lib/expo-swift-metadata.cjs +9 -7
  53. package/dist-lib/expo-swift-metadata.mjs +9 -7
  54. package/dist-lib/home-paths.cjs +1 -1
  55. package/dist-lib/host/bridge-host.cjs +43633 -2635
  56. package/dist-lib/host/fetch-proxy-handler.cjs +1 -1
  57. package/dist-lib/host/fetch-proxy-overrides.cjs +1 -1
  58. package/dist-lib/host/fetch-proxy-overrides.mjs +1 -1
  59. package/dist-lib/host/replacement-module-handler.cjs +1 -1
  60. package/dist-lib/host/websocket-proxy.cjs +1 -1
  61. package/dist-lib/index.cjs +2748 -128
  62. package/dist-lib/jump-to-source-babel.cjs +1 -1
  63. package/dist-lib/jump-to-source-native.cjs +1 -1
  64. package/dist-lib/kotlin-host.cjs +1 -1
  65. package/dist-lib/menu.cjs +1 -1
  66. package/dist-lib/menu.mjs +1 -1
  67. package/dist-lib/metro-fingerprint-registry.cjs +1 -1
  68. package/dist-lib/metro-fingerprint-registry.mjs +1 -1
  69. package/dist-lib/metro-production-bundle.cjs +1 -1
  70. package/dist-lib/metro-production-bundle.mjs +1 -1
  71. package/dist-lib/metro.cjs +2547 -83
  72. package/dist-lib/native-app-identity-project.cjs +237 -50
  73. package/dist-lib/native-app-identity-project.mjs +237 -50
  74. package/dist-lib/native-app-identity.cjs +29 -30
  75. package/dist-lib/native-app-identity.mjs +29 -30
  76. package/dist-lib/native-firebase-metadata.cjs +1 -1
  77. package/dist-lib/native-firebase-metadata.mjs +1 -1
  78. package/dist-lib/plist.cjs +1 -1
  79. package/dist-lib/plist.mjs +1 -1
  80. package/dist-lib/profiles.cjs +1 -1
  81. package/dist-lib/public-brand.cjs +1 -1
  82. package/dist-lib/react-native-host-modules.cjs +2 -2
  83. package/dist-lib/react-native-host-modules.mjs +2 -2
  84. package/dist-lib/scripts/dev-server-scanner.cjs +8 -6
  85. package/dist-lib/sdk.cjs +1 -1
  86. package/dist-lib/sdk.mjs +1 -1
  87. package/dist-lib/skills.cjs +65403 -22739
  88. package/dist-lib/swift-compile.cjs +93 -32
  89. package/dist-lib/swift-compile.mjs +93 -32
  90. package/dist-lib/swift-package.cjs +1 -1
  91. package/dist-lib/swift-package.mjs +1 -1
  92. package/dist-lib/swift-submit.cjs +7 -5
  93. package/dist-lib/swift-submit.mjs +7 -5
  94. package/dist-lib/swift-toolchain.cjs +316 -41
  95. package/dist-lib/swift.cjs +1 -1
  96. package/dist-lib/vite-swift.cjs +7335 -5432
  97. package/dist-lib/vite.cjs +2857 -12
  98. package/dist-lib/worklet-executable.cjs +14 -2
  99. package/dist-lib/worklet-executable.mjs +14 -2
  100. package/package.json +1 -1
  101. package/src/backend-origin.ts +13 -6
  102. package/src/expo-swift-host.ts +5 -2
  103. package/src/expoKotlinContract.ts +4 -7
  104. package/src/expoSwiftContract.ts +4 -6
  105. package/src/host/staged-host-files.ts +9 -0
  106. package/src/native-app-identity-project.ts +1 -4
  107. package/src/native-app-identity.ts +1 -4
  108. package/src/nativeAppIconContract.ts +1 -4
  109. package/src/output-lock-stdio.ts +36 -0
  110. package/src/react-native-bridge-modules.ts +21 -6
  111. package/src/react-native-host-modules.ts +4 -1
  112. package/src/settings-bundle.ts +1 -4
  113. package/src/swift-compile.ts +91 -33
  114. package/src/swift-distribution.lock.json +22 -12
  115. package/src/swift-distribution.ts +103 -4
  116. package/src/swift-host.ts +89 -26
  117. package/src/swift-icu.ts +16 -10
  118. package/src/swift-objc-compile.ts +355 -0
  119. package/src/swift-objc-sdk.ts +689 -18
  120. package/src/swift-objc-standin.ts +126 -14
  121. package/src/swift-package-manifest.ts +39 -1
  122. package/src/swift-packages.ts +35 -21
  123. package/src/swift-standin-emit.ts +40 -7
  124. package/src/swift-standins.ts +404 -138
  125. package/src/swift-submit.ts +3 -5
  126. package/src/swift-toolchain.ts +378 -46
  127. package/src/worker-system-chunks.ts +11 -12
  128. package/src/worklet-executable.ts +19 -1
  129. package/src/xcode-project.ts +270 -30
@@ -1,4 +1,4 @@
1
- /*! peach v0.1.1635 | (c) 2026 Tamagui LLC | Proprietary; see LICENSE */
1
+ /*! peach v0.1.1640 | (c) 2026 Tamagui LLC | Proprietary; see LICENSE */
2
2
 
3
3
  // src/native-app-identity-project.ts
4
4
  import fs2 from "node:fs";
@@ -187,10 +187,12 @@ function androidMergedResourceValuesDirectory(manifestFile) {
187
187
  return `${intermediates}incremental/${variant}/merge${taskVariant}Resources/merged.dir`;
188
188
  }
189
189
 
190
- // src/nativeAppIconContract.ts
190
+ // src/is-record.ts
191
191
  function isRecord(value) {
192
192
  return typeof value === "object" && value !== null && !Array.isArray(value);
193
193
  }
194
+
195
+ // src/nativeAppIconContract.ts
194
196
  function resolveNativeAppIconArtwork(resources, readText, resourceUri, icons, primaryName, alternateNames, resolveReference) {
195
197
  const members = new Set(resources);
196
198
  const dictionary = isRecord(icons) ? icons : {};
@@ -444,21 +446,18 @@ function visitXcodeTargetMembers(objects, targetId, resolvePath, filesUnder, joi
444
446
  }
445
447
 
446
448
  // src/native-app-identity.ts
447
- function isRecord2(value) {
448
- return typeof value === "object" && value !== null && !Array.isArray(value);
449
- }
450
449
  function nonEmptyString(value) {
451
450
  return typeof value === "string" && value.length > 0 ? value : null;
452
451
  }
453
452
  function readGoogleSignInConfiguration(plist3, resources) {
454
453
  const clientIds = {};
455
454
  for (const [file, value] of Object.entries(resources)) {
456
- if (isRecord2(value) && typeof value.CLIENT_ID === "string")
455
+ if (isRecord(value) && typeof value.CLIENT_ID === "string")
457
456
  clientIds[file.split("/").pop()?.replace(/\.plist$/, "") ?? file] = value.CLIENT_ID;
458
457
  }
459
458
  const urlSchemes = [];
460
459
  for (const entry of Array.isArray(plist3.CFBundleURLTypes) ? plist3.CFBundleURLTypes : []) {
461
- if (!isRecord2(entry) || !Array.isArray(entry.CFBundleURLSchemes)) continue;
460
+ if (!isRecord(entry) || !Array.isArray(entry.CFBundleURLSchemes)) continue;
462
461
  for (const scheme of entry.CFBundleURLSchemes)
463
462
  if (typeof scheme === "string") urlSchemes.push(scheme);
464
463
  }
@@ -566,14 +565,14 @@ function nativeAppIdentityFromIos(files, parseInfoPlist, iosTarget, resourceUri)
566
565
  let objects = {};
567
566
  try {
568
567
  const parsed = parseOpenStepPlist(pbxproj);
569
- if (isRecord2(parsed)) {
570
- objects = isRecord2(parsed.objects) ? parsed.objects : parsed;
568
+ if (isRecord(parsed)) {
569
+ objects = isRecord(parsed.objects) ? parsed.objects : parsed;
571
570
  }
572
571
  } catch {
573
572
  }
574
573
  const targets = [];
575
574
  for (const [id, obj] of Object.entries(objects)) {
576
- if (isRecord2(obj) && obj.isa === "PBXNativeTarget" && typeof obj.name === "string") {
575
+ if (isRecord(obj) && obj.isa === "PBXNativeTarget" && typeof obj.name === "string") {
577
576
  targets.push({
578
577
  id,
579
578
  name: obj.name,
@@ -619,13 +618,13 @@ function nativeAppIdentityFromIos(files, parseInfoPlist, iosTarget, resourceUri)
619
618
  PRODUCT_NAME: targetName
620
619
  };
621
620
  for (const obj of Object.values(objects)) {
622
- if (isRecord2(obj) && obj.isa === "PBXProject" && typeof obj.buildConfigurationList === "string") {
621
+ if (isRecord(obj) && obj.isa === "PBXProject" && typeof obj.buildConfigurationList === "string") {
623
622
  const listObj = objects[obj.buildConfigurationList];
624
- if (isRecord2(listObj) && Array.isArray(listObj.buildConfigurations)) {
623
+ if (isRecord(listObj) && Array.isArray(listObj.buildConfigurations)) {
625
624
  for (const configId of listObj.buildConfigurations) {
626
625
  if (typeof configId === "string") {
627
626
  const configObj = objects[configId];
628
- if (isRecord2(configObj) && configObj.name === "Release" && isRecord2(configObj.buildSettings)) {
627
+ if (isRecord(configObj) && configObj.name === "Release" && isRecord(configObj.buildSettings)) {
629
628
  for (const [k, v] of Object.entries(configObj.buildSettings)) {
630
629
  if (typeof v === "string") settings[k] = v;
631
630
  }
@@ -637,11 +636,11 @@ function nativeAppIdentityFromIos(files, parseInfoPlist, iosTarget, resourceUri)
637
636
  }
638
637
  if (selectedTarget?.buildConfigurationList) {
639
638
  const listObj = objects[selectedTarget.buildConfigurationList];
640
- if (isRecord2(listObj) && Array.isArray(listObj.buildConfigurations)) {
639
+ if (isRecord(listObj) && Array.isArray(listObj.buildConfigurations)) {
641
640
  for (const configId of listObj.buildConfigurations) {
642
641
  if (typeof configId === "string") {
643
642
  const configObj = objects[configId];
644
- if (isRecord2(configObj) && configObj.name === "Release" && isRecord2(configObj.buildSettings)) {
643
+ if (isRecord(configObj) && configObj.name === "Release" && isRecord(configObj.buildSettings)) {
645
644
  for (const [k, v] of Object.entries(configObj.buildSettings)) {
646
645
  if (typeof v === "string") settings[k] = v;
647
646
  }
@@ -692,7 +691,7 @@ function nativeAppIdentityFromIos(files, parseInfoPlist, iosTarget, resourceUri)
692
691
  if (!bundleName) return null;
693
692
  const applicationName = identityFieldFrom(settings, plistString(plist3, "CFBundleDisplayName"), void 0) ?? bundleName;
694
693
  const dictionary = parseInfoPlist(plist3);
695
- if (!isRecord2(dictionary)) throw new Error("native app Info.plist is not a dictionary");
694
+ if (!isRecord(dictionary)) throw new Error("native app Info.plist is not a dictionary");
696
695
  const declaredDisplayName = dictionary.CFBundleDisplayName;
697
696
  const applicationDisplayName = typeof declaredDisplayName === "string" ? resolveBuildSetting(declaredDisplayName, settings) : void 0;
698
697
  if (applicationDisplayName === null)
@@ -705,9 +704,9 @@ function nativeAppIdentityFromIos(files, parseInfoPlist, iosTarget, resourceUri)
705
704
  if (dtPlatformVersion === null)
706
705
  throw new Error("native app Info.plist DTPlatformVersion is unresolved");
707
706
  const icons = dictionary.CFBundleIcons;
708
- const alternates = isRecord2(icons) ? icons.CFBundleAlternateIcons : void 0;
707
+ const alternates = isRecord(icons) ? icons.CFBundleAlternateIcons : void 0;
709
708
  const alternateIconNames = /* @__PURE__ */ new Set();
710
- for (const name of isRecord2(alternates) ? Object.keys(alternates) : []) {
709
+ for (const name of isRecord(alternates) ? Object.keys(alternates) : []) {
711
710
  const resolved = resolveBuildSetting(name, settings);
712
711
  if (resolved === null) throw new Error("native alternate icon name is unresolved");
713
712
  alternateIconNames.add(resolved);
@@ -811,11 +810,11 @@ function nativeAppIdentityFromIos(files, parseInfoPlist, iosTarget, resourceUri)
811
810
  return `${base.startsWith("/") ? "/" : ""}${segments.join("/")}`;
812
811
  };
813
812
  const project = Object.values(objects).find(
814
- (object) => isRecord2(object) && object.isa === "PBXProject"
813
+ (object) => isRecord(object) && object.isa === "PBXProject"
815
814
  );
816
815
  const projectDir = join(
817
816
  pbxprojPath.replace(/(?:^|\/)[^/]+\.xcodeproj\/project\.pbxproj$/, ""),
818
- isRecord2(project) && typeof project.projectDirPath === "string" ? project.projectDirPath : ""
817
+ isRecord(project) && typeof project.projectDirPath === "string" ? project.projectDirPath : ""
819
818
  );
820
819
  const paths = Object.keys(files);
821
820
  visitXcodeTargetMembers(
@@ -928,6 +927,8 @@ function parsePlistSource(source) {
928
927
  }
929
928
 
930
929
  // src/xcode-project.ts
930
+ import { execFileSync } from "node:child_process";
931
+ import { createHash } from "node:crypto";
931
932
  import fs from "node:fs";
932
933
  import path2 from "node:path";
933
934
  import plist2 from "plist";
@@ -1535,33 +1536,131 @@ function expand(value, lookup) {
1535
1536
  }
1536
1537
  );
1537
1538
  }
1538
- function targetMembers(ref, settings, options = {}) {
1539
+ var preparedSourcePhases = /* @__PURE__ */ new Map();
1540
+ function targetMembers(ref, settings, options, settingKeys, projectInputs) {
1539
1541
  const { project, target, id: targetId } = ref;
1540
1542
  const targetName = str(target.name) ?? targetId;
1541
1543
  const sources = /* @__PURE__ */ new Set();
1542
1544
  const allSources = /* @__PURE__ */ new Set();
1543
1545
  const resources = /* @__PURE__ */ new Set();
1544
1546
  const scriptForOutput = /* @__PURE__ */ new Map();
1545
- const noteScriptOutput = (raw, script) => {
1546
- const expanded = expand(raw, settings);
1547
- if (!expanded.endsWith(".swift")) return;
1548
- const absolute = path2.isAbsolute(expanded) ? path2.normalize(expanded) : path2.resolve(project.projectDir, expanded);
1549
- if (!scriptForOutput.has(absolute)) scriptForOutput.set(absolute, script);
1550
- };
1551
1547
  for (const phaseId of list(target.buildPhases)) {
1552
1548
  const phase = project.object(phaseId);
1553
1549
  if (phase?.isa !== "PBXShellScriptBuildPhase") continue;
1554
1550
  const script = str(phase.name) ?? phaseId;
1555
- for (const raw of list(phase.outputPaths)) noteScriptOutput(raw, script);
1556
- for (const listPath of list(phase.outputFileListPaths)) {
1557
- const expandedList = expand(listPath, settings);
1558
- const absoluteList = path2.isAbsolute(expandedList) ? expandedList : path2.resolve(project.projectDir, expandedList);
1559
- if (!fs.existsSync(absoluteList)) continue;
1560
- for (const line of fs.readFileSync(absoluteList, "utf8").split("\n")) {
1561
- const trimmed = line.trim();
1562
- if (trimmed === "" || trimmed.startsWith("#")) continue;
1563
- noteScriptOutput(trimmed, script);
1551
+ const absolute = (raw) => path2.resolve(project.projectDir, expand(raw, settings));
1552
+ const inputs = list(phase.inputPaths).map(absolute);
1553
+ const outputs = list(phase.outputPaths).map(absolute);
1554
+ const fileLists = /* @__PURE__ */ new Map();
1555
+ for (const kind of ["INPUT", "OUTPUT"]) {
1556
+ const lists = list(
1557
+ kind === "INPUT" ? phase.inputFileListPaths : phase.outputFileListPaths
1558
+ ).map((raw) => {
1559
+ const file = absolute(raw);
1560
+ if (!fs.existsSync(file)) {
1561
+ return { file, entries: [] };
1562
+ }
1563
+ const entries = fs.readFileSync(file, "utf8").split(/\r?\n/).map((line) => line.trim()).filter((line) => line !== "" && !line.startsWith("#")).map(absolute);
1564
+ return { file, entries };
1565
+ });
1566
+ fileLists.set(kind, lists);
1567
+ }
1568
+ const allOutputs = [
1569
+ ...outputs,
1570
+ ...fileLists.get("OUTPUT").flatMap((item) => item.entries)
1571
+ ];
1572
+ for (const output of allOutputs)
1573
+ if (output.endsWith(".swift") && !scriptForOutput.has(output))
1574
+ scriptForOutput.set(output, script);
1575
+ const inputFiles = [
1576
+ ...inputs,
1577
+ ...fileLists.get("INPUT").flatMap((item) => [item.file, ...item.entries]),
1578
+ ...fileLists.get("OUTPUT").map((item) => item.file)
1579
+ ];
1580
+ if (allOutputs.some((file) => file.endsWith(".swift"))) {
1581
+ for (const file of inputFiles) if (fs.existsSync(file)) projectInputs.add(file);
1582
+ }
1583
+ if (options.prepareGeneratedSources && options.requireSources !== false && allOutputs.some((file) => file.endsWith(".swift"))) {
1584
+ const phaseDir = path2.join(settings("TARGET_TEMP_DIR"), `Script-${phaseId}`);
1585
+ for (const lists of fileLists.values())
1586
+ for (const { file } of lists)
1587
+ if (!fs.existsSync(file))
1588
+ throw new Error(
1589
+ `${targetName}: Run Script "${script}" missing file list ${file}`
1590
+ );
1591
+ const env = {
1592
+ ...process.env,
1593
+ ...Object.fromEntries(
1594
+ [...settingKeys].filter((key2) => /^[A-Za-z_][A-Za-z0-9_]*$/.test(key2)).map((key2) => [key2, settings(key2)])
1595
+ )
1596
+ };
1597
+ const declared = { INPUT: inputs, OUTPUT: outputs };
1598
+ for (const kind of ["INPUT", "OUTPUT"]) {
1599
+ env[`SCRIPT_${kind}_FILE_COUNT`] = String(declared[kind].length);
1600
+ declared[kind].forEach((file, index) => {
1601
+ env[`SCRIPT_${kind}_FILE_${index}`] = file;
1602
+ });
1603
+ const lists = fileLists.get(kind);
1604
+ env[`SCRIPT_${kind}_FILE_LIST_COUNT`] = String(lists.length);
1605
+ lists.forEach((_item, index) => {
1606
+ env[`SCRIPT_${kind}_FILE_LIST_${index}`] = path2.join(
1607
+ phaseDir,
1608
+ `${kind}-${index}.xcfilelist`
1609
+ );
1610
+ });
1564
1611
  }
1612
+ const signature = createHash("sha256").update(
1613
+ JSON.stringify([phase, [...settingKeys].map((key2) => [key2, settings(key2)])])
1614
+ );
1615
+ for (const file of inputFiles) {
1616
+ signature.update(file);
1617
+ if (fs.existsSync(file)) {
1618
+ const stat = fs.statSync(file);
1619
+ signature.update(`${stat.mtimeMs}:${stat.ctimeMs}:${stat.size}`);
1620
+ } else signature.update("missing");
1621
+ }
1622
+ const stamp = signature.digest("hex");
1623
+ const key = `${project.projectFile}:${targetId}:${phaseId}:${settings("CONFIGURATION")}`;
1624
+ if (preparedSourcePhases.get(key) === stamp && allOutputs.every((file) => fs.existsSync(file)))
1625
+ continue;
1626
+ fs.mkdirSync(phaseDir, { recursive: true });
1627
+ fs.mkdirSync(settings("BUILT_PRODUCTS_DIR"), { recursive: true });
1628
+ fs.mkdirSync(settings("DERIVED_FILE_DIR"), { recursive: true });
1629
+ for (const [kind, lists] of fileLists)
1630
+ lists.forEach((item, index) => {
1631
+ fs.writeFileSync(
1632
+ env[`SCRIPT_${kind}_FILE_LIST_${index}`],
1633
+ `${item.entries.join("\n")}
1634
+ `
1635
+ );
1636
+ });
1637
+ try {
1638
+ execFileSync(
1639
+ str(phase.shellPath) ?? "/bin/sh",
1640
+ ["-c", str(phase.shellScript) ?? ""],
1641
+ {
1642
+ cwd: project.projectDir,
1643
+ env,
1644
+ stdio: ["ignore", "pipe", "pipe"],
1645
+ timeout: 12e4
1646
+ }
1647
+ );
1648
+ } catch (error) {
1649
+ const output = error instanceof Error ? `${error.message}
1650
+ ${"stdout" in error ? String(error.stdout) : ""}${"stderr" in error ? String(error.stderr) : ""}` : String(error);
1651
+ throw new Error(
1652
+ `${targetName}: Run Script "${script}" failed preparing generated Swift sources:
1653
+ ${output}`
1654
+ );
1655
+ }
1656
+ const missing = allOutputs.filter(
1657
+ (file) => file.endsWith(".swift") && !fs.existsSync(file)
1658
+ );
1659
+ if (missing.length > 0)
1660
+ throw new Error(
1661
+ `${targetName}: Run Script "${script}" did not produce ${missing.join(", ")}`
1662
+ );
1663
+ preparedSourcePhases.set(key, stamp);
1565
1664
  }
1566
1665
  }
1567
1666
  visitXcodeTargetMembers(
@@ -1751,22 +1850,95 @@ function readXcodeAppTarget(input, targetName, configurationName, options = {})
1751
1850
  SRCROOT: ref.project.projectDir,
1752
1851
  SOURCE_ROOT: ref.project.projectDir,
1753
1852
  PROJECT_DIR: ref.project.projectDir,
1853
+ SYMROOT: path2.join(ref.project.projectDir, ".build/peach-xcode/Build/Products"),
1854
+ BUILD_DIR: "$(SYMROOT)",
1855
+ OBJROOT: path2.join(
1856
+ ref.project.projectDir,
1857
+ ".build/peach-xcode/Build/Intermediates.noindex"
1858
+ ),
1859
+ CONFIGURATION_BUILD_DIR: "$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)",
1860
+ BUILT_PRODUCTS_DIR: "$(CONFIGURATION_BUILD_DIR)",
1861
+ TARGET_BUILD_DIR: "$(CONFIGURATION_BUILD_DIR)",
1862
+ PROJECT_TEMP_DIR: "$(OBJROOT)/$(PROJECT_NAME).build",
1863
+ CONFIGURATION_TEMP_DIR: "$(PROJECT_TEMP_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)",
1864
+ TARGET_TEMP_DIR: "$(CONFIGURATION_TEMP_DIR)/$(TARGET_NAME).build",
1865
+ DERIVED_FILE_DIR: "$(TARGET_TEMP_DIR)/DerivedSources",
1866
+ DERIVED_FILES_DIR: "$(DERIVED_FILE_DIR)",
1867
+ PLATFORM_NAME: "iphonesimulator",
1868
+ EFFECTIVE_PLATFORM_NAME: "-iphonesimulator",
1869
+ CURRENT_ARCH: "arm64",
1870
+ ARCHS: "arm64",
1871
+ ACTION: "build",
1754
1872
  DEVELOPMENT_LANGUAGE: str(ref.project.project.developmentRegion) ?? "en"
1755
1873
  },
1756
1874
  options
1757
1875
  );
1758
1876
  for (const file of read) xcconfigs.add(file);
1759
1877
  const swiftVersion = Number.parseFloat(settings2("SWIFT_VERSION") || "5");
1878
+ const members = targetMembers(ref, settings2, options, keys, xcconfigs);
1879
+ const implementations = members.allSources.filter(
1880
+ (file) => /\.(c|cc|cpp|cxx|m|mm)$/.test(file)
1881
+ );
1882
+ const absolute = (file) => path2.resolve(ref.project.projectDir, file);
1883
+ const fileFlags = {};
1884
+ for (const phaseId of list(ref.target.buildPhases)) {
1885
+ const phase = ref.project.object(phaseId);
1886
+ if (phase?.isa !== "PBXSourcesBuildPhase") continue;
1887
+ for (const id of list(phase.files)) {
1888
+ const file = ref.project.object(id);
1889
+ const resolved = ref.project.resolvePath(str(file?.fileRef) ?? "");
1890
+ if (resolved && implementations.includes(resolved))
1891
+ fileFlags[resolved] = settingList(
1892
+ expand(
1893
+ str(isDict(file?.settings) ? file.settings.COMPILER_FLAGS : void 0) ?? "",
1894
+ settings2
1895
+ )
1896
+ );
1897
+ }
1898
+ }
1760
1899
  return {
1761
1900
  settings: settings2,
1762
1901
  keys,
1763
1902
  module: {
1764
1903
  name,
1765
1904
  moduleName: applyOperator(settings2("PRODUCT_MODULE_NAME"), "c99extidentifier"),
1766
- ...targetMembers(ref, settings2, options),
1905
+ ...members,
1767
1906
  languageMode: swiftVersion >= 6 ? 6 : 5,
1768
1907
  mainActorIsolation: settings2("SWIFT_DEFAULT_ACTOR_ISOLATION") === "MainActor",
1769
- defines: compilationConditions(settings2)
1908
+ defines: compilationConditions(settings2),
1909
+ iosDeploymentTarget: settings2("IPHONEOS_DEPLOYMENT_TARGET") || null,
1910
+ ...implementations.some((file) => /\.mm?$/.test(file)) ? {
1911
+ objc: {
1912
+ headers: Object.keys(ref.project.objects).flatMap((id) => {
1913
+ const file = ref.project.resolvePath(id);
1914
+ return file && /\.(h|hh|hpp|hxx|pch)$/.test(file) && fs.existsSync(file) ? [file] : [];
1915
+ }),
1916
+ prefixHeader: settings2("GCC_PREFIX_HEADER") ? absolute(settings2("GCC_PREFIX_HEADER")) : null,
1917
+ bridgingHeader: settings2("SWIFT_OBJC_BRIDGING_HEADER") ? absolute(settings2("SWIFT_OBJC_BRIDGING_HEADER")) : null,
1918
+ headerSearchPaths: [
1919
+ ...settingList(settings2("HEADER_SEARCH_PATHS")),
1920
+ ...settingList(settings2("USER_HEADER_SEARCH_PATHS"))
1921
+ ].map(absolute),
1922
+ frameworkSearchPaths: settingList(settings2("FRAMEWORK_SEARCH_PATHS")).map(
1923
+ absolute
1924
+ ),
1925
+ flags: [
1926
+ ...settings2("CLANG_ENABLE_OBJC_ARC") === "YES" ? ["-fobjc-arc"] : [],
1927
+ ...settings2("CLANG_ENABLE_OBJC_WEAK") === "YES" ? ["-fobjc-weak"] : [],
1928
+ ...settings2("CLANG_ENABLE_MODULES") === "YES" ? ["-fmodules"] : [],
1929
+ ...settings2("GCC_C_LANGUAGE_STANDARD") ? [`-std=${settings2("GCC_C_LANGUAGE_STANDARD")}`] : [],
1930
+ ...settingList(settings2("GCC_PREPROCESSOR_DEFINITIONS")).map(
1931
+ (value) => `-D${value}`
1932
+ ),
1933
+ ...settingList(settings2("OTHER_CFLAGS"))
1934
+ ],
1935
+ cxxFlags: [
1936
+ ...settings2("CLANG_CXX_LANGUAGE_STANDARD") ? [`-std=${settings2("CLANG_CXX_LANGUAGE_STANDARD")}`] : [],
1937
+ ...settingList(settings2("OTHER_CPLUSPLUSFLAGS"))
1938
+ ],
1939
+ fileFlags
1940
+ }
1941
+ } : {}
1770
1942
  }
1771
1943
  };
1772
1944
  };
@@ -1815,6 +1987,23 @@ function readXcodeAppTarget(input, targetName, configurationName, options = {})
1815
1987
  ...projects.flatMap(
1816
1988
  (project) => Object.entries(project.objects).flatMap(([id, entry]) => {
1817
1989
  if (!isDict(entry)) return [];
1990
+ if (entry.isa === "PBXFileSystemSynchronizedRootGroup") {
1991
+ const folder = project.resolvePath(id);
1992
+ const pending = folder ? [folder] : [];
1993
+ const packages = [];
1994
+ while (pending.length > 0) {
1995
+ const dir = pending.pop();
1996
+ if (fs.existsSync(path2.join(dir, "Package.swift"))) {
1997
+ packages.push(dir);
1998
+ continue;
1999
+ }
2000
+ if (!isDirectory(dir)) continue;
2001
+ for (const child of fs.readdirSync(dir, { withFileTypes: true }))
2002
+ if (child.isDirectory() && !child.name.startsWith("."))
2003
+ pending.push(path2.join(dir, child.name));
2004
+ }
2005
+ return packages;
2006
+ }
1818
2007
  const candidate = entry.isa === "XCLocalSwiftPackageReference" ? path2.resolve(project.projectDir, str(entry.relativePath) ?? "") : entry.isa === "PBXFileReference" ? project.resolvePath(id) : null;
1819
2008
  return candidate && fs.existsSync(path2.join(candidate, "Package.swift")) ? [candidate] : [];
1820
2009
  })
@@ -1869,6 +2058,7 @@ function readXcodeAppTarget(input, targetName, configurationName, options = {})
1869
2058
  "swiftpm",
1870
2059
  "Package.resolved"
1871
2060
  );
2061
+ const packageResolved = fs.existsSync(resolvedFile) ? [fs.realpathSync(resolvedFile)] : [...new Set(localPackageDirs.map((dir) => path2.join(dir, "Package.resolved")))].filter((file) => fs.existsSync(file)).map((file) => fs.realpathSync(file)).sort();
1872
2062
  const used = order.map((ref) => ref.project);
1873
2063
  return {
1874
2064
  ...module,
@@ -1894,7 +2084,7 @@ function readXcodeAppTarget(input, targetName, configurationName, options = {})
1894
2084
  ...new Set(localPackageDirs.map((dir) => fs.realpathSync(dir)))
1895
2085
  ].sort(),
1896
2086
  binaryFrameworks: [...binaryFrameworks].map(([name, file]) => ({ name, path: file })).sort((left, right) => left.name.localeCompare(right.name)),
1897
- packageResolved: fs.existsSync(resolvedFile) ? resolvedFile : null,
2087
+ packageResolved,
1898
2088
  appTargets: appTargetNames,
1899
2089
  configuration,
1900
2090
  settings
@@ -1902,15 +2092,12 @@ function readXcodeAppTarget(input, targetName, configurationName, options = {})
1902
2092
  }
1903
2093
 
1904
2094
  // src/native-app-identity-project.ts
1905
- function isRecord3(value) {
1906
- return typeof value === "object" && value !== null && !Array.isArray(value);
1907
- }
1908
2095
  function nonEmptyString2(value) {
1909
2096
  return typeof value === "string" && value.length > 0 ? value : void 0;
1910
2097
  }
1911
2098
  function readNativeAppIdentityFromXcodeTarget(app, parseInfoPlist = parsePlistSource) {
1912
2099
  const dictionary = parseInfoPlist(app.infoPlist);
1913
- if (!isRecord3(dictionary)) throw new Error("native app Info.plist is not a dictionary");
2100
+ if (!isRecord(dictionary)) throw new Error("native app Info.plist is not a dictionary");
1914
2101
  const settings = app.settings;
1915
2102
  const bundleIdentifier = nonEmptyString2(dictionary.CFBundleIdentifier) ?? nonEmptyString2(settings?.("PRODUCT_BUNDLE_IDENTIFIER"));
1916
2103
  if (!bundleIdentifier) throw new Error("native app has no bundle identifier");
@@ -1927,8 +2114,8 @@ function readNativeAppIdentityFromXcodeTarget(app, parseInfoPlist = parsePlistSo
1927
2114
  const designRequiresCompatibility = dictionary.UIDesignRequiresCompatibility === true;
1928
2115
  const alternateIconNames = /* @__PURE__ */ new Set();
1929
2116
  const icons = dictionary.CFBundleIcons;
1930
- const alternates = isRecord3(icons) ? icons.CFBundleAlternateIcons : void 0;
1931
- if (isRecord3(alternates)) {
2117
+ const alternates = isRecord(icons) ? icons.CFBundleAlternateIcons : void 0;
2118
+ if (isRecord(alternates)) {
1932
2119
  for (const name of Object.keys(alternates)) {
1933
2120
  if (name) alternateIconNames.add(name);
1934
2121
  }
@@ -2160,7 +2347,7 @@ function readIosNativeAppIdentity(projectRoot, parseInfoPlist, iosTarget) {
2160
2347
  const installedManifest = JSON.parse(
2161
2348
  fs2.readFileSync(reanimatedManifestPath, "utf8")
2162
2349
  );
2163
- const installedVersion = isRecord3(installedManifest) ? nonEmptyString2(installedManifest.version) : void 0;
2350
+ const installedVersion = isRecord(installedManifest) ? nonEmptyString2(installedManifest.version) : void 0;
2164
2351
  if (!installedVersion) throw new Error("Reanimated package version is malformed");
2165
2352
  if (Number.parseInt(installedVersion, 10) < 4) return identity;
2166
2353
  const defaults = JSON.parse(
@@ -2172,11 +2359,11 @@ function readIosNativeAppIdentity(projectRoot, parseInfoPlist, iosTarget) {
2172
2359
  "utf8"
2173
2360
  )
2174
2361
  );
2175
- if (!isRecord3(defaults)) throw new Error("Reanimated static flags are malformed");
2362
+ if (!isRecord(defaults)) throw new Error("Reanimated static flags are malformed");
2176
2363
  const manifest = JSON.parse(fs2.readFileSync(projectManifestPath, "utf8"));
2177
- const reanimated = isRecord3(manifest) ? manifest.reanimated : void 0;
2178
- const overrides = isRecord3(reanimated) ? reanimated.staticFeatureFlags : void 0;
2179
- if (overrides !== void 0 && !isRecord3(overrides)) {
2364
+ const reanimated = isRecord(manifest) ? manifest.reanimated : void 0;
2365
+ const overrides = isRecord(reanimated) ? reanimated.staticFeatureFlags : void 0;
2366
+ if (overrides !== void 0 && !isRecord(overrides)) {
2180
2367
  throw new Error("Reanimated static flag overrides are malformed");
2181
2368
  }
2182
2369
  const flags = {};
@@ -1,4 +1,4 @@
1
- /*! peach v0.1.1635 | (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;
@@ -241,6 +241,11 @@ function isFooterBlockLine(source, line, end) {
241
241
  return line === end || source.startsWith("globalThis.", line) || source.startsWith("//", line);
242
242
  }
243
243
 
244
+ // src/is-record.ts
245
+ function isRecord(value) {
246
+ return typeof value === "object" && value !== null && !Array.isArray(value);
247
+ }
248
+
244
249
  // src/assetCatalogContract.ts
245
250
  function isSwiftImageVariants(value) {
246
251
  return Array.isArray(value) && value.length > 0 && value.every(
@@ -249,9 +254,6 @@ function isSwiftImageVariants(value) {
249
254
  }
250
255
 
251
256
  // src/nativeAppIconContract.ts
252
- function isRecord(value) {
253
- return typeof value === "object" && value !== null && !Array.isArray(value);
254
- }
255
257
  function isNativeAppIconArtwork(value) {
256
258
  return isRecord(value) && (value.primary === void 0 || isSwiftImageVariants(value.primary)) && isRecord(value.alternates) && Object.values(value.alternates).every(isSwiftImageVariants);
257
259
  }
@@ -525,35 +527,32 @@ function visitXcodeTargetMembers(objects, targetId, resolvePath, filesUnder, joi
525
527
  var NATIVE_APP_IDENTITY_PREFIX = "globalThis.__sootsimNativeAppIdentity=";
526
528
  var METRO_MODULE_PATHS_PREFIX = "globalThis.__sootsimModulePaths=";
527
529
  var NATIVE_APP_IDENTITY_HEADER = "Peach-Native-App-Identity";
528
- function isRecord2(value) {
529
- return typeof value === "object" && value !== null && !Array.isArray(value);
530
- }
531
530
  function nonEmptyString(value) {
532
531
  return typeof value === "string" && value.length > 0 ? value : null;
533
532
  }
534
533
  function isNativeAppIdentity(value) {
535
- if (!isRecord2(value)) return false;
534
+ if (!isRecord(value)) return false;
536
535
  for (const key of ["statusBarHidden", "viewControllerBasedStatusBarAppearance"]) {
537
536
  if (value[key] !== void 0 && typeof value[key] !== "boolean") return false;
538
537
  }
539
538
  const oneUpdates = value.oneUpdates;
540
- if (oneUpdates !== void 0 && (!isRecord2(oneUpdates) || typeof oneUpdates.enabled !== "boolean" || oneUpdates.url !== null && typeof oneUpdates.url !== "string" || oneUpdates.runtimeVersion !== null && typeof oneUpdates.runtimeVersion !== "string" || oneUpdates.embeddedManifestJson !== null && typeof oneUpdates.embeddedManifestJson !== "string" || oneUpdates.enabled && (typeof oneUpdates.url !== "string" || oneUpdates.url.length === 0 || typeof oneUpdates.runtimeVersion !== "string" || oneUpdates.runtimeVersion.length === 0))) {
539
+ if (oneUpdates !== void 0 && (!isRecord(oneUpdates) || typeof oneUpdates.enabled !== "boolean" || oneUpdates.url !== null && typeof oneUpdates.url !== "string" || oneUpdates.runtimeVersion !== null && typeof oneUpdates.runtimeVersion !== "string" || oneUpdates.embeddedManifestJson !== null && typeof oneUpdates.embeddedManifestJson !== "string" || oneUpdates.enabled && (typeof oneUpdates.url !== "string" || oneUpdates.url.length === 0 || typeof oneUpdates.runtimeVersion !== "string" || oneUpdates.runtimeVersion.length === 0))) {
541
540
  return false;
542
541
  }
543
542
  if (value.dtPlatformVersion !== void 0 && typeof value.dtPlatformVersion !== "string")
544
543
  return false;
545
544
  if (value.androidManifestPermissions !== void 0 && (!Array.isArray(value.androidManifestPermissions) || !value.androidManifestPermissions.every(
546
- (permission) => isRecord2(permission) && typeof permission.name === "string" && permission.name.length > 0 && Number.isInteger(permission.minSdkVersion) && typeof permission.minSdkVersion === "number" && permission.minSdkVersion > 0 && (permission.maxSdkVersion === void 0 || typeof permission.maxSdkVersion === "number" && Number.isInteger(permission.maxSdkVersion) && permission.maxSdkVersion >= 0)
545
+ (permission) => isRecord(permission) && typeof permission.name === "string" && permission.name.length > 0 && Number.isInteger(permission.minSdkVersion) && typeof permission.minSdkVersion === "number" && permission.minSdkVersion > 0 && (permission.maxSdkVersion === void 0 || typeof permission.maxSdkVersion === "number" && Number.isInteger(permission.maxSdkVersion) && permission.maxSdkVersion >= 0)
547
546
  )))
548
547
  return false;
549
- if (value.googleSignIn !== void 0 && !isRecord2(value.googleSignIn)) return false;
548
+ if (value.googleSignIn !== void 0 && !isRecord(value.googleSignIn)) return false;
550
549
  const descriptions = value.permissionUsageDescriptions;
551
- if (value.reanimatedStaticFeatureFlags !== void 0 && (!isRecord2(value.reanimatedStaticFeatureFlags) || !Object.values(value.reanimatedStaticFeatureFlags).every(
550
+ if (value.reanimatedStaticFeatureFlags !== void 0 && (!isRecord(value.reanimatedStaticFeatureFlags) || !Object.values(value.reanimatedStaticFeatureFlags).every(
552
551
  (flag) => typeof flag === "boolean"
553
552
  )))
554
553
  return false;
555
- if (descriptions !== void 0 && !isRecord2(descriptions)) return false;
556
- if (value.infoPlistStrings !== void 0 && (!isRecord2(value.infoPlistStrings) || !Object.values(value.infoPlistStrings).every((entry) => typeof entry === "string")))
554
+ if (descriptions !== void 0 && !isRecord(descriptions)) return false;
555
+ if (value.infoPlistStrings !== void 0 && (!isRecord(value.infoPlistStrings) || !Object.values(value.infoPlistStrings).every((entry) => typeof entry === "string")))
557
556
  return false;
558
557
  if (value.urlQuerySchemes !== void 0 && !Array.isArray(value.urlQuerySchemes))
559
558
  return false;
@@ -673,7 +672,7 @@ function equalIdentityValues(left, right) {
673
672
  if (Array.isArray(left) && Array.isArray(right)) {
674
673
  return left.length === right.length && left.every((value, index) => equalIdentityValues(value, right[index]));
675
674
  }
676
- if (!isRecord2(left) || !isRecord2(right)) return false;
675
+ if (!isRecord(left) || !isRecord(right)) return false;
677
676
  const keys = Object.keys(left);
678
677
  return keys.length === Object.keys(right).length && keys.every(
679
678
  (key) => Object.hasOwn(right, key) && equalIdentityValues(left[key], right[key])
@@ -763,12 +762,12 @@ function insertNativeAppIdentityFooter(source, identity) {
763
762
  function readGoogleSignInConfiguration(plist, resources) {
764
763
  const clientIds = {};
765
764
  for (const [file, value] of Object.entries(resources)) {
766
- if (isRecord2(value) && typeof value.CLIENT_ID === "string")
765
+ if (isRecord(value) && typeof value.CLIENT_ID === "string")
767
766
  clientIds[file.split("/").pop()?.replace(/\.plist$/, "") ?? file] = value.CLIENT_ID;
768
767
  }
769
768
  const urlSchemes = [];
770
769
  for (const entry of Array.isArray(plist.CFBundleURLTypes) ? plist.CFBundleURLTypes : []) {
771
- if (!isRecord2(entry) || !Array.isArray(entry.CFBundleURLSchemes)) continue;
770
+ if (!isRecord(entry) || !Array.isArray(entry.CFBundleURLSchemes)) continue;
772
771
  for (const scheme of entry.CFBundleURLSchemes)
773
772
  if (typeof scheme === "string") urlSchemes.push(scheme);
774
773
  }
@@ -876,14 +875,14 @@ function nativeAppIdentityFromIos(files, parseInfoPlist, iosTarget, resourceUri)
876
875
  let objects = {};
877
876
  try {
878
877
  const parsed = parseOpenStepPlist(pbxproj);
879
- if (isRecord2(parsed)) {
880
- objects = isRecord2(parsed.objects) ? parsed.objects : parsed;
878
+ if (isRecord(parsed)) {
879
+ objects = isRecord(parsed.objects) ? parsed.objects : parsed;
881
880
  }
882
881
  } catch {
883
882
  }
884
883
  const targets = [];
885
884
  for (const [id, obj] of Object.entries(objects)) {
886
- if (isRecord2(obj) && obj.isa === "PBXNativeTarget" && typeof obj.name === "string") {
885
+ if (isRecord(obj) && obj.isa === "PBXNativeTarget" && typeof obj.name === "string") {
887
886
  targets.push({
888
887
  id,
889
888
  name: obj.name,
@@ -929,13 +928,13 @@ function nativeAppIdentityFromIos(files, parseInfoPlist, iosTarget, resourceUri)
929
928
  PRODUCT_NAME: targetName
930
929
  };
931
930
  for (const obj of Object.values(objects)) {
932
- if (isRecord2(obj) && obj.isa === "PBXProject" && typeof obj.buildConfigurationList === "string") {
931
+ if (isRecord(obj) && obj.isa === "PBXProject" && typeof obj.buildConfigurationList === "string") {
933
932
  const listObj = objects[obj.buildConfigurationList];
934
- if (isRecord2(listObj) && Array.isArray(listObj.buildConfigurations)) {
933
+ if (isRecord(listObj) && Array.isArray(listObj.buildConfigurations)) {
935
934
  for (const configId of listObj.buildConfigurations) {
936
935
  if (typeof configId === "string") {
937
936
  const configObj = objects[configId];
938
- if (isRecord2(configObj) && configObj.name === "Release" && isRecord2(configObj.buildSettings)) {
937
+ if (isRecord(configObj) && configObj.name === "Release" && isRecord(configObj.buildSettings)) {
939
938
  for (const [k, v] of Object.entries(configObj.buildSettings)) {
940
939
  if (typeof v === "string") settings[k] = v;
941
940
  }
@@ -947,11 +946,11 @@ function nativeAppIdentityFromIos(files, parseInfoPlist, iosTarget, resourceUri)
947
946
  }
948
947
  if (selectedTarget?.buildConfigurationList) {
949
948
  const listObj = objects[selectedTarget.buildConfigurationList];
950
- if (isRecord2(listObj) && Array.isArray(listObj.buildConfigurations)) {
949
+ if (isRecord(listObj) && Array.isArray(listObj.buildConfigurations)) {
951
950
  for (const configId of listObj.buildConfigurations) {
952
951
  if (typeof configId === "string") {
953
952
  const configObj = objects[configId];
954
- if (isRecord2(configObj) && configObj.name === "Release" && isRecord2(configObj.buildSettings)) {
953
+ if (isRecord(configObj) && configObj.name === "Release" && isRecord(configObj.buildSettings)) {
955
954
  for (const [k, v] of Object.entries(configObj.buildSettings)) {
956
955
  if (typeof v === "string") settings[k] = v;
957
956
  }
@@ -1002,7 +1001,7 @@ function nativeAppIdentityFromIos(files, parseInfoPlist, iosTarget, resourceUri)
1002
1001
  if (!bundleName) return null;
1003
1002
  const applicationName = identityFieldFrom(settings, plistString(plist, "CFBundleDisplayName"), void 0) ?? bundleName;
1004
1003
  const dictionary = parseInfoPlist(plist);
1005
- if (!isRecord2(dictionary)) throw new Error("native app Info.plist is not a dictionary");
1004
+ if (!isRecord(dictionary)) throw new Error("native app Info.plist is not a dictionary");
1006
1005
  const declaredDisplayName = dictionary.CFBundleDisplayName;
1007
1006
  const applicationDisplayName = typeof declaredDisplayName === "string" ? resolveBuildSetting(declaredDisplayName, settings) : void 0;
1008
1007
  if (applicationDisplayName === null)
@@ -1015,9 +1014,9 @@ function nativeAppIdentityFromIos(files, parseInfoPlist, iosTarget, resourceUri)
1015
1014
  if (dtPlatformVersion === null)
1016
1015
  throw new Error("native app Info.plist DTPlatformVersion is unresolved");
1017
1016
  const icons = dictionary.CFBundleIcons;
1018
- const alternates = isRecord2(icons) ? icons.CFBundleAlternateIcons : void 0;
1017
+ const alternates = isRecord(icons) ? icons.CFBundleAlternateIcons : void 0;
1019
1018
  const alternateIconNames = /* @__PURE__ */ new Set();
1020
- for (const name of isRecord2(alternates) ? Object.keys(alternates) : []) {
1019
+ for (const name of isRecord(alternates) ? Object.keys(alternates) : []) {
1021
1020
  const resolved = resolveBuildSetting(name, settings);
1022
1021
  if (resolved === null) throw new Error("native alternate icon name is unresolved");
1023
1022
  alternateIconNames.add(resolved);
@@ -1121,11 +1120,11 @@ function nativeAppIdentityFromIos(files, parseInfoPlist, iosTarget, resourceUri)
1121
1120
  return `${base.startsWith("/") ? "/" : ""}${segments.join("/")}`;
1122
1121
  };
1123
1122
  const project = Object.values(objects).find(
1124
- (object) => isRecord2(object) && object.isa === "PBXProject"
1123
+ (object) => isRecord(object) && object.isa === "PBXProject"
1125
1124
  );
1126
1125
  const projectDir = join(
1127
1126
  pbxprojPath.replace(/(?:^|\/)[^/]+\.xcodeproj\/project\.pbxproj$/, ""),
1128
- isRecord2(project) && typeof project.projectDirPath === "string" ? project.projectDirPath : ""
1127
+ isRecord(project) && typeof project.projectDirPath === "string" ? project.projectDirPath : ""
1129
1128
  );
1130
1129
  const paths = Object.keys(files);
1131
1130
  visitXcodeTargetMembers(