@wp-playground/cli 3.0.22 → 3.0.30

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,22 +1,22 @@
1
- import { loadNodeRuntime as _ } from "@php-wasm/node";
2
- import { EmscriptenDownloadMonitor as v } from "@php-wasm/progress";
3
- import { exposeAPI as E, PHPWorker as L, consumeAPI as O, consumeAPISync as x, sandboxedSpawnHandlerFactory as I } from "@php-wasm/universal";
4
- import { sprintf as A } from "@php-wasm/util";
5
- import { RecommendedPHPVersion as C } from "@wp-playground/common";
6
- import { bootWordPressAndRequestHandler as D, bootRequestHandler as F } from "@wp-playground/wordpress";
7
- import { rootCertificates as B } from "tls";
8
- import { jspi as U } from "wasm-feature-detect";
9
- import { MessageChannel as j, parentPort as G } from "worker_threads";
10
- import { m as s } from "./mounts-ChxECdbN.js";
11
- import { logger as N } from "@php-wasm/logger";
12
- function M(c, e, ...a) {
1
+ import { loadNodeRuntime as H } from "@php-wasm/node";
2
+ import { EmscriptenDownloadMonitor as W } from "@php-wasm/progress";
3
+ import { exposeAPI as S, PHPWorker as R, consumeAPI as g, consumeAPISync as _, sandboxedSpawnHandlerFactory as P } from "@php-wasm/universal";
4
+ import { sprintf as q } from "@php-wasm/util";
5
+ import { RecommendedPHPVersion as M } from "@wp-playground/common";
6
+ import { bootWordPressAndRequestHandler as v, bootRequestHandler as L } from "@wp-playground/wordpress";
7
+ import { rootCertificates as A } from "tls";
8
+ import { jspi as D } from "wasm-feature-detect";
9
+ import { MessageChannel as E, parentPort as F } from "worker_threads";
10
+ import { m as n, s as U } from "./run-cli-pLJHMn5d.js";
11
+ import { logger as B } from "@php-wasm/logger";
12
+ function C(t, e, ...r) {
13
13
  console.log(
14
14
  performance.now().toFixed(6).padStart(15, "0"),
15
- c.toString().padStart(16, "0"),
16
- A(e, ...a)
15
+ t.toString().padStart(16, "0"),
16
+ q(e, ...r)
17
17
  );
18
18
  }
19
- class V extends L {
19
+ class x extends R {
20
20
  constructor(e) {
21
21
  super(void 0, e), this.booted = !1;
22
22
  }
@@ -30,134 +30,99 @@ class V extends L {
30
30
  * @see phpwasm-emscripten-library-file-locking-for-node.js
31
31
  */
32
32
  async useFileLockManager(e) {
33
- await U() ? this.fileLockManager = O(e) : this.fileLockManager = await x(e);
33
+ await D() ? this.fileLockManager = g(e) : this.fileLockManager = await _(e);
34
34
  }
35
- async bootAndSetUpInitialWorker({
36
- siteUrl: e,
37
- mountsBeforeWpInstall: a,
38
- mountsAfterWpInstall: l,
39
- phpVersion: n = C,
40
- wordpressInstallMode: P,
41
- wordPressZip: p,
42
- sqliteIntegrationPluginZip: d,
43
- firstProcessId: i,
44
- processIdSpaceLength: u,
45
- dataSqlPath: f,
46
- followSymlinks: o,
47
- trace: y,
48
- internalCookieStore: t,
49
- withXdebug: g,
50
- nativeInternalDirPath: r
51
- }) {
35
+ async bootAndSetUpInitialWorker(e) {
36
+ const {
37
+ siteUrl: r,
38
+ mountsBeforeWpInstall: a,
39
+ mountsAfterWpInstall: o,
40
+ wordpressInstallMode: I,
41
+ wordPressZip: l,
42
+ sqliteIntegrationPluginZip: c,
43
+ dataSqlPath: k,
44
+ internalCookieStore: b
45
+ } = e;
52
46
  if (this.booted)
53
47
  throw new Error("Playground already booted");
54
48
  this.booted = !0;
55
- let m = i;
56
- const q = i + u - 1;
57
49
  try {
58
- const h = {
50
+ const s = {
59
51
  WP_DEBUG: !0,
60
52
  WP_DEBUG_LOG: !0,
61
53
  WP_DEBUG_DISPLAY: !1
62
54
  };
63
- let H = !1;
64
- const k = await D({
65
- siteUrl: e,
66
- createPhpRuntime: async () => {
67
- const w = m;
68
- return m < q ? m++ : m = i, await _(n, {
69
- emscriptenOptions: {
70
- fileLockManager: this.fileLockManager,
71
- processId: w,
72
- trace: y ? M : void 0,
73
- phpWasmInitOptions: { nativeInternalDirPath: r }
74
- },
75
- followSymlinks: o,
76
- withXdebug: g
77
- });
78
- },
79
- wordpressInstallMode: P,
80
- wordPressZip: p !== void 0 ? new File([p], "wordpress.zip") : void 0,
81
- sqliteIntegrationPluginZip: d !== void 0 ? new File(
82
- [d],
55
+ let d = !1;
56
+ const p = await v({
57
+ siteUrl: r,
58
+ createPhpRuntime: u(
59
+ e,
60
+ this.fileLockManager
61
+ ),
62
+ wordpressInstallMode: I,
63
+ wordPressZip: l !== void 0 ? new File([l], "wordpress.zip") : void 0,
64
+ sqliteIntegrationPluginZip: c !== void 0 ? new File(
65
+ [c],
83
66
  "sqlite-integration-plugin.zip"
84
67
  ) : void 0,
85
68
  sapiName: "cli",
86
69
  createFiles: {
87
- "/internal/shared/ca-bundle.crt": B.join(`
70
+ "/internal/shared/ca-bundle.crt": A.join(`
88
71
  `)
89
72
  },
90
- constants: h,
73
+ constants: s,
91
74
  phpIniEntries: {
92
75
  "openssl.cafile": "/internal/shared/ca-bundle.crt",
93
76
  allow_url_fopen: "1",
94
77
  disable_functions: ""
95
78
  },
96
- cookieStore: t ? void 0 : !1,
97
- dataSqlPath: f,
98
- spawnHandler: I,
99
- async onPHPInstanceCreated(w) {
100
- await s(w, a), H && await s(w, l);
79
+ cookieStore: b ? void 0 : !1,
80
+ dataSqlPath: k,
81
+ spawnHandler: () => P(
82
+ () => w(e, this.fileLockManager)
83
+ ),
84
+ async onPHPInstanceCreated(m) {
85
+ await n(m, a), d && await n(m, o);
101
86
  }
102
87
  });
103
- this.__internal_setRequestHandler(k), H = !0;
104
- const R = await k.getPrimaryPhp();
105
- await this.setPrimaryPHP(R), await s(R, l), S();
106
- } catch (h) {
107
- throw W(h), h;
88
+ this.__internal_setRequestHandler(p), d = !0;
89
+ const h = await p.getPrimaryPhp();
90
+ await this.setPrimaryPHP(h), await n(h, o), f();
91
+ } catch (s) {
92
+ throw y(s), s;
108
93
  }
109
94
  }
95
+ async hello() {
96
+ return "hello";
97
+ }
110
98
  async bootWorker(e) {
111
99
  await this.bootRequestHandler(e);
112
100
  }
113
- async bootRequestHandler({
114
- siteUrl: e,
115
- followSymlinks: a,
116
- phpVersion: l,
117
- firstProcessId: n,
118
- processIdSpaceLength: P,
119
- trace: p,
120
- nativeInternalDirPath: d,
121
- mountsBeforeWpInstall: i,
122
- mountsAfterWpInstall: u,
123
- withXdebug: f
124
- }) {
101
+ async bootRequestHandler(e) {
125
102
  if (this.booted)
126
103
  throw new Error("Playground already booted");
127
104
  this.booted = !0;
128
- let o = n;
129
- const y = n + P - 1;
130
105
  try {
131
- const t = await F({
132
- siteUrl: e,
133
- createPhpRuntime: async () => {
134
- const r = o;
135
- return o < y ? o++ : o = n, await _(l, {
136
- emscriptenOptions: {
137
- fileLockManager: this.fileLockManager,
138
- processId: r,
139
- trace: p ? M : void 0,
140
- ENV: {
141
- DOCROOT: "/wordpress"
142
- },
143
- phpWasmInitOptions: { nativeInternalDirPath: d }
144
- },
145
- followSymlinks: a,
146
- withXdebug: f
147
- });
148
- },
149
- onPHPInstanceCreated: async (r) => {
150
- await s(r, i), await s(r, u);
106
+ const r = await L({
107
+ siteUrl: e.siteUrl,
108
+ createPhpRuntime: u(
109
+ e,
110
+ this.fileLockManager
111
+ ),
112
+ onPHPInstanceCreated: async (o) => {
113
+ await n(o, e.mountsBeforeWpInstall), await n(o, e.mountsAfterWpInstall);
151
114
  },
152
115
  sapiName: "cli",
153
116
  cookieStore: !1,
154
- spawnHandler: I
117
+ spawnHandler: () => P(
118
+ () => w(e, this.fileLockManager)
119
+ )
155
120
  });
156
- this.__internal_setRequestHandler(t);
157
- const g = await t.getPrimaryPhp();
158
- await this.setPrimaryPHP(g), S();
159
- } catch (t) {
160
- throw W(t), t;
121
+ this.__internal_setRequestHandler(r);
122
+ const a = await r.getPrimaryPhp();
123
+ await this.setPrimaryPHP(a), f();
124
+ } catch (r) {
125
+ throw y(r), r;
161
126
  }
162
127
  }
163
128
  // Provide a named disposal method that can be invoked via comlink.
@@ -165,22 +130,63 @@ class V extends L {
165
130
  await this[Symbol.asyncDispose]();
166
131
  }
167
132
  }
168
- process.on("unhandledRejection", (c) => {
169
- N.error("Unhandled rejection:", c);
133
+ function u(t, e) {
134
+ let r = t.firstProcessId;
135
+ const a = t.firstProcessId + t.processIdSpaceLength - 1;
136
+ return async () => {
137
+ const o = r;
138
+ return r < a ? r++ : r = t.firstProcessId, await H(
139
+ t.phpVersion || M,
140
+ {
141
+ emscriptenOptions: {
142
+ fileLockManager: e,
143
+ processId: o,
144
+ trace: t.trace ? C : void 0,
145
+ phpWasmInitOptions: {
146
+ nativeInternalDirPath: t.nativeInternalDirPath
147
+ }
148
+ },
149
+ followSymlinks: t.followSymlinks,
150
+ withIntl: t.withIntl,
151
+ withXdebug: t.withXdebug
152
+ }
153
+ );
154
+ };
155
+ }
156
+ async function w(t, e) {
157
+ const r = await U("v1"), a = g(
158
+ r.phpPort
159
+ );
160
+ return a.useFileLockManager(e), await a.bootWorker(t), {
161
+ php: a,
162
+ reap: () => {
163
+ try {
164
+ a.dispose();
165
+ } catch {
166
+ }
167
+ try {
168
+ r.worker.terminate();
169
+ } catch {
170
+ }
171
+ }
172
+ };
173
+ }
174
+ process.on("unhandledRejection", (t) => {
175
+ B.error("Unhandled rejection:", t);
170
176
  });
171
- const b = new j(), [S, W] = E(
172
- new V(new v()),
177
+ const i = new E(), [f, y] = S(
178
+ new x(new W()),
173
179
  void 0,
174
- b.port1
180
+ i.port1
175
181
  );
176
- G?.postMessage(
182
+ F?.postMessage(
177
183
  {
178
184
  command: "worker-script-initialized",
179
- phpPort: b.port2
185
+ phpPort: i.port2
180
186
  },
181
- [b.port2]
187
+ [i.port2]
182
188
  );
183
189
  export {
184
- V as PlaygroundCliBlueprintV1Worker
190
+ x as PlaygroundCliBlueprintV1Worker
185
191
  };
186
192
  //# sourceMappingURL=worker-thread-v1.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"worker-thread-v1.js","sources":["../../../../packages/playground/cli/src/blueprints-v1/worker-thread-v1.ts"],"sourcesContent":["import type { FileLockManager } from '@php-wasm/node';\nimport { loadNodeRuntime } from '@php-wasm/node';\nimport { EmscriptenDownloadMonitor } from '@php-wasm/progress';\nimport type { RemoteAPI, SupportedPHPVersion } from '@php-wasm/universal';\nimport {\n\tPHPWorker,\n\tconsumeAPI,\n\tconsumeAPISync,\n\texposeAPI,\n\tsandboxedSpawnHandlerFactory,\n} from '@php-wasm/universal';\nimport { sprintf } from '@php-wasm/util';\nimport { RecommendedPHPVersion } from '@wp-playground/common';\nimport {\n\ttype WordPressInstallMode,\n\tbootRequestHandler,\n\tbootWordPressAndRequestHandler,\n} from '@wp-playground/wordpress';\nimport { rootCertificates } from 'tls';\nimport { jspi } from 'wasm-feature-detect';\nimport { MessageChannel, type MessagePort, parentPort } from 'worker_threads';\nimport { mountResources } from '../mounts';\nimport { logger } from '@php-wasm/logger';\n\nexport interface Mount {\n\thostPath: string;\n\tvfsPath: string;\n}\n\nexport type WorkerBootOptions = {\n\tphpVersion: SupportedPHPVersion;\n\tsiteUrl: string;\n\tmountsBeforeWpInstall: Array<Mount>;\n\tmountsAfterWpInstall: Array<Mount>;\n\tfirstProcessId: number;\n\tprocessIdSpaceLength: number;\n\tfollowSymlinks: boolean;\n\ttrace: boolean;\n\t/**\n\t * When true, Playground will not send cookies to the client but will manage\n\t * them internally. This can be useful in environments that can't store cookies,\n\t * e.g. VS Code WebView.\n\t *\n\t * Default: false.\n\t */\n\tinternalCookieStore?: boolean;\n\twithXdebug?: boolean;\n\tnativeInternalDirPath: string;\n};\n\nexport type PrimaryWorkerBootOptions = WorkerBootOptions & {\n\twordpressInstallMode: WordPressInstallMode;\n\twpVersion?: string;\n\twordPressZip?: ArrayBuffer;\n\tsqliteIntegrationPluginZip?: ArrayBuffer;\n\tdataSqlPath?: string;\n};\n\ninterface WorkerBootRequestHandlerOptions {\n\tsiteUrl: string;\n\tfollowSymlinks: boolean;\n\tphpVersion: SupportedPHPVersion;\n\tfirstProcessId: number;\n\tprocessIdSpaceLength: number;\n\ttrace: boolean;\n\tnativeInternalDirPath: string;\n\tmountsBeforeWpInstall: Array<Mount>;\n\tmountsAfterWpInstall: Array<Mount>;\n\twithXdebug?: boolean;\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\nexport class PlaygroundCliBlueprintV1Worker extends PHPWorker {\n\tbooted = false;\n\tfileLockManager: RemoteAPI<FileLockManager> | 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\tif (await jspi()) {\n\t\t\t/**\n\t\t\t * If JSPI is available, php.js supports both synchronous and asynchronous locking syscalls.\n\t\t\t * Web browsers, however, only support asynchronous message passing so let's use the\n\t\t\t * asynchronous API. Every method call will return a promise.\n\t\t\t *\n\t\t\t * @see comlink-sync.ts\n\t\t\t * @see phpwasm-emscripten-library-file-locking-for-node.js\n\t\t\t */\n\t\t\tthis.fileLockManager = consumeAPI<FileLockManager>(port);\n\t\t} else {\n\t\t\t/**\n\t\t\t * If JSPI is not available, php.js only supports synchronous locking syscalls.\n\t\t\t * Let's use the synchronous API. Every method call will block this thread\n\t\t\t * until the result is available.\n\t\t\t *\n\t\t\t * @see comlink-sync.ts\n\t\t\t * @see phpwasm-emscripten-library-file-locking-for-node.js\n\t\t\t */\n\t\t\tthis.fileLockManager = await consumeAPISync<FileLockManager>(port);\n\t\t}\n\t}\n\n\tasync bootAndSetUpInitialWorker({\n\t\tsiteUrl,\n\t\tmountsBeforeWpInstall,\n\t\tmountsAfterWpInstall,\n\t\tphpVersion: php = RecommendedPHPVersion,\n\t\twordpressInstallMode,\n\t\twordPressZip,\n\t\tsqliteIntegrationPluginZip,\n\t\tfirstProcessId,\n\t\tprocessIdSpaceLength,\n\t\tdataSqlPath,\n\t\tfollowSymlinks,\n\t\ttrace,\n\t\tinternalCookieStore,\n\t\twithXdebug,\n\t\tnativeInternalDirPath,\n\t}: PrimaryWorkerBootOptions) {\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\tlet nextProcessId = firstProcessId;\n\t\tconst lastProcessId = firstProcessId + processIdSpaceLength - 1;\n\n\t\ttry {\n\t\t\tconst constants: Record<string, string | number | boolean | null> =\n\t\t\t\t{\n\t\t\t\t\tWP_DEBUG: true,\n\t\t\t\t\tWP_DEBUG_LOG: true,\n\t\t\t\t\tWP_DEBUG_DISPLAY: false,\n\t\t\t\t};\n\t\t\tlet wordpressBooted = false;\n\t\t\tconst requestHandler = await bootWordPressAndRequestHandler({\n\t\t\t\tsiteUrl,\n\t\t\t\tcreatePhpRuntime: async () => {\n\t\t\t\t\tconst processId = nextProcessId;\n\n\t\t\t\t\tif (nextProcessId < lastProcessId) {\n\t\t\t\t\t\tnextProcessId++;\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// We've reached the end of the process ID space. Start over.\n\t\t\t\t\t\tnextProcessId = firstProcessId;\n\t\t\t\t\t}\n\n\t\t\t\t\treturn await loadNodeRuntime(php, {\n\t\t\t\t\t\temscriptenOptions: {\n\t\t\t\t\t\t\tfileLockManager: this.fileLockManager!,\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\tphpWasmInitOptions: { nativeInternalDirPath },\n\t\t\t\t\t\t},\n\t\t\t\t\t\tfollowSymlinks,\n\t\t\t\t\t\twithXdebug,\n\t\t\t\t\t});\n\t\t\t\t},\n\t\t\t\twordpressInstallMode,\n\t\t\t\twordPressZip:\n\t\t\t\t\twordPressZip !== undefined\n\t\t\t\t\t\t? new File([wordPressZip], 'wordpress.zip')\n\t\t\t\t\t\t: undefined,\n\t\t\t\tsqliteIntegrationPluginZip:\n\t\t\t\t\tsqliteIntegrationPluginZip !== undefined\n\t\t\t\t\t\t? new File(\n\t\t\t\t\t\t\t\t[sqliteIntegrationPluginZip],\n\t\t\t\t\t\t\t\t'sqlite-integration-plugin.zip'\n\t\t\t\t\t\t )\n\t\t\t\t\t\t: undefined,\n\t\t\t\tsapiName: 'cli',\n\t\t\t\tcreateFiles: {\n\t\t\t\t\t'/internal/shared/ca-bundle.crt':\n\t\t\t\t\t\trootCertificates.join('\\n'),\n\t\t\t\t},\n\t\t\t\tconstants,\n\t\t\t\tphpIniEntries: {\n\t\t\t\t\t'openssl.cafile': '/internal/shared/ca-bundle.crt',\n\t\t\t\t\tallow_url_fopen: '1',\n\t\t\t\t\tdisable_functions: '',\n\t\t\t\t},\n\t\t\t\tcookieStore: internalCookieStore ? undefined : false,\n\t\t\t\tdataSqlPath,\n\t\t\t\tspawnHandler: sandboxedSpawnHandlerFactory,\n\t\t\t\tasync onPHPInstanceCreated(php) {\n\t\t\t\t\tawait mountResources(php, mountsBeforeWpInstall);\n\t\t\t\t\tif (wordpressBooted) {\n\t\t\t\t\t\tawait mountResources(php, mountsAfterWpInstall);\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t});\n\t\t\tthis.__internal_setRequestHandler(requestHandler);\n\t\t\twordpressBooted = true;\n\n\t\t\tconst primaryPhp = await requestHandler.getPrimaryPhp();\n\t\t\tawait this.setPrimaryPHP(primaryPhp);\n\n\t\t\t// The primary PHP instance is persistent, so we need to apply\n\t\t\t// post-install mounts now that WordPress has been booted.\n\t\t\t// All secondary PHP instances created after WP boot will get\n\t\t\t// these mounts automatically.\n\t\t\tawait mountResources(primaryPhp, mountsAfterWpInstall);\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 bootWorker(args: WorkerBootOptions) {\n\t\tawait this.bootRequestHandler(args);\n\t}\n\n\tasync bootRequestHandler({\n\t\tsiteUrl,\n\t\tfollowSymlinks,\n\t\tphpVersion,\n\t\tfirstProcessId,\n\t\tprocessIdSpaceLength,\n\t\ttrace,\n\t\tnativeInternalDirPath,\n\t\tmountsBeforeWpInstall,\n\t\tmountsAfterWpInstall,\n\t\twithXdebug,\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\tlet nextProcessId = firstProcessId;\n\t\tconst lastProcessId = firstProcessId + processIdSpaceLength - 1;\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\tconst processId = nextProcessId;\n\n\t\t\t\t\tif (nextProcessId < lastProcessId) {\n\t\t\t\t\t\tnextProcessId++;\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// We've reached the end of the process ID space. Start over.\n\t\t\t\t\t\tnextProcessId = firstProcessId;\n\t\t\t\t\t}\n\n\t\t\t\t\treturn await loadNodeRuntime(phpVersion, {\n\t\t\t\t\t\temscriptenOptions: {\n\t\t\t\t\t\t\tfileLockManager: this.fileLockManager!,\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\tphpWasmInitOptions: { nativeInternalDirPath },\n\t\t\t\t\t\t},\n\t\t\t\t\t\tfollowSymlinks,\n\t\t\t\t\t\twithXdebug,\n\t\t\t\t\t});\n\t\t\t\t},\n\t\t\t\tonPHPInstanceCreated: async (php) => {\n\t\t\t\t\tawait mountResources(php, mountsBeforeWpInstall);\n\t\t\t\t\tawait mountResources(php, mountsAfterWpInstall);\n\t\t\t\t},\n\t\t\t\tsapiName: 'cli',\n\t\t\t\tcookieStore: false,\n\t\t\t\tspawnHandler: sandboxedSpawnHandlerFactory,\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\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\nprocess.on('unhandledRejection', (e: any) => {\n\tlogger.error('Unhandled rejection:', e);\n});\n\nconst phpChannel = new MessageChannel();\n\nconst [setApiReady, setAPIError] = exposeAPI(\n\tnew PlaygroundCliBlueprintV1Worker(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":["tracePhpWasm","processId","format","args","sprintf","PlaygroundCliBlueprintV1Worker","PHPWorker","monitor","port","jspi","consumeAPI","consumeAPISync","siteUrl","mountsBeforeWpInstall","mountsAfterWpInstall","php","RecommendedPHPVersion","wordpressInstallMode","wordPressZip","sqliteIntegrationPluginZip","firstProcessId","processIdSpaceLength","dataSqlPath","followSymlinks","trace","internalCookieStore","withXdebug","nativeInternalDirPath","nextProcessId","lastProcessId","constants","wordpressBooted","requestHandler","bootWordPressAndRequestHandler","loadNodeRuntime","rootCertificates","sandboxedSpawnHandlerFactory","mountResources","primaryPhp","setApiReady","e","setAPIError","phpVersion","bootRequestHandler","logger","phpChannel","MessageChannel","exposeAPI","EmscriptenDownloadMonitor","parentPort"],"mappings":"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"}
1
+ {"version":3,"file":"worker-thread-v1.js","sources":["../../../../packages/playground/cli/src/blueprints-v1/worker-thread-v1.ts"],"sourcesContent":["import type { FileLockManager } from '@php-wasm/node';\nimport { loadNodeRuntime } from '@php-wasm/node';\nimport { EmscriptenDownloadMonitor } from '@php-wasm/progress';\nimport type { RemoteAPI, SupportedPHPVersion } from '@php-wasm/universal';\nimport {\n\tPHPWorker,\n\tconsumeAPI,\n\tconsumeAPISync,\n\texposeAPI,\n\tsandboxedSpawnHandlerFactory,\n} from '@php-wasm/universal';\nimport { sprintf } from '@php-wasm/util';\nimport { RecommendedPHPVersion } from '@wp-playground/common';\nimport {\n\ttype WordPressInstallMode,\n\tbootRequestHandler,\n\tbootWordPressAndRequestHandler,\n} from '@wp-playground/wordpress';\nimport { rootCertificates } from 'tls';\nimport { jspi } from 'wasm-feature-detect';\nimport { MessageChannel, type MessagePort, parentPort } from 'worker_threads';\nimport { mountResources } from '../mounts';\nimport { logger } from '@php-wasm/logger';\nimport { spawnWorkerThread } from '../run-cli';\n\nimport type { Mount } from '@php-wasm/cli-util';\n\nexport type WorkerBootOptions = {\n\tphpVersion: SupportedPHPVersion;\n\tsiteUrl: string;\n\tmountsBeforeWpInstall: Array<Mount>;\n\tmountsAfterWpInstall: Array<Mount>;\n\tfirstProcessId: number;\n\tprocessIdSpaceLength: number;\n\tfollowSymlinks: boolean;\n\ttrace: boolean;\n\t/**\n\t * When true, Playground will not send cookies to the client but will manage\n\t * them internally. This can be useful in environments that can't store cookies,\n\t * e.g. VS Code WebView.\n\t *\n\t * Default: false.\n\t */\n\tinternalCookieStore?: boolean;\n\twithIntl?: boolean;\n\twithXdebug?: boolean;\n\tnativeInternalDirPath: string;\n};\n\nexport type PrimaryWorkerBootOptions = WorkerBootOptions & {\n\twordpressInstallMode: WordPressInstallMode;\n\twpVersion?: string;\n\twordPressZip?: ArrayBuffer;\n\tsqliteIntegrationPluginZip?: ArrayBuffer;\n\tdataSqlPath?: string;\n};\n\ninterface WorkerBootRequestHandlerOptions {\n\tsiteUrl: string;\n\tfollowSymlinks: boolean;\n\tphpVersion: SupportedPHPVersion;\n\tfirstProcessId: number;\n\tprocessIdSpaceLength: number;\n\ttrace: boolean;\n\tnativeInternalDirPath: string;\n\tmountsBeforeWpInstall: Array<Mount>;\n\tmountsAfterWpInstall: Array<Mount>;\n\twithIntl?: boolean;\n\twithXdebug?: boolean;\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\nexport class PlaygroundCliBlueprintV1Worker extends PHPWorker {\n\tbooted = false;\n\tfileLockManager: RemoteAPI<FileLockManager> | 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\tif (await jspi()) {\n\t\t\t/**\n\t\t\t * If JSPI is available, php.js supports both synchronous and asynchronous locking syscalls.\n\t\t\t * Web browsers, however, only support asynchronous message passing so let's use the\n\t\t\t * asynchronous API. Every method call will return a promise.\n\t\t\t *\n\t\t\t * @see comlink-sync.ts\n\t\t\t * @see phpwasm-emscripten-library-file-locking-for-node.js\n\t\t\t */\n\t\t\tthis.fileLockManager = consumeAPI<FileLockManager>(port);\n\t\t} else {\n\t\t\t/**\n\t\t\t * If JSPI is not available, php.js only supports synchronous locking syscalls.\n\t\t\t * Let's use the synchronous API. Every method call will block this thread\n\t\t\t * until the result is available.\n\t\t\t *\n\t\t\t * @see comlink-sync.ts\n\t\t\t * @see phpwasm-emscripten-library-file-locking-for-node.js\n\t\t\t */\n\t\t\tthis.fileLockManager = await consumeAPISync<FileLockManager>(port);\n\t\t}\n\t}\n\n\tasync bootAndSetUpInitialWorker(options: PrimaryWorkerBootOptions) {\n\t\tconst {\n\t\t\tsiteUrl,\n\t\t\tmountsBeforeWpInstall,\n\t\t\tmountsAfterWpInstall,\n\t\t\twordpressInstallMode,\n\t\t\twordPressZip,\n\t\t\tsqliteIntegrationPluginZip,\n\t\t\tdataSqlPath,\n\t\t\tinternalCookieStore,\n\t\t} = options;\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 constants: Record<string, string | number | boolean | null> =\n\t\t\t\t{\n\t\t\t\t\tWP_DEBUG: true,\n\t\t\t\t\tWP_DEBUG_LOG: true,\n\t\t\t\t\tWP_DEBUG_DISPLAY: false,\n\t\t\t\t};\n\t\t\tlet wordpressBooted = false;\n\t\t\tconst requestHandler = await bootWordPressAndRequestHandler({\n\t\t\t\tsiteUrl,\n\t\t\t\tcreatePhpRuntime: createPhpRuntimeFactory(\n\t\t\t\t\toptions,\n\t\t\t\t\tthis.fileLockManager!\n\t\t\t\t),\n\t\t\t\twordpressInstallMode,\n\t\t\t\twordPressZip:\n\t\t\t\t\twordPressZip !== undefined\n\t\t\t\t\t\t? new File([wordPressZip], 'wordpress.zip')\n\t\t\t\t\t\t: undefined,\n\t\t\t\tsqliteIntegrationPluginZip:\n\t\t\t\t\tsqliteIntegrationPluginZip !== undefined\n\t\t\t\t\t\t? new File(\n\t\t\t\t\t\t\t\t[sqliteIntegrationPluginZip],\n\t\t\t\t\t\t\t\t'sqlite-integration-plugin.zip'\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t: undefined,\n\t\t\t\tsapiName: 'cli',\n\t\t\t\tcreateFiles: {\n\t\t\t\t\t'/internal/shared/ca-bundle.crt':\n\t\t\t\t\t\trootCertificates.join('\\n'),\n\t\t\t\t},\n\t\t\t\tconstants,\n\t\t\t\tphpIniEntries: {\n\t\t\t\t\t'openssl.cafile': '/internal/shared/ca-bundle.crt',\n\t\t\t\t\tallow_url_fopen: '1',\n\t\t\t\t\tdisable_functions: '',\n\t\t\t\t},\n\t\t\t\tcookieStore: internalCookieStore ? undefined : false,\n\t\t\t\tdataSqlPath,\n\t\t\t\tspawnHandler: () =>\n\t\t\t\t\tsandboxedSpawnHandlerFactory(() =>\n\t\t\t\t\t\tcreatePHPWorker(options, this.fileLockManager!)\n\t\t\t\t\t),\n\t\t\t\tasync onPHPInstanceCreated(php) {\n\t\t\t\t\tawait mountResources(php, mountsBeforeWpInstall);\n\t\t\t\t\tif (wordpressBooted) {\n\t\t\t\t\t\tawait mountResources(php, mountsAfterWpInstall);\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t});\n\t\t\tthis.__internal_setRequestHandler(requestHandler);\n\t\t\twordpressBooted = true;\n\n\t\t\tconst primaryPhp = await requestHandler.getPrimaryPhp();\n\t\t\tawait this.setPrimaryPHP(primaryPhp);\n\n\t\t\t// The primary PHP instance is persistent, so we need to apply\n\t\t\t// post-install mounts now that WordPress has been booted.\n\t\t\t// All secondary PHP instances created after WP boot will get\n\t\t\t// these mounts automatically.\n\t\t\tawait mountResources(primaryPhp, mountsAfterWpInstall);\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 hello() {\n\t\treturn 'hello';\n\t}\n\n\tasync bootWorker(args: WorkerBootOptions) {\n\t\tawait this.bootRequestHandler(args);\n\t}\n\n\tasync bootRequestHandler(options: 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: options.siteUrl,\n\t\t\t\tcreatePhpRuntime: createPhpRuntimeFactory(\n\t\t\t\t\toptions,\n\t\t\t\t\tthis.fileLockManager!\n\t\t\t\t),\n\t\t\t\tonPHPInstanceCreated: async (php) => {\n\t\t\t\t\tawait mountResources(php, options.mountsBeforeWpInstall);\n\t\t\t\t\tawait mountResources(php, options.mountsAfterWpInstall);\n\t\t\t\t},\n\t\t\t\tsapiName: 'cli',\n\t\t\t\tcookieStore: false,\n\t\t\t\tspawnHandler: () =>\n\t\t\t\t\tsandboxedSpawnHandlerFactory(() =>\n\t\t\t\t\t\tcreatePHPWorker(options, this.fileLockManager!)\n\t\t\t\t\t),\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\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 * Returns a factory function that starts a new PHP runtime in the currently\n * running process. This is used for rotating the PHP runtime periodically.\n */\nfunction createPhpRuntimeFactory(\n\toptions: WorkerBootRequestHandlerOptions,\n\tfileLockManager: FileLockManager | RemoteAPI<FileLockManager>\n) {\n\tlet nextProcessId = options.firstProcessId;\n\tconst lastProcessId =\n\t\toptions.firstProcessId + options.processIdSpaceLength - 1;\n\treturn async () => {\n\t\tconst processId = nextProcessId;\n\n\t\tif (nextProcessId < lastProcessId) {\n\t\t\tnextProcessId++;\n\t\t} else {\n\t\t\t// We've reached the end of the process ID space. Start over.\n\t\t\tnextProcessId = options.firstProcessId;\n\t\t}\n\n\t\treturn await loadNodeRuntime(\n\t\t\toptions.phpVersion || RecommendedPHPVersion,\n\t\t\t{\n\t\t\t\temscriptenOptions: {\n\t\t\t\t\tfileLockManager,\n\t\t\t\t\tprocessId,\n\t\t\t\t\ttrace: options.trace ? tracePhpWasm : undefined,\n\t\t\t\t\tphpWasmInitOptions: {\n\t\t\t\t\t\tnativeInternalDirPath: options.nativeInternalDirPath,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\tfollowSymlinks: options.followSymlinks,\n\t\t\t\twithIntl: options.withIntl,\n\t\t\t\twithXdebug: options.withXdebug,\n\t\t\t}\n\t\t);\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\toptions: WorkerBootRequestHandlerOptions,\n\tfileLockManager: FileLockManager | RemoteAPI<FileLockManager>\n) {\n\tconst spawnedWorker = await spawnWorkerThread('v1');\n\n\tconst handler = consumeAPI<PlaygroundCliBlueprintV1Worker>(\n\t\tspawnedWorker.phpPort\n\t);\n\thandler.useFileLockManager(fileLockManager as any);\n\tawait handler.bootWorker(options);\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 PlaygroundCliBlueprintV1Worker(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":["tracePhpWasm","processId","format","args","sprintf","PlaygroundCliBlueprintV1Worker","PHPWorker","monitor","port","jspi","consumeAPI","consumeAPISync","options","siteUrl","mountsBeforeWpInstall","mountsAfterWpInstall","wordpressInstallMode","wordPressZip","sqliteIntegrationPluginZip","dataSqlPath","internalCookieStore","constants","wordpressBooted","requestHandler","bootWordPressAndRequestHandler","createPhpRuntimeFactory","rootCertificates","sandboxedSpawnHandlerFactory","createPHPWorker","php","mountResources","primaryPhp","setApiReady","e","setAPIError","bootRequestHandler","fileLockManager","nextProcessId","lastProcessId","loadNodeRuntime","RecommendedPHPVersion","spawnedWorker","spawnWorkerThread","handler","logger","phpChannel","MessageChannel","exposeAPI","EmscriptenDownloadMonitor","parentPort"],"mappings":"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"}
@@ -1,11 +1,15 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const W=require("@php-wasm/logger"),y=require("@php-wasm/node"),x=require("@php-wasm/progress"),u=require("@php-wasm/universal"),k=require("@php-wasm/util"),I=require("@wp-playground/blueprints"),M=require("@wp-playground/wordpress"),_=require("fs"),m=require("path"),$=require("tls"),T=require("worker_threads"),S=require("wasm-feature-detect");async function h(s,e){for(const r of e)try{s.mkdir(r.vfsPath),await s.mount(r.vfsPath,y.createNodeFsMountHandler(r.hostPath))}catch{i.stderr(`\x1B[31m\x1B[1mError mounting path ${r.hostPath} at ${r.vfsPath}\x1B[0m
2
- `),process.exit(1)}}function A(s,e,...r){console.log(performance.now().toFixed(6).padStart(15,"0"),s.toString().padStart(16,"0"),k.sprintf(e,...r))}Object.defineProperty(process.stdout,"isTTY",{value:!0});Object.defineProperty(process.stderr,"isTTY",{value:!0});const i={lastWriteWasProgress:!1,progress(s){process.stdout.isTTY?(i.lastWriteWasProgress||process.stdout.write(`
3
- `),process.stdout.write("\r\x1B[K"+s),i.lastWriteWasProgress=!0):console.log(s)},stdout(s){i.lastWriteWasProgress&&(process.stdout.write(`
4
- `),i.lastWriteWasProgress=!1),process.stdout.write(s)},stderr(s){i.lastWriteWasProgress&&(process.stdout.write(`
5
- `),i.lastWriteWasProgress=!1),process.stderr.write(s)}};class R extends u.PHPWorker{constructor(e){super(void 0,e),this.booted=!1,this.blueprintTargetResolved=!1,this.phpInstancesThatNeedMountsAfterTargetResolved=new Set}async useFileLockManager(e){await S.jspi()?this.fileLockManager=u.consumeAPI(e):this.fileLockManager=await u.consumeAPISync(e)}async bootAndSetUpInitialWorker(e){const r={WP_DEBUG:!0,WP_DEBUG_LOG:!0,WP_DEBUG_DISPLAY:!1},p={...e,createFiles:{"/internal/shared/ca-bundle.crt":$.rootCertificates.join(`
6
- `)},constants:r,phpIniEntries:{"openssl.cafile":"/internal/shared/ca-bundle.crt"},onPHPInstanceCreated:async o=>{await h(o,e["mount-before-install"]||[]),this.blueprintTargetResolved?await h(o,e.mount||[]):(this.phpInstancesThatNeedMountsAfterTargetResolved.add(o),o.addEventListener("runtime.beforeExit",()=>{this.phpInstancesThatNeedMountsAfterTargetResolved.delete(o)}))}};await this.bootRequestHandler(p);const w=this.__internal_getPHP();if(e.mode==="mount-only"){await h(w,e.mount||[]);return}await this.runBlueprintV2(e)}async bootWorker(e){await this.bootRequestHandler({...e,onPHPInstanceCreated:async r=>{await h(r,e.mountsBeforeWpInstall||[]),await h(r,e.mountsAfterWpInstall||[])}})}async runBlueprintV2(e){const r=this.__internal_getRequestHandler(),{php:p,reap:w}=await r.processManager.acquirePHPInstance({considerPrimary:!1}),o=this.__internal_getPHP();let f=()=>{};if(typeof e.blueprint=="string"){const n=m.resolve(process.cwd(),e.blueprint);_.existsSync(n)&&(o.mkdir("/internal/shared/cwd"),f=await o.mount("/internal/shared/cwd",y.createNodeFsMountHandler(m.dirname(n))),e.blueprint=m.join("/internal/shared/cwd",m.basename(e.blueprint)))}try{const l=["mode","db-engine","db-host","db-user","db-pass","db-name","db-path","truncate-new-site-directory","allow"].filter(t=>t in e).map(t=>`--${t}=${e[t]}`);l.push(`--site-url=${e.siteUrl}`);const c=await I.runBlueprintV2({php:p,blueprint:e.blueprint,blueprintOverrides:{additionalSteps:e["additional-blueprint-steps"],wordpressVersion:e.wp},cliArgs:l,onMessage:async t=>{switch(t.type){case"blueprint.target_resolved":{if(!this.blueprintTargetResolved){this.blueprintTargetResolved=!0;for(const a of this.phpInstancesThatNeedMountsAfterTargetResolved)this.phpInstancesThatNeedMountsAfterTargetResolved.delete(a),await h(a,e.mount||[])}break}case"blueprint.progress":{const a=`${t.caption.trim()} – ${t.progress.toFixed(2)}%`;i.progress(a);break}case"blueprint.error":{const a="\x1B[31m",b="\x1B[1m",d="\x1B[0m";e.debug&&t.details?i.stderr(`${a}${b}Fatal error:${d} Uncaught ${t.details.exception}: ${t.details.message}
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const x=require("@php-wasm/logger"),g=require("@php-wasm/node"),M=require("@php-wasm/progress"),p=require("@php-wasm/universal"),$=require("@php-wasm/util"),S=require("@wp-playground/blueprints"),_=require("@wp-playground/wordpress"),B=require("fs"),W=require("path"),F=require("tls"),I=require("worker_threads"),E=require("wasm-feature-detect"),H=require("./run-cli-D8BNUM1f.cjs");async function b(s,e){for(const r of e)try{s.mkdir(r.vfsPath),await s.mount(r.vfsPath,g.createNodeFsMountHandler(r.hostPath))}catch{i.stderr(`\x1B[31m\x1B[1mError mounting path ${r.hostPath} at ${r.vfsPath}\x1B[0m
2
+ `),process.exit(1)}}function L(s,e,...r){console.log(performance.now().toFixed(6).padStart(15,"0"),s.toString().padStart(16,"0"),$.sprintf(e,...r))}Object.defineProperty(process.stdout,"isTTY",{value:!0});Object.defineProperty(process.stderr,"isTTY",{value:!0});const i={lastWriteWasProgress:!1,progress(s){H.shouldRenderProgress(process.stdout)&&(process.stdout.isTTY?(i.lastWriteWasProgress||process.stdout.write(`
3
+ `),process.stdout.write("\r\x1B[K"+s),i.lastWriteWasProgress=!0):console.log(s))},stdout(s){process.stdout.write(`
4
+
5
+
6
+ `),i.lastWriteWasProgress&&(i.lastWriteWasProgress=!1),process.stdout.write(s)},stderr(s){process.stdout.write(`
7
+
8
+
9
+ `),i.lastWriteWasProgress&&(i.lastWriteWasProgress=!1),process.stderr.write(s)}};class R extends p.PHPWorker{constructor(e){super(void 0,e),this.booted=!1,this.blueprintTargetResolved=!1,this.phpInstancesThatNeedMountsAfterTargetResolved=new Set}async useFileLockManager(e){await E.jspi()?this.fileLockManager=p.consumeAPI(e):this.fileLockManager=await p.consumeAPISync(e)}async bootAndSetUpInitialWorker(e){const r={WP_DEBUG:!0,WP_DEBUG_LOG:!0,WP_DEBUG_DISPLAY:!1},u={...e,createFiles:{"/internal/shared/ca-bundle.crt":F.rootCertificates.join(`
10
+ `)},constants:r,phpIniEntries:{"openssl.cafile":"/internal/shared/ca-bundle.crt"},onPHPInstanceCreated:async n=>{await b(n,e.mountsBeforeWpInstall||[]),this.blueprintTargetResolved?await b(n,e.mountsAfterWpInstall||[]):(this.phpInstancesThatNeedMountsAfterTargetResolved.add(n),n.addEventListener("runtime.beforeExit",()=>{this.phpInstancesThatNeedMountsAfterTargetResolved.delete(n)}))},spawnHandler:()=>p.sandboxedSpawnHandlerFactory(()=>T(e,this.fileLockManager))};await this.bootRequestHandler(u);const w=this.__internal_getPHP();if(e.mode==="mount-only"){await b(w,e.mountsAfterWpInstall||[]);return}await this.runBlueprintV2({...e,mountsAfterWpInstall:e.mountsAfterWpInstall||[]})}async bootWorker(e){await this.bootRequestHandler({...e,onPHPInstanceCreated:async r=>{await b(r,e.mountsBeforeWpInstall||[]),await b(r,e.mountsAfterWpInstall||[]),r.isDir("/wordpress/wp-content")||r.mkdir("/wordpress/wp-content"),r.isDir("/wordpress/wp-content/database")||r.mkdir("/wordpress/wp-content/database"),r.isFile("/wordpress/wp-content/database/.htaccess")||r.writeFile("/wordpress/wp-content/database/.htaccess","deny from all"),r.isFile("/wordpress/wp-content/database/index.php")||r.writeFile("/wordpress/wp-content/database/index.php","deny from all")},spawnHandler:()=>p.sandboxedSpawnHandlerFactory(()=>T(e,this.fileLockManager))})}async runBlueprintV2(e){const r=this.__internal_getRequestHandler(),{php:u,reap:w}=await r.instanceManager.acquirePHPInstance({considerPrimary:!1}),n=this.__internal_getPHP();let h=()=>{};if(typeof e.blueprint=="string"){const o=W.resolve(process.cwd(),e.blueprint);B.existsSync(o)&&(n.mkdir("/internal/shared/cwd"),h=await n.mount("/internal/shared/cwd",g.createNodeFsMountHandler(W.dirname(o))),e.blueprint=W.join("/internal/shared/cwd",W.basename(e.blueprint)))}try{const l=["mode","db-engine","db-host","db-user","db-pass","db-name","db-path","truncate-new-site-directory","allow"].filter(t=>t in e).map(t=>`--${t}=${e[t]}`);l.push(`--site-url=${e.siteUrl}`);const c=await S.runBlueprintV2({php:u,blueprint:e.blueprint,blueprintOverrides:{additionalSteps:e["additional-blueprint-steps"],wordpressVersion:e.wp},cliArgs:l,onMessage:async t=>{switch(t.type){case"blueprint.target_resolved":{if(!this.blueprintTargetResolved){this.blueprintTargetResolved=!0;for(const a of this.phpInstancesThatNeedMountsAfterTargetResolved)this.phpInstancesThatNeedMountsAfterTargetResolved.delete(a),await b(a,e.mountsAfterWpInstall||[])}break}case"blueprint.progress":{const a=`${t.caption.trim()} – ${t.progress.toFixed(2)}%`;i.progress(a);break}case"blueprint.error":{const a="\x1B[31m",f="\x1B[1m",P="\x1B[0m";e.debug&&t.details?i.stderr(`${a}${f}Fatal error:${P} Uncaught ${t.details.exception}: ${t.details.message}
7
11
  at ${t.details.file}:${t.details.line}
8
12
  `+(t.details.trace?t.details.trace+`
9
- `:"")):i.stderr(`${a}${b}Error:${d} ${t.message}
10
- `);break}}}});if(e.debug&&(c.stdout.pipeTo(new WritableStream({write(t){process.stdout.write(t)}})),c.stderr.pipeTo(new WritableStream({write(t){process.stderr.write(t)}}))),await c.finished,await c.exitCode!==0){const t=await u.PHPResponse.fromStreamedResponse(c);throw new u.PHPExecutionFailureError(`PHP.run() failed with exit code ${t.exitCode}.`,t,"request")}}catch(n){let l="";try{l=p.readFileAsText(W.errorLogPath)}catch{}throw n.phpLogs=l,n}finally{w(),f()}}async bootRequestHandler({siteUrl:e,allow:r,phpVersion:p,createFiles:w,constants:o,phpIniEntries:f,firstProcessId:n,processIdSpaceLength:l,trace:c,nativeInternalDirPath:t,withXdebug:a,onPHPInstanceCreated:b}){if(this.booted)throw new Error("Playground already booted");this.booted=!0;let d=n;const q=n+l-1;try{const P=await M.bootRequestHandler({siteUrl:e,createPhpRuntime:async()=>{const H=d;return d<q?d++:d=n,await y.loadNodeRuntime(p,{emscriptenOptions:{fileLockManager:this.fileLockManager,processId:H,trace:c?A:void 0,ENV:{DOCROOT:"/wordpress"},phpWasmInitOptions:{nativeInternalDirPath:t}},followSymlinks:r?.includes("follow-symlinks"),withXdebug:a})},onPHPInstanceCreated:b,sapiName:"cli",createFiles:w,constants:o,phpIniEntries:f,cookieStore:!1,spawnHandler:u.sandboxedSpawnHandlerFactory});this.__internal_setRequestHandler(P);const v=await P.getPrimaryPhp();await this.setPrimaryPHP(v),B()}catch(P){throw E(P),P}}async dispose(){await this[Symbol.asyncDispose]()}}process.on("unhandledRejection",s=>{W.logger.error("Unhandled rejection:",s)});const g=new T.MessageChannel,[B,E]=u.exposeAPI(new R(new x.EmscriptenDownloadMonitor),void 0,g.port1);T.parentPort?.postMessage({command:"worker-script-initialized",phpPort:g.port2},[g.port2]);exports.PlaygroundCliBlueprintV2Worker=R;
13
+ `:"")):i.stderr(`${a}${f}Error:${P} ${t.message}
14
+ `);break}}}});if(e.debug&&(c.stdout.pipeTo(new WritableStream({write(t){process.stdout.write(t)}})),c.stderr.pipeTo(new WritableStream({write(t){process.stderr.write(t)}}))),await c.finished,await c.exitCode!==0){const t=await p.PHPResponse.fromStreamedResponse(c);throw new p.PHPExecutionFailureError(`PHP.run() failed with exit code ${t.exitCode}. ${t.errors} ${t.text}`,t,"request")}}catch(o){let l="";try{l=u.readFileAsText(x.errorLogPath)}catch{}throw o.phpLogs=l,o}finally{w(),h()}}async bootRequestHandler({siteUrl:e,allow:r,phpVersion:u,createFiles:w,constants:n,phpIniEntries:h,firstProcessId:o,processIdSpaceLength:l,trace:c,nativeInternalDirPath:t,withIntl:a,withXdebug:f,onPHPInstanceCreated:P,spawnHandler:y}){if(this.booted)throw new Error("Playground already booted");this.booted=!0;let d=o;const q=o+l-1;try{const m=await _.bootRequestHandler({siteUrl:e,createPhpRuntime:async()=>{const A=d;return d<q?d++:d=o,await g.loadNodeRuntime(u,{emscriptenOptions:{fileLockManager:this.fileLockManager,processId:A,trace:c?L:void 0,ENV:{DOCROOT:"/wordpress"},phpWasmInitOptions:{nativeInternalDirPath:t}},followSymlinks:r?.includes("follow-symlinks"),withIntl:a,withXdebug:f})},maxPhpInstances:1,onPHPInstanceCreated:P,sapiName:"cli",createFiles:w,constants:n,phpIniEntries:h,cookieStore:!1,spawnHandler:y});this.__internal_setRequestHandler(m);const v=await m.getPrimaryPhp();await this.setPrimaryPHP(v),C()}catch(m){throw O(m),m}}async dispose(){await this[Symbol.asyncDispose]()}}async function T({siteUrl:s,allow:e,phpVersion:r,createFiles:u,constants:w,phpIniEntries:n,firstProcessId:h,processIdSpaceLength:o,trace:l,nativeInternalDirPath:c,withXdebug:t,mountsBeforeWpInstall:a,mountsAfterWpInstall:f},P){const y=await H.spawnWorkerThread("v2"),d=p.consumeAPI(y.phpPort);return d.useFileLockManager(P),await d.bootWorker({siteUrl:s,allow:e,phpVersion:r,createFiles:u,constants:w,phpIniEntries:n,firstProcessId:h,processIdSpaceLength:o,trace:l,nativeInternalDirPath:c,withXdebug:t,mountsBeforeWpInstall:a,mountsAfterWpInstall:f}),{php:d,reap:()=>{try{d.dispose()}catch{}try{y.worker.terminate()}catch{}}}}process.on("unhandledRejection",s=>{x.logger.error("Unhandled rejection:",s)});const k=new I.MessageChannel,[C,O]=p.exposeAPI(new R(new M.EmscriptenDownloadMonitor),void 0,k.port1);I.parentPort?.postMessage({command:"worker-script-initialized",phpPort:k.port2},[k.port2]);exports.PlaygroundCliBlueprintV2Worker=R;
11
15
  //# sourceMappingURL=worker-thread-v2.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"worker-thread-v2.cjs","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/node';\nimport { createNodeFsMountHandler, loadNodeRuntime } from '@php-wasm/node';\nimport { EmscriptenDownloadMonitor } from '@php-wasm/progress';\nimport type {\n\tPHP,\n\tFileTree,\n\tRemoteAPI,\n\tSupportedPHPVersion,\n} from '@php-wasm/universal';\nimport {\n\tPHPExecutionFailureError,\n\tPHPResponse,\n\tPHPWorker,\n\tconsumeAPI,\n\tconsumeAPISync,\n\texposeAPI,\n\tsandboxedSpawnHandlerFactory,\n} from '@php-wasm/universal';\nimport { 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 { bootRequestHandler } 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 { Mount } from '../mounts';\nimport { jspi } from 'wasm-feature-detect';\nimport { type RunCLIArgs } from '../run-cli';\nimport type {\n\tPhpIniOptions,\n\tPHPInstanceCreatedHook,\n} from '@wp-playground/wordpress';\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 *\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 (!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\tif (output.lastWriteWasProgress) {\n\t\t\tprocess.stdout.write('\\n');\n\t\t\toutput.lastWriteWasProgress = false;\n\t\t}\n\t\tprocess.stdout.write(data);\n\t},\n\tstderr(data: string) {\n\t\tif (output.lastWriteWasProgress) {\n\t\t\tprocess.stdout.write('\\n');\n\t\t\toutput.lastWriteWasProgress = false;\n\t\t}\n\t\tprocess.stderr.write(data);\n\t},\n};\n\nexport type PrimaryWorkerBootArgs = RunCLIArgs & {\n\tphpVersion: SupportedPHPVersion;\n\tsiteUrl: string;\n\tfirstProcessId: number;\n\tprocessIdSpaceLength: number;\n\ttrace: boolean;\n\tblueprint:\n\t\t| RawBlueprintV2Data\n\t\t| ParsedBlueprintV2String\n\t\t| BlueprintV1Declaration;\n\tnativeInternalDirPath: string;\n};\n\ntype WorkerRunBlueprintArgs = RunCLIArgs & {\n\tsiteUrl: string;\n\tblueprint:\n\t\t| RawBlueprintV2Data\n\t\t| ParsedBlueprintV2String\n\t\t| BlueprintV1Declaration;\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\tfirstProcessId: number;\n\tprocessIdSpaceLength: number;\n\ttrace: boolean;\n\tnativeInternalDirPath: string;\n\twithXdebug?: boolean;\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};\n\nexport class PlaygroundCliBlueprintV2Worker extends PHPWorker {\n\tbooted = false;\n\tblueprintTargetResolved = false;\n\tphpInstancesThatNeedMountsAfterTargetResolved = new Set<PHP>();\n\tfileLockManager: RemoteAPI<FileLockManager> | 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\tif (await jspi()) {\n\t\t\t/**\n\t\t\t * If JSPI is available, php.js supports both synchronous and asynchronous locking syscalls.\n\t\t\t * Web browsers, however, only support asynchronous message passing so let's use the\n\t\t\t * asynchronous API. Every method call will return a promise.\n\t\t\t *\n\t\t\t * @see comlink-sync.ts\n\t\t\t * @see phpwasm-emscripten-library-file-locking-for-node.js\n\t\t\t */\n\t\t\tthis.fileLockManager = consumeAPI<FileLockManager>(port);\n\t\t} else {\n\t\t\t/**\n\t\t\t * If JSPI is not available, php.js only supports synchronous locking syscalls.\n\t\t\t * Let's use the synchronous API. Every method call will block this thread\n\t\t\t * until the result is available.\n\t\t\t *\n\t\t\t * @see comlink-sync.ts\n\t\t\t * @see phpwasm-emscripten-library-file-locking-for-node.js\n\t\t\t */\n\t\t\tthis.fileLockManager = await consumeAPISync<FileLockManager>(port);\n\t\t}\n\t}\n\n\tasync bootAndSetUpInitialWorker(args: PrimaryWorkerBootArgs) {\n\t\tconst constants = {\n\t\t\tWP_DEBUG: true,\n\t\t\tWP_DEBUG_LOG: true,\n\t\t\tWP_DEBUG_DISPLAY: false,\n\t\t};\n\t\tconst requestHandlerOptions: WorkerBootRequestHandlerOptions = {\n\t\t\t...args,\n\t\t\tcreateFiles: {\n\t\t\t\t'/internal/shared/ca-bundle.crt': rootCertificates.join('\\n'),\n\t\t\t},\n\t\t\tconstants,\n\t\t\tphpIniEntries: {\n\t\t\t\t'openssl.cafile': '/internal/shared/ca-bundle.crt',\n\t\t\t},\n\t\t\tonPHPInstanceCreated: async (php: PHP) => {\n\t\t\t\tawait mountResources(php, args['mount-before-install'] || []);\n\t\t\t\tif (this.blueprintTargetResolved) {\n\t\t\t\t\tawait mountResources(php, args.mount || []);\n\t\t\t\t} else {\n\t\t\t\t\t// NOTE: Today (2025-09-11), during boot with a plugin auto-mount,\n\t\t\t\t\t// the Blueprint runner fails unless post-resolution mounts are\n\t\t\t\t\t// added to existing PHP instances. So we track them here so they\n\t\t\t\t\t// can be mounted at the necessary time.\n\t\t\t\t\t// Only plugin auto-mounts seem to need this, so perhaps there\n\t\t\t\t\t// is a change we can make to the Blueprint runner so such\n\t\t\t\t\t// a dance is unnecessary.\n\t\t\t\t\tthis.phpInstancesThatNeedMountsAfterTargetResolved.add(php);\n\t\t\t\t\tphp.addEventListener('runtime.beforeExit', () => {\n\t\t\t\t\t\tthis.phpInstancesThatNeedMountsAfterTargetResolved.delete(\n\t\t\t\t\t\t\tphp\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};\n\t\tawait this.bootRequestHandler(requestHandlerOptions);\n\n\t\tconst primaryPhp = this.__internal_getPHP()!;\n\n\t\tif (args.mode === 'mount-only') {\n\t\t\tawait mountResources(primaryPhp, args.mount || []);\n\t\t\treturn;\n\t\t}\n\n\t\tawait this.runBlueprintV2(args);\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\t\t\t},\n\t\t});\n\t}\n\n\tasync runBlueprintV2(args: WorkerRunBlueprintArgs) {\n\t\tconst requestHandler = this.__internal_getRequestHandler()!;\n\t\tconst { php, reap } =\n\t\t\tawait requestHandler.processManager.acquirePHPInstance({\n\t\t\t\tconsiderPrimary: false,\n\t\t\t});\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\tfor (const php of this\n\t\t\t\t\t\t\t\t\t.phpInstancesThatNeedMountsAfterTargetResolved) {\n\t\t\t\t\t\t\t\t\t// console.log('mounting resources for php', php);\n\t\t\t\t\t\t\t\t\tthis.phpInstancesThatNeedMountsAfterTargetResolved.delete(\n\t\t\t\t\t\t\t\t\t\tphp\n\t\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\t\tawait mountResources(php, args.mount || []);\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.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.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 = await PHPResponse.fromStreamedResponse(\n\t\t\t\t\tstreamedResponse\n\t\t\t\t);\n\t\t\t\tthrow new PHPExecutionFailureError(\n\t\t\t\t\t`PHP.run() failed with exit code ${syncResponse.exitCode}.`,\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\tcreateFiles,\n\t\tconstants,\n\t\tphpIniEntries,\n\t\tfirstProcessId,\n\t\tprocessIdSpaceLength,\n\t\ttrace,\n\t\tnativeInternalDirPath,\n\t\twithXdebug,\n\t\tonPHPInstanceCreated,\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\tlet nextProcessId = firstProcessId;\n\t\tconst lastProcessId = firstProcessId + processIdSpaceLength - 1;\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\tconst processId = nextProcessId;\n\n\t\t\t\t\tif (nextProcessId < lastProcessId) {\n\t\t\t\t\t\tnextProcessId++;\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// We've reached the end of the process ID space. Start over.\n\t\t\t\t\t\tnextProcessId = firstProcessId;\n\t\t\t\t\t}\n\n\t\t\t\t\treturn await loadNodeRuntime(phpVersion, {\n\t\t\t\t\t\temscriptenOptions: {\n\t\t\t\t\t\t\tfileLockManager: this.fileLockManager!,\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\tphpWasmInitOptions: { nativeInternalDirPath },\n\t\t\t\t\t\t},\n\t\t\t\t\t\tfollowSymlinks: allow?.includes('follow-symlinks'),\n\t\t\t\t\t\twithXdebug,\n\t\t\t\t\t});\n\t\t\t\t},\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\tcookieStore: false,\n\t\t\t\tspawnHandler: sandboxedSpawnHandlerFactory,\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\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\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","PlaygroundCliBlueprintV2Worker","PHPWorker","monitor","port","jspi","consumeAPI","consumeAPISync","constants","requestHandlerOptions","rootCertificates","primaryPhp","requestHandler","reap","unmountCwd","blueprintPath","path","existsSync","cliArgs","arg","streamedResponse","runBlueprintV2","message","progressMessage","red","bold","reset","chunk","syncResponse","PHPResponse","PHPExecutionFailureError","error","phpLogs","errorLogPath","siteUrl","allow","phpVersion","createFiles","phpIniEntries","firstProcessId","processIdSpaceLength","trace","nativeInternalDirPath","withXdebug","onPHPInstanceCreated","nextProcessId","lastProcessId","bootRequestHandler","loadNodeRuntime","sandboxedSpawnHandlerFactory","setApiReady","e","setAPIError","logger","phpChannel","MessageChannel","exposeAPI","EmscriptenDownloadMonitor","parentPort"],"mappings":"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"}
1
+ {"version":3,"file":"worker-thread-v2.cjs","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/node';\nimport { createNodeFsMountHandler, loadNodeRuntime } from '@php-wasm/node';\nimport { EmscriptenDownloadMonitor } from '@php-wasm/progress';\nimport type {\n\tPHP,\n\tFileTree,\n\tRemoteAPI,\n\tSupportedPHPVersion,\n\tSpawnHandler,\n} from '@php-wasm/universal';\nimport {\n\tPHPExecutionFailureError,\n\tPHPResponse,\n\tPHPWorker,\n\tconsumeAPI,\n\tconsumeAPISync,\n\texposeAPI,\n\tsandboxedSpawnHandlerFactory,\n} from '@php-wasm/universal';\nimport { 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 { bootRequestHandler } 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 { jspi } from 'wasm-feature-detect';\nimport { spawnWorkerThread, type RunCLIArgs } 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 PrimaryWorkerBootArgs = Omit<\n\tRunCLIArgs,\n\t'mount-before-install' | 'mount'\n> & {\n\tphpVersion: SupportedPHPVersion;\n\tsiteUrl: string;\n\tfirstProcessId: number;\n\tprocessIdSpaceLength: number;\n\ttrace: boolean;\n\tblueprint:\n\t\t| RawBlueprintV2Data\n\t\t| ParsedBlueprintV2String\n\t\t| BlueprintV1Declaration;\n\tnativeInternalDirPath: string;\n\tmountsBeforeWpInstall?: Array<Mount>;\n\tmountsAfterWpInstall?: Array<Mount>;\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\tfirstProcessId: number;\n\tprocessIdSpaceLength: number;\n\ttrace: boolean;\n\tnativeInternalDirPath: string;\n\twithIntl?: boolean;\n\twithXdebug?: boolean;\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: RemoteAPI<FileLockManager> | 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\tif (await jspi()) {\n\t\t\t/**\n\t\t\t * If JSPI is available, php.js supports both synchronous and asynchronous locking syscalls.\n\t\t\t * Web browsers, however, only support asynchronous message passing so let's use the\n\t\t\t * asynchronous API. Every method call will return a promise.\n\t\t\t *\n\t\t\t * @see comlink-sync.ts\n\t\t\t * @see phpwasm-emscripten-library-file-locking-for-node.js\n\t\t\t */\n\t\t\tthis.fileLockManager = consumeAPI<FileLockManager>(port);\n\t\t} else {\n\t\t\t/**\n\t\t\t * If JSPI is not available, php.js only supports synchronous locking syscalls.\n\t\t\t * Let's use the synchronous API. Every method call will block this thread\n\t\t\t * until the result is available.\n\t\t\t *\n\t\t\t * @see comlink-sync.ts\n\t\t\t * @see phpwasm-emscripten-library-file-locking-for-node.js\n\t\t\t */\n\t\t\tthis.fileLockManager = await consumeAPISync<FileLockManager>(port);\n\t\t}\n\t}\n\n\tasync bootAndSetUpInitialWorker(args: PrimaryWorkerBootArgs) {\n\t\tconst constants = {\n\t\t\tWP_DEBUG: true,\n\t\t\tWP_DEBUG_LOG: true,\n\t\t\tWP_DEBUG_DISPLAY: false,\n\t\t};\n\t\tconst requestHandlerOptions: WorkerBootRequestHandlerOptions = {\n\t\t\t...args,\n\t\t\tcreateFiles: {\n\t\t\t\t'/internal/shared/ca-bundle.crt': rootCertificates.join('\\n'),\n\t\t\t},\n\t\t\tconstants,\n\t\t\tphpIniEntries: {\n\t\t\t\t'openssl.cafile': '/internal/shared/ca-bundle.crt',\n\t\t\t},\n\t\t\tonPHPInstanceCreated: async (php: PHP) => {\n\t\t\t\tawait mountResources(php, args.mountsBeforeWpInstall || []);\n\t\t\t\tif (this.blueprintTargetResolved) {\n\t\t\t\t\tawait mountResources(php, args.mountsAfterWpInstall || []);\n\t\t\t\t} else {\n\t\t\t\t\t// NOTE: Today (2025-09-11), during boot with a plugin auto-mount,\n\t\t\t\t\t// the Blueprint runner fails unless post-resolution mounts are\n\t\t\t\t\t// added to existing PHP instances. So we track them here so they\n\t\t\t\t\t// can be mounted at the necessary time.\n\t\t\t\t\t// Only plugin auto-mounts seem to need this, so perhaps there\n\t\t\t\t\t// is a change we can make to the Blueprint runner so such\n\t\t\t\t\t// a dance is unnecessary.\n\t\t\t\t\tthis.phpInstancesThatNeedMountsAfterTargetResolved.add(php);\n\t\t\t\t\tphp.addEventListener('runtime.beforeExit', () => {\n\t\t\t\t\t\tthis.phpInstancesThatNeedMountsAfterTargetResolved.delete(\n\t\t\t\t\t\t\tphp\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\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\tawait this.bootRequestHandler(requestHandlerOptions);\n\n\t\tconst primaryPhp = this.__internal_getPHP()!;\n\n\t\tif (args.mode === 'mount-only') {\n\t\t\tawait mountResources(primaryPhp, args.mountsAfterWpInstall || []);\n\t\t\treturn;\n\t\t}\n\n\t\tawait this.runBlueprintV2({\n\t\t\t...args,\n\t\t\tmountsAfterWpInstall: args.mountsAfterWpInstall || [],\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(args: WorkerRunBlueprintArgs) {\n\t\tconst requestHandler = this.__internal_getRequestHandler()!;\n\t\tconst { php, reap } =\n\t\t\tawait requestHandler.instanceManager.acquirePHPInstance({\n\t\t\t\tconsiderPrimary: false,\n\t\t\t});\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\tfor (const php of this\n\t\t\t\t\t\t\t\t\t.phpInstancesThatNeedMountsAfterTargetResolved) {\n\t\t\t\t\t\t\t\t\t// console.log('mounting resources for php', php);\n\t\t\t\t\t\t\t\t\tthis.phpInstancesThatNeedMountsAfterTargetResolved.delete(\n\t\t\t\t\t\t\t\t\t\tphp\n\t\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\t\tawait mountResources(\n\t\t\t\t\t\t\t\t\t\tphp,\n\t\t\t\t\t\t\t\t\t\targs.mountsAfterWpInstall || []\n\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}\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.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.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\tcreateFiles,\n\t\tconstants,\n\t\tphpIniEntries,\n\t\tfirstProcessId,\n\t\tprocessIdSpaceLength,\n\t\ttrace,\n\t\tnativeInternalDirPath,\n\t\twithIntl,\n\t\twithXdebug,\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\tlet nextProcessId = firstProcessId;\n\t\tconst lastProcessId = firstProcessId + processIdSpaceLength - 1;\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\tconst processId = nextProcessId;\n\n\t\t\t\t\tif (nextProcessId < lastProcessId) {\n\t\t\t\t\t\tnextProcessId++;\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// We've reached the end of the process ID space. Start over.\n\t\t\t\t\t\tnextProcessId = firstProcessId;\n\t\t\t\t\t}\n\n\t\t\t\t\treturn await loadNodeRuntime(phpVersion, {\n\t\t\t\t\t\temscriptenOptions: {\n\t\t\t\t\t\t\tfileLockManager: this.fileLockManager!,\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\tphpWasmInitOptions: { nativeInternalDirPath },\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\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\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\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\tfirstProcessId,\n\t\tprocessIdSpaceLength,\n\t\ttrace,\n\t\tnativeInternalDirPath,\n\t\twithXdebug,\n\t\tmountsBeforeWpInstall,\n\t\tmountsAfterWpInstall,\n\t}: SecondaryWorkerBootArgs,\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\tfirstProcessId,\n\t\tprocessIdSpaceLength,\n\t\ttrace,\n\t\tnativeInternalDirPath,\n\t\twithXdebug,\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","jspi","consumeAPI","consumeAPISync","constants","requestHandlerOptions","rootCertificates","sandboxedSpawnHandlerFactory","createPHPWorker","primaryPhp","requestHandler","reap","unmountCwd","blueprintPath","path","existsSync","cliArgs","arg","streamedResponse","runBlueprintV2","message","progressMessage","red","bold","reset","chunk","syncResponse","PHPResponse","PHPExecutionFailureError","error","phpLogs","errorLogPath","siteUrl","allow","phpVersion","createFiles","phpIniEntries","firstProcessId","processIdSpaceLength","trace","nativeInternalDirPath","withIntl","withXdebug","onPHPInstanceCreated","spawnHandler","nextProcessId","lastProcessId","bootRequestHandler","loadNodeRuntime","setApiReady","e","setAPIError","mountsBeforeWpInstall","mountsAfterWpInstall","fileLockManager","spawnedWorker","spawnWorkerThread","handler","logger","phpChannel","MessageChannel","exposeAPI","EmscriptenDownloadMonitor","parentPort"],"mappings":"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"}