@wordpress/env 6.0.0 → 7.0.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.
Files changed (54) hide show
  1. package/README.md +109 -43
  2. package/lib/build-docker-compose-config.js +67 -96
  3. package/lib/cache.js +1 -0
  4. package/lib/cli.js +16 -3
  5. package/lib/commands/clean.js +14 -1
  6. package/lib/commands/destroy.js +12 -37
  7. package/lib/commands/index.js +1 -0
  8. package/lib/commands/install-path.js +1 -0
  9. package/lib/commands/logs.js +1 -0
  10. package/lib/commands/run.js +59 -3
  11. package/lib/commands/start.js +30 -8
  12. package/lib/commands/stop.js +1 -0
  13. package/lib/config/add-or-replace-port.js +12 -3
  14. package/lib/config/db-env.js +1 -0
  15. package/lib/config/detect-directory-type.js +1 -1
  16. package/lib/config/get-cache-directory.js +39 -0
  17. package/lib/config/get-config-from-environment-vars.js +86 -0
  18. package/lib/config/index.js +7 -5
  19. package/lib/config/load-config.js +92 -0
  20. package/lib/config/merge-configs.js +104 -0
  21. package/lib/config/parse-config.js +418 -157
  22. package/lib/config/parse-source-string.js +164 -0
  23. package/lib/config/post-process-config.js +202 -0
  24. package/lib/config/read-raw-config-file.js +7 -33
  25. package/lib/config/test/__snapshots__/config-integration.js.snap +271 -0
  26. package/lib/config/test/add-or-replace-port.js +29 -1
  27. package/lib/config/test/config-integration.js +143 -0
  28. package/lib/config/test/get-cache-directory.js +57 -0
  29. package/lib/config/test/merge-configs.js +111 -0
  30. package/lib/config/test/parse-config.js +342 -0
  31. package/lib/config/test/parse-source-string.js +154 -0
  32. package/lib/config/test/post-process-config.js +295 -0
  33. package/lib/config/test/read-raw-config-file.js +19 -63
  34. package/lib/config/test/validate-config.js +305 -0
  35. package/lib/config/validate-config.js +93 -54
  36. package/lib/env.js +2 -0
  37. package/lib/execute-after-setup.js +51 -0
  38. package/lib/get-host-user.js +31 -0
  39. package/lib/init-config.js +181 -63
  40. package/lib/md5.js +1 -0
  41. package/lib/parse-xdebug-mode.js +1 -0
  42. package/lib/retry.js +1 -0
  43. package/lib/test/__snapshots__/md5.js.snap +9 -0
  44. package/lib/test/build-docker-compose-config.js +134 -0
  45. package/lib/test/cache.js +154 -0
  46. package/lib/test/cli.js +149 -0
  47. package/lib/test/execute-after-setup.js +66 -0
  48. package/lib/test/md5.js +35 -0
  49. package/lib/test/parse-xdebug-mode.js +41 -0
  50. package/lib/wordpress.js +4 -19
  51. package/package.json +2 -2
  52. package/lib/config/config.js +0 -353
  53. package/lib/config/test/__snapshots__/config.js.snap +0 -83
  54. package/lib/config/test/config.js +0 -1241
