budexp 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.
- package/package.json +2 -2
- package/src/commands/build.js +15 -11
- package/src/commands/check.js +2 -2
- package/src/commands/dev.js +3 -2
- package/src/utils/cleaner.js +9 -21
- package/src/utils/commands.js +31 -0
- package/src/utils/eas.js +6 -6
- package/src/utils/expo-doctor.js +2 -1
package/package.json
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "budexp",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.2",
|
|
4
4
|
"description": "A powerful CLI tool to facilitate mobile development with Expo + React Native stack",
|
|
5
5
|
"main": "./bin/budexp.js",
|
|
6
6
|
"bin": {
|
|
7
|
-
"budexp": "
|
|
7
|
+
"budexp": "bin/budexp.js"
|
|
8
8
|
},
|
|
9
9
|
"files": [
|
|
10
10
|
"bin",
|
package/src/commands/build.js
CHANGED
|
@@ -7,7 +7,7 @@ const logger = require('../utils/logger');
|
|
|
7
7
|
const cleaner = require('../utils/cleaner');
|
|
8
8
|
const expoDoctor = require('../utils/expo-doctor');
|
|
9
9
|
const eas = require('../utils/eas');
|
|
10
|
-
const {
|
|
10
|
+
const { execCommandSync } = require('../utils/commands');
|
|
11
11
|
const fs = require('fs-extra');
|
|
12
12
|
const path = require('path');
|
|
13
13
|
|
|
@@ -102,7 +102,7 @@ async function buildCommand(options) {
|
|
|
102
102
|
|
|
103
103
|
if (loginAnswer.login) {
|
|
104
104
|
try {
|
|
105
|
-
|
|
105
|
+
execCommandSync('eas', ['login'], { stdio: 'inherit' });
|
|
106
106
|
} catch (e) {
|
|
107
107
|
logger.error('Failed to login to EAS');
|
|
108
108
|
return;
|
|
@@ -180,7 +180,7 @@ async function buildCommand(options) {
|
|
|
180
180
|
// Local build
|
|
181
181
|
if (platform === 'all') {
|
|
182
182
|
logger.info('Building Android first...');
|
|
183
|
-
|
|
183
|
+
execCommandSync(
|
|
184
184
|
'eas',
|
|
185
185
|
['build', '--platform', 'android', '--local', '--profile', buildProfile],
|
|
186
186
|
{
|
|
@@ -190,12 +190,16 @@ async function buildCommand(options) {
|
|
|
190
190
|
await moveBuildArtifactsToFolder('android');
|
|
191
191
|
|
|
192
192
|
logger.info('Now building iOS...');
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
193
|
+
execCommandSync(
|
|
194
|
+
'eas',
|
|
195
|
+
['build', '--platform', 'ios', '--local', '--profile', buildProfile],
|
|
196
|
+
{
|
|
197
|
+
stdio: 'inherit',
|
|
198
|
+
}
|
|
199
|
+
);
|
|
196
200
|
await moveBuildArtifactsToFolder('ios');
|
|
197
201
|
} else {
|
|
198
|
-
|
|
202
|
+
execCommandSync(
|
|
199
203
|
'eas',
|
|
200
204
|
['build', '--platform', platform, '--local', '--profile', buildProfile],
|
|
201
205
|
{
|
|
@@ -208,16 +212,16 @@ async function buildCommand(options) {
|
|
|
208
212
|
// Cloud build via EAS
|
|
209
213
|
if (platform === 'all') {
|
|
210
214
|
logger.info('Starting Android cloud build...');
|
|
211
|
-
|
|
215
|
+
execCommandSync('eas', ['build', '--platform', 'android', '--profile', buildProfile], {
|
|
212
216
|
stdio: 'inherit',
|
|
213
217
|
});
|
|
214
218
|
|
|
215
219
|
logger.info('Starting iOS cloud build...');
|
|
216
|
-
|
|
220
|
+
execCommandSync('eas', ['build', '--platform', 'ios', '--profile', buildProfile], {
|
|
217
221
|
stdio: 'inherit',
|
|
218
222
|
});
|
|
219
223
|
} else {
|
|
220
|
-
|
|
224
|
+
execCommandSync('eas', ['build', '--platform', platform, '--profile', buildProfile], {
|
|
221
225
|
stdio: 'inherit',
|
|
222
226
|
});
|
|
223
227
|
}
|
|
@@ -291,7 +295,7 @@ async function buildCommand(options) {
|
|
|
291
295
|
|
|
292
296
|
if (loginAnswer.login) {
|
|
293
297
|
try {
|
|
294
|
-
|
|
298
|
+
execCommandSync('eas', ['login'], { stdio: 'inherit' });
|
|
295
299
|
} catch (e) {
|
|
296
300
|
logger.error('Failed to login to EAS');
|
|
297
301
|
return;
|
package/src/commands/check.js
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
const logger = require('../utils/logger');
|
|
5
5
|
const expoDoctor = require('../utils/expo-doctor');
|
|
6
6
|
const eas = require('../utils/eas');
|
|
7
|
-
const {
|
|
7
|
+
const { execCommandSync } = require('../utils/commands');
|
|
8
8
|
|
|
9
9
|
async function checkCommand(type, buildId, options = {}) {
|
|
10
10
|
if (type === 'health') {
|
|
@@ -103,7 +103,7 @@ async function checkFix(options = {}) {
|
|
|
103
103
|
console.log('');
|
|
104
104
|
|
|
105
105
|
try {
|
|
106
|
-
|
|
106
|
+
execCommandSync('npx', ['expo', 'fix'], { stdio: 'inherit' });
|
|
107
107
|
logger.success('expo fix completed');
|
|
108
108
|
console.log('');
|
|
109
109
|
|
package/src/commands/dev.js
CHANGED
|
@@ -3,7 +3,8 @@ const prompt = inquirer.default?.prompt || inquirer.prompt;
|
|
|
3
3
|
const logger = require('../utils/logger');
|
|
4
4
|
const cleaner = require('../utils/cleaner');
|
|
5
5
|
const expoDoctor = require('../utils/expo-doctor');
|
|
6
|
-
const {
|
|
6
|
+
const { execSync } = require('child_process');
|
|
7
|
+
const { execCommandSync } = require('../utils/commands');
|
|
7
8
|
|
|
8
9
|
async function devCommand(options) {
|
|
9
10
|
logger.info('Starting development mode...');
|
|
@@ -103,7 +104,7 @@ async function devCommand(options) {
|
|
|
103
104
|
const runWithDeviceSelection = async (targetPlatform) => {
|
|
104
105
|
if (options.device) {
|
|
105
106
|
// Expo CLI will prompt to choose among available emulators/simulators and connected devices.
|
|
106
|
-
|
|
107
|
+
execCommandSync('npx', ['expo', `run:${targetPlatform}`, '--device'], { stdio: 'inherit' });
|
|
107
108
|
return;
|
|
108
109
|
}
|
|
109
110
|
|
package/src/utils/cleaner.js
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
const {
|
|
1
|
+
const { execSync } = require('child_process');
|
|
2
2
|
const fs = require('fs-extra');
|
|
3
3
|
const path = require('path');
|
|
4
4
|
const readline = require('readline');
|
|
5
5
|
const logger = require('./logger');
|
|
6
|
+
const { commandExists, execCommandSync } = require('./commands');
|
|
6
7
|
|
|
7
8
|
function askQuestion(question) {
|
|
8
9
|
const rl = readline.createInterface({
|
|
@@ -45,7 +46,7 @@ function removeFilesByPrefix(directory, prefixes) {
|
|
|
45
46
|
|
|
46
47
|
function tryExecFile(command, args, options = {}) {
|
|
47
48
|
try {
|
|
48
|
-
|
|
49
|
+
execCommandSync(command, args, options);
|
|
49
50
|
return true;
|
|
50
51
|
} catch (e) {
|
|
51
52
|
return false;
|
|
@@ -61,13 +62,13 @@ async function killRunningApps(bundleId, platform) {
|
|
|
61
62
|
if (platform === 'android' || platform === 'all') {
|
|
62
63
|
try {
|
|
63
64
|
if (commandExists('adb')) {
|
|
64
|
-
const devices =
|
|
65
|
+
const devices = execCommandSync('adb', ['devices'], { encoding: 'utf8' });
|
|
65
66
|
const deviceCount = (devices.match(/device$/gm) || []).length;
|
|
66
67
|
|
|
67
68
|
if (deviceCount > 0 && bundleId) {
|
|
68
69
|
try {
|
|
69
70
|
if (isValidBundleId(bundleId)) {
|
|
70
|
-
|
|
71
|
+
execCommandSync('adb', ['shell', 'am', 'force-stop', bundleId], { stdio: 'ignore' });
|
|
71
72
|
logger.success('Stopped Android app');
|
|
72
73
|
} else {
|
|
73
74
|
logger.warning('Invalid bundle identifier, skipping Android app kill');
|
|
@@ -108,7 +109,7 @@ async function cleanWatchman() {
|
|
|
108
109
|
logger.step('Cleaning watchman cache...');
|
|
109
110
|
try {
|
|
110
111
|
if (commandExists('watchman')) {
|
|
111
|
-
|
|
112
|
+
execCommandSync('watchman', ['watch-del-all'], { stdio: 'ignore' });
|
|
112
113
|
logger.success('Watchman cache cleared');
|
|
113
114
|
} else {
|
|
114
115
|
logger.warning('Watchman not found, skipping...');
|
|
@@ -275,7 +276,7 @@ async function reinstallDependencies() {
|
|
|
275
276
|
}
|
|
276
277
|
|
|
277
278
|
try {
|
|
278
|
-
|
|
279
|
+
execCommandSync(packageManager, ['install'], { stdio: 'inherit' });
|
|
279
280
|
logger.success('Dependencies installed');
|
|
280
281
|
} catch (e) {
|
|
281
282
|
logger.error('Failed to install dependencies');
|
|
@@ -291,9 +292,9 @@ async function rebuildNative(platform) {
|
|
|
291
292
|
|
|
292
293
|
try {
|
|
293
294
|
if (platform === 'all') {
|
|
294
|
-
|
|
295
|
+
execCommandSync('npx', ['expo', 'prebuild', '--clean'], { stdio: 'inherit' });
|
|
295
296
|
} else {
|
|
296
|
-
|
|
297
|
+
execCommandSync('npx', ['expo', 'prebuild', '--clean', '--platform', platform], {
|
|
297
298
|
stdio: 'inherit',
|
|
298
299
|
});
|
|
299
300
|
}
|
|
@@ -304,19 +305,6 @@ async function rebuildNative(platform) {
|
|
|
304
305
|
}
|
|
305
306
|
}
|
|
306
307
|
|
|
307
|
-
/**
|
|
308
|
-
* Check if command exists
|
|
309
|
-
*/
|
|
310
|
-
function commandExists(command) {
|
|
311
|
-
try {
|
|
312
|
-
const lookupCommand = process.platform === 'win32' ? 'where' : 'which';
|
|
313
|
-
execFileSync(lookupCommand, [command], { stdio: 'ignore' });
|
|
314
|
-
return true;
|
|
315
|
-
} catch (e) {
|
|
316
|
-
return false;
|
|
317
|
-
}
|
|
318
|
-
}
|
|
319
|
-
|
|
320
308
|
/**
|
|
321
309
|
* Get bundle ID from app config
|
|
322
310
|
*/
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
const { execFileSync } = require('child_process');
|
|
2
|
+
|
|
3
|
+
function shouldUseShell(command, options = {}) {
|
|
4
|
+
return (
|
|
5
|
+
process.platform === 'win32' &&
|
|
6
|
+
options.shell === undefined &&
|
|
7
|
+
typeof command === 'string' &&
|
|
8
|
+
!command.includes('\\') &&
|
|
9
|
+
!command.includes('/')
|
|
10
|
+
);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
function execCommandSync(command, args = [], options = {}) {
|
|
14
|
+
const execOptions = shouldUseShell(command, options) ? { ...options, shell: true } : options;
|
|
15
|
+
return execFileSync(command, args, execOptions);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function commandExists(command) {
|
|
19
|
+
try {
|
|
20
|
+
const lookupCommand = process.platform === 'win32' ? 'where' : 'which';
|
|
21
|
+
execFileSync(lookupCommand, [command], { stdio: 'ignore' });
|
|
22
|
+
return true;
|
|
23
|
+
} catch (e) {
|
|
24
|
+
return false;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
module.exports = {
|
|
29
|
+
commandExists,
|
|
30
|
+
execCommandSync,
|
|
31
|
+
};
|
package/src/utils/eas.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
// ============================================
|
|
2
2
|
// FILE: src/utils/eas.js (Enhanced)
|
|
3
3
|
// ============================================
|
|
4
|
-
const { execFileSync } = require('child_process');
|
|
5
4
|
const logger = require('./logger');
|
|
5
|
+
const { execCommandSync } = require('./commands');
|
|
6
6
|
|
|
7
7
|
function validatePlatform(platform) {
|
|
8
8
|
if (!['android', 'ios'].includes(platform)) {
|
|
@@ -23,7 +23,7 @@ async function checkEASLogin() {
|
|
|
23
23
|
logger.step('Checking EAS login status...');
|
|
24
24
|
|
|
25
25
|
try {
|
|
26
|
-
const output =
|
|
26
|
+
const output = execCommandSync('eas', ['whoami'], { encoding: 'utf8', stdio: 'pipe' });
|
|
27
27
|
const email = output.trim();
|
|
28
28
|
|
|
29
29
|
if (email && !email.includes('error') && !email.includes('not logged')) {
|
|
@@ -130,7 +130,7 @@ async function listEASBuilds() {
|
|
|
130
130
|
|
|
131
131
|
try {
|
|
132
132
|
console.log('');
|
|
133
|
-
|
|
133
|
+
execCommandSync('eas', ['build:list', '--limit', '20'], { stdio: 'inherit' });
|
|
134
134
|
console.log('');
|
|
135
135
|
} catch (e) {
|
|
136
136
|
logger.error('Failed to fetch builds. Make sure you are logged in to EAS.');
|
|
@@ -147,7 +147,7 @@ async function viewEASBuild(buildId) {
|
|
|
147
147
|
try {
|
|
148
148
|
validateBuildId(buildId);
|
|
149
149
|
console.log('');
|
|
150
|
-
|
|
150
|
+
execCommandSync('eas', ['build:view', buildId], { stdio: 'inherit' });
|
|
151
151
|
console.log('');
|
|
152
152
|
} catch (e) {
|
|
153
153
|
logger.error(`Failed to fetch build ${buildId}`);
|
|
@@ -163,7 +163,7 @@ async function displayEASProjectInfo() {
|
|
|
163
163
|
|
|
164
164
|
try {
|
|
165
165
|
console.log('');
|
|
166
|
-
|
|
166
|
+
execCommandSync('eas', ['project:info'], { stdio: 'inherit' });
|
|
167
167
|
console.log('');
|
|
168
168
|
} catch (e) {
|
|
169
169
|
logger.error('Failed to fetch project info');
|
|
@@ -179,7 +179,7 @@ async function submitToEAS(platform) {
|
|
|
179
179
|
|
|
180
180
|
try {
|
|
181
181
|
validatePlatform(platform);
|
|
182
|
-
|
|
182
|
+
execCommandSync('eas', ['submit', '--platform', platform], { stdio: 'inherit' });
|
|
183
183
|
logger.success('Build submitted successfully');
|
|
184
184
|
} catch (e) {
|
|
185
185
|
logger.error('Failed to submit build to EAS');
|
package/src/utils/expo-doctor.js
CHANGED
|
@@ -2,6 +2,7 @@ const { execFileSync } = require('child_process');
|
|
|
2
2
|
const fs = require('fs-extra');
|
|
3
3
|
const path = require('path');
|
|
4
4
|
const logger = require('./logger');
|
|
5
|
+
const { execCommandSync } = require('./commands');
|
|
5
6
|
|
|
6
7
|
/**
|
|
7
8
|
* Run expo-doctor and generate HTML report
|
|
@@ -17,7 +18,7 @@ async function runExpoDoctor(options = {}) {
|
|
|
17
18
|
|
|
18
19
|
try {
|
|
19
20
|
// Run expo-doctor and capture output
|
|
20
|
-
const output =
|
|
21
|
+
const output = execCommandSync('npx', ['expo-doctor'], {
|
|
21
22
|
encoding: 'utf8',
|
|
22
23
|
stdio: 'pipe',
|
|
23
24
|
});
|