expo-release-it 0.1.0 → 0.1.2

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 (67) hide show
  1. package/build/command/build.js +156 -94
  2. package/build/command/build.js.map +1 -1
  3. package/build/command/bump.js +33 -27
  4. package/build/command/bump.js.map +1 -1
  5. package/build/command/init.js +161 -47
  6. package/build/command/init.js.map +1 -1
  7. package/build/command/pull.d.ts +5 -0
  8. package/build/command/pull.js +525 -0
  9. package/build/command/pull.js.map +1 -0
  10. package/build/command/submit.js +139 -84
  11. package/build/command/submit.js.map +1 -1
  12. package/build/command/upload.js +154 -104
  13. package/build/command/upload.js.map +1 -1
  14. package/build/index.js +414 -219
  15. package/build/index.js.map +1 -1
  16. package/build/util/FastlaneOption.js +9 -14
  17. package/build/util/FastlaneOption.js.map +1 -1
  18. package/build/util/FileUtil.d.ts +2 -1
  19. package/build/util/FileUtil.js +4 -0
  20. package/build/util/FileUtil.js.map +1 -1
  21. package/build/util/OptionHolder.d.ts +1 -3
  22. package/build/util/OptionHolder.js +7 -8
  23. package/build/util/OptionHolder.js.map +1 -1
  24. package/build/util/generateAppStoreConnectApiKeyFile.d.ts +3 -0
  25. package/build/util/{setup/promptCommonInputs.js → generateAppStoreConnectApiKeyFile.js} +36 -20
  26. package/build/util/generateAppStoreConnectApiKeyFile.js.map +1 -0
  27. package/build/util/injectTemplatePlaceHolders.js +8 -11
  28. package/build/util/injectTemplatePlaceHolders.js.map +1 -1
  29. package/build/util/input/InqueryInputs.d.ts +7 -1
  30. package/build/util/input/InqueryInputs.js +51 -13
  31. package/build/util/input/InqueryInputs.js.map +1 -1
  32. package/build/util/iterateAllFiles.js.map +1 -1
  33. package/build/util/logger.d.ts +1 -0
  34. package/build/util/logger.js +1 -0
  35. package/build/util/logger.js.map +1 -1
  36. package/build/util/{VersionUtil.js → setup/VersionUtil.js} +9 -9
  37. package/build/util/setup/VersionUtil.js.map +1 -0
  38. package/build/util/setup/execShellScript.d.ts +19 -0
  39. package/build/util/setup/execShellScript.js +19 -0
  40. package/build/util/setup/execShellScript.js.map +1 -0
  41. package/build/util/{hydrateKeyholderFileValues.js → setup/hydrateKeyholderFileValues.js} +14 -10
  42. package/build/util/setup/hydrateKeyholderFileValues.js.map +1 -0
  43. package/build/util/setup/prepareAndroid.js +64 -37
  44. package/build/util/setup/prepareAndroid.js.map +1 -1
  45. package/build/util/setup/prepareIos.js +63 -35
  46. package/build/util/setup/prepareIos.js.map +1 -1
  47. package/build/util/setup/setup.d.ts +2 -1
  48. package/build/util/setup/setup.js +30 -25
  49. package/build/util/setup/setup.js.map +1 -1
  50. package/build/util/spinner.d.ts +3 -0
  51. package/build/util/spinner.js +14 -0
  52. package/build/util/spinner.js.map +1 -0
  53. package/build/util/throwError.js +1 -0
  54. package/build/util/throwError.js.map +1 -1
  55. package/package.json +5 -5
  56. package/template/android/Gemfile +1 -1
  57. package/template/android/fastlane/Fastfile +2 -2
  58. package/template/ios/Gemfile +2 -1
  59. package/template/ios/fastlane/Appfile +0 -2
  60. package/template/ios/fastlane/Fastfile +20 -3
  61. package/build/util/VersionUtil.js.map +0 -1
  62. package/build/util/hydrateKeyholderFileValues.js.map +0 -1
  63. package/build/util/setup/promptCommonInputs.d.ts +0 -3
  64. package/build/util/setup/promptCommonInputs.js.map +0 -1
  65. package/template/ios/fastlane/Matchfile +0 -5
  66. /package/build/util/{VersionUtil.d.ts → setup/VersionUtil.d.ts} +0 -0
  67. /package/build/util/{hydrateKeyholderFileValues.d.ts → setup/hydrateKeyholderFileValues.d.ts} +0 -0
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../package.json","../../src/util/FileUtil.ts","../../src/util/OptionHolder.ts","../../src/util/input/InqueryInputs.ts","../../src/util/setup/hydrateKeyholderFileValues.ts","../../src/util/logger.ts","../../src/util/throwError.ts","../../src/util/setup/VersionUtil.ts","../../src/util/EnvUtil.ts","../../src/util/setup/setup.ts","../../src/util/setup/execShellScript.ts","../../src/util/iterateAllFiles.ts","../../src/util/injectTemplatePlaceHolders.ts","../../src/util/spinner.ts","../../src/util/setup/prepareIos.ts","../../src/util/setup/prepareAndroid.ts","../../src/util/generateAppStoreConnectApiKeyFile.ts","../../src/command/pull.ts"],"sourcesContent":["{\n \"name\": \"expo-release-it\",\n \"module\": \"src/index.ts\",\n \"type\": \"module\",\n \"version\": \"0.1.1\",\n \"license\": \"MIT\",\n \"scripts\": {\n \"build\": \"tsup\",\n \"dev\": \"yarn 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 \"execa\": \"^9.5.2\",\n \"fs-extra\": \"^11.3.0\",\n \"ora\": \"^8.2.0\",\n \"react\": \"18.3.1\",\n \"react-native\": \"0.76.9\",\n \"semver\": \"^7.7.1\",\n \"url\": \"^0.11.4\"\n },\n \"devDependencies\": {\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}\nexport function move(src: string, dest: string, options?: fs.MoveOptions) {\n fs.moveSync(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_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 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 tempDir: 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 projectDir: '',\n outputOfInitDir: '',\n keyDir: '',\n keyholderFilePath: '',\n versionName: '',\n versionCode: '',\n tempDir: '',\n};\n","import { OptionHolder } from '../OptionHolder';\nimport { select } from '@inquirer/prompts';\nimport { is } from '@mj-studio/js-util';\nimport chalk from 'chalk';\n\nexport const InqueryInputs = {\n platform: async () => {\n if (!OptionHolder.input.platform) {\n OptionHolder.input.platform = await select({\n message: constructInquirerFormattedMessage({\n name: 'Platform',\n explanation: `Platform to run action`,\n }),\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: constructInquirerFormattedMessage({\n name: 'Install CocoaPods?',\n }),\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: constructInquirerFormattedMessage({\n name: 'Android output artifact type',\n }),\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: constructInquirerFormattedMessage({\n name: 'Upload Metadata(screenshot, title, description, ...)',\n }),\n choices: [\n { name: 'yes', value: true, description: 'Upload' },\n { name: 'no', value: false, description: \"Don't Upload\" },\n ],\n });\n }\n },\n};\n\nexport function constructInquirerFormattedMessage({\n example,\n explanation,\n referUrl,\n name,\n}: {\n name: string;\n explanation?: string;\n example?: string;\n referUrl?: string;\n}) {\n let ret = `${chalk.bold(name)}`;\n if (explanation) {\n ret += `\\n\\n${chalk.italic.blue(explanation)}`;\n }\n if (example) {\n ret += `\\n${chalk.italic(`${chalk.greenBright('example :')} ${example}`)}`;\n }\n if (referUrl) {\n ret += `\\n${chalk.italic(`${chalk.greenBright('references :')} ${chalk.underline.blue(referUrl)}`)}`;\n }\n\n if (explanation) {\n ret += '\\n';\n if (example || referUrl) {\n ret += '\\n';\n }\n }\n\n return ret;\n}\n","import { OptionHolder } from '../OptionHolder';\nimport { readJsonSlow, exist } from '../FileUtil';\n\nexport async function hydrateKeyholderFileValues() {\n if (exist(OptionHolder.keyholderFilePath)) {\n Object.assign(OptionHolder.keyholderMap, readJsonSlow(OptionHolder.keyholderFilePath));\n }\n}\n","import chalk from 'chalk';\n\nexport const logger = {\n success: (...msg: any[]) => console.log(chalk.green(`✔ ${msg.join(', ')}`)),\n done: (...msg: any[]) => console.log(chalk.green(`✔ ${msg.join(', ')} - Done`)),\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","export const isDev = process.env.NODE_ENV === 'development';\nexport const isWin = process.platform.startsWith('win');\n","import { hydrateKeyholderFileValues } from './hydrateKeyholderFileValues';\nimport { parseBinaryVersions } from './VersionUtil';\nimport { OptionHolder } from '../OptionHolder';\nimport { isDev } from '../EnvUtil';\nimport { resolve } from '../FileUtil';\n\nexport async function setup() {\n await setupBasicOptions();\n await hydrateKeyholderFileValues();\n await parseBinaryVersions();\n}\n\nexport async function setupBasicOptions() {\n OptionHolder.projectDir = isDev ? resolve('example') : resolve('.');\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 OptionHolder.tempDir = resolve(OptionHolder.outputOfInitDir, '.temp');\n}\n","import { execa, type Options } from 'execa';\n\nexport const exe = execa({\n stdin: 'pipe',\n stdout: 'inherit',\n stderr: 'inherit',\n shell: false,\n});\n\nexport const yesShell = <OptionsType extends Options>(\n command: string,\n args: string[] = [],\n options: OptionsType,\n) => {\n const subProcess = exe(command, args, { ...options, stdin: 'pipe' });\n subProcess.stdin?.write('y\\n');\n subProcess.stdin?.end();\n return subProcess;\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 { read, relativePath, write } from './FileUtil';\nimport { OptionHolder } from './OptionHolder';\nimport * as path from 'node:path';\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 { oraPromise } from 'ora';\nimport chalk from 'chalk';\n\nexport async function spinner<T>(text: string, promise: Promise<T>): Promise<T> {\n return oraPromise(promise, {\n text,\n successText: chalk.green(`${text} - Done`),\n failText: chalk.red(`${text} - Failed`),\n });\n}\n","import { remove, resolve, iterateDir, copy } from '../FileUtil';\nimport { OptionHolder } from '../OptionHolder';\nimport { injectTemplatePlaceHolders } from '../injectTemplatePlaceHolders';\nimport { spinner } from '../spinner';\nimport { exe, yesShell } from './execShellScript';\nimport { logger } from '../logger';\n\nexport async function prepareIos() {\n const srcDir = resolve(OptionHolder.cli.templateDir, 'ios');\n const destDir = resolve(OptionHolder.projectDir, 'ios');\n\n await yesShell('expo', ['prebuild', '-p', 'ios', '--no-install'], {\n cwd: OptionHolder.projectDir,\n });\n logger.success('Expo Prebuild - Done');\n\n await spinner(\n 'Inject templates',\n iterateDir(srcDir, async (file) => {\n const filePath = resolve(srcDir, file);\n remove(resolve(destDir, file));\n copy(filePath, resolve(destDir, file));\n }),\n );\n\n await spinner(\n 'Hydrate template placeholders',\n injectTemplatePlaceHolders(resolve(destDir, 'fastlane')),\n );\n\n await exe({ cwd: destDir })`bundle install`;\n logger.success('Bunder Install - Done');\n}\n","import { resolve, remove, iterateDir, copy, read, write, relativePath } from '../FileUtil';\nimport { OptionHolder } from '../OptionHolder';\nimport { injectTemplatePlaceHolders } from '../injectTemplatePlaceHolders';\nimport { spinner } from '../spinner';\nimport { exe, yesShell } from './execShellScript';\nimport { logger } from '../logger';\n\nexport async function prepareAndroid() {\n const srcDir = resolve(OptionHolder.cli.templateDir, 'android');\n const destDir = resolve(OptionHolder.projectDir, 'android');\n\n await yesShell('expo', ['prebuild', '-p', 'android', '--no-install'], {\n cwd: OptionHolder.projectDir,\n });\n logger.success('Expo Prebuild - Done');\n\n await spinner(\n 'Inject Templates',\n iterateDir(srcDir, async (file) => {\n const filePath = resolve(srcDir, file);\n remove(resolve(destDir, file));\n copy(filePath, resolve(destDir, file));\n }),\n );\n\n await spinner('Overwrite Android Release Signing Config', replaceAndroidSigningConfig(destDir));\n\n await spinner(\n 'Hydrate template placeholders',\n injectTemplatePlaceHolders(resolve(destDir, 'fastlane')),\n );\n\n await exe({ cwd: destDir })`bundle install`;\n logger.success('Bunder Install - Done');\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 { OptionHolder } from './OptionHolder';\nimport { resolve, read, writeJson, join } from './FileUtil';\n\nexport function generateAppStoreConnectApiKeyFile() {\n const json = {\n key: read(resolve(OptionHolder.keyDir, 'ios_testflight_upload_api_key.p8')),\n key_id: OptionHolder.keyholderMap.ios_app_store_connect_api_key_id,\n issuer_id: OptionHolder.keyholderMap.ios_app_store_connect_api_key_issuer_id,\n };\n const file = join(OptionHolder.tempDir, 'app_store_connect_api.json');\n writeJson(file, json);\n return file;\n}\n","import { OptionHolder } from '../util/OptionHolder';\nimport { InqueryInputs } from '../util/input/InqueryInputs';\nimport { setup } from '../util/setup/setup';\nimport { join, move } from '../util/FileUtil';\nimport { exe } from '../util/setup/execShellScript';\nimport { prepareIos } from '../util/setup/prepareIos';\nimport { prepareAndroid } from '../util/setup/prepareAndroid';\nimport { generateAppStoreConnectApiKeyFile } from '../util/generateAppStoreConnectApiKeyFile';\n\nexport async function pull({ options }: { options: any }) {\n Object.assign(OptionHolder.input, options);\n await setup();\n await promptInputs();\n\n if (OptionHolder.input.platform === 'ios') {\n await pullIosMetadata();\n } else {\n await pullAndroidMetadata();\n }\n}\n\nasync function promptInputs() {\n await InqueryInputs.platform();\n}\n\nasync function pullIosMetadata() {\n await prepareIos();\n const iosDir = join(OptionHolder.projectDir, 'ios');\n const exeEnv = exe({\n cwd: iosDir,\n env: {\n MATCH_PASSWORD: OptionHolder.keyholderMap.ios_match_password,\n },\n });\n\n await exeEnv('bundle', [\n 'exec',\n 'fastlane',\n 'deliver',\n 'download_metadata',\n '-f',\n '--api_key_path',\n generateAppStoreConnectApiKeyFile(),\n ]);\n\n await exeEnv('bundle', [\n 'exec',\n 'fastlane',\n 'deliver',\n 'download_screenshots',\n '-f',\n '--api_key_path',\n generateAppStoreConnectApiKeyFile(),\n ]);\n\n const metadataSrcDir = join(iosDir, 'fastlane/metadata');\n const screenshotsSrcDir = join(iosDir, 'fastlane/screenshots');\n\n const metadataDestDir = join(OptionHolder.outputOfInitDir, 'metadata/ios/metadata');\n const screenshotsDestDir = join(OptionHolder.outputOfInitDir, 'metadata/ios/screenshots');\n\n move(metadataSrcDir, metadataDestDir);\n move(screenshotsSrcDir, screenshotsDestDir);\n}\n\nasync function pullAndroidMetadata() {\n await prepareAndroid();\n const androidDir = join(OptionHolder.projectDir, 'android');\n\n await exe('bundle', ['exec', 'fastlane', 'supply', 'init'], { cwd: androidDir });\n}\n"],"mappings":"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","names":["join","resolve","path","resolve","chalk","resolve","resolve","join","path","chalk","resolve","resolve","resolve","join","join"]}
@@ -3,11 +3,11 @@ var package_default = {
3
3
  name: "expo-release-it",
4
4
  module: "src/index.ts",
5
5
  type: "module",
6
- version: "0.0.17",
6
+ version: "0.1.1",
7
7
  license: "MIT",
8
8
  scripts: {
9
9
  build: "tsup",
10
- dev: "bun run build && NODE_ENV=development node bin/expo-release-it.mjs",
10
+ dev: "yarn run build && NODE_ENV=development node bin/expo-release-it.mjs",
11
11
  release: "yarn build && release-it",
12
12
  android: "expo run:android",
13
13
  ios: "expo run:ios",
@@ -18,15 +18,15 @@ var package_default = {
18
18
  "@mj-studio/js-util": "^1.1.20",
19
19
  chalk: "^5.4.1",
20
20
  commander: "^13.1.0",
21
+ execa: "^9.5.2",
21
22
  "fs-extra": "^11.3.0",
23
+ ora: "^8.2.0",
22
24
  react: "18.3.1",
23
25
  "react-native": "0.76.9",
24
26
  semver: "^7.7.1",
25
- url: "^0.11.4",
26
- zx: "^8.5.3"
27
+ url: "^0.11.4"
27
28
  },
28
29
  devDependencies: {
29
- "@types/bun": "latest",
30
30
  "@types/fs-extra": "^11.0.4",
31
31
  "@types/semver": "^7.7.0",
32
32
  prettier: "3.5.3",
@@ -114,37 +114,27 @@ var OptionHolder = {
114
114
  input: {},
115
115
  keyholderMap: {},
116
116
  templateDirNames: ["key"],
117
- iosBundleIdentifier: "",
118
- androidPackageName: "",
119
117
  projectDir: "",
120
118
  outputOfInitDir: "",
121
119
  keyDir: "",
122
120
  keyholderFilePath: "",
123
121
  versionName: "",
124
- versionCode: ""
122
+ versionCode: "",
123
+ tempDir: ""
125
124
  };
126
125
 
127
- // src/util/EnvUtil.ts
128
- var isDev = process.env.NODE_ENV === "development";
129
- var isWin = process.platform.startsWith("win");
130
-
131
- // src/util/setup/promptCommonInputs.ts
132
- async function promptCommonInputs() {
133
- OptionHolder.projectDir = isDev ? resolve2("example") : resolve2(".");
134
- OptionHolder.outputOfInitDir = resolve2(OptionHolder.projectDir, "expo-release-it");
135
- OptionHolder.keyDir = resolve2(OptionHolder.outputOfInitDir, "key");
136
- OptionHolder.keyholderFilePath = resolve2(OptionHolder.outputOfInitDir, "keyholder.json");
137
- }
138
-
139
- // src/util/hydrateKeyholderFileValues.ts
126
+ // src/util/setup/hydrateKeyholderFileValues.ts
140
127
  async function hydrateKeyholderFileValues() {
141
- Object.assign(OptionHolder.keyholderMap, readJsonSlow(OptionHolder.keyholderFilePath));
128
+ if (exist(OptionHolder.keyholderFilePath)) {
129
+ Object.assign(OptionHolder.keyholderMap, readJsonSlow(OptionHolder.keyholderFilePath));
130
+ }
142
131
  }
143
132
 
144
133
  // src/util/logger.ts
145
134
  import chalk from "chalk";
146
135
  var logger = {
147
136
  success: (...msg) => console.log(chalk.green(`\u2714 ${msg.join(", ")}`)),
137
+ done: (...msg) => console.log(chalk.green(`\u2714 ${msg.join(", ")} - Done`)),
148
138
  error: (...msg) => console.log(chalk.red(`\u2716 ${msg.join(", ")}`)),
149
139
  warn: (...msg) => console.log(chalk.yellow(`\u26A0 ${msg.join(", ")}`)),
150
140
  info: (...msg) => console.log(chalk.cyan(`\u2139 ${msg.join(", ")}`)),
@@ -163,7 +153,7 @@ function throwError(message, e) {
163
153
  process.exit(1);
164
154
  }
165
155
 
166
- // src/util/VersionUtil.ts
156
+ // src/util/setup/VersionUtil.ts
167
157
  import semver from "semver";
168
158
  async function parseBinaryVersions() {
169
159
  const files = readdir(OptionHolder.projectDir);
@@ -220,15 +210,26 @@ async function parseBinaryVersions() {
220
210
  }
221
211
  }
222
212
 
213
+ // src/util/EnvUtil.ts
214
+ var isDev = process.env.NODE_ENV === "development";
215
+ var isWin = process.platform.startsWith("win");
216
+
223
217
  // src/util/setup/setup.ts
224
218
  async function setup() {
225
- await promptCommonInputs();
219
+ await setupBasicOptions();
226
220
  await hydrateKeyholderFileValues();
227
221
  await parseBinaryVersions();
228
222
  }
223
+ async function setupBasicOptions() {
224
+ OptionHolder.projectDir = isDev ? resolve2("example") : resolve2(".");
225
+ OptionHolder.outputOfInitDir = resolve2(OptionHolder.projectDir, "expo-release-it");
226
+ OptionHolder.keyDir = resolve2(OptionHolder.outputOfInitDir, "key");
227
+ OptionHolder.keyholderFilePath = resolve2(OptionHolder.outputOfInitDir, "keyholder.json");
228
+ OptionHolder.tempDir = resolve2(OptionHolder.outputOfInitDir, ".temp");
229
+ }
229
230
 
230
231
  // src/command/submit.ts
231
- import chalk2 from "chalk";
232
+ import chalk4 from "chalk";
232
233
 
233
234
  // src/util/calculateElapsed.ts
234
235
  import { padZero } from "@mj-studio/js-util";
@@ -239,12 +240,6 @@ function calculateElapsed(t) {
239
240
  return `${minutes}:${padZero(seconds)}`;
240
241
  }
241
242
 
242
- // src/command/submit.ts
243
- import { spinner as spinner3, $ as $3 } from "zx";
244
-
245
- // src/util/setup/prepareAndroid.ts
246
- import { spinner, $ } from "zx";
247
-
248
243
  // src/util/iterateAllFiles.ts
249
244
  async function iterateAllFiles(root, callback) {
250
245
  await go(root);
@@ -261,7 +256,7 @@ async function iterateAllFiles(root, callback) {
261
256
  }
262
257
 
263
258
  // src/util/injectTemplatePlaceHolders.ts
264
- import { path as path2 } from "zx";
259
+ import * as path2 from "node:path";
265
260
  async function injectTemplatePlaceHolders(root) {
266
261
  await iterateAllFiles(root, async (filePath) => {
267
262
  const dirPath = path2.dirname(filePath);
@@ -277,25 +272,55 @@ async function injectTemplatePlaceHolders(root) {
277
272
  });
278
273
  }
279
274
 
275
+ // src/util/spinner.ts
276
+ import { oraPromise } from "ora";
277
+ import chalk2 from "chalk";
278
+ async function spinner(text, promise) {
279
+ return oraPromise(promise, {
280
+ text,
281
+ successText: chalk2.green(`${text} - Done`),
282
+ failText: chalk2.red(`${text} - Failed`)
283
+ });
284
+ }
285
+
286
+ // src/util/setup/execShellScript.ts
287
+ import { execa } from "execa";
288
+ var exe = execa({
289
+ stdin: "pipe",
290
+ stdout: "inherit",
291
+ stderr: "inherit",
292
+ shell: false
293
+ });
294
+ var yesShell = (command, args = [], options) => {
295
+ const subProcess = exe(command, args, { ...options, stdin: "pipe" });
296
+ subProcess.stdin?.write("y\n");
297
+ subProcess.stdin?.end();
298
+ return subProcess;
299
+ };
300
+
280
301
  // src/util/setup/prepareAndroid.ts
281
302
  async function prepareAndroid() {
282
303
  const srcDir = resolve2(OptionHolder.cli.templateDir, "android");
283
304
  const destDir = resolve2(OptionHolder.projectDir, "android");
305
+ await yesShell("expo", ["prebuild", "-p", "android", "--no-install"], {
306
+ cwd: OptionHolder.projectDir
307
+ });
308
+ logger.success("Expo Prebuild - Done");
284
309
  await spinner(
285
- "Prebuild Android",
286
- () => $`cd ${OptionHolder.projectDir} && expo prebuild -p android --no-install`
310
+ "Inject Templates",
311
+ iterateDir(srcDir, async (file) => {
312
+ const filePath = resolve2(srcDir, file);
313
+ remove(resolve2(destDir, file));
314
+ copy(filePath, resolve2(destDir, file));
315
+ })
287
316
  );
288
- logger.success("expo prebuild");
289
- await iterateDir(srcDir, async (file) => {
290
- const filePath = resolve2(srcDir, file);
291
- remove(resolve2(destDir, file));
292
- copy(filePath, resolve2(destDir, file));
293
- });
294
- logger.success("Inject Android templates");
295
- await replaceAndroidSigningConfig(destDir);
296
- logger.success("Overwrite Android Release Signing Config");
297
- await injectTemplatePlaceHolders(resolve2(destDir, "fastlane"));
298
- logger.success("Hydrate template placeholders");
317
+ await spinner("Overwrite Android Release Signing Config", replaceAndroidSigningConfig(destDir));
318
+ await spinner(
319
+ "Hydrate template placeholders",
320
+ injectTemplatePlaceHolders(resolve2(destDir, "fastlane"))
321
+ );
322
+ await exe({ cwd: destDir })`bundle install`;
323
+ logger.success("Bunder Install - Done");
299
324
  }
300
325
  async function replaceAndroidSigningConfig(destDir) {
301
326
  const buildGradleDirPath = resolve2(destDir, "app");
@@ -322,33 +347,41 @@ async function replaceAndroidSigningConfig(destDir) {
322
347
  }
323
348
 
324
349
  // src/util/setup/prepareIos.ts
325
- import { $ as $2, spinner as spinner2 } from "zx";
326
350
  async function prepareIos() {
327
351
  const srcDir = resolve2(OptionHolder.cli.templateDir, "ios");
328
352
  const destDir = resolve2(OptionHolder.projectDir, "ios");
329
- await spinner2(
330
- "Prebuild iOS",
331
- () => $2`cd ${OptionHolder.projectDir} && expo prebuild -p ios --no-install`
332
- );
333
- logger.success("expo prebuild");
334
- await iterateDir(srcDir, async (file) => {
335
- const filePath = resolve2(srcDir, file);
336
- remove(resolve2(destDir, file));
337
- copy(filePath, resolve2(destDir, file));
353
+ await yesShell("expo", ["prebuild", "-p", "ios", "--no-install"], {
354
+ cwd: OptionHolder.projectDir
338
355
  });
339
- logger.success("Inject iOS templates");
340
- await injectTemplatePlaceHolders(resolve2(destDir, "fastlane"));
341
- logger.success("Hydrate template placeholders");
356
+ logger.success("Expo Prebuild - Done");
357
+ await spinner(
358
+ "Inject templates",
359
+ iterateDir(srcDir, async (file) => {
360
+ const filePath = resolve2(srcDir, file);
361
+ remove(resolve2(destDir, file));
362
+ copy(filePath, resolve2(destDir, file));
363
+ })
364
+ );
365
+ await spinner(
366
+ "Hydrate template placeholders",
367
+ injectTemplatePlaceHolders(resolve2(destDir, "fastlane"))
368
+ );
369
+ await exe({ cwd: destDir })`bundle install`;
370
+ logger.success("Bunder Install - Done");
342
371
  }
343
372
 
344
373
  // src/util/input/InqueryInputs.ts
345
374
  import { select } from "@inquirer/prompts";
346
375
  import { is } from "@mj-studio/js-util";
376
+ import chalk3 from "chalk";
347
377
  var InqueryInputs = {
348
378
  platform: async () => {
349
379
  if (!OptionHolder.input.platform) {
350
380
  OptionHolder.input.platform = await select({
351
- message: "Platform to release",
381
+ message: constructInquirerFormattedMessage({
382
+ name: "Platform",
383
+ explanation: `Platform to run action`
384
+ }),
352
385
  choices: [
353
386
  { name: "ios", value: "ios", description: "Release ios" },
354
387
  { name: "android", value: "android", description: "Release android" }
@@ -359,7 +392,9 @@ var InqueryInputs = {
359
392
  podinstall: async () => {
360
393
  if (OptionHolder.input.platform === "ios") {
361
394
  OptionHolder.input.pod = await select({
362
- message: "Install Cocoapods",
395
+ message: constructInquirerFormattedMessage({
396
+ name: "Install CocoaPods?"
397
+ }),
363
398
  choices: [
364
399
  { name: "yes", value: true, description: "Install pods before release" },
365
400
  { name: "no", value: false, description: "Skip pods install" }
@@ -371,7 +406,9 @@ var InqueryInputs = {
371
406
  if (OptionHolder.input.platform === "android") {
372
407
  if (!OptionHolder.input.androidOutput) {
373
408
  OptionHolder.input.androidOutput = await select({
374
- message: "Android Output",
409
+ message: constructInquirerFormattedMessage({
410
+ name: "Android output artifact type"
411
+ }),
375
412
  choices: [
376
413
  { name: "aab", value: "aab", description: "Build as App bundle" },
377
414
  { name: "apk", value: "apk", description: "Build as APK" }
@@ -383,7 +420,9 @@ var InqueryInputs = {
383
420
  uploadMetadata: async () => {
384
421
  if (!is.boolean(OptionHolder.input.uploadMetadata)) {
385
422
  OptionHolder.input.uploadMetadata = await select({
386
- message: "Upload Metadata(screenshot, title, description, ...)",
423
+ message: constructInquirerFormattedMessage({
424
+ name: "Upload Metadata(screenshot, title, description, ...)"
425
+ }),
387
426
  choices: [
388
427
  { name: "yes", value: true, description: "Upload" },
389
428
  { name: "no", value: false, description: "Don't Upload" }
@@ -392,13 +431,41 @@ var InqueryInputs = {
392
431
  }
393
432
  }
394
433
  };
434
+ function constructInquirerFormattedMessage({
435
+ example,
436
+ explanation,
437
+ referUrl,
438
+ name
439
+ }) {
440
+ let ret = `${chalk3.bold(name)}`;
441
+ if (explanation) {
442
+ ret += `
443
+
444
+ ${chalk3.italic.blue(explanation)}`;
445
+ }
446
+ if (example) {
447
+ ret += `
448
+ ${chalk3.italic(`${chalk3.greenBright("example :")} ${example}`)}`;
449
+ }
450
+ if (referUrl) {
451
+ ret += `
452
+ ${chalk3.italic(`${chalk3.greenBright("references :")} ${chalk3.underline.blue(referUrl)}`)}`;
453
+ }
454
+ if (explanation) {
455
+ ret += "\n";
456
+ if (example || referUrl) {
457
+ ret += "\n";
458
+ }
459
+ }
460
+ return ret;
461
+ }
395
462
 
396
463
  // src/util/FastlaneOption.ts
397
464
  function getAndroidFastlaneOptions() {
398
465
  return [
466
+ ...Object.entries(OptionHolder.keyholderMap).map(([k, v]) => `${k}:${v}`),
399
467
  `version_name:${OptionHolder.versionName}`,
400
468
  `version_code:${OptionHolder.versionCode}`,
401
- `package_name:${OptionHolder.androidPackageName}`,
402
469
  `upload_metadata:${OptionHolder.input.uploadMetadata}`,
403
470
  `aab_path:${resolve2(OptionHolder.outputOfInitDir, "output", "android", "aab", "app-release.aab")}`,
404
471
  `apk_path:${resolve2(OptionHolder.outputOfInitDir, "output", "android", "apk", "app-release.apk")}`,
@@ -408,13 +475,9 @@ function getAndroidFastlaneOptions() {
408
475
  }
409
476
  function getIosFastlaneOptions() {
410
477
  return [
478
+ ...Object.entries(OptionHolder.keyholderMap).map(([k, v]) => `${k}:${v}`),
411
479
  `version_name:${OptionHolder.versionName}`,
412
480
  `version_code:${OptionHolder.versionCode}`,
413
- `ios_app_identifier:${OptionHolder.iosBundleIdentifier}`,
414
- `ios_xcode_project_target:${OptionHolder.keyholderMap.ios_xcode_project_target}`,
415
- `ios_developer_team_id:${OptionHolder.keyholderMap.ios_developer_team_id}`,
416
- `ios_app_store_connect_api_key_id:${OptionHolder.keyholderMap.ios_app_store_connect_api_key_id}`,
417
- `ios_app_store_connect_api_key_issuer_id:${OptionHolder.keyholderMap.ios_app_store_connect_api_key_issuer_id}`,
418
481
  `api_key_filepath:${resolve2(OptionHolder.keyDir, "ios_testflight_upload_api_key.p8")}`,
419
482
  `upload_metadata:${OptionHolder.input.uploadMetadata}`,
420
483
  `ipa_path:${resolve2(OptionHolder.outputOfInitDir, "output", "ios", "app.ipa")}`,
@@ -433,10 +496,10 @@ async function submit({ options }) {
433
496
  logger.info(`Version: ${OptionHolder.versionName}(${OptionHolder.versionCode})`);
434
497
  if (OptionHolder.input.platform === "ios") {
435
498
  await submitIos();
436
- logger.success(`Appstore Review Submitted ${chalk2.bold.inverse(calculateElapsed(startTime))}`);
499
+ logger.success(`Appstore Review Submitted ${chalk4.bold.inverse(calculateElapsed(startTime))}`);
437
500
  } else {
438
501
  await submitAndroid();
439
- logger.success(`Playstore Review Submitted ${chalk2.bold.inverse(calculateElapsed(startTime))}`);
502
+ logger.success(`Playstore Review Submitted ${chalk4.bold.inverse(calculateElapsed(startTime))}`);
440
503
  }
441
504
  }
442
505
  async function promptInputs() {
@@ -444,31 +507,23 @@ async function promptInputs() {
444
507
  await InqueryInputs.uploadMetadata();
445
508
  }
446
509
  async function submitAndroid() {
447
- const $$ = $3({
448
- verbose: false,
449
- cwd: resolve2(OptionHolder.projectDir, "android")
450
- });
451
510
  await prepareAndroid();
452
511
  await fastlane();
453
512
  async function fastlane() {
454
- await spinner3("Bundler Install", () => $$`bundle install`);
455
- logger.success("Bundler Install");
456
- await spinner3("Fastlane", () => $$`bundle exec fastlane sumbit ${getIosFastlaneOptions()}`);
513
+ await exe({
514
+ cwd: resolve2(OptionHolder.projectDir, "android")
515
+ })`bundle exec fastlane sumbit ${getIosFastlaneOptions()}`;
457
516
  }
458
517
  }
459
518
  async function submitIos() {
460
519
  const iosDir = resolve2(OptionHolder.projectDir, "ios");
461
- const $$ = $3({
462
- verbose: false,
463
- cwd: iosDir
464
- });
465
520
  await prepareIos();
466
521
  await fastlane();
467
522
  async function fastlane() {
468
- await spinner3("Bundler Install", () => $$`bundle install`);
469
- logger.success("Bundler Install");
470
523
  remove(resolve2(iosDir, ".xcode.env.local"));
471
- await spinner3("Fastlane", () => $$`bundle exec fastlane submit ${getAndroidFastlaneOptions()}`);
524
+ await exe({
525
+ cwd: iosDir
526
+ })`bundle exec fastlane submit ${getAndroidFastlaneOptions()}`;
472
527
  }
473
528
  }
474
529
  export {