@@ -3,40 +3,63 @@ import { type ConfigPlugin, createRunOncePlugin, withAppBuildGradle, withInfoPli
33import pkg from '../../package.json' ;
44
55/**
6- * Add packaging exclusions to Android app build.gradle to resolve
7- * duplicate META-INF file conflicts from clerk-android dependencies.
6+ * Add packaging exclusions and Kotlin compatibility flags to Android app build.gradle.
7+ *
8+ * - Resolves duplicate META-INF file conflicts from clerk-android dependencies
9+ * - Adds -Xskip-metadata-version-check to kotlinOptions so the app module can
10+ * consume clerk-android (compiled with a newer Kotlin version than Expo/RN ships)
811 */
9- const withClerkAndroidPackaging : ConfigPlugin = config => {
12+ const withClerkAndroidConfig : ConfigPlugin = config => {
1013 return withAppBuildGradle ( config , modConfig => {
1114 let buildGradle = modConfig . modResults . contents ;
1215
13- // Check if exclusion already exists
14- if ( buildGradle . includes ( 'META-INF/versions/9/OSGI-INF/MANIFEST.MF' ) ) {
15- return modConfig ;
16- }
17-
18- // AGP 8+ uses `packaging` DSL, older versions use `packagingOptions`
19- const packagingMatch = buildGradle . match ( / p a c k a g i n g \s * \{ / ) || buildGradle . match ( / p a c k a g i n g O p t i o n s \s * \{ / ) ;
20- if ( packagingMatch ) {
21- const blockName = packagingMatch [ 0 ] . trim ( ) . replace ( / \s * \{ $ / , '' ) ;
22- const resourcesExclude = `${ blockName } {
16+ // --- META-INF exclusion ---
17+ if ( ! buildGradle . includes ( 'META-INF/versions/9/OSGI-INF/MANIFEST.MF' ) ) {
18+ // AGP 8+ uses `packaging` DSL, older versions use `packagingOptions`
19+ const packagingMatch = buildGradle . match ( / p a c k a g i n g \s * \{ / ) || buildGradle . match ( / p a c k a g i n g O p t i o n s \s * \{ / ) ;
20+ if ( packagingMatch ) {
21+ const blockName = packagingMatch [ 0 ] . trim ( ) . replace ( / \s * \{ $ / , '' ) ;
22+ const resourcesExclude = `${ blockName } {
2323 // Clerk Android SDK: exclude duplicate META-INF files
2424 resources {
2525 excludes += ['META-INF/versions/9/OSGI-INF/MANIFEST.MF']
2626 }` ;
2727
28- buildGradle = buildGradle . replace ( new RegExp ( `${ blockName } \\s*\\{` ) , resourcesExclude ) ;
29- modConfig . modResults . contents = buildGradle ;
30- } else {
31- // No packaging block found; append one at the end of the android block
32- const androidBlockEnd = buildGradle . lastIndexOf ( '}' ) ;
33- if ( androidBlockEnd !== - 1 ) {
34- const packagingBlock = `\n packaging {\n resources {\n excludes += ['META-INF/versions/9/OSGI-INF/MANIFEST.MF']\n }\n }\n` ;
35- buildGradle = buildGradle . slice ( 0 , androidBlockEnd ) + packagingBlock + buildGradle . slice ( androidBlockEnd ) ;
36- modConfig . modResults . contents = buildGradle ;
28+ buildGradle = buildGradle . replace ( new RegExp ( `${ blockName } \\s*\\{` ) , resourcesExclude ) ;
29+ } else {
30+ // No packaging block found; append one at the end of the android block
31+ const androidBlockEnd = buildGradle . lastIndexOf ( '}' ) ;
32+ if ( androidBlockEnd !== - 1 ) {
33+ const packagingBlock = `\n packaging {\n resources {\n excludes += ['META-INF/versions/9/OSGI-INF/MANIFEST.MF']\n }\n }\n` ;
34+ buildGradle = buildGradle . slice ( 0 , androidBlockEnd ) + packagingBlock + buildGradle . slice ( androidBlockEnd ) ;
35+ }
36+ }
37+ }
38+
39+ // --- Kotlin metadata version check skip ---
40+ // clerk-android is compiled with a newer Kotlin than Expo/RN ships.
41+ // Without this flag, the app module fails to compile with:
42+ // "Module was compiled with an incompatible version of Kotlin"
43+ if ( ! buildGradle . includes ( '-Xskip-metadata-version-check' ) ) {
44+ const kotlinOptionsMatch = buildGradle . match ( / k o t l i n O p t i o n s \s * \{ / ) ;
45+ if ( kotlinOptionsMatch ) {
46+ buildGradle = buildGradle . replace (
47+ / k o t l i n O p t i o n s \s * \{ / ,
48+ `kotlinOptions {\n // Clerk: allow reading metadata from newer Kotlin versions\n freeCompilerArgs += ['-Xskip-metadata-version-check']` ,
49+ ) ;
50+ } else {
51+ // No kotlinOptions block; add one inside the android block
52+ const androidMatch = buildGradle . match ( / a n d r o i d \s * \{ / ) ;
53+ if ( androidMatch ) {
54+ buildGradle = buildGradle . replace (
55+ / a n d r o i d \s * \{ / ,
56+ `android {\n kotlinOptions {\n // Clerk: allow reading metadata from newer Kotlin versions\n freeCompilerArgs += ['-Xskip-metadata-version-check']\n }` ,
57+ ) ;
58+ }
3759 }
3860 }
3961
62+ modConfig . modResults . contents = buildGradle ;
4063 return modConfig ;
4164 } ) ;
4265} ;
@@ -84,13 +107,14 @@ const withClerkGoogleSignIn: ConfigPlugin = config => {
84107 * When this plugin is used, it:
85108 * 1. Configures iOS URL scheme for Google Sign-In (if env var is set)
86109 * 2. Adds Android packaging exclusions to resolve dependency conflicts
110+ * 3. Adds Kotlin metadata version compatibility flag for clerk-android
87111 *
88112 * Native modules are registered via react-native.config.js and standard
89113 * React Native autolinking (RCTViewManager / ReactPackage).
90114 */
91115const withClerkExpo : ConfigPlugin = config => {
92116 config = withClerkGoogleSignIn ( config ) ;
93- config = withClerkAndroidPackaging ( config ) ;
117+ config = withClerkAndroidConfig ( config ) ;
94118 return config ;
95119} ;
96120
0 commit comments