expo-release-it 0.0.11 → 0.0.13

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 (70) hide show
  1. package/bin/expo-release-it.mjs +3 -1
  2. package/build/command/build.d.ts +10 -0
  3. package/build/command/build.js +422 -69
  4. package/build/command/build.js.map +1 -0
  5. package/build/command/bump.d.ts +6 -0
  6. package/build/command/bump.js +291 -32
  7. package/build/command/bump.js.map +1 -0
  8. package/build/command/init.d.ts +6 -0
  9. package/build/command/init.js +334 -92
  10. package/build/command/init.js.map +1 -0
  11. package/build/command/submit.d.ts +8 -0
  12. package/build/command/submit.js +376 -56
  13. package/build/command/submit.js.map +1 -0
  14. package/build/command/upload.d.ts +8 -0
  15. package/build/command/upload.js +379 -57
  16. package/build/command/upload.js.map +1 -0
  17. package/build/index.d.ts +3 -0
  18. package/build/index.js +670 -53
  19. package/build/index.js.map +1 -0
  20. package/build/util/EnvUtil.d.ts +4 -0
  21. package/build/util/EnvUtil.js +8 -2
  22. package/build/util/EnvUtil.js.map +1 -0
  23. package/build/util/FileUtil.d.ts +18 -0
  24. package/build/util/FileUtil.js +73 -55
  25. package/build/util/FileUtil.js.map +1 -0
  26. package/build/util/OptionHolder.d.ts +50 -0
  27. package/build/util/OptionHolder.js +83 -28
  28. package/build/util/OptionHolder.js.map +1 -0
  29. package/build/util/VersionUtil.d.ts +7 -0
  30. package/build/util/VersionUtil.js +217 -80
  31. package/build/util/VersionUtil.js.map +1 -0
  32. package/build/util/calculateElapsed.d.ts +3 -0
  33. package/build/util/calculateElapsed.js +11 -6
  34. package/build/util/calculateElapsed.js.map +1 -0
  35. package/build/util/hydrateKeyholderFileValues.d.ts +3 -0
  36. package/build/util/hydrateKeyholderFileValues.js +91 -4
  37. package/build/util/hydrateKeyholderFileValues.js.map +1 -0
  38. package/build/util/iterateAllFilesInGeneratedTemplate.d.ts +3 -0
  39. package/build/util/iterateAllFilesInGeneratedTemplate.js +112 -16
  40. package/build/util/iterateAllFilesInGeneratedTemplate.js.map +1 -0
  41. package/build/util/logger.d.ts +10 -0
  42. package/build/util/logger.js +15 -0
  43. package/build/util/logger.js.map +1 -0
  44. package/build/util/setup/prepareAndroid.d.ts +3 -0
  45. package/build/util/setup/prepareAndroid.js +170 -26
  46. package/build/util/setup/prepareAndroid.js.map +1 -0
  47. package/build/util/setup/prepareIos.d.ts +3 -0
  48. package/build/util/setup/prepareIos.js +143 -16
  49. package/build/util/setup/prepareIos.js.map +1 -0
  50. package/build/util/setup/promptCommonInputs.d.ts +3 -0
  51. package/build/util/setup/promptCommonInputs.js +113 -21
  52. package/build/util/setup/promptCommonInputs.js.map +1 -0
  53. package/build/util/setup/setup.d.ts +3 -0
  54. package/build/util/setup/setup.js +213 -7
  55. package/build/util/setup/setup.js.map +1 -0
  56. package/build/util/throwError.d.ts +3 -0
  57. package/build/util/throwError.js +24 -9
  58. package/build/util/throwError.js.map +1 -0
  59. package/package.json +5 -3
  60. package/build/command/release.js +0 -86
  61. package/build/util/EnvironmentPreparationUtil.js +0 -41
  62. package/build/util/Log.js +0 -9
  63. package/build/util/Logger.js +0 -9
  64. package/build/util/logutil.js +0 -9
  65. package/build/util/parseBinaryVersion.js +0 -59
  66. package/build/util/pathfinder.js +0 -5
  67. package/build/util/prepareAndroid.js +0 -34
  68. package/build/util/prepareIos.js +0 -17
  69. package/build/util/promptCommonInputs.js +0 -27
  70. package/build/util/setup.js +0 -8
