peachsim 0.1.939 → 0.1.1399
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.
- package/README.md +28 -22
- package/cli/app-catalog.ts +29 -14
- package/cli/app-fonts.ts +5 -3
- package/cli/bridge-flow-runner.ts +40 -29
- package/cli/cloud-client.ts +57 -21
- package/cli/cloud-test-tunnel.ts +12 -18
- package/cli/commands/agent.ts +1 -1
- package/cli/commands/app-fonts.ts +3 -3
- package/cli/commands/assert.ts +8 -8
- package/cli/commands/auth.ts +8 -3
- package/cli/commands/box/bundle-plane.ts +13 -1
- package/cli/commands/box.ts +16 -5
- package/cli/commands/compat.ts +1 -1
- package/cli/commands/config.ts +2 -2
- package/cli/commands/control.ts +125 -71
- package/cli/commands/cpu-profile.ts +45 -1
- package/cli/commands/daemon.ts +131 -33
- package/cli/commands/debug.ts +24 -17
- package/cli/commands/desktop.ts +7 -1
- package/cli/commands/detect.ts +101 -0
- package/cli/commands/detox.ts +6 -6
- package/cli/commands/device.ts +12 -12
- package/cli/commands/electron.ts +32 -14
- package/cli/commands/flow.ts +49 -41
- package/cli/commands/guest-host.ts +39 -1
- package/cli/commands/inspect/core.ts +14 -8
- package/cli/commands/inspect/list.ts +1 -1
- package/cli/commands/inspect/settle.ts +5 -3
- package/cli/commands/inspect/settling.ts +229 -44
- package/cli/commands/inspect/wait-idle.ts +3 -2
- package/cli/commands/inspect.ts +105 -93
- package/cli/commands/install-cli.ts +36 -15
- package/cli/commands/install-desktop.ts +68 -195
- package/cli/commands/kotlin.ts +6 -5
- package/cli/commands/login.ts +5 -5
- package/cli/commands/maestro-compare.ts +554 -0
- package/cli/commands/maestro-generate.ts +6 -3
- package/cli/commands/maestro.ts +22 -0
- package/cli/commands/mode.ts +2 -2
- package/cli/commands/no-bridge-hint.ts +6 -2
- package/cli/commands/platform.ts +35 -6
- package/cli/commands/preview.ts +6 -0
- package/cli/commands/project-report.ts +10 -12
- package/cli/commands/record.ts +37 -37
- package/cli/commands/runtime.ts +9 -9
- package/cli/commands/screenshot-layers.ts +4 -4
- package/cli/commands/screenshot-mode.ts +2 -2
- package/cli/commands/screenshot.ts +8 -8
- package/cli/commands/screenshots-capture.ts +2 -2
- package/cli/commands/serve.ts +9 -12
- package/cli/commands/setup.ts +29 -14
- package/cli/commands/shell-boolean-mode.ts +2 -2
- package/cli/commands/show-touches-mode.ts +2 -2
- package/cli/commands/skills.ts +11 -11
- package/cli/commands/swift.ts +29 -11
- package/cli/commands/telemetry.ts +2 -2
- package/cli/commands/test.ts +5 -0
- package/cli/commands/three-mode.ts +3 -3
- package/cli/commands/timeline.ts +4 -4
- package/cli/commands/upgrade.ts +2 -2
- package/cli/commands/upload.ts +15 -15
- package/cli/commands/what-happened.ts +2 -2
- package/cli/current-sim.ts +6 -3
- package/cli/desktop-companion.ts +55 -149
- package/cli/dev-build-freshness.ts +2 -2
- package/cli/drivers/desktop.ts +17 -9
- package/cli/drivers/electron.ts +1 -2
- package/cli/drivers/playwright-sim-host.ts +11 -2
- package/cli/drivers/playwright.ts +35 -2
- package/cli/drivers/types.ts +8 -0
- package/cli/maestro-compare.ts +670 -0
- package/cli/outbound-endpoints.ts +46 -8
- package/cli/recording-access.ts +6 -6
- package/cli/run-registry.ts +1 -1
- package/cli/runtime-compat.ts +5 -1
- package/cli/send-to-box.ts +3 -3
- package/cli/shell-init.ts +2 -1
- package/cli/ws-bridge.ts +9 -5
- package/detox/element-types.ts +1 -0
- package/detox/gestures.ts +3 -3
- package/detox/index.ts +67 -38
- package/detox/navigation-lifecycle.ts +9 -6
- package/detox/proof-frame.cjs +6 -4
- package/dist-lib/agent-daemon-client.cjs +1 -1
- package/dist-lib/agent-events.cjs +1 -1
- package/dist-lib/attached-projects.cjs +1 -1
- package/dist-lib/auth/shared-session.cjs +1 -1
- package/dist-lib/backend-origin.cjs +1 -1
- package/dist-lib/beta.cjs +1 -1
- package/dist-lib/beta.mjs +1 -1
- package/dist-lib/bridge-constants.cjs +1 -1
- package/dist-lib/bridge-contract-input.cjs +42 -17
- package/dist-lib/bridge-contract-input.mjs +41 -16
- package/dist-lib/bridge-contract.cjs +1 -4
- package/dist-lib/bridge-contract.mjs +1 -3
- package/dist-lib/bundle-channel.cjs +2918 -550
- package/dist-lib/capture-contract.cjs +65 -24
- package/dist-lib/capture-contract.mjs +63 -24
- package/dist-lib/cloud-contract.cjs +2 -2
- package/dist-lib/cloud-contract.mjs +2 -2
- package/dist-lib/cloud-test-args.cjs +1 -1
- package/dist-lib/cloud-test-args.mjs +1 -1
- package/dist-lib/cloud.cjs +3 -3
- package/dist-lib/cloud.mjs +3 -3
- package/dist-lib/config.cjs +15 -5
- package/dist-lib/config.mjs +154 -0
- package/dist-lib/detox/index.cjs +495 -139
- package/dist-lib/dev-bundle-resolution.cjs +1 -1
- package/dist-lib/expo-swift-bundle.cjs +1168 -238
- package/dist-lib/expo-swift-metadata.cjs +34 -23
- package/dist-lib/expo-swift-metadata.mjs +32 -23
- package/dist-lib/home-paths.cjs +2 -2
- package/dist-lib/host/bridge-host.cjs +2938 -654
- package/dist-lib/host/fetch-proxy-handler.cjs +14 -1
- package/dist-lib/host/fetch-proxy-overrides.cjs +7 -1
- package/dist-lib/host/fetch-proxy-overrides.mjs +5 -1
- package/dist-lib/host/replacement-module-handler.cjs +2 -2
- package/dist-lib/host/websocket-proxy.cjs +1 -1
- package/dist-lib/index.cjs +999 -353
- package/dist-lib/jump-to-source-babel.cjs +1 -1
- package/dist-lib/jump-to-source-native.cjs +1 -1
- package/dist-lib/kotlin-host.cjs +332 -19
- package/dist-lib/menu.cjs +1 -1
- package/dist-lib/menu.mjs +1 -1
- package/dist-lib/metro-fingerprint-registry.cjs +1 -1
- package/dist-lib/metro-fingerprint-registry.mjs +1 -1
- package/dist-lib/metro-production-bundle.cjs +7 -7
- package/dist-lib/metro-production-bundle.mjs +5 -5
- package/dist-lib/metro.cjs +688 -250
- package/dist-lib/native-app-identity-project.cjs +2647 -0
- package/dist-lib/native-app-identity-project.mjs +1257 -0
- package/dist-lib/native-app-identity.cjs +325 -25
- package/dist-lib/native-app-identity.mjs +323 -25
- package/dist-lib/native-firebase-metadata.cjs +1 -1
- package/dist-lib/native-firebase-metadata.mjs +1 -1
- package/dist-lib/plist.cjs +1 -1
- package/dist-lib/plist.mjs +1 -1
- package/dist-lib/profiles.cjs +1 -1
- package/dist-lib/public-brand.cjs +1 -1
- package/dist-lib/react-native-host-modules.cjs +5 -1
- package/dist-lib/react-native-host-modules.mjs +5 -1
- package/dist-lib/scripts/dev-server-scanner.cjs +57 -32
- package/dist-lib/sdk.cjs +231 -51
- package/dist-lib/sdk.mjs +231 -51
- package/dist-lib/skills.cjs +4107 -1374
- package/dist-lib/swift-compile.cjs +290 -30
- package/dist-lib/swift-compile.mjs +290 -30
- package/dist-lib/swift-package.cjs +143 -12
- package/dist-lib/swift-package.mjs +137 -11
- package/dist-lib/swift-submit.cjs +47 -5
- package/dist-lib/swift-submit.mjs +42 -5
- package/dist-lib/swift-toolchain.cjs +7 -2
- package/dist-lib/swift.cjs +1 -1
- package/dist-lib/vite-swift.cjs +1392 -458
- package/dist-lib/vite.cjs +13 -17
- package/dist-lib/worklet-executable.cjs +248 -33
- package/dist-lib/worklet-executable.mjs +248 -33
- package/install.sh +10 -1
- package/kotlin/{AppSources → AndroidViewSources}/android/content/res/Resources.kt +9 -9
- package/kotlin/AndroidViewSources/android/graphics/Canvas.kt +20 -0
- package/kotlin/AndroidViewSources/android/view/View.kt +211 -0
- package/kotlin/AndroidViewSources/android/widget/FrameLayout.kt +61 -0
- package/kotlin/AndroidViewSources/android/widget/LinearLayout.kt +49 -0
- package/kotlin/AppSources/android/view/Window.kt +36 -0
- package/kotlin/AppSources/android/view/WindowInsets.kt +9 -0
- package/kotlin/AppSources/android/view/WindowInsetsController.kt +5 -0
- package/kotlin/AppSources/android/window/OnBackInvokedDispatcher.kt +48 -0
- package/kotlin/AppSources/androidx/activity/OnBackPressedDispatcher.kt +20 -5
- package/kotlin/AppSources/androidx/compose/foundation/layout/WindowInsets.kt +15 -0
- package/kotlin/AppSources/androidx/compose/ui/platform/ComposeView.kt +2 -1
- package/kotlin/AppSources/dev/peach/app/PeachApp.kt +42 -50
- package/kotlin/ComposeSources/PeachComposeHost.kt +200 -84
- package/kotlin/ExpoComposeSources/PeachAndroidView.kt +87 -0
- package/kotlin/ExpoComposeSources/PeachExpoViewMount.kt +24 -0
- package/kotlin/ExpoComposeSources/dev/peach/expo/PeachExpoCompose.kt +28 -0
- package/kotlin/ExpoComposeSources/expo/modules/kotlin/views/ExpoComposeView.kt +70 -0
- package/kotlin/ExpoSources/dev/peach/expo/PeachExpoRuntime.kt +513 -0
- package/kotlin/ExpoSources/dev/peach/expo/PeachExpoTypes.kt +173 -0
- package/kotlin/ExpoSources/expo/modules/kotlin/AppContext.kt +20 -0
- package/kotlin/ExpoSources/expo/modules/kotlin/Promise.kt +19 -0
- package/kotlin/ExpoSources/expo/modules/kotlin/classcomponent/ClassComponentBuilder.kt +198 -0
- package/kotlin/ExpoSources/expo/modules/kotlin/exception/CodedException.kt +126 -0
- package/kotlin/ExpoSources/expo/modules/kotlin/functions/Functions.kt +132 -0
- package/kotlin/ExpoSources/expo/modules/kotlin/jni/JavaScriptTypedArray.kt +81 -0
- package/kotlin/ExpoSources/expo/modules/kotlin/modules/Module.kt +98 -0
- package/kotlin/ExpoSources/expo/modules/kotlin/objects/ObjectDefinitionBuilder.kt +236 -0
- package/kotlin/ExpoSources/expo/modules/kotlin/records/Record.kt +12 -0
- package/kotlin/ExpoSources/expo/modules/kotlin/runtime/Runtime.kt +9 -0
- package/kotlin/ExpoSources/expo/modules/kotlin/sharedobjects/SharedObject.kt +50 -0
- package/kotlin/ExpoSources/expo/modules/kotlin/sharedobjects/SharedObjectRegistry.kt +57 -0
- package/kotlin/ExpoSources/expo/modules/kotlin/sharedobjects/SharedRef.kt +19 -0
- package/kotlin/ExpoSources/expo/modules/kotlin/typedarray/ConcreteTypedArrays.kt +158 -0
- package/kotlin/ExpoSources/expo/modules/kotlin/typedarray/GenericTypedArray.kt +8 -0
- package/kotlin/ExpoSources/expo/modules/kotlin/typedarray/TypedArray.kt +29 -0
- package/kotlin/ExpoSources/expo/modules/kotlin/typedarray/TypedArrayIterator.kt +9 -0
- package/kotlin/ExpoSources/expo/modules/kotlin/types/AnyType.kt +155 -0
- package/kotlin/ExpoSources/expo/modules/kotlin/types/Either.kt +91 -0
- package/kotlin/ExpoSources/expo/modules/kotlin/types/Enumerable.kt +6 -0
- package/kotlin/ExpoSources/expo/modules/kotlin/viewevent/ViewEvent.kt +54 -0
- package/kotlin/ExpoSources/expo/modules/kotlin/views/ExpoView.kt +23 -0
- package/kotlin/ExpoSources/expo/modules/kotlin/views/ViewDefinitionBuilder.kt +71 -0
- package/kotlin/ExpoSources/expo/modules/kotlin/views/ViewProps.kt +35 -0
- package/kotlin/README.md +13 -3
- package/kotlin/Sources/android/os/Build.kt +17 -0
- package/kotlin/Sources/android/os/Handler.kt +35 -0
- package/kotlin/Sources/android/os/Looper.kt +17 -0
- package/kotlin/Sources/android/os/MessageQueue.kt +56 -0
- package/kotlin/Sources/android/os/SystemClock.kt +14 -0
- package/kotlin/Sources/android/util/Log.kt +64 -0
- package/kotlin/Sources/java/security/MessageDigest.kt +114 -0
- package/kotlin/Sources/kotlin/text/StringFormat.kt +9 -0
- package/kotlin/Sources/org/json/JSON.kt +44 -0
- package/kotlin/fixtures/counter/Counter.d.kt.ts +1 -0
- package/kotlin/fixtures/counter/Counter.kt +10 -3
- package/kotlin/fixtures/counter/CounterApp.native.tsx +1 -1
- package/kotlin/fixtures/counter/vite.config.ts +2 -2
- package/kotlin/fixtures/headless-counter/Headless.kt +7 -6
- package/kotlin/fixtures/import-animation/Animation.d.kt.ts +7 -0
- package/kotlin/fixtures/import-animation/Animation.kt +80 -0
- package/kotlin/fixtures/import-animation/ImportAnimation.native.tsx +13 -0
- package/kotlin/fixtures/import-animation/README.md +24 -0
- package/kotlin/fixtures/import-animation/app/_layout.tsx +4 -0
- package/kotlin/fixtures/import-animation/app/index+spa.tsx +1 -0
- package/kotlin/fixtures/import-animation/app/routes.d.ts +18 -0
- package/kotlin/fixtures/import-animation/package.json +23 -0
- package/kotlin/fixtures/import-animation/tsconfig.json +20 -0
- package/kotlin/fixtures/import-animation/vite.config.ts +20 -0
- package/kotlin/fixtures/import-editor/Editor.d.kt.ts +7 -0
- package/kotlin/fixtures/import-editor/Editor.kt +59 -0
- package/kotlin/fixtures/import-editor/ImportEditor.native.tsx +23 -0
- package/kotlin/fixtures/import-editor/README.md +27 -0
- package/kotlin/fixtures/import-editor/app/_layout.tsx +4 -0
- package/kotlin/fixtures/import-editor/app/index+spa.tsx +1 -0
- package/kotlin/fixtures/import-editor/package.json +23 -0
- package/kotlin/fixtures/import-editor/tsconfig.json +20 -0
- package/kotlin/fixtures/import-editor/vite.config.ts +20 -0
- package/kotlin/fixtures/import-effects/Effects.d.kt.ts +7 -0
- package/kotlin/fixtures/import-effects/Effects.kt +87 -0
- package/kotlin/fixtures/import-effects/ImportEffects.native.tsx +13 -0
- package/kotlin/fixtures/import-effects/README.md +19 -0
- package/kotlin/fixtures/import-effects/app/_layout.tsx +4 -0
- package/kotlin/fixtures/import-effects/app/index+spa.tsx +1 -0
- package/kotlin/fixtures/import-effects/package.json +23 -0
- package/kotlin/fixtures/import-effects/tsconfig.json +20 -0
- package/kotlin/fixtures/import-effects/vite.config.ts +20 -0
- package/kotlin/fixtures/import-layout/ImportLayout.native.tsx +13 -0
- package/kotlin/fixtures/import-layout/Layout.d.kt.ts +7 -0
- package/kotlin/fixtures/import-layout/Layout.kt +72 -0
- package/kotlin/fixtures/import-layout/README.md +24 -0
- package/kotlin/fixtures/import-layout/app/_layout.tsx +4 -0
- package/kotlin/fixtures/import-layout/app/index+spa.tsx +1 -0
- package/kotlin/fixtures/import-layout/package.json +23 -0
- package/kotlin/fixtures/import-layout/tsconfig.json +20 -0
- package/kotlin/fixtures/import-layout/vite.config.ts +20 -0
- package/kotlin/fixtures/import-navigation/ImportNavigation.native.tsx +18 -0
- package/kotlin/fixtures/import-navigation/Navigation.d.kt.ts +7 -0
- package/kotlin/fixtures/import-navigation/Navigation.kt +104 -0
- package/kotlin/fixtures/import-navigation/README.md +31 -0
- package/kotlin/fixtures/import-navigation/app/_layout.tsx +4 -0
- package/kotlin/fixtures/import-navigation/app/index+spa.tsx +1 -0
- package/kotlin/fixtures/import-navigation/package.json +23 -0
- package/kotlin/fixtures/import-navigation/tsconfig.json +20 -0
- package/kotlin/fixtures/import-navigation/vite.config.ts +20 -0
- package/kotlin/fixtures/import-overlays/ImportOverlays.native.tsx +29 -0
- package/kotlin/fixtures/import-overlays/Overlays.d.kt.ts +7 -0
- package/kotlin/fixtures/import-overlays/Overlays.kt +93 -0
- package/kotlin/fixtures/import-overlays/README.md +34 -0
- package/kotlin/fixtures/import-overlays/app/_layout.tsx +4 -0
- package/kotlin/fixtures/import-overlays/app/index+spa.tsx +1 -0
- package/kotlin/fixtures/import-overlays/package.json +23 -0
- package/kotlin/fixtures/import-overlays/tsconfig.json +20 -0
- package/kotlin/fixtures/import-overlays/vite.config.ts +20 -0
- package/kotlin/fixtures/import-scroll/ImportScroll.native.tsx +13 -0
- package/kotlin/fixtures/import-scroll/README.md +23 -0
- package/kotlin/fixtures/import-scroll/Scroll.d.kt.ts +7 -0
- package/kotlin/fixtures/import-scroll/Scroll.kt +91 -0
- package/kotlin/fixtures/import-scroll/app/_layout.tsx +4 -0
- package/kotlin/fixtures/import-scroll/app/index+spa.tsx +1 -0
- package/kotlin/fixtures/import-scroll/package.json +23 -0
- package/kotlin/fixtures/import-scroll/tsconfig.json +20 -0
- package/kotlin/fixtures/import-scroll/vite.config.ts +20 -0
- package/kotlin/fixtures/import-selection/ImportSelection.native.tsx +44 -0
- package/kotlin/fixtures/import-selection/README.md +32 -0
- package/kotlin/fixtures/import-selection/Selection.d.kt.ts +8 -0
- package/kotlin/fixtures/import-selection/Selection.kt +78 -0
- package/kotlin/fixtures/import-selection/app/_layout.tsx +4 -0
- package/kotlin/fixtures/import-selection/app/index+spa.tsx +1 -0
- package/kotlin/fixtures/import-selection/package.json +23 -0
- package/kotlin/fixtures/import-selection/tsconfig.json +20 -0
- package/kotlin/fixtures/import-selection/vite.config.ts +20 -0
- package/kotlin/fixtures/import-surfaces/ImportSurfaces.native.tsx +13 -0
- package/kotlin/fixtures/import-surfaces/README.md +22 -0
- package/kotlin/fixtures/import-surfaces/Surfaces.d.kt.ts +7 -0
- package/kotlin/fixtures/import-surfaces/Surfaces.kt +64 -0
- package/kotlin/fixtures/import-surfaces/app/_layout.tsx +4 -0
- package/kotlin/fixtures/import-surfaces/app/index+spa.tsx +1 -0
- package/kotlin/fixtures/import-surfaces/package.json +23 -0
- package/kotlin/fixtures/import-surfaces/tsconfig.json +20 -0
- package/kotlin/fixtures/import-surfaces/vite.config.ts +20 -0
- package/kotlin/fixtures/import-values/ImportValues.native.tsx +35 -0
- package/kotlin/fixtures/import-values/README.md +23 -0
- package/kotlin/fixtures/import-values/Values.d.kt.ts +11 -0
- package/kotlin/fixtures/import-values/Values.kt +66 -0
- package/kotlin/fixtures/import-values/app/_layout.tsx +4 -0
- package/kotlin/fixtures/import-values/app/index+spa.tsx +1 -0
- package/kotlin/fixtures/import-values/package.json +23 -0
- package/kotlin/fixtures/import-values/tsconfig.json +20 -0
- package/kotlin/fixtures/import-values/vite.config.ts +20 -0
- package/kotlin/fixtures/kotlin-app-variants/BarBehavior.kt +38 -0
- package/kotlin/fixtures/kotlin-app-variants/BarVisibility.kt +36 -0
- package/kotlin/fixtures/kotlin-app-variants/Ime.kt +3 -1
- package/kotlin/fixtures/kotlin-app-variants/TransientInsets.kt +50 -0
- package/kotlin/fork/NOTICE +6 -1
- package/kotlin/fork/README.md +15 -7
- package/kotlin/fork/build.sh +2 -0
- package/kotlin/fork/compose-worker-globals.patch +186 -4
- package/kotlin/fork/fork.json +2 -2
- package/kotlin/fork/skiko-worker-clock.patch +12 -0
- package/kotlin/toolchain.json +12 -12
- package/kotlin/tools/expo-types.main.kts +115 -0
- package/package.json +17 -23
- package/scripts/dev-server-scanner.ts +92 -66
- package/skills/contrast/SKILL.md +2 -2
- package/skills/peach-debug/SKILL.md +1 -1
- package/skills/peach-perf/SKILL.md +1 -1
- package/skills/peach-setup/SKILL.md +2 -1
- package/skills/peach-test/SKILL.md +8 -0
- package/src/assetCatalogContract.ts +43 -1
- package/src/bridge-contract-input.ts +46 -19
- package/src/bridge-contract.ts +0 -1
- package/src/bundle-channel.mjs +197 -84
- package/src/bundleGlobalFooter.ts +38 -0
- package/src/capture-contract.ts +107 -33
- package/src/cloud-contract.ts +5 -1
- package/src/cloud.ts +5 -2
- package/src/config.ts +22 -3
- package/src/configured-bundle-producer.ts +1 -1
- package/src/desktop-host-delivery.ts +95 -1
- package/src/expo-kotlin-bundle.ts +29 -0
- package/src/expo-kotlin-host.ts +201 -0
- package/src/expo-swift-host.ts +96 -76
- package/src/expoKotlinContract.ts +70 -0
- package/src/expoSwiftContract.ts +4 -25
- package/src/home-paths.ts +7 -4
- package/src/host/bridge-host.ts +23 -3
- package/src/host/fetch-proxy-handler.ts +13 -0
- package/src/host/fetch-proxy-overrides.ts +11 -0
- package/src/host/replacement-module-handler.ts +5 -2
- package/src/index.ts +3 -1
- package/src/kotlin-host.ts +463 -19
- package/src/metro-plugin.ts +56 -28
- package/src/metro-production-bundle.ts +2 -2
- package/src/native-app-identity-project.ts +190 -0
- package/src/native-app-identity.ts +398 -34
- package/src/native-firebase-config.ts +69 -15
- package/src/native-seam-manifest.ts +6 -0
- package/src/one-widget-discovery.ts +2 -1
- package/src/openstep-plist.ts +107 -0
- package/src/react-native-host-modules.ts +4 -0
- package/src/runtime-assets.ts +2 -2
- package/src/sim-client.ts +2 -2
- package/src/swift-binary-modules.ts +3 -1
- package/src/swift-compile.ts +286 -38
- package/src/swift-distribution-contract.ts +4 -0
- package/src/swift-distribution.lock.json +123 -12
- package/src/swift-distribution.ts +7 -3
- package/src/swift-host.ts +298 -83
- package/src/swift-package-manifest.ts +29 -2
- package/src/swift-package.ts +180 -10
- package/src/swift-packages.ts +4 -0
- package/src/swift-standin-emit.ts +4 -1
- package/src/swift-standins.ts +274 -15
- package/src/swift-submit.ts +62 -7
- package/src/swift-toolchain.ts +6 -1
- package/src/swiftContract.ts +126 -3
- package/src/vite-plugin-one.ts +13 -16
- package/src/vite-plugin-swift.ts +4 -5
- package/src/vite-plugin.ts +360 -144
- package/src/vite.d.ts +1 -1
- package/src/worker-system-chunks.ts +221 -0
- package/src/worklet-executable.ts +348 -38
- package/src/worklets-babel.ts +1 -1
- package/src/xcode-project.ts +243 -127
- package/dist-lib/agent-identity.cjs +0 -39
- package/dist-lib/agent-sessions.cjs +0 -760
- package/dist-lib/cli-constants.cjs +0 -32
- package/dist-lib/render-mode.cjs +0 -44
- package/kotlin/AppSources/android/view/View.kt +0 -74
- package/kotlin/AppSources/android/widget/FrameLayout.kt +0 -6
- package/src/render-mode.ts +0 -15
- /package/kotlin/{AppSources → AndroidViewSources}/android/content/Context.kt +0 -0
- /package/kotlin/{AppSources → AndroidViewSources}/android/content/res/Configuration.kt +0 -0
- /package/kotlin/{AppSources → AndroidViewSources}/android/graphics/Color.kt +0 -0
- /package/kotlin/{AppSources → AndroidViewSources}/android/util/DisplayMetrics.kt +0 -0
- /package/kotlin/{AppSources → AndroidViewSources}/dev/peach/app/JavaFormat.kt +0 -0
- /package/kotlin/{AppSources → Sources}/java/lang/Runnable.kt +0 -0
|
@@ -3,15 +3,29 @@
|
|
|
3
3
|
// against the Xcode Release build settings, or `android/app/build.gradle`), so
|
|
4
4
|
// a simulator tenant reports the same identity the native Release build does.
|
|
5
5
|
//
|
|
6
|
-
//
|
|
7
|
-
//
|
|
8
|
-
//
|
|
6
|
+
// identity travels in a bundle footer or response header. the one updates
|
|
7
|
+
// receipt travels only in the response header so publisher JavaScript stays
|
|
8
|
+
// unchanged. tenant boot validates both before evaluation and clears the realm
|
|
9
|
+
// store when neither carries identity.
|
|
10
|
+
|
|
11
|
+
import { parseOpenStepPlist } from './openstep-plist'
|
|
9
12
|
|
|
10
13
|
export type NativeAppIdentityPlatform = 'ios' | 'android'
|
|
11
14
|
|
|
15
|
+
export interface NativeOneUpdatesReceipt {
|
|
16
|
+
enabled: boolean
|
|
17
|
+
url: string | null
|
|
18
|
+
runtimeVersion: string | null
|
|
19
|
+
embeddedManifestJson: string | null
|
|
20
|
+
}
|
|
21
|
+
|
|
12
22
|
export interface NativeAppIdentity {
|
|
13
23
|
// the user-facing name (CFBundleDisplayName, else CFBundleName).
|
|
14
24
|
applicationName: string | null
|
|
25
|
+
// the literal CFBundleDisplayName, without a bundle-name fallback.
|
|
26
|
+
applicationDisplayName?: string
|
|
27
|
+
// the processed ARGB integer from RCTRootViewBackgroundColor.
|
|
28
|
+
rootViewBackgroundColor?: number
|
|
15
29
|
// CFBundleName, which CFNetwork stamps into the default User-Agent and iOS's
|
|
16
30
|
// own prompts use (the ASWebAuthenticationSession consent alert); distinct
|
|
17
31
|
// from the display name. absent in footers built before it was carried.
|
|
@@ -23,6 +37,16 @@ export interface NativeAppIdentity {
|
|
|
23
37
|
permissionUsageDescriptions?: Readonly<Record<string, unknown>>
|
|
24
38
|
urlQuerySchemes?: readonly unknown[]
|
|
25
39
|
appIntentIdentifiers?: readonly string[]
|
|
40
|
+
backgroundTaskIdentifiers?: readonly string[]
|
|
41
|
+
backgroundModes?: readonly string[]
|
|
42
|
+
supportedInterfaceOrientations?: readonly string[]
|
|
43
|
+
ipadSupportedInterfaceOrientations?: readonly string[]
|
|
44
|
+
defaultScreenOrientationMask?: string
|
|
45
|
+
shareIntoAppGroupId?: string
|
|
46
|
+
alternateIconNames?: readonly string[]
|
|
47
|
+
// one updates configuration travels only in response metadata, never in guest
|
|
48
|
+
// code or inferred from JavaScript build flags.
|
|
49
|
+
oneUpdates?: NativeOneUpdatesReceipt
|
|
26
50
|
}
|
|
27
51
|
|
|
28
52
|
export type NativeAppIdentityFiles = Record<string, string>
|
|
@@ -46,6 +70,24 @@ function nonEmptyString(value: unknown): string | null {
|
|
|
46
70
|
|
|
47
71
|
export function isNativeAppIdentity(value: unknown): value is NativeAppIdentity {
|
|
48
72
|
if (!isRecord(value)) return false
|
|
73
|
+
const oneUpdates = value.oneUpdates
|
|
74
|
+
if (
|
|
75
|
+
oneUpdates !== undefined &&
|
|
76
|
+
(!isRecord(oneUpdates) ||
|
|
77
|
+
typeof oneUpdates.enabled !== 'boolean' ||
|
|
78
|
+
(oneUpdates.url !== null && typeof oneUpdates.url !== 'string') ||
|
|
79
|
+
(oneUpdates.runtimeVersion !== null &&
|
|
80
|
+
typeof oneUpdates.runtimeVersion !== 'string') ||
|
|
81
|
+
(oneUpdates.embeddedManifestJson !== null &&
|
|
82
|
+
typeof oneUpdates.embeddedManifestJson !== 'string') ||
|
|
83
|
+
(oneUpdates.enabled &&
|
|
84
|
+
(typeof oneUpdates.url !== 'string' ||
|
|
85
|
+
oneUpdates.url.length === 0 ||
|
|
86
|
+
typeof oneUpdates.runtimeVersion !== 'string' ||
|
|
87
|
+
oneUpdates.runtimeVersion.length === 0)))
|
|
88
|
+
) {
|
|
89
|
+
return false
|
|
90
|
+
}
|
|
49
91
|
const descriptions = value.permissionUsageDescriptions
|
|
50
92
|
if (descriptions !== undefined && !isRecord(descriptions)) return false
|
|
51
93
|
if (value.urlQuerySchemes !== undefined && !Array.isArray(value.urlQuerySchemes))
|
|
@@ -56,7 +98,59 @@ export function isNativeAppIdentity(value: unknown): value is NativeAppIdentity
|
|
|
56
98
|
!value.appIntentIdentifiers.every((identifier) => typeof identifier === 'string'))
|
|
57
99
|
)
|
|
58
100
|
return false
|
|
101
|
+
if (
|
|
102
|
+
value.backgroundTaskIdentifiers !== undefined &&
|
|
103
|
+
(!Array.isArray(value.backgroundTaskIdentifiers) ||
|
|
104
|
+
!value.backgroundTaskIdentifiers.every(
|
|
105
|
+
(identifier) => typeof identifier === 'string',
|
|
106
|
+
))
|
|
107
|
+
)
|
|
108
|
+
return false
|
|
109
|
+
if (
|
|
110
|
+
value.backgroundModes !== undefined &&
|
|
111
|
+
(!Array.isArray(value.backgroundModes) ||
|
|
112
|
+
!value.backgroundModes.every((mode) => typeof mode === 'string'))
|
|
113
|
+
)
|
|
114
|
+
return false
|
|
115
|
+
if (
|
|
116
|
+
value.shareIntoAppGroupId !== undefined &&
|
|
117
|
+
typeof value.shareIntoAppGroupId !== 'string'
|
|
118
|
+
)
|
|
119
|
+
return false
|
|
120
|
+
if (
|
|
121
|
+
value.applicationDisplayName !== undefined &&
|
|
122
|
+
typeof value.applicationDisplayName !== 'string'
|
|
123
|
+
)
|
|
124
|
+
return false
|
|
125
|
+
if (
|
|
126
|
+
value.rootViewBackgroundColor !== undefined &&
|
|
127
|
+
(typeof value.rootViewBackgroundColor !== 'number' ||
|
|
128
|
+
!Number.isInteger(value.rootViewBackgroundColor))
|
|
129
|
+
)
|
|
130
|
+
return false
|
|
131
|
+
for (const orientations of [
|
|
132
|
+
value.supportedInterfaceOrientations,
|
|
133
|
+
value.ipadSupportedInterfaceOrientations,
|
|
134
|
+
]) {
|
|
135
|
+
if (
|
|
136
|
+
orientations !== undefined &&
|
|
137
|
+
(!Array.isArray(orientations) ||
|
|
138
|
+
!orientations.every((orientation) => typeof orientation === 'string'))
|
|
139
|
+
)
|
|
140
|
+
return false
|
|
141
|
+
}
|
|
142
|
+
if (
|
|
143
|
+
value.defaultScreenOrientationMask !== undefined &&
|
|
144
|
+
typeof value.defaultScreenOrientationMask !== 'string'
|
|
145
|
+
)
|
|
146
|
+
return false
|
|
59
147
|
const platform = value.platform
|
|
148
|
+
if (
|
|
149
|
+
value.alternateIconNames !== undefined &&
|
|
150
|
+
(!Array.isArray(value.alternateIconNames) ||
|
|
151
|
+
!value.alternateIconNames.every((name) => typeof name === 'string'))
|
|
152
|
+
)
|
|
153
|
+
return false
|
|
60
154
|
if (platform !== 'ios' && platform !== 'android') return false
|
|
61
155
|
const applicationName = value.applicationName
|
|
62
156
|
if (applicationName !== null && nonEmptyString(applicationName) === null) return false
|
|
@@ -79,11 +173,20 @@ export function readNativeAppIdentity(value: unknown): NativeAppIdentity | null
|
|
|
79
173
|
}
|
|
80
174
|
return {
|
|
81
175
|
applicationName: value.applicationName,
|
|
176
|
+
...(value.applicationDisplayName === undefined
|
|
177
|
+
? {}
|
|
178
|
+
: { applicationDisplayName: value.applicationDisplayName }),
|
|
179
|
+
...(value.rootViewBackgroundColor === undefined
|
|
180
|
+
? {}
|
|
181
|
+
: { rootViewBackgroundColor: value.rootViewBackgroundColor }),
|
|
82
182
|
...(value.bundleName === undefined ? {} : { bundleName: value.bundleName }),
|
|
83
183
|
appVersion: value.appVersion,
|
|
84
184
|
buildVersion: value.buildVersion,
|
|
85
185
|
bundleIdentifier: value.bundleIdentifier,
|
|
86
186
|
platform: value.platform,
|
|
187
|
+
...(value.alternateIconNames === undefined
|
|
188
|
+
? {}
|
|
189
|
+
: { alternateIconNames: [...value.alternateIconNames] }),
|
|
87
190
|
...(value.permissionUsageDescriptions === undefined
|
|
88
191
|
? {}
|
|
89
192
|
: {
|
|
@@ -92,9 +195,43 @@ export function readNativeAppIdentity(value: unknown): NativeAppIdentity | null
|
|
|
92
195
|
...(value.appIntentIdentifiers === undefined
|
|
93
196
|
? {}
|
|
94
197
|
: { appIntentIdentifiers: [...value.appIntentIdentifiers] }),
|
|
198
|
+
...(value.backgroundTaskIdentifiers === undefined
|
|
199
|
+
? {}
|
|
200
|
+
: { backgroundTaskIdentifiers: [...value.backgroundTaskIdentifiers] }),
|
|
201
|
+
...(value.supportedInterfaceOrientations === undefined
|
|
202
|
+
? {}
|
|
203
|
+
: {
|
|
204
|
+
supportedInterfaceOrientations: [...value.supportedInterfaceOrientations],
|
|
205
|
+
}),
|
|
206
|
+
...(value.ipadSupportedInterfaceOrientations === undefined
|
|
207
|
+
? {}
|
|
208
|
+
: {
|
|
209
|
+
ipadSupportedInterfaceOrientations: [
|
|
210
|
+
...value.ipadSupportedInterfaceOrientations,
|
|
211
|
+
],
|
|
212
|
+
}),
|
|
213
|
+
...(value.defaultScreenOrientationMask === undefined
|
|
214
|
+
? {}
|
|
215
|
+
: { defaultScreenOrientationMask: value.defaultScreenOrientationMask }),
|
|
216
|
+
...(value.backgroundModes === undefined
|
|
217
|
+
? {}
|
|
218
|
+
: { backgroundModes: [...value.backgroundModes] }),
|
|
219
|
+
...(value.shareIntoAppGroupId === undefined
|
|
220
|
+
? {}
|
|
221
|
+
: { shareIntoAppGroupId: value.shareIntoAppGroupId }),
|
|
95
222
|
...(value.urlQuerySchemes === undefined
|
|
96
223
|
? {}
|
|
97
224
|
: { urlQuerySchemes: [...value.urlQuerySchemes] }),
|
|
225
|
+
...(value.oneUpdates === undefined
|
|
226
|
+
? {}
|
|
227
|
+
: {
|
|
228
|
+
oneUpdates: {
|
|
229
|
+
enabled: value.oneUpdates.enabled,
|
|
230
|
+
url: value.oneUpdates.url,
|
|
231
|
+
runtimeVersion: value.oneUpdates.runtimeVersion,
|
|
232
|
+
embeddedManifestJson: value.oneUpdates.embeddedManifestJson,
|
|
233
|
+
},
|
|
234
|
+
}),
|
|
98
235
|
}
|
|
99
236
|
}
|
|
100
237
|
|
|
@@ -135,7 +272,10 @@ export function readNativeAppIdentityFromBundle(
|
|
|
135
272
|
}
|
|
136
273
|
const identity = readNativeAppIdentity(value)
|
|
137
274
|
if (!identity) throw new Error('native app identity response header is malformed')
|
|
138
|
-
|
|
275
|
+
const footerIdentity = footer ? readNativeAppIdentity(footer) : null
|
|
276
|
+
const headerBase = { ...identity, oneUpdates: undefined }
|
|
277
|
+
const footerBase = footerIdentity && { ...footerIdentity, oneUpdates: undefined }
|
|
278
|
+
if (footerIdentity && !equalIdentityValues(headerBase, footerBase)) {
|
|
139
279
|
throw new Error('native app identity response header conflicts with bundle footer')
|
|
140
280
|
}
|
|
141
281
|
return identity
|
|
@@ -158,7 +298,10 @@ export function getAppliedNativeAppIdentity(): NativeAppIdentity | null {
|
|
|
158
298
|
// one line, so the footer survives a bundle whose last statement is the Metro
|
|
159
299
|
// module identity footer and can be found again by reading the text.
|
|
160
300
|
export function createNativeAppIdentityFooter(identity: NativeAppIdentity): string {
|
|
161
|
-
const
|
|
301
|
+
const footerIdentity = { ...identity }
|
|
302
|
+
// native update configuration belongs to response metadata, never guest code.
|
|
303
|
+
delete footerIdentity.oneUpdates
|
|
304
|
+
const payload = JSON.stringify(footerIdentity)
|
|
162
305
|
.replace(/\u2028/g, '\\u2028')
|
|
163
306
|
.replace(/\u2029/g, '\\u2029')
|
|
164
307
|
.replace(/<\//g, '<\\/')
|
|
@@ -186,6 +329,9 @@ export function readNativeAppIdentityFooter(source: string): NativeAppIdentity |
|
|
|
186
329
|
if (!isNativeAppIdentity(parsed)) {
|
|
187
330
|
throw new Error('native app identity footer is malformed')
|
|
188
331
|
}
|
|
332
|
+
if (parsed.oneUpdates !== undefined) {
|
|
333
|
+
throw new Error('native app identity footer cannot contain one updates receipt')
|
|
334
|
+
}
|
|
189
335
|
return parsed
|
|
190
336
|
}
|
|
191
337
|
|
|
@@ -362,39 +508,162 @@ function appTargetReleaseSettings(
|
|
|
362
508
|
function nativeAppIdentityFromIos(
|
|
363
509
|
files: NativeAppIdentityFiles,
|
|
364
510
|
parseInfoPlist: (source: string) => unknown,
|
|
511
|
+
iosTarget?: string,
|
|
365
512
|
): NativeAppIdentity | null {
|
|
366
|
-
const pbxprojPath =
|
|
367
|
-
|
|
368
|
-
|
|
513
|
+
const pbxprojPath =
|
|
514
|
+
Object.keys(files).find((path) =>
|
|
515
|
+
/(?:^|\/)ios\/[^/]+\.xcodeproj\/project\.pbxproj$/.test(path),
|
|
516
|
+
) ??
|
|
517
|
+
Object.keys(files).find((path) =>
|
|
518
|
+
/(?:^|\/)[^/]+\.xcodeproj\/project\.pbxproj$/.test(path),
|
|
519
|
+
) ??
|
|
520
|
+
Object.keys(files).find((path) => /(?:^|\/)project\.pbxproj$/.test(path))
|
|
369
521
|
if (!pbxprojPath) return null
|
|
370
522
|
const pbxproj = files[pbxprojPath]
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
523
|
+
|
|
524
|
+
let objects: Record<string, unknown> = {}
|
|
525
|
+
try {
|
|
526
|
+
const parsed = parseOpenStepPlist(pbxproj)
|
|
527
|
+
if (isRecord(parsed)) {
|
|
528
|
+
objects = isRecord(parsed.objects) ? parsed.objects : parsed
|
|
529
|
+
}
|
|
530
|
+
} catch {
|
|
531
|
+
// fallback if unparseable
|
|
532
|
+
}
|
|
533
|
+
|
|
534
|
+
interface NativeTargetSummary {
|
|
535
|
+
id: string
|
|
536
|
+
name: string
|
|
537
|
+
productType?: string
|
|
538
|
+
buildConfigurationList?: string
|
|
539
|
+
}
|
|
540
|
+
const targets: NativeTargetSummary[] = []
|
|
541
|
+
for (const [id, obj] of Object.entries(objects)) {
|
|
542
|
+
if (isRecord(obj) && obj.isa === 'PBXNativeTarget' && typeof obj.name === 'string') {
|
|
543
|
+
targets.push({
|
|
544
|
+
id,
|
|
545
|
+
name: obj.name,
|
|
546
|
+
productType: typeof obj.productType === 'string' ? obj.productType : undefined,
|
|
547
|
+
buildConfigurationList:
|
|
548
|
+
typeof obj.buildConfigurationList === 'string'
|
|
549
|
+
? obj.buildConfigurationList
|
|
550
|
+
: undefined,
|
|
551
|
+
})
|
|
552
|
+
}
|
|
553
|
+
}
|
|
554
|
+
const applicationTargetNames = new Set(
|
|
555
|
+
targets
|
|
556
|
+
.filter((t) => t.productType === 'com.apple.product-type.application')
|
|
557
|
+
.map((t) => t.name),
|
|
380
558
|
)
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
559
|
+
if (applicationTargetNames.size === 0) {
|
|
560
|
+
for (const match of pbxproj.matchAll(
|
|
561
|
+
/isa = PBXNativeTarget;[^}]*?name = "?([^";]+)"?;[^}]*?productType = "com\.apple\.product-type\.application";/g,
|
|
562
|
+
)) {
|
|
563
|
+
applicationTargetNames.add(match[1])
|
|
564
|
+
}
|
|
565
|
+
}
|
|
566
|
+
|
|
567
|
+
let targetName: string | null = null
|
|
568
|
+
if (iosTarget) {
|
|
569
|
+
if (applicationTargetNames.has(iosTarget)) {
|
|
570
|
+
targetName = iosTarget
|
|
571
|
+
} else {
|
|
572
|
+
return null
|
|
573
|
+
}
|
|
574
|
+
} else if (applicationTargetNames.size === 1) {
|
|
575
|
+
targetName = [...applicationTargetNames][0]!
|
|
576
|
+
} else if (applicationTargetNames.size > 1) {
|
|
577
|
+
const appDelegatePattern = /(?:^|\/)ios\/([^/]+)\/AppDelegate\.(?:swift|mm|m)$/
|
|
578
|
+
const delegateTargets = Object.keys(files)
|
|
384
579
|
.filter((path) => !path.includes('/Pods/'))
|
|
385
580
|
.map((path) => path.match(appDelegatePattern)?.[1])
|
|
386
|
-
.
|
|
387
|
-
|
|
581
|
+
.filter(
|
|
582
|
+
(name): name is string =>
|
|
583
|
+
typeof name === 'string' && applicationTargetNames.has(name),
|
|
584
|
+
)
|
|
585
|
+
if (delegateTargets.length === 1) {
|
|
586
|
+
targetName = delegateTargets[0]!
|
|
587
|
+
} else {
|
|
588
|
+
return null
|
|
589
|
+
}
|
|
590
|
+
} else {
|
|
591
|
+
return null
|
|
592
|
+
}
|
|
388
593
|
|
|
389
|
-
const
|
|
390
|
-
|
|
594
|
+
const selectedTarget = targets.find((t) => t.name === targetName)
|
|
595
|
+
const settings: Record<string, string> = {
|
|
596
|
+
TARGET_NAME: targetName,
|
|
597
|
+
PRODUCT_NAME: targetName,
|
|
598
|
+
}
|
|
599
|
+
for (const obj of Object.values(objects)) {
|
|
600
|
+
if (
|
|
601
|
+
isRecord(obj) &&
|
|
602
|
+
obj.isa === 'PBXProject' &&
|
|
603
|
+
typeof obj.buildConfigurationList === 'string'
|
|
604
|
+
) {
|
|
605
|
+
const listObj = objects[obj.buildConfigurationList]
|
|
606
|
+
if (isRecord(listObj) && Array.isArray(listObj.buildConfigurations)) {
|
|
607
|
+
for (const configId of listObj.buildConfigurations) {
|
|
608
|
+
if (typeof configId === 'string') {
|
|
609
|
+
const configObj = objects[configId]
|
|
610
|
+
if (
|
|
611
|
+
isRecord(configObj) &&
|
|
612
|
+
configObj.name === 'Release' &&
|
|
613
|
+
isRecord(configObj.buildSettings)
|
|
614
|
+
) {
|
|
615
|
+
for (const [k, v] of Object.entries(configObj.buildSettings)) {
|
|
616
|
+
if (typeof v === 'string') settings[k] = v
|
|
617
|
+
}
|
|
618
|
+
}
|
|
619
|
+
}
|
|
620
|
+
}
|
|
621
|
+
}
|
|
622
|
+
}
|
|
623
|
+
}
|
|
624
|
+
if (selectedTarget?.buildConfigurationList) {
|
|
625
|
+
const listObj = objects[selectedTarget.buildConfigurationList]
|
|
626
|
+
if (isRecord(listObj) && Array.isArray(listObj.buildConfigurations)) {
|
|
627
|
+
for (const configId of listObj.buildConfigurations) {
|
|
628
|
+
if (typeof configId === 'string') {
|
|
629
|
+
const configObj = objects[configId]
|
|
630
|
+
if (
|
|
631
|
+
isRecord(configObj) &&
|
|
632
|
+
configObj.name === 'Release' &&
|
|
633
|
+
isRecord(configObj.buildSettings)
|
|
634
|
+
) {
|
|
635
|
+
for (const [k, v] of Object.entries(configObj.buildSettings)) {
|
|
636
|
+
if (typeof v === 'string') settings[k] = v
|
|
637
|
+
}
|
|
638
|
+
}
|
|
639
|
+
}
|
|
640
|
+
}
|
|
641
|
+
}
|
|
642
|
+
} else {
|
|
643
|
+
const legacy = appTargetReleaseSettings(
|
|
644
|
+
pbxproj,
|
|
645
|
+
targetName,
|
|
646
|
+
`${targetName}/Info.plist`,
|
|
647
|
+
)
|
|
648
|
+
if (legacy) Object.assign(settings, legacy)
|
|
649
|
+
}
|
|
391
650
|
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
651
|
+
let plist: string | undefined
|
|
652
|
+
const infoPlistPath = settings.INFOPLIST_FILE
|
|
653
|
+
if (infoPlistPath) {
|
|
654
|
+
const normalized = infoPlistPath.replace(/^"|"$/g, '')
|
|
655
|
+
plist =
|
|
656
|
+
files[`ios/${normalized}`] ??
|
|
657
|
+
files[normalized] ??
|
|
658
|
+
Object.entries(files).find(([k]) => k.endsWith(`/${normalized}`))?.[1]
|
|
659
|
+
}
|
|
660
|
+
if (!plist) {
|
|
661
|
+
plist =
|
|
662
|
+
files[`ios/${targetName}/Info.plist`] ??
|
|
663
|
+
files[`${targetName}/Info.plist`] ??
|
|
664
|
+
Object.entries(files).find(([k]) => k.endsWith(`/${targetName}/Info.plist`))?.[1]
|
|
665
|
+
}
|
|
666
|
+
if (!plist) return null
|
|
398
667
|
|
|
399
668
|
const bundleIdentifier = identityFieldFrom(
|
|
400
669
|
settings,
|
|
@@ -434,12 +703,87 @@ function nativeAppIdentityFromIos(
|
|
|
434
703
|
// with the build-side parser; the browser transport has no XML dependency.
|
|
435
704
|
const dictionary = parseInfoPlist(plist)
|
|
436
705
|
if (!isRecord(dictionary)) throw new Error('native app Info.plist is not a dictionary')
|
|
706
|
+
const declaredDisplayName = dictionary.CFBundleDisplayName
|
|
707
|
+
const applicationDisplayName =
|
|
708
|
+
typeof declaredDisplayName === 'string'
|
|
709
|
+
? resolveBuildSetting(declaredDisplayName, settings)
|
|
710
|
+
: undefined
|
|
711
|
+
if (applicationDisplayName === null)
|
|
712
|
+
throw new Error('native app Info.plist CFBundleDisplayName is unresolved')
|
|
713
|
+
const declaredBackgroundColor = dictionary.RCTRootViewBackgroundColor
|
|
714
|
+
const rootViewBackgroundColor =
|
|
715
|
+
typeof declaredBackgroundColor === 'number' &&
|
|
716
|
+
Number.isInteger(declaredBackgroundColor)
|
|
717
|
+
? declaredBackgroundColor
|
|
718
|
+
: undefined
|
|
719
|
+
const icons = dictionary.CFBundleIcons
|
|
720
|
+
const alternates = isRecord(icons) ? icons.CFBundleAlternateIcons : undefined
|
|
721
|
+
const alternateIconNames = new Set<string>()
|
|
722
|
+
for (const name of isRecord(alternates) ? Object.keys(alternates) : []) {
|
|
723
|
+
const resolved = resolveBuildSetting(name, settings)
|
|
724
|
+
if (resolved === null) throw new Error('native alternate icon name is unresolved')
|
|
725
|
+
alternateIconNames.add(resolved)
|
|
726
|
+
}
|
|
727
|
+
// xcode writes the declared asset catalog names into the compiled plist.
|
|
728
|
+
const alternateSetting = resolveBuildSetting(
|
|
729
|
+
settings.ASSETCATALOG_COMPILER_ALTERNATE_APPICON_NAMES ?? '',
|
|
730
|
+
settings,
|
|
731
|
+
)
|
|
732
|
+
if (alternateSetting === null)
|
|
733
|
+
throw new Error('native alternate icon setting is unresolved')
|
|
734
|
+
for (const match of alternateSetting
|
|
735
|
+
.replace(/\\"/g, '"')
|
|
736
|
+
.matchAll(/"([^"]*)"|([^\s(),]+)/g)) {
|
|
737
|
+
alternateIconNames.add(match[1] ?? match[2])
|
|
738
|
+
}
|
|
437
739
|
// swift casts the whole configured value to [String]; a mixed array grants none.
|
|
438
740
|
const intentIds = dictionary.OneAppIntentIdentifiers
|
|
439
741
|
const appIntentIdentifiers =
|
|
440
742
|
Array.isArray(intentIds) && intentIds.every((value) => typeof value === 'string')
|
|
441
743
|
? intentIds.map((value: string) => resolveBuildSetting(value, settings))
|
|
442
744
|
: []
|
|
745
|
+
const backgroundIds = dictionary.BGTaskSchedulerPermittedIdentifiers
|
|
746
|
+
const backgroundTaskIdentifiers =
|
|
747
|
+
Array.isArray(backgroundIds) &&
|
|
748
|
+
backgroundIds.every((value) => typeof value === 'string')
|
|
749
|
+
? backgroundIds.map((value: string) => resolveBuildSetting(value, settings))
|
|
750
|
+
: []
|
|
751
|
+
const declaredModes = dictionary.UIBackgroundModes
|
|
752
|
+
const backgroundModes =
|
|
753
|
+
Array.isArray(declaredModes) &&
|
|
754
|
+
declaredModes.every((value) => typeof value === 'string')
|
|
755
|
+
? declaredModes.map((value: string) => resolveBuildSetting(value, settings))
|
|
756
|
+
: []
|
|
757
|
+
// the root orientation controller casts each plist list as a whole [String].
|
|
758
|
+
const screenOrientationLists = [
|
|
759
|
+
'UISupportedInterfaceOrientations',
|
|
760
|
+
'UISupportedInterfaceOrientations~ipad',
|
|
761
|
+
].map((key) => {
|
|
762
|
+
const list = dictionary[key]
|
|
763
|
+
if (!Array.isArray(list) || !list.every((value) => typeof value === 'string'))
|
|
764
|
+
return []
|
|
765
|
+
return list.map((value: string) => {
|
|
766
|
+
const resolved = resolveBuildSetting(value, settings)
|
|
767
|
+
if (resolved === null) throw new Error(`native app Info.plist ${key} is unresolved`)
|
|
768
|
+
return resolved
|
|
769
|
+
})
|
|
770
|
+
})
|
|
771
|
+
const [supportedInterfaceOrientations, ipadSupportedInterfaceOrientations] =
|
|
772
|
+
screenOrientationLists
|
|
773
|
+
const declaredDefaultOrientationMask = dictionary.EXDefaultScreenOrientationMask
|
|
774
|
+
const defaultScreenOrientationMask =
|
|
775
|
+
typeof declaredDefaultOrientationMask === 'string'
|
|
776
|
+
? resolveBuildSetting(declaredDefaultOrientationMask, settings)
|
|
777
|
+
: undefined
|
|
778
|
+
if (defaultScreenOrientationMask === null)
|
|
779
|
+
throw new Error('native app Info.plist EXDefaultScreenOrientationMask is unresolved')
|
|
780
|
+
const declaredShareGroup = dictionary.ExpoShareIntoAppGroupId
|
|
781
|
+
const shareIntoAppGroupId =
|
|
782
|
+
typeof declaredShareGroup === 'string'
|
|
783
|
+
? resolveBuildSetting(declaredShareGroup, settings)
|
|
784
|
+
: undefined
|
|
785
|
+
if (shareIntoAppGroupId === null)
|
|
786
|
+
throw new Error('native app Info.plist ExpoShareIntoAppGroupId is unresolved')
|
|
443
787
|
const querySchemes = dictionary.LSApplicationQueriesSchemes
|
|
444
788
|
if (querySchemes !== undefined && !Array.isArray(querySchemes)) {
|
|
445
789
|
throw new Error('native app Info.plist LSApplicationQueriesSchemes is not an array')
|
|
@@ -453,7 +797,11 @@ function nativeAppIdentityFromIos(
|
|
|
453
797
|
})
|
|
454
798
|
const permissionUsageDescriptions: Record<string, unknown> = {}
|
|
455
799
|
for (const [key, value] of Object.entries(dictionary)) {
|
|
456
|
-
if (
|
|
800
|
+
if (
|
|
801
|
+
!/^NS.*UsageDescription$/.test(key) &&
|
|
802
|
+
key !== 'NSLocationTemporaryUsageDescriptionDictionary'
|
|
803
|
+
)
|
|
804
|
+
continue
|
|
457
805
|
// retain non-string plist values: the native factory checks key presence.
|
|
458
806
|
if (typeof value !== 'string') {
|
|
459
807
|
permissionUsageDescriptions[key] = value
|
|
@@ -479,13 +827,28 @@ function nativeAppIdentityFromIos(
|
|
|
479
827
|
|
|
480
828
|
return {
|
|
481
829
|
applicationName,
|
|
830
|
+
...(applicationDisplayName === undefined ? {} : { applicationDisplayName }),
|
|
831
|
+
...(rootViewBackgroundColor === undefined ? {} : { rootViewBackgroundColor }),
|
|
482
832
|
bundleName,
|
|
483
833
|
appVersion,
|
|
484
834
|
buildVersion,
|
|
485
835
|
bundleIdentifier,
|
|
486
836
|
platform: 'ios',
|
|
837
|
+
supportedInterfaceOrientations,
|
|
838
|
+
ipadSupportedInterfaceOrientations,
|
|
839
|
+
...(defaultScreenOrientationMask === undefined
|
|
840
|
+
? {}
|
|
841
|
+
: { defaultScreenOrientationMask }),
|
|
842
|
+
alternateIconNames: [...alternateIconNames],
|
|
487
843
|
permissionUsageDescriptions,
|
|
488
844
|
urlQuerySchemes,
|
|
845
|
+
...(shareIntoAppGroupId === undefined ? {} : { shareIntoAppGroupId }),
|
|
846
|
+
backgroundTaskIdentifiers: backgroundTaskIdentifiers.every((value) => value !== null)
|
|
847
|
+
? backgroundTaskIdentifiers
|
|
848
|
+
: [],
|
|
849
|
+
backgroundModes: backgroundModes.every((value) => value !== null)
|
|
850
|
+
? backgroundModes
|
|
851
|
+
: [],
|
|
489
852
|
appIntentIdentifiers: appIntentIdentifiers.every((value) => value !== null)
|
|
490
853
|
? appIntentIdentifiers
|
|
491
854
|
: [],
|
|
@@ -504,13 +867,14 @@ export function canExtractNativeAppIdentity(platform: unknown): platform is 'ios
|
|
|
504
867
|
// read the identity a bundle builder transports. files are project-relative
|
|
505
868
|
// paths to their text, so both a checked-out app directory and a stored
|
|
506
869
|
// project file map resolve identically. null when the project carries no
|
|
507
|
-
// resolvable native config
|
|
870
|
+
// resolvable native config.
|
|
508
871
|
export function extractNativeAppIdentityFromFiles(
|
|
509
872
|
files: NativeAppIdentityFiles,
|
|
510
|
-
platform:
|
|
873
|
+
platform: unknown,
|
|
511
874
|
parseInfoPlist: (source: string) => unknown,
|
|
875
|
+
iosTarget?: string,
|
|
512
876
|
): NativeAppIdentity | null {
|
|
513
877
|
return canExtractNativeAppIdentity(platform)
|
|
514
|
-
? nativeAppIdentityFromIos(files, parseInfoPlist)
|
|
878
|
+
? nativeAppIdentityFromIos(files, parseInfoPlist, iosTarget)
|
|
515
879
|
: null
|
|
516
880
|
}
|