From 909702bfe27720f808e6b30d79462ae7c6f3ebc4 Mon Sep 17 00:00:00 2001 From: wobsoriano Date: Wed, 17 Jun 2026 17:48:08 -0700 Subject: [PATCH] chore(expo): Revert google sign in expo module registration --- .changeset/tall-cameras-laugh.md | 5 + packages/expo/expo-module.config.json | 3 - packages/expo/ios/ClerkGoogleSignIn.podspec | 4 +- packages/expo/ios/ClerkGoogleSignInModule.m | 22 +++ .../expo/ios/ClerkGoogleSignInModule.swift | 164 +++++++++--------- .../expo/src/specs/NativeClerkGoogleSignIn.ts | 18 +- 6 files changed, 118 insertions(+), 98 deletions(-) create mode 100644 .changeset/tall-cameras-laugh.md create mode 100644 packages/expo/ios/ClerkGoogleSignInModule.m diff --git a/.changeset/tall-cameras-laugh.md b/.changeset/tall-cameras-laugh.md new file mode 100644 index 00000000000..29e9ae008f9 --- /dev/null +++ b/.changeset/tall-cameras-laugh.md @@ -0,0 +1,5 @@ +--- +"@clerk/expo": patch +--- + +Revert the iOS Google Sign-In module registration to restore the previous iOS build behavior. diff --git a/packages/expo/expo-module.config.json b/packages/expo/expo-module.config.json index 5b25775946c..5ed082ea351 100644 --- a/packages/expo/expo-module.config.json +++ b/packages/expo/expo-module.config.json @@ -1,8 +1,5 @@ { "platforms": ["apple", "android"], - "apple": { - "modules": ["ClerkGoogleSignInModule"] - }, "android": { "modules": [ "expo.modules.clerk.ClerkExpoModule", diff --git a/packages/expo/ios/ClerkGoogleSignIn.podspec b/packages/expo/ios/ClerkGoogleSignIn.podspec index a3cbcc4c4d0..e356ea70c8c 100644 --- a/packages/expo/ios/ClerkGoogleSignIn.podspec +++ b/packages/expo/ios/ClerkGoogleSignIn.podspec @@ -16,11 +16,9 @@ Pod::Spec.new do |s| s.static_framework = true s.dependency 'GoogleSignIn', '~> 9.0' - s.dependency 'GoogleUtilities' - s.dependency 'RecaptchaInterop' # Only include the Google Sign-In module files - s.source_files = 'ClerkGoogleSignInModule.swift' + s.source_files = 'ClerkGoogleSignInModule.swift', 'ClerkGoogleSignInModule.m' install_modules_dependencies(s) end diff --git a/packages/expo/ios/ClerkGoogleSignInModule.m b/packages/expo/ios/ClerkGoogleSignInModule.m new file mode 100644 index 00000000000..5848d4a17b7 --- /dev/null +++ b/packages/expo/ios/ClerkGoogleSignInModule.m @@ -0,0 +1,22 @@ +#import + +@interface RCT_EXTERN_MODULE(ClerkGoogleSignIn, NSObject) + +RCT_EXTERN_METHOD(configure:(NSDictionary *)params) + +RCT_EXTERN_METHOD(signIn:(NSDictionary *)params + resolve:(RCTPromiseResolveBlock)resolve + reject:(RCTPromiseRejectBlock)reject) + +RCT_EXTERN_METHOD(createAccount:(NSDictionary *)params + resolve:(RCTPromiseResolveBlock)resolve + reject:(RCTPromiseRejectBlock)reject) + +RCT_EXTERN_METHOD(presentExplicitSignIn:(NSDictionary *)params + resolve:(RCTPromiseResolveBlock)resolve + reject:(RCTPromiseRejectBlock)reject) + +RCT_EXTERN_METHOD(signOut:(RCTPromiseResolveBlock)resolve + reject:(RCTPromiseRejectBlock)reject) + +@end diff --git a/packages/expo/ios/ClerkGoogleSignInModule.swift b/packages/expo/ios/ClerkGoogleSignInModule.swift index d9484c50127..9e28b616c07 100644 --- a/packages/expo/ios/ClerkGoogleSignInModule.swift +++ b/packages/expo/ios/ClerkGoogleSignInModule.swift @@ -1,37 +1,23 @@ -import ExpoModulesCore +import React import GoogleSignIn -public class ClerkGoogleSignInModule: Module { - private var clientId: String? - private var hostedDomain: String? - - public func definition() -> ModuleDefinition { - Name("ClerkGoogleSignIn") - - Function("configure") { (params: [String: Any?]) in - self.configure(params) - } - - AsyncFunction("signIn") { (params: [String: Any?]?, promise: Promise) in - self.signIn(params, promise: promise) - }.runOnQueue(.main) - - AsyncFunction("createAccount") { (params: [String: Any?]?, promise: Promise) in - self.createAccount(params, promise: promise) - }.runOnQueue(.main) +@objc(ClerkGoogleSignIn) +class ClerkGoogleSignInModule: NSObject, RCTBridgeModule { - AsyncFunction("presentExplicitSignIn") { (params: [String: Any?]?, promise: Promise) in - self.presentExplicitSignIn(params, promise: promise) - }.runOnQueue(.main) + static func moduleName() -> String! { + return "ClerkGoogleSignIn" + } - AsyncFunction("signOut") { (promise: Promise) in - self.signOut(promise: promise) - }.runOnQueue(.main) + @objc static func requiresMainQueueSetup() -> Bool { + return false } + private var clientId: String? + private var hostedDomain: String? + // MARK: - configure - private func configure(_ params: [String: Any?]) { + @objc func configure(_ params: NSDictionary) { let webClientId = self.nonEmptyClientId(params["webClientId"] as? String) let iosClientId = self.nonEmptyClientId(params["iosClientId"] as? String) self.clientId = iosClientId ?? webClientId @@ -48,91 +34,101 @@ public class ClerkGoogleSignInModule: Module { // MARK: - signIn - private func signIn(_ params: [String: Any?]?, promise: Promise) { + @objc func signIn(_ params: NSDictionary?, + resolve: @escaping RCTPromiseResolveBlock, + reject: @escaping RCTPromiseRejectBlock) { guard self.clientId != nil else { - promise.reject("NOT_CONFIGURED", "Google Sign-In is not configured. Call configure() first.") + reject("NOT_CONFIGURED", "Google Sign-In is not configured. Call configure() first.", nil) return } - guard let presentingVC = self.getPresentingViewController() else { - promise.reject("GOOGLE_SIGN_IN_ERROR", "No presenting view controller available") - return - } + DispatchQueue.main.async { + guard let presentingVC = self.getPresentingViewController() else { + reject("GOOGLE_SIGN_IN_ERROR", "No presenting view controller available", nil) + return + } - let filterByAuthorized = params?["filterByAuthorizedAccounts"] as? Bool ?? false - let hint: String? = filterByAuthorized - ? GIDSignIn.sharedInstance.currentUser?.profile?.email - : nil - let nonce = params?["nonce"] as? String - - GIDSignIn.sharedInstance.signIn( - withPresenting: presentingVC, - hint: hint, - additionalScopes: nil, - nonce: nonce, - completion: { result, error in - self.handleSignInResult(result: result, error: error, promise: promise) + let filterByAuthorized = params?["filterByAuthorizedAccounts"] as? Bool ?? false + let hint: String? = filterByAuthorized + ? GIDSignIn.sharedInstance.currentUser?.profile?.email + : nil + let nonce = params?["nonce"] as? String + + GIDSignIn.sharedInstance.signIn( + withPresenting: presentingVC, + hint: hint, + additionalScopes: nil, + nonce: nonce + ) { result, error in + self.handleSignInResult(result: result, error: error, resolve: resolve, reject: reject) } - ) + } } // MARK: - createAccount - private func createAccount(_ params: [String: Any?]?, promise: Promise) { + @objc func createAccount(_ params: NSDictionary?, + resolve: @escaping RCTPromiseResolveBlock, + reject: @escaping RCTPromiseRejectBlock) { guard self.clientId != nil else { - promise.reject("NOT_CONFIGURED", "Google Sign-In is not configured. Call configure() first.") + reject("NOT_CONFIGURED", "Google Sign-In is not configured. Call configure() first.", nil) return } - guard let presentingVC = self.getPresentingViewController() else { - promise.reject("GOOGLE_SIGN_IN_ERROR", "No presenting view controller available") - return - } + DispatchQueue.main.async { + guard let presentingVC = self.getPresentingViewController() else { + reject("GOOGLE_SIGN_IN_ERROR", "No presenting view controller available", nil) + return + } - let nonce = params?["nonce"] as? String + let nonce = params?["nonce"] as? String - GIDSignIn.sharedInstance.signIn( - withPresenting: presentingVC, - hint: nil, - additionalScopes: nil, - nonce: nonce, - completion: { result, error in - self.handleSignInResult(result: result, error: error, promise: promise) + GIDSignIn.sharedInstance.signIn( + withPresenting: presentingVC, + hint: nil, + additionalScopes: nil, + nonce: nonce + ) { result, error in + self.handleSignInResult(result: result, error: error, resolve: resolve, reject: reject) } - ) + } } // MARK: - presentExplicitSignIn - private func presentExplicitSignIn(_ params: [String: Any?]?, promise: Promise) { + @objc func presentExplicitSignIn(_ params: NSDictionary?, + resolve: @escaping RCTPromiseResolveBlock, + reject: @escaping RCTPromiseRejectBlock) { guard self.clientId != nil else { - promise.reject("NOT_CONFIGURED", "Google Sign-In is not configured. Call configure() first.") + reject("NOT_CONFIGURED", "Google Sign-In is not configured. Call configure() first.", nil) return } - guard let presentingVC = self.getPresentingViewController() else { - promise.reject("GOOGLE_SIGN_IN_ERROR", "No presenting view controller available") - return - } + DispatchQueue.main.async { + guard let presentingVC = self.getPresentingViewController() else { + reject("GOOGLE_SIGN_IN_ERROR", "No presenting view controller available", nil) + return + } - let nonce = params?["nonce"] as? String + let nonce = params?["nonce"] as? String - GIDSignIn.sharedInstance.signIn( - withPresenting: presentingVC, - hint: nil, - additionalScopes: nil, - nonce: nonce, - completion: { result, error in - self.handleSignInResult(result: result, error: error, promise: promise) + GIDSignIn.sharedInstance.signIn( + withPresenting: presentingVC, + hint: nil, + additionalScopes: nil, + nonce: nonce + ) { result, error in + self.handleSignInResult(result: result, error: error, resolve: resolve, reject: reject) } - ) + } } // MARK: - signOut - private func signOut(promise: Promise) { + @objc func signOut(_ resolve: @escaping RCTPromiseResolveBlock, + reject: @escaping RCTPromiseRejectBlock) { GIDSignIn.sharedInstance.signOut() - promise.resolve() + resolve(nil) } // MARK: - Helpers @@ -159,23 +155,25 @@ public class ClerkGoogleSignInModule: Module { return topVC } - private func handleSignInResult(result: GIDSignInResult?, error: Error?, promise: Promise) { + private func handleSignInResult(result: GIDSignInResult?, error: Error?, + resolve: @escaping RCTPromiseResolveBlock, + reject: @escaping RCTPromiseRejectBlock) { if let error = error { let nsError = error as NSError // Check for user cancellation if nsError.domain == kGIDSignInErrorDomain && nsError.code == GIDSignInError.canceled.rawValue { - promise.reject("SIGN_IN_CANCELLED", "User cancelled the sign-in flow") + reject("SIGN_IN_CANCELLED", "User cancelled the sign-in flow", error) return } - promise.reject("GOOGLE_SIGN_IN_ERROR", error.localizedDescription) + reject("GOOGLE_SIGN_IN_ERROR", error.localizedDescription, error) return } guard let result = result, let idToken = result.user.idToken?.tokenString else { - promise.reject("GOOGLE_SIGN_IN_ERROR", "No ID token received") + reject("GOOGLE_SIGN_IN_ERROR", "No ID token received", nil) return } @@ -197,6 +195,6 @@ public class ClerkGoogleSignInModule: Module { ] as [String: Any] ] - promise.resolve(response) + resolve(response) } } diff --git a/packages/expo/src/specs/NativeClerkGoogleSignIn.ts b/packages/expo/src/specs/NativeClerkGoogleSignIn.ts index ee6e5b8c049..7ee7e3cc00b 100644 --- a/packages/expo/src/specs/NativeClerkGoogleSignIn.ts +++ b/packages/expo/src/specs/NativeClerkGoogleSignIn.ts @@ -1,13 +1,13 @@ -import { requireOptionalNativeModule } from 'expo'; +import type { TurboModule } from 'react-native'; +import { TurboModuleRegistry } from 'react-native'; +import type { UnsafeObject } from 'react-native/Libraries/Types/CodegenTypesNamespace'; -type NativeMap = Record; - -interface Spec { - configure(params: NativeMap): void; - signIn(params: NativeMap | null): Promise; - createAccount(params: NativeMap | null): Promise; - presentExplicitSignIn(params: NativeMap | null): Promise; +export interface Spec extends TurboModule { + configure(params: UnsafeObject): void; + signIn(params: UnsafeObject | null): Promise; + createAccount(params: UnsafeObject | null): Promise; + presentExplicitSignIn(params: UnsafeObject | null): Promise; signOut(): Promise; } -export default requireOptionalNativeModule('ClerkGoogleSignIn'); +export default TurboModuleRegistry.get('ClerkGoogleSignIn');