@forthtilliath/expo-config-plugins 0.1.0 → 0.3.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/README.md +27 -2
- package/dist/transforms.d.ts +33 -0
- package/dist/transforms.d.ts.map +1 -1
- package/dist/transforms.js +62 -0
- package/dist/withKotlinJvmTarget.d.ts +14 -0
- package/dist/withKotlinJvmTarget.d.ts.map +1 -0
- package/dist/withKotlinJvmTarget.js +17 -0
- package/dist/withReleaseRemovedPermissions.d.ts +17 -0
- package/dist/withReleaseRemovedPermissions.d.ts.map +1 -0
- package/dist/withReleaseRemovedPermissions.js +43 -0
- package/package.json +11 -9
package/README.md
CHANGED
|
@@ -19,7 +19,8 @@ npm install --save-dev @forthtilliath/expo-config-plugins
|
|
|
19
19
|
{ "propertyPrefix": "MYAPP" }
|
|
20
20
|
],
|
|
21
21
|
"@forthtilliath/expo-config-plugins/withAndroidAbis",
|
|
22
|
-
"@forthtilliath/expo-config-plugins/withShortCxxPath"
|
|
22
|
+
"@forthtilliath/expo-config-plugins/withShortCxxPath",
|
|
23
|
+
"@forthtilliath/expo-config-plugins/withKotlinJvmTarget"
|
|
23
24
|
]
|
|
24
25
|
}
|
|
25
26
|
}
|
|
@@ -59,9 +60,33 @@ On Windows, release builds can overflow the 260-character path limit inside `and
|
|
|
59
60
|
| ------------ | -------- | --------------------------------- |
|
|
60
61
|
| `stagingDir` | `string` | `C:/rncxx` on Windows, else unset |
|
|
61
62
|
|
|
63
|
+
## `withKotlinJvmTarget` — one JVM target for Kotlin
|
|
64
|
+
|
|
65
|
+
Some native modules (e.g. `expo-dynamic-app-icon`) compile their Kotlin code for another JVM target than the project's Java code, and the build fails with "Inconsistent JVM-target compatibility". This plugin appends a block to `android/build.gradle` forcing every Kotlin compile task, in every subproject, to the same target.
|
|
66
|
+
|
|
67
|
+
| Option | Type | Default |
|
|
68
|
+
| ----------- | -------- | ------- |
|
|
69
|
+
| `jvmTarget` | `string` | `"17"` |
|
|
70
|
+
|
|
71
|
+
## `withReleaseRemovedPermissions` — a release APK that can't go online
|
|
72
|
+
|
|
73
|
+
For an app that works fully offline (personal, health or intimate data), removing the `INTERNET` permission from the **release** APK makes Android itself guarantee that nothing can leave the phone — whatever a dependency (an SDK, a library's telemetry) tries. Debug builds keep the permission: Metro needs the network.
|
|
74
|
+
|
|
75
|
+
```json
|
|
76
|
+
"@forthtilliath/expo-config-plugins/withReleaseRemovedPermissions"
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
The plugin writes `android/app/src/release/AndroidManifest.xml`, merged by Gradle over the main manifest and every library's, with `tools:node="remove"` on each permission: it's dropped whoever declared it. It refuses to overwrite a release manifest it didn't generate, and fails the prebuild on anything but permission names (they end up in XML). Check the result with `aapt dump permissions app-release.apk`.
|
|
80
|
+
|
|
81
|
+
| Option | Type | Default | Notes |
|
|
82
|
+
| ------------- | ---------- | -------------- | ----------------------------------------------------------------------------------------- |
|
|
83
|
+
| `permissions` | `string[]` | `["INTERNET"]` | Short (`ACCESS_NETWORK_STATE`) or full (`com.google.android.gms.permission.AD_ID`) names. |
|
|
84
|
+
|
|
85
|
+
Remove it the day a feature really needs the network (update check, Drive backup…): without `INTERNET`, every request fails.
|
|
86
|
+
|
|
62
87
|
## Testing your own setup
|
|
63
88
|
|
|
64
|
-
The transforms behind the plugins are exported as pure functions from `@forthtilliath/expo-config-plugins/transforms` (`applyReleaseSigning`, `applyAndroidAbis`, `applyShortCxxPath`).
|
|
89
|
+
The transforms behind the plugins are exported as pure functions from `@forthtilliath/expo-config-plugins/transforms` (`applyReleaseSigning`, `applyAndroidAbis`, `applyShortCxxPath`, `applyKotlinJvmTarget`, `buildReleaseRemovedPermissionsManifest`).
|
|
65
90
|
|
|
66
91
|
## Scripts
|
|
67
92
|
|
package/dist/transforms.d.ts
CHANGED
|
@@ -38,6 +38,20 @@ export declare function applyAndroidAbis(properties: GradlePropertiesItem[], abi
|
|
|
38
38
|
* @throws When the `namespace` line to anchor on isn't found.
|
|
39
39
|
*/
|
|
40
40
|
export declare function applyShortCxxPath(contents: string, stagingDir: string): string;
|
|
41
|
+
/**
|
|
42
|
+
* Appends to the root `android/build.gradle` a block forcing every Kotlin
|
|
43
|
+
* compile task, in every subproject, to target `jvmTarget` — the Java code's
|
|
44
|
+
* target: a native module compiling its Kotlin for another one (e.g.
|
|
45
|
+
* expo-dynamic-app-icon) fails the build with "Inconsistent JVM-target
|
|
46
|
+
* compatibility". Already-patched contents are returned as is.
|
|
47
|
+
*
|
|
48
|
+
* @throws When `jvmTarget` isn't a JVM version such as `17` or `1.8`.
|
|
49
|
+
*/
|
|
50
|
+
export declare function applyKotlinJvmTarget(contents: string, jvmTarget?: string): string;
|
|
51
|
+
export interface KotlinJvmTargetOptions {
|
|
52
|
+
/** JVM version Kotlin compiles for, e.g. `"21"`. @defaultValue `"17"` */
|
|
53
|
+
jvmTarget?: string;
|
|
54
|
+
}
|
|
41
55
|
export interface ReleaseSigningOptions {
|
|
42
56
|
/**
|
|
43
57
|
* Prefix of the Gradle properties holding the upload key, e.g. `MYAPP` for
|
|
@@ -57,4 +71,23 @@ export interface ShortCxxPathOptions {
|
|
|
57
71
|
*/
|
|
58
72
|
stagingDir?: string;
|
|
59
73
|
}
|
|
74
|
+
export interface ReleaseRemovedPermissionsOptions {
|
|
75
|
+
/**
|
|
76
|
+
* Android permissions to strip from the release APK only, short (`INTERNET`)
|
|
77
|
+
* or full (`android.permission.INTERNET`) names.
|
|
78
|
+
*
|
|
79
|
+
* @defaultValue `["INTERNET"]`
|
|
80
|
+
*/
|
|
81
|
+
permissions?: string[];
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* The `android/app/src/release/AndroidManifest.xml` removing `permissions`
|
|
85
|
+
* from the release build: merged over the main manifest and every library's,
|
|
86
|
+
* `tools:node="remove"` drops the permission whoever declared it. Debug
|
|
87
|
+
* builds keep it (Metro needs `INTERNET`).
|
|
88
|
+
*
|
|
89
|
+
* @throws When the list is empty or holds anything but permission names —
|
|
90
|
+
* the names end up in XML, nothing else is let through.
|
|
91
|
+
*/
|
|
92
|
+
export declare function buildReleaseRemovedPermissionsManifest(permissions?: readonly string[]): string;
|
|
60
93
|
//# sourceMappingURL=transforms.d.ts.map
|
package/dist/transforms.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"transforms.d.ts","sourceRoot":"","sources":["../src/transforms.ts"],"names":[],"mappings":"AAoBA;;;;;;;;;GASG;AACH,wBAAgB,mBAAmB,CACjC,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,GAAG,SAAS,GACzB,MAAM,CAmBR;AAED,qFAAqF;AACrF,MAAM,MAAM,oBAAoB,GAC5B;IAAE,IAAI,EAAE,UAAU,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GAChD;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GAClC;IAAE,IAAI,EAAE,OAAO,CAAA;CAAE,CAAC;AAEtB,4CAA4C;AAC5C,eAAO,MAAM,QAAQ,EAAE,SAAS,MAAM,EAAiC,CAAC;AAExE;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAC9B,UAAU,EAAE,oBAAoB,EAAE,EAClC,IAAI,GAAE,SAAS,MAAM,EAAa,GACjC,oBAAoB,EAAE,CAcxB;AAED;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAC/B,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,MAAM,GACjB,MAAM,CAiBR;AAED,MAAM,WAAW,qBAAqB;IACpC;;;;OAIG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,kBAAkB;IACjC,sEAAsE;IACtE,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;CACjB;AAED,MAAM,WAAW,mBAAmB;IAClC;;;OAGG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB"}
|
|
1
|
+
{"version":3,"file":"transforms.d.ts","sourceRoot":"","sources":["../src/transforms.ts"],"names":[],"mappings":"AAoBA;;;;;;;;;GASG;AACH,wBAAgB,mBAAmB,CACjC,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,GAAG,SAAS,GACzB,MAAM,CAmBR;AAED,qFAAqF;AACrF,MAAM,MAAM,oBAAoB,GAC5B;IAAE,IAAI,EAAE,UAAU,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GAChD;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GAClC;IAAE,IAAI,EAAE,OAAO,CAAA;CAAE,CAAC;AAEtB,4CAA4C;AAC5C,eAAO,MAAM,QAAQ,EAAE,SAAS,MAAM,EAAiC,CAAC;AAExE;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAC9B,UAAU,EAAE,oBAAoB,EAAE,EAClC,IAAI,GAAE,SAAS,MAAM,EAAa,GACjC,oBAAoB,EAAE,CAcxB;AAED;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAC/B,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,MAAM,GACjB,MAAM,CAiBR;AAID;;;;;;;;GAQG;AACH,wBAAgB,oBAAoB,CAClC,QAAQ,EAAE,MAAM,EAChB,SAAS,SAAO,GACf,MAAM,CAkBR;AAED,MAAM,WAAW,sBAAsB;IACrC,yEAAyE;IACzE,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,qBAAqB;IACpC;;;;OAIG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,kBAAkB;IACjC,sEAAsE;IACtE,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;CACjB;AAED,MAAM,WAAW,mBAAmB;IAClC;;;OAGG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,gCAAgC;IAC/C;;;;;OAKG;IACH,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;CACxB;AAID;;;;;;;;GAQG;AACH,wBAAgB,sCAAsC,CACpD,WAAW,GAAE,SAAS,MAAM,EAAiB,GAC5C,MAAM,CA0BR"}
|
package/dist/transforms.js
CHANGED
|
@@ -6,6 +6,8 @@ exports.ARM_ABIS = void 0;
|
|
|
6
6
|
exports.applyReleaseSigning = applyReleaseSigning;
|
|
7
7
|
exports.applyAndroidAbis = applyAndroidAbis;
|
|
8
8
|
exports.applyShortCxxPath = applyShortCxxPath;
|
|
9
|
+
exports.applyKotlinJvmTarget = applyKotlinJvmTarget;
|
|
10
|
+
exports.buildReleaseRemovedPermissionsManifest = buildReleaseRemovedPermissionsManifest;
|
|
9
11
|
/** The `signingConfig signingConfigs.debug` of the `release` build type (not the `debug` one's). */
|
|
10
12
|
const RELEASE_USES_DEBUG_KEY = /(buildTypes\s*\{[\s\S]*?release\s*\{[^}]*?)signingConfig signingConfigs\.debug/;
|
|
11
13
|
function releaseSigningConfig(prefix) {
|
|
@@ -87,3 +89,63 @@ function applyShortCxxPath(contents, stagingDir) {
|
|
|
87
89
|
|
|
88
90
|
namespace`);
|
|
89
91
|
}
|
|
92
|
+
const KOTLIN_JVM_TARGET_MARKER = "withKotlinJvmTarget";
|
|
93
|
+
/**
|
|
94
|
+
* Appends to the root `android/build.gradle` a block forcing every Kotlin
|
|
95
|
+
* compile task, in every subproject, to target `jvmTarget` — the Java code's
|
|
96
|
+
* target: a native module compiling its Kotlin for another one (e.g.
|
|
97
|
+
* expo-dynamic-app-icon) fails the build with "Inconsistent JVM-target
|
|
98
|
+
* compatibility". Already-patched contents are returned as is.
|
|
99
|
+
*
|
|
100
|
+
* @throws When `jvmTarget` isn't a JVM version such as `17` or `1.8`.
|
|
101
|
+
*/
|
|
102
|
+
function applyKotlinJvmTarget(contents, jvmTarget = "17") {
|
|
103
|
+
if (!/^(1\.8|\d{1,2})$/.test(jvmTarget)) {
|
|
104
|
+
throw new Error(`withKotlinJvmTarget: invalid jvmTarget option "${jvmTarget}" (e.g. 17)`);
|
|
105
|
+
}
|
|
106
|
+
if (contents.includes(KOTLIN_JVM_TARGET_MARKER))
|
|
107
|
+
return contents;
|
|
108
|
+
return `${contents.trimEnd()}
|
|
109
|
+
|
|
110
|
+
// ${KOTLIN_JVM_TARGET_MARKER}: Kotlin targets the same JVM as Java (avoids "Inconsistent JVM-target compatibility").
|
|
111
|
+
subprojects {
|
|
112
|
+
tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile).configureEach {
|
|
113
|
+
compilerOptions {
|
|
114
|
+
jvmTarget.set(org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_${jvmTarget.replace(".", "_")})
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
`;
|
|
119
|
+
}
|
|
120
|
+
const PERMISSION_NAME = /^[A-Za-z][A-Za-z0-9_]*(\.[A-Za-z][A-Za-z0-9_]*)*$/;
|
|
121
|
+
/**
|
|
122
|
+
* The `android/app/src/release/AndroidManifest.xml` removing `permissions`
|
|
123
|
+
* from the release build: merged over the main manifest and every library's,
|
|
124
|
+
* `tools:node="remove"` drops the permission whoever declared it. Debug
|
|
125
|
+
* builds keep it (Metro needs `INTERNET`).
|
|
126
|
+
*
|
|
127
|
+
* @throws When the list is empty or holds anything but permission names —
|
|
128
|
+
* the names end up in XML, nothing else is let through.
|
|
129
|
+
*/
|
|
130
|
+
function buildReleaseRemovedPermissionsManifest(permissions = ["INTERNET"]) {
|
|
131
|
+
if (permissions.length === 0) {
|
|
132
|
+
throw new Error("withReleaseRemovedPermissions: empty permissions list");
|
|
133
|
+
}
|
|
134
|
+
const names = permissions.map((permission) => {
|
|
135
|
+
if (!PERMISSION_NAME.test(permission)) {
|
|
136
|
+
throw new Error(`withReleaseRemovedPermissions: invalid permission name "${permission}"`);
|
|
137
|
+
}
|
|
138
|
+
return permission.includes(".")
|
|
139
|
+
? permission
|
|
140
|
+
: `android.permission.${permission}`;
|
|
141
|
+
});
|
|
142
|
+
const lines = [...new Set(names)].map((name) => ` <uses-permission android:name="${name}" tools:node="remove"/>`);
|
|
143
|
+
return `<?xml version="1.0" encoding="utf-8"?>
|
|
144
|
+
<!-- Generated by @forthtilliath/expo-config-plugins/withReleaseRemovedPermissions -->
|
|
145
|
+
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
|
146
|
+
xmlns:tools="http://schemas.android.com/tools">
|
|
147
|
+
|
|
148
|
+
${lines.join("\n")}
|
|
149
|
+
</manifest>
|
|
150
|
+
`;
|
|
151
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { type ConfigPlugin } from "expo/config-plugins";
|
|
2
|
+
import { type KotlinJvmTargetOptions } from "./transforms.js";
|
|
3
|
+
/**
|
|
4
|
+
* Makes every Kotlin compile task target the same JVM as the Java code (17
|
|
5
|
+
* by default): some native modules (e.g. expo-dynamic-app-icon) compile
|
|
6
|
+
* their Kotlin for another target, and the build fails with "Inconsistent
|
|
7
|
+
* JVM-target compatibility".
|
|
8
|
+
*
|
|
9
|
+
* `"@forthtilliath/expo-config-plugins/withKotlinJvmTarget"`, or
|
|
10
|
+
* `["@forthtilliath/expo-config-plugins/withKotlinJvmTarget", { "jvmTarget": "21" }]`
|
|
11
|
+
*/
|
|
12
|
+
declare const withKotlinJvmTarget: ConfigPlugin<KotlinJvmTargetOptions | undefined>;
|
|
13
|
+
export = withKotlinJvmTarget;
|
|
14
|
+
//# sourceMappingURL=withKotlinJvmTarget.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"withKotlinJvmTarget.d.ts","sourceRoot":"","sources":["../src/withKotlinJvmTarget.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,YAAY,EAA0B,MAAM,qBAAqB,CAAC;AAEhF,OAAO,EAEL,KAAK,sBAAsB,EAC5B,MAAM,iBAAiB,CAAC;AAEzB;;;;;;;;GAQG;AACH,QAAA,MAAM,mBAAmB,EAAE,YAAY,CAAC,sBAAsB,GAAG,SAAS,CAUtE,CAAC;AAEL,SAAS,mBAAmB,CAAC"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
const config_plugins_1 = require("expo/config-plugins");
|
|
3
|
+
const transforms_js_1 = require("./transforms.js");
|
|
4
|
+
/**
|
|
5
|
+
* Makes every Kotlin compile task target the same JVM as the Java code (17
|
|
6
|
+
* by default): some native modules (e.g. expo-dynamic-app-icon) compile
|
|
7
|
+
* their Kotlin for another target, and the build fails with "Inconsistent
|
|
8
|
+
* JVM-target compatibility".
|
|
9
|
+
*
|
|
10
|
+
* `"@forthtilliath/expo-config-plugins/withKotlinJvmTarget"`, or
|
|
11
|
+
* `["@forthtilliath/expo-config-plugins/withKotlinJvmTarget", { "jvmTarget": "21" }]`
|
|
12
|
+
*/
|
|
13
|
+
const withKotlinJvmTarget = (config, options) => (0, config_plugins_1.withProjectBuildGradle)(config, (mod) => {
|
|
14
|
+
mod.modResults.contents = (0, transforms_js_1.applyKotlinJvmTarget)(mod.modResults.contents, options?.jvmTarget);
|
|
15
|
+
return mod;
|
|
16
|
+
});
|
|
17
|
+
module.exports = withKotlinJvmTarget;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { type ConfigPlugin } from "expo/config-plugins";
|
|
2
|
+
import { type ReleaseRemovedPermissionsOptions } from "./transforms.js";
|
|
3
|
+
/**
|
|
4
|
+
* Strips permissions from the **release** APK only — `INTERNET` by default:
|
|
5
|
+
* for an app that works fully offline, Android itself then guarantees that
|
|
6
|
+
* no data can leave the phone, whatever a dependency tries. Debug builds
|
|
7
|
+
* keep them (Metro needs the network).
|
|
8
|
+
*
|
|
9
|
+
* Writes `android/app/src/release/AndroidManifest.xml`; refuses to overwrite
|
|
10
|
+
* one it didn't generate.
|
|
11
|
+
*
|
|
12
|
+
* `"@forthtilliath/expo-config-plugins/withReleaseRemovedPermissions"`, or
|
|
13
|
+
* `["@forthtilliath/expo-config-plugins/withReleaseRemovedPermissions", { "permissions": ["INTERNET", "ACCESS_NETWORK_STATE"] }]`
|
|
14
|
+
*/
|
|
15
|
+
declare const withReleaseRemovedPermissions: ConfigPlugin<ReleaseRemovedPermissionsOptions | undefined>;
|
|
16
|
+
export = withReleaseRemovedPermissions;
|
|
17
|
+
//# sourceMappingURL=withReleaseRemovedPermissions.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"withReleaseRemovedPermissions.d.ts","sourceRoot":"","sources":["../src/withReleaseRemovedPermissions.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,YAAY,EAAoB,MAAM,qBAAqB,CAAC;AAI1E,OAAO,EAEL,KAAK,gCAAgC,EACtC,MAAM,iBAAiB,CAAC;AAYzB;;;;;;;;;;;GAWG;AACH,QAAA,MAAM,6BAA6B,EAAE,YAAY,CAC/C,gCAAgC,GAAG,SAAS,CAqB1C,CAAC;AAEL,SAAS,6BAA6B,CAAC"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
const config_plugins_1 = require("expo/config-plugins");
|
|
3
|
+
const promises_1 = require("node:fs/promises");
|
|
4
|
+
const node_path_1 = require("node:path");
|
|
5
|
+
const transforms_js_1 = require("./transforms.js");
|
|
6
|
+
const GENERATED_MARK = "withReleaseRemovedPermissions";
|
|
7
|
+
async function readIfExists(path) {
|
|
8
|
+
try {
|
|
9
|
+
return await (0, promises_1.readFile)(path, "utf8");
|
|
10
|
+
}
|
|
11
|
+
catch {
|
|
12
|
+
return null;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Strips permissions from the **release** APK only — `INTERNET` by default:
|
|
17
|
+
* for an app that works fully offline, Android itself then guarantees that
|
|
18
|
+
* no data can leave the phone, whatever a dependency tries. Debug builds
|
|
19
|
+
* keep them (Metro needs the network).
|
|
20
|
+
*
|
|
21
|
+
* Writes `android/app/src/release/AndroidManifest.xml`; refuses to overwrite
|
|
22
|
+
* one it didn't generate.
|
|
23
|
+
*
|
|
24
|
+
* `"@forthtilliath/expo-config-plugins/withReleaseRemovedPermissions"`, or
|
|
25
|
+
* `["@forthtilliath/expo-config-plugins/withReleaseRemovedPermissions", { "permissions": ["INTERNET", "ACCESS_NETWORK_STATE"] }]`
|
|
26
|
+
*/
|
|
27
|
+
const withReleaseRemovedPermissions = (config, options) => (0, config_plugins_1.withDangerousMod)(config, [
|
|
28
|
+
"android",
|
|
29
|
+
async (mod) => {
|
|
30
|
+
// Built first: invalid options fail the prebuild before any write.
|
|
31
|
+
const manifest = (0, transforms_js_1.buildReleaseRemovedPermissionsManifest)(options?.permissions);
|
|
32
|
+
const dir = (0, node_path_1.join)(mod.modRequest.platformProjectRoot, "app/src/release");
|
|
33
|
+
const path = (0, node_path_1.join)(dir, "AndroidManifest.xml");
|
|
34
|
+
const existing = await readIfExists(path);
|
|
35
|
+
if (existing !== null && !existing.includes(GENERATED_MARK)) {
|
|
36
|
+
throw new Error(`withReleaseRemovedPermissions: ${path} already exists and wasn't generated by this plugin`);
|
|
37
|
+
}
|
|
38
|
+
await (0, promises_1.mkdir)(dir, { recursive: true });
|
|
39
|
+
await (0, promises_1.writeFile)(path, manifest);
|
|
40
|
+
return mod;
|
|
41
|
+
},
|
|
42
|
+
]);
|
|
43
|
+
module.exports = withReleaseRemovedPermissions;
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@forthtilliath/expo-config-plugins",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "Expo config plugins for sideloaded Android apps: release signing with your own key, ARM-only native code, short CMake paths on Windows.",
|
|
3
|
+
"version": "0.3.0",
|
|
4
|
+
"description": "Expo config plugins for sideloaded Android apps: release signing with your own key, ARM-only native code, short CMake paths on Windows, one JVM target for Kotlin, permissions removed from release builds.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"publishConfig": {
|
|
7
7
|
"access": "public"
|
|
@@ -20,6 +20,8 @@
|
|
|
20
20
|
"./withReleaseSigning": "./dist/withReleaseSigning.js",
|
|
21
21
|
"./withAndroidAbis": "./dist/withAndroidAbis.js",
|
|
22
22
|
"./withShortCxxPath": "./dist/withShortCxxPath.js",
|
|
23
|
+
"./withKotlinJvmTarget": "./dist/withKotlinJvmTarget.js",
|
|
24
|
+
"./withReleaseRemovedPermissions": "./dist/withReleaseRemovedPermissions.js",
|
|
23
25
|
"./transforms": "./dist/transforms.js",
|
|
24
26
|
"./package.json": "./package.json"
|
|
25
27
|
},
|
|
@@ -27,14 +29,14 @@
|
|
|
27
29
|
"expo": ">=54.0.0"
|
|
28
30
|
},
|
|
29
31
|
"devDependencies": {
|
|
30
|
-
"@types/node": "^26.
|
|
31
|
-
"@vitest/coverage-v8": "5.0.
|
|
32
|
-
"eslint": "10.
|
|
33
|
-
"expo": "~57.0.
|
|
32
|
+
"@types/node": "^26.6.6",
|
|
33
|
+
"@vitest/coverage-v8": "5.0.5",
|
|
34
|
+
"eslint": "10.14.0",
|
|
35
|
+
"expo": "~57.0.31",
|
|
34
36
|
"typescript": "^5.9.3",
|
|
35
|
-
"vitest": "^5.0.
|
|
36
|
-
"@forthtilliath/
|
|
37
|
-
"@forthtilliath/
|
|
37
|
+
"vitest": "^5.0.5",
|
|
38
|
+
"@forthtilliath/typescript-config": "0.1.1",
|
|
39
|
+
"@forthtilliath/eslint-config": "0.10.1"
|
|
38
40
|
},
|
|
39
41
|
"scripts": {
|
|
40
42
|
"lint": "eslint . --max-warnings 0",
|