peachsim 0.1.2185 → 0.1.2186

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 (92) hide show
  1. package/cli/commands/cpu-profile.ts +6 -2
  2. package/cli/commands/shell-url.ts +3 -6
  3. package/dist-lib/agent-daemon-client.cjs +1 -1
  4. package/dist-lib/agent-events.cjs +1 -1
  5. package/dist-lib/attached-projects.cjs +1 -1
  6. package/dist-lib/auth/shared-session.cjs +1 -1
  7. package/dist-lib/backend-origin.cjs +1 -1
  8. package/dist-lib/beta.cjs +1 -1
  9. package/dist-lib/beta.mjs +1 -1
  10. package/dist-lib/bridge-constants.cjs +1 -1
  11. package/dist-lib/bridge-contract-input.cjs +1 -1
  12. package/dist-lib/bridge-contract-input.mjs +1 -1
  13. package/dist-lib/bridge-contract.cjs +1 -1
  14. package/dist-lib/bridge-contract.mjs +1 -1
  15. package/dist-lib/bundle-channel.cjs +55 -10
  16. package/dist-lib/capture-contract.cjs +1 -1
  17. package/dist-lib/capture-contract.mjs +1 -1
  18. package/dist-lib/cloud-contract.cjs +1 -1
  19. package/dist-lib/cloud-contract.mjs +1 -1
  20. package/dist-lib/cloud-test-args.cjs +1 -1
  21. package/dist-lib/cloud-test-args.mjs +1 -1
  22. package/dist-lib/cloud.cjs +1 -1
  23. package/dist-lib/cloud.mjs +1 -1
  24. package/dist-lib/config.cjs +1 -1
  25. package/dist-lib/config.mjs +1 -1
  26. package/dist-lib/detox/index.cjs +2 -2
  27. package/dist-lib/dev-bundle-resolution.cjs +1 -1
  28. package/dist-lib/expo-swift-bundle.cjs +41 -6
  29. package/dist-lib/expo-swift-metadata.cjs +2 -1
  30. package/dist-lib/expo-swift-metadata.mjs +2 -1
  31. package/dist-lib/home-paths.cjs +1 -1
  32. package/dist-lib/host/bridge-host.cjs +55 -10
  33. package/dist-lib/host/fetch-proxy-handler.cjs +4 -4
  34. package/dist-lib/host/fetch-proxy-overrides.cjs +1 -1
  35. package/dist-lib/host/fetch-proxy-overrides.mjs +1 -1
  36. package/dist-lib/host/replacement-module-handler.cjs +1 -1
  37. package/dist-lib/host/websocket-proxy.cjs +1 -1
  38. package/dist-lib/index.cjs +47 -6
  39. package/dist-lib/jump-to-source-babel.cjs +1 -1
  40. package/dist-lib/jump-to-source-native.cjs +1 -1
  41. package/dist-lib/kotlin-host.cjs +5 -3
  42. package/dist-lib/menu.cjs +1 -1
  43. package/dist-lib/menu.mjs +1 -1
  44. package/dist-lib/metro-fingerprint-registry.cjs +1 -1
  45. package/dist-lib/metro-fingerprint-registry.mjs +1 -1
  46. package/dist-lib/metro-production-bundle.cjs +1 -1
  47. package/dist-lib/metro-production-bundle.mjs +1 -1
  48. package/dist-lib/metro.cjs +47 -6
  49. package/dist-lib/native-app-identity-project.cjs +45 -4
  50. package/dist-lib/native-app-identity-project.mjs +45 -4
  51. package/dist-lib/native-app-identity.cjs +40 -2
  52. package/dist-lib/native-app-identity.mjs +40 -2
  53. package/dist-lib/native-firebase-metadata.cjs +1 -1
  54. package/dist-lib/native-firebase-metadata.mjs +1 -1
  55. package/dist-lib/pdfium-raster.cjs +1 -1
  56. package/dist-lib/pdfium-raster.mjs +1 -1
  57. package/dist-lib/plist.cjs +1 -1
  58. package/dist-lib/plist.mjs +1 -1
  59. package/dist-lib/profiles.cjs +1 -1
  60. package/dist-lib/public-brand.cjs +1 -1
  61. package/dist-lib/public-origins-lib-esm.json +24 -24
  62. package/dist-lib/public-origins-lib.json +53 -53
  63. package/dist-lib/react-native-host-modules.cjs +1 -1
  64. package/dist-lib/react-native-host-modules.mjs +1 -1
  65. package/dist-lib/reap-browser.cjs +1 -1
  66. package/dist-lib/scripts/dev-server-scanner.cjs +1 -1
  67. package/dist-lib/sdk.cjs +1 -1
  68. package/dist-lib/sdk.mjs +1 -1
  69. package/dist-lib/skills.cjs +67 -13
  70. package/dist-lib/swift-compile.cjs +2 -2
  71. package/dist-lib/swift-compile.mjs +2 -2
  72. package/dist-lib/swift-package.cjs +1 -1
  73. package/dist-lib/swift-package.mjs +1 -1
  74. package/dist-lib/swift-submit.cjs +1 -1
  75. package/dist-lib/swift-submit.mjs +1 -1
  76. package/dist-lib/swift-toolchain.cjs +1 -1
  77. package/dist-lib/swift.cjs +1 -1
  78. package/dist-lib/vite-swift.cjs +3 -3
  79. package/dist-lib/vite.cjs +4 -4
  80. package/dist-lib/worklet-executable.cjs +1 -1
  81. package/dist-lib/worklet-executable.mjs +1 -1
  82. package/dist-types/packages/peach-engine/src/render-worker/compositor-backend.d.ts +1 -0
  83. package/kotlin/sdk.tar.gz +0 -0
  84. package/package.json +1 -1
  85. package/runtime-companion.json +1 -1
  86. package/sdk/ios/System/Library/Frameworks/UIKit.framework/Headers/UIImageAsset.h +1 -1
  87. package/src/expo-native-workspace.ts +7 -1
  88. package/src/kotlin-host.ts +4 -2
  89. package/src/native-app-identity-project.ts +10 -2
  90. package/src/native-app-identity.ts +15 -1
  91. package/src/nativeAppIconContract.ts +37 -0
  92. package/src/swift-installed-targets.ts +8 -0
@@ -1,4 +1,4 @@
1
- /*! peach v0.1.2185 | (c) 2026 Tamagui LLC | Proprietary; see LICENSE */
1
+ /*! peach v0.1.2186 | (c) 2026 Tamagui LLC | Proprietary; see LICENSE */
2
2
  let __sootsim_import_meta_url = '', __sootsim_import_meta_dirname = '', __sootsim_import_meta_filename = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; __sootsim_import_meta_dirname = __dirname; __sootsim_import_meta_filename = __filename; } catch {}
