@callstack/react-native-brownfield 3.12.0 → 3.13.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (73) hide show
  1. package/CHANGELOG.md +22 -0
  2. package/gradle-plugin/brownfield/build.gradle.kts +134 -0
  3. package/gradle-plugin/brownfield/config/detekt/detekt.yml +936 -0
  4. package/gradle-plugin/brownfield/gradle/libs.versions.toml +19 -0
  5. package/gradle-plugin/brownfield/gradle/wrapper/gradle-wrapper.jar +0 -0
  6. package/gradle-plugin/brownfield/gradle/wrapper/gradle-wrapper.properties +7 -0
  7. package/gradle-plugin/brownfield/gradle.properties +14 -0
  8. package/gradle-plugin/brownfield/gradlew +249 -0
  9. package/gradle-plugin/brownfield/gradlew.bat +92 -0
  10. package/gradle-plugin/brownfield/settings.gradle +7 -0
  11. package/gradle-plugin/brownfield/src/main/kotlin/com/callstack/react/brownfield/artifacts/ArtifactsResolver.kt +132 -0
  12. package/gradle-plugin/brownfield/src/main/kotlin/com/callstack/react/brownfield/exceptions/NameSpaceNotFound.kt +4 -0
  13. package/gradle-plugin/brownfield/src/main/kotlin/com/callstack/react/brownfield/exceptions/TaskNotFound.kt +4 -0
  14. package/gradle-plugin/brownfield/src/main/kotlin/com/callstack/react/brownfield/expo/ExpoPublishingHelper.kt +432 -0
  15. package/gradle-plugin/brownfield/src/main/kotlin/com/callstack/react/brownfield/expo/utils/BrownfieldPrimitives.kt +31 -0
  16. package/gradle-plugin/brownfield/src/main/kotlin/com/callstack/react/brownfield/expo/utils/ExpoProjectionPrimitives.kt +22 -0
  17. package/gradle-plugin/brownfield/src/main/kotlin/com/callstack/react/brownfield/expo/utils/LocalMavenUtils.kt +83 -0
  18. package/gradle-plugin/brownfield/src/main/kotlin/com/callstack/react/brownfield/expo/utils/ReflectionUtils.kt +79 -0
  19. package/gradle-plugin/brownfield/src/main/kotlin/com/callstack/react/brownfield/expo/utils/VersionMediatingDependencySet.kt +100 -0
  20. package/gradle-plugin/brownfield/src/main/kotlin/com/callstack/react/brownfield/plugin/CustomDependencyResolver.kt +50 -0
  21. package/gradle-plugin/brownfield/src/main/kotlin/com/callstack/react/brownfield/plugin/ProjectConfigurations.kt +107 -0
  22. package/gradle-plugin/brownfield/src/main/kotlin/com/callstack/react/brownfield/plugin/RClassTransformer.kt +131 -0
  23. package/gradle-plugin/brownfield/src/main/kotlin/com/callstack/react/brownfield/plugin/RNBrownfieldPlugin.kt +171 -0
  24. package/gradle-plugin/brownfield/src/main/kotlin/com/callstack/react/brownfield/plugin/RNSourceSets.kt +149 -0
  25. package/gradle-plugin/brownfield/src/main/kotlin/com/callstack/react/brownfield/processors/AssetTaskProcessor.kt +29 -0
  26. package/gradle-plugin/brownfield/src/main/kotlin/com/callstack/react/brownfield/processors/ExplodeTaskProvider.kt +63 -0
  27. package/gradle-plugin/brownfield/src/main/kotlin/com/callstack/react/brownfield/processors/JNILibsProcessor.kt +165 -0
  28. package/gradle-plugin/brownfield/src/main/kotlin/com/callstack/react/brownfield/processors/ManifestTaskProcessor.kt +74 -0
  29. package/gradle-plugin/brownfield/src/main/kotlin/com/callstack/react/brownfield/processors/MergeProcessor.kt +55 -0
  30. package/gradle-plugin/brownfield/src/main/kotlin/com/callstack/react/brownfield/processors/ProguardProcessor.kt +61 -0
  31. package/gradle-plugin/brownfield/src/main/kotlin/com/callstack/react/brownfield/processors/ResourceTaskProcessor.kt +26 -0
  32. package/gradle-plugin/brownfield/src/main/kotlin/com/callstack/react/brownfield/processors/VariantHelper.kt +61 -0
  33. package/gradle-plugin/brownfield/src/main/kotlin/com/callstack/react/brownfield/processors/VariantPackagesProperty.kt +21 -0
  34. package/gradle-plugin/brownfield/src/main/kotlin/com/callstack/react/brownfield/processors/VariantTaskProvider.kt +103 -0
  35. package/gradle-plugin/brownfield/src/main/kotlin/com/callstack/react/brownfield/shared/BaseProject.kt +17 -0
  36. package/gradle-plugin/brownfield/src/main/kotlin/com/callstack/react/brownfield/shared/BundleTaskProvider.kt +46 -0
  37. package/gradle-plugin/brownfield/src/main/kotlin/com/callstack/react/brownfield/shared/Constants.kt +58 -0
  38. package/gradle-plugin/brownfield/src/main/kotlin/com/callstack/react/brownfield/shared/ExplodeAarTask.kt +72 -0
  39. package/gradle-plugin/brownfield/src/main/kotlin/com/callstack/react/brownfield/shared/GradleILogger.kt +59 -0
  40. package/gradle-plugin/brownfield/src/main/kotlin/com/callstack/react/brownfield/shared/Logging.kt +24 -0
  41. package/gradle-plugin/brownfield/src/main/kotlin/com/callstack/react/brownfield/shared/ModuleInfo.kt +22 -0
  42. package/gradle-plugin/brownfield/src/main/kotlin/com/callstack/react/brownfield/utils/AndroidArchiveLibrary.kt +77 -0
  43. package/gradle-plugin/brownfield/src/main/kotlin/com/callstack/react/brownfield/utils/DirectoryManager.kt +20 -0
  44. package/gradle-plugin/brownfield/src/main/kotlin/com/callstack/react/brownfield/utils/Extension.kt +44 -0
  45. package/gradle-plugin/brownfield/src/main/kotlin/com/callstack/react/brownfield/utils/StringExtensions.kt +5 -0
  46. package/gradle-plugin/brownfield/src/main/kotlin/com/callstack/react/brownfield/utils/StringMatcher.kt +21 -0
  47. package/gradle-plugin/brownfield/src/main/kotlin/com/callstack/react/brownfield/utils/Utils.kt +59 -0
  48. package/ios/Expo/ExpoHostRuntime.swift +3 -2
  49. package/ios/ReactNativeBrownfield.swift +1 -1
  50. package/ios/Vanilla/ReactNativeHostRuntime.swift +5 -2
  51. package/ios/swiftpm/Sources/BrownfieldBundleSupport/BrownfieldBundleURLResolver.swift +11 -5
  52. package/ios/swiftpm/Tests/BrownfieldBundleSupportTests/BrownfieldBundleURLResolverTests.swift +17 -5
  53. package/lib/commonjs/expo-config-plugin/android/utils/constants.js +1 -1
  54. package/lib/commonjs/expo-config-plugin/ios/xcodeHelpers.js +2 -1
  55. package/lib/commonjs/expo-config-plugin/ios/xcodeHelpers.js.map +1 -1
  56. package/lib/commonjs/index.js.map +1 -1
  57. package/lib/module/expo-config-plugin/android/utils/constants.js +1 -1
  58. package/lib/module/expo-config-plugin/ios/xcodeHelpers.js +2 -1
  59. package/lib/module/expo-config-plugin/ios/xcodeHelpers.js.map +1 -1
  60. package/lib/module/index.js.map +1 -1
  61. package/lib/typescript/commonjs/src/expo-config-plugin/android/utils/constants.d.ts +2 -2
  62. package/lib/typescript/commonjs/src/expo-config-plugin/ios/xcodeHelpers.d.ts.map +1 -1
  63. package/lib/typescript/commonjs/src/index.d.ts +1 -0
  64. package/lib/typescript/commonjs/src/index.d.ts.map +1 -1
  65. package/lib/typescript/module/src/expo-config-plugin/android/utils/constants.d.ts +2 -2
  66. package/lib/typescript/module/src/expo-config-plugin/ios/xcodeHelpers.d.ts.map +1 -1
  67. package/lib/typescript/module/src/index.d.ts +1 -0
  68. package/lib/typescript/module/src/index.d.ts.map +1 -1
  69. package/package.json +6 -4
  70. package/scripts/sync-gradle-plugin-source.js +58 -0
  71. package/src/expo-config-plugin/android/utils/constants.ts +1 -1
  72. package/src/expo-config-plugin/ios/xcodeHelpers.ts +14 -0
  73. package/src/index.ts +2 -0
