@caweb/cli 1.11.2 → 1.12.1

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.
@@ -53,19 +53,18 @@ async function activateCAWeb(
53
53
  * @param {Object} spinner A CLI spinner which indicates progress.
54
54
  */
55
55
  async function configureCAWeb( environment, config, spinner ) {
56
-
57
56
 
58
57
  const isThemeActivated = await activateCAWeb( environment, config );
59
58
 
60
- const {
61
- DESIGN_SYSTEM_ENABLED
62
- } = config.env[ environment ].config
63
-
64
59
  // if our theme is active.
65
60
  if( false !== isThemeActivated ){
61
+
66
62
  spinner.text = `Configuring CAWebPublishing ${environment} Environment...`;
67
63
 
68
- let themeOptions = [];
64
+ // lets set the default theme to CAWeb.
65
+ let themeOptions = [
66
+ 'wp config set WP_DEFAULT_THEME CAWeb',
67
+ ];
69
68
 
70
69
  // iterate over config options.
71
70
  Object.entries(config.env[ environment ].config).forEach(([k,v]) => {
@@ -104,21 +103,8 @@ async function configureCAWeb( environment, config, spinner ) {
104
103
  times: 2,
105
104
  } ),
106
105
  ] );
106
+
107
107
  }
108
-
109
- // Activate Design System plugin
110
- if( undefined !== DESIGN_SYSTEM_ENABLED && DESIGN_SYSTEM_ENABLED ){
111
- await runCLICmds(
112
- environment,
113
- [
114
- 'wp plugin is-installed design-system-wordpress',
115
- 'wp plugin activate design-system-wordpress'
116
- ],
117
- config,
118
- spinner
119
- )
120
- }
121
-
122
108
 
123
109
  }
124
110
 
@@ -17,6 +17,7 @@ import got from 'got';
17
17
  import stream from 'stream';
18
18
  import zip from 'extract-zip';
19
19
  import { rimraf } from 'rimraf';
20
+ import { env } from 'process';
20
21
 
21
22
  /**
22
23
  * Internal dependencies
@@ -176,11 +177,25 @@ async function downloadZipSource( source, { onProgress, spinner, debug } ) {
176
177
  onProgress( 1 );
177
178
  }
178
179
 
179
- function dowloadPlugins(pluginDir){
180
+ function defaultSources(pluginDir, themeDir){
180
181
  return [
182
+ {
183
+ basename: 'CAWeb Theme',
184
+ url: 'https://github.com/CAWebPublishing/CAWeb/archive/refs/tags/1.13.3.zip',
185
+ path: path.join(themeDir, 'CAWeb'),
186
+ type: 'zip',
187
+
188
+ },
189
+ {
190
+ basename: 'CAWebPublishing Development Plugin',
191
+ url: 'https://github.com/CAWebPublishing/caweb-dev/archive/refs/tags/1.1.1.zip',
192
+ path: path.join(pluginDir, 'caweb-dev'),
193
+ type: 'zip',
194
+
195
+ },
181
196
  {
182
197
  basename: 'Query Monitor',
183
- url: 'https://downloads.wordpress.org/plugin/query-monitor.3.15.0.zip',
198
+ url: 'https://downloads.wordpress.org/plugin/query-monitor.3.17.2.zip',
184
199
  path: path.join(pluginDir, 'query-monitor'),
185
200
  type: 'zip',
186
201
 
@@ -191,10 +206,11 @@ function dowloadPlugins(pluginDir){
191
206
  /**
192
207
  * Download CAWeb Resources.
193
208
  *
209
+ * @param {WPEnvironment} environment The environment to configure. Either 'development' or 'tests'.
194
210
  * @param {Object} spinner The spinner object to show progress.
195
211
  * @return {WPConfig} The config object we've loaded.
196
212
  */
