@wp-playground/cli 1.0.26 → 1.0.28
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/README.md +76 -0
- package/cli.js +5 -4
- package/cli.js.map +1 -1
- package/package.json +9 -9
package/README.md
ADDED
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
# WordPress Playground CLI
|
|
2
|
+
|
|
3
|
+
A CLI tool for running WordPress playground locally instead of in the browser:
|
|
4
|
+
|
|
5
|
+
```shell
|
|
6
|
+
$ bun packages/playground/cli/src/cli.ts server --wp=6.5
|
|
7
|
+
WordPress is running on http://127.0.0.1:9400
|
|
8
|
+
```
|
|
9
|
+
|
|
10
|
+
Playground CLI is simple, configurable, and unopinionated. You can set it up
|
|
11
|
+
to your unique WordPress setup. For example, this command would run the documentation
|
|
12
|
+
workflow at https://github.com/adamziel/playground-docs-workflow:
|
|
13
|
+
|
|
14
|
+
```shell
|
|
15
|
+
bun --config=/Users/adam/.bunfig.toml \
|
|
16
|
+
./packages/playground/cli/src/cli.ts \
|
|
17
|
+
server \
|
|
18
|
+
--mount=./wp-content/plugins/wp-docs-plugin:/wordpress/wp-content/plugins/wp-docs-plugin \
|
|
19
|
+
--mount=./wp-content/html-pages:/wordpress/wp-content/html-pages \
|
|
20
|
+
--mount=./wp-content/uploads:/wordpress/wp-content/uploads \
|
|
21
|
+
--mount=./wp-content/themes/playground-docs:/wordpress/wp-content/themes/playground-docs \
|
|
22
|
+
--blueprint=./wp-content/blueprint-wp-now.json \
|
|
23
|
+
--wp=6.5
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
It is long, sure, but it is also very flexible. If you need a shorter version, you can alias
|
|
27
|
+
it or write a bash script. In the future, Blueprints might support relative path mappings,
|
|
28
|
+
at which point that command would get much shorter.
|
|
29
|
+
|
|
30
|
+
## Philosophy
|
|
31
|
+
|
|
32
|
+
The data flow is as follows:
|
|
33
|
+
|
|
34
|
+
- Start PHP
|
|
35
|
+
- Mount any local directories
|
|
36
|
+
- Put a fresh WordPress in the resulting virtual filesystem (unless you're mounting directly at /wordpress).
|
|
37
|
+
- Run the Blueprint
|
|
38
|
+
- Start a local server, accept requests
|
|
39
|
+
|
|
40
|
+
On each run, a fresh WordPress release is unzipped in the virtual filesystem. It is sourced
|
|
41
|
+
from a zip file cached at ~/.wordpress-playground/. If you mess up your site, just restart the
|
|
42
|
+
server and you'll get a fresh one, again unzipped. The CLI tool never modifies the zip file
|
|
43
|
+
so you can always be sure you're starting from a clean slate.
|
|
44
|
+
|
|
45
|
+
## Future work
|
|
46
|
+
|
|
47
|
+
The CLI tool will have the following commands:
|
|
48
|
+
|
|
49
|
+
- `server` - start a fresh WordPress playground server.
|
|
50
|
+
- `build-snapshot` - run a Blueprint and output a .zip file with the resulting WordPress instance.
|
|
51
|
+
- `run-blueprint` - run a Blueprint and output errors to the console if they occur.
|
|
52
|
+
|
|
53
|
+
It will also support:
|
|
54
|
+
|
|
55
|
+
- Loading Blueprints from URLs.
|
|
56
|
+
- Saving the running WordPress site and loading it later.
|
|
57
|
+
- Caching all remote resources referenced in Blueprints. Currently, say, plugins are downloaded on each run.
|
|
58
|
+
|
|
59
|
+
Conceptually, this isn't too different from Docker containers. There are images (zip files),
|
|
60
|
+
containers (running instances), and commands (Blueprints). Playground could support the same
|
|
61
|
+
concepts such as:
|
|
62
|
+
|
|
63
|
+
- Listing and managing available images and containers.
|
|
64
|
+
- Saving a running container and restoring it later
|
|
65
|
+
- Starting a container from a specific image (already supported via zip files)
|
|
66
|
+
- Running a command in a container (the `php` command)
|
|
67
|
+
- Building a new image from a Blueprint (the `build` command)
|
|
68
|
+
- Step-by-step cache for Blueprints so that only the changed steps are re-run.
|
|
69
|
+
|
|
70
|
+
## Interoperability
|
|
71
|
+
|
|
72
|
+
This CLI package is not just a useful tool. It drives interoperability between the in-browser
|
|
73
|
+
Playground, CLI packages, and the PHP Blueprints library. Once complete, it will reuse the
|
|
74
|
+
same internals as the website at https://playground.wordpress.org whether we're talking about
|
|
75
|
+
running PHP code, executing Blueprints, building snapshots, serving requests, or maintaining
|
|
76
|
+
multiple PHP instances
|
package/cli.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import m from"fs";import
|
|
1
|
+
import m from"fs";import v,{basename as z}from"path";import x from"yargs";import C from"express";import{SupportedPHPVersions as D,PHPResponse as U}from"@php-wasm/universal";import{logger as d,errorLogPath as L}from"@php-wasm/logger";import{runBlueprintSteps as M,compileBlueprint as _}from"@wp-playground/blueprints";import{EmscriptenDownloadMonitor as k,ProgressTracker as q}from"@php-wasm/progress";import{loadNodeRuntime as A,createNodeFsMountHandler as O}from"@php-wasm/node";import{RecommendedPHPVersion as T,zipDirectory as Z}from"@wp-playground/common";import{resolveWordPressRelease as j,bootWordPress as N}from"@wp-playground/wordpress";import{rootCertificates as V}from"tls";import g from"fs-extra";import G from"os";async function Y(t){const e=C(),i=await new Promise((p,c)=>{const a=e.listen(t.port,()=>{const l=a.address();l===null||typeof l=="string"?c(new Error("Server address is not available")):p(a)})});e.use("/",async(p,c)=>{const a=await t.handleRequest({url:p.url,headers:K(p),method:p.method,body:await J(p)});c.statusCode=a.httpStatusCode;for(const l in a.headers)c.setHeader(l,a.headers[l]);c.end(a.bytes)});const P=i.address().port;await t.onBind(P)}const J=async t=>await new Promise(e=>{const i=[];t.on("data",u=>{i.push(u)}),t.on("end",()=>{e(Buffer.concat(i))})}),K=t=>{const e={};if(t.rawHeaders&&t.rawHeaders.length)for(let i=0;i<t.rawHeaders.length;i+=2)e[t.rawHeaders[i].toLowerCase()]=t.rawHeaders[i+1];return e};function Q(t){return/^latest$|^trunk$|^nightly$|^(?:(\d+)\.(\d+)(?:\.(\d+))?)((?:-beta(?:\d+)?)|(?:-RC(?:\d+)?))?$/.test(t)}const $=v.join(G.homedir(),".wordpress-playground");async function X(t){return await S("https://github.com/WordPress/sqlite-database-integration/archive/refs/heads/main.zip","sqlite.zip",t)}async function S(t,e,i){const u=v.join($,e);return g.existsSync(u)||(g.ensureDirSync($),await ee(t,u,i)),E(u)}async function ee(t,e,i){const P=(await i.monitorFetch(fetch(t))).body.getReader(),p=`${e}.partial`,c=g.createWriteStream(p);for(;;){const{done:a,value:l}=await P.read();if(l&&c.write(l),a)break}c.close(),c.closed||await new Promise((a,l)=>{c.on("finish",w=>{w?(g.removeSync(p),l(w)):(g.renameSync(p,e),a(null))})})}function E(t,e){return new File([g.readFileSync(t)],e??z(t))}async function te(){const t=await x(process.argv.slice(2)).usage("Usage: wp-playground <command> [options]").positional("command",{describe:"Command to run",type:"string",choices:["server","run-blueprint","build-snapshot"]}).option("outfile",{describe:"When building, write to this output file.",type:"string",default:"wordpress.zip"}).option("port",{describe:"Port to listen on when serving.",type:"number",default:9400}).option("php",{describe:"PHP version to use.",type:"string",default:T,choices:D}).option("wp",{describe:"WordPress version to use.",type:"string",default:"latest"}).option("mount",{describe:"Mount a directory to the PHP runtime. You can provide --mount multiple times. Format: /host/path:/vfs/path",type:"array",string:!0}).option("mountBeforeInstall",{describe:"Mount a directory to the PHP runtime before installing WordPress. You can provide --mount-before-install multiple times. Format: /host/path:/vfs/path",type:"array",string:!0}).option("login",{describe:"Should log the user in",type:"boolean",default:!1}).option("blueprint",{describe:"Blueprint to execute.",type:"string"}).option("skipWordPressSetup",{describe:"Do not download, unzip, and install WordPress. Useful for mounting a pre-configured WordPress directory at /wordpress.",type:"boolean",default:!1}).option("quiet",{describe:"Do not output logs and progress messages.",type:"boolean",default:!1}).option("debug",{describe:"Print PHP error log content if an error occurs during Playground boot.",type:"boolean",default:!1}).showHelpOnFail(!1).check(r=>{if(r.wp!==void 0&&!Q(r.wp))try{new URL(r.wp)}catch{throw new Error('Unrecognized WordPress version. Please use "latest", a URL, or a numeric version such as "6.2", "6.0.1", "6.2-beta1", or "6.2-RC1"')}if(r.blueprint!==void 0){const s=v.resolve(process.cwd(),r.blueprint);if(!m.existsSync(s))throw new Error("Blueprint file does not exist");const o=m.readFileSync(s,"utf-8");try{r.blueprint=JSON.parse(o)}catch{throw new Error("Blueprint file is not a valid JSON file")}}return!0});t.wrap(t.terminalWidth());const e=await t.argv;e.quiet&&(d.handlers=[]);async function i(r){const{php:s,reap:o}=await w.processManager.acquirePHPInstance();try{await s.run({code:`<?php
|
|
2
2
|
$zip = new ZipArchive();
|
|
3
3
|
if(false === $zip->open('/tmp/build.zip', ZipArchive::CREATE | ZipArchive::OVERWRITE)) {
|
|
4
4
|
throw new Exception('Failed to create ZIP');
|
|
@@ -15,7 +15,8 @@ import m from"fs";import y,{basename as B}from"path";import H from"yargs";import
|
|
|
15
15
|
}
|
|
16
16
|
$zip->close();
|
|
17
17
|
|
|
18
|
-
`});const n=
|
|
19
|
-
`))
|
|
20
|
-
`)}
|
|
18
|
+
`});const n=s.readFileAsBuffer("/tmp/build.zip");m.writeFileSync(r,n)}finally{o()}}function u(r,s){const o=s.map(n=>{const[f,y]=n.split(":");return{hostPath:v.resolve(process.cwd(),f),vfsPath:y}});for(const n of o)r.mkdir(n.vfsPath),r.mount(n.vfsPath,O(n.hostPath))}function P(){let r;e.blueprint?r=e.blueprint:r={preferredVersions:{php:e.php,wp:e.wp},login:e.login};const s=new q;let o="",n=!1;return s.addEventListener("progress",f=>{if(n)return;n=f.detail.progress===100;const y=Math.floor(f.detail.progress);o=f.detail.caption||o||"Running the Blueprint";const R=`${o.trim()} – ${y}%`;e.quiet||c(process.stdout,R,n)}),_(r,{progress:s})}let p="";function c(r,s,o){s!==p&&(p=s,r.isTTY?(r.cursorTo(0),r.write(s),r.clearLine(1),o&&r.write(`
|
|
19
|
+
`)):r.write(`${s}
|
|
20
|
+
`))}const a=e._[0];["run-blueprint","server","build-snapshot"].includes(a)||(t.showHelp(),process.exit(1));const l=P();let w,H=!1;d.log("Starting a PHP server..."),Y({port:e.port,onBind:async r=>{const s=`http://127.0.0.1:${r}`;d.log(`Setting up WordPress ${e.wp}`);let o;const n=new k;if(!e.skipWordPressSetup){let h=!1;n.addEventListener("progress",b=>{if(h)return;const{loaded:F,total:I}=b.detail,B=Math.floor(Math.min(100,100*F/I));h=B===100,e.quiet||c(process.stdout,`Downloading WordPress ${B}%...`,h)}),o=await j(e.wp)}d.log(`Resolved WordPress release URL: ${o?.releaseUrl}`);const f=o&&v.join($,`prebuilt-wp-content-for-wp-${o.version}.zip`),y=o?m.existsSync(f)?E(f):await S(o.releaseUrl,`${o.version}.zip`,n):void 0,R={WP_DEBUG:!0,WP_DEBUG_LOG:!0,WP_DEBUG_DISPLAY:!1};d.log("Booting WordPress..."),w=await N({siteUrl:s,createPhpRuntime:async()=>await A(l.versions.php),wordPressZip:y,sqliteIntegrationPluginZip:X(n),sapiName:"cli",createFiles:{"/internal/shared/ca-bundle.crt":V.join(`
|
|
21
|
+
`)},constants:R,phpIniEntries:{"openssl.cafile":"/internal/shared/ca-bundle.crt",allow_url_fopen:"1",disable_functions:""},hooks:{async beforeWordPressFiles(h){e.mountBeforeInstall&&u(h,e.mountBeforeInstall)}}}),d.log("Booted!");const W=await w.getPrimaryPhp();try{if(o&&!e.mountBeforeInstall&&!m.existsSync(f)&&(d.log("Caching preinstalled WordPress for the next boot..."),m.writeFileSync(f,await Z(W,"/wordpress")),d.log("Cached!")),e.mount&&u(W,e.mount),H=!0,l){const{php:h,reap:b}=await w.processManager.acquirePHPInstance();try{d.log("Running the Blueprint..."),await M(l,h),d.log("Finished running the blueprint")}finally{b()}}a==="build-snapshot"?(await i(e.outfile),d.log(`WordPress exported to ${e.outfile}`),process.exit(0)):a==="run-blueprint"?(d.log("Blueprint executed"),process.exit(0)):d.log(`WordPress is running on ${s}`)}catch(h){if(!e.debug)throw h;const b=W.readFileAsText(L);throw new Error(b,{cause:h})}},async handleRequest(r){return H?await w.request(r):U.forHttpCode(502,"WordPress is not ready yet")}})}te();
|
|
21
22
|
//# sourceMappingURL=cli.js.map
|
package/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.js","sources":["../../../../packages/playground/cli/src/server.ts","../../../../packages/playground/cli/src/is-valid-wordpress-slug.ts","../../../../packages/playground/cli/src/download.ts","../../../../packages/playground/cli/src/cli.ts"],"sourcesContent":["import express, { Request } from 'express';\nimport { PHPRequest, PHPResponse } from '@php-wasm/universal';\nimport { IncomingMessage, Server, ServerResponse } from 'http';\nimport { AddressInfo } from 'net';\n\nexport interface ServerOptions {\n\tport: number;\n\tonBind: (port: number) => Promise<any>;\n\thandleRequest: (request: PHPRequest) => Promise<PHPResponse>;\n}\n\nexport async function startServer(options: ServerOptions) {\n\tconst app = express();\n\n\tconst server = await new Promise<\n\t\tServer<typeof IncomingMessage, typeof ServerResponse>\n\t>((resolve, reject) => {\n\t\tconst server = app.listen(options.port, () => {\n\t\t\tconst address = server.address();\n\t\t\tif (address === null || typeof address === 'string') {\n\t\t\t\treject(new Error('Server address is not available'));\n\t\t\t} else {\n\t\t\t\tresolve(server);\n\t\t\t}\n\t\t});\n\t});\n\n\tapp.use('/', async (req, res) => {\n\t\tconst phpResponse = await options.handleRequest({\n\t\t\turl: req.url,\n\t\t\theaders: parseHeaders(req),\n\t\t\tmethod: req.method as any,\n\t\t\tbody: await bufferRequestBody(req),\n\t\t});\n\n\t\tres.statusCode = phpResponse.httpStatusCode;\n\t\tfor (const key in phpResponse.headers) {\n\t\t\tres.setHeader(key, phpResponse.headers[key]);\n\t\t}\n\t\tres.end(phpResponse.bytes);\n\t});\n\n\tconst address = server.address();\n\tconst port = (address! as AddressInfo).port;\n\tawait options.onBind(port);\n}\n\nconst bufferRequestBody = async (req: Request): Promise<Uint8Array> =>\n\tawait new Promise((resolve) => {\n\t\tconst body: Uint8Array[] = [];\n\t\treq.on('data', (chunk) => {\n\t\t\tbody.push(chunk);\n\t\t});\n\t\treq.on('end', () => {\n\t\t\tresolve(Buffer.concat(body));\n\t\t});\n\t});\n\nconst parseHeaders = (req: Request): Record<string, string> => {\n\tconst requestHeaders: Record<string, string> = {};\n\tif (req.rawHeaders && req.rawHeaders.length) {\n\t\tfor (let i = 0; i < req.rawHeaders.length; i += 2) {\n\t\t\trequestHeaders[req.rawHeaders[i].toLowerCase()] =\n\t\t\t\treq.rawHeaders[i + 1];\n\t\t}\n\t}\n\treturn requestHeaders;\n};\n","/**\n * Checks if the given version string is a valid WordPress version.\n *\n * The Regex is based on the releases on https://wordpress.org/download/releases/#betas\n * The version string can be one of the following formats:\n * - \"latest\"\n * - \"trunk\"\n * - \"nightly\"\n * - \"x.y\" (x and y are integers) e.g. \"6.2\"\n * - \"x.y.z\" (x, y and z are integers) e.g. \"6.2.1\"\n * - \"x.y.z-betaN\" (N is an integer) e.g. \"6.2.1-beta1\"\n * - \"x.y.z-RCN\" (N is an integer) e.g. \"6.2-RC1\"\n *\n * @param version The version string to check.\n * @returns A boolean value indicating whether the version string is a valid WordPress version.\n */\nexport function isValidWordPressSlug(version: string): boolean {\n\tconst versionPattern =\n\t\t/^latest$|^trunk$|^nightly$|^(?:(\\d+)\\.(\\d+)(?:\\.(\\d+))?)((?:-beta(?:\\d+)?)|(?:-RC(?:\\d+)?))?$/;\n\treturn versionPattern.test(version);\n}\n","import { EmscriptenDownloadMonitor } from '@php-wasm/progress';\nimport fs from 'fs-extra';\nimport os from 'os';\nimport path, { basename } from 'path';\n\nexport const CACHE_FOLDER = path.join(os.homedir(), '.wordpress-playground');\n\nexport async function fetchSqliteIntegration(\n\tmonitor: EmscriptenDownloadMonitor\n) {\n\tconst sqliteZip = await cachedDownload(\n\t\t'https://github.com/WordPress/sqlite-database-integration/archive/refs/heads/main.zip',\n\t\t'sqlite.zip',\n\t\tmonitor\n\t);\n\treturn sqliteZip;\n}\n\n// @TODO: Support HTTP cache, invalidate the local file if the remote file has\n// changed\nexport async function cachedDownload(\n\tremoteUrl: string,\n\tcacheKey: string,\n\tmonitor: EmscriptenDownloadMonitor\n) {\n\tconst artifactPath = path.join(CACHE_FOLDER, cacheKey);\n\tif (!fs.existsSync(artifactPath)) {\n\t\tfs.ensureDirSync(CACHE_FOLDER);\n\t\tawait downloadTo(remoteUrl, artifactPath, monitor);\n\t}\n\treturn readAsFile(artifactPath);\n}\n\nasync function downloadTo(\n\tremoteUrl: string,\n\tlocalPath: string,\n\tmonitor: EmscriptenDownloadMonitor\n) {\n\tconst response = await monitor.monitorFetch(fetch(remoteUrl));\n\tconst reader = response.body!.getReader();\n\tconst tmpPath = `${localPath}.partial`;\n\tconst writer = fs.createWriteStream(tmpPath);\n\twhile (true) {\n\t\tconst { done, value } = await reader.read();\n\t\tif (value) {\n\t\t\twriter.write(value);\n\t\t}\n\t\tif (done) {\n\t\t\tbreak;\n\t\t}\n\t}\n\twriter.close();\n\tif (!writer.closed) {\n\t\tawait new Promise((resolve, reject) => {\n\t\t\twriter.on('finish', (err: any) => {\n\t\t\t\tif (err) {\n\t\t\t\t\tfs.removeSync(tmpPath);\n\t\t\t\t\treject(err);\n\t\t\t\t} else {\n\t\t\t\t\tfs.renameSync(tmpPath, localPath);\n\t\t\t\t\tresolve(null);\n\t\t\t\t}\n\t\t\t});\n\t\t});\n\t}\n}\n\nexport function readAsFile(path: string, fileName?: string): File {\n\treturn new File([fs.readFileSync(path)], fileName ?? basename(path));\n}\n","import fs from 'fs';\nimport path from 'path';\nimport yargs from 'yargs';\nimport { startServer } from './server';\nimport {\n\tPHP,\n\tPHPRequest,\n\tPHPRequestHandler,\n\tPHPResponse,\n\tSupportedPHPVersion,\n\tSupportedPHPVersions,\n} from '@php-wasm/universal';\nimport { logger, errorLogPath } from '@php-wasm/logger';\nimport {\n\tBlueprint,\n\tcompileBlueprint,\n\trunBlueprintSteps,\n} from '@wp-playground/blueprints';\nimport { isValidWordPressSlug } from './is-valid-wordpress-slug';\nimport { EmscriptenDownloadMonitor, ProgressTracker } from '@php-wasm/progress';\nimport { createNodeFsMountHandler, loadNodeRuntime } from '@php-wasm/node';\nimport { RecommendedPHPVersion, zipDirectory } from '@wp-playground/common';\nimport { bootWordPress } from '@wp-playground/wordpress';\nimport { rootCertificates } from 'tls';\nimport {\n\tCACHE_FOLDER,\n\tcachedDownload,\n\tfetchSqliteIntegration,\n\treadAsFile,\n} from './download';\nimport { resolveWordPressRelease } from '@wp-playground/wordpress';\nexport interface Mount {\n\thostPath: string;\n\tvfsPath: string;\n}\n\nasync function run() {\n\t/**\n\t * @TODO This looks similar to Query API args https://wordpress.github.io/wordpress-playground/developers/apis/query-api/\n\t * Perhaps the two could be handled by the same code?\n\t */\n\tconst yargsObject = await yargs(process.argv.slice(2))\n\t\t.usage('Usage: wp-playground <command> [options]')\n\t\t.positional('command', {\n\t\t\tdescribe: 'Command to run',\n\t\t\ttype: 'string',\n\t\t\tchoices: ['server', 'run-blueprint', 'build-snapshot'],\n\t\t})\n\t\t.option('outfile', {\n\t\t\tdescribe: 'When building, write to this output file.',\n\t\t\ttype: 'string',\n\t\t\tdefault: 'wordpress.zip',\n\t\t})\n\t\t.option('port', {\n\t\t\tdescribe: 'Port to listen on when serving.',\n\t\t\ttype: 'number',\n\t\t\tdefault: 9400,\n\t\t})\n\t\t.option('php', {\n\t\t\tdescribe: 'PHP version to use.',\n\t\t\ttype: 'string',\n\t\t\tdefault: RecommendedPHPVersion,\n\t\t\tchoices: SupportedPHPVersions,\n\t\t})\n\t\t.option('wp', {\n\t\t\tdescribe: 'WordPress version to use.',\n\t\t\ttype: 'string',\n\t\t\tdefault: 'latest',\n\t\t})\n\t\t// @TODO: Support read-only mounts, e.g. via WORKERFS, a custom\n\t\t// ReadOnlyNODEFS, or by copying the files into MEMFS\n\t\t.option('mount', {\n\t\t\tdescribe:\n\t\t\t\t'Mount a directory to the PHP runtime. You can provide --mount multiple times. Format: /host/path:/vfs/path',\n\t\t\ttype: 'array',\n\t\t\tstring: true,\n\t\t})\n\t\t.option('mountBeforeInstall', {\n\t\t\tdescribe:\n\t\t\t\t'Mount a directory to the PHP runtime before installing WordPress. You can provide --mount-before-install multiple times. Format: /host/path:/vfs/path',\n\t\t\ttype: 'array',\n\t\t\tstring: true,\n\t\t})\n\t\t.option('login', {\n\t\t\tdescribe: 'Should log the user in',\n\t\t\ttype: 'boolean',\n\t\t\tdefault: false,\n\t\t})\n\t\t.option('blueprint', {\n\t\t\tdescribe: 'Blueprint to execute.',\n\t\t\ttype: 'string',\n\t\t})\n\t\t.option('skipWordPressSetup', {\n\t\t\tdescribe:\n\t\t\t\t'Do not download, unzip, and install WordPress. Useful for mounting a pre-configured WordPress directory at /wordpress.',\n\t\t\ttype: 'boolean',\n\t\t\tdefault: false,\n\t\t})\n\t\t.option('quiet', {\n\t\t\tdescribe: 'Do not output logs and progress messages.',\n\t\t\ttype: 'boolean',\n\t\t\tdefault: false,\n\t\t})\n\t\t.option('debug', {\n\t\t\tdescribe:\n\t\t\t\t'Print PHP error log content if an error occurs during Playground boot.',\n\t\t\ttype: 'boolean',\n\t\t\tdefault: false,\n\t\t})\n\t\t.showHelpOnFail(false)\n\t\t.check((args) => {\n\t\t\tif (args.wp !== undefined && !isValidWordPressSlug(args.wp)) {\n\t\t\t\ttry {\n\t\t\t\t\t// Check if is valid URL\n\t\t\t\t\tnew URL(args.wp);\n\t\t\t\t} catch (e) {\n\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t'Unrecognized WordPress version. Please use \"latest\", a URL, or a numeric version such as \"6.2\", \"6.0.1\", \"6.2-beta1\", or \"6.2-RC1\"'\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (args.blueprint !== undefined) {\n\t\t\t\tconst blueprintPath = path.resolve(\n\t\t\t\t\tprocess.cwd(),\n\t\t\t\t\targs.blueprint\n\t\t\t\t);\n\t\t\t\tif (!fs.existsSync(blueprintPath)) {\n\t\t\t\t\tthrow new Error('Blueprint file does not exist');\n\t\t\t\t}\n\n\t\t\t\tconst content = fs.readFileSync(blueprintPath, 'utf-8');\n\t\t\t\ttry {\n\t\t\t\t\targs.blueprint = JSON.parse(content);\n\t\t\t\t} catch (e) {\n\t\t\t\t\tthrow new Error('Blueprint file is not a valid JSON file');\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn true;\n\t\t});\n\n\tyargsObject.wrap(yargsObject.terminalWidth());\n\tconst args = await yargsObject.argv;\n\n\tif (args.quiet) {\n\t\t// @ts-ignore\n\t\tlogger.handlers = [];\n\t}\n\n\t/**\n\t * TODO: This exact feature will be provided in the PHP Blueprints library.\n\t * Let's use it when it ships. Let's also use it in the web Playground\n\t * app.\n\t */\n\tasync function zipSite(outfile: string) {\n\t\t// Fake URL for the build\n\t\tconst { php, reap } =\n\t\t\tawait requestHandler.processManager.acquirePHPInstance();\n\t\ttry {\n\t\t\tawait php.run({\n\t\t\t\tcode: `<?php\n\t\t\t\t$zip = new ZipArchive();\n\t\t\t\tif(false === $zip->open('/tmp/build.zip', ZipArchive::CREATE | ZipArchive::OVERWRITE)) {\n\t\t\t\t\tthrow new Exception('Failed to create ZIP');\n\t\t\t\t}\n\t\t\t\t$files = new RecursiveIteratorIterator(\n\t\t\t\t\tnew RecursiveDirectoryIterator('/wordpress')\n\t\t\t\t);\n\t\t\t\tforeach ($files as $file) {\n\t\t\t\t\techo $file . PHP_EOL;\n\t\t\t\t\tif (!$file->isFile()) {\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t\t$zip->addFile($file->getPathname(), $file->getPathname());\n\t\t\t\t}\n\t\t\t\t$zip->close();\n\n\t\t\t`,\n\t\t\t});\n\t\t\tconst zip = php.readFileAsBuffer('/tmp/build.zip');\n\t\t\tfs.writeFileSync(outfile, zip);\n\t\t} finally {\n\t\t\treap();\n\t\t}\n\t}\n\n\tfunction mountResources(php: PHP, rawMounts: string[]) {\n\t\tconst parsedMounts = rawMounts.map((mount) => {\n\t\t\tconst [source, vfsPath] = mount.split(':');\n\t\t\treturn {\n\t\t\t\thostPath: path.resolve(process.cwd(), source),\n\t\t\t\tvfsPath,\n\t\t\t};\n\t\t});\n\t\tfor (const mount of parsedMounts) {\n\t\t\tphp.mkdir(mount.vfsPath);\n\t\t\tphp.mount(mount.vfsPath, createNodeFsMountHandler(mount.hostPath));\n\t\t}\n\t}\n\n\tfunction compileInputBlueprint() {\n\t\t/**\n\t\t * @TODO This looks similar to the resolveBlueprint() call in the website package:\n\t\t * \t https://github.com/WordPress/wordpress-playground/blob/ce586059e5885d185376184fdd2f52335cca32b0/packages/playground/website/src/main.tsx#L41\n\t\t *\n\t\t * \t\t Also the Blueprint Builder tool does something similar.\n\t\t * Perhaps all these cases could be handled by the same function?\n\t\t */\n\t\tlet blueprint: Blueprint | undefined;\n\t\tif (args.blueprint) {\n\t\t\tblueprint = args.blueprint as Blueprint;\n\t\t} else {\n\t\t\tblueprint = {\n\t\t\t\tpreferredVersions: {\n\t\t\t\t\tphp: args.php as SupportedPHPVersion,\n\t\t\t\t\twp: args.wp,\n\t\t\t\t},\n\t\t\t\tlogin: args.login,\n\t\t\t};\n\t\t}\n\n\t\tconst tracker = new ProgressTracker();\n\t\tlet lastCaption = '';\n\t\tlet progress100 = false;\n\t\ttracker.addEventListener('progress', (e: any) => {\n\t\t\tif (progress100) {\n\t\t\t\treturn;\n\t\t\t} else if (e.detail.progress === 100) {\n\t\t\t\tprogress100 = true;\n\t\t\t}\n\t\t\tlastCaption =\n\t\t\t\te.detail.caption || lastCaption || 'Running the Blueprint';\n\t\t\tprocess.stdout.clearLine(0);\n\t\t\tprocess.stdout.cursorTo(0);\n\t\t\tprocess.stdout.write(\n\t\t\t\t'\\r\\x1b[K' + `${lastCaption.trim()} – ${e.detail.progress}%`\n\t\t\t);\n\t\t\tif (progress100) {\n\t\t\t\tprocess.stdout.write('\\n');\n\t\t\t}\n\t\t});\n\t\treturn compileBlueprint(blueprint as Blueprint, {\n\t\t\tprogress: tracker,\n\t\t});\n\t}\n\n\tconst command = args._[0] as string;\n\tif (!['run-blueprint', 'server', 'build-snapshot'].includes(command)) {\n\t\tyargsObject.showHelp();\n\t\tprocess.exit(1);\n\t}\n\n\tconst compiledBlueprint = compileInputBlueprint();\n\n\tlet requestHandler: PHPRequestHandler;\n\tlet wordPressReady = false;\n\n\tlogger.log('Starting a PHP server...');\n\n\tstartServer({\n\t\tport: args['port'] as number,\n\t\tonBind: async (port: number) => {\n\t\t\tconst absoluteUrl = `http://127.0.0.1:${port}`;\n\n\t\t\tlogger.log(`Setting up WordPress ${args.wp}`);\n\t\t\tlet wpDetails: any = undefined;\n\t\t\tconst monitor = new EmscriptenDownloadMonitor();\n\t\t\tif (!args.skipWordPressSetup) {\n\t\t\t\t// @TODO: Rename to FetchProgressMonitor. There's nothing Emscripten\n\t\t\t\t// about that class anymore.\n\t\t\t\tmonitor.addEventListener('progress', ((\n\t\t\t\t\te: CustomEvent<ProgressEvent & { finished: boolean }>\n\t\t\t\t) => {\n\t\t\t\t\t// @TODO Every progres bar will want percentages. The\n\t\t\t\t\t// download monitor should just provide that.\n\t\t\t\t\tconst percentProgress = Math.round(\n\t\t\t\t\t\tMath.min(100, (100 * e.detail.loaded) / e.detail.total)\n\t\t\t\t\t);\n\t\t\t\t\tif (!args.quiet) {\n\t\t\t\t\t\tprocess.stdout.clearLine(0);\n\t\t\t\t\t\tprocess.stdout.cursorTo(0);\n\t\t\t\t\t\tprocess.stdout.write(\n\t\t\t\t\t\t\t`Downloading WordPress ${percentProgress}%...`\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t}) as any);\n\n\t\t\t\twpDetails = await resolveWordPressRelease(args.wp);\n\t\t\t}\n\t\t\tlogger.log(\n\t\t\t\t`Resolved WordPress release URL: ${wpDetails?.releaseUrl}`\n\t\t\t);\n\n\t\t\tconst preinstalledWpContentPath =\n\t\t\t\twpDetails &&\n\t\t\t\tpath.join(\n\t\t\t\t\tCACHE_FOLDER,\n\t\t\t\t\t`prebuilt-wp-content-for-wp-${wpDetails.version}.zip`\n\t\t\t\t);\n\t\t\tconst wordPressZip = !wpDetails\n\t\t\t\t? undefined\n\t\t\t\t: fs.existsSync(preinstalledWpContentPath)\n\t\t\t\t? readAsFile(preinstalledWpContentPath)\n\t\t\t\t: await cachedDownload(\n\t\t\t\t\t\twpDetails.releaseUrl,\n\t\t\t\t\t\t`${wpDetails.version}.zip`,\n\t\t\t\t\t\tmonitor\n\t\t\t\t );\n\n\t\t\tconst constants: Record<string, string | number | boolean | null> =\n\t\t\t\t{\n\t\t\t\t\tWP_DEBUG: true,\n\t\t\t\t\tWP_DEBUG_LOG: true,\n\t\t\t\t\tWP_DEBUG_DISPLAY: false,\n\t\t\t\t};\n\n\t\t\tlogger.log(`Booting WordPress...`);\n\t\t\trequestHandler = await bootWordPress({\n\t\t\t\tsiteUrl: absoluteUrl,\n\t\t\t\tcreatePhpRuntime: async () =>\n\t\t\t\t\tawait loadNodeRuntime(compiledBlueprint.versions.php),\n\t\t\t\twordPressZip,\n\t\t\t\tsqliteIntegrationPluginZip: fetchSqliteIntegration(monitor),\n\t\t\t\tsapiName: 'cli',\n\t\t\t\tcreateFiles: {\n\t\t\t\t\t'/internal/shared/ca-bundle.crt':\n\t\t\t\t\t\trootCertificates.join('\\n'),\n\t\t\t\t},\n\t\t\t\tconstants,\n\t\t\t\tphpIniEntries: {\n\t\t\t\t\t'openssl.cafile': '/internal/shared/ca-bundle.crt',\n\t\t\t\t\tallow_url_fopen: '1',\n\t\t\t\t\tdisable_functions: '',\n\t\t\t\t},\n\t\t\t\thooks: {\n\t\t\t\t\tasync beforeWordPressFiles(php) {\n\t\t\t\t\t\tif (args.mountBeforeInstall) {\n\t\t\t\t\t\t\tmountResources(php, args.mountBeforeInstall);\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t});\n\t\t\tlogger.log(`Booted!`);\n\n\t\t\tconst php = await requestHandler.getPrimaryPhp();\n\t\t\ttry {\n\t\t\t\tif (\n\t\t\t\t\twpDetails &&\n\t\t\t\t\t!args.mountBeforeInstall &&\n\t\t\t\t\t!fs.existsSync(preinstalledWpContentPath)\n\t\t\t\t) {\n\t\t\t\t\tlogger.log(\n\t\t\t\t\t\t`Caching preinstalled WordPress for the next boot...`\n\t\t\t\t\t);\n\t\t\t\t\tfs.writeFileSync(\n\t\t\t\t\t\tpreinstalledWpContentPath,\n\t\t\t\t\t\tawait zipDirectory(php, '/wordpress')\n\t\t\t\t\t);\n\t\t\t\t\tlogger.log(`Cached!`);\n\t\t\t\t}\n\n\t\t\t\tif (args.mount) {\n\t\t\t\t\tmountResources(php, args.mount);\n\t\t\t\t}\n\n\t\t\t\twordPressReady = true;\n\n\t\t\t\tif (compiledBlueprint) {\n\t\t\t\t\tconst { php, reap } =\n\t\t\t\t\t\tawait requestHandler.processManager.acquirePHPInstance();\n\t\t\t\t\ttry {\n\t\t\t\t\t\tlogger.log(`Running the Blueprint...`);\n\t\t\t\t\t\tawait runBlueprintSteps(compiledBlueprint, php);\n\t\t\t\t\t\tlogger.log(`Finished running the blueprint`);\n\t\t\t\t\t} finally {\n\t\t\t\t\t\treap();\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (command === 'build-snapshot') {\n\t\t\t\t\tawait zipSite(args.outfile as string);\n\t\t\t\t\tlogger.log(`WordPress exported to ${args.outfile}`);\n\t\t\t\t\tprocess.exit(0);\n\t\t\t\t} else if (command === 'run-blueprint') {\n\t\t\t\t\tlogger.log(`Blueprint executed`);\n\t\t\t\t\tprocess.exit(0);\n\t\t\t\t} else {\n\t\t\t\t\tlogger.log(`WordPress is running on ${absoluteUrl}`);\n\t\t\t\t}\n\t\t\t} catch (error) {\n\t\t\t\tif (!args.debug) {\n\t\t\t\t\tthrow error;\n\t\t\t\t}\n\t\t\t\tconst phpLogs = php.readFileAsText(errorLogPath);\n\t\t\t\tthrow new Error(phpLogs, { cause: error });\n\t\t\t}\n\t\t},\n\t\tasync handleRequest(request: PHPRequest) {\n\t\t\tif (!wordPressReady) {\n\t\t\t\treturn PHPResponse.forHttpCode(\n\t\t\t\t\t502,\n\t\t\t\t\t'WordPress is not ready yet'\n\t\t\t\t);\n\t\t\t}\n\t\t\treturn await requestHandler.request(request);\n\t\t},\n\t});\n}\n\nrun();\n"],"names":["startServer","options","app","express","server","resolve","reject","address","req","res","phpResponse","parseHeaders","bufferRequestBody","key","port","body","chunk","requestHeaders","isValidWordPressSlug","version","CACHE_FOLDER","path","os","fetchSqliteIntegration","monitor","cachedDownload","remoteUrl","cacheKey","artifactPath","fs","downloadTo","readAsFile","localPath","reader","tmpPath","writer","done","value","err","fileName","basename","run","yargsObject","yargs","RecommendedPHPVersion","SupportedPHPVersions","args","blueprintPath","content","logger","zipSite","outfile","php","reap","requestHandler","zip","mountResources","rawMounts","parsedMounts","mount","source","vfsPath","createNodeFsMountHandler","compileInputBlueprint","blueprint","tracker","ProgressTracker","lastCaption","progress100","e","compileBlueprint","command","compiledBlueprint","wordPressReady","absoluteUrl","wpDetails","EmscriptenDownloadMonitor","percentProgress","resolveWordPressRelease","preinstalledWpContentPath","wordPressZip","constants","bootWordPress","loadNodeRuntime","rootCertificates","zipDirectory","runBlueprintSteps","error","phpLogs","errorLogPath","request","PHPResponse"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"cli.js","sources":["../../../../packages/playground/cli/src/server.ts","../../../../packages/playground/cli/src/is-valid-wordpress-slug.ts","../../../../packages/playground/cli/src/download.ts","../../../../packages/playground/cli/src/cli.ts"],"sourcesContent":["import express, { Request } from 'express';\nimport { PHPRequest, PHPResponse } from '@php-wasm/universal';\nimport { IncomingMessage, Server, ServerResponse } from 'http';\nimport { AddressInfo } from 'net';\n\nexport interface ServerOptions {\n\tport: number;\n\tonBind: (port: number) => Promise<any>;\n\thandleRequest: (request: PHPRequest) => Promise<PHPResponse>;\n}\n\nexport async function startServer(options: ServerOptions) {\n\tconst app = express();\n\n\tconst server = await new Promise<\n\t\tServer<typeof IncomingMessage, typeof ServerResponse>\n\t>((resolve, reject) => {\n\t\tconst server = app.listen(options.port, () => {\n\t\t\tconst address = server.address();\n\t\t\tif (address === null || typeof address === 'string') {\n\t\t\t\treject(new Error('Server address is not available'));\n\t\t\t} else {\n\t\t\t\tresolve(server);\n\t\t\t}\n\t\t});\n\t});\n\n\tapp.use('/', async (req, res) => {\n\t\tconst phpResponse = await options.handleRequest({\n\t\t\turl: req.url,\n\t\t\theaders: parseHeaders(req),\n\t\t\tmethod: req.method as any,\n\t\t\tbody: await bufferRequestBody(req),\n\t\t});\n\n\t\tres.statusCode = phpResponse.httpStatusCode;\n\t\tfor (const key in phpResponse.headers) {\n\t\t\tres.setHeader(key, phpResponse.headers[key]);\n\t\t}\n\t\tres.end(phpResponse.bytes);\n\t});\n\n\tconst address = server.address();\n\tconst port = (address! as AddressInfo).port;\n\tawait options.onBind(port);\n}\n\nconst bufferRequestBody = async (req: Request): Promise<Uint8Array> =>\n\tawait new Promise((resolve) => {\n\t\tconst body: Uint8Array[] = [];\n\t\treq.on('data', (chunk) => {\n\t\t\tbody.push(chunk);\n\t\t});\n\t\treq.on('end', () => {\n\t\t\tresolve(Buffer.concat(body));\n\t\t});\n\t});\n\nconst parseHeaders = (req: Request): Record<string, string> => {\n\tconst requestHeaders: Record<string, string> = {};\n\tif (req.rawHeaders && req.rawHeaders.length) {\n\t\tfor (let i = 0; i < req.rawHeaders.length; i += 2) {\n\t\t\trequestHeaders[req.rawHeaders[i].toLowerCase()] =\n\t\t\t\treq.rawHeaders[i + 1];\n\t\t}\n\t}\n\treturn requestHeaders;\n};\n","/**\n * Checks if the given version string is a valid WordPress version.\n *\n * The Regex is based on the releases on https://wordpress.org/download/releases/#betas\n * The version string can be one of the following formats:\n * - \"latest\"\n * - \"trunk\"\n * - \"nightly\"\n * - \"x.y\" (x and y are integers) e.g. \"6.2\"\n * - \"x.y.z\" (x, y and z are integers) e.g. \"6.2.1\"\n * - \"x.y.z-betaN\" (N is an integer) e.g. \"6.2.1-beta1\"\n * - \"x.y.z-RCN\" (N is an integer) e.g. \"6.2-RC1\"\n *\n * @param version The version string to check.\n * @returns A boolean value indicating whether the version string is a valid WordPress version.\n */\nexport function isValidWordPressSlug(version: string): boolean {\n\tconst versionPattern =\n\t\t/^latest$|^trunk$|^nightly$|^(?:(\\d+)\\.(\\d+)(?:\\.(\\d+))?)((?:-beta(?:\\d+)?)|(?:-RC(?:\\d+)?))?$/;\n\treturn versionPattern.test(version);\n}\n","import { EmscriptenDownloadMonitor } from '@php-wasm/progress';\nimport fs from 'fs-extra';\nimport os from 'os';\nimport path, { basename } from 'path';\n\nexport const CACHE_FOLDER = path.join(os.homedir(), '.wordpress-playground');\n\nexport async function fetchSqliteIntegration(\n\tmonitor: EmscriptenDownloadMonitor\n) {\n\tconst sqliteZip = await cachedDownload(\n\t\t'https://github.com/WordPress/sqlite-database-integration/archive/refs/heads/main.zip',\n\t\t'sqlite.zip',\n\t\tmonitor\n\t);\n\treturn sqliteZip;\n}\n\n// @TODO: Support HTTP cache, invalidate the local file if the remote file has\n// changed\nexport async function cachedDownload(\n\tremoteUrl: string,\n\tcacheKey: string,\n\tmonitor: EmscriptenDownloadMonitor\n) {\n\tconst artifactPath = path.join(CACHE_FOLDER, cacheKey);\n\tif (!fs.existsSync(artifactPath)) {\n\t\tfs.ensureDirSync(CACHE_FOLDER);\n\t\tawait downloadTo(remoteUrl, artifactPath, monitor);\n\t}\n\treturn readAsFile(artifactPath);\n}\n\nasync function downloadTo(\n\tremoteUrl: string,\n\tlocalPath: string,\n\tmonitor: EmscriptenDownloadMonitor\n) {\n\tconst response = await monitor.monitorFetch(fetch(remoteUrl));\n\tconst reader = response.body!.getReader();\n\tconst tmpPath = `${localPath}.partial`;\n\tconst writer = fs.createWriteStream(tmpPath);\n\twhile (true) {\n\t\tconst { done, value } = await reader.read();\n\t\tif (value) {\n\t\t\twriter.write(value);\n\t\t}\n\t\tif (done) {\n\t\t\tbreak;\n\t\t}\n\t}\n\twriter.close();\n\tif (!writer.closed) {\n\t\tawait new Promise((resolve, reject) => {\n\t\t\twriter.on('finish', (err: any) => {\n\t\t\t\tif (err) {\n\t\t\t\t\tfs.removeSync(tmpPath);\n\t\t\t\t\treject(err);\n\t\t\t\t} else {\n\t\t\t\t\tfs.renameSync(tmpPath, localPath);\n\t\t\t\t\tresolve(null);\n\t\t\t\t}\n\t\t\t});\n\t\t});\n\t}\n}\n\nexport function readAsFile(path: string, fileName?: string): File {\n\treturn new File([fs.readFileSync(path)], fileName ?? basename(path));\n}\n","import fs from 'fs';\nimport path from 'path';\nimport yargs from 'yargs';\nimport { startServer } from './server';\nimport {\n\tPHP,\n\tPHPRequest,\n\tPHPRequestHandler,\n\tPHPResponse,\n\tSupportedPHPVersion,\n\tSupportedPHPVersions,\n} from '@php-wasm/universal';\nimport { logger, errorLogPath } from '@php-wasm/logger';\nimport {\n\tBlueprint,\n\tcompileBlueprint,\n\trunBlueprintSteps,\n} from '@wp-playground/blueprints';\nimport { isValidWordPressSlug } from './is-valid-wordpress-slug';\nimport { EmscriptenDownloadMonitor, ProgressTracker } from '@php-wasm/progress';\nimport { createNodeFsMountHandler, loadNodeRuntime } from '@php-wasm/node';\nimport { RecommendedPHPVersion, zipDirectory } from '@wp-playground/common';\nimport { bootWordPress } from '@wp-playground/wordpress';\nimport { rootCertificates } from 'tls';\nimport {\n\tCACHE_FOLDER,\n\tcachedDownload,\n\tfetchSqliteIntegration,\n\treadAsFile,\n} from './download';\nimport { resolveWordPressRelease } from '@wp-playground/wordpress';\nexport interface Mount {\n\thostPath: string;\n\tvfsPath: string;\n}\n\nasync function run() {\n\t/**\n\t * @TODO This looks similar to Query API args https://wordpress.github.io/wordpress-playground/developers/apis/query-api/\n\t * Perhaps the two could be handled by the same code?\n\t */\n\tconst yargsObject = await yargs(process.argv.slice(2))\n\t\t.usage('Usage: wp-playground <command> [options]')\n\t\t.positional('command', {\n\t\t\tdescribe: 'Command to run',\n\t\t\ttype: 'string',\n\t\t\tchoices: ['server', 'run-blueprint', 'build-snapshot'],\n\t\t})\n\t\t.option('outfile', {\n\t\t\tdescribe: 'When building, write to this output file.',\n\t\t\ttype: 'string',\n\t\t\tdefault: 'wordpress.zip',\n\t\t})\n\t\t.option('port', {\n\t\t\tdescribe: 'Port to listen on when serving.',\n\t\t\ttype: 'number',\n\t\t\tdefault: 9400,\n\t\t})\n\t\t.option('php', {\n\t\t\tdescribe: 'PHP version to use.',\n\t\t\ttype: 'string',\n\t\t\tdefault: RecommendedPHPVersion,\n\t\t\tchoices: SupportedPHPVersions,\n\t\t})\n\t\t.option('wp', {\n\t\t\tdescribe: 'WordPress version to use.',\n\t\t\ttype: 'string',\n\t\t\tdefault: 'latest',\n\t\t})\n\t\t// @TODO: Support read-only mounts, e.g. via WORKERFS, a custom\n\t\t// ReadOnlyNODEFS, or by copying the files into MEMFS\n\t\t.option('mount', {\n\t\t\tdescribe:\n\t\t\t\t'Mount a directory to the PHP runtime. You can provide --mount multiple times. Format: /host/path:/vfs/path',\n\t\t\ttype: 'array',\n\t\t\tstring: true,\n\t\t})\n\t\t.option('mountBeforeInstall', {\n\t\t\tdescribe:\n\t\t\t\t'Mount a directory to the PHP runtime before installing WordPress. You can provide --mount-before-install multiple times. Format: /host/path:/vfs/path',\n\t\t\ttype: 'array',\n\t\t\tstring: true,\n\t\t})\n\t\t.option('login', {\n\t\t\tdescribe: 'Should log the user in',\n\t\t\ttype: 'boolean',\n\t\t\tdefault: false,\n\t\t})\n\t\t.option('blueprint', {\n\t\t\tdescribe: 'Blueprint to execute.',\n\t\t\ttype: 'string',\n\t\t})\n\t\t.option('skipWordPressSetup', {\n\t\t\tdescribe:\n\t\t\t\t'Do not download, unzip, and install WordPress. Useful for mounting a pre-configured WordPress directory at /wordpress.',\n\t\t\ttype: 'boolean',\n\t\t\tdefault: false,\n\t\t})\n\t\t.option('quiet', {\n\t\t\tdescribe: 'Do not output logs and progress messages.',\n\t\t\ttype: 'boolean',\n\t\t\tdefault: false,\n\t\t})\n\t\t.option('debug', {\n\t\t\tdescribe:\n\t\t\t\t'Print PHP error log content if an error occurs during Playground boot.',\n\t\t\ttype: 'boolean',\n\t\t\tdefault: false,\n\t\t})\n\t\t.showHelpOnFail(false)\n\t\t.check((args) => {\n\t\t\tif (args.wp !== undefined && !isValidWordPressSlug(args.wp)) {\n\t\t\t\ttry {\n\t\t\t\t\t// Check if is valid URL\n\t\t\t\t\tnew URL(args.wp);\n\t\t\t\t} catch (e) {\n\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t'Unrecognized WordPress version. Please use \"latest\", a URL, or a numeric version such as \"6.2\", \"6.0.1\", \"6.2-beta1\", or \"6.2-RC1\"'\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (args.blueprint !== undefined) {\n\t\t\t\tconst blueprintPath = path.resolve(\n\t\t\t\t\tprocess.cwd(),\n\t\t\t\t\targs.blueprint\n\t\t\t\t);\n\t\t\t\tif (!fs.existsSync(blueprintPath)) {\n\t\t\t\t\tthrow new Error('Blueprint file does not exist');\n\t\t\t\t}\n\n\t\t\t\tconst content = fs.readFileSync(blueprintPath, 'utf-8');\n\t\t\t\ttry {\n\t\t\t\t\targs.blueprint = JSON.parse(content);\n\t\t\t\t} catch (e) {\n\t\t\t\t\tthrow new Error('Blueprint file is not a valid JSON file');\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn true;\n\t\t});\n\n\tyargsObject.wrap(yargsObject.terminalWidth());\n\tconst args = await yargsObject.argv;\n\n\tif (args.quiet) {\n\t\t// @ts-ignore\n\t\tlogger.handlers = [];\n\t}\n\n\t/**\n\t * TODO: This exact feature will be provided in the PHP Blueprints library.\n\t * Let's use it when it ships. Let's also use it in the web Playground\n\t * app.\n\t */\n\tasync function zipSite(outfile: string) {\n\t\t// Fake URL for the build\n\t\tconst { php, reap } =\n\t\t\tawait requestHandler.processManager.acquirePHPInstance();\n\t\ttry {\n\t\t\tawait php.run({\n\t\t\t\tcode: `<?php\n\t\t\t\t$zip = new ZipArchive();\n\t\t\t\tif(false === $zip->open('/tmp/build.zip', ZipArchive::CREATE | ZipArchive::OVERWRITE)) {\n\t\t\t\t\tthrow new Exception('Failed to create ZIP');\n\t\t\t\t}\n\t\t\t\t$files = new RecursiveIteratorIterator(\n\t\t\t\t\tnew RecursiveDirectoryIterator('/wordpress')\n\t\t\t\t);\n\t\t\t\tforeach ($files as $file) {\n\t\t\t\t\techo $file . PHP_EOL;\n\t\t\t\t\tif (!$file->isFile()) {\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t\t$zip->addFile($file->getPathname(), $file->getPathname());\n\t\t\t\t}\n\t\t\t\t$zip->close();\n\n\t\t\t`,\n\t\t\t});\n\t\t\tconst zip = php.readFileAsBuffer('/tmp/build.zip');\n\t\t\tfs.writeFileSync(outfile, zip);\n\t\t} finally {\n\t\t\treap();\n\t\t}\n\t}\n\n\tfunction mountResources(php: PHP, rawMounts: string[]) {\n\t\tconst parsedMounts = rawMounts.map((mount) => {\n\t\t\tconst [source, vfsPath] = mount.split(':');\n\t\t\treturn {\n\t\t\t\thostPath: path.resolve(process.cwd(), source),\n\t\t\t\tvfsPath,\n\t\t\t};\n\t\t});\n\t\tfor (const mount of parsedMounts) {\n\t\t\tphp.mkdir(mount.vfsPath);\n\t\t\tphp.mount(mount.vfsPath, createNodeFsMountHandler(mount.hostPath));\n\t\t}\n\t}\n\n\tfunction compileInputBlueprint() {\n\t\t/**\n\t\t * @TODO This looks similar to the resolveBlueprint() call in the website package:\n\t\t * \t https://github.com/WordPress/wordpress-playground/blob/ce586059e5885d185376184fdd2f52335cca32b0/packages/playground/website/src/main.tsx#L41\n\t\t *\n\t\t * \t\t Also the Blueprint Builder tool does something similar.\n\t\t * Perhaps all these cases could be handled by the same function?\n\t\t */\n\t\tlet blueprint: Blueprint | undefined;\n\t\tif (args.blueprint) {\n\t\t\tblueprint = args.blueprint as Blueprint;\n\t\t} else {\n\t\t\tblueprint = {\n\t\t\t\tpreferredVersions: {\n\t\t\t\t\tphp: args.php as SupportedPHPVersion,\n\t\t\t\t\twp: args.wp,\n\t\t\t\t},\n\t\t\t\tlogin: args.login,\n\t\t\t};\n\t\t}\n\n\t\tconst tracker = new ProgressTracker();\n\t\tlet lastCaption = '';\n\t\tlet progressReached100 = false;\n\t\ttracker.addEventListener('progress', (e: any) => {\n\t\t\tif (progressReached100) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tprogressReached100 = e.detail.progress === 100;\n\n\t\t\t// Use floor() so we don't report 100% until truly there.\n\t\t\tconst progressInteger = Math.floor(e.detail.progress);\n\t\t\tlastCaption =\n\t\t\t\te.detail.caption || lastCaption || 'Running the Blueprint';\n\t\t\tconst message = `${lastCaption.trim()} – ${progressInteger}%`;\n\t\t\tif (!args.quiet) {\n\t\t\t\twriteProgressUpdate(\n\t\t\t\t\tprocess.stdout,\n\t\t\t\t\tmessage,\n\t\t\t\t\tprogressReached100\n\t\t\t\t);\n\t\t\t}\n\t\t});\n\t\treturn compileBlueprint(blueprint as Blueprint, {\n\t\t\tprogress: tracker,\n\t\t});\n\t}\n\n\tlet lastProgressMessage = '';\n\tfunction writeProgressUpdate(\n\t\twriteStream: NodeJS.WriteStream,\n\t\tmessage: string,\n\t\tfinalUpdate: boolean\n\t) {\n\t\tif (message === lastProgressMessage) {\n\t\t\t// Avoid repeating the same message\n\t\t\treturn;\n\t\t}\n\t\tlastProgressMessage = message;\n\n\t\tif (writeStream.isTTY) {\n\t\t\t// Overwrite previous progress updates in-place for a quieter UX.\n\t\t\twriteStream.cursorTo(0);\n\t\t\twriteStream.write(message);\n\t\t\twriteStream.clearLine(1);\n\n\t\t\tif (finalUpdate) {\n\t\t\t\twriteStream.write('\\n');\n\t\t\t}\n\t\t} else {\n\t\t\t// Fall back to writing one line per progress update\n\t\t\twriteStream.write(`${message}\\n`);\n\t\t}\n\t}\n\n\tconst command = args._[0] as string;\n\tif (!['run-blueprint', 'server', 'build-snapshot'].includes(command)) {\n\t\tyargsObject.showHelp();\n\t\tprocess.exit(1);\n\t}\n\n\tconst compiledBlueprint = compileInputBlueprint();\n\n\tlet requestHandler: PHPRequestHandler;\n\tlet wordPressReady = false;\n\n\tlogger.log('Starting a PHP server...');\n\n\tstartServer({\n\t\tport: args['port'] as number,\n\t\tonBind: async (port: number) => {\n\t\t\tconst absoluteUrl = `http://127.0.0.1:${port}`;\n\n\t\t\tlogger.log(`Setting up WordPress ${args.wp}`);\n\t\t\tlet wpDetails: any = undefined;\n\t\t\t// @TODO: Rename to FetchProgressMonitor. There's nothing Emscripten\n\t\t\t// about that class anymore.\n\t\t\tconst monitor = new EmscriptenDownloadMonitor();\n\t\t\tif (!args.skipWordPressSetup) {\n\t\t\t\tlet progressReached100 = false;\n\t\t\t\tmonitor.addEventListener('progress', ((\n\t\t\t\t\te: CustomEvent<ProgressEvent & { finished: boolean }>\n\t\t\t\t) => {\n\t\t\t\t\tif (progressReached100) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\t// @TODO Every progress bar will want percentages. The\n\t\t\t\t\t// download monitor should just provide that.\n\t\t\t\t\tconst { loaded, total } = e.detail;\n\t\t\t\t\t// Use floor() so we don't report 100% until truly there.\n\t\t\t\t\tconst percentProgress = Math.floor(\n\t\t\t\t\t\tMath.min(100, (100 * loaded) / total)\n\t\t\t\t\t);\n\t\t\t\t\tprogressReached100 = percentProgress === 100;\n\n\t\t\t\t\tif (!args.quiet) {\n\t\t\t\t\t\twriteProgressUpdate(\n\t\t\t\t\t\t\tprocess.stdout,\n\t\t\t\t\t\t\t`Downloading WordPress ${percentProgress}%...`,\n\t\t\t\t\t\t\tprogressReached100\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t}) as any);\n\n\t\t\t\twpDetails = await resolveWordPressRelease(args.wp);\n\t\t\t}\n\t\t\tlogger.log(\n\t\t\t\t`Resolved WordPress release URL: ${wpDetails?.releaseUrl}`\n\t\t\t);\n\n\t\t\tconst preinstalledWpContentPath =\n\t\t\t\twpDetails &&\n\t\t\t\tpath.join(\n\t\t\t\t\tCACHE_FOLDER,\n\t\t\t\t\t`prebuilt-wp-content-for-wp-${wpDetails.version}.zip`\n\t\t\t\t);\n\t\t\tconst wordPressZip = !wpDetails\n\t\t\t\t? undefined\n\t\t\t\t: fs.existsSync(preinstalledWpContentPath)\n\t\t\t\t? readAsFile(preinstalledWpContentPath)\n\t\t\t\t: await cachedDownload(\n\t\t\t\t\t\twpDetails.releaseUrl,\n\t\t\t\t\t\t`${wpDetails.version}.zip`,\n\t\t\t\t\t\tmonitor\n\t\t\t\t );\n\n\t\t\tconst constants: Record<string, string | number | boolean | null> =\n\t\t\t\t{\n\t\t\t\t\tWP_DEBUG: true,\n\t\t\t\t\tWP_DEBUG_LOG: true,\n\t\t\t\t\tWP_DEBUG_DISPLAY: false,\n\t\t\t\t};\n\n\t\t\tlogger.log(`Booting WordPress...`);\n\t\t\trequestHandler = await bootWordPress({\n\t\t\t\tsiteUrl: absoluteUrl,\n\t\t\t\tcreatePhpRuntime: async () =>\n\t\t\t\t\tawait loadNodeRuntime(compiledBlueprint.versions.php),\n\t\t\t\twordPressZip,\n\t\t\t\tsqliteIntegrationPluginZip: fetchSqliteIntegration(monitor),\n\t\t\t\tsapiName: 'cli',\n\t\t\t\tcreateFiles: {\n\t\t\t\t\t'/internal/shared/ca-bundle.crt':\n\t\t\t\t\t\trootCertificates.join('\\n'),\n\t\t\t\t},\n\t\t\t\tconstants,\n\t\t\t\tphpIniEntries: {\n\t\t\t\t\t'openssl.cafile': '/internal/shared/ca-bundle.crt',\n\t\t\t\t\tallow_url_fopen: '1',\n\t\t\t\t\tdisable_functions: '',\n\t\t\t\t},\n\t\t\t\thooks: {\n\t\t\t\t\tasync beforeWordPressFiles(php) {\n\t\t\t\t\t\tif (args.mountBeforeInstall) {\n\t\t\t\t\t\t\tmountResources(php, args.mountBeforeInstall);\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t});\n\t\t\tlogger.log(`Booted!`);\n\n\t\t\tconst php = await requestHandler.getPrimaryPhp();\n\t\t\ttry {\n\t\t\t\tif (\n\t\t\t\t\twpDetails &&\n\t\t\t\t\t!args.mountBeforeInstall &&\n\t\t\t\t\t!fs.existsSync(preinstalledWpContentPath)\n\t\t\t\t) {\n\t\t\t\t\tlogger.log(\n\t\t\t\t\t\t`Caching preinstalled WordPress for the next boot...`\n\t\t\t\t\t);\n\t\t\t\t\tfs.writeFileSync(\n\t\t\t\t\t\tpreinstalledWpContentPath,\n\t\t\t\t\t\tawait zipDirectory(php, '/wordpress')\n\t\t\t\t\t);\n\t\t\t\t\tlogger.log(`Cached!`);\n\t\t\t\t}\n\n\t\t\t\tif (args.mount) {\n\t\t\t\t\tmountResources(php, args.mount);\n\t\t\t\t}\n\n\t\t\t\twordPressReady = true;\n\n\t\t\t\tif (compiledBlueprint) {\n\t\t\t\t\tconst { php, reap } =\n\t\t\t\t\t\tawait requestHandler.processManager.acquirePHPInstance();\n\t\t\t\t\ttry {\n\t\t\t\t\t\tlogger.log(`Running the Blueprint...`);\n\t\t\t\t\t\tawait runBlueprintSteps(compiledBlueprint, php);\n\t\t\t\t\t\tlogger.log(`Finished running the blueprint`);\n\t\t\t\t\t} finally {\n\t\t\t\t\t\treap();\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (command === 'build-snapshot') {\n\t\t\t\t\tawait zipSite(args.outfile as string);\n\t\t\t\t\tlogger.log(`WordPress exported to ${args.outfile}`);\n\t\t\t\t\tprocess.exit(0);\n\t\t\t\t} else if (command === 'run-blueprint') {\n\t\t\t\t\tlogger.log(`Blueprint executed`);\n\t\t\t\t\tprocess.exit(0);\n\t\t\t\t} else {\n\t\t\t\t\tlogger.log(`WordPress is running on ${absoluteUrl}`);\n\t\t\t\t}\n\t\t\t} catch (error) {\n\t\t\t\tif (!args.debug) {\n\t\t\t\t\tthrow error;\n\t\t\t\t}\n\t\t\t\tconst phpLogs = php.readFileAsText(errorLogPath);\n\t\t\t\tthrow new Error(phpLogs, { cause: error });\n\t\t\t}\n\t\t},\n\t\tasync handleRequest(request: PHPRequest) {\n\t\t\tif (!wordPressReady) {\n\t\t\t\treturn PHPResponse.forHttpCode(\n\t\t\t\t\t502,\n\t\t\t\t\t'WordPress is not ready yet'\n\t\t\t\t);\n\t\t\t}\n\t\t\treturn await requestHandler.request(request);\n\t\t},\n\t});\n}\n\nrun();\n"],"names":["startServer","options","app","express","server","resolve","reject","address","req","res","phpResponse","parseHeaders","bufferRequestBody","key","port","body","chunk","requestHeaders","isValidWordPressSlug","version","CACHE_FOLDER","path","os","fetchSqliteIntegration","monitor","cachedDownload","remoteUrl","cacheKey","artifactPath","fs","downloadTo","readAsFile","localPath","reader","tmpPath","writer","done","value","err","fileName","basename","run","yargsObject","yargs","RecommendedPHPVersion","SupportedPHPVersions","args","blueprintPath","content","logger","zipSite","outfile","php","reap","requestHandler","zip","mountResources","rawMounts","parsedMounts","mount","source","vfsPath","createNodeFsMountHandler","compileInputBlueprint","blueprint","tracker","ProgressTracker","lastCaption","progressReached100","e","progressInteger","message","writeProgressUpdate","compileBlueprint","lastProgressMessage","writeStream","finalUpdate","command","compiledBlueprint","wordPressReady","absoluteUrl","wpDetails","EmscriptenDownloadMonitor","loaded","total","percentProgress","resolveWordPressRelease","preinstalledWpContentPath","wordPressZip","constants","bootWordPress","loadNodeRuntime","rootCertificates","zipDirectory","runBlueprintSteps","error","phpLogs","errorLogPath","request","PHPResponse"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wp-playground/cli",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.28",
|
|
4
4
|
"description": "WordPress Playground CLI",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
"type": "module",
|
|
24
24
|
"main": "main.js",
|
|
25
25
|
"bin": "wp-playground.js",
|
|
26
|
-
"gitHead": "
|
|
26
|
+
"gitHead": "ed7171a91717c70dd7162e3d93283f66d21c001d",
|
|
27
27
|
"dependencies": {
|
|
28
28
|
"ajv": "8.12.0",
|
|
29
29
|
"async-lock": "1.4.1",
|
|
@@ -47,12 +47,12 @@
|
|
|
47
47
|
"wasm-feature-detect": "1.8.0",
|
|
48
48
|
"ws": "8.18.0",
|
|
49
49
|
"yargs": "17.7.2",
|
|
50
|
-
"@php-wasm/universal": "1.0.
|
|
51
|
-
"@php-wasm/logger": "1.0.
|
|
52
|
-
"@wp-playground/blueprints": "1.0.
|
|
53
|
-
"@php-wasm/progress": "1.0.
|
|
54
|
-
"@php-wasm/node": "1.0.
|
|
55
|
-
"@wp-playground/common": "1.0.
|
|
56
|
-
"@wp-playground/wordpress": "1.0.
|
|
50
|
+
"@php-wasm/universal": "1.0.28",
|
|
51
|
+
"@php-wasm/logger": "1.0.28",
|
|
52
|
+
"@wp-playground/blueprints": "1.0.28",
|
|
53
|
+
"@php-wasm/progress": "1.0.28",
|
|
54
|
+
"@php-wasm/node": "1.0.28",
|
|
55
|
+
"@wp-playground/common": "1.0.28",
|
|
56
|
+
"@wp-playground/wordpress": "1.0.28"
|
|
57
57
|
}
|
|
58
58
|
}
|