@@ -1,8 +1,214 @@
1
- import { promptCommonInputs } from './promptCommonInputs';
2
- import { hydrateKeyholderFileValues } from '../hydrateKeyholderFileValues';
3
- import { parseBinaryVersions } from '../VersionUtil';
4
- export async function setup() {
5
- await promptCommonInputs();
6
- await hydrateKeyholderFileValues();
7
- await parseBinaryVersions();
1
+ // package.json
2
+ var package_default = {
3
+ name: "expo-release-it",
4
+ module: "src/index.ts",
5
+ type: "module",
6
+ version: "0.0.12",
7
+ license: "MIT",
8
+ scripts: {
9
+ build: "tsup",
10
+ dev: "bun run build && NODE_ENV=development node bin/expo-release-it.mjs",
11
+ release: "yarn build && release-it",
12
+ android: "expo run:android",
13
+ ios: "expo run:ios",
14
+ t: "tsc --noEmit -p ."
15
+ },
16
+ dependencies: {
17
+ "@inquirer/prompts": "^7.4.1",
18
+ "@mj-studio/js-util": "^1.1.20",
19
+ chalk: "^5.4.1",
20
+ commander: "^13.1.0",
21
+ "fs-extra": "^11.3.0",
22
+ react: "18.3.1",
23
+ "react-native": "0.76.9",
24
+ semver: "^7.7.1",
25
+ url: "^0.11.4",
26
+ zx: "^8.5.3"
27
+ },
28
+ devDependencies: {
29
+ "@types/bun": "latest",
30
+ "@types/fs-extra": "^11.0.4",
31
+ "@types/semver": "^7.7.0",
32
+ prettier: "3.5.3",
33
+ "release-it": "^19.0.1",
34
+ "tiny-glob": "^0.2.9",
35
+ tsup: "^8.4.0",
36
+ typescript: "^5.8.3"
37
+ },
38
+ workspaces: [
39
+ "example"
40
+ ],
41
+ bin: "./bin/expo-release-it.mjs",
42
+ files: [
43
+ "build",
44
+ "package.json",
45
+ "bin",
46
+ "template"
47
+ ],
48
+ packageManager: "yarn@4.9.1"
49
+ };
50
+
51
+ // src/util/FileUtil.ts
52
+ import fs from "fs-extra";
53
+ import * as path from "path";
54
+ var resolve2 = path.resolve;
55
+ function exist(path2) {
56
+ return fs.existsSync(path2);
8
57
  }
58
+ function read(path2) {
59
+ return fs.readFileSync(path2, { encoding: "utf8" });
60
+ }
61
+ function readdir(path2) {
62
+ return fs.readdirSync(path2);
63
+ }
64
+ function readJsonSlow(path2) {
65
+ return fs.readJSONSync(path2);
66
+ }
67
+
68
+ // src/util/OptionHolder.ts
69
+ import { fileURLToPath } from "url";
70
+ var OptionHolder = {
71
+ cli: {
72
+ version: package_default.version,
73
+ rootDir: resolve2(fileURLToPath(import.meta.url), "../.."),
74
+ templateDir: resolve2(fileURLToPath(import.meta.url), "../../template")
75
+ },
76
+ init: {},
77
+ bump: {},
78
+ build: {},
79
+ upload: {},
80
+ submit: {},
81
+ templateValuePlaceholderMap: {},
82
+ keyholderFileValueMap: {},
83
+ templateDirNames: ["fastlane-android", "fastlane-ios", "key"],
84
+ iosBundleIdentifier: "",
85
+ androidPackageName: "",
86
+ projectDir: "",
87
+ outputOfInitDir: "",
88
+ keyDir: "",
89
+ keyholderFilePath: "",
90
+ versionName: "",
91
+ versionCode: ""
92
+ };
93
+
94
+ // src/util/setup/promptCommonInputs.ts
95
+ import { input } from "@inquirer/prompts";
96
+
97
+ // src/util/EnvUtil.ts
98
+ var isDev = process.env.NODE_ENV === "development";
99
+ var isWin = process.platform.startsWith("win");
100
+
101
+ // src/util/setup/promptCommonInputs.ts
102
+ async function promptCommonInputs() {
103
+ OptionHolder.projectDir = isDev ? resolve2("example") : resolve2(
104
+ await input({
105
+ message: "react native project root directory path",
106
+ default: isDev ? "example" : ".",
107
+ validate: (value) => {
108
+ const p = resolve2(value, "package.json");
109
+ if (!exist(p)) {
110
+ return "package.json hasn't been detected. provider valid project root.";
111
+ }
112
+ return true;
113
+ }
114
+ })
115
+ );
116
+ OptionHolder.outputOfInitDir = resolve2(OptionHolder.projectDir, "expo-local-build");
117
+ OptionHolder.keyDir = resolve2(OptionHolder.outputOfInitDir, "key");
118
+ OptionHolder.keyholderFilePath = resolve2(OptionHolder.outputOfInitDir, "keyholder.json");
119
+ }
120
+
121
+ // src/util/hydrateKeyholderFileValues.ts
122
+ async function hydrateKeyholderFileValues() {
123
+ Object.assign(OptionHolder.keyholderFileValueMap, readJsonSlow(OptionHolder.keyholderFilePath));
124
+ }
125
+
126
+ // src/util/logger.ts
127
+ import chalk from "chalk";
128
+ var logger = {
129
+ success: (...msg) => console.log(chalk.green(`\u2714 ${msg.join(", ")}`)),
130
+ error: (...msg) => console.log(chalk.red(`\u2716 ${msg.join(", ")}`)),
131
+ warn: (...msg) => console.log(chalk.yellow(`\u26A0 ${msg.join(", ")}`)),
132
+ info: (...msg) => console.log(chalk.cyan(`\u2139 ${msg.join(", ")}`)),
133
+ title: (...msg) => console.log(chalk.bold.blue(`
134
+ ${msg.join(", ")}`)),
135
+ dim: (...msg) => console.log(chalk.dim(msg.join(", ")))
136
+ };
137
+
138
+ // src/util/throwError.ts
139
+ function throwError(message, e) {
140
+ if (e) {
141
+ logger.error(message, e);
142
+ } else {
143
+ logger.error(message);
144
+ }
145
+ process.exit(1);
146
+ }
147
+
148
+ // src/util/VersionUtil.ts
149
+ import semver from "semver";
150
+ async function parseBinaryVersions() {
151
+ const files = readdir(OptionHolder.projectDir);
152
+ const jsConfigFiles = ["app.config.ts", "app.config.js", "app.config.cjs", "app.config.mjs"];
153
+ const jsonConfigFile = "app.json";
154
+ for (const jsConfigFile of jsConfigFiles) {
155
+ if (files.includes(jsConfigFile)) {
156
+ await parseFromJsConfigFile(jsConfigFile);
157
+ return;
158
+ }
159
+ }
160
+ if (files.includes(jsonConfigFile)) {
161
+ await parseFromJsonConfigFile(jsonConfigFile);
162
+ return;
163
+ }
164
+ throwError("expo config file not found");
165
+ async function parseFromJsConfigFile(filename) {
166
+ const filePath = resolve2(OptionHolder.projectDir, filename);
167
+ const content = read(filePath);
168
+ const VERSION_NAME = /const VERSION_NAME = '(.*?)';/.exec(content)?.[1];
169
+ const VERSION_CODE = /const VERSION_CODE = (.*?);/.exec(content)?.[1];
170
+ if (!VERSION_NAME) {
171
+ throwError("cannot parse version name");
172
+ }
173
+ if (!VERSION_CODE) {
174
+ throwError("cannot parse version code");
175
+ }
176
+ if (!semver.valid(VERSION_NAME)) {
177
+ throwError("VERSION_NAME is not a valid semver format");
178
+ }
179
+ OptionHolder.versionName = VERSION_NAME;
180
+ OptionHolder.versionCode = VERSION_CODE;
181
+ }
182
+ async function parseFromJsonConfigFile(filename) {
183
+ const filePath = resolve2(OptionHolder.projectDir, filename);
184
+ const json = readJsonSlow(filePath);
185
+ const versionName = json.expo?.version + "";
186
+ const iosVersionCode = json.expo?.ios?.buildNumber + "";
187
+ const androidVersionCode = json.expo?.android?.versionCode + "";
188
+ if (!/\d+/.test(iosVersionCode)) {
189
+ throwError("app.json expo.ios.buildNumber is not an integer");
190
+ }
191
+ if (!/\d+/.test(androidVersionCode)) {
192
+ throwError("app.json expo.android.versionCode is not an integer");
193
+ }
194
+ if (iosVersionCode !== androidVersionCode) {
195
+ throwError("app.json expo.ios.buildNumber is not equal with expo.android.versionCode");
196
+ }
197
+ if (!semver.valid(versionName)) {
198
+ throwError("VERSION_NAME is not a valid semver format");
199
+ }
200
+ OptionHolder.versionName = versionName;
201
+ OptionHolder.versionCode = iosVersionCode;
202
+ }
203
+ }
204
+
205
+ // src/util/setup/setup.ts
206
+ async function setup() {
207
+ await promptCommonInputs();
208
+ await hydrateKeyholderFileValues();
209
+ await parseBinaryVersions();
210
+ }
211
+ export {
212
+ setup
213
+ };
214
+ //# sourceMappingURL=setup.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../package.json","../../../src/util/FileUtil.ts","../../../src/util/OptionHolder.ts","../../../src/util/setup/promptCommonInputs.ts","../../../src/util/EnvUtil.ts","../../../src/util/hydrateKeyholderFileValues.ts","../../../src/util/logger.ts","../../../src/util/throwError.ts","../../../src/util/VersionUtil.ts","../../../src/util/setup/setup.ts"],"sourcesContent":["{\n \"name\": \"expo-release-it\",\n \"module\": \"src/index.ts\",\n \"type\": \"module\",\n \"version\": \"0.0.12\",\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\n templateValuePlaceholderMap: {\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 android_package_name: string;\n key_dir_relative_path: string;\n };\n keyholderFileValueMap: {\n android_keystore_store_password: string;\n android_keystore_key_alias: string;\n android_keystore_key_password: string;\n ios_match_password: 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 templateValuePlaceholderMap: {} as any,\n keyholderFileValueMap: {} as any,\n templateDirNames: ['fastlane-android', 'fastlane-ios', 'key'],\n iosBundleIdentifier: '',\n androidPackageName: '',\n projectDir: '',\n outputOfInitDir: '',\n keyDir: '',\n keyholderFilePath: '',\n versionName: '',\n versionCode: '',\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.keyholderFileValueMap, readJsonSlow(OptionHolder.keyholderFilePath));\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 { 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","resolve","resolve","resolve"]}
@@ -0,0 +1,3 @@
1
+ declare function throwError(message: string, e?: any): never;
2
+
3
+ export { throwError };
@@ -1,10 +1,25 @@
1
- import { logger } from './logger';
2
- export function throwError(message, e) {
3
- if (e) {
4
- logger.error(message, e);
5
- }
6
- else {
7
- logger.error(message);
8
- }
9
- process.exit(1);
1
+ // src/util/logger.ts
2
+ import chalk from "chalk";
3
+ var logger = {
4
+ success: (...msg) => console.log(chalk.green(`\u2714 ${msg.join(", ")}`)),
5
+ error: (...msg) => console.log(chalk.red(`\u2716 ${msg.join(", ")}`)),
6
+ warn: (...msg) => console.log(chalk.yellow(`\u26A0 ${msg.join(", ")}`)),
7
+ info: (...msg) => console.log(chalk.cyan(`\u2139 ${msg.join(", ")}`)),
8
+ title: (...msg) => console.log(chalk.bold.blue(`
9
+ ${msg.join(", ")}`)),
10
+ dim: (...msg) => console.log(chalk.dim(msg.join(", ")))
11
+ };
12
+
13
+ // src/util/throwError.ts
14
+ function throwError(message, e) {
15
+ if (e) {
16
+ logger.error(message, e);
17
+ } else {
18
+ logger.error(message);
19
+ }
20
+ process.exit(1);
10
21
  }
22
+ export {
23
+ throwError
24
+ };
25
+ //# sourceMappingURL=throwError.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/util/logger.ts","../../src/util/throwError.ts"],"sourcesContent":["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"],"mappings":";AAAA,OAAO,WAAW;AAEX,IAAM,SAAS;AAAA,EACpB,SAAS,IAAI,QAAe,QAAQ,IAAI,MAAM,MAAM,UAAK,IAAI,KAAK,IAAI,CAAC,EAAE,CAAC;AAAA,EAC1E,OAAO,IAAI,QAAe,QAAQ,IAAI,MAAM,IAAI,UAAK,IAAI,KAAK,IAAI,CAAC,EAAE,CAAC;AAAA,EACtE,MAAM,IAAI,QAAe,QAAQ,IAAI,MAAM,OAAO,UAAK,IAAI,KAAK,IAAI,CAAC,EAAE,CAAC;AAAA,EACxE,MAAM,IAAI,QAAe,QAAQ,IAAI,MAAM,KAAK,UAAK,IAAI,KAAK,IAAI,CAAC,EAAE,CAAC;AAAA,EACtE,OAAO,IAAI,QAAe,QAAQ,IAAI,MAAM,KAAK,KAAK;AAAA,EAAK,IAAI,KAAK,IAAI,CAAC,EAAE,CAAC;AAAA,EAC5E,KAAK,IAAI,QAAe,QAAQ,IAAI,MAAM,IAAI,IAAI,KAAK,IAAI,CAAC,CAAC;AAC/D;;;ACPO,SAAS,WAAW,SAAiB,GAAgB;AAC1D,MAAI,GAAG;AACL,WAAO,MAAM,SAAS,CAAC;AAAA,EACzB,OAAO;AACL,WAAO,MAAM,OAAO;AAAA,EACtB;AACA,UAAQ,KAAK,CAAC;AAChB;","names":[]}
package/package.json CHANGED
@@ -2,11 +2,11 @@
2
2
  "name": "expo-release-it",
3
3
  "module": "src/index.ts",
4
4
  "type": "module",
5
- "version": "0.0.11",
5
+ "version": "0.0.13",
6
6
  "license": "MIT",
7
7
  "scripts": {
8
- "build": "tsc",
9
- "dev": "bun run build && NODE_ENV=development bun build/index.js",
8
+ "build": "tsup",
9
+ "dev": "bun run build && NODE_ENV=development node bin/expo-release-it.mjs",
10
10
  "release": "yarn build && release-it",
11
11
  "android": "expo run:android",
12
12
  "ios": "expo run:ios",
@@ -30,6 +30,8 @@
30
30
  "@types/semver": "^7.7.0",
31
31
  "prettier": "3.5.3",
32
32
  "release-it": "^19.0.1",
33
+ "tiny-glob": "^0.2.9",
34
+ "tsup": "^8.4.0",
33
35
  "typescript": "^5.8.3"
34
36
  },
35
37
  "workspaces": [
@@ -1,86 +0,0 @@
1
- import { select } from '@inquirer/prompts';
2
- import { prepareAndroid } from '../util/prepareAndroid';
3
- import { setup } from '../util/setup';
4
- import { prepareIos } from '../util/prepareIos';
5
- import { logger } from '../util/logger';
6
- import { OptionHolder } from '../util/OptionHolder';
7
- import { spinner, $ } from 'zx';
8
- import { resolve, remove } from '../util/FileUtil';
9
- import chalk from 'chalk';
10
- import { calculateElapsed } from '../util/calculateElapsed';
11
- const releaseOptions = {
12
- platform: 'ios',
13
- pod: true,
14
- };
15
- export async function release() {
16
- const startTime = Date.now();
17
- await setup();
18
- await promptInputs();
19
- logger.info('Build & Upload Started');
20
- logger.info(`Version: ${OptionHolder.versionName}(${OptionHolder.versionCode})`);
21
- if (releaseOptions.platform === 'ios') {
22
- await releaseIos();
23
- logger.success(`iOS Release Success ${chalk.bold.inverse(calculateElapsed(startTime))}`);
24
- }
25
- else {
26
- await releaseAndroid();
27
- logger.success(`Android Release Success ${chalk.bold.inverse(calculateElapsed(startTime))}`);
28
- }
29
- }
30
- async function promptInputs() {
31
- releaseOptions.platform = await select({
32
- message: 'Platform to release',
33
- choices: [
34
- { name: 'ios', value: 'ios', description: 'Release ios' },
35
- { name: 'android', value: 'android', description: 'Release android' },
36
- ],
37
- });
38
- if (releaseOptions.platform === 'ios') {
39
- releaseOptions.pod = await select({
40
- message: 'Install Cocoapods',
41
- choices: [
42
- { name: 'yes', value: true, description: 'Install pods before release' },
43
- { name: 'no', value: false, description: 'Skip pods install' },
44
- ],
45
- });
46
- }
47
- }
48
- async function releaseIos() {
49
- const iosDir = resolve(OptionHolder.rootDir, 'ios');
50
- const $$ = $({
51
- verbose: false,
52
- cwd: iosDir,
53
- env: {
54
- MATCH_PASSWORD: OptionHolder.keyholderFileValueMap.ios_match_password,
55
- },
56
- });
57
- await prepareIos();
58
- await fastlane();
59
- async function fastlane() {
60
- await spinner('Bundler Install', () => $$ `bundle install`);
61
- logger.success('Bundler Install');
62
- if (releaseOptions.pod) {
63
- await spinner('Pod Install', () => $$ `bundle exec pod install`);
64
- logger.success('Pod Install');
65
- }
66
- remove(resolve(iosDir, '.xcode.env.local'));
67
- await spinner('Fastlane', () => $$ `bundle exec fastlane release version_name:${OptionHolder.versionName} version_code:${OptionHolder.versionCode}`);
68
- logger.success('Deploy to App Store Connect Test Flight');
69
- }
70
- }
71
- async function releaseAndroid() {
72
- const $$ = $({
73
- verbose: false,
74
- cwd: resolve(OptionHolder.rootDir, 'android'),
75
- });
76
- await prepareAndroid();
77
- await fastlane();
78
- async function fastlane() {
79
- await spinner('Bundler Install', () => $$ `bundle install`);
80
- logger.success('Bundler Install');
81
- await spinner('Bundle AAB', () => $$ `./gradlew app:bundleRelease`);
82
- logger.success('Bundle AAB');
83
- await spinner('Fastlane Supply', () => $$ `bundle exec fastlane deploy version_name:${OptionHolder.versionName} version_code:${OptionHolder.versionCode}`);
84
- logger.success('Deploy to Play Store Internal Testing Track');
85
- }
86
- }
@@ -1,41 +0,0 @@
1
- import { spinner, $ } from 'zx';
2
- import { OptionHolder } from './OptionHolder';
3
- import { iterateDir, remove, resolve, copy, read, write } from './FileUtil';
4
- import { logger } from './logger';
5
- export async function prepareAndroid() {
6
- await spinner('Prebuild Android', () => $ `expo prebuild -p android --no-install`);
7
- const androidDir = resolve(OptionHolder.rootDir, 'android');
8
- const fastlaneSrcDir = resolve(OptionHolder.rootDir, 'fastlane-android');
9
- const fastlaneDestDir = resolve(OptionHolder.rootDir, 'android', 'fastlane');
10
- remove(fastlaneDestDir);
11
- await iterateDir(fastlaneSrcDir, async (file) => {
12
- const filePath = resolve(fastlaneSrcDir, file);
13
- copy(filePath, resolve(androidDir, file));
14
- });
15
- logger.info('Inject Android Fastlane files');
16
- await replaceAndroidSigningConfig();
17
- async function replaceAndroidSigningConfig() {
18
- const buildGradlePath = resolve('android', 'app', 'build.gradle');
19
- const content = read(buildGradlePath).replace(/signingConfigs.*?{.*?debug.*?{.*?}.*?}/s, `
20
- signingConfigs {
21
- debug {
22
- storeFile file('${resolve(OptionHolder.outDir, 'key', 'android_release_keystore.jks')}')
23
- storePassword '{{android_keystore_store_password}}'
24
- keyAlias '{{android_keystore_key_alias}}'
25
- keyPassword '{{android_keystore_key_password}}'
26
- }
27
- }
28
- `);
29
- write(buildGradlePath, content);
30
- logger.info('Replace Android Signing Config');
31
- }
32
- }
33
- // export async function prepareIos() {
34
- // await spinner('Prebuild iOS', () => $`expo prebuild -p ios --no-install`);
35
- // await remove('ios/fastlane');
36
- // await iterateDir('fastlane-ios', async (file) => {
37
- // const filePath = resolve('fastlane-ios', file);
38
- // await $`rm -rf ios/${file} && cp -r ${filePath} ios/${file}`;
39
- // });
40
- // printSuccess('Inject iOS Fastlane files');
41
- // }
package/build/util/Log.js DELETED
@@ -1,9 +0,0 @@
1
- import chalk from 'chalk';
2
- export const log = {
3
- success: (...msg) => console.log(chalk.green(`✔ ${msg.join(', ')}`)),
4
- error: (...msg) => console.log(chalk.red(`✖ ${msg.join(', ')}`)),
5
- warn: (...msg) => console.log(chalk.yellow(`⚠ ${msg.join(', ')}`)),
6
- info: (...msg) => console.log(chalk.cyan(`ℹ ${msg.join(', ')}`)),
7
- title: (...msg) => console.log(chalk.bold.blue(`\n${msg.join(', ')}`)),
8
- dim: (...msg) => console.log(chalk.dim(msg.join(', '))),
9
- };
@@ -1,9 +0,0 @@
1
- import chalk from 'chalk';
2
- export const logger = {
3
- success: (...msg) => console.log(chalk.green(`✔ ${msg.join(', ')}`)),
4
- error: (...msg) => console.log(chalk.red(`✖ ${msg.join(', ')}`)),
5
- warn: (...msg) => console.log(chalk.yellow(`⚠ ${msg.join(', ')}`)),
6
- info: (...msg) => console.log(chalk.cyan(`ℹ ${msg.join(', ')}`)),
7
- title: (...msg) => console.log(chalk.bold.blue(`\n${msg.join(', ')}`)),
8
- dim: (...msg) => console.log(chalk.dim(msg.join(', '))),
9
- };
@@ -1,9 +0,0 @@
1
- import chalk from 'chalk';
2
- export const log = {
3
- success: (msg) => console.log(chalk.green(`✔ ${msg}`)),
4
- error: (msg) => console.log(chalk.red(`✖ ${msg}`)),
5
- warn: (msg) => console.log(chalk.yellow(`⚠ ${msg}`)),
6
- info: (msg) => console.log(chalk.cyan(`ℹ ${msg}`)),
7
- title: (msg) => console.log(chalk.bold.blue(`\n${msg}`)),
8
- dim: (msg) => console.log(chalk.dim(msg)),
9
- };
@@ -1,59 +0,0 @@
1
- import fs from 'fs-extra';
2
- import { OptionHolder } from './OptionHolder';
3
- import * as path from 'path';
4
- import { throwError } from './throwError';
5
- import semver from 'semver';
6
- export async function parseBinaryVersion() {
7
- const files = await fs.readdir(OptionHolder.rootDir);
8
- const jsConfigFiles = ['app.config.ts', 'app.config.js', 'app.config.cjs', 'app.config.mjs'];
9
- const jsonConfigFile = 'app.json';
10
- for (const jsConfigFile of jsConfigFiles) {
11
- if (files.includes(jsConfigFile)) {
12
- await parseFromJsConfigFile(jsConfigFile);
13
- return;
14
- }
15
- }
16
- if (files.includes(jsonConfigFile)) {
17
- await parseFromJsonConfigFile(jsonConfigFile);
18
- return;
19
- }
20
- throwError('expo config file not found');
21
- async function parseFromJsConfigFile(filename) {
22
- const filePath = path.resolve(OptionHolder.rootDir, filename);
23
- const content = await fs.readFile(filePath, { encoding: 'utf-8' });
24
- const VERSION_NAME = /const VERSION_NAME = '(.*?)';?/.exec(content)?.[1];
25
- const VERSION_CODE = /const VERSION_CODE = (.*?);?/.exec(content)?.[1];
26
- if (!VERSION_NAME) {
27
- throwError('cannot parse version name');
28
- }
29
- if (!VERSION_CODE) {
30
- throwError('cannot parse version code');
31
- }
32
- if (!semver.valid(VERSION_NAME)) {
33
- throwError('VERSION_NAME is not a valid semver format');
34
- }
35
- OptionHolder.versionName = VERSION_NAME;
36
- OptionHolder.versionCode = VERSION_CODE;
37
- }
38
- async function parseFromJsonConfigFile(filename) {
39
- const filePath = path.resolve(OptionHolder.rootDir, filename);
40
- const json = JSON.parse(await fs.readFile(filePath, { encoding: 'utf-8' }));
41
- const versionName = json.expo?.version + '';
42
- const iosVersionCode = json.expo?.ios?.buildNumber + '';
43
- const androidVersionCode = json.expo?.android?.versionCode + '';
44
- if (!/\d+/.test(iosVersionCode)) {
45
- throwError('app.json expo.ios.buildNumber is not an integer');
46
- }
47
- if (!/\d+/.test(androidVersionCode)) {
48
- throwError('app.json expo.android.versionCode is not an integer');
49
- }
50
- if (iosVersionCode !== androidVersionCode) {
51
- throwError('app.json expo.ios.buildNumber is not equal with expo.android.versionCode');
52
- }
53
- if (!semver.valid(versionName)) {
54
- throwError('VERSION_NAME is not a valid semver format');
55
- }
56
- OptionHolder.versionName = versionName;
57
- OptionHolder.versionCode = iosVersionCode;
58
- }
59
- }
@@ -1,5 +0,0 @@
1
- export const PathFinder = {
2
- rootDir: () => {
3
- return process.cwd();
4
- }
5
- };
@@ -1,34 +0,0 @@
1
- import { spinner, $, path } from 'zx';
2
- import { resolve, remove, iterateDir, copy, read, write } from './FileUtil';
3
- import { OptionHolder } from './OptionHolder';
4
- import { logger } from './logger';
5
- export async function prepareAndroid() {
6
- const androidDir = resolve(OptionHolder.rootDir, 'android');
7
- const fastlaneSrcDir = resolve(OptionHolder.outDir, 'fastlane-android');
8
- const fastlaneDestDir = resolve(OptionHolder.rootDir, 'android', 'fastlane');
9
- await spinner('Prebuild Android', () => $ `cd ${OptionHolder.rootDir} && expo prebuild -p android --no-install`);
10
- remove(fastlaneDestDir);
11
- await iterateDir(fastlaneSrcDir, async (file) => {
12
- const filePath = resolve(fastlaneSrcDir, file);
13
- remove(resolve(androidDir, file));
14
- copy(filePath, resolve(androidDir, file));
15
- });
16
- logger.success('Inject Android Fastlane files');
17
- await replaceAndroidSigningConfig();
18
- async function replaceAndroidSigningConfig() {
19
- const buildGradlePath = resolve(androidDir, 'app', 'build.gradle');
20
- const { android_keystore_store_password, android_keystore_key_alias, android_keystore_key_password, } = OptionHolder.keyholderFileValueMap;
21
- const content = read(buildGradlePath).replace(/signingConfigs.*?{.*?debug.*?{.*?}.*?}/s, `
22
- signingConfigs {
23
- debug {
24
- storeFile file('${path.relative(buildGradlePath, resolve(OptionHolder.outDir, 'key', 'android_release_keystore.jks'))}')
25
- storePassword '${android_keystore_store_password}'
26
- keyAlias '${android_keystore_key_alias}'
27
- keyPassword '${android_keystore_key_password}'
28
- }
29
- }
30
- `);
31
- write(buildGradlePath, content);
32
- logger.success('Replace Android Signing Config');
33
- }
34
- }
@@ -1,17 +0,0 @@
1
- import { $, spinner } from 'zx';
2
- import { remove, resolve, iterateDir, copy } from './FileUtil';
3
- import { OptionHolder } from './OptionHolder';
4
- import { logger } from './logger';
5
- export async function prepareIos() {
6
- const iosDir = resolve(OptionHolder.rootDir, 'ios');
7
- const fastlaneSrcDir = resolve(OptionHolder.outDir, 'fastlane-ios');
8
- const fastlaneDestDir = resolve(OptionHolder.rootDir, 'ios', 'fastlane');
9
- await spinner('Prebuild iOS', () => $ `cd ${OptionHolder.rootDir} && expo prebuild -p ios --no-install`);
10
- remove(fastlaneDestDir);
11
- await iterateDir(fastlaneSrcDir, async (file) => {
12
- const filePath = resolve(fastlaneSrcDir, file);
13
- remove(resolve(iosDir, file));
14
- copy(filePath, resolve(iosDir, file));
15
- });
16
- logger.success('Inject iOS Fastlane files');
17
- }
@@ -1,27 +0,0 @@
1
- import { OptionHolder } from './OptionHolder';
2
- import { input } from '@inquirer/prompts';
3
- import { isDev } from './EnvUtil';
4
- import { exist, resolve } from './FileUtil';
5
- export async function promptCommonInputs() {
6
- OptionHolder.rootDir = isDev
7
- ? resolve('example')
8
- : resolve(await input({
9
- message: 'react native project root directory path',
10
- default: isDev ? 'example' : '.',
11
- validate: (value) => {
12
- const p = resolve(value, 'package.json');
13
- if (!exist(p)) {
14
- return "package.json hasn\'t been detected. provider valid project root.";
15
- }
16
- return true;
17
- },
18
- }));
19
- OptionHolder.outDir = isDev
20
- ? resolve(OptionHolder.rootDir, 'expo-local-build')
21
- : resolve(OptionHolder.rootDir, await input({
22
- message: 'output path',
23
- default: 'expo-local-build',
24
- }));
25
- OptionHolder.keyDir = resolve(OptionHolder.outDir, 'key');
26
- OptionHolder.keyholderFilePath = resolve(OptionHolder.outDir, 'keyholder.json');
27
- }
@@ -1,8 +0,0 @@
1
- import { promptCommonInputs } from './promptCommonInputs';
2
- import { hydrateKeyholderFileValues } from './hydrateKeyholderFileValues';
3
- import { parseBinaryVersions } from './VersionUtil';
4
- export async function setup() {
5
- await promptCommonInputs();
6
- await hydrateKeyholderFileValues();
7
- await parseBinaryVersions();
8
- }