From 56359e704e5bdd2638e047e301c92591575ac0ff Mon Sep 17 00:00:00 2001 From: Tomi Alu Date: Wed, 5 Aug 2026 00:32:37 +0100 Subject: [PATCH 1/3] feat(ios): upgrade GoogleSignIn SDK --- ReactNativeSocialAuth.podspec | 2 +- plugin/src/withSocialAuth.ts | 48 +++++++++++++++++++++++++++++++++++ 2 files changed, 49 insertions(+), 1 deletion(-) diff --git a/ReactNativeSocialAuth.podspec b/ReactNativeSocialAuth.podspec index e642d2a..b19e61e 100644 --- a/ReactNativeSocialAuth.podspec +++ b/ReactNativeSocialAuth.podspec @@ -18,5 +18,5 @@ Pod::Spec.new do |s| install_modules_dependencies(s) - s.dependency "GoogleSignIn", "~> 7.1" + s.dependency "GoogleSignIn", "~> 8.0" end diff --git a/plugin/src/withSocialAuth.ts b/plugin/src/withSocialAuth.ts index f2b704d..0a54f73 100644 --- a/plugin/src/withSocialAuth.ts +++ b/plugin/src/withSocialAuth.ts @@ -1,11 +1,14 @@ import { createRunOncePlugin, withAppDelegate, + withDangerousMod, withInfoPlist, } from '@expo/config-plugins'; import type { ConfigPlugin } from '@expo/config-plugins'; const pkg = require('../../package.json'); +const fs = require('fs').promises; +const path = require('path'); export type SocialAuthPluginProps = { /** @@ -20,6 +23,8 @@ export type SocialAuthPluginProps = { const PLUGIN_NAME = '@thoughtbot/react-native-social-auth'; const MARKER = '/* @thoughtbot/react-native-social-auth: URL handler */'; +const MODULAR_HEADERS_MARKER = + '# @thoughtbot/react-native-social-auth: GoogleSignIn 8+ dependencies'; /** * Compute the reversed iOS Client ID that GoogleSignIn-iOS expects as a @@ -141,6 +146,48 @@ ${MARKER} return next.replace(endRegex, `\n${snippet}\n@end\n`); } +/** @internal — exported for tests only. */ +export function injectModularHeaders(contents: string): string { + if ( + contents.includes(MODULAR_HEADERS_MARKER) || + /^\s*use_modular_headers!\s*$/m.test(contents) + ) { + return contents; + } + + const platformLine = /^platform :ios,.*$/m; + if (!platformLine.test(contents)) { + throw new Error( + `[${PLUGIN_NAME}] Could not locate the iOS platform declaration in the Podfile.` + ); + } + + return contents.replace( + platformLine, + `$&\n${MODULAR_HEADERS_MARKER}\nuse_modular_headers!` + ); +} + +const withGoogleSignInModularHeaders: ConfigPlugin = (config) => { + return withDangerousMod(config, [ + 'ios', + async (mod) => { + const podfilePath = path.join( + mod.modRequest.platformProjectRoot, + 'Podfile' + ); + const contents = await fs.readFile(podfilePath, 'utf8'); + const next = injectModularHeaders(contents); + + if (next !== contents) { + await fs.writeFile(podfilePath, next); + } + + return mod; + }, + ]); +}; + const withSocialAuth: ConfigPlugin = ( config, props @@ -160,6 +207,7 @@ const withSocialAuth: ConfigPlugin = ( config = withGoogleSignInURLScheme(config, { reversedClientId }); config = withGoogleSignInAppDelegate(config); + config = withGoogleSignInModularHeaders(config); return config; }; From 863f6dfd5086c88938440bd6d734712bac7db4bf Mon Sep 17 00:00:00 2001 From: Tomi Alu Date: Wed, 5 Aug 2026 00:35:53 +0100 Subject: [PATCH 2/3] docs: update readme --- README.md | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/README.md b/README.md index 2b9685b..3bd1a68 100644 --- a/README.md +++ b/README.md @@ -133,6 +133,17 @@ GoogleSignIn.configure({ Finally, run `cd ios && pod install` after installing the package. +GoogleSignIn 8 and later includes Swift dependencies that require module maps +when CocoaPods builds them as static libraries. Add this near the top of your +`ios/Podfile`, after the iOS platform declaration: + +```ruby +platform :ios, min_ios_version_supported +use_modular_headers! +``` + +The Expo config plugin adds this declaration automatically. + ## Expo config plugin This package ships an Expo config plugin so you don't have to hand-edit `Info.plist` or `AppDelegate` in Expo projects. **Both React Native CLI and Expo projects are supported** — pick the setup section that matches your project. From 3f0949f2c95b4e45a36bb6761a47dfbe0a7837e8 Mon Sep 17 00:00:00 2001 From: Tomi Alu Date: Wed, 5 Aug 2026 00:36:47 +0100 Subject: [PATCH 3/3] test(plugin): assert that modular headers are enabled --- plugin/src/__tests__/withSocialAuth.test.ts | 35 +++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/plugin/src/__tests__/withSocialAuth.test.ts b/plugin/src/__tests__/withSocialAuth.test.ts index dc90aa8..1516adc 100644 --- a/plugin/src/__tests__/withSocialAuth.test.ts +++ b/plugin/src/__tests__/withSocialAuth.test.ts @@ -1,5 +1,6 @@ import { describe, expect, it } from '@jest/globals'; import { + injectModularHeaders, injectObjCURLHandler, injectSwiftURLHandler, reverseClientId, @@ -106,3 +107,37 @@ describe('injectObjCURLHandler', () => { expect(() => injectObjCURLHandler('// no class here')).toThrow(/@end/); }); }); + +describe('injectModularHeaders', () => { + const PODFILE_FIXTURE = `require 'expo' + +platform :ios, '15.1' + +prepare_react_native_project! +`; + + it('enables modular headers after the platform declaration', () => { + const out = injectModularHeaders(PODFILE_FIXTURE); + expect(out).toContain( + "platform :ios, '15.1'\n" + + '# @thoughtbot/react-native-social-auth: GoogleSignIn 8+ dependencies\n' + + 'use_modular_headers!' + ); + }); + + it('does not add a duplicate declaration', () => { + const once = injectModularHeaders(PODFILE_FIXTURE); + expect(injectModularHeaders(once)).toBe(once); + }); + + it('preserves an existing modular-headers declaration', () => { + const podfile = `${PODFILE_FIXTURE}\nuse_modular_headers!\n`; + expect(injectModularHeaders(podfile)).toBe(podfile); + }); + + it('throws when the platform declaration is missing', () => { + expect(() => injectModularHeaders("require 'expo'\n")).toThrow( + /platform declaration/ + ); + }); +});