@wordpress/env 10.39.0 → 11.0.1-next.v.20260206T143.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
@@ -186,7 +186,7 @@ To reset the database:
186
186
  **⚠️ WARNING: This will permanently delete any posts, pages, media, etc. in the local WordPress installation.**
187
187
 
188
188
  ```sh
189
- $ wp-env clean all
189
+ $ wp-env reset all
190
190
  $ wp-env start
191
191
  ```
192
192
 
@@ -340,15 +340,15 @@ Options:
340
340
  --debug Enable debug output. [boolean] [default: false]
341
341
  ```
342
342
 
343
- ### `wp-env clean [environment]`
343
+ ### `wp-env reset [environment]`
344
344
 
345
345
  ```sh
346
- wp-env clean [environment]
346
+ wp-env reset [environment]
347
347
 
348
- Cleans the WordPress databases.
348
+ Resets the WordPress databases.
349
349
 
350
350
  Positionals:
351
- environment Which environments' databases to clean.
351
+ environment Which environments' databases to reset.
352
352
  [string] [choices: "all", "development", "tests"] [default: "tests"]
353
353
 
354
354
  Options:
@@ -469,17 +469,32 @@ To set the permalink to the year, month, and post name:
469
469
  wp-env run cli "wp rewrite structure /%year%/%monthnum%/%postname%/"
470
470
  ```
471
471
 
472
+ ### `wp-env cleanup`
473
+
474
+ ```sh
475
+ wp-env cleanup
476
+
477
+ Cleanup the WordPress environment. Removes docker containers, volumes, networks,
478
+ and local files, but preserves docker images for faster re-starts.
479
+
480
+ Options:
481
+ --debug Enable debug output. [boolean] [default: false]
482
+ --scripts Execute any configured lifecycle scripts. [boolean] [default: true]
483
+ --force Skip the confirmation prompt. [boolean] [default: false]
484
+ ```
485
+
472
486
  ### `wp-env destroy`
473
487
 
474
488
  ```sh
475
489
  wp-env destroy
476
490
 
477
- Destroy the WordPress environment. Deletes docker containers, volumes, and
478
- networks associated with the WordPress environment and removes local files.
491
+ Destroy the WordPress environment. Deletes docker containers, volumes, networks,
492
+ and images associated with the WordPress environment and removes local files.
479
493
 
480
494
  Options:
481
495
  --debug Enable debug output. [boolean] [default: false]
482
496
  --scripts Execute any configured lifecycle scripts. [boolean] [default: true]
497
+ --force Skip the confirmation prompt. [boolean] [default: false]
483
498
  ```
484
499
 
485
500
  ### `wp-env logs [environment]`
@@ -498,16 +513,36 @@ Options:
498
513
  --watch Watch for logs as they happen. [boolean] [default: true]
499
514
  ```
500
515
 
501
- ### `wp-env install-path`
516
+ ### `wp-env status`
502
517
 
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.
518
+ Get the status of the wp-env environment including whether it's running, URLs, ports, and configuration.
504
519
 
505
520
  Example:
506
521
 
507
522
  ```sh
508
- $ wp-env install-path
523
+ $ wp-env status
524
+
525
+ status: running
526
+ - runtime: docker
527
+ - install path: /home/user/.wp-env/63263e6506becb7b8613b02d42280a49
528
+ - config: /home/user/my-plugin
529
+
530
+ environment:
531
+ - url: http://localhost:8888
532
+ - multisite: no
533
+ - xdebug: off
534
+ - http port: 8888
535
+ - mysql port: 13306
536
+ - test http port: 8889
537
+ ```
509
538
 
510
- /home/user/.wp-env/63263e6506becb7b8613b02d42280a49
539
+ ```sh
540
+ $ wp-env status --help
541
+ Get the status of the wp-env environment including URLs, ports, and configuration.
542
+
543
+ Options:
544
+ --debug Enable debug output. [boolean] [default: false]
545
+ --json Output status as JSON. [boolean] [default: false]
511
546
  ```
512
547
 
513
548
  ## .wp-env.json
@@ -609,7 +644,8 @@ example, `WP_ENV_LIFECYCLE_SCRIPT_AFTER_START`. Keep in mind that these will be
609
644
  build won't break on subsequent executions.
610
645
 
611
646
  * `afterStart`: Runs after `wp-env start` has finished setting up the environment.
