@wp-playground/cli 1.0.28 → 1.0.29
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/cli.cjs +2 -0
- package/cli.cjs.map +1 -0
- package/cli.d.ts +1 -0
- package/cli.js +102 -21
- package/cli.js.map +1 -1
- package/download.d.ts +5 -0
- package/index.cjs +22 -0
- package/index.cjs.map +1 -0
- package/index.d.ts +1 -0
- package/index.js +247 -0
- package/index.js.map +1 -0
- package/is-valid-wordpress-slug.d.ts +17 -0
- package/package.json +10 -10
- package/run-cli.d.ts +27 -0
- package/server.d.ts +10 -0
package/cli.cjs
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use strict";const n=require("fs"),a=require("path"),l=require("yargs"),p=require("@php-wasm/universal"),d=require("@wp-playground/common"),c=require("./index.cjs");require("express");require("@php-wasm/logger");require("@wp-playground/blueprints");require("@php-wasm/progress");require("@php-wasm/node");require("@wp-playground/wordpress");require("tls");require("fs-extra");require("os");function f(e){return/^latest$|^trunk$|^nightly$|^(?:(\d+)\.(\d+)(?:\.(\d+))?)((?:-beta(?:\d+)?)|(?:-RC(?:\d+)?))?$/.test(e)}async function b(){const e=await l(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:d.RecommendedPHPVersion,choices:p.SupportedPHPVersions}).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&&!f(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 o=a.resolve(process.cwd(),r.blueprint);if(!n.existsSync(o))throw new Error("Blueprint file does not exist");const u=n.readFileSync(o,"utf-8");try{r.blueprint=JSON.parse(u)}catch{throw new Error("Blueprint file is not a valid JSON file")}}return!0});e.wrap(e.terminalWidth());const t=await e.argv,i=t._[0];["run-blueprint","server","build-snapshot"].includes(i)||(e.showHelp(),process.exit(1));const s={...t,command:i};return await c.runCLI(s)}b();
|
|
2
|
+
//# sourceMappingURL=cli.cjs.map
|
package/cli.cjs.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.cjs","sources":["../../../../packages/playground/cli/src/is-valid-wordpress-slug.ts","../../../../packages/playground/cli/src/cli.ts"],"sourcesContent":["/**\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 fs from 'fs';\nimport path from 'path';\nimport yargs from 'yargs';\nimport { SupportedPHPVersions } from '@php-wasm/universal';\nimport { isValidWordPressSlug } from './is-valid-wordpress-slug';\nimport { RecommendedPHPVersion } from '@wp-playground/common';\nimport { runCLI, RunCLIArgs } from './run-cli';\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\tconst command = args._[0] as string;\n\n\tif (!['run-blueprint', 'server', 'build-snapshot'].includes(command)) {\n\t\tyargsObject.showHelp();\n\t\tprocess.exit(1);\n\t}\n\n\tconst cliArgs = {\n\t\t...args,\n\t\tcommand,\n\t} as RunCLIArgs;\n\n\treturn await runCLI(cliArgs);\n}\n\nrun();\n"],"names":["isValidWordPressSlug","version","run","yargsObject","yargs","RecommendedPHPVersion","SupportedPHPVersions","args","blueprintPath","path","fs","content","command","cliArgs","runCLI"],"mappings":"sYAgBO,SAASA,EAAqBC,EAA0B,CAGvD,MADN,gGACqB,KAAKA,CAAO,CACnC,CCZA,eAAeC,GAAM,CAKpB,MAAMC,EAAc,MAAMC,EAAM,QAAQ,KAAK,MAAM,CAAC,CAAC,EACnD,MAAM,0CAA0C,EAChD,WAAW,UAAW,CACtB,SAAU,iBACV,KAAM,SACN,QAAS,CAAC,SAAU,gBAAiB,gBAAgB,CAAA,CACrD,EACA,OAAO,UAAW,CAClB,SAAU,4CACV,KAAM,SACN,QAAS,eAAA,CACT,EACA,OAAO,OAAQ,CACf,SAAU,kCACV,KAAM,SACN,QAAS,IAAA,CACT,EACA,OAAO,MAAO,CACd,SAAU,sBACV,KAAM,SACN,QAASC,EAAA,sBACT,QAASC,EAAA,oBAAA,CACT,EACA,OAAO,KAAM,CACb,SAAU,4BACV,KAAM,SACN,QAAS,QAAA,CACT,EAGA,OAAO,QAAS,CAChB,SACC,6GACD,KAAM,QACN,OAAQ,EAAA,CACR,EACA,OAAO,qBAAsB,CAC7B,SACC,wJACD,KAAM,QACN,OAAQ,EAAA,CACR,EACA,OAAO,QAAS,CAChB,SAAU,yBACV,KAAM,UACN,QAAS,EAAA,CACT,EACA,OAAO,YAAa,CACpB,SAAU,wBACV,KAAM,QAAA,CACN,EACA,OAAO,qBAAsB,CAC7B,SACC,yHACD,KAAM,UACN,QAAS,EAAA,CACT,EACA,OAAO,QAAS,CAChB,SAAU,4CACV,KAAM,UACN,QAAS,EAAA,CACT,EACA,OAAO,QAAS,CAChB,SACC,yEACD,KAAM,UACN,QAAS,EACT,CAAA,EACA,eAAe,EAAK,EACpB,MAAOC,GAAS,CAChB,GAAIA,EAAK,KAAO,QAAa,CAACP,EAAqBO,EAAK,EAAE,EACrD,GAAA,CAEC,IAAA,IAAIA,EAAK,EAAE,OACJ,CACX,MAAM,IAAI,MACT,oIAAA,CAEF,CAEGA,GAAAA,EAAK,YAAc,OAAW,CACjC,MAAMC,EAAgBC,EAAK,QAC1B,QAAQ,IAAI,EACZF,EAAK,SAAA,EAEN,GAAI,CAACG,EAAG,WAAWF,CAAa,EACzB,MAAA,IAAI,MAAM,+BAA+B,EAGhD,MAAMG,EAAUD,EAAG,aAAaF,EAAe,OAAO,EAClD,GAAA,CACHD,EAAK,UAAY,KAAK,MAAMI,CAAO,OACxB,CACL,MAAA,IAAI,MAAM,yCAAyC,CAC1D,CACD,CACO,MAAA,EAAA,CACP,EAEUR,EAAA,KAAKA,EAAY,cAAe,CAAA,EACtC,MAAAI,EAAO,MAAMJ,EAAY,KAEzBS,EAAUL,EAAK,EAAE,CAAC,EAEnB,CAAC,gBAAiB,SAAU,gBAAgB,EAAE,SAASK,CAAO,IAClET,EAAY,SAAS,EACrB,QAAQ,KAAK,CAAC,GAGf,MAAMU,EAAU,CACf,GAAGN,EACH,QAAAK,CAAA,EAGM,OAAA,MAAME,EAAAA,OAAOD,CAAO,CAC5B,CAEAX,EAAI"}
|
package/cli.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/cli.js
CHANGED
|
@@ -1,22 +1,103 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
1
|
+
import n from "fs";
|
|
2
|
+
import a from "path";
|
|
3
|
+
import u from "yargs";
|
|
4
|
+
import { SupportedPHPVersions as l } from "@php-wasm/universal";
|
|
5
|
+
import { RecommendedPHPVersion as d } from "@wp-playground/common";
|
|
6
|
+
import { runCLI as c } from "./index.js";
|
|
7
|
+
import "express";
|
|
8
|
+
import "@php-wasm/logger";
|
|
9
|
+
import "@wp-playground/blueprints";
|
|
10
|
+
import "@php-wasm/progress";
|
|
11
|
+
import "@php-wasm/node";
|
|
12
|
+
import "@wp-playground/wordpress";
|
|
13
|
+
import "tls";
|
|
14
|
+
import "fs-extra";
|
|
15
|
+
import "os";
|
|
16
|
+
function m(e) {
|
|
17
|
+
return /^latest$|^trunk$|^nightly$|^(?:(\d+)\.(\d+)(?:\.(\d+))?)((?:-beta(?:\d+)?)|(?:-RC(?:\d+)?))?$/.test(e);
|
|
18
|
+
}
|
|
19
|
+
async function f() {
|
|
20
|
+
const e = await u(process.argv.slice(2)).usage("Usage: wp-playground <command> [options]").positional("command", {
|
|
21
|
+
describe: "Command to run",
|
|
22
|
+
type: "string",
|
|
23
|
+
choices: ["server", "run-blueprint", "build-snapshot"]
|
|
24
|
+
}).option("outfile", {
|
|
25
|
+
describe: "When building, write to this output file.",
|
|
26
|
+
type: "string",
|
|
27
|
+
default: "wordpress.zip"
|
|
28
|
+
}).option("port", {
|
|
29
|
+
describe: "Port to listen on when serving.",
|
|
30
|
+
type: "number",
|
|
31
|
+
default: 9400
|
|
32
|
+
}).option("php", {
|
|
33
|
+
describe: "PHP version to use.",
|
|
34
|
+
type: "string",
|
|
35
|
+
default: d,
|
|
36
|
+
choices: l
|
|
37
|
+
}).option("wp", {
|
|
38
|
+
describe: "WordPress version to use.",
|
|
39
|
+
type: "string",
|
|
40
|
+
default: "latest"
|
|
41
|
+
}).option("mount", {
|
|
42
|
+
describe: "Mount a directory to the PHP runtime. You can provide --mount multiple times. Format: /host/path:/vfs/path",
|
|
43
|
+
type: "array",
|
|
44
|
+
string: !0
|
|
45
|
+
}).option("mountBeforeInstall", {
|
|
46
|
+
describe: "Mount a directory to the PHP runtime before installing WordPress. You can provide --mount-before-install multiple times. Format: /host/path:/vfs/path",
|
|
47
|
+
type: "array",
|
|
48
|
+
string: !0
|
|
49
|
+
}).option("login", {
|
|
50
|
+
describe: "Should log the user in",
|
|
51
|
+
type: "boolean",
|
|
52
|
+
default: !1
|
|
53
|
+
}).option("blueprint", {
|
|
54
|
+
describe: "Blueprint to execute.",
|
|
55
|
+
type: "string"
|
|
56
|
+
}).option("skipWordPressSetup", {
|
|
57
|
+
describe: "Do not download, unzip, and install WordPress. Useful for mounting a pre-configured WordPress directory at /wordpress.",
|
|
58
|
+
type: "boolean",
|
|
59
|
+
default: !1
|
|
60
|
+
}).option("quiet", {
|
|
61
|
+
describe: "Do not output logs and progress messages.",
|
|
62
|
+
type: "boolean",
|
|
63
|
+
default: !1
|
|
64
|
+
}).option("debug", {
|
|
65
|
+
describe: "Print PHP error log content if an error occurs during Playground boot.",
|
|
66
|
+
type: "boolean",
|
|
67
|
+
default: !1
|
|
68
|
+
}).showHelpOnFail(!1).check((t) => {
|
|
69
|
+
if (t.wp !== void 0 && !m(t.wp))
|
|
70
|
+
try {
|
|
71
|
+
new URL(t.wp);
|
|
72
|
+
} catch {
|
|
73
|
+
throw new Error(
|
|
74
|
+
'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"'
|
|
75
|
+
);
|
|
76
|
+
}
|
|
77
|
+
if (t.blueprint !== void 0) {
|
|
78
|
+
const r = a.resolve(
|
|
79
|
+
process.cwd(),
|
|
80
|
+
t.blueprint
|
|
81
|
+
);
|
|
82
|
+
if (!n.existsSync(r))
|
|
83
|
+
throw new Error("Blueprint file does not exist");
|
|
84
|
+
const p = n.readFileSync(r, "utf-8");
|
|
85
|
+
try {
|
|
86
|
+
t.blueprint = JSON.parse(p);
|
|
87
|
+
} catch {
|
|
88
|
+
throw new Error("Blueprint file is not a valid JSON file");
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
return !0;
|
|
92
|
+
});
|
|
93
|
+
e.wrap(e.terminalWidth());
|
|
94
|
+
const o = await e.argv, i = o._[0];
|
|
95
|
+
["run-blueprint", "server", "build-snapshot"].includes(i) || (e.showHelp(), process.exit(1));
|
|
96
|
+
const s = {
|
|
97
|
+
...o,
|
|
98
|
+
command: i
|
|
99
|
+
};
|
|
100
|
+
return await c(s);
|
|
101
|
+
}
|
|
102
|
+
f();
|
|
22
103
|
//# 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 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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"}
|
|
1
|
+
{"version":3,"file":"cli.js","sources":["../../../../packages/playground/cli/src/is-valid-wordpress-slug.ts","../../../../packages/playground/cli/src/cli.ts"],"sourcesContent":["/**\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 fs from 'fs';\nimport path from 'path';\nimport yargs from 'yargs';\nimport { SupportedPHPVersions } from '@php-wasm/universal';\nimport { isValidWordPressSlug } from './is-valid-wordpress-slug';\nimport { RecommendedPHPVersion } from '@wp-playground/common';\nimport { runCLI, RunCLIArgs } from './run-cli';\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\tconst command = args._[0] as string;\n\n\tif (!['run-blueprint', 'server', 'build-snapshot'].includes(command)) {\n\t\tyargsObject.showHelp();\n\t\tprocess.exit(1);\n\t}\n\n\tconst cliArgs = {\n\t\t...args,\n\t\tcommand,\n\t} as RunCLIArgs;\n\n\treturn await runCLI(cliArgs);\n}\n\nrun();\n"],"names":["isValidWordPressSlug","version","run","yargsObject","yargs","RecommendedPHPVersion","SupportedPHPVersions","args","blueprintPath","path","fs","content","command","cliArgs","runCLI"],"mappings":";;;;;;;;;;;;;;;AAgBO,SAASA,EAAqBC,GAA0B;AAGvD,SADN,gGACqB,KAAKA,CAAO;AACnC;ACZA,eAAeC,IAAM;AAKpB,QAAMC,IAAc,MAAMC,EAAM,QAAQ,KAAK,MAAM,CAAC,CAAC,EACnD,MAAM,0CAA0C,EAChD,WAAW,WAAW;AAAA,IACtB,UAAU;AAAA,IACV,MAAM;AAAA,IACN,SAAS,CAAC,UAAU,iBAAiB,gBAAgB;AAAA,EAAA,CACrD,EACA,OAAO,WAAW;AAAA,IAClB,UAAU;AAAA,IACV,MAAM;AAAA,IACN,SAAS;AAAA,EAAA,CACT,EACA,OAAO,QAAQ;AAAA,IACf,UAAU;AAAA,IACV,MAAM;AAAA,IACN,SAAS;AAAA,EAAA,CACT,EACA,OAAO,OAAO;AAAA,IACd,UAAU;AAAA,IACV,MAAM;AAAA,IACN,SAASC;AAAA,IACT,SAASC;AAAA,EAAA,CACT,EACA,OAAO,MAAM;AAAA,IACb,UAAU;AAAA,IACV,MAAM;AAAA,IACN,SAAS;AAAA,EAAA,CACT,EAGA,OAAO,SAAS;AAAA,IAChB,UACC;AAAA,IACD,MAAM;AAAA,IACN,QAAQ;AAAA,EAAA,CACR,EACA,OAAO,sBAAsB;AAAA,IAC7B,UACC;AAAA,IACD,MAAM;AAAA,IACN,QAAQ;AAAA,EAAA,CACR,EACA,OAAO,SAAS;AAAA,IAChB,UAAU;AAAA,IACV,MAAM;AAAA,IACN,SAAS;AAAA,EAAA,CACT,EACA,OAAO,aAAa;AAAA,IACpB,UAAU;AAAA,IACV,MAAM;AAAA,EAAA,CACN,EACA,OAAO,sBAAsB;AAAA,IAC7B,UACC;AAAA,IACD,MAAM;AAAA,IACN,SAAS;AAAA,EAAA,CACT,EACA,OAAO,SAAS;AAAA,IAChB,UAAU;AAAA,IACV,MAAM;AAAA,IACN,SAAS;AAAA,EAAA,CACT,EACA,OAAO,SAAS;AAAA,IAChB,UACC;AAAA,IACD,MAAM;AAAA,IACN,SAAS;AAAA,EACT,CAAA,EACA,eAAe,EAAK,EACpB,MAAM,CAACC,MAAS;AAChB,QAAIA,EAAK,OAAO,UAAa,CAACP,EAAqBO,EAAK,EAAE;AACrD,UAAA;AAEC,YAAA,IAAIA,EAAK,EAAE;AAAA,cACJ;AACX,cAAM,IAAI;AAAA,UACT;AAAA,QAAA;AAAA,MAEF;AAEGA,QAAAA,EAAK,cAAc,QAAW;AACjC,YAAMC,IAAgBC,EAAK;AAAA,QAC1B,QAAQ,IAAI;AAAA,QACZF,EAAK;AAAA,MAAA;AAEN,UAAI,CAACG,EAAG,WAAWF,CAAa;AACzB,cAAA,IAAI,MAAM,+BAA+B;AAGhD,YAAMG,IAAUD,EAAG,aAAaF,GAAe,OAAO;AAClD,UAAA;AACHD,QAAAA,EAAK,YAAY,KAAK,MAAMI,CAAO;AAAA,cACxB;AACL,cAAA,IAAI,MAAM,yCAAyC;AAAA,MAC1D;AAAA,IACD;AACO,WAAA;AAAA,EAAA,CACP;AAEU,EAAAR,EAAA,KAAKA,EAAY,cAAe,CAAA;AACtC,QAAAI,IAAO,MAAMJ,EAAY,MAEzBS,IAAUL,EAAK,EAAE,CAAC;AAEpB,EAAC,CAAC,iBAAiB,UAAU,gBAAgB,EAAE,SAASK,CAAO,MAClET,EAAY,SAAS,GACrB,QAAQ,KAAK,CAAC;AAGf,QAAMU,IAAU;AAAA,IACf,GAAGN;AAAA,IACH,SAAAK;AAAA,EAAA;AAGM,SAAA,MAAME,EAAOD,CAAO;AAC5B;AAEAX,EAAI;"}
|
package/download.d.ts
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { EmscriptenDownloadMonitor } from '@php-wasm/progress';
|
|
2
|
+
export declare const CACHE_FOLDER: string;
|
|
3
|
+
export declare function fetchSqliteIntegration(monitor: EmscriptenDownloadMonitor): Promise<File>;
|
|
4
|
+
export declare function cachedDownload(remoteUrl: string, cacheKey: string, monitor: EmscriptenDownloadMonitor): Promise<File>;
|
|
5
|
+
export declare function readAsFile(path: string, fileName?: string): File;
|
package/index.cjs
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const b=require("fs"),m=require("path"),D=require("express"),x=require("@php-wasm/universal"),l=require("@php-wasm/logger"),B=require("@wp-playground/blueprints"),W=require("@php-wasm/progress"),H=require("@php-wasm/node"),I=require("@wp-playground/common"),E=require("@wp-playground/wordpress"),A=require("tls"),P=require("fs-extra"),M=require("os");async function U(e){const s=D(),n=await new Promise((c,i)=>{const o=s.listen(e.port,()=>{const d=o.address();d===null||typeof d=="string"?i(new Error("Server address is not available")):c(o)})});s.use("/",async(c,i)=>{const o=await e.handleRequest({url:c.url,headers:T(c),method:c.method,body:await _(c)});i.statusCode=o.httpStatusCode;for(const d in o.headers)i.setHeader(d,o.headers[d]);i.end(o.bytes)});const g=n.address().port;return await e.onBind(n,g)}const _=async e=>await new Promise(s=>{const n=[];e.on("data",f=>{n.push(f)}),e.on("end",()=>{s(new Uint8Array(Buffer.concat(n)))})}),T=e=>{const s={};if(e.rawHeaders&&e.rawHeaders.length)for(let n=0;n<e.rawHeaders.length;n+=2)s[e.rawHeaders[n].toLowerCase()]=e.rawHeaders[n+1];return s},$=m.join(M.homedir(),".wordpress-playground");async function Z(e){return await S("https://github.com/WordPress/sqlite-database-integration/archive/refs/heads/main.zip","sqlite.zip",e)}async function S(e,s,n){const f=m.join($,s);return P.existsSync(f)||(P.ensureDirSync($),await k(e,f,n)),F(f)}async function k(e,s,n){const g=(await n.monitorFetch(fetch(e))).body.getReader(),c=`${s}.partial`,i=P.createWriteStream(c);for(;;){const{done:o,value:d}=await g.read();if(d&&i.write(d),o)break}i.close(),i.closed||await new Promise((o,d)=>{i.on("finish",t=>{t?(P.removeSync(c),d(t)):(P.renameSync(c,s),o(null))})})}function F(e,s){return new File([P.readFileSync(e)],s??m.basename(e))}async function j(e){e.quiet&&(l.logger.handlers=[]);async function s(t){const{php:a,reap:p}=await o.processManager.acquirePHPInstance();try{await a.run({code:`<?php
|
|
2
|
+
$zip = new ZipArchive();
|
|
3
|
+
if(false === $zip->open('/tmp/build.zip', ZipArchive::CREATE | ZipArchive::OVERWRITE)) {
|
|
4
|
+
throw new Exception('Failed to create ZIP');
|
|
5
|
+
}
|
|
6
|
+
$files = new RecursiveIteratorIterator(
|
|
7
|
+
new RecursiveDirectoryIterator('/wordpress')
|
|
8
|
+
);
|
|
9
|
+
foreach ($files as $file) {
|
|
10
|
+
echo $file . PHP_EOL;
|
|
11
|
+
if (!$file->isFile()) {
|
|
12
|
+
continue;
|
|
13
|
+
}
|
|
14
|
+
$zip->addFile($file->getPathname(), $file->getPathname());
|
|
15
|
+
}
|
|
16
|
+
$zip->close();
|
|
17
|
+
|
|
18
|
+
`});const r=a.readFileAsBuffer("/tmp/build.zip");b.writeFileSync(t,r)}finally{p()}}function n(t,a){const p=a.map(r=>{const[h,w]=r.split(":");return{hostPath:m.resolve(process.cwd(),h),vfsPath:w}});for(const r of p)t.mkdir(r.vfsPath),t.mount(r.vfsPath,H.createNodeFsMountHandler(r.hostPath))}function f(){let t;e.blueprint?t=e.blueprint:t={preferredVersions:{php:e.php??I.RecommendedPHPVersion,wp:e.wp??"latest"},login:e.login};const a=new W.ProgressTracker;let p="",r=!1;return a.addEventListener("progress",h=>{if(r)return;r=h.detail.progress===100;const w=Math.floor(h.detail.progress);p=h.detail.caption||p||"Running the Blueprint";const v=`${p.trim()} – ${w}%`;e.quiet||c(process.stdout,v,r)}),B.compileBlueprint(t,{progress:a})}let g="";function c(t,a,p){a!==g&&(g=a,t.isTTY?(t.cursorTo(0),t.write(a),t.clearLine(1),p&&t.write(`
|
|
19
|
+
`)):t.write(`${a}
|
|
20
|
+
`))}const i=f();let o,d=!1;return l.logger.log("Starting a PHP server..."),U({port:e.port,onBind:async(t,a)=>{const p=`http://127.0.0.1:${a}`;l.logger.log(`Setting up WordPress ${e.wp}`);let r;const h=new W.EmscriptenDownloadMonitor;if(!e.skipWordPressSetup){let u=!1;h.addEventListener("progress",y=>{if(u)return;const{loaded:z,total:L}=y.detail,q=Math.floor(Math.min(100,100*z/L));u=q===100,e.quiet||c(process.stdout,`Downloading WordPress ${q}%...`,u)}),r=await E.resolveWordPressRelease(e.wp)}l.logger.log(`Resolved WordPress release URL: ${r?.releaseUrl}`);const w=r&&m.join($,`prebuilt-wp-content-for-wp-${r.version}.zip`),v=r?b.existsSync(w)?F(w):await S(r.releaseUrl,`${r.version}.zip`,h):void 0,C={WP_DEBUG:!0,WP_DEBUG_LOG:!0,WP_DEBUG_DISPLAY:!1};l.logger.log("Booting WordPress..."),o=await E.bootWordPress({siteUrl:p,createPhpRuntime:async()=>await H.loadNodeRuntime(i.versions.php),wordPressZip:v,sqliteIntegrationPluginZip:Z(h),sapiName:"cli",createFiles:{"/internal/shared/ca-bundle.crt":A.rootCertificates.join(`
|
|
21
|
+
`)},constants:C,phpIniEntries:{"openssl.cafile":"/internal/shared/ca-bundle.crt",allow_url_fopen:"1",disable_functions:""},hooks:{async beforeWordPressFiles(u){e.mountBeforeInstall&&n(u,e.mountBeforeInstall)}}}),l.logger.log("Booted!");const R=await o.getPrimaryPhp();try{if(r&&!e.mountBeforeInstall&&!b.existsSync(w)&&(l.logger.log("Caching preinstalled WordPress for the next boot..."),b.writeFileSync(w,await I.zipDirectory(R,"/wordpress")),l.logger.log("Cached!")),e.mount&&n(R,e.mount),d=!0,i){const{php:u,reap:y}=await o.processManager.acquirePHPInstance();try{l.logger.log("Running the Blueprint..."),await B.runBlueprintSteps(i,u),l.logger.log("Finished running the blueprint")}finally{y()}}return e.command==="build-snapshot"?(await s(e.outfile),l.logger.log(`WordPress exported to ${e.outfile}`),process.exit(0)):e.command==="run-blueprint"?(l.logger.log("Blueprint executed"),process.exit(0)):l.logger.log(`WordPress is running on ${p}`),{requestHandler:o,server:t}}catch(u){if(!e.debug)throw u;const y=R.readFileAsText(l.errorLogPath);throw new Error(y,{cause:u})}},async handleRequest(t){return d?await o.request(t):x.PHPResponse.forHttpCode(502,"WordPress is not ready yet")}})}exports.runCLI=j;
|
|
22
|
+
//# sourceMappingURL=index.cjs.map
|
package/index.cjs.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.cjs","sources":["../../../../packages/playground/cli/src/server.ts","../../../../packages/playground/cli/src/download.ts","../../../../packages/playground/cli/src/run-cli.ts"],"sourcesContent":["import type { PHPRequest, PHPResponse } from '@php-wasm/universal';\nimport type { Request } from 'express';\nimport express from 'express';\nimport type { IncomingMessage, Server, ServerResponse } from 'http';\nimport type { AddressInfo } from 'net';\nimport type { RunCLIServer } from './run-cli';\n\nexport interface ServerOptions {\n\tport: number;\n\tonBind: (server: Server, port: number) => Promise<RunCLIServer>;\n\thandleRequest: (request: PHPRequest) => Promise<PHPResponse>;\n}\n\nexport async function startServer(\n\toptions: ServerOptions\n): Promise<RunCLIServer> {\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\treturn await options.onBind(server, 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(new Uint8Array(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","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 { startServer } from './server';\nimport {\n\tPHP,\n\tPHPRequest,\n\tPHPRequestHandler,\n\tPHPResponse,\n\tSupportedPHPVersion,\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 type { Server } from 'http';\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';\n\nexport interface RunCLIArgs {\n\tblueprint?: Blueprint;\n\tcommand: 'server' | 'run-blueprint' | 'build-snapshot';\n\tdebug?: boolean;\n\tlogin?: boolean;\n\tmount?: string[];\n\tmountBeforeInstall?: string[];\n\toutfile?: string;\n\tphp?: SupportedPHPVersion;\n\tport?: number;\n\tquiet?: boolean;\n\tskipWordPressSetup?: boolean;\n\twp?: string;\n}\n\nexport interface RunCLIServer {\n\trequestHandler: PHPRequestHandler;\n\tserver: Server;\n}\n\nexport interface Mount {\n\thostPath: string;\n\tvfsPath: string;\n}\n\nexport async function runCLI(args: RunCLIArgs): Promise<RunCLIServer> {\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 ?? RecommendedPHPVersion,\n\t\t\t\t\twp: args.wp ?? 'latest',\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 compiledBlueprint = compileInputBlueprint();\n\n\tlet requestHandler: PHPRequestHandler;\n\tlet wordPressReady = false;\n\n\tlogger.log('Starting a PHP server...');\n\n\treturn startServer({\n\t\tport: args['port'] as number,\n\t\tonBind: async (server: Server, port: number): Promise<RunCLIServer> => {\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 (args.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 (args.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\n\t\t\t\treturn { requestHandler, server };\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"],"names":["startServer","options","app","express","server","resolve","reject","address","req","res","phpResponse","parseHeaders","bufferRequestBody","key","port","body","chunk","requestHeaders","i","CACHE_FOLDER","path","os","fetchSqliteIntegration","monitor","cachedDownload","remoteUrl","cacheKey","artifactPath","fs","downloadTo","readAsFile","localPath","reader","tmpPath","writer","done","value","err","fileName","basename","runCLI","args","logger","zipSite","outfile","php","reap","requestHandler","zip","mountResources","rawMounts","parsedMounts","mount","source","vfsPath","createNodeFsMountHandler","compileInputBlueprint","blueprint","RecommendedPHPVersion","tracker","ProgressTracker","lastCaption","progressReached100","e","progressInteger","message","writeProgressUpdate","compileBlueprint","lastProgressMessage","writeStream","finalUpdate","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/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './run-cli';
|
package/index.js
ADDED
|
@@ -0,0 +1,247 @@
|
|
|
1
|
+
import g from "fs";
|
|
2
|
+
import b, { basename as S } from "path";
|
|
3
|
+
import z from "express";
|
|
4
|
+
import { PHPResponse as C } from "@php-wasm/universal";
|
|
5
|
+
import { logger as c, errorLogPath as x } from "@php-wasm/logger";
|
|
6
|
+
import { runBlueprintSteps as D, compileBlueprint as L } from "@wp-playground/blueprints";
|
|
7
|
+
import { EmscriptenDownloadMonitor as A, ProgressTracker as U } from "@php-wasm/progress";
|
|
8
|
+
import { loadNodeRuntime as _, createNodeFsMountHandler as q } from "@php-wasm/node";
|
|
9
|
+
import { zipDirectory as M, RecommendedPHPVersion as T } from "@wp-playground/common";
|
|
10
|
+
import { resolveWordPressRelease as Z, bootWordPress as k } from "@wp-playground/wordpress";
|
|
11
|
+
import { rootCertificates as j } from "tls";
|
|
12
|
+
import P from "fs-extra";
|
|
13
|
+
import G from "os";
|
|
14
|
+
async function O(e) {
|
|
15
|
+
const n = z(), s = await new Promise((l, i) => {
|
|
16
|
+
const o = n.listen(e.port, () => {
|
|
17
|
+
const p = o.address();
|
|
18
|
+
p === null || typeof p == "string" ? i(new Error("Server address is not available")) : l(o);
|
|
19
|
+
});
|
|
20
|
+
});
|
|
21
|
+
n.use("/", async (l, i) => {
|
|
22
|
+
const o = await e.handleRequest({
|
|
23
|
+
url: l.url,
|
|
24
|
+
headers: V(l),
|
|
25
|
+
method: l.method,
|
|
26
|
+
body: await N(l)
|
|
27
|
+
});
|
|
28
|
+
i.statusCode = o.httpStatusCode;
|
|
29
|
+
for (const p in o.headers)
|
|
30
|
+
i.setHeader(p, o.headers[p]);
|
|
31
|
+
i.end(o.bytes);
|
|
32
|
+
});
|
|
33
|
+
const m = s.address().port;
|
|
34
|
+
return await e.onBind(s, m);
|
|
35
|
+
}
|
|
36
|
+
const N = async (e) => await new Promise((n) => {
|
|
37
|
+
const s = [];
|
|
38
|
+
e.on("data", (f) => {
|
|
39
|
+
s.push(f);
|
|
40
|
+
}), e.on("end", () => {
|
|
41
|
+
n(new Uint8Array(Buffer.concat(s)));
|
|
42
|
+
});
|
|
43
|
+
}), V = (e) => {
|
|
44
|
+
const n = {};
|
|
45
|
+
if (e.rawHeaders && e.rawHeaders.length)
|
|
46
|
+
for (let s = 0; s < e.rawHeaders.length; s += 2)
|
|
47
|
+
n[e.rawHeaders[s].toLowerCase()] = e.rawHeaders[s + 1];
|
|
48
|
+
return n;
|
|
49
|
+
}, $ = b.join(G.homedir(), ".wordpress-playground");
|
|
50
|
+
async function Y(e) {
|
|
51
|
+
return await W(
|
|
52
|
+
"https://github.com/WordPress/sqlite-database-integration/archive/refs/heads/main.zip",
|
|
53
|
+
"sqlite.zip",
|
|
54
|
+
e
|
|
55
|
+
);
|
|
56
|
+
}
|
|
57
|
+
async function W(e, n, s) {
|
|
58
|
+
const f = b.join($, n);
|
|
59
|
+
return P.existsSync(f) || (P.ensureDirSync($), await J(e, f, s)), H(f);
|
|
60
|
+
}
|
|
61
|
+
async function J(e, n, s) {
|
|
62
|
+
const m = (await s.monitorFetch(fetch(e))).body.getReader(), l = `${n}.partial`, i = P.createWriteStream(l);
|
|
63
|
+
for (; ; ) {
|
|
64
|
+
const { done: o, value: p } = await m.read();
|
|
65
|
+
if (p && i.write(p), o)
|
|
66
|
+
break;
|
|
67
|
+
}
|
|
68
|
+
i.close(), i.closed || await new Promise((o, p) => {
|
|
69
|
+
i.on("finish", (t) => {
|
|
70
|
+
t ? (P.removeSync(l), p(t)) : (P.renameSync(l, n), o(null));
|
|
71
|
+
});
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
function H(e, n) {
|
|
75
|
+
return new File([P.readFileSync(e)], n ?? S(e));
|
|
76
|
+
}
|
|
77
|
+
async function ce(e) {
|
|
78
|
+
e.quiet && (c.handlers = []);
|
|
79
|
+
async function n(t) {
|
|
80
|
+
const { php: a, reap: d } = await o.processManager.acquirePHPInstance();
|
|
81
|
+
try {
|
|
82
|
+
await a.run({
|
|
83
|
+
code: `<?php
|
|
84
|
+
$zip = new ZipArchive();
|
|
85
|
+
if(false === $zip->open('/tmp/build.zip', ZipArchive::CREATE | ZipArchive::OVERWRITE)) {
|
|
86
|
+
throw new Exception('Failed to create ZIP');
|
|
87
|
+
}
|
|
88
|
+
$files = new RecursiveIteratorIterator(
|
|
89
|
+
new RecursiveDirectoryIterator('/wordpress')
|
|
90
|
+
);
|
|
91
|
+
foreach ($files as $file) {
|
|
92
|
+
echo $file . PHP_EOL;
|
|
93
|
+
if (!$file->isFile()) {
|
|
94
|
+
continue;
|
|
95
|
+
}
|
|
96
|
+
$zip->addFile($file->getPathname(), $file->getPathname());
|
|
97
|
+
}
|
|
98
|
+
$zip->close();
|
|
99
|
+
|
|
100
|
+
`
|
|
101
|
+
});
|
|
102
|
+
const r = a.readFileAsBuffer("/tmp/build.zip");
|
|
103
|
+
g.writeFileSync(t, r);
|
|
104
|
+
} finally {
|
|
105
|
+
d();
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
function s(t, a) {
|
|
109
|
+
const d = a.map((r) => {
|
|
110
|
+
const [h, w] = r.split(":");
|
|
111
|
+
return {
|
|
112
|
+
hostPath: b.resolve(process.cwd(), h),
|
|
113
|
+
vfsPath: w
|
|
114
|
+
};
|
|
115
|
+
});
|
|
116
|
+
for (const r of d)
|
|
117
|
+
t.mkdir(r.vfsPath), t.mount(r.vfsPath, q(r.hostPath));
|
|
118
|
+
}
|
|
119
|
+
function f() {
|
|
120
|
+
let t;
|
|
121
|
+
e.blueprint ? t = e.blueprint : t = {
|
|
122
|
+
preferredVersions: {
|
|
123
|
+
php: e.php ?? T,
|
|
124
|
+
wp: e.wp ?? "latest"
|
|
125
|
+
},
|
|
126
|
+
login: e.login
|
|
127
|
+
};
|
|
128
|
+
const a = new U();
|
|
129
|
+
let d = "", r = !1;
|
|
130
|
+
return a.addEventListener("progress", (h) => {
|
|
131
|
+
if (r)
|
|
132
|
+
return;
|
|
133
|
+
r = h.detail.progress === 100;
|
|
134
|
+
const w = Math.floor(h.detail.progress);
|
|
135
|
+
d = h.detail.caption || d || "Running the Blueprint";
|
|
136
|
+
const v = `${d.trim()} – ${w}%`;
|
|
137
|
+
e.quiet || l(
|
|
138
|
+
process.stdout,
|
|
139
|
+
v,
|
|
140
|
+
r
|
|
141
|
+
);
|
|
142
|
+
}), L(t, {
|
|
143
|
+
progress: a
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
let m = "";
|
|
147
|
+
function l(t, a, d) {
|
|
148
|
+
a !== m && (m = a, t.isTTY ? (t.cursorTo(0), t.write(a), t.clearLine(1), d && t.write(`
|
|
149
|
+
`)) : t.write(`${a}
|
|
150
|
+
`));
|
|
151
|
+
}
|
|
152
|
+
const i = f();
|
|
153
|
+
let o, p = !1;
|
|
154
|
+
return c.log("Starting a PHP server..."), O({
|
|
155
|
+
port: e.port,
|
|
156
|
+
onBind: async (t, a) => {
|
|
157
|
+
const d = `http://127.0.0.1:${a}`;
|
|
158
|
+
c.log(`Setting up WordPress ${e.wp}`);
|
|
159
|
+
let r;
|
|
160
|
+
const h = new A();
|
|
161
|
+
if (!e.skipWordPressSetup) {
|
|
162
|
+
let u = !1;
|
|
163
|
+
h.addEventListener("progress", (y) => {
|
|
164
|
+
if (u)
|
|
165
|
+
return;
|
|
166
|
+
const { loaded: I, total: F } = y.detail, B = Math.floor(
|
|
167
|
+
Math.min(100, 100 * I / F)
|
|
168
|
+
);
|
|
169
|
+
u = B === 100, e.quiet || l(
|
|
170
|
+
process.stdout,
|
|
171
|
+
`Downloading WordPress ${B}%...`,
|
|
172
|
+
u
|
|
173
|
+
);
|
|
174
|
+
}), r = await Z(e.wp);
|
|
175
|
+
}
|
|
176
|
+
c.log(
|
|
177
|
+
`Resolved WordPress release URL: ${r?.releaseUrl}`
|
|
178
|
+
);
|
|
179
|
+
const w = r && b.join(
|
|
180
|
+
$,
|
|
181
|
+
`prebuilt-wp-content-for-wp-${r.version}.zip`
|
|
182
|
+
), v = r ? g.existsSync(w) ? H(w) : await W(
|
|
183
|
+
r.releaseUrl,
|
|
184
|
+
`${r.version}.zip`,
|
|
185
|
+
h
|
|
186
|
+
) : void 0, E = {
|
|
187
|
+
WP_DEBUG: !0,
|
|
188
|
+
WP_DEBUG_LOG: !0,
|
|
189
|
+
WP_DEBUG_DISPLAY: !1
|
|
190
|
+
};
|
|
191
|
+
c.log("Booting WordPress..."), o = await k({
|
|
192
|
+
siteUrl: d,
|
|
193
|
+
createPhpRuntime: async () => await _(i.versions.php),
|
|
194
|
+
wordPressZip: v,
|
|
195
|
+
sqliteIntegrationPluginZip: Y(h),
|
|
196
|
+
sapiName: "cli",
|
|
197
|
+
createFiles: {
|
|
198
|
+
"/internal/shared/ca-bundle.crt": j.join(`
|
|
199
|
+
`)
|
|
200
|
+
},
|
|
201
|
+
constants: E,
|
|
202
|
+
phpIniEntries: {
|
|
203
|
+
"openssl.cafile": "/internal/shared/ca-bundle.crt",
|
|
204
|
+
allow_url_fopen: "1",
|
|
205
|
+
disable_functions: ""
|
|
206
|
+
},
|
|
207
|
+
hooks: {
|
|
208
|
+
async beforeWordPressFiles(u) {
|
|
209
|
+
e.mountBeforeInstall && s(u, e.mountBeforeInstall);
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
}), c.log("Booted!");
|
|
213
|
+
const R = await o.getPrimaryPhp();
|
|
214
|
+
try {
|
|
215
|
+
if (r && !e.mountBeforeInstall && !g.existsSync(w) && (c.log(
|
|
216
|
+
"Caching preinstalled WordPress for the next boot..."
|
|
217
|
+
), g.writeFileSync(
|
|
218
|
+
w,
|
|
219
|
+
await M(R, "/wordpress")
|
|
220
|
+
), c.log("Cached!")), e.mount && s(R, e.mount), p = !0, i) {
|
|
221
|
+
const { php: u, reap: y } = await o.processManager.acquirePHPInstance();
|
|
222
|
+
try {
|
|
223
|
+
c.log("Running the Blueprint..."), await D(i, u), c.log("Finished running the blueprint");
|
|
224
|
+
} finally {
|
|
225
|
+
y();
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
return e.command === "build-snapshot" ? (await n(e.outfile), c.log(`WordPress exported to ${e.outfile}`), process.exit(0)) : e.command === "run-blueprint" ? (c.log("Blueprint executed"), process.exit(0)) : c.log(`WordPress is running on ${d}`), { requestHandler: o, server: t };
|
|
229
|
+
} catch (u) {
|
|
230
|
+
if (!e.debug)
|
|
231
|
+
throw u;
|
|
232
|
+
const y = R.readFileAsText(x);
|
|
233
|
+
throw new Error(y, { cause: u });
|
|
234
|
+
}
|
|
235
|
+
},
|
|
236
|
+
async handleRequest(t) {
|
|
237
|
+
return p ? await o.request(t) : C.forHttpCode(
|
|
238
|
+
502,
|
|
239
|
+
"WordPress is not ready yet"
|
|
240
|
+
);
|
|
241
|
+
}
|
|
242
|
+
});
|
|
243
|
+
}
|
|
244
|
+
export {
|
|
245
|
+
ce as runCLI
|
|
246
|
+
};
|
|
247
|
+
//# sourceMappingURL=index.js.map
|
package/index.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../../../../packages/playground/cli/src/server.ts","../../../../packages/playground/cli/src/download.ts","../../../../packages/playground/cli/src/run-cli.ts"],"sourcesContent":["import type { PHPRequest, PHPResponse } from '@php-wasm/universal';\nimport type { Request } from 'express';\nimport express from 'express';\nimport type { IncomingMessage, Server, ServerResponse } from 'http';\nimport type { AddressInfo } from 'net';\nimport type { RunCLIServer } from './run-cli';\n\nexport interface ServerOptions {\n\tport: number;\n\tonBind: (server: Server, port: number) => Promise<RunCLIServer>;\n\thandleRequest: (request: PHPRequest) => Promise<PHPResponse>;\n}\n\nexport async function startServer(\n\toptions: ServerOptions\n): Promise<RunCLIServer> {\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\treturn await options.onBind(server, 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(new Uint8Array(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","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 { startServer } from './server';\nimport {\n\tPHP,\n\tPHPRequest,\n\tPHPRequestHandler,\n\tPHPResponse,\n\tSupportedPHPVersion,\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 type { Server } from 'http';\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';\n\nexport interface RunCLIArgs {\n\tblueprint?: Blueprint;\n\tcommand: 'server' | 'run-blueprint' | 'build-snapshot';\n\tdebug?: boolean;\n\tlogin?: boolean;\n\tmount?: string[];\n\tmountBeforeInstall?: string[];\n\toutfile?: string;\n\tphp?: SupportedPHPVersion;\n\tport?: number;\n\tquiet?: boolean;\n\tskipWordPressSetup?: boolean;\n\twp?: string;\n}\n\nexport interface RunCLIServer {\n\trequestHandler: PHPRequestHandler;\n\tserver: Server;\n}\n\nexport interface Mount {\n\thostPath: string;\n\tvfsPath: string;\n}\n\nexport async function runCLI(args: RunCLIArgs): Promise<RunCLIServer> {\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 ?? RecommendedPHPVersion,\n\t\t\t\t\twp: args.wp ?? 'latest',\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 compiledBlueprint = compileInputBlueprint();\n\n\tlet requestHandler: PHPRequestHandler;\n\tlet wordPressReady = false;\n\n\tlogger.log('Starting a PHP server...');\n\n\treturn startServer({\n\t\tport: args['port'] as number,\n\t\tonBind: async (server: Server, port: number): Promise<RunCLIServer> => {\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 (args.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 (args.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\n\t\t\t\treturn { requestHandler, server };\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"],"names":["startServer","options","app","express","server","resolve","reject","address","req","res","phpResponse","parseHeaders","bufferRequestBody","key","port","body","chunk","requestHeaders","i","CACHE_FOLDER","path","os","fetchSqliteIntegration","monitor","cachedDownload","remoteUrl","cacheKey","artifactPath","fs","downloadTo","readAsFile","localPath","reader","tmpPath","writer","done","value","err","fileName","basename","runCLI","args","logger","zipSite","outfile","php","reap","requestHandler","zip","mountResources","rawMounts","parsedMounts","mount","source","vfsPath","createNodeFsMountHandler","compileInputBlueprint","blueprint","RecommendedPHPVersion","tracker","ProgressTracker","lastCaption","progressReached100","e","progressInteger","message","writeProgressUpdate","compileBlueprint","lastProgressMessage","writeStream","finalUpdate","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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"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Checks if the given version string is a valid WordPress version.
|
|
3
|
+
*
|
|
4
|
+
* The Regex is based on the releases on https://wordpress.org/download/releases/#betas
|
|
5
|
+
* The version string can be one of the following formats:
|
|
6
|
+
* - "latest"
|
|
7
|
+
* - "trunk"
|
|
8
|
+
* - "nightly"
|
|
9
|
+
* - "x.y" (x and y are integers) e.g. "6.2"
|
|
10
|
+
* - "x.y.z" (x, y and z are integers) e.g. "6.2.1"
|
|
11
|
+
* - "x.y.z-betaN" (N is an integer) e.g. "6.2.1-beta1"
|
|
12
|
+
* - "x.y.z-RCN" (N is an integer) e.g. "6.2-RC1"
|
|
13
|
+
*
|
|
14
|
+
* @param version The version string to check.
|
|
15
|
+
* @returns A boolean value indicating whether the version string is a valid WordPress version.
|
|
16
|
+
*/
|
|
17
|
+
export declare function isValidWordPressSlug(version: string): boolean;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wp-playground/cli",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.29",
|
|
4
4
|
"description": "WordPress Playground CLI",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -21,9 +21,9 @@
|
|
|
21
21
|
},
|
|
22
22
|
"license": "GPL-2.0-or-later",
|
|
23
23
|
"type": "module",
|
|
24
|
-
"main": "
|
|
24
|
+
"main": "index.js",
|
|
25
25
|
"bin": "wp-playground.js",
|
|
26
|
-
"gitHead": "
|
|
26
|
+
"gitHead": "173e69f62e1b43bd7353b875054bb1ef5e394de8",
|
|
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
|
-
"@
|
|
52
|
-
"@
|
|
53
|
-
"@php-wasm/
|
|
54
|
-
"@
|
|
55
|
-
"@
|
|
56
|
-
"@wp-playground/wordpress": "1.0.
|
|
50
|
+
"@php-wasm/universal": "1.0.29",
|
|
51
|
+
"@wp-playground/common": "1.0.29",
|
|
52
|
+
"@php-wasm/progress": "1.0.29",
|
|
53
|
+
"@php-wasm/logger": "1.0.29",
|
|
54
|
+
"@wp-playground/blueprints": "1.0.29",
|
|
55
|
+
"@php-wasm/node": "1.0.29",
|
|
56
|
+
"@wp-playground/wordpress": "1.0.29"
|
|
57
57
|
}
|
|
58
58
|
}
|
package/run-cli.d.ts
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
import { PHPRequestHandler, SupportedPHPVersion } from '@php-wasm/universal';
|
|
3
|
+
import { Blueprint } from '@wp-playground/blueprints';
|
|
4
|
+
import type { Server } from 'http';
|
|
5
|
+
export interface RunCLIArgs {
|
|
6
|
+
blueprint?: Blueprint;
|
|
7
|
+
command: 'server' | 'run-blueprint' | 'build-snapshot';
|
|
8
|
+
debug?: boolean;
|
|
9
|
+
login?: boolean;
|
|
10
|
+
mount?: string[];
|
|
11
|
+
mountBeforeInstall?: string[];
|
|
12
|
+
outfile?: string;
|
|
13
|
+
php?: SupportedPHPVersion;
|
|
14
|
+
port?: number;
|
|
15
|
+
quiet?: boolean;
|
|
16
|
+
skipWordPressSetup?: boolean;
|
|
17
|
+
wp?: string;
|
|
18
|
+
}
|
|
19
|
+
export interface RunCLIServer {
|
|
20
|
+
requestHandler: PHPRequestHandler;
|
|
21
|
+
server: Server;
|
|
22
|
+
}
|
|
23
|
+
export interface Mount {
|
|
24
|
+
hostPath: string;
|
|
25
|
+
vfsPath: string;
|
|
26
|
+
}
|
|
27
|
+
export declare function runCLI(args: RunCLIArgs): Promise<RunCLIServer>;
|
package/server.d.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
import type { PHPRequest, PHPResponse } from '@php-wasm/universal';
|
|
3
|
+
import type { Server } from 'http';
|
|
4
|
+
import type { RunCLIServer } from './run-cli';
|
|
5
|
+
export interface ServerOptions {
|
|
6
|
+
port: number;
|
|
7
|
+
onBind: (server: Server, port: number) => Promise<RunCLIServer>;
|
|
8
|
+
handleRequest: (request: PHPRequest) => Promise<PHPResponse>;
|
|
9
|
+
}
|
|
10
|
+
export declare function startServer(options: ServerOptions): Promise<RunCLIServer>;
|