rn-env-setup 1.0.0 → 1.1.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 +271 -0
- package/dist/android/android-generator.d.ts +3 -0
- package/dist/android/android-generator.d.ts.map +1 -0
- package/dist/android/android-generator.js +154 -0
- package/dist/android/android-generator.js.map +1 -0
- package/dist/android/gradle-parser.d.ts +32 -0
- package/dist/android/gradle-parser.d.ts.map +1 -0
- package/dist/android/gradle-parser.js +107 -0
- package/dist/android/gradle-parser.js.map +1 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +227 -0
- package/dist/cli.js.map +1 -0
- package/dist/generators/ci-generator.d.ts +3 -0
- package/dist/generators/ci-generator.d.ts.map +1 -0
- package/dist/generators/ci-generator.js +130 -0
- package/dist/generators/ci-generator.js.map +1 -0
- package/dist/generators/js-env-generator.d.ts +3 -0
- package/dist/generators/js-env-generator.d.ts.map +1 -0
- package/dist/generators/js-env-generator.js +191 -0
- package/dist/generators/js-env-generator.js.map +1 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +11 -0
- package/dist/index.js.map +1 -0
- package/dist/ios/ios-generator.d.ts +3 -0
- package/dist/ios/ios-generator.d.ts.map +1 -0
- package/dist/ios/ios-generator.js +180 -0
- package/dist/ios/ios-generator.js.map +1 -0
- package/dist/ios/xcode-patcher.d.ts +14 -0
- package/dist/ios/xcode-patcher.d.ts.map +1 -0
- package/dist/ios/xcode-patcher.js +76 -0
- package/dist/ios/xcode-patcher.js.map +1 -0
- package/dist/types/index.d.ts +61 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +4 -0
- package/dist/types/index.js.map +1 -0
- package/dist/utils/config-loader.d.ts +16 -0
- package/dist/utils/config-loader.d.ts.map +1 -0
- package/dist/utils/config-loader.js +231 -0
- package/dist/utils/config-loader.js.map +1 -0
- package/dist/utils/file-utils.d.ts +29 -0
- package/dist/utils/file-utils.d.ts.map +1 -0
- package/dist/utils/file-utils.js +93 -0
- package/dist/utils/file-utils.js.map +1 -0
- package/dist/utils/validator.d.ts +3 -0
- package/dist/utils/validator.d.ts.map +1 -0
- package/dist/utils/validator.js +91 -0
- package/dist/utils/validator.js.map +1 -0
- package/package.json +40 -24
package/README.md
ADDED
|
@@ -0,0 +1,271 @@
|
|
|
1
|
+
# rn-env-setup
|
|
2
|
+
|
|
3
|
+
> One command to configure Android product flavors, iOS xcconfig + schemes, and JS env files for multi-environment React Native CI.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Install
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npm install -g rn-env-setup
|
|
11
|
+
# or use without installing:
|
|
12
|
+
npx rn-env-setup init
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
## Quick Start
|
|
18
|
+
|
|
19
|
+
### Option A — Interactive (no config file needed)
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
cd your-rn-project
|
|
23
|
+
npx rn-env-setup init # prompts for all details, saves rn-env.yaml
|
|
24
|
+
npx rn-env-setup generate # applies everything
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
### Option B — Config file (CI-friendly)
|
|
28
|
+
|
|
29
|
+
1. Create `rn-env.yaml` in your project root (see example below).
|
|
30
|
+
2. Run:
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
npx rn-env-setup validate # check for errors first
|
|
34
|
+
npx rn-env-setup generate # apply
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
---
|
|
38
|
+
|
|
39
|
+
## Config File (`rn-env.yaml`)
|
|
40
|
+
|
|
41
|
+
```yaml
|
|
42
|
+
appName: MyApp
|
|
43
|
+
packageName: com.myapp
|
|
44
|
+
jsEnvStrategy: react-native-config # react-native-config | dotenv | custom | none
|
|
45
|
+
generateJsEnv: true
|
|
46
|
+
generateCiSnippets: false
|
|
47
|
+
enableRollback: true
|
|
48
|
+
|
|
49
|
+
environments:
|
|
50
|
+
- name: dev
|
|
51
|
+
appName: MyApp Dev
|
|
52
|
+
bundleId: com.myapp.dev
|
|
53
|
+
apiUrl: https://dev.api.example.com
|
|
54
|
+
logo: ./assets/icons/dev.png
|
|
55
|
+
variables:
|
|
56
|
+
ENABLE_LOGS: true
|
|
57
|
+
FEATURE_NEW_UI: true
|
|
58
|
+
|
|
59
|
+
- name: staging
|
|
60
|
+
appName: MyApp Staging
|
|
61
|
+
bundleId: com.myapp.staging
|
|
62
|
+
apiUrl: https://staging.api.example.com
|
|
63
|
+
|
|
64
|
+
- name: prod
|
|
65
|
+
appName: MyApp
|
|
66
|
+
bundleId: com.myapp
|
|
67
|
+
apiUrl: https://api.example.com
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
---
|
|
71
|
+
|
|
72
|
+
## CLI Commands
|
|
73
|
+
|
|
74
|
+
| Command | Description |
|
|
75
|
+
|---|---|
|
|
76
|
+
| `rn-env-setup init` | Interactive setup, saves `rn-env.yaml` |
|
|
77
|
+
| `rn-env-setup generate` | Apply config to Android + iOS + JS layer |
|
|
78
|
+
| `rn-env-setup generate --dry-run` | Preview changes without writing files |
|
|
79
|
+
| `rn-env-setup generate --android-only` | Skip iOS generation |
|
|
80
|
+
| `rn-env-setup generate --ios-only` | Skip Android generation |
|
|
81
|
+
| `rn-env-setup generate --config path/to/rn-env.yaml` | Use a specific config file |
|
|
82
|
+
| `rn-env-setup validate` | Validate config without generating |
|
|
83
|
+
| `rn-env-setup rollback` | Restore original files from backups |
|
|
84
|
+
|
|
85
|
+
---
|
|
86
|
+
|
|
87
|
+
## What Gets Generated
|
|
88
|
+
|
|
89
|
+
### Android
|
|
90
|
+
|
|
91
|
+
- **`android/app/build.gradle`** — `flavorDimensions` + `productFlavors` block injected or updated. Includes:
|
|
92
|
+
- `applicationId` per flavor
|
|
93
|
+
- `resValue "string", "app_name"` per flavor
|
|
94
|
+
- `buildConfigField "String", "API_URL"` per flavor
|
|
95
|
+
- All custom `variables` as `buildConfigField` entries
|
|
96
|
+
|
|
97
|
+
- **`android/app/src/{env}/res/values/strings.xml`** — App name override per flavor
|
|
98
|
+
|
|
99
|
+
- **`android/app/src/{env}/res/mipmap-*/ic_launcher.png`** — App icon copied from `logo` path
|
|
100
|
+
|
|
101
|
+
**Build commands output:**
|
|
102
|
+
```bash
|
|
103
|
+
react-native run-android --variant=devDebug
|
|
104
|
+
react-native run-android --variant=stagingRelease
|
|
105
|
+
cd android && ./gradlew assembleProdRelease
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
### iOS
|
|
109
|
+
|
|
110
|
+
- **`ios/Configs/MyApp-Dev.xcconfig`** — Per-environment xcconfig with:
|
|
111
|
+
- `PRODUCT_BUNDLE_IDENTIFIER`
|
|
112
|
+
- `PRODUCT_NAME`
|
|
113
|
+
- `API_URL`
|
|
114
|
+
- All custom variables
|
|
115
|
+
|
|
116
|
+
- **`ios/MyApp.xcodeproj/xcshareddata/xcschemes/MyApp-Dev.xcscheme`** — Shared scheme per environment
|
|
117
|
+
|
|
118
|
+
- **`project.pbxproj`** — Build configurations added and wired to xcconfig files
|
|
119
|
+
|
|
120
|
+
**Build commands output:**
|
|
121
|
+
```bash
|
|
122
|
+
react-native run-ios --scheme MyApp-Dev
|
|
123
|
+
react-native run-ios --scheme MyApp-Staging
|
|
124
|
+
xcodebuild -scheme MyApp-Prod -configuration Prod archive
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
### JS Layer
|
|
128
|
+
|
|
129
|
+
**`react-native-config` strategy** → generates `.env.dev`, `.env.staging`, `.env.prod` + `src/env.d.ts`
|
|
130
|
+
|
|
131
|
+
```bash
|
|
132
|
+
# Usage
|
|
133
|
+
ENVFILE=.env.dev react-native run-android
|
|
134
|
+
ENVFILE=.env.staging react-native run-ios
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
**`custom` strategy** → generates `src/env.ts` with all environments baked in as a typed module:
|
|
138
|
+
|
|
139
|
+
```typescript
|
|
140
|
+
import Config from './env';
|
|
141
|
+
|
|
142
|
+
console.log(Config.API_URL); // https://dev.api.example.com
|
|
143
|
+
console.log(Config.ENABLE_LOGS); // true
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
---
|
|
147
|
+
|
|
148
|
+
## CI/CD Integration
|
|
149
|
+
|
|
150
|
+
Set `generateCiSnippets: true` in your config to generate:
|
|
151
|
+
- `.github/workflows/rn-multi-env.yml` — GitHub Actions workflow with one job per environment per platform
|
|
152
|
+
- `bitrise-rn-env.yml` — Bitrise workflow snippets
|
|
153
|
+
|
|
154
|
+
### Using in CI (no interactive prompts)
|
|
155
|
+
|
|
156
|
+
```yaml
|
|
157
|
+
# .github/workflows/build.yml
|
|
158
|
+
- name: Generate env config
|
|
159
|
+
run: npx rn-env-setup generate --config rn-env.yaml
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
The tool is fully non-interactive when a config file exists — safe for all CI environments.
|
|
163
|
+
|
|
164
|
+
---
|
|
165
|
+
|
|
166
|
+
## Idempotency
|
|
167
|
+
|
|
168
|
+
`rn-env-setup generate` is safe to run multiple times:
|
|
169
|
+
|
|
170
|
+
- **`build.gradle`**: The injected block is wrapped in marker comments. Re-running replaces only the marked block, leaving all other Gradle configuration untouched.
|
|
171
|
+
- **Xcconfig files**: Overwritten on each run (content is deterministic).
|
|
172
|
+
- **Scheme files**: Skipped if already exist (add `--force` to overwrite).
|
|
173
|
+
- **Source set directories**: Created with `ensureDir` — no-op if present.
|
|
174
|
+
- **Backups**: Only created once per file — won't overwrite an existing backup.
|
|
175
|
+
|
|
176
|
+
---
|
|
177
|
+
|
|
178
|
+
## Rollback
|
|
179
|
+
|
|
180
|
+
If generation fails or produces unexpected results:
|
|
181
|
+
|
|
182
|
+
```bash
|
|
183
|
+
npx rn-env-setup rollback
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
This restores `.rn-env-backup` copies of `build.gradle` and `project.pbxproj`.
|
|
187
|
+
|
|
188
|
+
---
|
|
189
|
+
|
|
190
|
+
## Architecture
|
|
191
|
+
|
|
192
|
+
```
|
|
193
|
+
src/
|
|
194
|
+
├── cli.ts # commander entry point: init, generate, validate, rollback
|
|
195
|
+
├── index.ts # package entrypoint exports for programmatic usage
|
|
196
|
+
│
|
|
197
|
+
├── android/
|
|
198
|
+
│ ├── android-generator.ts # Orchestrates Android: gradle + source sets + icons
|
|
199
|
+
│ └── gradle-parser.ts # Safe bracket-balanced build.gradle manipulation
|
|
200
|
+
│
|
|
201
|
+
├── ios/
|
|
202
|
+
│ ├── ios-generator.ts # Orchestrates iOS: xcconfig + schemes + pbxproj
|
|
203
|
+
│ └── xcode-patcher.ts # pbxproj manipulation via `xcode` npm package
|
|
204
|
+
│
|
|
205
|
+
├── generators/
|
|
206
|
+
│ ├── js-env-generator.ts # .env files / typed env.ts for JS layer
|
|
207
|
+
│ └── ci-generator.ts # GitHub Actions + Bitrise CI snippets
|
|
208
|
+
│
|
|
209
|
+
├── types/
|
|
210
|
+
│ ├── index.ts # ProjectConfig, EnvironmentConfig, GenerationResult types
|
|
211
|
+
│ └── xcode.d.ts # Local declaration shim for xcode package
|
|
212
|
+
│
|
|
213
|
+
└── utils/
|
|
214
|
+
├── config-loader.ts # YAML/JSON loader + inquirer interactive prompts
|
|
215
|
+
├── file-utils.ts # backup, rollback, logDry, normalizeEnvName, findFirst
|
|
216
|
+
└── validator.ts # Pre-flight validation: duplicates, paths, bundle IDs
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
---
|
|
220
|
+
|
|
221
|
+
## Gradle Modification Strategy
|
|
222
|
+
|
|
223
|
+
The tool uses **marker-comment-based block replacement** — not regex on the whole file:
|
|
224
|
+
|
|
225
|
+
1. On first run: locates the `android { }` block using bracket counting, appends the `productFlavors` block before the closing brace.
|
|
226
|
+
2. On subsequent runs: finds `// ── rn-env-setup: auto-generated` and `// ── end rn-env-setup` markers and replaces only what's between them.
|
|
227
|
+
|
|
228
|
+
This means your other Gradle configuration (signing, dependencies, build types) is **never touched**.
|
|
229
|
+
|
|
230
|
+
---
|
|
231
|
+
|
|
232
|
+
## Edge Cases Handled
|
|
233
|
+
|
|
234
|
+
| Case | Handling |
|
|
235
|
+
|---|---|
|
|
236
|
+
| Duplicate environment names | Validation error before generation |
|
|
237
|
+
| Duplicate bundle IDs | Validation error before generation |
|
|
238
|
+
| Missing logo file | Warning, generation continues |
|
|
239
|
+
| Existing productFlavors (not ours) | Warning, replaced by ours |
|
|
240
|
+
| No `.xcodeproj` found | iOS generation skipped with warning |
|
|
241
|
+
| Generation fails mid-way | Rollback restores all backed-up files |
|
|
242
|
+
| Config file not found | Clear error: run `init` first |
|
|
243
|
+
|
|
244
|
+
---
|
|
245
|
+
|
|
246
|
+
## Roadmap / Plugin System
|
|
247
|
+
|
|
248
|
+
Future versions will support a plugin API for custom generators:
|
|
249
|
+
|
|
250
|
+
```typescript
|
|
251
|
+
// rn-env-plugin-firebase.ts (planned)
|
|
252
|
+
export const plugin: RnEnvPlugin = {
|
|
253
|
+
name: 'firebase',
|
|
254
|
+
onGenerate: async (ctx, env) => {
|
|
255
|
+
// Copy google-services.json per flavor
|
|
256
|
+
},
|
|
257
|
+
};
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
Planned features:
|
|
261
|
+
- `--full-targets` flag for full iOS target duplication
|
|
262
|
+
- White-label / multi-brand support (overlapping environments)
|
|
263
|
+
- OTA / EAS Update channel injection
|
|
264
|
+
- Fastlane lane generation
|
|
265
|
+
- Firebase multi-app configuration
|
|
266
|
+
|
|
267
|
+
---
|
|
268
|
+
|
|
269
|
+
## License
|
|
270
|
+
|
|
271
|
+
MIT
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"android-generator.d.ts","sourceRoot":"","sources":["../../src/android/android-generator.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAMvE,wBAAsB,eAAe,CAAC,GAAG,EAAE,gBAAgB,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAgHtF"}
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
// src/android/android-generator.ts
|
|
2
|
+
// Generates Android product flavors, source sets, and app icon directories
|
|
3
|
+
import fs from 'fs-extra';
|
|
4
|
+
import path from 'path';
|
|
5
|
+
import chalk from 'chalk';
|
|
6
|
+
import { backup, logDry, normalizeEnvName } from '../utils/file-utils.js';
|
|
7
|
+
import { injectFlavorBlock } from './gradle-parser.js';
|
|
8
|
+
const GRADLE_PATH = 'android/app/build.gradle';
|
|
9
|
+
export async function generateAndroid(ctx) {
|
|
10
|
+
const result = {
|
|
11
|
+
success: false,
|
|
12
|
+
filesModified: [],
|
|
13
|
+
filesCreated: [],
|
|
14
|
+
commands: [],
|
|
15
|
+
warnings: [],
|
|
16
|
+
errors: [],
|
|
17
|
+
};
|
|
18
|
+
const gradlePath = path.join(ctx.projectRoot, GRADLE_PATH);
|
|
19
|
+
if (!fs.existsSync(gradlePath)) {
|
|
20
|
+
result.errors.push(`build.gradle not found at ${gradlePath}. Are you in a React Native project?`);
|
|
21
|
+
return result;
|
|
22
|
+
}
|
|
23
|
+
// ── Step 1: Backup original build.gradle ──────────────────────────────────
|
|
24
|
+
if (ctx.config.enableRollback && !ctx.dryRun) {
|
|
25
|
+
await backup(gradlePath);
|
|
26
|
+
}
|
|
27
|
+
// ── Step 2: Read and parse the gradle file ────────────────────────────────
|
|
28
|
+
const gradleContent = fs.readFileSync(gradlePath, 'utf-8');
|
|
29
|
+
// ── Step 3: Build the flavorDimensions + productFlavors block ─────────────
|
|
30
|
+
const flavorBlock = buildFlavorBlock(ctx);
|
|
31
|
+
// ── Step 4: Inject or replace the productFlavors block ───────────────────
|
|
32
|
+
const { content: newGradle, injected } = injectFlavorBlock(gradleContent, flavorBlock);
|
|
33
|
+
if (ctx.dryRun) {
|
|
34
|
+
logDry(`Would modify: ${GRADLE_PATH}`);
|
|
35
|
+
logDry('Generated productFlavors:\n' + flavorBlock);
|
|
36
|
+
}
|
|
37
|
+
else {
|
|
38
|
+
fs.writeFileSync(gradlePath, newGradle, 'utf-8');
|
|
39
|
+
result.filesModified.push(GRADLE_PATH);
|
|
40
|
+
console.log(chalk.green(` ✔ ${injected ? 'Updated' : 'Injected'} productFlavors in ${GRADLE_PATH}`));
|
|
41
|
+
}
|
|
42
|
+
// ── Step 5: Create source sets and icon directories per flavor ────────────
|
|
43
|
+
for (const env of ctx.config.environments) {
|
|
44
|
+
const envKey = normalizeEnvName(env.name);
|
|
45
|
+
// Source set directories
|
|
46
|
+
const srcDirs = [
|
|
47
|
+
`android/app/src/${envKey}/res/values`,
|
|
48
|
+
`android/app/src/${envKey}/res/mipmap-hdpi`,
|
|
49
|
+
`android/app/src/${envKey}/res/mipmap-mdpi`,
|
|
50
|
+
`android/app/src/${envKey}/res/mipmap-xhdpi`,
|
|
51
|
+
`android/app/src/${envKey}/res/mipmap-xxhdpi`,
|
|
52
|
+
`android/app/src/${envKey}/res/mipmap-xxxhdpi`,
|
|
53
|
+
];
|
|
54
|
+
for (const dir of srcDirs) {
|
|
55
|
+
const fullDir = path.join(ctx.projectRoot, dir);
|
|
56
|
+
if (ctx.dryRun) {
|
|
57
|
+
logDry(`Would create directory: ${dir}`);
|
|
58
|
+
}
|
|
59
|
+
else {
|
|
60
|
+
await fs.ensureDir(fullDir);
|
|
61
|
+
result.filesCreated.push(dir);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
// strings.xml for this flavor (app name override)
|
|
65
|
+
const stringsXml = buildStringsXml(env.appName);
|
|
66
|
+
const stringsPath = `android/app/src/${envKey}/res/values/strings.xml`;
|
|
67
|
+
const fullStringsPath = path.join(ctx.projectRoot, stringsPath);
|
|
68
|
+
if (ctx.dryRun) {
|
|
69
|
+
logDry(`Would create: ${stringsPath}`);
|
|
70
|
+
}
|
|
71
|
+
else {
|
|
72
|
+
fs.writeFileSync(fullStringsPath, stringsXml, 'utf-8');
|
|
73
|
+
result.filesCreated.push(stringsPath);
|
|
74
|
+
console.log(chalk.green(` ✔ Created ${stringsPath}`));
|
|
75
|
+
}
|
|
76
|
+
// Copy logo if specified
|
|
77
|
+
if (env.logo) {
|
|
78
|
+
const logoSrc = path.join(ctx.projectRoot, env.logo);
|
|
79
|
+
if (fs.existsSync(logoSrc)) {
|
|
80
|
+
const logoDest = path.join(ctx.projectRoot, `android/app/src/${envKey}/res/mipmap-xxxhdpi/ic_launcher.png`);
|
|
81
|
+
if (ctx.dryRun) {
|
|
82
|
+
logDry(`Would copy logo: ${env.logo} → android/app/src/${envKey}/res/mipmap-xxxhdpi/ic_launcher.png`);
|
|
83
|
+
}
|
|
84
|
+
else {
|
|
85
|
+
await fs.copy(logoSrc, logoDest, { overwrite: true });
|
|
86
|
+
result.filesCreated.push(logoDest);
|
|
87
|
+
console.log(chalk.green(` ✔ Copied logo for ${envKey}`));
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
else {
|
|
91
|
+
result.warnings.push(`Logo not found for ${envKey}: ${env.logo}`);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
// ── Build commands ─────────────────────────────────────────────────────
|
|
95
|
+
for (const buildType of ['debug', 'release']) {
|
|
96
|
+
const variant = `${envKey}${capitalize(buildType)}`;
|
|
97
|
+
result.commands.push({
|
|
98
|
+
platform: 'android',
|
|
99
|
+
environment: env.name,
|
|
100
|
+
buildType,
|
|
101
|
+
command: `react-native run-android --variant=${variant}`,
|
|
102
|
+
description: `Run Android ${env.name} (${buildType})`,
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
result.success = true;
|
|
107
|
+
return result;
|
|
108
|
+
}
|
|
109
|
+
// ── Gradle builders ──────────────────────────────────────────────────────────
|
|
110
|
+
function buildFlavorBlock(ctx) {
|
|
111
|
+
const { config } = ctx;
|
|
112
|
+
const flavorDimension = 'environment';
|
|
113
|
+
const flavorsCode = config.environments
|
|
114
|
+
.map((env) => {
|
|
115
|
+
const envKey = normalizeEnvName(env.name);
|
|
116
|
+
const customVars = Object.entries(env.variables ?? {})
|
|
117
|
+
.map(([k, v]) => {
|
|
118
|
+
const type = typeof v === 'boolean' ? 'boolean' : typeof v === 'number' ? 'int' : 'String';
|
|
119
|
+
const quotedVal = type === 'String' ? `\\"${v}\\"` : String(v);
|
|
120
|
+
return ` buildConfigField "${type}", "${k.toUpperCase()}", "${quotedVal}"`;
|
|
121
|
+
})
|
|
122
|
+
.join('\n');
|
|
123
|
+
const suffix = env.versionNameSuffix ?? (env.name !== 'prod' ? `-${env.name}` : '');
|
|
124
|
+
return `
|
|
125
|
+
${envKey} {
|
|
126
|
+
dimension "${flavorDimension}"
|
|
127
|
+
applicationId "${env.bundleId}"
|
|
128
|
+
versionNameSuffix "${suffix}"
|
|
129
|
+
resValue "string", "app_name", "${env.appName}"
|
|
130
|
+
buildConfigField "String", "API_URL", "\\"${env.apiUrl}\\""
|
|
131
|
+
${customVars ? customVars + '\n' : ''} }`;
|
|
132
|
+
})
|
|
133
|
+
.join('\n');
|
|
134
|
+
return `
|
|
135
|
+
// ── rn-env-setup: auto-generated — do not edit manually ──
|
|
136
|
+
flavorDimensions "${flavorDimension}"
|
|
137
|
+
productFlavors {${flavorsCode}
|
|
138
|
+
}
|
|
139
|
+
// ── end rn-env-setup ──`;
|
|
140
|
+
}
|
|
141
|
+
function buildStringsXml(appName) {
|
|
142
|
+
return `<?xml version="1.0" encoding="utf-8"?>
|
|
143
|
+
<resources>
|
|
144
|
+
<string name="app_name">${escapeXml(appName)}</string>
|
|
145
|
+
</resources>
|
|
146
|
+
`;
|
|
147
|
+
}
|
|
148
|
+
function escapeXml(str) {
|
|
149
|
+
return str.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"');
|
|
150
|
+
}
|
|
151
|
+
function capitalize(s) {
|
|
152
|
+
return s.charAt(0).toUpperCase() + s.slice(1);
|
|
153
|
+
}
|
|
154
|
+
//# sourceMappingURL=android-generator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"android-generator.js","sourceRoot":"","sources":["../../src/android/android-generator.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
export interface GradleInjectResult {
|
|
2
|
+
content: string;
|
|
3
|
+
injected: boolean;
|
|
4
|
+
}
|
|
5
|
+
/**
|
|
6
|
+
* Inject or replace the productFlavors block in build.gradle content.
|
|
7
|
+
*
|
|
8
|
+
* Strategy:
|
|
9
|
+
* 1. If our marker comments exist → replace the entire block between them (idempotent).
|
|
10
|
+
* 2. Else if an `android {` block exists → append inside it before the closing brace.
|
|
11
|
+
* 3. Else throw — we can't safely modify an unrecognized file.
|
|
12
|
+
*/
|
|
13
|
+
export declare function injectFlavorBlock(content: string, flavorBlock: string): GradleInjectResult;
|
|
14
|
+
/**
|
|
15
|
+
* Find the start/end character indices of a top-level named block, e.g. `android { ... }`.
|
|
16
|
+
* Uses bracket counting so it handles nested blocks correctly.
|
|
17
|
+
*/
|
|
18
|
+
export declare function findTopLevelBlock(content: string, blockName: string): {
|
|
19
|
+
start: number;
|
|
20
|
+
end: number;
|
|
21
|
+
} | null;
|
|
22
|
+
/**
|
|
23
|
+
* Check if a specific flavor name is already declared in the file.
|
|
24
|
+
* Used for idempotency reporting.
|
|
25
|
+
*/
|
|
26
|
+
export declare function hasExistingFlavor(content: string, flavorName: string): boolean;
|
|
27
|
+
/**
|
|
28
|
+
* Parse all declared applicationId values from productFlavors.
|
|
29
|
+
* Used to detect duplicate bundle ID conflicts before generation.
|
|
30
|
+
*/
|
|
31
|
+
export declare function parseExistingApplicationIds(content: string): string[];
|
|
32
|
+
//# sourceMappingURL=gradle-parser.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gradle-parser.d.ts","sourceRoot":"","sources":["../../src/android/gradle-parser.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,kBAAkB;IACjC,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,OAAO,CAAC;CACnB;AAKD;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,kBAAkB,CA6C1F;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAC/B,OAAO,EAAE,MAAM,EACf,SAAS,EAAE,MAAM,GAChB;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAqBvC;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAK9E;AAED;;;GAGG;AACH,wBAAgB,2BAA2B,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,EAAE,CAQrE"}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
// src/android/gradle-parser.ts
|
|
2
|
+
// Safe, idempotent Gradle file manipulation using bracket-balanced block replacement.
|
|
3
|
+
// Never uses regex on the full file — only finds and replaces the specific block.
|
|
4
|
+
const BLOCK_START_MARKER = '// ── rn-env-setup: auto-generated — do not edit manually ──';
|
|
5
|
+
const BLOCK_END_MARKER = '// ── end rn-env-setup ──';
|
|
6
|
+
/**
|
|
7
|
+
* Inject or replace the productFlavors block in build.gradle content.
|
|
8
|
+
*
|
|
9
|
+
* Strategy:
|
|
10
|
+
* 1. If our marker comments exist → replace the entire block between them (idempotent).
|
|
11
|
+
* 2. Else if an `android {` block exists → append inside it before the closing brace.
|
|
12
|
+
* 3. Else throw — we can't safely modify an unrecognized file.
|
|
13
|
+
*/
|
|
14
|
+
export function injectFlavorBlock(content, flavorBlock) {
|
|
15
|
+
// Case 1: Already has our markers — safe replace
|
|
16
|
+
const startIdx = content.indexOf(BLOCK_START_MARKER);
|
|
17
|
+
const endIdx = content.indexOf(BLOCK_END_MARKER);
|
|
18
|
+
if (startIdx !== -1 && endIdx !== -1) {
|
|
19
|
+
const before = content.substring(0, startIdx);
|
|
20
|
+
const after = content.substring(endIdx + BLOCK_END_MARKER.length);
|
|
21
|
+
return {
|
|
22
|
+
content: before + flavorBlock.trim() + after,
|
|
23
|
+
injected: true,
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
// Case 2: Remove any user-written productFlavors block (replace with ours)
|
|
27
|
+
// Find the `android {` block and locate/replace productFlavors inside it
|
|
28
|
+
const androidBlockRange = findTopLevelBlock(content, 'android');
|
|
29
|
+
if (!androidBlockRange) {
|
|
30
|
+
throw new Error('Could not find `android { }` block in build.gradle. Please ensure your build.gradle has a standard Android block.');
|
|
31
|
+
}
|
|
32
|
+
let androidContent = content.substring(androidBlockRange.start, androidBlockRange.end);
|
|
33
|
+
// Remove any existing productFlavors + flavorDimensions lines
|
|
34
|
+
const existingFlavorsRange = findTopLevelBlock(androidContent, 'productFlavors');
|
|
35
|
+
if (existingFlavorsRange) {
|
|
36
|
+
// Also strip the flavorDimensions line before it
|
|
37
|
+
androidContent =
|
|
38
|
+
androidContent.substring(0, existingFlavorsRange.start).replace(/\s*flavorDimensions[^\n]+\n/, '\n') +
|
|
39
|
+
androidContent.substring(existingFlavorsRange.end);
|
|
40
|
+
}
|
|
41
|
+
// Inject before the closing brace of the android block
|
|
42
|
+
const trimmed = androidContent.trimEnd();
|
|
43
|
+
const newAndroidContent = trimmed.slice(0, -1) + '\n' + indent(flavorBlock, 4) + '\n}\n';
|
|
44
|
+
return {
|
|
45
|
+
content: content.substring(0, androidBlockRange.start) +
|
|
46
|
+
newAndroidContent +
|
|
47
|
+
content.substring(androidBlockRange.end),
|
|
48
|
+
injected: false,
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Find the start/end character indices of a top-level named block, e.g. `android { ... }`.
|
|
53
|
+
* Uses bracket counting so it handles nested blocks correctly.
|
|
54
|
+
*/
|
|
55
|
+
export function findTopLevelBlock(content, blockName) {
|
|
56
|
+
// Match `blockName {` or `blockName(...) {`
|
|
57
|
+
const regex = new RegExp(`\\b${blockName}\\s*(?:\\([^)]*\\)\\s*)?\\{`);
|
|
58
|
+
const match = regex.exec(content);
|
|
59
|
+
if (!match)
|
|
60
|
+
return null;
|
|
61
|
+
let depth = 0;
|
|
62
|
+
let i = match.index;
|
|
63
|
+
// Walk forward, counting braces
|
|
64
|
+
for (; i < content.length; i++) {
|
|
65
|
+
if (content[i] === '{')
|
|
66
|
+
depth++;
|
|
67
|
+
else if (content[i] === '}') {
|
|
68
|
+
depth--;
|
|
69
|
+
if (depth === 0) {
|
|
70
|
+
return { start: match.index, end: i + 1 };
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
return null; // Unbalanced braces
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Check if a specific flavor name is already declared in the file.
|
|
78
|
+
* Used for idempotency reporting.
|
|
79
|
+
*/
|
|
80
|
+
export function hasExistingFlavor(content, flavorName) {
|
|
81
|
+
const flavorsRange = findTopLevelBlock(content, 'productFlavors');
|
|
82
|
+
if (!flavorsRange)
|
|
83
|
+
return false;
|
|
84
|
+
const flavorsBlock = content.substring(flavorsRange.start, flavorsRange.end);
|
|
85
|
+
return new RegExp(`\\b${flavorName}\\s*\\{`).test(flavorsBlock);
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Parse all declared applicationId values from productFlavors.
|
|
89
|
+
* Used to detect duplicate bundle ID conflicts before generation.
|
|
90
|
+
*/
|
|
91
|
+
export function parseExistingApplicationIds(content) {
|
|
92
|
+
const ids = [];
|
|
93
|
+
const regex = /applicationId\s+"([^"]+)"/g;
|
|
94
|
+
let match;
|
|
95
|
+
while ((match = regex.exec(content)) !== null) {
|
|
96
|
+
ids.push(match[1]);
|
|
97
|
+
}
|
|
98
|
+
return ids;
|
|
99
|
+
}
|
|
100
|
+
function indent(text, spaces) {
|
|
101
|
+
const pad = ' '.repeat(spaces);
|
|
102
|
+
return text
|
|
103
|
+
.split('\n')
|
|
104
|
+
.map((line) => (line.trim() ? pad + line : line))
|
|
105
|
+
.join('\n');
|
|
106
|
+
}
|
|
107
|
+
//# sourceMappingURL=gradle-parser.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gradle-parser.js","sourceRoot":"","sources":["../../src/android/gradle-parser.ts"],"names":[],"mappings":"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"}
|
package/dist/cli.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":""}
|