@@ -1,353 +0,0 @@
1
- 'use strict';
2
- /**
3
- * External dependencies
4
- */
5
- const fs = require( 'fs' ).promises;
6
- const path = require( 'path' );
7
- const os = require( 'os' );
8
-
9
- /**
10
- * Internal dependencies
11
- */
12
- const detectDirectoryType = require( './detect-directory-type' );
13
- const { validateConfig, ValidationError } = require( './validate-config' );
14
- const readRawConfigFile = require( './read-raw-config-file' );
15
- const parseConfig = require( './parse-config' );
16
- const { includeTestsPath, parseSourceString } = parseConfig;
17
- const addOrReplacePort = require( './add-or-replace-port' );
18
- const md5 = require( '../md5' );
19
-
20
- /**
21
- * wp-env configuration.
22
- *
23
- * @typedef WPConfig
24
- * @property {string} name Name of the environment.
25
- * @property {string} configDirectoryPath Path to the .wp-env.json file.
26
- * @property {string} workDirectoryPath Path to the work directory located in ~/.wp-env.
27
- * @property {string} dockerComposeConfigPath Path to the docker-compose.yml file.
28
- * @property {boolean} detectedLocalConfig If true, wp-env detected local config and used it.
29
- * @property {Object.<string, WPServiceConfig>} env Specific config for different environments.
30
- * @property {boolean} debug True if debug mode is enabled.
31
- */
32
-
33
- /**
34
- * Base-level config for any particular environment. (development/tests/etc)
35
- *
36
- * @typedef WPServiceConfig
37
- * @property {WPSource} coreSource The WordPress installation to load in the environment.
38
- * @property {WPSource[]} pluginSources Plugins to load in the environment.
39
- * @property {WPSource[]} themeSources Themes to load in the environment.
40
- * @property {number} port The port to use.
41
- * @property {Object} config Mapping of wp-config.php constants to their desired values.
42
- * @property {Object.<string, WPSource>} mappings Mapping of WordPress directories to local directories which should be mounted.
43
- * @property {string} phpVersion Version of PHP to use in the environments, of the format 0.0.
44
- */
45
-
46
- /**
47
- * A WordPress installation, plugin or theme to be loaded into the environment.
48
- *
49
- * @typedef WPSource
50
- * @property {'local'|'git'|'zip'} type The source type.
51
- * @property {string} path The path to the WordPress installation, plugin or theme.
52
- * @property {?string} url The URL to the source download if the source type is not local.
53
- * @property {?string} ref The git ref for the source if the source type is 'git'.
54
- * @property {string} basename Name that identifies the WordPress installation, plugin or theme.
55
- */
56
-
57
- /**
58
- * Reads, parses, and validates the given .wp-env.json file into a wp-env config
59
- * object for internal use.
60
- *
61
- * @param {string} configPath Path to the .wp-env.json file.
62
- *
63
- * @return {WPConfig} A parsed and validated wp-env config object.
64
- */
65
- module.exports = async function readConfig( configPath ) {
66
- const configDirectoryPath = path.dirname( configPath );
67
- const workDirectoryPath = path.resolve(
68
- await getHomeDirectory(),
69
- md5( configPath )
70
- );
71
-
72
- // The specified base configuration from .wp-env.json or from the local
73
- // source type which was automatically detected.
74
- const baseConfig =
75
- ( await readRawConfigFile( '.wp-env.json', configPath ) ) ||
76
- ( await getDefaultBaseConfig( configPath ) );
77
-
78
- // Overriden .wp-env.json on a per-user case.
79
- const overrideConfig =
80
- ( await readRawConfigFile(
81
- '.wp-env.override.json',
82
- configPath.replace( /\.wp-env\.json$/, '.wp-env.override.json' )
83
- ) ) || {};
84
-
85
- const detectedLocalConfig =
86
- Object.keys( { ...baseConfig, ...overrideConfig } ).length > 0;
87
-
88
- // Default configuration which is overridden by .wp-env.json files.
89
- const defaultConfiguration = {
90
- core: null, // Indicates that the latest stable version should ultimately be used.
91
- phpVersion: null,
92
- plugins: [],
93
- themes: [],
94
- port: 8888,
95
- mappings: {},
96
- config: {
97
- WP_DEBUG: true,
98
- SCRIPT_DEBUG: true,
99
- WP_ENVIRONMENT_TYPE: 'local',
100
- WP_PHP_BINARY: 'php',
101
- WP_TESTS_EMAIL: 'admin@example.org',
102
- WP_TESTS_TITLE: 'Test Blog',
103
- WP_TESTS_DOMAIN: 'localhost',
104
- WP_SITEURL: 'http://localhost',
105
- WP_HOME: 'http://localhost',
106
- },
107
- env: {
108
- development: {}, // No overrides needed, but it should exist.
109
- tests: {
110
- config: { WP_DEBUG: false, SCRIPT_DEBUG: false },
111
- port: 8889,
112
- },
113
- },
114
- };
115
-
116
- // A quick validation before merging on a service by service level allows us
117
- // to check the root configuration options and provide more helpful errors.
118
- validateConfig(
119
- mergeWpServiceConfigs( [
120
- defaultConfiguration,
121
- baseConfig,
122
- overrideConfig,
123
- ] )
124
- );
125
-
126
- // A unique array of the environments specified in the config options.
127
- // Needed so that we can override settings per-environment, rather than
128
- // overwriting each environment key.
129
- const getEnvKeys = ( config ) => Object.keys( config.env || {} );
130
- const allEnvs = [
131
- ...new Set( [
132
- ...getEnvKeys( defaultConfiguration ),
133
- ...getEnvKeys( baseConfig ),
134
- ...getEnvKeys( overrideConfig ),
135
- ] ),
136
- ];
137
-
138
- // Returns a pair with the root config options and the specific environment config options.
139
- const getEnvConfig = ( config, envName ) => [
140
- config,
141
- config.env && config.env[ envName ] ? config.env[ envName ] : {},
142
- ];
143
-
144
- // Merge each of the specified environment-level overrides.
145
- const allPorts = new Set(); // Keep track of unique ports for validation.
146
- const env = {};
147
- for ( const envName of allEnvs ) {
148
- env[ envName ] = await parseConfig(
149
- validateConfig(
150
- mergeWpServiceConfigs( [
151
- ...getEnvConfig( defaultConfiguration, envName ),
152
- ...getEnvConfig( baseConfig, envName ),
153
- ...getEnvConfig( overrideConfig, envName ),
154
- ] ),
155
- envName
156
- ),
157
- { workDirectoryPath }
158
- );
159
- allPorts.add( env[ envName ].port );
160
- }
161
-
162
- if ( allPorts.size !== allEnvs.length ) {
163
- throw new ValidationError(
164
- 'Invalid .wp-env.json: Each port value must be unique.'
165
- );
166
- }
167
-
168
- return withOverrides( {
169
- name: path.basename( configDirectoryPath ),
170
- dockerComposeConfigPath: path.resolve(
171
- workDirectoryPath,
172
- 'docker-compose.yml'
173
- ),
174
- configDirectoryPath,
175
- workDirectoryPath,
176
- detectedLocalConfig,
177
- env,
178
- } );
179
- };
180
-
181
- /**
182
- * Deep-merges the values in the given service environment. This allows us to
183
- * merge the wp-config.php values instead of overwriting them. Note that this
184
- * merges configs before they have been validated, so the passed config shape
185
- * will not match the WPServiceConfig type.
186
- *
187
- * @param {Object[]} configs Array of raw service config objects to merge.
188
- *
189
- * @return {Object} The merged configuration object.
190
- */
191
- function mergeWpServiceConfigs( configs ) {
192
- // Returns an array of nested values in the config object. For example,
193
- // an array of all the wp-config objects.
194
- const mergeNestedObjs = ( key ) =>
195
- Object.assign(
196
- {},
197
- ...configs.map( ( config ) => {
198
- if ( ! config[ key ] ) {
199
- return {};
200
- } else if ( typeof config[ key ] === 'object' ) {
201
- return config[ key ];
202
- }
203
- throw new ValidationError(
204
- `Invalid .wp-env.json: "${ key }" must be an object.`
205
- );
206
- } )
207
- );
208
-
209
- const mergedConfig = {
210
- ...Object.assign( {}, ...configs ),
211
- config: mergeNestedObjs( 'config' ),
212
- mappings: mergeNestedObjs( 'mappings' ),
213
- };
214
-
215
- delete mergedConfig.env;
216
- return mergedConfig;
217
- }
218
-
219
- /**
220
- * Detects basic config options to use if the .wp-env.json config file does not
221
- * exist. For example, if the local directory contains a plugin, that will be
222
- * added to the default plugin sources.
223
- *
224
- * @param {string} configPath A path to the config file for the source to detect.
225
- * @return {Object} Basic config options for the detected source type. Empty
226
- * object if no config detected.
227
- */
228
- async function getDefaultBaseConfig( configPath ) {
229
- const configDirectoryPath = path.dirname( configPath );
230
- const type = await detectDirectoryType( configDirectoryPath );
231
-
232
- if ( type === 'core' ) {
233
- return { core: '.' };
234
- } else if ( type === 'plugin' ) {
235
- return { plugins: [ '.' ] };
236
- } else if ( type === 'theme' ) {
237
- return { themes: [ '.' ] };
238
- }
239
-
240
- return {};
241
- }
242
-
243
- /**
244
- * Overrides keys in the config object with set environment variables or options
245
- * which should be merged.
246
- *
247
- * @param {WPConfig} config fully parsed configuration object.
248
- * @return {WPConfig} configuration object with overrides applied.
249
- */
250
- function withOverrides( config ) {
251
- const workDirectoryPath = config.workDirectoryPath;
252
- // Override port numbers with environment variables.
253
- config.env.development.port =
254
- getNumberFromEnvVariable( 'WP_ENV_PORT' ) ||
255
- config.env.development.port;
256
- config.env.tests.port =
257
- getNumberFromEnvVariable( 'WP_ENV_TESTS_PORT' ) ||
258
- config.env.tests.port;
259
-
260
- // Override WordPress core with environment variable.
261
- if ( process.env.WP_ENV_CORE ) {
262
- const coreSource = includeTestsPath(
263
- parseSourceString( process.env.WP_ENV_CORE, { workDirectoryPath } ),
264
- { workDirectoryPath }
265
- );
266
- config.env.development.coreSource = coreSource;
267
- config.env.tests.coreSource = coreSource;
268
- }
269
-
270
- // Override PHP version with environment variable.
271
- config.env.development.phpVersion =
272
- process.env.WP_ENV_PHP_VERSION || config.env.development.phpVersion;
273
- config.env.tests.phpVersion =
274
- process.env.WP_ENV_PHP_VERSION || config.env.tests.phpVersion;
275
-
276
- // Some of our configuration options need to have the port added to them.
277
- const addConfigPort = ( configKey ) => {
278
- // Don't replace the port if one is set in WP_HOME.
279
- const replace = configKey !== 'WP_HOME';
280
-
281
- config.env.development.config[ configKey ] = addOrReplacePort(
282
- config.env.development.config[ configKey ],
283
- config.env.development.port,
284
- replace
285
- );
286
- config.env.tests.config[ configKey ] = addOrReplacePort(
287
- config.env.tests.config[ configKey ],
288
- config.env.tests.port,
289
- replace
290
- );
291
- };
292
- addConfigPort( 'WP_TESTS_DOMAIN' );
293
- addConfigPort( 'WP_SITEURL' );
294
- addConfigPort( 'WP_HOME' );
295
-
296
- return config;
297
- }
298
-
299
- /**
300
- * Parses an environment variable which should be a number.
301
- *
302
- * Throws an error if the variable cannot be parsed to a number.
303
- * Returns null if the environment variable has not been specified.
304
- *
305
- * @param {string} varName The environment variable to check (e.g. WP_ENV_PORT).
306
- * @return {null|number} The number. Null if it does not exist.
307
- */
308
- function getNumberFromEnvVariable( varName ) {
309
- // Allow use of the default if it does not exist.
310
- if ( ! process.env[ varName ] ) {
311
- return null;
312
- }
313
-
314
- const maybeNumber = parseInt( process.env[ varName ] );
315
-
316
- // Throw an error if it is not parseable as a number.
317
- if ( isNaN( maybeNumber ) ) {
318
- throw new ValidationError(
319
- `Invalid environment variable: ${ varName } must be a number.`
320
- );
321
- }
322
-
323
- return maybeNumber;
324
- }
325
-
326
- /**
327
- * Gets the `wp-env` home directory in which generated files are created.
328
- *
329
- * By default: '~/.wp-env/'. On Linux with snap packages: '~/wp-env/'. Can be
330
- * overridden with the WP_ENV_HOME environment variable.
331
- *
332
- * @return {Promise<string>} The absolute path to the `wp-env` home directory.
333
- */
334
- async function getHomeDirectory() {
335
- // Allow user to override download location.
336
- if ( process.env.WP_ENV_HOME ) {
337
- return path.resolve( process.env.WP_ENV_HOME );
338
- }
339
-
340
- /**
341
- * Installing docker with Snap Packages on Linux is common, but does not
342
- * support hidden directories. Therefore we use a public directory when
343
- * snap packages exist.
344
- *
345
- * @see https://github.com/WordPress/gutenberg/issues/20180#issuecomment-587046325
346
- */
347
- return path.resolve(
348
- os.homedir(),
349
- !! ( await fs.stat( '/snap' ).catch( () => false ) )
350
- ? 'wp-env'
351
- : '.wp-env'
352
- );
353
- }
@@ -1,83 +0,0 @@
1
- // Jest Snapshot v1, https://goo.gl/fbAQLP
2
-
3
- exports[`readConfig config file should match snapshot 1`] = `
4
- {
5
- "configDirectoryPath": ".",
6
- "detectedLocalConfig": true,
7
- "env": {
8
- "development": {
9
- "config": {
10
- "SCRIPT_DEBUG": true,
11
- "TEST": 100,
12
- "TEST_VAL1": 1,
13
- "TEST_VAL2": "hello",
14
- "TEST_VAL3": false,
15
- "WP_DEBUG": true,
16
- "WP_ENVIRONMENT_TYPE": "local",
17
- "WP_HOME": "http://localhost:2000",
18
- "WP_PHP_BINARY": "php",
19
- "WP_SITEURL": "http://localhost:2000",
20
- "WP_TESTS_DOMAIN": "localhost:2000",
21
- "WP_TESTS_EMAIL": "admin@example.org",
22
- "WP_TESTS_TITLE": "Test Blog",
23
- },
24
- "mappings": {},
25
- "phpVersion": null,
26
- "pluginSources": [],
27
- "port": 2000,
28
- "themeSources": [],
29
- },
30
- "tests": {
31
- "config": {
32
- "SCRIPT_DEBUG": false,
33
- "TEST": 200,
34
- "TEST_VAL1": 1,
35
- "TEST_VAL2": "hello",
36
- "TEST_VAL3": false,
37
- "WP_DEBUG": false,
38
- "WP_ENVIRONMENT_TYPE": "local",
39
- "WP_HOME": "http://localhost:1000",
40
- "WP_PHP_BINARY": "php",
41
- "WP_SITEURL": "http://localhost:1000",
42
- "WP_TESTS_DOMAIN": "localhost:1000",
43
- "WP_TESTS_EMAIL": "admin@example.org",
44
- "WP_TESTS_TITLE": "Test Blog",
45
- },
46
- "mappings": {},
47
- "phpVersion": null,
48
- "pluginSources": [],
49
- "port": 1000,
50
- "themeSources": [],
51
- },
52
- },
53
- "name": ".",
54
- }
55
- `;
56
-
57
- exports[`readConfig wp config values should use default config values 1`] = `
58
- {
59
- "SCRIPT_DEBUG": false,
60
- "WP_DEBUG": false,
61
- "WP_ENVIRONMENT_TYPE": "local",
62
- "WP_HOME": "http://localhost:8889",
63
- "WP_PHP_BINARY": "php",
64
- "WP_SITEURL": "http://localhost:8889",
65
- "WP_TESTS_DOMAIN": "localhost:8889",
66
- "WP_TESTS_EMAIL": "admin@example.org",
67
- "WP_TESTS_TITLE": "Test Blog",
68
- }
69
- `;
70
-
71
- exports[`readConfig wp config values should use default config values 2`] = `
72
- {
73
- "SCRIPT_DEBUG": true,
74
- "WP_DEBUG": true,
75
- "WP_ENVIRONMENT_TYPE": "local",
76
- "WP_HOME": "http://localhost:8888",
77
- "WP_PHP_BINARY": "php",
78
- "WP_SITEURL": "http://localhost:8888",
79
- "WP_TESTS_DOMAIN": "localhost:8888",
80
- "WP_TESTS_EMAIL": "admin@example.org",
81
- "WP_TESTS_TITLE": "Test Blog",
82
- }
83
- `;