3
3
  "use strict";
4
4
  var __create = Object.create;
@@ -11308,7 +11308,7 @@ var init_registry = __esm({
11308
11308
  {
11309
11309
  range: ">=4.6.0",
11310
11310
  coverage: 0,
11311
- note: "the reference iOS simulator performs this package's behavior. Peach currently provides only this unsupported shape: native-seam only: the real customerio-reactnative runs from the bundle (CustomerIO object, CioRegion/CioLogLevel/CioPushPermissionStatus enums, in-app/push/notification-inbox wrappers : all upstream JS, no fabricated values). 4.6.0 is the first TurboModule release (4.0.0-4.5.2 use the old bridge module names, which this seam does not provide). we stub the six codegen modules (NativeCustomerIO/Logging/Location/MessagingPush/MessagingInApp/LiveActivities), mirroring src/specs/modules/*@7.2.0 exactly; its emitter properties also answer the earlier 4.6.0-6.x emitter calls, so every TurboModule line from 4.6.0 runs: calls accepted, getMessages/token empty, push permission reports NOTDETERMINED (fresh-sim), event-emitter properties return removable no-op subscriptions, live activities reject with live_activity_module_unavailable the way the real iOS wrapper does without its optional pod, and the nullable geofence module stays absent. the package's full JS surface imports and stays inert on Peach at 7.2.0. per docs/peach/conformance/compat-scoring.md analytics rule, delivery is intentionally absent. imports and API shape receive no behavior credit",
11311
+ note: "the reference iOS simulator performs this package's behavior. Peach currently provides only this unsupported shape: native-seam only: the real customerio-reactnative runs from the bundle (CustomerIO object, CioRegion/CioLogLevel/CioPushPermissionStatus enums, in-app/push/notification-inbox wrappers : all upstream JS, no fabricated values). 4.6.0 is the first TurboModule release (4.0.0-4.5.2 use the old bridge module names, which this seam does not provide). we stub the six codegen modules (NativeCustomerIO/Logging/Location/MessagingPush/MessagingInApp/LiveActivities), mirroring src/specs/modules/*@7.3.0 exactly (7.3.0 adds registerBackgroundPushHandler, unregisterBackgroundPushHandler, acknowledgeBackgroundPush and the onBackgroundPushReceived emitter, answered as inert no-ops); its emitter properties also answer the earlier 4.6.0-6.x emitter calls, so every TurboModule line from 4.6.0 runs: calls accepted, getMessages/token empty, push permission reports NOTDETERMINED (fresh-sim), event-emitter properties return removable no-op subscriptions, live activities reject with live_activity_module_unavailable the way the real iOS wrapper does without its optional pod, and the nullable geofence module stays absent. the package's full JS surface imports and stays inert on Peach at 7.3.0. per docs/peach/conformance/compat-scoring.md analytics rule, delivery is intentionally absent. imports and API shape receive no behavior credit",
11312
11312
  working: "full upstream JS surface (CustomerIO object + correct enums + in-app/push/inbox wrappers); initialize/identify/track/screen, profile+device attributes, device-token register/delete, trackMetric, deep-link routing ready + handler registration (no URL is ever delivered), push receipt/permission APIs, in-app dismiss + color scheme + inbox getMessages/mark/track, inbox event listener registration, all event-emitter subscriptions (no-op removable), live activities handleWidgetUrl pass-through with start/update/end reporting the native unavailable code",
11313
11313
  missing: "no events sent, no profile sync, no in-app messages displayed, push token not registered, no deep link delivered, no live activity started, no geofence refresh"
11314
11314
  }
@@ -35301,6 +35301,34 @@ var init_android_app_identity = __esm({
35301
35301
  });
35302
35302
 
35303
35303
  // src/nativeAppIconContract.ts
35304
+ function resolveNativeBundleIcons(icons, catalogNames, resolveReference) {
35305
+ if (!isRecord(icons) && catalogNames.length === 0) return void 0;
35306
+ const resolve13 = (value) => {
35307
+ if (typeof value === "string") return resolveReference(value);
35308
+ if (Array.isArray(value)) return value.map(resolve13);
35309
+ if (isRecord(value))
35310
+ return Object.fromEntries(
35311
+ Object.entries(value).map(([key2, entry]) => [
35312
+ resolveReference(key2),
35313
+ resolve13(entry)
35314
+ ])
35315
+ );
35316
+ return value;
35317
+ };
35318
+ const dictionary2 = isRecord(icons) ? Object.fromEntries(
35319
+ Object.entries(icons).map(([key2, value]) => [key2, resolve13(value)])
35320
+ ) : {};
35321
+ if (catalogNames.length === 0) return dictionary2;
35322
+ return {
35323
+ ...dictionary2,
35324
+ CFBundleAlternateIcons: {
35325
+ ...Object.fromEntries(
35326
+ catalogNames.map((name3) => [name3, { CFBundleIconName: name3 }])
35327
+ ),
35328
+ ...isRecord(dictionary2.CFBundleAlternateIcons) ? dictionary2.CFBundleAlternateIcons : {}
35329
+ }
35330
+ };
35331
+ }
35304
35332
  function isNativeAppIconArtwork(value) {
35305
35333
  return isRecord(value) && (value.primary === void 0 || isSwiftImageVariants(value.primary)) && isRecord(value.alternates) && Object.values(value.alternates).every(isSwiftImageVariants);
35306
35334
  }
@@ -35652,6 +35680,7 @@ function isNativeAppIdentity(value) {
35652
35680
  if (value.androidPhotoLibraryAddOnly !== void 0 && value.androidPhotoLibraryAddOnly !== true)
35653
35681
  return false;
35654
35682
  if (value.googleSignIn !== void 0 && !isRecord(value.googleSignIn)) return false;
35683
+ if (value.bundleIcons !== void 0 && !isRecord(value.bundleIcons)) return false;
35655
35684
  const descriptions = value.permissionUsageDescriptions;
35656
35685
  if (value.reanimatedStaticFeatureFlags !== void 0 && (!isRecord(value.reanimatedStaticFeatureFlags) || !Object.values(value.reanimatedStaticFeatureFlags).every(
35657
35686
  (flag) => typeof flag === "boolean"
@@ -35742,6 +35771,7 @@ function readNativeAppIdentity(value) {
35742
35771
  ...value.reanimatedStaticFeatureFlags === void 0 ? {} : { reanimatedStaticFeatureFlags: { ...value.reanimatedStaticFeatureFlags } },
35743
35772
  ...value.appIconArtwork === void 0 ? {} : { appIconArtwork: readNativeAppIconArtwork(value.appIconArtwork) },
35744
35773
  ...value.alternateIconNames === void 0 ? {} : { alternateIconNames: [...value.alternateIconNames] },
35774
+ ...value.bundleIcons === void 0 ? {} : { bundleIcons: structuredClone(value.bundleIcons) },
35745
35775
  ...value.androidManifestPermissions === void 0 ? {} : {
35746
35776
  androidManifestPermissions: value.androidManifestPermissions.map(
35747
35777
  (permission) => ({ ...permission })
@@ -36083,8 +36113,11 @@ function nativeAppIdentityFromIos(files2, parseInfoPlist, iosTarget, resourceUri
36083
36113
  );
36084
36114
  if (alternateSetting === null)
36085
36115
  throw new Error("native alternate icon setting is unresolved");
36116
+ const catalogAlternateNames = [];
36086
36117
  for (const match of alternateSetting.replace(/\\"/g, '"').matchAll(/"([^"]*)"|([^\s(),]+)/g)) {
36087
- alternateIconNames.add(match[1] ?? match[2]);
36118
+ const name3 = match[1] ?? match[2];
36119
+ alternateIconNames.add(name3);
36120
+ catalogAlternateNames.push(name3);
36088
36121
  }
36089
36122
  const intentIds = dictionary2.OneAppIntentIdentifiers;
36090
36123
  const appIntentIdentifiers = Array.isArray(intentIds) && intentIds.every((value) => typeof value === "string") ? intentIds.map((value) => resolveBuildSetting(value, settings)) : [];
@@ -36232,6 +36265,11 @@ function nativeAppIdentityFromIos(files2, parseInfoPlist, iosTarget, resourceUri
36232
36265
  ipadSupportedInterfaceOrientations,
36233
36266
  ...defaultScreenOrientationMask === void 0 ? {} : { defaultScreenOrientationMask },
36234
36267
  alternateIconNames: [...alternateIconNames],
36268
+ bundleIcons: resolveNativeBundleIcons(icons, catalogAlternateNames, (value) => {
36269
+ const resolved = resolveBuildSetting(value, settings);
36270
+ if (resolved === null) throw new Error("native bundle icon reference is unresolved");
36271
+ return resolved;
36272
+ }),
36235
36273
  ...resourceUri ? {
36236
36274
  appIconArtwork: resolveNativeAppIconArtwork(
36237
36275
  [...resources],
@@ -58177,7 +58215,7 @@ var init_swift_compile = __esm({
58177
58215
  REACTOR_FLAG = '"-Xclang-linker", "-mexec-model=reactor",\n';
58178
58216
  MULTI_MANIFEST_VERSION = 68;
58179
58217
  SWIFT_HEADER_PRODUCTS_TARGET = "PeachHeaderProducts";
58180
- compilerSourceDigest = true ? "e48d05f659c020e9d4ddc0f6a17da7924aae807faacd6bef7cbed911c43d08cc" : swiftCompilerSourceDigest(__sootsim_import_meta_dirname);
58218
+ compilerSourceDigest = true ? "0d2e8d6fb4545fb31a692a87bd3215ef3a9a64a8c3e1b2fc1f2a3e79511325ec" : swiftCompilerSourceDigest(__sootsim_import_meta_dirname);
58181
58219
  nativeCxxCompilerFlags = ["-fno-cxx-modules"];
58182
58220
  cFlagArray = (flags) => JSON.stringify(withoutGlogModuleMap(flags));
58183
58221
  cxxFlagArray = (flags) => JSON.stringify([...nativeCxxCompilerFlags, ...withoutGlogModuleMap(flags)]);
@@ -64044,7 +64082,8 @@ async function prepareWorkspace(app, stage, key2, podsEnvironment) {
64044
64082
  const command = [...prefix, ...args];
64045
64083
  await run12(command[0], command.slice(1), cwd, env);
64046
64084
  };
64047
- if (manager.startsWith("bun@") && (!projectReady || !import_node_fs63.default.existsSync(bunExecutable)))
64085
+ const installedBun = manager.startsWith("bun@") ? (0, import_node_child_process36.spawnSync)(bunExecutable, ["--version"], { encoding: "utf8" }) : null;
64086
+ if (manager.startsWith("bun@") && (installedBun?.status !== 0 || installedBun.stdout.trim() !== manager.slice(4)))
64048
64087
  await execute(
64049
64088
  [
64050
64089
  "npm",
@@ -64743,7 +64782,7 @@ var init_swift_standin_digest = __esm({
64743
64782
  STANDIN_DIGEST_ENTRYPOINTS = ["swift-standins.ts", "swift-objc-compile.ts"];
64744
64783
  SPECIFIER = /from\s*['"]([^'"]+)['"]|import\s*\(\s*['"]([^'"]+)['"]\s*\)/g;
64745
64784
  standinSourceDigest = (srcDir = __sootsim_import_meta_dirname) => sourceClosureDigest(srcDir, STANDIN_DIGEST_ENTRYPOINTS);
64746
- STANDIN_SOURCE_DIGEST = true ? "0981767eef4ad46fe5cb602ee15f1de9ea06dac3a2edb4dab0f6d5279b018a3b" : standinSourceDigest();
64785
+ STANDIN_SOURCE_DIGEST = true ? "62c7fc880aa6efc985c4786587cb8441b81094e44c28f8d65e1d6dffda9c24f4" : standinSourceDigest();
64747
64786
  }
64748
64787
  });
64749
64788
 
@@ -64841,9 +64880,13 @@ function readNativeAppIdentityFromXcodeTarget(app, parseInfoPlist = parsePlistSo
64841
64880
  }
64842
64881
  }
64843
64882
  const alternateSetting = settings?.("ASSETCATALOG_COMPILER_ALTERNATE_APPICON_NAMES") ?? "";
64883
+ const catalogAlternateNames = [];
64844
64884
  for (const match of alternateSetting.replace(/\\"/g, '"').matchAll(/"([^"]*)"|([^\s(),]+)/g)) {
64845
64885
  const val = match[1] ?? match[2];
64846
- if (val) alternateIconNames.add(val);
64886
+ if (val) {
64887
+ alternateIconNames.add(val);
64888
+ catalogAlternateNames.push(val);
64889
+ }
64847
64890
  }
64848
64891
  const permissionUsageDescriptions = {};
64849
64892
  for (const [key2, value] of Object.entries(dictionary2)) {
@@ -64906,6 +64949,7 @@ function readNativeAppIdentityFromXcodeTarget(app, parseInfoPlist = parsePlistSo
64906
64949
  ipadSupportedInterfaceOrientations,
64907
64950
  ...defaultScreenOrientationMask ? { defaultScreenOrientationMask } : {},
64908
64951
  alternateIconNames: [...alternateIconNames],
64952
+ bundleIcons: resolveNativeBundleIcons(icons, catalogAlternateNames, (value) => value),
64909
64953
  appIconArtwork: resolveNativeAppIconArtwork(
64910
64954
  app.resources,
64911
64955
  (file) => import_node_fs66.default.readFileSync(file, "utf8"),
@@ -65199,7 +65243,7 @@ var init_package_tree_digest = __esm({
65199
65243
 
65200
65244
  // src/expo-native-prebuilt.ts
65201
65245
  function expoNativeCompilerDigestValue() {
65202
- return true ? "5096ba1e78a0087b6e56f15c4b37fcbd9bcabb2acde17a257d8add357efd462c" : expoNativeCompilerDigest(__sootsim_import_meta_dirname);
65246
+ return true ? "e50ab1d8ec731167f92f711da0833fa534d1aec4b5ce950a6ba947279df8c1e7" : expoNativeCompilerDigest(__sootsim_import_meta_dirname);
65203
65247
  }
65204
65248
  function readSources(value) {
65205
65249
  const sources = isRecord(value) ? value.sources : null;
@@ -84013,6 +84057,14 @@ function applyInstalledSwiftTargets(collection, snapshot, generatedTargets, root
84013
84057
  return !collection.targets.some((target2) => target2.name === module2);
84014
84058
  });
84015
84059
  dropSuppliedHeaders(generated, native);
84060
+ if (native.flattensPublicHeaders && native.publicHeaders.length > 0)
84061
+ generated.swiftFlags = [
84062
+ ...generated.swiftFlags ?? [],
84063
+ "-Xcc",
84064
+ "-I",
84065
+ "-Xcc",
84066
+ `$(PEACH_INPUT_ROOT)/.build/peach-cxx-headers/${native.name}`
84067
+ ];
84016
84068
  const flags = originalModuleFlags(native.flags);
84017
84069
  generated.clangSettings = [
84018
84070
  { tool: "c", flags: [...flags, ...ndebug, ...search] },
@@ -84969,7 +85021,7 @@ var init_nitro_superset = __esm({
84969
85021
  init_nitroContract();
84970
85022
  init_swift_standin_digest();
84971
85023
  NITRO_SUPERSET_ENTRY_NAME = "superset";
84972
- NITRO_COMPILER_DIGEST = true ? "f02c3ec3fd9a77d144224ecf36dbf177c3878f12158689dcd8dcd6347e72ca55" : nitroCompilerSourceDigest(__sootsim_import_meta_dirname, STANDIN_SOURCE_DIGEST2);
85024
+ NITRO_COMPILER_DIGEST = true ? "657f6d25b5a8cead1b82960b638441e0fe6bc4380c409fbb9809a56d6f0102d6" : nitroCompilerSourceDigest(__sootsim_import_meta_dirname, STANDIN_SOURCE_DIGEST2);
84973
85025
  nitroSupersetLock = parseLock(nitro_superset_lock_default);
84974
85026
  nitroSupersetKey = (inputs) => nativeEntryKey({ ...inputs, compiler: NITRO_COMPILER_DIGEST });
84975
85027
  published2 = /* @__PURE__ */ new Map();
@@ -85681,7 +85733,7 @@ var init_one_sdk_bundle = __esm({
85681
85733
  var runtime_companion_default;
85682
85734
  var init_runtime_companion = __esm({
85683
85735
  "runtime-companion.json"() {
85684
- runtime_companion_default = { abi: 1, sha256: "d1826a4d4d05c87a157d5b160177de9cd6f1fd10a3d142804a92a0d57ff3060f", file: "node/cli-d1826a4d4d05c87a157d5b160177de9cd6f1fd10a3d142804a92a0d57ff3060f.cjs" };
85736
+ runtime_companion_default = { abi: 1, sha256: "c63f83dd24fd36986b72da8da6b6a51edce0a2d061e3bc05d3439d22b1a86c91", file: "node/cli-c63f83dd24fd36986b72da8da6b6a51edce0a2d061e3bc05d3439d22b1a86c91.cjs" };
85685
85737
  }
85686
85738
  });
85687
85739
 
@@ -95660,10 +95712,11 @@ function entrySource(ids) {
95660
95712
  "",
95661
95713
  "@OptIn(kotlin.js.ExperimentalJsExport::class)",
95662
95714
  "@JsExport",
95663
- "fun peachSetAndroidDeviceInfo(model: String, release: String, apiLevel: Int, locale: String, timeZone: String) {",
95715
+ "fun peachSetAndroidDeviceInfo(model: String, release: String, apiLevel: Int, locale: String, timeZone: String, settings: String) {",
95664
95716
  " Build.setDevice(model, release, apiLevel)",
95665
95717
  " java.util.Locale.setDefault(java.util.Locale.forLanguageTag(locale))",
95666
95718
  " java.util.TimeZone.setDevice(timeZone)",
95719
+ " dev.peach.android.ProcessSettings.configure(settings)",
95667
95720
  "}",
95668
95721
  "",
95669
95722
  "@OptIn(kotlin.js.ExperimentalJsExport::class, kotlinx.coroutines.DelicateCoroutinesApi::class)",
@@ -96031,10 +96084,11 @@ async function expoKotlinArtifact(root, moduleRoot, origin, modules) {
96031
96084
  " ))",
96032
96085
  "}",
96033
96086
  "",
96034
- "@JsExport fun peachSetAndroidDeviceInfo(model: String, release: String, apiLevel: Int, locale: String, timeZone: String) {",
96087
+ "@JsExport fun peachSetAndroidDeviceInfo(model: String, release: String, apiLevel: Int, locale: String, timeZone: String, settings: String) {",
96035
96088
  " android.os.Build.setDevice(model, release, apiLevel)",
96036
96089
  " java.util.Locale.setDefault(java.util.Locale.forLanguageTag(locale))",
96037
96090
  " java.util.TimeZone.setDevice(timeZone)",
96091
+ " dev.peach.android.ProcessSettings.configure(settings)",
96038
96092
  " PeachExpoRuntime.configureProcessLocale(locale)",
96039
96093
  "}",
96040
96094
  "",
@@ -113588,7 +113642,7 @@ function readProjectNativeAppIdentityWire(project2, platform2, iosTarget, enviro
113588
113642
  void 0,
113589
113643
  environment
113590
113644
  ) ?? readOneConfigNativeAppIdentity(project2.appDir, platform2);
113591
- return identity2 && createNativeAppIdentityHeader({ ...identity2, appIconArtwork: void 0 });
113645
+ return identity2 && createNativeAppIdentityHeader(identity2);
113592
113646
  } catch (error) {
113593
113647
  if (error instanceof NativeAppTargetSelectionError) return null;
113594
113648
  throw error;
@@ -1,4 +1,4 @@
1
- /*! peach v0.1.2185 | (c) 2026 Tamagui LLC | Proprietary; see LICENSE */
1
+ /*! peach v0.1.2186 | (c) 2026 Tamagui LLC | Proprietary; see LICENSE */
2
2
  let __sootsim_import_meta_url = '', __sootsim_import_meta_dirname = '', __sootsim_import_meta_filename = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; __sootsim_import_meta_dirname = __dirname; __sootsim_import_meta_filename = __filename; } catch {}
3
3
  "use strict";
4
4
  var __create = Object.create;
@@ -12474,7 +12474,7 @@ var darwinRecordsRegion = (quoted) => quoted.length ? ["-Wl,--start-lib", ...quo
12474
12474
  var REACTOR_FLAG = '"-Xclang-linker", "-mexec-model=reactor",\n';
12475
12475
  var MULTI_MANIFEST_VERSION = 68;
12476
12476
  var SWIFT_HEADER_PRODUCTS_TARGET = "PeachHeaderProducts";
12477
- var compilerSourceDigest = true ? "e48d05f659c020e9d4ddc0f6a17da7924aae807faacd6bef7cbed911c43d08cc" : swiftCompilerSourceDigest(__sootsim_import_meta_dirname);
12477
+ var compilerSourceDigest = true ? "0d2e8d6fb4545fb31a692a87bd3215ef3a9a64a8c3e1b2fc1f2a3e79511325ec" : swiftCompilerSourceDigest(__sootsim_import_meta_dirname);
12478
12478
  function swiftArtifactHash(input, release, moduleRoot) {
12479
12479
  const hash = (0, import_node_crypto13.createHash)("sha256");
12480
12480
  hash.update(`swift-compile
@@ -1,4 +1,4 @@
1
- /*! peach v0.1.2185 | (c) 2026 Tamagui LLC | Proprietary; see LICENSE */
1
+ /*! peach v0.1.2186 | (c) 2026 Tamagui LLC | Proprietary; see LICENSE */
2
2
 
3
3
  // src/swift-compile.ts
4
4
  import {
@@ -12454,7 +12454,7 @@ var darwinRecordsRegion = (quoted) => quoted.length ? ["-Wl,--start-lib", ...quo
12454
12454
  var REACTOR_FLAG = '"-Xclang-linker", "-mexec-model=reactor",\n';
12455
12455
  var MULTI_MANIFEST_VERSION = 68;
12456
12456
  var SWIFT_HEADER_PRODUCTS_TARGET = "PeachHeaderProducts";
12457
- var compilerSourceDigest = true ? "e48d05f659c020e9d4ddc0f6a17da7924aae807faacd6bef7cbed911c43d08cc" : swiftCompilerSourceDigest(import.meta.dirname);
12457
+ var compilerSourceDigest = true ? "0d2e8d6fb4545fb31a692a87bd3215ef3a9a64a8c3e1b2fc1f2a3e79511325ec" : swiftCompilerSourceDigest(import.meta.dirname);
12458
12458
  function swiftArtifactHash(input, release, moduleRoot) {
12459
12459
  const hash = createHash13("sha256");
12460
12460
  hash.update(`swift-compile
@@ -1,4 +1,4 @@
1
- /*! peach v0.1.2185 | (c) 2026 Tamagui LLC | Proprietary; see LICENSE */
1
+ /*! peach v0.1.2186 | (c) 2026 Tamagui LLC | Proprietary; see LICENSE */
2
2
  let __sootsim_import_meta_url = '', __sootsim_import_meta_dirname = '', __sootsim_import_meta_filename = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; __sootsim_import_meta_dirname = __dirname; __sootsim_import_meta_filename = __filename; } catch {}
3
3
  "use strict";
4
4
  var __defProp = Object.defineProperty;
@@ -1,4 +1,4 @@
1
- /*! peach v0.1.2185 | (c) 2026 Tamagui LLC | Proprietary; see LICENSE */
1
+ /*! peach v0.1.2186 | (c) 2026 Tamagui LLC | Proprietary; see LICENSE */
2
2
 
3
3
  // src/swift-package.ts
4
4
  function swiftManifestSettings(target) {
@@ -1,4 +1,4 @@
1
- /*! peach v0.1.2185 | (c) 2026 Tamagui LLC | Proprietary; see LICENSE */
1
+ /*! peach v0.1.2186 | (c) 2026 Tamagui LLC | Proprietary; see LICENSE */
2
2
  let __sootsim_import_meta_url = '', __sootsim_import_meta_dirname = '', __sootsim_import_meta_filename = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; __sootsim_import_meta_dirname = __dirname; __sootsim_import_meta_filename = __filename; } catch {}
3
3
  "use strict";
4
4
  var __defProp = Object.defineProperty;
@@ -1,4 +1,4 @@
1
- /*! peach v0.1.2185 | (c) 2026 Tamagui LLC | Proprietary; see LICENSE */
1
+ /*! peach v0.1.2186 | (c) 2026 Tamagui LLC | Proprietary; see LICENSE */
2
2
 
3
3
  // src/is-record.ts
4
4
  function isRecord(value) {
@@ -1,4 +1,4 @@
1
- /*! peach v0.1.2185 | (c) 2026 Tamagui LLC | Proprietary; see LICENSE */
1
+ /*! peach v0.1.2186 | (c) 2026 Tamagui LLC | Proprietary; see LICENSE */
2
2
  let __sootsim_import_meta_url = '', __sootsim_import_meta_dirname = '', __sootsim_import_meta_filename = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; __sootsim_import_meta_dirname = __dirname; __sootsim_import_meta_filename = __filename; } catch {}
3
3
  "use strict";
4
4
  var __create = Object.create;
@@ -1,4 +1,4 @@
1
- /*! peach v0.1.2185 | (c) 2026 Tamagui LLC | Proprietary; see LICENSE */
1
+ /*! peach v0.1.2186 | (c) 2026 Tamagui LLC | Proprietary; see LICENSE */
2
2
  let __sootsim_import_meta_url = '', __sootsim_import_meta_dirname = '', __sootsim_import_meta_filename = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; __sootsim_import_meta_dirname = __dirname; __sootsim_import_meta_filename = __filename; } catch {}
3
3
  "use strict";
4
4
  var __defProp = Object.defineProperty;
@@ -1,4 +1,4 @@
1
- /*! peach v0.1.2185 | (c) 2026 Tamagui LLC | Proprietary; see LICENSE */
1
+ /*! peach v0.1.2186 | (c) 2026 Tamagui LLC | Proprietary; see LICENSE */
2
2
  let __sootsim_import_meta_url = '', __sootsim_import_meta_dirname = '', __sootsim_import_meta_filename = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; __sootsim_import_meta_dirname = __dirname; __sootsim_import_meta_filename = __filename; } catch {}
3
3
  "use strict";
4
4
  var __create = Object.create;
@@ -17269,7 +17269,7 @@ var darwinRecordsRegion = (quoted) => quoted.length ? ["-Wl,--start-lib", ...quo
17269
17269
  var REACTOR_FLAG = '"-Xclang-linker", "-mexec-model=reactor",\n';
17270
17270
  var MULTI_MANIFEST_VERSION = 68;
17271
17271
  var SWIFT_HEADER_PRODUCTS_TARGET = "PeachHeaderProducts";
17272
- var compilerSourceDigest = true ? "e48d05f659c020e9d4ddc0f6a17da7924aae807faacd6bef7cbed911c43d08cc" : swiftCompilerSourceDigest(__sootsim_import_meta_dirname);
17272
+ var compilerSourceDigest = true ? "0d2e8d6fb4545fb31a692a87bd3215ef3a9a64a8c3e1b2fc1f2a3e79511325ec" : swiftCompilerSourceDigest(__sootsim_import_meta_dirname);
17273
17273
  function swiftArtifactHash(input, release, moduleRoot) {
17274
17274
  const hash = (0, import_node_crypto13.createHash)("sha256");
17275
17275
  hash.update(`swift-compile
@@ -30672,7 +30672,7 @@ function sourceClosureDigest(srcDir, entrypoints) {
30672
30672
  return hash.digest("hex");
30673
30673
  }
30674
30674
  var standinSourceDigest = (srcDir = __sootsim_import_meta_dirname) => sourceClosureDigest(srcDir, STANDIN_DIGEST_ENTRYPOINTS);
30675
- var STANDIN_SOURCE_DIGEST = true ? "0981767eef4ad46fe5cb602ee15f1de9ea06dac3a2edb4dab0f6d5279b018a3b" : standinSourceDigest();
30675
+ var STANDIN_SOURCE_DIGEST = true ? "62c7fc880aa6efc985c4786587cb8441b81094e44c28f8d65e1d6dffda9c24f4" : standinSourceDigest();
30676
30676
 
30677
30677
  // src/swift-standins.ts
30678
30678
  init_define_SWIFT_COVERAGE_SOURCE_DIGESTS();
package/dist-lib/vite.cjs CHANGED
@@ -1,4 +1,4 @@
1
- /*! peach v0.1.2185 | (c) 2026 Tamagui LLC | Proprietary; see LICENSE */
1
+ /*! peach v0.1.2186 | (c) 2026 Tamagui LLC | Proprietary; see LICENSE */
2
2
  let __sootsim_import_meta_url = '', __sootsim_import_meta_dirname = '', __sootsim_import_meta_filename = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; __sootsim_import_meta_dirname = __dirname; __sootsim_import_meta_filename = __filename; } catch {}
3
3
  "use strict";
4
4
  var __create = Object.create;
@@ -1416,7 +1416,7 @@ function isValidRuntimeVersion(value) {
1416
1416
  }
1417
1417
 
1418
1418
  // runtime-companion.json
1419
- var runtime_companion_default = { abi: 1, sha256: "d1826a4d4d05c87a157d5b160177de9cd6f1fd10a3d142804a92a0d57ff3060f", file: "node/cli-d1826a4d4d05c87a157d5b160177de9cd6f1fd10a3d142804a92a0d57ff3060f.cjs" };
1419
+ var runtime_companion_default = { abi: 1, sha256: "c63f83dd24fd36986b72da8da6b6a51edce0a2d061e3bc05d3439d22b1a86c91", file: "node/cli-c63f83dd24fd36986b72da8da6b6a51edce0a2d061e3bc05d3439d22b1a86c91.cjs" };
1420
1420
 
1421
1421
  // src/answeredNativePackages.ts
1422
1422
  init_define_SWIFT_COVERAGE_SOURCE_DIGESTS();
@@ -1909,7 +1909,7 @@ function readIosSdkTree(root) {
1909
1909
 
1910
1910
  // src/swift-standin-digest.ts
1911
1911
  init_define_SWIFT_COVERAGE_SOURCE_DIGESTS();
1912
- var STANDIN_SOURCE_DIGEST = true ? "0981767eef4ad46fe5cb602ee15f1de9ea06dac3a2edb4dab0f6d5279b018a3b" : standinSourceDigest();
1912
+ var STANDIN_SOURCE_DIGEST = true ? "62c7fc880aa6efc985c4786587cb8441b81094e44c28f8d65e1d6dffda9c24f4" : standinSourceDigest();
1913
1913
 
1914
1914
  // src/expo-native-workspace.ts
1915
1915
  init_define_SWIFT_COVERAGE_SOURCE_DIGESTS();
@@ -5391,7 +5391,7 @@ var FOUNDATION_IMPLICIT_MODULES = [
5391
5391
  var FOUNDATION_IMPLICIT_FLAGS = FOUNDATION_IMPLICIT_MODULES.map(
5392
5392
  (module2) => `, "-Xfrontend", "-import-module", "-Xfrontend", "${module2}"`
5393
5393
  ).join("");
5394
- var compilerSourceDigest = true ? "e48d05f659c020e9d4ddc0f6a17da7924aae807faacd6bef7cbed911c43d08cc" : swiftCompilerSourceDigest2(__sootsim_import_meta_dirname);
5394
+ var compilerSourceDigest = true ? "0d2e8d6fb4545fb31a692a87bd3215ef3a9a64a8c3e1b2fc1f2a3e79511325ec" : swiftCompilerSourceDigest2(__sootsim_import_meta_dirname);
5395
5395
  var CORE_FOUNDATION_HANDLE_IMPORTS = [
5396
5396
  "CFAllocator",
5397
5397
  "CFArray",
@@ -1,4 +1,4 @@
1
- /*! peach v0.1.2185 | (c) 2026 Tamagui LLC | Proprietary; see LICENSE */
1
+ /*! peach v0.1.2186 | (c) 2026 Tamagui LLC | Proprietary; see LICENSE */
2
2
  let __sootsim_import_meta_url = '', __sootsim_import_meta_dirname = '', __sootsim_import_meta_filename = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; __sootsim_import_meta_dirname = __dirname; __sootsim_import_meta_filename = __filename; } catch {}
3
3
  "use strict";
4
4
  var __defProp = Object.defineProperty;
@@ -1,4 +1,4 @@
1
- /*! peach v0.1.2185 | (c) 2026 Tamagui LLC | Proprietary; see LICENSE */
1
+ /*! peach v0.1.2186 | (c) 2026 Tamagui LLC | Proprietary; see LICENSE */
2
2
 
3
3
  // src/worklet-executable.ts
4
4
  import { parse } from "acorn";
@@ -15,6 +15,7 @@ export type CompositorDeviceProbe = {
15
15
  readonly device: boolean;
16
16
  readonly error?: string;
17
17
  };
18
+ export declare function inNativeHost(): boolean;
18
19
  export interface CompositorBackendEnvironment {
19
20
  readonly webGpuApiAvailable: boolean;
20
21
  readonly nativeHost: boolean;
package/kotlin/sdk.tar.gz CHANGED
Binary file
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "peachsim",
3
- "version": "0.1.2185",
3
+ "version": "0.1.2186",
4
4
  "description": "Vite and Metro plugins, testing drivers, and SDK exports for peach.",
5
5
  "author": "Tamagui LLC",
6
6
  "license": "SEE LICENSE IN LICENSE",
@@ -1 +1 @@
1
- {"abi":1,"sha256":"d1826a4d4d05c87a157d5b160177de9cd6f1fd10a3d142804a92a0d57ff3060f","file":"node/cli-d1826a4d4d05c87a157d5b160177de9cd6f1fd10a3d142804a92a0d57ff3060f.cjs"}
1
+ {"abi":1,"sha256":"c63f83dd24fd36986b72da8da6b6a51edce0a2d061e3bc05d3439d22b1a86c91","file":"node/cli-c63f83dd24fd36986b72da8da6b6a51edce0a2d061e3bc05d3439d22b1a86c91.cjs"}
@@ -15,7 +15,7 @@ NS_HEADER_AUDIT_BEGIN(nullability, sendability)
15
15
  @protocol UIImageConfiguration;
16
16
 
17
17
  UIKIT_EXTERN API_AVAILABLE(ios(8.0)) API_UNAVAILABLE(watchos) NS_SWIFT_SENDABLE
18
- @interface UIImageAsset : NSObject <NSSecureCoding>
18
+ PEACH_SWIFT_CLASS(UIKitCore) @interface UIImageAsset : NSObject <NSSecureCoding>
19
19
 
20
20
  - (instancetype)init NS_DESIGNATED_INITIALIZER;
21
21
  - (nullable instancetype)initWithCoder:(NSCoder *)coder NS_DESIGNATED_INITIALIZER;
@@ -905,7 +905,13 @@ async function prepareWorkspace(
905
905
  const command = [...prefix, ...args]
906
906
  await run(command[0]!, command.slice(1), cwd, env)
907
907
  }
908
- if (manager.startsWith('bun@') && (!projectReady || !fs.existsSync(bunExecutable)))
908
+ const installedBun = manager.startsWith('bun@')
909
+ ? spawnSync(bunExecutable, ['--version'], { encoding: 'utf8' })
910
+ : null
911
+ if (
912
+ manager.startsWith('bun@') &&
913
+ (installedBun?.status !== 0 || installedBun.stdout.trim() !== manager.slice(4))
914
+ )
909
915
  await execute(
910
916
  [
911
917
  'npm',
@@ -131,10 +131,11 @@ function entrySource(ids: string[]): string {
131
131
  '',
132
132
  '@OptIn(kotlin.js.ExperimentalJsExport::class)',
133
133
  '@JsExport',
134
- 'fun peachSetAndroidDeviceInfo(model: String, release: String, apiLevel: Int, locale: String, timeZone: String) {',
134
+ 'fun peachSetAndroidDeviceInfo(model: String, release: String, apiLevel: Int, locale: String, timeZone: String, settings: String) {',
135
135
  ' Build.setDevice(model, release, apiLevel)',
136
136
  ' java.util.Locale.setDefault(java.util.Locale.forLanguageTag(locale))',
137
137
  ' java.util.TimeZone.setDevice(timeZone)',
138
+ ' dev.peach.android.ProcessSettings.configure(settings)',
138
139
  '}',
139
140
  '',
140
141
  '@OptIn(kotlin.js.ExperimentalJsExport::class, kotlinx.coroutines.DelicateCoroutinesApi::class)',
@@ -730,10 +731,11 @@ export async function expoKotlinArtifact(
730
731
  ' ))',
731
732
  '}',
732
733
  '',
733
- '@JsExport fun peachSetAndroidDeviceInfo(model: String, release: String, apiLevel: Int, locale: String, timeZone: String) {',
734
+ '@JsExport fun peachSetAndroidDeviceInfo(model: String, release: String, apiLevel: Int, locale: String, timeZone: String, settings: String) {',
734
735
  ' android.os.Build.setDevice(model, release, apiLevel)',
735
736
  ' java.util.Locale.setDefault(java.util.Locale.forLanguageTag(locale))',
736
737
  ' java.util.TimeZone.setDevice(timeZone)',
738
+ ' dev.peach.android.ProcessSettings.configure(settings)',
737
739
  ' PeachExpoRuntime.configureProcessLocale(locale)',
738
740
  '}',
739
741
  '',
@@ -10,7 +10,10 @@ import {
10
10
  readGoogleSignInConfiguration,
11
11
  selectNativeAppIdentityReader,
12
12
  } from './native-app-identity'
13
- import { resolveNativeAppIconArtwork } from './nativeAppIconContract'
13
+ import {
14
+ resolveNativeAppIconArtwork,
15
+ resolveNativeBundleIcons,
16
+ } from './nativeAppIconContract'
14
17
  import { parsePlistSource } from './plist'
15
18
  import { NATIVE_GRAPH_SDK_VERSION } from './swift-objc-standin'
16
19
  import {
@@ -91,11 +94,15 @@ export function readNativeAppIdentityFromXcodeTarget(
91
94
  }
92
95
  const alternateSetting =
93
96
  settings?.('ASSETCATALOG_COMPILER_ALTERNATE_APPICON_NAMES') ?? ''
97
+ const catalogAlternateNames: string[] = []
94
98
  for (const match of alternateSetting
95
99
  .replace(/\\"/g, '"')
96
100
  .matchAll(/"([^"]*)"|([^\s(),]+)/g)) {
97
101
  const val = match[1] ?? match[2]
98
- if (val) alternateIconNames.add(val)
102
+ if (val) {
103
+ alternateIconNames.add(val)
104
+ catalogAlternateNames.push(val)
105
+ }
99
106
  }
100
107
 
101
108
  const permissionUsageDescriptions: Record<string, unknown> = {}
@@ -204,6 +211,7 @@ export function readNativeAppIdentityFromXcodeTarget(
204
211
  ipadSupportedInterfaceOrientations,
205
212
  ...(defaultScreenOrientationMask ? { defaultScreenOrientationMask } : {}),
206
213
  alternateIconNames: [...alternateIconNames],
214
+ bundleIcons: resolveNativeBundleIcons(icons, catalogAlternateNames, (value) => value),
207
215
  appIconArtwork: resolveNativeAppIconArtwork(
208
216
  app.resources,
209
217
  (file) => fs.readFileSync(file, 'utf8'),
@@ -13,6 +13,7 @@ import { nativeAppIdentityFromAndroidManifest } from './android-app-identity'
13
13
  import { isRecord } from './is-record'
14
14
  import {
15
15
  resolveNativeAppIconArtwork,
16
+ resolveNativeBundleIcons,
16
17
  isNativeAppIconArtwork,
17
18
  readNativeAppIconArtwork,
18
19
  type NativeAppIconArtwork,
@@ -87,6 +88,7 @@ export interface NativeAppIdentity {
87
88
  rtcAppGroupIdentifier?: string
88
89
  screenShareExtensionBundleId?: string
89
90
  alternateIconNames?: readonly string[]
91
+ bundleIcons?: Readonly<Record<string, unknown>>
90
92
  appIconArtwork?: NativeAppIconArtwork
91
93
  // resolved Reanimated compile flags from the native build inputs.
92
94
  reanimatedStaticFeatureFlags?: Readonly<Record<string, boolean>>
@@ -183,6 +185,7 @@ export function isNativeAppIdentity(value: unknown): value is NativeAppIdentity
183
185
  )
184
186
  return false
185
187
  if (value.googleSignIn !== undefined && !isRecord(value.googleSignIn)) return false
188
+ if (value.bundleIcons !== undefined && !isRecord(value.bundleIcons)) return false
186
189
  const descriptions = value.permissionUsageDescriptions
187
190
  if (
188
191
  value.reanimatedStaticFeatureFlags !== undefined &&
@@ -355,6 +358,9 @@ export function readNativeAppIdentity(value: unknown): NativeAppIdentity | null
355
358
  ...(value.alternateIconNames === undefined
356
359
  ? {}
357
360
  : { alternateIconNames: [...value.alternateIconNames] }),
361
+ ...(value.bundleIcons === undefined
362
+ ? {}
363
+ : { bundleIcons: structuredClone(value.bundleIcons) }),
358
364
  ...(value.androidManifestPermissions === undefined
359
365
  ? {}
360
366
  : {
@@ -1003,10 +1009,13 @@ function nativeAppIdentityFromIos(
1003
1009
  )
1004
1010
  if (alternateSetting === null)
1005
1011
  throw new Error('native alternate icon setting is unresolved')
1012
+ const catalogAlternateNames: string[] = []
1006
1013
  for (const match of alternateSetting
1007
1014
  .replace(/\\"/g, '"')
1008
1015
  .matchAll(/"([^"]*)"|([^\s(),]+)/g)) {
1009
- alternateIconNames.add(match[1] ?? match[2])
1016
+ const name = match[1] ?? match[2]
1017
+ alternateIconNames.add(name)
1018
+ catalogAlternateNames.push(name)
1010
1019
  }
1011
1020
  // swift casts the whole configured value to [String]; a mixed array grants none.
1012
1021
  const intentIds = dictionary.OneAppIntentIdentifiers
@@ -1208,6 +1217,11 @@ function nativeAppIdentityFromIos(
1208
1217
  ? {}
1209
1218
  : { defaultScreenOrientationMask }),
1210
1219
  alternateIconNames: [...alternateIconNames],
1220
+ bundleIcons: resolveNativeBundleIcons(icons, catalogAlternateNames, (value) => {
1221
+ const resolved = resolveBuildSetting(value, settings)
1222
+ if (resolved === null) throw new Error('native bundle icon reference is unresolved')
1223
+ return resolved
1224
+ }),
1211
1225
  ...(resourceUri
1212
1226
  ? {
1213
1227
  appIconArtwork: resolveNativeAppIconArtwork(
@@ -6,6 +6,43 @@ export interface NativeAppIconArtwork {
6
6
  alternates: Record<string, SwiftImageVariants>
7
7
  }
8
8
 
9
+ export function resolveNativeBundleIcons(
10
+ icons: unknown,
11
+ catalogNames: readonly string[],
12
+ resolveReference: (value: string) => string,
13
+ ): Record<string, unknown> | undefined {
14
+ if (!isRecord(icons) && catalogNames.length === 0) return undefined
15
+ const resolve = (value: unknown): unknown => {
16
+ if (typeof value === 'string') return resolveReference(value)
17
+ if (Array.isArray(value)) return value.map(resolve)
18
+ if (isRecord(value))
19
+ return Object.fromEntries(
20
+ Object.entries(value).map(([key, entry]) => [
21
+ resolveReference(key),
22
+ resolve(entry),
23
+ ]),
24
+ )
25
+ return value
26
+ }
27
+ const dictionary = isRecord(icons)
28
+ ? Object.fromEntries(
29
+ Object.entries(icons).map(([key, value]) => [key, resolve(value)]),
30
+ )
31
+ : {}
32
+ if (catalogNames.length === 0) return dictionary
33
+ return {
34
+ ...dictionary,
35
+ CFBundleAlternateIcons: {
36
+ ...Object.fromEntries(
37
+ catalogNames.map((name) => [name, { CFBundleIconName: name }]),
38
+ ),
39
+ ...(isRecord(dictionary.CFBundleAlternateIcons)
40
+ ? dictionary.CFBundleAlternateIcons
41
+ : {}),
42
+ },
43
+ }
44
+ }
45
+
9
46
  export function isNativeAppIconArtwork(value: unknown): value is NativeAppIconArtwork {
10
47
  return (
11
48
  isRecord(value) &&
@@ -201,6 +201,14 @@ export function applyInstalledSwiftTargets(
201
201
  return !collection.targets.some((target) => target.name === module)
202
202
  })
203
203
  dropSuppliedHeaders(generated, native)
204
+ if (native.flattensPublicHeaders && native.publicHeaders.length > 0)
205
+ generated.swiftFlags = [
206
+ ...(generated.swiftFlags ?? []),
207
+ '-Xcc',
208
+ '-I',
209
+ '-Xcc',
210
+ `$(PEACH_INPUT_ROOT)/.build/peach-cxx-headers/${native.name}`,
211
+ ]
204
212
  const flags = originalModuleFlags(native.flags)
205
213
  generated.clangSettings = [
206
214
  { tool: 'c', flags: [...flags, ...ndebug, ...search] },