@ideasonpurpose/build-tools-wordpress 2.0.1 → 2.0.3

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/CHANGELOG.md CHANGED
@@ -4,6 +4,18 @@ All notable changes to this project will be documented in this file. Dates are d
4
4
 
5
5
  Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog).
6
6
 
7
+ #### v2.0.2
8
+
9
+ > 13 January 2025
10
+
11
+ - bump deps
12
+
13
+ #### v2.0.1
14
+
15
+ > 19 October 2024
16
+
17
+ - another Sass bump
18
+
7
19
  #### v2.0.0
8
20
 
9
21
  > 19 October 2024
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # @ideasonpurpose/build-tools-wordpress
2
2
 
3
- #### Version 2.0.1
3
+ #### Version 2.0.3
4
4
 
5
5
  [![NPM Version](https://img.shields.io/npm/v/%40ideasonpurpose%2Fbuild-tools-wordpress?logo=npm)](https://www.npmjs.com/package/@ideasonpurpose/build-tools-wordpress)
6
6
  [![GitHub Actions Workflow Status](https://img.shields.io/github/actions/workflow/status/ideasonpurpose/build-tools-wordpress/npm-publish.yml?logo=github&logoColor=white)](https://github.com/ideasonpurpose/build-tools-wordpress#readme)
@@ -0,0 +1,299 @@
1
+ services:
2
+ # Primary database for the local WordPress development environment.
3
+ # Image from: https://hub.docker.com/_/mysql
4
+ db:
5
+ image: &db_img mysql:8.4
6
+ restart: always
7
+ volumes:
8
+ - db_data:/var/lib/mysql
9
+ - ./_db:/docker-entrypoint-initdb.d
10
+ # - ./_log/mysql:/var/log/mysql
11
+ environment:
12
+ MYSQL_ALLOW_EMPTY_PASSWORD: 1
13
+ MYSQL_DATABASE: wordpress
14
+ MYSQL_USER: wordpress
15
+ MYSQL_PASSWORD: wordpress
16
+ # command: >
17
+ # --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci
18
+
19
+ # Ideas On Purpose's local WordPress development environment.
20
+ # Update image version with `docker run ideasonpurpose/wordpress init`
21
+ # Project info: https://github.com/ideasonpurpose/docker-wordpress-dev
22
+ wordpress:
23
+ depends_on:
24
+ - db
25
+ # image: &wp_img ideasonpurpose/wordpress:dev
26
+ image: &wp_img ideasonpurpose/wordpress:6.7.2
27
+ restart: always
28
+ volumes:
29
+ - wp_data:/var/www/html
30
+ - ./wp-content/themes/${npm_package_name:-ioptheme}:/var/www/html/wp-content/themes/${npm_package_name:-ioptheme}
31
+ - ./wp-content/plugins:/var/www/html/wp-content/plugins
32
+ - ./wp-content/uploads:/var/www/html/wp-content/uploads
33
+ - ${IOP_DEV_PLUGIN_1:-/tmp/null:/tmp/IOP_DEV_PLUGIN_1}
34
+ - ${IOP_DEV_PLUGIN_2:-/tmp/null:/tmp/IOP_DEV_PLUGIN_2}
35
+ - ${IOP_DEV_PLUGIN_3:-/tmp/null:/tmp/IOP_DEV_PLUGIN_3}
36
+ - ${IOP_DEV_PLUGIN_4:-/tmp/null:/tmp/IOP_DEV_PLUGIN_4}
37
+ - ${IOP_DEV_PLUGIN_5:-/tmp/null:/tmp/IOP_DEV_PLUGIN_5}
38
+ - ${IOP_DEV_PLUGIN_6:-/tmp/null:/tmp/IOP_DEV_PLUGIN_6}
39
+ - ${IOP_DEV_PLUGIN_7:-/tmp/null:/tmp/IOP_DEV_PLUGIN_7}
40
+ - ${IOP_DEV_PLUGIN_8:-/tmp/null:/tmp/IOP_DEV_PLUGIN_8}
41
+ - ./webpack/xdebug:/tmp/xdebug
42
+
43
+ # Publish port 80 to an ephemeral host port to prepare for future local build tools
44
+ ports:
45
+ - "80"
46
+
47
+ # Internally expose port 9003 for XDebug and profiling
48
+ expose:
49
+ - 9003
50
+
51
+ # Link external plugin projects by defining host:container path pairs in .env
52
+ environment:
53
+ IOP_DEV_PLUGIN_1:
54
+ IOP_DEV_PLUGIN_2:
55
+ IOP_DEV_PLUGIN_3:
56
+ IOP_DEV_PLUGIN_4:
57
+ IOP_DEV_PLUGIN_5:
58
+ IOP_DEV_PLUGIN_6:
59
+ IOP_DEV_PLUGIN_7:
60
+ IOP_DEV_PLUGIN_8:
61
+
62
+ # Apache will throw errors for any ulimit value below 8192
63
+ # NOTE THAT THIS MIGHT BE MORE THAN THE SYSTEM OFFERS
64
+ # TODO: Still true?
65
+ # TODO: Testing removal. 2025-03-18
66
+ # ulimits:
67
+ # nofile: 8192
68
+
69
+ # Required for iptables port-mapping to work inside the Docker image
70
+ # This is used to fix a PHP/WordPress issue where internal requests
71
+ # from Site Health tried to load from external ports.
72
+ cap_add:
73
+ - NET_ADMIN
74
+
75
+ # # TODO: Deprecated and likely ready to remove 2025-03-18
76
+ # # Ideas On Purpose's development toolchain
77
+ # # Image from: https://hub.docker.com/r/ideasonpurpose/docker-build
78
+ # tools:
79
+ # # image: ideasonpurpose/docker-build:dev
80
+ # image: ideasonpurpose/docker-build:0.17.2
81
+ # user: "${UID:-1000}:${GID:-1000}"
82
+ # depends_on:
83
+ # - wordpress
84
+ # volumes:
85
+ # - .:/usr/src/site/
86
+ # ports:
87
+ # - "${npm_config_port:-8080}:8080"
88
+ # environment:
89
+ # PORT: ${npm_config_port:-8080}
90
+ # entrypoint: npm run
91
+ # command: start
92
+
93
+ # Utility service for running composer commands
94
+ # Image from: https://hub.docker.com/_/composer
95
+ composer:
96
+ image: composer:2.8
97
+ profiles: ["utility"]
98
+ user: "${UID:-1000}:${GID:-1000}"
99
+ environment:
100
+ COMPOSER_HOME: /.composer
101
+ volumes:
102
+ - ./:/app
103
+ - ~/.composer:/.composer
104
+ command: install
105
+
106
+ # Utility service which exposes wp-cli. Useful for testing pre-releases
107
+ # Update image version with `docker run ideasonpurpose/wordpress init`
108
+ # Project info: https://github.com/ideasonpurpose/docker-wordpress-dev
109
+ wp-cli:
110
+ depends_on:
111
+ - db
112
+ - wordpress
113
+ image: *wp_img
114
+ profiles: ["utility"]
115
+ user: www-data
116
+ volumes:
117
+ - wp_data:/var/www/html
118
+ - ./wp-content/themes/${npm_package_name:-ioptheme}:/var/www/html/wp-content/themes/${npm_package_name:-ioptheme}
119
+ - ./wp-content/plugins:/var/www/html/wp-content/plugins
120
+ - ./wp-content/uploads:/var/www/html/wp-content/uploads
121
+ environment:
122
+ - WP_CLI_CACHE_DIR=/tmp/wp-cli
123
+ - WP_CLI_DISABLE_AUTO_CHECK_UPDATE=true
124
+ command: wp theme activate ${npm_package_name:-ioptheme}
125
+
126
+ # Runs phpMyAdmin on port 8002
127
+ # Image from: https://hub.docker.com/_/phpmyadmin
128
+ phpmyadmin:
129
+ image: phpmyadmin:5.2-apache
130
+ profiles: ["utility"]
131
+ ports:
132
+ - "${npm_config_port:-8002}:80"
133
+ depends_on:
134
+ - db
135
+ environment:
136
+ PMA_USER: root
137
+ PMA_PASSWORD: ~
138
+ UPLOAD_LIMIT: 1G
139
+ command: |
140
+ bash -c 'echo &&
141
+ echo -e "🛠 \033[33mStarting phpMyAdmin at\033[0m \033[36mhttp://localhost:${npm_config_port:-8002}\033[0m" &&
142
+ echo &&
143
+ /docker-entrypoint.sh apache2-foreground'
144
+
145
+ # XDebug profile viewer at http://localhost:9001 (change port with --port=xxxx)
146
+ # Enable profiling by appending `?XDEBUG_PROFILE=1` to any request
147
+ # https://hub.docker.com/r/wodby/webgrind
148
+ webgrind:
149
+ image: wodby/webgrind:1.9
150
+ profiles: ["utility"]
151
+ user: "${UID:-1000}:${GID:-1000}"
152
+ ports:
153
+ - "${npm_config_port:-9004}:8080"
154
+ depends_on:
155
+ - wordpress
156
+ volumes:
157
+ - ./webpack/xdebug:/tmp
158
+ environment:
159
+ WEBGRIND_DEFAULT_TIMEZONE: America/New_York
160
+ command: |
161
+ bash -c 'echo &&
162
+ echo -e "🔍 \033[33mStarting WebGrind server at\033[0m \033[36mhttp://localhost:${npm_config_port:-9004}\033[0m" &&
163
+ echo -e "⏱️ Profile any request by adding \033[1;35m?XDEBUG_PROFILE=1\033[0m to the url" &&
164
+ echo &&
165
+ php -S 0.0.0.0:8080 index.php
166
+ '
167
+
168
+ # Dumps the current database to _db/theme-YYYY-MM-DDTHHMMSS.sql.gz
169
+ db-dump:
170
+ image: *db_img
171
+ profiles: ["utility"]
172
+ depends_on:
173
+ - db
174
+ volumes:
175
+ - ./_db:/usr/src
176
+ environment:
177
+ MYSQL_DATABASE: wordpress
178
+ OWNER_GROUP: "${UID:-1000}:${GID:-1000}"
179
+
180
+ # NOTE: The datbase dumpfile will include these CREATE/USE commands:
181
+ # CREATE DATABASE `wordpress`;
182
+ # USE `wordpress`;
183
+ # to drop those lines, remove "--databases" from the mysqldump command
184
+ command: |
185
+ bash -c 'for i in {1..10}
186
+ do echo -e "⏳ \033[33mWaiting for DB server...\033[0m" &&
187
+ mysql --ssl-mode=DISABLED -s -h db -e "exit" && break || sleep 3
188
+ done &&
189
+ sleep 2 &&
190
+ echo -e "✔️ \033[32mConnected to DB\033[0m" &&
191
+ export DUMPFILE="/usr/src/'${npm_package_name:-dumpfile}'-$$(date +%FT%H%M%S).sql" &&
192
+ echo $${DUMPFILE} &&
193
+ mysqldump --ssl-mode=DISABLED -hdb --databases $${MYSQL_DATABASE} > "$${DUMPFILE}" &&
194
+ gzip "$${DUMPFILE}" &&
195
+ chown -R $${OWNER_GROUP} /usr/src &&
196
+ echo "Successfully dumped database to \"$${DUMPFILE}.gz\""'
197
+
198
+ # Reloads the database from the first found *.sql dumpfile in _db
199
+ db-reload:
200
+ image: *db_img
201
+ profiles: ["utility"]
202
+ depends_on:
203
+ - db
204
+ volumes:
205
+ - ./_db:/usr/src/dumpfiles
206
+ environment:
207
+ MYSQL_DATABASE: wordpress
208
+ command: |
209
+ bash -c 'for i in {1..10}
210
+ do echo -e "⏳ \033[33mWaiting for DB server...\033[0m" &&
211
+ mysql --ssl-mode=DISABLED -s -h db -e "exit" && break || sleep 3
212
+ done &&
213
+ sleep 2 &&
214
+ echo -e "✔️ \033[32mConnected to DB\033[0m" &&
215
+ mysqladmin --ssl-mode=DISABLED -hdb -v -f drop $${MYSQL_DATABASE} &&
216
+ mysqladmin --ssl-mode=DISABLED -hdb -v -f create $${MYSQL_DATABASE} &&
217
+ echo Database \"$${MYSQL_DATABASE}\" created &&
218
+ echo Reloading database from dumpfile &&
219
+ mysql --ssl-mode=DISABLED -hdb $${MYSQL_DATABASE} < $$(ls /usr/src/dumpfiles/*.sql | tail -n1)'
220
+
221
+ # Activates the theme directly in the database
222
+ theme-activate:
223
+ image: *db_img
224
+ profiles: ["utility"]
225
+ depends_on:
226
+ - db
227
+ volumes:
228
+ - ./_db:/usr/src/dumpfiles
229
+ environment:
230
+ MYSQL_DATABASE: wordpress
231
+ command: |
232
+ bash -c 'for i in {1..10}
233
+ do echo -e "⏳ \033[33mWaiting for DB server...\033[0m" &&
234
+ mysql --ssl-mode=DISABLED -s -h db -e "exit" && break || sleep 3
235
+ done &&
236
+ sleep 2 &&
237
+ echo -e "✔️ \033[32mConnected to DB\033[0m" &&
238
+ if [[ $$(mysql --ssl-mode=DISABLED -s -h db $${MYSQL_DATABASE} -e "SHOW TABLES LIKE \"wp_options\"") ]]
239
+ then
240
+ echo -e "🎨 \033[36mActivating theme \033[0m\033[1m${npm_package_name:-ioptheme}\033[0m"
241
+ mysql --ssl-mode=DISABLED -h db $${MYSQL_DATABASE} \
242
+ -e "UPDATE wp_options \
243
+ SET option_value = \"'${npm_package_name:-ioptheme}'\" \
244
+ WHERE option_name in (\"template\",\"stylesheet\")"
245
+ else
246
+ echo -e "Unable to activate theme: \033[31m'\'wp_options\'' table does not exist.\033[0m"
247
+ echo "To recreate an existing site, copy the site'\''s DB dumpfile into _db"
248
+ echo If this project is starting from an empty database, you can ignore this message.
249
+ fi'
250
+
251
+ # Repairs permissions for known project files and directories
252
+ repair-permissions:
253
+ image: *wp_img
254
+ profiles: ["utility"]
255
+ volumes:
256
+ - .:/usr/src/site
257
+ environment:
258
+ OWNER_GROUP: "${UID:-1000}:${GID:-1000}"
259
+ entrypoint: /usr/local/bin/permissions.sh
260
+
261
+ # Locally mirror remote sites by pulling the database, plugins and uploads
262
+ # Remote connections are configured in the project's .env file
263
+ pull:
264
+ image: *wp_img
265
+ profiles: ["utility"]
266
+ volumes:
267
+ - .:/usr/src/site
268
+ entrypoint: |
269
+ /usr/local/bin/pull.sh
270
+ environment:
271
+ OWNER_GROUP: "${UID:-1000}:${GID:-1000}"
272
+ SSH_KEY_PATH:
273
+ SSH_LOGIN:
274
+ SSH_USER:
275
+ SSH_PORT:
276
+ SSH_WP_CONTENT_DIR:
277
+ secrets:
278
+ - SSH_KEY
279
+
280
+ # Run the init script from ideasonpurpose/wordpress:latest (intentionally "latest")
281
+ # to refresh tooling and bring the project inline with our boilerplate
282
+ # Project info: https://github.com/ideasonpurpose/docker-wordpress-dev
283
+ refresh:
284
+ # image: ideasonpurpose/wordpress:dev
285
+ image: ideasonpurpose/wordpress:latest
286
+ profiles: ["utility"]
287
+ volumes:
288
+ - .:/usr/src/site
289
+ command: init
290
+
291
+ secrets:
292
+ SSH_KEY:
293
+ file: ${SSH_KEY_PATH:-~/.ssh/your_ssh_private_key}
294
+
295
+ volumes:
296
+ db_data:
297
+ name: ${npm_package_name:-ioptheme}_db
298
+ wp_data:
299
+ name: ${npm_package_name:-ioptheme}_wp
@@ -10,6 +10,8 @@ import { findLocalPort } from "./find-local-docker-port.js";
10
10
  /**
11
11
  * If config.proxy is explicitly not false, return a {proxy} object
12
12
  * otherwise return an empty object.
13
+ *
14
+ * @returns {Promise<{ proxy: Object[] }>}
13
15
  */
14
16
  export async function devserverProxy(config) {
15
17
  let target = config.proxy;
@@ -44,17 +46,17 @@ export async function devserverProxy(config) {
44
46
  if (localPort && localPort.hostname && localPort.port) {
45
47
  target = new URL(`http://${localPort.hostname}:${localPort.port}`);
46
48
  console.log(
47
- chalk.cyan.bold(
48
- `PORT FROM DEVSERVER-PROXY: "${config.proxy} ${localPort.port}`,
49
- target,
50
- ),
49
+ "PORT FROM DEVSERVER-PROXY:",
50
+ chalk.cyan(config.proxy),
51
+ chalk.bold(localPort.port),
52
+ target,
51
53
  );
52
54
  }
53
55
  }
54
56
  }
55
57
 
56
58
  if (!target) {
57
- return {};
59
+ return { proxy: [] };
58
60
  }
59
61
 
60
62
  const proxy = [
@@ -114,7 +116,9 @@ export async function devserverProxy(config) {
114
116
 
115
117
  originalBody = Buffer.concat(originalBody);
116
118
  let newBody;
117
- const type = (proxyRes.headers["content-type"] || "").split(";")[0];
119
+ // TODO: Is there ever a case where content-type is missing?
120
+ const type = proxyRes.headers["content-type"].split(";")[0];
121
+ // const type = (proxyRes.headers["content-type"] || "").split(";")[0];
118
122
  const wpRegexp = new RegExp(
119
123
  "^/wp-(?:admin|includes|content/plugins).*(?:css|js|map)$",
120
124
  );
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ideasonpurpose/build-tools-wordpress",
3
- "version": "2.0.1",
3
+ "version": "2.0.3",
4
4
  "description": "Build scripts and dependencies for IOP's WordPress development environments.",
5
5
  "homepage": "https://github.com/ideasonpurpose/build-tools-wordpress#readme",
6
6
  "bugs": {
@@ -33,66 +33,66 @@
33
33
  "dependencies": {
34
34
  "@ideasonpurpose/prettier-config": "^1.0.0",
35
35
  "@ideasonpurpose/stylelint-config": "^1.1.0",
36
- "@rollup/plugin-commonjs": "^28.0.1",
36
+ "@rollup/plugin-commonjs": "^28.0.3",
37
37
  "@rollup/plugin-json": "^6.1.0",
38
- "@rollup/plugin-node-resolve": "^15.3.0",
38
+ "@rollup/plugin-node-resolve": "^16.0.1",
39
39
  "@svgr/webpack": "^8.1.0",
40
- "@wordpress/dependency-extraction-webpack-plugin": "^6.10.0",
40
+ "@wordpress/dependency-extraction-webpack-plugin": "^6.20.0",
41
41
  "ansi-html": "^0.0.9",
42
42
  "archiver": "^7.0.1",
43
43
  "auto-changelog": "^2.5.0",
44
- "autoprefixer": "^10.4.20",
45
- "babel-loader": "^9.2.1",
44
+ "autoprefixer": "^10.4.21",
45
+ "babel-loader": "^10.0.0",
46
46
  "body-parser": "^1.20.3",
47
- "caniuse-lite": "^1.0.30001669",
48
- "chalk": "^5.3.0",
47
+ "caniuse-lite": "^1.0.30001706",
48
+ "chalk": "^5.4.1",
49
49
  "chalk-cli": "^5.0.1",
50
50
  "classnames": "^2.5.1",
51
51
  "cli-truncate": "^4.0.0",
52
- "copy-webpack-plugin": "^12.0.2",
52
+ "copy-webpack-plugin": "^13.0.0",
53
53
  "cosmiconfig": "^9.0.0",
54
54
  "cross-env": "^7.0.3",
55
55
  "css-loader": "^7.1.2",
56
56
  "cssnano": "^7.0.6",
57
- "dotenv": "^16.4.5",
58
- "esbuild-loader": "^4.2.2",
59
- "eslint": "^9.13.0",
57
+ "dotenv": "^16.4.7",
58
+ "esbuild-loader": "^4.3.0",
59
+ "eslint": "^9.22.0",
60
60
  "filesize": "^10.1.6",
61
- "fs-extra": "^11.1.1",
62
- "globby": "^14.0.2",
61
+ "fs-extra": "^11.3.0",
62
+ "globby": "^14.1.0",
63
63
  "http-proxy": "^1.18.1",
64
64
  "humanize-duration": "^3.32.1",
65
- "image-minimizer-webpack-plugin": "^4.1.0",
65
+ "image-minimizer-webpack-plugin": "^4.1.3",
66
66
  "is-text-path": "^3.0.0",
67
67
  "lodash": "^4.17.21",
68
- "mini-css-extract-plugin": "^2.9.1",
69
- "ora": "^8.1.0",
70
- "postcss": "^8.4.47",
68
+ "mini-css-extract-plugin": "^2.9.2",
69
+ "ora": "^8.2.0",
70
+ "postcss": "^8.5.3",
71
71
  "postcss-loader": "^8.1.1",
72
72
  "postcss-scss": "^4.0.9",
73
73
  "pretty-hrtime": "^1.0.3",
74
74
  "read-package-up": "^11.0.0",
75
75
  "replacestream": "^4.0.3",
76
- "sass": "^1.80.3",
77
- "sass-embedded": "^1.80.3",
78
- "sass-loader": "^16.0.2",
79
- "semver": "^7.6.3",
76
+ "sass": "^1.86.0",
77
+ "sass-embedded": "^1.86.0",
78
+ "sass-loader": "^16.0.5",
79
+ "semver": "^7.7.1",
80
80
  "sharp": "^0.33.5",
81
- "sort-package-json": "^2.10.1",
81
+ "sort-package-json": "^3.0.0",
82
82
  "string-length": "^6.0.0",
83
83
  "style-loader": "^4.0.0",
84
84
  "svgo": "^3.3.2",
85
85
  "svgo-loader": "^4.0.0",
86
86
  "version-everything": "^0.11.4",
87
- "webpack": "^5.95.0",
87
+ "webpack": "^5.98.0",
88
88
  "webpack-bundle-analyzer": "^4.10.2",
89
- "webpack-cli": "^5.1.4",
89
+ "webpack-cli": "^6.0.1",
90
90
  "webpack-dev-middleware": "^7.4.2",
91
- "webpack-dev-server": "^5.1.0"
91
+ "webpack-dev-server": "^5.2.0"
92
92
  },
93
93
  "devDependencies": {
94
- "@vitest/coverage-v8": "^2.1.3",
95
- "vitest": "^2.1.3"
94
+ "@vitest/coverage-v8": "^3.0.9",
95
+ "vitest": "^3.0.9"
96
96
  },
97
97
  "version-everything": {
98
98
  "files": [
@@ -1,8 +1,12 @@
1
+ //@ts-check
2
+
1
3
  import { afterEach, beforeEach, describe, expect, test, vi } from "vitest";
2
4
 
3
5
  import fs from "fs";
4
6
  import dns from "dns";
5
7
 
8
+ import { EventEmitter } from "events";
9
+
6
10
  import { devserverProxy } from "../lib/devserver-proxy.js";
7
11
  import { findLocalPort } from "../lib/find-local-docker-port.js";
8
12
 
@@ -59,7 +63,6 @@ afterEach(() => {
59
63
  // expect(actual).toBe(expected);
60
64
  // });
61
65
 
62
-
63
66
  // test("Send legacy token where there's no wordpress service", async () => {
64
67
  // jest.spyOn(dns, "promises", "get").mockImplementation(() => {
65
68
  // // console.log("ONLY ONCE");
@@ -107,75 +110,153 @@ afterEach(() => {
107
110
 
108
111
  test("Test proxy settings", async () => {
109
112
  let proxy = true;
110
- const actual = await devserverProxy({ proxy });
111
- console.log(actual);
112
- expect(actual).toHaveProperty("proxy.**.target");
113
- expect(actual.proxy["**"].target).toMatch("stella");
113
+ const actual = (await devserverProxy({ proxy })).proxy[0];
114
+ expect(actual).toHaveProperty("target");
115
+ expect(actual.context).toContain("**");
114
116
  });
115
117
 
116
118
  test("proxy is bare IP address", async () => {
117
119
  let proxy = "4.3.2.1";
118
- const actual = await devserverProxy({ proxy });
119
- expect(actual).toHaveProperty("proxy.**.target", "http://4.3.2.1");
120
+ const actual = (await devserverProxy({ proxy })).proxy[0];
121
+ expect(actual).toHaveProperty("target", "http://4.3.2.1");
120
122
  });
121
123
 
122
124
  test("proxy is a url", async () => {
123
- let proxy = "https://example.com/";
124
- const actual = await devserverProxy({ proxy });
125
- expect(actual).toHaveProperty("proxy.**.target", "https://example.com");
125
+ let proxy = "https://example.com";
126
+ const actual = (await devserverProxy({ proxy })).proxy[0];
127
+ expect(actual).toHaveProperty("target", proxy);
126
128
  });
127
129
 
128
130
  test("proxy is a plain string", async () => {
129
131
  let proxy = "sandwich";
130
- const actual = await devserverProxy({ proxy });
131
- expect(actual).toHaveProperty("proxy.**.target", expectedTarget);
132
+ const actual = (await devserverProxy({ proxy })).proxy[0];
133
+ expect(actual).toHaveProperty("target", expectedTarget);
132
134
  expect(findLocalPort).toHaveBeenCalledWith(proxy);
133
135
  });
134
136
 
135
137
  test("Proxy boolean true", async () => {
136
138
  vi.mocked(findLocalPort).mockReturnValue(localPort);
137
139
  const proxy = true;
138
- const actual = await devserverProxy({ proxy });
139
- expect(actual).toHaveProperty("proxy.**.target", expectedTarget);
140
+ const actual = (await devserverProxy({ proxy })).proxy[0];
141
+ expect(actual).toHaveProperty("target", expectedTarget);
140
142
  });
141
143
 
142
144
  test("Proxy boolean false", async () => {
143
145
  const proxy = false;
144
- expect(await devserverProxy({ proxy })).toStrictEqual({});
146
+ expect(await devserverProxy({ proxy })).toStrictEqual({ proxy: [] });
145
147
  });
146
148
 
147
149
  test("test the returned proxy onError handler", async () => {
148
- let proxy = "wordpress";
149
150
  const logSpy = vi.spyOn(console, "log");
150
151
  const actual = await devserverProxy({ proxy: true });
151
152
 
152
- // console.log(actual);
153
- expect(actual).toHaveProperty("proxy.**");
153
+ const err = { code: "ECONNRESET" };
154
154
 
155
- const route = actual.proxy["**"];
156
- let err = new Error("boom");
157
- err.code = "ECONNRESET";
158
- route.onError(err);
159
-
160
- expect(route).toHaveProperty("onError");
155
+ actual.proxy[0].onError(err, "req", "res");
161
156
  expect(logSpy).toHaveBeenLastCalledWith(
162
157
  expect.stringContaining("ECONNRESET"),
163
158
  );
164
159
 
165
- const writeHead = vi.fn();
166
- const end = vi.fn();
167
- const res = { writeHead, end };
160
+ err.code = "Unknown Error Code";
161
+ err.stack = "STACK";
162
+
168
163
  const req = { url: "url" };
164
+ const res = { writeHead: vi.fn(), end: vi.fn() };
169
165
 
170
- err = new Error("boom-again ");
171
- err.code = "Unknown Error Code";
172
- route.onError(err, req, res);
166
+ actual.proxy[0].onError(err, req, res);
167
+
168
+ expect(logSpy).toHaveBeenLastCalledWith(
169
+ expect.stringContaining("Devserver Proxy Error"),
170
+ req.url,
171
+ expect.any(Object),
172
+ err.stack,
173
+ );
173
174
 
174
- // expect(logSpy).toHaveBeenCalledWith('PROXY ERROR');
175
- // expect(logSpy.mock.calls[1][0]).toMatch(/^PROXY ERROR/);
176
- // expect(end.mock.calls[0][0]).toMatch(/^Webpack DevServer/);
175
+ expect(res.writeHead).toHaveBeenCalledWith(500, expect.any(Object));
176
+ expect(res.end).toHaveBeenCalledWith(
177
+ expect.stringContaining("Webpack DevServer Proxy Error: "),
178
+ );
179
+ });
180
+
181
+ test("onProxyRes Handler", async () => {
182
+ const config = { proxy: "http://localhost:3000" };
183
+ const result = await devserverProxy(config);
184
+ const onProxyRes = result.proxy[0].onProxyRes;
185
+
186
+ const mockProxyRes = new EventEmitter();
187
+ mockProxyRes.statusCode = 200;
188
+ mockProxyRes.statusMessage = "OK";
189
+ mockProxyRes.headers = {
190
+ "content-type": "text/css",
191
+ };
192
+ const mockReq = {
193
+ headers: { host: "example.com" },
194
+ path: "/style.css",
195
+ };
196
+
197
+ const mockRes = {
198
+ statusCode: 0,
199
+ setHeader: vi.fn(),
200
+ end: vi.fn(),
201
+ };
202
+
203
+ onProxyRes(mockProxyRes, mockReq, mockRes);
204
+
205
+ const bodySrc = "body { color: red; }";
206
+ let originalBody = Buffer.from(bodySrc);
207
+ mockProxyRes.emit("data", originalBody);
208
+ mockProxyRes.emit("end");
209
+
210
+ // Assert
211
+ expect(mockRes.statusCode).toBe(200);
212
+ expect(mockRes.end).toHaveBeenCalledWith(bodySrc);
213
+ expect(mockRes.setHeader).toHaveBeenCalledWith(
214
+ "content-type",
215
+ expect.anything(),
216
+ );
217
+ });
218
+
219
+
220
+ test("onProxyRes Handler passthrough", async () => {
221
+ const config = { proxy: "http://localhost:3000" };
222
+ const result = await devserverProxy(config);
223
+ const onProxyRes = result.proxy[0].onProxyRes;
224
+
225
+ const mockProxyRes = new EventEmitter();
226
+ mockProxyRes.statusCode = 200;
227
+ mockProxyRes.statusMessage = "OK";
228
+ mockProxyRes.headers = {
229
+ "content-type": "nope/nope",
230
+ };
231
+ const mockReq = {
232
+ headers: { host: "example.com" },
233
+ path: "/style.css",
234
+ };
235
+
236
+ const mockRes = {
237
+ statusCode: 0,
238
+ setHeader: vi.fn(),
239
+ end: vi.fn(),
240
+ };
241
+
242
+ onProxyRes(mockProxyRes, mockReq, mockRes);
243
+
244
+ const bodySrc = "body { color: red; }";
245
+ let originalBody = Buffer.from(bodySrc);
246
+ mockProxyRes.emit("data", originalBody);
247
+ mockProxyRes.emit("end");
248
+
249
+ // Assert
250
+ expect(mockRes.statusCode).toBe(200);
251
+ expect(mockRes.end).toHaveBeenCalledWith(Buffer.from(bodySrc));
252
+ expect(mockRes.setHeader).toHaveBeenCalledWith(
253
+ "content-type",
254
+ expect.anything(),
255
+ );
177
256
  });
178
257
 
258
+
259
+
179
260
  // test("test proxy's onProxyRes handler", async () => {
180
261
  // let proxy = "https://example.com";
181
262
  // const logSpy = jest.spyOn(console, "log");
@@ -1,3 +1,5 @@
1
+ //@ts-check
2
+
1
3
  import { afterEach, beforeEach, describe, expect, test, vi } from "vitest";
2
4
 
3
5
  import { exec } from "node:child_process";
@@ -1,29 +0,0 @@
1
- /**
2
- * Future node versions should import package.json directly:
3
- * import packageJson from "./package.json" with { type: "json" };
4
- *
5
- * In the current node.js LTS v20, importing JSON throws the following warnings:
6
- * (node:14509) ExperimentalWarning: Importing JSON modules is an experimental feature and might change at any time
7
- * (Use `node --trace-warnings ...` to show where the warning was created)
8
- *
9
- * NOTE: This file does not work if the build runs from Docker. Inside a Docker volume, the
10
- * theme name pulls instead from the docker image's package.json file, which will probably
11
- * create a theme named 'iop-build-tools'.
12
- */
13
- import { readFileSync } from "fs";
14
- const packageJson = JSON.parse(readFileSync("./package.json"));
15
- // import packageJson from "./package.json" with { type: "json" };
16
-
17
- const { name: themeName } = packageJson;
18
-
19
- export default {
20
- src: `./wp-content/themes/${themeName}/src`,
21
- dist: `./wp-content/themes/${themeName}/dist`,
22
- entry: ["./js/main.js", "./js/admin.js", "./js/editor.js"],
23
- publicPath: `/wp-content/themes/${themeName}/dist/`,
24
-
25
- sass: "sass-embedded",
26
- esTarget: "es2020",
27
-
28
- devtool: "source-map",
29
- };