197
- export async function downloadSources(
213
+ export async function downloadSources( environment,
198
214
  {
199
215
  spinner,
200
216
  config
@@ -216,10 +232,12 @@ export async function downloadSources(
216
232
  const { workDirectoryPath } = config;
217
233
  const { development: dev, tests: test } = config.env;
218
234
 
219
- let pluginDir = path.resolve(workDirectoryPath, 'plugins');
220
- let themeDir = path.resolve(workDirectoryPath, 'themes');
235
+ let instance = ('tests' === environment ? 'Tests-' : '') + 'WordPress';
236
+
237
+ let pluginDir = path.resolve(workDirectoryPath, instance , 'wp-content' , 'plugins');
238
+ let themeDir = path.resolve(workDirectoryPath, instance, 'wp-content' , 'themes');
221
239
 
222
- let sources = dowloadPlugins(pluginDir);
240
+ let sources = defaultSources(pluginDir, themeDir);
223
241
 
224
242
  // Add Divi Theme and plugin to sources.
225
243
  if( (undefined !== dev.config.ET_USERNAME &&
@@ -249,16 +267,20 @@ export async function downloadSources(
249
267
  }
250
268
 
251
269
  // Ensure plugin/theme directory exists for downloading resources.
252
- fs.ensureDir(themeDir);
253
- fs.ensureDir(pluginDir);
254
-
255
- await Promise.all(
256
- sources.map( ( source ) =>
257
- downloadSource( source, {
258
- onProgress: getProgressSetter( source.basename ),
259
- spinner,
260
- } )
261
- )
270
+ // fs.ensureDir(themeDir);
271
+ // fs.ensureDir(pluginDir);
272
+
273
+ await Promise.all(
274
+ sources.map( ( source ) => {
275
+ if( 'development' === environment ){
276
+ downloadSource( source, {
277
+ onProgress: getProgressSetter( source.basename ),
278
+ spinner,
279
+ } )
280
+ }else{
281
+ downloadSource( source, {onProgress: () => {}, spinner} )
282
+ }
283
+ })
262
284
  );
263
285
 
264
286
  };
@@ -5,8 +5,6 @@
5
5
  /**
6
6
  * Missing options.
7
7
  *
8
- * CAWEB_FAV_ICON
9
- * CAWEB_ORG_LOGO
10
8
  * Social Media Links
11
9
  * Custom CSS/JS
12
10
  * Alert Banners
@@ -15,47 +13,47 @@
15
13
  * @todo Add missing options.
16
14
  */
17
15
  const caweb_general_options = {
18
- CAWEB_TEMPLATE_VER: {
19
- name: 'ca_site_version',
20
- defaultValue: '5.5',
21
- label: 'State Template Version'
16
+ CAWEB_FAV_ICON: {
17
+ name: 'ca_fav_ico',
18
+ defaultValue: '',
19
+ label: 'Fav Icon'
22
20
  },
23
- CAWEB_NAV_MENU_STYLE: {
21
+ CAWEB_NAV_MENU_STYLE: {
24
22
  name: 'ca_default_navigation_menu',
25
23
  defaultValue: 'singlelevel',
26
24
  label: 'Header Menu Type'
27
25
  },
28
- CAWEB_COLORSCHEME: {
26
+ CAWEB_COLORSCHEME: {
29
27
  name: 'ca_site_color_scheme',
30
28
  defaultValue: 'oceanside',
31
29
  label: 'Color Scheme'
32
30
  },
33
- CAWEB_TITLE_DISPLAY: {
31
+ CAWEB_TITLE_DISPLAY: {
34
32
  name: 'ca_default_post_title_display',
35
33
  defaultValue: false,
36
34
  label: 'Title Display Default'
37
35
  },
38
- CAWEB_STICKY_NAV: {
36
+ CAWEB_STICKY_NAV: {
39
37
  name: 'ca_sticky_navigation',
40
38
  defaultValue: false,
41
39
  label: 'Sticky Navigation'
42
40
  },
43
- CAWEB_MENU_HOME_LINK: {
41
+ CAWEB_MENU_HOME_LINK: {
44
42
  name: 'ca_home_nav_link',
45
43
  defaultValue: false,
46
44
  label: 'Menu Home Link'
47
45
  },
48
- CAWEB_DISPLAY_POSTS_DATE: {
46
+ CAWEB_DISPLAY_POSTS_DATE: {
49
47
  name: 'ca_default_post_date_display',
50
48
  defaultValue: false,
51
49
  label: 'Display Date for Non-Divi Posts'
52
50
  },
53
- CAWEB_X_UA_COMPATIBILITY: {
51
+ CAWEB_X_UA_COMPATIBILITY: {
54
52
  name: 'ca_x_ua_compatibility',
55
53
  defaultValue: false,
56
54
  label: 'Legacy Browser Support'
57
55
  },
58
- CAWEB_FRONTPAGE_SEARCH: {
56
+ CAWEB_FRONTPAGE_SEARCH: {
59
57
  name: 'ca_frontpage_search_enabled',
60
58
  defaultValue: false,
61
59
  label: 'Show Search on Front Page'
@@ -107,8 +105,13 @@ const caweb_utility_header_options = {
107
105
  };
108
106
 
109
107
  const page_header_options = {
110
- CAWEB_CAWEB_ORG_LOGO_ALT_TEXT: {
111
- name: '',
108
+ CAWEB_ORG_LOGO: {
109
+ name: 'header_ca_branding',
110
+ defaultValue: '',
111
+ label: 'Organization Logo-Brand'
112
+ },
113
+ CAWEB_ORG_LOGO_ALT_TEXT: {
114
+ name: 'header_ca_branding_alt_text',
112
115
  defaultValue: '',
113
116
  label: 'Organization Logo-Alt Text'
114
117
  }
@@ -181,7 +184,7 @@ const github_options = {
181
184
  };
182
185
 
183
186
  const CAWEB_OPTIONS = {
184
- ...caweb_general_options,
187
+ ...caweb_general_options,
185
188
  ...caweb_utility_header_options,
186
189
  ...page_header_options,
187
190
  ...google_options,
@@ -254,6 +257,6 @@ const DIVI_OPTIONS = {
254
257
  }
255
258
 
256
259
  export {
257
- CAWEB_OPTIONS,
260
+ CAWEB_OPTIONS,
258
261
  DIVI_OPTIONS
259
262
  }
@@ -3,12 +3,11 @@
3
3
  */
4
4
  import fs from 'fs';
5
5
  import path from 'path';
6
-
6
+ import yaml from 'js-yaml';
7
7
  /**
8
8
  * Internal dependencies
9
9
  */
10
- import {runCLICmds} from '../helpers.js';
11
-
10
+ import {appPath, runCLICmds} from '../helpers.js';
12
11
 
13
12
  /**
14
13
  * Checks whether WordPress environment is a multisite installation.
@@ -44,7 +43,8 @@ async function isMultisite( environment, config, spinner ){
44
43
  * @returns
45
44
  */
46
45
  async function convertToMultisite( environment, config, subdomain, spinner ){
47
- // before we can conver to multisite all plugins must be deactivated.
46
+
47
+ // before we can convert to multisite all plugins must be deactivated.
48
48
  // first lets get all plugins
49
49
  let activePlugins = await runCLICmds(
50
50
  environment,
@@ -65,23 +65,16 @@ async function convertToMultisite( environment, config, subdomain, spinner ){
65
65
  )
66
66
  }
67
67
 
68
- // convert to multisite.
69
- let command = 'wp core multisite-convert';
70
-
71
- if( subdomain ){
72
- command += ' --subdomains'
73
- }
74
-
75
68
  await runCLICmds(
76
69
  environment,
77
- [command],
70
+ [
71
+ // convert to multisite.
72
+ 'wp core multisite-convert' + ( subdomain ? ' --subdomains' : '' ),
73
+ ],
78
74
  config,
79
75
  spinner
80
76
  )
81
77
 
82
- // generate .htaccess
83
- await generateHTAccess( environment, config.workDirectoryPath, subdomain );
84
-
85
78
  // network activate all active plugins again.
86
79
  if( activePlugins.length ){
87
80
  await runCLICmds(
@@ -97,15 +90,39 @@ async function convertToMultisite( environment, config, subdomain, spinner ){
97
90
  /**
98
91
  * Generates .htaccess file content.
99
92
  *
100
- * @param {string} environment Which environment to generate .htaccess for.
93
+ * @param {string} environment Which environment to generate .htaccess for.
94
+ * @param {boolean} multisite True if converting to multisite.
101
95
  * @param {boolean} subdomain True if converting to multisite subdomain.
102
96
  */
103
- async function generateHTAccess(environment, workDirectoryPath, subdomain){
104
- let trailingSlash = subdomain ? '^wp-admin$ wp-admin/ [R=301,L]' : '^([_0-9a-zA-Z-]+/)?wp-admin$ $1wp-admin/';
105
- let writeRule1 = subdomain ? '^(wp-(content|admin|includes).*) $1 [L]' : '^([_0-9a-zA-Z-]+/)?(wp-(content|admin|includes).*) $2 [L]';
106
- let writeRule2 = subdomain ? '^(.*\.php)$ $1 [L]' : '^([_0-9a-zA-Z-]+/)?(.*\.php)$ $2 [L]';
97
+ async function generateHTAccess(environment, workDirectoryPath, multisite, subdomain){
98
+ let folder = 'development' === environment ? 'WordPress' : 'Tests-WordPress';
107
99
 
100
+ // if .htaccess already exists, no need to generate.
101
+ if( fs.existsSync(path.join(workDirectoryPath, folder, '.htaccess')) ){
102
+ return; // .htaccess already exists, no need to generate.
103
+ }
104
+
105
+ // default htaccess for single site.
108
106
  let htaccess = `
107
+ <IfModule mod_rewrite.c>
108
+ RewriteEngine On
109
+ RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
110
+ RewriteBase /
111
+ RewriteRule ^index\.php$ - [L]
112
+ RewriteCond %{REQUEST_FILENAME} !-f
113
+ RewriteCond %{REQUEST_FILENAME} !-d
114
+ RewriteRule . /index.php [L]
115
+ </IfModule>
116
+ `;
117
+
118
+
119
+ // if multisite, we need to add the multisite rules.
120
+ if( multisite ){
121
+ let trailingSlash = subdomain ? '^wp-admin$ wp-admin/ [R=301,L]' : '^([_0-9a-zA-Z-]+/)?wp-admin$ $1wp-admin/';
122
+ let writeRule1 = subdomain ? '^(wp-(content|admin|includes).*) $1 [L]' : '^([_0-9a-zA-Z-]+/)?(wp-(content|admin|includes).*) $2 [L]';
123
+ let writeRule2 = subdomain ? '^(.*\.php)$ $1 [L]' : '^([_0-9a-zA-Z-]+/)?(.*\.php)$ $2 [L]';
124
+
125
+ htaccess = `
109
126
  RewriteEngine On
110
127
  RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
111
128
  RewriteBase /
@@ -120,14 +137,68 @@ async function generateHTAccess(environment, workDirectoryPath, subdomain){
120
137
  RewriteRule ${writeRule1}
121
138
  RewriteRule ${writeRule2}
122
139
  RewriteRule . index.php [L]
123
- `.replace(/\t/g, '').trim();
140
+ `;
141
+ }
142
+
143
+ // write the .htaccess file.
144
+ fs.writeFileSync(path.join(workDirectoryPath, folder, '.htaccess'), htaccess.replace(/\t/g, '').trim());
145
+
146
+ }
147
+
148
+ /**
149
+ * Configures the application password for the given environment.
150
+ *
151
+ * @param {WPEnvironment} environment The environment to configure. Either 'development' or 'tests'.
152
+ * @param {WPConfig} config The wp-env config object.
153
+ * @param {Object} spinner A CLI spinner which indicates progress.
154
+ */
155
+ async function configureApplicationPassword( environment, config, spinner ){
156
+ let cawebJson = fs.existsSync( path.join(appPath, 'caweb.json') ) ?
157
+ JSON.parse(fs.readFileSync(path.join(appPath, 'caweb.json')))
158
+ : {};
159
+
160
+ // Check if application password exists.
161
+ const exists = await runCLICmds(
162
+ environment,
163
+ [ 'wp user application-password exists 1 caweb' ],
164
+ config, spinner
165
+ )
166
+
167
+ if( exists ){
168
+ const uuid = await runCLICmds(
169
+ environment,
170
+ [ 'wp user application-password list 1 --field=uuid --name=caweb --porcelain' ],
171
+ config, spinner
172
+ );
124
173
 
125
- let folder = 'development' === environment ? 'WordPress' : 'Tests-WordPress'
174
+ // delete the existing application password.
175
+ await runCLICmds(
176
+ environment,
177
+ [ `wp user application-password delete 1 ${uuid}` ],
178
+ config, spinner
179
+ )
180
+ }
126
181
 
127
- fs.writeFileSync(path.join(workDirectoryPath, folder, '.htaccess'), htaccess);
182
+ let pwd = await runCLICmds(
183
+ environment,
184
+ [ 'wp user application-password create 1 caweb --porcelain' ],
185
+ config, spinner
186
+ )
187
+
188
+ cawebJson['sync']['local'] = {
189
+ 'url': config.env.development.config?.WP_SITEURL || 'http://localhost:8888',
190
+ 'user': 'admin',
191
+ pwd,
192
+ }
128
193
 
194
+ // update the caweb.json file with the new sync information.
195
+ fs.writeFileSync(
196
+ path.join(appPath, 'caweb.json'),
197
+ JSON.stringify(cawebJson, null, 4)
198
+ );
129
199
  }
130
200
 
201
+
131
202
  /**
132
203
  * Configures WordPress for the given environment by installing WordPress,
133
204
  * activating all plugins, and activating the first theme. These steps are
@@ -140,32 +211,36 @@ async function generateHTAccess(environment, workDirectoryPath, subdomain){
140
211
  * @param {boolean} subdomain True if converting to multisite subdomain.
141
212
  */
142
213
  async function configureWordPress(environment, config, spinner, multisite, subdomain){
143
- const { workDirectoryPath} = config;
144
214
  const {
145
215
  WP_PERMALINK
146
216
  } = config.env[ environment ].config
147
217
 
218
+ // Create an Application Password for the user.
219
+ await configureApplicationPassword( environment, config, spinner );
148
220
 
149
221
  // Convert to multisite if flag was passed.
150
222
  if( multisite ){
151
- spinner.text = 'Converting to multisite ' + ( subdomain ? 'subdomain' : 'subdirectory') + '...'
152
-
153
223
  await convertToMultisite( environment, config, subdomain, spinner )
154
224
  }
155
-
225
+
156
226
  // rewrite and flush permalink structure.
157
227
  await runCLICmds(
158
- environment,
228
+ environment,
159
229
  [
160
230
  `wp rewrite structure ${WP_PERMALINK} --hard`
161
231
  ],
162
- config,
232
+ config,
163
233
  spinner
164
- );
234
+ )
235
+
236
+ // generate .htaccess
237
+ await generateHTAccess( environment, config.workDirectoryPath, multisite, subdomain );
238
+
165
239
  }
166
240
 
167
241
  export {
168
242
  configureWordPress,
243
+ configureApplicationPassword,
169
244
  isMultisite,
170
245
  convertToMultisite,
171
246
  generateHTAccess
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@caweb/cli",
3
- "version": "1.11.2",
3
+ "version": "1.12.1",
4
4
  "description": "CAWebPublishing Command Line Interface.",
5
5
  "exports": "./lib/env.js",
6
6
  "type": "module",
@@ -52,22 +52,26 @@
52
52
  "WP_MAX_MEMORY_LIMIT": "512M",
53
53
  "WP_PERMALINK": "/%year%/%monthnum%/%postname%/",
54
54
  "WP_POST_REVISIONS": true,
55
+ "WP_SITEURL": "http://localhost",
56
+ "WP_HOME": "http://localhost",
55
57
  "ADMIN_COOKIE_PATH": "/",
56
58
  "COOKIE_DOMAIN": "",
57
59
  "COOKIEPATH": "",
58
60
  "SITECOOKIEPATH": "",
59
- "CONCATENATE_SCRIPTS": false
61
+ "CONCATENATE_SCRIPTS": false,
62
+ "WP_ENV_PHPMYADMIN_PORT": 9999,
63
+ "WP_ENV_TESTS_PHPMYADMIN_PORT": 9998
60
64
  }
61
65
  },
62
66
  "dependencies": {
63
67
  "@caweb/a11y-webpack-plugin": "^1.0.9",
64
68
  "@caweb/css-audit-webpack-plugin": "^1.0.12",
65
69
  "@caweb/jshint-webpack-plugin": "^2.0.1",
66
- "@caweb/webpack": "^1.4.4",
70
+ "@caweb/webpack": "^1.5.0",
67
71
  "@inquirer/prompts": "^7.5.3",
68
- "@wordpress/create-block": "^4.67.0",
69
- "@wordpress/env": "^10.24.0",
70
- "axios": "^1.9.0",
72
+ "@wordpress/create-block": "^4.68.0",
73
+ "@wordpress/env": "^10.25.0",
74
+ "axios": "^1.10.0",
71
75
  "axios-retry": "^4.5.0",
72
76
  "chalk": "^5.4.1",
73
77
  "commander": "^14.0.0",
@@ -1,49 +0,0 @@
1
-
2
- /**
3
- * External dependencies
4
- */
5
- import { default as wpEnvDestroy } from '@wordpress/env/lib/commands/destroy.js';
6
-
7
- /**
8
- * Internal dependencies
9
- */
10
- import { runCmd } from '../../lib/index.js';
11
-
12
- /**
13
- * Destroys the development server.
14
- *
15
- * @param {Object} options
16
- * @param {Object} options.spinner A CLI spinner which indicates progress.
17
- * @param {boolean} options.scripts Indicates whether or not lifecycle scripts should be executed.
18
- * @param {boolean} options.debug True if debug mode is enabled.
19
- *
20
- */
21
- export default async function destroy({
22
- spinner,
23
- scripts,
24
- debug,
25
- }) {
26
-
27
- await wpEnvDestroy({spinner, scripts, debug });
28
-
29
- // wp-env destroy completed successfully if spinner.text reads.
30
- if( 'Removed WordPress environment.' === spinner.text ){
31
- spinner.text = "Cleaning up...";
32
-
33
- // Stop phpMyAdmin as well
34
- // wp-env doesn't destroy the phpmyadmin image so we have to do it ourselves.
35
- await runCmd(
36
- 'docker',
37
- [
38
- 'image',
39
- 'rm',
40
- 'phpmyadmin'
41
- ],
42
- { stdio: 'ignore' }
43
- )
44
-
45
- spinner.text = "Removed WordPress environment.'";
46
-
47
- }
48
-
49
- }
@@ -1,35 +0,0 @@
1
- /**
2
- * External dependencies
3
- */
4
- import path from 'path';
5
- import loadConfig from '@wordpress/env/lib/config/load-config.js';
6
- import * as dockerCompose from 'docker-compose';
7
-
8
- import { default as wpEnvStop } from '@wordpress/env/lib/commands/stop.js';
9
-
10
- /**
11
- * Starts the development server.
12
- *
13
- * @param {Object} options
14
- * @param {Object} options.spinner A CLI spinner which indicates progress.
15
- * @param {boolean} options.scripts Indicates whether or not lifecycle scripts should be executed.
16
- * @param {boolean} options.debug True if debug mode is enabled.
17
- *
18
- */
19
- export default async function stop({
20
- spinner,
21
- debug,
22
- }) {
23
- const config = await loadConfig(path.resolve('.'));
24
- const { workDirectoryPath } = config;
25
-
26
- // Stop wp-env services
27
- await wpEnvStop({spinner, debug });
28
-
29
- // Stop phpMyAdmin as well
30
- await dockerCompose.down( {
31
- config: path.join(workDirectoryPath, 'docker-compose.override.yml'),
32
- log: debug,
33
- } );
34
-
35
- }