@caweb/cli 1.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.
- package/README.md +15 -0
- package/bin/caweb +20 -0
- package/lib/caweb.js +140 -0
- package/lib/cli.js +135 -0
- package/lib/commands/index.js +17 -0
- package/lib/commands/shell.js +36 -0
- package/lib/commands/start.js +160 -0
- package/lib/commands/test.js +87 -0
- package/lib/configs.js +120 -0
- package/lib/download-sources.js +256 -0
- package/lib/env.js +12 -0
- package/lib/options.js +23 -0
- package/package.json +59 -0
package/README.md
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# caweb-cli
|
|
2
|
+
`caweb-cli` rapidly sets up a local WordPress environment using [wp-env](https://www.npmjs.com/package/@wordpress/env), fully configured to the [CAWebPublishing Service](https://caweb.cdt.ca.gov/). The cli will automatically generate the necessary [.wp-env.json](https://www.npmjs.com/package/@wordpress/env#wp-envjson) file, to override or add additional configuration options use the [.wp-env.override.json](https://www.npmjs.com/package/@wordpress/env#wp-envoverridejson) file.
|
|
3
|
+
|
|
4
|
+
## Additional Features
|
|
5
|
+
- phpMyAdmin Service
|
|
6
|
+
- Downloads and configures the [CAWeb Theme](https://github.com/CA-cODE-Works/CAWeb)
|
|
7
|
+
- Downloads and configures the [Divi Theme](https://www.elegantthemes.com/gallery/divi/) (*requires valid ElegantThemes Username and API Key*)
|
|
8
|
+
|
|
9
|
+
## Command Reference
|
|
10
|
+
`caweb-cli` is a wrapper for [wp-env](https://www.npmjs.com/package/@wordpress/env); therefore, all commands from wp-env are readily available, for more information on those commands [see](https://www.npmjs.com/package/@wordpress/env#command-referenced). ***Note:** substitute `wp-env` command with `caweb`.
|
|
11
|
+
|
|
12
|
+
### `caweb start`
|
|
13
|
+
Starts the CAWebPublishing WordPress Environment.
|
|
14
|
+
### `caweb shell`
|
|
15
|
+
Open a shell session in the WordPress environment.
|
package/bin/caweb
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
// Remove 'node' and the name of the script from the arguments.
|
|
5
|
+
let command = process.argv.slice( 2 );
|
|
6
|
+
// Default to help text when they aren't running any commands.
|
|
7
|
+
if ( ! command.length ) {
|
|
8
|
+
command = [ '--help' ];
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
// Rather than just executing the current CLI we will attempt to find a local version
|
|
12
|
+
// and execute that one instead. This prevents users from accidentally using the
|
|
13
|
+
// global CLI when a potentially different local version is expected.
|
|
14
|
+
const localPath = require.resolve( '@caweb/cli/lib/cli.js', {
|
|
15
|
+
paths: [ process.cwd(), __dirname ],
|
|
16
|
+
} );
|
|
17
|
+
const cli = require( localPath )();
|
|
18
|
+
|
|
19
|
+
// Now we can execute the CLI with the given command.
|
|
20
|
+
cli.parse( command );
|
package/lib/caweb.js
ADDED
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
/**
|
|
3
|
+
* External dependencies
|
|
4
|
+
*/
|
|
5
|
+
const dockerCompose = require( 'docker-compose' );
|
|
6
|
+
const path = require( 'path' );
|
|
7
|
+
const loadConfig = require( '@wordpress/env/lib/config/load-config' );
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Internal dependencies
|
|
12
|
+
*/
|
|
13
|
+
const { CAWEB_OPTIONS } = require('./options');
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
*
|
|
17
|
+
* @param {Object} options
|
|
18
|
+
* @param {Object} options.spinner A CLI spinner which indicates progress.
|
|
19
|
+
* @param {boolean} options.environment Which environment to open terminal in.
|
|
20
|
+
* @param {Array} options.cmds Array of commands to run.
|
|
21
|
+
*
|
|
22
|
+
* @returns {Object}
|
|
23
|
+
*/
|
|
24
|
+
async function runDockerCmd({
|
|
25
|
+
spinner,
|
|
26
|
+
environment,
|
|
27
|
+
cmds
|
|
28
|
+
}) {
|
|
29
|
+
|
|
30
|
+
try {
|
|
31
|
+
const config = await loadConfig(path.resolve('.'));
|
|
32
|
+
|
|
33
|
+
// -eo pipefail exits the command as soon as anything fails in bash.
|
|
34
|
+
//const setupCommands = [ 'set -eo pipefail' ];
|
|
35
|
+
|
|
36
|
+
// Execute all setup commands in a batch.
|
|
37
|
+
return await dockerCompose.run(
|
|
38
|
+
environment === 'development' ? 'cli' : 'tests-cli',
|
|
39
|
+
[ 'bash', '-c', cmds.join( ' && ' ) ],
|
|
40
|
+
{
|
|
41
|
+
cwd: config.workDirectoryPath,
|
|
42
|
+
commandOptions: [ '--rm' ],
|
|
43
|
+
log: config.debug,
|
|
44
|
+
}
|
|
45
|
+
).then(
|
|
46
|
+
(result) => {
|
|
47
|
+
if( '' !== result.out ){
|
|
48
|
+
console.log( result.out )
|
|
49
|
+
}else{
|
|
50
|
+
console.log(result.err)
|
|
51
|
+
}
|
|
52
|
+
return result;
|
|
53
|
+
},
|
|
54
|
+
(err) => {
|
|
55
|
+
return false;
|
|
56
|
+
}
|
|
57
|
+
)
|
|
58
|
+
|
|
59
|
+
} catch(error) {
|
|
60
|
+
console.log(error)
|
|
61
|
+
|
|
62
|
+
process.exit( 1 );
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Activates the CAWeb Theme for the WordPress Environment if it's installed.
|
|
69
|
+
*
|
|
70
|
+
* @param {Object} options
|
|
71
|
+
* @param {Object} options.spinner A CLI spinner which indicates progress.
|
|
72
|
+
* @param {boolean} options.environment Which environment to activate the theme on.
|
|
73
|
+
*/
|
|
74
|
+
async function activateCAWeb({
|
|
75
|
+
spinner,
|
|
76
|
+
environment
|
|
77
|
+
}){
|
|
78
|
+
return await runDockerCmd( {
|
|
79
|
+
spinner,
|
|
80
|
+
environment,
|
|
81
|
+
cmds: ['wp theme is-installed CAWeb && wp theme activate CAWeb']
|
|
82
|
+
}).then(
|
|
83
|
+
(result) => {
|
|
84
|
+
return true;
|
|
85
|
+
},
|
|
86
|
+
(err) => {
|
|
87
|
+
return false;
|
|
88
|
+
}
|
|
89
|
+
)
|
|
90
|
+
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Configures WordPress for the given environment by installing WordPress,
|
|
95
|
+
* activating all plugins, and activating the first theme. These steps are
|
|
96
|
+
* performed sequentially so as to not overload the WordPress instance.
|
|
97
|
+
*
|
|
98
|
+
* @param {WPEnvironment} environment The environment to configure. Either 'development' or 'tests'.
|
|
99
|
+
* @param {WPConfig} config The wp-env config object.
|
|
100
|
+
* @param {Object} spinner A CLI spinner which indicates progress.
|
|
101
|
+
*/
|
|
102
|
+
async function configureCAWeb( environment, config, spinner ) {
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
const isThemeActivated = await activateCAWeb( {
|
|
106
|
+
spinner,
|
|
107
|
+
environment
|
|
108
|
+
})
|
|
109
|
+
|
|
110
|
+
// if our theme is active.
|
|
111
|
+
if( isThemeActivated ){
|
|
112
|
+
let themeOptions = [];
|
|
113
|
+
|
|
114
|
+
// iterate over config options.
|
|
115
|
+
Object.entries(config.env[ environment ].config).forEach(([k,v]) => {
|
|
116
|
+
// if the option is prefixed with CAWEB_ and is a valid CAWeb Option.
|
|
117
|
+
if ( `${k}`.startsWith('CAWEB_') && undefined !== CAWEB_OPTIONS[k] ){
|
|
118
|
+
// set the option.
|
|
119
|
+
themeOptions.push(
|
|
120
|
+
`wp option set '${CAWEB_OPTIONS[k]}' "${v}"`
|
|
121
|
+
);
|
|
122
|
+
}
|
|
123
|
+
})
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
await runDockerCmd({
|
|
127
|
+
spinner,
|
|
128
|
+
environment,
|
|
129
|
+
cmds: themeOptions
|
|
130
|
+
})
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
module.exports = {
|
|
137
|
+
activateCAWeb,
|
|
138
|
+
configureCAWeb,
|
|
139
|
+
runDockerCmd
|
|
140
|
+
};
|
package/lib/cli.js
ADDED
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
/**
|
|
3
|
+
* External dependencies
|
|
4
|
+
*/
|
|
5
|
+
const wpenv_cli = require('@wordpress/env/lib/cli');
|
|
6
|
+
|
|
7
|
+
const chalk = require( 'chalk' );
|
|
8
|
+
const ora = require( 'ora' );
|
|
9
|
+
let yargs = require( 'yargs' );
|
|
10
|
+
const terminalLink = require( 'terminal-link' );
|
|
11
|
+
const { execSync } = require( 'child_process' );
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Internal dependencies
|
|
15
|
+
*/
|
|
16
|
+
const pkg = require( '../package.json' );
|
|
17
|
+
const env = require( './commands' );
|
|
18
|
+
const parseXdebugMode = require( '@wordpress/env/lib/parse-xdebug-mode' );
|
|
19
|
+
|
|
20
|
+
// Colors.
|
|
21
|
+
const boldWhite = chalk.bold.white;
|
|
22
|
+
const wpPrimary = boldWhite.bgHex( '#00669b' );
|
|
23
|
+
const wpGreen = boldWhite.bgHex( '#4ab866' );
|
|
24
|
+
const wpRed = boldWhite.bgHex( '#d94f4f' );
|
|
25
|
+
const wpYellow = boldWhite.bgHex( '#f0b849' );
|
|
26
|
+
|
|
27
|
+
// Spinner.
|
|
28
|
+
const withSpinner =
|
|
29
|
+
( command ) =>
|
|
30
|
+
( ...args ) => {
|
|
31
|
+
const spinner = ora().start();
|
|
32
|
+
args[ 0 ].spinner = spinner;
|
|
33
|
+
let time = process.hrtime();
|
|
34
|
+
return command( ...args ).then(
|
|
35
|
+
( message ) => {
|
|
36
|
+
time = process.hrtime( time );
|
|
37
|
+
spinner.succeed(
|
|
38
|
+
`${ message || spinner.text } (in ${ time[ 0 ] }s ${ (
|
|
39
|
+
time[ 1 ] / 1e6
|
|
40
|
+
).toFixed( 0 ) }ms)`
|
|
41
|
+
);
|
|
42
|
+
process.exit( 0 );
|
|
43
|
+
},
|
|
44
|
+
( error ) => {
|
|
45
|
+
if( error ){
|
|
46
|
+
// Error is an unknown error. That means there was a bug in our code.
|
|
47
|
+
spinner.fail(
|
|
48
|
+
typeof error === 'string' ? error : error.message
|
|
49
|
+
);
|
|
50
|
+
// Disable reason: Using console.error() means we get a stack trace.
|
|
51
|
+
console.error( error );
|
|
52
|
+
process.exit( 1 );
|
|
53
|
+
}else{
|
|
54
|
+
spinner.fail( 'An unknown error occurred.' );
|
|
55
|
+
process.exit( 1 );
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
);
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
module.exports = function cli() {
|
|
62
|
+
yargs = wpenv_cli();
|
|
63
|
+
|
|
64
|
+
// we are overwriting the default wp-env start command with our own.
|
|
65
|
+
yargs.command(
|
|
66
|
+
'start',
|
|
67
|
+
wpGreen(
|
|
68
|
+
chalk`Starts WordPress for development on port {bold.underline ${ terminalLink(
|
|
69
|
+
'8888',
|
|
70
|
+
'http://localhost:8888'
|
|
71
|
+
) }} (override with WP_ENV_PORT) and tests on port {bold.underline ${ terminalLink(
|
|
72
|
+
'8889',
|
|
73
|
+
'http://localhost:8889'
|
|
74
|
+
) }} (override with WP_ENV_TESTS_PORT). The current working directory must be a WordPress installation, a plugin, a theme, or contain a .wp-env.json file. After first install, use the '--update' flag to download updates to mapped sources and to re-apply WordPress configuration options.`
|
|
75
|
+
),
|
|
76
|
+
( args ) => {
|
|
77
|
+
args.option( 'update', {
|
|
78
|
+
type: 'boolean',
|
|
79
|
+
describe:
|
|
80
|
+
'Download source updates and apply WordPress configuration.',
|
|
81
|
+
default: false,
|
|
82
|
+
} );
|
|
83
|
+
args.option( 'xdebug', {
|
|
84
|
+
describe:
|
|
85
|
+
'Enables Xdebug. If not passed, Xdebug is turned off. If no modes are set, uses "debug". You may set multiple Xdebug modes by passing them in a comma-separated list: `--xdebug=develop,coverage`. See https://xdebug.org/docs/all_settings#mode for information about Xdebug modes.',
|
|
86
|
+
coerce: parseXdebugMode,
|
|
87
|
+
type: 'string',
|
|
88
|
+
} );
|
|
89
|
+
args.option( 'scripts', {
|
|
90
|
+
type: 'boolean',
|
|
91
|
+
describe: 'Execute any configured lifecycle scripts.',
|
|
92
|
+
default: true,
|
|
93
|
+
} );
|
|
94
|
+
args.option( 'bare', {
|
|
95
|
+
type: 'boolean',
|
|
96
|
+
describe: 'True if excluding any downloads from CAWeb, use this if you want to use a local version of the CAWeb Theme, Configurations will still be applied.',
|
|
97
|
+
default: false,
|
|
98
|
+
} );
|
|
99
|
+
|
|
100
|
+
},
|
|
101
|
+
withSpinner( env.start )
|
|
102
|
+
);
|
|
103
|
+
|
|
104
|
+
// Shell Terminal Command.
|
|
105
|
+
yargs.command(
|
|
106
|
+
'shell ',
|
|
107
|
+
'Open shell terminal in WordPress environment.',
|
|
108
|
+
(args) => {
|
|
109
|
+
args.positional( 'environment', {
|
|
110
|
+
type: 'string',
|
|
111
|
+
describe: "Which environment to open terminal in.",
|
|
112
|
+
choices: [ 'development', 'tests' ],
|
|
113
|
+
default: 'development',
|
|
114
|
+
} );
|
|
115
|
+
},
|
|
116
|
+
withSpinner( env.shell )
|
|
117
|
+
)
|
|
118
|
+
|
|
119
|
+
// Test Command.
|
|
120
|
+
yargs.command(
|
|
121
|
+
'test [environment]',
|
|
122
|
+
'Test commands on a WordPress environment',
|
|
123
|
+
(args) => {
|
|
124
|
+
args.positional( 'environment', {
|
|
125
|
+
type: 'string',
|
|
126
|
+
describe: "Which environment to test in.",
|
|
127
|
+
choices: [ 'development', 'tests' ],
|
|
128
|
+
default: 'development',
|
|
129
|
+
} );
|
|
130
|
+
},
|
|
131
|
+
withSpinner( env.test )
|
|
132
|
+
)
|
|
133
|
+
|
|
134
|
+
return yargs;
|
|
135
|
+
};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
/**
|
|
3
|
+
* External dependencies
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Internal dependencies
|
|
8
|
+
*/
|
|
9
|
+
const shell = require('./shell')
|
|
10
|
+
const start = require('./start')
|
|
11
|
+
const test = require( './test' );
|
|
12
|
+
|
|
13
|
+
module.exports = {
|
|
14
|
+
shell,
|
|
15
|
+
start,
|
|
16
|
+
test
|
|
17
|
+
};
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
/**
|
|
3
|
+
* External dependencies
|
|
4
|
+
*/
|
|
5
|
+
const wpEnvRun = require( '@wordpress/env/lib/commands/run' );
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Internal dependencies
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Opens shell terminal in WordPress environment
|
|
13
|
+
*
|
|
14
|
+
* @param {Object} options
|
|
15
|
+
* @param {Object} options.spinner A CLI spinner which indicates progress.
|
|
16
|
+
* @param {boolean} options.environment Which environment to open terminal in.
|
|
17
|
+
* @param {boolean} options.debug True if debug mode is enabled.
|
|
18
|
+
*/
|
|
19
|
+
module.exports = async function shell({
|
|
20
|
+
spinner,
|
|
21
|
+
environment,
|
|
22
|
+
debug
|
|
23
|
+
}) {
|
|
24
|
+
|
|
25
|
+
const container = 'tests' === environment ? 'tests-cli' : 'cli';
|
|
26
|
+
|
|
27
|
+
await wpEnvRun({
|
|
28
|
+
container: container,
|
|
29
|
+
command: ['bash'],
|
|
30
|
+
"": "",
|
|
31
|
+
envCwd: '.',
|
|
32
|
+
spinner,
|
|
33
|
+
debug
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
};
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Modified from wp-env 8.11.0
|
|
3
|
+
* @see @wordpress/env/lib/commands/start
|
|
4
|
+
*/
|
|
5
|
+
'use strict';
|
|
6
|
+
/**
|
|
7
|
+
* External dependencies
|
|
8
|
+
*/
|
|
9
|
+
const path = require( 'path' );
|
|
10
|
+
const fs = require( 'fs-extra' );
|
|
11
|
+
const wpEnvStart = require('@wordpress/env/lib/commands/start');
|
|
12
|
+
const util = require( 'util' );
|
|
13
|
+
const { didCacheChange, getCache } = require( '@wordpress/env/lib/cache' );
|
|
14
|
+
const {
|
|
15
|
+
checkDatabaseConnection,
|
|
16
|
+
canAccessWPORG
|
|
17
|
+
} = require( '@wordpress/env/lib/wordpress' );
|
|
18
|
+
const loadConfig = require( '@wordpress/env/lib/config/load-config' );
|
|
19
|
+
const retry = require( '@wordpress/env/lib/retry' );
|
|
20
|
+
const yaml = require( 'js-yaml' );
|
|
21
|
+
const dockerCompose = require( 'docker-compose' );
|
|
22
|
+
|
|
23
|
+
const CONFIG_CACHE_KEY = 'config_checksum';
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Internal dependencies
|
|
27
|
+
*/
|
|
28
|
+
const { configureCAWeb } = require('../caweb');
|
|
29
|
+
const { buildWPEnvConfig, buildDockerComposeConfig } = require('../configs');
|
|
30
|
+
const {downloadSources } = require('../download-sources');
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Promisified dependencies
|
|
34
|
+
*/
|
|
35
|
+
const { writeFile } = fs.promises;
|
|
36
|
+
const sleep = util.promisify( setTimeout );
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Starts the development server.
|
|
40
|
+
*
|
|
41
|
+
* @param {Object} options
|
|
42
|
+
* @param {Object} options.spinner A CLI spinner which indicates progress.
|
|
43
|
+
* @param {boolean} options.update If true, update sources.
|
|
44
|
+
* @param {string} options.xdebug The Xdebug mode to set.
|
|
45
|
+
* @param {boolean} options.scripts Indicates whether or not lifecycle scripts should be executed.
|
|
46
|
+
* @param {boolean} options.debug True if debug mode is enabled.
|
|
47
|
+
* @param {boolean} options.bare True if excluding any CAWeb Configurations.
|
|
48
|
+
*
|
|
49
|
+
*/
|
|
50
|
+
module.exports = async function start({
|
|
51
|
+
spinner,
|
|
52
|
+
update,
|
|
53
|
+
xdebug,
|
|
54
|
+
scripts,
|
|
55
|
+
debug,
|
|
56
|
+
bare
|
|
57
|
+
}) {
|
|
58
|
+
spinner.text = 'Writing configuration file...';
|
|
59
|
+
|
|
60
|
+
// Write CAWeb .wp-env.json file.
|
|
61
|
+
await writeFile(
|
|
62
|
+
path.join(process.cwd(), '.wp-env.json'),
|
|
63
|
+
JSON.stringify( buildWPEnvConfig({bare}), null, 4 )
|
|
64
|
+
);
|
|
65
|
+
|
|
66
|
+
// Get current wp-env cache key
|
|
67
|
+
const config = await loadConfig(path.resolve('.'));
|
|
68
|
+
const { workDirectoryPath } = config;
|
|
69
|
+
const cacheKey = await getCache(CONFIG_CACHE_KEY, {workDirectoryPath});
|
|
70
|
+
|
|
71
|
+
// wp-env launch.
|
|
72
|
+
await wpEnvStart({
|
|
73
|
+
spinner,
|
|
74
|
+
update,
|
|
75
|
+
xdebug,
|
|
76
|
+
scripts,
|
|
77
|
+
debug,
|
|
78
|
+
})
|
|
79
|
+
|
|
80
|
+
// Check if we should configure settings.
|
|
81
|
+
const shouldConfigureWp = ( update ||
|
|
82
|
+
( await didCacheChange( CONFIG_CACHE_KEY, cacheKey, {
|
|
83
|
+
workDirectoryPath,
|
|
84
|
+
} ) )) &&
|
|
85
|
+
// Don't reconfigure everything when we can't connect to the internet because
|
|
86
|
+
// the majority of update tasks involve connecting to the internet. (Such
|
|
87
|
+
// as downloading sources and pulling docker images.)
|
|
88
|
+
( await canAccessWPORG() );
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
// Only run configurations when config has changed.
|
|
92
|
+
if( shouldConfigureWp ){
|
|
93
|
+
// Save pretext from wp-env if it exists for later.
|
|
94
|
+
let preText = undefined !== spinner.prefixText ? spinner.prefixText.slice(0, -1) : '';
|
|
95
|
+
|
|
96
|
+
try {
|
|
97
|
+
// We aren't done lets clear the default WordPress text.
|
|
98
|
+
spinner.prefixText = '';
|
|
99
|
+
spinner.text = '';
|
|
100
|
+
|
|
101
|
+
await checkDatabaseConnection( config );
|
|
102
|
+
} catch ( error ) {
|
|
103
|
+
// Wait 30 seconds for MySQL to accept connections.
|
|
104
|
+
await retry( () => checkDatabaseConnection( config ), {
|
|
105
|
+
times: 30,
|
|
106
|
+
delay: 1000,
|
|
107
|
+
} );
|
|
108
|
+
|
|
109
|
+
// It takes 3-4 seconds for MySQL to be ready after it starts accepting connections.
|
|
110
|
+
await sleep( 4000 );
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// Download any resources required for CAWeb.
|
|
114
|
+
if( ! bare ){
|
|
115
|
+
await downloadSources({spinner, config});
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// Write docker-compose.override.yml file to workDirectoryPath.
|
|
119
|
+
await writeFile(
|
|
120
|
+
path.join(workDirectoryPath, 'docker-compose.override.yml'),
|
|
121
|
+
yaml.dump( buildDockerComposeConfig(workDirectoryPath) )
|
|
122
|
+
);
|
|
123
|
+
|
|
124
|
+
// Start phpMyAdmin Service.
|
|
125
|
+
spinner.text = 'Starting phpMyAdmin Service';
|
|
126
|
+
|
|
127
|
+
// We need to bring the WordPress instances up again so they pick up
|
|
128
|
+
// any config changes that may have been added to the docker-compose.override.yml.
|
|
129
|
+
await dockerCompose.upMany(
|
|
130
|
+
[
|
|
131
|
+
'phpmyadmin','tests-phpmyadmin',
|
|
132
|
+
'wordpress', 'tests-wordpress',
|
|
133
|
+
'cli', 'tests-cli'
|
|
134
|
+
], {
|
|
135
|
+
cwd: workDirectoryPath,
|
|
136
|
+
commandOptions: ['--build', '--force-recreate'],
|
|
137
|
+
log: debug
|
|
138
|
+
})
|
|
139
|
+
|
|
140
|
+
spinner.text = 'Configuring CAWebPublishing Environments...';
|
|
141
|
+
|
|
142
|
+
// Make CAWeb WordPress Configurations.
|
|
143
|
+
await Promise.all( [
|
|
144
|
+
retry( () => configureCAWeb( 'development', config, spinner ), {
|
|
145
|
+
times: 2,
|
|
146
|
+
} ),
|
|
147
|
+
retry( () => configureCAWeb( 'tests', config, spinner ), {
|
|
148
|
+
times: 2,
|
|
149
|
+
} ),
|
|
150
|
+
] );
|
|
151
|
+
|
|
152
|
+
spinner.prefixText = preText +
|
|
153
|
+
`phpMyAdmin development site started at http://localhost:8080\n` +
|
|
154
|
+
`phpMyAdmin development site started at http://localhost:9090\n\n`;
|
|
155
|
+
|
|
156
|
+
spinner.text = 'Done!';
|
|
157
|
+
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
};
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
/**
|
|
3
|
+
* External dependencies
|
|
4
|
+
*/
|
|
5
|
+
const path = require( 'path' );
|
|
6
|
+
const fs = require( 'fs-extra' );
|
|
7
|
+
const SimpleGit = require( 'simple-git' );
|
|
8
|
+
const { execSync } = require( 'child_process' );
|
|
9
|
+
const dockerCompose = require( 'docker-compose' );
|
|
10
|
+
const loadConfig = require( '@wordpress/env/lib/config/load-config' );
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Internal dependencies
|
|
14
|
+
*/
|
|
15
|
+
const {
|
|
16
|
+
runDockerCmd,
|
|
17
|
+
} = require('../caweb');
|
|
18
|
+
|
|
19
|
+
const { buildWPEnvConfig, buildDockerComposeConfig } = require('../configs');
|
|
20
|
+
|
|
21
|
+
const pkg = require( '../../package.json' );
|
|
22
|
+
const { CAWEB_OPTIONS } = require('../options');
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Promisified dependencies
|
|
27
|
+
*/
|
|
28
|
+
const { writeFile } = fs.promises;
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Test code.
|
|
32
|
+
*
|
|
33
|
+
* @param {Object} options
|
|
34
|
+
* @param {Object} options.spinner A CLI spinner which indicates progress.
|
|
35
|
+
* @param {boolean} options.environment Which environment to test in.
|
|
36
|
+
*/
|
|
37
|
+
module.exports = async function test({
|
|
38
|
+
spinner,
|
|
39
|
+
environment
|
|
40
|
+
}) {
|
|
41
|
+
|
|
42
|
+
try {
|
|
43
|
+
const config = await loadConfig(path.resolve('.'));
|
|
44
|
+
/*
|
|
45
|
+
let themeOptions = [];
|
|
46
|
+
|
|
47
|
+
Object.entries(config.env[ 'development' ].config).forEach(([k,v]) => {
|
|
48
|
+
// if the option is prefixed with CAWEB_ and is a valid CAWeb Option.
|
|
49
|
+
if ( `${k}`.startsWith('CAWEB_') && undefined !== CAWEB_OPTIONS[k] ){
|
|
50
|
+
console.log(CAWEB_OPTIONS[k])
|
|
51
|
+
// set the option.
|
|
52
|
+
themeOptions.push(
|
|
53
|
+
`wp option set '${CAWEB_OPTIONS[k]}' "${v}"`
|
|
54
|
+
);
|
|
55
|
+
}
|
|
56
|
+
})
|
|
57
|
+
|
|
58
|
+
console.log(themeOptions);
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
// Write CAWeb .wp-env.json file.
|
|
62
|
+
await writeFile(
|
|
63
|
+
path.join(process.cwd(), '.wp-env.json'),
|
|
64
|
+
JSON.stringify( buildWPEnvConfig({bare: false}), null, 4 )
|
|
65
|
+
);
|
|
66
|
+
|
|
67
|
+
let result = await runDockerCmd( {
|
|
68
|
+
spinner,
|
|
69
|
+
environment,
|
|
70
|
+
cmds: [`wp option set 'ca_site_version' "5.5"`]
|
|
71
|
+
})
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
Object.entries(result).forEach((k,v) => {
|
|
75
|
+
//console.log(`${k}:${v}`)
|
|
76
|
+
})
|
|
77
|
+
|
|
78
|
+
//console.log(`Result: ${result}`)
|
|
79
|
+
*/
|
|
80
|
+
|
|
81
|
+
} catch(error) {
|
|
82
|
+
console.log(error)
|
|
83
|
+
|
|
84
|
+
process.exit( 1 );
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
};
|
package/lib/configs.js
ADDED
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* External dependencies
|
|
3
|
+
*/
|
|
4
|
+
const path = require( 'path' );
|
|
5
|
+
const fs = require('fs-extra');
|
|
6
|
+
const pkg = require( '../package.json' );
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Build .wp-env.json
|
|
11
|
+
*
|
|
12
|
+
* @param {boolean} options.bare True if excluding any CAWeb Configurations.
|
|
13
|
+
* @returns object
|
|
14
|
+
*/
|
|
15
|
+
const buildWPEnvConfig = ({bare}) => {
|
|
16
|
+
let config = {
|
|
17
|
+
core: `WordPress/WordPress#${pkg.config.WP_VER}`,
|
|
18
|
+
phpVersion: `${pkg.config.PHP_VER}`,
|
|
19
|
+
config: {
|
|
20
|
+
...pkg.config.DEFAULTS
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
// if not bare then include our theme.
|
|
25
|
+
if( ! bare ){
|
|
26
|
+
config['themes'] = [`CA-CODE-Works/CAWeb`];
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
return config;
|
|
30
|
+
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Build docker-compose.override.yml
|
|
35
|
+
*
|
|
36
|
+
* @param {string} workDirectoryPath Path to the work directory located in ~/.wp-env.
|
|
37
|
+
* @returns object
|
|
38
|
+
*/
|
|
39
|
+
const buildDockerComposeConfig = (workDirectoryPath) => {
|
|
40
|
+
let dockerConfig = {
|
|
41
|
+
version: '3.7',
|
|
42
|
+
services: {
|
|
43
|
+
phpmyadmin: {
|
|
44
|
+
image: `phpmyadmin:latest`,
|
|
45
|
+
restart: 'always',
|
|
46
|
+
ports: ['8080:80'],
|
|
47
|
+
environment: {
|
|
48
|
+
PMA_HOST : 'mysql',
|
|
49
|
+
UPLOAD_LIMIT: '3G',
|
|
50
|
+
MEMORY_LIMIT: '5G',
|
|
51
|
+
MAX_EXECUTION_TIME: 7200
|
|
52
|
+
}
|
|
53
|
+
},
|
|
54
|
+
"tests-phpmyadmin": {
|
|
55
|
+
image: `phpmyadmin:latest`,
|
|
56
|
+
restart: 'always',
|
|
57
|
+
ports: ['9090:80'],
|
|
58
|
+
environment: {
|
|
59
|
+
PMA_HOST : 'tests-mysql',
|
|
60
|
+
UPLOAD_LIMIT: '3G',
|
|
61
|
+
MEMORY_LIMIT: '5G',
|
|
62
|
+
MAX_EXECUTION_TIME: 7200
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
let extraVolumes = [];
|
|
70
|
+
|
|
71
|
+
// Divi theme to wordpress services volumes.
|
|
72
|
+
if( fs.existsSync(path.join(workDirectoryPath, 'Divi')) ){
|
|
73
|
+
extraVolumes = extraVolumes.concat(path.join(workDirectoryPath, 'Divi') + ':/var/www/html/wp-content/themes/Divi');
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// Divi plugin to wordpress services volumes.
|
|
77
|
+
if( fs.existsSync(path.join(workDirectoryPath, 'divi-builder')) ){
|
|
78
|
+
extraVolumes = extraVolumes.concat(path.join(workDirectoryPath, 'divi-builder') + ':/var/www/html/wp-content/plugins/divi-builder');
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// Add extra volumes to WordPress instances.
|
|
82
|
+
if( extraVolumes.length ){
|
|
83
|
+
|
|
84
|
+
dockerConfig.services.wordpress = {
|
|
85
|
+
build: {
|
|
86
|
+
context: '.',
|
|
87
|
+
dockerfile: 'WordPress.Dockerfile'
|
|
88
|
+
},
|
|
89
|
+
volumes: extraVolumes,
|
|
90
|
+
};
|
|
91
|
+
dockerConfig.services.cli = {
|
|
92
|
+
build: {
|
|
93
|
+
context: '.',
|
|
94
|
+
dockerfile: 'CLI.Dockerfile'
|
|
95
|
+
},
|
|
96
|
+
volumes: extraVolumes,
|
|
97
|
+
};
|
|
98
|
+
dockerConfig.services['tests-wordpress'] = {
|
|
99
|
+
build: {
|
|
100
|
+
context: '.',
|
|
101
|
+
dockerfile: 'Tests-WordPress.Dockerfile'
|
|
102
|
+
},
|
|
103
|
+
volumes: extraVolumes,
|
|
104
|
+
};
|
|
105
|
+
dockerConfig.services['tests-cli'] = {
|
|
106
|
+
build: {
|
|
107
|
+
context: '.',
|
|
108
|
+
dockerfile: 'Tests-CLI.Dockerfile'
|
|
109
|
+
},
|
|
110
|
+
volumes: extraVolumes,
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
return dockerConfig;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
module.exports = {
|
|
118
|
+
buildWPEnvConfig,
|
|
119
|
+
buildDockerComposeConfig
|
|
120
|
+
}
|
|
@@ -0,0 +1,256 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Modified from wp-env 8.11.0
|
|
3
|
+
* Few modifications made:
|
|
4
|
+
* - Downloads CAWebPublishing Resources, excluding WordPress.
|
|
5
|
+
* - Target directory for downloadZipSource is expected to be absolute.
|
|
6
|
+
* - Ensure parent directory of source.path exists before attempting to extract in downloadZipSource, otherwise it will complain that file/directory doesn't exist.
|
|
7
|
+
* @see @wordpress/env/lib/download-sources.js
|
|
8
|
+
*/
|
|
9
|
+
'use strict';
|
|
10
|
+
/**
|
|
11
|
+
* External dependencies
|
|
12
|
+
*/
|
|
13
|
+
const util = require( 'util' );
|
|
14
|
+
const path = require( 'path' );
|
|
15
|
+
const fs = require( 'fs-extra' );
|
|
16
|
+
const SimpleGit = require( 'simple-git' );
|
|
17
|
+
const got = require( 'got' );
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Internal dependencies
|
|
21
|
+
*/
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Promisified dependencies
|
|
25
|
+
*/
|
|
26
|
+
const pipeline = util.promisify( require( 'stream' ).pipeline );
|
|
27
|
+
const extractZip = util.promisify( require( 'extract-zip' ) );
|
|
28
|
+
const rimraf = util.promisify( require( 'rimraf' ) );
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Download CAWeb Resources.
|
|
32
|
+
*
|
|
33
|
+
* @param {Object} spinner The spinner object to show progress.
|
|
34
|
+
* @return {WPConfig} The config object we've loaded.
|
|
35
|
+
*/
|
|
36
|
+
async function downloadSources(
|
|
37
|
+
{
|
|
38
|
+
spinner,
|
|
39
|
+
config
|
|
40
|
+
}
|
|
41
|
+
) {
|
|
42
|
+
const progresses = {};
|
|
43
|
+
const getProgressSetter = ( id ) => ( progress ) => {
|
|
44
|
+
progresses[ id ] = progress;
|
|
45
|
+
spinner.text =
|
|
46
|
+
`Downloading ${id}.\n` +
|
|
47
|
+
Object.entries( progresses )
|
|
48
|
+
.map(
|
|
49
|
+
( [ key, value ] ) =>
|
|
50
|
+
` - ${ key }: ${ ( value * 100 ).toFixed( 0 ) }/100%`
|
|
51
|
+
)
|
|
52
|
+
.join( '\n' );
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
const { workDirectoryPath } = config;
|
|
56
|
+
const { development: dev, tests: test } = config.env;
|
|
57
|
+
let sources = [];
|
|
58
|
+
|
|
59
|
+
// Add Divi Theme and plugin to sources.
|
|
60
|
+
if( (undefined !== dev.config.ET_USERNAME &&
|
|
61
|
+
undefined !== dev.config.ET_API_KEY) ||
|
|
62
|
+
(undefined !== test.config.ET_USERNAME &&
|
|
63
|
+
undefined !== test.config.ET_API_KEY)
|
|
64
|
+
){
|
|
65
|
+
let url = 'https://www.elegantthemes.com/api/api_downloads.php';
|
|
66
|
+
let user = undefined !== dev.config.ET_USERNAME ? dev.config.ET_USERNAME : test.config.ET_USERNAME;
|
|
67
|
+
let key = undefined !== dev.config.ET_API_KEY ? dev.config.ET_API_KEY : test.config.ET_API_KEY;
|
|
68
|
+
|
|
69
|
+
// Add Divi sources.
|
|
70
|
+
sources = sources.concat( [
|
|
71
|
+
{
|
|
72
|
+
basename: 'Divi',
|
|
73
|
+
url: `${url}?api_update=1&theme=Divi&api_key=${key}&username=${user}`,
|
|
74
|
+
path: path.join(workDirectoryPath, 'Divi'),
|
|
75
|
+
type: 'zip'
|
|
76
|
+
},
|
|
77
|
+
{
|
|
78
|
+
basename: 'Divi Plugin',
|
|
79
|
+
url: `${url}?api_update=1&theme=divi-builder&api_key=${key}&username=${user}`,
|
|
80
|
+
path: path.join(workDirectoryPath, 'divi-builder'),
|
|
81
|
+
type: 'zip'
|
|
82
|
+
}
|
|
83
|
+
]);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
// filter any undefined sources.
|
|
88
|
+
/*sources = sources.filter(function( element ) {
|
|
89
|
+
return element !== undefined;
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
*/
|
|
93
|
+
await Promise.all(
|
|
94
|
+
sources.map( ( source ) =>
|
|
95
|
+
downloadSource( source, {
|
|
96
|
+
onProgress: getProgressSetter( source.basename ),
|
|
97
|
+
spinner,
|
|
98
|
+
} )
|
|
99
|
+
)
|
|
100
|
+
);
|
|
101
|
+
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Downloads the given source if necessary. The specific action taken depends
|
|
106
|
+
* on the source type. The source is downloaded to source.path.
|
|
107
|
+
*
|
|
108
|
+
* @param {WPSource} source The source to download.
|
|
109
|
+
* @param {Object} options
|
|
110
|
+
* @param {Function} options.onProgress A function called with download progress. Will be invoked with one argument: a number that ranges from 0 to 1 which indicates current download progress for this source.
|
|
111
|
+
* @param {Object} options.spinner A CLI spinner which indicates progress.
|
|
112
|
+
* @param {boolean} options.debug True if debug mode is enabled.
|
|
113
|
+
*/
|
|
114
|
+
async function downloadSource(src, { onProgress, spinner, debug } ){
|
|
115
|
+
if( 'git' == src.type ){
|
|
116
|
+
await downloadGitSource(src, { onProgress, spinner, debug });
|
|
117
|
+
}else if( 'zip' == src.type ) {
|
|
118
|
+
await downloadZipSource(src, { onProgress, spinner, debug });
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Clones the git repository at `source.url` into `source.path`. If the
|
|
125
|
+
* repository already exists, it is updated instead.
|
|
126
|
+
*
|
|
127
|
+
* @param {WPSource} source The source to download.
|
|
128
|
+
* @param {Object} options
|
|
129
|
+
* @param {Function} options.onProgress A function called with download progress. Will be invoked with one argument: a number that ranges from 0 to 1 which indicates current download progress for this source.
|
|
130
|
+
* @param {Object} options.spinner A CLI spinner which indicates progress.
|
|
131
|
+
* @param {boolean} options.debug True if debug mode is enabled.
|
|
132
|
+
*/
|
|
133
|
+
async function downloadGitSource( source, { onProgress, spinner, debug } ) {
|
|
134
|
+
const log = debug
|
|
135
|
+
? ( message ) => {
|
|
136
|
+
spinner.info( `SimpleGit: ${ message }` );
|
|
137
|
+
spinner.start();
|
|
138
|
+
}
|
|
139
|
+
: () => {};
|
|
140
|
+
onProgress( 0 );
|
|
141
|
+
|
|
142
|
+
const progressHandler = ( { progress } ) => {
|
|
143
|
+
onProgress( progress / 100 );
|
|
144
|
+
};
|
|
145
|
+
|
|
146
|
+
log( 'Cloning or getting the repo.' );
|
|
147
|
+
const git = SimpleGit( { progress: progressHandler } );
|
|
148
|
+
|
|
149
|
+
const isRepo =
|
|
150
|
+
fs.existsSync( source.clonePath ) &&
|
|
151
|
+
( await git.cwd( source.clonePath ).checkIsRepo( 'root' ) );
|
|
152
|
+
|
|
153
|
+
// repository already exists.
|
|
154
|
+
if ( isRepo ) {
|
|
155
|
+
log( 'Repo already exists, using it.' );
|
|
156
|
+
} else {
|
|
157
|
+
// repository doesn't exists, but the directory does.
|
|
158
|
+
if( fs.existsSync( source.clonePath ) ){
|
|
159
|
+
// reinitialize repo.
|
|
160
|
+
await git.cwd( source.clonePath );
|
|
161
|
+
|
|
162
|
+
await git.init().addRemote('origin', source.url );
|
|
163
|
+
}else{
|
|
164
|
+
|
|
165
|
+
await git.clone( source.url, source.clonePath, {
|
|
166
|
+
'--depth': '1',
|
|
167
|
+
'--no-single-branch': null
|
|
168
|
+
} );
|
|
169
|
+
await git.cwd( source.clonePath );
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
log( 'Fetching the specified ref.' );
|
|
174
|
+
await git.fetch( 'origin', source.ref, {
|
|
175
|
+
'--tags': null,
|
|
176
|
+
} );
|
|
177
|
+
|
|
178
|
+
log( 'Checking out the specified ref.' );
|
|
179
|
+
await git.checkout( source.ref, {
|
|
180
|
+
'--force': null
|
|
181
|
+
});
|
|
182
|
+
|
|
183
|
+
onProgress( 1 );
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
/**
|
|
187
|
+
* Downloads and extracts the zip file at `source.url` into `source.path`.
|
|
188
|
+
*
|
|
189
|
+
* @param {WPSource} source The source to download.
|
|
190
|
+
* @param {Object} options
|
|
191
|
+
* @param {Function} options.onProgress A function called with download progress. Will be invoked with one argument: a number that ranges from 0 to 1 which indicates current download progress for this source.
|
|
192
|
+
* @param {Object} options.spinner A CLI spinner which indicates progress.
|
|
193
|
+
* @param {boolean} options.debug True if debug mode is enabled.
|
|
194
|
+
*/
|
|
195
|
+
async function downloadZipSource( source, { onProgress, spinner, debug } ) {
|
|
196
|
+
const log = debug
|
|
197
|
+
? ( message ) => {
|
|
198
|
+
spinner.info( `NodeGit: ${ message }` );
|
|
199
|
+
spinner.start();
|
|
200
|
+
}
|
|
201
|
+
: () => {};
|
|
202
|
+
onProgress( 0 );
|
|
203
|
+
|
|
204
|
+
log( 'Downloading zip file.' );
|
|
205
|
+
const zipName = `${ source.path }.zip`;
|
|
206
|
+
const zipFile = fs.createWriteStream( zipName );
|
|
207
|
+
const responseStream = got.stream( source.url );
|
|
208
|
+
responseStream.on( 'downloadProgress', ( { percent } ) =>
|
|
209
|
+
onProgress( percent )
|
|
210
|
+
);
|
|
211
|
+
|
|
212
|
+
await pipeline( responseStream, zipFile );
|
|
213
|
+
|
|
214
|
+
log( 'Extracting to temporary directory.' );
|
|
215
|
+
// Target directory is expected to be absolute.
|
|
216
|
+
const tempDir = `${ source.path }.temp`;
|
|
217
|
+
await extractZip( zipName, { dir: tempDir } );
|
|
218
|
+
|
|
219
|
+
const files = (
|
|
220
|
+
await Promise.all( [
|
|
221
|
+
rimraf( zipName ),
|
|
222
|
+
rimraf( source.path ),
|
|
223
|
+
fs.promises.readdir( tempDir ),
|
|
224
|
+
] )
|
|
225
|
+
)[ 2 ];
|
|
226
|
+
/**
|
|
227
|
+
* The plugin container is the extracted directory which is the direct parent
|
|
228
|
+
* of the contents of the plugin. It seems a zip file can have two fairly
|
|
229
|
+
* common approaches to where the content lives:
|
|
230
|
+
* 1. The .zip is the direct container of the files. So after extraction, the
|
|
231
|
+
* extraction directory contains plugin contents.
|
|
232
|
+
* 2. The .zip contains a directory with the same name which is the container.
|
|
233
|
+
* So after extraction, the extraction directory contains another directory.
|
|
234
|
+
* That subdirectory is the actual container of the plugin contents.
|
|
235
|
+
*
|
|
236
|
+
* We support both situations with the following check.
|
|
237
|
+
*/
|
|
238
|
+
let pluginContainer = tempDir;
|
|
239
|
+
const firstSubItem = path.join( tempDir, files[ 0 ] );
|
|
240
|
+
if (
|
|
241
|
+
files.length === 1 &&
|
|
242
|
+
( await fs.promises.lstat( firstSubItem ) ).isDirectory()
|
|
243
|
+
) {
|
|
244
|
+
// In this case, only one sub directory exists, so use that as the container.
|
|
245
|
+
pluginContainer = firstSubItem;
|
|
246
|
+
}
|
|
247
|
+
await fs.promises.rename( pluginContainer, source.path );
|
|
248
|
+
await rimraf( tempDir );
|
|
249
|
+
|
|
250
|
+
onProgress( 1 );
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
module.exports = {
|
|
254
|
+
downloadSources
|
|
255
|
+
|
|
256
|
+
}
|
package/lib/env.js
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
/**
|
|
3
|
+
* Internal dependencies
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
//const { ValidationError } = require( './config' );
|
|
7
|
+
//const { LifecycleScriptError } = require( './execute-lifecycle-script' );
|
|
8
|
+
const commands = require( './commands' );
|
|
9
|
+
|
|
10
|
+
module.exports = {
|
|
11
|
+
...commands
|
|
12
|
+
};
|
package/lib/options.js
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* External dependencies
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
const caweb_general_options = {
|
|
6
|
+
CAWEB_TEMPLATE_VER: 'ca_site_version', // State Template Version
|
|
7
|
+
CAWEB_NAV_MENU_STYLE: 'ca_default_navigation_menu', // Header Menu Type
|
|
8
|
+
CAWEB_COLORSCHEME: 'ca_site_color_scheme', // Color Scheme
|
|
9
|
+
CAWEB_TITLE_DISPLAY: 'ca_default_post_title_display', // Title Display Default
|
|
10
|
+
CAWEB_STICKY_NAV: 'ca_sticky_navigation', // Sticky Navigation
|
|
11
|
+
CAWEB_MENU_HOME_LINK: 'ca_home_nav_link', // Menu Home Link
|
|
12
|
+
CAWEB_DISPLAY_POSTS_DATE: 'ca_default_post_date_display', // Display Date for Non-Divi Posts
|
|
13
|
+
CAWEB_X_UA_COMPATIBILITY: 'ca_x_ua_compatibility', // Legacy Browser Support
|
|
14
|
+
CAWEB_FRONTPAGE_SEARCH: 'ca_frontpage_search_enabled', // Show Search on Front Page
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const CAWEB_OPTIONS = {
|
|
18
|
+
...caweb_general_options
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
module.exports = {
|
|
22
|
+
CAWEB_OPTIONS
|
|
23
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@caweb/cli",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "CAWebPublishing Command Line Interface.",
|
|
5
|
+
"main": "lib/env.js",
|
|
6
|
+
"files": [
|
|
7
|
+
"bin",
|
|
8
|
+
"lib"
|
|
9
|
+
],
|
|
10
|
+
"bin": {
|
|
11
|
+
"caweb": "bin/caweb"
|
|
12
|
+
},
|
|
13
|
+
"scripts": {
|
|
14
|
+
"caweb": "caweb",
|
|
15
|
+
"launch": "caweb start",
|
|
16
|
+
"pretest": "npm uninstall @caweb/cli",
|
|
17
|
+
"test": "npm pack && npm i caweb-cli-%npm_package_version%.tgz",
|
|
18
|
+
"posttest": "del caweb-cli-%npm_package_version%.tgz"
|
|
19
|
+
},
|
|
20
|
+
"repository": {
|
|
21
|
+
"type": "git",
|
|
22
|
+
"url": "git+https://github.com/CAWebPublishing/caweb-cli.git"
|
|
23
|
+
},
|
|
24
|
+
"keywords": [
|
|
25
|
+
"caweb",
|
|
26
|
+
"cagov"
|
|
27
|
+
],
|
|
28
|
+
"author": "CAWebPublishing",
|
|
29
|
+
"license": "ISC",
|
|
30
|
+
"bugs": {
|
|
31
|
+
"url": "https://github.com/CAWebPublishing/caweb-cli/issues"
|
|
32
|
+
},
|
|
33
|
+
"homepage": "https://github.com/CAWebPublishing/caweb-cli#readme",
|
|
34
|
+
"dependencies": {
|
|
35
|
+
"@wordpress/env": "^8.11.0",
|
|
36
|
+
"chalk": "^4.0.0",
|
|
37
|
+
"fs-extra": "^11.1.1"
|
|
38
|
+
},
|
|
39
|
+
"config": {
|
|
40
|
+
"WP_VER": "6.3.1",
|
|
41
|
+
"PHP_VER": "8.1",
|
|
42
|
+
"DEFAULTS": {
|
|
43
|
+
"WP_DEFAULT_THEME": "CAWeb",
|
|
44
|
+
"FS_METHOD": "direct",
|
|
45
|
+
"WP_DEBUG": true,
|
|
46
|
+
"WP_DEBUG_LOG": true,
|
|
47
|
+
"WP_DEBUG_DISPLAY": false,
|
|
48
|
+
"ADMIN_COOKIE_PATH": "/",
|
|
49
|
+
"COOKIE_DOMAIN": "",
|
|
50
|
+
"COOKIEPATH": "",
|
|
51
|
+
"SITECOOKIEPATH": ""
|
|
52
|
+
}
|
|
53
|
+
},
|
|
54
|
+
"directories": {
|
|
55
|
+
"doc": "docs",
|
|
56
|
+
"lib": "lib"
|
|
57
|
+
},
|
|
58
|
+
"devDependencies": {}
|
|
59
|
+
}
|