@wp-playground/cli 3.1.21 → 3.1.25
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/download.d.ts +1 -1
- package/blueprints-v1/worker-thread-v1.d.ts +2 -4
- package/blueprints-v2/worker-thread-v2.d.ts +3 -5
- package/cli-output.d.ts +8 -33
- package/cli.cjs +1 -1
- package/cli.js +1 -1
- package/index.cjs +1 -1
- package/index.js +1 -1
- package/package.json +15 -14
- package/php-extensions.d.ts +21 -0
- package/{run-cli-C2bV7mIt.js → run-cli-CC9V0J3D.js} +648 -665
- package/run-cli-CC9V0J3D.js.map +1 -0
- package/run-cli-b6r6MAhq.cjs +65 -0
- package/run-cli-b6r6MAhq.cjs.map +1 -0
- package/sqlite-database-integration.zip +0 -0
- package/worker-thread-v1.cjs +2 -2
- package/worker-thread-v1.cjs.map +1 -1
- package/worker-thread-v1.js +22 -24
- package/worker-thread-v1.js.map +1 -1
- package/worker-thread-v2.cjs +8 -8
- package/worker-thread-v2.cjs.map +1 -1
- package/worker-thread-v2.js +105 -110
- package/worker-thread-v2.js.map +1 -1
- package/run-cli-C2bV7mIt.js.map +0 -1
- package/run-cli-vtAjdYXb.cjs +0 -66
- package/run-cli-vtAjdYXb.cjs.map +0 -1
package/worker-thread-v2.js
CHANGED
|
@@ -1,58 +1,58 @@
|
|
|
1
|
-
import { logger as
|
|
2
|
-
import { createNodeFsMountHandler as
|
|
3
|
-
import { EmscriptenDownloadMonitor as
|
|
4
|
-
import { exposeAPI as
|
|
5
|
-
import { joinPaths as
|
|
6
|
-
import { runBlueprintV2 as
|
|
7
|
-
import { setupPlatformLevelMuPlugins as
|
|
8
|
-
import { existsSync as
|
|
9
|
-
import
|
|
10
|
-
import { rootCertificates as
|
|
11
|
-
import { MessageChannel as
|
|
12
|
-
import { s as
|
|
13
|
-
async function
|
|
1
|
+
import { logger as x, errorLogPath as _ } from "@php-wasm/logger";
|
|
2
|
+
import { createNodeFsMountHandler as y, loadNodeRuntime as R, bindUserSpace as T } from "@php-wasm/node";
|
|
3
|
+
import { EmscriptenDownloadMonitor as H } from "@php-wasm/progress";
|
|
4
|
+
import { exposeAPI as M, PHPWorker as $, consumeAPISync as I, setPhpIniEntries as v, writeFiles as A, sandboxedSpawnHandlerFactory as S, PHPResponse as L, PHPExecutionFailureError as B, consumeAPI as W, releaseApiProxy as C } from "@php-wasm/universal";
|
|
5
|
+
import { joinPaths as E, sprintf as F } from "@php-wasm/util";
|
|
6
|
+
import { runBlueprintV2 as U } from "@wp-playground/blueprints";
|
|
7
|
+
import { setupPlatformLevelMuPlugins as q, preloadPhpInfoRoute as D, bootRequestHandler as O } from "@wp-playground/wordpress";
|
|
8
|
+
import { existsSync as j } from "fs";
|
|
9
|
+
import P from "path";
|
|
10
|
+
import { rootCertificates as V } from "tls";
|
|
11
|
+
import { MessageChannel as N, parentPort as G } from "worker_threads";
|
|
12
|
+
import { s as Y, c as z } from "./run-cli-CC9V0J3D.js";
|
|
13
|
+
async function m(s, e) {
|
|
14
14
|
for (const t of e)
|
|
15
15
|
try {
|
|
16
16
|
s.mkdir(t.vfsPath), await s.mount(
|
|
17
17
|
t.vfsPath,
|
|
18
|
-
|
|
18
|
+
y(t.hostPath)
|
|
19
19
|
);
|
|
20
20
|
} catch {
|
|
21
|
-
|
|
21
|
+
i.stderr(
|
|
22
22
|
`\x1B[31m\x1B[1mError mounting path ${t.hostPath} at ${t.vfsPath}\x1B[0m
|
|
23
23
|
`
|
|
24
24
|
), process.exit(1);
|
|
25
25
|
}
|
|
26
26
|
}
|
|
27
|
-
function
|
|
27
|
+
function K(s, e, ...t) {
|
|
28
28
|
console.log(
|
|
29
29
|
performance.now().toFixed(6).padStart(15, "0"),
|
|
30
30
|
s.toString().padStart(16, "0"),
|
|
31
|
-
|
|
31
|
+
F(e, ...t)
|
|
32
32
|
);
|
|
33
33
|
}
|
|
34
34
|
Object.defineProperty(process.stdout, "isTTY", { value: !0 });
|
|
35
35
|
Object.defineProperty(process.stderr, "isTTY", { value: !0 });
|
|
36
|
-
const
|
|
36
|
+
const i = {
|
|
37
37
|
lastWriteWasProgress: !1,
|
|
38
38
|
progress(s) {
|
|
39
|
-
|
|
40
|
-
`), process.stdout.write("\r\x1B[K" + s),
|
|
39
|
+
z(process.stdout) && (process.stdout.isTTY ? (i.lastWriteWasProgress || process.stdout.write(`
|
|
40
|
+
`), process.stdout.write("\r\x1B[K" + s), i.lastWriteWasProgress = !0) : console.log(s));
|
|
41
41
|
},
|
|
42
42
|
stdout(s) {
|
|
43
43
|
process.stdout.write(`
|
|
44
44
|
|
|
45
45
|
|
|
46
|
-
`),
|
|
46
|
+
`), i.lastWriteWasProgress && (i.lastWriteWasProgress = !1), process.stdout.write(s);
|
|
47
47
|
},
|
|
48
48
|
stderr(s) {
|
|
49
49
|
process.stdout.write(`
|
|
50
50
|
|
|
51
51
|
|
|
52
|
-
`),
|
|
52
|
+
`), i.lastWriteWasProgress && (i.lastWriteWasProgress = !1), process.stderr.write(s);
|
|
53
53
|
}
|
|
54
54
|
};
|
|
55
|
-
class
|
|
55
|
+
class J extends $ {
|
|
56
56
|
constructor(e) {
|
|
57
57
|
super(void 0, e), this.booted = !1, this.blueprintTargetResolved = !1, this.phpInstancesThatNeedMountsAfterTargetResolved = /* @__PURE__ */ new Set();
|
|
58
58
|
}
|
|
@@ -66,20 +66,21 @@ class Z extends A {
|
|
|
66
66
|
* @see phpwasm-emscripten-library-file-locking-for-node.js
|
|
67
67
|
*/
|
|
68
68
|
async useFileLockManager(e) {
|
|
69
|
-
this.fileLockManager = await
|
|
69
|
+
this.fileLockManager = await I(e);
|
|
70
70
|
}
|
|
71
71
|
async bootWordPress(e, t) {
|
|
72
72
|
const o = await this.__internal_getRequestHandler().getPrimaryPhp();
|
|
73
|
-
if (o.defineConstant("WP_DEBUG", "true"), o.defineConstant("WP_DEBUG_LOG", "true"), o.defineConstant("WP_DEBUG_DISPLAY", "false"), o.defineConstant("WP_HOME", e.siteUrl), o.defineConstant("WP_SITEURL", e.siteUrl), await
|
|
73
|
+
if (o.defineConstant("WP_DEBUG", "true"), o.defineConstant("WP_DEBUG_LOG", "true"), o.defineConstant("WP_DEBUG_DISPLAY", "false"), o.defineConstant("WP_HOME", e.siteUrl), o.defineConstant("WP_SITEURL", e.siteUrl), await v(o, {
|
|
74
74
|
"openssl.cafile": "/internal/shared/ca-bundle.crt",
|
|
75
|
+
"curl.cainfo": "/internal/shared/ca-bundle.crt",
|
|
75
76
|
allow_url_fopen: "1",
|
|
76
77
|
disable_functions: ""
|
|
77
|
-
}), await
|
|
78
|
-
"/internal/shared/ca-bundle.crt":
|
|
78
|
+
}), await q(o), await A(o, "/", {
|
|
79
|
+
"/internal/shared/ca-bundle.crt": V.join(`
|
|
79
80
|
`)
|
|
80
|
-
}), await
|
|
81
|
+
}), await D(
|
|
81
82
|
o,
|
|
82
|
-
|
|
83
|
+
E(new URL(e.siteUrl).pathname, "phpinfo.php")
|
|
83
84
|
), e.mode === "mount-only") {
|
|
84
85
|
await this.applyPostInstallMountsToAllWorkers(
|
|
85
86
|
t
|
|
@@ -98,7 +99,7 @@ class Z extends A {
|
|
|
98
99
|
await this.bootRequestHandler({
|
|
99
100
|
...e,
|
|
100
101
|
onPHPInstanceCreated: async (t) => {
|
|
101
|
-
await
|
|
102
|
+
await m(t, e.mountsBeforeWpInstall || []), await m(t, e.mountsAfterWpInstall || []), t.isDir("/wordpress/wp-content") || t.mkdir("/wordpress/wp-content"), t.isDir("/wordpress/wp-content/database") || t.mkdir("/wordpress/wp-content/database"), t.isFile("/wordpress/wp-content/database/.htaccess") || t.writeFile(
|
|
102
103
|
"/wordpress/wp-content/database/.htaccess",
|
|
103
104
|
"deny from all"
|
|
104
105
|
), t.isFile("/wordpress/wp-content/database/index.php") || t.writeFile(
|
|
@@ -106,8 +107,8 @@ class Z extends A {
|
|
|
106
107
|
"deny from all"
|
|
107
108
|
);
|
|
108
109
|
},
|
|
109
|
-
spawnHandler: () =>
|
|
110
|
-
() =>
|
|
110
|
+
spawnHandler: () => S(
|
|
111
|
+
() => Q(e, this.fileLockManager)
|
|
111
112
|
)
|
|
112
113
|
});
|
|
113
114
|
}
|
|
@@ -116,17 +117,17 @@ class Z extends A {
|
|
|
116
117
|
let f = () => {
|
|
117
118
|
};
|
|
118
119
|
if (typeof e.blueprint == "string") {
|
|
119
|
-
const
|
|
120
|
-
|
|
120
|
+
const a = P.resolve(process.cwd(), e.blueprint);
|
|
121
|
+
j(a) && (w.mkdir("/internal/shared/cwd"), f = await w.mount(
|
|
121
122
|
"/internal/shared/cwd",
|
|
122
|
-
|
|
123
|
-
), e.blueprint =
|
|
123
|
+
y(P.dirname(a))
|
|
124
|
+
), e.blueprint = P.join(
|
|
124
125
|
"/internal/shared/cwd",
|
|
125
|
-
|
|
126
|
+
P.basename(e.blueprint)
|
|
126
127
|
));
|
|
127
128
|
}
|
|
128
129
|
try {
|
|
129
|
-
const
|
|
130
|
+
const l = [
|
|
130
131
|
"mode",
|
|
131
132
|
"db-engine",
|
|
132
133
|
"db-host",
|
|
@@ -137,15 +138,15 @@ class Z extends A {
|
|
|
137
138
|
"truncate-new-site-directory",
|
|
138
139
|
"allow"
|
|
139
140
|
].filter((r) => r in e).map((r) => `--${r}=${e[r]}`);
|
|
140
|
-
|
|
141
|
-
const
|
|
141
|
+
l.push(`--site-url=${e.siteUrl}`);
|
|
142
|
+
const d = await U({
|
|
142
143
|
php: u,
|
|
143
144
|
blueprint: e.blueprint,
|
|
144
145
|
blueprintOverrides: {
|
|
145
146
|
additionalSteps: e["additional-blueprint-steps"],
|
|
146
147
|
wordpressVersion: e.wp
|
|
147
148
|
},
|
|
148
|
-
cliArgs:
|
|
149
|
+
cliArgs: l,
|
|
149
150
|
onMessage: async (r) => {
|
|
150
151
|
switch (r.type) {
|
|
151
152
|
case "blueprint.target_resolved": {
|
|
@@ -155,21 +156,21 @@ class Z extends A {
|
|
|
155
156
|
break;
|
|
156
157
|
}
|
|
157
158
|
case "blueprint.progress": {
|
|
158
|
-
const
|
|
159
|
+
const c = `${r.caption.trim()} – ${r.progress.toFixed(
|
|
159
160
|
2
|
|
160
161
|
)}%`;
|
|
161
|
-
|
|
162
|
+
i.progress(c);
|
|
162
163
|
break;
|
|
163
164
|
}
|
|
164
165
|
case "blueprint.error": {
|
|
165
|
-
const
|
|
166
|
-
e.verbosity === "debug" && r.details ?
|
|
167
|
-
`${
|
|
166
|
+
const c = "\x1B[31m", p = "\x1B[1m", n = "\x1B[0m";
|
|
167
|
+
e.verbosity === "debug" && r.details ? i.stderr(
|
|
168
|
+
`${c}${p}Fatal error:${n} Uncaught ${r.details.exception}: ${r.details.message}
|
|
168
169
|
at ${r.details.file}:${r.details.line}
|
|
169
170
|
` + (r.details.trace ? r.details.trace + `
|
|
170
171
|
` : "")
|
|
171
|
-
) :
|
|
172
|
-
`${
|
|
172
|
+
) : i.stderr(
|
|
173
|
+
`${c}${p}Error:${n} ${r.message}
|
|
173
174
|
`
|
|
174
175
|
);
|
|
175
176
|
break;
|
|
@@ -177,33 +178,33 @@ class Z extends A {
|
|
|
177
178
|
}
|
|
178
179
|
}
|
|
179
180
|
});
|
|
180
|
-
if (e.verbosity === "debug" && (
|
|
181
|
+
if (e.verbosity === "debug" && (d.stdout.pipeTo(
|
|
181
182
|
new WritableStream({
|
|
182
183
|
write(r) {
|
|
183
184
|
process.stdout.write(r);
|
|
184
185
|
}
|
|
185
186
|
})
|
|
186
|
-
),
|
|
187
|
+
), d.stderr.pipeTo(
|
|
187
188
|
new WritableStream({
|
|
188
189
|
write(r) {
|
|
189
190
|
process.stderr.write(r);
|
|
190
191
|
}
|
|
191
192
|
})
|
|
192
|
-
)), await
|
|
193
|
-
const r = await
|
|
194
|
-
throw new
|
|
193
|
+
)), await d.finished, await d.exitCode !== 0) {
|
|
194
|
+
const r = await L.fromStreamedResponse(d);
|
|
195
|
+
throw new B(
|
|
195
196
|
`PHP.run() failed with exit code ${r.exitCode}. ${r.errors} ${r.text}`,
|
|
196
197
|
r,
|
|
197
198
|
"request"
|
|
198
199
|
);
|
|
199
200
|
}
|
|
200
|
-
} catch (
|
|
201
|
-
let
|
|
201
|
+
} catch (a) {
|
|
202
|
+
let l = "";
|
|
202
203
|
try {
|
|
203
|
-
|
|
204
|
+
l = u.readFileAsText(_);
|
|
204
205
|
} catch {
|
|
205
206
|
}
|
|
206
|
-
throw
|
|
207
|
+
throw a.phpLogs = l, a;
|
|
207
208
|
} finally {
|
|
208
209
|
h(), f();
|
|
209
210
|
}
|
|
@@ -216,74 +217,68 @@ class Z extends A {
|
|
|
216
217
|
createFiles: h,
|
|
217
218
|
constants: w,
|
|
218
219
|
phpIniEntries: f,
|
|
219
|
-
trace:
|
|
220
|
-
nativeInternalDirPath:
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
pathAliases: d,
|
|
226
|
-
onPHPInstanceCreated: k,
|
|
227
|
-
spawnHandler: x
|
|
220
|
+
trace: a,
|
|
221
|
+
nativeInternalDirPath: l,
|
|
222
|
+
extensions: d,
|
|
223
|
+
pathAliases: r,
|
|
224
|
+
onPHPInstanceCreated: c,
|
|
225
|
+
spawnHandler: p
|
|
228
226
|
}) {
|
|
229
227
|
if (this.booted)
|
|
230
228
|
throw new Error("Playground already booted");
|
|
231
229
|
this.booted = !0;
|
|
232
230
|
try {
|
|
233
|
-
const
|
|
231
|
+
const n = await O({
|
|
234
232
|
siteUrl: e,
|
|
235
|
-
createPhpRuntime: async () => await
|
|
233
|
+
createPhpRuntime: async () => await R(o, {
|
|
236
234
|
fileLockManager: this.fileLockManager,
|
|
237
235
|
emscriptenOptions: {
|
|
238
236
|
processId: u,
|
|
239
|
-
trace:
|
|
237
|
+
trace: a ? K : void 0,
|
|
240
238
|
ENV: {
|
|
241
239
|
DOCROOT: "/wordpress"
|
|
242
240
|
},
|
|
243
|
-
nativeInternalDirPath:
|
|
244
|
-
bindUserSpace: (
|
|
241
|
+
nativeInternalDirPath: l,
|
|
242
|
+
bindUserSpace: (k) => T(
|
|
245
243
|
{
|
|
246
244
|
fileLockManager: this.fileLockManager
|
|
247
245
|
},
|
|
248
|
-
|
|
246
|
+
k
|
|
249
247
|
)
|
|
250
248
|
},
|
|
251
249
|
followSymlinks: t?.includes("follow-symlinks"),
|
|
252
|
-
|
|
253
|
-
withRedis: r,
|
|
254
|
-
withMemcached: p,
|
|
255
|
-
withXdebug: c
|
|
250
|
+
extensions: d
|
|
256
251
|
}),
|
|
257
252
|
maxPhpInstances: 1,
|
|
258
|
-
onPHPInstanceCreated:
|
|
253
|
+
onPHPInstanceCreated: c,
|
|
259
254
|
sapiName: "cli",
|
|
260
255
|
createFiles: h,
|
|
261
256
|
constants: w,
|
|
262
257
|
phpIniEntries: f,
|
|
263
|
-
pathAliases:
|
|
258
|
+
pathAliases: r,
|
|
264
259
|
cookieStore: !1,
|
|
265
|
-
spawnHandler:
|
|
260
|
+
spawnHandler: p
|
|
266
261
|
});
|
|
267
|
-
this.__internal_setRequestHandler(
|
|
268
|
-
const
|
|
269
|
-
await this.setPrimaryPHP(
|
|
270
|
-
} catch (
|
|
271
|
-
throw
|
|
262
|
+
this.__internal_setRequestHandler(n);
|
|
263
|
+
const g = await n.getPrimaryPhp();
|
|
264
|
+
await this.setPrimaryPHP(g), X();
|
|
265
|
+
} catch (n) {
|
|
266
|
+
throw Z(n), n;
|
|
272
267
|
}
|
|
273
268
|
}
|
|
274
269
|
async mountAfterWordPressInstall(e) {
|
|
275
|
-
await
|
|
270
|
+
await m(this.__internal_getPHP(), e);
|
|
276
271
|
}
|
|
277
272
|
async applyPostInstallMountsToAllWorkers(e) {
|
|
278
|
-
const t =
|
|
279
|
-
await t(), t[
|
|
273
|
+
const t = W(e);
|
|
274
|
+
await t(), t[C]();
|
|
280
275
|
}
|
|
281
276
|
// Provide a named disposal method that can be invoked via comlink.
|
|
282
277
|
async dispose() {
|
|
283
278
|
await this[Symbol.asyncDispose]();
|
|
284
279
|
}
|
|
285
280
|
}
|
|
286
|
-
async function
|
|
281
|
+
async function Q({
|
|
287
282
|
siteUrl: s,
|
|
288
283
|
allow: e,
|
|
289
284
|
phpVersion: t,
|
|
@@ -292,58 +287,58 @@ async function ee({
|
|
|
292
287
|
phpIniEntries: h,
|
|
293
288
|
trace: w,
|
|
294
289
|
nativeInternalDirPath: f,
|
|
295
|
-
|
|
296
|
-
pathAliases:
|
|
297
|
-
mountsBeforeWpInstall:
|
|
290
|
+
extensions: a,
|
|
291
|
+
pathAliases: l,
|
|
292
|
+
mountsBeforeWpInstall: d,
|
|
298
293
|
mountsAfterWpInstall: r
|
|
299
|
-
},
|
|
300
|
-
const
|
|
301
|
-
|
|
294
|
+
}, c) {
|
|
295
|
+
const p = await Y("v2"), n = W(
|
|
296
|
+
p.phpPort
|
|
302
297
|
);
|
|
303
|
-
return
|
|
298
|
+
return n.useFileLockManager(c), await n.bootWorker({
|
|
304
299
|
siteUrl: s,
|
|
305
300
|
allow: e,
|
|
306
301
|
phpVersion: t,
|
|
307
302
|
createFiles: o,
|
|
308
303
|
constants: u,
|
|
309
304
|
phpIniEntries: h,
|
|
310
|
-
processId:
|
|
305
|
+
processId: p.processId,
|
|
311
306
|
trace: w,
|
|
312
307
|
nativeInternalDirPath: f,
|
|
313
|
-
|
|
314
|
-
pathAliases:
|
|
315
|
-
mountsBeforeWpInstall:
|
|
308
|
+
extensions: a,
|
|
309
|
+
pathAliases: l,
|
|
310
|
+
mountsBeforeWpInstall: d,
|
|
316
311
|
mountsAfterWpInstall: r
|
|
317
312
|
}), {
|
|
318
|
-
php:
|
|
313
|
+
php: n,
|
|
319
314
|
reap: () => {
|
|
320
315
|
try {
|
|
321
|
-
|
|
316
|
+
n.dispose();
|
|
322
317
|
} catch {
|
|
323
318
|
}
|
|
324
319
|
try {
|
|
325
|
-
|
|
320
|
+
p.worker.terminate();
|
|
326
321
|
} catch {
|
|
327
322
|
}
|
|
328
323
|
}
|
|
329
324
|
};
|
|
330
325
|
}
|
|
331
326
|
process.on("unhandledRejection", (s) => {
|
|
332
|
-
|
|
327
|
+
x.error("Unhandled rejection:", s);
|
|
333
328
|
});
|
|
334
|
-
const
|
|
335
|
-
new
|
|
329
|
+
const b = new N(), [X, Z] = M(
|
|
330
|
+
new J(new H()),
|
|
336
331
|
void 0,
|
|
337
|
-
|
|
332
|
+
b.port1
|
|
338
333
|
);
|
|
339
|
-
|
|
334
|
+
G?.postMessage(
|
|
340
335
|
{
|
|
341
336
|
command: "worker-script-initialized",
|
|
342
|
-
phpPort:
|
|
337
|
+
phpPort: b.port2
|
|
343
338
|
},
|
|
344
|
-
[
|
|
339
|
+
[b.port2]
|
|
345
340
|
);
|
|
346
341
|
export {
|
|
347
|
-
|
|
342
|
+
J as PlaygroundCliBlueprintV2Worker
|
|
348
343
|
};
|
|
349
344
|
//# sourceMappingURL=worker-thread-v2.js.map
|
package/worker-thread-v2.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"worker-thread-v2.js","sources":["../../../../packages/playground/cli/src/blueprints-v2/worker-thread-v2.ts"],"sourcesContent":["import { errorLogPath, logger } from '@php-wasm/logger';\nimport type { FileLockManager } from '@php-wasm/universal';\nimport {\n\tbindUserSpace,\n\tcreateNodeFsMountHandler,\n\tloadNodeRuntime,\n\ttype WasmUserSpaceContext,\n} from '@php-wasm/node';\nimport { EmscriptenDownloadMonitor } from '@php-wasm/progress';\nimport type {\n\tPathAlias,\n\tPHP,\n\tFileTree,\n\tRemoteAPI,\n\tSupportedPHPVersion,\n\tSpawnHandler,\n} from '@php-wasm/universal';\nimport {\n\tPHPExecutionFailureError,\n\tPHPResponse,\n\tPHPWorker,\n\treleaseApiProxy,\n\tconsumeAPI,\n\tconsumeAPISync,\n\texposeAPI,\n\tsandboxedSpawnHandlerFactory,\n\tsetPhpIniEntries,\n\twriteFiles,\n} from '@php-wasm/universal';\nimport { joinPaths, sprintf } from '@php-wasm/util';\nimport {\n\ttype BlueprintMessage,\n\trunBlueprintV2,\n\ttype BlueprintV1Declaration,\n} from '@wp-playground/blueprints';\nimport {\n\ttype ParsedBlueprintV2String,\n\ttype RawBlueprintV2Data,\n} from '@wp-playground/blueprints';\nimport {\n\tbootRequestHandler,\n\tpreloadPhpInfoRoute,\n\tsetupPlatformLevelMuPlugins,\n} from '@wp-playground/wordpress';\nimport { existsSync } from 'fs';\nimport path from 'path';\nimport { rootCertificates } from 'tls';\nimport { MessageChannel, type MessagePort, parentPort } from 'worker_threads';\nimport { type RunCLIArgs, spawnWorkerThread } from '../run-cli';\nimport type {\n\tPhpIniOptions,\n\tPHPInstanceCreatedHook,\n} from '@wp-playground/wordpress';\nimport { shouldRenderProgress } from '../utils/progress';\nimport type { Mount } from '@php-wasm/cli-util';\n\nasync function mountResources(php: PHP, mounts: Mount[]) {\n\tfor (const mount of mounts) {\n\t\ttry {\n\t\t\tphp.mkdir(mount.vfsPath);\n\t\t\tawait php.mount(\n\t\t\t\tmount.vfsPath,\n\t\t\t\tcreateNodeFsMountHandler(mount.hostPath)\n\t\t\t);\n\t\t} catch {\n\t\t\toutput.stderr(\n\t\t\t\t`\\x1b[31m\\x1b[1mError mounting path ${mount.hostPath} at ${mount.vfsPath}\\x1b[0m\\n`\n\t\t\t);\n\t\t\tprocess.exit(1);\n\t\t}\n\t}\n}\n\n/**\n * Print trace messages from PHP-WASM.\n *\n * @param {number} processId - The process ID.\n * @param {string} format - The format string.\n * @param {...any} args - The arguments.\n */\nfunction tracePhpWasm(processId: number, format: string, ...args: any[]) {\n\t// eslint-disable-next-line no-console\n\tconsole.log(\n\t\tperformance.now().toFixed(6).padStart(15, '0'),\n\t\tprocessId.toString().padStart(16, '0'),\n\t\tsprintf(format, ...args)\n\t);\n}\n\n/**\n * Force TTY status to preserve ANSI control codes in the output\n * when the environment is interactive.\n *\n * This script is spawned as `new Worker()` and process.stdout and process.stderr are\n * WritableWorkerStdio objects. By default, they strip ANSI control codes from the output\n * causing every progress bar update to be printed in a new line instead of updating the\n * same line.\n */\nObject.defineProperty(process.stdout, 'isTTY', { value: true });\nObject.defineProperty(process.stderr, 'isTTY', { value: true });\n\n/**\n * Output writer that ensures that progress bars are not printed on the same line as other output.\n */\nconst output = {\n\tlastWriteWasProgress: false,\n\tprogress(data: string) {\n\t\tif (!shouldRenderProgress(process.stdout)) {\n\t\t\treturn;\n\t\t}\n\t\tif (!process.stdout.isTTY) {\n\t\t\t// eslint-disable-next-line no-console\n\t\t\tconsole.log(data);\n\t\t} else {\n\t\t\tif (!output.lastWriteWasProgress) {\n\t\t\t\tprocess.stdout.write('\\n');\n\t\t\t}\n\t\t\tprocess.stdout.write('\\r\\x1b[K' + data);\n\t\t\toutput.lastWriteWasProgress = true;\n\t\t}\n\t},\n\tstdout(data: string) {\n\t\tprocess.stdout.write('\\n\\n\\n');\n\t\tif (output.lastWriteWasProgress) {\n\t\t\toutput.lastWriteWasProgress = false;\n\t\t}\n\t\tprocess.stdout.write(data);\n\t},\n\tstderr(data: string) {\n\t\tprocess.stdout.write('\\n\\n\\n');\n\t\tif (output.lastWriteWasProgress) {\n\t\t\toutput.lastWriteWasProgress = false;\n\t\t}\n\t\tprocess.stderr.write(data);\n\t},\n};\n\nexport type WorkerWordPressBootArgs = Omit<\n\tRunCLIArgs,\n\t'mount-before-install' | 'mount'\n> & {\n\tsiteUrl: string;\n\tblueprint:\n\t\t| RawBlueprintV2Data\n\t\t| ParsedBlueprintV2String\n\t\t| BlueprintV1Declaration;\n};\n\ntype WorkerRunBlueprintArgs = Omit<\n\tRunCLIArgs,\n\t'mount-before-install' | 'mount'\n> & {\n\tsiteUrl: string;\n\tblueprint:\n\t\t| RawBlueprintV2Data\n\t\t| ParsedBlueprintV2String\n\t\t| BlueprintV1Declaration;\n\tmountsAfterWpInstall?: Array<Mount>;\n};\n\nexport type SecondaryWorkerBootArgs = {\n\tsiteUrl: string;\n\tallow?: string;\n\tphpVersion: SupportedPHPVersion;\n\tphpIniEntries?: PhpIniOptions;\n\tconstants?: Record<string, string | number | boolean | null>;\n\tcreateFiles?: FileTree;\n\tprocessId: number;\n\ttrace: boolean;\n\tnativeInternalDirPath: string;\n\twithIntl?: boolean;\n\twithRedis?: boolean;\n\twithMemcached?: boolean;\n\twithXdebug?: boolean;\n\tpathAliases?: PathAlias[];\n\tmountsBeforeWpInstall?: Array<Mount>;\n\tmountsAfterWpInstall?: Array<Mount>;\n};\n\nexport type WorkerBootRequestHandlerOptions = Omit<\n\tSecondaryWorkerBootArgs,\n\t'mountsBeforeWpInstall' | 'mountsAfterWpInstall'\n> & {\n\tonPHPInstanceCreated: PHPInstanceCreatedHook;\n\tspawnHandler: () => SpawnHandler;\n};\n\nexport class PlaygroundCliBlueprintV2Worker extends PHPWorker {\n\tbooted = false;\n\tblueprintTargetResolved = false;\n\tphpInstancesThatNeedMountsAfterTargetResolved = new Set<PHP>();\n\tfileLockManager: FileLockManager | undefined;\n\n\tconstructor(monitor: EmscriptenDownloadMonitor) {\n\t\tsuper(undefined, monitor);\n\t}\n\n\t/**\n\t * Call this method before boot() to use file locking.\n\t *\n\t * This method is separate from boot() to simplify the related Comlink.transferHandlers\n\t * setup – if an argument is a MessagePort, we're transferring it, not copying it.\n\t *\n\t * @see comlink-sync.ts\n\t * @see phpwasm-emscripten-library-file-locking-for-node.js\n\t */\n\tasync useFileLockManager(port: MessagePort) {\n\t\t/**\n\t\t * If JSPI is not available, php.js only supports synchronous locking syscalls.\n\t\t * Let's use the synchronous API. Every method call will block this thread\n\t\t * until the result is available.\n\t\t *\n\t\t * @see comlink-sync.ts\n\t\t * @see phpwasm-emscripten-library-file-locking-for-node.js\n\t\t */\n\t\tthis.fileLockManager = await consumeAPISync<FileLockManager>(port);\n\t}\n\n\tasync bootWordPress(\n\t\targs: WorkerWordPressBootArgs,\n\t\tworkerPostInstallMountsPort: MessagePort\n\t) {\n\t\t// TODO: Should we move a process like this back into the\n\t\t// `@wp-playground/wordpress` package?\n\t\tconst php = await this.__internal_getRequestHandler()!.getPrimaryPhp();\n\t\tphp.defineConstant('WP_DEBUG', 'true');\n\t\tphp.defineConstant('WP_DEBUG_LOG', 'true');\n\t\tphp.defineConstant('WP_DEBUG_DISPLAY', 'false');\n\t\tphp.defineConstant('WP_HOME', args.siteUrl);\n\t\tphp.defineConstant('WP_SITEURL', args.siteUrl);\n\n\t\tawait setPhpIniEntries(php, {\n\t\t\t'openssl.cafile': '/internal/shared/ca-bundle.crt',\n\t\t\tallow_url_fopen: '1',\n\t\t\tdisable_functions: '',\n\t\t});\n\n\t\tawait setupPlatformLevelMuPlugins(php);\n\t\tawait writeFiles(php, '/', {\n\t\t\t'/internal/shared/ca-bundle.crt': rootCertificates.join('\\n'),\n\t\t});\n\t\tawait preloadPhpInfoRoute(\n\t\t\tphp,\n\t\t\tjoinPaths(new URL(args.siteUrl).pathname, 'phpinfo.php')\n\t\t);\n\n\t\tif (args.mode === 'mount-only') {\n\t\t\tawait this.applyPostInstallMountsToAllWorkers(\n\t\t\t\tworkerPostInstallMountsPort\n\t\t\t);\n\t\t\treturn;\n\t\t}\n\n\t\tawait this.runBlueprintV2(\n\t\t\t{\n\t\t\t\t// TODO: Do we really want to create a new object or can we pass args directly?\n\t\t\t\t...args,\n\t\t\t},\n\t\t\tworkerPostInstallMountsPort\n\t\t);\n\t}\n\n\tasync bootWorker(args: SecondaryWorkerBootArgs) {\n\t\tawait this.bootRequestHandler({\n\t\t\t...args,\n\t\t\tonPHPInstanceCreated: async (php: PHP) => {\n\t\t\t\tawait mountResources(php, args.mountsBeforeWpInstall || []);\n\t\t\t\tawait mountResources(php, args.mountsAfterWpInstall || []);\n\n\t\t\t\t// Temporary workaround for LOCK_EX in sqlite-database-integration.\n\t\t\t\t// Creation of these files results in this error:\n\t\t\t\t// PHP Warning: file_put_contents(): Exclusive locks are not supported for this stream\n\t\t\t\t// in\n\t\t\t\t// /wordpress/wp-content/plugins/sqlite-database-integration/wp-includes/sqlite/class-wp-sqlite-db.php\n\t\t\t\t// on line 670\n\t\t\t\tif (!php.isDir('/wordpress/wp-content')) {\n\t\t\t\t\tphp.mkdir('/wordpress/wp-content');\n\t\t\t\t}\n\t\t\t\tif (!php.isDir('/wordpress/wp-content/database')) {\n\t\t\t\t\tphp.mkdir('/wordpress/wp-content/database');\n\t\t\t\t}\n\t\t\t\tif (!php.isFile('/wordpress/wp-content/database/.htaccess')) {\n\t\t\t\t\tphp.writeFile(\n\t\t\t\t\t\t'/wordpress/wp-content/database/.htaccess',\n\t\t\t\t\t\t'deny from all'\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tif (!php.isFile('/wordpress/wp-content/database/index.php')) {\n\t\t\t\t\tphp.writeFile(\n\t\t\t\t\t\t'/wordpress/wp-content/database/index.php',\n\t\t\t\t\t\t'deny from all'\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t},\n\t\t\tspawnHandler: () =>\n\t\t\t\tsandboxedSpawnHandlerFactory(() =>\n\t\t\t\t\tcreatePHPWorker(args, this.fileLockManager!)\n\t\t\t\t),\n\t\t});\n\t}\n\n\tasync runBlueprintV2(\n\t\targs: WorkerRunBlueprintArgs,\n\t\tworkerPostInstallMountsPort: MessagePort\n\t) {\n\t\tconst requestHandler = this.__internal_getRequestHandler()!;\n\t\tconst { php, reap } =\n\t\t\tawait requestHandler.instanceManager.acquirePHPInstance();\n\n\t\t// Mount the current working directory to the PHP runtime for the purposes of\n\t\t// Blueprint resolution.\n\t\tconst primaryPhp = this.__internal_getPHP()!;\n\t\tlet unmountCwd = () => {};\n\t\tif (typeof args.blueprint === 'string') {\n\t\t\tconst blueprintPath = path.resolve(process.cwd(), args.blueprint);\n\t\t\tif (existsSync(blueprintPath)) {\n\t\t\t\tprimaryPhp.mkdir('/internal/shared/cwd');\n\t\t\t\tunmountCwd = await primaryPhp.mount(\n\t\t\t\t\t'/internal/shared/cwd',\n\t\t\t\t\tcreateNodeFsMountHandler(path.dirname(blueprintPath))\n\t\t\t\t);\n\t\t\t\targs.blueprint = path.join(\n\t\t\t\t\t'/internal/shared/cwd',\n\t\t\t\t\tpath.basename(args.blueprint)\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\ttry {\n\t\t\tconst cliArgsToPass: (keyof WorkerRunBlueprintArgs)[] = [\n\t\t\t\t'mode',\n\t\t\t\t'db-engine',\n\t\t\t\t'db-host',\n\t\t\t\t'db-user',\n\t\t\t\t'db-pass',\n\t\t\t\t'db-name',\n\t\t\t\t'db-path',\n\t\t\t\t'truncate-new-site-directory',\n\t\t\t\t'allow',\n\t\t\t];\n\t\t\tconst cliArgs = cliArgsToPass\n\t\t\t\t.filter((arg) => arg in args)\n\t\t\t\t.map((arg) => `--${arg}=${args[arg]}`);\n\t\t\tcliArgs.push(`--site-url=${args.siteUrl}`);\n\n\t\t\tconst streamedResponse = await runBlueprintV2({\n\t\t\t\tphp,\n\t\t\t\tblueprint: args.blueprint,\n\t\t\t\tblueprintOverrides: {\n\t\t\t\t\tadditionalSteps: args['additional-blueprint-steps'],\n\t\t\t\t\twordpressVersion: args.wp,\n\t\t\t\t},\n\t\t\t\tcliArgs,\n\t\t\t\tonMessage: async (message: BlueprintMessage) => {\n\t\t\t\t\tswitch (message.type) {\n\t\t\t\t\t\tcase 'blueprint.target_resolved': {\n\t\t\t\t\t\t\tif (!this.blueprintTargetResolved) {\n\t\t\t\t\t\t\t\tthis.blueprintTargetResolved = true;\n\t\t\t\t\t\t\t\tawait this.applyPostInstallMountsToAllWorkers(\n\t\t\t\t\t\t\t\t\tworkerPostInstallMountsPort\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tcase 'blueprint.progress': {\n\t\t\t\t\t\t\tconst progressMessage = `${message.caption.trim()} – ${message.progress.toFixed(\n\t\t\t\t\t\t\t\t2\n\t\t\t\t\t\t\t)}%`;\n\t\t\t\t\t\t\toutput.progress(progressMessage);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tcase 'blueprint.error': {\n\t\t\t\t\t\t\tconst red = '\\x1b[31m';\n\t\t\t\t\t\t\tconst bold = '\\x1b[1m';\n\t\t\t\t\t\t\tconst reset = '\\x1b[0m';\n\t\t\t\t\t\t\tif (args.verbosity === 'debug' && message.details) {\n\t\t\t\t\t\t\t\toutput.stderr(\n\t\t\t\t\t\t\t\t\t`${red}${bold}Fatal error:${reset} Uncaught ${message.details.exception}: ${message.details.message}\\n` +\n\t\t\t\t\t\t\t\t\t\t` at ${message.details.file}:${message.details.line}\\n` +\n\t\t\t\t\t\t\t\t\t\t(message.details.trace\n\t\t\t\t\t\t\t\t\t\t\t? message.details.trace + '\\n'\n\t\t\t\t\t\t\t\t\t\t\t: '')\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\toutput.stderr(\n\t\t\t\t\t\t\t\t\t`${red}${bold}Error:${reset} ${message.message}\\n`\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t});\n\t\t\t/**\n\t\t\t * When we're debugging, every bit of information matters – let's immediately output\n\t\t\t * everything we get from the PHP output streams.\n\t\t\t */\n\t\t\tif (args.verbosity === 'debug') {\n\t\t\t\tstreamedResponse!.stdout.pipeTo(\n\t\t\t\t\tnew WritableStream({\n\t\t\t\t\t\twrite(chunk) {\n\t\t\t\t\t\t\tprocess.stdout.write(chunk);\n\t\t\t\t\t\t},\n\t\t\t\t\t})\n\t\t\t\t);\n\t\t\t\tstreamedResponse!.stderr.pipeTo(\n\t\t\t\t\tnew WritableStream({\n\t\t\t\t\t\twrite(chunk) {\n\t\t\t\t\t\t\tprocess.stderr.write(chunk);\n\t\t\t\t\t\t},\n\t\t\t\t\t})\n\t\t\t\t);\n\t\t\t}\n\t\t\tawait streamedResponse!.finished;\n\t\t\tif ((await streamedResponse!.exitCode) !== 0) {\n\t\t\t\t// exitCode != 1 means the blueprint execution failed. Let's throw an error.\n\t\t\t\t// and clean up.\n\t\t\t\tconst syncResponse =\n\t\t\t\t\tawait PHPResponse.fromStreamedResponse(streamedResponse);\n\t\t\t\tthrow new PHPExecutionFailureError(\n\t\t\t\t\t`PHP.run() failed with exit code ${syncResponse.exitCode}. ${syncResponse.errors} ${syncResponse.text}`,\n\t\t\t\t\tsyncResponse,\n\t\t\t\t\t'request'\n\t\t\t\t);\n\t\t\t}\n\t\t} catch (error) {\n\t\t\t// Capture the PHP error log details to provide more context for debugging.\n\t\t\tlet phpLogs = '';\n\t\t\ttry {\n\t\t\t\t// @TODO: Don't assume errorLogPath starts with /wordpress/\n\t\t\t\t// ...or maybe we can assume that in Playground CLI?\n\t\t\t\tphpLogs = php.readFileAsText(errorLogPath);\n\t\t\t} catch {\n\t\t\t\t// Ignore errors reading the PHP error log.\n\t\t\t}\n\t\t\t(error as any).phpLogs = phpLogs;\n\t\t\tthrow error;\n\t\t} finally {\n\t\t\treap();\n\t\t\tunmountCwd();\n\t\t}\n\t}\n\n\tasync bootRequestHandler({\n\t\tsiteUrl,\n\t\tallow,\n\t\tphpVersion,\n\t\tprocessId,\n\t\tcreateFiles,\n\t\tconstants,\n\t\tphpIniEntries,\n\t\ttrace,\n\t\tnativeInternalDirPath,\n\t\twithIntl,\n\t\twithRedis,\n\t\twithMemcached,\n\t\twithXdebug,\n\t\tpathAliases,\n\t\tonPHPInstanceCreated,\n\t\tspawnHandler,\n\t}: WorkerBootRequestHandlerOptions) {\n\t\tif (this.booted) {\n\t\t\tthrow new Error('Playground already booted');\n\t\t}\n\t\tthis.booted = true;\n\n\t\ttry {\n\t\t\tconst requestHandler = await bootRequestHandler({\n\t\t\t\tsiteUrl,\n\t\t\t\tcreatePhpRuntime: async () => {\n\t\t\t\t\treturn await loadNodeRuntime(phpVersion, {\n\t\t\t\t\t\tfileLockManager: this.fileLockManager!,\n\t\t\t\t\t\temscriptenOptions: {\n\t\t\t\t\t\t\tprocessId,\n\t\t\t\t\t\t\ttrace: trace ? tracePhpWasm : undefined,\n\t\t\t\t\t\t\tENV: {\n\t\t\t\t\t\t\t\tDOCROOT: '/wordpress',\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tnativeInternalDirPath,\n\t\t\t\t\t\t\tbindUserSpace: (\n\t\t\t\t\t\t\t\tuserSpaceContext: WasmUserSpaceContext\n\t\t\t\t\t\t\t) => {\n\t\t\t\t\t\t\t\treturn bindUserSpace(\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\tfileLockManager: this.fileLockManager!,\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\tuserSpaceContext\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tfollowSymlinks: allow?.includes('follow-symlinks'),\n\t\t\t\t\t\twithIntl: withIntl,\n\t\t\t\t\t\twithRedis,\n\t\t\t\t\t\twithMemcached,\n\t\t\t\t\t\twithXdebug,\n\t\t\t\t\t});\n\t\t\t\t},\n\t\t\t\tmaxPhpInstances: 1,\n\t\t\t\tonPHPInstanceCreated,\n\t\t\t\tsapiName: 'cli',\n\t\t\t\tcreateFiles,\n\t\t\t\tconstants,\n\t\t\t\tphpIniEntries,\n\t\t\t\tpathAliases,\n\t\t\t\tcookieStore: false,\n\t\t\t\tspawnHandler,\n\t\t\t});\n\t\t\tthis.__internal_setRequestHandler(requestHandler);\n\n\t\t\tconst primaryPhp = await requestHandler.getPrimaryPhp();\n\t\t\tawait this.setPrimaryPHP(primaryPhp);\n\n\t\t\tsetApiReady();\n\t\t} catch (e) {\n\t\t\tsetAPIError(e as Error);\n\t\t\tthrow e;\n\t\t}\n\t}\n\n\tasync mountAfterWordPressInstall(mounts: Array<Mount>) {\n\t\tawait mountResources(this.__internal_getPHP()!, mounts);\n\t}\n\n\tasync applyPostInstallMountsToAllWorkers(\n\t\tpostInstallMountsPort: MessagePort\n\t): Promise<void> {\n\t\tconst applyPostInstallMountsToAllWorkers = consumeAPI<\n\t\t\t() => Promise<void>\n\t\t>(postInstallMountsPort);\n\t\tawait applyPostInstallMountsToAllWorkers();\n\t\tapplyPostInstallMountsToAllWorkers[releaseApiProxy]();\n\t}\n\n\t// Provide a named disposal method that can be invoked via comlink.\n\tasync dispose() {\n\t\tawait this[Symbol.asyncDispose]();\n\t}\n}\n\n/**\n * Spawns a new PHP process to be used in the PHP spawn handler (in proc_open() etc. calls).\n * It boots from this worker-thread-v1.ts file, but is a separate process.\n *\n * We explicitly avoid using PHPProcessManager.acquirePHPInstance() here.\n *\n * Why?\n *\n * Because each PHP instance acquires actual OS-level file locks via fcntl() and LockFileEx()\n * syscalls. Running multiple PHP instances from the same OS process would allow them to\n * acquire overlapping locks. Running every PHP instance in a separate OS process ensures\n * any locks that overlap between PHP instances conflict with each other as expected.\n *\n * @param options - The options for the worker.\n * @param fileLockManager - The file lock manager to use.\n * @returns A promise that resolves to the PHP worker.\n */\nasync function createPHPWorker(\n\t{\n\t\tsiteUrl,\n\t\tallow,\n\t\tphpVersion,\n\t\tcreateFiles,\n\t\tconstants,\n\t\tphpIniEntries,\n\t\ttrace,\n\t\tnativeInternalDirPath,\n\t\twithXdebug,\n\t\tpathAliases,\n\t\tmountsBeforeWpInstall,\n\t\tmountsAfterWpInstall,\n\t}: // NOTE: We explicitly remove processId from the options\n\t// type so the type system will catch if we try to reuse\n\t// our parent's process ID.\n\tOmit<SecondaryWorkerBootArgs, 'processId'>,\n\tfileLockManager: FileLockManager | RemoteAPI<FileLockManager>\n) {\n\tconst spawnedWorker = await spawnWorkerThread('v2');\n\n\tconst handler = consumeAPI<PlaygroundCliBlueprintV2Worker>(\n\t\tspawnedWorker.phpPort\n\t);\n\thandler.useFileLockManager(fileLockManager as any);\n\tawait handler.bootWorker({\n\t\tsiteUrl,\n\t\tallow,\n\t\tphpVersion,\n\t\tcreateFiles,\n\t\tconstants,\n\t\tphpIniEntries,\n\t\tprocessId: spawnedWorker.processId,\n\t\ttrace,\n\t\tnativeInternalDirPath,\n\t\twithXdebug,\n\t\tpathAliases,\n\t\tmountsBeforeWpInstall,\n\t\tmountsAfterWpInstall,\n\t});\n\n\treturn {\n\t\tphp: handler,\n\t\treap: () => {\n\t\t\ttry {\n\t\t\t\thandler.dispose();\n\t\t\t} catch {\n\t\t\t\t/** */\n\t\t\t}\n\t\t\ttry {\n\t\t\t\tspawnedWorker.worker.terminate();\n\t\t\t} catch {\n\t\t\t\t/** */\n\t\t\t}\n\t\t},\n\t};\n}\n\nprocess.on('unhandledRejection', (e: any) => {\n\tlogger.error('Unhandled rejection:', e);\n});\n\nconst phpChannel = new MessageChannel();\n\nconst [setApiReady, setAPIError] = exposeAPI(\n\tnew PlaygroundCliBlueprintV2Worker(new EmscriptenDownloadMonitor()),\n\tundefined,\n\tphpChannel.port1\n);\n\nparentPort?.postMessage(\n\t{\n\t\tcommand: 'worker-script-initialized',\n\t\tphpPort: phpChannel.port2,\n\t},\n\t[phpChannel.port2 as any]\n);\n"],"names":["mountResources","php","mounts","mount","createNodeFsMountHandler","output","tracePhpWasm","processId","format","args","sprintf","data","shouldRenderProgress","PlaygroundCliBlueprintV2Worker","PHPWorker","monitor","port","consumeAPISync","workerPostInstallMountsPort","setPhpIniEntries","setupPlatformLevelMuPlugins","writeFiles","rootCertificates","preloadPhpInfoRoute","joinPaths","sandboxedSpawnHandlerFactory","createPHPWorker","requestHandler","reap","primaryPhp","unmountCwd","blueprintPath","path","existsSync","cliArgs","arg","streamedResponse","runBlueprintV2","message","progressMessage","red","bold","reset","chunk","syncResponse","PHPResponse","PHPExecutionFailureError","error","phpLogs","errorLogPath","siteUrl","allow","phpVersion","createFiles","constants","phpIniEntries","trace","nativeInternalDirPath","withIntl","withRedis","withMemcached","withXdebug","pathAliases","onPHPInstanceCreated","spawnHandler","bootRequestHandler","loadNodeRuntime","userSpaceContext","bindUserSpace","setApiReady","e","setAPIError","postInstallMountsPort","applyPostInstallMountsToAllWorkers","consumeAPI","releaseApiProxy","mountsBeforeWpInstall","mountsAfterWpInstall","fileLockManager","spawnedWorker","spawnWorkerThread","handler","logger","phpChannel","MessageChannel","exposeAPI","EmscriptenDownloadMonitor","parentPort"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"worker-thread-v2.js","sources":["../../../../packages/playground/cli/src/blueprints-v2/worker-thread-v2.ts"],"sourcesContent":["import { errorLogPath, logger } from '@php-wasm/logger';\nimport type { FileLockManager } from '@php-wasm/universal';\nimport {\n\tbindUserSpace,\n\tcreateNodeFsMountHandler,\n\tloadNodeRuntime,\n\ttype PHPExtension,\n\ttype WasmUserSpaceContext,\n} from '@php-wasm/node';\nimport { EmscriptenDownloadMonitor } from '@php-wasm/progress';\nimport type {\n\tPathAlias,\n\tPHP,\n\tFileTree,\n\tRemoteAPI,\n\tSupportedPHPVersion,\n\tSpawnHandler,\n} from '@php-wasm/universal';\nimport {\n\tPHPExecutionFailureError,\n\tPHPResponse,\n\tPHPWorker,\n\treleaseApiProxy,\n\tconsumeAPI,\n\tconsumeAPISync,\n\texposeAPI,\n\tsandboxedSpawnHandlerFactory,\n\tsetPhpIniEntries,\n\twriteFiles,\n} from '@php-wasm/universal';\nimport { joinPaths, sprintf } from '@php-wasm/util';\nimport {\n\ttype BlueprintMessage,\n\trunBlueprintV2,\n\ttype BlueprintV1Declaration,\n} from '@wp-playground/blueprints';\nimport {\n\ttype ParsedBlueprintV2String,\n\ttype RawBlueprintV2Data,\n} from '@wp-playground/blueprints';\nimport {\n\tbootRequestHandler,\n\tpreloadPhpInfoRoute,\n\tsetupPlatformLevelMuPlugins,\n} from '@wp-playground/wordpress';\nimport { existsSync } from 'fs';\nimport path from 'path';\nimport { rootCertificates } from 'tls';\nimport { MessageChannel, type MessagePort, parentPort } from 'worker_threads';\nimport { type RunCLIArgs, spawnWorkerThread } from '../run-cli';\nimport type {\n\tPhpIniOptions,\n\tPHPInstanceCreatedHook,\n} from '@wp-playground/wordpress';\nimport { shouldRenderProgress } from '../utils/progress';\nimport type { Mount } from '@php-wasm/cli-util';\n\nasync function mountResources(php: PHP, mounts: Mount[]) {\n\tfor (const mount of mounts) {\n\t\ttry {\n\t\t\tphp.mkdir(mount.vfsPath);\n\t\t\tawait php.mount(\n\t\t\t\tmount.vfsPath,\n\t\t\t\tcreateNodeFsMountHandler(mount.hostPath)\n\t\t\t);\n\t\t} catch {\n\t\t\toutput.stderr(\n\t\t\t\t`\\x1b[31m\\x1b[1mError mounting path ${mount.hostPath} at ${mount.vfsPath}\\x1b[0m\\n`\n\t\t\t);\n\t\t\tprocess.exit(1);\n\t\t}\n\t}\n}\n\n/**\n * Print trace messages from PHP-WASM.\n *\n * @param {number} processId - The process ID.\n * @param {string} format - The format string.\n * @param {...any} args - The arguments.\n */\nfunction tracePhpWasm(processId: number, format: string, ...args: any[]) {\n\t// eslint-disable-next-line no-console\n\tconsole.log(\n\t\tperformance.now().toFixed(6).padStart(15, '0'),\n\t\tprocessId.toString().padStart(16, '0'),\n\t\tsprintf(format, ...args)\n\t);\n}\n\n/**\n * Force TTY status to preserve ANSI control codes in the output\n * when the environment is interactive.\n *\n * This script is spawned as `new Worker()` and process.stdout and process.stderr are\n * WritableWorkerStdio objects. By default, they strip ANSI control codes from the output\n * causing every progress bar update to be printed in a new line instead of updating the\n * same line.\n */\nObject.defineProperty(process.stdout, 'isTTY', { value: true });\nObject.defineProperty(process.stderr, 'isTTY', { value: true });\n\n/**\n * Output writer that ensures that progress bars are not printed on the same line as other output.\n */\nconst output = {\n\tlastWriteWasProgress: false,\n\tprogress(data: string) {\n\t\tif (!shouldRenderProgress(process.stdout)) {\n\t\t\treturn;\n\t\t}\n\t\tif (!process.stdout.isTTY) {\n\t\t\t// eslint-disable-next-line no-console\n\t\t\tconsole.log(data);\n\t\t} else {\n\t\t\tif (!output.lastWriteWasProgress) {\n\t\t\t\tprocess.stdout.write('\\n');\n\t\t\t}\n\t\t\tprocess.stdout.write('\\r\\x1b[K' + data);\n\t\t\toutput.lastWriteWasProgress = true;\n\t\t}\n\t},\n\tstdout(data: string) {\n\t\tprocess.stdout.write('\\n\\n\\n');\n\t\tif (output.lastWriteWasProgress) {\n\t\t\toutput.lastWriteWasProgress = false;\n\t\t}\n\t\tprocess.stdout.write(data);\n\t},\n\tstderr(data: string) {\n\t\tprocess.stdout.write('\\n\\n\\n');\n\t\tif (output.lastWriteWasProgress) {\n\t\t\toutput.lastWriteWasProgress = false;\n\t\t}\n\t\tprocess.stderr.write(data);\n\t},\n};\n\nexport type WorkerWordPressBootArgs = Omit<\n\tRunCLIArgs,\n\t'mount-before-install' | 'mount'\n> & {\n\tsiteUrl: string;\n\tblueprint:\n\t\t| RawBlueprintV2Data\n\t\t| ParsedBlueprintV2String\n\t\t| BlueprintV1Declaration;\n};\n\ntype WorkerRunBlueprintArgs = Omit<\n\tRunCLIArgs,\n\t'mount-before-install' | 'mount'\n> & {\n\tsiteUrl: string;\n\tblueprint:\n\t\t| RawBlueprintV2Data\n\t\t| ParsedBlueprintV2String\n\t\t| BlueprintV1Declaration;\n\tmountsAfterWpInstall?: Array<Mount>;\n};\n\nexport type SecondaryWorkerBootArgs = {\n\tsiteUrl: string;\n\tallow?: string;\n\tphpVersion: SupportedPHPVersion;\n\tphpIniEntries?: PhpIniOptions;\n\tconstants?: Record<string, string | number | boolean | null>;\n\tcreateFiles?: FileTree;\n\tprocessId: number;\n\ttrace: boolean;\n\tnativeInternalDirPath: string;\n\textensions?: PHPExtension[];\n\tpathAliases?: PathAlias[];\n\tmountsBeforeWpInstall?: Array<Mount>;\n\tmountsAfterWpInstall?: Array<Mount>;\n};\n\nexport type WorkerBootRequestHandlerOptions = Omit<\n\tSecondaryWorkerBootArgs,\n\t'mountsBeforeWpInstall' | 'mountsAfterWpInstall'\n> & {\n\tonPHPInstanceCreated: PHPInstanceCreatedHook;\n\tspawnHandler: () => SpawnHandler;\n};\n\nexport class PlaygroundCliBlueprintV2Worker extends PHPWorker {\n\tbooted = false;\n\tblueprintTargetResolved = false;\n\tphpInstancesThatNeedMountsAfterTargetResolved = new Set<PHP>();\n\tfileLockManager: FileLockManager | undefined;\n\n\tconstructor(monitor: EmscriptenDownloadMonitor) {\n\t\tsuper(undefined, monitor);\n\t}\n\n\t/**\n\t * Call this method before boot() to use file locking.\n\t *\n\t * This method is separate from boot() to simplify the related Comlink.transferHandlers\n\t * setup – if an argument is a MessagePort, we're transferring it, not copying it.\n\t *\n\t * @see comlink-sync.ts\n\t * @see phpwasm-emscripten-library-file-locking-for-node.js\n\t */\n\tasync useFileLockManager(port: MessagePort) {\n\t\t/**\n\t\t * If JSPI is not available, php.js only supports synchronous locking syscalls.\n\t\t * Let's use the synchronous API. Every method call will block this thread\n\t\t * until the result is available.\n\t\t *\n\t\t * @see comlink-sync.ts\n\t\t * @see phpwasm-emscripten-library-file-locking-for-node.js\n\t\t */\n\t\tthis.fileLockManager = await consumeAPISync<FileLockManager>(port);\n\t}\n\n\tasync bootWordPress(\n\t\targs: WorkerWordPressBootArgs,\n\t\tworkerPostInstallMountsPort: MessagePort\n\t) {\n\t\t// TODO: Should we move a process like this back into the\n\t\t// `@wp-playground/wordpress` package?\n\t\tconst php = await this.__internal_getRequestHandler()!.getPrimaryPhp();\n\t\tphp.defineConstant('WP_DEBUG', 'true');\n\t\tphp.defineConstant('WP_DEBUG_LOG', 'true');\n\t\tphp.defineConstant('WP_DEBUG_DISPLAY', 'false');\n\t\tphp.defineConstant('WP_HOME', args.siteUrl);\n\t\tphp.defineConstant('WP_SITEURL', args.siteUrl);\n\n\t\tawait setPhpIniEntries(php, {\n\t\t\t'openssl.cafile': '/internal/shared/ca-bundle.crt',\n\t\t\t'curl.cainfo': '/internal/shared/ca-bundle.crt',\n\t\t\tallow_url_fopen: '1',\n\t\t\tdisable_functions: '',\n\t\t});\n\n\t\tawait setupPlatformLevelMuPlugins(php);\n\t\tawait writeFiles(php, '/', {\n\t\t\t'/internal/shared/ca-bundle.crt': rootCertificates.join('\\n'),\n\t\t});\n\t\tawait preloadPhpInfoRoute(\n\t\t\tphp,\n\t\t\tjoinPaths(new URL(args.siteUrl).pathname, 'phpinfo.php')\n\t\t);\n\n\t\tif (args.mode === 'mount-only') {\n\t\t\tawait this.applyPostInstallMountsToAllWorkers(\n\t\t\t\tworkerPostInstallMountsPort\n\t\t\t);\n\t\t\treturn;\n\t\t}\n\n\t\tawait this.runBlueprintV2(\n\t\t\t{\n\t\t\t\t// TODO: Do we really want to create a new object or can we pass args directly?\n\t\t\t\t...args,\n\t\t\t},\n\t\t\tworkerPostInstallMountsPort\n\t\t);\n\t}\n\n\tasync bootWorker(args: SecondaryWorkerBootArgs) {\n\t\tawait this.bootRequestHandler({\n\t\t\t...args,\n\t\t\tonPHPInstanceCreated: async (php: PHP) => {\n\t\t\t\tawait mountResources(php, args.mountsBeforeWpInstall || []);\n\t\t\t\tawait mountResources(php, args.mountsAfterWpInstall || []);\n\n\t\t\t\t// Temporary workaround for LOCK_EX in sqlite-database-integration.\n\t\t\t\t// Creation of these files results in this error:\n\t\t\t\t// PHP Warning: file_put_contents(): Exclusive locks are not supported for this stream\n\t\t\t\t// in\n\t\t\t\t// /wordpress/wp-content/plugins/sqlite-database-integration/wp-includes/sqlite/class-wp-sqlite-db.php\n\t\t\t\t// on line 670\n\t\t\t\tif (!php.isDir('/wordpress/wp-content')) {\n\t\t\t\t\tphp.mkdir('/wordpress/wp-content');\n\t\t\t\t}\n\t\t\t\tif (!php.isDir('/wordpress/wp-content/database')) {\n\t\t\t\t\tphp.mkdir('/wordpress/wp-content/database');\n\t\t\t\t}\n\t\t\t\tif (!php.isFile('/wordpress/wp-content/database/.htaccess')) {\n\t\t\t\t\tphp.writeFile(\n\t\t\t\t\t\t'/wordpress/wp-content/database/.htaccess',\n\t\t\t\t\t\t'deny from all'\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tif (!php.isFile('/wordpress/wp-content/database/index.php')) {\n\t\t\t\t\tphp.writeFile(\n\t\t\t\t\t\t'/wordpress/wp-content/database/index.php',\n\t\t\t\t\t\t'deny from all'\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t},\n\t\t\tspawnHandler: () =>\n\t\t\t\tsandboxedSpawnHandlerFactory(() =>\n\t\t\t\t\tcreatePHPWorker(args, this.fileLockManager!)\n\t\t\t\t),\n\t\t});\n\t}\n\n\tasync runBlueprintV2(\n\t\targs: WorkerRunBlueprintArgs,\n\t\tworkerPostInstallMountsPort: MessagePort\n\t) {\n\t\tconst requestHandler = this.__internal_getRequestHandler()!;\n\t\tconst { php, reap } =\n\t\t\tawait requestHandler.instanceManager.acquirePHPInstance();\n\n\t\t// Mount the current working directory to the PHP runtime for the purposes of\n\t\t// Blueprint resolution.\n\t\tconst primaryPhp = this.__internal_getPHP()!;\n\t\tlet unmountCwd = () => {};\n\t\tif (typeof args.blueprint === 'string') {\n\t\t\tconst blueprintPath = path.resolve(process.cwd(), args.blueprint);\n\t\t\tif (existsSync(blueprintPath)) {\n\t\t\t\tprimaryPhp.mkdir('/internal/shared/cwd');\n\t\t\t\tunmountCwd = await primaryPhp.mount(\n\t\t\t\t\t'/internal/shared/cwd',\n\t\t\t\t\tcreateNodeFsMountHandler(path.dirname(blueprintPath))\n\t\t\t\t);\n\t\t\t\targs.blueprint = path.join(\n\t\t\t\t\t'/internal/shared/cwd',\n\t\t\t\t\tpath.basename(args.blueprint)\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\ttry {\n\t\t\tconst cliArgsToPass: (keyof WorkerRunBlueprintArgs)[] = [\n\t\t\t\t'mode',\n\t\t\t\t'db-engine',\n\t\t\t\t'db-host',\n\t\t\t\t'db-user',\n\t\t\t\t'db-pass',\n\t\t\t\t'db-name',\n\t\t\t\t'db-path',\n\t\t\t\t'truncate-new-site-directory',\n\t\t\t\t'allow',\n\t\t\t];\n\t\t\tconst cliArgs = cliArgsToPass\n\t\t\t\t.filter((arg) => arg in args)\n\t\t\t\t.map((arg) => `--${arg}=${args[arg]}`);\n\t\t\tcliArgs.push(`--site-url=${args.siteUrl}`);\n\n\t\t\tconst streamedResponse = await runBlueprintV2({\n\t\t\t\tphp,\n\t\t\t\tblueprint: args.blueprint,\n\t\t\t\tblueprintOverrides: {\n\t\t\t\t\tadditionalSteps: args['additional-blueprint-steps'],\n\t\t\t\t\twordpressVersion: args.wp,\n\t\t\t\t},\n\t\t\t\tcliArgs,\n\t\t\t\tonMessage: async (message: BlueprintMessage) => {\n\t\t\t\t\tswitch (message.type) {\n\t\t\t\t\t\tcase 'blueprint.target_resolved': {\n\t\t\t\t\t\t\tif (!this.blueprintTargetResolved) {\n\t\t\t\t\t\t\t\tthis.blueprintTargetResolved = true;\n\t\t\t\t\t\t\t\tawait this.applyPostInstallMountsToAllWorkers(\n\t\t\t\t\t\t\t\t\tworkerPostInstallMountsPort\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tcase 'blueprint.progress': {\n\t\t\t\t\t\t\tconst progressMessage = `${message.caption.trim()} – ${message.progress.toFixed(\n\t\t\t\t\t\t\t\t2\n\t\t\t\t\t\t\t)}%`;\n\t\t\t\t\t\t\toutput.progress(progressMessage);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tcase 'blueprint.error': {\n\t\t\t\t\t\t\tconst red = '\\x1b[31m';\n\t\t\t\t\t\t\tconst bold = '\\x1b[1m';\n\t\t\t\t\t\t\tconst reset = '\\x1b[0m';\n\t\t\t\t\t\t\tif (args.verbosity === 'debug' && message.details) {\n\t\t\t\t\t\t\t\toutput.stderr(\n\t\t\t\t\t\t\t\t\t`${red}${bold}Fatal error:${reset} Uncaught ${message.details.exception}: ${message.details.message}\\n` +\n\t\t\t\t\t\t\t\t\t\t` at ${message.details.file}:${message.details.line}\\n` +\n\t\t\t\t\t\t\t\t\t\t(message.details.trace\n\t\t\t\t\t\t\t\t\t\t\t? message.details.trace + '\\n'\n\t\t\t\t\t\t\t\t\t\t\t: '')\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\toutput.stderr(\n\t\t\t\t\t\t\t\t\t`${red}${bold}Error:${reset} ${message.message}\\n`\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t});\n\t\t\t/**\n\t\t\t * When we're debugging, every bit of information matters – let's immediately output\n\t\t\t * everything we get from the PHP output streams.\n\t\t\t */\n\t\t\tif (args.verbosity === 'debug') {\n\t\t\t\tstreamedResponse!.stdout.pipeTo(\n\t\t\t\t\tnew WritableStream({\n\t\t\t\t\t\twrite(chunk) {\n\t\t\t\t\t\t\tprocess.stdout.write(chunk);\n\t\t\t\t\t\t},\n\t\t\t\t\t})\n\t\t\t\t);\n\t\t\t\tstreamedResponse!.stderr.pipeTo(\n\t\t\t\t\tnew WritableStream({\n\t\t\t\t\t\twrite(chunk) {\n\t\t\t\t\t\t\tprocess.stderr.write(chunk);\n\t\t\t\t\t\t},\n\t\t\t\t\t})\n\t\t\t\t);\n\t\t\t}\n\t\t\tawait streamedResponse!.finished;\n\t\t\tif ((await streamedResponse!.exitCode) !== 0) {\n\t\t\t\t// exitCode != 1 means the blueprint execution failed. Let's throw an error.\n\t\t\t\t// and clean up.\n\t\t\t\tconst syncResponse =\n\t\t\t\t\tawait PHPResponse.fromStreamedResponse(streamedResponse);\n\t\t\t\tthrow new PHPExecutionFailureError(\n\t\t\t\t\t`PHP.run() failed with exit code ${syncResponse.exitCode}. ${syncResponse.errors} ${syncResponse.text}`,\n\t\t\t\t\tsyncResponse,\n\t\t\t\t\t'request'\n\t\t\t\t);\n\t\t\t}\n\t\t} catch (error) {\n\t\t\t// Capture the PHP error log details to provide more context for debugging.\n\t\t\tlet phpLogs = '';\n\t\t\ttry {\n\t\t\t\t// @TODO: Don't assume errorLogPath starts with /wordpress/\n\t\t\t\t// ...or maybe we can assume that in Playground CLI?\n\t\t\t\tphpLogs = php.readFileAsText(errorLogPath);\n\t\t\t} catch {\n\t\t\t\t// Ignore errors reading the PHP error log.\n\t\t\t}\n\t\t\t(error as any).phpLogs = phpLogs;\n\t\t\tthrow error;\n\t\t} finally {\n\t\t\treap();\n\t\t\tunmountCwd();\n\t\t}\n\t}\n\n\tasync bootRequestHandler({\n\t\tsiteUrl,\n\t\tallow,\n\t\tphpVersion,\n\t\tprocessId,\n\t\tcreateFiles,\n\t\tconstants,\n\t\tphpIniEntries,\n\t\ttrace,\n\t\tnativeInternalDirPath,\n\t\textensions,\n\t\tpathAliases,\n\t\tonPHPInstanceCreated,\n\t\tspawnHandler,\n\t}: WorkerBootRequestHandlerOptions) {\n\t\tif (this.booted) {\n\t\t\tthrow new Error('Playground already booted');\n\t\t}\n\t\tthis.booted = true;\n\n\t\ttry {\n\t\t\tconst requestHandler = await bootRequestHandler({\n\t\t\t\tsiteUrl,\n\t\t\t\tcreatePhpRuntime: async () => {\n\t\t\t\t\treturn await loadNodeRuntime(phpVersion, {\n\t\t\t\t\t\tfileLockManager: this.fileLockManager!,\n\t\t\t\t\t\temscriptenOptions: {\n\t\t\t\t\t\t\tprocessId,\n\t\t\t\t\t\t\ttrace: trace ? tracePhpWasm : undefined,\n\t\t\t\t\t\t\tENV: {\n\t\t\t\t\t\t\t\tDOCROOT: '/wordpress',\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tnativeInternalDirPath,\n\t\t\t\t\t\t\tbindUserSpace: (\n\t\t\t\t\t\t\t\tuserSpaceContext: WasmUserSpaceContext\n\t\t\t\t\t\t\t) => {\n\t\t\t\t\t\t\t\treturn bindUserSpace(\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\tfileLockManager: this.fileLockManager!,\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\tuserSpaceContext\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tfollowSymlinks: allow?.includes('follow-symlinks'),\n\t\t\t\t\t\textensions,\n\t\t\t\t\t});\n\t\t\t\t},\n\t\t\t\tmaxPhpInstances: 1,\n\t\t\t\tonPHPInstanceCreated,\n\t\t\t\tsapiName: 'cli',\n\t\t\t\tcreateFiles,\n\t\t\t\tconstants,\n\t\t\t\tphpIniEntries,\n\t\t\t\tpathAliases,\n\t\t\t\tcookieStore: false,\n\t\t\t\tspawnHandler,\n\t\t\t});\n\t\t\tthis.__internal_setRequestHandler(requestHandler);\n\n\t\t\tconst primaryPhp = await requestHandler.getPrimaryPhp();\n\t\t\tawait this.setPrimaryPHP(primaryPhp);\n\n\t\t\tsetApiReady();\n\t\t} catch (e) {\n\t\t\tsetAPIError(e as Error);\n\t\t\tthrow e;\n\t\t}\n\t}\n\n\tasync mountAfterWordPressInstall(mounts: Array<Mount>) {\n\t\tawait mountResources(this.__internal_getPHP()!, mounts);\n\t}\n\n\tasync applyPostInstallMountsToAllWorkers(\n\t\tpostInstallMountsPort: MessagePort\n\t): Promise<void> {\n\t\tconst applyPostInstallMountsToAllWorkers = consumeAPI<\n\t\t\t() => Promise<void>\n\t\t>(postInstallMountsPort);\n\t\tawait applyPostInstallMountsToAllWorkers();\n\t\tapplyPostInstallMountsToAllWorkers[releaseApiProxy]();\n\t}\n\n\t// Provide a named disposal method that can be invoked via comlink.\n\tasync dispose() {\n\t\tawait this[Symbol.asyncDispose]();\n\t}\n}\n\n/**\n * Spawns a new PHP process to be used in the PHP spawn handler (in proc_open() etc. calls).\n * It boots from this worker-thread-v1.ts file, but is a separate process.\n *\n * We explicitly avoid using PHPProcessManager.acquirePHPInstance() here.\n *\n * Why?\n *\n * Because each PHP instance acquires actual OS-level file locks via fcntl() and LockFileEx()\n * syscalls. Running multiple PHP instances from the same OS process would allow them to\n * acquire overlapping locks. Running every PHP instance in a separate OS process ensures\n * any locks that overlap between PHP instances conflict with each other as expected.\n *\n * @param options - The options for the worker.\n * @param fileLockManager - The file lock manager to use.\n * @returns A promise that resolves to the PHP worker.\n */\nasync function createPHPWorker(\n\t{\n\t\tsiteUrl,\n\t\tallow,\n\t\tphpVersion,\n\t\tcreateFiles,\n\t\tconstants,\n\t\tphpIniEntries,\n\t\ttrace,\n\t\tnativeInternalDirPath,\n\t\textensions,\n\t\tpathAliases,\n\t\tmountsBeforeWpInstall,\n\t\tmountsAfterWpInstall,\n\t}: // NOTE: We explicitly remove processId from the options\n\t// type so the type system will catch if we try to reuse\n\t// our parent's process ID.\n\tOmit<SecondaryWorkerBootArgs, 'processId'>,\n\tfileLockManager: FileLockManager | RemoteAPI<FileLockManager>\n) {\n\tconst spawnedWorker = await spawnWorkerThread('v2');\n\n\tconst handler = consumeAPI<PlaygroundCliBlueprintV2Worker>(\n\t\tspawnedWorker.phpPort\n\t);\n\thandler.useFileLockManager(fileLockManager as any);\n\tawait handler.bootWorker({\n\t\tsiteUrl,\n\t\tallow,\n\t\tphpVersion,\n\t\tcreateFiles,\n\t\tconstants,\n\t\tphpIniEntries,\n\t\tprocessId: spawnedWorker.processId,\n\t\ttrace,\n\t\tnativeInternalDirPath,\n\t\textensions,\n\t\tpathAliases,\n\t\tmountsBeforeWpInstall,\n\t\tmountsAfterWpInstall,\n\t});\n\n\treturn {\n\t\tphp: handler,\n\t\treap: () => {\n\t\t\ttry {\n\t\t\t\thandler.dispose();\n\t\t\t} catch {\n\t\t\t\t/** */\n\t\t\t}\n\t\t\ttry {\n\t\t\t\tspawnedWorker.worker.terminate();\n\t\t\t} catch {\n\t\t\t\t/** */\n\t\t\t}\n\t\t},\n\t};\n}\n\nprocess.on('unhandledRejection', (e: any) => {\n\tlogger.error('Unhandled rejection:', e);\n});\n\nconst phpChannel = new MessageChannel();\n\nconst [setApiReady, setAPIError] = exposeAPI(\n\tnew PlaygroundCliBlueprintV2Worker(new EmscriptenDownloadMonitor()),\n\tundefined,\n\tphpChannel.port1\n);\n\nparentPort?.postMessage(\n\t{\n\t\tcommand: 'worker-script-initialized',\n\t\tphpPort: phpChannel.port2,\n\t},\n\t[phpChannel.port2 as any]\n);\n"],"names":["mountResources","php","mounts","mount","createNodeFsMountHandler","output","tracePhpWasm","processId","format","args","sprintf","data","shouldRenderProgress","PlaygroundCliBlueprintV2Worker","PHPWorker","monitor","port","consumeAPISync","workerPostInstallMountsPort","setPhpIniEntries","setupPlatformLevelMuPlugins","writeFiles","rootCertificates","preloadPhpInfoRoute","joinPaths","sandboxedSpawnHandlerFactory","createPHPWorker","requestHandler","reap","primaryPhp","unmountCwd","blueprintPath","path","existsSync","cliArgs","arg","streamedResponse","runBlueprintV2","message","progressMessage","red","bold","reset","chunk","syncResponse","PHPResponse","PHPExecutionFailureError","error","phpLogs","errorLogPath","siteUrl","allow","phpVersion","createFiles","constants","phpIniEntries","trace","nativeInternalDirPath","extensions","pathAliases","onPHPInstanceCreated","spawnHandler","bootRequestHandler","loadNodeRuntime","userSpaceContext","bindUserSpace","setApiReady","e","setAPIError","postInstallMountsPort","applyPostInstallMountsToAllWorkers","consumeAPI","releaseApiProxy","mountsBeforeWpInstall","mountsAfterWpInstall","fileLockManager","spawnedWorker","spawnWorkerThread","handler","logger","phpChannel","MessageChannel","exposeAPI","EmscriptenDownloadMonitor","parentPort"],"mappings":"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"}
|