@@ -0,0 +1,100 @@
1
+ package com.callstack.react.brownfield.expo.utils
2
+
3
+ import io.github.g00fy2.versioncompare.Version
4
+
5
+ /**
6
+ * A set that stores DependencyInfo objects based only on their groupId and artifactId.
7
+ * When adding a new dependency with the same groupId and artifactId,
8
+ * it compares the versions and keeps the one with the higher version.
9
+ */
10
+ open class VersionMediatingDependencySet : Iterable<DependencyInfo> {
11
+ private var backingMap =
12
+ mutableMapOf<Pair<String, String>, DependencyInfo>()
13
+
14
+ val size: Int get() = backingMap.size
15
+
16
+ fun contains(element: DependencyInfo): Boolean {
17
+ return backingMap.containsKey(element.groupId to element.artifactId)
18
+ }
19
+
20
+ fun add(element: DependencyInfo): Boolean {
21
+ val key = element.groupId to element.artifactId
22
+ val existing = backingMap[key]
23
+
24
+ if (existing == null) {
25
+ backingMap[key] = element
26
+ return true
27
+ }
28
+
29
+ // compare versions - replace if new version is greater (behavior of Gradle itself)
30
+ val existingVersion = existing.version
31
+ val newVersion = element.version
32
+
33
+ if (newVersion != null && (
34
+ existingVersion == null || compareVersions(
35
+ newVersion,
36
+ existingVersion,
37
+ ) > 0
38
+ )
39
+ ) {
40
+ backingMap[key] = element
41
+ return true
42
+ }
43
+
44
+ return false
45
+ }
46
+
47
+ fun forEach(action: (DependencyInfo) -> Unit) {
48
+ backingMap.values.forEach(action)
49
+ }
50
+
51
+ fun filter(predicate: (DependencyInfo) -> Boolean): VersionMediatingDependencySet {
52
+ backingMap =
53
+ backingMap.filter {
54
+ predicate(it.value)
55
+ }.toMutableMap()
56
+
57
+ return this
58
+ }
59
+
60
+ fun addAll(elements: Iterable<DependencyInfo>): Boolean {
61
+ var modified = false
62
+ elements.forEach { if (add(it)) modified = true }
63
+ return modified
64
+ }
65
+
66
+ fun removeAll(predicate: (it: DependencyInfo) -> Boolean): List<DependencyInfo?> {
67
+ val keysToBeRemoved = mutableSetOf<Pair<String, String>>()
68
+
69
+ forEach {
70
+ if (predicate(it)) {
71
+ keysToBeRemoved.add(it.groupId to it.artifactId)
72
+ }
73
+ }
74
+
75
+ return keysToBeRemoved.map {
76
+ backingMap.remove(it)
77
+ }
78
+ }
79
+
80
+ private fun compareVersions(
81
+ version1: String,
82
+ version2: String,
83
+ ): Int {
84
+ return Version(version1).compareTo(Version(version2))
85
+ }
86
+
87
+ override fun iterator(): Iterator<DependencyInfo> {
88
+ return backingMap.values.iterator()
89
+ }
90
+
91
+ companion object {
92
+ fun from(source: Iterable<DependencyInfo>): VersionMediatingDependencySet {
93
+ val instance = VersionMediatingDependencySet()
94
+
95
+ instance.addAll(source)
96
+
97
+ return instance
98
+ }
99
+ }
100
+ }
@@ -0,0 +1,50 @@
1
+ package com.callstack.react.brownfield.plugin
2
+
3
+ import org.gradle.api.Project
4
+ import org.gradle.api.artifacts.Configuration
5
+ import org.gradle.api.artifacts.DependencyResolutionListener
6
+ import org.gradle.api.artifacts.ResolvableDependencies
7
+ import org.gradle.api.internal.artifacts.dependencies.DefaultProjectDependency
8
+
9
+ /**
10
+ * The goal of this class is to find the project dependencies
11
+ * either local or remote and link to the Aar for code hints and supports.
12
+ *
13
+ * It does not embed anything to the Aar.
14
+ */
15
+ class CustomDependencyResolver(
16
+ private val project: Project,
17
+ private val configuration: Configuration,
18
+ ) : DependencyResolutionListener {
19
+ private fun getCompileOnlyConfigName(configurationName: String): String {
20
+ val configSuffix = ProjectConfigurations.CONFIG_SUFFIX
21
+ if (configurationName.endsWith(configSuffix)) {
22
+ val configName = configurationName.dropLast(configSuffix.length)
23
+ return "${configName}CompileOnly"
24
+ } else {
25
+ return "compileOnly"
26
+ }
27
+ }
28
+
29
+ override fun beforeResolve(dependencies: ResolvableDependencies) {
30
+ val configName = getCompileOnlyConfigName(configuration.name)
31
+ configuration.dependencies.forEach { dependency ->
32
+ if (dependency is DefaultProjectDependency) {
33
+ if (dependency.targetConfiguration == null) {
34
+ dependency.targetConfiguration = "default"
35
+ }
36
+
37
+ val dependencyClone = dependency.copy()
38
+ dependencyClone.targetConfiguration = null
39
+
40
+ project.dependencies.add(configName, dependencyClone)
41
+ } else {
42
+ project.dependencies.add(configName, dependency)
43
+ }
44
+ }
45
+ }
46
+
47
+ override fun afterResolve(dependencies: ResolvableDependencies) {
48
+ project.gradle.removeListener(this)
49
+ }
50
+ }
@@ -0,0 +1,107 @@
1
+ package com.callstack.react.brownfield.plugin
2
+
3
+ import com.android.build.api.variant.LibraryAndroidComponentsExtension
4
+ import com.android.build.gradle.LibraryExtension
5
+ import com.callstack.react.brownfield.shared.Logging
6
+ import com.callstack.react.brownfield.utils.capitalized
7
+ import org.gradle.api.Project
8
+ import org.gradle.api.artifacts.Configuration
9
+ import org.gradle.api.attributes.Attribute
10
+ import org.gradle.api.attributes.AttributeContainer
11
+
12
+ class ProjectConfigurations(private val project: Project) {
13
+ private val configurations: MutableCollection<Configuration> = mutableListOf()
14
+
15
+ companion object {
16
+ const val CONFIG_NAME = "embed"
17
+ const val CONFIG_SUFFIX = "Embed"
18
+ }
19
+
20
+ fun getConfigurations(): MutableCollection<Configuration> {
21
+ return configurations
22
+ }
23
+
24
+ /**
25
+ * Handles setting up the configuration for the project.
26
+ * It operates in the following manner:
27
+ *
28
+ * 1. creates main config
29
+ * 2. creates configs for buildTypes
30
+ * 3. creates configs for flavours
31
+ * 4. creates configs for flavours with buildTypes
32
+ */
33
+ fun configure() {
34
+ // create main configuration
35
+ createConfiguration(CONFIG_NAME)
36
+ val androidExtension = project.extensions.getByName("android") as LibraryExtension
37
+ createBuildTypesConfiguration(androidExtension)
38
+ createFlavorConfigurations(androidExtension)
39
+ }
40
+
41
+ /**
42
+ * creates configs for buildTypes
43
+ */
44
+ private fun createBuildTypesConfiguration(androidExtension: LibraryExtension) {
45
+ androidExtension.buildTypes.all { buildType ->
46
+ createConfiguration(getConfigName(buildType.name))
47
+ }
48
+ }
49
+
50
+ /**
51
+ * 1. creates configs for flavours
52
+ * 2. creates configs for flavours with buildTypes
53
+ */
54
+ private fun createFlavorConfigurations(androidExtension: LibraryExtension) {
55
+ androidExtension.productFlavors.all { flavor ->
56
+ createConfiguration(getConfigName(flavor.name))
57
+
58
+ androidExtension.buildTypes.all { buildType ->
59
+ val variantName = "${flavor.name}${buildType.name.capitalized()}"
60
+ createConfiguration(getConfigName(variantName))
61
+ }
62
+ }
63
+ }
64
+
65
+ /**
66
+ * creates configuration based on `configName`. Also attaches a resolution listener.
67
+ */
68
+ private fun createConfiguration(configName: String) {
69
+ Logging.log("creating configuration $configName ⌛️")
70
+ val configuration = project.configurations.create(configName)
71
+
72
+ configuration.extendsFrom(project.configurations.getByName("implementation"))
73
+ configuration.isVisible = false
74
+ configuration.isTransitive = false
75
+
76
+ val androidComponents = project.extensions.getByType(LibraryAndroidComponentsExtension::class.java)
77
+ androidComponents.onVariants { variant ->
78
+
79
+ val runtimeAttributes = variant.runtimeConfiguration.attributes
80
+ runtimeAttributes.keySet().forEach { key ->
81
+ copyAttribute(
82
+ key,
83
+ runtimeAttributes,
84
+ configuration.attributes,
85
+ )
86
+ }
87
+ }
88
+
89
+ project.gradle.addListener(CustomDependencyResolver(project, configuration))
90
+ configurations.add(configuration)
91
+ Logging.log("created configuration $configName ✅")
92
+ }
93
+
94
+ private fun <T : Any> copyAttribute(
95
+ key: Attribute<T>,
96
+ from: AttributeContainer,
97
+ into: AttributeContainer,
98
+ ) {
99
+ from.getAttribute(key)?.let {
100
+ into.attribute(key, it)
101
+ }
102
+ }
103
+
104
+ private fun getConfigName(prefix: String): String {
105
+ return "${prefix}$CONFIG_SUFFIX"
106
+ }
107
+ }
@@ -0,0 +1,131 @@
1
+ package com.callstack.react.brownfield.plugin
2
+
3
+ import com.android.build.api.instrumentation.AsmClassVisitorFactory
4
+ import com.android.build.api.instrumentation.ClassContext
5
+ import com.android.build.api.instrumentation.ClassData
6
+ import com.android.build.api.instrumentation.FramesComputationMode
7
+ import com.android.build.api.instrumentation.InstrumentationParameters
8
+ import com.android.build.api.instrumentation.InstrumentationScope
9
+ import com.android.build.api.variant.AndroidComponentsExtension
10
+ import com.callstack.react.brownfield.processors.VariantPackagesProperty
11
+ import com.callstack.react.brownfield.shared.BaseProject
12
+ import org.gradle.api.provider.ListProperty
13
+ import org.gradle.api.provider.Property
14
+ import org.gradle.api.tasks.Input
15
+ import org.gradle.api.tasks.Optional
16
+ import org.objectweb.asm.ClassVisitor
17
+ import org.objectweb.asm.commons.ClassRemapper
18
+ import org.objectweb.asm.commons.Remapper
19
+ import java.util.Collections
20
+ import java.util.stream.Collectors
21
+
22
+ /**
23
+ * Transforms R classes of all modules into a single
24
+ * R class. This avoid duplicates issues as each module
25
+ * can have it's own R class, so this redirects all
26
+ * references to a single R class.
27
+ */
28
+ object RClassTransformer : BaseProject() {
29
+ fun registerASMTransformation() {
30
+ val components = project.extensions.getByType(AndroidComponentsExtension::class.java)
31
+ val variantPackagesProperty = VariantPackagesProperty.getVariantPackagesProperty()
32
+
33
+ components.onVariants(components.selector().all()) { variant ->
34
+ variant.instrumentation.transformClassesWith(
35
+ RClassAsmTransformerFactory::class.java,
36
+ InstrumentationScope.PROJECT,
37
+ ) { params ->
38
+ params.namespace.set(variant.namespace)
39
+ params.libraryNamespaces.set(
40
+ variantPackagesProperty.getting(variant.name)
41
+ .map { list -> list.toList() },
42
+ )
43
+ }
44
+
45
+ variant.instrumentation.setAsmFramesComputationMode(FramesComputationMode.COPY_FRAMES)
46
+ }
47
+ }
48
+
49
+ /**
50
+ * transforms R class into bytecode
51
+ */
52
+ abstract class RClassAsmTransformerFactory :
53
+ AsmClassVisitorFactory<RClassAsmTransformerFactory.Params> {
54
+ interface Params : InstrumentationParameters {
55
+ @get:Input
56
+ val namespace: Property<String>
57
+
58
+ @get:Input
59
+ @get:Optional
60
+ val libraryNamespaces: ListProperty<String>
61
+ }
62
+
63
+ /**
64
+ * Creates a class that remaps R class and its subclasses.
65
+ */
66
+ override fun createClassVisitor(
67
+ classContext: ClassContext,
68
+ nextClassVisitor: ClassVisitor,
69
+ ): ClassVisitor {
70
+ val params = parameters.get()
71
+ val namespace = params.namespace.get()
72
+ val libraryNamespaces = params.libraryNamespaces.orElse(Collections.emptyList()).get()
73
+
74
+ if (libraryNamespaces.isEmpty()) {
75
+ return nextClassVisitor
76
+ }
77
+
78
+ return ClassRemapper(nextClassVisitor, getRemapper(libraryNamespaces, namespace))
79
+ }
80
+
81
+ private fun getRemapper(
82
+ libraryNamespaces: List<String>,
83
+ namespace: String,
84
+ ): Remapper {
85
+ val formattedNameSpace = namespace.replace(".", "/")
86
+ val targetRClass = "$formattedNameSpace/R"
87
+ val targetRSubclass = "$formattedNameSpace/R$"
88
+
89
+ val libraryRClasses = getLibraryRClasses(libraryNamespaces)
90
+ val libraryRSubclasses = getLibraryRSubclasses(libraryNamespaces)
91
+
92
+ val remapper =
93
+ object : Remapper() {
94
+ override fun map(internalName: String?): String? {
95
+ if (internalName == null) {
96
+ return null
97
+ }
98
+ if (libraryRClasses.contains(internalName)) {
99
+ return targetRClass
100
+ }
101
+ for (libraryRSubclass in libraryRSubclasses) {
102
+ if (internalName.startsWith(libraryRSubclass)) {
103
+ return internalName.replaceFirst(libraryRSubclass, targetRSubclass, false)
104
+ }
105
+ }
106
+ return super.map(internalName)
107
+ }
108
+ }
109
+ return remapper
110
+ }
111
+
112
+ private fun getLibraryRClasses(libraryNamespaces: List<String>): Set<String> {
113
+ return libraryNamespaces.stream()
114
+ .map { it.replace(".", "/") + "/R" }
115
+ .collect(Collectors.toSet())
116
+ }
117
+
118
+ private fun getLibraryRSubclasses(libraryNamespaces: List<String>): List<String> {
119
+ return libraryNamespaces.stream()
120
+ .map { it.replace(".", "/") + "/R$" }
121
+ .collect(Collectors.toList())
122
+ }
123
+
124
+ /**
125
+ * Determines if the class can be checked for transformation.
126
+ */
127
+ override fun isInstrumentable(classData: ClassData): Boolean {
128
+ return true
129
+ }
130
+ }
131
+ }
@@ -0,0 +1,171 @@
1
+ package com.callstack.react.brownfield.plugin
2
+
3
+ import com.android.build.gradle.LibraryExtension
4
+ import com.android.build.gradle.api.LibraryVariant
5
+ import com.callstack.react.brownfield.artifacts.ArtifactsResolver
6
+ import com.callstack.react.brownfield.expo.ExpoPublishingHelper
7
+ import com.callstack.react.brownfield.expo.utils.ExpoGradleProjectProjection
8
+ import com.callstack.react.brownfield.processors.AssetTaskProcessor
9
+ import com.callstack.react.brownfield.processors.ExplodeTaskProvider
10
+ import com.callstack.react.brownfield.processors.JNILibsProcessor
11
+ import com.callstack.react.brownfield.processors.ManifestTaskProcessor
12
+ import com.callstack.react.brownfield.processors.ProguardProcessor
13
+ import com.callstack.react.brownfield.processors.ResourceTaskProcessor
14
+ import com.callstack.react.brownfield.processors.VariantPackagesProperty
15
+ import com.callstack.react.brownfield.processors.VariantTaskProvider
16
+ import com.callstack.react.brownfield.shared.BaseProject
17
+ import com.callstack.react.brownfield.shared.Constants.PROJECT_ID
18
+ import com.callstack.react.brownfield.shared.Logging
19
+ import com.callstack.react.brownfield.shared.UnresolvedArtifactInfo
20
+ import com.callstack.react.brownfield.utils.AndroidArchiveLibrary
21
+ import com.callstack.react.brownfield.utils.DirectoryManager
22
+ import com.callstack.react.brownfield.utils.Extension
23
+ import com.callstack.react.brownfield.utils.Utils
24
+ import org.gradle.api.Plugin
25
+ import org.gradle.api.Project
26
+ import org.gradle.api.ProjectConfigurationException
27
+
28
+ class RNBrownfieldPlugin : Plugin<Project> {
29
+ private lateinit var extension: Extension
30
+ private lateinit var project: Project
31
+
32
+ private val isExpoProject: Boolean
33
+ get() = Utils.isExpoProject(project)
34
+
35
+ override fun apply(project: Project) {
36
+ verifyAndroidPluginApplied(project)
37
+
38
+ this.project = project
39
+ initializers()
40
+
41
+ val projectConfigurations = ProjectConfigurations(project)
42
+ projectConfigurations.configure()
43
+ RNSourceSets.configure(project, extension)
44
+ RClassTransformer.registerASMTransformation()
45
+
46
+ /**
47
+ * Must run before processDefaultDependencies: ArtifactsResolver reads :expo's api configuration,
48
+ * which is only populated after the expo project is evaluated.
49
+ */
50
+ if (this.isExpoProject) {
51
+ project.evaluationDependsOn(EXPO_PROJECT_LOCATOR)
52
+ }
53
+
54
+ var expoProjects = listOf<ExpoGradleProjectProjection>()
55
+ if (this.isExpoProject) {
56
+ val expoPublishingHelper = ExpoPublishingHelper(brownfieldAppProject = project)
57
+ expoProjects = expoPublishingHelper.configure()
58
+ }
59
+
60
+ /**
61
+ * curates a list of artifacts that we need to bundle with the Aar
62
+ */
63
+ val artifactsResolver = ArtifactsResolver(project, isExpoProject)
64
+ val artifacts = artifactsResolver.processDefaultDependencies(expoProjects)
65
+
66
+ val variantTaskProvider = VariantTaskProvider(project)
67
+
68
+ /**
69
+ * Configure Tasks
70
+ */
71
+ project.extensions.getByType(LibraryExtension::class.java).libraryVariants.all { variant ->
72
+ configureTasks(variant, artifacts, variantTaskProvider)
73
+ }
74
+ }
75
+
76
+ companion object {
77
+ const val EXPO_PROJECT_LOCATOR = ":expo"
78
+ }
79
+
80
+ private fun initializers() {
81
+ RClassTransformer.project = project
82
+ Logging.project = project
83
+ val baseProject = BaseProject()
84
+ baseProject.project = project
85
+ DirectoryManager.project = project
86
+
87
+ this.extension = project.extensions.create(Extension.NAME, Extension::class.java)
88
+ VariantPackagesProperty.setVariantPackagesProperty(project)
89
+ }
90
+
91
+ /**
92
+ * Verifies and throws error if `com.android.library` plugin is not applied
93
+ */
94
+ private fun verifyAndroidPluginApplied(project: Project) {
95
+ if (!project.plugins.hasPlugin("com.android.library")) {
96
+ throw ProjectConfigurationException(
97
+ "$PROJECT_ID must be applied to an android library project",
98
+ Throwable("Apply $PROJECT_ID"),
99
+ )
100
+ }
101
+ }
102
+
103
+ private fun getAarLibraries(
104
+ artifacts: List<UnresolvedArtifactInfo>,
105
+ variantName: String,
106
+ ): List<AndroidArchiveLibrary> {
107
+ val aarLibraries = mutableListOf<AndroidArchiveLibrary>()
108
+ artifacts.forEach { art ->
109
+ val archiveLibrary =
110
+ AndroidArchiveLibrary(
111
+ this.project,
112
+ art,
113
+ variantName,
114
+ )
115
+ aarLibraries.add(archiveLibrary)
116
+ }
117
+
118
+ return aarLibraries
119
+ }
120
+
121
+ private fun configureTasks(
122
+ variant: LibraryVariant,
123
+ artifacts: List<UnresolvedArtifactInfo>,
124
+ variantTaskProvider: VariantTaskProvider,
125
+ ) {
126
+ val variantName = variant.name
127
+ val capitalizedVariantName = variantName.replaceFirstChar(Char::titlecase)
128
+
129
+ /** ======= EXPLODE AAR =========*/
130
+ val explodeTask = ExplodeTaskProvider.getTask(variant, project, artifacts)
131
+
132
+ /** ======= Pre<Variant>Build =========*/
133
+ variantTaskProvider.preBuildTaskByVariant(
134
+ variantName,
135
+ variant.buildType.name,
136
+ variant.buildType.isDebuggable,
137
+ explodeTask,
138
+ )
139
+
140
+ val aarLibraries = getAarLibraries(artifacts, variantName)
141
+
142
+ /**
143
+ * Flat IDs to be put into the variant property, required for RClass Transformer
144
+ */
145
+ val packageIDs = aarLibraries.map { it.getPackageName() }
146
+ VariantPackagesProperty.getVariantPackagesProperty().put(variantName, packageIDs)
147
+
148
+ /** ======= MANIFEST MERGER =========*/
149
+ ManifestTaskProcessor.process(variant, project, aarLibraries)
150
+
151
+ /** ======= GENERATE RESOURCES =========*/
152
+ ResourceTaskProcessor.process(variant, project, aarLibraries)
153
+
154
+ /** ======= GENERATE ASSETS ========= */
155
+ AssetTaskProcessor.process(variant, project, aarLibraries)
156
+
157
+ /** ===== jniLibsProcessor ===== */
158
+ val jniLibsProcessor = JNILibsProcessor(project)
159
+ jniLibsProcessor.processJniLibs(aarLibraries, variantName)
160
+
161
+ /** ===== proguardProcessor ===== */
162
+ val proguardProcessor = ProguardProcessor(project)
163
+ val proguardRules = aarLibraries.map { it.getProguardRules() }
164
+ proguardProcessor.processConsumerFiles(proguardRules, capitalizedVariantName)
165
+ proguardProcessor.processGeneratedFiles(proguardRules, capitalizedVariantName)
166
+
167
+ /** ===== processDataBinding ===== */
168
+ val bundleTask = variantTaskProvider.bundleTaskProvider(project, variantName)
169
+ variantTaskProvider.processDataBinding(bundleTask, aarLibraries, variantName)
170
+ }
171
+ }