Skip to content

Commit ee52259

Browse files
committed
chore: wip
1 parent 86c2620 commit ee52259

File tree

5 files changed

+139
-13
lines changed

5 files changed

+139
-13
lines changed

packages/launchpad/bin/cli.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -681,12 +681,16 @@ async function installGlobalDependencies(options: {
681681
const dir = path.dirname(file)
682682
const sniffResult = await sniff({ string: dir })
683683

684-
for (const pkg of sniffResult.pkgs) {
684+
// Only include packages explicitly marked as global (or via top-level global flag)
685+
const globalPkgs = sniffResult.pkgs.filter(p => p.global)
686+
687+
for (const pkg of globalPkgs) {
685688
allPackages.add(pkg.project)
686689
}
687690

688691
if (options.verbose) {
689-
console.log(` 📄 ${file}: ${sniffResult.pkgs.length} packages`)
692+
const skipped = sniffResult.pkgs.length - globalPkgs.length
693+
console.log(` 📄 ${file}: ${globalPkgs.length} global package(s)${skipped > 0 ? `, skipped ${skipped} local` : ''}`)
690694
}
691695
}
692696
catch (error) {

packages/launchpad/src/binary-downloader.ts

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -64,8 +64,8 @@ export class PrecompiledBinaryDownloader {
6464
* Detect the optimal PHP configuration based on the system and requirements
6565
*/
6666
private getOptimalConfiguration(): string {
67-
// Default to Laravel MySQL (most common setup)
68-
return 'laravel-mysql'
67+
// Default to full-stack (most comprehensive setup)
68+
return 'full-stack'
6969
}
7070

7171
/**
@@ -208,10 +208,10 @@ export class PrecompiledBinaryDownloader {
208208
else if (envContent.includes('DB_CONNECTION=sqlite')) {
209209
return 'laravel-sqlite'
210210
}
211-
// Default to MySQL for Laravel
212-
return 'laravel-mysql'
211+
// Default to full-stack for Laravel
212+
return 'full-stack'
213213
}
214-
return 'laravel-mysql'
214+
return 'full-stack'
215215
}
216216

217217
// Check for API-only Laravel (Lumen-like)
@@ -234,11 +234,11 @@ export class PrecompiledBinaryDownloader {
234234
return 'wordpress'
235235
}
236236

237-
// Default to Laravel MySQL (most popular setup)
238-
return 'laravel-mysql'
237+
// Default to full-stack (most comprehensive setup)
238+
return 'full-stack'
239239
}
240240
catch {
241-
return 'laravel-mysql'
241+
return 'full-stack'
242242
}
243243
}
244244

packages/launchpad/src/config.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ export const defaultConfig: LaunchpadConfig = {
126126
},
127127
// Manual configuration (when auto-detect is disabled)
128128
manual: {
129-
configuration: (process.env.LAUNCHPAD_PHP_CONFIGURATION as 'laravel-mysql' | 'laravel-postgres' | 'laravel-sqlite' | 'api-only' | 'enterprise' | 'wordpress' | 'full-stack') || 'laravel-mysql',
129+
configuration: (process.env.LAUNCHPAD_PHP_CONFIGURATION as 'laravel-mysql' | 'laravel-postgres' | 'laravel-sqlite' | 'api-only' | 'enterprise' | 'wordpress' | 'full-stack') || 'full-stack',
130130
},
131131
},
132132
},

packages/launchpad/src/install-core.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -225,8 +225,6 @@ export async function installPackage(packageName: string, packageSpec: string, i
225225

226226
// Special handling for PHP - use precompiled binaries from GitHub
227227
if (name === 'php' || domain === 'php.net') {
228-
console.log('🐘 Installing PHP using precompiled binaries from GitHub...')
229-
230228
try {
231229
// Import the binary downloader
232230
const { downloadPhpBinary } = await import('./binary-downloader')
Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
import { afterEach, beforeEach, describe, expect, it } from 'bun:test'
2+
import fs from 'node:fs'
3+
import os from 'node:os'
4+
import path from 'node:path'
5+
import process from 'node:process'
6+
import { spawn } from 'node:child_process'
7+
8+
function getTestEnv(extra?: Record<string, string>): NodeJS.ProcessEnv {
9+
return {
10+
...process.env,
11+
NODE_ENV: 'test',
12+
// Ensure basic PATH so spawned bun can run in CI/dev
13+
PATH: process.env.PATH?.includes('/usr/local/bin')
14+
? process.env.PATH!
15+
: `/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:${process.env.PATH || ''}`,
16+
...extra,
17+
}
18+
}
19+
20+
describe('Global Deps Filtering (regression)', () => {
21+
let originalEnv: NodeJS.ProcessEnv
22+
let tempHome: string
23+
24+
beforeEach(() => {
25+
originalEnv = { ...process.env }
26+
tempHome = fs.mkdtempSync(path.join(os.tmpdir(), 'launchpad-global-filtering-'))
27+
})
28+
29+
afterEach(() => {
30+
// Restore environment variables properly without replacing the entire process.env object
31+
Object.keys(process.env).forEach((key) => {
32+
delete process.env[key]
33+
})
34+
Object.assign(process.env, originalEnv)
35+
36+
if (fs.existsSync(tempHome)) {
37+
fs.rmSync(tempHome, { recursive: true, force: true })
38+
}
39+
})
40+
41+
it('installs only explicitly global packages during --global-deps scan', () => {
42+
// Arrange: create two projects under typical scan locations
43+
const localOnlyProject = path.join(tempHome, 'Code', 'the-one-otc-api')
44+
const globalToolsProject = path.join(tempHome, 'Projects', 'global-tools')
45+
fs.mkdirSync(localOnlyProject, { recursive: true })
46+
fs.mkdirSync(globalToolsProject, { recursive: true })
47+
48+
// Local-only deps (should be ignored by --global-deps)
49+
fs.writeFileSync(
50+
path.join(localOnlyProject, 'deps.yaml'),
51+
`dependencies:
52+
php.net: ^8.4.0
53+
getcomposer.org: ^2.8.10
54+
`,
55+
'utf8',
56+
)
57+
58+
// Explicitly-global deps (should be included)
59+
fs.writeFileSync(
60+
path.join(globalToolsProject, 'dependencies.yaml'),
61+
`global: true
62+
dependencies:
63+
bun.sh: ^1.2.19
64+
starship.rs: ^1.23.0
65+
`,
66+
'utf8',
67+
)
68+
69+
// Act: run CLI with --global-deps in dry-run + verbose to capture listing
70+
const cliPath = path.join(__dirname, '..', 'bin', 'cli.ts')
71+
72+
return new Promise<void>((resolve, reject) => {
73+
const proc = spawn(
74+
'bun',
75+
[cliPath, 'install', '--global-deps', '--dry-run', '--verbose'],
76+
{
77+
stdio: ['ignore', 'pipe', 'pipe'],
78+
env: getTestEnv({ HOME: tempHome }),
79+
},
80+
)
81+
82+
let stdout = ''
83+
let stderr = ''
84+
85+
proc.stdout.on('data', (data) => { stdout += data.toString() })
86+
proc.stderr.on('data', (data) => { stderr += data.toString() })
87+
88+
const timeout = setTimeout(() => {
89+
try { proc.kill() } catch {}
90+
reject(new Error('Timed out waiting for CLI output'))
91+
}, 20000)
92+
93+
proc.on('close', () => {
94+
clearTimeout(timeout)
95+
const output = `${stdout}\n${stderr}`
96+
97+
try {
98+
// Should show scan summary
99+
expect(output).toContain('Found')
100+
expect(output).toMatch(/dependency files?/)
101+
102+
// Should list packages that would be installed (only global ones)
103+
expect(output).toContain('Packages that would be installed')
104+
// Include explicitly global
105+
expect(output).toMatch(/bun\.sh/i)
106+
expect(output).toMatch(/starship\.rs/i)
107+
108+
// Exclude local-only entries
109+
expect(output).not.toMatch(/php\.net/i)
110+
expect(output).not.toMatch(/getcomposer\.org/i)
111+
112+
// Optional: per-file verbose summary should mention skipped local packages
113+
// We expect at least one "skipped X local" occurrence
114+
expect(/skipped\s+\d+\s+local/.test(output)).toBe(true)
115+
116+
resolve()
117+
}
118+
catch (err) {
119+
reject(err)
120+
}
121+
})
122+
})
123+
}, 30000)
124+
})

0 commit comments

Comments
 (0)