@wp-playground/client 0.1.56 → 0.1.59
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/blueprint-schema.json +3 -0
- package/index.cjs +34 -21
- package/index.d.ts +20 -16
- package/index.js +396 -379
- package/package.json +2 -2
package/blueprint-schema.json
CHANGED
package/index.cjs
CHANGED
|
@@ -1,23 +1,36 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const
|
|
2
|
-
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const D=async(t,{pluginPath:e,pluginName:r},s)=>{s?.tracker.setCaption(`Activating ${r||e}`);const n=[`${await t.documentRoot}/wp-load.php`,`${await t.documentRoot}/wp-admin/includes/plugin.php`];if(!n.every(a=>t.fileExists(a)))throw new Error(`Required WordPress files do not exist: ${n.join(", ")}`);if((await t.run({code:`<?php
|
|
2
|
+
${n.map(a=>`require_once( '${a}' );`).join(`
|
|
3
3
|
`)}
|
|
4
|
-
|
|
5
|
-
|
|
4
|
+
$plugin_path = '${e}';
|
|
5
|
+
if (!is_dir($plugin_path)) {
|
|
6
|
+
activate_plugin($plugin_path);
|
|
7
|
+
return;
|
|
8
|
+
}
|
|
9
|
+
// Find plugin entry file
|
|
10
|
+
foreach ( ( glob( $plugin_path . '/*.php' ) ?: array() ) as $file ) {
|
|
11
|
+
$info = get_plugin_data( $file, false, false );
|
|
12
|
+
if ( ! empty( $info['Name'] ) ) {
|
|
13
|
+
activate_plugin( $file );
|
|
14
|
+
return;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
echo 'NO_ENTRY_FILE';
|
|
18
|
+
`})).text.endsWith("NO_ENTRY_FILE"))throw new Error("Could not find plugin entry file.")},q=async(t,{themeFolderName:e},r)=>{r?.tracker.setCaption(`Activating ${e}`);const s=`${await t.documentRoot}/wp-load.php`;if(!t.fileExists(s))throw new Error(`Required WordPress file does not exist: ${s}`);await t.run({code:`<?php
|
|
6
19
|
require_once( '${s}' );
|
|
7
20
|
switch_theme( '${e}' );
|
|
8
|
-
`})};function
|
|
21
|
+
`})};function L(t){const e=t.split(".").shift().replace(/-/g," ");return e.charAt(0).toUpperCase()+e.slice(1).toLowerCase()}async function S(t,e,r){let s="";await t.fileExists(e)&&(s=await t.readFileAsText(e)),await t.writeFile(e,r(s))}async function rt(t){return new Uint8Array(await t.arrayBuffer())}class st extends File{constructor(e,r){super(e,r),this.buffers=e}async arrayBuffer(){return this.buffers[0]}}const j=File.prototype.arrayBuffer instanceof Function?File:st,ge=async(t,e)=>{const r=new nt(t,e.siteUrl,e.wordpressPath||"/wordpress");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()};class nt{constructor(e,r,s){this.php=e,this.scopedSiteUrl=r,this.wordpressPath=s}async patchSqlitePlugin(){await S(this.php,`${this.wordpressPath}/wp-content/plugins/sqlite-database-integration/wp-includes/sqlite/class-wp-sqlite-translator.php`,e=>e.replace("if ( false === strtotime( $value ) )",'if ( $value === "0000-00-00 00:00:00" || false === strtotime( $value ) )'))}async addPhpInfo(){await this.php.writeFile(`${this.wordpressPath}/phpinfo.php`,"<?php phpinfo(); ")}async patchSiteUrl(){await S(this.php,`${this.wordpressPath}/wp-config.php`,e=>`<?php
|
|
9
22
|
if(!defined('WP_HOME')) {
|
|
10
23
|
define('WP_HOME', "${this.scopedSiteUrl}");
|
|
11
24
|
define('WP_SITEURL', "${this.scopedSiteUrl}");
|
|
12
25
|
}
|
|
13
|
-
?>${e}`)}async disableSiteHealth(){await
|
|
26
|
+
?>${e}`)}async disableSiteHealth(){await S(this.php,`${this.wordpressPath}/wp-includes/default-filters.php`,e=>e.replace(/add_filter[^;]+wp_maybe_grant_site_health_caps[^;]+;/i,""))}async disableWpNewBlogNotification(){await S(this.php,`${this.wordpressPath}/wp-config.php`,e=>`${e} function wp_new_blog_notification(...$args){} `)}}const ye=async(t,{code:e})=>await t.run({code:e}),Pe=async(t,{options:e})=>await t.run(e),be=async(t,{key:e,value:r})=>{await t.setPhpIniEntry(e,r)},_e=async(t,{request:e})=>await t.request(e),$e=async(t,{fromPath:e,toPath:r})=>{await t.writeFile(r,await t.readFileAsBuffer(e))},Ee=async(t,{fromPath:e,toPath:r})=>{await t.mv(e,r)},ve=async(t,{path:e})=>{await t.mkdir(e)},Se=async(t,{path:e})=>{await t.unlink(e)},Re=async(t,{path:e})=>{await t.rmdir(e)},B=async(t,{path:e,data:r})=>{r instanceof File&&(r=await rt(r)),await t.writeFile(e,r)},Q="/vfs-blueprints",V=async(t,{consts:e,virtualize:r=!1})=>{const s=await t.documentRoot,n=r?Q:s,i=`${n}/playground-consts.json`,o=`${n}/wp-config.php`;return r&&(t.mkdir(Q),t.setPhpIniEntry("auto_prepend_file",o)),await S(t,i,a=>JSON.stringify({...JSON.parse(a||"{}"),...e})),await S(t,o,a=>a.includes("playground-consts.json")?a:`<?php
|
|
14
27
|
$consts = json_decode(file_get_contents('${i}'), true);
|
|
15
28
|
foreach ($consts as $const => $value) {
|
|
16
29
|
if (!defined($const)) {
|
|
17
30
|
define($const, $value);
|
|
18
31
|
}
|
|
19
32
|
}
|
|
20
|
-
?>${a}`),o},xe=async(t,{siteUrl:e})=>await
|
|
33
|
+
?>${a}`),o},xe=async(t,{siteUrl:e})=>await V(t,{consts:{WP_HOME:e,WP_SITEURL:e}});class Te{constructor({concurrency:e}){this._running=0,this.concurrency=e,this.queue=[]}get running(){return this._running}async acquire(){for(;;)if(this._running>=this.concurrency)await new Promise(e=>this.queue.push(e));else return this._running++,()=>{this._running--,this.queue.length>0&&this.queue.shift()()}}async run(e){const r=await this.acquire();try{return await e()}finally{r()}}}const it=Symbol("literal");function _(t){if(typeof t=="string")return t.startsWith("$")?t:JSON.stringify(t);if(typeof t=="number")return t.toString();if(Array.isArray(t))return`array(${t.map(_).join(", ")})`;if(t===null)return"null";if(typeof t=="object")return it in t?t.toString():`array(${Object.entries(t).map(([r,s])=>`${JSON.stringify(r)} => ${_(s)}`).join(", ")})`;if(typeof t=="function")return t();throw new Error(`Unsupported value: ${t}`)}function O(t){const e={};for(const r in t)e[r]=_(t[r]);return e}const X=`<?php
|
|
21
34
|
|
|
22
35
|
function zipDir($dir, $output, $additionalFiles = array())
|
|
23
36
|
{
|
|
@@ -79,32 +92,32 @@ function delTree($dir)
|
|
|
79
92
|
}
|
|
80
93
|
return rmdir($dir);
|
|
81
94
|
}
|
|
82
|
-
`;async function
|
|
95
|
+
`;async function Fe(t){const e="wordpress-playground.zip",r=`/${e}`,s=O({zipPath:r,documentRoot:await t.documentRoot});await Ae(t,`zipDir(${s.documentRoot}, ${s.zipPath});`);const n=await t.readFileAsBuffer(r);return t.unlink(r),new File([n],e)}const Ce=async(t,{fullSiteZip:e})=>{const r="/import.zip";await t.writeFile(r,new Uint8Array(await e.arrayBuffer()));const s=await t.absoluteUrl,n=await t.documentRoot;await t.rmdir(n),await U(t,{zipPath:r,extractToPath:"/"});const i=O({absoluteUrl:s});await at(t,`${n}/wp-config.php`,o=>`<?php
|
|
83
96
|
if(!defined('WP_HOME')) {
|
|
84
97
|
define('WP_HOME', ${i.absoluteUrl});
|
|
85
98
|
define('WP_SITEURL', ${i.absoluteUrl});
|
|
86
99
|
}
|
|
87
|
-
?>${o}`)},
|
|
100
|
+
?>${o}`)},U=async(t,{zipPath:e,extractToPath:r})=>{const s=O({zipPath:e,extractToPath:r});await Ae(t,`unzip(${s.zipPath}, ${s.extractToPath});`)},ke=async(t,{file:e})=>{const r=await t.request({url:"/wp-admin/admin.php?import=wordpress"}),s=ee(r).getElementById("import-upload-form")?.getAttribute("action"),n=await t.request({url:`/wp-admin/${s}`,method:"POST",files:{import:e}}),i=ee(n).querySelector("#wpbody-content form");if(!i)throw console.log(n.text),new Error("Could not find an importer form in response. See the response text above for details.");const o=ot(i);o.fetch_attachments="1";for(const a in o)if(a.startsWith("user_map[")){const l="user_new["+a.slice(9,-1)+"]";o[l]="1"}await t.request({url:i.action,method:"POST",formData:o})};function ee(t){return new DOMParser().parseFromString(t.text,"text/html")}function ot(t){return Object.fromEntries(new FormData(t).entries())}async function at(t,e,r){await t.writeFile(e,r(await t.readFileAsText(e)))}async function Ae(t,e){const r=await t.run({code:X+e});if(r.exitCode!==0)throw console.log(X+e),console.log(e+""),console.log(r.errors),r.errors;return r}async function Le(t,{targetPath:e,zipFile:r}){const s=r.name,n=s.replace(/\.zip$/,""),i=`/tmp/assets/${n}`,o=`/tmp/${s}`,a=()=>t.rmdir(i,{recursive:!0});await t.fileExists(i)&&await a(),await B(t,{path:o,data:r});const l=()=>Promise.all([a,()=>t.unlink(o)]);try{await U(t,{zipPath:o,extractToPath:i});const c=await t.listFiles(i,{prependPath:!0}),u=c.length===1&&await t.isDir(c[0]);let d,p="";u?(p=c[0],d=c[0].split("/").pop()):(p=i,d=n);const y=`${e}/${d}`;return await t.mv(p,y),await l(),{assetFolderPath:y,assetFolderName:d}}catch(c){throw await l(),c}}const Oe=async(t,{pluginZipFile:e,options:r={}},s)=>{const n=e.name.split("/").pop()||"plugin.zip",i=L(n);s?.tracker.setCaption(`Installing the ${i} plugin`);try{const{assetFolderPath:o}=await Le(t,{zipFile:e,targetPath:`${await t.documentRoot}/wp-content/plugins`});("activate"in r?r.activate:!0)&&await D(t,{pluginPath:o,pluginName:i},s),await ct(t)}catch(o){console.error(`Proceeding without the ${i} plugin. Could not install it in wp-admin. The original error was: ${o}`),console.error(o)}};async function ct(t){await t.isDir("/wordpress/wp-content/plugins/gutenberg")&&!await t.fileExists("/wordpress/.gutenberg-patched")&&(await t.writeFile("/wordpress/.gutenberg-patched","1"),await te(t,"/wordpress/wp-content/plugins/gutenberg/build/block-editor/index.js",e=>e.replace(/srcDoc:("[^"]+"|[^,]+)/g,'src:"/wp-includes/empty.html"')),await te(t,"/wordpress/wp-content/plugins/gutenberg/build/block-editor/index.min.js",e=>e.replace(/srcDoc:("[^"]+"|[^,]+)/g,'src:"/wp-includes/empty.html"')))}async function te(t,e,r){return await t.writeFile(e,r(await t.readFileAsText(e)))}const Ue=async(t,{themeZipFile:e,options:r={}},s)=>{const n=L(e.name);s?.tracker.setCaption(`Installing the ${n} theme`);try{const{assetFolderName:i}=await Le(t,{zipFile:e,targetPath:`${await t.documentRoot}/wp-content/themes`});("activate"in r?r.activate:!0)&&await q(t,{themeFolderName:i},s)}catch(i){console.error(`Proceeding without the ${n} theme. Could not install it in wp-admin. The original error was: ${i}`),console.error(i)}},He=async(t,{username:e="admin",password:r="password"}={},s)=>{s?.tracker.setCaption(s?.initialCaption||"Logging in"),await t.request({url:"/wp-login.php"}),await t.request({url:"/wp-login.php",method:"POST",formData:{log:e,pwd:r,rememberme:"forever"}})},Ne=async(t,{options:e})=>{await t.request({url:"/wp-admin/install.php?step=2",method:"POST",formData:{language:"en",prefix:"wp_",weblog_title:"My WordPress Website",user_name:e.adminPassword||"admin",admin_password:e.adminPassword||"password",admin_password2:e.adminPassword||"password",Submit:"Install WordPress",pw_weak:"1",admin_email:"admin@localhost.com"}})},We=async(t,{options:e})=>{const r=`<?php
|
|
88
101
|
include 'wordpress/wp-load.php';
|
|
89
102
|
$site_options = ${_(e)};
|
|
90
103
|
foreach($site_options as $name => $value) {
|
|
91
104
|
update_option($name, $value);
|
|
92
105
|
}
|
|
93
106
|
echo "Success";
|
|
94
|
-
`,s=await t.run({code:r});return
|
|
107
|
+
`,s=await t.run({code:r});return ze(s),{code:r,result:s}},Ie=async(t,{meta:e,userId:r})=>{const s=`<?php
|
|
95
108
|
include 'wordpress/wp-load.php';
|
|
96
109
|
$meta = ${_(e)};
|
|
97
110
|
foreach($meta as $name => $value) {
|
|
98
111
|
update_user_meta(${_(r)}, $name, $value);
|
|
99
112
|
}
|
|
100
113
|
echo "Success";
|
|
101
|
-
`,n=await t.run({code:s});return
|
|
114
|
+
`,n=await t.run({code:s});return ze(n),{code:s,result:n}};async function ze(t){if(t.text!=="Success")throw console.log(t),new Error(`Failed to run code: ${t.text} ${t.errors}`)}const lt=Object.freeze(Object.defineProperty({__proto__:null,activatePlugin:D,activateTheme:q,applyWordPressPatches:ge,cp:$e,defineSiteUrl:xe,defineWpConfigConsts:V,importFile:ke,installPlugin:Oe,installTheme:Ue,login:He,mkdir:ve,mv:Ee,replaceSite:Ce,request:_e,rm:Se,rmdir:Re,runPHP:ye,runPHPWithOptions:Pe,runWpInstallationWizard:Ne,setPhpIniEntry:be,setSiteOptions:We,unzip:U,updateUserMeta:Ie,writeFile:B,zipEntireSite:Fe},Symbol.toStringTag,{value:"Module"})),ut=5*1024*1024;function ht(t,e){const r=t.headers.get("content-length")||"",s=parseInt(r,10)||ut;function n(i,o){e(new CustomEvent("progress",{detail:{loaded:i,total:o}}))}return new Response(new ReadableStream({async start(i){if(!t.body){i.close();return}const o=t.body.getReader();let a=0;for(;;)try{const{done:l,value:c}=await o.read();if(c&&(a+=c.byteLength),l){n(a,a),i.close();break}else n(a,s),i.enqueue(c)}catch(l){console.error({e:l}),i.error(l);break}}}),{status:t.status,statusText:t.statusText,headers:t.headers})}const W=1e-5;class H extends EventTarget{constructor({weight:e=1,caption:r="",fillTime:s=4}={}){super(),this._selfWeight=1,this._selfDone=!1,this._selfProgress=0,this._selfCaption="",this._isFilling=!1,this._subTrackers=[],this._weight=e,this._selfCaption=r,this._fillTime=s}stage(e,r=""){if(e||(e=this._selfWeight),this._selfWeight-e<-W)throw new Error(`Cannot add a stage with weight ${e} as the total weight of registered stages would exceed 1.`);this._selfWeight-=e;const s=new H({caption:r,weight:e,fillTime:this._fillTime});return this._subTrackers.push(s),s.addEventListener("progress",()=>this.notifyProgress()),s.addEventListener("done",()=>{this.done&&this.notifyDone()}),s}fillSlowly({stopBeforeFinishing:e=!0}={}){if(this._isFilling)return;this._isFilling=!0;const r=100,s=this._fillTime/r;this._fillInterval=setInterval(()=>{this.set(this._selfProgress+1),e&&this._selfProgress>=99&&clearInterval(this._fillInterval)},s)}set(e){this._selfProgress=Math.min(e,100),this.notifyProgress(),this._selfProgress+W>=100&&this.finish()}finish(){this._fillInterval&&clearInterval(this._fillInterval),this._selfDone=!0,this._selfProgress=100,this._isFilling=!1,this._fillInterval=void 0,this.notifyProgress(),this.notifyDone()}get caption(){for(let e=this._subTrackers.length-1;e>=0;e--)if(!this._subTrackers[e].done){const r=this._subTrackers[e].caption;if(r)return r}return this._selfCaption}setCaption(e){this._selfCaption=e,this.notifyProgress()}get done(){return this.progress+W>=100}get progress(){if(this._selfDone)return 100;const e=this._subTrackers.reduce((r,s)=>r+s.progress*s.weight,this._selfProgress*this._selfWeight);return Math.round(e*1e4)/1e4}get weight(){return this._weight}get observer(){return this._progressObserver||(this._progressObserver=e=>{this.set(e)}),this._progressObserver}get loadingListener(){return this._loadingListener||(this._loadingListener=e=>{this.set(e.detail.loaded/e.detail.total*100)}),this._loadingListener}pipe(e){e.setProgress({progress:this.progress,caption:this.caption}),this.addEventListener("progress",r=>{e.setProgress({progress:r.detail.progress,caption:r.detail.caption})}),this.addEventListener("done",()=>{e.setLoaded()})}addEventListener(e,r){super.addEventListener(e,r)}removeEventListener(e,r){super.removeEventListener(e,r)}notifyProgress(){const e=this;this.dispatchEvent(new CustomEvent("progress",{detail:{get progress(){return e.progress},get caption(){return e.caption}}}))}notifyDone(){this.dispatchEvent(new CustomEvent("done"))}}const re=Symbol("error"),se=Symbol("message");class G extends Event{constructor(e,r={}){super(e),this[re]=r.error===void 0?null:r.error,this[se]=r.message===void 0?"":r.message}get error(){return this[re]}get message(){return this[se]}}Object.defineProperty(G.prototype,"error",{enumerable:!0});Object.defineProperty(G.prototype,"message",{enumerable:!0});const dt=typeof globalThis.ErrorEvent=="function"?globalThis.ErrorEvent:G;class pt extends EventTarget{constructor(){super(...arguments),this.listenersCount=0}addEventListener(e,r){++this.listenersCount,super.addEventListener(e,r)}removeEventListener(e,r){--this.listenersCount,super.removeEventListener(e,r)}hasListeners(){return this.listenersCount>0}}function ft(t){t.asm={...t.asm};const e=new pt;for(const r in t.asm)if(typeof t.asm[r]=="function"){const s=t.asm[r];t.asm[r]=function(...n){try{return s(...n)}catch(i){if(!(i instanceof Error))throw i;if("exitCode"in i&&i?.exitCode===0)return;const o=wt(i,t.lastAsyncifyStackSource?.stack);if(t.lastAsyncifyStackSource&&(i.cause=t.lastAsyncifyStackSource),!e.hasListeners())throw Pt(o),i;e.dispatchEvent(new dt("error",{error:i,message:o}))}}}return e}let z=[];function mt(){return z}function wt(t,e){if(t.message==="unreachable"){let r=gt;e||(r+=`
|
|
102
115
|
|
|
103
116
|
This stack trace is lacking. For a better one initialize
|
|
104
117
|
the PHP runtime with { debug: true }, e.g. PHPNode.load('8.1', { debug: true }).
|
|
105
118
|
|
|
106
|
-
`),
|
|
107
|
-
`;return r}return t.message}const
|
|
119
|
+
`),z=bt(e||t.stack||"");for(const s of z)r+=` * ${s}
|
|
120
|
+
`;return r}return t.message}const gt=`
|
|
108
121
|
"unreachable" WASM instruction executed.
|
|
109
122
|
|
|
110
123
|
The typical reason is a PHP function missing from the ASYNCIFY_ONLY
|
|
@@ -128,17 +141,17 @@ the Dockerfile, you'll need to trigger this error again with long stack
|
|
|
128
141
|
traces enabled. In node.js, you can do it using the --stack-trace-limit=100
|
|
129
142
|
CLI option:
|
|
130
143
|
|
|
131
|
-
`,
|
|
132
|
-
${
|
|
133
|
-
${
|
|
134
|
-
`))console.log(`${
|
|
135
|
-
`).slice(1).map(r=>{const s=r.trim().substring(3).split(" ");return{fn:s.length>=2?s[0]:"<unknown>",isWasm:r.includes("wasm://")}}).filter(({fn:r,isWasm:s})=>s&&!r.startsWith("dynCall_")&&!r.startsWith("invoke_")).map(({fn:r})=>r);return Array.from(new Set(e))}catch{return[]}}class b{constructor(e,r,s,n="",i=0){this.httpStatusCode=e,this.headers=r,this.bytes=s,this.exitCode=i,this.errors=n}static fromRawData(e){return new b(e.httpStatusCode,e.headers,e.bytes,e.errors,e.exitCode)}toRawData(){return{headers:this.headers,bytes:this.bytes,errors:this.errors,exitCode:this.exitCode,httpStatusCode:this.httpStatusCode}}get json(){return JSON.parse(this.text)}get text(){return new TextDecoder().decode(this.bytes)}}const
|
|
144
|
+
`,ne="\x1B[41m",yt="\x1B[1m",ie="\x1B[0m",oe="\x1B[K";let ae=!1;function Pt(t){if(!ae){ae=!0,console.log(`${ne}
|
|
145
|
+
${oe}
|
|
146
|
+
${yt} WASM ERROR${ie}${ne}`);for(const e of t.split(`
|
|
147
|
+
`))console.log(`${oe} ${e} `);console.log(`${ie}`)}}function bt(t){try{const e=t.split(`
|
|
148
|
+
`).slice(1).map(r=>{const s=r.trim().substring(3).split(" ");return{fn:s.length>=2?s[0]:"<unknown>",isWasm:r.includes("wasm://")}}).filter(({fn:r,isWasm:s})=>s&&!r.startsWith("dynCall_")&&!r.startsWith("invoke_")).map(({fn:r})=>r);return Array.from(new Set(e))}catch{return[]}}class b{constructor(e,r,s,n="",i=0){this.httpStatusCode=e,this.headers=r,this.bytes=s,this.exitCode=i,this.errors=n}static fromRawData(e){return new b(e.httpStatusCode,e.headers,e.bytes,e.errors,e.exitCode)}toRawData(){return{headers:this.headers,bytes:this.bytes,errors:this.errors,exitCode:this.exitCode,httpStatusCode:this.httpStatusCode}}get json(){return JSON.parse(this.text)}get text(){return new TextDecoder().decode(this.bytes)}}const N=["8.2","8.1","8.0","7.4","7.3","7.2","7.1","7.0","5.6"],Me=N[0],_t=N;class $t{#e;#t;constructor(e,r={}){this.requestHandler=e,this.#e={},this.#t={handleRedirects:!1,maxRedirects:4,...r}}async request(e,r=0){const s=await this.requestHandler.request({...e,headers:{...e.headers,cookie:this.#r()}});if(s.headers["set-cookie"]&&this.#s(s.headers["set-cookie"]),this.#t.handleRedirects&&s.headers.location&&r<this.#t.maxRedirects){const n=new URL(s.headers.location[0],this.requestHandler.absoluteUrl);return this.request({url:n.toString(),method:"GET",headers:{}},r+1)}return s}pathToInternalUrl(e){return this.requestHandler.pathToInternalUrl(e)}internalUrlToPath(e){return this.requestHandler.internalUrlToPath(e)}get absoluteUrl(){return this.requestHandler.absoluteUrl}get documentRoot(){return this.requestHandler.documentRoot}#s(e){for(const r of e)try{if(!r.includes("="))continue;const s=r.indexOf("="),n=r.substring(0,s),i=r.substring(s+1).split(";")[0];this.#e[n]=i}catch(s){console.error(s)}}#r(){const e=[];for(const r in this.#e)e.push(`${r}=${this.#e[r]}`);return e.join("; ")}}const Et="http://example.com";function ce(t){return t.toString().substring(t.origin.length)}function le(t,e){return!e||!t.startsWith(e)?t:t.substring(e.length)}function vt(t,e){return!e||t.startsWith(e)?t:e+t}class St{#e;#t;#s;#r;#i;#n;#o;#a;#c;constructor(e,r={}){this.#a=new Te({concurrency:1});const{documentRoot:s="/www/",absoluteUrl:n=typeof location=="object"?location?.href:"",isStaticFilePath:i=()=>!1}=r;this.php=e,this.#e=s,this.#c=i;const o=new URL(n);this.#s=o.hostname,this.#r=o.port?Number(o.port):o.protocol==="https:"?443:80,this.#t=(o.protocol||"").replace(":","");const a=this.#r!==443&&this.#r!==80;this.#i=[this.#s,a?`:${this.#r}`:""].join(""),this.#n=o.pathname.replace(/\/+$/,""),this.#o=[`${this.#t}://`,this.#i,this.#n].join("")}pathToInternalUrl(e){return`${this.absoluteUrl}${e}`}internalUrlToPath(e){const r=new URL(e);return r.pathname.startsWith(this.#n)&&(r.pathname=r.pathname.slice(this.#n.length)),ce(r)}get isRequestRunning(){return this.#a.running>0}get absoluteUrl(){return this.#o}get documentRoot(){return this.#e}async request(e){const r=e.url.startsWith("http://")||e.url.startsWith("https://"),s=new URL(e.url,r?void 0:Et),n=le(s.pathname,this.#n);return this.#c(n)?this.#l(n):await this.#u(e,s)}#l(e){const r=`${this.#e}${e}`;if(!this.php.fileExists(r))return new b(404,{},new TextEncoder().encode("404 File not found"));const s=this.php.readFileAsBuffer(r);return new b(200,{"content-length":[`${s.byteLength}`],"content-type":[xt(r)],"accept-ranges":["bytes"],"cache-control":["public, max-age=0"]},s)}async#u(e,r){const s=await this.#a.acquire();try{this.php.addServerGlobalEntry("DOCUMENT_ROOT",this.#e),this.php.addServerGlobalEntry("HTTPS",this.#o.startsWith("https://")?"on":"");let n="GET";const i={host:this.#i,...De(e.headers||{})},o=[];if(e.files&&Object.keys(e.files).length){n="POST";for(const c in e.files){const u=e.files[c];o.push({key:c,name:u.name,type:u.type,data:new Uint8Array(await u.arrayBuffer())})}i["content-type"]?.startsWith("multipart/form-data")&&(e.formData=Rt(e.body||""),i["content-type"]="application/x-www-form-urlencoded",delete e.body)}let a;e.formData!==void 0?(n="POST",i["content-type"]=i["content-type"]||"application/x-www-form-urlencoded",a=new URLSearchParams(e.formData).toString()):a=e.body;let l;try{l=this.#h(r.pathname)}catch{return new b(404,{},new TextEncoder().encode("404 File not found"))}return await this.php.run({relativeUri:vt(ce(r),this.#n),protocol:this.#t,method:e.method||n,body:a,fileInfos:o,scriptPath:l,headers:i})}finally{s()}}#h(e){let r=le(e,this.#n);r.includes(".php")?r=r.split(".php")[0]+".php":(r.endsWith("/")||(r+="/"),r.endsWith("index.php")||(r+="index.php"));const s=`${this.#e}${r}`;if(this.php.fileExists(s))return s;if(!this.php.fileExists(`${this.#e}/index.php`))throw new Error(`File not found: ${s}`);return`${this.#e}/index.php`}}function Rt(t){const e={},r=t.match(/--(.*)\r\n/);if(!r)return e;const s=r[1],n=t.split(`--${s}`);return n.shift(),n.pop(),n.forEach(i=>{const o=i.indexOf(`\r
|
|
136
149
|
\r
|
|
137
|
-
`),a=i.substring(0,o).trim(),l=i.substring(o+4).trim(),c=a.match(/name="([^"]+)"/);if(c){const u=c[1];e[u]=l}}),e}function
|
|
150
|
+
`),a=i.substring(0,o).trim(),l=i.substring(o+4).trim(),c=a.match(/name="([^"]+)"/);if(c){const u=c[1];e[u]=l}}),e}function xt(t){switch(t.split(".").pop()){case"css":return"text/css";case"js":return"application/javascript";case"png":return"image/png";case"jpg":case"jpeg":return"image/jpeg";case"gif":return"image/gif";case"svg":return"image/svg+xml";case"woff":return"font/woff";case"woff2":return"font/woff2";case"ttf":return"font/ttf";case"otf":return"font/otf";case"eot":return"font/eot";case"ico":return"image/x-icon";case"html":return"text/html";case"json":return"application/json";case"xml":return"application/xml";case"txt":case"md":return"text/plain";default:return"application-octet-stream"}}const ue={0:"No error occurred. System call completed successfully.",1:"Argument list too long.",2:"Permission denied.",3:"Address in use.",4:"Address not available.",5:"Address family not supported.",6:"Resource unavailable, or operation would block.",7:"Connection already in progress.",8:"Bad file descriptor.",9:"Bad message.",10:"Device or resource busy.",11:"Operation canceled.",12:"No child processes.",13:"Connection aborted.",14:"Connection refused.",15:"Connection reset.",16:"Resource deadlock would occur.",17:"Destination address required.",18:"Mathematics argument out of domain of function.",19:"Reserved.",20:"File exists.",21:"Bad address.",22:"File too large.",23:"Host is unreachable.",24:"Identifier removed.",25:"Illegal byte sequence.",26:"Operation in progress.",27:"Interrupted function.",28:"Invalid argument.",29:"I/O error.",30:"Socket is connected.",31:"There is a directory under that path.",32:"Too many levels of symbolic links.",33:"File descriptor value too large.",34:"Too many links.",35:"Message too large.",36:"Reserved.",37:"Filename too long.",38:"Network is down.",39:"Connection aborted by network.",40:"Network unreachable.",41:"Too many files open in system.",42:"No buffer space available.",43:"No such device.",44:"There is no such file or directory OR the parent directory does not exist.",45:"Executable file format error.",46:"No locks available.",47:"Reserved.",48:"Not enough space.",49:"No message of the desired type.",50:"Protocol not available.",51:"No space left on device.",52:"Function not supported.",53:"The socket is not connected.",54:"Not a directory or a symbolic link to a directory.",55:"Directory not empty.",56:"State not recoverable.",57:"Not a socket.",58:"Not supported, or operation not supported on socket.",59:"Inappropriate I/O control operation.",60:"No such device or address.",61:"Value too large to be stored in data type.",62:"Previous owner died.",63:"Operation not permitted.",64:"Broken pipe.",65:"Protocol error.",66:"Protocol not supported.",67:"Protocol wrong type for socket.",68:"Result too large.",69:"Read-only file system.",70:"Invalid seek.",71:"No such process.",72:"Reserved.",73:"Connection timed out.",74:"Text file busy.",75:"Cross-device link.",76:"Extension: Capabilities insufficient."};function m(t=""){return function(r,s,n){const i=n.value;n.value=function(...o){try{return i.apply(this,o)}catch(a){const l=typeof a=="object"?a?.errno:null;if(l in ue){const c=ue[l],u=typeof o[0]=="string"?o[0]:null,d=u!==null?t.replaceAll("{path}",u):t;throw new Error(`${d}: ${c}`,{cause:a})}throw a}}}}const Tt=[];function Ft(t){return Tt[t]}(function(){return typeof process<"u"&&process.release?.name==="node"?"NODE":typeof window<"u"?"WEB":typeof WorkerGlobalScope<"u"&&self instanceof WorkerGlobalScope?"WORKER":"NODE"})();var Ct=Object.defineProperty,kt=Object.getOwnPropertyDescriptor,w=(t,e,r,s)=>{for(var n=s>1?void 0:s?kt(e,r):e,i=t.length-1,o;i>=0;i--)(o=t[i])&&(n=(s?o(e,r,n):o(n))||n);return s&&n&&Ct(e,r,n),n};const f="string",E="number",h=Symbol("__private__dont__use");class g{constructor(e,r){this.#e=[],this.#t=!1,this.#s=null,this.#r={},e!==void 0&&this.initializeRuntime(e),r&&(this.requestHandler=new $t(new St(this,r)))}#e;#t;#s;#r;get absoluteUrl(){return this.requestHandler.requestHandler.absoluteUrl}get documentRoot(){return this.requestHandler.requestHandler.documentRoot}pathToInternalUrl(e){return this.requestHandler.requestHandler.pathToInternalUrl(e)}internalUrlToPath(e){return this.requestHandler.requestHandler.internalUrlToPath(e)}initializeRuntime(e){if(this[h])throw new Error("PHP runtime already initialized.");const r=Ft(e);if(!r)throw new Error("Invalid PHP runtime id.");this[h]=r,this.#s=ft(r)}setPhpIniPath(e){if(this.#t)throw new Error("Cannot set PHP ini path after calling run().");this[h].ccall("wasm_set_phpini_path",null,["string"],[e])}setPhpIniEntry(e,r){if(this.#t)throw new Error("Cannot set PHP ini entries after calling run().");this.#e.push([e,r])}chdir(e){this[h].FS.chdir(e)}async request(e,r){if(!this.requestHandler)throw new Error("No request handler available.");return this.requestHandler.request(e,r)}async run(e){this.#t||(this.#i(),this.#t=!0),this.#h(e.scriptPath||""),this.#o(e.relativeUri||""),this.#c(e.method||"GET");const{host:r,...s}={host:"example.com:443",...De(e.headers||{})};if(this.#a(r,e.protocol||"http"),this.#l(s),e.body&&this.#u(e.body),e.fileInfos)for(const n of e.fileInfos)this.#p(n);return e.code&&this.#f(" ?>"+e.code),this.#d(),await this.#m()}#i(){if(this.#e.length>0){const e=this.#e.map(([r,s])=>`${r}=${s}`).join(`
|
|
138
151
|
`)+`
|
|
139
152
|
|
|
140
|
-
`;this[h].ccall("wasm_set_phpini_entries",null,[f],[e])}this[h].ccall("php_wasm_init",null,[],[])}#n(){const e="/tmp/headers.json";if(!this.fileExists(e))throw new Error("SAPI Error: Could not find response headers file.");const r=JSON.parse(this.readFileAsText(e)),s={};for(const n of r.headers){if(!n.includes(": "))continue;const i=n.indexOf(": "),o=n.substring(0,i).toLowerCase(),a=n.substring(i+2);o in s||(s[o]=[]),s[o].push(a)}return{headers:s,httpStatusCode:r.status}}#o(e){if(this[h].ccall("wasm_set_request_uri",null,[f],[e]),e.includes("?")){const r=e.substring(e.indexOf("?")+1);this[h].ccall("wasm_set_query_string",null,[f],[r])}}#a(e,r){this[h].ccall("wasm_set_request_host",null,[f],[e]);let s;try{s=parseInt(new URL(e).port,10)}catch{}(!s||isNaN(s)||s===80)&&(s=r==="https"?443:80),this[h].ccall("wasm_set_request_port",null,[E],[s]),(r==="https"||!r&&s===443)&&this.addServerGlobalEntry("HTTPS","on")}#c(e){this[h].ccall("wasm_set_request_method",null,[f],[e])}#l(e){e.cookie&&this[h].ccall("wasm_set_cookies",null,[f],[e.cookie]),e["content-type"]&&this[h].ccall("wasm_set_content_type",null,[f],[e["content-type"]]),e["content-length"]&&this[h].ccall("wasm_set_content_length",null,[E],[parseInt(e["content-length"],10)]);for(const r in e)this.addServerGlobalEntry(
|
|
153
|
+
`;this[h].ccall("wasm_set_phpini_entries",null,[f],[e])}this[h].ccall("php_wasm_init",null,[],[])}#n(){const e="/tmp/headers.json";if(!this.fileExists(e))throw new Error("SAPI Error: Could not find response headers file.");const r=JSON.parse(this.readFileAsText(e)),s={};for(const n of r.headers){if(!n.includes(": "))continue;const i=n.indexOf(": "),o=n.substring(0,i).toLowerCase(),a=n.substring(i+2);o in s||(s[o]=[]),s[o].push(a)}return{headers:s,httpStatusCode:r.status}}#o(e){if(this[h].ccall("wasm_set_request_uri",null,[f],[e]),e.includes("?")){const r=e.substring(e.indexOf("?")+1);this[h].ccall("wasm_set_query_string",null,[f],[r])}}#a(e,r){this[h].ccall("wasm_set_request_host",null,[f],[e]);let s;try{s=parseInt(new URL(e).port,10)}catch{}(!s||isNaN(s)||s===80)&&(s=r==="https"?443:80),this[h].ccall("wasm_set_request_port",null,[E],[s]),(r==="https"||!r&&s===443)&&this.addServerGlobalEntry("HTTPS","on")}#c(e){this[h].ccall("wasm_set_request_method",null,[f],[e])}#l(e){e.cookie&&this[h].ccall("wasm_set_cookies",null,[f],[e.cookie]),e["content-type"]&&this[h].ccall("wasm_set_content_type",null,[f],[e["content-type"]]),e["content-length"]&&this[h].ccall("wasm_set_content_length",null,[E],[parseInt(e["content-length"],10)]);for(const r in e){let s="HTTP_";["content-type","content-length"].includes(r.toLowerCase())&&(s=""),this.addServerGlobalEntry(`${s}${r.toUpperCase().replace(/-/g,"_")}`,e[r])}}#u(e){this[h].ccall("wasm_set_request_body",null,[f],[e]),this[h].ccall("wasm_set_content_length",null,[E],[new TextEncoder().encode(e).length])}#h(e){this[h].ccall("wasm_set_path_translated",null,[f],[e])}addServerGlobalEntry(e,r){this.#r[e]=r}#d(){for(const e in this.#r)this[h].ccall("wasm_add_SERVER_entry",null,[f,f],[e,this.#r[e]])}#p(e){const{key:r,name:s,type:n,data:i}=e,o=`/tmp/${Math.random().toFixed(20)}`;this.writeFile(o,i);const a=0;this[h].ccall("wasm_add_uploaded_file",null,[f,f,f,f,E,E],[r,s,n,o,a,i.byteLength])}#f(e){this[h].ccall("wasm_set_php_code",null,[f],[e])}async#m(){let e,r;try{e=await new Promise((i,o)=>{r=l=>{const c=new Error("Rethrown");c.cause=l.error,c.betterMessage=l.message,o(c)},this.#s?.addEventListener("error",r);const a=this[h].ccall("wasm_sapi_handle_request",E,[],[]);return a instanceof Promise?a.then(i,o):i(a)})}catch(i){for(const c in this)typeof this[c]=="function"&&(this[c]=()=>{throw new Error("PHP runtime has crashed – see the earlier error for details.")});this.functionsMaybeMissingFromAsyncify=mt();const o=i,a="betterMessage"in o?o.betterMessage:o.message,l=new Error(a);throw l.cause=o,l}finally{this.#s?.removeEventListener("error",r),this.#r={}}const{headers:s,httpStatusCode:n}=this.#n();return new b(n,s,this.readFileAsBuffer("/tmp/stdout"),this.readFileAsText("/tmp/stderr"),e)}mkdir(e){this[h].FS.mkdirTree(e)}mkdirTree(e){this.mkdir(e)}readFileAsText(e){return new TextDecoder().decode(this.readFileAsBuffer(e))}readFileAsBuffer(e){return this[h].FS.readFile(e)}writeFile(e,r){this[h].FS.writeFile(e,r)}unlink(e){this[h].FS.unlink(e)}mv(e,r){this[h].FS.rename(e,r)}rmdir(e,r={recursive:!0}){r?.recursive&&this.listFiles(e).forEach(s=>{const n=`${e}/${s}`;this.isDir(n)?this.rmdir(n,r):this.unlink(n)}),this[h].FS.rmdir(e)}listFiles(e,r={prependPath:!1}){if(!this.fileExists(e))return[];try{const s=this[h].FS.readdir(e).filter(n=>n!=="."&&n!=="..");if(r.prependPath){const n=e.replace(/\/$/,"");return s.map(i=>`${n}/${i}`)}return s}catch(s){return console.error(s,{path:e}),[]}}isDir(e){return this.fileExists(e)?this[h].FS.isDir(this[h].FS.lookupPath(e).node.mode):!1}fileExists(e){try{return this[h].FS.lookupPath(e),!0}catch{return!1}}}w([m('Could not create directory "{path}"')],g.prototype,"mkdir",1);w([m('Could not create directory "{path}"')],g.prototype,"mkdirTree",1);w([m('Could not read "{path}"')],g.prototype,"readFileAsText",1);w([m('Could not read "{path}"')],g.prototype,"readFileAsBuffer",1);w([m('Could not write to "{path}"')],g.prototype,"writeFile",1);w([m('Could not unlink "{path}"')],g.prototype,"unlink",1);w([m('Could not move "{path}"')],g.prototype,"mv",1);w([m('Could not remove directory "{path}"')],g.prototype,"rmdir",1);w([m('Could not list files in "{path}"')],g.prototype,"listFiles",1);w([m('Could not stat "{path}"')],g.prototype,"isDir",1);w([m('Could not stat "{path}"')],g.prototype,"fileExists",1);function De(t){const e={};for(const r in t)e[r.toLowerCase()]=t[r];return e}const At=["vfs","literal","wordpress.org/themes","wordpress.org/plugins","url"];function Lt(t){return t&&typeof t=="object"&&typeof t.resource=="string"&&At.includes(t.resource)}class ${static create(e,{semaphore:r,progress:s}){let n;switch(e.resource){case"vfs":n=new Ot(e,s);break;case"literal":n=new Ut(e,s);break;case"wordpress.org/themes":n=new It(e,s);break;case"wordpress.org/plugins":n=new zt(e,s);break;case"url":n=new Nt(e,s);break;default:throw new Error(`Invalid resource: ${e}`)}return n=new Mt(n),r&&(n=new Dt(n,r)),n}setPlayground(e){this.playground=e}get isAsync(){return!1}}class Ot extends ${constructor(e,r){super(),this.resource=e,this.progress=r}async resolve(){const e=await this.playground.readFileAsBuffer(this.resource.path);return this.progress?.set(100),new j([e],this.name)}get name(){return this.resource.path.split("/").pop()||""}}class Ut extends ${constructor(e,r){super(),this.resource=e,this.progress=r}async resolve(){return this.progress?.set(100),new j([this.resource.contents],this.resource.name)}get name(){return this.resource.name}}class Y extends ${constructor(e){super(),this.progress=e}async resolve(){this.progress?.setCaption(this.caption);const e=this.getURL();let r=await fetch(e);if(r=await ht(r,this.progress?.loadingListener??Ht),r.status!==200)throw new Error(`Could not download "${e}"`);return new j([await r.blob()],this.name)}get caption(){return`Downloading ${this.name}`}get name(){try{return new URL(this.getURL(),"http://example.com").pathname.split("/").pop()}catch{return this.getURL()}}get isAsync(){return!0}}const Ht=()=>{};class Nt extends Y{constructor(e,r){super(r),this.resource=e}getURL(){return this.resource.url}get caption(){return this.resource.caption??super.caption}}let J="https://playground.wordpress.net/plugin-proxy";function Wt(t){J=t}class It extends Y{constructor(e,r){super(r),this.resource=e}get name(){return L(this.resource.slug)}getURL(){const e=qe(this.resource.slug);return`${J}?theme=`+e}}class zt extends Y{constructor(e,r){super(r),this.resource=e}get name(){return L(this.resource.slug)}getURL(){const e=qe(this.resource.slug);return`${J}?plugin=`+e}}function qe(t){return!t||t.endsWith(".zip")?t:t+".latest-stable.zip"}class je extends ${constructor(e){super(),this.resource=e}async resolve(){return this.resource.resolve()}async setPlayground(e){return this.resource.setPlayground(e)}get progress(){return this.resource.progress}set progress(e){this.resource.progress=e}get name(){return this.resource.name}get isAsync(){return this.resource.isAsync}}class Mt extends je{async resolve(){return this.promise||(this.promise=super.resolve()),this.promise}}class Dt extends je{constructor(e,r){super(e),this.semaphore=r}async resolve(){return this.isAsync?this.semaphore.run(()=>super.resolve()):super.resolve()}}const qt=["6.2","6.1","6.0","5.9"];function Be(t,{progress:e=new H,semaphore:r=new Te({concurrency:3}),onStepCompleted:s=()=>{}}={}){const n=(t.steps||[]).filter(jt),i=n.reduce((a,l)=>a+(l.progress?.weight||1),0),o=n.map(a=>Bt(a,{semaphore:r,rootProgressTracker:e,totalProgressWeight:i}));return{versions:{php:he(t.preferredVersions?.php,N,Me),wp:he(t.preferredVersions?.wp,qt,"6.2")},run:async a=>{try{for(const{resources:l}of o)for(const c of l)c.setPlayground(a),c.isAsync&&c.resolve();for(const{run:l,step:c}of o){const u=await l(a);s(u,c)}try{await a.goTo(t.landingPage||"/")}catch{}}finally{e.finish()}}}}function he(t,e,r){return t&&e.includes(t)?t:r}function jt(t){return!!(typeof t=="object"&&t)}function Bt(t,{semaphore:e,rootProgressTracker:r,totalProgressWeight:s}){const n=r.stage((t.progress?.weight||1)/s),i={};for(const u of Object.keys(t)){let d=t[u];Lt(d)&&(d=$.create(d,{semaphore:e})),i[u]=d}const o=async u=>{try{return n.fillSlowly(),await lt[t.step](u,await Vt(i),{tracker:n,initialCaption:t.progress?.caption})}finally{n.finish()}},a=de(i),l=de(i).filter(u=>u.isAsync),c=1/(l.length+1);for(const u of l)u.progress=n.stage(c);return{run:o,step:t,resources:a}}function de(t){const e=[];for(const r in t){const s=t[r];s instanceof $&&e.push(s)}return e}async function Vt(t){const e={};for(const r in t){const s=t[r];s instanceof $?e[r]=await s.resolve():e[r]=s}return e}async function Ve(t,e){await t.run(e)}/**
|
|
141
154
|
* @license
|
|
142
155
|
* Copyright 2019 Google LLC
|
|
143
156
|
* SPDX-License-Identifier: Apache-2.0
|
|
144
|
-
*/const
|
|
157
|
+
*/const Ge=Symbol("Comlink.proxy"),Gt=Symbol("Comlink.endpoint"),Yt=Symbol("Comlink.releaseProxy"),I=Symbol("Comlink.finalizer"),T=Symbol("Comlink.thrown"),Ye=t=>typeof t=="object"&&t!==null||typeof t=="function",Jt={canHandle:t=>Ye(t)&&t[Ge],serialize(t){const{port1:e,port2:r}=new MessageChannel;return K(t,e),[r,[r]]},deserialize(t){return t.start(),Z(t)}},Kt={canHandle:t=>Ye(t)&&T in t,serialize({value:t}){let e;return t instanceof Error?e={isError:!0,value:{message:t.message,name:t.name,stack:t.stack}}:e={isError:!1,value:t},[e,[]]},deserialize(t){throw t.isError?Object.assign(new Error(t.value.message),t.value):t.value}},R=new Map([["proxy",Jt],["throw",Kt]]);function Zt(t,e){for(const r of t)if(e===r||r==="*"||r instanceof RegExp&&r.test(e))return!0;return!1}function K(t,e=globalThis,r=["*"]){e.addEventListener("message",function s(n){if(!n||!n.data)return;if(!Zt(r,n.origin)){console.warn(`Invalid origin '${n.origin}' for comlink proxy`);return}const{id:i,type:o,path:a}=Object.assign({path:[]},n.data),l=(n.data.argumentList||[]).map(P);let c;try{const u=a.slice(0,-1).reduce((p,y)=>p[y],t),d=a.reduce((p,y)=>p[y],t);switch(o){case"GET":c=d;break;case"SET":u[a.slice(-1)[0]]=P(n.data.value),c=!0;break;case"APPLY":c=d.apply(u,l);break;case"CONSTRUCT":{const p=new d(...l);c=Qe(p)}break;case"ENDPOINT":{const{port1:p,port2:y}=new MessageChannel;K(t,y),c=rr(p,[p])}break;case"RELEASE":c=void 0;break;default:return}}catch(u){c={value:u,[T]:0}}Promise.resolve(c).catch(u=>({value:u,[T]:0})).then(u=>{const[d,p]=A(u);e.postMessage(Object.assign(Object.assign({},d),{id:i}),p),o==="RELEASE"&&(e.removeEventListener("message",s),Je(e),I in t&&typeof t[I]=="function"&&t[I]())}).catch(u=>{const[d,p]=A({value:new TypeError("Unserializable return value"),[T]:0});e.postMessage(Object.assign(Object.assign({},d),{id:i}),p)})}),e.start&&e.start()}function Qt(t){return t.constructor.name==="MessagePort"}function Je(t){Qt(t)&&t.close()}function Z(t,e){return M(t,[],e)}function x(t){if(t)throw new Error("Proxy has been released and is not useable")}function Ke(t){return v(t,{type:"RELEASE"}).then(()=>{Je(t)})}const C=new WeakMap,k="FinalizationRegistry"in globalThis&&new FinalizationRegistry(t=>{const e=(C.get(t)||0)-1;C.set(t,e),e===0&&Ke(t)});function Xt(t,e){const r=(C.get(e)||0)+1;C.set(e,r),k&&k.register(t,e,t)}function er(t){k&&k.unregister(t)}function M(t,e=[],r=function(){}){let s=!1;const n=new Proxy(r,{get(i,o){if(x(s),o===Yt)return()=>{er(n),Ke(t),s=!0};if(o==="then"){if(e.length===0)return{then:()=>n};const a=v(t,{type:"GET",path:e.map(l=>l.toString())}).then(P);return a.then.bind(a)}return M(t,[...e,o])},set(i,o,a){x(s);const[l,c]=A(a);return v(t,{type:"SET",path:[...e,o].map(u=>u.toString()),value:l},c).then(P)},apply(i,o,a){x(s);const l=e[e.length-1];if(l===Gt)return v(t,{type:"ENDPOINT"}).then(P);if(l==="bind")return M(t,e.slice(0,-1));const[c,u]=pe(a);return v(t,{type:"APPLY",path:e.map(d=>d.toString()),argumentList:c},u).then(P)},construct(i,o){x(s);const[a,l]=pe(o);return v(t,{type:"CONSTRUCT",path:e.map(c=>c.toString()),argumentList:a},l).then(P)}});return Xt(n,t),n}function tr(t){return Array.prototype.concat.apply([],t)}function pe(t){const e=t.map(A);return[e.map(r=>r[0]),tr(e.map(r=>r[1]))]}const Ze=new WeakMap;function rr(t,e){return Ze.set(t,e),t}function Qe(t){return Object.assign(t,{[Ge]:!0})}function sr(t,e=globalThis,r="*"){return{postMessage:(s,n)=>t.postMessage(s,r,n),addEventListener:e.addEventListener.bind(e),removeEventListener:e.removeEventListener.bind(e)}}function A(t){for(const[e,r]of R)if(r.canHandle(t)){const[s,n]=r.serialize(t);return[{type:"HANDLER",name:e,value:s},n]}return[{type:"RAW",value:t},Ze.get(t)||[]]}function P(t){switch(t.type){case"HANDLER":return R.get(t.name).deserialize(t.value);case"RAW":return t.value}}function v(t,e,r){return new Promise(s=>{const n=nr();t.addEventListener("message",function i(o){!o.data||!o.data.id||o.data.id!==n||(t.removeEventListener("message",i),s(o.data))}),t.start&&t.start(),t.postMessage(Object.assign({id:n},e),r)})}function nr(){return new Array(4).fill(0).map(()=>Math.floor(Math.random()*Number.MAX_SAFE_INTEGER).toString(16)).join("-")}function Xe(t){ir();const e=t instanceof Worker?t:sr(t),r=Z(e),s=et(r);return new Proxy(s,{get:(n,i)=>i==="isConnected"?()=>r.isConnected():r[i]})}let fe=!1;function ir(){fe||(fe=!0,R.set("EVENT",{canHandle:t=>t instanceof CustomEvent,serialize:t=>[{detail:t.detail},[]],deserialize:t=>t}),R.set("FUNCTION",{canHandle:t=>typeof t=="function",serialize(t){console.debug("[Comlink][Performance] Proxying a function");const{port1:e,port2:r}=new MessageChannel;return K(t,e),[r,[r]]},deserialize(t){return t.start(),Z(t)}}),R.set("PHPResponse",{canHandle:t=>typeof t=="object"&&t!==null&&"headers"in t&&"bytes"in t&&"errors"in t&&"exitCode"in t&&"httpStatusCode"in t,serialize(t){return[t.toRawData(),[]]},deserialize(t){return b.fromRawData(t)}}))}function et(t){return new Proxy(t,{get(e,r){switch(typeof e[r]){case"function":return(...s)=>e[r](...s);case"object":return e[r]===null?e[r]:et(e[r]);case"undefined":case"number":case"string":return e[r];default:return Qe(e[r])}}})}(function(){return typeof navigator<"u"&&navigator?.userAgent?.toLowerCase().indexOf("firefox")>-1?"iframe":"webworker"})();async function tt({iframe:t,blueprint:e,remoteUrl:r,progressTracker:s=new H,disableProgressBar:n,onBlueprintStepCompleted:i}){if(or(r),r=we(r,{progressbar:!n}),s.setCaption("Preparing WordPress"),!e)return me(t,r,s);const o=Be(e,{progress:s.stage(.5),onStepCompleted:i}),a=await me(t,we(r,{php:o.versions.php,wp:o.versions.wp}),s);return await Ve(o,a),s.finish(),a}async function me(t,e,r){await new Promise(i=>{t.src=e,t.addEventListener("load",i,!1)});const s=Xe(t.contentWindow);await s.isConnected(),r.pipe(s);const n=r.stage();return await s.onDownloadProgress(n.loadingListener),await s.isReady(),n.finish(),s}const F="https://playground.wordpress.net";function or(t){const e=new URL(t,F);if((e.origin===F||e.hostname==="localhost")&&e.pathname!=="/remote.html")throw new Error(`Invalid remote URL: ${e}. Expected origin to be ${F}/remote.html.`)}function we(t,e){const r=new URL(t,F),s=new URLSearchParams(r.search);for(const[n,i]of Object.entries(e))i!=null&&i!==!1&&s.set(n,i.toString());return r.search=s.toString(),r.toString()}async function ar(t,e){if(console.warn("`connectPlayground` is deprecated and will be removed. Use `startPlayground` instead."),e?.loadRemote)return tt({iframe:t,remoteUrl:e.loadRemote});const r=Xe(t.contentWindow);return await r.isConnected(),r}exports.LatestSupportedPHPVersion=Me;exports.SupportedPHPVersions=N;exports.SupportedPHPVersionsList=_t;exports.activatePlugin=D;exports.activateTheme=q;exports.applyWordPressPatches=ge;exports.compileBlueprint=Be;exports.connectPlayground=ar;exports.cp=$e;exports.defineSiteUrl=xe;exports.defineWpConfigConsts=V;exports.importFile=ke;exports.installPlugin=Oe;exports.installTheme=Ue;exports.login=He;exports.mkdir=ve;exports.mv=Ee;exports.phpVar=_;exports.phpVars=O;exports.replaceSite=Ce;exports.request=_e;exports.rm=Se;exports.rmdir=Re;exports.runBlueprintSteps=Ve;exports.runPHP=ye;exports.runPHPWithOptions=Pe;exports.runWpInstallationWizard=Ne;exports.setPhpIniEntry=be;exports.setPluginProxyURL=Wt;exports.setSiteOptions=We;exports.startPlaygroundWeb=tt;exports.unzip=U;exports.updateUserMeta=Ie;exports.writeFile=B;exports.zipEntireSite=Fe;
|
package/index.d.ts
CHANGED
|
@@ -407,9 +407,10 @@ export interface IsomorphicLocalPHP extends RequestHandler {
|
|
|
407
407
|
* Lists the files and directories in the given directory.
|
|
408
408
|
*
|
|
409
409
|
* @param path - The directory path to list.
|
|
410
|
+
* @param options - Options for the listing.
|
|
410
411
|
* @returns The list of files and directories in the given directory.
|
|
411
412
|
*/
|
|
412
|
-
listFiles(path: string): string[];
|
|
413
|
+
listFiles(path: string, options?: ListFilesOptions): string[];
|
|
413
414
|
/**
|
|
414
415
|
* Checks if a directory exists in the PHP filesystem.
|
|
415
416
|
*
|
|
@@ -593,6 +594,13 @@ export interface RmDirOptions {
|
|
|
593
594
|
*/
|
|
594
595
|
recursive?: boolean;
|
|
595
596
|
}
|
|
597
|
+
export interface ListFilesOptions {
|
|
598
|
+
/**
|
|
599
|
+
* If true, prepend given folder path to all file names.
|
|
600
|
+
* Default: false.
|
|
601
|
+
*/
|
|
602
|
+
prependPath: boolean;
|
|
603
|
+
}
|
|
596
604
|
/**
|
|
597
605
|
* Emscripten's filesystem-related Exception.
|
|
598
606
|
*
|
|
@@ -782,7 +790,7 @@ declare abstract class BasePHP implements IsomorphicLocalPHP {
|
|
|
782
790
|
/** @inheritDoc */
|
|
783
791
|
rmdir(path: string, options?: RmDirOptions): void;
|
|
784
792
|
/** @inheritDoc */
|
|
785
|
-
listFiles(path: string): string[];
|
|
793
|
+
listFiles(path: string, options?: ListFilesOptions): string[];
|
|
786
794
|
/** @inheritDoc */
|
|
787
795
|
isDir(path: string): boolean;
|
|
788
796
|
/** @inheritDoc */
|
|
@@ -1012,12 +1020,12 @@ export declare class SemaphoreResource<T extends Resource> extends DecoratedReso
|
|
|
1012
1020
|
export interface ActivatePluginStep {
|
|
1013
1021
|
step: "activatePlugin";
|
|
1014
1022
|
pluginPath: string;
|
|
1023
|
+
pluginName?: string;
|
|
1015
1024
|
}
|
|
1016
1025
|
/**
|
|
1017
1026
|
* Activates a WordPress plugin in the Playground.
|
|
1018
1027
|
*
|
|
1019
1028
|
* @param playground The playground client.
|
|
1020
|
-
* @param plugin The plugin slug.
|
|
1021
1029
|
*/
|
|
1022
1030
|
export declare const activatePlugin: StepHandler<ActivatePluginStep>;
|
|
1023
1031
|
export interface ApplyWordPressPatchesStep {
|
|
@@ -1130,8 +1138,6 @@ export interface InstallPluginOptions {
|
|
|
1130
1138
|
}
|
|
1131
1139
|
/**
|
|
1132
1140
|
* Installs a WordPress plugin in the Playground.
|
|
1133
|
-
* Technically, it uses the same plugin upload form as a WordPress user
|
|
1134
|
-
* would, and then activates the plugin if needed.
|
|
1135
1141
|
*
|
|
1136
1142
|
* @param playground The playground client.
|
|
1137
1143
|
* @param pluginZipFile The plugin zip file.
|
|
@@ -1184,8 +1190,6 @@ export interface InstallThemeOptions {
|
|
|
1184
1190
|
}
|
|
1185
1191
|
/**
|
|
1186
1192
|
* Installs a WordPress theme in the Playground.
|
|
1187
|
-
* Technically, it uses the same theme upload form as a WordPress user
|
|
1188
|
-
* would, and then activates the theme if needed.
|
|
1189
1193
|
*
|
|
1190
1194
|
* @param playground The playground client.
|
|
1191
1195
|
* @param themeZipFile The theme zip file.
|
|
@@ -1322,7 +1326,7 @@ export declare const runPHP: StepHandler<RunPHPStep>;
|
|
|
1322
1326
|
* {
|
|
1323
1327
|
* "step": "runPHP",
|
|
1324
1328
|
* "options": {
|
|
1325
|
-
* "code": "<?php echo $_SERVER['
|
|
1329
|
+
* "code": "<?php echo $_SERVER['CONTENT_TYPE']; ?>",
|
|
1326
1330
|
* "headers": {
|
|
1327
1331
|
* "Content-type": "text/plain"
|
|
1328
1332
|
* }
|
|
@@ -1565,18 +1569,18 @@ export type StepDefinition = Step & {
|
|
|
1565
1569
|
* add it to the exports below.
|
|
1566
1570
|
*/
|
|
1567
1571
|
export type GenericStep<Resource> = ActivatePluginStep | ActivateThemeStep | ApplyWordPressPatchesStep | CpStep | DefineWpConfigConstsStep | DefineSiteUrlStep | ImportFileStep<Resource> | InstallPluginStep<Resource> | InstallThemeStep<Resource> | LoginStep | MkdirStep | MvStep | RequestStep | ReplaceSiteStep<Resource> | RmStep | RmdirStep | RunPHPStep | RunPHPWithOptionsStep | RunWpInstallationWizardStep | SetPhpIniEntryStep | SetSiteOptionsStep | UnzipStep | UpdateUserMetaStep | WriteFileStep<Resource>;
|
|
1568
|
-
export type StepHandler<S extends GenericStep<File>> = (
|
|
1569
|
-
/**
|
|
1570
|
-
* A PHP instance or Playground client.
|
|
1571
|
-
*/
|
|
1572
|
-
php: UniversalPHP, args: Omit<S, "step">,
|
|
1573
1572
|
/**
|
|
1574
1573
|
* Progress reporting details.
|
|
1575
1574
|
*/
|
|
1576
|
-
|
|
1575
|
+
export type StepProgress = {
|
|
1577
1576
|
tracker: ProgressTracker;
|
|
1578
1577
|
initialCaption?: string;
|
|
1579
|
-
}
|
|
1578
|
+
};
|
|
1579
|
+
export type StepHandler<S extends GenericStep<File>> = (
|
|
1580
|
+
/**
|
|
1581
|
+
* A PHP instance or Playground client.
|
|
1582
|
+
*/
|
|
1583
|
+
php: UniversalPHP, args: Omit<S, "step">, progressArgs?: StepProgress) => any;
|
|
1580
1584
|
export interface Blueprint {
|
|
1581
1585
|
/**
|
|
1582
1586
|
* The URL to navigate to after the blueprint has been run.
|
|
@@ -1726,7 +1730,7 @@ declare class WebPHPEndpoint implements IsomorphicLocalPHP {
|
|
|
1726
1730
|
/** @inheritDoc @php-wasm/web!WebPHP.unlink */
|
|
1727
1731
|
unlink(path: string): void;
|
|
1728
1732
|
/** @inheritDoc @php-wasm/web!WebPHP.listFiles */
|
|
1729
|
-
listFiles(path: string): string[];
|
|
1733
|
+
listFiles(path: string, options?: ListFilesOptions): string[];
|
|
1730
1734
|
/** @inheritDoc @php-wasm/web!WebPHP.isDir */
|
|
1731
1735
|
isDir(path: string): boolean;
|
|
1732
1736
|
/** @inheritDoc @php-wasm/web!WebPHP.fileExists */
|