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 CHANGED
@@ -1,10 +1,10 @@
1
1
  {
2
2
  "name": "budexp",
3
- "version": "0.1.0",
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": "./bin/budexp.js"
7
+ "budexp": "bin/budexp.js"
8
8
  },
9
9
  "files": [
10
10
  "bin",
@@ -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 { execFileSync } = require('child_process');
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
- execFileSync('eas', ['login'], { stdio: 'inherit' });
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
- execFileSync(
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
- execFileSync('eas', ['build', '--platform', 'ios', '--local', '--profile', buildProfile], {
194
- stdio: 'inherit',
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
- execFileSync(
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
- execFileSync('eas', ['build', '--platform', 'android', '--profile', buildProfile], {
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
- execFileSync('eas', ['build', '--platform', 'ios', '--profile', buildProfile], {
220
+ execCommandSync('eas', ['build', '--platform', 'ios', '--profile', buildProfile], {
217
221
  stdio: 'inherit',
218
222
  });
219
223
  } else {
220
- execFileSync('eas', ['build', '--platform', platform, '--profile', buildProfile], {
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
- execFileSync('eas', ['login'], { stdio: 'inherit' });
298
+ execCommandSync('eas', ['login'], { stdio: 'inherit' });
295
299
  } catch (e) {
296
300
  logger.error('Failed to login to EAS');
297
301
  return;
@@ -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 { execFileSync } = require('child_process');
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
- execFileSync('npx', ['expo', 'fix'], { stdio: 'inherit' });
106
+ execCommandSync('npx', ['expo', 'fix'], { stdio: 'inherit' });
107
107
  logger.success('expo fix completed');
108
108
  console.log('');
109
109
 
@@ -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 { execFileSync, execSync } = require('child_process');
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
- execFileSync('npx', ['expo', `run:${targetPlatform}`, '--device'], { stdio: 'inherit' });
107
+ execCommandSync('npx', ['expo', `run:${targetPlatform}`, '--device'], { stdio: 'inherit' });
107
108
  return;
108
109
  }
109
110
 
@@ -1,8 +1,9 @@
1
- const { execFileSync, execSync } = require('child_process');
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
- execFileSync(command, args, options);
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 = execFileSync('adb', ['devices'], { encoding: 'utf8' });
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
- execFileSync('adb', ['shell', 'am', 'force-stop', bundleId], { stdio: 'ignore' });
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
- execFileSync('watchman', ['watch-del-all'], { stdio: 'ignore' });
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
- execFileSync(packageManager, ['install'], { stdio: 'inherit' });
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
- execFileSync('npx', ['expo', 'prebuild', '--clean'], { stdio: 'inherit' });
295
+ execCommandSync('npx', ['expo', 'prebuild', '--clean'], { stdio: 'inherit' });
295
296
  } else {
296
- execFileSync('npx', ['expo', 'prebuild', '--clean', '--platform', platform], {
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 = execFileSync('eas', ['whoami'], { encoding: 'utf8', stdio: 'pipe' });
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
- execFileSync('eas', ['build:list', '--limit', '20'], { stdio: 'inherit' });
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
- execFileSync('eas', ['build:view', buildId], { stdio: 'inherit' });
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
- execFileSync('eas', ['project:info'], { stdio: 'inherit' });
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
- execFileSync('eas', ['submit', '--platform', platform], { stdio: 'inherit' });
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');
@@ -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 = execFileSync('npx', ['expo-doctor'], {
21
+ const output = execCommandSync('npx', ['expo-doctor'], {
21
22
  encoding: 'utf8',
22
23
  stdio: 'pipe',
23
24
  });