612
- * `afterClean`: Runs after `wp-env clean` has finished cleaning the environment.
647
+ * `afterReset`: Runs after `wp-env reset` has finished resetting the environment.
648
+ * `afterCleanup`: Runs after `wp-env cleanup` has cleaned up the environment.
613
649
  * `afterDestroy`: Runs after `wp-env destroy` has destroyed the environment.
614
650
 
615
651
  ## Examples
@@ -749,7 +785,7 @@ You can tell `wp-env` to use a specific PHP version for compatibility and testin
749
785
 
750
786
  ### Multisite support
751
787
 
752
- You can tell `wp-env` if the site should be multisite enabled. This can also be set via the environment variable `WP_ENV_MULTISITE`.
788
+ You can tell `wp-env` if the site should be multisite enabled.
753
789
 
754
790
  ```json
755
791
  {
package/lib/cli.js CHANGED
@@ -18,6 +18,7 @@ const {
18
18
  getAvailableRuntimes,
19
19
  getRuntime,
20
20
  UnsupportedCommandError,
21
+ EnvironmentNotInitializedError,
21
22
  } = require( './runtime' );
22
23
 
23
24
  // Colors.
@@ -45,8 +46,11 @@ const withSpinner =
45
46
  process.exit( 0 );
46
47
  },
47
48
  ( error ) => {
48
- if ( error instanceof UnsupportedCommandError ) {
49
- // Error is an unsupported command in the current runtime.
49
+ if (
50
+ error instanceof UnsupportedCommandError ||
51
+ error instanceof EnvironmentNotInitializedError
52
+ ) {
53
+ // Error is a known user-facing error.
50
54
  spinner.fail( error.message );
51
55
  process.exit( 1 );
52
56
  } else if (
@@ -162,13 +166,31 @@ module.exports = function cli() {
162
166
  () => {},
163
167
  withSpinner( env.stop )
164
168
  );
169
+ yargs.command(
170
+ 'reset [environment]',
171
+ wpYellow( 'Resets the WordPress databases.' ),
172
+ ( args ) => {
173
+ args.positional( 'environment', {
174
+ type: 'string',
175
+ describe: "Which environments' databases to reset.",
176
+ choices: [ 'all', 'development', 'tests' ],
177
+ default: 'tests',
178
+ } );
179
+ args.option( 'scripts', {
180
+ type: 'boolean',
181
+ describe: 'Execute any configured lifecycle scripts.',
182
+ default: true,
183
+ } );
184
+ },
185
+ withSpinner( env.reset )
186
+ );
165
187
  yargs.command(
166
188
  'clean [environment]',
167
- wpYellow( 'Cleans the WordPress databases.' ),
189
+ chalk.gray( '[Deprecated: use reset] Resets the WordPress databases.' ),
168
190
  ( args ) => {
169
191
  args.positional( 'environment', {
170
192
  type: 'string',
171
- describe: "Which environments' databases to clean.",
193
+ describe: "Which environments' databases to reset.",
172
194
  choices: [ 'all', 'development', 'tests' ],
173
195
  default: 'tests',
174
196
  } );
@@ -246,7 +268,7 @@ module.exports = function cli() {
246
268
  yargs.command(
247
269
  'destroy',
248
270
  wpRed(
249
- 'Destroy the WordPress environment. Deletes docker containers, volumes, and networks associated with the WordPress environment and removes local files.'
271
+ 'Destroy the WordPress environment. Deletes docker containers, volumes, networks, and images associated with the WordPress environment and removes local files.'
250
272
  ),
251
273
  ( args ) => {
252
274
  args.option( 'scripts', {
@@ -254,14 +276,44 @@ module.exports = function cli() {
254
276
  describe: 'Execute any configured lifecycle scripts.',
255
277
  default: true,
256
278
  } );
279
+ args.option( 'force', {
280
+ type: 'boolean',
281
+ describe: 'Skip the confirmation prompt.',
282
+ default: false,
283
+ } );
257
284
  },
258
285
  withSpinner( env.destroy )
259
286
  );
260
287
  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 )
288
+ 'cleanup',
289
+ wpYellow(
290
+ 'Cleanup the WordPress environment. Removes docker containers, volumes, networks, and local files, but preserves docker images for faster re-starts.'
291
+ ),
292
+ ( args ) => {
293
+ args.option( 'scripts', {
294
+ type: 'boolean',
295
+ describe: 'Execute any configured lifecycle scripts.',
296
+ default: true,
297
+ } );
298
+ args.option( 'force', {
299
+ type: 'boolean',
300
+ describe: 'Skip the confirmation prompt.',
301
+ default: false,
302
+ } );
303
+ },
304
+ withSpinner( env.cleanup )
305
+ );
306
+ yargs.command(
307
+ 'status',
308
+ 'Get the status of the wp-env environment including URLs, ports, and configuration.',
309
+ ( args ) => {
310
+ args.option( 'json', {
311
+ type: 'boolean',
312
+ describe: 'Output status as JSON.',
313
+ default: false,
314
+ } );
315
+ },
316
+ withSpinner( env.status )
265
317
  );
266
318
 
267
319
  return yargs;
@@ -17,10 +17,12 @@ const { getRuntime, detectRuntime } = require( '../runtime' );
17
17
  */
18
18
 
19
19
  /**
20
- * Wipes the development server's database, the tests server's database, or both.
20
+ * @deprecated Use `reset` instead.
21
+ *
22
+ * Resets the development server's database, the tests server's database, or both.
21
23
  *
22
24
  * @param {Object} options
23
- * @param {WPEnvironmentSelection} options.environment The environment to clean. Either 'development', 'tests', or 'all'.
25
+ * @param {WPEnvironmentSelection} options.environment The environment to reset. Either 'development', 'tests', or 'all'.
24
26
  * @param {Object} options.spinner A CLI spinner which indicates progress.
25
27
  * @param {boolean} options.scripts Indicates whether or not lifecycle scripts should be executed.
26
28
  * @param {boolean} options.debug True if debug mode is enabled.
@@ -31,11 +33,16 @@ module.exports = async function clean( {
31
33
  scripts,
32
34
  debug,
33
35
  } ) {
36
+ spinner.warn( 'The `clean` command is deprecated. Use `reset` instead.' );
37
+
34
38
  const config = await loadConfig( path.resolve( '.' ) );
35
- const runtime = getRuntime( detectRuntime( config.workDirectoryPath ) );
39
+ const runtime = getRuntime(
40
+ await detectRuntime( config.workDirectoryPath )
41
+ );
36
42
 
37
43
  await runtime.clean( config, { environment, spinner, debug } );
38
44
 
45
+ // Execute afterClean for backwards compatibility.
39
46
  if ( scripts ) {
40
47
  await executeLifecycleScript( 'afterClean', config, spinner );
41
48
  }
@@ -0,0 +1,70 @@
1
+ 'use strict';
2
+ /**
3
+ * External dependencies
4
+ */
5
+ const fs = require( 'fs' ).promises;
6
+ const path = require( 'path' );
7
+ const { confirm } = require( '@inquirer/prompts' );
8
+
9
+ /**
10
+ * Internal dependencies
11
+ */
12
+ const { loadConfig } = require( '../config' );
13
+ const { executeLifecycleScript } = require( '../execute-lifecycle-script' );
14
+ const { getRuntime, detectRuntime } = require( '../runtime' );
15
+
16
+ /**
17
+ * Cleanup the development server.
18
+ *
19
+ * Removes Docker containers, volumes, networks, and local files,
20
+ * but preserves Docker images for faster re-starts.
21
+ *
22
+ * @param {Object} options
23
+ * @param {Object} options.spinner A CLI spinner which indicates progress.
24
+ * @param {boolean} options.scripts Indicates whether or not lifecycle scripts should be executed.
25
+ * @param {boolean} options.force If true, skips the confirmation prompt.
26
+ * @param {boolean} options.debug True if debug mode is enabled.
27
+ */
28
+ module.exports = async function cleanup( { spinner, scripts, force, debug } ) {
29
+ const config = await loadConfig( path.resolve( '.' ) );
30
+
31
+ try {
32
+ await fs.readdir( config.workDirectoryPath );
33
+ } catch {
34
+ spinner.text = 'Could not find any files to remove.';
35
+ return;
36
+ }
37
+
38
+ const runtime = getRuntime( detectRuntime( config.workDirectoryPath ) );
39
+
40
+ spinner.info( runtime.getCleanupWarningMessage() );
41
+
42
+ let yesDelete = force;
43
+ if ( ! force ) {
44
+ try {
45
+ yesDelete = await confirm( {
46
+ message: 'Are you sure you want to continue?',
47
+ default: false,
48
+ } );
49
+ } catch ( error ) {
50
+ if ( error.name === 'ExitPromptError' ) {
51
+ console.log( 'Cancelled.' );
52
+ process.exit( 1 );
53
+ }
54
+ throw error;
55
+ }
56
+ }
57
+
58
+ spinner.start();
59
+
60
+ if ( ! yesDelete ) {
61
+ spinner.text = 'Cancelled.';
62
+ return;
63
+ }
64
+
65
+ await runtime.cleanup( config, { spinner, debug } );
66
+
67
+ if ( scripts ) {
68
+ await executeLifecycleScript( 'afterCleanup', config, spinner );
69
+ }
70
+ };
@@ -19,9 +19,10 @@ const { getRuntime, detectRuntime } = require( '../runtime' );
19
19
  * @param {Object} options
20
20
  * @param {Object} options.spinner A CLI spinner which indicates progress.
21
21
  * @param {boolean} options.scripts Indicates whether or not lifecycle scripts should be executed.
22
+ * @param {boolean} options.force If true, skips the confirmation prompt.
22
23
  * @param {boolean} options.debug True if debug mode is enabled.
23
24
  */
24
- module.exports = async function destroy( { spinner, scripts, debug } ) {
25
+ module.exports = async function destroy( { spinner, scripts, force, debug } ) {
25
26
  const config = await loadConfig( path.resolve( '.' ) );
26
27
 
27
28
  try {
@@ -31,22 +32,26 @@ module.exports = async function destroy( { spinner, scripts, debug } ) {
31
32
  return;
32
33
  }
33
34
 
34
- const runtime = getRuntime( detectRuntime( config.workDirectoryPath ) );
35
+ const runtime = getRuntime(
36
+ await detectRuntime( config.workDirectoryPath )
37
+ );
35
38
 
36
39
  spinner.info( runtime.getDestroyWarningMessage() );
37
40
 
38
- let yesDelete = false;
39
- try {
40
- yesDelete = await confirm( {
41
- message: 'Are you sure you want to continue?',
42
- default: false,
43
- } );
44
- } catch ( error ) {
45
- if ( error.name === 'ExitPromptError' ) {
46
- console.log( 'Cancelled.' );
47
- process.exit( 1 );
41
+ let yesDelete = force;
42
+ if ( ! force ) {
43
+ try {
44
+ yesDelete = await confirm( {
45
+ message: 'Are you sure you want to continue?',
46
+ default: false,
47
+ } );
48
+ } catch ( error ) {
49
+ if ( error.name === 'ExitPromptError' ) {
50
+ console.log( 'Cancelled.' );
51
+ process.exit( 1 );
52
+ }
53
+ throw error;
48
54
  }
49
- throw error;
50
55
  }
51
56
 
52
57
  spinner.start();
@@ -4,18 +4,22 @@
4
4
  */
5
5
  const start = require( './start' );
6
6
  const stop = require( './stop' );
7
+ const reset = require( './reset' );
7
8
  const clean = require( './clean' );
8
9
  const run = require( './run' );
9
10
  const destroy = require( './destroy' );
11
+ const cleanup = require( './cleanup' );
10
12
  const logs = require( './logs' );
11
- const installPath = require( './install-path' );
13
+ const status = require( './status' );
12
14
 
13
15
  module.exports = {
14
16
  start,
15
17
  stop,
18
+ reset,
16
19
  clean,
17
20
  run,
18
21
  destroy,
22
+ cleanup,
19
23
  logs,
20
- installPath,
24
+ status,
21
25
  };
@@ -21,6 +21,8 @@ const { getRuntime, detectRuntime } = require( '../runtime' );
21
21
  */
22
22
  module.exports = async function logs( { environment, watch, spinner, debug } ) {
23
23
  const config = await loadConfig( path.resolve( '.' ) );
24
- const runtime = getRuntime( detectRuntime( config.workDirectoryPath ) );
24
+ const runtime = getRuntime(
25
+ await detectRuntime( config.workDirectoryPath )
26
+ );
25
27
  await runtime.logs( config, { environment, watch, spinner, debug } );
26
28
  };
@@ -0,0 +1,42 @@
1
+ 'use strict';
2
+ /**
3
+ * External dependencies
4
+ */
5
+ const path = require( 'path' );
6
+
7
+ /**
8
+ * Internal dependencies
9
+ */
10
+ const { executeLifecycleScript } = require( '../execute-lifecycle-script' );
11
+ const { loadConfig } = require( '../config' );
12
+ const { getRuntime, detectRuntime } = require( '../runtime' );
13
+
14
+ /**
15
+ * @typedef {import('../wordpress').WPEnvironment} WPEnvironment
16
+ * @typedef {import('../wordpress').WPEnvironmentSelection} WPEnvironmentSelection
17
+ */
18
+
19
+ /**
20
+ * Resets the development server's database, the tests server's database, or both.
21
+ *
22
+ * @param {Object} options
23
+ * @param {WPEnvironmentSelection} options.environment The environment to reset. Either 'development', 'tests', or 'all'.
24
+ * @param {Object} options.spinner A CLI spinner which indicates progress.
25
+ * @param {boolean} options.scripts Indicates whether or not lifecycle scripts should be executed.
26
+ * @param {boolean} options.debug True if debug mode is enabled.
27
+ */
28
+ module.exports = async function reset( {
29
+ environment,
30
+ spinner,
31
+ scripts,
32
+ debug,
33
+ } ) {
34
+ const config = await loadConfig( path.resolve( '.' ) );
35
+ const runtime = getRuntime( detectRuntime( config.workDirectoryPath ) );
36
+
37
+ await runtime.clean( config, { environment, spinner, debug } );
38
+
39
+ if ( scripts ) {
40
+ await executeLifecycleScript( 'afterReset', config, spinner );
41
+ }
42
+ };
@@ -30,7 +30,9 @@ module.exports = async function run( {
30
30
  debug,
31
31
  } ) {
32
32
  const config = await loadConfig( path.resolve( '.' ) );
33
- const runtime = getRuntime( detectRuntime( config.workDirectoryPath ) );
33
+ const runtime = getRuntime(
34
+ await detectRuntime( config.workDirectoryPath )
35
+ );
34
36
 
35
37
  // Include any double dashed arguments in the command so that we can pass them to Docker.
36
38
  // This lets users pass options that the command defines without them being parsed.
@@ -12,7 +12,7 @@ const { rimraf } = require( 'rimraf' );
12
12
  */
13
13
  const { loadConfig } = require( '../config' );
14
14
  const { executeLifecycleScript } = require( '../execute-lifecycle-script' );
15
- const { getRuntime } = require( '../runtime' );
15
+ const { getRuntime, getSavedRuntime, saveRuntime } = require( '../runtime' );
16
16
 
17
17
  /**
18
18
  * @typedef {import('../config').WPConfig} WPConfig
@@ -51,6 +51,38 @@ module.exports = async function start( {
51
51
  const config = await loadConfig( path.resolve( '.' ) );
52
52
  config.debug = debug;
53
53
 
54
+ // Check if switching runtimes and prompt user to destroy old environment first.
55
+ const savedRuntime = await getSavedRuntime( config.workDirectoryPath );
56
+ if ( savedRuntime && savedRuntime !== runtimeName ) {
57
+ spinner.stop();
58
+ let shouldDestroy = false;
59
+ try {
60
+ shouldDestroy = await confirm( {
61
+ message: `Environment was previously started with '${ savedRuntime }' runtime. Destroy it and start with '${ runtimeName }'?`,
62
+ default: true,
63
+ } );
64
+ } catch ( error ) {
65
+ if ( error.name === 'ExitPromptError' ) {
66
+ console.log( 'Cancelled.' );
67
+ process.exit( 1 );
68
+ }
69
+ throw error;
70
+ }
71
+
72
+ if ( ! shouldDestroy ) {
73
+ spinner.fail(
74
+ `Aborted. Run 'wp-env destroy' manually or start with '--runtime=${ savedRuntime }'.`
75
+ );
76
+ process.exit( 1 );
77
+ }
78
+
79
+ // User confirmed - destroy old runtime first.
80
+ spinner.start();
81
+ spinner.text = `Destroying previous ${ savedRuntime } environment.`;
82
+ const oldRuntime = getRuntime( savedRuntime );
83
+ await oldRuntime.destroy( config, { spinner } );
84
+ }
85
+
54
86
  if ( ! config.detectedLocalConfig ) {
55
87
  const { configDirectoryPath } = config;
56
88
  spinner.warn(
@@ -76,6 +108,9 @@ module.exports = async function start( {
76
108
  spx,
77
109
  debug,
78
110
  } );
111
+
112
+ // Save the runtime type after successful start.
113
+ await saveRuntime( runtimeName, config.workDirectoryPath );
79
114
  } catch ( error ) {
80
115
  // Attempt to stop any partially-started environment so that
81
116
  // processes do not linger after a failed start.