@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.
- package/blueprints-v1/blueprints-v1-handler.d.ts +3 -3
- package/blueprints-v2/blueprints-v2-handler.d.ts +3 -3
- package/cli-output.d.ts +114 -0
- package/cli.cjs +1 -1
- package/cli.js +1 -1
- package/index.cjs +1 -1
- package/index.js +1 -1
- package/package.json +13 -13
- package/run-cli-B8Dv6R-o.cjs +64 -0
- package/run-cli-B8Dv6R-o.cjs.map +1 -0
- package/{run-cli-vem_UKTF.js → run-cli-NcKUE5gJ.js} +688 -532
- package/run-cli-NcKUE5gJ.js.map +1 -0
- package/worker-thread-v1.cjs +1 -1
- package/worker-thread-v1.js +1 -1
- package/worker-thread-v2.cjs +1 -1
- package/worker-thread-v2.js +1 -1
- package/run-cli-DJNPNQa1.cjs +0 -53
- package/run-cli-DJNPNQa1.cjs.map +0 -1
- package/run-cli-vem_UKTF.js.map +0 -1
|
@@ -1,38 +1,38 @@
|
|
|
1
|
-
import { logger as
|
|
2
|
-
import { PHPResponse as
|
|
3
|
-
import { resolveRemoteBlueprint as
|
|
4
|
-
import { zipDirectory as Ie, RecommendedPHPVersion as
|
|
5
|
-
import
|
|
6
|
-
import { MessageChannel as
|
|
7
|
-
import { createNodeFsMountHandler as
|
|
8
|
-
import h, { basename as
|
|
9
|
-
import
|
|
10
|
-
import
|
|
11
|
-
import { jspi as
|
|
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
|
|
14
|
-
import { EmscriptenDownloadMonitor as
|
|
15
|
-
import { resolveWordPressRelease as
|
|
16
|
-
import
|
|
17
|
-
import { startBridge as
|
|
18
|
-
import { exec as
|
|
19
|
-
import { dir as
|
|
20
|
-
import
|
|
21
|
-
import { removeTempDirSymlink as
|
|
22
|
-
import { createHash as
|
|
23
|
-
function
|
|
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
|
|
26
|
-
const
|
|
27
|
-
if (
|
|
28
|
-
throw new Error(`Invalid mount format: ${
|
|
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 [
|
|
33
|
-
if (!
|
|
34
|
-
throw new Error(`Host path does not exist: ${
|
|
35
|
-
t.push({ hostPath:
|
|
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
|
|
44
|
-
const
|
|
45
|
-
if (!
|
|
46
|
-
throw new Error(`Host path does not exist: ${
|
|
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(),
|
|
49
|
-
vfsPath:
|
|
48
|
+
hostPath: h.resolve(process.cwd(), s),
|
|
49
|
+
vfsPath: o
|
|
50
50
|
});
|
|
51
51
|
}
|
|
52
52
|
return t;
|
|
53
53
|
}
|
|
54
|
-
async function
|
|
55
|
-
for (const
|
|
54
|
+
async function Gt(e, t) {
|
|
55
|
+
for (const r of t)
|
|
56
56
|
await e.mount(
|
|
57
|
-
|
|
58
|
-
|
|
57
|
+
r.vfsPath,
|
|
58
|
+
Ee(r.hostPath)
|
|
59
59
|
);
|
|
60
60
|
}
|
|
61
|
-
const
|
|
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
|
|
81
|
-
const t = e.autoMount,
|
|
80
|
+
function de(e) {
|
|
81
|
+
const t = e.autoMount, r = [...e.mount || []], s = [...e["mount-before-install"] || []], o = {
|
|
82
82
|
...e,
|
|
83
|
-
mount:
|
|
84
|
-
"mount-before-install":
|
|
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
|
|
91
|
-
|
|
90
|
+
const n = `/wordpress/wp-content/plugins/${A(t)}`;
|
|
91
|
+
r.push({
|
|
92
92
|
hostPath: t,
|
|
93
|
-
vfsPath:
|
|
94
|
-
|
|
93
|
+
vfsPath: n,
|
|
94
|
+
autoMounted: !0
|
|
95
|
+
}), o["additional-blueprint-steps"].push({
|
|
95
96
|
step: "activatePlugin",
|
|
96
|
-
pluginPath: `/wordpress/wp-content/plugins/${
|
|
97
|
+
pluginPath: `/wordpress/wp-content/plugins/${A(t)}`
|
|
97
98
|
});
|
|
98
99
|
} else if (et(t)) {
|
|
99
|
-
const
|
|
100
|
-
|
|
100
|
+
const i = A(t), n = `/wordpress/wp-content/themes/${i}`;
|
|
101
|
+
r.push({
|
|
101
102
|
hostPath: t,
|
|
102
|
-
vfsPath:
|
|
103
|
-
|
|
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:
|
|
108
|
+
themeDirectoryName: i
|
|
107
109
|
} : {
|
|
108
110
|
step: "activateTheme",
|
|
109
|
-
themeFolderName:
|
|
111
|
+
themeFolderName: i
|
|
110
112
|
}
|
|
111
113
|
);
|
|
112
114
|
} else if (Ke(t)) {
|
|
113
|
-
const
|
|
114
|
-
for (const
|
|
115
|
-
|
|
116
|
-
hostPath: `${t}/${
|
|
117
|
-
vfsPath: `/wordpress/wp-content/${
|
|
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
|
-
|
|
120
|
-
} else
|
|
121
|
-
|
|
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
|
|
124
|
-
const t =
|
|
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 =
|
|
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 (!
|
|
139
|
+
if (!p.readdirSync(e).includes("style.css"))
|
|
133
140
|
return !1;
|
|
134
|
-
const
|
|
135
|
-
return !!/^(?:[ \t]*<\?php)?[ \t/*#@]*Theme Name:(.*)$/im.exec(
|
|
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 =
|
|
139
|
-
return !!t.filter((
|
|
140
|
-
const
|
|
141
|
-
return !!
|
|
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
|
|
145
|
-
const t =
|
|
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
|
|
148
|
-
|
|
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 (
|
|
158
|
+
t.use("/", async (i, n) => {
|
|
152
159
|
let l;
|
|
153
160
|
try {
|
|
154
161
|
l = await e.handleRequest({
|
|
155
|
-
url:
|
|
156
|
-
headers: st(
|
|
157
|
-
method:
|
|
158
|
-
body: await
|
|
162
|
+
url: i.url,
|
|
163
|
+
headers: st(i),
|
|
164
|
+
method: i.method,
|
|
165
|
+
body: await ot(i)
|
|
159
166
|
});
|
|
160
|
-
} catch (
|
|
161
|
-
|
|
167
|
+
} catch (u) {
|
|
168
|
+
g.error(u), l = Y.forHttpCode(500);
|
|
162
169
|
}
|
|
163
|
-
|
|
164
|
-
for (const
|
|
165
|
-
|
|
166
|
-
|
|
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
|
|
169
|
-
return await e.onBind(
|
|
175
|
+
const o = r.address().port;
|
|
176
|
+
return await e.onBind(r, o);
|
|
170
177
|
}
|
|
171
|
-
const
|
|
172
|
-
const
|
|
173
|
-
e.on("data", (
|
|
174
|
-
|
|
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(
|
|
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
|
|
182
|
-
t[e.rawHeaders[
|
|
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
|
|
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
|
|
197
|
-
(
|
|
203
|
+
const r = this.workerLoads.findIndex(
|
|
204
|
+
(o) => o.worker === t
|
|
198
205
|
);
|
|
199
|
-
if (
|
|
206
|
+
if (r === -1)
|
|
200
207
|
return;
|
|
201
|
-
const [
|
|
202
|
-
await Promise.allSettled(
|
|
208
|
+
const [s] = this.workerLoads.splice(r, 1);
|
|
209
|
+
await Promise.allSettled(s.activeRequests);
|
|
203
210
|
}
|
|
204
211
|
async handleRequest(t) {
|
|
205
|
-
let
|
|
206
|
-
for (let
|
|
207
|
-
const
|
|
208
|
-
|
|
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
|
|
211
|
-
return
|
|
212
|
-
|
|
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
|
|
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
|
|
227
|
-
let
|
|
228
|
-
if (!
|
|
229
|
-
throw new Error(`Blueprint file does not exist: ${
|
|
230
|
-
const
|
|
231
|
-
if (
|
|
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: ${
|
|
240
|
+
`Blueprint path is neither a file nor a directory: ${r}`
|
|
234
241
|
);
|
|
235
|
-
const
|
|
236
|
-
switch (
|
|
242
|
+
const o = h.extname(r);
|
|
243
|
+
switch (o) {
|
|
237
244
|
case ".zip":
|
|
238
|
-
return
|
|
239
|
-
|
|
245
|
+
return Ue.fromArrayBuffer(
|
|
246
|
+
p.readFileSync(r).buffer
|
|
240
247
|
);
|
|
241
248
|
case ".json": {
|
|
242
|
-
const
|
|
249
|
+
const i = p.readFileSync(r, "utf-8");
|
|
243
250
|
try {
|
|
244
|
-
JSON.parse(
|
|
251
|
+
JSON.parse(i);
|
|
245
252
|
} catch {
|
|
246
253
|
throw new Error(
|
|
247
|
-
`Blueprint file at ${
|
|
254
|
+
`Blueprint file at ${r} is not a valid JSON file`
|
|
248
255
|
);
|
|
249
256
|
}
|
|
250
|
-
const
|
|
251
|
-
return new
|
|
257
|
+
const n = h.dirname(r), l = new De(n);
|
|
258
|
+
return new Ae([
|
|
252
259
|
new Fe({
|
|
253
|
-
"blueprint.json":
|
|
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(
|
|
267
|
+
read(u) {
|
|
261
268
|
if (!t)
|
|
262
269
|
throw new Error(
|
|
263
|
-
`Error: Blueprint contained tried to read a local file at path "${
|
|
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(
|
|
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: ${
|
|
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,
|
|
283
|
-
this.
|
|
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,
|
|
289
|
-
const
|
|
290
|
-
await
|
|
291
|
-
const
|
|
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:
|
|
310
|
+
nativeInternalDirPath: s,
|
|
307
311
|
mountsBeforeWpInstall: this.args["mount-before-install"] || [],
|
|
308
312
|
mountsAfterWpInstall: this.args.mount || []
|
|
309
313
|
};
|
|
310
|
-
return await
|
|
314
|
+
return await o.bootAndSetUpInitialWorker(i), o;
|
|
311
315
|
}
|
|
312
316
|
async bootPlayground({
|
|
313
317
|
worker: t,
|
|
314
|
-
fileLockManagerPort:
|
|
315
|
-
firstProcessId:
|
|
316
|
-
nativeInternalDirPath:
|
|
318
|
+
fileLockManagerPort: r,
|
|
319
|
+
firstProcessId: s,
|
|
320
|
+
nativeInternalDirPath: o
|
|
317
321
|
}) {
|
|
318
|
-
const
|
|
319
|
-
await
|
|
320
|
-
const
|
|
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:
|
|
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:
|
|
333
|
+
nativeInternalDirPath: o,
|
|
330
334
|
mountsBeforeWpInstall: this.args["mount-before-install"] || [],
|
|
331
335
|
mountsAfterWpInstall: this.args.mount || []
|
|
332
336
|
};
|
|
333
|
-
return await
|
|
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
|
|
342
|
-
async function
|
|
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,
|
|
350
|
-
const
|
|
351
|
-
return
|
|
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
|
|
354
|
-
const
|
|
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:
|
|
357
|
-
if (
|
|
355
|
+
const { done: l, value: u } = await o.read();
|
|
356
|
+
if (u && n.write(u), l)
|
|
358
357
|
break;
|
|
359
358
|
}
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
}),
|
|
364
|
-
|
|
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
|
|
369
|
-
return new File([
|
|
367
|
+
function ce(e, t) {
|
|
368
|
+
return new File([B.readFileSync(e)], A(e));
|
|
370
369
|
}
|
|
371
|
-
class
|
|
372
|
-
constructor(t,
|
|
373
|
-
this.
|
|
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,
|
|
379
|
-
let
|
|
380
|
-
const l = new
|
|
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
|
|
383
|
-
l.addEventListener("progress", (
|
|
384
|
-
if (
|
|
381
|
+
let E = !1;
|
|
382
|
+
l.addEventListener("progress", (k) => {
|
|
383
|
+
if (E)
|
|
385
384
|
return;
|
|
386
|
-
const { loaded:
|
|
387
|
-
Math.min(100, 100 *
|
|
385
|
+
const { loaded: W, total: Z } = k.detail, C = Math.floor(
|
|
386
|
+
Math.min(100, 100 * W / Z)
|
|
388
387
|
);
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
v
|
|
388
|
+
E = C === 100, this.cliOutput.updateProgress(
|
|
389
|
+
"Downloading WordPress",
|
|
390
|
+
C
|
|
393
391
|
);
|
|
394
|
-
}),
|
|
395
|
-
|
|
396
|
-
`prebuilt-wp-content-for-wp-${
|
|
397
|
-
),
|
|
398
|
-
|
|
399
|
-
`${
|
|
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
|
-
),
|
|
402
|
-
`Resolved WordPress release URL: ${
|
|
399
|
+
), g.debug(
|
|
400
|
+
`Resolved WordPress release URL: ${o?.releaseUrl}`
|
|
403
401
|
);
|
|
404
402
|
}
|
|
405
|
-
let
|
|
406
|
-
this.args.skipSqliteSetup ? (
|
|
407
|
-
const b = this.args.followSymlinks === !0,
|
|
408
|
-
await
|
|
409
|
-
const
|
|
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
|
|
413
|
-
phpVersion:
|
|
414
|
-
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:
|
|
415
|
+
mountsAfterWpInstall: f,
|
|
418
416
|
wordpressInstallMode: this.args.wordpressInstallMode || "download-and-install",
|
|
419
|
-
wordPressZip:
|
|
420
|
-
sqliteIntegrationPluginZip: await
|
|
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:
|
|
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:
|
|
433
|
-
}),
|
|
434
|
-
|
|
435
|
-
await Ie(
|
|
436
|
-
)
|
|
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:
|
|
441
|
-
firstProcessId:
|
|
442
|
-
nativeInternalDirPath:
|
|
438
|
+
fileLockManagerPort: r,
|
|
439
|
+
firstProcessId: s,
|
|
440
|
+
nativeInternalDirPath: o
|
|
443
441
|
}) {
|
|
444
|
-
const
|
|
442
|
+
const i = F(
|
|
445
443
|
t.phpPort
|
|
446
444
|
);
|
|
447
|
-
await
|
|
448
|
-
const
|
|
445
|
+
await i.isConnected();
|
|
446
|
+
const n = await re(
|
|
449
447
|
this.getEffectiveBlueprint()
|
|
450
448
|
);
|
|
451
|
-
return await
|
|
452
|
-
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:
|
|
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:
|
|
466
|
-
}), await
|
|
463
|
+
nativeInternalDirPath: o
|
|
464
|
+
}), await i.isReady(), i;
|
|
467
465
|
}
|
|
468
466
|
async compileInputBlueprint(t) {
|
|
469
|
-
const
|
|
470
|
-
let
|
|
471
|
-
return
|
|
472
|
-
if (
|
|
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
|
-
|
|
475
|
-
const l = Math.floor(
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
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 ??
|
|
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
|
|
507
|
-
const
|
|
508
|
-
prefix:
|
|
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(),
|
|
506
|
+
return t && qe(), o;
|
|
520
507
|
}
|
|
521
|
-
async function
|
|
522
|
-
const
|
|
508
|
+
async function ht(e, t, r) {
|
|
509
|
+
const o = (await mt(
|
|
523
510
|
e,
|
|
524
511
|
t,
|
|
525
|
-
|
|
512
|
+
r
|
|
526
513
|
)).map(
|
|
527
|
-
(
|
|
528
|
-
|
|
529
|
-
l ?
|
|
530
|
-
`Failed to delete stale Playground temp dir: ${
|
|
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
|
-
) :
|
|
533
|
-
`Deleted stale Playground temp dir: ${
|
|
534
|
-
),
|
|
519
|
+
) : g.info(
|
|
520
|
+
`Deleted stale Playground temp dir: ${i}`
|
|
521
|
+
), n();
|
|
535
522
|
});
|
|
536
523
|
})
|
|
537
524
|
);
|
|
538
|
-
await Promise.all(
|
|
525
|
+
await Promise.all(o);
|
|
539
526
|
}
|
|
540
|
-
async function
|
|
527
|
+
async function mt(e, t, r) {
|
|
541
528
|
try {
|
|
542
|
-
const
|
|
543
|
-
for (const
|
|
544
|
-
await
|
|
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
|
-
|
|
548
|
-
) &&
|
|
549
|
-
return
|
|
550
|
-
} catch (
|
|
551
|
-
return
|
|
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
|
|
555
|
-
if (!
|
|
541
|
+
async function ft(e, t, r) {
|
|
542
|
+
if (!p.lstatSync(r).isDirectory())
|
|
556
543
|
return !1;
|
|
557
|
-
const
|
|
558
|
-
if (!
|
|
544
|
+
const o = h.basename(r);
|
|
545
|
+
if (!o.includes(e))
|
|
559
546
|
return !1;
|
|
560
|
-
const
|
|
547
|
+
const i = o.match(
|
|
561
548
|
new RegExp(`^(.+)${e}(\\d+)-`)
|
|
562
549
|
);
|
|
563
|
-
if (!
|
|
550
|
+
if (!i)
|
|
564
551
|
return !1;
|
|
565
|
-
const
|
|
566
|
-
executableName:
|
|
567
|
-
pid:
|
|
552
|
+
const n = {
|
|
553
|
+
executableName: i[1],
|
|
554
|
+
pid: i[2]
|
|
568
555
|
};
|
|
569
|
-
if (await wt(
|
|
556
|
+
if (await wt(n.pid, n.executableName))
|
|
570
557
|
return !1;
|
|
571
558
|
const l = Date.now() - t;
|
|
572
|
-
return
|
|
559
|
+
return p.statSync(r).mtime.getTime() < l;
|
|
573
560
|
}
|
|
574
561
|
async function wt(e, t) {
|
|
575
|
-
const [
|
|
576
|
-
(
|
|
577
|
-
|
|
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
|
-
(
|
|
585
|
-
|
|
571
|
+
(i, n) => {
|
|
572
|
+
i ? o(i) : s(n);
|
|
586
573
|
}
|
|
587
574
|
);
|
|
588
575
|
}
|
|
589
576
|
);
|
|
590
|
-
return !!
|
|
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
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
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
|
|
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:
|
|
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:
|
|
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:
|
|
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(
|
|
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
|
-
},
|
|
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 ??
|
|
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
|
-
},
|
|
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:
|
|
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:
|
|
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
|
-
},
|
|
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
|
-
},
|
|
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(
|
|
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
|
-
...
|
|
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
|
-
...
|
|
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,
|
|
883
|
-
if (
|
|
884
|
-
throw
|
|
885
|
-
a && a.includes("Please specify a command") && (
|
|
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" && !
|
|
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
|
|
897
|
-
if (typeof
|
|
1039
|
+
const f = a["site-url"];
|
|
1040
|
+
if (typeof f == "string" && f.trim() !== "")
|
|
898
1041
|
try {
|
|
899
|
-
new URL(
|
|
1042
|
+
new URL(f);
|
|
900
1043
|
} catch {
|
|
901
1044
|
throw new Error(
|
|
902
|
-
`Invalid site-url "${
|
|
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
|
|
1049
|
+
let c = !1;
|
|
907
1050
|
try {
|
|
908
|
-
|
|
1051
|
+
c = p.statSync(
|
|
909
1052
|
a["auto-mount"]
|
|
910
1053
|
).isDirectory();
|
|
911
1054
|
} catch {
|
|
912
|
-
|
|
1055
|
+
c = !1;
|
|
913
1056
|
}
|
|
914
|
-
if (!
|
|
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
|
|
946
|
-
a.followSymlinks === !0 &&
|
|
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
|
-
|
|
954
|
-
const
|
|
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
|
-
) || (
|
|
958
|
-
const
|
|
959
|
-
...
|
|
1100
|
+
) || (i.showHelp(), process.exit(1));
|
|
1101
|
+
const u = {
|
|
1102
|
+
...n,
|
|
960
1103
|
command: l,
|
|
961
1104
|
mount: [
|
|
962
|
-
...
|
|
963
|
-
...
|
|
1105
|
+
...n.mount || [],
|
|
1106
|
+
...n["mount-dir"] || []
|
|
964
1107
|
],
|
|
965
1108
|
"mount-before-install": [
|
|
966
|
-
...
|
|
967
|
-
...
|
|
1109
|
+
...n["mount-before-install"] || [],
|
|
1110
|
+
...n["mount-dir-before-install"] || []
|
|
968
1111
|
]
|
|
969
|
-
}, b = await
|
|
1112
|
+
}, b = await St(u);
|
|
970
1113
|
b === void 0 && process.exit(0);
|
|
971
|
-
const
|
|
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",
|
|
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
|
|
985
|
-
let
|
|
1127
|
+
const s = [];
|
|
1128
|
+
let o = t;
|
|
986
1129
|
do
|
|
987
|
-
|
|
988
|
-
while (
|
|
1130
|
+
s.push(o.message), o = o.cause;
|
|
1131
|
+
while (o instanceof Error);
|
|
989
1132
|
console.error(
|
|
990
|
-
"\x1B[1m" +
|
|
1133
|
+
"\x1B[1m" + s.join(" caused by: ") + "\x1B[0m"
|
|
991
1134
|
);
|
|
992
1135
|
}
|
|
993
1136
|
process.exit(1);
|
|
994
1137
|
}
|
|
995
1138
|
}
|
|
996
|
-
function
|
|
1139
|
+
function ne(e, t) {
|
|
997
1140
|
return e.find(
|
|
998
|
-
(
|
|
1141
|
+
(r) => r.vfsPath.replace(/\/$/, "") === t.replace(/\/$/, "")
|
|
999
1142
|
);
|
|
1000
1143
|
}
|
|
1001
|
-
const
|
|
1002
|
-
async function
|
|
1003
|
-
let t,
|
|
1004
|
-
const
|
|
1005
|
-
if (e.command === "start" && (e =
|
|
1006
|
-
const
|
|
1007
|
-
(
|
|
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
|
-
|
|
1152
|
+
g.setSeverityFilterLevel(a);
|
|
1010
1153
|
}
|
|
1011
1154
|
e.intl || (e.intl = !0);
|
|
1012
|
-
const
|
|
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((
|
|
1016
|
-
|
|
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
|
-
}),
|
|
1020
|
-
let
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
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
|
-
|
|
1028
|
-
) :
|
|
1029
|
-
|
|
1030
|
-
),
|
|
1031
|
-
|
|
1032
|
-
const
|
|
1033
|
-
if (await
|
|
1034
|
-
await
|
|
1035
|
-
|
|
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
|
|
1040
|
-
hostPath: h.join(".", h.sep,
|
|
1196
|
+
const d = {
|
|
1197
|
+
hostPath: h.join(".", h.sep, J),
|
|
1041
1198
|
vfsPath: "/"
|
|
1042
1199
|
};
|
|
1043
1200
|
try {
|
|
1044
|
-
await
|
|
1045
|
-
const w = typeof e.xdebug == "object" ? e.xdebug : void 0,
|
|
1046
|
-
name:
|
|
1047
|
-
host:
|
|
1048
|
-
port:
|
|
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
|
-
|
|
1209
|
+
d,
|
|
1053
1210
|
...e["mount-before-install"] || [],
|
|
1054
1211
|
...e.mount || []
|
|
1055
1212
|
],
|
|
1056
1213
|
ideKey: w?.ideKey
|
|
1057
|
-
}), m = e.experimentalUnsafeIdeIntegration,
|
|
1058
|
-
console.log(""),
|
|
1059
|
-
ae("Updated IDE config: ") +
|
|
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
|
-
|
|
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(
|
|
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(""),
|
|
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 ${
|
|
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
|
-
|
|
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
|
-
),
|
|
1085
|
-
` 1. Choose "${
|
|
1086
|
-
|
|
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
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
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
|
|
1106
|
-
z(
|
|
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
|
|
1119
|
-
const w = (m) => m.vfsPath === `/${
|
|
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
|
-
|
|
1123
|
-
|
|
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: `/${
|
|
1283
|
+
vfsPath: `/${d}`,
|
|
1127
1284
|
hostPath: m
|
|
1128
1285
|
});
|
|
1129
1286
|
}
|
|
1130
1287
|
}
|
|
1131
1288
|
if (e["mount-before-install"])
|
|
1132
|
-
for (const
|
|
1133
|
-
|
|
1134
|
-
`Mount before WP install: ${
|
|
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
|
|
1138
|
-
|
|
1139
|
-
`Mount after WP install: ${
|
|
1294
|
+
for (const d of e.mount)
|
|
1295
|
+
g.debug(
|
|
1296
|
+
`Mount after WP install: ${d.vfsPath} -> ${d.hostPath}`
|
|
1140
1297
|
);
|
|
1141
|
-
let
|
|
1142
|
-
e["experimental-blueprints-v2-runner"] ?
|
|
1143
|
-
siteUrl:
|
|
1144
|
-
processIdSpaceLength:
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
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
|
|
1153
|
-
const
|
|
1154
|
-
|
|
1155
|
-
[...
|
|
1156
|
-
async ([w,
|
|
1157
|
-
await
|
|
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
|
-
),
|
|
1319
|
+
), a && await new Promise((w) => a.close(w)), await I.cleanup());
|
|
1161
1320
|
}, ge = kt(
|
|
1162
1321
|
W,
|
|
1163
|
-
|
|
1164
|
-
({ exitCode:
|
|
1165
|
-
|
|
1166
|
-
`Worker ${w} exited with code ${
|
|
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
|
-
|
|
1330
|
+
o.startProgress("Starting...");
|
|
1172
1331
|
try {
|
|
1173
|
-
const
|
|
1332
|
+
const d = await ge, w = await le(l);
|
|
1174
1333
|
{
|
|
1175
|
-
const m =
|
|
1334
|
+
const m = d.shift(), y = await $.bootAndSetUpInitialPlayground(
|
|
1176
1335
|
m.phpPort,
|
|
1177
1336
|
w,
|
|
1178
|
-
|
|
1337
|
+
H
|
|
1179
1338
|
);
|
|
1180
|
-
if (
|
|
1339
|
+
if (s.set(
|
|
1181
1340
|
m.worker,
|
|
1182
|
-
|
|
1183
|
-
), await
|
|
1184
|
-
const
|
|
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
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
)
|
|
1346
|
+
x && await ke(
|
|
1347
|
+
x,
|
|
1348
|
+
y
|
|
1349
|
+
);
|
|
1191
1350
|
}
|
|
1192
1351
|
if (e.command === "build-snapshot") {
|
|
1193
|
-
await
|
|
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
|
-
|
|
1355
|
+
o.finishProgress("Done"), await R();
|
|
1197
1356
|
return;
|
|
1198
1357
|
}
|
|
1199
|
-
await t.removeWorker(
|
|
1358
|
+
await t.removeWorker(y), await y.dispose(), await m.worker.terminate(), s.delete(m.worker);
|
|
1200
1359
|
}
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
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:
|
|
1208
|
-
firstProcessId:
|
|
1209
|
-
nativeInternalDirPath:
|
|
1365
|
+
fileLockManagerPort: D,
|
|
1366
|
+
firstProcessId: x,
|
|
1367
|
+
nativeInternalDirPath: H
|
|
1210
1368
|
});
|
|
1211
|
-
return
|
|
1369
|
+
return s.set(
|
|
1212
1370
|
m.worker,
|
|
1213
|
-
|
|
1214
|
-
), t.addWorker(
|
|
1371
|
+
N
|
|
1372
|
+
), t.addWorker(N), N;
|
|
1215
1373
|
})
|
|
1216
|
-
),
|
|
1217
|
-
|
|
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:
|
|
1223
|
-
server:
|
|
1224
|
-
serverUrl:
|
|
1225
|
-
[Symbol.asyncDispose]:
|
|
1226
|
-
[
|
|
1227
|
-
workerThreadCount:
|
|
1228
|
-
getWorkerNumberFromProcessId: (m) => Math.floor(m /
|
|
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 (
|
|
1387
|
+
} catch (d) {
|
|
1232
1388
|
if (e.verbosity !== "debug")
|
|
1233
|
-
throw
|
|
1389
|
+
throw d;
|
|
1234
1390
|
let w = "";
|
|
1235
|
-
throw await
|
|
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(
|
|
1239
|
-
if (!
|
|
1240
|
-
return
|
|
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 (
|
|
1245
|
-
|
|
1246
|
-
const
|
|
1400
|
+
if (b) {
|
|
1401
|
+
b = !1;
|
|
1402
|
+
const f = {
|
|
1247
1403
|
"Content-Type": ["text/plain"],
|
|
1248
1404
|
"Content-Length": ["0"],
|
|
1249
|
-
Location: [
|
|
1405
|
+
Location: [a.url]
|
|
1250
1406
|
};
|
|
1251
|
-
return
|
|
1407
|
+
return a.headers?.cookie?.includes(
|
|
1252
1408
|
"playground_auto_login_already_happened"
|
|
1253
|
-
) && (
|
|
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
|
|
1411
|
+
]), new Y(302, f, new Uint8Array());
|
|
1256
1412
|
}
|
|
1257
|
-
return await t.handleRequest(
|
|
1413
|
+
return await t.handleRequest(a);
|
|
1258
1414
|
}
|
|
1259
1415
|
});
|
|
1260
|
-
return
|
|
1416
|
+
return v && e.command === "start" && !e.skipBrowser && $t(v.serverUrl), v;
|
|
1261
1417
|
}
|
|
1262
|
-
function
|
|
1418
|
+
function xt(e) {
|
|
1263
1419
|
let t = { ...e, command: "server" };
|
|
1264
|
-
e.noAutoMount || (t.autoMount = h.resolve(process.cwd(), t.path ?? ""), t =
|
|
1265
|
-
const
|
|
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
|
-
) ||
|
|
1269
|
-
if (
|
|
1270
|
-
console.log("Site files stored at:",
|
|
1271
|
-
|
|
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
|
|
1281
|
-
|
|
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
|
-
|
|
1439
|
+
o
|
|
1284
1440
|
);
|
|
1285
|
-
console.log("Site files stored at:",
|
|
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:
|
|
1288
|
-
], t.wordpressInstallMode = Te(
|
|
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,
|
|
1300
|
-
const
|
|
1301
|
-
for (let
|
|
1302
|
-
const
|
|
1303
|
-
|
|
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:
|
|
1461
|
+
workerIndex: o
|
|
1306
1462
|
});
|
|
1307
1463
|
} });
|
|
1308
|
-
|
|
1464
|
+
s.push(n);
|
|
1309
1465
|
}
|
|
1310
|
-
return Promise.all(
|
|
1466
|
+
return Promise.all(s);
|
|
1311
1467
|
}
|
|
1312
|
-
function
|
|
1313
|
-
let
|
|
1314
|
-
return e === "v1" ?
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
}),
|
|
1318
|
-
console.error(
|
|
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. ${
|
|
1476
|
+
`Worker failed to load worker. ${n.message ? `Original error: ${n.message}` : ""}`
|
|
1321
1477
|
);
|
|
1322
|
-
|
|
1478
|
+
o(l);
|
|
1323
1479
|
});
|
|
1324
|
-
let
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
}),
|
|
1328
|
-
|
|
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:
|
|
1334
|
-
return await
|
|
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
|
|
1337
|
-
const t =
|
|
1338
|
-
let
|
|
1492
|
+
function $t(e) {
|
|
1493
|
+
const t = O.platform();
|
|
1494
|
+
let r;
|
|
1339
1495
|
switch (t) {
|
|
1340
1496
|
case "darwin":
|
|
1341
|
-
|
|
1497
|
+
r = `open "${e}"`;
|
|
1342
1498
|
break;
|
|
1343
1499
|
case "win32":
|
|
1344
|
-
|
|
1500
|
+
r = `start "" "${e}"`;
|
|
1345
1501
|
break;
|
|
1346
1502
|
default:
|
|
1347
|
-
|
|
1503
|
+
r = `xdg-open "${e}"`;
|
|
1348
1504
|
break;
|
|
1349
1505
|
}
|
|
1350
|
-
|
|
1351
|
-
|
|
1506
|
+
je(r, (s) => {
|
|
1507
|
+
s && g.debug(`Could not open browser: ${s.message}`);
|
|
1352
1508
|
});
|
|
1353
1509
|
}
|
|
1354
|
-
async function
|
|
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
|
|
1376
|
-
|
|
1531
|
+
const r = await e.readFileAsBuffer("/tmp/build.zip");
|
|
1532
|
+
p.writeFileSync(t, r);
|
|
1377
1533
|
}
|
|
1378
1534
|
export {
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
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-
|
|
1543
|
+
//# sourceMappingURL=run-cli-NcKUE5gJ.js.map
|