Skip to content

Commit

Permalink
feat(android): added custom scope method for android dependencies (re…
Browse files Browse the repository at this point in the history
…act-native-community#1430)

* feat: added customScope key to the dependency config type

* feat: added ability to define config inside project.android

* chore: updated docs

* chore: typo

* chore: revert `,`

* Update projects.md

* Update projects.md

* chore: rename

* Revert "chore: rename"

This reverts commit 58d3d23.

* chore: rename

Co-authored-by: Mike Grabowski <[email protected]>
  • Loading branch information
TMaszko and grabbou authored Jul 6, 2021
1 parent 83a370f commit 6615eb3
Show file tree
Hide file tree
Showing 7 changed files with 64 additions and 6 deletions.
6 changes: 6 additions & 0 deletions docs/dependencies.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ type DependencyParamsAndroidT = {
packageImportPath?: string;
packageInstance?: string;
buildTypes?: string[];
dependencyConfiguration?: string;
};
```

Expand Down Expand Up @@ -135,6 +136,11 @@ For settings applicable on other platforms, please consult their respective docu

An array of build variants or flavors which will include the dependency. If the array is empty, your dependency will be included in all build types. If you're working on a helper library that should only be included in development, such as a replacement for the React Native development menu, you should set this to `['debug']` to avoid shipping the library in a release build. For more details, see [`build variants`](https://developer.android.com/studio/build/build-variants#dependencies).

### platforms.android.dependencyConfiguration

A string that defines which method other than `implementation` do you want to use
for autolinking inside `build.gradle` i.e: `'embed project(path: ":$dependencyName", configuration: "default")',` - `"dependencyName` will be replaced by the actual package's name. You can achieve the same result by directly defining this key per `dependency` _(without placeholder)_ and it will have higher priority than this option.

### assets

An array of assets folders to glob for files to link.
Expand Down
5 changes: 3 additions & 2 deletions docs/platforms.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,11 +60,10 @@ type PlatformConfig<ProjectParams, ProjectConfig, DependencyConfig> = {

### npmPackageName

Returns the name of the npm package that should be used as the source for react-native JS code for platforms that provide platform specific overrides to core JS files. This causes the default metro config to redirect imports of react-native to another package based when bundling for that platform. The package specified should provide a complete react-native implementation for that platform.
Returns the name of the npm package that should be used as the source for react-native JS code for platforms that provide platform specific overrides to core JS files. This causes the default metro config to redirect imports of react-native to another package based when bundling for that platform. The package specified should provide a complete react-native implementation for that platform.

If this property is not specified, it is assumed that the code in core `react-native` works for the platform.


### projectConfig

Returns a project configuration for a given platform or `null`, when no project found. This is later used inside `linkConfig` to perform linking and unlinking.
Expand Down Expand Up @@ -112,6 +111,7 @@ type ProjectConfigAndroidT = {
packageName: string;
packageFolder: string;
appName: string;
dependencyConfiguration?: string;
};
```

Expand Down Expand Up @@ -145,6 +145,7 @@ type DependencyConfigAndroidT = {
packageInstance: string;
manifestPath: string;
packageName: string;
dependencyConfiguration?: string;
};
```

Expand Down
20 changes: 20 additions & 0 deletions docs/projects.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ type AndroidProjectParams = {
assetsPath?: string;
buildGradlePath?: string;
appName?: string; // A name of the app in the Android `sourceDir`, equivalent to Gradle project name. By default it's `app`.
dependencyConfiguration?: string;
};

type IOSProjectParams = {
Expand Down Expand Up @@ -121,6 +122,25 @@ module.exports = {

in order to disable linking of React Native WebView on iOS.

or you could set:

```js
module.exports = {
dependencies: {
'react-native-brownfield': {
platforms: {
android: {
dependencyConfiguration:
'embed project(path: ":react-native-brownfield-bridge", configuration: "default")',
},
},
},
},
};
```

in order to use something else than `implementation` _(default scope method)_

Another use-case would be supporting local libraries that are not discoverable for autolinking, since they're not part of your `dependencies` or `devDependencies`:

```js
Expand Down
2 changes: 2 additions & 0 deletions packages/cli-types/src/android.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ export interface AndroidProjectConfig {
packageName: string;
packageFolder: string;
appName: string;
dependencyConfiguration?: string;
}

export type AndroidProjectParams = Partial<AndroidProjectConfig>;
Expand All @@ -22,6 +23,7 @@ export interface AndroidDependencyConfig {
packageInstance: string;
manifestPath: string;
packageName: string;
dependencyConfiguration?: string;
buildTypes: string[];
}

Expand Down
3 changes: 3 additions & 0 deletions packages/cli/src/tools/config/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ export const dependencyConfig = t
manifestPath: t.string(),
packageImportPath: t.string(),
packageInstance: t.string(),
dependencyConfiguration: t.string(),
buildTypes: t.array().items(t.string()).default([]),
})
.default({}),
Expand Down Expand Up @@ -140,6 +141,7 @@ export const projectConfig = t
folder: t.string(),
packageImportPath: t.string(),
packageInstance: t.string(),
dependencyConfiguration: t.string(),
buildTypes: t.array().items(t.string()).default([]),
})
.allow(null),
Expand Down Expand Up @@ -178,6 +180,7 @@ export const projectConfig = t
assetsPath: t.string(),
buildGradlePath: t.string(),
appName: t.string(),
dependencyConfiguration: t.string(),
})
.default({}),
})
Expand Down
27 changes: 23 additions & 4 deletions packages/platform-android/native_modules.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -105,16 +105,24 @@ class ReactNativeModules {
void addReactNativeModuleDependencies(Project appProject) {
reactNativeModules.forEach { reactNativeModule ->
def nameCleansed = reactNativeModule["nameCleansed"]
def dependencyConfiguration = reactNativeModule["dependencyConfiguration"]
appProject.dependencies {
if (reactNativeModulesBuildVariants.containsKey(nameCleansed)) {
reactNativeModulesBuildVariants
.get(nameCleansed)
.forEach { buildVariant ->
"${buildVariant}Implementation" project(path: ":${nameCleansed}")
.forEach { buildVariant ->
if(dependencyConfiguration != null) {
"${buildVariant}${dependencyConfiguration}"
} else {
"${buildVariant}Implementation" project(path: ":${nameCleansed}")
}
}
} else {
// TODO(salakar): are other dependency scope methods such as `api` required?
implementation project(path: ":${nameCleansed}")
if(dependencyConfiguration != null) {
"${dependencyConfiguration}"
} else {
implementation project(path: ":${nameCleansed}")
}
}
}
}
Expand Down Expand Up @@ -248,6 +256,8 @@ class ReactNativeModules {
throw new Exception("React Native CLI failed to determine Android project configuration. This is likely due to misconfiguration. Config output:\n${json.toMapString()}")
}

def engine = new groovy.text.SimpleTemplateEngine()

dependencies.each { name, value ->
def platformsConfig = value["platforms"];
def androidConfig = platformsConfig["android"]
Expand All @@ -265,6 +275,15 @@ class ReactNativeModules {
if (!androidConfig["buildTypes"].isEmpty()) {
reactNativeModulesBuildVariants.put(nameCleansed, androidConfig["buildTypes"])
}
if(androidConfig.containsKey("dependencyConfiguration")) {
reactNativeModuleConfig.put("dependencyConfiguration", androidConfig["dependencyConfiguration"])
} else if (project.containsKey("dependencyConfiguration")) {
def bindings = ["dependencyName": nameCleansed]
def template = engine.createTemplate(project["dependencyConfiguration"]).make(bindings)

reactNativeModuleConfig.put("dependencyConfiguration", template.toString())
}

this.logger.trace("${LOG_PREFIX}'${name}': ${reactNativeModuleConfig.toMapString()}")

reactNativeModules.add(reactNativeModuleConfig)
Expand Down
7 changes: 7 additions & 0 deletions packages/platform-android/src/config/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,9 @@ export function projectConfig(
userConfig.buildGradlePath || 'build.gradle',
);

const dependencyConfiguration =
userConfig.dependencyConfiguration;

return {
sourceDir,
isFlat,
Expand All @@ -97,6 +100,7 @@ export function projectConfig(
packageName,
packageFolder,
appName,
dependencyConfiguration,
};
}

Expand Down Expand Up @@ -155,12 +159,15 @@ export function dependencyConfig(
userConfig.packageInstance || `new ${packageClassName}()`;

const buildTypes = userConfig.buildTypes || [];
const dependencyConfiguration =
userConfig.dependencyConfiguration;

return {
sourceDir,
folder: root,
packageImportPath,
packageInstance,
buildTypes,
dependencyConfiguration,
};
}

0 comments on commit 6615eb3

Please sign in to comment.