Files
2026-07-13 13:05:33 +08:00

58 lines
1.7 KiB
JavaScript

import { spawn } from 'node:child_process'
import { existsSync } from 'node:fs'
import path from 'node:path'
import process from 'node:process'
const expoBinNames =
process.platform === 'win32' ? ['expo.CMD', 'expo.cmd', 'expo.ps1', 'expo'] : ['expo']
function expoBinPaths(mobileDir) {
return expoBinNames.map((binName) => path.join(mobileDir, 'node_modules', '.bin', binName))
}
export function getMobileExpoExecutablePath(mobileDir) {
return expoBinPaths(mobileDir).find((binPath) => existsSync(binPath)) ?? null
}
function runPnpmInstall(mobileDir) {
return new Promise((resolve, reject) => {
const install = spawn('pnpm', ['install', '--frozen-lockfile'], {
cwd: mobileDir,
env: process.env,
shell: process.platform === 'win32',
stdio: 'inherit'
})
install.on('error', reject)
install.on('exit', (code, signal) => {
if (signal) {
reject(new Error(`pnpm install --frozen-lockfile was terminated by ${signal}`))
} else if (code === 0) {
resolve()
} else {
reject(new Error(`pnpm install --frozen-lockfile exited with code ${code}`))
}
})
})
}
export async function ensureMobileExpoCli(mobileDir, logger = {}) {
if (getMobileExpoExecutablePath(mobileDir)) {
return
}
const message = 'Mobile dependencies are missing; running pnpm install --frozen-lockfile...'
if (logger.logStep) {
logger.logStep('deps', message)
} else {
console.log(`[start] ${message}`)
}
await runPnpmInstall(mobileDir)
if (!getMobileExpoExecutablePath(mobileDir)) {
throw new Error('pnpm install completed, but node_modules/.bin/expo is still missing.')
}
logger.logSuccess?.('Mobile dependencies installed')
}