From 503a5ffd704dde3a60bbe2215a810dd775a96a4f Mon Sep 17 00:00:00 2001 From: Tomi Alu Date: Fri, 26 Jun 2026 15:43:28 +0100 Subject: [PATCH 1/7] feat(expo): add config plugin for iOS Info.plist and AppDelegate setup 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. --- app.plugin.js | 1 + package.json | 16 +- plugin/src/__tests__/withSocialAuth.test.ts | 98 ++ plugin/src/withSocialAuth.ts | 167 +++ plugin/tsconfig.json | 19 + yarn.lock | 1313 ++++++++++++++++++- 6 files changed, 1604 insertions(+), 10 deletions(-) create mode 100644 app.plugin.js create mode 100644 plugin/src/__tests__/withSocialAuth.test.ts create mode 100644 plugin/src/withSocialAuth.ts create mode 100644 plugin/tsconfig.json diff --git a/app.plugin.js b/app.plugin.js new file mode 100644 index 0000000..8749684 --- /dev/null +++ b/app.plugin.js @@ -0,0 +1 @@ +module.exports = require('./plugin/build/withSocialAuth').default; diff --git a/package.json b/package.json index ba189c0..d5f8b1a 100644 --- a/package.json +++ b/package.json @@ -18,6 +18,8 @@ "android", "ios", "cpp", + "plugin/build", + "app.plugin.js", "*.podspec", "react-native.config.js", "!ios/build", @@ -33,8 +35,9 @@ ], "scripts": { "example": "yarn workspace @thoughtbot/react-native-social-auth-example", - "clean": "del-cli lib", - "prepare": "bob build", + "clean": "del-cli lib plugin/build", + "prepare": "bob build && yarn build:plugin", + "build:plugin": "tsc --project plugin/tsconfig.json", "typecheck": "tsc", "test": "jest", "release": "release-it --only-version", @@ -68,12 +71,14 @@ "@eslint/compat": "^2.0.3", "@eslint/eslintrc": "^3.3.5", "@eslint/js": "^10.0.1", + "@expo/config-plugins": "^9", "@jest/globals": "^30.0.0", "@react-native/babel-preset": "0.85.0", "@react-native/eslint-config": "0.85.0", "@react-native/jest-preset": "0.85.0", "@release-it/conventional-changelog": "^10.0.6", "@testing-library/react-native": "^13.3", + "@types/node": "^26.0.1", "@types/react": "^19.2.0", "@types/react-test-renderer": "^19", "commitlint": "^20.5.0", @@ -82,6 +87,7 @@ "eslint-config-prettier": "^10.1.8", "eslint-plugin-ft-flow": "^3.0.11", "eslint-plugin-prettier": "^5.5.5", + "expo": "^56.0.12", "jest": "^30.3.0", "lefthook": "^2.1.4", "prettier": "^3.8.1", @@ -95,10 +101,16 @@ "typescript": "^6.0.2" }, "peerDependencies": { + "@expo/config-plugins": ">=9.0.0", "react": "*", "react-native": "*", "react-native-svg": ">=13.0.0" }, + "peerDependenciesMeta": { + "@expo/config-plugins": { + "optional": true + } + }, "workspaces": [ "example" ], diff --git a/plugin/src/__tests__/withSocialAuth.test.ts b/plugin/src/__tests__/withSocialAuth.test.ts new file mode 100644 index 0000000..a6a1935 --- /dev/null +++ b/plugin/src/__tests__/withSocialAuth.test.ts @@ -0,0 +1,98 @@ +import { describe, expect, it } from '@jest/globals'; +import { + injectObjCURLHandler, + injectSwiftURLHandler, + reverseClientId, +} from '../withSocialAuth'; + +describe('reverseClientId', () => { + it('reverses a valid iOS client ID', () => { + expect(reverseClientId('123456-abc.apps.googleusercontent.com')).toBe( + 'com.googleusercontent.apps.123456-abc' + ); + }); + + it('throws on a Web client ID (missing iOS suffix)', () => { + expect(() => reverseClientId('123456-xyz.example.com')).toThrow( + /must end with "\.apps\.googleusercontent\.com"/ + ); + }); + + it('throws on an empty string', () => { + expect(() => reverseClientId('')).toThrow(); + }); +}); + +const SWIFT_FIXTURE = `import Expo +import ExpoModulesCore + +@UIApplicationMain +public class AppDelegate: ExpoAppDelegate { + public override func application( + _ application: UIApplication, + didFinishLaunchingWithOptions launchOptions: ... + ) -> Bool { + return super.application(application, didFinishLaunchingWithOptions: launchOptions) + } +} +`; + +describe('injectSwiftURLHandler', () => { + it('adds the import and URL handler override', () => { + const out = injectSwiftURLHandler(SWIFT_FIXTURE); + expect(out).toContain('import react_native_social_auth'); + expect(out).toContain('GoogleSignIn.handleURL(url)'); + expect(out).toContain( + 'public override func application(\n _ app: UIApplication' + ); + }); + + it('places the override inside the AppDelegate class (before the closing brace)', () => { + const out = injectSwiftURLHandler(SWIFT_FIXTURE); + const handlerIndex = out.indexOf('GoogleSignIn.handleURL'); + const lastBraceIndex = out.lastIndexOf('}'); + expect(handlerIndex).toBeLessThan(lastBraceIndex); + }); + + it('throws if the closing brace cannot be located', () => { + expect(() => injectSwiftURLHandler('// no class here')).toThrow( + /closing brace/ + ); + }); +}); + +const OBJC_FIXTURE = `#import "AppDelegate.h" +#import + +@implementation AppDelegate + +- (BOOL)application:(UIApplication *)application + didFinishLaunchingWithOptions:(NSDictionary *)launchOptions +{ + return [super application:application didFinishLaunchingWithOptions:launchOptions]; +} + +@end +`; + +describe('injectObjCURLHandler', () => { + it('adds the import and openURL method', () => { + const out = injectObjCURLHandler(OBJC_FIXTURE); + expect(out).toContain('#import '); + expect(out).toContain('[GoogleSignIn handleURL:url]'); + expect(out).toContain( + '- (BOOL)application:(UIApplication *)application\n openURL:(NSURL *)url' + ); + }); + + it('places the method before @end', () => { + const out = injectObjCURLHandler(OBJC_FIXTURE); + const handlerIndex = out.indexOf('[GoogleSignIn handleURL:url]'); + const endIndex = out.lastIndexOf('@end'); + expect(handlerIndex).toBeLessThan(endIndex); + }); + + it('throws if @end is missing', () => { + expect(() => injectObjCURLHandler('// no class here')).toThrow(/@end/); + }); +}); diff --git a/plugin/src/withSocialAuth.ts b/plugin/src/withSocialAuth.ts new file mode 100644 index 0000000..27ffd4d --- /dev/null +++ b/plugin/src/withSocialAuth.ts @@ -0,0 +1,167 @@ +import { + createRunOncePlugin, + withAppDelegate, + withInfoPlist, +} from '@expo/config-plugins'; +import type { ConfigPlugin } from '@expo/config-plugins'; + +const pkg = require('../../package.json'); + +export type SocialAuthPluginProps = { + /** + * The OAuth 2.0 iOS application client ID from Google Cloud Console + * (format: `*.apps.googleusercontent.com`). Required to register the + * URL scheme that GoogleSignIn-iOS uses for its OAuth callback. + * + * Omit for Android-only setups — the plugin becomes a no-op on iOS. + */ + iosClientId?: string; +}; + +const PLUGIN_NAME = '@thoughtbot/react-native-social-auth'; +const MARKER = '/* @thoughtbot/react-native-social-auth: URL handler */'; + +/** + * Compute the reversed iOS Client ID that GoogleSignIn-iOS expects as a + * `CFBundleURLSchemes` entry. + * + * Example: + * `123-abc.apps.googleusercontent.com` + * → `com.googleusercontent.apps.123-abc` + */ +/** @internal — exported for tests only. */ +export function reverseClientId(iosClientId: string): string { + const suffix = '.apps.googleusercontent.com'; + if (!iosClientId.endsWith(suffix)) { + throw new Error( + `[${PLUGIN_NAME}] iosClientId must end with "${suffix}". Received: "${iosClientId}".` + ); + } + const id = iosClientId.slice(0, -suffix.length); + return `com.googleusercontent.apps.${id}`; +} + +const withGoogleSignInURLScheme: ConfigPlugin<{ reversedClientId: string }> = ( + config, + { reversedClientId } +) => { + return withInfoPlist(config, (config) => { + const urlTypes = (config.modResults.CFBundleURLTypes ??= []); + const alreadyRegistered = urlTypes.some((entry) => + (entry.CFBundleURLSchemes ?? []).includes(reversedClientId) + ); + if (!alreadyRegistered) { + urlTypes.push({ + CFBundleURLSchemes: [reversedClientId], + }); + } + return config; + }); +}; + +const withGoogleSignInAppDelegate: ConfigPlugin = (config) => { + return withAppDelegate(config, (config) => { + const { language, contents } = config.modResults; + + if (contents.includes(MARKER)) { + return config; + } + + if (language === 'swift') { + config.modResults.contents = injectSwiftURLHandler(contents); + } else if (language === 'objcpp' || language === 'objc') { + config.modResults.contents = injectObjCURLHandler(contents); + } else { + throw new Error( + `[${PLUGIN_NAME}] Unknown AppDelegate language "${language}". Expected "swift" or "objcpp".` + ); + } + return config; + }); +}; + +/** @internal — exported for tests only. */ +export function injectSwiftURLHandler(contents: string): string { + const snippet = ` + ${MARKER} + public override func application( + _ app: UIApplication, + open url: URL, + options: [UIApplication.OpenURLOptionsKey: Any] = [:] + ) -> Bool { + if GoogleSignIn.handleURL(url) { return true } + return super.application(app, open: url, options: options) + } +`; + + const importLine = 'import react_native_social_auth'; + let next = contents; + if (!next.includes(importLine)) { + next = next.replace( + /(import ExpoModulesCore|import React|import Expo)/, + `$1\n${importLine}` + ); + } + + // Inject the override before the closing brace of the AppDelegate class. + const classCloseRegex = /\n\}\s*$/; + if (!classCloseRegex.test(next)) { + throw new Error( + `[${PLUGIN_NAME}] Could not locate the AppDelegate class closing brace.` + ); + } + return next.replace(classCloseRegex, `\n${snippet}}\n`); +} + +/** @internal — exported for tests only. */ +export function injectObjCURLHandler(contents: string): string { + const snippet = ` +${MARKER} +- (BOOL)application:(UIApplication *)application + openURL:(NSURL *)url + options:(NSDictionary *)options +{ + if ([GoogleSignIn handleURL:url]) { return YES; } + return [super application:application openURL:url options:options]; +} +`; + + const importLine = '#import '; + let next = contents; + if (!next.includes(importLine)) { + next = next.replace(/(#import "AppDelegate\.h")/, `$1\n${importLine}`); + } + + const endRegex = /\n@end\s*$/; + if (!endRegex.test(next)) { + throw new Error( + `[${PLUGIN_NAME}] Could not locate the AppDelegate's @end directive.` + ); + } + return next.replace(endRegex, `\n${snippet}\n@end\n`); +} + +const withSocialAuth: ConfigPlugin = ( + config, + props +) => { + const iosClientId = props?.iosClientId; + + if (!iosClientId) { + console.warn( + `[${PLUGIN_NAME}] No iosClientId provided — skipping iOS configuration. ` + + 'Android consumers can ignore this warning; iOS consumers must pass ' + + '{ iosClientId } in their app config plugin entry.' + ); + return config; + } + + const reversedClientId = reverseClientId(iosClientId); + + config = withGoogleSignInURLScheme(config, { reversedClientId }); + config = withGoogleSignInAppDelegate(config); + + return config; +}; + +export default createRunOncePlugin(withSocialAuth, PLUGIN_NAME, pkg.version); diff --git a/plugin/tsconfig.json b/plugin/tsconfig.json new file mode 100644 index 0000000..a130440 --- /dev/null +++ b/plugin/tsconfig.json @@ -0,0 +1,19 @@ +{ + "compilerOptions": { + "outDir": "build", + "rootDir": "src", + "module": "commonjs", + "moduleResolution": "node10", + "ignoreDeprecations": "6.0", + "target": "ES2020", + "lib": ["ES2020"], + "types": ["node"], + "esModuleInterop": true, + "strict": true, + "skipLibCheck": true, + "declaration": true, + "noEmit": false + }, + "include": ["./src/**/*"], + "exclude": ["**/__tests__/*", "build"] +} diff --git a/yarn.lock b/yarn.lock index 2d73d86..01aca70 100644 --- a/yarn.lock +++ b/yarn.lock @@ -32,6 +32,26 @@ __metadata: languageName: node linkType: hard +"@babel/code-frame@npm:^7.29.7": + version: 7.29.7 + resolution: "@babel/code-frame@npm:7.29.7" + dependencies: + "@babel/helper-validator-identifier": "npm:^7.29.7" + js-tokens: "npm:^4.0.0" + picocolors: "npm:^1.1.1" + checksum: 10c0/169fc2080169a40c1760155eaaaf739bcb882df0bec76a83adbda5493645bc17270a3434b8848c494b1933e96fe1d147370001e3cda09a39f43ae30f08ef2069 + languageName: node + linkType: hard + +"@babel/code-frame@npm:~7.10.4": + version: 7.10.4 + resolution: "@babel/code-frame@npm:7.10.4" + dependencies: + "@babel/highlight": "npm:^7.10.4" + checksum: 10c0/69e0f52986a1f40231d891224f420436629b6678711b68c088e97b7bdba1607aeb5eb9cfb070275c433f0bf43c37c134845db80d1cdbf5ac88a69b0bdcce9402 + languageName: node + linkType: hard + "@babel/compat-data@npm:^7.28.6, @babel/compat-data@npm:^7.29.0": version: 7.29.0 resolution: "@babel/compat-data@npm:7.29.0" @@ -89,6 +109,19 @@ __metadata: languageName: node linkType: hard +"@babel/generator@npm:^7.29.7": + version: 7.29.7 + resolution: "@babel/generator@npm:7.29.7" + dependencies: + "@babel/parser": "npm:^7.29.7" + "@babel/types": "npm:^7.29.7" + "@jridgewell/gen-mapping": "npm:^0.3.12" + "@jridgewell/trace-mapping": "npm:^0.3.28" + jsesc: "npm:^3.0.2" + checksum: 10c0/9bf72b01b5bd0ea5b1288a0e37dbd360bff2f2b1ce73342c0d40fb3db2ec3dc004ada5ffa925c5e12939a416eed59e600d562b8ecd938ce0d27dfd0eb6c6c2b7 + languageName: node + linkType: hard + "@babel/helper-annotate-as-pure@npm:^7.27.1, @babel/helper-annotate-as-pure@npm:^7.27.3": version: 7.27.3 resolution: "@babel/helper-annotate-as-pure@npm:7.27.3" @@ -98,6 +131,15 @@ __metadata: languageName: node linkType: hard +"@babel/helper-annotate-as-pure@npm:^7.29.7": + version: 7.29.7 + resolution: "@babel/helper-annotate-as-pure@npm:7.29.7" + dependencies: + "@babel/types": "npm:^7.29.7" + checksum: 10c0/c56536b52d17632d89d49db2063ed6102f0e3bbadf6a0ccb74e6599d6a77173b644c7fe8c3ef17c7a162709d55b75ee5145ef6db917d16ba7f375fbffcf2e942 + languageName: node + linkType: hard + "@babel/helper-compilation-targets@npm:^7.27.1, @babel/helper-compilation-targets@npm:^7.28.6": version: 7.28.6 resolution: "@babel/helper-compilation-targets@npm:7.28.6" @@ -163,6 +205,13 @@ __metadata: languageName: node linkType: hard +"@babel/helper-globals@npm:^7.29.7": + version: 7.29.7 + resolution: "@babel/helper-globals@npm:7.29.7" + checksum: 10c0/f38417c40b1129a1b2b519ca961b9040c8827d1444fd74068702286b91b77089431dc76b6b9d5c1496e5da2a4f3ad329c6946e688ba3fa0d1d0b3d2b4f34f36a + languageName: node + linkType: hard + "@babel/helper-member-expression-to-functions@npm:^7.28.5": version: 7.28.5 resolution: "@babel/helper-member-expression-to-functions@npm:7.28.5" @@ -183,6 +232,16 @@ __metadata: languageName: node linkType: hard +"@babel/helper-module-imports@npm:^7.29.7": + version: 7.29.7 + resolution: "@babel/helper-module-imports@npm:7.29.7" + dependencies: + "@babel/traverse": "npm:^7.29.7" + "@babel/types": "npm:^7.29.7" + checksum: 10c0/6adf60d97356027413342a092f818d9678c4f5caff716a33e3284b5ae14e47a9e88059d421dde4ee4894691260039a12602c0e7becadc175602194b40dfa345d + languageName: node + linkType: hard + "@babel/helper-module-transforms@npm:^7.27.1, @babel/helper-module-transforms@npm:^7.28.6": version: 7.28.6 resolution: "@babel/helper-module-transforms@npm:7.28.6" @@ -212,6 +271,13 @@ __metadata: languageName: node linkType: hard +"@babel/helper-plugin-utils@npm:^7.29.7": + version: 7.29.7 + resolution: "@babel/helper-plugin-utils@npm:7.29.7" + checksum: 10c0/380477a06133274a2759f9355929cb60a95e8b8fee624a1ae1fa349e1d1645b89daca456f72833f6d1062bffa12ee4271c5bf0cc5a61c0166cdc24c7591e2408 + languageName: node + linkType: hard + "@babel/helper-remap-async-to-generator@npm:^7.27.1": version: 7.27.1 resolution: "@babel/helper-remap-async-to-generator@npm:7.27.1" @@ -255,6 +321,20 @@ __metadata: languageName: node linkType: hard +"@babel/helper-string-parser@npm:^7.29.7": + version: 7.29.7 + resolution: "@babel/helper-string-parser@npm:7.29.7" + checksum: 10c0/194bc0f1716e396d5ffde56ad6119745fb9557662c98611590e5e454906783a4ccb21ce93056b8eb69a4909044834e45d96e50ac695bbe9e3221648fe033c06c + languageName: node + linkType: hard + +"@babel/helper-validator-identifier@npm:^7.25.9, @babel/helper-validator-identifier@npm:^7.29.7": + version: 7.29.7 + resolution: "@babel/helper-validator-identifier@npm:7.29.7" + checksum: 10c0/4795354e7ae0dcafa72de1cd04ec51252dc1498517170beaf019e03effc5b7bf13c6b21a3949a77e07b8125be7f106ed1131350d8ebd4566ae874094a726d62b + languageName: node + linkType: hard + "@babel/helper-validator-identifier@npm:^7.28.5": version: 7.28.5 resolution: "@babel/helper-validator-identifier@npm:7.28.5" @@ -290,6 +370,18 @@ __metadata: languageName: node linkType: hard +"@babel/highlight@npm:^7.10.4": + version: 7.25.9 + resolution: "@babel/highlight@npm:7.25.9" + dependencies: + "@babel/helper-validator-identifier": "npm:^7.25.9" + chalk: "npm:^2.4.2" + js-tokens: "npm:^4.0.0" + picocolors: "npm:^1.0.0" + checksum: 10c0/ae0ed93c151b85a07df42936117fa593ce91563a22dfc8944a90ae7088c9679645c33e00dcd20b081c1979665d65f986241172dae1fc9e5922692fc3ff685a49 + languageName: node + linkType: hard + "@babel/parser@npm:^7.1.0, @babel/parser@npm:^7.14.7, @babel/parser@npm:^7.20.7, @babel/parser@npm:^7.23.9, @babel/parser@npm:^7.24.4, @babel/parser@npm:^7.25.3, @babel/parser@npm:^7.28.6, @babel/parser@npm:^7.29.0": version: 7.29.2 resolution: "@babel/parser@npm:7.29.2" @@ -301,6 +393,17 @@ __metadata: languageName: node linkType: hard +"@babel/parser@npm:^7.29.7": + version: 7.29.7 + resolution: "@babel/parser@npm:7.29.7" + dependencies: + "@babel/types": "npm:^7.29.7" + bin: + parser: ./bin/babel-parser.js + checksum: 10c0/65133038f80b54a714d6027cb77cee3f9a6b5c4c6842ce674301e13947cbcbfa8055e63acaf1b84c085d34226a14425b2c2b97b829e0e226d2e8f1299942a51d + languageName: node + linkType: hard + "@babel/plugin-bugfix-firefox-class-in-computed-class-key@npm:^7.28.5": version: 7.28.5 resolution: "@babel/plugin-bugfix-firefox-class-in-computed-class-key@npm:7.28.5" @@ -536,6 +639,17 @@ __metadata: languageName: node linkType: hard +"@babel/plugin-syntax-jsx@npm:^7.29.7": + version: 7.29.7 + resolution: "@babel/plugin-syntax-jsx@npm:7.29.7" + dependencies: + "@babel/helper-plugin-utils": "npm:^7.29.7" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 10c0/1736000de183538ba8eef34520105508860e48b0c763254ba9158af5e814ed8bbceeedbb4281fbda33de787ae5b3870e92f60c6ae7131e7d322e451d57387896 + languageName: node + linkType: hard + "@babel/plugin-syntax-logical-assignment-operators@npm:^7.10.4": version: 7.10.4 resolution: "@babel/plugin-syntax-logical-assignment-operators@npm:7.10.4" @@ -1182,6 +1296,21 @@ __metadata: languageName: node linkType: hard +"@babel/plugin-transform-react-jsx@npm:^7.28.6": + version: 7.29.7 + resolution: "@babel/plugin-transform-react-jsx@npm:7.29.7" + dependencies: + "@babel/helper-annotate-as-pure": "npm:^7.29.7" + "@babel/helper-module-imports": "npm:^7.29.7" + "@babel/helper-plugin-utils": "npm:^7.29.7" + "@babel/plugin-syntax-jsx": "npm:^7.29.7" + "@babel/types": "npm:^7.29.7" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 10c0/ae6487c3deafcffda8a2c1b1eb77e0b7121630fa1a9646cecd73dbbdd8271532a0f7f0e8c01f69b6d39a36d8d79eb67e2d51031369c9055f18f7d8e70d9b5446 + languageName: node + linkType: hard + "@babel/plugin-transform-react-pure-annotations@npm:^7.27.1": version: 7.27.1 resolution: "@babel/plugin-transform-react-pure-annotations@npm:7.27.1" @@ -1515,6 +1644,17 @@ __metadata: languageName: node linkType: hard +"@babel/template@npm:^7.29.7": + version: 7.29.7 + resolution: "@babel/template@npm:7.29.7" + dependencies: + "@babel/code-frame": "npm:^7.29.7" + "@babel/parser": "npm:^7.29.7" + "@babel/types": "npm:^7.29.7" + checksum: 10c0/8bb7f900dcab0e9e1c5ffbc33ca10e0d26b7b2e2ca804becb73ee771b9c4ed6e2908a4ae4a14c08560febb45d2b6b9a173955e42ad404d05f8b04840a14d9c58 + languageName: node + linkType: hard + "@babel/traverse@npm:^7.25.3, @babel/traverse@npm:^7.27.1, @babel/traverse@npm:^7.28.5, @babel/traverse@npm:^7.28.6, @babel/traverse@npm:^7.29.0": version: 7.29.0 resolution: "@babel/traverse@npm:7.29.0" @@ -1530,6 +1670,21 @@ __metadata: languageName: node linkType: hard +"@babel/traverse@npm:^7.29.7": + version: 7.29.7 + resolution: "@babel/traverse@npm:7.29.7" + dependencies: + "@babel/code-frame": "npm:^7.29.7" + "@babel/generator": "npm:^7.29.7" + "@babel/helper-globals": "npm:^7.29.7" + "@babel/parser": "npm:^7.29.7" + "@babel/template": "npm:^7.29.7" + "@babel/types": "npm:^7.29.7" + debug: "npm:^4.3.1" + checksum: 10c0/e256a1fbdb956555b76f3c285b1e453f6bedec8b3afb61751d99d933efd11c7d79caf5ddf2493570058a9f7deaa1b48324380d7c1aa1443fd9508becbf56331a + languageName: node + linkType: hard + "@babel/types@npm:^7.0.0, @babel/types@npm:^7.20.7, @babel/types@npm:^7.26.0, @babel/types@npm:^7.27.1, @babel/types@npm:^7.27.3, @babel/types@npm:^7.28.2, @babel/types@npm:^7.28.5, @babel/types@npm:^7.28.6, @babel/types@npm:^7.29.0, @babel/types@npm:^7.3.3, @babel/types@npm:^7.4.4": version: 7.29.0 resolution: "@babel/types@npm:7.29.0" @@ -1540,6 +1695,16 @@ __metadata: languageName: node linkType: hard +"@babel/types@npm:^7.29.7": + version: 7.29.7 + resolution: "@babel/types@npm:7.29.7" + dependencies: + "@babel/helper-string-parser": "npm:^7.29.7" + "@babel/helper-validator-identifier": "npm:^7.29.7" + checksum: 10c0/b6623994c69717fa27294f5fa46d59140338e2d86c6c1c13085c84ef7d53086ee357fbf4fe9abe3dd3da75734dc77c4c0df2f90fb29e667558bb3b3fb705e88f + languageName: node + linkType: hard + "@bcoe/v8-coverage@npm:^0.2.3": version: 0.2.3 resolution: "@bcoe/v8-coverage@npm:0.2.3" @@ -1983,6 +2148,82 @@ __metadata: languageName: node linkType: hard +"@expo/cli@npm:^56.1.16": + version: 56.1.16 + resolution: "@expo/cli@npm:56.1.16" + dependencies: + "@expo/code-signing-certificates": "npm:^0.0.6" + "@expo/config": "npm:~56.0.9" + "@expo/config-plugins": "npm:~56.0.9" + "@expo/devcert": "npm:^1.2.1" + "@expo/env": "npm:~2.3.0" + "@expo/image-utils": "npm:^0.10.1" + "@expo/inline-modules": "npm:^0.0.12" + "@expo/json-file": "npm:^10.2.0" + "@expo/log-box": "npm:^56.0.13" + "@expo/metro": "npm:~56.0.0" + "@expo/metro-config": "npm:~56.0.14" + "@expo/metro-file-map": "npm:^56.0.3" + "@expo/osascript": "npm:^2.6.0" + "@expo/package-manager": "npm:^1.12.1" + "@expo/plist": "npm:^0.7.0" + "@expo/prebuild-config": "npm:^56.0.16" + "@expo/require-utils": "npm:^56.1.3" + "@expo/router-server": "npm:^56.0.14" + "@expo/schema-utils": "npm:^56.0.0" + "@expo/spawn-async": "npm:^1.8.0" + "@expo/ws-tunnel": "npm:^2.0.0" + "@expo/xcpretty": "npm:^4.4.4" + "@react-native/dev-middleware": "npm:0.85.3" + accepts: "npm:^1.3.8" + arg: "npm:^5.0.2" + bplist-creator: "npm:0.1.0" + bplist-parser: "npm:^0.3.1" + chalk: "npm:^4.0.0" + ci-info: "npm:^3.3.0" + compression: "npm:^1.7.4" + connect: "npm:^3.7.0" + debug: "npm:^4.3.4" + dnssd-advertise: "npm:^1.1.4" + expo-server: "npm:^56.0.5" + fetch-nodeshim: "npm:^0.4.10" + getenv: "npm:^2.0.0" + glob: "npm:^13.0.0" + lan-network: "npm:^0.2.1" + multitars: "npm:^1.0.0" + node-forge: "npm:^1.3.3" + npm-package-arg: "npm:^11.0.0" + ora: "npm:^3.4.0" + picomatch: "npm:^4.0.4" + pretty-format: "npm:^29.7.0" + progress: "npm:^2.0.3" + prompts: "npm:^2.3.2" + resolve-from: "npm:^5.0.0" + semver: "npm:^7.6.0" + send: "npm:^0.19.0" + slugify: "npm:^1.3.4" + stacktrace-parser: "npm:^0.1.10" + structured-headers: "npm:^0.4.1" + terminal-link: "npm:^2.1.1" + toqr: "npm:^0.1.1" + wrap-ansi: "npm:^7.0.0" + ws: "npm:^8.12.1" + zod: "npm:^3.25.76" + peerDependencies: + expo: "*" + expo-router: "*" + react-native: "*" + peerDependenciesMeta: + expo-router: + optional: true + react-native: + optional: true + bin: + expo-internal: main.js + checksum: 10c0/03728d661991cdcecee7a5902ce701582358046223a48e9fe0cf8a5f5f6773381aae35408e052cdafd270699b3536f9c408a9bafdc8b11bdcc1abeefe5dc77a6 + languageName: node + linkType: hard + "@expo/code-signing-certificates@npm:^0.0.6": version: 0.0.6 resolution: "@expo/code-signing-certificates@npm:0.0.6" @@ -1992,6 +2233,28 @@ __metadata: languageName: node linkType: hard +"@expo/config-plugins@npm:^9": + version: 9.1.7 + resolution: "@expo/config-plugins@npm:9.1.7" + dependencies: + "@expo/config-types": "npm:^53.0.0" + "@expo/json-file": "npm:~9.1.3" + "@expo/plist": "npm:^0.3.3" + "@expo/sdk-runtime-versions": "npm:^1.0.0" + chalk: "npm:^4.1.2" + debug: "npm:^4.3.5" + getenv: "npm:^1.0.0" + glob: "npm:^10.4.2" + resolve-from: "npm:^5.0.0" + semver: "npm:^7.5.4" + slash: "npm:^3.0.0" + slugify: "npm:^1.6.6" + xcode: "npm:^3.0.1" + xml2js: "npm:0.6.0" + checksum: 10c0/fc2bbf909ebe5294ced2a0e4754c2409fa77a3d463c9b7c94973e97143489a62e3b31b20b91fdb2d8719f690b4c431915ce2e0f0f5d6129a21e2b2924d1bb2dd + languageName: node + linkType: hard + "@expo/config-plugins@npm:~55.0.8": version: 55.0.8 resolution: "@expo/config-plugins@npm:55.0.8" @@ -2013,6 +2276,34 @@ __metadata: languageName: node linkType: hard +"@expo/config-plugins@npm:~56.0.8, @expo/config-plugins@npm:~56.0.9": + version: 56.0.9 + resolution: "@expo/config-plugins@npm:56.0.9" + dependencies: + "@expo/config-types": "npm:^56.0.6" + "@expo/json-file": "npm:~10.2.0" + "@expo/plist": "npm:^0.7.0" + "@expo/require-utils": "npm:^56.1.3" + "@expo/sdk-runtime-versions": "npm:^1.0.0" + chalk: "npm:^4.1.2" + debug: "npm:^4.3.5" + getenv: "npm:^2.0.0" + glob: "npm:^13.0.0" + semver: "npm:^7.5.4" + slugify: "npm:^1.6.6" + xcode: "npm:^3.0.1" + xml2js: "npm:0.6.0" + checksum: 10c0/401be0071d0bdc1e86431a8dd2b19dfa117ad04b2c58c583b62a5ab5ebb93be3eed26857bdbec9433cb9f554771dda32ea2b7aa5aabf45b8037e6ce7cd705dee + languageName: node + linkType: hard + +"@expo/config-types@npm:^53.0.0": + version: 53.0.5 + resolution: "@expo/config-types@npm:53.0.5" + checksum: 10c0/a7c96f65327de5608aedaf0669bc95b721323113064bdad3473d6faa07b619100ef1df5811f3fdb5dc50d05610842aec8d6bc1902dd0345d51ba2d520884487d + languageName: node + linkType: hard + "@expo/config-types@npm:^55.0.5": version: 55.0.5 resolution: "@expo/config-types@npm:55.0.5" @@ -2020,6 +2311,13 @@ __metadata: languageName: node linkType: hard +"@expo/config-types@npm:^56.0.5, @expo/config-types@npm:^56.0.6": + version: 56.0.6 + resolution: "@expo/config-types@npm:56.0.6" + checksum: 10c0/fa5d8b6a755a5ffa4ee4a138e7a3273f2f3fb7d1a84c4986ecc804f40656e18da89209cf85f3f93d4b3ca730c1a2688e5dc620a1ffd20dc9781834f3b426853f + languageName: node + linkType: hard + "@expo/config@npm:~55.0.14, @expo/config@npm:~55.0.15": version: 55.0.15 resolution: "@expo/config@npm:55.0.15" @@ -2038,6 +2336,24 @@ __metadata: languageName: node linkType: hard +"@expo/config@npm:~56.0.9": + version: 56.0.9 + resolution: "@expo/config@npm:56.0.9" + dependencies: + "@expo/config-plugins": "npm:~56.0.8" + "@expo/config-types": "npm:^56.0.5" + "@expo/json-file": "npm:^10.2.0" + "@expo/require-utils": "npm:^56.1.3" + deepmerge: "npm:^4.3.1" + getenv: "npm:^2.0.0" + glob: "npm:^13.0.0" + resolve-workspace-root: "npm:^2.0.0" + semver: "npm:^7.6.0" + slugify: "npm:^1.3.4" + checksum: 10c0/ef643ee063229e1cfba67998f2fd63c5e75781110af0bef99e8730e541fe5599cc8616c571d03918f2b21988652d108e6d0116b8a0d0599f21e7988d3e59f9c4 + languageName: node + linkType: hard + "@expo/devcert@npm:^1.2.1": version: 1.2.1 resolution: "@expo/devcert@npm:1.2.1" @@ -2065,6 +2381,23 @@ __metadata: languageName: node linkType: hard +"@expo/devtools@npm:~56.0.2": + version: 56.0.2 + resolution: "@expo/devtools@npm:56.0.2" + dependencies: + chalk: "npm:^4.1.2" + peerDependencies: + react: "*" + react-native: "*" + peerDependenciesMeta: + react: + optional: true + react-native: + optional: true + checksum: 10c0/05455baf5ab1b5213f90c408b42ca38cb7db21fce1b616300072a6b82de14ee1d9cb80023cb6774573abdccbd52a835e04fed06c90b82b4e5ba2958320fb1265 + languageName: node + linkType: hard + "@expo/dom-webview@npm:^55.0.5": version: 55.0.5 resolution: "@expo/dom-webview@npm:55.0.5" @@ -2076,6 +2409,17 @@ __metadata: languageName: node linkType: hard +"@expo/dom-webview@npm:^56.0.5, @expo/dom-webview@npm:~56.0.5": + version: 56.0.5 + resolution: "@expo/dom-webview@npm:56.0.5" + peerDependencies: + expo: "*" + react: "*" + react-native: "*" + checksum: 10c0/0bdd893754586de59ccecac06eb98da203dada8e8a6434c3bb214a3c19f007ab0847d3bd3ec0dd53f1e6e80d64656f4775c654adb883f95b0a0bd8d9266512ef + languageName: node + linkType: hard + "@expo/env@npm:^2.0.11, @expo/env@npm:~2.1.1": version: 2.1.1 resolution: "@expo/env@npm:2.1.1" @@ -2087,6 +2431,35 @@ __metadata: languageName: node linkType: hard +"@expo/env@npm:^2.3.0": + version: 2.4.0 + resolution: "@expo/env@npm:2.4.0" + dependencies: + chalk: "npm:^4.0.0" + debug: "npm:^4.3.4" + getenv: "npm:^2.0.0" + checksum: 10c0/fff6b4eccd03c77508fc57b0d80b77736e272de147346a38bead900f5b8580874568b8ad536af1b56efdc42f0f3a9d505fe738346b9ac2f1beb5e974cd2d67f5 + languageName: node + linkType: hard + +"@expo/env@npm:~2.3.0": + version: 2.3.0 + resolution: "@expo/env@npm:2.3.0" + dependencies: + chalk: "npm:^4.0.0" + debug: "npm:^4.3.4" + getenv: "npm:^2.0.0" + checksum: 10c0/2a930a86a12daa63503ca250dfe8a45fe060f1f9b2e272a0aef83924cb103f7dc0ebbe6ebe6b067ecb369fafdcb7e017bd88bb161b5d54465b8da014fda89f84 + languageName: node + linkType: hard + +"@expo/expo-modules-macros-plugin@npm:0.2.2": + version: 0.2.2 + resolution: "@expo/expo-modules-macros-plugin@npm:0.2.2" + checksum: 10c0/12c5d95d139ac0071f8b60b8454e9d5928fd7ce7f84339674e39e5f2eb8cf63edb0169336f587d4d5f277143e0679705852f9e520c94a0bcd356501ede6fdc58 + languageName: node + linkType: hard + "@expo/fingerprint@npm:0.16.6": version: 0.16.6 resolution: "@expo/fingerprint@npm:0.16.6" @@ -2108,6 +2481,42 @@ __metadata: languageName: node linkType: hard +"@expo/fingerprint@npm:^0.19.4": + version: 0.19.4 + resolution: "@expo/fingerprint@npm:0.19.4" + dependencies: + "@expo/env": "npm:^2.3.0" + "@expo/spawn-async": "npm:^1.8.0" + arg: "npm:^5.0.2" + chalk: "npm:^4.1.2" + debug: "npm:^4.3.4" + getenv: "npm:^2.0.0" + glob: "npm:^13.0.0" + ignore: "npm:^5.3.1" + minimatch: "npm:^10.2.2" + resolve-from: "npm:^5.0.0" + semver: "npm:^7.6.0" + bin: + fingerprint: bin/cli.js + checksum: 10c0/f617e54d7aafbdff2af98c7f9522e3cb7ecd7bb7e645db800df8cc043e087e0083077e511b83081901402cfff83132e5bb6bbdba2c02c2ea5e194581252d6e73 + languageName: node + linkType: hard + +"@expo/image-utils@npm:^0.10.1": + version: 0.10.1 + resolution: "@expo/image-utils@npm:0.10.1" + dependencies: + "@expo/require-utils": "npm:^56.1.3" + "@expo/spawn-async": "npm:^1.8.0" + chalk: "npm:^4.0.0" + getenv: "npm:^2.0.0" + jimp-compact: "npm:0.16.1" + parse-png: "npm:^2.1.0" + semver: "npm:^7.6.0" + checksum: 10c0/3e6a71c370a1dda958599dacdf0406c1f849a21c80c713c3e6b5c11928a7e95b0317828eee3d70990add7f91e8bf33c20c2bc117cf9acf579ed5405c80bea482 + languageName: node + linkType: hard + "@expo/image-utils@npm:^0.8.13": version: 0.8.13 resolution: "@expo/image-utils@npm:0.8.13" @@ -2123,6 +2532,15 @@ __metadata: languageName: node linkType: hard +"@expo/inline-modules@npm:^0.0.12": + version: 0.0.12 + resolution: "@expo/inline-modules@npm:0.0.12" + dependencies: + "@expo/config-plugins": "npm:~56.0.9" + checksum: 10c0/39c37ee86cdfc6cae8c448b2617202fc951c51f930098f29176df68317956190be69d62b29ec6b286fa229d91dc3903dda4e4a06bda8a8cb50f2c0feaab274a7 + languageName: node + linkType: hard + "@expo/json-file@npm:^10.0.13, @expo/json-file@npm:~10.0.13": version: 10.0.13 resolution: "@expo/json-file@npm:10.0.13" @@ -2133,6 +2551,36 @@ __metadata: languageName: node linkType: hard +"@expo/json-file@npm:^10.2.0, @expo/json-file@npm:~10.2.0": + version: 10.2.0 + resolution: "@expo/json-file@npm:10.2.0" + dependencies: + "@babel/code-frame": "npm:^7.20.0" + json5: "npm:^2.2.3" + checksum: 10c0/198058e18dea2f31083c2ae8a6831dddfc8fc01c4cb30020728da04f155a6b600b4219830b6df48195548fa29a450b5b775007ed8430fb8098fd9a1656188ea0 + languageName: node + linkType: hard + +"@expo/json-file@npm:^11.0.0": + version: 11.0.0 + resolution: "@expo/json-file@npm:11.0.0" + dependencies: + "@babel/code-frame": "npm:^7.20.0" + json5: "npm:^2.2.3" + checksum: 10c0/4e040a6763efea8a2589788a1cd2fbadc8818cd5b2197162a300249567f624fd1ad320493fd463cab5ac704fe2a1480b85eca477e7c3226415181e48bd3d6a88 + languageName: node + linkType: hard + +"@expo/json-file@npm:~9.1.3": + version: 9.1.5 + resolution: "@expo/json-file@npm:9.1.5" + dependencies: + "@babel/code-frame": "npm:~7.10.4" + json5: "npm:^2.2.3" + checksum: 10c0/989e3aa6d3e31a7f499d7979c6062694f2bc1fe1a4bc81b64aff74c39f27ed5f52098861897236cdc26b86186062560f3191814a2e8ff5b821a74a71d617f135 + languageName: node + linkType: hard + "@expo/local-build-cache-provider@npm:55.0.11": version: 55.0.11 resolution: "@expo/local-build-cache-provider@npm:55.0.11" @@ -2143,6 +2591,16 @@ __metadata: languageName: node linkType: hard +"@expo/local-build-cache-provider@npm:^56.0.8": + version: 56.0.8 + resolution: "@expo/local-build-cache-provider@npm:56.0.8" + dependencies: + "@expo/config": "npm:~56.0.9" + chalk: "npm:^4.1.2" + checksum: 10c0/8be8c2f79c7c4a8138c665322faf66df61f46d472d24ed1a071c36deced1cfc67e9127e370947efec1ab4ed9d24cd50d693fcadca7f123f9517d25bcfa0550a1 + languageName: node + linkType: hard + "@expo/log-box@npm:55.0.10": version: 55.0.10 resolution: "@expo/log-box@npm:55.0.10" @@ -2159,6 +2617,22 @@ __metadata: languageName: node linkType: hard +"@expo/log-box@npm:^56.0.13": + version: 56.0.13 + resolution: "@expo/log-box@npm:56.0.13" + dependencies: + "@expo/dom-webview": "npm:^56.0.5" + anser: "npm:^1.4.9" + stacktrace-parser: "npm:^0.1.10" + peerDependencies: + "@expo/dom-webview": ^56.0.5 + expo: "*" + react: "*" + react-native: "*" + checksum: 10c0/af5908660c1696e0e0028cd50cd06509cdc34b89d6b48aa120cc2971a0246e79bcc98c5523f637da1d2c5bac8ae15b165189c470d159477e196bbecd28869f06 + languageName: node + linkType: hard + "@expo/metro-config@npm:55.0.16, @expo/metro-config@npm:~55.0.16": version: 55.0.16 resolution: "@expo/metro-config@npm:55.0.16" @@ -2191,6 +2665,56 @@ __metadata: languageName: node linkType: hard +"@expo/metro-config@npm:~56.0.14": + version: 56.0.14 + resolution: "@expo/metro-config@npm:56.0.14" + dependencies: + "@babel/code-frame": "npm:^7.20.0" + "@babel/core": "npm:^7.20.0" + "@babel/generator": "npm:^7.20.5" + "@expo/config": "npm:~56.0.9" + "@expo/env": "npm:~2.3.0" + "@expo/json-file": "npm:~10.2.0" + "@expo/metro": "npm:~56.0.0" + "@expo/require-utils": "npm:^56.1.3" + "@expo/spawn-async": "npm:^1.8.0" + "@jridgewell/gen-mapping": "npm:^0.3.13" + "@jridgewell/remapping": "npm:^2.3.5" + "@jridgewell/sourcemap-codec": "npm:^1.5.5" + browserslist: "npm:^4.25.0" + chalk: "npm:^4.1.0" + debug: "npm:^4.3.2" + getenv: "npm:^2.0.0" + glob: "npm:^13.0.0" + hermes-parser: "npm:^0.33.3" + jsc-safe-url: "npm:^0.2.4" + lightningcss: "npm:^1.30.1" + picomatch: "npm:^4.0.4" + postcss: "npm:^8.5.14" + resolve-from: "npm:^5.0.0" + peerDependencies: + expo: "*" + peerDependenciesMeta: + expo: + optional: true + checksum: 10c0/3abbcd28d746be0afd21dfbf9be21ecea8471fded8df98bd381bf16c555c21a11617deda38b2586856a09eec1dd9f5edcea04a24ddcf7fca734fd3da1373e9db + languageName: node + linkType: hard + +"@expo/metro-file-map@npm:^56.0.3": + version: 56.0.3 + resolution: "@expo/metro-file-map@npm:56.0.3" + dependencies: + debug: "npm:^4.3.4" + fb-watchman: "npm:^2.0.2" + invariant: "npm:^2.2.4" + jest-worker: "npm:^29.7.0" + micromatch: "npm:^4.0.4" + walker: "npm:^1.0.8" + checksum: 10c0/457e751c7a2824788494dc456579b6badde852c1ebc22a37231f5f6caf543e51155c276b6283ffd751e430e7300847cd8c85c7cc5e630469b09513ead4d97e9a + languageName: node + linkType: hard + "@expo/metro-runtime@npm:~55.0.9": version: 55.0.9 resolution: "@expo/metro-runtime@npm:55.0.9" @@ -2234,6 +2758,28 @@ __metadata: languageName: node linkType: hard +"@expo/metro@npm:~56.0.0": + version: 56.0.0 + resolution: "@expo/metro@npm:56.0.0" + dependencies: + metro: "npm:0.84.4" + metro-babel-transformer: "npm:0.84.4" + metro-cache: "npm:0.84.4" + metro-cache-key: "npm:0.84.4" + metro-config: "npm:0.84.4" + metro-core: "npm:0.84.4" + metro-file-map: "npm:0.84.4" + metro-minify-terser: "npm:0.84.4" + metro-resolver: "npm:0.84.4" + metro-runtime: "npm:0.84.4" + metro-source-map: "npm:0.84.4" + metro-symbolicate: "npm:0.84.4" + metro-transform-plugins: "npm:0.84.4" + metro-transform-worker: "npm:0.84.4" + checksum: 10c0/51f647dfce71a45ac0092ae06826be91ed05000eb96390c79499c407678121ee9fed1d807d00356e4636020801a42395ef32d316c997fad34806207145d9e9d1 + languageName: node + linkType: hard + "@expo/osascript@npm:^2.4.2": version: 2.4.2 resolution: "@expo/osascript@npm:2.4.2" @@ -2243,6 +2789,15 @@ __metadata: languageName: node linkType: hard +"@expo/osascript@npm:^2.6.0": + version: 2.7.0 + resolution: "@expo/osascript@npm:2.7.0" + dependencies: + "@expo/spawn-async": "npm:^1.8.0" + checksum: 10c0/38265bfe01f94b9d0193df5eb5d8ed2e1efecfd615960bd7b433827711fa5cfc9d30832e2de74121da9dcfff5aabfc600c2d71da2422724ccea4a5b85055a64b + languageName: node + linkType: hard + "@expo/package-manager@npm:^1.10.4": version: 1.10.4 resolution: "@expo/package-manager@npm:1.10.4" @@ -2257,6 +2812,31 @@ __metadata: languageName: node linkType: hard +"@expo/package-manager@npm:^1.12.1": + version: 1.13.0 + resolution: "@expo/package-manager@npm:1.13.0" + dependencies: + "@expo/json-file": "npm:^11.0.0" + "@expo/spawn-async": "npm:^1.8.0" + chalk: "npm:^4.0.0" + npm-package-arg: "npm:^11.0.0" + ora: "npm:^3.4.0" + resolve-workspace-root: "npm:^2.0.0" + checksum: 10c0/8a2256558a2a6c9053221e31246ad487a95d7addf53d05ba71e7437f75201e00ccbdf4a8e52d8e21ecce3aa7b5dfe19587244875dd93b1062ca42d9c26a90efa + languageName: node + linkType: hard + +"@expo/plist@npm:^0.3.3": + version: 0.3.5 + resolution: "@expo/plist@npm:0.3.5" + dependencies: + "@xmldom/xmldom": "npm:^0.8.8" + base64-js: "npm:^1.2.3" + xmlbuilder: "npm:^15.1.1" + checksum: 10c0/d0cde0024b6363f3c96ac186a59795d7c7655986407623324083261ea7e8dcaa7014f385baa1a70422765299eb6d828515ebf0d40590caf34f81997288b74cc1 + languageName: node + linkType: hard + "@expo/plist@npm:^0.5.2": version: 0.5.2 resolution: "@expo/plist@npm:0.5.2" @@ -2268,6 +2848,17 @@ __metadata: languageName: node linkType: hard +"@expo/plist@npm:^0.7.0": + version: 0.7.0 + resolution: "@expo/plist@npm:0.7.0" + dependencies: + "@xmldom/xmldom": "npm:^0.8.8" + base64-js: "npm:^1.5.1" + xmlbuilder: "npm:^15.1.1" + checksum: 10c0/b0d3df057f9a388a761a9261381d55e86ad0935ca15d32bd78da536c803bfc9334c2381fdced99f086e76f5d675535101bfb652d9a79a39c10b0c764c140dcc9 + languageName: node + linkType: hard + "@expo/prebuild-config@npm:^55.0.15": version: 55.0.15 resolution: "@expo/prebuild-config@npm:55.0.15" @@ -2288,6 +2879,24 @@ __metadata: languageName: node linkType: hard +"@expo/prebuild-config@npm:^56.0.16": + version: 56.0.16 + resolution: "@expo/prebuild-config@npm:56.0.16" + dependencies: + "@expo/config": "npm:~56.0.9" + "@expo/config-plugins": "npm:~56.0.9" + "@expo/config-types": "npm:^56.0.6" + "@expo/image-utils": "npm:^0.10.1" + "@expo/json-file": "npm:^10.2.0" + "@react-native/normalize-colors": "npm:0.85.3" + debug: "npm:^4.3.1" + expo-modules-autolinking: "npm:~56.0.16" + resolve-from: "npm:^5.0.0" + semver: "npm:^7.6.0" + checksum: 10c0/8c0a7e2645459022608793299c03a918ee834f3d336c5949912dbbb0bf90391383e2826804dd11b95a7144de2c973284ecbefff4b0d13fbd105a70031dba33e8 + languageName: node + linkType: hard + "@expo/require-utils@npm:^55.0.4": version: 55.0.4 resolution: "@expo/require-utils@npm:55.0.4" @@ -2304,6 +2913,22 @@ __metadata: languageName: node linkType: hard +"@expo/require-utils@npm:^56.1.3": + version: 56.1.3 + resolution: "@expo/require-utils@npm:56.1.3" + dependencies: + "@babel/code-frame": "npm:^7.20.0" + "@babel/core": "npm:^7.25.2" + "@babel/plugin-transform-modules-commonjs": "npm:^7.24.8" + peerDependencies: + typescript: ^5.0.0 || ^5.0.0-0 || ^6.0.0 + peerDependenciesMeta: + typescript: + optional: true + checksum: 10c0/b0fc61db4e45507508bf01524f42770a5bf1f53fab9b244a7dc6c9d8acce0e912940d9945716b8f0c747a07262d34128150c78d00bbe996b2efc5d522c45d874 + languageName: node + linkType: hard + "@expo/router-server@npm:^55.0.14": version: 55.0.14 resolution: "@expo/router-server@npm:55.0.14" @@ -2332,6 +2957,34 @@ __metadata: languageName: node linkType: hard +"@expo/router-server@npm:^56.0.14": + version: 56.0.14 + resolution: "@expo/router-server@npm:56.0.14" + dependencies: + debug: "npm:^4.3.4" + peerDependencies: + "@expo/metro-runtime": ^56.0.15 + expo: "*" + expo-constants: ^56.0.18 + expo-font: ^56.0.6 + expo-router: "*" + expo-server: ^56.0.5 + react: "*" + react-dom: "*" + react-server-dom-webpack: ~19.0.1 || ~19.1.2 || ~19.2.1 + peerDependenciesMeta: + "@expo/metro-runtime": + optional: true + expo-router: + optional: true + react-dom: + optional: true + react-server-dom-webpack: + optional: true + checksum: 10c0/c012de8d9fd595a361ea497738e3d33c24cf4adad82cec3f77054de7b996c102a72b9a6e471fa00454dcc94dc3e13d9e04a97a6f8e9ada30aac1c25cb726260a + languageName: node + linkType: hard + "@expo/schema-utils@npm:^55.0.3": version: 55.0.3 resolution: "@expo/schema-utils@npm:55.0.3" @@ -2339,6 +2992,13 @@ __metadata: languageName: node linkType: hard +"@expo/schema-utils@npm:^56.0.0": + version: 56.0.1 + resolution: "@expo/schema-utils@npm:56.0.1" + checksum: 10c0/8d6b2c76a754f64ae7f10ff417ab11ee64e6e665d34f13a6428ee86b1657cae5c0f40811b41c9716bd5e5f87461d403a08c915cb1c169408031e3c244184980d + languageName: node + linkType: hard + "@expo/sdk-runtime-versions@npm:^1.0.0": version: 1.0.0 resolution: "@expo/sdk-runtime-versions@npm:1.0.0" @@ -2355,6 +3015,15 @@ __metadata: languageName: node linkType: hard +"@expo/spawn-async@npm:^1.8.0": + version: 1.8.0 + resolution: "@expo/spawn-async@npm:1.8.0" + dependencies: + cross-spawn: "npm:^7.0.6" + checksum: 10c0/08d3c63f9cc097ce9c8cf6850ca482fd7999a6fddc4cb38a3a9915a1662cb674fe7353de2eb3c693728542bf57db732ae433e82b2d698be141d07cea3092ebf3 + languageName: node + linkType: hard + "@expo/sudo-prompt@npm:^9.3.1": version: 9.3.2 resolution: "@expo/sudo-prompt@npm:9.3.2" @@ -2380,6 +3049,15 @@ __metadata: languageName: node linkType: hard +"@expo/ws-tunnel@npm:^2.0.0": + version: 2.0.0 + resolution: "@expo/ws-tunnel@npm:2.0.0" + peerDependencies: + ws: ^8.0.0 + checksum: 10c0/5668ffcb3525f98339f1eac579267483771788f98a216ecf6d4c4a106c62ed4e4501ab64ded530a14b865f1b014bb7631dd2c243b08b91e425b422cfee9d0fdf + languageName: node + linkType: hard + "@expo/xcpretty@npm:^4.4.0": version: 4.4.3 resolution: "@expo/xcpretty@npm:4.4.3" @@ -2393,6 +3071,19 @@ __metadata: languageName: node linkType: hard +"@expo/xcpretty@npm:^4.4.4": + version: 4.4.4 + resolution: "@expo/xcpretty@npm:4.4.4" + dependencies: + "@babel/code-frame": "npm:^7.20.0" + chalk: "npm:^4.1.0" + js-yaml: "npm:^4.1.0" + bin: + excpretty: build/cli.js + checksum: 10c0/cd555ad49438dee2cc3f2950ecbef3048f7169bbdadc8db169cfcddaad13668fee6377c010624ed4079dc439c46d6023d2551da403a2070deec000bc864e8dd8 + languageName: node + linkType: hard + "@gar/promise-retry@npm:^1.0.0": version: 1.0.3 resolution: "@gar/promise-retry@npm:1.0.3" @@ -3089,7 +3780,7 @@ __metadata: languageName: node linkType: hard -"@jridgewell/gen-mapping@npm:^0.3.12, @jridgewell/gen-mapping@npm:^0.3.5": +"@jridgewell/gen-mapping@npm:^0.3.12, @jridgewell/gen-mapping@npm:^0.3.13, @jridgewell/gen-mapping@npm:^0.3.5": version: 0.3.13 resolution: "@jridgewell/gen-mapping@npm:0.3.13" dependencies: @@ -3126,7 +3817,7 @@ __metadata: languageName: node linkType: hard -"@jridgewell/sourcemap-codec@npm:^1.4.14, @jridgewell/sourcemap-codec@npm:^1.5.0": +"@jridgewell/sourcemap-codec@npm:^1.4.14, @jridgewell/sourcemap-codec@npm:^1.5.0, @jridgewell/sourcemap-codec@npm:^1.5.5": version: 1.5.5 resolution: "@jridgewell/sourcemap-codec@npm:1.5.5" checksum: 10c0/f9e538f302b63c0ebc06eecb1dd9918dd4289ed36147a0ddce35d6ea4d7ebbda243cda7b2213b6a5e1d8087a298d5cf630fb2bd39329cdecb82017023f6081a0 @@ -3401,6 +4092,16 @@ __metadata: languageName: node linkType: hard +"@react-native/babel-plugin-codegen@npm:0.85.3": + version: 0.85.3 + resolution: "@react-native/babel-plugin-codegen@npm:0.85.3" + dependencies: + "@babel/traverse": "npm:^7.29.0" + "@react-native/codegen": "npm:0.85.3" + checksum: 10c0/59f61f5d783ac0a820a84ff45b7700b3c290de32e313e55171fe3bf0234d9836422bc239832d2650f893dc409a63772a50664f9487a8e6f86bc0c3bc88eb7ecd + languageName: node + linkType: hard + "@react-native/babel-preset@npm:0.83.4": version: 0.83.4 resolution: "@react-native/babel-preset@npm:0.83.4" @@ -3533,6 +4234,23 @@ __metadata: languageName: node linkType: hard +"@react-native/codegen@npm:0.85.3": + version: 0.85.3 + resolution: "@react-native/codegen@npm:0.85.3" + dependencies: + "@babel/core": "npm:^7.25.2" + "@babel/parser": "npm:^7.29.0" + hermes-parser: "npm:0.33.3" + invariant: "npm:^2.2.4" + nullthrows: "npm:^1.1.1" + tinyglobby: "npm:^0.2.15" + yargs: "npm:^17.6.2" + peerDependencies: + "@babel/core": "*" + checksum: 10c0/3d6e08564c3436fcbd450c279b6755768ddfa47a534455c3077c222d5aa0a77270682afe933aa8d84bcd952b1a43107d25220d17c83f4f003fd338846a33ea4c + languageName: node + linkType: hard + "@react-native/community-cli-plugin@npm:0.83.4": version: 0.83.4 resolution: "@react-native/community-cli-plugin@npm:0.83.4" @@ -3563,6 +4281,13 @@ __metadata: languageName: node linkType: hard +"@react-native/debugger-frontend@npm:0.85.3": + version: 0.85.3 + resolution: "@react-native/debugger-frontend@npm:0.85.3" + checksum: 10c0/4e52fc9f10051d0d1ae225ff5c1d0fbcf5e5cc2fdfa13f5985b8578352a3196bd0ad6c7714f62901496be7f231e593308964a469f26575680f558f48e6161a2e + languageName: node + linkType: hard + "@react-native/debugger-shell@npm:0.83.4": version: 0.83.4 resolution: "@react-native/debugger-shell@npm:0.83.4" @@ -3573,6 +4298,17 @@ __metadata: languageName: node linkType: hard +"@react-native/debugger-shell@npm:0.85.3": + version: 0.85.3 + resolution: "@react-native/debugger-shell@npm:0.85.3" + dependencies: + cross-spawn: "npm:^7.0.6" + debug: "npm:^4.4.0" + fb-dotslash: "npm:0.5.8" + checksum: 10c0/2782929d1352c323cc33289fb2b08a8d05b4df5b59af7d588958729f59db966ffd6d73e2df86a66b240f005e23f796829b56978f4a0152a6837e67fd0fae1dd0 + languageName: node + linkType: hard + "@react-native/dev-middleware@npm:0.83.4": version: 0.83.4 resolution: "@react-native/dev-middleware@npm:0.83.4" @@ -3593,6 +4329,26 @@ __metadata: languageName: node linkType: hard +"@react-native/dev-middleware@npm:0.85.3": + version: 0.85.3 + resolution: "@react-native/dev-middleware@npm:0.85.3" + dependencies: + "@isaacs/ttlcache": "npm:^1.4.1" + "@react-native/debugger-frontend": "npm:0.85.3" + "@react-native/debugger-shell": "npm:0.85.3" + chrome-launcher: "npm:^0.15.2" + chromium-edge-launcher: "npm:^0.3.0" + connect: "npm:^3.6.5" + debug: "npm:^4.4.0" + invariant: "npm:^2.2.4" + nullthrows: "npm:^1.1.1" + open: "npm:^7.0.3" + serve-static: "npm:^1.16.2" + ws: "npm:^7.5.10" + checksum: 10c0/6adb5e0ecf933f1936eaf993bc39dd8afd4b20e1f1f6525f2c1428fb9000855a764fa93a4043a1bb1678ec827d9c5fca2d6082a928c3dac49f51ea882d991011 + languageName: node + linkType: hard + "@react-native/eslint-config@npm:0.85.0": version: 0.85.0 resolution: "@react-native/eslint-config@npm:0.85.0" @@ -3666,6 +4422,13 @@ __metadata: languageName: node linkType: hard +"@react-native/normalize-colors@npm:0.85.3": + version: 0.85.3 + resolution: "@react-native/normalize-colors@npm:0.85.3" + checksum: 10c0/343cdbe79e51b0f62e13fcf8620d9c72d7d956d18e9b1b04380a231cff1ec43ff2c54f1ed7a9b975bc23ed4879b96520a7c88aa1c8c7f17a99c32ef8073cf341 + languageName: node + linkType: hard + "@react-native/normalize-colors@npm:^0.74.1": version: 0.74.89 resolution: "@react-native/normalize-colors@npm:0.74.89" @@ -3803,6 +4566,7 @@ __metadata: resolution: "@thoughtbot/react-native-social-auth-example@workspace:example" dependencies: "@expo/metro-runtime": "npm:~55.0.9" + "@thoughtbot/react-native-social-auth": "workspace:^" expo: "npm:~55.0.15" expo-dev-client: "npm:~55.0.27" expo-status-bar: "npm:~55.0.5" @@ -3816,7 +4580,7 @@ __metadata: languageName: unknown linkType: soft -"@thoughtbot/react-native-social-auth@workspace:.": +"@thoughtbot/react-native-social-auth@workspace:., @thoughtbot/react-native-social-auth@workspace:^": version: 0.0.0-use.local resolution: "@thoughtbot/react-native-social-auth@workspace:." dependencies: @@ -3824,12 +4588,14 @@ __metadata: "@eslint/compat": "npm:^2.0.3" "@eslint/eslintrc": "npm:^3.3.5" "@eslint/js": "npm:^10.0.1" + "@expo/config-plugins": "npm:^9" "@jest/globals": "npm:^30.0.0" "@react-native/babel-preset": "npm:0.85.0" "@react-native/eslint-config": "npm:0.85.0" "@react-native/jest-preset": "npm:0.85.0" "@release-it/conventional-changelog": "npm:^10.0.6" "@testing-library/react-native": "npm:^13.3" + "@types/node": "npm:^26.0.1" "@types/react": "npm:^19.2.0" "@types/react-test-renderer": "npm:^19" commitlint: "npm:^20.5.0" @@ -3838,6 +4604,7 @@ __metadata: eslint-config-prettier: "npm:^10.1.8" eslint-plugin-ft-flow: "npm:^3.0.11" eslint-plugin-prettier: "npm:^5.5.5" + expo: "npm:^56.0.12" jest: "npm:^30.3.0" lefthook: "npm:^2.1.4" prettier: "npm:^3.8.1" @@ -3850,9 +4617,13 @@ __metadata: turbo: "npm:^2.8.21" typescript: "npm:^6.0.2" peerDependencies: + "@expo/config-plugins": ">=9.0.0" react: "*" react-native: "*" react-native-svg: ">=13.0.0" + peerDependenciesMeta: + "@expo/config-plugins": + optional: true languageName: unknown linkType: soft @@ -4012,6 +4783,15 @@ __metadata: languageName: node linkType: hard +"@types/node@npm:^26.0.1": + version: 26.0.1 + resolution: "@types/node@npm:26.0.1" + dependencies: + undici-types: "npm:~8.3.0" + checksum: 10c0/31d204333c70124da6bcac7d1f27d8980149fe3f95a8419bfcd19c3e5823705c0e370d71ac34399352e1263b2d5fc41c87af964ec81e5a05a32224d65d8d224e + languageName: node + linkType: hard + "@types/normalize-package-data@npm:^2.4.4": version: 2.4.4 resolution: "@types/normalize-package-data@npm:2.4.4" @@ -4868,7 +5648,7 @@ __metadata: languageName: node linkType: hard -"babel-plugin-syntax-hermes-parser@npm:0.33.3": +"babel-plugin-syntax-hermes-parser@npm:0.33.3, babel-plugin-syntax-hermes-parser@npm:^0.33.3": version: 0.33.3 resolution: "babel-plugin-syntax-hermes-parser@npm:0.33.3" dependencies: @@ -4972,6 +5752,68 @@ __metadata: languageName: node linkType: hard +"babel-preset-expo@npm:~56.0.15": + version: 56.0.15 + resolution: "babel-preset-expo@npm:56.0.15" + dependencies: + "@babel/generator": "npm:^7.20.5" + "@babel/helper-module-imports": "npm:^7.25.9" + "@babel/plugin-proposal-decorators": "npm:^7.12.9" + "@babel/plugin-proposal-export-default-from": "npm:^7.24.7" + "@babel/plugin-syntax-dynamic-import": "npm:^7.8.3" + "@babel/plugin-syntax-export-default-from": "npm:^7.24.7" + "@babel/plugin-syntax-nullish-coalescing-operator": "npm:^7.8.3" + "@babel/plugin-syntax-optional-chaining": "npm:^7.8.3" + "@babel/plugin-transform-async-generator-functions": "npm:^7.25.4" + "@babel/plugin-transform-async-to-generator": "npm:^7.24.7" + "@babel/plugin-transform-block-scoping": "npm:^7.25.0" + "@babel/plugin-transform-class-properties": "npm:^7.25.4" + "@babel/plugin-transform-class-static-block": "npm:^7.27.1" + "@babel/plugin-transform-classes": "npm:^7.25.4" + "@babel/plugin-transform-destructuring": "npm:^7.24.8" + "@babel/plugin-transform-export-namespace-from": "npm:^7.25.9" + "@babel/plugin-transform-flow-strip-types": "npm:^7.25.2" + "@babel/plugin-transform-for-of": "npm:^7.24.7" + "@babel/plugin-transform-logical-assignment-operators": "npm:^7.24.7" + "@babel/plugin-transform-modules-commonjs": "npm:^7.24.8" + "@babel/plugin-transform-named-capturing-groups-regex": "npm:^7.24.7" + "@babel/plugin-transform-nullish-coalescing-operator": "npm:^7.24.7" + "@babel/plugin-transform-object-rest-spread": "npm:^7.24.7" + "@babel/plugin-transform-optional-catch-binding": "npm:^7.24.7" + "@babel/plugin-transform-optional-chaining": "npm:^7.24.8" + "@babel/plugin-transform-parameters": "npm:^7.24.7" + "@babel/plugin-transform-private-methods": "npm:^7.24.7" + "@babel/plugin-transform-private-property-in-object": "npm:^7.24.7" + "@babel/plugin-transform-react-display-name": "npm:^7.24.7" + "@babel/plugin-transform-react-jsx": "npm:^7.28.6" + "@babel/plugin-transform-react-jsx-development": "npm:^7.27.1" + "@babel/plugin-transform-react-pure-annotations": "npm:^7.27.1" + "@babel/plugin-transform-runtime": "npm:^7.24.7" + "@babel/plugin-transform-typescript": "npm:^7.25.2" + "@babel/plugin-transform-unicode-regex": "npm:^7.24.7" + "@babel/preset-typescript": "npm:^7.23.0" + "@react-native/babel-plugin-codegen": "npm:0.85.3" + babel-plugin-react-compiler: "npm:^1.0.0" + babel-plugin-react-native-web: "npm:~0.21.0" + babel-plugin-syntax-hermes-parser: "npm:^0.33.3" + babel-plugin-transform-flow-enums: "npm:^0.0.2" + debug: "npm:^4.3.4" + peerDependencies: + "@babel/runtime": ^7.20.0 + expo: "*" + expo-widgets: ^56.0.18 + react-refresh: ">=0.14.0 <1.0.0" + peerDependenciesMeta: + "@babel/runtime": + optional: true + expo: + optional: true + expo-widgets: + optional: true + checksum: 10c0/b54f3c6e34501f55fabb14c438f6b30277a1c1f46eb4dbc749701992506119b2308e4fbacece5eb1519cd966515d96a0e070f2b32e0f5fc9aab5d69e952aa62b + languageName: node + linkType: hard + "babel-preset-jest@npm:30.3.0": version: 30.3.0 resolution: "babel-preset-jest@npm:30.3.0" @@ -5010,7 +5852,7 @@ __metadata: languageName: node linkType: hard -"base64-js@npm:^1.5.1": +"base64-js@npm:^1.2.3, base64-js@npm:^1.5.1": version: 1.5.1 resolution: "base64-js@npm:1.5.1" checksum: 10c0/f23823513b63173a001030fae4f2dabe283b99a9d324ade3ad3d148e218134676f1ee8568c877cd79ec1c53158dcf2d2ba527a97c606618928ba99dd930102bf @@ -5363,6 +6205,19 @@ __metadata: languageName: node linkType: hard +"chromium-edge-launcher@npm:^0.3.0": + version: 0.3.0 + resolution: "chromium-edge-launcher@npm:0.3.0" + dependencies: + "@types/node": "npm:*" + escape-string-regexp: "npm:^4.0.0" + is-wsl: "npm:^2.2.0" + lighthouse-logger: "npm:^1.0.0" + mkdirp: "npm:^1.0.4" + checksum: 10c0/ad04a75bf53ebed0b7adc5bd133587369b0c2e55c92fe460eb6ccec5efe03c161a7466756173969867a2acbe02dd40449186bd74671dd892520492283d4ff43d + languageName: node + linkType: hard + "ci-info@npm:^2.0.0": version: 2.0.0 resolution: "ci-info@npm:2.0.0" @@ -6890,6 +7745,20 @@ __metadata: languageName: node linkType: hard +"expo-asset@npm:~56.0.17": + version: 56.0.17 + resolution: "expo-asset@npm:56.0.17" + dependencies: + "@expo/image-utils": "npm:^0.10.1" + expo-constants: "npm:~56.0.18" + peerDependencies: + expo: "*" + react: "*" + react-native: "*" + checksum: 10c0/686a7e135551ee0cf330dbee6b666198d4063af8ad80ba9ca56abaed02ddbbcda5469ab71e573c9132ce460bb50fa178248e21948f8162cbaf2c95d68d69205d + languageName: node + linkType: hard + "expo-constants@npm:~55.0.14": version: 55.0.14 resolution: "expo-constants@npm:55.0.14" @@ -6903,6 +7772,18 @@ __metadata: languageName: node linkType: hard +"expo-constants@npm:~56.0.18": + version: 56.0.18 + resolution: "expo-constants@npm:56.0.18" + dependencies: + "@expo/env": "npm:~2.3.0" + peerDependencies: + expo: "*" + react-native: "*" + checksum: 10c0/4a8c35f4eeeb078c0feb3d5b55da403ef1d151a35b9b3a4e17505cedfb7ddd78cc02d670ebc5b7c9fb11d42052fd1b0c143cd0a652d22fa6a3730685b19ca0b2 + languageName: node + linkType: hard + "expo-dev-client@npm:~55.0.27": version: 55.0.27 resolution: "expo-dev-client@npm:55.0.27" @@ -6961,6 +7842,16 @@ __metadata: languageName: node linkType: hard +"expo-file-system@npm:~56.0.8": + version: 56.0.8 + resolution: "expo-file-system@npm:56.0.8" + peerDependencies: + expo: "*" + react-native: "*" + checksum: 10c0/55708fe9599d11fd6a9114875f66eee04d22137c72ce86d018c24c7f44649c274366554e63c354394054048f343750b1790bbe1099ac68191a7688b5bf22dec0 + languageName: node + linkType: hard + "expo-font@npm:~55.0.6": version: 55.0.6 resolution: "expo-font@npm:55.0.6" @@ -6974,6 +7865,19 @@ __metadata: languageName: node linkType: hard +"expo-font@npm:~56.0.7": + version: 56.0.7 + resolution: "expo-font@npm:56.0.7" + dependencies: + fontfaceobserver: "npm:^2.1.0" + peerDependencies: + expo: "*" + react: "*" + react-native: "*" + checksum: 10c0/b54285346a391e2497acec4786742f504e4a96ddf8738f00d2e4415e14ae8c3ea0f7f935b61d130a879983d9d5299f95e1a0f540ccab133ca2d59d36f89033c4 + languageName: node + linkType: hard + "expo-json-utils@npm:~55.0.2": version: 55.0.2 resolution: "expo-json-utils@npm:55.0.2" @@ -6991,6 +7895,16 @@ __metadata: languageName: node linkType: hard +"expo-keep-awake@npm:~56.0.3": + version: 56.0.3 + resolution: "expo-keep-awake@npm:56.0.3" + peerDependencies: + expo: "*" + react: "*" + checksum: 10c0/5137da41b6d45deca54f9bbbfbbb1e1c90b6459d489e0f8ce2cf5090cd5298f56947a5d4a4aec8ebd77c587978ce96f05ef86c8610a6e6b24718dc3ab2282802 + languageName: node + linkType: hard + "expo-manifests@npm:~55.0.15": version: 55.0.15 resolution: "expo-manifests@npm:55.0.15" @@ -7017,6 +7931,20 @@ __metadata: languageName: node linkType: hard +"expo-modules-autolinking@npm:~56.0.16": + version: 56.0.16 + resolution: "expo-modules-autolinking@npm:56.0.16" + dependencies: + "@expo/require-utils": "npm:^56.1.3" + "@expo/spawn-async": "npm:^1.8.0" + chalk: "npm:^4.1.0" + commander: "npm:^7.2.0" + bin: + expo-modules-autolinking: bin/expo-modules-autolinking.js + checksum: 10c0/d5fb7c0d3ad29f30198442e938bce831f9481809bf354949c9bb2eed684426a3e06721919f02e9564ba26925f7cc75770958bdae292b75fafa9b02bd6dde972a + languageName: node + linkType: hard + "expo-modules-core@npm:55.0.22": version: 55.0.22 resolution: "expo-modules-core@npm:55.0.22" @@ -7033,6 +7961,33 @@ __metadata: languageName: node linkType: hard +"expo-modules-core@npm:~56.0.17": + version: 56.0.17 + resolution: "expo-modules-core@npm:56.0.17" + dependencies: + "@expo/expo-modules-macros-plugin": "npm:0.2.2" + expo-modules-jsi: "npm:~56.0.10" + invariant: "npm:^2.2.4" + peerDependencies: + react: "*" + react-native: "*" + react-native-worklets: ^0.7.4 || ^0.8.0 + peerDependenciesMeta: + react-native-worklets: + optional: true + checksum: 10c0/8aee9588f1718c07ea4d27b2abac03f396df92885b52e4e64c8cb65e786253e4c93c51306adf5f09bc52484cffeece09268eb3313dc0c14edf116437c8e737d0 + languageName: node + linkType: hard + +"expo-modules-jsi@npm:~56.0.10": + version: 56.0.10 + resolution: "expo-modules-jsi@npm:56.0.10" + peerDependencies: + react-native: "*" + checksum: 10c0/a99fee08eb9732a8e82d4e7ed7ca7d8dd5f18e4a17460d6322642231abde38f983a6be7b09eb958af33f834b817d14e6f51e517769224a0893ef2562d382486e + languageName: node + linkType: hard + "expo-server@npm:^55.0.7": version: 55.0.7 resolution: "expo-server@npm:55.0.7" @@ -7040,6 +7995,13 @@ __metadata: languageName: node linkType: hard +"expo-server@npm:^56.0.5": + version: 56.0.5 + resolution: "expo-server@npm:56.0.5" + checksum: 10c0/8665db31f2bec4d146f2c484ef652c5b604b7ea7c6454e65efff4742754cf981c4ab027a37901588d1794fc37fbeaac89c6024f92930fc0ebdf133e6fec67e80 + languageName: node + linkType: hard + "expo-status-bar@npm:~55.0.5": version: 55.0.5 resolution: "expo-status-bar@npm:55.0.5" @@ -7061,6 +8023,60 @@ __metadata: languageName: node linkType: hard +"expo@npm:^56.0.12": + version: 56.0.12 + resolution: "expo@npm:56.0.12" + dependencies: + "@babel/runtime": "npm:^7.20.0" + "@expo/cli": "npm:^56.1.16" + "@expo/config": "npm:~56.0.9" + "@expo/config-plugins": "npm:~56.0.9" + "@expo/devtools": "npm:~56.0.2" + "@expo/dom-webview": "npm:~56.0.5" + "@expo/fingerprint": "npm:^0.19.4" + "@expo/local-build-cache-provider": "npm:^56.0.8" + "@expo/log-box": "npm:^56.0.13" + "@expo/metro": "npm:~56.0.0" + "@expo/metro-config": "npm:~56.0.14" + "@ungap/structured-clone": "npm:^1.3.0" + babel-preset-expo: "npm:~56.0.15" + expo-asset: "npm:~56.0.17" + expo-constants: "npm:~56.0.18" + expo-file-system: "npm:~56.0.8" + expo-font: "npm:~56.0.7" + expo-keep-awake: "npm:~56.0.3" + expo-modules-autolinking: "npm:~56.0.16" + expo-modules-core: "npm:~56.0.17" + pretty-format: "npm:^29.7.0" + react-refresh: "npm:^0.14.2" + whatwg-url-minimum: "npm:^0.1.2" + peerDependencies: + "@expo/dom-webview": "*" + "@expo/metro-runtime": "*" + react: "*" + react-dom: "*" + react-native: "*" + react-native-web: "*" + react-native-webview: "*" + peerDependenciesMeta: + "@expo/dom-webview": + optional: true + "@expo/metro-runtime": + optional: true + react-dom: + optional: true + react-native-web: + optional: true + react-native-webview: + optional: true + bin: + expo: bin/cli + expo-modules-autolinking: bin/autolinking + fingerprint: bin/fingerprint + checksum: 10c0/ebe1614f61a2e00656aab57c320a8e319099ad09b2e0ab3d19e7ff1f1fe335f3ae6dfd3af9de883aa7e98a1007e05eb00d7e3edeeaddb57072a5b8de090be789 + languageName: node + linkType: hard + "expo@npm:~55.0.15": version: 55.0.15 resolution: "expo@npm:55.0.15" @@ -7550,6 +8566,13 @@ __metadata: languageName: node linkType: hard +"getenv@npm:^1.0.0": + version: 1.0.0 + resolution: "getenv@npm:1.0.0" + checksum: 10c0/9661c5996c7622e12eab1d23448474ae51dbec6f8862eed903ebaa864dcd332895441c23d962e3ff5c180a9e3dff6cb1f569a115e1447db4acb52af2d880d655 + languageName: node + linkType: hard + "getenv@npm:^2.0.0": version: 2.0.0 resolution: "getenv@npm:2.0.0" @@ -7622,7 +8645,7 @@ __metadata: languageName: node linkType: hard -"glob@npm:^10.5.0": +"glob@npm:^10.4.2, glob@npm:^10.5.0": version: 10.5.0 resolution: "glob@npm:10.5.0" dependencies: @@ -7866,7 +8889,7 @@ __metadata: languageName: node linkType: hard -"hermes-parser@npm:0.33.3": +"hermes-parser@npm:0.33.3, hermes-parser@npm:^0.33.3": version: 0.33.3 resolution: "hermes-parser@npm:0.33.3" dependencies: @@ -10030,6 +11053,19 @@ __metadata: languageName: node linkType: hard +"metro-babel-transformer@npm:0.84.4": + version: 0.84.4 + resolution: "metro-babel-transformer@npm:0.84.4" + dependencies: + "@babel/core": "npm:^7.25.2" + flow-enums-runtime: "npm:^0.0.6" + hermes-parser: "npm:0.35.0" + metro-cache-key: "npm:0.84.4" + nullthrows: "npm:^1.1.1" + checksum: 10c0/d1ac996666334bc1cfe9d399cbf4cd747b675f6f8f758c2317eebcc52bd76046ed864ddb7b270efeb8cf337940a61fb03912e5c859b7cbc54687c2f5c41a9d2a + languageName: node + linkType: hard + "metro-cache-key@npm:0.83.5": version: 0.83.5 resolution: "metro-cache-key@npm:0.83.5" @@ -10048,6 +11084,15 @@ __metadata: languageName: node linkType: hard +"metro-cache-key@npm:0.84.4": + version: 0.84.4 + resolution: "metro-cache-key@npm:0.84.4" + dependencies: + flow-enums-runtime: "npm:^0.0.6" + checksum: 10c0/a82ab6367f11886d960cc8fa1f3aa54f6529fe30c16059c141c3e789084c50838fdd7e1a5528534cd9c11a74c63aa5c6a7461dbfa50e8c449b6141eaf2fd05e0 + languageName: node + linkType: hard + "metro-cache@npm:0.83.5": version: 0.83.5 resolution: "metro-cache@npm:0.83.5" @@ -10072,6 +11117,18 @@ __metadata: languageName: node linkType: hard +"metro-cache@npm:0.84.4": + version: 0.84.4 + resolution: "metro-cache@npm:0.84.4" + dependencies: + exponential-backoff: "npm:^3.1.1" + flow-enums-runtime: "npm:^0.0.6" + https-proxy-agent: "npm:^7.0.5" + metro-core: "npm:0.84.4" + checksum: 10c0/3bf7f3a1f85b4f1af05f4b2c71c78e56fd3262d967ee43f02e9ff6820254063af33a70b6549e3dc5e993a6a0b9df92e9279632ad9a8b1cde2577342f93df45eb + languageName: node + linkType: hard + "metro-config@npm:0.83.5": version: 0.83.5 resolution: "metro-config@npm:0.83.5" @@ -10104,6 +11161,22 @@ __metadata: languageName: node linkType: hard +"metro-config@npm:0.84.4": + version: 0.84.4 + resolution: "metro-config@npm:0.84.4" + dependencies: + connect: "npm:^3.6.5" + flow-enums-runtime: "npm:^0.0.6" + jest-validate: "npm:^29.7.0" + metro: "npm:0.84.4" + metro-cache: "npm:0.84.4" + metro-core: "npm:0.84.4" + metro-runtime: "npm:0.84.4" + yaml: "npm:^2.6.1" + checksum: 10c0/f8aaf7d8cff9b486353b62f4746b0a70f99749bd4061f5ae847524aaedcd9c5a34bf176cbbe12fb33e771e8ed3c1496654b2578fa5ba8b9e4f856f0589744d98 + languageName: node + linkType: hard + "metro-core@npm:0.83.5": version: 0.83.5 resolution: "metro-core@npm:0.83.5" @@ -10126,6 +11199,17 @@ __metadata: languageName: node linkType: hard +"metro-core@npm:0.84.4": + version: 0.84.4 + resolution: "metro-core@npm:0.84.4" + dependencies: + flow-enums-runtime: "npm:^0.0.6" + lodash.throttle: "npm:^4.1.1" + metro-resolver: "npm:0.84.4" + checksum: 10c0/19d859de16b5e082c9c31bed981c579a4e6d31a626c7829b725df9ae0ffb755d0ef7809ba9f8adf22d3921f5ffdd931ed77b21b95ca2ea17895f0c99b3cab831 + languageName: node + linkType: hard + "metro-file-map@npm:0.83.5": version: 0.83.5 resolution: "metro-file-map@npm:0.83.5" @@ -10160,6 +11244,23 @@ __metadata: languageName: node linkType: hard +"metro-file-map@npm:0.84.4": + version: 0.84.4 + resolution: "metro-file-map@npm:0.84.4" + dependencies: + debug: "npm:^4.4.0" + fb-watchman: "npm:^2.0.0" + flow-enums-runtime: "npm:^0.0.6" + graceful-fs: "npm:^4.2.4" + invariant: "npm:^2.2.4" + jest-worker: "npm:^29.7.0" + micromatch: "npm:^4.0.4" + nullthrows: "npm:^1.1.1" + walker: "npm:^1.0.7" + checksum: 10c0/09ca829570d1d6dc5beb0534da8a7f2bfcae5415b0974fd5f58b4a05da95dbafdd47f7dc8dedeb11b6562ee9a92c4d918466d02a05cda6e1eaf2c400cbbe6fb4 + languageName: node + linkType: hard + "metro-minify-terser@npm:0.83.5": version: 0.83.5 resolution: "metro-minify-terser@npm:0.83.5" @@ -10180,6 +11281,16 @@ __metadata: languageName: node linkType: hard +"metro-minify-terser@npm:0.84.4": + version: 0.84.4 + resolution: "metro-minify-terser@npm:0.84.4" + dependencies: + flow-enums-runtime: "npm:^0.0.6" + terser: "npm:^5.15.0" + checksum: 10c0/c9b36c2adb8254c38bdedad9da8bf2b7fae7f45cbd883e590430a5fc9cad808af24dd08a9420925e15733dab886528ad553e3eeb3faffc53d3ad80e7e03e5f6d + languageName: node + linkType: hard + "metro-resolver@npm:0.83.5": version: 0.83.5 resolution: "metro-resolver@npm:0.83.5" @@ -10198,6 +11309,15 @@ __metadata: languageName: node linkType: hard +"metro-resolver@npm:0.84.4": + version: 0.84.4 + resolution: "metro-resolver@npm:0.84.4" + dependencies: + flow-enums-runtime: "npm:^0.0.6" + checksum: 10c0/468334270598222e15cbee32af51a3b5e1f4fa6869794955b95d1134b28a58594e8e3879e841ccf00bbb5cd86c689a4481714d6c6a464931987d5333d2c55f80 + languageName: node + linkType: hard + "metro-runtime@npm:0.83.5": version: 0.83.5 resolution: "metro-runtime@npm:0.83.5" @@ -10218,6 +11338,16 @@ __metadata: languageName: node linkType: hard +"metro-runtime@npm:0.84.4": + version: 0.84.4 + resolution: "metro-runtime@npm:0.84.4" + dependencies: + "@babel/runtime": "npm:^7.25.0" + flow-enums-runtime: "npm:^0.0.6" + checksum: 10c0/e2b2e819027940c6bbd081e5650238d52b6c6d78561cd486b8c10cd1e7fce0213c66fa7f885e37ad5377fcd5726b1c9e473fba6de13938cdf2c966e82968c05f + languageName: node + linkType: hard + "metro-source-map@npm:0.83.5": version: 0.83.5 resolution: "metro-source-map@npm:0.83.5" @@ -10252,6 +11382,23 @@ __metadata: languageName: node linkType: hard +"metro-source-map@npm:0.84.4": + version: 0.84.4 + resolution: "metro-source-map@npm:0.84.4" + dependencies: + "@babel/traverse": "npm:^7.29.0" + "@babel/types": "npm:^7.29.0" + flow-enums-runtime: "npm:^0.0.6" + invariant: "npm:^2.2.4" + metro-symbolicate: "npm:0.84.4" + nullthrows: "npm:^1.1.1" + ob1: "npm:0.84.4" + source-map: "npm:^0.5.6" + vlq: "npm:^1.0.0" + checksum: 10c0/39df4524022e07aa4b4d09dd874a9509eb9e2e1e491e80a35099020347ab6be2407851b026452296aad314b0eb7ecf14f9b6bab96bd7c31d47d8b1eb30279aaf + languageName: node + linkType: hard + "metro-symbolicate@npm:0.83.5": version: 0.83.5 resolution: "metro-symbolicate@npm:0.83.5" @@ -10284,6 +11431,22 @@ __metadata: languageName: node linkType: hard +"metro-symbolicate@npm:0.84.4": + version: 0.84.4 + resolution: "metro-symbolicate@npm:0.84.4" + dependencies: + flow-enums-runtime: "npm:^0.0.6" + invariant: "npm:^2.2.4" + metro-source-map: "npm:0.84.4" + nullthrows: "npm:^1.1.1" + source-map: "npm:^0.5.6" + vlq: "npm:^1.0.0" + bin: + metro-symbolicate: src/index.js + checksum: 10c0/416a9ef694150a8ec708187743b74ab67e0b4fec39c64610b3771b584830117670a62acb9aa824f84a44efbb1cfec07aaf943d1aaf349d977eecf7c72bd8c0bf + languageName: node + linkType: hard + "metro-transform-plugins@npm:0.83.5": version: 0.83.5 resolution: "metro-transform-plugins@npm:0.83.5" @@ -10312,6 +11475,20 @@ __metadata: languageName: node linkType: hard +"metro-transform-plugins@npm:0.84.4": + version: 0.84.4 + resolution: "metro-transform-plugins@npm:0.84.4" + dependencies: + "@babel/core": "npm:^7.25.2" + "@babel/generator": "npm:^7.29.1" + "@babel/template": "npm:^7.28.6" + "@babel/traverse": "npm:^7.29.0" + flow-enums-runtime: "npm:^0.0.6" + nullthrows: "npm:^1.1.1" + checksum: 10c0/7edb0c0d3655e9f5f5fb8bd8221ec297394b8730c959a3245ea81e50da8177ad7782f21696201a0dcb922281efd919e9548d5b819d8338e52d4b130f06333123 + languageName: node + linkType: hard + "metro-transform-worker@npm:0.83.5": version: 0.83.5 resolution: "metro-transform-worker@npm:0.83.5" @@ -10354,6 +11531,27 @@ __metadata: languageName: node linkType: hard +"metro-transform-worker@npm:0.84.4": + version: 0.84.4 + resolution: "metro-transform-worker@npm:0.84.4" + dependencies: + "@babel/core": "npm:^7.25.2" + "@babel/generator": "npm:^7.29.1" + "@babel/parser": "npm:^7.29.0" + "@babel/types": "npm:^7.29.0" + flow-enums-runtime: "npm:^0.0.6" + metro: "npm:0.84.4" + metro-babel-transformer: "npm:0.84.4" + metro-cache: "npm:0.84.4" + metro-cache-key: "npm:0.84.4" + metro-minify-terser: "npm:0.84.4" + metro-source-map: "npm:0.84.4" + metro-transform-plugins: "npm:0.84.4" + nullthrows: "npm:^1.1.1" + checksum: 10c0/95924f9bcaf6df931bba2783f440d8fab29909bdde8cecdcc3bc7603e7de71e51728a34288f045694b616c94216d1fc683493b8a470e074c9c8a7f220aa9f9b5 + languageName: node + linkType: hard + "metro@npm:0.83.5": version: 0.83.5 resolution: "metro@npm:0.83.5" @@ -10454,6 +11652,55 @@ __metadata: languageName: node linkType: hard +"metro@npm:0.84.4": + version: 0.84.4 + resolution: "metro@npm:0.84.4" + dependencies: + "@babel/code-frame": "npm:^7.29.0" + "@babel/core": "npm:^7.25.2" + "@babel/generator": "npm:^7.29.1" + "@babel/parser": "npm:^7.29.0" + "@babel/template": "npm:^7.28.6" + "@babel/traverse": "npm:^7.29.0" + "@babel/types": "npm:^7.29.0" + accepts: "npm:^2.0.0" + ci-info: "npm:^2.0.0" + connect: "npm:^3.6.5" + debug: "npm:^4.4.0" + error-stack-parser: "npm:^2.0.6" + flow-enums-runtime: "npm:^0.0.6" + graceful-fs: "npm:^4.2.4" + hermes-parser: "npm:0.35.0" + image-size: "npm:^1.0.2" + invariant: "npm:^2.2.4" + jest-worker: "npm:^29.7.0" + jsc-safe-url: "npm:^0.2.2" + lodash.throttle: "npm:^4.1.1" + metro-babel-transformer: "npm:0.84.4" + metro-cache: "npm:0.84.4" + metro-cache-key: "npm:0.84.4" + metro-config: "npm:0.84.4" + metro-core: "npm:0.84.4" + metro-file-map: "npm:0.84.4" + metro-resolver: "npm:0.84.4" + metro-runtime: "npm:0.84.4" + metro-source-map: "npm:0.84.4" + metro-symbolicate: "npm:0.84.4" + metro-transform-plugins: "npm:0.84.4" + metro-transform-worker: "npm:0.84.4" + mime-types: "npm:^3.0.1" + nullthrows: "npm:^1.1.1" + serialize-error: "npm:^2.1.0" + source-map: "npm:^0.5.6" + throat: "npm:^5.0.0" + ws: "npm:^7.5.10" + yargs: "npm:^17.6.2" + bin: + metro: src/cli.js + checksum: 10c0/ff92915119db29cd855274f3789d391cba83c50cb92e22d1e9b8c729e7f6d39495e32540a22ca4c6591eea6a847ade49fcfa5faab01b2300227e3f1fc7df359c + languageName: node + linkType: hard + "micromatch@npm:^4.0.4, micromatch@npm:^4.0.8": version: 4.0.8 resolution: "micromatch@npm:4.0.8" @@ -10680,6 +11927,13 @@ __metadata: languageName: node linkType: hard +"multitars@npm:^1.0.0": + version: 1.0.0 + resolution: "multitars@npm:1.0.0" + checksum: 10c0/c3c432ae6c76f802270bfaff63de66ba740d8599503e78cca7c489d43968869509330f68329abd5d3dfc495790c47598fd3994a2cccb68b738d76eba66ae4b04 + languageName: node + linkType: hard + "mute-stream@npm:^2.0.0": version: 2.0.0 resolution: "mute-stream@npm:2.0.0" @@ -10687,6 +11941,15 @@ __metadata: languageName: node linkType: hard +"nanoid@npm:^3.3.12": + version: 3.3.15 + resolution: "nanoid@npm:3.3.15" + bin: + nanoid: bin/nanoid.cjs + checksum: 10c0/e0b12e3a1d361f74150fa4b25631d0ae29f7162dab01a12f0f1be1f53b7a2a219f9b729504e474d4821207d0fe349bd3c97569ab5cf7ec2fff6aa94711956c93 + languageName: node + linkType: hard + "nanoid@npm:^3.3.7": version: 3.3.11 resolution: "nanoid@npm:3.3.11" @@ -10936,6 +12199,15 @@ __metadata: languageName: node linkType: hard +"ob1@npm:0.84.4": + version: 0.84.4 + resolution: "ob1@npm:0.84.4" + dependencies: + flow-enums-runtime: "npm:^0.0.6" + checksum: 10c0/8bf3a3bdc2b27f1b1b60569c31ff2d9d829025f9a1ce7388b5e810242e48672c8d6b24e5972d6e30aef4d84f6894d12b13d0c6c418460d031da1972b96920bba + languageName: node + linkType: hard + "object-assign@npm:^4.1.0, object-assign@npm:^4.1.1": version: 4.1.1 resolution: "object-assign@npm:4.1.1" @@ -11398,7 +12670,7 @@ __metadata: languageName: node linkType: hard -"picocolors@npm:^1.1.1": +"picocolors@npm:^1.0.0, picocolors@npm:^1.1.1": version: 1.1.1 resolution: "picocolors@npm:1.1.1" checksum: 10c0/e2e3e8170ab9d7c7421969adaa7e1b31434f789afb9b3f115f6b96d91945041ac3ceb02e9ec6fe6510ff036bcc0bf91e69a1772edc0b707e12b19c0f2d6bcf58 @@ -11478,6 +12750,17 @@ __metadata: languageName: node linkType: hard +"postcss@npm:^8.5.14": + version: 8.5.15 + resolution: "postcss@npm:8.5.15" + dependencies: + nanoid: "npm:^3.3.12" + picocolors: "npm:^1.1.1" + source-map-js: "npm:^1.2.1" + checksum: 10c0/7f2e63ae22fbe43aace1bf652bd99da4e90737c64194d49e51ddc9cd0f9e51ff2861a7d734379b494deffa03a880a5c65eec70bc29ee9ebaa7136dde3eee8f31 + languageName: node + linkType: hard + "postcss@npm:~8.4.32": version: 8.4.49 resolution: "postcss@npm:8.4.49" @@ -13312,6 +14595,13 @@ __metadata: languageName: node linkType: hard +"undici-types@npm:~8.3.0": + version: 8.3.0 + resolution: "undici-types@npm:8.3.0" + checksum: 10c0/c8aa7e2fbebfce519654dafadc0ece59be888d2ccaf180fb4495da875e7b536d2456345c384069c7e6f3e9c9ab7435f074957da306f142343eee86ff8048855a + languageName: node + linkType: hard + "undici@npm:6.23.0": version: 6.23.0 resolution: "undici@npm:6.23.0" @@ -13586,6 +14876,13 @@ __metadata: languageName: node linkType: hard +"whatwg-url-minimum@npm:^0.1.2": + version: 0.1.2 + resolution: "whatwg-url-minimum@npm:0.1.2" + checksum: 10c0/5437bc4e1f49d89ff58b7565214db4640c4ad5d90de6c61207e0dc766dae9b9894a0ea7b7883b8576524601586705c5dc359681c388d76c18eddb51f50de558f + languageName: node + linkType: hard + "whatwg-url@npm:^5.0.0": version: 5.0.0 resolution: "whatwg-url@npm:5.0.0" From 394ced4966ea6ad4fc7f75ffcc337308e2860b5a Mon Sep 17 00:00:00 2001 From: Tomi Alu Date: Fri, 26 Jun 2026 15:43:42 +0100 Subject: [PATCH 2/7] feat(example): migrate iOS URL scheme to the Expo config plugin 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. --- example/app.json | 19 +++++++++---------- example/package.json | 1 + 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/example/app.json b/example/app.json index 063f5b1..33acda7 100644 --- a/example/app.json +++ b/example/app.json @@ -13,17 +13,16 @@ }, "ios": { "supportsTablet": true, - "bundleIdentifier": "thoughtbot.reactnativesocialauth.example", - "infoPlist": { - "CFBundleURLTypes": [ - { - "CFBundleURLSchemes": [ - "com.googleusercontent.apps.476683722118-27sdo4g5f7n5egip0r3ig7v3m35q9cql" - ] - } - ] - } + "bundleIdentifier": "thoughtbot.reactnativesocialauth.example" }, + "plugins": [ + [ + "@thoughtbot/react-native-social-auth", + { + "iosClientId": "476683722118-27sdo4g5f7n5egip0r3ig7v3m35q9cql.apps.googleusercontent.com" + } + ] + ], "android": { "adaptiveIcon": { "backgroundColor": "#E6F4FE", diff --git a/example/package.json b/example/package.json index 91d0168..1bfb418 100644 --- a/example/package.json +++ b/example/package.json @@ -13,6 +13,7 @@ }, "dependencies": { "@expo/metro-runtime": "~55.0.9", + "@thoughtbot/react-native-social-auth": "workspace:^", "expo": "~55.0.15", "expo-status-bar": "~55.0.5", "react": "19.2.0", From 7563360b865a85353b1f5c47a3f0b56110aa8dae Mon Sep 17 00:00:00 2001 From: Tomi Alu Date: Fri, 26 Jun 2026 15:43:54 +0100 Subject: [PATCH 3/7] docs: document Expo config plugin support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 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. --- CONTRIBUTING.md | 4 +++- README.md | 52 +++++++++++++++++++++++++++++++++++++++++++++++++ ROADMAP.md | 8 ++++---- 3 files changed, 59 insertions(+), 5 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index a886671..bf66d3c 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -92,6 +92,7 @@ The test suite covers: - **JS API tests** (`src/google/__tests__/GoogleSignIn.test.ts`) — the `configure`-then-call contract on the `GoogleSignIn` wrapper, with the native TurboModule mocked. - **Error tests** (`src/google/__tests__/errors.test.ts`) — `GoogleSignInError`, the `GoogleSignInErrorCode` enum, and the `isGoogleSignInError` type guard. - **Component tests** (`src/google/__tests__/GoogleSignInButton.test.tsx`) — accessibility labels, `onPress` / `disabled` behavior, and theme/shape/text variants, using [React Native Testing Library](https://callstack.github.io/react-native-testing-library/). +- **Expo config plugin tests** (`plugin/src/__tests__/withSocialAuth.test.ts`) — `Info.plist` URL scheme reversal and `AppDelegate` URL-handler injection, for both Swift and Objective-C fixtures. `react-native-svg` is mocked via `__mocks__/react-native-svg.js` so the button renders without native bindings during tests. @@ -151,7 +152,8 @@ The `package.json` file contains various scripts for common tasks: - `yarn typecheck`: type-check files with TypeScript. - `yarn lint`: lint files with [ESLint](https://eslint.org/). - `yarn test`: run unit + component tests with [Jest](https://jestjs.io/) and [React Native Testing Library](https://callstack.github.io/react-native-testing-library/). -- `yarn prepare`: build the library to `lib/` with [react-native-builder-bob](https://github.com/callstack/react-native-builder-bob) (also runs automatically before `npm publish`). +- `yarn prepare`: build the library to `lib/` with [react-native-builder-bob](https://github.com/callstack/react-native-builder-bob) and compile the Expo config plugin to `plugin/build/` (also runs automatically before `npm publish`). +- `yarn build:plugin`: compile only the Expo config plugin (faster than `yarn prepare` when iterating on plugin code). - `yarn example start`: start the Metro server for the example app. - `yarn example android`: run the example app on Android. - `yarn example ios`: run the example app on iOS. diff --git a/README.md b/README.md index f1c7d59..84ebd86 100644 --- a/README.md +++ b/README.md @@ -65,6 +65,8 @@ The Web client ID is what your code references for the ID-token audience; each p In addition to the Cloud Console step above, the host app needs two iOS-specific changes. +> **Using Expo?** Skip the manual `Info.plist` and `AppDelegate` edits below — [our config plugin](#expo-config-plugin) handles them during `expo prebuild`. Bare React Native CLI users continue with the manual steps in this section. + ### 1. Register the OAuth URL scheme Google routes the sign-in callback back into your app via a custom URL scheme. Add the reversed iOS Client ID to `Info.plist`: @@ -124,6 +126,56 @@ GoogleSignIn.configure({ Finally, run `cd ios && pod install` after installing the package. +## 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. + +> **Heads up:** Expo Go cannot ship third-party native modules. You must use a [development build](https://docs.expo.dev/develop/development-builds/introduction/) (via `expo-dev-client` and EAS Build) or the bare workflow. + +### Install + +```sh +npx expo install @thoughtbot/react-native-social-auth react-native-svg +``` + +### Add the plugin + +In `app.config.ts` (or `app.json`): + +```ts +export default { + expo: { + // ... + plugins: [ + [ + '@thoughtbot/react-native-social-auth', + { + iosClientId: process.env.EXPO_PUBLIC_GOOGLE_IOS_CLIENT_ID, + }, + ], + ], + }, +}; +``` + +### Plugin props + +| Prop | Type | Required for iOS | Description | +| ------------- | -------- | ---------------- | --------------------------------------------------------------------------------------------------------------------------------- | +| `iosClientId` | `string` | Yes | Your iOS OAuth Client ID (e.g. `123456-abc.apps.googleusercontent.com`). The plugin reverses it and registers the URL scheme. | + +Omit `iosClientId` if you only target Android — the plugin becomes a no-op on iOS and logs a warning. + +### Regenerate native code + +```sh +npx expo prebuild --clean +``` + +This runs the plugin, which writes the reversed iOS Client ID into `Info.plist`'s `CFBundleURLSchemes` and adds the `application(_:open:options:)` URL forwarder to `AppDelegate`. Subsequent prebuilds are idempotent — the plugin won't re-inject if its marker is already present. + +You still call `GoogleSignIn.configure({ webClientId, iosClientId })` from JS at runtime (the plugin handles the native bits; it doesn't replace `configure()`). + ## Quick start ```tsx diff --git a/ROADMAP.md b/ROADMAP.md index 08a3b04..1b9677e 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -64,10 +64,10 @@ ## Phase 6: Expo Support -- [ ] Write an Expo config plugin that handles `Info.plist` URL schemes (iOS) and any Android manifest needs -- [ ] Test in Expo prebuild / development build workflow -- [ ] Document Expo managed workflow limitations (if any) and EAS build setup -- [ ] Add the config plugin to the package's `app.plugin.js` entry +- [x] Write an Expo config plugin that handles `Info.plist` URL schemes and `AppDelegate` URL forwarding (iOS). Android is a no-op — Credential Manager needs no manifest changes. +- [x] Test in Expo prebuild / development build workflow (covered by `plugin/src/__tests__/withSocialAuth.test.ts` + the example app) +- [x] Document Expo managed workflow limitations (Expo Go not supported; dev client / EAS Build required) and the install flow +- [x] Add the config plugin to the package's `app.plugin.js` entry ## Phase 7: Documentation From 4ef58561d1ed7fe9b5e555c08d3b9c68dc8e00a4 Mon Sep 17 00:00:00 2001 From: Tomi Alu Date: Fri, 26 Jun 2026 15:51:42 +0100 Subject: [PATCH 4/7] refactor(expo): rename inner callback parameter to avoid shadowing MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `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/`. --- eslint.config.mjs | 2 +- plugin/src/withSocialAuth.ts | 18 +++++++++--------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/eslint.config.mjs b/eslint.config.mjs index 16b00bb..e1aefbc 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -24,6 +24,6 @@ export default defineConfig([ }, }, { - ignores: ['node_modules/', 'lib/'], + ignores: ['node_modules/', 'lib/', 'plugin/build/'], }, ]); diff --git a/plugin/src/withSocialAuth.ts b/plugin/src/withSocialAuth.ts index 27ffd4d..b47928d 100644 --- a/plugin/src/withSocialAuth.ts +++ b/plugin/src/withSocialAuth.ts @@ -45,8 +45,8 @@ const withGoogleSignInURLScheme: ConfigPlugin<{ reversedClientId: string }> = ( config, { reversedClientId } ) => { - return withInfoPlist(config, (config) => { - const urlTypes = (config.modResults.CFBundleURLTypes ??= []); + return withInfoPlist(config, (mod) => { + const urlTypes = (mod.modResults.CFBundleURLTypes ??= []); const alreadyRegistered = urlTypes.some((entry) => (entry.CFBundleURLSchemes ?? []).includes(reversedClientId) ); @@ -55,28 +55,28 @@ const withGoogleSignInURLScheme: ConfigPlugin<{ reversedClientId: string }> = ( CFBundleURLSchemes: [reversedClientId], }); } - return config; + return mod; }); }; const withGoogleSignInAppDelegate: ConfigPlugin = (config) => { - return withAppDelegate(config, (config) => { - const { language, contents } = config.modResults; + return withAppDelegate(config, (mod) => { + const { language, contents } = mod.modResults; if (contents.includes(MARKER)) { - return config; + return mod; } if (language === 'swift') { - config.modResults.contents = injectSwiftURLHandler(contents); + mod.modResults.contents = injectSwiftURLHandler(contents); } else if (language === 'objcpp' || language === 'objc') { - config.modResults.contents = injectObjCURLHandler(contents); + mod.modResults.contents = injectObjCURLHandler(contents); } else { throw new Error( `[${PLUGIN_NAME}] Unknown AppDelegate language "${language}". Expected "swift" or "objcpp".` ); } - return config; + return mod; }); }; From 4d27968cb049cdcc03cbcb5080abff823ef313d8 Mon Sep 17 00:00:00 2001 From: Tomi Alu Date: Fri, 26 Jun 2026 16:01:20 +0100 Subject: [PATCH 5/7] fix(ci): build Expo config plugin before example prebuild MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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. --- .github/workflows/ci.yml | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index da30014..c7ed236 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -98,6 +98,10 @@ jobs: run: | /bin/bash -c "yes | $ANDROID_HOME/cmdline-tools/latest/bin/sdkmanager --licenses > /dev/null" + - name: Build Expo config plugin + if: env.turbo_cache_hit != 1 + run: yarn build:plugin + - name: Prebuild expo app for Android if: env.turbo_cache_hit != 1 run: | @@ -158,6 +162,10 @@ jobs: with: xcode-version: ${{ env.XCODE_VERSION }} + - name: Build Expo config plugin + if: env.turbo_cache_hit != 1 + run: yarn build:plugin + - name: Prebuild expo app for iOS if: env.turbo_cache_hit != 1 run: | @@ -177,6 +185,9 @@ jobs: - name: Setup uses: ./.github/actions/setup + - name: Build Expo config plugin + run: yarn build:plugin + - name: Build example for Web run: | yarn example build:web From dd94d3f2ea37cfea018162783a79e1d43c31c927 Mon Sep 17 00:00:00 2001 From: Tomi Alu Date: Fri, 26 Jun 2026 16:09:34 +0100 Subject: [PATCH 6/7] fix(expo): expose app.plugin.js through the package's exports field MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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. --- package.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index d5f8b1a..77f6c3b 100644 --- a/package.json +++ b/package.json @@ -10,7 +10,8 @@ "types": "./lib/typescript/src/index.d.ts", "default": "./lib/module/index.js" }, - "./package.json": "./package.json" + "./package.json": "./package.json", + "./app.plugin.js": "./app.plugin.js" }, "files": [ "src", From 51c9e77cbd7dff270e79b42e3507c482d7eec9cf Mon Sep 17 00:00:00 2001 From: Tomi Alu Date: Fri, 26 Jun 2026 16:25:09 +0100 Subject: [PATCH 7/7] fix(expo): inject AppDelegate URL handler that compiles against Expo's base class MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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. --- README.md | 13 ++++----- plugin/src/__tests__/withSocialAuth.test.ts | 30 ++++++++++++++------- plugin/src/withSocialAuth.ts | 12 ++++----- 3 files changed, 33 insertions(+), 22 deletions(-) diff --git a/README.md b/README.md index 84ebd86..637d922 100644 --- a/README.md +++ b/README.md @@ -87,29 +87,30 @@ If you use **Expo**, declare it in `app.json` under `expo.ios.infoPlist.CFBundle ### 2. Forward incoming URLs to the SDK -In your `AppDelegate`, forward `application(_:open:options:)` to `GoogleSignIn.handleURL(_:)`. +In your `AppDelegate`, forward `application(_:open:options:)` to `GIDSignIn.sharedInstance.handle(_:)`. Importing `GoogleSignIn` here pulls in the official GoogleSignIn-iOS SDK module (already a transitive dependency of this package). **Swift:** ```swift -import react_native_social_auth +import GoogleSignIn -func application( +@objc +public func application( _ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey: Any] = [:] ) -> Bool { - return GoogleSignIn.handleURL(url) + return GIDSignIn.sharedInstance.handle(url) } ``` **Objective-C:** ```objc -#import +#import - (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary *)options { - return [GoogleSignIn handleURL:url]; + return [[GIDSignIn sharedInstance] handleURL:url]; } ``` diff --git a/plugin/src/__tests__/withSocialAuth.test.ts b/plugin/src/__tests__/withSocialAuth.test.ts index a6a1935..dc90aa8 100644 --- a/plugin/src/__tests__/withSocialAuth.test.ts +++ b/plugin/src/__tests__/withSocialAuth.test.ts @@ -38,18 +38,26 @@ public class AppDelegate: ExpoAppDelegate { `; describe('injectSwiftURLHandler', () => { - it('adds the import and URL handler override', () => { + it('adds the import and URL handler method', () => { const out = injectSwiftURLHandler(SWIFT_FIXTURE); - expect(out).toContain('import react_native_social_auth'); - expect(out).toContain('GoogleSignIn.handleURL(url)'); - expect(out).toContain( - 'public override func application(\n _ app: UIApplication' + expect(out).toContain('import GoogleSignIn'); + expect(out).toContain('GIDSignIn.sharedInstance.handle(url)'); + expect(out).toContain('public func application(\n _ app: UIApplication'); + expect(out).toContain('@objc'); + }); + + it('does not use `override` on the URL handler (parent class does not declare it)', () => { + const out = injectSwiftURLHandler(SWIFT_FIXTURE); + const markerIndex = out.indexOf( + '/* @thoughtbot/react-native-social-auth: URL handler */' ); + const injected = out.slice(markerIndex); + expect(injected).not.toContain('override'); }); - it('places the override inside the AppDelegate class (before the closing brace)', () => { + it('places the method inside the AppDelegate class (before the closing brace)', () => { const out = injectSwiftURLHandler(SWIFT_FIXTURE); - const handlerIndex = out.indexOf('GoogleSignIn.handleURL'); + const handlerIndex = out.indexOf('GIDSignIn.sharedInstance.handle'); const lastBraceIndex = out.lastIndexOf('}'); expect(handlerIndex).toBeLessThan(lastBraceIndex); }); @@ -78,8 +86,8 @@ const OBJC_FIXTURE = `#import "AppDelegate.h" describe('injectObjCURLHandler', () => { it('adds the import and openURL method', () => { const out = injectObjCURLHandler(OBJC_FIXTURE); - expect(out).toContain('#import '); - expect(out).toContain('[GoogleSignIn handleURL:url]'); + expect(out).toContain('#import '); + expect(out).toContain('[[GIDSignIn sharedInstance] handleURL:url]'); expect(out).toContain( '- (BOOL)application:(UIApplication *)application\n openURL:(NSURL *)url' ); @@ -87,7 +95,9 @@ describe('injectObjCURLHandler', () => { it('places the method before @end', () => { const out = injectObjCURLHandler(OBJC_FIXTURE); - const handlerIndex = out.indexOf('[GoogleSignIn handleURL:url]'); + const handlerIndex = out.indexOf( + '[[GIDSignIn sharedInstance] handleURL:url]' + ); const endIndex = out.lastIndexOf('@end'); expect(handlerIndex).toBeLessThan(endIndex); }); diff --git a/plugin/src/withSocialAuth.ts b/plugin/src/withSocialAuth.ts index b47928d..f2b704d 100644 --- a/plugin/src/withSocialAuth.ts +++ b/plugin/src/withSocialAuth.ts @@ -84,17 +84,17 @@ const withGoogleSignInAppDelegate: ConfigPlugin = (config) => { export function injectSwiftURLHandler(contents: string): string { const snippet = ` ${MARKER} - public override func application( + @objc + public func application( _ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey: Any] = [:] ) -> Bool { - if GoogleSignIn.handleURL(url) { return true } - return super.application(app, open: url, options: options) + return GIDSignIn.sharedInstance.handle(url) } `; - const importLine = 'import react_native_social_auth'; + const importLine = 'import GoogleSignIn'; let next = contents; if (!next.includes(importLine)) { next = next.replace( @@ -121,12 +121,12 @@ ${MARKER} openURL:(NSURL *)url options:(NSDictionary *)options { - if ([GoogleSignIn handleURL:url]) { return YES; } + if ([[GIDSignIn sharedInstance] handleURL:url]) { return YES; } return [super application:application openURL:url options:options]; } `; - const importLine = '#import '; + const importLine = '#import '; let next = contents; if (!next.includes(importLine)) { next = next.replace(/(#import "AppDelegate\.h")/, `$1\n${importLine}`);