@wp-playground/cli 3.0.41 → 3.0.42

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.
@@ -1,38 +1,38 @@
1
- import { logger as u, LogSeverity as N, errorLogPath as ee } from "@php-wasm/logger";
2
- import { PHPResponse as j, consumeAPI as D, SupportedPHPVersions as te, printDebugDetails as ye, exposeAPI as be, exposeSyncAPI as Pe } from "@php-wasm/universal";
3
- import { resolveRemoteBlueprint as ve, resolveRuntimeConfiguration as oe, compileBlueprintV1 as ke, isBlueprintBundle as xe, runBlueprintV1Steps as Se } from "@wp-playground/blueprints";
4
- import { zipDirectory as Ie, RecommendedPHPVersion as q } from "@wp-playground/common";
5
- import f, { existsSync as Y, rmdirSync as $e, mkdirSync as z, readdirSync as Te } from "fs";
6
- import { MessageChannel as Ee, Worker as re } from "worker_threads";
7
- import { createNodeFsMountHandler as Ce, FileLockManagerForNode as We } from "@php-wasm/node";
8
- import h, { basename as R, join as de } from "path";
9
- import Be from "express";
10
- import U, { cpus as Me } from "os";
11
- import { jspi as Le } from "wasm-feature-detect";
1
+ import { logger as g, LogSeverity as j, errorLogPath as ee } from "@php-wasm/logger";
2
+ import { PHPResponse as Y, consumeAPI as F, SupportedPHPVersions as te, printDebugDetails as ye, exposeAPI as be, exposeSyncAPI as ve } from "@php-wasm/universal";
3
+ import { resolveRemoteBlueprint as Pe, resolveRuntimeConfiguration as re, compileBlueprintV1 as Se, isBlueprintBundle as xe, runBlueprintV1Steps as ke } from "@wp-playground/blueprints";
4
+ import { zipDirectory as Ie, RecommendedPHPVersion as U } from "@wp-playground/common";
5
+ import p, { existsSync as X, rmdirSync as $e, mkdirSync as z, readdirSync as Te } from "fs";
6
+ import { MessageChannel as Be, Worker as oe } from "worker_threads";
7
+ import { createNodeFsMountHandler as Ee, FileLockManagerForNode as Le } from "@php-wasm/node";
8
+ import h, { basename as A, join as ue } from "path";
9
+ import We from "express";
10
+ import O, { cpus as Ce } from "os";
11
+ import { jspi as Me } from "wasm-feature-detect";
12
12
  import Re from "yargs";
