feat(ios): opt-in Google Maps SDK via Podfile.properties - #51
Conversation
📝 WalkthroughSummary by CodeRabbit
WalkthroughThe Expo plugin now normalizes platform keys and controls iOS Google Maps pod linkage. The podspec conditionally includes Google Maps, while iOS Swift code compiles only when the module is available and reports an explicit SDK-not-linked error otherwise. Documentation and tests cover the updated setup and resolution behavior. ChangesiOS Google Maps linkage
Estimated code review effort: 3 (Moderate) | ~20 minutes Sequence Diagram(s)sequenceDiagram
participant ExpoPlugin
participant PodfileProperties
participant Podspec
participant HybridMapView
participant GoogleMapsSDK
ExpoPlugin->>PodfileProperties: write betterMaps.iosGoogleProvider
Podspec->>PodfileProperties: read provider flag
Podspec->>GoogleMapsSDK: include GoogleMaps when enabled
HybridMapView->>GoogleMapsSDK: check module availability
GoogleMapsSDK-->>HybridMapView: available or unavailable
Suggested reviewers: 🚥 Pre-merge checks | ✅ 5 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (5 passed)
Warning There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure. 🔧 ESLint
ESLint install timed out. The project may have too many dependencies for the sandbox. Comment |
|
React Doctor could not complete this scan.
Reviewed by React Doctor for commit |
There was a problem hiding this comment.
Actionable comments posted: 4
🧹 Nitpick comments (2)
package/plugin/src/ios.test.ts (2)
15-29: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winTest the Podfile mutation, not just the podspec text.
This assertion passes even if the config plugin stops setting or clearing
Podfile.properties.json. Add a behavior-level test that invokes the plugin’s Podfile-property mutation for configured and unconfigured iOS keys.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@package/plugin/src/ios.test.ts` around lines 15 - 29, Extend the test suite around IOS_GOOGLE_PROVIDER_PODFILE_PROPERTY to invoke the plugin’s Podfile-property mutation and verify behavior for both configured and unconfigured iOS values. Assert that the configured key is written with the expected value and that the unconfigured case clears or removes the property, while retaining the existing podspec key consistency check.
44-69: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick winCover blank iOS keys with shared-key fallback.
resolveIosGoogleMapsApiKeyfalls back togoogleMapsApiKeyafter normalization, but the blank-key test has no shared key. Add this case to prevent regressions in the precedence contract:Suggested test
+ it('falls back to googleMapsApiKey when the iOS key is blank', () => { + expect( + resolveIosGoogleMapsApiKey({ + iosGoogleMapsApiKey: ' ', + googleMapsApiKey: 'shared', + }), + ).toBe('shared'); + });🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@package/plugin/src/ios.test.ts` around lines 44 - 69, Update the blank-key test for resolveIosGoogleMapsApiKey to include a googleMapsApiKey value and assert that the shared key is returned when iosGoogleMapsApiKey contains only whitespace, preserving iOS-key precedence when a nonblank value is provided.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@docs/expo-setup.md`:
- Around line 89-91: Update the iOS setup documentation to remove the claim that
prebuild synchronizes the Google Maps API key and pod linkage. Document that
removing keys from plugin config clears betterMaps.iosGoogleProvider but may
leave GoogleMapsIosApiKey in Info.plist, which users must remove manually, and
adjust the prebuild/pod install guidance accordingly.
In `@package/ios/GoogleMapsAPIKey.swift`:
- Around line 27-37: Update the googleMapsSdkNotLinked case in
MapProviderConfigurationError.errorDescription to mention the manual bare React
Native setup via Podfile.properties.json with betterMaps.iosGoogleProvider=true,
while retaining the existing config-plugin options and pod install instruction.
In `@package/plugin/src/ios.ts`:
- Around line 72-77: Update withBetterMapsIos so the Info.plist modification
always runs, including when the resolved Google Maps API key is absent, and
removes the existing GoogleMapsIosApiKey entry in that case. Keep key injection
for configured keys and preserve the Podfile configuration handled by
withIosGoogleProviderPodfileProperty.
In `@README.md`:
- Around line 414-418: Remove the `// ios/Podfile.properties.json` comment from
the JSON example in the README, leaving only valid JSON content.
---
Nitpick comments:
In `@package/plugin/src/ios.test.ts`:
- Around line 15-29: Extend the test suite around
IOS_GOOGLE_PROVIDER_PODFILE_PROPERTY to invoke the plugin’s Podfile-property
mutation and verify behavior for both configured and unconfigured iOS values.
Assert that the configured key is written with the expected value and that the
unconfigured case clears or removes the property, while retaining the existing
podspec key consistency check.
- Around line 44-69: Update the blank-key test for resolveIosGoogleMapsApiKey to
include a googleMapsApiKey value and assert that the shared key is returned when
iosGoogleMapsApiKey contains only whitespace, preserving iOS-key precedence when
a nonblank value is provided.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 6ea0c739-914b-4282-8e24-1fa5aef6dc90
📒 Files selected for processing (18)
README.mddocs/expo-setup.mdexample/app.config.jspackage/ios/Camera+GMSCameraPosition.swiftpackage/ios/GMSMapView+VisibleRegion.swiftpackage/ios/GoogleMapOverlayController.swiftpackage/ios/GoogleMapProviderAdapter.swiftpackage/ios/GoogleMapsAPIKey.swiftpackage/ios/HybridMapView.swiftpackage/ios/MapType+GMSMapViewType.swiftpackage/ios/OverlayEnteringAnimation.swiftpackage/ios/README.mdpackage/ios/Region+GMSCoordinateBounds.swiftpackage/plugin/src/android.test.tspackage/plugin/src/ios.test.tspackage/plugin/src/ios.tspackage/plugin/src/types.tspackage/react-native-better-maps.podspec
| - **iOS:** `GoogleMapsIosApiKey` in `Info.plist` and `betterMaps.iosGoogleProvider` in `Podfile.properties.json` (when `googleMapsApiKey` or `iosGoogleMapsApiKey` is set), plus location usage description strings (when location options are set) | ||
|
|
||
| On iOS, the API key and pod linkage are separate artifacts. The plugin keeps them in sync during prebuild. If you later remove Google Maps keys from the plugin config, re-run `expo prebuild` so `Podfile.properties.json` is updated and run `pod install` — a stale `"betterMaps.iosGoogleProvider": "true"` can leave the SDK linked after you stop providing a key. Bare React Native apps without the plugin must set both manually; see [Bare React Native](../README.md#bare-react-native) in the README. |
There was a problem hiding this comment.
🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win
Do not claim that prebuild keeps both iOS artifacts synchronized.
When the key is removed, the plugin clears betterMaps.iosGoogleProvider but leaves an existing GoogleMapsIosApiKey in Info.plist. These lines currently promise synchronization and instruct users that rerunning prebuild keeps both aligned, which is false. Either make the plugin remove the stale Info.plist key or document that it must be removed manually.
Also applies to: 116-116
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@docs/expo-setup.md` around lines 89 - 91, Update the iOS setup documentation
to remove the claim that prebuild synchronizes the Google Maps API key and pod
linkage. Document that removing keys from plugin config clears
betterMaps.iosGoogleProvider but may leave GoogleMapsIosApiKey in Info.plist,
which users must remove manually, and adjust the prebuild/pod install guidance
accordingly.
| enum MapProviderConfigurationError: LocalizedError { | ||
| case missingGoogleMapsIosApiKey | ||
| case googleMapsSdkNotLinked | ||
| case unsupportedIOSProvider(MapProvider) | ||
|
|
||
| var errorDescription: String? { | ||
| switch self { | ||
| case .missingGoogleMapsIosApiKey: | ||
| return "react-native-better-maps: provider=\"google\" on iOS requires GoogleMapsIosApiKey in the host app Info.plist." | ||
| case .googleMapsSdkNotLinked: | ||
| return "react-native-better-maps: provider=\"google\" on iOS requires iosGoogleMapsApiKey or googleMapsApiKey in the react-native-better-maps config plugin to link the Google Maps SDK, then run pod install." |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
Mention bare React Native linkage in the SDK error.
Bare React Native users may enable the pod through Podfile.properties.json without the Expo config plugin, but this message tells them only to configure the plugin. Include the manual betterMaps.iosGoogleProvider=true path (alongside pod install) so the troubleshooting instruction matches both supported setups.
Suggested wording
- return "react-native-better-maps: provider=\"google\" on iOS requires iosGoogleMapsApiKey or googleMapsApiKey in the react-native-better-maps config plugin to link the Google Maps SDK, then run pod install."
+ return "react-native-better-maps: provider=\"google\" on iOS requires the Google Maps SDK to be linked. Configure iosGoogleMapsApiKey/googleMapsApiKey in the config plugin, or set betterMaps.iosGoogleProvider=true in Podfile.properties.json, then run pod install."📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| enum MapProviderConfigurationError: LocalizedError { | |
| case missingGoogleMapsIosApiKey | |
| case googleMapsSdkNotLinked | |
| case unsupportedIOSProvider(MapProvider) | |
| var errorDescription: String? { | |
| switch self { | |
| case .missingGoogleMapsIosApiKey: | |
| return "react-native-better-maps: provider=\"google\" on iOS requires GoogleMapsIosApiKey in the host app Info.plist." | |
| case .googleMapsSdkNotLinked: | |
| return "react-native-better-maps: provider=\"google\" on iOS requires iosGoogleMapsApiKey or googleMapsApiKey in the react-native-better-maps config plugin to link the Google Maps SDK, then run pod install." | |
| enum MapProviderConfigurationError: LocalizedError { | |
| case missingGoogleMapsIosApiKey | |
| case googleMapsSdkNotLinked | |
| case unsupportedIOSProvider(MapProvider) | |
| var errorDescription: String? { | |
| switch self { | |
| case .missingGoogleMapsIosApiKey: | |
| return "react-native-better-maps: provider=\"google\" on iOS requires GoogleMapsIosApiKey in the host app Info.plist." | |
| case .googleMapsSdkNotLinked: | |
| return "react-native-better-maps: provider=\"google\" on iOS requires the Google Maps SDK to be linked. Configure iosGoogleMapsApiKey/googleMapsApiKey in the config plugin, or set betterMaps.iosGoogleProvider=true in Podfile.properties.json, then run pod install." |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@package/ios/GoogleMapsAPIKey.swift` around lines 27 - 37, Update the
googleMapsSdkNotLinked case in MapProviderConfigurationError.errorDescription to
mention the manual bare React Native setup via Podfile.properties.json with
betterMaps.iosGoogleProvider=true, while retaining the existing config-plugin
options and pod install instruction.
| export const withBetterMapsIos: ConfigPlugin<BetterMapsPluginOptions> = ( | ||
| config, | ||
| options = {}, | ||
| ) => { | ||
| config = withIosGoogleProviderPodfileProperty(config, options); | ||
|
|
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
Clear the stale Info.plist API key when disabling Google Maps.
Line 76 removes the Podfile flag, but an app that previously had a key configured returns at Lines 81-83 and retains GoogleMapsIosApiKey. Always apply the Info.plist mod and delete that entry when the resolved key is absent, so SDK linkage and key injection stay synchronized.
Proposed fix
- if (!iosGoogleMapsApiKey && !needsLocation) {
- return config;
- }
-
return withInfoPlist(config, (config) => {
- if (iosGoogleMapsApiKey) {
- config.modResults = applyGoogleMapsIosApiKey(
- config.modResults,
- iosGoogleMapsApiKey,
- );
- }
+ config.modResults = applyGoogleMapsIosApiKey(
+ config.modResults,
+ iosGoogleMapsApiKey,
+ ); export function applyGoogleMapsIosApiKey(infoPlist: InfoPlist, apiKey: string | undefined) {
- if (!apiKey) return infoPlist;
- return { ...infoPlist, [IOS_GOOGLE_MAPS_API_KEY]: apiKey };
+ const next = { ...infoPlist };
+ if (apiKey) next[IOS_GOOGLE_MAPS_API_KEY] = apiKey;
+ else delete next[IOS_GOOGLE_MAPS_API_KEY];
+ return next;
}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| export const withBetterMapsIos: ConfigPlugin<BetterMapsPluginOptions> = ( | |
| config, | |
| options = {}, | |
| ) => { | |
| config = withIosGoogleProviderPodfileProperty(config, options); | |
| export const withBetterMapsIos: ConfigPlugin<BetterMapsPluginOptions> = ( | |
| config, | |
| options = {}, | |
| ) => { | |
| config = withIosGoogleProviderPodfileProperty(config, options); | |
| return withInfoPlist(config, (config) => { | |
| config.modResults = applyGoogleMapsIosApiKey( | |
| config.modResults, | |
| iosGoogleMapsApiKey, | |
| ); | |
| return config; | |
| }); | |
| }; | |
| export function applyGoogleMapsIosApiKey( | |
| infoPlist: InfoPlist, | |
| apiKey: string | undefined, | |
| ) { | |
| const next = { ...infoPlist }; | |
| if (apiKey) next[IOS_GOOGLE_MAPS_API_KEY] = apiKey; | |
| else delete next[IOS_GOOGLE_MAPS_API_KEY]; | |
| return next; | |
| } |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@package/plugin/src/ios.ts` around lines 72 - 77, Update withBetterMapsIos so
the Info.plist modification always runs, including when the resolved Google Maps
API key is absent, and removes the existing GoogleMapsIosApiKey entry in that
case. Keep key injection for configured keys and preserve the Podfile
configuration handled by withIosGoogleProviderPodfileProperty.
| ```json | ||
| // ios/Podfile.properties.json | ||
| { | ||
| "betterMaps.iosGoogleProvider": "true" | ||
| } |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
Remove the comment from this JSON example.
// ios/Podfile.properties.json is not valid JSON. Copying this snippet verbatim will make CocoaPods fail to parse the file and disable the Google Maps pod.
Proposed fix
-// ios/Podfile.properties.json
{
"betterMaps.iosGoogleProvider": "true"
}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| ```json | |
| // ios/Podfile.properties.json | |
| { | |
| "betterMaps.iosGoogleProvider": "true" | |
| } |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@README.md` around lines 414 - 418, Remove the `//
ios/Podfile.properties.json` comment from the JSON example in the README,
leaving only valid JSON content.
Summary
GoogleMapsonly whenbetterMaps.iosGoogleProvideristrueinPodfile.properties.json.Test plan
package/plugin) and confirm new iOS/Android key resolution + podfile property cases passiosGoogleMapsApiKey/googleMapsApiKey:expo prebuildwritesbetterMaps.iosGoogleProvider: "true", thenpod installlinks GoogleMapsGoogleMapsIosApiKey+betterMaps.iosGoogleProvider, runpod install, verifyprovider="google"worksMade with Cursor
Need help on this PR? Tag
@codesmith-botwith what you need. Autofix is disabled.