expo-release-it 0.0.16 → 0.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.
Files changed (46) hide show
  1. package/README.md +71 -3
  2. package/build/command/build.d.ts +2 -7
  3. package/build/command/build.js +82 -65
  4. package/build/command/build.js.map +1 -1
  5. package/build/command/bump.d.ts +2 -3
  6. package/build/command/bump.js +5 -22
  7. package/build/command/bump.js.map +1 -1
  8. package/build/command/init.d.ts +2 -3
  9. package/build/command/init.js +20 -37
  10. package/build/command/init.js.map +1 -1
  11. package/build/command/submit.d.ts +2 -5
  12. package/build/command/submit.js +92 -43
  13. package/build/command/submit.js.map +1 -1
  14. package/build/command/upload.d.ts +2 -5
  15. package/build/command/upload.js +104 -44
  16. package/build/command/upload.js.map +1 -1
  17. package/build/index.js +145 -127
  18. package/build/index.js.map +1 -1
  19. package/build/util/FastlaneOption.d.ts +4 -0
  20. package/build/util/FastlaneOption.js +110 -0
  21. package/build/util/FastlaneOption.js.map +1 -0
  22. package/build/util/OptionHolder.d.ts +6 -12
  23. package/build/util/OptionHolder.js +2 -6
  24. package/build/util/OptionHolder.js.map +1 -1
  25. package/build/util/VersionUtil.js +2 -6
  26. package/build/util/VersionUtil.js.map +1 -1
  27. package/build/util/hydrateKeyholderFileValues.js +2 -6
  28. package/build/util/hydrateKeyholderFileValues.js.map +1 -1
  29. package/build/util/injectTemplatePlaceHolders.js +2 -6
  30. package/build/util/injectTemplatePlaceHolders.js.map +1 -1
  31. package/build/util/input/InqueryInputs.d.ts +8 -0
  32. package/build/util/input/InqueryInputs.js +131 -0
  33. package/build/util/input/InqueryInputs.js.map +1 -0
  34. package/build/util/setup/prepareAndroid.js +2 -6
  35. package/build/util/setup/prepareAndroid.js.map +1 -1
  36. package/build/util/setup/prepareIos.js +2 -6
  37. package/build/util/setup/prepareIos.js.map +1 -1
  38. package/build/util/setup/promptCommonInputs.js +4 -26
  39. package/build/util/setup/promptCommonInputs.js.map +1 -1
  40. package/build/util/setup/setup.js +4 -26
  41. package/build/util/setup/setup.js.map +1 -1
  42. package/package.json +1 -1
  43. package/template/android/fastlane/Fastfile +20 -13
  44. package/template/ios/fastlane/Fastfile +36 -57
  45. package/template/key/android_upload_certificate.pem +2 -2
  46. package/template/key/ios_provision_profile.mobileprovision +0 -0
package/README.md CHANGED
@@ -1,7 +1,75 @@
1
- # expo-local-build
1
+ # Expo Release It ⚡️
2
2
 
3
- Construct environment for Build & Submit Expo CNG Project locally.
3
+ ![expo-release-it thumbnail](./asset/social-image.png)
4
4
 
5
- # Placeholers
5
+ Opinioned Expo CICD workflow CLI for building & uploading & submitting Expo CNG project on your machine
6
6
 
7
+ > [!CAUTION]
8
+ > This project is under developing.
7
9
 
10
+ # Features
11
+
12
+ - No EAS
13
+ - Manage Keys, Credentials, Metadatas in a simple way
14
+ - Working with CNG mode (also available with non CNG environment)
15
+ - Build artifacts locally (`apk`, `aab`, `ipa`)
16
+ - Upload artifacts to Google Play Console Internal Testing Track & iOS Testflight
17
+ - Submit releases for review
18
+
19
+ # Why?
20
+
21
+ Expo EAS is convenient, but it requires additional configuration files, console setup, and a conceptual understanding of Over-The-Air (OTA) updates. Also, builds must be performed on EAS Cloud, which is not free and can be slow.
22
+
23
+ While EAS is useful for larger teams, if you are developing alone or with just a few people and question the need for such a process, `expo-release-it` is the answer.
24
+
25
+ Based on years of experience developing with React Native, I encourage a more traditional approach: build APK, AAB, and IPA files locally, upload them to each platform’s store testing track, and request reviews—without worrying about binary versions, OTA update versions, or branch management.
26
+
27
+ This approach is much faster, simpler, and, most importantly, allows you to take full advantage of your computer’s fast CPU.
28
+
29
+ `expo-release-it` is a CLI tool that encapsulates the know-how I have gained over years of automating build and review processes.
30
+ Internally, it ports and integrates tools like Fastlane and Match to automate native binary builds and review requests.
31
+
32
+ Therefore, this tool enforces an opinionated versioning, build, and review request workflow.
33
+ However, once you understand this approach, your app deployment process will become significantly faster.
34
+
35
+
36
+ # Requirements
37
+
38
+ - Match iOS, Android Binary build version like `1.0.0`
39
+ - All Keys, Credentials(except iOS certificates & provisioning profiles) are stored in VCS
40
+
41
+ # Getting Started
42
+
43
+
44
+
45
+ # Usage
46
+
47
+ ```shell
48
+ npx expo-release-it (init|bump|build|upload|submit) [options]
49
+ ```
50
+
51
+ ## init
52
+
53
+ ## bump
54
+
55
+ ## build
56
+
57
+ ## upload
58
+
59
+ ## submit
60
+
61
+ # Limitation
62
+
63
+
64
+ - See [LICENSE](/LICENSE)
65
+
66
+ ---
67
+
68
+ <p align="center">
69
+ <a href="https://mjstudio.net/">
70
+ <img width="75px" src="https://raw.githubusercontent.com/mym0404/image-archive/master/202404201239152.webp">
71
+ </a>
72
+ <p align="center">
73
+ Built and maintained by <a href="https://mjstudio.net/">MJ Studio</a>.
74
+ </p>
75
+ </p>
@@ -1,10 +1,5 @@
1
- type BuildOptions = {
2
- platform: 'ios' | 'android';
3
- androidOutput: 'apk' | 'aab';
4
- pod: boolean;
5
- };
6
1
  declare function build({ options }: {
7
- options: BuildOptions;
2
+ options: any;
8
3
  }): Promise<void>;
9
4
 
10
- export { type BuildOptions, build };
5
+ export { build };
@@ -1,6 +1,3 @@
1
- // src/command/build.ts
2
- import { select } from "@inquirer/prompts";
3
-
4
1
  // src/util/setup/prepareAndroid.ts
5
2
  import { spinner, $ } from "zx";
6
3
 