13
- import { NodeJsFilesystem as De, OverlayFilesystem as Ue, InMemoryFilesystem as Fe, ZipFilesystem as Ae } from "@wp-playground/storage";
14
- import { EmscriptenDownloadMonitor as He, ProgressTracker as Ve } from "@php-wasm/progress";
15
- import { resolveWordPressRelease as Ne } from "@wp-playground/wordpress";
16
- import C from "fs-extra";
17
- import { startBridge as Oe } from "@php-wasm/xdebug-bridge";
18
- import { exec as _e } from "child_process";
19
- import { dir as je, setGracefulCleanup as qe } from "tmp-promise";
20
- import ze from "ps-man";
21
- import { removeTempDirSymlink as Xe, createTempDirSymlink as Ye, clearXdebugIDEConfig as Ze, addXdebugIDEConfig as Ge } from "@php-wasm/cli-util";
22
- import { createHash as Je } from "crypto";
23
- function O(e) {
13
+ import { NodeJsFilesystem as De, OverlayFilesystem as Ae, InMemoryFilesystem as Fe, ZipFilesystem as Ue } from "@wp-playground/storage";
14
+ import { EmscriptenDownloadMonitor as Oe, ProgressTracker as He } from "@php-wasm/progress";
15
+ import { resolveWordPressRelease as Ve } from "@wp-playground/wordpress";
16
+ import B from "fs-extra";
17
+ import { startBridge as Ne } from "@php-wasm/xdebug-bridge";
18
+ import { exec as je } from "child_process";
19
+ import { dir as _e, setGracefulCleanup as qe } from "tmp-promise";
20
+ import Ye from "ps-man";
21
+ import { removeTempDirSymlink as ze, createTempDirSymlink as Qe, clearXdebugIDEConfig as Xe, addXdebugIDEConfig as Ze } from "@php-wasm/cli-util";
22
+ import { createHash as Ge } from "crypto";
23
+ function _(e) {
24
24
  const t = [];
25
- for (const o of e) {
26
- const n = o.split(":");
27
- if (n.length !== 2)
28
- throw new Error(`Invalid mount format: ${o}.
25
+ for (const r of e) {
26
+ const s = r.split(":");
27
+ if (s.length !== 2)
28
+ throw new Error(`Invalid mount format: ${r}.
29
29
  Expected format: /host/path:/vfs/path.
30
30
  If your path contains a colon, e.g. C:\\myplugin, use the --mount-dir option instead.
31
31
  Example: --mount-dir C:\\my-plugin /wordpress/wp-content/plugins/my-plugin`);
32
- const [r, s] = n;
33
- if (!Y(r))
34
- throw new Error(`Host path does not exist: ${r}`);
35
- t.push({ hostPath: r, vfsPath: s });
32
+ const [o, i] = s;
33
+ if (!X(o))
34
+ throw new Error(`Host path does not exist: ${o}`);
35
+ t.push({ hostPath: o, vfsPath: i });
36
36
  }
37
37
  return t;
38
38
  }
@@ -40,25 +40,25 @@ function se(e) {
40
40
  if (e.length % 2 !== 0)
41
41
  throw new Error("Invalid mount format. Expected: /host/path /vfs/path");
42
42
  const t = [];
43
- for (let o = 0; o < e.length; o += 2) {
44
- const n = e[o], r = e[o + 1];
45
- if (!Y(n))
46
- throw new Error(`Host path does not exist: ${n}`);
43
+ for (let r = 0; r < e.length; r += 2) {
44
+ const s = e[r], o = e[r + 1];
45
+ if (!X(s))
46
+ throw new Error(`Host path does not exist: ${s}`);
47
47
  t.push({
48
- hostPath: h.resolve(process.cwd(), n),
49
- vfsPath: r
48
+ hostPath: h.resolve(process.cwd(), s),
49
+ vfsPath: o
50
50
  });
51
51
  }
52
52
  return t;
53
53
  }
54
- async function Zt(e, t) {
55
- for (const o of t)
54
+ async function Gt(e, t) {
55
+ for (const r of t)
56
56
  await e.mount(
57
- o.vfsPath,
58
- Ce(o.hostPath)
57
+ r.vfsPath,
58
+ Ee(r.hostPath)
59
59
  );
60
60
  }
61
- const ne = {
61
+ const ie = {
62
62
  step: "runPHP",
63
63
  code: {
64
64
  filename: "activate-theme.php",
@@ -77,112 +77,119 @@ const ne = {
77
77
  `
78
78
  }
79
79
  };
80
- function ue(e) {
81
- const t = e.autoMount, o = [...e.mount || []], n = [...e["mount-before-install"] || []], r = {
80
+ function de(e) {
81
+ const t = e.autoMount, r = [...e.mount || []], s = [...e["mount-before-install"] || []], o = {
82
82
  ...e,
83
- mount: o,
84
- "mount-before-install": n,
83
+ mount: r,
84
+ "mount-before-install": s,
85
85
  "additional-blueprint-steps": [
86
86
  ...e["additional-blueprint-steps"] || []
87
87
  ]
88
88
  };
89
89
  if (tt(t)) {
90
- const s = R(t);
91
- o.push({
90
+ const n = `/wordpress/wp-content/plugins/${A(t)}`;
91
+ r.push({
92
92
  hostPath: t,
93
- vfsPath: `/wordpress/wp-content/plugins/${s}`
94
- }), r["additional-blueprint-steps"].push({
93
+ vfsPath: n,
94
+ autoMounted: !0
95
+ }), o["additional-blueprint-steps"].push({
95
96
  step: "activatePlugin",
96
- pluginPath: `/wordpress/wp-content/plugins/${R(t)}`
97
+ pluginPath: `/wordpress/wp-content/plugins/${A(t)}`
97
98
  });
98
99
  } else if (et(t)) {
99
- const s = R(t);
100
- o.push({
100
+ const i = A(t), n = `/wordpress/wp-content/themes/${i}`;
101
+ r.push({
101
102
  hostPath: t,
102
- vfsPath: `/wordpress/wp-content/themes/${s}`
103
- }), r["additional-blueprint-steps"].push(
103
+ vfsPath: n,
104
+ autoMounted: !0
105
+ }), o["additional-blueprint-steps"].push(
104
106
  e["experimental-blueprints-v2-runner"] ? {
105
107
  step: "activateTheme",
106
- themeDirectoryName: s
108
+ themeDirectoryName: i
107
109
  } : {
108
110
  step: "activateTheme",
109
- themeFolderName: s
111
+ themeFolderName: i
110
112
  }
111
113
  );
112
114
  } else if (Ke(t)) {
113
- const s = f.readdirSync(t);
114
- for (const i of s)
115
- i !== "index.php" && o.push({
116
- hostPath: `${t}/${i}`,
117
- vfsPath: `/wordpress/wp-content/${i}`
115
+ const i = p.readdirSync(t);
116
+ for (const n of i)
117
+ n !== "index.php" && r.push({
118
+ hostPath: `${t}/${n}`,
119
+ vfsPath: `/wordpress/wp-content/${n}`,
120
+ autoMounted: !0
118
121
  });
119
- r["additional-blueprint-steps"].push(ne);
120
- } else Qe(t) && (n.push({ hostPath: t, vfsPath: "/wordpress" }), r.mode = "apply-to-existing-site", r["additional-blueprint-steps"].push(ne), r.wordpressInstallMode || (r.wordpressInstallMode = "install-from-existing-files-if-needed"));
121
- return r;
122
+ o["additional-blueprint-steps"].push(ie);
123
+ } else Je(t) && (s.push({
124
+ hostPath: t,
125
+ vfsPath: "/wordpress",
126
+ autoMounted: !0
127
+ }), o.mode = "apply-to-existing-site", o["additional-blueprint-steps"].push(ie), o.wordpressInstallMode || (o.wordpressInstallMode = "install-from-existing-files-if-needed"));
128
+ return o;
122
129
  }
123
- function Qe(e) {
124
- const t = f.readdirSync(e);
130
+ function Je(e) {
131
+ const t = p.readdirSync(e);
125
132
  return t.includes("wp-admin") && t.includes("wp-includes") && t.includes("wp-content");
126
133
  }
127
134
  function Ke(e) {
128
- const t = f.readdirSync(e);
135
+ const t = p.readdirSync(e);
129
136
  return t.includes("themes") || t.includes("plugins") || t.includes("mu-plugins") || t.includes("uploads");
130
137
  }
131
138
  function et(e) {
132
- if (!f.readdirSync(e).includes("style.css"))
139
+ if (!p.readdirSync(e).includes("style.css"))
133
140
  return !1;
134
- const o = f.readFileSync(de(e, "style.css"), "utf8");
135
- return !!/^(?:[ \t]*<\?php)?[ \t/*#@]*Theme Name:(.*)$/im.exec(o);
141
+ const r = p.readFileSync(ue(e, "style.css"), "utf8");
142
+ return !!/^(?:[ \t]*<\?php)?[ \t/*#@]*Theme Name:(.*)$/im.exec(r);
136
143
  }
137
144
  function tt(e) {
138
- const t = f.readdirSync(e), o = /^(?:[ \t]*<\?php)?[ \t/*#@]*Plugin Name:(.*)$/im;
139
- return !!t.filter((r) => r.endsWith(".php")).find((r) => {
140
- const s = f.readFileSync(de(e, r), "utf8");
141
- return !!o.exec(s);
145
+ const t = p.readdirSync(e), r = /^(?:[ \t]*<\?php)?[ \t/*#@]*Plugin Name:(.*)$/im;
146
+ return !!t.filter((o) => o.endsWith(".php")).find((o) => {
147
+ const i = p.readFileSync(ue(e, o), "utf8");
148
+ return !!r.exec(i);
142
149
  });
143
150
  }
144
- async function ot(e) {
145
- const t = Be(), o = await new Promise((s, i) => {
151
+ async function rt(e) {
152
+ const t = We(), r = await new Promise((i, n) => {
146
153
  const l = t.listen(e.port, () => {
147
- const d = l.address();
148
- d === null || typeof d == "string" ? i(new Error("Server address is not available")) : s(l);
154
+ const u = l.address();
155
+ u === null || typeof u == "string" ? n(new Error("Server address is not available")) : i(l);
149
156
  });
150
157
  });
151
- t.use("/", async (s, i) => {
158
+ t.use("/", async (i, n) => {
152
159
  let l;
153
160
  try {
154
161
  l = await e.handleRequest({
155
- url: s.url,
156
- headers: st(s),
157
- method: s.method,
158
- body: await rt(s)
162
+ url: i.url,
163
+ headers: st(i),
164
+ method: i.method,
165
+ body: await ot(i)
159
166
  });
160
- } catch (d) {
161
- u.error(d), l = j.forHttpCode(500);
167
+ } catch (u) {
168
+ g.error(u), l = Y.forHttpCode(500);
162
169
  }
163
- i.statusCode = l.httpStatusCode;
164
- for (const d in l.headers)
165
- i.setHeader(d, l.headers[d]);
166
- i.end(l.bytes);
170
+ n.statusCode = l.httpStatusCode;
171
+ for (const u in l.headers)
172
+ n.setHeader(u, l.headers[u]);
173
+ n.end(l.bytes);
167
174
  });
168
- const r = o.address().port;
169
- return await e.onBind(o, r);
175
+ const o = r.address().port;
176
+ return await e.onBind(r, o);
170
177
  }
171
- const rt = async (e) => await new Promise((t) => {
172
- const o = [];
173
- e.on("data", (n) => {
174
- o.push(n);
178
+ const ot = async (e) => await new Promise((t) => {
179
+ const r = [];
180
+ e.on("data", (s) => {
181
+ r.push(s);
175
182
  }), e.on("end", () => {
176
- t(new Uint8Array(Buffer.concat(o)));
183
+ t(new Uint8Array(Buffer.concat(r)));
177
184
  });
178
185
  }), st = (e) => {
179
186
  const t = {};
180
187
  if (e.rawHeaders && e.rawHeaders.length)
181
- for (let o = 0; o < e.rawHeaders.length; o += 2)
182
- t[e.rawHeaders[o].toLowerCase()] = e.rawHeaders[o + 1];
188
+ for (let r = 0; r < e.rawHeaders.length; r += 2)
189
+ t[e.rawHeaders[r].toLowerCase()] = e.rawHeaders[r + 1];
183
190
  return t;
184
191
  };
185
- class nt {
192
+ class it {
186
193
  constructor(t) {
187
194
  this.workerLoads = [], this.addWorker(t);
188
195
  }
@@ -193,27 +200,27 @@ class nt {
193
200
  });
194
201
  }
195
202
  async removeWorker(t) {
196
- const o = this.workerLoads.findIndex(
197
- (r) => r.worker === t
203
+ const r = this.workerLoads.findIndex(
204
+ (o) => o.worker === t
198
205
  );
199
- if (o === -1)
206
+ if (r === -1)
200
207
  return;
201
- const [n] = this.workerLoads.splice(o, 1);
202
- await Promise.allSettled(n.activeRequests);
208
+ const [s] = this.workerLoads.splice(r, 1);
209
+ await Promise.allSettled(s.activeRequests);
203
210
  }
204
211
  async handleRequest(t) {
205
- let o = this.workerLoads[0];
206
- for (let r = 1; r < this.workerLoads.length; r++) {
207
- const s = this.workerLoads[r];
208
- s.activeRequests.size < o.activeRequests.size && (o = s);
212
+ let r = this.workerLoads[0];
213
+ for (let o = 1; o < this.workerLoads.length; o++) {
214
+ const i = this.workerLoads[o];
215
+ i.activeRequests.size < r.activeRequests.size && (r = i);
209
216
  }
210
- const n = o.worker.request(t);
211
- return o.activeRequests.add(n), n.url = t.url, n.finally(() => {
212
- o.activeRequests.delete(n);
217
+ const s = r.worker.request(t);
218
+ return r.activeRequests.add(s), s.url = t.url, s.finally(() => {
219
+ r.activeRequests.delete(s);
213
220
  });
214
221
  }
215
222
  }
216
- function it(e) {
223
+ function nt(e) {
217
224
  return /^latest$|^trunk$|^nightly$|^(?:(\d+)\.(\d+)(?:\.(\d+))?)((?:-beta(?:\d+)?)|(?:-RC(?:\d+)?))?$/.test(e);
218
225
  }
219
226
  async function at({
@@ -223,72 +230,69 @@ async function at({
223
230
  if (!e)
224
231
  return;
225
232
  if (e.startsWith("http://") || e.startsWith("https://"))
226
- return await ve(e);
227
- let o = h.resolve(process.cwd(), e);
228
- if (!f.existsSync(o))
229
- throw new Error(`Blueprint file does not exist: ${o}`);
230
- const n = f.statSync(o);
231
- if (n.isDirectory() && (o = h.join(o, "blueprint.json")), !n.isFile() && n.isSymbolicLink())
233
+ return await Pe(e);
234
+ let r = h.resolve(process.cwd(), e);
235
+ if (!p.existsSync(r))
236
+ throw new Error(`Blueprint file does not exist: ${r}`);
237
+ const s = p.statSync(r);
238
+ if (s.isDirectory() && (r = h.join(r, "blueprint.json")), !s.isFile() && s.isSymbolicLink())
232
239
  throw new Error(
233
- `Blueprint path is neither a file nor a directory: ${o}`
240
+ `Blueprint path is neither a file nor a directory: ${r}`
234
241
  );
235
- const r = h.extname(o);
236
- switch (r) {
242
+ const o = h.extname(r);
243
+ switch (o) {
237
244
  case ".zip":
238
- return Ae.fromArrayBuffer(
239
- f.readFileSync(o).buffer
245
+ return Ue.fromArrayBuffer(
246
+ p.readFileSync(r).buffer
240
247
  );
241
248
  case ".json": {
242
- const s = f.readFileSync(o, "utf-8");
249
+ const i = p.readFileSync(r, "utf-8");
243
250
  try {
244
- JSON.parse(s);
251
+ JSON.parse(i);
245
252
  } catch {
246
253
  throw new Error(
247
- `Blueprint file at ${o} is not a valid JSON file`
254
+ `Blueprint file at ${r} is not a valid JSON file`
248
255
  );
249
256
  }
250
- const i = h.dirname(o), l = new De(i);
251
- return new Ue([
257
+ const n = h.dirname(r), l = new De(n);
258
+ return new Ae([
252
259
  new Fe({
253
- "blueprint.json": s
260
+ "blueprint.json": i
254
261
  }),
255
262
  /**
256
263
  * Wrap the NodeJS filesystem to prevent access to local files
257
264
  * unless the user explicitly allowed it.
258
265
  */
259
266
  {
260
- read(d) {
267
+ read(u) {
261
268
  if (!t)
262
269
  throw new Error(
263
- `Error: Blueprint contained tried to read a local file at path "${d}" (via a resource of type "bundled"). Playground restricts access to local resources by default as a security measure.
270
+ `Error: Blueprint contained tried to read a local file at path "${u}" (via a resource of type "bundled"). Playground restricts access to local resources by default as a security measure.
264
271
 
265
272
  You can allow this Blueprint to read files from the same parent directory by explicitly adding the --blueprint-may-read-adjacent-files option to your command.`
266
273
  );
267
- return l.read(d);
274
+ return l.read(u);
268
275
  }
269
276
  }
270
277
  ]);
271
278
  }
272
279
  default:
273
280
  throw new Error(
274
- `Unsupported blueprint file extension: ${r}. Only .zip and .json files are supported.`
281
+ `Unsupported blueprint file extension: ${o}. Only .zip and .json files are supported.`
275
282
  );
276
283
  }
277
284
  }
278
- function ce(e) {
279
- return process.env.CI === "true" || process.env.CI === "1" || process.env.GITHUB_ACTIONS === "true" || process.env.GITHUB_ACTIONS === "1" || (process.env.TERM || "").toLowerCase() === "dumb" ? !1 : e ? !!e.isTTY : process.stdout.isTTY;
280
- }
281
285
  class lt {
282
- constructor(t, o) {
283
- this.lastProgressMessage = "", this.args = t, this.siteUrl = o.siteUrl, this.processIdSpaceLength = o.processIdSpaceLength, this.phpVersion = t.php;
286
+ constructor(t, r) {
287
+ this.args = t, this.siteUrl = r.siteUrl, this.processIdSpaceLength = r.processIdSpaceLength, this.phpVersion = t.php, this.cliOutput = r.cliOutput;
284
288
  }
285
289
  getWorkerType() {
286
290
  return "v2";
287
291
  }
288
- async bootAndSetUpInitialPlayground(t, o, n) {
289
- const r = D(t);
290
- await r.useFileLockManager(o);
291
- const s = {
292
+ async bootAndSetUpInitialPlayground(t, r, s) {
293
+ const o = F(t);
294
+ await o.useFileLockManager(r);
295
+ const i = {
292
296
  ...this.args,
293
297
  phpVersion: this.phpVersion,
294
298
  siteUrl: this.siteUrl,
@@ -303,125 +307,119 @@ class lt {
303
307
  // TODO: Consider supporting Xdebug for the initial worker via a dedicated flag.
304
308
  withXdebug: !1,
305
309
  xdebug: void 0,
306
- nativeInternalDirPath: n,
310
+ nativeInternalDirPath: s,
307
311
  mountsBeforeWpInstall: this.args["mount-before-install"] || [],
308
312
  mountsAfterWpInstall: this.args.mount || []
309
313
  };
310
- return await r.bootAndSetUpInitialWorker(s), r;
314
+ return await o.bootAndSetUpInitialWorker(i), o;
311
315
  }
312
316
  async bootPlayground({
313
317
  worker: t,
314
- fileLockManagerPort: o,
315
- firstProcessId: n,
316
- nativeInternalDirPath: r
318
+ fileLockManagerPort: r,
319
+ firstProcessId: s,
320
+ nativeInternalDirPath: o
317
321
  }) {
318
- const s = D(t.phpPort);
319
- await s.useFileLockManager(o);
320
- const i = {
322
+ const i = F(t.phpPort);
323
+ await i.useFileLockManager(r);
324
+ const n = {
321
325
  ...this.args,
322
326
  phpVersion: this.phpVersion,
323
327
  siteUrl: this.siteUrl,
324
- firstProcessId: n,
328
+ firstProcessId: s,
325
329
  processIdSpaceLength: this.processIdSpaceLength,
326
330
  trace: this.args.verbosity === "debug",
327
331
  withIntl: this.args.intl,
328
332
  withXdebug: !!this.args.xdebug,
329
- nativeInternalDirPath: r,
333
+ nativeInternalDirPath: o,
330
334
  mountsBeforeWpInstall: this.args["mount-before-install"] || [],
331
335
  mountsAfterWpInstall: this.args.mount || []
332
336
  };
333
- return await s.bootWorker(i), s;
334
- }
335
- writeProgressUpdate(t, o, n) {
336
- ce(t) && o !== this.lastProgressMessage && (this.lastProgressMessage = o, t.isTTY ? (t.cursorTo(0), t.write(o), t.clearLine(1), n && t.write(`
337
- `)) : t.write(`${o}
338
- `));
337
+ return await i.bootWorker(n), i;
339
338
  }
340
339
  }
341
- const X = h.join(U.homedir(), ".wordpress-playground");
342
- async function dt(e) {
340
+ const Q = h.join(O.homedir(), ".wordpress-playground");
341
+ async function ut(e) {
343
342
  return await pe(
344
343
  "https://github.com/WordPress/sqlite-database-integration/archive/refs/heads/develop.zip",
345
344
  "sqlite.zip",
346
345
  e
347
346
  );
348
347
  }
349
- async function pe(e, t, o) {
350
- const n = h.join(X, t);
351
- return C.existsSync(n) || (C.ensureDirSync(X), await ut(e, n, o)), fe(n);
348
+ async function pe(e, t, r) {
349
+ const s = h.join(Q, t);
350
+ return B.existsSync(s) || (B.ensureDirSync(Q), await dt(e, s, r)), ce(s);
352
351
  }
353
- async function ut(e, t, o) {
354
- const r = (await o.monitorFetch(fetch(e))).body.getReader(), s = `${t}.partial`, i = C.createWriteStream(s);
352
+ async function dt(e, t, r) {
353
+ const o = (await r.monitorFetch(fetch(e))).body.getReader(), i = `${t}.partial`, n = B.createWriteStream(i);
355
354
  for (; ; ) {
356
- const { done: l, value: d } = await r.read();
357
- if (d && i.write(d), l)
355
+ const { done: l, value: u } = await o.read();
356
+ if (u && n.write(u), l)
358
357
  break;
359
358
  }
360
- i.close(), i.closed || await new Promise((l, d) => {
361
- i.on("finish", () => {
362
- C.renameSync(s, t), l(null);
363
- }), i.on("error", (b) => {
364
- C.removeSync(s), d(b);
359
+ n.close(), n.closed || await new Promise((l, u) => {
360
+ n.on("finish", () => {
361
+ B.renameSync(i, t), l(null);
362
+ }), n.on("error", (b) => {
363
+ B.removeSync(i), u(b);
365
364
  });
366
365
  });
367
366
  }
368
- function fe(e, t) {
369
- return new File([C.readFileSync(e)], R(e));
367
+ function ce(e, t) {
368
+ return new File([B.readFileSync(e)], A(e));
370
369
  }
371
- class ct {
372
- constructor(t, o) {
373
- this.lastProgressMessage = "", this.args = t, this.siteUrl = o.siteUrl, this.processIdSpaceLength = o.processIdSpaceLength;
370
+ class pt {
371
+ constructor(t, r) {
372
+ this.args = t, this.siteUrl = r.siteUrl, this.processIdSpaceLength = r.processIdSpaceLength, this.cliOutput = r.cliOutput;
374
373
  }
375
374
  getWorkerType() {
376
375
  return "v1";
377
376
  }
378
- async bootAndSetUpInitialPlayground(t, o, n) {
379
- let r, s, i;
380
- const l = new He();
377
+ async bootAndSetUpInitialPlayground(t, r, s) {
378
+ let o, i, n;
379
+ const l = new Oe();
381
380
  if (this.args.wordpressInstallMode === "download-and-install") {
382
- let v = !1;
383
- l.addEventListener("progress", (W) => {
384
- if (v)
381
+ let E = !1;
382
+ l.addEventListener("progress", (k) => {
383
+ if (E)
385
384
  return;
386
- const { loaded: G, total: F } = W.detail, k = Math.floor(
387
- Math.min(100, 100 * G / F)
385
+ const { loaded: W, total: Z } = k.detail, C = Math.floor(
386
+ Math.min(100, 100 * W / Z)
388
387
  );
389
- v = k === 100, this.writeProgressUpdate(
390
- process.stdout,
391
- `Downloading WordPress ${k}%...`,
392
- v
388
+ E = C === 100, this.cliOutput.updateProgress(
389
+ "Downloading WordPress",
390
+ C
393
391
  );
394
- }), r = await Ne(this.args.wp), i = h.join(
395
- X,
396
- `prebuilt-wp-content-for-wp-${r.version}.zip`
397
- ), s = f.existsSync(i) ? fe(i) : await pe(
398
- r.releaseUrl,
399
- `${r.version}.zip`,
392
+ }), o = await Ve(this.args.wp), n = h.join(
393
+ Q,
394
+ `prebuilt-wp-content-for-wp-${o.version}.zip`
395
+ ), i = p.existsSync(n) ? ce(n) : await pe(
396
+ o.releaseUrl,
397
+ `${o.version}.zip`,
400
398
  l
401
- ), u.log(
402
- `Resolved WordPress release URL: ${r?.releaseUrl}`
399
+ ), g.debug(
400
+ `Resolved WordPress release URL: ${o?.releaseUrl}`
403
401
  );
404
402
  }
405
- let d;
406
- this.args.skipSqliteSetup ? (u.log("Skipping SQLite integration plugin setup..."), d = void 0) : (u.log("Fetching SQLite integration plugin..."), d = await dt(l));
407
- const b = this.args.followSymlinks === !0, g = this.args.experimentalTrace === !0, a = this.args["mount-before-install"] || [], y = this.args.mount || [], p = D(t);
408
- await p.isConnected(), u.log("Booting WordPress...");
409
- const I = await oe(
403
+ let u;
404
+ this.args.skipSqliteSetup ? (g.debug("Skipping SQLite integration plugin setup..."), u = void 0) : (this.cliOutput.updateProgress("Preparing SQLite database"), u = await ut(l));
405
+ const b = this.args.followSymlinks === !0, v = this.args.experimentalTrace === !0, a = this.args["mount-before-install"] || [], f = this.args.mount || [], c = F(t);
406
+ await c.isConnected(), this.cliOutput.updateProgress("Booting WordPress");
407
+ const S = await re(
410
408
  this.getEffectiveBlueprint()
411
409
  );
412
- return await p.useFileLockManager(o), await p.bootAndSetUpInitialWorker({
413
- phpVersion: I.phpVersion,
414
- wpVersion: I.wpVersion,
410
+ return await c.useFileLockManager(r), await c.bootAndSetUpInitialWorker({
411
+ phpVersion: S.phpVersion,
412
+ wpVersion: S.wpVersion,
415
413
  siteUrl: this.siteUrl,
416
414
  mountsBeforeWpInstall: a,
417
- mountsAfterWpInstall: y,
415
+ mountsAfterWpInstall: f,
418
416
  wordpressInstallMode: this.args.wordpressInstallMode || "download-and-install",
419
- wordPressZip: s && await s.arrayBuffer(),
420
- sqliteIntegrationPluginZip: await d?.arrayBuffer(),
417
+ wordPressZip: i && await i.arrayBuffer(),
418
+ sqliteIntegrationPluginZip: await u?.arrayBuffer(),
421
419
  firstProcessId: 0,
422
420
  processIdSpaceLength: this.processIdSpaceLength,
423
421
  followSymlinks: b,
424
- trace: g,
422
+ trace: v,
425
423
  internalCookieStore: this.args.internalCookieStore,
426
424
  withIntl: this.args.intl,
427
425
  // We do not enable Xdebug by default for the initial worker
@@ -429,31 +427,31 @@ class ct {
429
427
  // until Playground has fully booted.
430
428
  // TODO: Consider supporting Xdebug for the initial worker via a dedicated flag.
431
429
  withXdebug: !1,
432
- nativeInternalDirPath: n
433
- }), i && !this.args["mount-before-install"] && !f.existsSync(i) && (u.log("Caching preinstalled WordPress for the next boot..."), f.writeFileSync(
434
- i,
435
- await Ie(p, "/wordpress")
436
- ), u.log("Cached!")), p;
430
+ nativeInternalDirPath: s
431
+ }), n && !this.args["mount-before-install"] && !p.existsSync(n) && (this.cliOutput.updateProgress("Caching WordPress for next boot"), p.writeFileSync(
432
+ n,
433
+ await Ie(c, "/wordpress")
434
+ )), c;
437
435
  }
438
436
  async bootPlayground({
439
437
  worker: t,
440
- fileLockManagerPort: o,
441
- firstProcessId: n,
442
- nativeInternalDirPath: r
438
+ fileLockManagerPort: r,
439
+ firstProcessId: s,
440
+ nativeInternalDirPath: o
443
441
  }) {
444
- const s = D(
442
+ const i = F(
445
443
  t.phpPort
446
444
  );
447
- await s.isConnected();
448
- const i = await oe(
445
+ await i.isConnected();
446
+ const n = await re(
449
447
  this.getEffectiveBlueprint()
450
448
  );
451
- return await s.useFileLockManager(o), await s.bootWorker({
452
- phpVersion: i.phpVersion,
449
+ return await i.useFileLockManager(r), await i.bootWorker({
450
+ phpVersion: n.phpVersion,
453
451
  siteUrl: this.siteUrl,
454
452
  mountsBeforeWpInstall: this.args["mount-before-install"] || [],
455
453
  mountsAfterWpInstall: this.args.mount || [],
456
- firstProcessId: n,
454
+ firstProcessId: s,
457
455
  processIdSpaceLength: this.processIdSpaceLength,
458
456
  followSymlinks: this.args.followSymlinks === !0,
459
457
  trace: this.args.experimentalTrace === !0,
@@ -462,26 +460,20 @@ class ct {
462
460
  internalCookieStore: this.args.internalCookieStore,
463
461
  withIntl: this.args.intl,
464
462
  withXdebug: !!this.args.xdebug,
465
- nativeInternalDirPath: r
466
- }), await s.isReady(), s;
463
+ nativeInternalDirPath: o
464
+ }), await i.isReady(), i;
467
465
  }
468
466
  async compileInputBlueprint(t) {
469
- const o = this.getEffectiveBlueprint(), n = new Ve();
470
- let r = "", s = !1;
471
- return n.addEventListener("progress", (i) => {
472
- if (s)
467
+ const r = this.getEffectiveBlueprint(), s = new He();
468
+ let o = "", i = !1;
469
+ return s.addEventListener("progress", (n) => {
470
+ if (i)
473
471
  return;
474
- s = i.detail.progress === 100;
475
- const l = Math.floor(i.detail.progress);
476
- r = i.detail.caption || r || "Running the Blueprint";
477
- const d = `${r.trim()} – ${l}%`;
478
- this.writeProgressUpdate(
479
- process.stdout,
480
- d,
481
- s
482
- );
483
- }), await ke(o, {
484
- progress: n,
472
+ i = n.detail.progress === 100;
473
+ const l = Math.floor(n.detail.progress);
474
+ o = n.detail.caption || o || "Running Blueprint", this.cliOutput.updateProgress(o.trim(), l);
475
+ }), await Se(r, {
476
+ progress: s,
485
477
  additionalSteps: t
486
478
  });
487
479
  }
@@ -491,21 +483,16 @@ class ct {
491
483
  login: this.args.login,
492
484
  ...t || {},
493
485
  preferredVersions: {
494
- php: this.args.php ?? t?.preferredVersions?.php ?? q,
486
+ php: this.args.php ?? t?.preferredVersions?.php ?? U,
495
487
  wp: this.args.wp ?? t?.preferredVersions?.wp ?? "latest",
496
488
  ...t?.preferredVersions || {}
497
489
  }
498
490
  };
499
491
  }
500
- writeProgressUpdate(t, o, n) {
501
- this.args.verbosity !== Z.Quiet.name && ce(t) && o !== this.lastProgressMessage && (this.lastProgressMessage = o, t.isTTY ? (t.cursorTo(0), t.write(o), t.clearLine(1), n && t.write(`
502
- `)) : t.write(`${o}
503
- `));
504
- }
505
492
  }
506
- async function pt(e, t = !0) {
507
- const n = `${h.basename(process.argv0)}${e}${process.pid}-`, r = await je({
508
- prefix: n,
493
+ async function ct(e, t = !0) {
494
+ const s = `${h.basename(process.argv0)}${e}${process.pid}-`, o = await _e({
495
+ prefix: s,
509
496
  /*
510
497
  * Allow recursive cleanup on process exit.
511
498
  *
@@ -516,85 +503,241 @@ async function pt(e, t = !0) {
516
503
  */
517
504
  unsafeCleanup: !0
518
505
  });
519
- return t && qe(), r;
506
+ return t && qe(), o;
520
507
  }
521
- async function ft(e, t, o) {
522
- const r = (await ht(
508
+ async function ht(e, t, r) {
509
+ const o = (await mt(
523
510
  e,
524
511
  t,
525
- o
512
+ r
526
513
  )).map(
527
- (s) => new Promise((i) => {
528
- f.rm(s, { recursive: !0 }, (l) => {
529
- l ? u.warn(
530
- `Failed to delete stale Playground temp dir: ${s}`,
514
+ (i) => new Promise((n) => {
515
+ p.rm(i, { recursive: !0 }, (l) => {
516
+ l ? g.warn(
517
+ `Failed to delete stale Playground temp dir: ${i}`,
531
518
  l
532
- ) : u.info(
533
- `Deleted stale Playground temp dir: ${s}`
534
- ), i();
519
+ ) : g.info(
520
+ `Deleted stale Playground temp dir: ${i}`
521
+ ), n();
535
522
  });
536
523
  })
537
524
  );
538
- await Promise.all(r);
525
+ await Promise.all(o);
539
526
  }
540
- async function ht(e, t, o) {
527
+ async function mt(e, t, r) {
541
528
  try {
542
- const n = f.readdirSync(o).map((s) => h.join(o, s)), r = [];
543
- for (const s of n)
544
- await mt(
529
+ const s = p.readdirSync(r).map((i) => h.join(r, i)), o = [];
530
+ for (const i of s)
531
+ await ft(
545
532
  e,
546
533
  t,
547
- s
548
- ) && r.push(s);
549
- return r;
550
- } catch (n) {
551
- return u.warn(`Failed to find stale Playground temp dirs: ${n}`), [];
534
+ i
535
+ ) && o.push(i);
536
+ return o;
537
+ } catch (s) {
538
+ return g.warn(`Failed to find stale Playground temp dirs: ${s}`), [];
552
539
  }
553
540
  }
554
- async function mt(e, t, o) {
555
- if (!f.lstatSync(o).isDirectory())
541
+ async function ft(e, t, r) {
542
+ if (!p.lstatSync(r).isDirectory())
556
543
  return !1;
557
- const r = h.basename(o);
558
- if (!r.includes(e))
544
+ const o = h.basename(r);
545
+ if (!o.includes(e))
559
546
  return !1;
560
- const s = r.match(
547
+ const i = o.match(
561
548
  new RegExp(`^(.+)${e}(\\d+)-`)
562
549
  );
563
- if (!s)
550
+ if (!i)
564
551
  return !1;
565
- const i = {
566
- executableName: s[1],
567
- pid: s[2]
552
+ const n = {
553
+ executableName: i[1],
554
+ pid: i[2]
568
555
  };
569
- if (await wt(i.pid, i.executableName))
556
+ if (await wt(n.pid, n.executableName))
570
557
  return !1;
571
558
  const l = Date.now() - t;
572
- return f.statSync(o).mtime.getTime() < l;
559
+ return p.statSync(r).mtime.getTime() < l;
573
560
  }
574
561
  async function wt(e, t) {
575
- const [o] = await new Promise(
576
- (n, r) => {
577
- ze.list(
562
+ const [r] = await new Promise(
563
+ (s, o) => {
564
+ Ye.list(
578
565
  {
579
566
  pid: e,
580
567
  name: t,
581
568
  // Remove path from executable name in the results.
582
569
  clean: !0
583
570
  },
584
- (s, i) => {
585
- s ? r(s) : n(i);
571
+ (i, n) => {
572
+ i ? o(i) : s(n);
586
573
  }
587
574
  );
588
575
  }
589
576
  );
590
- return !!o && o.pid === e && o.command === t;
577
+ return !!r && r.pid === e && r.command === t;
578
+ }
579
+ function gt(e) {
580
+ return process.env.CI === "true" || process.env.CI === "1" || process.env.GITHUB_ACTIONS === "true" || process.env.GITHUB_ACTIONS === "1" || (process.env.TERM || "").toLowerCase() === "dumb" ? !1 : e ? !!e.isTTY : process.stdout.isTTY;
591
581
  }
592
- const Z = {
593
- Quiet: { name: "quiet", severity: N.Fatal },
594
- Normal: { name: "normal", severity: N.Info },
595
- Debug: { name: "debug", severity: N.Debug }
582
+ class yt {
583
+ constructor(t) {
584
+ this.lastProgressLine = "", this.progressActive = !1, this.verbosity = t.verbosity, this.writeStream = t.writeStream || process.stdout;
585
+ }
586
+ get isTTY() {
587
+ return !!this.writeStream.isTTY;
588
+ }
589
+ /**
590
+ * Determines if progress updates should be rendered.
591
+ *
592
+ * Returns false when output is piped, redirected, or in CI environments.
593
+ * This prevents progress spam in logs - users only see the final outcome.
594
+ */
595
+ get shouldRender() {
596
+ return gt(this.writeStream);
597
+ }
598
+ get isQuiet() {
599
+ return this.verbosity === "quiet";
600
+ }
601
+ /**
602
+ * ANSI formatting helpers.
603
+ *
604
+ * These only apply color codes when outputting to a terminal (TTY).
605
+ * When piped to files or non-TTY streams, they return plain text to
606
+ * avoid polluting logs with escape sequences.
607
+ */
608
+ bold(t) {
609
+ return this.isTTY ? `\x1B[1m${t}\x1B[0m` : t;
610
+ }
611
+ dim(t) {
612
+ return this.isTTY ? `\x1B[2m${t}\x1B[0m` : t;
613
+ }
614
+ green(t) {
615
+ return this.isTTY ? `\x1B[32m${t}\x1B[0m` : t;
616
+ }
617
+ cyan(t) {
618
+ return this.isTTY ? `\x1B[36m${t}\x1B[0m` : t;
619
+ }
620
+ yellow(t) {
621
+ return this.isTTY ? `\x1B[33m${t}\x1B[0m` : t;
622
+ }
623
+ red(t) {
624
+ return this.isTTY ? `\x1B[31m${t}\x1B[0m` : t;
625
+ }
626
+ printBanner() {
627
+ if (this.isQuiet) return;
628
+ const t = this.bold("WordPress Playground CLI");
629
+ this.writeStream.write(`
630
+ ${t}
631
+
632
+ `);
633
+ }
634
+ /**
635
+ * Prints the configuration summary before starting the server.
636
+ *
637
+ * Displays PHP/WordPress versions, enabled extensions, all mounts
638
+ * (with auto-mounts labeled), and any loaded blueprint. This gives
639
+ * users a clear view of what's configured before the server boots.
640
+ */
641
+ printConfig(t) {
642
+ if (this.isQuiet) return;
643
+ const r = [];
644
+ r.push(
645
+ `${this.dim("PHP")} ${this.cyan(t.phpVersion)} ${this.dim("WordPress")} ${this.cyan(t.wpVersion)}`
646
+ );
647
+ const s = [];
648
+ if (t.intl && s.push("intl"), t.xdebug && s.push(this.yellow("xdebug")), s.length > 0 && r.push(`${this.dim("Extensions")} ${s.join(", ")}`), t.mounts.length > 0)
649
+ for (const o of t.mounts) {
650
+ const i = o.autoMounted ? ` ${this.dim("(auto-mount)")}` : "";
651
+ r.push(
652
+ `${this.dim("Mount")} ${o.hostPath} ${this.dim("→")} ${o.vfsPath}${i}`
653
+ );
654
+ }
655
+ t.blueprint && r.push(`${this.dim("Blueprint")} ${t.blueprint}`), this.writeStream.write(r.join(`
656
+ `) + `
657
+
658
+ `);
659
+ }
660
+ /**
661
+ * Starts a progress indicator that updates in-place.
662
+ *
663
+ * Subsequent updateProgress() calls rewrite the same line in TTY mode.
664
+ * When output is piped or redirected, progress is completely skipped.
665
+ */
666
+ startProgress(t) {
667
+ this.isQuiet || this.shouldRender && (this.progressActive = !0, this.updateProgress(t));
668
+ }
669
+ /**
670
+ * Updates the current progress message and optional percentage.
671
+ *
672
+ * Rewrites the current line using ANSI cursor control in TTY mode.
673
+ * Identical messages are skipped to prevent flickering. When piped,
674
+ * this method does nothing (early return via shouldRender check).
675
+ */
676
+ updateProgress(t, r) {
677
+ if (this.isQuiet || !this.shouldRender) return;
678
+ this.progressActive || (this.progressActive = !0);
679
+ let s = `${t}`;
680
+ r !== void 0 && (s = `${t} ${this.dim(`${r}%`)}`), s !== this.lastProgressLine && (this.lastProgressLine = s, this.isTTY ? (this.writeStream.cursorTo(0), this.writeStream.write(s), this.writeStream.clearLine(1)) : this.writeStream.write(`${s}
681
+ `));
682
+ }
683
+ /**
684
+ * Completes the progress indicator and moves to a new line.
685
+ *
686
+ * Optionally displays a final message before finishing. In TTY mode,
687
+ * this ensures the cursor moves to the next line after the progress.
688
+ */
689
+ finishProgress(t) {
690
+ this.isQuiet || this.shouldRender && (t && (this.isTTY ? (this.writeStream.cursorTo(0), this.writeStream.write(`${t}`), this.writeStream.clearLine(1)) : this.writeStream.write(`${t}
691
+ `)), this.isTTY && this.writeStream.write(`
692
+ `), this.progressActive = !1, this.lastProgressLine = "");
693
+ }
694
+ /**
695
+ * Prints a status message, interrupting any active progress.
696
+ *
697
+ * Unlike progress updates, status messages are always printed on their
698
+ * own line. Any active progress indicator is cleared before the message.
699
+ */
700
+ printStatus(t) {
701
+ this.isQuiet || (this.progressActive && this.isTTY && (this.writeStream.cursorTo(0), this.writeStream.clearLine(0)), this.writeStream.write(`${t}
702
+ `), this.progressActive = !1, this.lastProgressLine = "");
703
+ }
704
+ /**
705
+ * Prints an error message.
706
+ *
707
+ * Errors are always shown, even in quiet mode, and interrupt any
708
+ * active progress display to ensure visibility.
709
+ */
710
+ printError(t) {
711
+ this.progressActive && this.isTTY && (this.writeStream.cursorTo(0), this.writeStream.clearLine(0), this.progressActive = !1), this.writeStream.write(`${this.red("Error:")} ${t}
712
+ `);
713
+ }
714
+ /**
715
+ * Prints the final "server ready" message with the URL.
716
+ *
717
+ * Note: The exact wording "WordPress is running on" is checked by
718
+ * CI tests, so changes to this string will break test assertions.
719
+ */
720
+ printReady(t, r) {
721
+ if (this.isQuiet) return;
722
+ const s = r === 1 ? "worker" : "workers";
723
+ this.writeStream.write(
724
+ `
725
+ ${this.green("Ready!")} WordPress is running on ${this.bold(t)} ${this.dim(`(${r} ${s})`)}
726
+
727
+ `
728
+ );
729
+ }
730
+ printWarning(t) {
731
+ this.isQuiet || this.writeStream.write(`${this.yellow("Warning:")} ${t}
732
+ `);
733
+ }
734
+ }
735
+ const he = {
736
+ Quiet: { name: "quiet", severity: j.Fatal },
737
+ Normal: { name: "normal", severity: j.Info },
738
+ Debug: { name: "debug", severity: j.Debug }
596
739
  };
597
- async function Gt(e) {
740
+ async function Jt(e) {
598
741
  try {
599
742
  const t = {
600
743
  "site-url": {
@@ -604,7 +747,7 @@ async function Gt(e) {
604
747
  php: {
605
748
  describe: "PHP version to use.",
606
749
  type: "string",
607
- default: q,
750
+ default: U,
608
751
  choices: te
609
752
  },
610
753
  wp: {
@@ -618,13 +761,13 @@ async function Gt(e) {
618
761
  describe: "Mount a directory to the PHP runtime (can be used multiple times). Format: /host/path:/vfs/path",
619
762
  type: "array",
620
763
  string: !0,
621
- coerce: O
764
+ coerce: _
622
765
  },
623
766
  "mount-before-install": {
624
767
  describe: "Mount a directory to the PHP runtime before WordPress installation (can be used multiple times). Format: /host/path:/vfs/path",
625
768
  type: "array",
626
769
  string: !0,
627
- coerce: O
770
+ coerce: _
628
771
  },
629
772
  "mount-dir": {
630
773
  describe: 'Mount a directory to the PHP runtime (can be used multiple times). Format: "/host/path" "/vfs/path"',
@@ -685,7 +828,7 @@ async function Gt(e) {
685
828
  verbosity: {
686
829
  describe: "Output logs and progress messages.",
687
830
  type: "string",
688
- choices: Object.values(Z).map(
831
+ choices: Object.values(he).map(
689
832
  (a) => a.name
690
833
  ),
691
834
  default: "normal"
@@ -752,7 +895,7 @@ Warning: Following symlinks will expose files outside mounted directories to Pla
752
895
  // Remove the "hidden" flag once Blueprint V2 is fully supported
753
896
  hidden: !0
754
897
  }
755
- }, o = {
898
+ }, r = {
756
899
  port: {
757
900
  describe: "Port to listen on when serving.",
758
901
  type: "number",
@@ -761,13 +904,13 @@ Warning: Following symlinks will expose files outside mounted directories to Pla
761
904
  "experimental-multi-worker": {
762
905
  describe: "Enable experimental multi-worker support which requires a /wordpress directory backed by a real filesystem. Pass a positive number to specify the number of workers to use. Otherwise, default to the number of CPUs minus 1.",
763
906
  type: "number",
764
- coerce: (a) => a ?? Me().length - 1
907
+ coerce: (a) => a ?? Ce().length - 1
765
908
  },
766
909
  "experimental-devtools": {
767
910
  describe: "Enable experimental browser development tools.",
768
911
  type: "boolean"
769
912
  }
770
- }, n = {
913
+ }, s = {
771
914
  path: {
772
915
  describe: "Path to the project directory. Playground will auto-detect if this is a plugin, theme, wp-content, or WordPress directory.",
773
916
  type: "string",
@@ -776,7 +919,7 @@ Warning: Following symlinks will expose files outside mounted directories to Pla
776
919
  php: {
777
920
  describe: "PHP version to use.",
778
921
  type: "string",
779
- default: q,
922
+ default: U,
780
923
  choices: te
781
924
  },
782
925
  wp: {
@@ -823,7 +966,7 @@ Warning: Following symlinks will expose files outside mounted directories to Pla
823
966
  describe: "Mount a directory to the PHP runtime (can be used multiple times). Format: /host/path:/vfs/path. Use this for additional mounts beyond auto-detection.",
824
967
  type: "array",
825
968
  string: !0,
826
- coerce: O
969
+ coerce: _
827
970
  },
828
971
  reset: {
829
972
  describe: "Deletes the stored site directory and starts a new site from scratch.",
@@ -835,13 +978,13 @@ Warning: Following symlinks will expose files outside mounted directories to Pla
835
978
  type: "boolean",
836
979
  default: !1
837
980
  }
838
- }, r = {
981
+ }, o = {
839
982
  outfile: {
840
983
  describe: "When building, write to this output file.",
841
984
  type: "string",
842
985
  default: "wordpress.zip"
843
986
  }
844
- }, s = Re(e).usage("Usage: wp-playground <command> [options]").command(
987
+ }, i = Re(e).usage("Usage: wp-playground <command> [options]").command(
845
988
  "start",
846
989
  "Start a local WordPress server with automatic project detection (recommended)",
847
990
  (a) => a.usage(
@@ -857,13 +1000,13 @@ Examples:
857
1000
  wp-playground start --wp=6.7 --php=8.3 # Use specific versions
858
1001
  wp-playground start --skip-browser # Skip opening browser
859
1002
  wp-playground start --no-auto-mount # Disable auto-detection`
860
- ).options(n)
1003
+ ).options(s)
861
1004
  ).command(
862
1005
  "server",
863
1006
  "Start a local WordPress server (advanced, low-level)",
864
1007
  (a) => a.options({
865
1008
  ...t,
866
- ...o
1009
+ ...r
867
1010
  })
868
1011
  ).command(
869
1012
  "run-blueprint",
@@ -874,18 +1017,18 @@ Examples:
874
1017
  "Build a ZIP snapshot of a WordPress site based on a Blueprint",
875
1018
  (a) => a.options({
876
1019
  ...t,
877
- ...r
1020
+ ...o
878
1021
  })
879
1022
  ).demandCommand(1, "Please specify a command").strictCommands().conflicts(
880
1023
  "experimental-unsafe-ide-integration",
881
1024
  "experimental-devtools"
882
- ).showHelpOnFail(!1).fail((a, y, p) => {
883
- if (y)
884
- throw y;
885
- a && a.includes("Please specify a command") && (p.showHelp(), console.error(`
1025
+ ).showHelpOnFail(!1).fail((a, f, c) => {
1026
+ if (f)
1027
+ throw f;
1028
+ a && a.includes("Please specify a command") && (c.showHelp(), console.error(`
886
1029
  ` + a), process.exit(1)), console.error(a), process.exit(1);
887
1030
  }).strictOptions().check(async (a) => {
888
- if (a["skip-wordpress-install"] === !0 && (a["wordpress-install-mode"] = "do-not-attempt-installing", a.wordpressInstallMode = "do-not-attempt-installing"), a.wp !== void 0 && typeof a.wp == "string" && !it(a.wp))
1031
+ if (a["skip-wordpress-install"] === !0 && (a["wordpress-install-mode"] = "do-not-attempt-installing", a.wordpressInstallMode = "do-not-attempt-installing"), a.wp !== void 0 && typeof a.wp == "string" && !nt(a.wp))
889
1032
  try {
890
1033
  new URL(a.wp);
891
1034
  } catch {
@@ -893,25 +1036,25 @@ Examples:
893
1036
  'Unrecognized WordPress version. Please use "latest", a URL, or a numeric version such as "6.2", "6.0.1", "6.2-beta1", or "6.2-RC1"'
894
1037
  );
895
1038
  }
896
- const y = a["site-url"];
897
- if (typeof y == "string" && y.trim() !== "")
1039
+ const f = a["site-url"];
1040
+ if (typeof f == "string" && f.trim() !== "")
898
1041
  try {
899
- new URL(y);
1042
+ new URL(f);
900
1043
  } catch {
901
1044
  throw new Error(
902
- `Invalid site-url "${y}". Please provide a valid URL (e.g., http://localhost:8080 or https://example.com)`
1045
+ `Invalid site-url "${f}". Please provide a valid URL (e.g., http://localhost:8080 or https://example.com)`
903
1046
  );
904
1047
  }
905
1048
  if (a["auto-mount"]) {
906
- let p = !1;
1049
+ let c = !1;
907
1050
  try {
908
- p = f.statSync(
1051
+ c = p.statSync(
909
1052
  a["auto-mount"]
910
1053
  ).isDirectory();
911
1054
  } catch {
912
- p = !1;
1055
+ c = !1;
913
1056
  }
914
- if (!p)
1057
+ if (!c)
915
1058
  throw new Error(
916
1059
  `The specified --auto-mount path is not a directory: '${a["auto-mount"]}'.`
917
1060
  );
@@ -942,148 +1085,162 @@ Examples:
942
1085
  );
943
1086
  } else
944
1087
  a["wordpress-install-mode"] === "do-not-attempt-installing" ? a.mode = "apply-to-existing-site" : a.mode = "create-new-site";
945
- const p = a.allow || [];
946
- a.followSymlinks === !0 && p.push("follow-symlinks"), a["blueprint-may-read-adjacent-files"] === !0 && p.push("read-local-fs"), a.allow = p;
1088
+ const c = a.allow || [];
1089
+ a.followSymlinks === !0 && c.push("follow-symlinks"), a["blueprint-may-read-adjacent-files"] === !0 && c.push("read-local-fs"), a.allow = c;
947
1090
  } else if (a.mode !== void 0)
948
1091
  throw new Error(
949
1092
  "The --mode option requires the --experimentalBlueprintsV2Runner flag."
950
1093
  );
951
1094
  return !0;
952
1095
  });
953
- s.wrap(s.terminalWidth());
954
- const i = await s.argv, l = i._[0];
1096
+ i.wrap(i.terminalWidth());
1097
+ const n = await i.argv, l = n._[0];
955
1098
  ["start", "run-blueprint", "server", "build-snapshot"].includes(
956
1099
  l
957
- ) || (s.showHelp(), process.exit(1));
958
- const d = {
959
- ...i,
1100
+ ) || (i.showHelp(), process.exit(1));
1101
+ const u = {
1102
+ ...n,
960
1103
  command: l,
961
1104
  mount: [
962
- ...i.mount || [],
963
- ...i["mount-dir"] || []
1105
+ ...n.mount || [],
1106
+ ...n["mount-dir"] || []
964
1107
  ],
965
1108
  "mount-before-install": [
966
- ...i["mount-before-install"] || [],
967
- ...i["mount-dir-before-install"] || []
1109
+ ...n["mount-before-install"] || [],
1110
+ ...n["mount-dir-before-install"] || []
968
1111
  ]
969
- }, b = await Pt(d);
1112
+ }, b = await St(u);
970
1113
  b === void 0 && process.exit(0);
971
- const g = /* @__PURE__ */ (() => {
1114
+ const v = /* @__PURE__ */ (() => {
972
1115
  let a;
973
1116
  return async () => {
974
1117
  a !== void 0 && (a = b[Symbol.asyncDispose]()), await a, process.exit(0);
975
1118
  };
976
1119
  })();
977
- process.on("SIGINT", g), process.on("SIGTERM", g);
1120
+ process.on("SIGINT", v), process.on("SIGTERM", v);
978
1121
  } catch (t) {
979
1122
  if (console.error(t), !(t instanceof Error))
980
1123
  throw t;
981
1124
  if (process.argv.includes("--debug"))
982
1125
  ye(t);
983
1126
  else {
984
- const n = [];
985
- let r = t;
1127
+ const s = [];
1128
+ let o = t;
986
1129
  do
987
- n.push(r.message), r = r.cause;
988
- while (r instanceof Error);
1130
+ s.push(o.message), o = o.cause;
1131
+ while (o instanceof Error);
989
1132
  console.error(
990
- "\x1B[1m" + n.join(" caused by: ") + "\x1B[0m"
1133
+ "\x1B[1m" + s.join(" caused by: ") + "\x1B[0m"
991
1134
  );
992
1135
  }
993
1136
  process.exit(1);
994
1137
  }
995
1138
  }
996
- function ie(e, t) {
1139
+ function ne(e, t) {
997
1140
  return e.find(
998
- (o) => o.vfsPath.replace(/\/$/, "") === t.replace(/\/$/, "")
1141
+ (r) => r.vfsPath.replace(/\/$/, "") === t.replace(/\/$/, "")
999
1142
  );
1000
1143
  }
1001
- const gt = Symbol("playground-cli-testing"), E = (e) => process.stdout.isTTY ? "\x1B[1m" + e + "\x1B[0m" : e, yt = (e) => process.stdout.isTTY ? "\x1B[31m" + e + "\x1B[0m" : e, bt = (e) => process.stdout.isTTY ? `\x1B[2m${e}\x1B[0m` : e, _ = (e) => process.stdout.isTTY ? `\x1B[3m${e}\x1B[0m` : e, ae = (e) => process.stdout.isTTY ? `\x1B[33m${e}\x1B[0m` : e;
1002
- async function Pt(e) {
1003
- let t, o;
1004
- const n = /* @__PURE__ */ new Map();
1005
- if (e.command === "start" && (e = vt(e)), e.autoMount !== void 0 && (e.autoMount === "" && (e = { ...e, autoMount: process.cwd() }), e = ue(e)), e.wordpressInstallMode === void 0 && (e.wordpressInstallMode = "download-and-install"), e.quiet && (e.verbosity = "quiet", delete e.quiet), e.debug && (e.verbosity = "debug", delete e.debug), e.verbosity) {
1006
- const g = Object.values(Z).find(
1007
- (a) => a.name === e.verbosity
1144
+ const bt = Symbol("playground-cli-testing"), T = (e) => process.stdout.isTTY ? "\x1B[1m" + e + "\x1B[0m" : e, vt = (e) => process.stdout.isTTY ? "\x1B[31m" + e + "\x1B[0m" : e, Pt = (e) => process.stdout.isTTY ? `\x1B[2m${e}\x1B[0m` : e, q = (e) => process.stdout.isTTY ? `\x1B[3m${e}\x1B[0m` : e, ae = (e) => process.stdout.isTTY ? `\x1B[33m${e}\x1B[0m` : e;
1145
+ async function St(e) {
1146
+ let t, r;
1147
+ const s = /* @__PURE__ */ new Map();
1148
+ if (e.command === "start" && (e = xt(e)), e.autoMount !== void 0 && (e.autoMount === "" && (e = { ...e, autoMount: process.cwd() }), e = de(e)), e.wordpressInstallMode === void 0 && (e.wordpressInstallMode = "download-and-install"), e.quiet && (e.verbosity = "quiet", delete e.quiet), e.debug && (e.verbosity = "debug", delete e.debug), e.verbosity) {
1149
+ const a = Object.values(he).find(
1150
+ (f) => f.name === e.verbosity
1008
1151
  ).severity;
1009
- u.setSeverityFilterLevel(g);
1152
+ g.setSeverityFilterLevel(a);
1010
1153
  }
1011
1154
  e.intl || (e.intl = !0);
1012
- const r = e.command === "server" ? e.port ?? 9400 : 0, s = U.platform() === "win32" ? (
1155
+ const o = new yt({
1156
+ verbosity: e.verbosity || "normal"
1157
+ });
1158
+ e.command === "server" && (o.printBanner(), o.printConfig({
1159
+ phpVersion: e.php || U,
1160
+ wpVersion: e.wp || "latest",
1161
+ port: e.port || 9400,
1162
+ xdebug: !!e.xdebug,
1163
+ intl: !!e.intl,
1164
+ mounts: [
1165
+ ...e.mount || [],
1166
+ ...e["mount-before-install"] || []
1167
+ ],
1168
+ blueprint: typeof e.blueprint == "string" ? e.blueprint : void 0
1169
+ }));
1170
+ const i = e.command === "server" ? e.port ?? 9400 : 0, n = O.platform() === "win32" ? (
1013
1171
  // @TODO: Enable fs-ext here when it works with Windows.
1014
1172
  void 0
1015
- ) : await import("fs-ext").then((g) => g.flockSync).catch(() => {
1016
- u.warn(
1173
+ ) : await import("fs-ext").then((a) => a.flockSync).catch(() => {
1174
+ g.debug(
1017
1175
  "The fs-ext package is not installed. Internal file locking will not be integrated with host OS file locking."
1018
1176
  );
1019
- }), i = new We(s);
1020
- let l = !1, d = !0;
1021
- u.log("Starting a PHP server...");
1022
- const b = await ot({
1023
- port: r,
1024
- onBind: async (g, a) => {
1025
- const y = "127.0.0.1", p = `http://${y}:${a}`, I = e["site-url"] || p, v = e.command === "server" ? e.experimentalMultiWorker ?? 1 : 1, W = e.command === "server" ? (
1177
+ }), l = new Le(n);
1178
+ let u = !1, b = !0;
1179
+ const v = await rt({
1180
+ port: i,
1181
+ onBind: async (a, f) => {
1182
+ const c = "127.0.0.1", S = `http://${c}:${f}`, E = e["site-url"] || S, k = e.command === "server" ? e.experimentalMultiWorker ?? 1 : 1, W = e.command === "server" ? (
1026
1183
  // Account for the initial worker which is discarded by the server after setup.
1027
- v + 1
1028
- ) : v, F = 2 ** 31 - 1, k = Math.floor(
1029
- F / W
1030
- ), J = "-playground-cli-site-", $ = await pt(J);
1031
- u.debug(`Native temp dir for VFS root: ${$.path}`);
1032
- const B = "WP Playground CLI - Listen for Xdebug", Q = ".playground-xdebug-root", K = h.join(process.cwd(), Q);
1033
- if (await Xe(K), e.xdebug && e.experimentalUnsafeIdeIntegration) {
1034
- await Ye(
1035
- $.path,
1184
+ k + 1
1185
+ ) : k, C = 2 ** 31 - 1, L = Math.floor(
1186
+ C / W
1187
+ ), G = "-playground-cli-site-", I = await ct(G);
1188
+ g.debug(`Native temp dir for VFS root: ${I.path}`);
1189
+ const M = "WP Playground CLI - Listen for Xdebug", J = ".playground-xdebug-root", K = h.join(process.cwd(), J);
1190
+ if (await ze(K), e.xdebug && e.experimentalUnsafeIdeIntegration) {
1191
+ await Qe(
1192
+ I.path,
1036
1193
  K,
1037
1194
  process.platform
1038
1195
  );
1039
- const c = {
1040
- hostPath: h.join(".", h.sep, Q),
1196
+ const d = {
1197
+ hostPath: h.join(".", h.sep, J),
1041
1198
  vfsPath: "/"
1042
1199
  };
1043
1200
  try {
1044
- await Ze(B, process.cwd());
1045
- const w = typeof e.xdebug == "object" ? e.xdebug : void 0, x = await Ge({
1046
- name: B,
1047
- host: y,
1048
- port: a,
1201
+ await Xe(M, process.cwd());
1202
+ const w = typeof e.xdebug == "object" ? e.xdebug : void 0, P = await Ze({
1203
+ name: M,
1204
+ host: c,
1205
+ port: f,
1049
1206
  ides: e.experimentalUnsafeIdeIntegration,
1050
1207
  cwd: process.cwd(),
1051
1208
  mounts: [
1052
- c,
1209
+ d,
1053
1210
  ...e["mount-before-install"] || [],
1054
1211
  ...e.mount || []
1055
1212
  ],
1056
1213
  ideKey: w?.ideKey
1057
- }), m = e.experimentalUnsafeIdeIntegration, P = m.includes("vscode"), S = m.includes("phpstorm"), L = Object.values(x);
1058
- console.log(""), L.length > 0 ? (console.log(E("Xdebug configured successfully")), console.log(
1059
- ae("Updated IDE config: ") + L.join(" ")
1214
+ }), m = e.experimentalUnsafeIdeIntegration, y = m.includes("vscode"), x = m.includes("phpstorm"), D = Object.values(P);
1215
+ console.log(""), D.length > 0 ? (console.log(T("Xdebug configured successfully")), console.log(
1216
+ ae("Updated IDE config: ") + D.join(" ")
1060
1217
  ), console.log(
1061
- ae("Playground source root: ") + ".playground-xdebug-root" + _(
1062
- bt(
1218
+ ae("Playground source root: ") + ".playground-xdebug-root" + q(
1219
+ Pt(
1063
1220
  " – you can set breakpoints and preview Playground's VFS structure in there."
1064
1221
  )
1065
1222
  )
1066
- )) : (console.log(E("Xdebug configuration failed.")), console.log(
1223
+ )) : (console.log(T("Xdebug configuration failed.")), console.log(
1067
1224
  "No IDE-specific project settings directory was found in the current working directory."
1068
- )), console.log(""), P && x.vscode && (console.log(E("VS Code / Cursor instructions:")), console.log(
1225
+ )), console.log(""), y && P.vscode && (console.log(T("VS Code / Cursor instructions:")), console.log(
1069
1226
  " 1. Ensure you have installed an IDE extension for PHP Debugging"
1070
1227
  ), console.log(
1071
- ` (The ${E("PHP Debug")} extension by ${E(
1228
+ ` (The ${T("PHP Debug")} extension by ${T(
1072
1229
  "Xdebug"
1073
1230
  )} has been a solid option)`
1074
1231
  ), console.log(
1075
1232
  " 2. Open the Run and Debug panel on the left sidebar"
1076
1233
  ), console.log(
1077
- ` 3. Select "${_(
1078
- B
1234
+ ` 3. Select "${q(
1235
+ M
1079
1236
  )}" from the dropdown`
1080
1237
  ), console.log(' 3. Click "start debugging"'), console.log(
1081
1238
  " 5. Set a breakpoint. For example, in .playground-xdebug-root/wordpress/index.php"
1082
1239
  ), console.log(
1083
1240
  " 6. Visit Playground in your browser to hit the breakpoint"
1084
- ), S && console.log("")), S && x.phpstorm && (console.log(E("PhpStorm instructions:")), console.log(
1085
- ` 1. Choose "${_(
1086
- B
1241
+ ), x && console.log("")), x && P.phpstorm && (console.log(T("PhpStorm instructions:")), console.log(
1242
+ ` 1. Choose "${q(
1243
+ M
1087
1244
  )}" debug configuration in the toolbar`
1088
1245
  ), console.log(" 2. Click the debug button (bug icon)`"), console.log(
1089
1246
  " 3. Set a breakpoint. For example, in .playground-xdebug-root/wordpress/index.php"
@@ -1096,14 +1253,14 @@ async function Pt(e) {
1096
1253
  });
1097
1254
  }
1098
1255
  }
1099
- const he = h.dirname($.path), me = 2 * 24 * 60 * 60 * 1e3;
1100
- ft(
1101
- J,
1102
- me,
1103
- he
1256
+ const me = h.dirname(I.path), fe = 2 * 24 * 60 * 60 * 1e3;
1257
+ ht(
1258
+ G,
1259
+ fe,
1260
+ me
1104
1261
  );
1105
- const A = h.join($.path, "internal");
1106
- z(A);
1262
+ const H = h.join(I.path, "internal");
1263
+ z(H);
1107
1264
  const we = [
1108
1265
  "wordpress",
1109
1266
  // Note: These dirs are from Emscripten's "default dirs" list:
@@ -1115,160 +1272,159 @@ async function Pt(e) {
1115
1272
  "tmp",
1116
1273
  "home"
1117
1274
  ];
1118
- for (const c of we) {
1119
- const w = (m) => m.vfsPath === `/${c}`;
1275
+ for (const d of we) {
1276
+ const w = (m) => m.vfsPath === `/${d}`;
1120
1277
  if (!(e["mount-before-install"]?.some(w) || e.mount?.some(w))) {
1121
1278
  const m = h.join(
1122
- $.path,
1123
- c
1279
+ I.path,
1280
+ d
1124
1281
  );
1125
1282
  z(m), e["mount-before-install"] === void 0 && (e["mount-before-install"] = []), e["mount-before-install"].unshift({
1126
- vfsPath: `/${c}`,
1283
+ vfsPath: `/${d}`,
1127
1284
  hostPath: m
1128
1285
  });
1129
1286
  }
1130
1287
  }
1131
1288
  if (e["mount-before-install"])
1132
- for (const c of e["mount-before-install"])
1133
- u.debug(
1134
- `Mount before WP install: ${c.vfsPath} -> ${c.hostPath}`
1289
+ for (const d of e["mount-before-install"])
1290
+ g.debug(
1291
+ `Mount before WP install: ${d.vfsPath} -> ${d.hostPath}`
1135
1292
  );
1136
1293
  if (e.mount)
1137
- for (const c of e.mount)
1138
- u.debug(
1139
- `Mount after WP install: ${c.vfsPath} -> ${c.hostPath}`
1294
+ for (const d of e.mount)
1295
+ g.debug(
1296
+ `Mount after WP install: ${d.vfsPath} -> ${d.hostPath}`
1140
1297
  );
1141
- let T;
1142
- e["experimental-blueprints-v2-runner"] ? T = new lt(e, {
1143
- siteUrl: I,
1144
- processIdSpaceLength: k
1145
- }) : (T = new ct(e, {
1146
- siteUrl: I,
1147
- processIdSpaceLength: k
1298
+ let $;
1299
+ e["experimental-blueprints-v2-runner"] ? $ = new lt(e, {
1300
+ siteUrl: E,
1301
+ processIdSpaceLength: L,
1302
+ cliOutput: o
1303
+ }) : ($ = new pt(e, {
1304
+ siteUrl: E,
1305
+ processIdSpaceLength: L,
1306
+ cliOutput: o
1148
1307
  }), typeof e.blueprint == "string" && (e.blueprint = await at({
1149
1308
  sourceString: e.blueprint,
1150
1309
  blueprintMayReadAdjacentFiles: e["blueprint-may-read-adjacent-files"] === !0
1151
1310
  })));
1152
- let H = !1;
1153
- const M = async function() {
1154
- H || (H = !0, await Promise.all(
1155
- [...n].map(
1156
- async ([w, x]) => {
1157
- await x.dispose(), await w.terminate();
1311
+ let V = !1;
1312
+ const R = async function() {
1313
+ V || (V = !0, await Promise.all(
1314
+ [...s].map(
1315
+ async ([w, P]) => {
1316
+ await P.dispose(), await w.terminate();
1158
1317
  }
1159
1318
  )
1160
- ), g && await new Promise((w) => g.close(w)), await $.cleanup());
1319
+ ), a && await new Promise((w) => a.close(w)), await I.cleanup());
1161
1320
  }, ge = kt(
1162
1321
  W,
1163
- T.getWorkerType(),
1164
- ({ exitCode: c, workerIndex: w }) => {
1165
- H || c === 0 && u.error(
1166
- `Worker ${w} exited with code ${c}
1322
+ $.getWorkerType(),
1323
+ ({ exitCode: d, workerIndex: w }) => {
1324
+ V || d === 0 && g.error(
1325
+ `Worker ${w} exited with code ${d}
1167
1326
  `
1168
1327
  );
1169
1328
  }
1170
1329
  );
1171
- u.log("Starting up workers");
1330
+ o.startProgress("Starting...");
1172
1331
  try {
1173
- const c = await ge, w = await le(i);
1332
+ const d = await ge, w = await le(l);
1174
1333
  {
1175
- const m = c.shift(), P = await T.bootAndSetUpInitialPlayground(
1334
+ const m = d.shift(), y = await $.bootAndSetUpInitialPlayground(
1176
1335
  m.phpPort,
1177
1336
  w,
1178
- A
1337
+ H
1179
1338
  );
1180
- if (n.set(
1339
+ if (s.set(
1181
1340
  m.worker,
1182
- P
1183
- ), await P.isReady(), l = !0, u.log("Booted!"), t = new nt(P), !e["experimental-blueprints-v2-runner"]) {
1184
- const S = await T.compileInputBlueprint(
1341
+ y
1342
+ ), await y.isReady(), u = !0, t = new it(y), !e["experimental-blueprints-v2-runner"]) {
1343
+ const x = await $.compileInputBlueprint(
1185
1344
  e["additional-blueprint-steps"] || []
1186
1345
  );
1187
- S && (u.log("Running the Blueprint..."), await Se(
1188
- S,
1189
- P
1190
- ), u.log("Finished running the blueprint"));
1346
+ x && await ke(
1347
+ x,
1348
+ y
1349
+ );
1191
1350
  }
1192
1351
  if (e.command === "build-snapshot") {
1193
- await It(o, e.outfile), u.log(`WordPress exported to ${e.outfile}`), await M();
1352
+ await Tt(r, e.outfile), o.printStatus(`Exported to ${e.outfile}`), await R();
1194
1353
  return;
1195
1354
  } else if (e.command === "run-blueprint") {
1196
- u.log("Blueprint executed"), await M();
1355
+ o.finishProgress("Done"), await R();
1197
1356
  return;
1198
1357
  }
1199
- await t.removeWorker(P), await P.dispose(), await m.worker.terminate(), n.delete(m.worker);
1358
+ await t.removeWorker(y), await y.dispose(), await m.worker.terminate(), s.delete(m.worker);
1200
1359
  }
1201
- u.log("Preparing workers...");
1202
- const x = k;
1203
- return [o] = await Promise.all(
1204
- c.map(async (m, P) => {
1205
- const S = x + P * k, L = await le(i), V = await T.bootPlayground({
1360
+ const P = L;
1361
+ return [r] = await Promise.all(
1362
+ d.map(async (m, y) => {
1363
+ const x = P + y * L, D = await le(l), N = await $.bootPlayground({
1206
1364
  worker: m,
1207
- fileLockManagerPort: L,
1208
- firstProcessId: S,
1209
- nativeInternalDirPath: A
1365
+ fileLockManagerPort: D,
1366
+ firstProcessId: x,
1367
+ nativeInternalDirPath: H
1210
1368
  });
1211
- return n.set(
1369
+ return s.set(
1212
1370
  m.worker,
1213
- V
1214
- ), t.addWorker(V), V;
1371
+ N
1372
+ ), t.addWorker(N), N;
1215
1373
  })
1216
- ), u.log(
1217
- `WordPress is running on ${p} with ${v} worker(s)`
1218
- ), e.xdebug && e.experimentalDevtools && (await Oe({
1219
- phpInstance: o,
1374
+ ), o.finishProgress(), o.printReady(S, k), e.xdebug && e.experimentalDevtools && (await Ne({
1375
+ phpInstance: r,
1220
1376
  phpRoot: "/wordpress"
1221
1377
  })).start(), {
1222
- playground: o,
1223
- server: g,
1224
- serverUrl: p,
1225
- [Symbol.asyncDispose]: M,
1226
- [gt]: {
1227
- workerThreadCount: v,
1228
- getWorkerNumberFromProcessId: (m) => Math.floor(m / k)
1378
+ playground: r,
1379
+ server: a,
1380
+ serverUrl: S,
1381
+ [Symbol.asyncDispose]: R,
1382
+ [bt]: {
1383
+ workerThreadCount: k,
1384
+ getWorkerNumberFromProcessId: (m) => Math.floor(m / L)
1229
1385
  }
1230
1386
  };
1231
- } catch (c) {
1387
+ } catch (d) {
1232
1388
  if (e.verbosity !== "debug")
1233
- throw c;
1389
+ throw d;
1234
1390
  let w = "";
1235
- throw await o?.fileExists(ee) && (w = await o.readFileAsText(ee)), await M(), new Error(w, { cause: c });
1391
+ throw await r?.fileExists(ee) && (w = await r.readFileAsText(ee)), await R(), new Error(w, { cause: d });
1236
1392
  }
1237
1393
  },
1238
- async handleRequest(g) {
1239
- if (!l)
1240
- return j.forHttpCode(
1394
+ async handleRequest(a) {
1395
+ if (!u)
1396
+ return Y.forHttpCode(
1241
1397
  502,
1242
1398
  "WordPress is not ready yet"
1243
1399
  );
1244
- if (d) {
1245
- d = !1;
1246
- const a = {
1400
+ if (b) {
1401
+ b = !1;
1402
+ const f = {
1247
1403
  "Content-Type": ["text/plain"],
1248
1404
  "Content-Length": ["0"],
1249
- Location: [g.url]
1405
+ Location: [a.url]
1250
1406
  };
1251
- return g.headers?.cookie?.includes(
1407
+ return a.headers?.cookie?.includes(
1252
1408
  "playground_auto_login_already_happened"
1253
- ) && (a["Set-Cookie"] = [
1409
+ ) && (f["Set-Cookie"] = [
1254
1410
  "playground_auto_login_already_happened=1; Max-Age=0; Expires=Thu, 01 Jan 1970 00:00:00 GMT; Path=/"
1255
- ]), new j(302, a, new Uint8Array());
1411
+ ]), new Y(302, f, new Uint8Array());
1256
1412
  }
1257
- return await t.handleRequest(g);
1413
+ return await t.handleRequest(a);
1258
1414
  }
1259
1415
  });
1260
- return b && e.command === "start" && !e.skipBrowser && St(b.serverUrl), b;
1416
+ return v && e.command === "start" && !e.skipBrowser && $t(v.serverUrl), v;
1261
1417
  }
1262
- function vt(e) {
1418
+ function xt(e) {
1263
1419
  let t = { ...e, command: "server" };
1264
- e.noAutoMount || (t.autoMount = h.resolve(process.cwd(), t.path ?? ""), t = ue(t), delete t.autoMount);
1265
- const o = ie(
1420
+ e.noAutoMount || (t.autoMount = h.resolve(process.cwd(), t.path ?? ""), t = de(t), delete t.autoMount);
1421
+ const r = ne(
1266
1422
  t["mount-before-install"] || [],
1267
1423
  "/wordpress"
1268
- ) || ie(t.mount || [], "/wordpress");
1269
- if (o)
1270
- console.log("Site files stored at:", o?.hostPath), e.reset && (console.log(""), console.log(
1271
- yt(
1424
+ ) || ne(t.mount || [], "/wordpress");
1425
+ if (r)
1426
+ console.log("Site files stored at:", r?.hostPath), e.reset && (console.log(""), console.log(
1427
+ vt(
1272
1428
  "This site is not managed by Playground CLI and cannot be reset."
1273
1429
  )
1274
1430
  ), console.log(
@@ -1277,15 +1433,15 @@ function vt(e) {
1277
1433
  "You may still remove the site's directory manually if you wish."
1278
1434
  ), process.exit(1));
1279
1435
  else {
1280
- const n = t.autoMount || process.cwd(), r = Je("sha256").update(n).digest("hex"), s = U.homedir(), i = h.join(
1281
- s,
1436
+ const s = t.autoMount || process.cwd(), o = Ge("sha256").update(s).digest("hex"), i = O.homedir(), n = h.join(
1437
+ i,
1282
1438
  ".wordpress-playground/sites",
1283
- r
1439
+ o
1284
1440
  );
1285
- console.log("Site files stored at:", i), Y(i) && e.reset && (console.log("Resetting site..."), $e(i, { recursive: !0 })), z(i, { recursive: !0 }), t["mount-before-install"] = [
1441
+ console.log("Site files stored at:", n), X(n) && e.reset && (console.log("Resetting site..."), $e(n, { recursive: !0 })), z(n, { recursive: !0 }), t["mount-before-install"] = [
1286
1442
  ...t["mount-before-install"] || [],
1287
- { vfsPath: "/wordpress", hostPath: i }
1288
- ], t.wordpressInstallMode = Te(i).length === 0 ? (
1443
+ { vfsPath: "/wordpress", hostPath: n }
1444
+ ], t.wordpressInstallMode = Te(n).length === 0 ? (
1289
1445
  // Only download WordPress on the first run when the site directory is still
1290
1446
  // empty.
1291
1447
  "download-and-install"
@@ -1296,62 +1452,62 @@ function vt(e) {
1296
1452
  }
1297
1453
  return t;
1298
1454
  }
1299
- async function kt(e, t, o) {
1300
- const n = [];
1301
- for (let r = 0; r < e; r++) {
1302
- const i = xt(t, { onExit: (l) => {
1303
- o({
1455
+ async function kt(e, t, r) {
1456
+ const s = [];
1457
+ for (let o = 0; o < e; o++) {
1458
+ const n = It(t, { onExit: (l) => {
1459
+ r({
1304
1460
  exitCode: l,
1305
- workerIndex: r
1461
+ workerIndex: o
1306
1462
  });
1307
1463
  } });
1308
- n.push(i);
1464
+ s.push(n);
1309
1465
  }
1310
- return Promise.all(n);
1466
+ return Promise.all(s);
1311
1467
  }
1312
- function xt(e, { onExit: t } = {}) {
1313
- let o;
1314
- return e === "v1" ? o = new re(new URL("./worker-thread-v1.js", import.meta.url)) : o = new re(new URL("./worker-thread-v2.js", import.meta.url)), new Promise((n, r) => {
1315
- o.once("message", function(i) {
1316
- i.command === "worker-script-initialized" && n({ worker: o, phpPort: i.phpPort });
1317
- }), o.once("error", function(i) {
1318
- console.error(i);
1468
+ function It(e, { onExit: t } = {}) {
1469
+ let r;
1470
+ return e === "v1" ? r = new oe(new URL("./worker-thread-v1.js", import.meta.url)) : r = new oe(new URL("./worker-thread-v2.js", import.meta.url)), new Promise((s, o) => {
1471
+ r.once("message", function(n) {
1472
+ n.command === "worker-script-initialized" && s({ worker: r, phpPort: n.phpPort });
1473
+ }), r.once("error", function(n) {
1474
+ console.error(n);
1319
1475
  const l = new Error(
1320
- `Worker failed to load worker. ${i.message ? `Original error: ${i.message}` : ""}`
1476
+ `Worker failed to load worker. ${n.message ? `Original error: ${n.message}` : ""}`
1321
1477
  );
1322
- r(l);
1478
+ o(l);
1323
1479
  });
1324
- let s = !1;
1325
- o.once("spawn", () => {
1326
- s = !0;
1327
- }), o.once("exit", (i) => {
1328
- s || r(new Error(`Worker exited before spawning: ${i}`)), t?.(i);
1480
+ let i = !1;
1481
+ r.once("spawn", () => {
1482
+ i = !0;
1483
+ }), r.once("exit", (n) => {
1484
+ i || o(new Error(`Worker exited before spawning: ${n}`)), t?.(n);
1329
1485
  });
1330
1486
  });
1331
1487
  }
1332
1488
  async function le(e) {
1333
- const { port1: t, port2: o } = new Ee();
1334
- return await Le() ? be(e, null, t) : await Pe(e, t), o;
1489
+ const { port1: t, port2: r } = new Be();
1490
+ return await Me() ? be(e, null, t) : await ve(e, t), r;
1335
1491
  }
1336
- function St(e) {
1337
- const t = U.platform();
1338
- let o;
1492
+ function $t(e) {
1493
+ const t = O.platform();
1494
+ let r;
1339
1495
  switch (t) {
1340
1496
  case "darwin":
1341
- o = `open "${e}"`;
1497
+ r = `open "${e}"`;
1342
1498
  break;
1343
1499
  case "win32":
1344
- o = `start "" "${e}"`;
1500
+ r = `start "" "${e}"`;
1345
1501
  break;
1346
1502
  default:
1347
- o = `xdg-open "${e}"`;
1503
+ r = `xdg-open "${e}"`;
1348
1504
  break;
1349
1505
  }
1350
- _e(o, (n) => {
1351
- n && u.debug(`Could not open browser: ${n.message}`);
1506
+ je(r, (s) => {
1507
+ s && g.debug(`Could not open browser: ${s.message}`);
1352
1508
  });
1353
1509
  }
1354
- async function It(e, t) {
1510
+ async function Tt(e, t) {
1355
1511
  await e.run({
1356
1512
  code: `<?php
1357
1513
  $zip = new ZipArchive();
@@ -1372,16 +1528,16 @@ async function It(e, t) {
1372
1528
 
1373
1529
  `
1374
1530
  });
1375
- const o = await e.readFileAsBuffer("/tmp/build.zip");
1376
- f.writeFileSync(t, o);
1531
+ const r = await e.readFileAsBuffer("/tmp/build.zip");
1532
+ p.writeFileSync(t, r);
1377
1533
  }
1378
1534
  export {
1379
- Z as L,
1380
- ce as a,
1381
- gt as i,
1382
- Zt as m,
1383
- Gt as p,
1384
- Pt as r,
1385
- xt as s
1535
+ he as L,
1536
+ gt as a,
1537
+ bt as i,
1538
+ Gt as m,
1539
+ Jt as p,
1540
+ St as r,
1541
+ It as s
1386
1542
  };
1387
- //# sourceMappingURL=run-cli-vem_UKTF.js.map
1543
+ //# sourceMappingURL=run-cli-NcKUE5gJ.js.map