Skip to content

Commit 92ba206

Browse files
committed
chore: wip
1 parent e0da65c commit 92ba206

File tree

4 files changed

+392
-206
lines changed

4 files changed

+392
-206
lines changed

packages/launchpad/bin/cli.ts

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1966,7 +1966,15 @@ cli
19661966
.command('dev:shellcode', 'Generate shell integration code')
19671967
.option('--test-mode', 'Generate shellcode for testing (bypasses test environment checks)')
19681968
.action(({ testMode }) => {
1969-
console.log(shellcode(testMode))
1969+
try {
1970+
console.log(shellcode(testMode))
1971+
// Force immediate exit to prevent any hanging
1972+
process.exit(0)
1973+
}
1974+
catch (error) {
1975+
console.error('Failed to generate shellcode:', error instanceof Error ? error.message : String(error))
1976+
process.exit(1)
1977+
}
19701978
})
19711979

19721980
cli
@@ -1990,6 +1998,11 @@ cli
19901998
shellOutput: isShellIntegration,
19911999
skipGlobal: process.env.NODE_ENV === 'test' || process.env.LAUNCHPAD_SKIP_GLOBAL_AUTO_SCAN === 'true', // Skip global packages only in test mode or when explicitly disabled
19922000
})
2001+
2002+
// Force immediate exit for shell integration to prevent hanging
2003+
if (isShellIntegration) {
2004+
process.exit(0)
2005+
}
19932006
}
19942007
catch (error) {
19952008
if (!options?.quiet && !options?.shell) {
@@ -2007,7 +2020,7 @@ cli
20072020
console.log('done')
20082021
console.log('# Clear command hash to ensure fresh lookups')
20092022
console.log('hash -r 2>/dev/null || true')
2010-
return
2023+
process.exit(0)
20112024
}
20122025
if (!options?.shell) {
20132026
process.exit(1)

packages/launchpad/src/dev/dump.ts

Lines changed: 88 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -1105,19 +1105,14 @@ export async function dump(dir: string, options: DumpOptions = {}): Promise<void
11051105
catch {}
11061106
}
11071107
if (isReady) {
1108-
const tIni = tick()
1109-
await ensureProjectPhpIni(projectDir, envDir)
1110-
addTiming('ensurePhpIni', tIni)
1111-
try {
1112-
const tSvc = tick()
1113-
await setupProjectServices(projectDir, sniffResult, true)
1114-
addTiming('setupServices', tSvc)
1115-
const tPost = tick()
1116-
// Run project-configured post-setup once in shell fast path (idempotent)
1117-
await maybeRunProjectPostSetup(projectDir, envDir, true)
1118-
addTiming('postSetup', tPost)
1108+
// Skip all expensive operations in shell integration mode for instant activation
1109+
// Services, PHP ini, and post-setup will be handled by regular dev command when needed
1110+
if (isVerbose) {
1111+
try {
1112+
process.stderr.write(`🔍 Shell fast path: skipping services/php/post-setup for performance\n`)
1113+
}
1114+
catch {}
11191115
}
1120-
catch {}
11211116
}
11221117

11231118
const tOut1 = tick()
@@ -1306,51 +1301,66 @@ export async function dump(dir: string, options: DumpOptions = {}): Promise<void
13061301
const globalBinPath = path.join(globalEnvDir, 'bin')
13071302
const globalSbinPath = path.join(globalEnvDir, 'sbin')
13081303

1309-
// Check what packages are actually missing and need installation
1310-
const packageStatus = needsPackageInstallation(localPackages, globalPackages, envDir, globalEnvDir)
1311-
1312-
// Install missing packages if any are found
1313-
if (packageStatus.needsLocal || packageStatus.needsGlobal) {
1314-
const tInstall = tick()
1315-
await installPackagesOptimized(
1316-
packageStatus.missingLocal,
1317-
packageStatus.missingGlobal,
1318-
envDir,
1319-
globalEnvDir,
1320-
dryrun,
1321-
quiet,
1322-
)
1323-
addTiming('install(packages)', tInstall)
1304+
// In shell integration mode with ready environment, skip package installation checks
1305+
const readyMarker = path.join(envDir, '.launchpad_ready')
1306+
const isEnvReady = fs.existsSync(readyMarker)
1307+
1308+
if (!isEnvReady) {
1309+
// Check what packages are actually missing and need installation
1310+
const packageStatus = needsPackageInstallation(localPackages, globalPackages, envDir, globalEnvDir)
1311+
1312+
// Install missing packages if any are found
1313+
if (packageStatus.needsLocal || packageStatus.needsGlobal) {
1314+
const tInstall = tick()
1315+
await installPackagesOptimized(
1316+
packageStatus.missingLocal,
1317+
packageStatus.missingGlobal,
1318+
envDir,
1319+
globalEnvDir,
1320+
dryrun,
1321+
quiet,
1322+
)
1323+
addTiming('install(packages)', tInstall)
1324+
}
13241325
}
1325-
1326-
// Create PHP shims after all dependencies are installed
1327-
if (config.verbose) {
1328-
console.log('🔍 Checking for PHP installations to create shims...')
1326+
else if (isVerbose) {
1327+
try {
1328+
process.stderr.write(`🔍 Shell integration: environment ready, skipping package checks\n`)
1329+
}
1330+
catch {}
13291331
}
1330-
const tShim = tick()
1331-
await createPhpShimsAfterInstall(envDir)
1332-
addTiming('createPhpShims', tShim)
13331332

1334-
// Start services during shell integration when configured
1335-
try {
1336-
const tSvc2 = tick()
1337-
await setupProjectServices(projectDir, sniffResult, true)
1338-
addTiming('setupServices', tSvc2)
1333+
// Create PHP shims only if environment was just created or updated
1334+
if (!isEnvReady) {
1335+
if (config.verbose) {
1336+
console.log('🔍 Checking for PHP installations to create shims...')
1337+
}
1338+
const tShim = tick()
1339+
if (isShellIntegration) {
1340+
// Run PHP shim creation in background to avoid blocking shell activation
1341+
createPhpShimsAfterInstall(envDir).catch(() => {}) // Fire and forget
1342+
addTiming('createPhpShims(async)', tShim)
1343+
}
1344+
else {
1345+
await createPhpShimsAfterInstall(envDir)
1346+
addTiming('createPhpShims', tShim)
1347+
}
1348+
}
1349+
else if (isVerbose) {
1350+
try {
1351+
process.stderr.write(`🔍 Shell integration: environment ready, skipping PHP shim creation\n`)
1352+
}
1353+
catch {}
13391354
}
1340-
catch {}
1341-
1342-
// Ensure project php.ini exists only
1343-
const tIni2 = tick()
1344-
await ensureProjectPhpIni(projectDir, envDir)
1345-
addTiming('ensurePhpIni', tIni2)
13461355

1347-
// Run project-configured post-setup once (idempotent marker)
1348-
try {
1349-
const tPost2 = tick()
1350-
await maybeRunProjectPostSetup(projectDir, envDir, true)
1351-
addTiming('postSetup', tPost2)
1356+
// Skip expensive operations in shell integration mode for instant activation
1357+
// Services, PHP ini, and post-setup will be handled by regular dev command when needed
1358+
if (isVerbose) {
1359+
try {
1360+
process.stderr.write(`🔍 Shell integration: skipping services/php/post-setup for performance\n`)
1361+
}
1362+
catch {}
13521363
}
1353-
catch {}
13541364

13551365
const tOut2 = tick()
13561366
outputShellCode(dir, envBinPath, envSbinPath, projectHash, sniffResult, globalBinPath, globalSbinPath)
@@ -1414,10 +1424,12 @@ export async function dump(dir: string, options: DumpOptions = {}): Promise<void
14141424
}
14151425

14161426
// Ensure php.ini and Laravel post-setup runs (regular path)
1417-
const tIni3 = tick()
1418-
await ensureProjectPhpIni(projectDir, envDir)
1419-
addTiming('ensurePhpIni', tIni3)
1427+
// Skip expensive operations in shell integration mode
14201428
if (!isShellIntegration) {
1429+
const tIni3 = tick()
1430+
await ensureProjectPhpIni(projectDir, envDir)
1431+
addTiming('ensurePhpIni', tIni3)
1432+
14211433
const tPost3 = tick()
14221434
await maybeRunProjectPostSetup(projectDir, envDir, isShellIntegration)
14231435
addTiming('postSetup', tPost3)
@@ -1475,16 +1487,18 @@ export async function dump(dir: string, options: DumpOptions = {}): Promise<void
14751487
addTiming('total', tTotal)
14761488
flushTimings('regular-activation')
14771489

1478-
// Post-activation hook (file-level then config)
1479-
if (dependencyFile) {
1480-
const filePostActivation = extractHookCommandsFromDepsYaml(dependencyFile, 'postActivation')
1481-
if (filePostActivation.length > 0) {
1482-
await executepostSetup(projectDir, filePostActivation)
1490+
// Post-activation hook (file-level then config) - skip in shell integration mode for performance
1491+
if (!isShellIntegration) {
1492+
if (dependencyFile) {
1493+
const filePostActivation = extractHookCommandsFromDepsYaml(dependencyFile, 'postActivation')
1494+
if (filePostActivation.length > 0) {
1495+
await executepostSetup(projectDir, filePostActivation)
1496+
}
1497+
}
1498+
const postActivation = config.postActivation
1499+
if (postActivation?.enabled) {
1500+
await executepostSetup(projectDir, postActivation.commands || [])
14831501
}
1484-
}
1485-
const postActivation = config.postActivation
1486-
if (postActivation?.enabled) {
1487-
await executepostSetup(projectDir, postActivation.commands || [])
14881502
}
14891503
}
14901504
}
@@ -1910,8 +1924,8 @@ function outputShellCode(dir: string, envBinPath: string, envSbinPath: string, p
19101924
process.stdout.write(` ;;\n`)
19111925
process.stdout.write(` esac\n`)
19121926
process.stdout.write(`}\n`)
1913-
// Refresh the command hash so version switches take effect immediately
1914-
process.stdout.write(`hash -r 2>/dev/null || true\n`)
1927+
// Refresh the command hash so version switches take effect immediately (async)
1928+
process.stdout.write(`{ hash -r 2>/dev/null || true; } &\n`)
19151929
}
19161930

19171931
/**
@@ -1966,8 +1980,13 @@ async function createPhpShimsAfterInstall(envDir: string): Promise<void> {
19661980
/**
19671981
* Run Laravel post-setup commands once per project activation
19681982
*/
1969-
async function maybeRunProjectPostSetup(projectDir: string, envDir: string, _isShellIntegration: boolean): Promise<void> {
1983+
async function maybeRunProjectPostSetup(projectDir: string, envDir: string, isShellIntegration: boolean): Promise<void> {
19701984
try {
1985+
// Skip post-setup entirely in shell integration mode for performance
1986+
if (isShellIntegration) {
1987+
return
1988+
}
1989+
19711990
if (process.env.LAUNCHPAD_VERBOSE === 'true') {
19721991
console.warn(`maybeRunProjectPostSetup called: projectDir=${projectDir}, envDir=${envDir}`)
19731992
}
@@ -2050,6 +2069,9 @@ async function setupProjectServices(projectDir: string, sniffResult: any, showMe
20502069
try {
20512070
// Check services.autoStart configuration from deps.yaml
20522071
if (!sniffResult?.services?.enabled || !sniffResult.services.autoStart || sniffResult.services.autoStart.length === 0) {
2072+
if (showMessages && process.env.LAUNCHPAD_VERBOSE === 'true') {
2073+
console.log('🔍 No services configured in deps.yaml - skipping service setup')
2074+
}
20532075
return // No services to auto-start
20542076
}
20552077

0 commit comments

Comments
 (0)