@wordpress/env 10.39.0 → 11.0.1-next.v.0

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/README.md CHANGED
@@ -498,16 +498,36 @@ Options:
498
498
  --watch Watch for logs as they happen. [boolean] [default: true]
499
499
  ```
500
500
 
501
- ### `wp-env install-path`
501
+ ### `wp-env status`
502
502
 
503
- Get the path where all of the environment files are stored. This includes the Docker files, WordPress, PHPUnit files, and any sources that were downloaded.
503
+ Get the status of the wp-env environment including whether it's running, URLs, ports, and configuration.
504
504
 
505
505
  Example:
506
506
 
507
507
  ```sh
508
- $ wp-env install-path
508
+ $ wp-env status
509
509
 
510
- /home/user/.wp-env/63263e6506becb7b8613b02d42280a49
510
+ status: running
511
+ - runtime: docker
512
+ - install path: /home/user/.wp-env/63263e6506becb7b8613b02d42280a49
513
+ - config: /home/user/my-plugin
514
+
515
+ environment:
516
+ - url: http://localhost:8888
517
+ - multisite: no
518
+ - xdebug: off
519
+ - http port: 8888
520
+ - mysql port: 13306
521
+ - test http port: 8889
522
+ ```
523
+
524
+ ```sh
525
+ $ wp-env status --help
526
+ Get the status of the wp-env environment including URLs, ports, and configuration.
527
+
528
+ Options:
529
+ --debug Enable debug output. [boolean] [default: false]
530
+ --json Output status as JSON. [boolean] [default: false]
511
531
  ```
512
532
 
513
533
  ## .wp-env.json
package/lib/cli.js CHANGED
@@ -258,10 +258,16 @@ module.exports = function cli() {
258
258
  withSpinner( env.destroy )
259
259
  );
260
260
  yargs.command(
261
- 'install-path',
262
- 'Get the path where all of the environment files are stored. This includes the Docker files, WordPress, PHPUnit files, and any sources that were downloaded.',
263
- () => {},
264
- withSpinner( env.installPath )
261
+ 'status',
262
+ 'Get the status of the wp-env environment including URLs, ports, and configuration.',
263
+ ( args ) => {
264
+ args.option( 'json', {
265
+ type: 'boolean',
266
+ describe: 'Output status as JSON.',
267
+ default: false,
268
+ } );
269
+ },
270
+ withSpinner( env.status )
265
271
  );
266
272
 
267
273
  return yargs;
@@ -8,7 +8,7 @@ const clean = require( './clean' );
8
8
  const run = require( './run' );
9
9
  const destroy = require( './destroy' );
10
10
  const logs = require( './logs' );
11
- const installPath = require( './install-path' );
11
+ const status = require( './status' );
12
12
 
13
13
  module.exports = {
14
14
  start,
@@ -17,5 +17,5 @@ module.exports = {
17
17
  run,
18
18
  destroy,
19
19
  logs,
20
- installPath,
20
+ status,
21
21
  };
@@ -0,0 +1,154 @@
1
+ 'use strict';
2
+ /**
3
+ * External dependencies
4
+ */
5
+ const path = require( 'path' );
6
+ const { existsSync } = require( 'fs' );
7
+ const chalk = require( 'chalk' );
8
+
9
+ /**
10
+ * Internal dependencies
11
+ */
12
+ const { loadConfig } = require( '../config' );
13
+ const { getRuntime, detectRuntime } = require( '../runtime' );
14
+
15
+ /**
16
+ * Check if an environment has been initialized by looking for runtime-specific files.
17
+ *
18
+ * @param {Object} config The wp-env configuration object.
19
+ * @return {boolean} True if the environment has been initialized.
20
+ */
21
+ function isEnvironmentInitialized( config ) {
22
+ // Check for Docker's docker-compose.yml
23
+ if ( existsSync( config.dockerComposeConfigPath ) ) {
24
+ return true;
25
+ }
26
+
27
+ // Check for Playground's blueprint file
28
+ const playgroundBlueprintPath = path.join(
29
+ config.workDirectoryPath,
30
+ 'playground-blueprint.json'
31
+ );
32
+ if ( existsSync( playgroundBlueprintPath ) ) {
33
+ return true;
34
+ }
35
+
36
+ return false;
37
+ }
38
+
39
+ /**
40
+ * Outputs the status of the wp-env environment.
41
+ *
42
+ * @param {Object} options
43
+ * @param {Object} options.spinner A CLI spinner which indicates progress.
44
+ * @param {boolean} options.debug True if debug mode is enabled.
45
+ * @param {boolean} options.json True to output as JSON.
46
+ */
47
+ module.exports = async function status( { spinner, debug, json } ) {
48
+ spinner.text = 'Getting environment status.';
49
+
50
+ const config = await loadConfig( path.resolve( '.' ) );
51
+
52
+ // Check if environment is initialized by looking for runtime-specific files.
53
+ // We check for these files specifically because the work directory may exist
54
+ // just from caching the WordPress version, but these files are only created
55
+ // when `wp-env start` is actually run.
56
+ if ( ! isEnvironmentInitialized( config ) ) {
57
+ spinner.stop();
58
+ if ( json ) {
59
+ console.log(
60
+ JSON.stringify( {
61
+ status: 'uninitialized',
62
+ installPath: config.workDirectoryPath,
63
+ configPath: config.configDirectoryPath,
64
+ } )
65
+ );
66
+ } else {
67
+ console.log( formatNotInitialized( config ) );
68
+ }
69
+ return;
70
+ }
71
+
72
+ // Detect and get runtime.
73
+ const runtimeName = detectRuntime( config.workDirectoryPath );
74
+ const runtime = getRuntime( runtimeName );
75
+
76
+ // Get status from runtime.
77
+ const statusData = await runtime.getStatus( config, { spinner, debug } );
78
+
79
+ spinner.stop();
80
+ if ( json ) {
81
+ console.log( JSON.stringify( statusData ) );
82
+ } else {
83
+ console.log( formatStatus( statusData ) );
84
+ }
85
+ };
86
+
87
+ /**
88
+ * Format status for human-readable output when not initialized.
89
+ *
90
+ * @param {Object} config The config object.
91
+ * @return {string} Formatted output.
92
+ */
93
+ function formatNotInitialized( config ) {
94
+ const indent = ' - ';
95
+ return `
96
+ ${ chalk.bold( 'status' ) }: ${ chalk.red( 'uninitialized' ) }
97
+ ${ indent }install path: ${ chalk.dim( config.workDirectoryPath ) }
98
+ ${ indent }config: ${ chalk.dim( config.configDirectoryPath ) }
99
+
100
+ ${ chalk.dim( 'Run `wp-env start` to initialize the environment.' ) }
101
+ `;
102
+ }
103
+
104
+ /**
105
+ * Format status data for human-readable output.
106
+ *
107
+ * @param {Object} status The status object from runtime.
108
+ * @return {string} Formatted output.
109
+ */
110
+ function formatStatus( status ) {
111
+ const statusColor = status.status === 'running' ? chalk.green : chalk.red;
112
+ const indent = ' - ';
113
+
114
+ let output = `
115
+ ${ chalk.bold( 'status' ) }: ${ statusColor( status.status ) }
116
+ ${ indent }runtime: ${ chalk.dim( status.runtime ) }
117
+ ${ indent }install path: ${ chalk.dim( status.installPath ) }
118
+ ${ indent }config: ${ chalk.dim( status.configPath ) }
119
+ `;
120
+
121
+ // Environment section.
122
+ output += `\n${ chalk.bold( 'environment' ) }:\n`;
123
+ if ( status.urls?.development ) {
124
+ output += `${ indent }url: ${ chalk.dim( status.urls.development ) }\n`;
125
+ }
126
+ output += `${ indent }multisite: ${ chalk.dim(
127
+ status.config?.multisite ? 'yes' : 'no'
128
+ ) }\n`;
129
+ output += `${ indent }xdebug: ${ chalk.dim(
130
+ status.config?.xdebug || 'off'
131
+ ) }\n`;
132
+ if ( status.ports?.development ) {
133
+ output += `${ indent }http port: ${ chalk.dim(
134
+ status.ports.development
135
+ ) }\n`;
136
+ }
137
+ if ( status.urls?.phpmyadmin ) {
138
+ output += `${ indent }phpmyadmin url: ${ chalk.dim(
139
+ status.urls.phpmyadmin
140
+ ) }\n`;
141
+ }
142
+ if ( status.ports?.mysql ) {
143
+ output += `${ indent }mysql port: ${ chalk.dim(
144
+ status.ports.mysql
145
+ ) }\n`;
146
+ }
147
+ if ( status.ports?.tests ) {
148
+ output += `${ indent }test http port: ${ chalk.dim(
149
+ status.ports.tests
150
+ ) }\n`;
151
+ }
152
+
153
+ return output;
154
+ }
@@ -577,6 +577,74 @@ class DockerRuntime {
577
577
  spinner.text = 'Finished showing logs.';
578
578
  }
579
579
 
580
+ /**
581
+ * Get the status of the Docker environment.
582
+ *
583
+ * @param {WPConfig} config The wp-env config object.
584
+ * @param {Object} options Status options.
585
+ * @param {Object} options.spinner A CLI spinner which indicates progress.
586
+ * @param {boolean} options.debug True if debug mode is enabled.
587
+ * @return {Promise<Object>} Status object with environment information.
588
+ */
589
+ async getStatus( config, { spinner, debug } ) {
590
+ spinner.text = 'Getting environment status.';
591
+
592
+ const fullConfig = await initConfig( { spinner, debug } );
593
+ const dockerComposeConfig = {
594
+ config: fullConfig.dockerComposeConfigPath,
595
+ log: debug,
596
+ };
597
+
598
+ // Check if containers are running by trying to get a port.
599
+ let isRunning = false;
600
+ let mySQLPort = null;
601
+ let phpmyadminPort = null;
602
+
603
+ try {
604
+ mySQLPort = await this._getPublicDockerPort(
605
+ 'mysql',
606
+ 3306,
607
+ dockerComposeConfig
608
+ );
609
+ isRunning = true;
610
+
611
+ if ( fullConfig.env.development.phpmyadminPort ) {
612
+ phpmyadminPort = await this._getPublicDockerPort(
613
+ 'phpmyadmin',
614
+ 80,
615
+ dockerComposeConfig
616
+ );
617
+ }
618
+ } catch {
619
+ // Containers are not running.
620
+ }
621
+
622
+ const siteUrl = fullConfig.env.development.config.WP_SITEURL;
623
+
624
+ return {
625
+ status: isRunning ? 'running' : 'stopped',
626
+ runtime: 'docker',
627
+ urls: {
628
+ development: isRunning ? siteUrl : null,
629
+ phpmyadmin:
630
+ isRunning && phpmyadminPort
631
+ ? `http://localhost:${ phpmyadminPort }`
632
+ : null,
633
+ },
634
+ ports: {
635
+ development: fullConfig.env.development.port,
636
+ tests: fullConfig.env.tests.port,
637
+ mysql: mySQLPort,
638
+ },
639
+ config: {
640
+ multisite: fullConfig.env.development.multisite,
641
+ xdebug: fullConfig.xdebug || 'off',
642
+ },
643
+ configPath: fullConfig.configDirectoryPath,
644
+ installPath: fullConfig.workDirectoryPath,
645
+ };
646
+ }
647
+
580
648
  /**
581
649
  * Runs an arbitrary command on the given Docker container.
582
650
  *
@@ -384,6 +384,56 @@ class PlaygroundRuntime {
384
384
  spinner.text = 'Cleaned WordPress Playground environment.';
385
385
  }
386
386
 
387
+ /**
388
+ * Get the status of the Playground environment.
389
+ *
390
+ * @param {Object} config The wp-env config object.
391
+ * @param {Object} options Status options.
392
+ * @param {Object} options.spinner A CLI spinner which indicates progress.
393
+ * @return {Promise<Object>} Status object with environment information.
394
+ */
395
+ async getStatus( config, { spinner } ) {
396
+ spinner.text = 'Getting environment status.';
397
+
398
+ const envConfig = config.env.development;
399
+ const port = envConfig.port || 8888;
400
+ const pidFile = path.join( config.workDirectoryPath, 'playground.pid' );
401
+
402
+ // Check if server is running.
403
+ let isRunning = false;
404
+
405
+ try {
406
+ const pidContent = await fs.readFile( pidFile, 'utf8' );
407
+ const pid = parseInt( pidContent.trim(), 10 );
408
+
409
+ // Check if process is still alive.
410
+ process.kill( pid, 0 );
411
+
412
+ // Check if server is responding.
413
+ await this._checkServer( port );
414
+ isRunning = true;
415
+ } catch {
416
+ // Process not running or server not responding.
417
+ }
418
+
419
+ return {
420
+ status: isRunning ? 'running' : 'stopped',
421
+ runtime: 'playground',
422
+ urls: {
423
+ development: isRunning ? `http://localhost:${ port }` : null,
424
+ },
425
+ ports: {
426
+ development: port,
427
+ },
428
+ config: {
429
+ multisite: envConfig.multisite,
430
+ xdebug: 'off',
431
+ },
432
+ configPath: config.configDirectoryPath,
433
+ installPath: config.workDirectoryPath,
434
+ };
435
+ }
436
+
387
437
  /**
388
438
  * Show logs from the Playground environment.
389
439
  *
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wordpress/env",
3
- "version": "10.39.0",
3
+ "version": "11.0.1-next.v.0+5aba098fc",
4
4
  "description": "A zero-config, self contained local WordPress environment for development and testing.",
5
5
  "author": "The WordPress Contributors",
6
6
  "license": "GPL-2.0-or-later",
@@ -64,5 +64,5 @@
64
64
  "scripts": {
65
65
  "test": "echo \"Error: run tests from root\" && exit 1"
66
66
  },
67
- "gitHead": "eee1cfb1472f11183e40fb77465a5f13145df7ad"
67
+ "gitHead": "d730f9e00f5462d1b9d2660632850f5f43ccff44"
68
68
  }
@@ -1,33 +0,0 @@
1
- 'use strict';
2
- /**
3
- * External dependencies
4
- */
5
- const path = require( 'path' );
6
- const { existsSync } = require( 'fs' );
7
-
8
- /**
9
- * Internal dependencies
10
- */
11
- const { loadConfig } = require( '../config' );
12
-
13
- /**
14
- * Logs the path to where wp-env files are installed.
15
- *
16
- * @param {Object} options
17
- * @param {Object} options.spinner
18
- */
19
- module.exports = async function installPath( { spinner } ) {
20
- // Stop the spinner so that stdout is not polluted.
21
- spinner.stop();
22
-
23
- const config = await loadConfig( path.resolve( '.' ) );
24
-
25
- if ( ! existsSync( config.workDirectoryPath ) ) {
26
- console.error(
27
- 'wp-env has not yet been initialized. Please run `wp-env start` first.'
28
- );
29
- process.exit( 1 );
30
- }
31
-
32
- console.log( config.workDirectoryPath );
33
- };