expo-build-properties 0.0.0
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.
- package/.eslintrc.js +2 -0
- package/CHANGELOG.md +15 -0
- package/README.md +49 -0
- package/app.plugin.js +1 -0
- package/build/android.d.ts +15 -0
- package/build/android.js +97 -0
- package/build/ios.d.ts +4 -0
- package/build/ios.js +52 -0
- package/build/pluginConfig.d.ts +56 -0
- package/build/pluginConfig.js +114 -0
- package/build/withBuildProperties.d.ts +10 -0
- package/build/withBuildProperties.js +22 -0
- package/jest.config.js +1 -0
- package/package.json +48 -0
- package/src/android.ts +110 -0
- package/src/ios.ts +77 -0
- package/src/pluginConfig.ts +184 -0
- package/src/withBuildProperties.ts +24 -0
- package/tsconfig.json +8 -0
package/.eslintrc.js
ADDED
package/CHANGELOG.md
ADDED
package/README.md
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# expo-build-properties
|
|
2
|
+
|
|
3
|
+
**`expo-build-properties`** is a config plugin for managed apps to override the default native build properties.
|
|
4
|
+
|
|
5
|
+
## API documentation
|
|
6
|
+
|
|
7
|
+
- [Documentation for the main branch][docs-main]
|
|
8
|
+
- [Documentation for the latest stable release][docs-stable]
|
|
9
|
+
|
|
10
|
+
### Installation
|
|
11
|
+
|
|
12
|
+
**Note:** To use this config plugin, your apps must be a managed app and build by either [EAS Build](/build/introduction.md) or `expo run:[android|ios]`.
|
|
13
|
+
|
|
14
|
+
```
|
|
15
|
+
expo install expo-build-properties
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
Add plugin to `app.json`. For example:
|
|
19
|
+
|
|
20
|
+
```json
|
|
21
|
+
{
|
|
22
|
+
"expo": {
|
|
23
|
+
"plugins": [
|
|
24
|
+
[
|
|
25
|
+
"expo-build-properties",
|
|
26
|
+
{
|
|
27
|
+
"android": {
|
|
28
|
+
"compileSdkVersion": 31,
|
|
29
|
+
"targetSdkVersion": 31,
|
|
30
|
+
"buildToolsVersion": "31.0.0"
|
|
31
|
+
},
|
|
32
|
+
"ios": {
|
|
33
|
+
"deploymentTarget": "13.0"
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
]
|
|
37
|
+
]
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
## Contributing
|
|
43
|
+
|
|
44
|
+
Contributions are very welcome! Please refer to guidelines described in the [contributing guide][contributing].
|
|
45
|
+
|
|
46
|
+
[docs-main]: https://github.com/expo/expo/blob/main/docs/pages/versions/unversioned/sdk/build-properties.md
|
|
47
|
+
[docs-stable]: https://docs.expo.dev/versions/latest/sdk/build-properties/
|
|
48
|
+
[contributing]: https://github.com/expo/expo#contributing
|
|
49
|
+
[config-plugins]: https://docs.expo.dev/guides/config-plugins/
|
package/app.plugin.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
module.exports = require('./build/withBuildProperties');
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { ConfigPlugin } from '@expo/config-plugins';
|
|
2
|
+
import type { PluginConfigType } from './pluginConfig';
|
|
3
|
+
export declare const withAndroidBuildProperties: ConfigPlugin<PluginConfigType>;
|
|
4
|
+
/**
|
|
5
|
+
* Appends `props.android.extraProguardRules` content into `android/app/proguard-rules.pro`
|
|
6
|
+
*/
|
|
7
|
+
export declare const withAndroidProguardRules: ConfigPlugin<PluginConfigType>;
|
|
8
|
+
/**
|
|
9
|
+
* Update `newProguardRules` to original `proguard-rules.pro` contents if needed
|
|
10
|
+
*
|
|
11
|
+
* @param contents the original `proguard-rules.pro` contents
|
|
12
|
+
* @param newProguardRules new proguard rules to add. If the value is null, the generated proguard rules will be cleanup
|
|
13
|
+
* @returns return string when results is updated or return null when nothing changed.
|
|
14
|
+
*/
|
|
15
|
+
export declare function updateAndroidProguardRules(contents: string, newProguardRules: string | null): string | null;
|
package/build/android.js
ADDED
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.updateAndroidProguardRules = exports.withAndroidProguardRules = exports.withAndroidBuildProperties = void 0;
|
|
7
|
+
const config_plugins_1 = require("@expo/config-plugins");
|
|
8
|
+
const generateCode_1 = require("@expo/config-plugins/build/utils/generateCode");
|
|
9
|
+
const fs_1 = __importDefault(require("fs"));
|
|
10
|
+
const path_1 = __importDefault(require("path"));
|
|
11
|
+
const { createBuildGradlePropsConfigPlugin } = config_plugins_1.AndroidConfig.BuildProperties;
|
|
12
|
+
exports.withAndroidBuildProperties = createBuildGradlePropsConfigPlugin([
|
|
13
|
+
{
|
|
14
|
+
propName: 'android.compileSdkVersion',
|
|
15
|
+
propValueGetter: (config) => { var _a, _b; return (_b = (_a = config.android) === null || _a === void 0 ? void 0 : _a.compileSdkVersion) === null || _b === void 0 ? void 0 : _b.toString(); },
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
propName: 'android.targetSdkVersion',
|
|
19
|
+
propValueGetter: (config) => { var _a, _b; return (_b = (_a = config.android) === null || _a === void 0 ? void 0 : _a.targetSdkVersion) === null || _b === void 0 ? void 0 : _b.toString(); },
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
propName: 'android.buildToolsVersion',
|
|
23
|
+
propValueGetter: (config) => { var _a; return (_a = config.android) === null || _a === void 0 ? void 0 : _a.buildToolsVersion; },
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
propName: 'android.kotlinVersion',
|
|
27
|
+
propValueGetter: (config) => { var _a; return (_a = config.android) === null || _a === void 0 ? void 0 : _a.kotlinVersion; },
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
propName: 'android.packagingOptions.pickFirsts',
|
|
31
|
+
propValueGetter: (config) => { var _a, _b, _c; return (_c = (_b = (_a = config.android) === null || _a === void 0 ? void 0 : _a.packagingOptions) === null || _b === void 0 ? void 0 : _b.pickFirst) === null || _c === void 0 ? void 0 : _c.join(','); },
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
propName: 'android.packagingOptions.excludes',
|
|
35
|
+
propValueGetter: (config) => { var _a, _b, _c; return (_c = (_b = (_a = config.android) === null || _a === void 0 ? void 0 : _a.packagingOptions) === null || _b === void 0 ? void 0 : _b.exclude) === null || _c === void 0 ? void 0 : _c.join(','); },
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
propName: 'android.packagingOptions.merges',
|
|
39
|
+
propValueGetter: (config) => { var _a, _b, _c; return (_c = (_b = (_a = config.android) === null || _a === void 0 ? void 0 : _a.packagingOptions) === null || _b === void 0 ? void 0 : _b.merge) === null || _c === void 0 ? void 0 : _c.join(','); },
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
propName: 'android.packagingOptions.doNotStrip',
|
|
43
|
+
propValueGetter: (config) => { var _a, _b, _c; return (_c = (_b = (_a = config.android) === null || _a === void 0 ? void 0 : _a.packagingOptions) === null || _b === void 0 ? void 0 : _b.doNotStrip) === null || _c === void 0 ? void 0 : _c.join(','); },
|
|
44
|
+
},
|
|
45
|
+
], 'withAndroidBuildProperties');
|
|
46
|
+
/**
|
|
47
|
+
* Appends `props.android.extraProguardRules` content into `android/app/proguard-rules.pro`
|
|
48
|
+
*/
|
|
49
|
+
const withAndroidProguardRules = (config, props) => {
|
|
50
|
+
return (0, config_plugins_1.withDangerousMod)(config, [
|
|
51
|
+
'android',
|
|
52
|
+
async (config) => {
|
|
53
|
+
var _a, _b;
|
|
54
|
+
const extraProguardRules = (_b = (_a = props.android) === null || _a === void 0 ? void 0 : _a.extraProguardRules) !== null && _b !== void 0 ? _b : null;
|
|
55
|
+
const proguardRulesFile = path_1.default.join(config.modRequest.platformProjectRoot, 'app', 'proguard-rules.pro');
|
|
56
|
+
const contents = await fs_1.default.promises.readFile(proguardRulesFile, 'utf8');
|
|
57
|
+
const newContents = updateAndroidProguardRules(contents, extraProguardRules);
|
|
58
|
+
if (newContents) {
|
|
59
|
+
await fs_1.default.promises.writeFile(proguardRulesFile, newContents);
|
|
60
|
+
}
|
|
61
|
+
return config;
|
|
62
|
+
},
|
|
63
|
+
]);
|
|
64
|
+
};
|
|
65
|
+
exports.withAndroidProguardRules = withAndroidProguardRules;
|
|
66
|
+
/**
|
|
67
|
+
* Update `newProguardRules` to original `proguard-rules.pro` contents if needed
|
|
68
|
+
*
|
|
69
|
+
* @param contents the original `proguard-rules.pro` contents
|
|
70
|
+
* @param newProguardRules new proguard rules to add. If the value is null, the generated proguard rules will be cleanup
|
|
71
|
+
* @returns return string when results is updated or return null when nothing changed.
|
|
72
|
+
*/
|
|
73
|
+
function updateAndroidProguardRules(contents, newProguardRules) {
|
|
74
|
+
const mergeTag = 'expo-build-properties';
|
|
75
|
+
let mergeResults;
|
|
76
|
+
if (newProguardRules) {
|
|
77
|
+
mergeResults = (0, generateCode_1.mergeContents)({
|
|
78
|
+
tag: mergeTag,
|
|
79
|
+
src: contents,
|
|
80
|
+
newSrc: newProguardRules,
|
|
81
|
+
anchor: /^/,
|
|
82
|
+
offset: contents.length,
|
|
83
|
+
comment: '#',
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
else {
|
|
87
|
+
mergeResults = (0, generateCode_1.removeContents)({
|
|
88
|
+
tag: mergeTag,
|
|
89
|
+
src: contents,
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
if (mergeResults.didMerge || mergeResults.didClear) {
|
|
93
|
+
return mergeResults.contents;
|
|
94
|
+
}
|
|
95
|
+
return null;
|
|
96
|
+
}
|
|
97
|
+
exports.updateAndroidProguardRules = updateAndroidProguardRules;
|
package/build/ios.d.ts
ADDED
package/build/ios.js
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.withIosDeploymentTarget = exports.withIosBuildProperties = void 0;
|
|
4
|
+
const config_plugins_1 = require("@expo/config-plugins");
|
|
5
|
+
const { createBuildPodfilePropsConfigPlugin } = config_plugins_1.IOSConfig.BuildProperties;
|
|
6
|
+
exports.withIosBuildProperties = createBuildPodfilePropsConfigPlugin([
|
|
7
|
+
{
|
|
8
|
+
propName: 'ios.useFrameworks',
|
|
9
|
+
propValueGetter: (config) => { var _a; return (_a = config.ios) === null || _a === void 0 ? void 0 : _a.useFrameworks; },
|
|
10
|
+
},
|
|
11
|
+
], 'withIosBuildProperties');
|
|
12
|
+
const withIosDeploymentTarget = (config, props) => {
|
|
13
|
+
var _a;
|
|
14
|
+
const deploymentTarget = (_a = props.ios) === null || _a === void 0 ? void 0 : _a.deploymentTarget;
|
|
15
|
+
if (!deploymentTarget) {
|
|
16
|
+
return config;
|
|
17
|
+
}
|
|
18
|
+
// Updates deployment target in app xcodeproj
|
|
19
|
+
config = withIosDeploymentTargetXcodeProject(config, { deploymentTarget });
|
|
20
|
+
// Updates deployement target in Podfile (Pods project)
|
|
21
|
+
config = withIosDeploymentTargetPodfile(config, props);
|
|
22
|
+
return config;
|
|
23
|
+
};
|
|
24
|
+
exports.withIosDeploymentTarget = withIosDeploymentTarget;
|
|
25
|
+
const withIosDeploymentTargetXcodeProject = (config, props) => {
|
|
26
|
+
return (0, config_plugins_1.withXcodeProject)(config, (config) => {
|
|
27
|
+
config.modResults = updateDeploymentTargetXcodeProject(config.modResults, props.deploymentTarget);
|
|
28
|
+
return config;
|
|
29
|
+
});
|
|
30
|
+
};
|
|
31
|
+
function updateDeploymentTargetXcodeProject(project, deploymentTarget) {
|
|
32
|
+
const { Target } = config_plugins_1.IOSConfig;
|
|
33
|
+
const targetBuildConfigListIds = Target.getNativeTargets(project)
|
|
34
|
+
.filter(([_, target]) => Target.isTargetOfType(target, Target.TargetType.APPLICATION))
|
|
35
|
+
.map(([_, target]) => target.buildConfigurationList);
|
|
36
|
+
for (const buildConfigListId of targetBuildConfigListIds) {
|
|
37
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
38
|
+
for (const [_, configurations] of config_plugins_1.IOSConfig.XcodeUtils.getBuildConfigurationsForListId(project, buildConfigListId)) {
|
|
39
|
+
const { buildSettings } = configurations;
|
|
40
|
+
if (buildSettings === null || buildSettings === void 0 ? void 0 : buildSettings.IPHONEOS_DEPLOYMENT_TARGET) {
|
|
41
|
+
buildSettings.IPHONEOS_DEPLOYMENT_TARGET = deploymentTarget;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
return project;
|
|
46
|
+
}
|
|
47
|
+
const withIosDeploymentTargetPodfile = createBuildPodfilePropsConfigPlugin([
|
|
48
|
+
{
|
|
49
|
+
propName: 'ios.deploymentTarget',
|
|
50
|
+
propValueGetter: (config) => { var _a; return (_a = config.ios) === null || _a === void 0 ? void 0 : _a.deploymentTarget; },
|
|
51
|
+
},
|
|
52
|
+
], 'withIosDeploymentTargetPodfile');
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Configuration for `expo-build-properties`
|
|
3
|
+
*/
|
|
4
|
+
export interface PluginConfigType {
|
|
5
|
+
android?: PluginConfigTypeAndroid;
|
|
6
|
+
ios?: PluginConfigTypeIos;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Config for Android native build properties
|
|
10
|
+
*/
|
|
11
|
+
export interface PluginConfigTypeAndroid {
|
|
12
|
+
/** Override the default `compileSdkVersion` version number in `build.gradle` */
|
|
13
|
+
compileSdkVersion?: number;
|
|
14
|
+
/** Override the default `targetSdkVersion` version number in `build.gradle` */
|
|
15
|
+
targetSdkVersion?: number;
|
|
16
|
+
/** Override the default `buildToolsVersion` version number in `build.gradle` */
|
|
17
|
+
buildToolsVersion?: string;
|
|
18
|
+
/** Override the default Kotlin version when building the app */
|
|
19
|
+
kotlinVersion?: string;
|
|
20
|
+
/** Enable Proguard (R8) in release builds to obfuscate Java code and reduce app size */
|
|
21
|
+
enableProguardInReleaseBuilds?: boolean;
|
|
22
|
+
/** Append custom [Proguard rules](https://www.guardsquare.com/manual/configuration/usage) to `android/app/proguard-rules.pro` */
|
|
23
|
+
extraProguardRules?: string;
|
|
24
|
+
/** AGP [PackagingOptions](https://developer.android.com/reference/tools/gradle-api/7.0/com/android/build/api/dsl/PackagingOptions) */
|
|
25
|
+
packagingOptions?: PluginConfigTypeAndroidPackagingOptions;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Config for iOS native build properties
|
|
29
|
+
*/
|
|
30
|
+
export interface PluginConfigTypeIos {
|
|
31
|
+
/**
|
|
32
|
+
* Override the default iOS *Deployment Target* version in the following projects:
|
|
33
|
+
* - in CocoaPods projects
|
|
34
|
+
* - `PBXNativeTarget` with `com.apple.product-type.application` productType in the app project
|
|
35
|
+
*/
|
|
36
|
+
deploymentTarget?: string;
|
|
37
|
+
/** Enable [`use_frameworks!`](https://guides.cocoapods.org/syntax/podfile.html#use_frameworks_bang) in `Podfile` */
|
|
38
|
+
useFrameworks?: 'static' | 'dynamic';
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* AGP [PackagingOptions](https://developer.android.com/reference/tools/gradle-api/7.0/com/android/build/api/dsl/PackagingOptions)
|
|
42
|
+
*/
|
|
43
|
+
export interface PluginConfigTypeAndroidPackagingOptions {
|
|
44
|
+
/** Adds a first-pick pattern */
|
|
45
|
+
pickFirst?: string[];
|
|
46
|
+
/** Adds an excluded pattern */
|
|
47
|
+
exclude?: string[];
|
|
48
|
+
/** Adds a merge pattern */
|
|
49
|
+
merge?: string[];
|
|
50
|
+
/** Adds a doNotStrip pattern */
|
|
51
|
+
doNotStrip?: string[];
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* @ignore
|
|
55
|
+
*/
|
|
56
|
+
export declare function validateConfig(config: any): PluginConfigType;
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.validateConfig = void 0;
|
|
7
|
+
const ajv_1 = __importDefault(require("ajv"));
|
|
8
|
+
const semver_1 = __importDefault(require("semver"));
|
|
9
|
+
/**
|
|
10
|
+
* The minimal supported versions. These values should align to SDK
|
|
11
|
+
* @ignore
|
|
12
|
+
*/
|
|
13
|
+
const EXPO_SDK_MINIMAL_SUPPORTED_VERSIONS = {
|
|
14
|
+
android: {
|
|
15
|
+
compileSdkVersion: 31,
|
|
16
|
+
targetSdkVersion: 31,
|
|
17
|
+
kotlinVersion: '1.6.10',
|
|
18
|
+
},
|
|
19
|
+
ios: {
|
|
20
|
+
deploymentTarget: '12.0',
|
|
21
|
+
},
|
|
22
|
+
};
|
|
23
|
+
const schema = {
|
|
24
|
+
type: 'object',
|
|
25
|
+
properties: {
|
|
26
|
+
android: {
|
|
27
|
+
type: 'object',
|
|
28
|
+
properties: {
|
|
29
|
+
compileSdkVersion: { type: 'integer', nullable: true },
|
|
30
|
+
targetSdkVersion: { type: 'integer', nullable: true },
|
|
31
|
+
buildToolsVersion: { type: 'string', nullable: true },
|
|
32
|
+
kotlinVersion: { type: 'string', nullable: true },
|
|
33
|
+
enableProguardInReleaseBuilds: { type: 'boolean', nullable: true },
|
|
34
|
+
extraProguardRules: { type: 'string', nullable: true },
|
|
35
|
+
packagingOptions: {
|
|
36
|
+
type: 'object',
|
|
37
|
+
properties: {
|
|
38
|
+
pickFirst: { type: 'array', items: { type: 'string' }, nullable: true },
|
|
39
|
+
exclude: { type: 'array', items: { type: 'string' }, nullable: true },
|
|
40
|
+
merge: { type: 'array', items: { type: 'string' }, nullable: true },
|
|
41
|
+
doNotStrip: { type: 'array', items: { type: 'string' }, nullable: true },
|
|
42
|
+
},
|
|
43
|
+
nullable: true,
|
|
44
|
+
},
|
|
45
|
+
},
|
|
46
|
+
nullable: true,
|
|
47
|
+
},
|
|
48
|
+
ios: {
|
|
49
|
+
type: 'object',
|
|
50
|
+
properties: {
|
|
51
|
+
deploymentTarget: { type: 'string', pattern: '\\d+\\.\\d+', nullable: true },
|
|
52
|
+
useFrameworks: { type: 'string', enum: ['static', 'dynamic'], nullable: true },
|
|
53
|
+
},
|
|
54
|
+
nullable: true,
|
|
55
|
+
},
|
|
56
|
+
},
|
|
57
|
+
};
|
|
58
|
+
/**
|
|
59
|
+
* Check versions to meet expo minimal supported versions.
|
|
60
|
+
* Will throw error message whenever there are invalid versions.
|
|
61
|
+
* For the implementation, we check items one by one because ajv does not well support custom error message.
|
|
62
|
+
*
|
|
63
|
+
* @param config the validated config passed from ajv
|
|
64
|
+
* @ignore
|
|
65
|
+
*/
|
|
66
|
+
function maybeThrowInvalidVersions(config) {
|
|
67
|
+
var _a, _b, _c, _d, _e, _f;
|
|
68
|
+
const checkItems = [
|
|
69
|
+
{
|
|
70
|
+
name: 'android.compileSdkVersion',
|
|
71
|
+
configVersion: (_a = config.android) === null || _a === void 0 ? void 0 : _a.compileSdkVersion,
|
|
72
|
+
minimalVersion: EXPO_SDK_MINIMAL_SUPPORTED_VERSIONS.android.compileSdkVersion,
|
|
73
|
+
},
|
|
74
|
+
{
|
|
75
|
+
name: 'android.targetSdkVersion',
|
|
76
|
+
configVersion: (_b = config.android) === null || _b === void 0 ? void 0 : _b.targetSdkVersion,
|
|
77
|
+
minimalVersion: EXPO_SDK_MINIMAL_SUPPORTED_VERSIONS.android.targetSdkVersion,
|
|
78
|
+
},
|
|
79
|
+
{
|
|
80
|
+
name: 'android.kotlinVersion',
|
|
81
|
+
configVersion: (_c = config.android) === null || _c === void 0 ? void 0 : _c.kotlinVersion,
|
|
82
|
+
minimalVersion: EXPO_SDK_MINIMAL_SUPPORTED_VERSIONS.android.kotlinVersion,
|
|
83
|
+
},
|
|
84
|
+
{
|
|
85
|
+
name: 'ios.deploymentTarget',
|
|
86
|
+
configVersion: (_d = config.ios) === null || _d === void 0 ? void 0 : _d.deploymentTarget,
|
|
87
|
+
minimalVersion: EXPO_SDK_MINIMAL_SUPPORTED_VERSIONS.ios.deploymentTarget,
|
|
88
|
+
},
|
|
89
|
+
];
|
|
90
|
+
for (const { name, configVersion, minimalVersion } of checkItems) {
|
|
91
|
+
if (typeof configVersion === 'number' &&
|
|
92
|
+
typeof minimalVersion === 'number' &&
|
|
93
|
+
configVersion < minimalVersion) {
|
|
94
|
+
throw new Error(`\`${name}\` needs to be at least version ${minimalVersion}.`);
|
|
95
|
+
}
|
|
96
|
+
if (typeof configVersion === 'string' &&
|
|
97
|
+
typeof minimalVersion === 'string' &&
|
|
98
|
+
semver_1.default.lt((_e = semver_1.default.coerce(configVersion)) !== null && _e !== void 0 ? _e : '0.0.0', (_f = semver_1.default.coerce(minimalVersion)) !== null && _f !== void 0 ? _f : '0.0.0')) {
|
|
99
|
+
throw new Error(`\`${name}\` needs to be at least version ${minimalVersion}.`);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* @ignore
|
|
105
|
+
*/
|
|
106
|
+
function validateConfig(config) {
|
|
107
|
+
const validate = new ajv_1.default().compile(schema);
|
|
108
|
+
if (!validate(config)) {
|
|
109
|
+
throw new Error('Invalid expo-build-properties config: ' + JSON.stringify(validate.errors));
|
|
110
|
+
}
|
|
111
|
+
maybeThrowInvalidVersions(config);
|
|
112
|
+
return config;
|
|
113
|
+
}
|
|
114
|
+
exports.validateConfig = validateConfig;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { ConfigPlugin } from '@expo/config-plugins';
|
|
2
|
+
import { PluginConfigType } from './pluginConfig';
|
|
3
|
+
/**
|
|
4
|
+
* Config plugin to customize native Android or iOS build properties for managed apps
|
|
5
|
+
*
|
|
6
|
+
* @param config ExpoConfig
|
|
7
|
+
* @param props Configuration for the config plugin
|
|
8
|
+
*/
|
|
9
|
+
export declare const withBuildProperties: ConfigPlugin<PluginConfigType>;
|
|
10
|
+
export default withBuildProperties;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.withBuildProperties = void 0;
|
|
4
|
+
const android_1 = require("./android");
|
|
5
|
+
const ios_1 = require("./ios");
|
|
6
|
+
const pluginConfig_1 = require("./pluginConfig");
|
|
7
|
+
/**
|
|
8
|
+
* Config plugin to customize native Android or iOS build properties for managed apps
|
|
9
|
+
*
|
|
10
|
+
* @param config ExpoConfig
|
|
11
|
+
* @param props Configuration for the config plugin
|
|
12
|
+
*/
|
|
13
|
+
const withBuildProperties = (config, props) => {
|
|
14
|
+
const pluginConfig = (0, pluginConfig_1.validateConfig)(props || {});
|
|
15
|
+
config = (0, android_1.withAndroidBuildProperties)(config, pluginConfig);
|
|
16
|
+
config = (0, android_1.withAndroidProguardRules)(config, pluginConfig);
|
|
17
|
+
config = (0, ios_1.withIosBuildProperties)(config, pluginConfig);
|
|
18
|
+
config = (0, ios_1.withIosDeploymentTarget)(config, pluginConfig);
|
|
19
|
+
return config;
|
|
20
|
+
};
|
|
21
|
+
exports.withBuildProperties = withBuildProperties;
|
|
22
|
+
exports.default = exports.withBuildProperties;
|
package/jest.config.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
module.exports = require('expo-module-scripts/jest-preset-plugin');
|
package/package.json
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "expo-build-properties",
|
|
3
|
+
"version": "0.0.0",
|
|
4
|
+
"description": "Config plugin to customize native build properties on prebuild",
|
|
5
|
+
"main": "build/withBuildProperties.js",
|
|
6
|
+
"types": "build/withBuildProperties.d.ts",
|
|
7
|
+
"scripts": {
|
|
8
|
+
"build": "expo-module build",
|
|
9
|
+
"clean": "expo-module clean",
|
|
10
|
+
"lint": "expo-module lint",
|
|
11
|
+
"test": "expo-module test",
|
|
12
|
+
"prepare": "expo-module prepare",
|
|
13
|
+
"prepublishOnly": "expo-module prepublishOnly",
|
|
14
|
+
"expo-module": "expo-module"
|
|
15
|
+
},
|
|
16
|
+
"keywords": [
|
|
17
|
+
"react-native",
|
|
18
|
+
"expo",
|
|
19
|
+
"build",
|
|
20
|
+
"build-properties"
|
|
21
|
+
],
|
|
22
|
+
"repository": {
|
|
23
|
+
"type": "git",
|
|
24
|
+
"url": "https://github.com/expo/expo.git",
|
|
25
|
+
"directory": "packages/expo-build-properties"
|
|
26
|
+
},
|
|
27
|
+
"bugs": {
|
|
28
|
+
"url": "https://github.com/expo/expo/issues"
|
|
29
|
+
},
|
|
30
|
+
"author": "650 Industries, Inc.",
|
|
31
|
+
"license": "MIT",
|
|
32
|
+
"homepage": "https://docs.expo.dev/versions/latest/sdk/build-properties",
|
|
33
|
+
"dependencies": {
|
|
34
|
+
"@expo/config-plugins": "~4.1.4",
|
|
35
|
+
"ajv": "^8.11.0",
|
|
36
|
+
"semver": "^7.3.5"
|
|
37
|
+
},
|
|
38
|
+
"devDependencies": {
|
|
39
|
+
"expo-module-scripts": "^2.0.0"
|
|
40
|
+
},
|
|
41
|
+
"jest": {
|
|
42
|
+
"preset": "expo-module-scripts"
|
|
43
|
+
},
|
|
44
|
+
"peerDependencies": {
|
|
45
|
+
"expo": "*"
|
|
46
|
+
},
|
|
47
|
+
"gitHead": "6720e2f264c7439062be002ea343f33090aa89f8"
|
|
48
|
+
}
|
package/src/android.ts
ADDED
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import { AndroidConfig, ConfigPlugin, withDangerousMod } from '@expo/config-plugins';
|
|
2
|
+
import {
|
|
3
|
+
mergeContents,
|
|
4
|
+
removeContents,
|
|
5
|
+
MergeResults,
|
|
6
|
+
} from '@expo/config-plugins/build/utils/generateCode';
|
|
7
|
+
import fs from 'fs';
|
|
8
|
+
import path from 'path';
|
|
9
|
+
|
|
10
|
+
import type { PluginConfigType } from './pluginConfig';
|
|
11
|
+
|
|
12
|
+
const { createBuildGradlePropsConfigPlugin } = AndroidConfig.BuildProperties;
|
|
13
|
+
|
|
14
|
+
export const withAndroidBuildProperties = createBuildGradlePropsConfigPlugin<PluginConfigType>(
|
|
15
|
+
[
|
|
16
|
+
{
|
|
17
|
+
propName: 'android.compileSdkVersion',
|
|
18
|
+
propValueGetter: (config) => config.android?.compileSdkVersion?.toString(),
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
propName: 'android.targetSdkVersion',
|
|
22
|
+
propValueGetter: (config) => config.android?.targetSdkVersion?.toString(),
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
propName: 'android.buildToolsVersion',
|
|
26
|
+
propValueGetter: (config) => config.android?.buildToolsVersion,
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
propName: 'android.kotlinVersion',
|
|
30
|
+
propValueGetter: (config) => config.android?.kotlinVersion,
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
propName: 'android.packagingOptions.pickFirsts',
|
|
34
|
+
propValueGetter: (config) => config.android?.packagingOptions?.pickFirst?.join(','),
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
propName: 'android.packagingOptions.excludes',
|
|
38
|
+
propValueGetter: (config) => config.android?.packagingOptions?.exclude?.join(','),
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
propName: 'android.packagingOptions.merges',
|
|
42
|
+
propValueGetter: (config) => config.android?.packagingOptions?.merge?.join(','),
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
propName: 'android.packagingOptions.doNotStrip',
|
|
46
|
+
propValueGetter: (config) => config.android?.packagingOptions?.doNotStrip?.join(','),
|
|
47
|
+
},
|
|
48
|
+
],
|
|
49
|
+
'withAndroidBuildProperties'
|
|
50
|
+
);
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Appends `props.android.extraProguardRules` content into `android/app/proguard-rules.pro`
|
|
54
|
+
*/
|
|
55
|
+
export const withAndroidProguardRules: ConfigPlugin<PluginConfigType> = (config, props) => {
|
|
56
|
+
return withDangerousMod(config, [
|
|
57
|
+
'android',
|
|
58
|
+
async (config) => {
|
|
59
|
+
const extraProguardRules = props.android?.extraProguardRules ?? null;
|
|
60
|
+
const proguardRulesFile = path.join(
|
|
61
|
+
config.modRequest.platformProjectRoot,
|
|
62
|
+
'app',
|
|
63
|
+
'proguard-rules.pro'
|
|
64
|
+
);
|
|
65
|
+
|
|
66
|
+
const contents = await fs.promises.readFile(proguardRulesFile, 'utf8');
|
|
67
|
+
const newContents = updateAndroidProguardRules(contents, extraProguardRules);
|
|
68
|
+
if (newContents) {
|
|
69
|
+
await fs.promises.writeFile(proguardRulesFile, newContents);
|
|
70
|
+
}
|
|
71
|
+
return config;
|
|
72
|
+
},
|
|
73
|
+
]);
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Update `newProguardRules` to original `proguard-rules.pro` contents if needed
|
|
78
|
+
*
|
|
79
|
+
* @param contents the original `proguard-rules.pro` contents
|
|
80
|
+
* @param newProguardRules new proguard rules to add. If the value is null, the generated proguard rules will be cleanup
|
|
81
|
+
* @returns return string when results is updated or return null when nothing changed.
|
|
82
|
+
*/
|
|
83
|
+
export function updateAndroidProguardRules(
|
|
84
|
+
contents: string,
|
|
85
|
+
newProguardRules: string | null
|
|
86
|
+
): string | null {
|
|
87
|
+
const mergeTag = 'expo-build-properties';
|
|
88
|
+
|
|
89
|
+
let mergeResults: MergeResults;
|
|
90
|
+
if (newProguardRules) {
|
|
91
|
+
mergeResults = mergeContents({
|
|
92
|
+
tag: mergeTag,
|
|
93
|
+
src: contents,
|
|
94
|
+
newSrc: newProguardRules,
|
|
95
|
+
anchor: /^/,
|
|
96
|
+
offset: contents.length,
|
|
97
|
+
comment: '#',
|
|
98
|
+
});
|
|
99
|
+
} else {
|
|
100
|
+
mergeResults = removeContents({
|
|
101
|
+
tag: mergeTag,
|
|
102
|
+
src: contents,
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
if (mergeResults.didMerge || mergeResults.didClear) {
|
|
107
|
+
return mergeResults.contents;
|
|
108
|
+
}
|
|
109
|
+
return null;
|
|
110
|
+
}
|
package/src/ios.ts
ADDED
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { IOSConfig, ConfigPlugin, withXcodeProject, XcodeProject } from '@expo/config-plugins';
|
|
2
|
+
|
|
3
|
+
import type { PluginConfigType } from './pluginConfig';
|
|
4
|
+
|
|
5
|
+
const { createBuildPodfilePropsConfigPlugin } = IOSConfig.BuildProperties;
|
|
6
|
+
|
|
7
|
+
export const withIosBuildProperties = createBuildPodfilePropsConfigPlugin<PluginConfigType>(
|
|
8
|
+
[
|
|
9
|
+
{
|
|
10
|
+
propName: 'ios.useFrameworks',
|
|
11
|
+
propValueGetter: (config) => config.ios?.useFrameworks,
|
|
12
|
+
},
|
|
13
|
+
],
|
|
14
|
+
'withIosBuildProperties'
|
|
15
|
+
);
|
|
16
|
+
|
|
17
|
+
export const withIosDeploymentTarget: ConfigPlugin<PluginConfigType> = (config, props) => {
|
|
18
|
+
const deploymentTarget = props.ios?.deploymentTarget;
|
|
19
|
+
if (!deploymentTarget) {
|
|
20
|
+
return config;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
// Updates deployment target in app xcodeproj
|
|
24
|
+
config = withIosDeploymentTargetXcodeProject(config, { deploymentTarget });
|
|
25
|
+
|
|
26
|
+
// Updates deployement target in Podfile (Pods project)
|
|
27
|
+
config = withIosDeploymentTargetPodfile(config, props);
|
|
28
|
+
|
|
29
|
+
return config;
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
const withIosDeploymentTargetXcodeProject: ConfigPlugin<{ deploymentTarget: string }> = (
|
|
33
|
+
config,
|
|
34
|
+
props
|
|
35
|
+
) => {
|
|
36
|
+
return withXcodeProject(config, (config) => {
|
|
37
|
+
config.modResults = updateDeploymentTargetXcodeProject(
|
|
38
|
+
config.modResults,
|
|
39
|
+
props.deploymentTarget
|
|
40
|
+
);
|
|
41
|
+
return config;
|
|
42
|
+
});
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
function updateDeploymentTargetXcodeProject(
|
|
46
|
+
project: XcodeProject,
|
|
47
|
+
deploymentTarget: string
|
|
48
|
+
): XcodeProject {
|
|
49
|
+
const { Target } = IOSConfig;
|
|
50
|
+
const targetBuildConfigListIds = Target.getNativeTargets(project)
|
|
51
|
+
.filter(([_, target]) => Target.isTargetOfType(target, Target.TargetType.APPLICATION))
|
|
52
|
+
.map(([_, target]) => target.buildConfigurationList);
|
|
53
|
+
|
|
54
|
+
for (const buildConfigListId of targetBuildConfigListIds) {
|
|
55
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
56
|
+
for (const [_, configurations] of IOSConfig.XcodeUtils.getBuildConfigurationsForListId(
|
|
57
|
+
project,
|
|
58
|
+
buildConfigListId
|
|
59
|
+
)) {
|
|
60
|
+
const { buildSettings } = configurations;
|
|
61
|
+
if (buildSettings?.IPHONEOS_DEPLOYMENT_TARGET) {
|
|
62
|
+
buildSettings.IPHONEOS_DEPLOYMENT_TARGET = deploymentTarget;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
return project;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
const withIosDeploymentTargetPodfile = createBuildPodfilePropsConfigPlugin<PluginConfigType>(
|
|
70
|
+
[
|
|
71
|
+
{
|
|
72
|
+
propName: 'ios.deploymentTarget',
|
|
73
|
+
propValueGetter: (config) => config.ios?.deploymentTarget,
|
|
74
|
+
},
|
|
75
|
+
],
|
|
76
|
+
'withIosDeploymentTargetPodfile'
|
|
77
|
+
);
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
import Ajv, { JSONSchemaType } from 'ajv';
|
|
2
|
+
import semver from 'semver';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* The minimal supported versions. These values should align to SDK
|
|
6
|
+
* @ignore
|
|
7
|
+
*/
|
|
8
|
+
const EXPO_SDK_MINIMAL_SUPPORTED_VERSIONS = {
|
|
9
|
+
android: {
|
|
10
|
+
compileSdkVersion: 31,
|
|
11
|
+
targetSdkVersion: 31,
|
|
12
|
+
kotlinVersion: '1.6.10',
|
|
13
|
+
},
|
|
14
|
+
ios: {
|
|
15
|
+
deploymentTarget: '12.0',
|
|
16
|
+
},
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Configuration for `expo-build-properties`
|
|
21
|
+
*/
|
|
22
|
+
export interface PluginConfigType {
|
|
23
|
+
android?: PluginConfigTypeAndroid;
|
|
24
|
+
ios?: PluginConfigTypeIos;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Config for Android native build properties
|
|
29
|
+
*/
|
|
30
|
+
export interface PluginConfigTypeAndroid {
|
|
31
|
+
/** Override the default `compileSdkVersion` version number in `build.gradle` */
|
|
32
|
+
compileSdkVersion?: number;
|
|
33
|
+
|
|
34
|
+
/** Override the default `targetSdkVersion` version number in `build.gradle` */
|
|
35
|
+
targetSdkVersion?: number;
|
|
36
|
+
|
|
37
|
+
/** Override the default `buildToolsVersion` version number in `build.gradle` */
|
|
38
|
+
buildToolsVersion?: string;
|
|
39
|
+
|
|
40
|
+
/** Override the default Kotlin version when building the app */
|
|
41
|
+
kotlinVersion?: string;
|
|
42
|
+
|
|
43
|
+
/** Enable Proguard (R8) in release builds to obfuscate Java code and reduce app size */
|
|
44
|
+
enableProguardInReleaseBuilds?: boolean;
|
|
45
|
+
|
|
46
|
+
/** Append custom [Proguard rules](https://www.guardsquare.com/manual/configuration/usage) to `android/app/proguard-rules.pro` */
|
|
47
|
+
extraProguardRules?: string;
|
|
48
|
+
|
|
49
|
+
/** AGP [PackagingOptions](https://developer.android.com/reference/tools/gradle-api/7.0/com/android/build/api/dsl/PackagingOptions) */
|
|
50
|
+
packagingOptions?: PluginConfigTypeAndroidPackagingOptions;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Config for iOS native build properties
|
|
55
|
+
*/
|
|
56
|
+
export interface PluginConfigTypeIos {
|
|
57
|
+
/**
|
|
58
|
+
* Override the default iOS *Deployment Target* version in the following projects:
|
|
59
|
+
* - in CocoaPods projects
|
|
60
|
+
* - `PBXNativeTarget` with `com.apple.product-type.application` productType in the app project
|
|
61
|
+
*/
|
|
62
|
+
deploymentTarget?: string;
|
|
63
|
+
|
|
64
|
+
/** Enable [`use_frameworks!`](https://guides.cocoapods.org/syntax/podfile.html#use_frameworks_bang) in `Podfile` */
|
|
65
|
+
useFrameworks?: 'static' | 'dynamic';
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* AGP [PackagingOptions](https://developer.android.com/reference/tools/gradle-api/7.0/com/android/build/api/dsl/PackagingOptions)
|
|
70
|
+
*/
|
|
71
|
+
export interface PluginConfigTypeAndroidPackagingOptions {
|
|
72
|
+
/** Adds a first-pick pattern */
|
|
73
|
+
pickFirst?: string[];
|
|
74
|
+
|
|
75
|
+
/** Adds an excluded pattern */
|
|
76
|
+
exclude?: string[];
|
|
77
|
+
|
|
78
|
+
/** Adds a merge pattern */
|
|
79
|
+
merge?: string[];
|
|
80
|
+
|
|
81
|
+
/** Adds a doNotStrip pattern */
|
|
82
|
+
doNotStrip?: string[];
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
const schema: JSONSchemaType<PluginConfigType> = {
|
|
86
|
+
type: 'object',
|
|
87
|
+
properties: {
|
|
88
|
+
android: {
|
|
89
|
+
type: 'object',
|
|
90
|
+
properties: {
|
|
91
|
+
compileSdkVersion: { type: 'integer', nullable: true },
|
|
92
|
+
targetSdkVersion: { type: 'integer', nullable: true },
|
|
93
|
+
buildToolsVersion: { type: 'string', nullable: true },
|
|
94
|
+
kotlinVersion: { type: 'string', nullable: true },
|
|
95
|
+
|
|
96
|
+
enableProguardInReleaseBuilds: { type: 'boolean', nullable: true },
|
|
97
|
+
extraProguardRules: { type: 'string', nullable: true },
|
|
98
|
+
|
|
99
|
+
packagingOptions: {
|
|
100
|
+
type: 'object',
|
|
101
|
+
properties: {
|
|
102
|
+
pickFirst: { type: 'array', items: { type: 'string' }, nullable: true },
|
|
103
|
+
exclude: { type: 'array', items: { type: 'string' }, nullable: true },
|
|
104
|
+
merge: { type: 'array', items: { type: 'string' }, nullable: true },
|
|
105
|
+
doNotStrip: { type: 'array', items: { type: 'string' }, nullable: true },
|
|
106
|
+
},
|
|
107
|
+
nullable: true,
|
|
108
|
+
},
|
|
109
|
+
},
|
|
110
|
+
nullable: true,
|
|
111
|
+
},
|
|
112
|
+
ios: {
|
|
113
|
+
type: 'object',
|
|
114
|
+
properties: {
|
|
115
|
+
deploymentTarget: { type: 'string', pattern: '\\d+\\.\\d+', nullable: true },
|
|
116
|
+
useFrameworks: { type: 'string', enum: ['static', 'dynamic'], nullable: true },
|
|
117
|
+
},
|
|
118
|
+
nullable: true,
|
|
119
|
+
},
|
|
120
|
+
},
|
|
121
|
+
};
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Check versions to meet expo minimal supported versions.
|
|
125
|
+
* Will throw error message whenever there are invalid versions.
|
|
126
|
+
* For the implementation, we check items one by one because ajv does not well support custom error message.
|
|
127
|
+
*
|
|
128
|
+
* @param config the validated config passed from ajv
|
|
129
|
+
* @ignore
|
|
130
|
+
*/
|
|
131
|
+
function maybeThrowInvalidVersions(config: PluginConfigType) {
|
|
132
|
+
const checkItems = [
|
|
133
|
+
{
|
|
134
|
+
name: 'android.compileSdkVersion',
|
|
135
|
+
configVersion: config.android?.compileSdkVersion,
|
|
136
|
+
minimalVersion: EXPO_SDK_MINIMAL_SUPPORTED_VERSIONS.android.compileSdkVersion,
|
|
137
|
+
},
|
|
138
|
+
{
|
|
139
|
+
name: 'android.targetSdkVersion',
|
|
140
|
+
configVersion: config.android?.targetSdkVersion,
|
|
141
|
+
minimalVersion: EXPO_SDK_MINIMAL_SUPPORTED_VERSIONS.android.targetSdkVersion,
|
|
142
|
+
},
|
|
143
|
+
{
|
|
144
|
+
name: 'android.kotlinVersion',
|
|
145
|
+
configVersion: config.android?.kotlinVersion,
|
|
146
|
+
minimalVersion: EXPO_SDK_MINIMAL_SUPPORTED_VERSIONS.android.kotlinVersion,
|
|
147
|
+
},
|
|
148
|
+
{
|
|
149
|
+
name: 'ios.deploymentTarget',
|
|
150
|
+
configVersion: config.ios?.deploymentTarget,
|
|
151
|
+
minimalVersion: EXPO_SDK_MINIMAL_SUPPORTED_VERSIONS.ios.deploymentTarget,
|
|
152
|
+
},
|
|
153
|
+
];
|
|
154
|
+
|
|
155
|
+
for (const { name, configVersion, minimalVersion } of checkItems) {
|
|
156
|
+
if (
|
|
157
|
+
typeof configVersion === 'number' &&
|
|
158
|
+
typeof minimalVersion === 'number' &&
|
|
159
|
+
configVersion < minimalVersion
|
|
160
|
+
) {
|
|
161
|
+
throw new Error(`\`${name}\` needs to be at least version ${minimalVersion}.`);
|
|
162
|
+
}
|
|
163
|
+
if (
|
|
164
|
+
typeof configVersion === 'string' &&
|
|
165
|
+
typeof minimalVersion === 'string' &&
|
|
166
|
+
semver.lt(semver.coerce(configVersion) ?? '0.0.0', semver.coerce(minimalVersion) ?? '0.0.0')
|
|
167
|
+
) {
|
|
168
|
+
throw new Error(`\`${name}\` needs to be at least version ${minimalVersion}.`);
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
/**
|
|
174
|
+
* @ignore
|
|
175
|
+
*/
|
|
176
|
+
export function validateConfig(config: any): PluginConfigType {
|
|
177
|
+
const validate = new Ajv().compile(schema);
|
|
178
|
+
if (!validate(config)) {
|
|
179
|
+
throw new Error('Invalid expo-build-properties config: ' + JSON.stringify(validate.errors));
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
maybeThrowInvalidVersions(config);
|
|
183
|
+
return config;
|
|
184
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { ConfigPlugin } from '@expo/config-plugins';
|
|
2
|
+
|
|
3
|
+
import { withAndroidBuildProperties, withAndroidProguardRules } from './android';
|
|
4
|
+
import { withIosBuildProperties, withIosDeploymentTarget } from './ios';
|
|
5
|
+
import { PluginConfigType, validateConfig } from './pluginConfig';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Config plugin to customize native Android or iOS build properties for managed apps
|
|
9
|
+
*
|
|
10
|
+
* @param config ExpoConfig
|
|
11
|
+
* @param props Configuration for the config plugin
|
|
12
|
+
*/
|
|
13
|
+
export const withBuildProperties: ConfigPlugin<PluginConfigType> = (config, props) => {
|
|
14
|
+
const pluginConfig = validateConfig(props || {});
|
|
15
|
+
|
|
16
|
+
config = withAndroidBuildProperties(config, pluginConfig);
|
|
17
|
+
config = withAndroidProguardRules(config, pluginConfig);
|
|
18
|
+
config = withIosBuildProperties(config, pluginConfig);
|
|
19
|
+
config = withIosDeploymentTarget(config, pluginConfig);
|
|
20
|
+
|
|
21
|
+
return config;
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
export default withBuildProperties;
|