@wp-playground/client 0.1.25 → 0.1.33

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/index.js CHANGED
@@ -1,15 +1,763 @@
1
- class oe {
1
+ function T(t) {
2
+ return new DOMParser().parseFromString(t.text, "text/html");
3
+ }
4
+ function A(t) {
5
+ const e = t.split(".").shift().replace("-", " ");
6
+ return e.charAt(0).toUpperCase() + e.slice(1).toLowerCase();
7
+ }
8
+ async function E(t, e, r) {
9
+ await t.writeFile(e, r(await t.readFileAsText(e)));
10
+ }
11
+ async function we(t) {
12
+ return new Uint8Array(await t.arrayBuffer());
13
+ }
14
+ const ge = async (t, { plugin: e }, r) => {
15
+ r?.tracker.setCaption(`Activating ${e}`);
16
+ const i = T(
17
+ await t.request({
18
+ url: "/wp-admin/plugins.php"
19
+ })
20
+ ).querySelector(
21
+ `tr[data-slug="${e}"] a`
22
+ ).attributes.getNamedItem("href").value;
23
+ await t.request({
24
+ url: "/wp-admin/" + i
25
+ });
26
+ }, ye = async (t, e) => {
27
+ const r = new Pe(
28
+ t,
29
+ e.siteUrl,
30
+ e.wordpressPath || "/wordpress"
31
+ );
32
+ e.patchSqlitePlugin !== !1 && await r.patchSqlitePlugin(), e.addPhpInfo !== !1 && await r.addPhpInfo(), e.patchSiteUrl !== !1 && await r.patchSiteUrl(), e.disableSiteHealth !== !1 && await r.disableSiteHealth(), e.disableWpNewBlogNotification !== !1 && await r.disableWpNewBlogNotification();
33
+ };
34
+ class Pe {
35
+ constructor(e, r, s) {
36
+ this.php = e, this.scopedSiteUrl = r, this.wordpressPath = s;
37
+ }
38
+ async patchSqlitePlugin() {
39
+ await E(
40
+ this.php,
41
+ `${this.wordpressPath}/wp-content/plugins/sqlite-database-integration/wp-includes/sqlite/class-wp-sqlite-translator.php`,
42
+ (e) => e.replace(
43
+ "if ( false === strtotime( $value ) )",
44
+ 'if ( $value === "0000-00-00 00:00:00" || false === strtotime( $value ) )'
45
+ )
46
+ );
47
+ }
48
+ async addPhpInfo() {
49
+ await this.php.writeFile(
50
+ `${this.wordpressPath}/phpinfo.php`,
51
+ "<?php phpinfo(); "
52
+ );
53
+ }
54
+ async patchSiteUrl() {
55
+ await E(
56
+ this.php,
57
+ `${this.wordpressPath}/wp-config.php`,
58
+ (e) => `<?php
59
+ if(!defined('WP_HOME')) {
60
+ define('WP_HOME', "${this.scopedSiteUrl}");
61
+ define('WP_SITEURL', "${this.scopedSiteUrl}");
62
+ }
63
+ ?>${e}`
64
+ );
65
+ }
66
+ async disableSiteHealth() {
67
+ await E(
68
+ this.php,
69
+ `${this.wordpressPath}/wp-includes/default-filters.php`,
70
+ (e) => e.replace(
71
+ /add_filter[^;]+wp_maybe_grant_site_health_caps[^;]+;/i,
72
+ ""
73
+ )
74
+ );
75
+ }
76
+ async disableWpNewBlogNotification() {
77
+ await E(
78
+ this.php,
79
+ `${this.wordpressPath}/wp-config.php`,
80
+ // The original version of this function crashes WASM PHP, let's define an empty one instead.
81
+ (e) => `${e} function wp_new_blog_notification(...$args){} `
82
+ );
83
+ }
84
+ }
85
+ const be = async (t, { code: e }) => await t.run({ code: e }), _e = async (t, { options: e }) => await t.run(e), $e = async (t, { key: e, value: r }) => {
86
+ await t.setPhpIniEntry(e, r);
87
+ }, Se = async (t, { request: e }) => await t.request(e), ve = async (t, { fromPath: e, toPath: r }) => {
88
+ await t.writeFile(
89
+ r,
90
+ await t.readFileAsBuffer(e)
91
+ );
92
+ }, Ee = async (t, { fromPath: e, toPath: r }) => {
93
+ await t.mv(e, r);
94
+ }, Re = async (t, { path: e }) => {
95
+ await t.mkdir(e);
96
+ }, Te = async (t, { path: e }) => {
97
+ await t.unlink(e);
98
+ }, xe = async (t, { path: e }) => {
99
+ await t.rmdir(e);
100
+ }, Fe = async (t, { path: e, data: r }) => {
101
+ r instanceof File && (r = await we(r)), await t.writeFile(e, r);
102
+ }, Ce = async (t, { siteUrl: e }) => {
103
+ await E(
104
+ t,
105
+ "/wordpress/wp-config.php",
106
+ (r) => `<?php
107
+ if ( ! defined( 'WP_HOME' ) ) {
108
+ define('WP_HOME', "${e}");
109
+ }
110
+ if ( ! defined( 'WP_SITEURL' ) ) {
111
+ define('WP_SITEURL', "${e}");
112
+ }
113
+ ?>${r}`
114
+ );
115
+ };
116
+ class te {
117
+ constructor({ concurrency: e }) {
118
+ this._running = 0, this.concurrency = e, this.queue = [];
119
+ }
120
+ get running() {
121
+ return this._running;
122
+ }
123
+ async acquire() {
124
+ for (; ; )
125
+ if (this._running >= this.concurrency)
126
+ await new Promise((e) => this.queue.push(e));
127
+ else
128
+ return this._running++, () => {
129
+ this._running--, this.queue.length > 0 && this.queue.shift()();
130
+ };
131
+ }
132
+ async run(e) {
133
+ const r = await this.acquire();
134
+ try {
135
+ return await e();
136
+ } finally {
137
+ r();
138
+ }
139
+ }
140
+ }
141
+ const ke = Symbol("literal");
142
+ function S(t) {
143
+ if (typeof t == "string")
144
+ return t.startsWith("$") ? t : JSON.stringify(t);
145
+ if (typeof t == "number")
146
+ return t.toString();
147
+ if (Array.isArray(t))
148
+ return `array(${t.map(S).join(", ")})`;
149
+ if (t === null)
150
+ return "null";
151
+ if (typeof t == "object")
152
+ return ke in t ? t.toString() : `array(${Object.entries(t).map(([r, s]) => `${JSON.stringify(r)} => ${S(s)}`).join(", ")})`;
153
+ if (typeof t == "function")
154
+ return t();
155
+ throw new Error(`Unsupported value: ${t}`);
156
+ }
157
+ function z(t) {
158
+ const e = {};
159
+ for (const r in t)
160
+ e[r] = S(t[r]);
161
+ return e;
162
+ }
163
+ const j = `<?php
164
+
165
+ function zipDir($dir, $output, $additionalFiles = array())
166
+ {
167
+ $zip = new ZipArchive;
168
+ $res = $zip->open($output, ZipArchive::CREATE);
169
+ if ($res === TRUE) {
170
+ foreach ($additionalFiles as $file) {
171
+ $zip->addFile($file);
172
+ }
173
+ $directories = array(
174
+ rtrim($dir, '/') . '/'
175
+ );
176
+ while (sizeof($directories)) {
177
+ $dir = array_pop($directories);
178
+
179
+ if ($handle = opendir($dir)) {
180
+ while (false !== ($entry = readdir($handle))) {
181
+ if ($entry == '.' || $entry == '..') {
182
+ continue;
183
+ }
184
+
185
+ $entry = $dir . $entry;
186
+
187
+ if (is_dir($entry)) {
188
+ $directory_path = $entry . '/';
189
+ array_push($directories, $directory_path);
190
+ } else if (is_file($entry)) {
191
+ $zip->addFile($entry);
192
+ }
193
+ }
194
+ closedir($handle);
195
+ }
196
+ }
197
+ $zip->close();
198
+ chmod($output, 0777);
199
+ }
200
+ }
201
+
202
+ function unzip($zipPath, $extractTo, $overwrite = true)
203
+ {
204
+ if(!is_dir($extractTo)) {
205
+ mkdir($extractTo, 0777, true);
206
+ }
207
+ $zip = new ZipArchive;
208
+ $res = $zip->open($zipPath);
209
+ if ($res === TRUE) {
210
+ $zip->extractTo($extractTo);
211
+ $zip->close();
212
+ chmod($extractTo, 0777);
213
+ }
214
+ }
215
+
216
+
217
+ function delTree($dir)
218
+ {
219
+ $files = array_diff(scandir($dir), array('.', '..'));
220
+ foreach ($files as $file) {
221
+ (is_dir("$dir/$file")) ? delTree("$dir/$file") : unlink("$dir/$file");
222
+ }
223
+ return rmdir($dir);
224
+ }
225
+ `;
226
+ async function Oe(t) {
227
+ const e = "wordpress-playground.zip", r = `/${e}`, s = z({
228
+ zipPath: r,
229
+ documentRoot: await t.documentRoot
230
+ });
231
+ await se(
232
+ t,
233
+ `zipDir(${s.documentRoot}, ${s.zipPath});`
234
+ );
235
+ const n = await t.readFileAsBuffer(r);
236
+ return t.unlink(r), new File([n], e);
237
+ }
238
+ const Ue = async (t, { fullSiteZip: e }) => {
239
+ const r = "/import.zip";
240
+ await t.writeFile(
241
+ r,
242
+ new Uint8Array(await e.arrayBuffer())
243
+ );
244
+ const s = await t.absoluteUrl, n = await t.documentRoot;
245
+ await t.rmdir(n), await re(t, { zipPath: r, extractToPath: "/" });
246
+ const i = z({ absoluteUrl: s });
247
+ await He(
248
+ t,
249
+ `${n}/wp-config.php`,
250
+ (o) => `<?php
251
+ if(!defined('WP_HOME')) {
252
+ define('WP_HOME', ${i.absoluteUrl});
253
+ define('WP_SITEURL', ${i.absoluteUrl});
254
+ }
255
+ ?>${o}`
256
+ );
257
+ }, re = async (t, { zipPath: e, extractToPath: r }) => {
258
+ const s = z({
259
+ zipPath: e,
260
+ extractToPath: r
261
+ });
262
+ await se(
263
+ t,
264
+ `unzip(${s.zipPath}, ${s.extractToPath});`
265
+ );
266
+ }, Ae = async (t, { file: e }) => {
267
+ const r = await t.request({
268
+ url: "/wp-admin/admin.php?import=wordpress"
269
+ }), s = B(r).getElementById("import-upload-form")?.getAttribute("action"), n = await t.request({
270
+ url: `/wp-admin/${s}`,
271
+ method: "POST",
272
+ files: { import: e }
273
+ }), i = B(n).querySelector(
274
+ "#wpbody-content form"
275
+ );
276
+ if (!i)
277
+ throw console.log(n.text), new Error(
278
+ "Could not find an importer form in response. See the response text above for details."
279
+ );
280
+ const o = Le(i);
281
+ o.fetch_attachments = "1";
282
+ for (const a in o)
283
+ if (a.startsWith("user_map[")) {
284
+ const l = "user_new[" + a.slice(9, -1) + "]";
285
+ o[l] = "1";
286
+ }
287
+ await t.request({
288
+ url: i.action,
289
+ method: "POST",
290
+ formData: o
291
+ });
292
+ };
293
+ function B(t) {
294
+ return new DOMParser().parseFromString(t.text, "text/html");
295
+ }
296
+ function Le(t) {
297
+ return Object.fromEntries(new FormData(t).entries());
298
+ }
299
+ async function He(t, e, r) {
300
+ await t.writeFile(
301
+ e,
302
+ r(await t.readFileAsText(e))
303
+ );
304
+ }
305
+ async function se(t, e) {
306
+ const r = await t.run({
307
+ code: j + e
308
+ });
309
+ if (r.exitCode !== 0)
310
+ throw console.log(j + e), console.log(e + ""), console.log(r.errors), r.errors;
311
+ return r;
312
+ }
313
+ const Ie = async (t, { pluginZipFile: e, options: r = {} }, s) => {
314
+ s?.tracker.setCaption(
315
+ `Installing the ${A(e?.name)} plugin`
316
+ );
317
+ try {
318
+ const n = "activate" in r ? r.activate : !0, i = await t.request({
319
+ url: "/wp-admin/plugin-install.php?tab=upload"
320
+ }), o = T(i), a = new FormData(
321
+ o.querySelector(".wp-upload-form")
322
+ ), { pluginzip: l, ...c } = Object.fromEntries(
323
+ a.entries()
324
+ ), u = await t.request({
325
+ url: "/wp-admin/update.php?action=upload-plugin",
326
+ method: "POST",
327
+ formData: c,
328
+ files: { pluginzip: e }
329
+ });
330
+ if (n) {
331
+ const p = T(u).querySelector("#wpbody-content .button.button-primary").attributes.getNamedItem("href").value, y = new URL(
332
+ p,
333
+ await t.pathToInternalUrl("/wp-admin/")
334
+ ).toString();
335
+ await t.request({
336
+ url: y
337
+ });
338
+ }
339
+ await t.isDir(
340
+ "/wordpress/wp-content/plugins/gutenberg"
341
+ ) && !await t.fileExists("/wordpress/.gutenberg-patched") && (await t.writeFile("/wordpress/.gutenberg-patched", "1"), await V(
342
+ t,
343
+ "/wordpress/wp-content/plugins/gutenberg/build/block-editor/index.js",
344
+ (d) => d.replace(
345
+ /srcDoc:("[^"]+"|[^,]+)/g,
346
+ 'src:"/wp-includes/empty.html"'
347
+ )
348
+ ), await V(
349
+ t,
350
+ "/wordpress/wp-content/plugins/gutenberg/build/block-editor/index.min.js",
351
+ (d) => d.replace(
352
+ /srcDoc:("[^"]+"|[^,]+)/g,
353
+ 'src:"/wp-includes/empty.html"'
354
+ )
355
+ ));
356
+ } catch (n) {
357
+ console.error(
358
+ `Proceeding without the ${e.name} theme. Could not install it in wp-admin. The original error was: ${n}`
359
+ ), console.error(n);
360
+ }
361
+ };
362
+ async function V(t, e, r) {
363
+ return await t.writeFile(
364
+ e,
365
+ r(await t.readFileAsText(e))
366
+ );
367
+ }
368
+ const Ne = async (t, { themeZipFile: e, options: r = {} }, s) => {
369
+ s?.tracker.setCaption(
370
+ `Installing the ${A(e.name)} theme`
371
+ );
372
+ try {
373
+ const n = "activate" in r ? r.activate : !0, i = await t.request({
374
+ url: "/wp-admin/theme-install.php"
375
+ }), o = T(i), a = new FormData(
376
+ o.querySelector(".wp-upload-form")
377
+ ), { themezip: l, ...c } = Object.fromEntries(
378
+ a.entries()
379
+ ), u = await t.request({
380
+ url: "/wp-admin/update.php?action=upload-theme",
381
+ method: "POST",
382
+ formData: c,
383
+ files: { themezip: e }
384
+ });
385
+ if (n) {
386
+ const d = T(u), p = d.querySelector(
387
+ "#wpbody-content > .wrap"
388
+ );
389
+ if (p?.textContent?.includes(
390
+ "Theme installation failed."
391
+ )) {
392
+ console.error(p?.textContent);
393
+ return;
394
+ }
395
+ const y = d.querySelector(
396
+ "#wpbody-content .activatelink, .update-from-upload-actions .button.button-primary"
397
+ );
398
+ if (!y) {
399
+ console.error('The "activate" button was not found.');
400
+ return;
401
+ }
402
+ const fe = y.attributes.getNamedItem("href").value, me = new URL(
403
+ fe,
404
+ await t.pathToInternalUrl("/wp-admin/")
405
+ ).toString();
406
+ await t.request({
407
+ url: me
408
+ });
409
+ }
410
+ } catch (n) {
411
+ console.error(
412
+ `Proceeding without the ${e.name} theme. Could not install it in wp-admin. The original error was: ${n}`
413
+ ), console.error(n);
414
+ }
415
+ }, ze = async (t, { username: e = "admin", password: r = "password" } = {}, s) => {
416
+ s?.tracker.setCaption(s?.initialCaption || "Logging in"), await t.request({
417
+ url: "/wp-login.php"
418
+ }), await t.request({
419
+ url: "/wp-login.php",
420
+ method: "POST",
421
+ formData: {
422
+ log: e,
423
+ pwd: r,
424
+ rememberme: "forever"
425
+ }
426
+ });
427
+ }, De = async (t, { options: e }) => {
428
+ await t.request({
429
+ url: "/wp-admin/install.php?step=2",
430
+ method: "POST",
431
+ formData: {
432
+ language: "en",
433
+ prefix: "wp_",
434
+ weblog_title: "My WordPress Website",
435
+ user_name: e.adminPassword || "admin",
436
+ admin_password: e.adminPassword || "password",
437
+ // The installation wizard demands typing the same password twice
438
+ admin_password2: e.adminPassword || "password",
439
+ Submit: "Install WordPress",
440
+ pw_weak: "1",
441
+ admin_email: "admin@localhost.com"
442
+ }
443
+ });
444
+ }, qe = async (t, { options: e }) => {
445
+ const r = `<?php
446
+ include 'wordpress/wp-load.php';
447
+ $site_options = ${S(e)};
448
+ foreach($site_options as $name => $value) {
449
+ update_option($name, $value);
450
+ }
451
+ echo "Success";
452
+ `, s = await t.run({
453
+ code: r
454
+ });
455
+ return ne(s), { code: r, result: s };
456
+ }, We = async (t, { meta: e, userId: r }) => {
457
+ const s = `<?php
458
+ include 'wordpress/wp-load.php';
459
+ $meta = ${S(e)};
460
+ foreach($meta as $name => $value) {
461
+ update_user_meta(${S(r)}, $name, $value);
462
+ }
463
+ echo "Success";
464
+ `, n = await t.run({
465
+ code: s
466
+ });
467
+ return ne(n), { code: s, result: n };
468
+ };
469
+ async function ne(t) {
470
+ if (t.text !== "Success")
471
+ throw console.log(t), new Error(`Failed to run code: ${t.text} ${t.errors}`);
472
+ }
473
+ const Me = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
474
+ __proto__: null,
475
+ activatePlugin: ge,
476
+ applyWordPressPatches: ye,
477
+ cp: ve,
478
+ defineSiteUrl: Ce,
479
+ importFile: Ae,
480
+ installPlugin: Ie,
481
+ installTheme: Ne,
482
+ login: ze,
483
+ mkdir: Re,
484
+ mv: Ee,
485
+ replaceSite: Ue,
486
+ request: Se,
487
+ rm: Te,
488
+ rmdir: xe,
489
+ runPHP: be,
490
+ runPHPWithOptions: _e,
491
+ runWpInstallationWizard: De,
492
+ setPhpIniEntry: $e,
493
+ setSiteOptions: qe,
494
+ unzip: re,
495
+ updateUserMeta: We,
496
+ writeFile: Fe,
497
+ zipEntireSite: Oe
498
+ }, Symbol.toStringTag, { value: "Module" })), je = 5 * 1024 * 1024;
499
+ function Be(t, e) {
500
+ const r = t.headers.get("content-length") || "", s = parseInt(r, 10) || je;
501
+ function n(i, o) {
502
+ e(
503
+ new CustomEvent("progress", {
504
+ detail: {
505
+ loaded: i,
506
+ total: o
507
+ }
508
+ })
509
+ );
510
+ }
511
+ return new Response(
512
+ new ReadableStream({
513
+ async start(i) {
514
+ if (!t.body) {
515
+ i.close();
516
+ return;
517
+ }
518
+ const o = t.body.getReader();
519
+ let a = 0;
520
+ for (; ; )
521
+ try {
522
+ const { done: l, value: c } = await o.read();
523
+ if (c && (a += c.byteLength), l) {
524
+ n(a, a), i.close();
525
+ break;
526
+ } else
527
+ n(a, s), i.enqueue(c);
528
+ } catch (l) {
529
+ console.error({ e: l }), i.error(l);
530
+ break;
531
+ }
532
+ }
533
+ }),
534
+ {
535
+ status: t.status,
536
+ statusText: t.statusText,
537
+ headers: t.headers
538
+ }
539
+ );
540
+ }
541
+ const H = 1e-5;
542
+ class L extends EventTarget {
543
+ constructor({
544
+ weight: e = 1,
545
+ caption: r = "",
546
+ fillTime: s = 4
547
+ } = {}) {
548
+ super(), this._selfWeight = 1, this._selfProgress = 0, this._selfCaption = "", this._isFilling = !1, this._subTrackers = [], this._weight = e, this._selfCaption = r, this._fillTime = s;
549
+ }
550
+ /**
551
+ * Creates a new sub-tracker with a specific weight.
552
+ *
553
+ * The weight determines what percentage of the overall progress
554
+ * the sub-tracker represents. For example, if the main tracker is
555
+ * monitoring a process that has two stages, and the first stage
556
+ * is expected to take twice as long as the second stage, you could
557
+ * create the first sub-tracker with a weight of 0.67 and the second
558
+ * sub-tracker with a weight of 0.33.
559
+ *
560
+ * The caption is an optional string that describes the current stage
561
+ * of the operation. If provided, it will be used as the progress caption
562
+ * for the sub-tracker. If not provided, the main tracker will look for
563
+ * the next sub-tracker with a non-empty caption and use that as the progress
564
+ * caption instead.
565
+ *
566
+ * Returns the newly-created sub-tracker.
567
+ *
568
+ * @throws {Error} If the weight of the new stage would cause the total weight of all stages to exceed 1.
569
+ *
570
+ * @param weight The weight of the new stage, as a decimal value between 0 and 1.
571
+ * @param caption The caption for the new stage, which will be used as the progress caption for the sub-tracker.
572
+ *
573
+ * @example
574
+ * ```ts
575
+ * const tracker = new ProgressTracker();
576
+ * const subTracker1 = tracker.stage(0.67, 'Slow stage');
577
+ * const subTracker2 = tracker.stage(0.33, 'Fast stage');
578
+ *
579
+ * subTracker2.set(50);
580
+ * subTracker1.set(75);
581
+ * subTracker2.set(100);
582
+ * subTracker1.set(100);
583
+ * ```
584
+ */
585
+ stage(e, r = "") {
586
+ if (e || (e = this._selfWeight), this._selfWeight - e < -H)
587
+ throw new Error(
588
+ `Cannot add a stage with weight ${e} as the total weight of registered stages would exceed 1.`
589
+ );
590
+ this._selfWeight -= e;
591
+ const s = new L({
592
+ caption: r,
593
+ weight: e,
594
+ fillTime: this._fillTime
595
+ });
596
+ return this._subTrackers.push(s), s.addEventListener("progress", () => this.notifyProgress()), s.addEventListener("done", () => {
597
+ this.done && this.notifyDone();
598
+ }), s;
599
+ }
600
+ /**
601
+ * Fills the progress bar slowly over time, simulating progress.
602
+ *
603
+ * The progress bar is filled in a 100 steps, and each step, the progress
604
+ * is increased by 1. If `stopBeforeFinishing` is true, the progress bar
605
+ * will stop filling when it reaches 99% so that you can call `finish()`
606
+ * explicitly.
607
+ *
608
+ * If the progress bar is filling or already filled, this method does nothing.
609
+ *
610
+ * @example
611
+ * ```ts
612
+ * const progress = new ProgressTracker({ caption: 'Processing...' });
613
+ * progress.fillSlowly();
614
+ * ```
615
+ *
616
+ * @param options Optional options.
617
+ */
618
+ fillSlowly({ stopBeforeFinishing: e = !0 } = {}) {
619
+ if (this._isFilling)
620
+ return;
621
+ this._isFilling = !0;
622
+ const r = 100, s = this._fillTime / r;
623
+ this._fillInterval = setInterval(() => {
624
+ this.set(this._selfProgress + 1), e && this._selfProgress >= 99 && clearInterval(this._fillInterval);
625
+ }, s);
626
+ }
627
+ set(e) {
628
+ this._selfProgress = Math.min(e, 100), this.notifyProgress(), this._selfProgress + H >= 100 && this.finish();
629
+ }
630
+ finish() {
631
+ this._fillInterval && clearInterval(this._fillInterval), this._selfProgress = 100, this._isFilling = !1, this._fillInterval = void 0, this.notifyProgress(), this.notifyDone();
632
+ }
633
+ get caption() {
634
+ for (let e = this._subTrackers.length - 1; e >= 0; e--)
635
+ if (!this._subTrackers[e].done) {
636
+ const r = this._subTrackers[e].caption;
637
+ if (r)
638
+ return r;
639
+ }
640
+ return this._selfCaption;
641
+ }
642
+ setCaption(e) {
643
+ this._selfCaption = e, this.notifyProgress();
644
+ }
645
+ get done() {
646
+ return this.progress + H >= 100;
647
+ }
648
+ get progress() {
649
+ const e = this._subTrackers.reduce(
650
+ (r, s) => r + s.progress * s.weight,
651
+ this._selfProgress * this._selfWeight
652
+ );
653
+ return Math.round(e * 1e4) / 1e4;
654
+ }
655
+ get weight() {
656
+ return this._weight;
657
+ }
658
+ get observer() {
659
+ return this._progressObserver || (this._progressObserver = (e) => {
660
+ this.set(e);
661
+ }), this._progressObserver;
662
+ }
663
+ get loadingListener() {
664
+ return this._loadingListener || (this._loadingListener = (e) => {
665
+ this.set(e.detail.loaded / e.detail.total * 100);
666
+ }), this._loadingListener;
667
+ }
668
+ pipe(e) {
669
+ this.addEventListener("progress", (r) => {
670
+ e.setProgress({
671
+ progress: r.detail.progress,
672
+ caption: r.detail.caption
673
+ });
674
+ }), this.addEventListener("done", () => {
675
+ e.setLoaded();
676
+ });
677
+ }
678
+ addEventListener(e, r) {
679
+ super.addEventListener(e, r);
680
+ }
681
+ removeEventListener(e, r) {
682
+ super.removeEventListener(e, r);
683
+ }
684
+ notifyProgress() {
685
+ const e = this;
686
+ this.dispatchEvent(
687
+ new CustomEvent("progress", {
688
+ detail: {
689
+ get progress() {
690
+ return e.progress;
691
+ },
692
+ get caption() {
693
+ return e.caption;
694
+ }
695
+ }
696
+ })
697
+ );
698
+ }
699
+ notifyDone() {
700
+ this.dispatchEvent(new CustomEvent("done"));
701
+ }
702
+ }
703
+ class v {
704
+ constructor(e, r, s, n = "", i = 0) {
705
+ this.httpStatusCode = e, this.headers = r, this.bytes = s, this.exitCode = i, this.errors = n;
706
+ }
707
+ static fromRawData(e) {
708
+ return new v(
709
+ e.httpStatusCode,
710
+ e.headers,
711
+ e.bytes,
712
+ e.errors,
713
+ e.exitCode
714
+ );
715
+ }
716
+ toRawData() {
717
+ return {
718
+ headers: this.headers,
719
+ bytes: this.bytes,
720
+ errors: this.errors,
721
+ exitCode: this.exitCode,
722
+ httpStatusCode: this.httpStatusCode
723
+ };
724
+ }
725
+ /**
726
+ * Response body as JSON.
727
+ */
728
+ get json() {
729
+ return JSON.parse(this.text);
730
+ }
731
+ /**
732
+ * Response body as text.
733
+ */
734
+ get text() {
735
+ return new TextDecoder().decode(this.bytes);
736
+ }
737
+ }
738
+ const D = [
739
+ "8.2",
740
+ "8.1",
741
+ "8.0",
742
+ "7.4",
743
+ "7.3",
744
+ "7.2",
745
+ "7.1",
746
+ "7.0",
747
+ "5.6"
748
+ ], Ve = D[0], Lt = D;
749
+ class Ge {
2
750
  #e;
3
751
  #t;
4
752
  /**
5
753
  * @param server - The PHP server to browse.
6
754
  * @param config - The browser configuration.
7
755
  */
8
- constructor(e, n = {}) {
9
- this.server = e, this.#e = {}, this.#t = {
756
+ constructor(e, r = {}) {
757
+ this.requestHandler = e, this.#e = {}, this.#t = {
10
758
  handleRedirects: !1,
11
759
  maxRedirects: 4,
12
- ...n
760
+ ...r
13
761
  };
14
762
  }
15
763
  /**
@@ -26,196 +774,138 @@ class oe {
26
774
  * @param redirects - Internal. The number of redirects handled so far.
27
775
  * @returns PHPRequestHandler response.
28
776
  */
29
- async request(e, n = 0) {
30
- const r = await this.server.request({
777
+ async request(e, r = 0) {
778
+ const s = await this.requestHandler.request({
31
779
  ...e,
32
780
  headers: {
33
781
  ...e.headers,
34
- cookie: this.#r()
782
+ cookie: this.#s()
35
783
  }
36
784
  });
37
- if (r.headers["set-cookie"] && this.#n(r.headers["set-cookie"]), this.#t.handleRedirects && r.headers.location && n < this.#t.maxRedirects) {
38
- const o = new URL(
39
- r.headers.location[0],
40
- this.server.absoluteUrl
785
+ if (s.headers["set-cookie"] && this.#n(s.headers["set-cookie"]), this.#t.handleRedirects && s.headers.location && r < this.#t.maxRedirects) {
786
+ const n = new URL(
787
+ s.headers.location[0],
788
+ this.requestHandler.absoluteUrl
41
789
  );
42
790
  return this.request(
43
791
  {
44
- url: o.toString(),
792
+ url: n.toString(),
45
793
  method: "GET",
46
794
  headers: {}
47
795
  },
48
- n + 1
796
+ r + 1
49
797
  );
50
798
  }
51
- return r;
799
+ return s;
800
+ }
801
+ /** @inheritDoc */
802
+ pathToInternalUrl(e) {
803
+ return this.requestHandler.pathToInternalUrl(e);
804
+ }
805
+ /** @inheritDoc */
806
+ internalUrlToPath(e) {
807
+ return this.requestHandler.internalUrlToPath(e);
808
+ }
809
+ /** @inheritDoc */
810
+ get absoluteUrl() {
811
+ return this.requestHandler.absoluteUrl;
812
+ }
813
+ /** @inheritDoc */
814
+ get documentRoot() {
815
+ return this.requestHandler.documentRoot;
52
816
  }
53
817
  #n(e) {
54
- for (const n of e)
818
+ for (const r of e)
55
819
  try {
56
- if (!n.includes("="))
820
+ if (!r.includes("="))
57
821
  continue;
58
- const r = n.indexOf("="), o = n.substring(0, r), a = n.substring(r + 1).split(";")[0];
59
- this.#e[o] = a;
60
- } catch (r) {
61
- console.error(r);
822
+ const s = r.indexOf("="), n = r.substring(0, s), i = r.substring(s + 1).split(";")[0];
823
+ this.#e[n] = i;
824
+ } catch (s) {
825
+ console.error(s);
62
826
  }
63
827
  }
64
- #r() {
828
+ #s() {
65
829
  const e = [];
66
- for (const n in this.#e)
67
- e.push(`${n}=${this.#e[n]}`);
830
+ for (const r in this.#e)
831
+ e.push(`${r}=${this.#e[r]}`);
68
832
  return e.join("; ");
69
833
  }
70
834
  }
71
- const ie = "http://example.com";
72
- function j(t) {
835
+ const Je = "http://example.com";
836
+ function G(t) {
73
837
  return t.toString().substring(t.origin.length);
74
838
  }
75
- function B(t, e) {
839
+ function J(t, e) {
76
840
  return !e || !t.startsWith(e) ? t : t.substring(e.length);
77
841
  }
78
- function se(t, e) {
842
+ function Ke(t, e) {
79
843
  return !e || t.startsWith(e) ? t : e + t;
80
844
  }
81
- class ae {
82
- constructor({ concurrency: e }) {
83
- this._running = 0, this.concurrency = e, this.queue = [];
84
- }
85
- get running() {
86
- return this._running;
87
- }
88
- async acquire() {
89
- for (; ; )
90
- if (this._running >= this.concurrency)
91
- await new Promise((e) => this.queue.push(e));
92
- else
93
- return this._running++, () => {
94
- this._running--, this.queue.length > 0 && this.queue.shift()();
95
- };
96
- }
97
- }
98
- class E {
99
- constructor(e, n, r, o = "", a = 0) {
100
- this.httpStatusCode = e, this.headers = n, this.bytes = r, this.exitCode = a, this.errors = o;
101
- }
102
- static fromRawData(e) {
103
- return new E(
104
- e.httpStatusCode,
105
- e.headers,
106
- e.bytes,
107
- e.errors,
108
- e.exitCode
109
- );
110
- }
111
- toRawData() {
112
- return {
113
- headers: this.headers,
114
- bytes: this.bytes,
115
- errors: this.errors,
116
- exitCode: this.exitCode,
117
- httpStatusCode: this.httpStatusCode
118
- };
119
- }
120
- /**
121
- * Response body as JSON.
122
- */
123
- get json() {
124
- return JSON.parse(this.text);
125
- }
126
- /**
127
- * Response body as text.
128
- */
129
- get text() {
130
- return new TextDecoder().decode(this.bytes);
131
- }
132
- }
133
- class le {
845
+ class Ye {
134
846
  #e;
135
847
  #t;
136
848
  #n;
137
- #r;
849
+ #s;
138
850
  #i;
851
+ #r;
139
852
  #o;
140
- #s;
141
853
  #a;
142
- #l;
854
+ #c;
143
855
  /**
144
856
  * @param php - The PHP instance.
145
857
  * @param config - Request Handler configuration.
146
858
  */
147
- constructor(e, n = {}) {
148
- this.#a = new ae({ concurrency: 1 });
859
+ constructor(e, r = {}) {
860
+ this.#a = new te({ concurrency: 1 });
149
861
  const {
150
- documentRoot: r = "/www/",
151
- absoluteUrl: o = typeof location == "object" ? location?.href : "",
152
- isStaticFilePath: a = () => !1
153
- } = n;
154
- this.php = e, this.#e = r, this.#l = a;
155
- const i = new URL(o);
156
- this.#n = i.hostname, this.#r = i.port ? Number(i.port) : i.protocol === "https:" ? 443 : 80, this.#t = (i.protocol || "").replace(":", "");
157
- const d = this.#r !== 443 && this.#r !== 80;
862
+ documentRoot: s = "/www/",
863
+ absoluteUrl: n = typeof location == "object" ? location?.href : "",
864
+ isStaticFilePath: i = () => !1
865
+ } = r;
866
+ this.php = e, this.#e = s, this.#c = i;
867
+ const o = new URL(n);
868
+ this.#n = o.hostname, this.#s = o.port ? Number(o.port) : o.protocol === "https:" ? 443 : 80, this.#t = (o.protocol || "").replace(":", "");
869
+ const a = this.#s !== 443 && this.#s !== 80;
158
870
  this.#i = [
159
871
  this.#n,
160
- d ? `:${this.#r}` : ""
161
- ].join(""), this.#o = i.pathname.replace(/\/+$/, ""), this.#s = [
872
+ a ? `:${this.#s}` : ""
873
+ ].join(""), this.#r = o.pathname.replace(/\/+$/, ""), this.#o = [
162
874
  `${this.#t}://`,
163
875
  this.#i,
164
- this.#o
876
+ this.#r
165
877
  ].join("");
166
878
  }
167
- /**
168
- * Converts a path to an absolute URL based at the PHPRequestHandler
169
- * root.
170
- *
171
- * @param path The server path to convert to an absolute URL.
172
- * @returns The absolute URL.
173
- */
879
+ /** @inheritDoc */
174
880
  pathToInternalUrl(e) {
175
881
  return `${this.absoluteUrl}${e}`;
176
882
  }
177
- /**
178
- * Converts an absolute URL based at the PHPRequestHandler to a relative path
179
- * without the server pathname and scope.
180
- *
181
- * @param internalUrl An absolute URL based at the PHPRequestHandler root.
182
- * @returns The relative path.
183
- */
883
+ /** @inheritDoc */
184
884
  internalUrlToPath(e) {
185
- const n = new URL(e);
186
- return n.pathname.startsWith(this.#o) && (n.pathname = n.pathname.slice(this.#o.length)), j(n);
885
+ const r = new URL(e);
886
+ return r.pathname.startsWith(this.#r) && (r.pathname = r.pathname.slice(this.#r.length)), G(r);
187
887
  }
188
888
  get isRequestRunning() {
189
889
  return this.#a.running > 0;
190
890
  }
191
- /**
192
- * The absolute URL of this PHPRequestHandler instance.
193
- */
891
+ /** @inheritDoc */
194
892
  get absoluteUrl() {
195
- return this.#s;
893
+ return this.#o;
196
894
  }
197
- /**
198
- * The absolute URL of this PHPRequestHandler instance.
199
- */
895
+ /** @inheritDoc */
200
896
  get documentRoot() {
201
897
  return this.#e;
202
898
  }
203
- /**
204
- * Serves the request – either by serving a static file, or by
205
- * dispatching it to the PHP runtime.
206
- *
207
- * @param request - The request.
208
- * @returns The response.
209
- */
899
+ /** @inheritDoc */
210
900
  async request(e) {
211
- const n = e.url.startsWith("http://") || e.url.startsWith("https://"), r = new URL(
901
+ const r = e.url.startsWith("http://") || e.url.startsWith("https://"), s = new URL(
212
902
  e.url,
213
- n ? void 0 : ie
214
- ), o = B(
215
- r.pathname,
216
- this.#o
903
+ r ? void 0 : Je
904
+ ), n = J(
905
+ s.pathname,
906
+ this.#r
217
907
  );
218
- return this.#l(o) ? this.#c(o) : await this.#u(e, r);
908
+ return this.#c(n) ? this.#l(n) : await this.#u(e, s);
219
909
  }
220
910
  /**
221
911
  * Serves a static file from the PHP filesystem.
@@ -223,27 +913,27 @@ class le {
223
913
  * @param path - The requested static file path.
224
914
  * @returns The response.
225
915
  */
226
- #c(e) {
227
- const n = `${this.#e}${e}`;
228
- if (!this.php.fileExists(n))
229
- return new E(
916
+ #l(e) {
917
+ const r = `${this.#e}${e}`;
918
+ if (!this.php.fileExists(r))
919
+ return new v(
230
920
  404,
231
921
  {},
232
922
  new TextEncoder().encode("404 File not found")
233
923
  );
234
- const r = this.php.readFileAsBuffer(n);
235
- return new E(
924
+ const s = this.php.readFileAsBuffer(r);
925
+ return new v(
236
926
  200,
237
927
  {
238
- "content-length": [`${r.byteLength}`],
928
+ "content-length": [`${s.byteLength}`],
239
929
  // @TODO: Infer the content-type from the arrayBuffer instead of the file path.
240
930
  // The code below won't return the correct mime-type if the extension
241
931
  // was tampered with.
242
- "content-type": [ue(n)],
932
+ "content-type": [Xe(r)],
243
933
  "accept-ranges": ["bytes"],
244
934
  "cache-control": ["public, max-age=0"]
245
935
  },
246
- r
936
+ s
247
937
  );
248
938
  }
249
939
  /**
@@ -253,50 +943,50 @@ class le {
253
943
  * @param request - The request.
254
944
  * @returns The response.
255
945
  */
256
- async #u(e, n) {
257
- const r = await this.#a.acquire();
946
+ async #u(e, r) {
947
+ const s = await this.#a.acquire();
258
948
  try {
259
949
  this.php.addServerGlobalEntry("DOCUMENT_ROOT", this.#e), this.php.addServerGlobalEntry(
260
950
  "HTTPS",
261
- this.#s.startsWith("https://") ? "on" : ""
951
+ this.#o.startsWith("https://") ? "on" : ""
262
952
  );
263
- let o = "GET";
264
- const a = {
953
+ let n = "GET";
954
+ const i = {
265
955
  host: this.#i,
266
- ...K(e.headers || {})
267
- }, i = [];
956
+ ...ie(e.headers || {})
957
+ }, o = [];
268
958
  if (e.files && Object.keys(e.files).length) {
269
- o = "POST";
270
- for (const c in e.files) {
271
- const s = e.files[c];
272
- i.push({
273
- key: c,
274
- name: s.name,
275
- type: s.type,
276
- data: new Uint8Array(await s.arrayBuffer())
959
+ n = "POST";
960
+ for (const l in e.files) {
961
+ const c = e.files[l];
962
+ o.push({
963
+ key: l,
964
+ name: c.name,
965
+ type: c.type,
966
+ data: new Uint8Array(await c.arrayBuffer())
277
967
  });
278
968
  }
279
- a["content-type"]?.startsWith("multipart/form-data") && (e.formData = ce(
969
+ i["content-type"]?.startsWith("multipart/form-data") && (e.formData = Qe(
280
970
  e.body || ""
281
- ), a["content-type"] = "application/x-www-form-urlencoded", delete e.body);
971
+ ), i["content-type"] = "application/x-www-form-urlencoded", delete e.body);
282
972
  }
283
- let d;
284
- return e.formData !== void 0 ? (o = "POST", a["content-type"] = a["content-type"] || "application/x-www-form-urlencoded", d = new URLSearchParams(
973
+ let a;
974
+ return e.formData !== void 0 ? (n = "POST", i["content-type"] = i["content-type"] || "application/x-www-form-urlencoded", a = new URLSearchParams(
285
975
  e.formData
286
- ).toString()) : d = e.body, await this.php.run({
287
- relativeUri: se(
288
- j(n),
289
- this.#o
976
+ ).toString()) : a = e.body, await this.php.run({
977
+ relativeUri: Ke(
978
+ G(r),
979
+ this.#r
290
980
  ),
291
981
  protocol: this.#t,
292
- method: e.method || o,
293
- body: d,
294
- fileInfos: i,
295
- scriptPath: this.#d(n.pathname),
296
- headers: a
982
+ method: e.method || n,
983
+ body: a,
984
+ fileInfos: o,
985
+ scriptPath: this.#h(r.pathname),
986
+ headers: i
297
987
  });
298
988
  } finally {
299
- r();
989
+ s();
300
990
  }
301
991
  }
302
992
  /**
@@ -307,29 +997,29 @@ class le {
307
997
  * @param requestedPath - The requested pathname.
308
998
  * @returns The resolved filesystem path.
309
999
  */
310
- #d(e) {
311
- let n = B(e, this.#o);
312
- n.includes(".php") ? n = n.split(".php")[0] + ".php" : (n.endsWith("/") || (n += "/"), n.endsWith("index.php") || (n += "index.php"));
313
- const r = `${this.#e}${n}`;
314
- return this.php.fileExists(r) ? r : `${this.#e}/index.php`;
1000
+ #h(e) {
1001
+ let r = J(e, this.#r);
1002
+ r.includes(".php") ? r = r.split(".php")[0] + ".php" : (r.endsWith("/") || (r += "/"), r.endsWith("index.php") || (r += "index.php"));
1003
+ const s = `${this.#e}${r}`;
1004
+ return this.php.fileExists(s) ? s : `${this.#e}/index.php`;
315
1005
  }
316
1006
  }
317
- function ce(t) {
318
- const e = {}, n = t.match(/--(.*)\r\n/);
319
- if (!n)
1007
+ function Qe(t) {
1008
+ const e = {}, r = t.match(/--(.*)\r\n/);
1009
+ if (!r)
320
1010
  return e;
321
- const r = n[1], o = t.split(`--${r}`);
322
- return o.shift(), o.pop(), o.forEach((a) => {
323
- const i = a.indexOf(`\r
1011
+ const s = r[1], n = t.split(`--${s}`);
1012
+ return n.shift(), n.pop(), n.forEach((i) => {
1013
+ const o = i.indexOf(`\r
324
1014
  \r
325
- `), d = a.substring(0, i).trim(), c = a.substring(i + 4).trim(), s = d.match(/name="([^"]+)"/);
326
- if (s) {
327
- const l = s[1];
328
- e[l] = c;
1015
+ `), a = i.substring(0, o).trim(), l = i.substring(o + 4).trim(), c = a.match(/name="([^"]+)"/);
1016
+ if (c) {
1017
+ const u = c[1];
1018
+ e[u] = l;
329
1019
  }
330
1020
  }), e;
331
1021
  }
332
- function ue(t) {
1022
+ function Xe(t) {
333
1023
  switch (t.split(".").pop()) {
334
1024
  case "css":
335
1025
  return "text/css";
@@ -369,7 +1059,7 @@ function ue(t) {
369
1059
  return "application-octet-stream";
370
1060
  }
371
1061
  }
372
- const W = {
1062
+ const K = {
373
1063
  0: "No error occurred. System call completed successfully.",
374
1064
  1: "Argument list too long.",
375
1065
  2: "Permission denied.",
@@ -449,34 +1139,38 @@ const W = {
449
1139
  76: "Extension: Capabilities insufficient."
450
1140
  };
451
1141
  function m(t = "") {
452
- return function(n, r, o) {
453
- const a = o.value;
454
- o.value = function(...i) {
1142
+ return function(r, s, n) {
1143
+ const i = n.value;
1144
+ n.value = function(...o) {
455
1145
  try {
456
- return a.apply(this, i);
457
- } catch (d) {
458
- const c = typeof d == "object" ? d?.errno : null;
459
- if (c in W) {
460
- const s = W[c], l = typeof i[0] == "string" ? i[0] : null, h = l !== null ? t.replaceAll("{path}", l) : t;
461
- throw new Error(`${h}: ${s}`, {
462
- cause: d
1146
+ return i.apply(this, o);
1147
+ } catch (a) {
1148
+ const l = typeof a == "object" ? a?.errno : null;
1149
+ if (l in K) {
1150
+ const c = K[l], u = typeof o[0] == "string" ? o[0] : null, d = u !== null ? t.replaceAll("{path}", u) : t;
1151
+ throw new Error(`${d}: ${c}`, {
1152
+ cause: a
463
1153
  });
464
1154
  }
465
- throw d;
1155
+ throw a;
466
1156
  }
467
1157
  };
468
1158
  };
469
1159
  }
470
- var de = Object.defineProperty, he = Object.getOwnPropertyDescriptor, w = (t, e, n, r) => {
471
- for (var o = r > 1 ? void 0 : r ? he(e, n) : e, a = t.length - 1, i; a >= 0; a--)
472
- (i = t[a]) && (o = (r ? i(e, n, o) : i(o)) || o);
473
- return r && o && de(e, n, o), o;
474
- };
475
- const f = "string", g = "number", G = [];
1160
+ const Ze = [];
1161
+ function et(t) {
1162
+ return Ze[t];
1163
+ }
476
1164
  (function() {
477
1165
  return typeof window < "u" && !{}.TEST ? "WEB" : typeof WorkerGlobalScope < "u" && self instanceof WorkerGlobalScope ? "WORKER" : "NODE";
478
1166
  })();
479
- class y {
1167
+ var tt = Object.defineProperty, rt = Object.getOwnPropertyDescriptor, w = (t, e, r, s) => {
1168
+ for (var n = s > 1 ? void 0 : s ? rt(e, r) : e, i = t.length - 1, o; i >= 0; i--)
1169
+ (o = t[i]) && (n = (s ? o(e, r, n) : o(n)) || n);
1170
+ return s && n && tt(e, r, n), n;
1171
+ };
1172
+ const f = "string", _ = "number", h = Symbol("__private__dont__use");
1173
+ class g {
480
1174
  /**
481
1175
  * Initializes a PHP runtime.
482
1176
  *
@@ -484,164 +1178,204 @@ class y {
484
1178
  * @param PHPRuntime - Optional. PHP Runtime ID as initialized by loadPHPRuntime.
485
1179
  * @param serverOptions - Optional. Options for the PHPRequestHandler. If undefined, no request handler will be initialized.
486
1180
  */
487
- constructor(e, n) {
488
- this.#t = [], this.#n = !1, e !== void 0 && this.initializeRuntime(e), n && (this.requestHandler = new oe(
489
- new le(this, n)
1181
+ constructor(e, r) {
1182
+ this.#e = [], this.#t = !1, e !== void 0 && this.initializeRuntime(e), r && (this.requestHandler = new Ge(
1183
+ new Ye(this, r)
490
1184
  ));
491
1185
  }
492
1186
  #e;
493
1187
  #t;
494
- #n;
1188
+ /** @inheritDoc */
1189
+ get absoluteUrl() {
1190
+ return this.requestHandler.requestHandler.absoluteUrl;
1191
+ }
1192
+ /** @inheritDoc */
1193
+ get documentRoot() {
1194
+ return this.requestHandler.requestHandler.absoluteUrl;
1195
+ }
1196
+ /** @inheritDoc */
1197
+ pathToInternalUrl(e) {
1198
+ return this.requestHandler.requestHandler.pathToInternalUrl(e);
1199
+ }
1200
+ /** @inheritDoc */
1201
+ internalUrlToPath(e) {
1202
+ return this.requestHandler.requestHandler.internalUrlToPath(
1203
+ e
1204
+ );
1205
+ }
495
1206
  initializeRuntime(e) {
496
- if (this.#e)
1207
+ if (this[h])
497
1208
  throw new Error("PHP runtime already initialized.");
498
- if (!G[e])
1209
+ const r = et(e);
1210
+ if (!r)
499
1211
  throw new Error("Invalid PHP runtime id.");
500
- this.#e = G[e];
1212
+ this[h] = r;
501
1213
  }
502
1214
  /** @inheritDoc */
503
1215
  setPhpIniPath(e) {
504
- if (this.#n)
1216
+ if (this.#t)
505
1217
  throw new Error("Cannot set PHP ini path after calling run().");
506
- this.#e.ccall("wasm_set_phpini_path", null, ["string"], [e]);
1218
+ this[h].ccall(
1219
+ "wasm_set_phpini_path",
1220
+ null,
1221
+ ["string"],
1222
+ [e]
1223
+ );
507
1224
  }
508
1225
  /** @inheritDoc */
509
- setPhpIniEntry(e, n) {
510
- if (this.#n)
1226
+ setPhpIniEntry(e, r) {
1227
+ if (this.#t)
511
1228
  throw new Error("Cannot set PHP ini entries after calling run().");
512
- this.#t.push([e, n]);
1229
+ this.#e.push([e, r]);
513
1230
  }
514
1231
  /** @inheritDoc */
515
1232
  chdir(e) {
516
- this.#e.FS.chdir(e);
1233
+ this[h].FS.chdir(e);
517
1234
  }
518
1235
  /** @inheritDoc */
519
- async request(e, n) {
1236
+ async request(e, r) {
520
1237
  if (!this.requestHandler)
521
1238
  throw new Error("No request handler available.");
522
- return this.requestHandler.request(e, n);
1239
+ return this.requestHandler.request(e, r);
523
1240
  }
524
1241
  /** @inheritDoc */
525
- async run(e = {}) {
526
- this.#n || (this.#r(), this.#n = !0), this.#u(e.scriptPath || ""), this.#o(e.relativeUri || ""), this.#a(e.method || "GET");
527
- const { host: n, ...r } = {
1242
+ async run(e) {
1243
+ this.#t || (this.#n(), this.#t = !0), this.#l(e.scriptPath || ""), this.#i(e.relativeUri || ""), this.#o(e.method || "GET");
1244
+ const { host: r, ...s } = {
528
1245
  host: "example.com:443",
529
- ...K(e.headers || {})
1246
+ ...ie(e.headers || {})
530
1247
  };
531
- if (this.#s(n, e.protocol || "http"), this.#l(r), e.body && this.#c(e.body), e.fileInfos)
532
- for (const o of e.fileInfos)
533
- this.#d(o);
534
- return e.code && this.#h(" ?>" + e.code), await this.#p();
535
- }
536
- #r() {
537
- if (this.#t.length > 0) {
538
- const e = this.#t.map(([n, r]) => `${n}=${r}`).join(`
1248
+ if (this.#r(r, e.protocol || "http"), this.#a(s), e.body && this.#c(e.body), e.fileInfos)
1249
+ for (const n of e.fileInfos)
1250
+ this.#u(n);
1251
+ return e.code && this.#h(" ?>" + e.code), await this.#d();
1252
+ }
1253
+ #n() {
1254
+ if (this.#e.length > 0) {
1255
+ const e = this.#e.map(([r, s]) => `${r}=${s}`).join(`
539
1256
  `) + `
540
1257
 
541
1258
  `;
542
- this.#e.ccall(
1259
+ this[h].ccall(
543
1260
  "wasm_set_phpini_entries",
544
1261
  null,
545
1262
  [f],
546
1263
  [e]
547
1264
  );
548
1265
  }
549
- this.#e.ccall("php_wasm_init", null, [], []);
550
- }
551
- cli(e) {
552
- for (const n of e)
553
- this.#e.ccall("wasm_add_cli_arg", null, [f], [n]);
554
- return this.#e.ccall("run_cli", null, [], [], { async: !0 });
1266
+ this[h].ccall("php_wasm_init", null, [], []);
555
1267
  }
556
- #i() {
1268
+ #s() {
557
1269
  const e = "/tmp/headers.json";
558
1270
  if (!this.fileExists(e))
559
1271
  throw new Error(
560
1272
  "SAPI Error: Could not find response headers file."
561
1273
  );
562
- const n = JSON.parse(this.readFileAsText(e)), r = {};
563
- for (const o of n.headers) {
564
- if (!o.includes(": "))
1274
+ const r = JSON.parse(this.readFileAsText(e)), s = {};
1275
+ for (const n of r.headers) {
1276
+ if (!n.includes(": "))
565
1277
  continue;
566
- const a = o.indexOf(": "), i = o.substring(0, a).toLowerCase(), d = o.substring(a + 2);
567
- i in r || (r[i] = []), r[i].push(d);
1278
+ const i = n.indexOf(": "), o = n.substring(0, i).toLowerCase(), a = n.substring(i + 2);
1279
+ o in s || (s[o] = []), s[o].push(a);
568
1280
  }
569
1281
  return {
570
- headers: r,
571
- httpStatusCode: n.status
1282
+ headers: s,
1283
+ httpStatusCode: r.status
572
1284
  };
573
1285
  }
574
- #o(e) {
575
- if (this.#e.ccall("wasm_set_request_uri", null, [f], [e]), e.includes("?")) {
576
- const n = e.substring(e.indexOf("?") + 1);
577
- this.#e.ccall(
1286
+ #i(e) {
1287
+ if (this[h].ccall(
1288
+ "wasm_set_request_uri",
1289
+ null,
1290
+ [f],
1291
+ [e]
1292
+ ), e.includes("?")) {
1293
+ const r = e.substring(e.indexOf("?") + 1);
1294
+ this[h].ccall(
578
1295
  "wasm_set_query_string",
579
1296
  null,
580
1297
  [f],
581
- [n]
1298
+ [r]
582
1299
  );
583
1300
  }
584
1301
  }
585
- #s(e, n) {
586
- this.#e.ccall("wasm_set_request_host", null, [f], [e]);
587
- let r;
1302
+ #r(e, r) {
1303
+ this[h].ccall(
1304
+ "wasm_set_request_host",
1305
+ null,
1306
+ [f],
1307
+ [e]
1308
+ );
1309
+ let s;
588
1310
  try {
589
- r = parseInt(new URL(e).port, 10);
1311
+ s = parseInt(new URL(e).port, 10);
590
1312
  } catch {
591
1313
  }
592
- (!r || isNaN(r) || r === 80) && (r = n === "https" ? 443 : 80), this.#e.ccall("wasm_set_request_port", null, [g], [r]), (n === "https" || !n && r === 443) && this.addServerGlobalEntry("HTTPS", "on");
593
- }
594
- #a(e) {
595
- this.#e.ccall("wasm_set_request_method", null, [f], [e]);
1314
+ (!s || isNaN(s) || s === 80) && (s = r === "https" ? 443 : 80), this[h].ccall(
1315
+ "wasm_set_request_port",
1316
+ null,
1317
+ [_],
1318
+ [s]
1319
+ ), (r === "https" || !r && s === 443) && this.addServerGlobalEntry("HTTPS", "on");
596
1320
  }
597
- setSkipShebang(e) {
598
- this.#e.ccall(
599
- "wasm_set_skip_shebang",
1321
+ #o(e) {
1322
+ this[h].ccall(
1323
+ "wasm_set_request_method",
600
1324
  null,
601
- [g],
602
- [e ? 1 : 0]
1325
+ [f],
1326
+ [e]
603
1327
  );
604
1328
  }
605
- #l(e) {
606
- e.cookie && this.#e.ccall(
1329
+ #a(e) {
1330
+ e.cookie && this[h].ccall(
607
1331
  "wasm_set_cookies",
608
1332
  null,
609
1333
  [f],
610
1334
  [e.cookie]
611
- ), e["content-type"] && this.#e.ccall(
1335
+ ), e["content-type"] && this[h].ccall(
612
1336
  "wasm_set_content_type",
613
1337
  null,
614
1338
  [f],
615
1339
  [e["content-type"]]
616
- ), e["content-length"] && this.#e.ccall(
1340
+ ), e["content-length"] && this[h].ccall(
617
1341
  "wasm_set_content_length",
618
1342
  null,
619
- [g],
1343
+ [_],
620
1344
  [parseInt(e["content-length"], 10)]
621
1345
  );
622
- for (const n in e)
1346
+ for (const r in e)
623
1347
  this.addServerGlobalEntry(
624
- `HTTP_${n.toUpperCase().replace(/-/g, "_")}`,
625
- e[n]
1348
+ `HTTP_${r.toUpperCase().replace(/-/g, "_")}`,
1349
+ e[r]
626
1350
  );
627
1351
  }
628
1352
  #c(e) {
629
- this.#e.ccall("wasm_set_request_body", null, [f], [e]), this.#e.ccall(
1353
+ this[h].ccall(
1354
+ "wasm_set_request_body",
1355
+ null,
1356
+ [f],
1357
+ [e]
1358
+ ), this[h].ccall(
630
1359
  "wasm_set_content_length",
631
1360
  null,
632
- [g],
1361
+ [_],
633
1362
  [e.length]
634
1363
  );
635
1364
  }
636
- #u(e) {
637
- this.#e.ccall("wasm_set_path_translated", null, [f], [e]);
1365
+ #l(e) {
1366
+ this[h].ccall(
1367
+ "wasm_set_path_translated",
1368
+ null,
1369
+ [f],
1370
+ [e]
1371
+ );
638
1372
  }
639
- addServerGlobalEntry(e, n) {
640
- this.#e.ccall(
1373
+ addServerGlobalEntry(e, r) {
1374
+ this[h].ccall(
641
1375
  "wasm_add_SERVER_entry",
642
1376
  null,
643
1377
  [f, f],
644
- [e, n]
1378
+ [e, r]
645
1379
  );
646
1380
  }
647
1381
  /**
@@ -653,136 +1387,472 @@ class y {
653
1387
  *
654
1388
  * @param fileInfo - File details
655
1389
  */
656
- #d(e) {
657
- const { key: n, name: r, type: o, data: a } = e, i = `/tmp/${Math.random().toFixed(20)}`;
658
- this.writeFile(i, a);
659
- const d = 0;
660
- this.#e.ccall(
1390
+ #u(e) {
1391
+ const { key: r, name: s, type: n, data: i } = e, o = `/tmp/${Math.random().toFixed(20)}`;
1392
+ this.writeFile(o, i);
1393
+ const a = 0;
1394
+ this[h].ccall(
661
1395
  "wasm_add_uploaded_file",
662
1396
  null,
663
- [f, f, f, f, g, g],
664
- [n, r, o, i, d, a.byteLength]
1397
+ [f, f, f, f, _, _],
1398
+ [r, s, n, o, a, i.byteLength]
1399
+ );
1400
+ }
1401
+ #h(e) {
1402
+ this[h].ccall(
1403
+ "wasm_set_php_code",
1404
+ null,
1405
+ [f],
1406
+ [e]
1407
+ );
1408
+ }
1409
+ async #d() {
1410
+ const e = await await this[h].ccall(
1411
+ "wasm_sapi_handle_request",
1412
+ _,
1413
+ [],
1414
+ []
1415
+ ), { headers: r, httpStatusCode: s } = this.#s();
1416
+ return new v(
1417
+ s,
1418
+ r,
1419
+ this.readFileAsBuffer("/tmp/stdout"),
1420
+ this.readFileAsText("/tmp/stderr"),
1421
+ e
1422
+ );
1423
+ }
1424
+ mkdir(e) {
1425
+ this[h].FS.mkdirTree(e);
1426
+ }
1427
+ mkdirTree(e) {
1428
+ this.mkdir(e);
1429
+ }
1430
+ readFileAsText(e) {
1431
+ return new TextDecoder().decode(this.readFileAsBuffer(e));
1432
+ }
1433
+ readFileAsBuffer(e) {
1434
+ return this[h].FS.readFile(e);
1435
+ }
1436
+ writeFile(e, r) {
1437
+ this[h].FS.writeFile(e, r);
1438
+ }
1439
+ unlink(e) {
1440
+ this[h].FS.unlink(e);
1441
+ }
1442
+ mv(e, r) {
1443
+ this[h].FS.mv(e, r);
1444
+ }
1445
+ rmdir(e, r = { recursive: !0 }) {
1446
+ r?.recursive && this.listFiles(e).forEach((s) => {
1447
+ const n = `${e}/${s}`;
1448
+ this.isDir(n) ? this.rmdir(n, r) : this.unlink(n);
1449
+ }), this[h].FS.rmdir(e);
1450
+ }
1451
+ listFiles(e) {
1452
+ if (!this.fileExists(e))
1453
+ return [];
1454
+ try {
1455
+ return this[h].FS.readdir(e).filter(
1456
+ (r) => r !== "." && r !== ".."
1457
+ );
1458
+ } catch (r) {
1459
+ return console.error(r, { path: e }), [];
1460
+ }
1461
+ }
1462
+ isDir(e) {
1463
+ return this.fileExists(e) ? this[h].FS.isDir(
1464
+ this[h].FS.lookupPath(e).node.mode
1465
+ ) : !1;
1466
+ }
1467
+ fileExists(e) {
1468
+ try {
1469
+ return this[h].FS.lookupPath(e), !0;
1470
+ } catch {
1471
+ return !1;
1472
+ }
1473
+ }
1474
+ }
1475
+ w([
1476
+ m('Could not create directory "{path}"')
1477
+ ], g.prototype, "mkdir", 1);
1478
+ w([
1479
+ m('Could not create directory "{path}"')
1480
+ ], g.prototype, "mkdirTree", 1);
1481
+ w([
1482
+ m('Could not read "{path}"')
1483
+ ], g.prototype, "readFileAsText", 1);
1484
+ w([
1485
+ m('Could not read "{path}"')
1486
+ ], g.prototype, "readFileAsBuffer", 1);
1487
+ w([
1488
+ m('Could not write to "{path}"')
1489
+ ], g.prototype, "writeFile", 1);
1490
+ w([
1491
+ m('Could not unlink "{path}"')
1492
+ ], g.prototype, "unlink", 1);
1493
+ w([
1494
+ m('Could not move "{path}"')
1495
+ ], g.prototype, "mv", 1);
1496
+ w([
1497
+ m('Could not remove directory "{path}"')
1498
+ ], g.prototype, "rmdir", 1);
1499
+ w([
1500
+ m('Could not list files in "{path}"')
1501
+ ], g.prototype, "listFiles", 1);
1502
+ w([
1503
+ m('Could not stat "{path}"')
1504
+ ], g.prototype, "isDir", 1);
1505
+ w([
1506
+ m('Could not stat "{path}"')
1507
+ ], g.prototype, "fileExists", 1);
1508
+ function ie(t) {
1509
+ const e = {};
1510
+ for (const r in t)
1511
+ e[r.toLowerCase()] = t[r];
1512
+ return e;
1513
+ }
1514
+ const st = [
1515
+ "vfs",
1516
+ "literal",
1517
+ "wordpress.org/themes",
1518
+ "wordpress.org/plugins",
1519
+ "url"
1520
+ ];
1521
+ function nt(t) {
1522
+ return t && typeof t == "object" && typeof t.resource == "string" && st.includes(t.resource);
1523
+ }
1524
+ class b {
1525
+ /**
1526
+ * Creates a new Resource based on the given file reference
1527
+ *
1528
+ * @param ref The file reference to create the Resource for
1529
+ * @param options Additional options for the Resource
1530
+ * @returns A new Resource instance
1531
+ */
1532
+ static create(e, { semaphore: r, progress: s }) {
1533
+ let n;
1534
+ switch (e.resource) {
1535
+ case "vfs":
1536
+ n = new it(e, s);
1537
+ break;
1538
+ case "literal":
1539
+ n = new ot(e, s);
1540
+ break;
1541
+ case "wordpress.org/themes":
1542
+ n = new lt(e, s);
1543
+ break;
1544
+ case "wordpress.org/plugins":
1545
+ n = new ut(e, s);
1546
+ break;
1547
+ case "url":
1548
+ n = new ct(e, s);
1549
+ break;
1550
+ default:
1551
+ throw new Error(`Invalid resource: ${e}`);
1552
+ }
1553
+ return n = new ht(n), r && (n = new dt(n, r)), n;
1554
+ }
1555
+ setPlayground(e) {
1556
+ this.playground = e;
1557
+ }
1558
+ /** Whether this Resource is loaded asynchronously */
1559
+ get isAsync() {
1560
+ return !1;
1561
+ }
1562
+ }
1563
+ class it extends b {
1564
+ /**
1565
+ * Creates a new instance of `VFSResource`.
1566
+ * @param playground The playground client.
1567
+ * @param resource The VFS reference.
1568
+ * @param progress The progress tracker.
1569
+ */
1570
+ constructor(e, r) {
1571
+ super(), this.resource = e, this.progress = r;
1572
+ }
1573
+ /** @inheritDoc */
1574
+ async resolve() {
1575
+ const e = await this.playground.readFileAsBuffer(
1576
+ this.resource.path
665
1577
  );
1578
+ return this.progress?.set(100), new File([e], this.name);
1579
+ }
1580
+ /** @inheritDoc */
1581
+ get name() {
1582
+ return this.resource.path;
1583
+ }
1584
+ }
1585
+ class ot extends b {
1586
+ /**
1587
+ * Creates a new instance of `LiteralResource`.
1588
+ * @param resource The literal reference.
1589
+ * @param progress The progress tracker.
1590
+ */
1591
+ constructor(e, r) {
1592
+ super(), this.resource = e, this.progress = r;
1593
+ }
1594
+ /** @inheritDoc */
1595
+ async resolve() {
1596
+ return this.progress?.set(100), new File([this.resource.contents], this.resource.name);
1597
+ }
1598
+ /** @inheritDoc */
1599
+ get name() {
1600
+ return this.resource.name;
1601
+ }
1602
+ }
1603
+ class q extends b {
1604
+ /**
1605
+ * Creates a new instance of `FetchResource`.
1606
+ * @param progress The progress tracker.
1607
+ */
1608
+ constructor(e) {
1609
+ super(), this.progress = e;
1610
+ }
1611
+ /** @inheritDoc */
1612
+ async resolve() {
1613
+ this.progress?.setCaption(this.caption);
1614
+ const e = this.getURL();
1615
+ let r = await fetch(e);
1616
+ if (r = await Be(
1617
+ r,
1618
+ this.progress?.loadingListener ?? at
1619
+ ), r.status !== 200)
1620
+ throw new Error(`Could not download "${e}"`);
1621
+ return new File([await r.blob()], this.name);
1622
+ }
1623
+ /**
1624
+ * Gets the caption for the progress tracker.
1625
+ * @returns The caption.
1626
+ */
1627
+ get caption() {
1628
+ return `Downloading ${this.name}`;
1629
+ }
1630
+ /** @inheritDoc */
1631
+ get name() {
1632
+ return this.getURL();
1633
+ }
1634
+ /** @inheritDoc */
1635
+ get isAsync() {
1636
+ return !0;
1637
+ }
1638
+ }
1639
+ const at = () => {
1640
+ };
1641
+ class ct extends q {
1642
+ /**
1643
+ * Creates a new instance of `UrlResource`.
1644
+ * @param resource The URL reference.
1645
+ * @param progress The progress tracker.
1646
+ */
1647
+ constructor(e, r) {
1648
+ super(r), this.resource = e;
1649
+ }
1650
+ /** @inheritDoc */
1651
+ getURL() {
1652
+ return this.resource.url;
1653
+ }
1654
+ /** @inheritDoc */
1655
+ get caption() {
1656
+ return this.resource.caption ?? super.caption;
1657
+ }
1658
+ }
1659
+ class lt extends q {
1660
+ constructor(e, r) {
1661
+ super(r), this.resource = e;
1662
+ }
1663
+ get name() {
1664
+ return A(this.resource.slug);
666
1665
  }
667
- #h(e) {
668
- this.#e.ccall("wasm_set_php_code", null, [f], [e]);
1666
+ getURL() {
1667
+ return "/plugin-proxy?theme=" + oe(this.resource.slug);
669
1668
  }
670
- async #p() {
671
- const e = await await this.#e.ccall(
672
- "wasm_sapi_handle_request",
673
- g,
674
- [],
675
- []
676
- ), { headers: n, httpStatusCode: r } = this.#i();
677
- return new E(
678
- r,
679
- n,
680
- this.readFileAsBuffer("/tmp/stdout"),
681
- this.readFileAsText("/tmp/stderr"),
682
- e
683
- );
1669
+ }
1670
+ class ut extends q {
1671
+ constructor(e, r) {
1672
+ super(r), this.resource = e;
684
1673
  }
685
- mkdir(e) {
686
- this.#e.FS.mkdirTree(e);
1674
+ /** @inheritDoc */
1675
+ get name() {
1676
+ return A(this.resource.slug);
687
1677
  }
688
- mkdirTree(e) {
689
- this.mkdir(e);
1678
+ /** @inheritDoc */
1679
+ getURL() {
1680
+ return "/plugin-proxy?plugin=" + oe(this.resource.slug);
690
1681
  }
691
- readFileAsText(e) {
692
- return new TextDecoder().decode(this.readFileAsBuffer(e));
1682
+ }
1683
+ function oe(t) {
1684
+ return !t || t.endsWith(".zip") ? t : t + ".latest-stable.zip";
1685
+ }
1686
+ class ae extends b {
1687
+ constructor(e) {
1688
+ super(), this.resource = e;
693
1689
  }
694
- readFileAsBuffer(e) {
695
- return this.#e.FS.readFile(e);
1690
+ /** @inheritDoc */
1691
+ async resolve() {
1692
+ return this.resource.resolve();
696
1693
  }
697
- writeFile(e, n) {
698
- this.#e.FS.writeFile(e, n);
1694
+ /** @inheritDoc */
1695
+ async setPlayground(e) {
1696
+ return this.resource.setPlayground(e);
699
1697
  }
700
- unlink(e) {
701
- this.#e.FS.unlink(e);
1698
+ /** @inheritDoc */
1699
+ get progress() {
1700
+ return this.resource.progress;
702
1701
  }
703
- listFiles(e) {
704
- if (!this.fileExists(e))
705
- return [];
706
- try {
707
- return this.#e.FS.readdir(e).filter(
708
- (n) => n !== "." && n !== ".."
709
- );
710
- } catch (n) {
711
- return console.error(n, { path: e }), [];
712
- }
1702
+ /** @inheritDoc */
1703
+ set progress(e) {
1704
+ this.resource.progress = e;
713
1705
  }
714
- isDir(e) {
715
- return this.fileExists(e) ? this.#e.FS.isDir(
716
- this.#e.FS.lookupPath(e).node.mode
717
- ) : !1;
1706
+ /** @inheritDoc */
1707
+ get name() {
1708
+ return this.resource.name;
718
1709
  }
719
- fileExists(e) {
1710
+ /** @inheritDoc */
1711
+ get isAsync() {
1712
+ return this.resource.isAsync;
1713
+ }
1714
+ }
1715
+ class ht extends ae {
1716
+ /** @inheritDoc */
1717
+ async resolve() {
1718
+ return this.promise || (this.promise = super.resolve()), this.promise;
1719
+ }
1720
+ }
1721
+ class dt extends ae {
1722
+ constructor(e, r) {
1723
+ super(e), this.semaphore = r;
1724
+ }
1725
+ /** @inheritDoc */
1726
+ async resolve() {
1727
+ return this.isAsync ? this.semaphore.run(() => super.resolve()) : super.resolve();
1728
+ }
1729
+ }
1730
+ const pt = ["6.2", "6.1", "6.0", "5.9"];
1731
+ function ft(t, {
1732
+ progress: e = new L(),
1733
+ semaphore: r = new te({ concurrency: 3 }),
1734
+ onStepCompleted: s = () => {
1735
+ }
1736
+ } = {}) {
1737
+ const n = (t.steps || []).filter(mt), i = n.reduce(
1738
+ (a, l) => a + (l.progress?.weight || 1),
1739
+ 0
1740
+ ), o = n.map(
1741
+ (a) => wt(a, {
1742
+ semaphore: r,
1743
+ rootProgressTracker: e,
1744
+ totalProgressWeight: i
1745
+ })
1746
+ );
1747
+ return {
1748
+ versions: {
1749
+ php: Y(
1750
+ t.preferredVersions?.php,
1751
+ D,
1752
+ Ve
1753
+ ),
1754
+ wp: Y(
1755
+ t.preferredVersions?.wp,
1756
+ pt,
1757
+ "6.2"
1758
+ )
1759
+ },
1760
+ run: async (a) => {
1761
+ try {
1762
+ for (const { resources: l } of o)
1763
+ for (const c of l)
1764
+ c.setPlayground(a), c.isAsync && c.resolve();
1765
+ for (const { run: l, step: c } of o) {
1766
+ const u = await l(a);
1767
+ s(u, c);
1768
+ }
1769
+ try {
1770
+ await a.goTo(
1771
+ t.landingPage || "/"
1772
+ );
1773
+ } catch {
1774
+ }
1775
+ } finally {
1776
+ e.finish();
1777
+ }
1778
+ }
1779
+ };
1780
+ }
1781
+ function Y(t, e, r) {
1782
+ return t && e.includes(t) ? t : r;
1783
+ }
1784
+ function mt(t) {
1785
+ return !!(typeof t == "object" && t);
1786
+ }
1787
+ function wt(t, {
1788
+ semaphore: e,
1789
+ rootProgressTracker: r,
1790
+ totalProgressWeight: s
1791
+ }) {
1792
+ const n = r.stage(
1793
+ (t.progress?.weight || 1) / s
1794
+ ), i = {};
1795
+ for (const u of Object.keys(t)) {
1796
+ let d = t[u];
1797
+ nt(d) && (d = b.create(d, {
1798
+ semaphore: e
1799
+ })), i[u] = d;
1800
+ }
1801
+ const o = async (u) => {
720
1802
  try {
721
- return this.#e.FS.lookupPath(e), !0;
722
- } catch {
723
- return !1;
1803
+ return n.fillSlowly(), await Me[t.step](
1804
+ u,
1805
+ await gt(i),
1806
+ {
1807
+ tracker: n,
1808
+ initialCaption: t.progress?.caption
1809
+ }
1810
+ );
1811
+ } finally {
1812
+ n.finish();
724
1813
  }
1814
+ }, a = Q(i), l = Q(i).filter(
1815
+ (u) => u.isAsync
1816
+ ), c = 1 / (l.length + 1);
1817
+ for (const u of l)
1818
+ u.progress = n.stage(c);
1819
+ return { run: o, step: t, resources: a };
1820
+ }
1821
+ function Q(t) {
1822
+ const e = [];
1823
+ for (const r in t) {
1824
+ const s = t[r];
1825
+ s instanceof b && e.push(s);
725
1826
  }
726
- mount(e, n) {
727
- this.#e.FS.mount(
728
- this.#e.FS.filesystems.NODEFS,
729
- typeof e == "object" ? e : { root: e },
730
- n
731
- );
732
- }
1827
+ return e;
733
1828
  }
734
- w([
735
- m('Could not create directory "{path}"')
736
- ], y.prototype, "mkdir", 1);
737
- w([
738
- m('Could not create directory "{path}"')
739
- ], y.prototype, "mkdirTree", 1);
740
- w([
741
- m('Could not read "{path}"')
742
- ], y.prototype, "readFileAsText", 1);
743
- w([
744
- m('Could not read "{path}"')
745
- ], y.prototype, "readFileAsBuffer", 1);
746
- w([
747
- m('Could not write to "{path}"')
748
- ], y.prototype, "writeFile", 1);
749
- w([
750
- m('Could not unlink "{path}"')
751
- ], y.prototype, "unlink", 1);
752
- w([
753
- m('Could not list files in "{path}"')
754
- ], y.prototype, "listFiles", 1);
755
- w([
756
- m('Could not stat "{path}"')
757
- ], y.prototype, "isDir", 1);
758
- w([
759
- m('Could not stat "{path}"')
760
- ], y.prototype, "fileExists", 1);
761
- w([
762
- m("Could not mount a directory")
763
- ], y.prototype, "mount", 1);
764
- function K(t) {
1829
+ async function gt(t) {
765
1830
  const e = {};
766
- for (const n in t)
767
- e[n.toLowerCase()] = t[n];
1831
+ for (const r in t) {
1832
+ const s = t[r];
1833
+ s instanceof b ? e[r] = await s.resolve() : e[r] = s;
1834
+ }
768
1835
  return e;
769
1836
  }
1837
+ async function yt(t, e) {
1838
+ await t.run(e);
1839
+ }
770
1840
  /**
771
1841
  * @license
772
1842
  * Copyright 2019 Google LLC
773
1843
  * SPDX-License-Identifier: Apache-2.0
774
1844
  */
775
- const X = Symbol("Comlink.proxy"), pe = Symbol("Comlink.endpoint"), fe = Symbol("Comlink.releaseProxy"), D = Symbol("Comlink.finalizer"), O = Symbol("Comlink.thrown"), J = (t) => typeof t == "object" && t !== null || typeof t == "function", me = {
776
- canHandle: (t) => J(t) && t[X],
1845
+ const ce = Symbol("Comlink.proxy"), Pt = Symbol("Comlink.endpoint"), bt = Symbol("Comlink.releaseProxy"), I = Symbol("Comlink.finalizer"), F = Symbol("Comlink.thrown"), le = (t) => typeof t == "object" && t !== null || typeof t == "function", _t = {
1846
+ canHandle: (t) => le(t) && t[ce],
777
1847
  serialize(t) {
778
- const { port1: e, port2: n } = new MessageChannel();
779
- return M(t, e), [n, [n]];
1848
+ const { port1: e, port2: r } = new MessageChannel();
1849
+ return W(t, e), [r, [r]];
780
1850
  },
781
1851
  deserialize(t) {
782
- return t.start(), N(t);
1852
+ return t.start(), M(t);
783
1853
  }
784
- }, we = {
785
- canHandle: (t) => J(t) && O in t,
1854
+ }, $t = {
1855
+ canHandle: (t) => le(t) && F in t,
786
1856
  serialize({ value: t }) {
787
1857
  let e;
788
1858
  return t instanceof Error ? e = {
@@ -797,191 +1867,191 @@ const X = Symbol("Comlink.proxy"), pe = Symbol("Comlink.endpoint"), fe = Symbol(
797
1867
  deserialize(t) {
798
1868
  throw t.isError ? Object.assign(new Error(t.value.message), t.value) : t.value;
799
1869
  }
800
- }, T = /* @__PURE__ */ new Map([
801
- ["proxy", me],
802
- ["throw", we]
1870
+ }, R = /* @__PURE__ */ new Map([
1871
+ ["proxy", _t],
1872
+ ["throw", $t]
803
1873
  ]);
804
- function ye(t, e) {
805
- for (const n of t)
806
- if (e === n || n === "*" || n instanceof RegExp && n.test(e))
1874
+ function St(t, e) {
1875
+ for (const r of t)
1876
+ if (e === r || r === "*" || r instanceof RegExp && r.test(e))
807
1877
  return !0;
808
1878
  return !1;
809
1879
  }
810
- function M(t, e = globalThis, n = ["*"]) {
811
- e.addEventListener("message", function r(o) {
812
- if (!o || !o.data)
1880
+ function W(t, e = globalThis, r = ["*"]) {
1881
+ e.addEventListener("message", function s(n) {
1882
+ if (!n || !n.data)
813
1883
  return;
814
- if (!ye(n, o.origin)) {
815
- console.warn(`Invalid origin '${o.origin}' for comlink proxy`);
1884
+ if (!St(r, n.origin)) {
1885
+ console.warn(`Invalid origin '${n.origin}' for comlink proxy`);
816
1886
  return;
817
1887
  }
818
- const { id: a, type: i, path: d } = Object.assign({ path: [] }, o.data), c = (o.data.argumentList || []).map(b);
819
- let s;
1888
+ const { id: i, type: o, path: a } = Object.assign({ path: [] }, n.data), l = (n.data.argumentList || []).map(P);
1889
+ let c;
820
1890
  try {
821
- const l = d.slice(0, -1).reduce((u, p) => u[p], t), h = d.reduce((u, p) => u[p], t);
822
- switch (i) {
1891
+ const u = a.slice(0, -1).reduce((p, y) => p[y], t), d = a.reduce((p, y) => p[y], t);
1892
+ switch (o) {
823
1893
  case "GET":
824
- s = h;
1894
+ c = d;
825
1895
  break;
826
1896
  case "SET":
827
- l[d.slice(-1)[0]] = b(o.data.value), s = !0;
1897
+ u[a.slice(-1)[0]] = P(n.data.value), c = !0;
828
1898
  break;
829
1899
  case "APPLY":
830
- s = h.apply(l, c);
1900
+ c = d.apply(u, l);
831
1901
  break;
832
1902
  case "CONSTRUCT":
833
1903
  {
834
- const u = new h(...c);
835
- s = xe(u);
1904
+ const p = new d(...l);
1905
+ c = Ft(p);
836
1906
  }
837
1907
  break;
838
1908
  case "ENDPOINT":
839
1909
  {
840
- const { port1: u, port2: p } = new MessageChannel();
841
- M(t, p), s = Ee(u, [u]);
1910
+ const { port1: p, port2: y } = new MessageChannel();
1911
+ W(t, y), c = xt(p, [p]);
842
1912
  }
843
1913
  break;
844
1914
  case "RELEASE":
845
- s = void 0;
1915
+ c = void 0;
846
1916
  break;
847
1917
  default:
848
1918
  return;
849
1919
  }
850
- } catch (l) {
851
- s = { value: l, [O]: 0 };
1920
+ } catch (u) {
1921
+ c = { value: u, [F]: 0 };
852
1922
  }
853
- Promise.resolve(s).catch((l) => ({ value: l, [O]: 0 })).then((l) => {
854
- const [h, u] = U(l);
855
- e.postMessage(Object.assign(Object.assign({}, h), { id: a }), u), i === "RELEASE" && (e.removeEventListener("message", r), Y(e), D in t && typeof t[D] == "function" && t[D]());
856
- }).catch((l) => {
857
- const [h, u] = U({
1923
+ Promise.resolve(c).catch((u) => ({ value: u, [F]: 0 })).then((u) => {
1924
+ const [d, p] = U(u);
1925
+ e.postMessage(Object.assign(Object.assign({}, d), { id: i }), p), o === "RELEASE" && (e.removeEventListener("message", s), ue(e), I in t && typeof t[I] == "function" && t[I]());
1926
+ }).catch((u) => {
1927
+ const [d, p] = U({
858
1928
  value: new TypeError("Unserializable return value"),
859
- [O]: 0
1929
+ [F]: 0
860
1930
  });
861
- e.postMessage(Object.assign(Object.assign({}, h), { id: a }), u);
1931
+ e.postMessage(Object.assign(Object.assign({}, d), { id: i }), p);
862
1932
  });
863
1933
  }), e.start && e.start();
864
1934
  }
865
- function ge(t) {
1935
+ function vt(t) {
866
1936
  return t.constructor.name === "MessagePort";
867
1937
  }
868
- function Y(t) {
869
- ge(t) && t.close();
1938
+ function ue(t) {
1939
+ vt(t) && t.close();
870
1940
  }
871
- function N(t, e) {
872
- return I(t, [], e);
1941
+ function M(t, e) {
1942
+ return N(t, [], e);
873
1943
  }
874
- function k(t) {
1944
+ function x(t) {
875
1945
  if (t)
876
1946
  throw new Error("Proxy has been released and is not useable");
877
1947
  }
878
- function Q(t) {
879
- return P(t, {
1948
+ function he(t) {
1949
+ return $(t, {
880
1950
  type: "RELEASE"
881
1951
  }).then(() => {
882
- Y(t);
1952
+ ue(t);
883
1953
  });
884
1954
  }
885
- const A = /* @__PURE__ */ new WeakMap(), L = "FinalizationRegistry" in globalThis && new FinalizationRegistry((t) => {
886
- const e = (A.get(t) || 0) - 1;
887
- A.set(t, e), e === 0 && Q(t);
1955
+ const k = /* @__PURE__ */ new WeakMap(), O = "FinalizationRegistry" in globalThis && new FinalizationRegistry((t) => {
1956
+ const e = (k.get(t) || 0) - 1;
1957
+ k.set(t, e), e === 0 && he(t);
888
1958
  });
889
- function be(t, e) {
890
- const n = (A.get(e) || 0) + 1;
891
- A.set(e, n), L && L.register(t, e, t);
1959
+ function Et(t, e) {
1960
+ const r = (k.get(e) || 0) + 1;
1961
+ k.set(e, r), O && O.register(t, e, t);
892
1962
  }
893
- function ve(t) {
894
- L && L.unregister(t);
1963
+ function Rt(t) {
1964
+ O && O.unregister(t);
895
1965
  }
896
- function I(t, e = [], n = function() {
1966
+ function N(t, e = [], r = function() {
897
1967
  }) {
898
- let r = !1;
899
- const o = new Proxy(n, {
900
- get(a, i) {
901
- if (k(r), i === fe)
1968
+ let s = !1;
1969
+ const n = new Proxy(r, {
1970
+ get(i, o) {
1971
+ if (x(s), o === bt)
902
1972
  return () => {
903
- ve(o), Q(t), r = !0;
1973
+ Rt(n), he(t), s = !0;
904
1974
  };
905
- if (i === "then") {
1975
+ if (o === "then") {
906
1976
  if (e.length === 0)
907
- return { then: () => o };
908
- const d = P(t, {
1977
+ return { then: () => n };
1978
+ const a = $(t, {
909
1979
  type: "GET",
910
- path: e.map((c) => c.toString())
911
- }).then(b);
912
- return d.then.bind(d);
1980
+ path: e.map((l) => l.toString())
1981
+ }).then(P);
1982
+ return a.then.bind(a);
913
1983
  }
914
- return I(t, [...e, i]);
1984
+ return N(t, [...e, o]);
915
1985
  },
916
- set(a, i, d) {
917
- k(r);
918
- const [c, s] = U(d);
919
- return P(t, {
1986
+ set(i, o, a) {
1987
+ x(s);
1988
+ const [l, c] = U(a);
1989
+ return $(t, {
920
1990
  type: "SET",
921
- path: [...e, i].map((l) => l.toString()),
922
- value: c
923
- }, s).then(b);
1991
+ path: [...e, o].map((u) => u.toString()),
1992
+ value: l
1993
+ }, c).then(P);
924
1994
  },
925
- apply(a, i, d) {
926
- k(r);
927
- const c = e[e.length - 1];
928
- if (c === pe)
929
- return P(t, {
1995
+ apply(i, o, a) {
1996
+ x(s);
1997
+ const l = e[e.length - 1];
1998
+ if (l === Pt)
1999
+ return $(t, {
930
2000
  type: "ENDPOINT"
931
- }).then(b);
932
- if (c === "bind")
933
- return I(t, e.slice(0, -1));
934
- const [s, l] = V(d);
935
- return P(t, {
2001
+ }).then(P);
2002
+ if (l === "bind")
2003
+ return N(t, e.slice(0, -1));
2004
+ const [c, u] = X(a);
2005
+ return $(t, {
936
2006
  type: "APPLY",
937
- path: e.map((h) => h.toString()),
938
- argumentList: s
939
- }, l).then(b);
2007
+ path: e.map((d) => d.toString()),
2008
+ argumentList: c
2009
+ }, u).then(P);
940
2010
  },
941
- construct(a, i) {
942
- k(r);
943
- const [d, c] = V(i);
944
- return P(t, {
2011
+ construct(i, o) {
2012
+ x(s);
2013
+ const [a, l] = X(o);
2014
+ return $(t, {
945
2015
  type: "CONSTRUCT",
946
- path: e.map((s) => s.toString()),
947
- argumentList: d
948
- }, c).then(b);
2016
+ path: e.map((c) => c.toString()),
2017
+ argumentList: a
2018
+ }, l).then(P);
949
2019
  }
950
2020
  });
951
- return be(o, t), o;
2021
+ return Et(n, t), n;
952
2022
  }
953
- function Pe(t) {
2023
+ function Tt(t) {
954
2024
  return Array.prototype.concat.apply([], t);
955
2025
  }
956
- function V(t) {
2026
+ function X(t) {
957
2027
  const e = t.map(U);
958
- return [e.map((n) => n[0]), Pe(e.map((n) => n[1]))];
2028
+ return [e.map((r) => r[0]), Tt(e.map((r) => r[1]))];
959
2029
  }
960
- const ee = /* @__PURE__ */ new WeakMap();
961
- function Ee(t, e) {
962
- return ee.set(t, e), t;
2030
+ const de = /* @__PURE__ */ new WeakMap();
2031
+ function xt(t, e) {
2032
+ return de.set(t, e), t;
963
2033
  }
964
- function xe(t) {
965
- return Object.assign(t, { [X]: !0 });
2034
+ function Ft(t) {
2035
+ return Object.assign(t, { [ce]: !0 });
966
2036
  }
967
- function $e(t, e = globalThis, n = "*") {
2037
+ function Ct(t, e = globalThis, r = "*") {
968
2038
  return {
969
- postMessage: (r, o) => t.postMessage(r, n, o),
2039
+ postMessage: (s, n) => t.postMessage(s, r, n),
970
2040
  addEventListener: e.addEventListener.bind(e),
971
2041
  removeEventListener: e.removeEventListener.bind(e)
972
2042
  };
973
2043
  }
974
2044
  function U(t) {
975
- for (const [e, n] of T)
976
- if (n.canHandle(t)) {
977
- const [r, o] = n.serialize(t);
2045
+ for (const [e, r] of R)
2046
+ if (r.canHandle(t)) {
2047
+ const [s, n] = r.serialize(t);
978
2048
  return [
979
2049
  {
980
2050
  type: "HANDLER",
981
2051
  name: e,
982
- value: r
2052
+ value: s
983
2053
  },
984
- o
2054
+ n
985
2055
  ];
986
2056
  }
987
2057
  return [
@@ -989,35 +2059,35 @@ function U(t) {
989
2059
  type: "RAW",
990
2060
  value: t
991
2061
  },
992
- ee.get(t) || []
2062
+ de.get(t) || []
993
2063
  ];
994
2064
  }
995
- function b(t) {
2065
+ function P(t) {
996
2066
  switch (t.type) {
997
2067
  case "HANDLER":
998
- return T.get(t.name).deserialize(t.value);
2068
+ return R.get(t.name).deserialize(t.value);
999
2069
  case "RAW":
1000
2070
  return t.value;
1001
2071
  }
1002
2072
  }
1003
- function P(t, e, n) {
1004
- return new Promise((r) => {
1005
- const o = Fe();
1006
- t.addEventListener("message", function a(i) {
1007
- !i.data || !i.data.id || i.data.id !== o || (t.removeEventListener("message", a), r(i.data));
1008
- }), t.start && t.start(), t.postMessage(Object.assign({ id: o }, e), n);
2073
+ function $(t, e, r) {
2074
+ return new Promise((s) => {
2075
+ const n = kt();
2076
+ t.addEventListener("message", function i(o) {
2077
+ !o.data || !o.data.id || o.data.id !== n || (t.removeEventListener("message", i), s(o.data));
2078
+ }), t.start && t.start(), t.postMessage(Object.assign({ id: n }, e), r);
1009
2079
  });
1010
2080
  }
1011
- function Fe() {
2081
+ function kt() {
1012
2082
  return new Array(4).fill(0).map(() => Math.floor(Math.random() * Number.MAX_SAFE_INTEGER).toString(16)).join("-");
1013
2083
  }
1014
- function Se(t) {
1015
- Te();
1016
- const e = t instanceof Worker ? t : $e(t);
1017
- return N(e);
2084
+ function pe(t) {
2085
+ Ot();
2086
+ const e = t instanceof Worker ? t : Ct(t);
2087
+ return M(e);
1018
2088
  }
1019
- function Te() {
1020
- T.set("EVENT", {
2089
+ function Ot() {
2090
+ R.set("EVENT", {
1021
2091
  canHandle: (t) => t instanceof CustomEvent,
1022
2092
  serialize: (t) => [
1023
2093
  {
@@ -1026,507 +2096,123 @@ function Te() {
1026
2096
  []
1027
2097
  ],
1028
2098
  deserialize: (t) => t
1029
- }), T.set("FUNCTION", {
2099
+ }), R.set("FUNCTION", {
1030
2100
  canHandle: (t) => typeof t == "function",
1031
2101
  serialize(t) {
1032
2102
  console.debug("[Comlink][Performance] Proxying a function");
1033
- const { port1: e, port2: n } = new MessageChannel();
1034
- return M(t, e), [n, [n]];
2103
+ const { port1: e, port2: r } = new MessageChannel();
2104
+ return W(t, e), [r, [r]];
1035
2105
  },
1036
2106
  deserialize(t) {
1037
- return t.start(), N(t);
2107
+ return t.start(), M(t);
1038
2108
  }
1039
- }), T.set("PHPResponse", {
2109
+ }), R.set("PHPResponse", {
1040
2110
  canHandle: (t) => typeof t == "object" && t !== null && "headers" in t && "bytes" in t && "errors" in t && "exitCode" in t && "httpStatusCode" in t,
1041
2111
  serialize(t) {
1042
2112
  return [t.toRawData(), []];
1043
2113
  },
1044
2114
  deserialize(t) {
1045
- return E.fromRawData(t);
2115
+ return v.fromRawData(t);
1046
2116
  }
1047
2117
  });
1048
2118
  }
1049
2119
  (function() {
1050
2120
  return typeof navigator < "u" && navigator?.userAgent?.toLowerCase().indexOf("firefox") > -1 ? "iframe" : "webworker";
1051
2121
  })();
1052
- var S = typeof globalThis < "u" ? globalThis : typeof window < "u" ? window : typeof global < "u" ? global : typeof self < "u" ? self : {}, z = {}, Re = {
1053
- get exports() {
1054
- return z;
1055
- },
1056
- set exports(t) {
1057
- z = t;
1058
- }
1059
- };
1060
- (function(t, e) {
1061
- (function(n, r) {
1062
- r();
1063
- })(S, function() {
1064
- function n(s, l) {
1065
- return typeof l > "u" ? l = { autoBom: !1 } : typeof l != "object" && (console.warn("Deprecated: Expected third argument to be a object"), l = { autoBom: !l }), l.autoBom && /^\s*(?:text\/\S*|application\/xml|\S*\/\S*\+xml)\s*;.*charset\s*=\s*utf-8/i.test(s.type) ? new Blob(["\uFEFF", s], { type: s.type }) : s;
1066
- }
1067
- function r(s, l, h) {
1068
- var u = new XMLHttpRequest();
1069
- u.open("GET", s), u.responseType = "blob", u.onload = function() {
1070
- c(u.response, l, h);
1071
- }, u.onerror = function() {
1072
- console.error("could not download file");
1073
- }, u.send();
1074
- }
1075
- function o(s) {
1076
- var l = new XMLHttpRequest();
1077
- l.open("HEAD", s, !1);
1078
- try {
1079
- l.send();
1080
- } catch {
1081
- }
1082
- return 200 <= l.status && 299 >= l.status;
1083
- }
1084
- function a(s) {
1085
- try {
1086
- s.dispatchEvent(new MouseEvent("click"));
1087
- } catch {
1088
- var l = document.createEvent("MouseEvents");
1089
- l.initMouseEvent("click", !0, !0, window, 0, 0, 0, 80, 20, !1, !1, !1, !1, 0, null), s.dispatchEvent(l);
1090
- }
1091
- }
1092
- var i = typeof window == "object" && window.window === window ? window : typeof self == "object" && self.self === self ? self : typeof S == "object" && S.global === S ? S : void 0, d = i.navigator && /Macintosh/.test(navigator.userAgent) && /AppleWebKit/.test(navigator.userAgent) && !/Safari/.test(navigator.userAgent), c = i.saveAs || (typeof window != "object" || window !== i ? function() {
1093
- } : "download" in HTMLAnchorElement.prototype && !d ? function(s, l, h) {
1094
- var u = i.URL || i.webkitURL, p = document.createElement("a");
1095
- l = l || s.name || "download", p.download = l, p.rel = "noopener", typeof s == "string" ? (p.href = s, p.origin === location.origin ? a(p) : o(p.href) ? r(s, l, h) : a(p, p.target = "_blank")) : (p.href = u.createObjectURL(s), setTimeout(function() {
1096
- u.revokeObjectURL(p.href);
1097
- }, 4e4), setTimeout(function() {
1098
- a(p);
1099
- }, 0));
1100
- } : "msSaveOrOpenBlob" in navigator ? function(s, l, h) {
1101
- if (l = l || s.name || "download", typeof s != "string")
1102
- navigator.msSaveOrOpenBlob(n(s, h), l);
1103
- else if (o(s))
1104
- r(s, l, h);
1105
- else {
1106
- var u = document.createElement("a");
1107
- u.href = s, u.target = "_blank", setTimeout(function() {
1108
- a(u);
1109
- });
1110
- }
1111
- } : function(s, l, h, u) {
1112
- if (u = u || open("", "_blank"), u && (u.document.title = u.document.body.innerText = "downloading..."), typeof s == "string")
1113
- return r(s, l, h);
1114
- var p = s.type === "application/octet-stream", x = /constructor/i.test(i.HTMLElement) || i.safari, _ = /CriOS\/[\d]+/.test(navigator.userAgent);
1115
- if ((_ || p && x || d) && typeof FileReader < "u") {
1116
- var $ = new FileReader();
1117
- $.onloadend = function() {
1118
- var F = $.result;
1119
- F = _ ? F : F.replace(/^data:[^;]*;/, "data:attachment/file;"), u ? u.location.href = F : location = F, u = null;
1120
- }, $.readAsDataURL(s);
1121
- } else {
1122
- var C = i.URL || i.webkitURL, v = C.createObjectURL(s);
1123
- u ? u.location = v : location.href = v, u = null, setTimeout(function() {
1124
- C.revokeObjectURL(v);
1125
- }, 4e4);
1126
- }
1127
- });
1128
- i.saveAs = c.saveAs = c, t.exports = c;
1129
- });
1130
- })(Re);
1131
- const q = `<?php
1132
-
1133
- function generateZipFile($exportPath, $databasePath, $docRoot) {
1134
- $zip = new ZipArchive;
1135
- $res = $zip->open($exportPath, ZipArchive::CREATE);
1136
- if ($res === TRUE) {
1137
- $zip->addFile($databasePath);
1138
- $directories = array();
1139
- $directories[] = $docRoot . '/';
1140
-
1141
- while(sizeof($directories)) {
1142
- $dir = array_pop($directories);
1143
-
1144
- if ($handle = opendir($dir)) {
1145
- while (false !== ($entry = readdir($handle))) {
1146
- if ($entry == '.' || $entry == '..') {
1147
- continue;
1148
- }
1149
-
1150
- $entry = $dir . $entry;
1151
-
1152
- if (
1153
- is_dir($entry) &&
1154
- strpos($entry, 'wp-content/database') == false &&
1155
- strpos($entry, 'wp-includes') == false
1156
- ) {
1157
- $directory_path = $entry . '/';
1158
- array_push($directories, $directory_path);
1159
- } else if (is_file($entry)) {
1160
- $zip->addFile($entry);
1161
- }
1162
- }
1163
- closedir($handle);
1164
- }
1165
- }
1166
- $zip->close();
1167
- chmod($exportPath, 0777);
1168
- }
1169
- }
1170
-
1171
- function readFileFromZipArchive($pathToZip, $pathToFile) {
1172
- chmod($pathToZip, 0777);
1173
- $zip = new ZipArchive;
1174
- $res = $zip->open($pathToZip);
1175
- if ($res === TRUE) {
1176
- $file = $zip->getFromName($pathToFile);
1177
- echo $file;
1178
- }
1179
- }
1180
-
1181
- function importZipFile($pathToZip) {
1182
- $zip = new ZipArchive;
1183
- $res = $zip->open($pathToZip);
1184
- if ($res === TRUE) {
1185
- $counter = 0;
1186
- while ($zip->statIndex($counter)) {
1187
- $file = $zip->statIndex($counter);
1188
- $filePath = $file['name'];
1189
- if (!file_exists(dirname($filePath))) {
1190
- mkdir(dirname($filePath), 0777, true);
1191
- }
1192
- $overwrite = fopen($filePath, 'w');
1193
- fwrite($overwrite, $zip->getFromIndex($counter));
1194
- $counter++;
1195
- }
1196
- $zip->close();
1197
- }
1198
- }
1199
- `, te = "databaseExport.xml", H = "/" + te;
1200
- async function Oe(t) {
1201
- const n = (await t.request({
1202
- url: "/wp-admin/export.php?download=true&content=all"
1203
- })).text;
1204
- await t.writeFile(H, n);
1205
- const r = await t.wordPressVersion, o = await t.phpVersion, a = await t.documentRoot, i = `wordpress-playground--wp${r}--php${o}.zip`, d = `/${i}`, c = await t.run({
1206
- code: q + ` generateZipFile('${d}', '${H}', '${a}');`
1207
- });
1208
- if (c.exitCode !== 0)
1209
- throw c.errors;
1210
- const s = await t.readFileAsBuffer(i), l = new File([s], i);
1211
- z.saveAs(l);
1212
- }
1213
- async function Ae(t, e) {
1214
- if (
1215
- // eslint-disable-next-line no-alert
1216
- !confirm(
1217
- "Are you sure you want to import this file? Previous data will be lost."
1218
- )
1219
- )
1220
- return !1;
1221
- const n = await e.arrayBuffer(), r = new Uint8Array(n), o = "/import.zip";
1222
- await t.writeFile(o, r);
1223
- const a = await t.run({
1224
- code: q + ` readFileFromZipArchive('${o}', '${H}');`
1225
- });
1226
- if (a.exitCode !== 0)
1227
- throw a.errors;
1228
- const i = new TextDecoder().decode(
1229
- a.bytes
1230
- ), d = new File(
1231
- [i],
1232
- te
1233
- ), c = await t.request({
1234
- url: "/wp-admin/admin.php?import=wordpress"
1235
- }), l = new DOMParser().parseFromString(
1236
- c.text,
1237
- "text/html"
1238
- ).getElementById("import-upload-form")?.getAttribute("action"), h = await t.request({
1239
- url: `/wp-admin/${l}`,
1240
- method: "POST",
1241
- files: { import: d }
1242
- }), p = new DOMParser().parseFromString(
1243
- h.text,
1244
- "text/html"
1245
- ).querySelector(
1246
- "#wpbody-content form"
1247
- ), x = p?.getAttribute(
1248
- "action"
1249
- ), _ = (p?.querySelector(
1250
- "input[name='_wpnonce']"
1251
- )).value, $ = (p?.querySelector(
1252
- "input[name='_wp_http_referer']"
1253
- )).value, C = (p?.querySelector(
1254
- "input[name='import_id']"
1255
- )).value;
1256
- await t.request({
1257
- url: x,
1258
- method: "POST",
1259
- formData: {
1260
- _wpnonce: _,
1261
- _wp_http_referer: $,
1262
- import_id: C
1263
- }
1264
- });
1265
- const v = await t.run({
1266
- code: q + ` importZipFile('${o}');`
1267
- });
1268
- if (v.exitCode !== 0)
1269
- throw v.errors;
1270
- return !0;
1271
- }
1272
- async function Le(t, e = "admin", n = "password") {
1273
- await t.request({
1274
- url: "/wp-login.php"
1275
- }), await t.request({
1276
- url: "/wp-login.php",
1277
- method: "POST",
1278
- formData: {
1279
- log: e,
1280
- pwd: n,
1281
- rememberme: "forever"
1282
- }
1283
- });
1284
- }
1285
- function R(t) {
1286
- return new DOMParser().parseFromString(t.text, "text/html");
1287
- }
1288
- function ne(t) {
1289
- const e = t.split(".").shift().replace("-", " ");
1290
- return e.charAt(0).toUpperCase() + e.slice(1).toLowerCase();
1291
- }
1292
- async function _e(t, e, n = {}) {
1293
- const r = "activate" in n ? n.activate : !0, o = await t.request({
1294
- url: "/wp-admin/theme-install.php"
1295
- }), a = R(o), i = new FormData(
1296
- a.querySelector(".wp-upload-form")
1297
- ), { themezip: d, ...c } = Object.fromEntries(
1298
- i.entries()
1299
- ), s = await t.request({
1300
- url: "/wp-admin/update.php?action=upload-theme",
1301
- method: "POST",
1302
- formData: c,
1303
- files: { themezip: e }
1304
- });
1305
- if (r) {
1306
- const l = R(s), h = l.querySelector(
1307
- "#wpbody-content > .wrap"
1308
- );
1309
- if (h?.textContent?.includes(
1310
- "Theme installation failed."
1311
- )) {
1312
- console.error(h?.textContent);
1313
- return;
1314
- }
1315
- const u = l.querySelector(
1316
- "#wpbody-content .activatelink, .update-from-upload-actions .button.button-primary"
1317
- );
1318
- if (!u) {
1319
- console.error('The "activate" button was not found.');
1320
- return;
1321
- }
1322
- const p = u.attributes.getNamedItem("href").value, x = new URL(
1323
- p,
1324
- await t.pathToInternalUrl("/wp-admin/")
1325
- ).toString();
1326
- await t.request({
1327
- url: x
1328
- });
1329
- }
2122
+ async function Ut({
2123
+ iframe: t,
2124
+ blueprint: e,
2125
+ remoteUrl: r,
2126
+ progressTracker: s = new L(),
2127
+ disableProgressBar: n,
2128
+ onBlueprintStepCompleted: i
2129
+ }) {
2130
+ if (At(r), r = ee(r, {
2131
+ progressbar: !n
2132
+ }), s.setCaption("Preparing WordPress"), !e)
2133
+ return Z(t, r, s);
2134
+ const o = ft(e, {
2135
+ progress: s.stage(0.5),
2136
+ onStepCompleted: i
2137
+ }), a = await Z(
2138
+ t,
2139
+ ee(r, {
2140
+ php: o.versions.php,
2141
+ wp: o.versions.wp
2142
+ }),
2143
+ s
2144
+ );
2145
+ return await yt(o, a), a;
1330
2146
  }
1331
- async function Ce(t, e, n = {}) {
1332
- const r = "activate" in n ? n.activate : !0, o = await t.request({
1333
- url: "/wp-admin/plugin-install.php?tab=upload"
1334
- }), a = R(o), i = new FormData(
1335
- a.querySelector(".wp-upload-form")
1336
- ), { pluginzip: d, ...c } = Object.fromEntries(
1337
- i.entries()
1338
- ), s = await t.request({
1339
- url: "/wp-admin/update.php?action=upload-plugin",
1340
- method: "POST",
1341
- formData: c,
1342
- files: { pluginzip: e }
1343
- });
1344
- if (r) {
1345
- const u = R(s).querySelector("#wpbody-content .button.button-primary").attributes.getNamedItem("href").value, p = new URL(
1346
- u,
1347
- await t.pathToInternalUrl("/wp-admin/")
1348
- ).toString();
1349
- await t.request({
1350
- url: p
1351
- });
1352
- }
1353
- async function l(h, u) {
1354
- return await t.writeFile(
1355
- h,
1356
- u(await t.readFileAsText(h))
1357
- );
1358
- }
1359
- await t.isDir("/wordpress/wp-content/plugins/gutenberg") && !await t.fileExists("/wordpress/.gutenberg-patched") && (await t.writeFile("/wordpress/.gutenberg-patched", "1"), await l(
1360
- "/wordpress/wp-content/plugins/gutenberg/build/block-editor/index.js",
1361
- (h) => h.replace(
1362
- /srcDoc:("[^"]+"|[^,]+)/g,
1363
- 'src:"/wp-includes/empty.html"'
1364
- )
1365
- ), await l(
1366
- "/wordpress/wp-content/plugins/gutenberg/build/block-editor/index.min.js",
1367
- (h) => h.replace(
1368
- /srcDoc:("[^"]+"|[^,]+)/g,
1369
- 'src:"/wp-includes/empty.html"'
1370
- )
1371
- ));
1372
- }
1373
- async function Ue(t, e) {
1374
- const o = R(
1375
- await t.request({
1376
- url: "/wp-admin/plugins.php"
1377
- })
1378
- ).querySelector(
1379
- `tr[data-slug="${e}"] a`
1380
- ).attributes.getNamedItem("href").value;
1381
- await t.request({
1382
- url: "/wp-admin/" + o
2147
+ async function Z(t, e, r) {
2148
+ await new Promise((n) => {
2149
+ t.src = e, t.addEventListener("load", n, !1);
1383
2150
  });
1384
- }
1385
- const ke = 5 * 1024 * 1024;
1386
- function re(t, e) {
1387
- const n = t.headers.get("content-length") || "", r = parseInt(n, 10) || ke;
1388
- function o(a, i) {
1389
- e(
1390
- new CustomEvent("progress", {
1391
- detail: {
1392
- loaded: a,
1393
- total: i
1394
- }
1395
- })
1396
- );
1397
- }
1398
- return new Response(
1399
- new ReadableStream({
1400
- async start(a) {
1401
- if (!t.body) {
1402
- a.close();
1403
- return;
1404
- }
1405
- const i = t.body.getReader();
1406
- let d = 0;
1407
- for (; ; )
1408
- try {
1409
- const { done: c, value: s } = await i.read();
1410
- if (s && (d += s.byteLength), c) {
1411
- o(d, d), a.close();
1412
- break;
1413
- } else
1414
- o(d, r), a.enqueue(s);
1415
- } catch (c) {
1416
- console.error({ e: c }), a.error(c);
1417
- break;
1418
- }
1419
- }
1420
- }),
1421
- {
1422
- status: t.status,
1423
- statusText: t.statusText,
1424
- headers: t.headers
1425
- }
2151
+ const s = pe(
2152
+ t.contentWindow
1426
2153
  );
2154
+ return await s.connected, r.pipe(s), await s.onDownloadProgress(
2155
+ r.stage().loadingListener
2156
+ ), await s.isReady(), s;
1427
2157
  }
1428
- async function De(t, e, n = 100, r) {
1429
- let o = await fetch("/plugin-proxy?theme=" + e);
1430
- if (r && (o = re(
1431
- o,
1432
- r.partialObserver(
1433
- n / 2,
1434
- `Installing ${ne(e)} theme...`
1435
- )
1436
- ), r.slowlyIncrementBy(n / 2)), o.status === 200) {
1437
- const a = new File([await o.blob()], e);
1438
- try {
1439
- await _e(t, a);
1440
- } catch (i) {
1441
- console.error(
1442
- `Proceeding without the ${e} theme. Could not install it in wp-admin. The original error was: ${i}`
1443
- ), console.error(i);
1444
- }
1445
- } else
1446
- console.error(
1447
- `Proceeding without the ${e} theme. Could not download the zip bundle from https://downloads.wordpress.org/themes/${e} – Is the file name correct?`
2158
+ const C = "https://playground.wordpress.net";
2159
+ function At(t) {
2160
+ const e = new URL(t, C);
2161
+ if ((e.origin === C || e.hostname === "localhost") && e.pathname !== "/remote.html")
2162
+ throw new Error(
2163
+ `Invalid remote URL: ${e}. Expected origin to be ${C}/remote.html.`
1448
2164
  );
1449
2165
  }
1450
- async function Ie(t, e, n = 100, r) {
1451
- const o = new Z(), a = new Z(), i = n / e.length;
1452
- await new Promise((d) => {
1453
- for (const c of e)
1454
- o.enqueue(async () => {
1455
- let s = await fetch(
1456
- "/plugin-proxy?plugin=" + c
1457
- );
1458
- return r && (s = re(
1459
- s,
1460
- r.partialObserver(
1461
- i * 0.66,
1462
- `Installing ${ne(
1463
- c
1464
- )} plugin...`
1465
- )
1466
- )), s.status !== 200 ? (console.error(
1467
- `Proceeding without the ${c} plugin. Could not download the zip bundle from https://downloads.wordpress.org/plugin/${c} – Is the file name correct?`
1468
- ), null) : new File([await s.blob()], c);
1469
- });
1470
- o.addEventListener("resolved", (c) => {
1471
- a.enqueue(async () => {
1472
- if (c.detail) {
1473
- r?.slowlyIncrementBy(i * 0.33);
1474
- try {
1475
- await Ce(t, c.detail);
1476
- } catch (s) {
1477
- console.error(
1478
- `Proceeding without the ${c.detail.name} plugin. Could not install it in wp-admin. The original error was: ${s}`
1479
- ), console.error(s);
1480
- }
1481
- }
1482
- });
1483
- }), a.addEventListener("empty", () => {
1484
- a.resolved === e.length && d(null);
1485
- });
1486
- });
1487
- }
1488
- class Z extends EventTarget {
1489
- #e = [];
1490
- #t = !1;
1491
- #n = 0;
1492
- get resolved() {
1493
- return this.#n;
1494
- }
1495
- async enqueue(e) {
1496
- this.#e.push(e), this.#r();
1497
- }
1498
- async #r() {
1499
- if (!this.#t)
1500
- try {
1501
- for (this.#t = !0; this.#e.length; ) {
1502
- const e = this.#e.shift();
1503
- if (!e)
1504
- break;
1505
- const n = await e();
1506
- ++this.#n, this.dispatchEvent(
1507
- new CustomEvent("resolved", { detail: n })
1508
- );
1509
- }
1510
- } finally {
1511
- this.#t = !1, this.dispatchEvent(new CustomEvent("empty"));
1512
- }
1513
- }
2166
+ function ee(t, e) {
2167
+ const r = new URL(t, C), s = new URLSearchParams(r.search);
2168
+ for (const [n, i] of Object.entries(e))
2169
+ i != null && i !== !1 && s.set(n, i.toString());
2170
+ return r.search = s.toString(), r.toString();
1514
2171
  }
1515
- async function ze(t, e) {
1516
- e?.loadRemote && (t.src = e?.loadRemote, await new Promise((r) => {
1517
- t.addEventListener("load", r, !1);
1518
- }));
1519
- const n = Se(t.contentWindow);
1520
- return await n.absoluteUrl, n;
2172
+ async function Ht(t, e) {
2173
+ if (console.warn(
2174
+ "`connectPlayground` is deprecated and will be removed. Use `startPlayground` instead."
2175
+ ), e?.loadRemote)
2176
+ return Ut({
2177
+ iframe: t,
2178
+ remoteUrl: e.loadRemote
2179
+ });
2180
+ const r = pe(
2181
+ t.contentWindow
2182
+ );
2183
+ return await r.connected, r;
1521
2184
  }
1522
2185
  export {
1523
- Ue as activatePlugin,
1524
- ze as connectPlayground,
1525
- Oe as exportFile,
2186
+ Ve as LatestSupportedPHPVersion,
2187
+ D as SupportedPHPVersions,
2188
+ Lt as SupportedPHPVersionsList,
2189
+ ge as activatePlugin,
2190
+ ye as applyWordPressPatches,
2191
+ ft as compileBlueprint,
2192
+ Ht as connectPlayground,
2193
+ ve as cp,
2194
+ Ce as defineSiteUrl,
1526
2195
  Ae as importFile,
1527
- Ce as installPlugin,
1528
- Ie as installPluginsFromDirectory,
1529
- _e as installTheme,
1530
- De as installThemeFromDirectory,
1531
- Le as login
2196
+ Ie as installPlugin,
2197
+ Ne as installTheme,
2198
+ ze as login,
2199
+ Re as mkdir,
2200
+ Ee as mv,
2201
+ S as phpVar,
2202
+ z as phpVars,
2203
+ Ue as replaceSite,
2204
+ Se as request,
2205
+ Te as rm,
2206
+ xe as rmdir,
2207
+ yt as runBlueprintSteps,
2208
+ be as runPHP,
2209
+ _e as runPHPWithOptions,
2210
+ De as runWpInstallationWizard,
2211
+ $e as setPhpIniEntry,
2212
+ qe as setSiteOptions,
2213
+ Ut as startPlaygroundWeb,
2214
+ re as unzip,
2215
+ We as updateUserMeta,
2216
+ Fe as writeFile,
2217
+ Oe as zipEntireSite
1532
2218
  };