@@ -64,7 +61,7 @@ var package_default = {
64
61
  name: "expo-release-it",
65
62
  module: "src/index.ts",
66
63
  type: "module",
67
- version: "0.0.15",
64
+ version: "0.0.17",
68
65
  license: "MIT",
69
66
  scripts: {
70
67
  build: "tsup",
@@ -117,11 +114,7 @@ var OptionHolder = {
117
114
  rootDir: resolve2(fileURLToPath(import.meta.url), "../.."),
118
115
  templateDir: resolve2(fileURLToPath(import.meta.url), "../../template")
119
116
  },
120
- init: {},
121
- bump: {},
122
- build: {},
123
- upload: {},
124
- submit: {},
117
+ input: {},
125
118
  keyholderMap: {},
126
119
  templateDirNames: ["key"],
127
120
  iosBundleIdentifier: "",
@@ -222,29 +215,14 @@ async function replaceAndroidSigningConfig(destDir) {
222
215
  write(buildGradlePath, content);
223
216
  }
224
217
 
225
- // src/util/setup/promptCommonInputs.ts
226
- import { input } from "@inquirer/prompts";
227
-
228
218
  // src/util/EnvUtil.ts
229
219
  var isDev = process.env.NODE_ENV === "development";
230
220
  var isWin = process.platform.startsWith("win");
231
221
 
232
222
  // src/util/setup/promptCommonInputs.ts
233
223
  async function promptCommonInputs() {
234
- OptionHolder.projectDir = isDev ? resolve2("example") : resolve2(
235
- await input({
236
- message: "react native project root directory path",
237
- default: isDev ? "example" : ".",
238
- validate: (value) => {
239
- const p = resolve2(value, "package.json");
240
- if (!exist(p)) {
241
- return "package.json hasn't been detected. provider valid project root.";
242
- }
243
- return true;
244
- }
245
- })
246
- );
247
- OptionHolder.outputOfInitDir = resolve2(OptionHolder.projectDir, "expo-local-build");
224
+ OptionHolder.projectDir = isDev ? resolve2("example") : resolve2(".");
225
+ OptionHolder.outputOfInitDir = resolve2(OptionHolder.projectDir, "expo-release-it");
248
226
  OptionHolder.keyDir = resolve2(OptionHolder.outputOfInitDir, "key");
249
227
  OptionHolder.keyholderFilePath = resolve2(OptionHolder.outputOfInitDir, "keyholder.json");
250
228
  }
@@ -361,17 +339,85 @@ function calculateElapsed(t) {
361
339
  return `${minutes}:${padZero(seconds)}`;
362
340
  }
363
341
 
342
+ // src/util/input/InqueryInputs.ts
343
+ import { select } from "@inquirer/prompts";
344
+ import { is } from "@mj-studio/js-util";
345
+ var InqueryInputs = {
346
+ platform: async () => {
347
+ if (!OptionHolder.input.platform) {
348
+ OptionHolder.input.platform = await select({
349
+ message: "Platform to release",
350
+ choices: [
351
+ { name: "ios", value: "ios", description: "Release ios" },
352
+ { name: "android", value: "android", description: "Release android" }
353
+ ]
354
+ });
355
+ }
356
+ },
357
+ podinstall: async () => {
358
+ if (OptionHolder.input.platform === "ios") {
359
+ OptionHolder.input.pod = await select({
360
+ message: "Install Cocoapods",
361
+ choices: [
362
+ { name: "yes", value: true, description: "Install pods before release" },
363
+ { name: "no", value: false, description: "Skip pods install" }
364
+ ]
365
+ });
366
+ }
367
+ },
368
+ androidBuildOutput: async () => {
369
+ if (OptionHolder.input.platform === "android") {
370
+ if (!OptionHolder.input.androidOutput) {
371
+ OptionHolder.input.androidOutput = await select({
372
+ message: "Android Output",
373
+ choices: [
374
+ { name: "aab", value: "aab", description: "Build as App bundle" },
375
+ { name: "apk", value: "apk", description: "Build as APK" }
376
+ ]
377
+ });
378
+ }
379
+ }
380
+ },
381
+ uploadMetadata: async () => {
382
+ if (!is.boolean(OptionHolder.input.uploadMetadata)) {
383
+ OptionHolder.input.uploadMetadata = await select({
384
+ message: "Upload Metadata(screenshot, title, description, ...)",
385
+ choices: [
386
+ { name: "yes", value: true, description: "Upload" },
387
+ { name: "no", value: false, description: "Don't Upload" }
388
+ ]
389
+ });
390
+ }
391
+ }
392
+ };
393
+
394
+ // src/util/FastlaneOption.ts
395
+ function getIosFastlaneOptions() {
396
+ return [
397
+ `version_name:${OptionHolder.versionName}`,
398
+ `version_code:${OptionHolder.versionCode}`,
399
+ `ios_app_identifier:${OptionHolder.iosBundleIdentifier}`,
400
+ `ios_xcode_project_target:${OptionHolder.keyholderMap.ios_xcode_project_target}`,
401
+ `ios_developer_team_id:${OptionHolder.keyholderMap.ios_developer_team_id}`,
402
+ `ios_app_store_connect_api_key_id:${OptionHolder.keyholderMap.ios_app_store_connect_api_key_id}`,
403
+ `ios_app_store_connect_api_key_issuer_id:${OptionHolder.keyholderMap.ios_app_store_connect_api_key_issuer_id}`,
404
+ `api_key_filepath:${resolve2(OptionHolder.keyDir, "ios_testflight_upload_api_key.p8")}`,
405
+ `upload_metadata:${OptionHolder.input.uploadMetadata}`,
406
+ `ipa_path:${resolve2(OptionHolder.outputOfInitDir, "output", "ios", "app.ipa")}`,
407
+ `ipa_dir:${resolve2(OptionHolder.outputOfInitDir, "output", "ios")}`,
408
+ `ipa_name:app.ipa`
409
+ ];
410
+ }
411
+
364
412
  // src/command/build.ts
365
- import { formatJson } from "@mj-studio/js-util";
366
413
  async function build({ options }) {
367
- Object.assign(OptionHolder.build, options);
368
- logger.dim(formatJson(OptionHolder.build));
414
+ Object.assign(OptionHolder.input, options);
369
415
  const startTime = Date.now();
370
416
  await setup();
371
417
  await promptInputs();
372
418
  logger.info("Build Started");
373
419
  logger.info(`Version: ${OptionHolder.versionName}(${OptionHolder.versionCode})`);
374
- if (OptionHolder.build.platform === "ios") {
420
+ if (OptionHolder.input.platform === "ios") {
375
421
  await buildIos();
376
422
  logger.success(`iOS Build ${chalk2.bold.inverse(calculateElapsed(startTime))}`);
377
423
  } else {
@@ -380,35 +426,9 @@ async function build({ options }) {
380
426
  }
381
427
  }
382
428
  async function promptInputs() {
383
- if (!OptionHolder.build.platform) {
384
- OptionHolder.build.platform = await select({
385
- message: "Platform to release",
386
- choices: [
387
- { name: "ios", value: "ios", description: "Release ios" },
388
- { name: "android", value: "android", description: "Release android" }
389
- ]
390
- });
391
- }
392
- if (OptionHolder.build.platform === "ios") {
393
- OptionHolder.build.pod = await select({
394
- message: "Install Cocoapods",
395
- choices: [
396
- { name: "yes", value: true, description: "Install pods before release" },
397
- { name: "no", value: false, description: "Skip pods install" }
398
- ]
399
- });
400
- }
401
- if (OptionHolder.build.platform === "android") {
402
- if (!OptionHolder.build.androidOutput) {
403
- OptionHolder.build.androidOutput = await select({
404
- message: "Android Output",
405
- choices: [
406
- { name: "aab", value: "aab", description: "Build as App bundle" },
407
- { name: "apk", value: "apk", description: "Build as APK" }
408
- ]
409
- });
410
- }
411
- }
429
+ await InqueryInputs.platform();
430
+ await InqueryInputs.podinstall();
431
+ await InqueryInputs.androidBuildOutput();
412
432
  }
413
433
  async function buildIos() {
414
434
  const iosDir = resolve2(OptionHolder.projectDir, "ios");
@@ -424,15 +444,12 @@ async function buildIos() {
424
444
  async function fastlane() {
425
445
  await spinner3("Bundler Install", () => $$`bundle install`);
426
446
  logger.success("Bundler Install");
427
- if (OptionHolder.build.pod) {
447
+ if (OptionHolder.input.pod) {
428
448
  await spinner3("Pod Install", () => $$`bundle exec pod install`);
429
449
  logger.success("Pod Install");
430
450
  }
431
451
  remove(resolve2(iosDir, ".xcode.env.local"));
432
- await spinner3(
433
- "Fastlane",
434
- () => $$`bundle exec fastlane build version_name:${OptionHolder.versionName} version_code:${OptionHolder.versionCode}`
435
- );
452
+ await spinner3("Fastlane", () => $$`bundle exec fastlane build ${getIosFastlaneOptions()}`);
436
453
  }
437
454
  }
438
455
  async function buildAndroid() {
@@ -448,7 +465,7 @@ async function buildAndroid() {
448
465
  logger.success("Bundler Install");
449
466
  let buildOutputDir;
450
467
  let outputDir;
451
- if (OptionHolder.build.androidOutput === "aab") {
468
+ if (OptionHolder.input.androidOutput === "aab") {
452
469
  await spinner3(
453
470
  "Bundle AAB",
454
471
  () => $$`${isWin ? "gradle.bat" : "./gradlew"} app:bundleRelease`
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/command/build.ts","../../src/util/setup/prepareAndroid.ts","../../src/util/FileUtil.ts","../../package.json","../../src/util/OptionHolder.ts","../../src/util/logger.ts","../../src/util/iterateAllFiles.ts","../../src/util/injectTemplatePlaceHolders.ts","../../src/util/setup/promptCommonInputs.ts","../../src/util/EnvUtil.ts","../../src/util/hydrateKeyholderFileValues.ts","../../src/util/throwError.ts","../../src/util/VersionUtil.ts","../../src/util/setup/setup.ts","../../src/util/setup/prepareIos.ts","../../src/util/calculateElapsed.ts"],"sourcesContent":["import { select } from '@inquirer/prompts';\nimport { prepareAndroid } from '../util/setup/prepareAndroid';\nimport { setup } from '../util/setup/setup';\nimport { prepareIos } from '../util/setup/prepareIos';\nimport { logger } from '../util/logger';\nimport { OptionHolder } from '../util/OptionHolder';\nimport { spinner, $ } from 'zx';\nimport { resolve, remove, copy, relativePath } from '../util/FileUtil';\nimport chalk from 'chalk';\nimport { calculateElapsed } from '../util/calculateElapsed';\nimport { isWin } from '../util/EnvUtil';\nimport { formatJson } from '@mj-studio/js-util';\n\nexport type BuildOptions = {\n platform: 'ios' | 'android';\n androidOutput: 'apk' | 'aab';\n pod: boolean;\n};\n\nexport async function build({ options }: { options: BuildOptions }) {\n Object.assign(OptionHolder.build, options);\n logger.dim(formatJson(OptionHolder.build));\n const startTime = Date.now();\n await setup();\n await promptInputs();\n\n logger.info('Build Started');\n logger.info(`Version: ${OptionHolder.versionName}(${OptionHolder.versionCode})`);\n\n if (OptionHolder.build.platform === 'ios') {\n await buildIos();\n logger.success(`iOS Build ${chalk.bold.inverse(calculateElapsed(startTime))}`);\n } else {\n await buildAndroid();\n logger.success(`Android Build ${chalk.bold.inverse(calculateElapsed(startTime))}`);\n }\n}\n\nasync function promptInputs() {\n if (!OptionHolder.build.platform) {\n OptionHolder.build.platform = await select({\n message: 'Platform to release',\n choices: [\n { name: 'ios', value: 'ios', description: 'Release ios' },\n { name: 'android', value: 'android', description: 'Release android' },\n ],\n });\n }\n\n // ios\n if (OptionHolder.build.platform === 'ios') {\n OptionHolder.build.pod = await select({\n message: 'Install Cocoapods',\n choices: [\n { name: 'yes', value: true, description: 'Install pods before release' },\n { name: 'no', value: false, description: 'Skip pods install' },\n ],\n });\n }\n\n // android\n if (OptionHolder.build.platform === 'android') {\n if (!OptionHolder.build.androidOutput) {\n OptionHolder.build.androidOutput = await select({\n message: 'Android Output',\n choices: [\n { name: 'aab', value: 'aab', description: 'Build as App bundle' },\n { name: 'apk', value: 'apk', description: 'Build as APK' },\n ],\n });\n }\n }\n}\n\nasync function buildIos() {\n const iosDir = resolve(OptionHolder.projectDir, 'ios');\n const $$ = $({\n verbose: false,\n cwd: iosDir,\n env: {\n MATCH_PASSWORD: OptionHolder.keyholderMap.ios_match_password,\n },\n });\n await prepareIos();\n await fastlane();\n\n async function fastlane() {\n await spinner('Bundler Install', () => $$`bundle install`);\n logger.success('Bundler Install');\n\n if (OptionHolder.build.pod) {\n await spinner('Pod Install', () => $$`bundle exec pod install`);\n logger.success('Pod Install');\n }\n remove(resolve(iosDir, '.xcode.env.local'));\n\n await spinner(\n 'Fastlane',\n () =>\n $$`bundle exec fastlane build version_name:${OptionHolder.versionName} version_code:${OptionHolder.versionCode}`,\n );\n }\n}\nasync function buildAndroid() {\n const androidDir = resolve(OptionHolder.projectDir, 'android');\n const $$ = $({\n verbose: false,\n cwd: androidDir,\n });\n await prepareAndroid();\n await fastlane();\n\n async function fastlane() {\n await spinner('Bundler Install', () => $$`bundle install`);\n logger.success('Bundler Install');\n\n let buildOutputDir: string;\n let outputDir: string;\n\n if (OptionHolder.build.androidOutput === 'aab') {\n // aab: app/build/outputs/bundle/release/app-release.aab\n await spinner(\n 'Bundle AAB',\n () => $$`${isWin ? 'gradle.bat' : './gradlew'} app:bundleRelease`,\n );\n buildOutputDir = resolve(androidDir, 'app', 'build', 'outputs', 'bundle', 'release');\n outputDir = resolve(OptionHolder.outputOfInitDir, 'output', 'android', 'aab');\n } else {\n // apk: app/build/outputs/apk/release/app-release.apk\n await spinner(\n 'Bundle APK',\n () => $$`${isWin ? 'gradle.bat' : './gradlew'} app:assembleRelease`,\n );\n buildOutputDir = resolve(androidDir, 'app', 'build', 'outputs', 'apk', 'release');\n outputDir = resolve(OptionHolder.outputOfInitDir, 'output', 'android', 'apk');\n }\n\n remove(outputDir);\n copy(buildOutputDir, outputDir);\n\n logger.success(`artifact generated: ${relativePath(OptionHolder.projectDir, outputDir)}`);\n }\n}\n","import { spinner, $ } from 'zx';\nimport { resolve, remove, iterateDir, copy, read, write, relativePath } from '../FileUtil';\nimport { OptionHolder } from '../OptionHolder';\nimport { logger } from '../logger';\nimport { injectTemplatePlaceHolders } from '../injectTemplatePlaceHolders';\n\nexport async function prepareAndroid() {\n const srcDir = resolve(OptionHolder.cli.templateDir, 'android');\n const destDir = resolve(OptionHolder.projectDir, 'android');\n\n await spinner(\n 'Prebuild Android',\n () => $`cd ${OptionHolder.projectDir} && expo prebuild -p android --no-install`,\n );\n logger.success('expo prebuild');\n\n await iterateDir(srcDir, async (file) => {\n const filePath = resolve(srcDir, file);\n remove(resolve(destDir, file));\n copy(filePath, resolve(destDir, file));\n });\n logger.success('Inject Android templates');\n\n await replaceAndroidSigningConfig(destDir);\n logger.success('Overwrite Android Release Signing Config');\n\n await injectTemplatePlaceHolders(resolve(destDir, 'fastlane'));\n logger.success('Hydrate template placeholders');\n}\n\nasync function replaceAndroidSigningConfig(destDir: string) {\n const buildGradleDirPath = resolve(destDir, 'app');\n const buildGradlePath = resolve(destDir, 'app', 'build.gradle');\n const {\n android_keystore_store_password,\n android_keystore_key_alias,\n android_keystore_key_password,\n } = OptionHolder.keyholderMap;\n\n const content = read(buildGradlePath).replace(\n /signingConfigs.*?{.*?debug.*?{.*?}.*?}/s,\n `\n signingConfigs {\n debug {\n storeFile file('${relativePath(buildGradleDirPath, resolve(OptionHolder.outputOfInitDir, 'key', 'android_release_keystore.jks'))}')\n storePassword '${android_keystore_store_password}'\n keyAlias '${android_keystore_key_alias}'\n keyPassword '${android_keystore_key_password}'\n }\n }\n `,\n );\n write(buildGradlePath, content);\n}\n","import fs from 'fs-extra';\nimport * as path from 'path';\n\nexport const join = path.join;\nexport const resolve = path.resolve;\n\nexport function exist(path: string) {\n return fs.existsSync(path);\n}\n\nexport function isDir(path: string) {\n return exist(path) && fs.lstatSync(path).isDirectory();\n}\n\nexport function relativePath(from: string, to: string) {\n return path.relative(from, to);\n}\n\nexport function isFile(path: string) {\n return exist(path) && fs.lstatSync(path).isFile();\n}\n\nexport function read(path: string) {\n return fs.readFileSync(path, { encoding: 'utf8' });\n}\n\nexport function readdir(path: string) {\n return fs.readdirSync(path);\n}\n\n// you should require when possible(optimized in js)\nexport function readJsonSlow(path: string) {\n return fs.readJSONSync(path);\n}\n\nexport function write(p: string, content: string) {\n const dir = path.dirname(p);\n if (!exist(dir)) {\n fs.mkdirSync(dir, { recursive: true });\n }\n\n return fs.writeFileSync(p, content);\n}\nexport function copy(src: string, dest: string, options?: fs.CopyOptionsSync) {\n fs.copySync(src, dest, options);\n}\n\nexport function writeJson(path: string, json: any) {\n return write(path, JSON.stringify(json, null, 2));\n}\n\nexport function remove(path: string) {\n if (!exist(path)) {\n return;\n }\n\n if (fs.lstatSync(path).isDirectory()) {\n return fs.rmSync(path, { force: true, recursive: true });\n } else {\n return fs.rmSync(path, { force: true });\n }\n}\n\nexport async function iterateDir(path: string, fn: (file: string) => Promise<void> | void) {\n if (!isDir(path)) {\n return;\n }\n\n for (const file of fs.readdirSync(path)) {\n await fn(file);\n }\n}\n","{\n \"name\": \"expo-release-it\",\n \"module\": \"src/index.ts\",\n \"type\": \"module\",\n \"version\": \"0.0.15\",\n \"license\": \"MIT\",\n \"scripts\": {\n \"build\": \"tsup\",\n \"dev\": \"bun run build && NODE_ENV=development node bin/expo-release-it.mjs\",\n \"release\": \"yarn build && release-it\",\n \"android\": \"expo run:android\",\n \"ios\": \"expo run:ios\",\n \"t\": \"tsc --noEmit -p .\"\n },\n \"dependencies\": {\n \"@inquirer/prompts\": \"^7.4.1\",\n \"@mj-studio/js-util\": \"^1.1.20\",\n \"chalk\": \"^5.4.1\",\n \"commander\": \"^13.1.0\",\n \"fs-extra\": \"^11.3.0\",\n \"react\": \"18.3.1\",\n \"react-native\": \"0.76.9\",\n \"semver\": \"^7.7.1\",\n \"url\": \"^0.11.4\",\n \"zx\": \"^8.5.3\"\n },\n \"devDependencies\": {\n \"@types/bun\": \"latest\",\n \"@types/fs-extra\": \"^11.0.4\",\n \"@types/semver\": \"^7.7.0\",\n \"prettier\": \"3.5.3\",\n \"release-it\": \"^19.0.1\",\n \"tiny-glob\": \"^0.2.9\",\n \"tsup\": \"^8.4.0\",\n \"typescript\": \"^5.8.3\"\n },\n \"workspaces\": [\n \"example\"\n ],\n \"bin\": \"./bin/expo-release-it.mjs\",\n \"files\": [\n \"build\",\n \"package.json\",\n \"bin\",\n \"template\"\n ],\n \"packageManager\": \"yarn@4.9.1\"\n}\n","import pkgJson from '../../package.json';\nimport { resolve } from './FileUtil';\nimport type { BuildOptions } from '../command/build';\nimport type { InitOptions } from '../command/init';\nimport type { BumpOptions } from '../command/bump';\nimport type { SubmitOptions } from '../command/submit';\nimport type { UploadOptions } from '../command/upload';\nimport { fileURLToPath } from 'url';\n\n/**\n * CLI Comprehensive options\n * Each values can be empty by command and timing.\n */\nexport const OptionHolder: {\n // cli specific options\n cli: {\n // cli version\n version: string;\n // cli project root directory\n rootDir: string;\n // cli template source directory\n templateDir: string;\n };\n init: InitOptions;\n bump: BumpOptions;\n build: BuildOptions;\n upload: UploadOptions;\n submit: SubmitOptions;\n keyholderMap: {\n ios_app_identifier: string;\n ios_app_store_connect_team_id: string;\n ios_developer_team_id: string;\n ios_match_git_url: string;\n ios_app_store_connect_api_key_id: string;\n ios_app_store_connect_api_key_issuer_id: string;\n ios_xcode_project_target: string;\n ios_match_password: string;\n\n key_dir_relative_path: string;\n\n android_keystore_store_password: string;\n android_keystore_key_alias: string;\n android_keystore_key_password: string;\n android_package_name: string;\n };\n iosBundleIdentifier: string;\n androidPackageName: string;\n templateDirNames: string[];\n // dest project root directory\n projectDir: string;\n // dest project output of init command direcotry\n outputOfInitDir: string;\n keyDir: string;\n keyholderFilePath: string;\n versionName: string;\n versionCode: string;\n} = {\n cli: {\n version: pkgJson.version,\n rootDir: resolve(fileURLToPath(import.meta.url), '../..'),\n templateDir: resolve(fileURLToPath(import.meta.url), '../../template'),\n },\n init: {} as any,\n bump: {} as any,\n build: {} as any,\n upload: {} as any,\n submit: {} as any,\n keyholderMap: {} as any,\n templateDirNames: ['key'],\n iosBundleIdentifier: '',\n androidPackageName: '',\n projectDir: '',\n outputOfInitDir: '',\n keyDir: '',\n keyholderFilePath: '',\n versionName: '',\n versionCode: '',\n};\n","import chalk from 'chalk';\n\nexport const logger = {\n success: (...msg: any[]) => console.log(chalk.green(`✔ ${msg.join(', ')}`)),\n error: (...msg: any[]) => console.log(chalk.red(`✖ ${msg.join(', ')}`)),\n warn: (...msg: any[]) => console.log(chalk.yellow(`⚠ ${msg.join(', ')}`)),\n info: (...msg: any[]) => console.log(chalk.cyan(`ℹ ${msg.join(', ')}`)),\n title: (...msg: any[]) => console.log(chalk.bold.blue(`\\n${msg.join(', ')}`)),\n dim: (...msg: any[]) => console.log(chalk.dim(msg.join(', '))),\n};\n","import { readdir, isFile, isDir, join } from './FileUtil';\n\nexport async function iterateAllFiles(root: string, callback: (filePath: string) => Promise<void>) {\n await go(root);\n\n async function go(dirPath: string) {\n const paths = readdir(dirPath).map((f) => join(dirPath, f));\n\n for (const p of paths) {\n if (isFile(p)) {\n await callback(p);\n } else if (isDir(p)) {\n await go(p);\n }\n }\n }\n}\n","import { iterateAllFiles } from './iterateAllFiles';\nimport { path } from 'zx';\nimport { read, relativePath, write } from './FileUtil';\nimport { OptionHolder } from './OptionHolder';\n\nexport async function injectTemplatePlaceHolders(root: string) {\n await iterateAllFiles(root, async (filePath: string) => {\n const dirPath = path.dirname(filePath);\n let content = read(filePath);\n for (const [key, value] of Object.entries(OptionHolder.keyholderMap)) {\n content = content.replaceAll(`{{${key}}}`, value);\n }\n // dynamic replacements\n content = content.replaceAll(\n '{{key_dir_relative_path}}',\n relativePath(dirPath, OptionHolder.keyDir),\n );\n write(filePath, content);\n });\n}\n","import { OptionHolder } from '../OptionHolder';\nimport { input } from '@inquirer/prompts';\nimport { isDev } from '../EnvUtil';\nimport { exist, resolve } from '../FileUtil';\n\nexport async function promptCommonInputs() {\n OptionHolder.projectDir = isDev\n ? resolve('example')\n : resolve(\n await input({\n message: 'react native project root directory path',\n default: isDev ? 'example' : '.',\n validate: (value) => {\n const p = resolve(value, 'package.json');\n if (!exist(p)) {\n return \"package.json hasn\\'t been detected. provider valid project root.\";\n }\n return true;\n },\n }),\n );\n\n OptionHolder.outputOfInitDir = resolve(OptionHolder.projectDir, 'expo-local-build');\n OptionHolder.keyDir = resolve(OptionHolder.outputOfInitDir, 'key');\n OptionHolder.keyholderFilePath = resolve(OptionHolder.outputOfInitDir, 'keyholder.json');\n}\n","export const isDev = process.env.NODE_ENV === 'development';\nexport const isWin = process.platform.startsWith('win');\n","import { OptionHolder } from './OptionHolder';\nimport { readJsonSlow } from './FileUtil';\n\nexport async function hydrateKeyholderFileValues() {\n Object.assign(OptionHolder.keyholderMap, readJsonSlow(OptionHolder.keyholderFilePath));\n}\n","import { logger } from './logger';\n\nexport function throwError(message: string, e?: any): never {\n if (e) {\n logger.error(message, e);\n } else {\n logger.error(message);\n }\n process.exit(1);\n}\n","import { OptionHolder } from './OptionHolder';\nimport { throwError } from './throwError';\nimport semver from 'semver';\nimport { readdir, read, readJsonSlow, write, writeJson, resolve } from './FileUtil';\n\nexport async function parseBinaryVersions() {\n const files = readdir(OptionHolder.projectDir);\n\n const jsConfigFiles = ['app.config.ts', 'app.config.js', 'app.config.cjs', 'app.config.mjs'];\n const jsonConfigFile = 'app.json';\n\n for (const jsConfigFile of jsConfigFiles) {\n if (files.includes(jsConfigFile)) {\n await parseFromJsConfigFile(jsConfigFile);\n return;\n }\n }\n\n if (files.includes(jsonConfigFile)) {\n await parseFromJsonConfigFile(jsonConfigFile);\n return;\n }\n\n throwError('expo config file not found');\n\n async function parseFromJsConfigFile(filename: string) {\n const filePath = resolve(OptionHolder.projectDir, filename);\n const content = read(filePath);\n\n const VERSION_NAME = /const VERSION_NAME = '(.*?)';/.exec(content)?.[1];\n const VERSION_CODE = /const VERSION_CODE = (.*?);/.exec(content)?.[1];\n\n if (!VERSION_NAME) {\n throwError('cannot parse version name');\n }\n if (!VERSION_CODE) {\n throwError('cannot parse version code');\n }\n\n if (!semver.valid(VERSION_NAME)) {\n throwError('VERSION_NAME is not a valid semver format');\n }\n\n OptionHolder.versionName = VERSION_NAME;\n OptionHolder.versionCode = VERSION_CODE;\n }\n\n async function parseFromJsonConfigFile(filename: string) {\n const filePath = resolve(OptionHolder.projectDir, filename);\n const json = readJsonSlow(filePath);\n\n const versionName = json.expo?.version + '';\n const iosVersionCode = json.expo?.ios?.buildNumber + '';\n const androidVersionCode = json.expo?.android?.versionCode + '';\n\n if (!/\\d+/.test(iosVersionCode)) {\n throwError('app.json expo.ios.buildNumber is not an integer');\n }\n\n if (!/\\d+/.test(androidVersionCode)) {\n throwError('app.json expo.android.versionCode is not an integer');\n }\n\n if (iosVersionCode !== androidVersionCode) {\n throwError('app.json expo.ios.buildNumber is not equal with expo.android.versionCode');\n }\n\n if (!semver.valid(versionName)) {\n throwError('VERSION_NAME is not a valid semver format');\n }\n\n OptionHolder.versionName = versionName;\n OptionHolder.versionCode = iosVersionCode;\n }\n}\n\nexport async function injectBinaryVersions({\n versionCode,\n versionName,\n}: {\n versionName: string;\n versionCode: string;\n}) {\n const files = readdir(OptionHolder.projectDir);\n\n const jsConfigFiles = ['app.config.ts', 'app.config.js', 'app.config.cjs', 'app.config.mjs'];\n const jsonConfigFile = 'app.json';\n\n for (const jsConfigFile of jsConfigFiles) {\n if (files.includes(jsConfigFile)) {\n await injectToJsConfigFile(jsConfigFile);\n return;\n }\n }\n\n if (files.includes(jsonConfigFile)) {\n await injectToJsonConfigFile(jsonConfigFile);\n return;\n }\n\n throwError('expo config file not found');\n\n async function injectToJsConfigFile(filename: string) {\n const filePath = resolve(OptionHolder.projectDir, filename);\n let content = read(filePath);\n\n content = content.replace(\n /const VERSION_NAME = '(.*?)';/,\n `const VERSION_NAME = '${versionName}';`,\n );\n content = content.replace(\n /const VERSION_CODE = (.*?);/,\n `const VERSION_CODE = ${versionCode};`,\n );\n\n write(filePath, content);\n }\n\n async function injectToJsonConfigFile(filename: string) {\n const filePath = resolve(OptionHolder.projectDir, filename);\n const json = readJsonSlow(filePath);\n\n json.expo.version = versionName;\n json.expo.ios.buildNumber = versionCode;\n json.expo.android.versionCode = +versionCode;\n\n writeJson(filePath, json);\n }\n}\n","import { promptCommonInputs } from './promptCommonInputs';\nimport { hydrateKeyholderFileValues } from '../hydrateKeyholderFileValues';\nimport { parseBinaryVersions } from '../VersionUtil';\n\nexport async function setup() {\n await promptCommonInputs();\n await hydrateKeyholderFileValues();\n await parseBinaryVersions();\n}\n","import { $, spinner } from 'zx';\nimport { remove, resolve, iterateDir, copy } from '../FileUtil';\nimport { OptionHolder } from '../OptionHolder';\nimport { logger } from '../logger';\nimport { injectTemplatePlaceHolders } from '../injectTemplatePlaceHolders';\n\nexport async function prepareIos() {\n const srcDir = resolve(OptionHolder.cli.templateDir, 'ios');\n const destDir = resolve(OptionHolder.projectDir, 'ios');\n\n await spinner(\n 'Prebuild iOS',\n () => $`cd ${OptionHolder.projectDir} && expo prebuild -p ios --no-install`,\n );\n logger.success('expo prebuild');\n\n await iterateDir(srcDir, async (file) => {\n const filePath = resolve(srcDir, file);\n remove(resolve(destDir, file));\n copy(filePath, resolve(destDir, file));\n });\n logger.success('Inject iOS templates');\n\n await injectTemplatePlaceHolders(resolve(destDir, 'fastlane'));\n logger.success('Hydrate template placeholders');\n}\n","import { padZero } from '@mj-studio/js-util';\n\nexport function calculateElapsed(t: number) {\n let seconds = Math.floor((Date.now() - t) / 1000);\n const minutes = Math.floor(seconds / 60);\n seconds = seconds % 60;\n return `${minutes}:${padZero(seconds)}`;\n}\n"],"mappings":"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","names":["join","resolve","path","path","resolve","join","path","path","resolve","resolve","resolve","$","spinner","resolve","spinner","$","spinner","$","chalk","chalk","resolve","$","spinner"]}
1
+ {"version":3,"sources":["../../src/util/setup/prepareAndroid.ts","../../src/util/FileUtil.ts","../../package.json","../../src/util/OptionHolder.ts","../../src/util/logger.ts","../../src/util/iterateAllFiles.ts","../../src/util/injectTemplatePlaceHolders.ts","../../src/util/EnvUtil.ts","../../src/util/setup/promptCommonInputs.ts","../../src/util/hydrateKeyholderFileValues.ts","../../src/util/throwError.ts","../../src/util/VersionUtil.ts","../../src/util/setup/setup.ts","../../src/util/setup/prepareIos.ts","../../src/command/build.ts","../../src/util/calculateElapsed.ts","../../src/util/input/InqueryInputs.ts","../../src/util/FastlaneOption.ts"],"sourcesContent":["import { spinner, $ } from 'zx';\nimport { resolve, remove, iterateDir, copy, read, write, relativePath } from '../FileUtil';\nimport { OptionHolder } from '../OptionHolder';\nimport { logger } from '../logger';\nimport { injectTemplatePlaceHolders } from '../injectTemplatePlaceHolders';\n\nexport async function prepareAndroid() {\n const srcDir = resolve(OptionHolder.cli.templateDir, 'android');\n const destDir = resolve(OptionHolder.projectDir, 'android');\n\n await spinner(\n 'Prebuild Android',\n () => $`cd ${OptionHolder.projectDir} && expo prebuild -p android --no-install`,\n );\n logger.success('expo prebuild');\n\n await iterateDir(srcDir, async (file) => {\n const filePath = resolve(srcDir, file);\n remove(resolve(destDir, file));\n copy(filePath, resolve(destDir, file));\n });\n logger.success('Inject Android templates');\n\n await replaceAndroidSigningConfig(destDir);\n logger.success('Overwrite Android Release Signing Config');\n\n await injectTemplatePlaceHolders(resolve(destDir, 'fastlane'));\n logger.success('Hydrate template placeholders');\n}\n\nasync function replaceAndroidSigningConfig(destDir: string) {\n const buildGradleDirPath = resolve(destDir, 'app');\n const buildGradlePath = resolve(destDir, 'app', 'build.gradle');\n const {\n android_keystore_store_password,\n android_keystore_key_alias,\n android_keystore_key_password,\n } = OptionHolder.keyholderMap;\n\n const content = read(buildGradlePath).replace(\n /signingConfigs.*?{.*?debug.*?{.*?}.*?}/s,\n `\n signingConfigs {\n debug {\n storeFile file('${relativePath(buildGradleDirPath, resolve(OptionHolder.outputOfInitDir, 'key', 'android_release_keystore.jks'))}')\n storePassword '${android_keystore_store_password}'\n keyAlias '${android_keystore_key_alias}'\n keyPassword '${android_keystore_key_password}'\n }\n }\n `,\n );\n write(buildGradlePath, content);\n}\n","import fs from 'fs-extra';\nimport * as path from 'path';\n\nexport const join = path.join;\nexport const resolve = path.resolve;\n\nexport function exist(path: string) {\n return fs.existsSync(path);\n}\n\nexport function isDir(path: string) {\n return exist(path) && fs.lstatSync(path).isDirectory();\n}\n\nexport function relativePath(from: string, to: string) {\n return path.relative(from, to);\n}\n\nexport function isFile(path: string) {\n return exist(path) && fs.lstatSync(path).isFile();\n}\n\nexport function read(path: string) {\n return fs.readFileSync(path, { encoding: 'utf8' });\n}\n\nexport function readdir(path: string) {\n return fs.readdirSync(path);\n}\n\n// you should require when possible(optimized in js)\nexport function readJsonSlow(path: string) {\n return fs.readJSONSync(path);\n}\n\nexport function write(p: string, content: string) {\n const dir = path.dirname(p);\n if (!exist(dir)) {\n fs.mkdirSync(dir, { recursive: true });\n }\n\n return fs.writeFileSync(p, content);\n}\nexport function copy(src: string, dest: string, options?: fs.CopyOptionsSync) {\n fs.copySync(src, dest, options);\n}\n\nexport function writeJson(path: string, json: any) {\n return write(path, JSON.stringify(json, null, 2));\n}\n\nexport function remove(path: string) {\n if (!exist(path)) {\n return;\n }\n\n if (fs.lstatSync(path).isDirectory()) {\n return fs.rmSync(path, { force: true, recursive: true });\n } else {\n return fs.rmSync(path, { force: true });\n }\n}\n\nexport async function iterateDir(path: string, fn: (file: string) => Promise<void> | void) {\n if (!isDir(path)) {\n return;\n }\n\n for (const file of fs.readdirSync(path)) {\n await fn(file);\n }\n}\n","{\n \"name\": \"expo-release-it\",\n \"module\": \"src/index.ts\",\n \"type\": \"module\",\n \"version\": \"0.0.17\",\n \"license\": \"MIT\",\n \"scripts\": {\n \"build\": \"tsup\",\n \"dev\": \"bun run build && NODE_ENV=development node bin/expo-release-it.mjs\",\n \"release\": \"yarn build && release-it\",\n \"android\": \"expo run:android\",\n \"ios\": \"expo run:ios\",\n \"t\": \"tsc --noEmit -p .\"\n },\n \"dependencies\": {\n \"@inquirer/prompts\": \"^7.4.1\",\n \"@mj-studio/js-util\": \"^1.1.20\",\n \"chalk\": \"^5.4.1\",\n \"commander\": \"^13.1.0\",\n \"fs-extra\": \"^11.3.0\",\n \"react\": \"18.3.1\",\n \"react-native\": \"0.76.9\",\n \"semver\": \"^7.7.1\",\n \"url\": \"^0.11.4\",\n \"zx\": \"^8.5.3\"\n },\n \"devDependencies\": {\n \"@types/bun\": \"latest\",\n \"@types/fs-extra\": \"^11.0.4\",\n \"@types/semver\": \"^7.7.0\",\n \"prettier\": \"3.5.3\",\n \"release-it\": \"^19.0.1\",\n \"tiny-glob\": \"^0.2.9\",\n \"tsup\": \"^8.4.0\",\n \"typescript\": \"^5.8.3\"\n },\n \"workspaces\": [\n \"example\"\n ],\n \"bin\": \"./bin/expo-release-it.mjs\",\n \"files\": [\n \"build\",\n \"package.json\",\n \"bin\",\n \"template\"\n ],\n \"packageManager\": \"yarn@4.9.1\"\n}\n","import pkgJson from '../../package.json';\nimport { resolve } from './FileUtil';\nimport { fileURLToPath } from 'url';\n\n/**\n * CLI Comprehensive options\n * Each values can be empty by command and timing.\n */\nexport const OptionHolder: {\n // cli specific options\n cli: {\n // cli version\n version: string;\n // cli project root directory\n rootDir: string;\n // cli template source directory\n templateDir: string;\n };\n input: {\n platform: 'android' | 'ios';\n uploadMetadata: boolean;\n androidOutput: 'apk' | 'aab';\n pod: boolean;\n };\n keyholderMap: {\n ios_app_identifier: string;\n ios_app_store_connect_team_id: string;\n ios_developer_team_id: string;\n ios_match_git_url: string;\n ios_app_store_connect_api_key_id: string;\n ios_app_store_connect_api_key_issuer_id: string;\n ios_xcode_project_target: string;\n ios_match_password: string;\n\n android_keystore_store_password: string;\n android_keystore_key_alias: string;\n android_keystore_key_password: string;\n android_package_name: string;\n };\n iosBundleIdentifier: string;\n androidPackageName: string;\n templateDirNames: string[];\n // dest project root directory\n projectDir: string;\n // dest project output of init command direcotry\n outputOfInitDir: string;\n keyDir: string;\n keyholderFilePath: string;\n versionName: string;\n versionCode: string;\n} = {\n cli: {\n version: pkgJson.version,\n rootDir: resolve(fileURLToPath(import.meta.url), '../..'),\n templateDir: resolve(fileURLToPath(import.meta.url), '../../template'),\n },\n input: {} as any,\n keyholderMap: {} as any,\n templateDirNames: ['key'],\n iosBundleIdentifier: '',\n androidPackageName: '',\n projectDir: '',\n outputOfInitDir: '',\n keyDir: '',\n keyholderFilePath: '',\n versionName: '',\n versionCode: '',\n};\n","import chalk from 'chalk';\n\nexport const logger = {\n success: (...msg: any[]) => console.log(chalk.green(`✔ ${msg.join(', ')}`)),\n error: (...msg: any[]) => console.log(chalk.red(`✖ ${msg.join(', ')}`)),\n warn: (...msg: any[]) => console.log(chalk.yellow(`⚠ ${msg.join(', ')}`)),\n info: (...msg: any[]) => console.log(chalk.cyan(`ℹ ${msg.join(', ')}`)),\n title: (...msg: any[]) => console.log(chalk.bold.blue(`\\n${msg.join(', ')}`)),\n dim: (...msg: any[]) => console.log(chalk.dim(msg.join(', '))),\n};\n","import { readdir, isFile, isDir, join } from './FileUtil';\n\nexport async function iterateAllFiles(root: string, callback: (filePath: string) => Promise<void>) {\n await go(root);\n\n async function go(dirPath: string) {\n const paths = readdir(dirPath).map((f) => join(dirPath, f));\n\n for (const p of paths) {\n if (isFile(p)) {\n await callback(p);\n } else if (isDir(p)) {\n await go(p);\n }\n }\n }\n}\n","import { iterateAllFiles } from './iterateAllFiles';\nimport { path } from 'zx';\nimport { read, relativePath, write } from './FileUtil';\nimport { OptionHolder } from './OptionHolder';\n\nexport async function injectTemplatePlaceHolders(root: string) {\n await iterateAllFiles(root, async (filePath: string) => {\n const dirPath = path.dirname(filePath);\n let content = read(filePath);\n for (const [key, value] of Object.entries(OptionHolder.keyholderMap)) {\n content = content.replaceAll(`{{${key}}}`, value);\n }\n // dynamic replacements\n content = content.replaceAll(\n '{{key_dir_relative_path}}',\n relativePath(dirPath, OptionHolder.keyDir),\n );\n write(filePath, content);\n });\n}\n","export const isDev = process.env.NODE_ENV === 'development';\nexport const isWin = process.platform.startsWith('win');\n","import { OptionHolder } from '../OptionHolder';\nimport { isDev } from '../EnvUtil';\nimport { resolve } from '../FileUtil';\n\nexport async function promptCommonInputs() {\n OptionHolder.projectDir = isDev ? resolve('example') : resolve('.');\n\n OptionHolder.outputOfInitDir = resolve(OptionHolder.projectDir, 'expo-release-it');\n OptionHolder.keyDir = resolve(OptionHolder.outputOfInitDir, 'key');\n OptionHolder.keyholderFilePath = resolve(OptionHolder.outputOfInitDir, 'keyholder.json');\n}\n","import { OptionHolder } from './OptionHolder';\nimport { readJsonSlow } from './FileUtil';\n\nexport async function hydrateKeyholderFileValues() {\n Object.assign(OptionHolder.keyholderMap, readJsonSlow(OptionHolder.keyholderFilePath));\n}\n","import { logger } from './logger';\n\nexport function throwError(message: string, e?: any): never {\n if (e) {\n logger.error(message, e);\n } else {\n logger.error(message);\n }\n process.exit(1);\n}\n","import { OptionHolder } from './OptionHolder';\nimport { throwError } from './throwError';\nimport semver from 'semver';\nimport { readdir, read, readJsonSlow, write, writeJson, resolve } from './FileUtil';\n\nexport async function parseBinaryVersions() {\n const files = readdir(OptionHolder.projectDir);\n\n const jsConfigFiles = ['app.config.ts', 'app.config.js', 'app.config.cjs', 'app.config.mjs'];\n const jsonConfigFile = 'app.json';\n\n for (const jsConfigFile of jsConfigFiles) {\n if (files.includes(jsConfigFile)) {\n await parseFromJsConfigFile(jsConfigFile);\n return;\n }\n }\n\n if (files.includes(jsonConfigFile)) {\n await parseFromJsonConfigFile(jsonConfigFile);\n return;\n }\n\n throwError('expo config file not found');\n\n async function parseFromJsConfigFile(filename: string) {\n const filePath = resolve(OptionHolder.projectDir, filename);\n const content = read(filePath);\n\n const VERSION_NAME = /const VERSION_NAME = '(.*?)';/.exec(content)?.[1];\n const VERSION_CODE = /const VERSION_CODE = (.*?);/.exec(content)?.[1];\n\n if (!VERSION_NAME) {\n throwError('cannot parse version name');\n }\n if (!VERSION_CODE) {\n throwError('cannot parse version code');\n }\n\n if (!semver.valid(VERSION_NAME)) {\n throwError('VERSION_NAME is not a valid semver format');\n }\n\n OptionHolder.versionName = VERSION_NAME;\n OptionHolder.versionCode = VERSION_CODE;\n }\n\n async function parseFromJsonConfigFile(filename: string) {\n const filePath = resolve(OptionHolder.projectDir, filename);\n const json = readJsonSlow(filePath);\n\n const versionName = json.expo?.version + '';\n const iosVersionCode = json.expo?.ios?.buildNumber + '';\n const androidVersionCode = json.expo?.android?.versionCode + '';\n\n if (!/\\d+/.test(iosVersionCode)) {\n throwError('app.json expo.ios.buildNumber is not an integer');\n }\n\n if (!/\\d+/.test(androidVersionCode)) {\n throwError('app.json expo.android.versionCode is not an integer');\n }\n\n if (iosVersionCode !== androidVersionCode) {\n throwError('app.json expo.ios.buildNumber is not equal with expo.android.versionCode');\n }\n\n if (!semver.valid(versionName)) {\n throwError('VERSION_NAME is not a valid semver format');\n }\n\n OptionHolder.versionName = versionName;\n OptionHolder.versionCode = iosVersionCode;\n }\n}\n\nexport async function injectBinaryVersions({\n versionCode,\n versionName,\n}: {\n versionName: string;\n versionCode: string;\n}) {\n const files = readdir(OptionHolder.projectDir);\n\n const jsConfigFiles = ['app.config.ts', 'app.config.js', 'app.config.cjs', 'app.config.mjs'];\n const jsonConfigFile = 'app.json';\n\n for (const jsConfigFile of jsConfigFiles) {\n if (files.includes(jsConfigFile)) {\n await injectToJsConfigFile(jsConfigFile);\n return;\n }\n }\n\n if (files.includes(jsonConfigFile)) {\n await injectToJsonConfigFile(jsonConfigFile);\n return;\n }\n\n throwError('expo config file not found');\n\n async function injectToJsConfigFile(filename: string) {\n const filePath = resolve(OptionHolder.projectDir, filename);\n let content = read(filePath);\n\n content = content.replace(\n /const VERSION_NAME = '(.*?)';/,\n `const VERSION_NAME = '${versionName}';`,\n );\n content = content.replace(\n /const VERSION_CODE = (.*?);/,\n `const VERSION_CODE = ${versionCode};`,\n );\n\n write(filePath, content);\n }\n\n async function injectToJsonConfigFile(filename: string) {\n const filePath = resolve(OptionHolder.projectDir, filename);\n const json = readJsonSlow(filePath);\n\n json.expo.version = versionName;\n json.expo.ios.buildNumber = versionCode;\n json.expo.android.versionCode = +versionCode;\n\n writeJson(filePath, json);\n }\n}\n","import { promptCommonInputs } from './promptCommonInputs';\nimport { hydrateKeyholderFileValues } from '../hydrateKeyholderFileValues';\nimport { parseBinaryVersions } from '../VersionUtil';\n\nexport async function setup() {\n await promptCommonInputs();\n await hydrateKeyholderFileValues();\n await parseBinaryVersions();\n}\n","import { $, spinner } from 'zx';\nimport { remove, resolve, iterateDir, copy } from '../FileUtil';\nimport { OptionHolder } from '../OptionHolder';\nimport { logger } from '../logger';\nimport { injectTemplatePlaceHolders } from '../injectTemplatePlaceHolders';\n\nexport async function prepareIos() {\n const srcDir = resolve(OptionHolder.cli.templateDir, 'ios');\n const destDir = resolve(OptionHolder.projectDir, 'ios');\n\n await spinner(\n 'Prebuild iOS',\n () => $`cd ${OptionHolder.projectDir} && expo prebuild -p ios --no-install`,\n );\n logger.success('expo prebuild');\n\n await iterateDir(srcDir, async (file) => {\n const filePath = resolve(srcDir, file);\n remove(resolve(destDir, file));\n copy(filePath, resolve(destDir, file));\n });\n logger.success('Inject iOS templates');\n\n await injectTemplatePlaceHolders(resolve(destDir, 'fastlane'));\n logger.success('Hydrate template placeholders');\n}\n","import { prepareAndroid } from '../util/setup/prepareAndroid';\nimport { setup } from '../util/setup/setup';\nimport { prepareIos } from '../util/setup/prepareIos';\nimport { logger } from '../util/logger';\nimport { OptionHolder } from '../util/OptionHolder';\nimport { spinner, $ } from 'zx';\nimport { resolve, remove, copy, relativePath } from '../util/FileUtil';\nimport chalk from 'chalk';\nimport { calculateElapsed } from '../util/calculateElapsed';\nimport { isWin } from '../util/EnvUtil';\nimport { InqueryInputs } from '../util/input/InqueryInputs';\nimport { getIosFastlaneOptions } from '../util/FastlaneOption';\n\nexport async function build({ options }: { options: any }) {\n Object.assign(OptionHolder.input, options);\n const startTime = Date.now();\n await setup();\n await promptInputs();\n\n logger.info('Build Started');\n logger.info(`Version: ${OptionHolder.versionName}(${OptionHolder.versionCode})`);\n\n if (OptionHolder.input.platform === 'ios') {\n await buildIos();\n logger.success(`iOS Build ${chalk.bold.inverse(calculateElapsed(startTime))}`);\n } else {\n await buildAndroid();\n logger.success(`Android Build ${chalk.bold.inverse(calculateElapsed(startTime))}`);\n }\n}\n\nasync function promptInputs() {\n await InqueryInputs.platform();\n await InqueryInputs.podinstall();\n await InqueryInputs.androidBuildOutput();\n}\n\nasync function buildIos() {\n const iosDir = resolve(OptionHolder.projectDir, 'ios');\n const $$ = $({\n verbose: false,\n cwd: iosDir,\n env: {\n MATCH_PASSWORD: OptionHolder.keyholderMap.ios_match_password,\n },\n });\n await prepareIos();\n await fastlane();\n\n async function fastlane() {\n await spinner('Bundler Install', () => $$`bundle install`);\n logger.success('Bundler Install');\n\n if (OptionHolder.input.pod) {\n await spinner('Pod Install', () => $$`bundle exec pod install`);\n logger.success('Pod Install');\n }\n remove(resolve(iosDir, '.xcode.env.local'));\n\n await spinner('Fastlane', () => $$`bundle exec fastlane build ${getIosFastlaneOptions()}`);\n }\n}\nasync function buildAndroid() {\n const androidDir = resolve(OptionHolder.projectDir, 'android');\n const $$ = $({\n verbose: false,\n cwd: androidDir,\n });\n await prepareAndroid();\n await fastlane();\n\n async function fastlane() {\n await spinner('Bundler Install', () => $$`bundle install`);\n logger.success('Bundler Install');\n\n let buildOutputDir: string;\n let outputDir: string;\n\n if (OptionHolder.input.androidOutput === 'aab') {\n // aab: app/build/outputs/bundle/release/app-release.aab\n await spinner(\n 'Bundle AAB',\n () => $$`${isWin ? 'gradle.bat' : './gradlew'} app:bundleRelease`,\n );\n buildOutputDir = resolve(androidDir, 'app', 'build', 'outputs', 'bundle', 'release');\n outputDir = resolve(OptionHolder.outputOfInitDir, 'output', 'android', 'aab');\n } else {\n // apk: app/build/outputs/apk/release/app-release.apk\n await spinner(\n 'Bundle APK',\n () => $$`${isWin ? 'gradle.bat' : './gradlew'} app:assembleRelease`,\n );\n buildOutputDir = resolve(androidDir, 'app', 'build', 'outputs', 'apk', 'release');\n outputDir = resolve(OptionHolder.outputOfInitDir, 'output', 'android', 'apk');\n }\n\n remove(outputDir);\n copy(buildOutputDir, outputDir);\n\n logger.success(`artifact generated: ${relativePath(OptionHolder.projectDir, outputDir)}`);\n }\n}\n","import { padZero } from '@mj-studio/js-util';\n\nexport function calculateElapsed(t: number) {\n let seconds = Math.floor((Date.now() - t) / 1000);\n const minutes = Math.floor(seconds / 60);\n seconds = seconds % 60;\n return `${minutes}:${padZero(seconds)}`;\n}\n","import { OptionHolder } from '../OptionHolder';\nimport { select } from '@inquirer/prompts';\nimport { is } from '@mj-studio/js-util';\n\nexport const InqueryInputs = {\n platform: async () => {\n if (!OptionHolder.input.platform) {\n OptionHolder.input.platform = await select({\n message: 'Platform to release',\n choices: [\n { name: 'ios', value: 'ios', description: 'Release ios' },\n { name: 'android', value: 'android', description: 'Release android' },\n ],\n });\n }\n },\n podinstall: async () => {\n if (OptionHolder.input.platform === 'ios') {\n OptionHolder.input.pod = await select({\n message: 'Install Cocoapods',\n choices: [\n { name: 'yes', value: true, description: 'Install pods before release' },\n { name: 'no', value: false, description: 'Skip pods install' },\n ],\n });\n }\n },\n androidBuildOutput: async () => {\n if (OptionHolder.input.platform === 'android') {\n if (!OptionHolder.input.androidOutput) {\n OptionHolder.input.androidOutput = await select({\n message: 'Android Output',\n choices: [\n { name: 'aab', value: 'aab', description: 'Build as App bundle' },\n { name: 'apk', value: 'apk', description: 'Build as APK' },\n ],\n });\n }\n }\n },\n uploadMetadata: async () => {\n if (!is.boolean(OptionHolder.input.uploadMetadata)) {\n OptionHolder.input.uploadMetadata = await select({\n message: 'Upload Metadata(screenshot, title, description, ...)',\n choices: [\n { name: 'yes', value: true, description: 'Upload' },\n { name: 'no', value: false, description: \"Don't Upload\" },\n ],\n });\n }\n },\n};\n","import { OptionHolder } from './OptionHolder';\nimport { resolve } from './FileUtil';\n\nexport function getAndroidFastlaneOptions() {\n return [\n `version_name:${OptionHolder.versionName}`,\n `version_code:${OptionHolder.versionCode}`,\n `package_name:${OptionHolder.androidPackageName}`,\n `upload_metadata:${OptionHolder.input.uploadMetadata}`,\n `aab_path:${resolve(OptionHolder.outputOfInitDir, 'output', 'android', 'aab', 'app-release.aab')}`,\n `apk_path:${resolve(OptionHolder.outputOfInitDir, 'output', 'android', 'apk', 'app-release.apk')}`,\n `skip_upload_apk:${OptionHolder.input.androidOutput !== 'apk'}`,\n `skip_upload_aab:${OptionHolder.input.androidOutput !== 'aab'}`,\n ];\n}\n\nexport function getIosFastlaneOptions() {\n return [\n `version_name:${OptionHolder.versionName}`,\n `version_code:${OptionHolder.versionCode}`,\n `ios_app_identifier:${OptionHolder.iosBundleIdentifier}`,\n `ios_xcode_project_target:${OptionHolder.keyholderMap.ios_xcode_project_target}`,\n `ios_developer_team_id:${OptionHolder.keyholderMap.ios_developer_team_id}`,\n `ios_app_store_connect_api_key_id:${OptionHolder.keyholderMap.ios_app_store_connect_api_key_id}`,\n `ios_app_store_connect_api_key_issuer_id:${OptionHolder.keyholderMap.ios_app_store_connect_api_key_issuer_id}`,\n `api_key_filepath:${resolve(OptionHolder.keyDir, 'ios_testflight_upload_api_key.p8')}`,\n `upload_metadata:${OptionHolder.input.uploadMetadata}`,\n `ipa_path:${resolve(OptionHolder.outputOfInitDir, 'output', 'ios', 'app.ipa')}`,\n `ipa_dir:${resolve(OptionHolder.outputOfInitDir, 'output', 'ios')}`,\n `ipa_name:app.ipa`,\n ];\n}\n"],"mappings":"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","names":["join","resolve","path","path","resolve","join","path","path","resolve","resolve","resolve","$","spinner","resolve","spinner","$","spinner","$","chalk","resolve","chalk","resolve","$","spinner"]}
@@ -1,6 +1,5 @@
1
- type BumpOptions = {};
2
1
  declare function bump({ options }: {
3
- options: BumpOptions;
2
+ options: any;
4
3
  }): Promise<void>;
5
4
 
6
- export { type BumpOptions, bump };
5
+ export { bump };
@@ -3,7 +3,7 @@ var package_default = {
3
3
  name: "expo-release-it",
4
4
  module: "src/index.ts",
5
5
  type: "module",
6
- version: "0.0.15",
6
+ version: "0.0.17",
7
7
  license: "MIT",
8
8
  scripts: {
9
9
  build: "tsup",
@@ -83,11 +83,7 @@ var OptionHolder = {
83
83
  rootDir: resolve2(fileURLToPath(import.meta.url), "../.."),
84
84
  templateDir: resolve2(fileURLToPath(import.meta.url), "../../template")
85
85
  },
86
- init: {},
87
- bump: {},
88
- build: {},
89
- upload: {},
90
- submit: {},
86
+ input: {},
91
87
  keyholderMap: {},
92
88
  templateDirNames: ["key"],
93
89
  iosBundleIdentifier: "",
@@ -230,22 +226,9 @@ var isWin = process.platform.startsWith("win");
230
226
  import { $ } from "zx";
231
227
 
232
228
  // src/util/setup/promptCommonInputs.ts
233
- import { input } from "@inquirer/prompts";
234
229
  async function promptCommonInputs() {
235
- OptionHolder.projectDir = isDev ? resolve2("example") : resolve2(
236
- await input({
237
- message: "react native project root directory path",
238
- default: isDev ? "example" : ".",
239
- validate: (value) => {
240
- const p = resolve2(value, "package.json");
241
- if (!exist(p)) {
242
- return "package.json hasn't been detected. provider valid project root.";
243
- }
244
- return true;
245
- }
246
- })
247
- );
248
- OptionHolder.outputOfInitDir = resolve2(OptionHolder.projectDir, "expo-local-build");
230
+ OptionHolder.projectDir = isDev ? resolve2("example") : resolve2(".");
231
+ OptionHolder.outputOfInitDir = resolve2(OptionHolder.projectDir, "expo-release-it");
249
232
  OptionHolder.keyDir = resolve2(OptionHolder.outputOfInitDir, "key");
250
233
  OptionHolder.keyholderFilePath = resolve2(OptionHolder.outputOfInitDir, "keyholder.json");
251
234
  }
@@ -264,7 +247,7 @@ async function setup() {
264
247
 
265
248
  // src/command/bump.ts
266
249
  async function bump({ options }) {
267
- Object.assign(OptionHolder.bump, options);
250
+ Object.assign(OptionHolder.input, options);
268
251
  await preCheck();
269
252
  await setup();
270
253
  logger.info(`current version: ${OptionHolder.versionName}(${OptionHolder.versionCode})`);
@@ -1 +1 @@
1
- {"version":3,"sources":["../../package.json","../../src/util/FileUtil.ts","../../src/util/OptionHolder.ts","../../src/util/logger.ts","../../src/util/throwError.ts","../../src/util/VersionUtil.ts","../../src/command/bump.ts","../../src/util/EnvUtil.ts","../../src/util/setup/promptCommonInputs.ts","../../src/util/hydrateKeyholderFileValues.ts","../../src/util/setup/setup.ts"],"sourcesContent":["{\n \"name\": \"expo-release-it\",\n \"module\": \"src/index.ts\",\n \"type\": \"module\",\n \"version\": \"0.0.15\",\n \"license\": \"MIT\",\n \"scripts\": {\n \"build\": \"tsup\",\n \"dev\": \"bun run build && NODE_ENV=development node bin/expo-release-it.mjs\",\n \"release\": \"yarn build && release-it\",\n \"android\": \"expo run:android\",\n \"ios\": \"expo run:ios\",\n \"t\": \"tsc --noEmit -p .\"\n },\n \"dependencies\": {\n \"@inquirer/prompts\": \"^7.4.1\",\n \"@mj-studio/js-util\": \"^1.1.20\",\n \"chalk\": \"^5.4.1\",\n \"commander\": \"^13.1.0\",\n \"fs-extra\": \"^11.3.0\",\n \"react\": \"18.3.1\",\n \"react-native\": \"0.76.9\",\n \"semver\": \"^7.7.1\",\n \"url\": \"^0.11.4\",\n \"zx\": \"^8.5.3\"\n },\n \"devDependencies\": {\n \"@types/bun\": \"latest\",\n \"@types/fs-extra\": \"^11.0.4\",\n \"@types/semver\": \"^7.7.0\",\n \"prettier\": \"3.5.3\",\n \"release-it\": \"^19.0.1\",\n \"tiny-glob\": \"^0.2.9\",\n \"tsup\": \"^8.4.0\",\n \"typescript\": \"^5.8.3\"\n },\n \"workspaces\": [\n \"example\"\n ],\n \"bin\": \"./bin/expo-release-it.mjs\",\n \"files\": [\n \"build\",\n \"package.json\",\n \"bin\",\n \"template\"\n ],\n \"packageManager\": \"yarn@4.9.1\"\n}\n","import fs from 'fs-extra';\nimport * as path from 'path';\n\nexport const join = path.join;\nexport const resolve = path.resolve;\n\nexport function exist(path: string) {\n return fs.existsSync(path);\n}\n\nexport function isDir(path: string) {\n return exist(path) && fs.lstatSync(path).isDirectory();\n}\n\nexport function relativePath(from: string, to: string) {\n return path.relative(from, to);\n}\n\nexport function isFile(path: string) {\n return exist(path) && fs.lstatSync(path).isFile();\n}\n\nexport function read(path: string) {\n return fs.readFileSync(path, { encoding: 'utf8' });\n}\n\nexport function readdir(path: string) {\n return fs.readdirSync(path);\n}\n\n// you should require when possible(optimized in js)\nexport function readJsonSlow(path: string) {\n return fs.readJSONSync(path);\n}\n\nexport function write(p: string, content: string) {\n const dir = path.dirname(p);\n if (!exist(dir)) {\n fs.mkdirSync(dir, { recursive: true });\n }\n\n return fs.writeFileSync(p, content);\n}\nexport function copy(src: string, dest: string, options?: fs.CopyOptionsSync) {\n fs.copySync(src, dest, options);\n}\n\nexport function writeJson(path: string, json: any) {\n return write(path, JSON.stringify(json, null, 2));\n}\n\nexport function remove(path: string) {\n if (!exist(path)) {\n return;\n }\n\n if (fs.lstatSync(path).isDirectory()) {\n return fs.rmSync(path, { force: true, recursive: true });\n } else {\n return fs.rmSync(path, { force: true });\n }\n}\n\nexport async function iterateDir(path: string, fn: (file: string) => Promise<void> | void) {\n if (!isDir(path)) {\n return;\n }\n\n for (const file of fs.readdirSync(path)) {\n await fn(file);\n }\n}\n","import pkgJson from '../../package.json';\nimport { resolve } from './FileUtil';\nimport type { BuildOptions } from '../command/build';\nimport type { InitOptions } from '../command/init';\nimport type { BumpOptions } from '../command/bump';\nimport type { SubmitOptions } from '../command/submit';\nimport type { UploadOptions } from '../command/upload';\nimport { fileURLToPath } from 'url';\n\n/**\n * CLI Comprehensive options\n * Each values can be empty by command and timing.\n */\nexport const OptionHolder: {\n // cli specific options\n cli: {\n // cli version\n version: string;\n // cli project root directory\n rootDir: string;\n // cli template source directory\n templateDir: string;\n };\n init: InitOptions;\n bump: BumpOptions;\n build: BuildOptions;\n upload: UploadOptions;\n submit: SubmitOptions;\n keyholderMap: {\n ios_app_identifier: string;\n ios_app_store_connect_team_id: string;\n ios_developer_team_id: string;\n ios_match_git_url: string;\n ios_app_store_connect_api_key_id: string;\n ios_app_store_connect_api_key_issuer_id: string;\n ios_xcode_project_target: string;\n ios_match_password: string;\n\n key_dir_relative_path: string;\n\n android_keystore_store_password: string;\n android_keystore_key_alias: string;\n android_keystore_key_password: string;\n android_package_name: string;\n };\n iosBundleIdentifier: string;\n androidPackageName: string;\n templateDirNames: string[];\n // dest project root directory\n projectDir: string;\n // dest project output of init command direcotry\n outputOfInitDir: string;\n keyDir: string;\n keyholderFilePath: string;\n versionName: string;\n versionCode: string;\n} = {\n cli: {\n version: pkgJson.version,\n rootDir: resolve(fileURLToPath(import.meta.url), '../..'),\n templateDir: resolve(fileURLToPath(import.meta.url), '../../template'),\n },\n init: {} as any,\n bump: {} as any,\n build: {} as any,\n upload: {} as any,\n submit: {} as any,\n keyholderMap: {} as any,\n templateDirNames: ['key'],\n iosBundleIdentifier: '',\n androidPackageName: '',\n projectDir: '',\n outputOfInitDir: '',\n keyDir: '',\n keyholderFilePath: '',\n versionName: '',\n versionCode: '',\n};\n","import chalk from 'chalk';\n\nexport const logger = {\n success: (...msg: any[]) => console.log(chalk.green(`✔ ${msg.join(', ')}`)),\n error: (...msg: any[]) => console.log(chalk.red(`✖ ${msg.join(', ')}`)),\n warn: (...msg: any[]) => console.log(chalk.yellow(`⚠ ${msg.join(', ')}`)),\n info: (...msg: any[]) => console.log(chalk.cyan(`ℹ ${msg.join(', ')}`)),\n title: (...msg: any[]) => console.log(chalk.bold.blue(`\\n${msg.join(', ')}`)),\n dim: (...msg: any[]) => console.log(chalk.dim(msg.join(', '))),\n};\n","import { logger } from './logger';\n\nexport function throwError(message: string, e?: any): never {\n if (e) {\n logger.error(message, e);\n } else {\n logger.error(message);\n }\n process.exit(1);\n}\n","import { OptionHolder } from './OptionHolder';\nimport { throwError } from './throwError';\nimport semver from 'semver';\nimport { readdir, read, readJsonSlow, write, writeJson, resolve } from './FileUtil';\n\nexport async function parseBinaryVersions() {\n const files = readdir(OptionHolder.projectDir);\n\n const jsConfigFiles = ['app.config.ts', 'app.config.js', 'app.config.cjs', 'app.config.mjs'];\n const jsonConfigFile = 'app.json';\n\n for (const jsConfigFile of jsConfigFiles) {\n if (files.includes(jsConfigFile)) {\n await parseFromJsConfigFile(jsConfigFile);\n return;\n }\n }\n\n if (files.includes(jsonConfigFile)) {\n await parseFromJsonConfigFile(jsonConfigFile);\n return;\n }\n\n throwError('expo config file not found');\n\n async function parseFromJsConfigFile(filename: string) {\n const filePath = resolve(OptionHolder.projectDir, filename);\n const content = read(filePath);\n\n const VERSION_NAME = /const VERSION_NAME = '(.*?)';/.exec(content)?.[1];\n const VERSION_CODE = /const VERSION_CODE = (.*?);/.exec(content)?.[1];\n\n if (!VERSION_NAME) {\n throwError('cannot parse version name');\n }\n if (!VERSION_CODE) {\n throwError('cannot parse version code');\n }\n\n if (!semver.valid(VERSION_NAME)) {\n throwError('VERSION_NAME is not a valid semver format');\n }\n\n OptionHolder.versionName = VERSION_NAME;\n OptionHolder.versionCode = VERSION_CODE;\n }\n\n async function parseFromJsonConfigFile(filename: string) {\n const filePath = resolve(OptionHolder.projectDir, filename);\n const json = readJsonSlow(filePath);\n\n const versionName = json.expo?.version + '';\n const iosVersionCode = json.expo?.ios?.buildNumber + '';\n const androidVersionCode = json.expo?.android?.versionCode + '';\n\n if (!/\\d+/.test(iosVersionCode)) {\n throwError('app.json expo.ios.buildNumber is not an integer');\n }\n\n if (!/\\d+/.test(androidVersionCode)) {\n throwError('app.json expo.android.versionCode is not an integer');\n }\n\n if (iosVersionCode !== androidVersionCode) {\n throwError('app.json expo.ios.buildNumber is not equal with expo.android.versionCode');\n }\n\n if (!semver.valid(versionName)) {\n throwError('VERSION_NAME is not a valid semver format');\n }\n\n OptionHolder.versionName = versionName;\n OptionHolder.versionCode = iosVersionCode;\n }\n}\n\nexport async function injectBinaryVersions({\n versionCode,\n versionName,\n}: {\n versionName: string;\n versionCode: string;\n}) {\n const files = readdir(OptionHolder.projectDir);\n\n const jsConfigFiles = ['app.config.ts', 'app.config.js', 'app.config.cjs', 'app.config.mjs'];\n const jsonConfigFile = 'app.json';\n\n for (const jsConfigFile of jsConfigFiles) {\n if (files.includes(jsConfigFile)) {\n await injectToJsConfigFile(jsConfigFile);\n return;\n }\n }\n\n if (files.includes(jsonConfigFile)) {\n await injectToJsonConfigFile(jsonConfigFile);\n return;\n }\n\n throwError('expo config file not found');\n\n async function injectToJsConfigFile(filename: string) {\n const filePath = resolve(OptionHolder.projectDir, filename);\n let content = read(filePath);\n\n content = content.replace(\n /const VERSION_NAME = '(.*?)';/,\n `const VERSION_NAME = '${versionName}';`,\n );\n content = content.replace(\n /const VERSION_CODE = (.*?);/,\n `const VERSION_CODE = ${versionCode};`,\n );\n\n write(filePath, content);\n }\n\n async function injectToJsonConfigFile(filename: string) {\n const filePath = resolve(OptionHolder.projectDir, filename);\n const json = readJsonSlow(filePath);\n\n json.expo.version = versionName;\n json.expo.ios.buildNumber = versionCode;\n json.expo.android.versionCode = +versionCode;\n\n writeJson(filePath, json);\n }\n}\n","import { injectBinaryVersions } from '../util/VersionUtil';\nimport { throwError } from '../util/throwError';\nimport { logger } from '../util/logger';\nimport { OptionHolder } from '../util/OptionHolder';\nimport semver from 'semver';\nimport { isDev } from '../util/EnvUtil';\nimport { $ } from 'zx';\nimport { setup } from '../util/setup/setup';\n\nexport type BumpOptions = {};\n\nexport async function bump({ options }: { options: BumpOptions }) {\n Object.assign(OptionHolder.bump, options);\n await preCheck();\n await setup();\n\n logger.info(`current version: ${OptionHolder.versionName}(${OptionHolder.versionCode})`);\n const nextVersionName = semver.inc(OptionHolder.versionName, 'patch')!;\n const nextVersionCode = Number(OptionHolder.versionCode) + 1 + '';\n logger.info(`next version: ${nextVersionName}(${nextVersionCode})`);\n\n await injectBinaryVersions({ versionName: nextVersionName, versionCode: nextVersionCode });\n logger.success('Binary versions have been bumped in expo config file');\n}\n\nasync function preCheck() {\n if (isDev) return;\n try {\n let hasChange = false;\n try {\n await $`git diff --quiet HEAD`;\n } catch (_) {\n hasChange = true;\n }\n if (hasChange) {\n throwError('Workspace is not clean. Before bump version, you should commit all changes.');\n }\n } catch (e) {\n throwError('Precheck Failed', e);\n }\n}\n","export const isDev = process.env.NODE_ENV === 'development';\nexport const isWin = process.platform.startsWith('win');\n","import { OptionHolder } from '../OptionHolder';\nimport { input } from '@inquirer/prompts';\nimport { isDev } from '../EnvUtil';\nimport { exist, resolve } from '../FileUtil';\n\nexport async function promptCommonInputs() {\n OptionHolder.projectDir = isDev\n ? resolve('example')\n : resolve(\n await input({\n message: 'react native project root directory path',\n default: isDev ? 'example' : '.',\n validate: (value) => {\n const p = resolve(value, 'package.json');\n if (!exist(p)) {\n return \"package.json hasn\\'t been detected. provider valid project root.\";\n }\n return true;\n },\n }),\n );\n\n OptionHolder.outputOfInitDir = resolve(OptionHolder.projectDir, 'expo-local-build');\n OptionHolder.keyDir = resolve(OptionHolder.outputOfInitDir, 'key');\n OptionHolder.keyholderFilePath = resolve(OptionHolder.outputOfInitDir, 'keyholder.json');\n}\n","import { OptionHolder } from './OptionHolder';\nimport { readJsonSlow } from './FileUtil';\n\nexport async function hydrateKeyholderFileValues() {\n Object.assign(OptionHolder.keyholderMap, readJsonSlow(OptionHolder.keyholderFilePath));\n}\n","import { promptCommonInputs } from './promptCommonInputs';\nimport { hydrateKeyholderFileValues } from '../hydrateKeyholderFileValues';\nimport { parseBinaryVersions } from '../VersionUtil';\n\nexport async function setup() {\n await promptCommonInputs();\n await hydrateKeyholderFileValues();\n await parseBinaryVersions();\n}\n"],"mappings":"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","names":["resolve","path","path","path","resolve","resolve","semver","resolve","semver"]}
1
+ {"version":3,"sources":["../../package.json","../../src/util/FileUtil.ts","../../src/util/OptionHolder.ts","../../src/util/logger.ts","../../src/util/throwError.ts","../../src/util/VersionUtil.ts","../../src/command/bump.ts","../../src/util/EnvUtil.ts","../../src/util/setup/promptCommonInputs.ts","../../src/util/hydrateKeyholderFileValues.ts","../../src/util/setup/setup.ts"],"sourcesContent":["{\n \"name\": \"expo-release-it\",\n \"module\": \"src/index.ts\",\n \"type\": \"module\",\n \"version\": \"0.0.17\",\n \"license\": \"MIT\",\n \"scripts\": {\n \"build\": \"tsup\",\n \"dev\": \"bun run build && NODE_ENV=development node bin/expo-release-it.mjs\",\n \"release\": \"yarn build && release-it\",\n \"android\": \"expo run:android\",\n \"ios\": \"expo run:ios\",\n \"t\": \"tsc --noEmit -p .\"\n },\n \"dependencies\": {\n \"@inquirer/prompts\": \"^7.4.1\",\n \"@mj-studio/js-util\": \"^1.1.20\",\n \"chalk\": \"^5.4.1\",\n \"commander\": \"^13.1.0\",\n \"fs-extra\": \"^11.3.0\",\n \"react\": \"18.3.1\",\n \"react-native\": \"0.76.9\",\n \"semver\": \"^7.7.1\",\n \"url\": \"^0.11.4\",\n \"zx\": \"^8.5.3\"\n },\n \"devDependencies\": {\n \"@types/bun\": \"latest\",\n \"@types/fs-extra\": \"^11.0.4\",\n \"@types/semver\": \"^7.7.0\",\n \"prettier\": \"3.5.3\",\n \"release-it\": \"^19.0.1\",\n \"tiny-glob\": \"^0.2.9\",\n \"tsup\": \"^8.4.0\",\n \"typescript\": \"^5.8.3\"\n },\n \"workspaces\": [\n \"example\"\n ],\n \"bin\": \"./bin/expo-release-it.mjs\",\n \"files\": [\n \"build\",\n \"package.json\",\n \"bin\",\n \"template\"\n ],\n \"packageManager\": \"yarn@4.9.1\"\n}\n","import fs from 'fs-extra';\nimport * as path from 'path';\n\nexport const join = path.join;\nexport const resolve = path.resolve;\n\nexport function exist(path: string) {\n return fs.existsSync(path);\n}\n\nexport function isDir(path: string) {\n return exist(path) && fs.lstatSync(path).isDirectory();\n}\n\nexport function relativePath(from: string, to: string) {\n return path.relative(from, to);\n}\n\nexport function isFile(path: string) {\n return exist(path) && fs.lstatSync(path).isFile();\n}\n\nexport function read(path: string) {\n return fs.readFileSync(path, { encoding: 'utf8' });\n}\n\nexport function readdir(path: string) {\n return fs.readdirSync(path);\n}\n\n// you should require when possible(optimized in js)\nexport function readJsonSlow(path: string) {\n return fs.readJSONSync(path);\n}\n\nexport function write(p: string, content: string) {\n const dir = path.dirname(p);\n if (!exist(dir)) {\n fs.mkdirSync(dir, { recursive: true });\n }\n\n return fs.writeFileSync(p, content);\n}\nexport function copy(src: string, dest: string, options?: fs.CopyOptionsSync) {\n fs.copySync(src, dest, options);\n}\n\nexport function writeJson(path: string, json: any) {\n return write(path, JSON.stringify(json, null, 2));\n}\n\nexport function remove(path: string) {\n if (!exist(path)) {\n return;\n }\n\n if (fs.lstatSync(path).isDirectory()) {\n return fs.rmSync(path, { force: true, recursive: true });\n } else {\n return fs.rmSync(path, { force: true });\n }\n}\n\nexport async function iterateDir(path: string, fn: (file: string) => Promise<void> | void) {\n if (!isDir(path)) {\n return;\n }\n\n for (const file of fs.readdirSync(path)) {\n await fn(file);\n }\n}\n","import pkgJson from '../../package.json';\nimport { resolve } from './FileUtil';\nimport { fileURLToPath } from 'url';\n\n/**\n * CLI Comprehensive options\n * Each values can be empty by command and timing.\n */\nexport const OptionHolder: {\n // cli specific options\n cli: {\n // cli version\n version: string;\n // cli project root directory\n rootDir: string;\n // cli template source directory\n templateDir: string;\n };\n input: {\n platform: 'android' | 'ios';\n uploadMetadata: boolean;\n androidOutput: 'apk' | 'aab';\n pod: boolean;\n };\n keyholderMap: {\n ios_app_identifier: string;\n ios_app_store_connect_team_id: string;\n ios_developer_team_id: string;\n ios_match_git_url: string;\n ios_app_store_connect_api_key_id: string;\n ios_app_store_connect_api_key_issuer_id: string;\n ios_xcode_project_target: string;\n ios_match_password: string;\n\n android_keystore_store_password: string;\n android_keystore_key_alias: string;\n android_keystore_key_password: string;\n android_package_name: string;\n };\n iosBundleIdentifier: string;\n androidPackageName: string;\n templateDirNames: string[];\n // dest project root directory\n projectDir: string;\n // dest project output of init command direcotry\n outputOfInitDir: string;\n keyDir: string;\n keyholderFilePath: string;\n versionName: string;\n versionCode: string;\n} = {\n cli: {\n version: pkgJson.version,\n rootDir: resolve(fileURLToPath(import.meta.url), '../..'),\n templateDir: resolve(fileURLToPath(import.meta.url), '../../template'),\n },\n input: {} as any,\n keyholderMap: {} as any,\n templateDirNames: ['key'],\n iosBundleIdentifier: '',\n androidPackageName: '',\n projectDir: '',\n outputOfInitDir: '',\n keyDir: '',\n keyholderFilePath: '',\n versionName: '',\n versionCode: '',\n};\n","import chalk from 'chalk';\n\nexport const logger = {\n success: (...msg: any[]) => console.log(chalk.green(`✔ ${msg.join(', ')}`)),\n error: (...msg: any[]) => console.log(chalk.red(`✖ ${msg.join(', ')}`)),\n warn: (...msg: any[]) => console.log(chalk.yellow(`⚠ ${msg.join(', ')}`)),\n info: (...msg: any[]) => console.log(chalk.cyan(`ℹ ${msg.join(', ')}`)),\n title: (...msg: any[]) => console.log(chalk.bold.blue(`\\n${msg.join(', ')}`)),\n dim: (...msg: any[]) => console.log(chalk.dim(msg.join(', '))),\n};\n","import { logger } from './logger';\n\nexport function throwError(message: string, e?: any): never {\n if (e) {\n logger.error(message, e);\n } else {\n logger.error(message);\n }\n process.exit(1);\n}\n","import { OptionHolder } from './OptionHolder';\nimport { throwError } from './throwError';\nimport semver from 'semver';\nimport { readdir, read, readJsonSlow, write, writeJson, resolve } from './FileUtil';\n\nexport async function parseBinaryVersions() {\n const files = readdir(OptionHolder.projectDir);\n\n const jsConfigFiles = ['app.config.ts', 'app.config.js', 'app.config.cjs', 'app.config.mjs'];\n const jsonConfigFile = 'app.json';\n\n for (const jsConfigFile of jsConfigFiles) {\n if (files.includes(jsConfigFile)) {\n await parseFromJsConfigFile(jsConfigFile);\n return;\n }\n }\n\n if (files.includes(jsonConfigFile)) {\n await parseFromJsonConfigFile(jsonConfigFile);\n return;\n }\n\n throwError('expo config file not found');\n\n async function parseFromJsConfigFile(filename: string) {\n const filePath = resolve(OptionHolder.projectDir, filename);\n const content = read(filePath);\n\n const VERSION_NAME = /const VERSION_NAME = '(.*?)';/.exec(content)?.[1];\n const VERSION_CODE = /const VERSION_CODE = (.*?);/.exec(content)?.[1];\n\n if (!VERSION_NAME) {\n throwError('cannot parse version name');\n }\n if (!VERSION_CODE) {\n throwError('cannot parse version code');\n }\n\n if (!semver.valid(VERSION_NAME)) {\n throwError('VERSION_NAME is not a valid semver format');\n }\n\n OptionHolder.versionName = VERSION_NAME;\n OptionHolder.versionCode = VERSION_CODE;\n }\n\n async function parseFromJsonConfigFile(filename: string) {\n const filePath = resolve(OptionHolder.projectDir, filename);\n const json = readJsonSlow(filePath);\n\n const versionName = json.expo?.version + '';\n const iosVersionCode = json.expo?.ios?.buildNumber + '';\n const androidVersionCode = json.expo?.android?.versionCode + '';\n\n if (!/\\d+/.test(iosVersionCode)) {\n throwError('app.json expo.ios.buildNumber is not an integer');\n }\n\n if (!/\\d+/.test(androidVersionCode)) {\n throwError('app.json expo.android.versionCode is not an integer');\n }\n\n if (iosVersionCode !== androidVersionCode) {\n throwError('app.json expo.ios.buildNumber is not equal with expo.android.versionCode');\n }\n\n if (!semver.valid(versionName)) {\n throwError('VERSION_NAME is not a valid semver format');\n }\n\n OptionHolder.versionName = versionName;\n OptionHolder.versionCode = iosVersionCode;\n }\n}\n\nexport async function injectBinaryVersions({\n versionCode,\n versionName,\n}: {\n versionName: string;\n versionCode: string;\n}) {\n const files = readdir(OptionHolder.projectDir);\n\n const jsConfigFiles = ['app.config.ts', 'app.config.js', 'app.config.cjs', 'app.config.mjs'];\n const jsonConfigFile = 'app.json';\n\n for (const jsConfigFile of jsConfigFiles) {\n if (files.includes(jsConfigFile)) {\n await injectToJsConfigFile(jsConfigFile);\n return;\n }\n }\n\n if (files.includes(jsonConfigFile)) {\n await injectToJsonConfigFile(jsonConfigFile);\n return;\n }\n\n throwError('expo config file not found');\n\n async function injectToJsConfigFile(filename: string) {\n const filePath = resolve(OptionHolder.projectDir, filename);\n let content = read(filePath);\n\n content = content.replace(\n /const VERSION_NAME = '(.*?)';/,\n `const VERSION_NAME = '${versionName}';`,\n );\n content = content.replace(\n /const VERSION_CODE = (.*?);/,\n `const VERSION_CODE = ${versionCode};`,\n );\n\n write(filePath, content);\n }\n\n async function injectToJsonConfigFile(filename: string) {\n const filePath = resolve(OptionHolder.projectDir, filename);\n const json = readJsonSlow(filePath);\n\n json.expo.version = versionName;\n json.expo.ios.buildNumber = versionCode;\n json.expo.android.versionCode = +versionCode;\n\n writeJson(filePath, json);\n }\n}\n","import { injectBinaryVersions } from '../util/VersionUtil';\nimport { throwError } from '../util/throwError';\nimport { logger } from '../util/logger';\nimport { OptionHolder } from '../util/OptionHolder';\nimport semver from 'semver';\nimport { isDev } from '../util/EnvUtil';\nimport { $ } from 'zx';\nimport { setup } from '../util/setup/setup';\n\nexport async function bump({ options }: { options: any }) {\n Object.assign(OptionHolder.input, options);\n await preCheck();\n await setup();\n\n logger.info(`current version: ${OptionHolder.versionName}(${OptionHolder.versionCode})`);\n const nextVersionName = semver.inc(OptionHolder.versionName, 'patch')!;\n const nextVersionCode = Number(OptionHolder.versionCode) + 1 + '';\n logger.info(`next version: ${nextVersionName}(${nextVersionCode})`);\n\n await injectBinaryVersions({ versionName: nextVersionName, versionCode: nextVersionCode });\n logger.success('Binary versions have been bumped in expo config file');\n}\n\nasync function preCheck() {\n if (isDev) return;\n try {\n let hasChange = false;\n try {\n await $`git diff --quiet HEAD`;\n } catch (_) {\n hasChange = true;\n }\n if (hasChange) {\n throwError('Workspace is not clean. Before bump version, you should commit all changes.');\n }\n } catch (e) {\n throwError('Precheck Failed', e);\n }\n}\n","export const isDev = process.env.NODE_ENV === 'development';\nexport const isWin = process.platform.startsWith('win');\n","import { OptionHolder } from '../OptionHolder';\nimport { isDev } from '../EnvUtil';\nimport { resolve } from '../FileUtil';\n\nexport async function promptCommonInputs() {\n OptionHolder.projectDir = isDev ? resolve('example') : resolve('.');\n\n OptionHolder.outputOfInitDir = resolve(OptionHolder.projectDir, 'expo-release-it');\n OptionHolder.keyDir = resolve(OptionHolder.outputOfInitDir, 'key');\n OptionHolder.keyholderFilePath = resolve(OptionHolder.outputOfInitDir, 'keyholder.json');\n}\n","import { OptionHolder } from './OptionHolder';\nimport { readJsonSlow } from './FileUtil';\n\nexport async function hydrateKeyholderFileValues() {\n Object.assign(OptionHolder.keyholderMap, readJsonSlow(OptionHolder.keyholderFilePath));\n}\n","import { promptCommonInputs } from './promptCommonInputs';\nimport { hydrateKeyholderFileValues } from '../hydrateKeyholderFileValues';\nimport { parseBinaryVersions } from '../VersionUtil';\n\nexport async function setup() {\n await promptCommonInputs();\n await hydrateKeyholderFileValues();\n await parseBinaryVersions();\n}\n"],"mappings":"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","names":["resolve","path","path","path","resolve","resolve","semver","resolve","semver"]}