@elementor/wp-lite-env 0.0.8 → 0.0.9

Sign up to get free protection for your applications and to get access to all the features.
package/README.md ADDED
@@ -0,0 +1,76 @@
1
+ # wp-lite-env
2
+ A simple, lightweight, docker-based WordPress environment
3
+
4
+ # Usage
5
+ ## Installation
6
+ To install the package, run the following command:
7
+ ```bash
8
+ npm install -g @elementor/wp-lite-env
9
+ ```
10
+ If you want to install the package for a specific project, run the following command:
11
+ ```bash
12
+ npm install --save-dev @elementor/wp-lite-env
13
+ ```
14
+ ## Creating a configuration file
15
+ The configuration file is a JSON file that contains the configuration for the WordPress environment.
16
+
17
+ | Field | Type | Default | Description |
18
+ |----------------|----------------|---------|------------------------------------------------------------------------------------------------------------------------------------------------------------|
19
+ | `"core"` | `string\|null` | `null` | The WordPress installation to use. If `null` is specified, the latest production release of WordPress will be used. |
20
+ | `"phpVersion"` | `string\|null` | `null` | The PHP version to use. If `null` is specified, the latest version of PHP that is compatible with the latest production release of WordPress will be used. |
21
+ | `"plugins"` | `Object` | `{}` | A set of plugins to install and activate in the environment. The entries are a key-value pair in the format of <slug>: <path to plugin> |
22
+ | `"themes"` | `Object` | `{}` | A set of themes to install in the environment. The entries are a key-value pair in the format of <slug>: <path to theme> |
23
+ | `"config"` | `Object` | `{}` | Mapping of wp-config.php constants to their desired values. |
24
+ | `"mappings"` | `Object` | `"{}"` | Mapping of WordPress directories to local directories to be mounted in the WordPress instance. |
25
+
26
+ The following is an example of a configuration file:
27
+ ```json
28
+ {
29
+ "core": "6.7",
30
+ "phpVersion": "8.2",
31
+ "plugins": {
32
+ "elementor": "./elementor/build"
33
+ },
34
+ "themes": {
35
+ "hello-elementor": "./hello-elementor"
36
+ },
37
+ "mappings": {
38
+ "resources": "./resources"
39
+ },
40
+ "config": {
41
+ "SCRIPT_DEBUG": false,
42
+ "WP_DEBUG": false
43
+ }
44
+ }
45
+ ```
46
+ ## Usage
47
+ ### Starting a new WordPress environment
48
+ To start a new WordPress environment, run the following command:
49
+ ```bash
50
+ npx wp-lite-env start config=<path to configuration file> -- port=<port>
51
+ ```
52
+ For example:
53
+ ```bash
54
+ npx wp-lite-env start config=./tests/.wp-lite-env.json -- port=1234
55
+ ```
56
+ ### Stopping a WordPress environment
57
+ To stop a running WordPress environment, run the following command:
58
+ ```bash
59
+ npx wp-lite-env start config=<path to configuration file> -- port=<port used by the WordPress environment>
60
+ ```
61
+ For example:
62
+ ```bash
63
+ npx wp-lite-env stop config=./tests/.wp-lite-env.json -- port=1234
64
+ ```
65
+ ### Starting a new WordPress environment
66
+ The WordPress CLI is available for use on the server. To use it, run the following command:
67
+ ```bash
68
+ npx wp-lite-env cli config=<path to configuration file> -- port=<port used by the WordPress environment> command="<CLI command>"
69
+ ```
70
+ For example:
71
+ ```bash
72
+ npx wp-lite-env cli config=./tests/.wp-lite-env.json -- port=1234 command="ls -la /var/www/html"
73
+ ```
74
+
75
+ # Contributors
76
+ This package is developed and maintained by the [Elementor](https://elementor.com) team. With that being said, we want to thank the [@wordpress/env](https://www.npmjs.com/package/@wordpress/env) team, this package is heavily inspired by their wonderful work.
@@ -0,0 +1,71 @@
1
+ // Jest Snapshot v1, https://goo.gl/fbAQLP
2
+
3
+ exports[`templates compose file generation snapshot test 1`] = `
4
+ "services:
5
+ mysql:
6
+ image: 'mariadb:lts'
7
+ ports:
8
+ - '\${WP_ENV_MYSQL_PORT:-}:3306'
9
+ environment:
10
+ MYSQL_ROOT_HOST: '%'
11
+ MYSQL_ROOT_PASSWORD: password
12
+ MYSQL_DATABASE: wordpress
13
+ volumes:
14
+ - 'mysql:/var/lib/mysql'
15
+ wordpress:
16
+ depends_on:
17
+ - mysql
18
+ build:
19
+ context: .
20
+ dockerfile: WordPress.Dockerfile
21
+ no_cache: true
22
+ args: &ref_0
23
+ HOST_USERNAME: yotams
24
+ HOST_UID: '502'
25
+ HOST_GID: '20'
26
+ ports:
27
+ - '\${WP_ENV_PORT:-1234}:80'
28
+ environment:
29
+ APACHE_RUN_USER: '#502'
30
+ APACHE_RUN_GROUP: '#20'
31
+ WORDPRESS_DB_USER: root
32
+ WORDPRESS_DB_PASSWORD: password
33
+ WORDPRESS_DB_NAME: wordpress
34
+ volumes: &ref_1
35
+ - >-
36
+ wpcontent:/var/www/html
37
+ - >-
38
+ /some/wp-config/path:/var/www/html/wp-config
39
+
40
+ extra_hosts:
41
+ - 'host.docker.internal:host-gateway'
42
+ cli:
43
+ depends_on:
44
+ - wordpress
45
+ build:
46
+ context: .
47
+ dockerfile: CLI.Dockerfile
48
+ args: *ref_0
49
+ volumes: *ref_1
50
+ user: '502:20'
51
+ environment:
52
+ WORDPRESS_DB_USER: root
53
+ WORDPRESS_DB_PASSWORD: password
54
+ WORDPRESS_DB_NAME: wordpress
55
+ extra_hosts:
56
+ - 'host.docker.internal:host-gateway'
57
+ volumes:
58
+ mysql: {}
59
+ wpcontent: {}
60
+ "
61
+ `;
62
+
63
+ exports[`templates configuration file generation config file is generated with the correct values 1`] = `
64
+ "#!/bin/bash
65
+ set -eox pipefail
66
+
67
+ wp core install --url="http://localhost:1234" --title="test" --admin_user=admin --admin_password=password --admin_email=wordpress@example.com --skip-email
68
+ wp config set ELEMENTOR_SHOW_HIDDEN_EXPERIMENTS true --raw
69
+ wp config set SCRIPT_DEBUG false --raw
70
+ wp config set WP_DEBUG false --raw"
71
+ `;
@@ -0,0 +1,20 @@
1
+ import {describe, expect, jest, test} from '@jest/globals';
2
+ import fs from 'fs';
3
+ import {getConfig} from "../src/config";
4
+ import {MockInstance} from "jest-mock";
5
+
6
+ jest.mock('fs');
7
+ describe('config', () => {
8
+ test('defaults', () => {
9
+ (fs.readFileSync as unknown as MockInstance).mockReturnValueOnce(JSON.stringify({"some" : "data"}));
10
+ const config = getConfig('some/path');
11
+ expect(config).toEqual({
12
+ core: '6.7',
13
+ phpVersion: '8.1',
14
+ plugins: {},
15
+ themes: {},
16
+ mappings: {},
17
+ config: {},
18
+ });
19
+ });
20
+ });
@@ -0,0 +1,21 @@
1
+ import {afterEach, describe, expect, test} from "@jest/globals";
2
+ import {cleanup, generateFiles, getConfigFilePath, start, stop} from "../src/run";
3
+
4
+ const port = '1234';
5
+ const runPath = (port: string) => {
6
+ return generateFiles(port, getConfigFilePath(['', '', '', 'config=./tests/.wp-lite-env.json']));
7
+ };
8
+
9
+ describe('end to end tests', () => {
10
+ afterEach(async () => {
11
+ const theRunPath = runPath(port);
12
+ await stop(port, theRunPath);
13
+ cleanup(port, theRunPath);
14
+ }, 30000);
15
+ test('WordPress is up and running', async () => {
16
+ await start( port, runPath(port) );
17
+ const response = await fetch(`http://localhost:${port}`);
18
+ expect(response.ok).toBe(true);
19
+ expect(await response.text()).toContain('Welcome to WordPress');
20
+ }, 60000);
21
+ });
@@ -0,0 +1,103 @@
1
+ import {describe, expect, test} from '@jest/globals';
2
+ import {
3
+ generateCliDockerfileTemplate,
4
+ generateConfiguration, generateDockerComposeYmlTemplate,
5
+ generateWordPressDockerfileTemplate
6
+ } from "../src/templates";
7
+
8
+ describe('templates', () => {
9
+ describe('docker files', () => {
10
+ test('WordPress Dockerfile', () => {
11
+ const core = '1.2';
12
+ const phpVersion = '3.4';
13
+ const dockerfile = generateWordPressDockerfileTemplate( { core, phpVersion});
14
+ expect(dockerfile).toMatch(new RegExp(`^FROM wordpress:${ core }-php${ phpVersion }?`));
15
+ });
16
+
17
+ test('CLI Dockerfile', () => {
18
+ const phpVersion = '3.4';
19
+ const dockerfile = generateCliDockerfileTemplate( { phpVersion});
20
+ expect(dockerfile).toMatch(new RegExp(`^FROM wordpress:cli-php${ phpVersion }?`));
21
+ });
22
+ });
23
+
24
+ describe('configuration file generation', () => {
25
+ test('config file is generated with the correct values', () => {
26
+ const config = {
27
+ config: {
28
+ "ELEMENTOR_SHOW_HIDDEN_EXPERIMENTS": true,
29
+ "SCRIPT_DEBUG": false,
30
+ "WP_DEBUG": false
31
+ }
32
+ };
33
+ const configTemplate = generateConfiguration( config, '1234' );
34
+ expect(configTemplate).toMatchSnapshot();
35
+ });
36
+ });
37
+
38
+ describe('compose file generation', () => {
39
+ test('snapshot test', () => {
40
+ const config = {
41
+ mappings: {},
42
+ plugins: {},
43
+ themes: {},
44
+ }
45
+ const composeYml = generateDockerComposeYmlTemplate( config, '/some/base/path', '1234', '/some/wp-config/path' );
46
+ expect(composeYml).toMatchSnapshot();
47
+ });
48
+ test('mappings are mounted correctly', () => {
49
+ const config = {
50
+ mappings: {
51
+ 'some/host/path': 'some/container/path',
52
+ 'some/other/host/path': 'some/other/container/path',
53
+ },
54
+ plugins: {},
55
+ themes: {},
56
+ }
57
+ const basePath = '/some/base/path';
58
+ const composeYml = generateDockerComposeYmlTemplate( config, basePath, '1234', '/some/wp-config/path' );
59
+ expect(composeYml).toMatch(new RegExp(`${basePath}/some/container/path:/var/www/html/some/host/path`));
60
+ expect(composeYml).toMatch(new RegExp(`${basePath}/some/other/container/path:/var/www/html/some/other/host/path`));
61
+ });
62
+ test('plugins are mounted correctly', () => {
63
+ const config = {
64
+ mappings: {
65
+ },
66
+ plugins: {
67
+ 'plugin1': '../some/plugin/path',
68
+ 'plugin2': '../some/other/plugin/path',
69
+ },
70
+ themes: {},
71
+ }
72
+ const basePath = '/some/base/path';
73
+ const composeYml = generateDockerComposeYmlTemplate( config, basePath, '1234', '/some/wp-config/path' );
74
+ expect(composeYml).toMatch(new RegExp(`/some/base/some/plugin/path:/var/www/html/wp-content/plugins/plugin1`));
75
+ expect(composeYml).toMatch(new RegExp(`/some/base/some/other/plugin/path:/var/www/html/wp-content/plugins/plugin2`));
76
+ });
77
+ test('themes are mounted correctly', () => {
78
+ const config = {
79
+ mappings: {},
80
+ plugins: {},
81
+ themes: {
82
+ 'theme1': '../some/theme/path',
83
+ 'theme2': '../some/other/theme/path',
84
+ },
85
+ }
86
+ const basePath = '/some/base/path';
87
+ const composeYml = generateDockerComposeYmlTemplate( config, basePath, '1234', '/some/wp-config/path' );
88
+ expect(composeYml).toMatch(new RegExp(`/some/base/some/theme/path:/var/www/html/wp-content/themes/theme1`));
89
+ expect(composeYml).toMatch(new RegExp(`/some/base/some/other/theme/path:/var/www/html/wp-content/themes/theme2`));
90
+ });
91
+ test('wp-config is mounted correctly', () => {
92
+ // /some/wp-config/path:/var/www/html/wp-config
93
+ const config = {
94
+ mappings: {},
95
+ plugins: {},
96
+ themes: {},
97
+ }
98
+ const basePath = '/some/base/path';
99
+ const composeYml = generateDockerComposeYmlTemplate( config, basePath, '1234', '/some/wp-config/path' );
100
+ expect(composeYml).toMatch(new RegExp(`/some/wp-config/path:/var/www/html/wp-config`));
101
+ });
102
+ });
103
+ });
@@ -0,0 +1,46 @@
1
+ {
2
+ "name": "@elementor/wp-lite-env",
3
+ "version": "0.0.9",
4
+ "private": false,
5
+ "description": "A simple, lightweight, docker-based WordPress environment",
6
+ "main": "dist/index.js",
7
+ "type": "module",
8
+ "types": "dist/index.d.ts",
9
+ "bin": {
10
+ "wp-lite-env": "dist/index.js"
11
+ },
12
+ "scripts": {
13
+ "build": "tsc",
14
+ "lint": "eslint",
15
+ "release": "npm run build && changeset publish",
16
+ "test": "jest --coverage=true"
17
+ },
18
+ "repository": {
19
+ "type": "git",
20
+ "url": "git+https://github.com/elementor/wp-lite-env.git"
21
+ },
22
+ "publishConfig": {
23
+ "access": "public"
24
+ },
25
+ "author": "Elementor Team",
26
+ "license": "ISC",
27
+ "bugs": {
28
+ "url": "https://github.com/elementor/wp-lite-env/issues"
29
+ },
30
+ "homepage": "https://github.com/elementor/wp-lite-env#readme",
31
+ "dependencies": {
32
+ "docker-compose": "^1.1.0"
33
+ },
34
+ "devDependencies": {
35
+ "@changesets/cli": "^2.27.9",
36
+ "@eslint/js": "^9.15.0",
37
+ "@jest/globals": "^29.7.0",
38
+ "@types/eslint__js": "^8.42.3",
39
+ "@types/node": "^22.9.0",
40
+ "eslint": "~9.14.0",
41
+ "jest": "^29.7.0",
42
+ "ts-jest": "^29.2.5",
43
+ "typescript": "^5.6.3",
44
+ "typescript-eslint": "^8.14.0"
45
+ }
46
+ }
@@ -0,0 +1,13 @@
1
+ // @ts-check
2
+
3
+ import eslint from '@eslint/js';
4
+ import tseslint from 'typescript-eslint';
5
+
6
+ export default tseslint.config(
7
+ {
8
+ // config with just ignores is the replacement for `.eslintignore`
9
+ ignores: ['dist/**', '**.js', '**.map'],
10
+ },
11
+ eslint.configs.recommended,
12
+ ...tseslint.configs.recommended,
13
+ );
package/index.ts ADDED
@@ -0,0 +1,19 @@
1
+ #!/usr/bin/env node
2
+
3
+ import {cleanup, commandMap, generateFiles, getCliCommand, getConfigFilePath, getPort} from './src/run';
4
+
5
+ const command = process.argv[ 2 ];
6
+ if ( ! commandMap[ command ] ) {
7
+ console.log( `Valid commands: ${ Object.keys( commandMap ).join( ', ' ) }. You used ${ command }` );
8
+ }
9
+
10
+ const port = getPort( process.argv );
11
+ const configFilePath = getConfigFilePath( process.argv )
12
+ const runPath = generateFiles( port, configFilePath );
13
+ const cliCommand = getCliCommand( process.argv );
14
+
15
+ try {
16
+ await commandMap[command](port, runPath, cliCommand);
17
+ } finally {
18
+ cleanup( port, runPath );
19
+ }
package/jest.config.js ADDED
@@ -0,0 +1,8 @@
1
+ /** @type {import('ts-jest').JestConfigWithTsJest} **/
2
+ export default {
3
+ testEnvironment: "node",
4
+ testPathIgnorePatterns: ["<rootDir>/dist/", "<rootDir>/node_modules/"],
5
+ transform: {
6
+ "^.+.tsx?$": ["ts-jest",{}],
7
+ },
8
+ };
package/package.json CHANGED
@@ -1,47 +1,46 @@
1
1
  {
2
- "name": "@elementor/wp-lite-env",
3
- "version": "0.0.8",
4
- "private": false,
5
- "description": "A simple, lightweight, docker-based WordPress environment",
6
- "main": "dist/index.js",
7
- "type": "module",
8
- "types": "dist/index.d.ts",
9
- "bin": {
10
- "wp-lite-env": "dist/index.js"
11
- },
12
- "scripts": {
13
- "build": "tsc",
14
- "lint": "eslint",
15
- "release": "npm run build && changeset publish",
16
- "test": "jest --coverage=true"
17
- },
18
- "repository": {
19
- "type": "git",
20
- "url": "git+https://github.com/elementor/wp-lite-env.git"
21
- },
22
- "publishConfig": {
23
- "access": "public",
24
- "directory": "dist"
25
- },
26
- "author": "Elementor Team",
27
- "license": "ISC",
28
- "bugs": {
29
- "url": "https://github.com/elementor/wp-lite-env/issues"
30
- },
31
- "homepage": "https://github.com/elementor/wp-lite-env#readme",
32
- "dependencies": {
33
- "docker-compose": "^1.1.0"
34
- },
35
- "devDependencies": {
36
- "@changesets/cli": "^2.27.9",
37
- "@eslint/js": "^9.15.0",
38
- "@jest/globals": "^29.7.0",
39
- "@types/eslint__js": "^8.42.3",
40
- "@types/node": "^22.9.0",
41
- "eslint": "~9.14.0",
42
- "jest": "^29.7.0",
43
- "ts-jest": "^29.2.5",
44
- "typescript": "^5.6.3",
45
- "typescript-eslint": "^8.14.0"
46
- }
2
+ "name": "@elementor/wp-lite-env",
3
+ "version": "0.0.9",
4
+ "private": false,
5
+ "description": "A simple, lightweight, docker-based WordPress environment",
6
+ "main": "dist/index.js",
7
+ "type": "module",
8
+ "types": "dist/index.d.ts",
9
+ "bin": {
10
+ "wp-lite-env": "dist/index.js"
11
+ },
12
+ "scripts": {
13
+ "build": "tsc",
14
+ "lint": "eslint",
15
+ "release": "npm run build && changeset publish",
16
+ "test": "jest --coverage=true"
17
+ },
18
+ "repository": {
19
+ "type": "git",
20
+ "url": "git+https://github.com/elementor/wp-lite-env.git"
21
+ },
22
+ "publishConfig": {
23
+ "access": "public"
24
+ },
25
+ "author": "Elementor Team",
26
+ "license": "ISC",
27
+ "bugs": {
28
+ "url": "https://github.com/elementor/wp-lite-env/issues"
29
+ },
30
+ "homepage": "https://github.com/elementor/wp-lite-env#readme",
31
+ "dependencies": {
32
+ "docker-compose": "^1.1.0"
33
+ },
34
+ "devDependencies": {
35
+ "@changesets/cli": "^2.27.9",
36
+ "@eslint/js": "^9.15.0",
37
+ "@jest/globals": "^29.7.0",
38
+ "@types/eslint__js": "^8.42.3",
39
+ "@types/node": "^22.9.0",
40
+ "eslint": "~9.14.0",
41
+ "jest": "^29.7.0",
42
+ "ts-jest": "^29.2.5",
43
+ "typescript": "^5.6.3",
44
+ "typescript-eslint": "^8.14.0"
45
+ }
47
46
  }
package/src/config.ts ADDED
@@ -0,0 +1,35 @@
1
+ import fs from 'fs';
2
+
3
+ export type Config = {
4
+ core?: string,
5
+ phpVersion?: string,
6
+ plugins?: { [key: string]: string },
7
+ themes?: { [key: string]: string },
8
+ mappings?: { [key: string]: string },
9
+ config?: Record<string, string|boolean>,
10
+ }
11
+
12
+ export const getConfig = ( configFilePath?: string ): Config => {
13
+ let configFile: Config = {};
14
+ if ( configFilePath ) {
15
+ configFile = JSON.parse( fs.readFileSync( configFilePath, 'utf8' ) ) as Config;
16
+ }
17
+
18
+ const defaultConfig: Config = {
19
+ core: '6.7',
20
+ phpVersion: '8.1',
21
+ plugins: {},
22
+ themes: {},
23
+ mappings: {},
24
+ config: {},
25
+ };
26
+
27
+ return {
28
+ core: configFile.core || defaultConfig.core,
29
+ phpVersion: configFile.phpVersion || defaultConfig.phpVersion,
30
+ plugins: configFile.plugins || defaultConfig.plugins,
31
+ themes: configFile.themes || defaultConfig.themes,
32
+ mappings: configFile.mappings || defaultConfig.mappings,
33
+ config: configFile.config || defaultConfig.config,
34
+ };
35
+ };
package/src/run.ts ADDED
@@ -0,0 +1,125 @@
1
+ import {downAll, run, upAll} from "docker-compose";
2
+ import path from "path";
3
+ import {getConfig} from "./config";
4
+ import fs from "fs";
5
+ import {
6
+ generateCliDockerfileTemplate,
7
+ generateConfiguration,
8
+ generateDockerComposeYmlTemplate,
9
+ generateWordPressDockerfileTemplate
10
+ } from "./templates";
11
+ import {createHash} from "crypto";
12
+ import os from "node:os";
13
+
14
+ const waitForServer = async ( url: string, timeoutMs: number ) => {
15
+ const startTime = Date.now();
16
+ const sleep = ( ms: number ) => new Promise( ( r ) => setTimeout( r, ms ) );
17
+
18
+ while ( startTime + timeoutMs > Date.now() ) {
19
+ try {
20
+ const response = await fetch( url );
21
+ if ( response.ok && ( 200 === response.status || 302 === response.status ) ) {
22
+ return true;
23
+ }
24
+ } catch ( e ) { // eslint-disable-line @typescript-eslint/no-unused-vars
25
+ // Ignore
26
+ } finally {
27
+ await sleep( 100 );
28
+ }
29
+ }
30
+ return false;
31
+ };
32
+
33
+ export const start = async ( port: string, runPath: string ) => {
34
+ await upAll( {
35
+ commandOptions: [ '--build' ],
36
+ composeOptions: [ '-p', `port${ port }` ],
37
+ cwd: runPath,
38
+ log: true,
39
+ } );
40
+ await waitForServer( `http://localhost:${ port }`, 10000 );
41
+ await cli( port, runPath, 'bash wp-config/configure-wp.sh' );
42
+ };
43
+
44
+ export const stop = async ( port: string, runPath: string ) => {
45
+ await downAll( {
46
+ cwd: runPath,
47
+ commandOptions: [ '--volumes', '--remove-orphans' ],
48
+ composeOptions: [ '-p', `port${ port }` ],
49
+ log: true,
50
+ } );
51
+ };
52
+
53
+ const cli = async ( port: string, runPath: string, command: string ) => {
54
+ await run( 'cli', command, {
55
+ cwd: runPath,
56
+ commandOptions: [ '--rm' ],
57
+ composeOptions: [ '-p', `port${ port }` ],
58
+ log: true,
59
+ } );
60
+ };
61
+
62
+ export const commandMap: { [key: string]: ( ( port: string ) => Promise<void> ) | ( ( port: string, runPath: string, command: string ) => Promise<void> ) } = {
63
+ start,
64
+ stop,
65
+ cli,
66
+ };
67
+
68
+ const getWpConfigPath = ( port: string ) => path.resolve( process.cwd(), port );
69
+
70
+ export const generateFiles = ( port: string, configFilePath: string ) => {
71
+ const config = getConfig( configFilePath );
72
+
73
+ // Using a local path since Docker Compose cannot access /tmp
74
+ // See: https://github.com/docker/compose/issues/1153
75
+ const wpConfigPath = getWpConfigPath( port );
76
+ if ( ! fs.existsSync( wpConfigPath ) ) {
77
+ fs.mkdirSync( wpConfigPath, { recursive: true } );
78
+ }
79
+ const wpConfig = generateConfiguration( config, port );
80
+ fs.writeFileSync( path.resolve( wpConfigPath, 'configure-wp.sh' ), wpConfig );
81
+
82
+ const dockerComposeYmlTemplate = generateDockerComposeYmlTemplate( config, process.cwd(), port, wpConfigPath );
83
+ const wordPressDockerfileTemplate = generateWordPressDockerfileTemplate( config );
84
+ const cliDockerfileTemplate = generateCliDockerfileTemplate( config );
85
+ const hash = createHash( 'sha256' );
86
+ hash.update( dockerComposeYmlTemplate + wordPressDockerfileTemplate + cliDockerfileTemplate + port );
87
+ const runPath = path.resolve( os.tmpdir(), `${ hash.digest( 'hex' ) }` );
88
+ if ( ! fs.existsSync( runPath ) ) {
89
+ fs.mkdirSync( runPath );
90
+ }
91
+
92
+ console.log( `writing files to run path: ${ runPath }` );
93
+ fs.writeFileSync( path.resolve( runPath, 'docker-compose.yml' ), dockerComposeYmlTemplate );
94
+ fs.writeFileSync( path.resolve( runPath, 'WordPress.Dockerfile' ), wordPressDockerfileTemplate );
95
+ fs.writeFileSync( path.resolve( runPath, 'CLI.Dockerfile' ), cliDockerfileTemplate );
96
+
97
+ return runPath;
98
+ };
99
+
100
+ const getArgument = ( argumentKey: string, processArgs: string[] ) => {
101
+ for ( let i = 3; i < processArgs.length; i++ ) {
102
+ const argument = processArgs[ i ];
103
+ if ( argument.startsWith( `${ argumentKey }=` ) ) {
104
+ return argument.substring( argumentKey.length + 1 );
105
+ }
106
+ }
107
+ return undefined;
108
+ };
109
+
110
+ export const getConfigFilePath = ( processArgs: string[] ) => {
111
+ return path.resolve(getArgument( 'config', processArgs ));
112
+ };
113
+
114
+ export const getCliCommand = ( processArgs: string[] ) => {
115
+ return getArgument( 'command', processArgs );
116
+ };
117
+
118
+ export const getPort = ( processArgs: string[] ) => {
119
+ return getArgument( 'port', processArgs ) || '8888';
120
+ };
121
+
122
+ export const cleanup = ( port: string, runPath: string ) => {
123
+ fs.rmSync( getWpConfigPath( port ), { recursive: true, force: true } );
124
+ fs.rmSync( runPath, { recursive: true, force: true } );
125
+ }