@@ -9,19 +9,32 @@ import {
99 LatestSupportedPHPVersion ,
1010 SupportedPHPVersionsList ,
1111} from '@php-wasm/universal' ;
12+ /* eslint-disable no-console */
1213import type { SupportedPHPVersion } from '@php-wasm/universal' ;
13-
1414import { FileLockManagerForNode } from '@php-wasm/node' ;
1515import { PHP } from '@php-wasm/universal' ;
1616import { loadNodeRuntime , useHostFilesystem } from '@php-wasm/node' ;
1717import { startBridge } from '@php-wasm/xdebug-bridge' ;
18+ import {
19+ addXdebugIDEConfig ,
20+ clearXdebugIDEConfig ,
21+ } from './xdebug-path-mappings' ;
1822import path from 'path' ;
1923
2024let args = process . argv . slice ( 2 ) ;
2125if ( ! args . length ) {
2226 args = [ '--help' ] ;
2327}
2428
29+ const bold = ( text : string ) =>
30+ process . stdout . isTTY ? '\x1b[1m' + text + '\x1b[0m' : text ;
31+
32+ const italic = ( text : string ) =>
33+ process . stdout . isTTY ? `\x1b[3m${ text } \x1b[0m` : text ;
34+
35+ const highlight = ( text : string ) =>
36+ process . stdout . isTTY ? `\x1b[33m${ text } \x1b[0m` : text ;
37+
2538const baseUrl = ( import . meta || { } ) . url ;
2639
2740// Write the ca-bundle.crt file to disk so that PHP can find it.
@@ -51,6 +64,23 @@ async function run() {
5164 args = args . filter ( ( arg ) => arg !== '--experimental-devtools' ) ;
5265 }
5366
67+ const experimentalUnsafeIDEIntegrationOptions =
68+ args
69+ . filter ( ( arg ) =>
70+ arg . startsWith ( '--experimental-unsafe-ide-integration' )
71+ )
72+ . map ( ( arg ) => {
73+ const value = arg . split ( '=' ) [ 1 ] ;
74+ if ( value === undefined ) return [ 'vscode' , 'phpstorm' ] ;
75+ if ( value . includes ( ',' ) ) return value . split ( ',' ) ;
76+ return [ value ] ;
77+ } ) [ 0 ] ?? false ;
78+ if ( experimentalUnsafeIDEIntegrationOptions ) {
79+ args = args . filter (
80+ ( arg ) => ! arg . startsWith ( '--experimental-unsafe-ide-integration' )
81+ ) ;
82+ }
83+
5484 // npm scripts set the TMPDIR env variable
5585 // PHP accepts a TMPDIR env variable and expects it to
5686 // be a writable directory within the PHP filesystem.
@@ -105,7 +135,90 @@ ${process.argv[0]} ${process.execArgv.join(' ')} ${process.argv[1]}
105135
106136 useHostFilesystem ( php ) ;
107137
108- if ( hasDevtoolsOption && hasXdebugOption ) {
138+ // If xdebug, and experimental IDE are enabled,
139+ // recreate the symlink pointing to the temporary
140+ // directory and add the new IDE config.
141+ if ( hasXdebugOption && experimentalUnsafeIDEIntegrationOptions ) {
142+ try {
143+ const IDEConfigName = 'PHP.wasm CLI - Listen for Xdebug' ;
144+ const ides = experimentalUnsafeIDEIntegrationOptions ;
145+
146+ // NOTE: Both the 'clear' and 'add' operations can throw errors.
147+ await clearXdebugIDEConfig ( IDEConfigName , process . cwd ( ) ) ;
148+
149+ const modifiedConfig = await addXdebugIDEConfig ( {
150+ name : IDEConfigName ,
151+ host : 'example.com' ,
152+ port : 443 ,
153+ ides : ides ,
154+ cwd : process . cwd ( ) ,
155+ } ) ;
156+
157+ // Display IDE-specific instructions
158+ const hasVSCode = ides . includes ( 'vscode' ) ;
159+ const hasPhpStorm = ides . includes ( 'phpstorm' ) ;
160+
161+ console . log ( '' ) ;
162+
163+ if ( modifiedConfig . length > 0 ) {
164+ console . log ( bold ( `Xdebug configured successfully` ) ) ;
165+ console . log (
166+ highlight ( `Updated IDE config: ` ) + modifiedConfig . join ( ' ' )
167+ ) ;
168+ } else {
169+ console . log ( bold ( `Xdebug configuration failed.` ) ) ;
170+ console . log (
171+ 'No IDE-specific project settings directory was found in the current working directory.'
172+ ) ;
173+ }
174+
175+ console . log ( '' ) ;
176+
177+ if ( hasVSCode ) {
178+ console . log ( bold ( 'VS Code / Cursor instructions:' ) ) ;
179+ console . log (
180+ ' 1. Ensure you have installed an IDE extension for PHP Debugging'
181+ ) ;
182+ console . log (
183+ ` (The ${ bold ( 'PHP Debug' ) } extension by ${ bold (
184+ 'Xdebug'
185+ ) } has been a solid option)`
186+ ) ;
187+ console . log (
188+ ' 2. Open the Run and Debug panel on the left sidebar'
189+ ) ;
190+ console . log (
191+ ` 3. Select "${ italic ( IDEConfigName ) } " from the dropdown`
192+ ) ;
193+ console . log ( ' 3. Click "start debugging"' ) ;
194+ console . log ( ' 5. Set a breakpoint.' ) ;
195+ console . log ( ' 6. Run your command with PHP.wasm CLI.' ) ;
196+ if ( hasPhpStorm ) {
197+ console . log ( '' ) ;
198+ }
199+ }
200+
201+ if ( hasPhpStorm ) {
202+ console . log ( bold ( 'PhpStorm instructions:' ) ) ;
203+ console . log (
204+ ` 1. Choose "${ italic (
205+ IDEConfigName
206+ ) } " debug configuration in the toolbar`
207+ ) ;
208+ console . log ( ' 2. Click the debug button (bug icon)`' ) ;
209+ console . log ( ' 3. Set a breakpoint.' ) ;
210+ console . log ( ' 4. Run your command with PHP.wasm CLI.' ) ;
211+ }
212+
213+ console . log ( '' ) ;
214+ } catch ( error ) {
215+ throw new Error ( 'Could not configure Xdebug' , {
216+ cause : error ,
217+ } ) ;
218+ }
219+ }
220+
221+ if ( hasXdebugOption && hasDevtoolsOption ) {
109222 const bridge = await startBridge ( { breakOnFirstLine : true } ) ;
110223
111224 bridge . start ( ) ;
0 commit comments