feat: create expo config plugin#2
Merged
Merged
Conversation
Replaces the manual app.json edits and AppDelegate snippet copy-paste with a first-party Expo config plugin. Consumers pass `iosClientId` once and the plugin handles the reversed Client ID injection into CFBundleURLSchemes and the application(_:open:options:) URL forwarder during prebuild. `@expo/config-plugins` is declared as an optional peer dependency so bare React Native CLI users don't install Expo tooling they won't use. Supports both Swift and Objective-C AppDelegates. Idempotent via a marker comment.
Replace the hand-rolled `ios.infoPlist.CFBundleURLTypes` block in example/app.json with a plugin entry that derives the reversed iOS Client ID at prebuild time. Demonstrates the canonical Expo pattern and removes the brittle "remember to update the placeholder when the client ID changes" footgun. Declare the library as a workspace dependency so Expo's plugin resolver can locate it in example/node_modules.
- README: add "Using Expo?" callout at the top of iOS Setup pointing bare-RN users to the manual steps below, and a new "Expo config plugin" section covering install, app.config entry, props table, and the Expo Go incompatibility note. - CONTRIBUTING: add `yarn build:plugin` to the script reference and document the plugin test suite location. - ROADMAP: check off Phase 6 (Expo Support) items now that the plugin, example coverage, and docs are all shipped. The existing manual iOS setup snippets stay verbatim — bare React Native CLI users see one extra callout and skip it; their setup section is unchanged.
`withInfoPlist` and `withAppDelegate` pass the modified config to their callback as the same parameter name (`config`) that the outer `ConfigPlugin` already binds. Rename the inner parameter to `mod` (matching its `modResults` field) so the no-shadow lint rule passes without disabling it. Also exclude `plugin/build/` from eslint so the compiled CommonJS output doesn't get linted as TypeScript source — same pattern we already use for `lib/`.
The build-android, build-ios, and build-web jobs all invoke commands that load app.json plugins (`expo prebuild` and the Expo web export), which in turn `require` the compiled plugin at `plugin/build/withSocialAuth.js`. That file is produced by `yarn build:plugin` (or `yarn prepare`), but neither was running in those jobs — only `build-library` runs `yarn prepare`, and yarn 4 does not auto-run the `prepare` lifecycle script during a CI install. Add an explicit `yarn build:plugin` step to each of the three jobs before the Expo command. This is the minimum scope — the lint and test jobs don't need the artifact and stay unchanged.
The `exports` field in package.json restricts which subpaths consumers
can resolve from `require.resolve('@thoughtbot/react-native-social-auth/...')`.
`app.plugin.js` was on disk and in the npm tarball, but was not listed
in the exports map, so Node's resolver refused to find it.
Expo's plugin resolver tries `require.resolve(pkg + '/app.plugin.js')`
first; when that throws, it falls back to importing the package's
`main` entry as a plugin. That fallback fails further down with
`Unexpected token 'typeof'` because the main transitively imports
`react-native`, which ships Flow type annotations that Node cannot
parse — leading to a confusing two-bullet error message.
Adding `./app.plugin.js` to the exports map fixes the original
resolution and prevents the broken fallback from ever firing.
…s base class The plugin previously injected `import react_native_social_auth` and called `GoogleSignIn.handleURL(url)` — both wrong. The CocoaPods module name for this pod is `ReactNativeSocialAuth`, not `react_native_social_auth`, and our wrapper's header is private to the pod, so Swift in the host app can't see it. Two further bugs: the injected method was declared `public override` and called `super.application(...)`, but Expo's `ExpoReactNativeFactoryDelegate` base class does not declare `application(_:open:options:)`, so the override + super-call don't type-check. Switch to calling the GoogleSignIn-iOS SDK directly: import GoogleSignIn // ... @objc public func application(_ app: ..., open url: URL, ...) -> Bool { return GIDSignIn.sharedInstance.handle(url) } The SDK's module name (`GoogleSignIn`) is stable, its public headers are exposed, and dropping `override` + `super` makes the method work on Expo's factory-style AppDelegate. UIKit still dispatches to it through the Obj-C runtime because the class inherits from NSObject and we annotate `@objc`. README's iOS Setup snippet updated to the same shape. Tests assert the new injection format. Verified end-to-end: the example app builds, installs, and launches on iPhone 15 Pro simulator with 0 errors.
c6f48dd to
51c9e77
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Added an expo config plugin to reduce set up steps on Expo