@wp-playground/cli 1.1.2 → 1.1.4
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 +8 -5
- package/cli.cjs.map +1 -1
- package/cli.js +650 -591
- package/cli.js.map +1 -1
- package/index.cjs +1 -1
- package/index.js +1 -1
- package/load-balancer.d.ts +13 -0
- package/package.json +13 -11
- package/run-cli-CznLz9jO.js +420 -0
- package/run-cli-CznLz9jO.js.map +1 -0
- package/run-cli-s3Rtz7Gj.cjs +31 -0
- package/run-cli-s3Rtz7Gj.cjs.map +1 -0
- package/run-cli.d.ts +7 -4
- package/worker-thread-BQ8BezvJ.js +152 -0
- package/worker-thread-BQ8BezvJ.js.map +1 -0
- package/worker-thread.cjs +3 -0
- package/worker-thread.cjs.map +1 -0
- package/worker-thread.d.ts +27 -0
- package/worker-thread.js +105 -0
- package/worker-thread.js.map +1 -0
- package/run-cli-BSw9FKSW.cjs +0 -35
- package/run-cli-BSw9FKSW.cjs.map +0 -1
- package/run-cli-_8y4VW5F.js +0 -375
- package/run-cli-_8y4VW5F.js.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"run-cli-s3Rtz7Gj.cjs","sources":["../../../../packages/playground/cli/src/cli-auto-mount.ts","../../../../packages/playground/cli/src/download.ts","../../../../packages/playground/cli/src/server.ts","../../../../packages/playground/cli/src/load-balancer.ts","../../../../packages/playground/cli/src/run-cli.ts"],"sourcesContent":["import { basename, join } from 'path';\nimport type {\n\tBlueprintDeclaration,\n\tStepDefinition,\n} from '@wp-playground/blueprints';\nimport fs from 'fs';\nimport type { RunCLIArgs } from './run-cli';\nimport type { Mount } from './mount';\n\nexport function expandAutoMounts(args: RunCLIArgs): RunCLIArgs {\n\tconst path = process.cwd();\n\n\tconst mount = [...(args.mount || [])];\n\tconst mountBeforeInstall = [...(args.mountBeforeInstall || [])];\n\n\tif (isPluginDirectory(path)) {\n\t\tconst pluginName = basename(path);\n\t\tmount.push({\n\t\t\thostPath: path,\n\t\t\tvfsPath: `/wordpress/wp-content/plugins/${pluginName}`,\n\t\t});\n\t} else if (isThemeDirectory(path)) {\n\t\tconst themeName = basename(path);\n\t\tmount.push({\n\t\t\thostPath: path,\n\t\t\tvfsPath: `/wordpress/wp-content/themes/${themeName}`,\n\t\t});\n\t} else if (containsWpContentDirectories(path)) {\n\t\tmount.push(...wpContentMounts(path));\n\t} else if (containsFullWordPressInstallation(path)) {\n\t\t/**\n\t\t * We don't want Playground and WordPress to modify the OS filesystem on their own\n\t\t * by creating files like wp-config.php or wp-content/db.php.\n\t\t * To ensure WordPress can write to the /wordpress/ and /wordpress/wp-content/ directories,\n\t\t * we leave these directories as MEMFS nodes and mount individual files\n\t\t * and directories into them instead of mounting the entire directory as a NODEFS node.\n\t\t */\n\t\tconst files = fs.readdirSync(path);\n\t\tconst mounts: Mount[] = [];\n\t\tfor (const file of files) {\n\t\t\tif (file.startsWith('wp-content')) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tmounts.push({\n\t\t\t\thostPath: `${path}/${file}`,\n\t\t\t\tvfsPath: `/wordpress/${file}`,\n\t\t\t});\n\t\t}\n\t\tmountBeforeInstall.push(\n\t\t\t...mounts,\n\t\t\t...wpContentMounts(join(path, 'wp-content'))\n\t\t);\n\t} else {\n\t\t/**\n\t\t * By default, mount the current working directory as the Playground root.\n\t\t * This allows users to run and PHP or HTML files using the Playground CLI.\n\t\t */\n\t\tmount.push({ hostPath: path, vfsPath: '/wordpress' });\n\t}\n\n\tconst blueprint = (args.blueprint as BlueprintDeclaration) || {};\n\tblueprint.steps = [...(blueprint.steps || []), ...getSteps(path)];\n\n\t/**\n\t * If Playground is mounting a full WordPress directory,\n\t * it doesn't need to setup WordPress.\n\t */\n\tconst skipWordPressSetup =\n\t\targs.skipWordPressSetup || containsFullWordPressInstallation(path);\n\n\treturn {\n\t\t...args,\n\t\tblueprint,\n\t\tmount,\n\t\tmountBeforeInstall,\n\t\tskipWordPressSetup,\n\t} as RunCLIArgs;\n}\n\nexport function containsFullWordPressInstallation(path: string): boolean {\n\tconst files = fs.readdirSync(path);\n\treturn (\n\t\tfiles.includes('wp-admin') &&\n\t\tfiles.includes('wp-includes') &&\n\t\tfiles.includes('wp-content')\n\t);\n}\n\nexport function containsWpContentDirectories(path: string): boolean {\n\tconst files = fs.readdirSync(path);\n\treturn (\n\t\tfiles.includes('themes') ||\n\t\tfiles.includes('plugins') ||\n\t\tfiles.includes('mu-plugins') ||\n\t\tfiles.includes('uploads')\n\t);\n}\n\nexport function isThemeDirectory(path: string): boolean {\n\tconst files = fs.readdirSync(path);\n\tif (!files.includes('style.css')) {\n\t\treturn false;\n\t}\n\tconst styleCssContent = fs.readFileSync(join(path, 'style.css'), 'utf8');\n\tconst themeNameRegex = /^(?:[ \\t]*<\\?php)?[ \\t/*#@]*Theme Name:(.*)$/im;\n\treturn !!themeNameRegex.exec(styleCssContent);\n}\n\nexport function isPluginDirectory(path: string): boolean {\n\tconst files = fs.readdirSync(path);\n\tconst pluginNameRegex = /^(?:[ \\t]*<\\?php)?[ \\t/*#@]*Plugin Name:(.*)$/im;\n\tconst pluginNameMatch = files\n\t\t.filter((file) => file.endsWith('.php'))\n\t\t.find((file) => {\n\t\t\tconst fileContent = fs.readFileSync(join(path, file), 'utf8');\n\t\t\treturn !!pluginNameRegex.exec(fileContent);\n\t\t});\n\treturn !!pluginNameMatch;\n}\n\n/**\n * Returns a list of files and directories in the wp-content directory\n * to be mounted individually.\n *\n * This is needed because WordPress needs to be able to write to the\n * wp-content directory without Playground modifying the OS filesystem.\n *\n * See expandAutoMounts for more details.\n */\nexport function wpContentMounts(wpContentDir: string): Mount[] {\n\tconst files = fs.readdirSync(wpContentDir);\n\treturn (\n\t\tfiles\n\t\t\t/**\n\t\t\t * index.php is added by WordPress automatically and\n\t\t\t * can't be mounted from the current working directory\n\t\t\t * because it already exists.\n\t\t\t *\n\t\t\t * Because index.php should be empty, it's safe to not include it.\n\t\t\t */\n\t\t\t.filter((file) => !file.startsWith('index.php'))\n\t\t\t.map((file) => ({\n\t\t\t\thostPath: `${wpContentDir}/${file}`,\n\t\t\t\tvfsPath: `/wordpress/wp-content/${file}`,\n\t\t\t}))\n\t);\n}\n\nexport function getSteps(path: string): StepDefinition[] {\n\tif (isPluginDirectory(path)) {\n\t\treturn [\n\t\t\t{\n\t\t\t\tstep: 'activatePlugin',\n\t\t\t\tpluginPath: `/wordpress/wp-content/plugins/${basename(path)}`,\n\t\t\t},\n\t\t];\n\t} else if (isThemeDirectory(path)) {\n\t\treturn [\n\t\t\t{\n\t\t\t\tstep: 'activateTheme',\n\t\t\t\tthemeFolderName: basename(path),\n\t\t\t},\n\t\t];\n\t} else if (\n\t\tcontainsWpContentDirectories(path) ||\n\t\tcontainsFullWordPressInstallation(path)\n\t) {\n\t\t/**\n\t\t * Playground needs to ensure there is an active theme.\n\t\t * Otherwise when WordPress loads it will show a white screen.\n\t\t */\n\t\treturn [\n\t\t\t{\n\t\t\t\tstep: 'runPHP',\n\t\t\t\tcode: `<?php\n\t\t\t\t\trequire_once '/wordpress/wp-load.php';\n\t\t\t\t\t$theme = wp_get_theme();\n\t\t\t\t\tif (!$theme->exists()) {\n\t\t\t\t\t\t$themes = wp_get_themes();\n\t\t\t\t\t\tif (count($themes) > 0) {\n\t\t\t\t\t\t\t$themeName = array_keys($themes)[0];\n\t\t\t\t\t\t\tswitch_theme($themeName);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t`,\n\t\t\t},\n\t\t];\n\t}\n\treturn [];\n}\n","import type { 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/develop.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', () => {\n\t\t\t\tfs.renameSync(tmpPath, localPath);\n\t\t\t\tresolve(null);\n\t\t\t});\n\t\t\twriter.on('error', (err: any) => {\n\t\t\t\tfs.removeSync(tmpPath);\n\t\t\t\treject(err);\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 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 type { PHPRequest, PHPResponse, RemoteAPI } from '@php-wasm/universal';\nimport type { PlaygroundCliWorker } from './worker-thread';\n\n// TODO: Let's merge worker management into PHPProcessManager\n// when we can have multiple workers in both CLI and web.\n// ¡ATTENTION!:Please don't expand upon this as an independent abstraction.\n\n// TODO: Could we just spawn a worker using the factory function to PHPProcessManager?\ntype WorkerLoad = {\n\tworker: RemoteAPI<PlaygroundCliWorker>;\n\tactiveRequests: Set<Promise<PHPResponse>>;\n};\nexport class LoadBalancer {\n\tworkerLoads: WorkerLoad[] = [];\n\n\tconstructor(\n\t\t// NOTE: We require a worker to start so that a load balancer\n\t\t// may not exist without being able to service requests.\n\t\t// Playground CLI initialization, as of 2025-06-11, requires that\n\t\t// an initial worker is booted alone and initialized via Blueprint\n\t\t// before additional workers are created based on the initialized worker.\n\t\tinitialWorker: RemoteAPI<PlaygroundCliWorker>\n\t) {\n\t\tthis.addWorker(initialWorker);\n\t}\n\n\taddWorker(worker: RemoteAPI<PlaygroundCliWorker>) {\n\t\tthis.workerLoads.push({\n\t\t\tworker,\n\t\t\tactiveRequests: new Set(),\n\t\t});\n\t}\n\n\tasync handleRequest(request: PHPRequest) {\n\t\tlet smallestWorkerLoad = this.workerLoads[0];\n\n\t\t// TODO: Is there any way for us to track CPU load so we could avoid\n\t\t// picking a worker that is under heavy load despite few requests?\n\t\t// Possibly this: https://nodejs.org/api/worker_threads.html#workerperformance\n\t\t// Though we probably don't need to worry about it.\n\t\tfor (let i = 1; i < this.workerLoads.length; i++) {\n\t\t\tconst workerLoad = this.workerLoads[i];\n\t\t\tif (\n\t\t\t\tworkerLoad.activeRequests.size <\n\t\t\t\tsmallestWorkerLoad.activeRequests.size\n\t\t\t) {\n\t\t\t\tsmallestWorkerLoad = workerLoad;\n\t\t\t}\n\t\t}\n\n\t\t// TODO: Add trace facility to Playground CLI to observe internals like request routing.\n\n\t\tconst promiseForResponse = smallestWorkerLoad.worker.request(request);\n\t\tsmallestWorkerLoad.activeRequests.add(promiseForResponse);\n\n\t\t// Add URL to promise for use while debugging\n\t\t(promiseForResponse as any).url = request.url;\n\n\t\treturn promiseForResponse.finally(() => {\n\t\t\tsmallestWorkerLoad.activeRequests.delete(promiseForResponse);\n\t\t});\n\t}\n}\n","import { errorLogPath, logger } from '@php-wasm/logger';\nimport { EmscriptenDownloadMonitor, ProgressTracker } from '@php-wasm/progress';\nimport type {\n\tPHPRequest,\n\tRemoteAPI,\n\tSupportedPHPVersion,\n} from '@php-wasm/universal';\nimport { consumeAPI, exposeAPI, PHPResponse } from '@php-wasm/universal';\nimport type {\n\tBlueprintDeclaration,\n\tBlueprintBundle,\n} from '@wp-playground/blueprints';\nimport {\n\tcompileBlueprint,\n\trunBlueprintSteps,\n\tisBlueprintBundle,\n} from '@wp-playground/blueprints';\nimport {\n\tRecommendedPHPVersion,\n\tunzipFile,\n\tzipDirectory,\n} from '@wp-playground/common';\nimport fs from 'fs';\nimport type { Server } from 'http';\nimport path from 'path';\nimport { Worker } from 'worker_threads';\n// @ts-ignore\nimport importedWorkerUrlString from './worker-thread?worker&url';\nimport { expandAutoMounts } from './cli-auto-mount';\nimport {\n\tCACHE_FOLDER,\n\tcachedDownload,\n\tfetchSqliteIntegration,\n\treadAsFile,\n} from './download';\nimport { startServer } from './server';\nimport { resolveWordPressRelease } from '@wp-playground/wordpress';\nimport type { PlaygroundCliWorker, Mount } from './worker-thread';\n// @ts-ignore\nimport { FileLockManagerForNode } from '@php-wasm/node';\nimport { LoadBalancer } from './load-balancer';\n\nexport interface RunCLIArgs {\n\tblueprint?: BlueprintDeclaration | BlueprintBundle;\n\tcommand: 'server' | 'run-blueprint' | 'build-snapshot';\n\tdebug?: boolean;\n\tlogin?: boolean;\n\tmount?: Mount[];\n\tmountBeforeInstall?: Mount[];\n\toutfile?: string;\n\tphp?: SupportedPHPVersion;\n\tport?: number;\n\tquiet?: boolean;\n\tskipWordPressSetup?: boolean;\n\tskipSqliteSetup?: boolean;\n\twp?: string;\n\tautoMount?: boolean;\n\tfollowSymlinks?: boolean;\n\texperimentalMultiWorker?: number;\n\texperimentalTrace?: boolean;\n}\n\nexport interface RunCLIServer extends AsyncDisposable {\n\tplayground: RemoteAPI<PlaygroundCliWorker>;\n\tserver: Server;\n\t[Symbol.asyncDispose](): Promise<void>;\n}\n\nexport async function runCLI(args: RunCLIArgs): Promise<RunCLIServer> {\n\tlet loadBalancer: LoadBalancer;\n\tlet playground: RemoteAPI<PlaygroundCliWorker>;\n\n\tconst playgroundsToCleanUp: {\n\t\tplayground: RemoteAPI<PlaygroundCliWorker>;\n\t\tworker: Worker;\n\t}[] = [];\n\n\t/**\n\t * Expand auto-mounts to include the necessary mounts and steps\n\t * when running in auto-mount mode.\n\t */\n\tif (args.autoMount) {\n\t\targs = expandAutoMounts(args);\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\tawait playground.run({\n\t\t\tcode: `<?php\n\t\t\t$zip = new ZipArchive();\n\t\t\tif(false === $zip->open('/tmp/build.zip', ZipArchive::CREATE | ZipArchive::OVERWRITE)) {\n\t\t\t\tthrow new Exception('Failed to create ZIP');\n\t\t\t}\n\t\t\t$files = new RecursiveIteratorIterator(\n\t\t\t\tnew RecursiveDirectoryIterator('/wordpress')\n\t\t\t);\n\t\t\tforeach ($files as $file) {\n\t\t\t\techo $file . PHP_EOL;\n\t\t\t\tif (!$file->isFile()) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\t$zip->addFile($file->getPathname(), $file->getPathname());\n\t\t\t}\n\t\t\t$zip->close();\n\n\t\t`,\n\t\t});\n\t\tconst zip = await playground.readFileAsBuffer('/tmp/build.zip');\n\t\tfs.writeFileSync(outfile, zip);\n\t}\n\n\tasync function 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\tconst blueprint: BlueprintDeclaration | BlueprintBundle =\n\t\t\tisBlueprintBundle(args.blueprint)\n\t\t\t\t? args.blueprint\n\t\t\t\t: {\n\t\t\t\t\t\tlogin: args.login,\n\t\t\t\t\t\t...args.blueprint,\n\t\t\t\t\t\tpreferredVersions: {\n\t\t\t\t\t\t\tphp:\n\t\t\t\t\t\t\t\targs.php ??\n\t\t\t\t\t\t\t\targs?.blueprint?.preferredVersions?.php ??\n\t\t\t\t\t\t\t\tRecommendedPHPVersion,\n\t\t\t\t\t\t\twp:\n\t\t\t\t\t\t\t\targs.wp ??\n\t\t\t\t\t\t\t\targs?.blueprint?.preferredVersions?.wp ??\n\t\t\t\t\t\t\t\t'latest',\n\t\t\t\t\t\t\t...(args.blueprint?.preferredVersions || {}),\n\t\t\t\t\t\t},\n\t\t\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 await compileBlueprint(blueprint as BlueprintDeclaration, {\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\t/**\n\t * Spawns a new Worker Thread.\n\t *\n\t * @param workerUrl The absolute URL of the worker script.\n\t * @returns The spawned Worker Thread.\n\t */\n\tasync function spawnPHPWorkerThread(workerUrl: URL) {\n\t\tconst worker = new Worker(workerUrl);\n\n\t\treturn new Promise<Worker>((resolve, reject) => {\n\t\t\tfunction onMessage(event: string) {\n\t\t\t\t// Let the worker confirm it has initialized.\n\t\t\t\t// We could use the 'online' event to detect start of JS execution,\n\t\t\t\t// but that would miss initialization errors.\n\t\t\t\tif (event === 'worker-script-initialized') {\n\t\t\t\t\tresolve(worker);\n\t\t\t\t\tworker.off('message', onMessage);\n\t\t\t\t}\n\t\t\t}\n\t\t\tfunction onError(e: Error) {\n\t\t\t\tconst error = new Error(\n\t\t\t\t\t`Worker failed to load at ${workerUrl}. ${\n\t\t\t\t\t\te.message ? `Original error: ${e.message}` : ''\n\t\t\t\t\t}`\n\t\t\t\t);\n\t\t\t\t(error as any).filename = workerUrl;\n\t\t\t\treject(error);\n\t\t\t\tworker.off('error', onError);\n\t\t\t}\n\t\t\tworker.on('message', onMessage);\n\t\t\tworker.on('error', onError);\n\t\t});\n\t}\n\n\tfunction spawnWorkerThreads(count: number): Promise<Worker[]> {\n\t\tconst moduleWorkerUrl = new URL(\n\t\t\timportedWorkerUrlString,\n\t\t\timport.meta.url\n\t\t);\n\n\t\tconst promises = [];\n\t\tfor (let i = 0; i < count; i++) {\n\t\t\tpromises.push(spawnPHPWorkerThread(moduleWorkerUrl));\n\t\t}\n\t\treturn Promise.all(promises);\n\t}\n\n\tif (args.quiet) {\n\t\t// @ts-ignore\n\t\tlogger.handlers = [];\n\t}\n\n\tconst compiledBlueprint = await compileInputBlueprint();\n\n\t// Declare file lock manager outside scope of startServer\n\t// so we can look at it when debugging request handling.\n\tconst fileLockManager = new FileLockManagerForNode();\n\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\t// Kick off worker threads now to save time later.\n\t\t\t// There is no need to wait for other async processes to complete.\n\t\t\tconst totalWorkerCount = args.experimentalMultiWorker ?? 1;\n\t\t\tconst promisedWorkers = spawnWorkerThreads(totalWorkerCount);\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\tlogger.log(\n\t\t\t\t\t`Resolved WordPress release URL: ${wpDetails?.releaseUrl}`\n\t\t\t\t);\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\tlogger.log(`Fetching SQLite integration plugin...`);\n\t\t\tconst sqliteIntegrationPluginZip = args.skipSqliteSetup\n\t\t\t\t? undefined\n\t\t\t\t: await fetchSqliteIntegration(monitor);\n\n\t\t\tconst followSymlinks = args.followSymlinks === true;\n\t\t\tconst trace = args.experimentalTrace === true;\n\t\t\ttry {\n\t\t\t\tconst mountsBeforeWpInstall = args.mountBeforeInstall || [];\n\t\t\t\tconst mountsAfterWpInstall = args.mount || [];\n\n\t\t\t\tconst [initialWorker, ...additionalWorkers] =\n\t\t\t\t\tawait promisedWorkers;\n\n\t\t\t\tplayground = consumeAPI<PlaygroundCliWorker>(initialWorker);\n\t\t\t\tplaygroundsToCleanUp.push({\n\t\t\t\t\tplayground,\n\t\t\t\t\tworker: initialWorker,\n\t\t\t\t});\n\n\t\t\t\tawait playground.isConnected();\n\n\t\t\t\texposeAPI(fileLockManager, undefined, initialWorker);\n\n\t\t\t\tlogger.log(`Booting WordPress...`);\n\n\t\t\t\t// Each additional worker needs a separate process ID space\n\t\t\t\t// for file locking to work properly because locks are associated\n\t\t\t\t// with individual processes. To accommodate this, we split the safe\n\t\t\t\t// integers into a range for each worker.\n\t\t\t\tconst processIdSpaceLength = Math.floor(\n\t\t\t\t\tNumber.MAX_SAFE_INTEGER / totalWorkerCount\n\t\t\t\t);\n\n\t\t\t\tawait playground.boot({\n\t\t\t\t\tphpVersion: compiledBlueprint.versions.php,\n\t\t\t\t\twpVersion: compiledBlueprint.versions.wp,\n\t\t\t\t\tabsoluteUrl,\n\t\t\t\t\tmountsBeforeWpInstall,\n\t\t\t\t\tmountsAfterWpInstall,\n\t\t\t\t\twordPressZip:\n\t\t\t\t\t\twordPressZip && (await wordPressZip!.arrayBuffer()),\n\t\t\t\t\tsqliteIntegrationPluginZip:\n\t\t\t\t\t\tawait sqliteIntegrationPluginZip!.arrayBuffer(),\n\t\t\t\t\tfirstProcessId: 0,\n\t\t\t\t\tprocessIdSpaceLength,\n\t\t\t\t\tfollowSymlinks,\n\t\t\t\t\ttrace,\n\t\t\t\t});\n\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(playground, '/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\tloadBalancer = new LoadBalancer(playground);\n\n\t\t\t\tawait playground.isReady();\n\t\t\t\twordPressReady = true;\n\t\t\t\tlogger.log(`Booted!`);\n\n\t\t\t\tif (compiledBlueprint) {\n\t\t\t\t\tlogger.log(`Running the Blueprint...`);\n\t\t\t\t\tawait runBlueprintSteps(compiledBlueprint, playground);\n\t\t\t\t\tlogger.log(`Finished running the blueprint`);\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}\n\n\t\t\t\tif (\n\t\t\t\t\targs.experimentalMultiWorker &&\n\t\t\t\t\targs.experimentalMultiWorker > 1\n\t\t\t\t) {\n\t\t\t\t\tlogger.log(`Preparing additional workers...`);\n\n\t\t\t\t\t// Save /internal directory from initial worker so we can replicate it\n\t\t\t\t\t// in each additional worker.\n\t\t\t\t\tconst internalZip = await zipDirectory(\n\t\t\t\t\t\tplayground,\n\t\t\t\t\t\t'/internal'\n\t\t\t\t\t);\n\n\t\t\t\t\t// Boot additional workers\n\t\t\t\t\tconst initialWorkerProcessIdSpace = processIdSpaceLength;\n\t\t\t\t\tawait Promise.all(\n\t\t\t\t\t\tadditionalWorkers.map(async (worker, index) => {\n\t\t\t\t\t\t\tconst additionalPlayground =\n\t\t\t\t\t\t\t\tconsumeAPI<PlaygroundCliWorker>(worker);\n\t\t\t\t\t\t\tplaygroundsToCleanUp.push({\n\t\t\t\t\t\t\t\tplayground: additionalPlayground,\n\t\t\t\t\t\t\t\tworker,\n\t\t\t\t\t\t\t});\n\n\t\t\t\t\t\t\tawait additionalPlayground.isConnected();\n\t\t\t\t\t\t\texposeAPI(fileLockManager, undefined, worker);\n\n\t\t\t\t\t\t\tconst firstProcessId =\n\t\t\t\t\t\t\t\tinitialWorkerProcessIdSpace +\n\t\t\t\t\t\t\t\tindex * processIdSpaceLength;\n\n\t\t\t\t\t\t\tawait additionalPlayground.boot({\n\t\t\t\t\t\t\t\tphpVersion: compiledBlueprint.versions.php,\n\t\t\t\t\t\t\t\tabsoluteUrl,\n\t\t\t\t\t\t\t\tmountsBeforeWpInstall,\n\t\t\t\t\t\t\t\tmountsAfterWpInstall,\n\t\t\t\t\t\t\t\t// Skip WordPress zip because we share the /wordpress directory\n\t\t\t\t\t\t\t\t// populated by the initial worker.\n\t\t\t\t\t\t\t\twordPressZip: undefined,\n\t\t\t\t\t\t\t\t// Skip SQLite integration plugin for now because we\n\t\t\t\t\t\t\t\t// will copy it from primary's `/internal` directory.\n\t\t\t\t\t\t\t\tsqliteIntegrationPluginZip: undefined,\n\t\t\t\t\t\t\t\tdataSqlPath:\n\t\t\t\t\t\t\t\t\t'/wordpress/wp-content/database/.ht.sqlite',\n\t\t\t\t\t\t\t\tfirstProcessId,\n\t\t\t\t\t\t\t\tprocessIdSpaceLength,\n\t\t\t\t\t\t\t\tfollowSymlinks,\n\t\t\t\t\t\t\t\ttrace,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\tawait additionalPlayground.isReady();\n\n\t\t\t\t\t\t\t// Replicate the Blueprint-initialized /internal directory\n\t\t\t\t\t\t\tawait additionalPlayground.writeFile(\n\t\t\t\t\t\t\t\t'/tmp/internal.zip',\n\t\t\t\t\t\t\t\tinternalZip\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\tawait unzipFile(\n\t\t\t\t\t\t\t\tadditionalPlayground,\n\t\t\t\t\t\t\t\t'/tmp/internal.zip',\n\t\t\t\t\t\t\t\t'/internal'\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\tawait additionalPlayground.unlink(\n\t\t\t\t\t\t\t\t'/tmp/internal.zip'\n\t\t\t\t\t\t\t);\n\n\t\t\t\t\t\t\tloadBalancer.addWorker(additionalPlayground);\n\t\t\t\t\t\t})\n\t\t\t\t\t);\n\n\t\t\t\t\tlogger.log(`Ready!`);\n\t\t\t\t}\n\n\t\t\t\tlogger.log(`WordPress is running on ${absoluteUrl}`);\n\n\t\t\t\treturn {\n\t\t\t\t\tplayground,\n\t\t\t\t\tserver,\n\t\t\t\t\t[Symbol.asyncDispose]: async function disposeCLI() {\n\t\t\t\t\t\tawait Promise.all(\n\t\t\t\t\t\t\tplaygroundsToCleanUp.map(\n\t\t\t\t\t\t\t\tasync ({ playground, worker }) => {\n\t\t\t\t\t\t\t\t\tawait playground.dispose();\n\t\t\t\t\t\t\t\t\tawait worker.terminate();\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t);\n\t\t\t\t\t\tawait new Promise((resolve) => server.close(resolve));\n\t\t\t\t\t},\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 = await playground.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 loadBalancer.handleRequest(request);\n\t\t},\n\t});\n}\n"],"names":["expandAutoMounts","args","path","mount","mountBeforeInstall","isPluginDirectory","pluginName","basename","isThemeDirectory","themeName","containsWpContentDirectories","wpContentMounts","containsFullWordPressInstallation","files","fs","mounts","file","join","blueprint","getSteps","skipWordPressSetup","styleCssContent","pluginNameRegex","fileContent","wpContentDir","CACHE_FOLDER","os","fetchSqliteIntegration","monitor","cachedDownload","remoteUrl","cacheKey","artifactPath","downloadTo","readAsFile","localPath","reader","tmpPath","writer","done","value","resolve","reject","err","fileName","startServer","options","app","express","server","address","req","res","phpResponse","parseHeaders","bufferRequestBody","key","port","body","chunk","requestHeaders","i","LoadBalancer","initialWorker","worker","request","smallestWorkerLoad","workerLoad","promiseForResponse","runCLI","loadBalancer","playground","playgroundsToCleanUp","zipSite","outfile","zip","compileInputBlueprint","isBlueprintBundle","RecommendedPHPVersion","tracker","ProgressTracker","lastCaption","progressReached100","e","progressInteger","message","writeProgressUpdate","compileBlueprint","lastProgressMessage","writeStream","finalUpdate","spawnPHPWorkerThread","workerUrl","Worker","onMessage","event","onError","error","spawnWorkerThreads","count","moduleWorkerUrl","importedWorkerUrlString","_documentCurrentScript","promises","logger","compiledBlueprint","fileLockManager","FileLockManagerForNode","wordPressReady","absoluteUrl","totalWorkerCount","promisedWorkers","wpDetails","EmscriptenDownloadMonitor","loaded","total","percentProgress","resolveWordPressRelease","preinstalledWpContentPath","wordPressZip","sqliteIntegrationPluginZip","followSymlinks","trace","mountsBeforeWpInstall","mountsAfterWpInstall","additionalWorkers","consumeAPI","exposeAPI","processIdSpaceLength","zipDirectory","runBlueprintSteps","internalZip","initialWorkerProcessIdSpace","index","additionalPlayground","firstProcessId","unzipFile","phpLogs","errorLogPath","PHPResponse"],"mappings":"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"}
|
package/run-cli.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
/// <reference types="node" />
|
|
2
|
-
import type {
|
|
2
|
+
import type { RemoteAPI, SupportedPHPVersion } from '@php-wasm/universal';
|
|
3
3
|
import type { BlueprintDeclaration, BlueprintBundle } from '@wp-playground/blueprints';
|
|
4
4
|
import type { Server } from 'http';
|
|
5
|
-
import {
|
|
5
|
+
import type { PlaygroundCliWorker, Mount } from './worker-thread';
|
|
6
6
|
export interface RunCLIArgs {
|
|
7
7
|
blueprint?: BlueprintDeclaration | BlueprintBundle;
|
|
8
8
|
command: 'server' | 'run-blueprint' | 'build-snapshot';
|
|
@@ -19,9 +19,12 @@ export interface RunCLIArgs {
|
|
|
19
19
|
wp?: string;
|
|
20
20
|
autoMount?: boolean;
|
|
21
21
|
followSymlinks?: boolean;
|
|
22
|
+
experimentalMultiWorker?: number;
|
|
23
|
+
experimentalTrace?: boolean;
|
|
22
24
|
}
|
|
23
|
-
export interface RunCLIServer {
|
|
24
|
-
|
|
25
|
+
export interface RunCLIServer extends AsyncDisposable {
|
|
26
|
+
playground: RemoteAPI<PlaygroundCliWorker>;
|
|
25
27
|
server: Server;
|
|
28
|
+
[Symbol.asyncDispose](): Promise<void>;
|
|
26
29
|
}
|
|
27
30
|
export declare function runCLI(args: RunCLIArgs): Promise<RunCLIServer>;
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
import { exposeAPI as k, PHPWorker as S, consumeAPI as _ } from "@php-wasm/universal";
|
|
2
|
+
import { loadNodeRuntime as N, createNodeFsMountHandler as W } from "@php-wasm/node";
|
|
3
|
+
import { EmscriptenDownloadMonitor as v } from "@php-wasm/progress";
|
|
4
|
+
import { bootWordPress as x } from "@wp-playground/wordpress";
|
|
5
|
+
import { parentPort as f } from "worker_threads";
|
|
6
|
+
import { rootCertificates as E } from "tls";
|
|
7
|
+
function I(r, ...o) {
|
|
8
|
+
let e = "", n = 0;
|
|
9
|
+
for (let i = 0; i < r.length; i++)
|
|
10
|
+
if (r[i] === "%" && i + 1 < r.length) {
|
|
11
|
+
i++;
|
|
12
|
+
const a = r[i];
|
|
13
|
+
switch (a) {
|
|
14
|
+
case "s": {
|
|
15
|
+
const t = o[n++];
|
|
16
|
+
let s;
|
|
17
|
+
if (typeof t == "object")
|
|
18
|
+
try {
|
|
19
|
+
s = JSON.stringify(
|
|
20
|
+
t,
|
|
21
|
+
// Represent bigint values as strings in JSON.stringify().
|
|
22
|
+
(u, c) => typeof c == "bigint" ? `0x${c.toString(16)}` : c,
|
|
23
|
+
2
|
|
24
|
+
);
|
|
25
|
+
} catch {
|
|
26
|
+
}
|
|
27
|
+
else
|
|
28
|
+
s = String(t);
|
|
29
|
+
e += s;
|
|
30
|
+
break;
|
|
31
|
+
}
|
|
32
|
+
case "d": {
|
|
33
|
+
const t = o[n++];
|
|
34
|
+
typeof t == "bigint" ? e += t.toString() : e += Math.floor(Number(t));
|
|
35
|
+
break;
|
|
36
|
+
}
|
|
37
|
+
case "f": {
|
|
38
|
+
const t = o[n++];
|
|
39
|
+
e += Number(t);
|
|
40
|
+
break;
|
|
41
|
+
}
|
|
42
|
+
case "x": {
|
|
43
|
+
const t = o[n++];
|
|
44
|
+
typeof t == "bigint" ? e += t.toString(16) : e += Math.floor(Number(t)).toString(16);
|
|
45
|
+
break;
|
|
46
|
+
}
|
|
47
|
+
case "%": {
|
|
48
|
+
e += "%";
|
|
49
|
+
break;
|
|
50
|
+
}
|
|
51
|
+
default:
|
|
52
|
+
e += "%" + a;
|
|
53
|
+
}
|
|
54
|
+
} else
|
|
55
|
+
e += r[i];
|
|
56
|
+
return e;
|
|
57
|
+
}
|
|
58
|
+
function P(r, o) {
|
|
59
|
+
for (const e of o)
|
|
60
|
+
r.mkdir(e.vfsPath), r.mount(e.vfsPath, W(e.hostPath));
|
|
61
|
+
}
|
|
62
|
+
function D(r, o, ...e) {
|
|
63
|
+
console.log(
|
|
64
|
+
performance.now().toFixed(6).padStart(15, "0"),
|
|
65
|
+
r.toString().padStart(16, "0"),
|
|
66
|
+
I(o, ...e)
|
|
67
|
+
);
|
|
68
|
+
}
|
|
69
|
+
class F extends S {
|
|
70
|
+
constructor(o) {
|
|
71
|
+
super(void 0, o), this.booted = !1;
|
|
72
|
+
}
|
|
73
|
+
async boot({
|
|
74
|
+
absoluteUrl: o,
|
|
75
|
+
mountsBeforeWpInstall: e,
|
|
76
|
+
mountsAfterWpInstall: n,
|
|
77
|
+
phpVersion: i = "8.0",
|
|
78
|
+
wordPressZip: a,
|
|
79
|
+
sqliteIntegrationPluginZip: t,
|
|
80
|
+
firstProcessId: s,
|
|
81
|
+
processIdSpaceLength: u,
|
|
82
|
+
dataSqlPath: c,
|
|
83
|
+
followSymlinks: g,
|
|
84
|
+
trace: y
|
|
85
|
+
}) {
|
|
86
|
+
if (this.booted)
|
|
87
|
+
throw new Error("Playground already booted");
|
|
88
|
+
this.booted = !0;
|
|
89
|
+
let l = s;
|
|
90
|
+
const w = s + u - 1, m = _(f);
|
|
91
|
+
await m.isConnected();
|
|
92
|
+
try {
|
|
93
|
+
const d = {
|
|
94
|
+
WP_DEBUG: !0,
|
|
95
|
+
WP_DEBUG_LOG: !0,
|
|
96
|
+
WP_DEBUG_DISPLAY: !1
|
|
97
|
+
}, h = await x({
|
|
98
|
+
siteUrl: o,
|
|
99
|
+
createPhpRuntime: async () => {
|
|
100
|
+
const p = l;
|
|
101
|
+
return l < w ? l++ : l = s, await N(i, {
|
|
102
|
+
emscriptenOptions: {
|
|
103
|
+
fileLockManager: m,
|
|
104
|
+
processId: p,
|
|
105
|
+
trace: y ? D : void 0
|
|
106
|
+
},
|
|
107
|
+
followSymlinks: g
|
|
108
|
+
});
|
|
109
|
+
},
|
|
110
|
+
wordPressZip: a !== void 0 ? new File([a], "wordpress.zip") : void 0,
|
|
111
|
+
sqliteIntegrationPluginZip: t !== void 0 ? new File(
|
|
112
|
+
[t],
|
|
113
|
+
"sqlite-integration-plugin.zip"
|
|
114
|
+
) : void 0,
|
|
115
|
+
sapiName: "cli",
|
|
116
|
+
createFiles: {
|
|
117
|
+
"/internal/shared/ca-bundle.crt": E.join(`
|
|
118
|
+
`)
|
|
119
|
+
},
|
|
120
|
+
constants: d,
|
|
121
|
+
phpIniEntries: {
|
|
122
|
+
"openssl.cafile": "/internal/shared/ca-bundle.crt",
|
|
123
|
+
allow_url_fopen: "1",
|
|
124
|
+
disable_functions: ""
|
|
125
|
+
},
|
|
126
|
+
hooks: {
|
|
127
|
+
async beforeWordPressFiles(p) {
|
|
128
|
+
P(p, e);
|
|
129
|
+
}
|
|
130
|
+
},
|
|
131
|
+
cookieStore: !1,
|
|
132
|
+
dataSqlPath: c
|
|
133
|
+
});
|
|
134
|
+
this.__internal_setRequestHandler(h);
|
|
135
|
+
const b = await h.getPrimaryPhp();
|
|
136
|
+
await this.setPrimaryPHP(b), P(b, n), M();
|
|
137
|
+
} catch (d) {
|
|
138
|
+
throw A(d), d;
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
// Provide a named disposal method that can be invoked via comlink.
|
|
142
|
+
async dispose() {
|
|
143
|
+
await this[Symbol.asyncDispose]();
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
const [M, A] = k(
|
|
147
|
+
new F(new v()),
|
|
148
|
+
void 0,
|
|
149
|
+
f
|
|
150
|
+
);
|
|
151
|
+
f.postMessage("worker-script-initialized");
|
|
152
|
+
//# sourceMappingURL=worker-thread-BQ8BezvJ.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"worker-thread-BQ8BezvJ.js","sources":["packages/php-wasm/util/src/lib/sprintf.ts","packages/playground/cli/src/worker-thread.ts"],"sourcesContent":["/**\n * Formats a string like sprintf().\n *\n * This function:\n * - Supports basic format specifiers: %s, %d, %f, %x, %%\n * - Supports bigint values\n *\n * The purpose of this function is for use in optional php-wasm tracing.\n * If we use printf-style formatting for trace messages, we let the trace\n * function decide whether to format and do not have to pay for formatting\n * unless tracing is enabled.\n */\nexport function sprintf(format: string, ...args: any[]): string {\n\tlet result = '';\n\tlet argIndex = 0;\n\n\tfor (let i = 0; i < format.length; i++) {\n\t\tif (format[i] === '%' && i + 1 < format.length) {\n\t\t\ti++;\n\t\t\tconst specifier = format[i];\n\n\t\t\tswitch (specifier) {\n\t\t\t\tcase 's': {\n\t\t\t\t\tconst arg = args[argIndex++];\n\t\t\t\t\tlet str;\n\t\t\t\t\tif (typeof arg === 'object') {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t// If an object doesn't provide its own toString(),\n\t\t\t\t\t\t\t// try to represent it as JSON.\n\t\t\t\t\t\t\tstr = JSON.stringify(\n\t\t\t\t\t\t\t\targ,\n\t\t\t\t\t\t\t\t// Represent bigint values as strings in JSON.stringify().\n\t\t\t\t\t\t\t\t(key, value) => {\n\t\t\t\t\t\t\t\t\tif (typeof value === 'bigint') {\n\t\t\t\t\t\t\t\t\t\treturn `0x${value.toString(16)}`;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\treturn value;\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t2\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t} catch {\n\t\t\t\t\t\t\t// Ignore error and use default representation.\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tstr = String(arg);\n\t\t\t\t\t}\n\n\t\t\t\t\tresult += str;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tcase 'd': {\n\t\t\t\t\tconst arg = args[argIndex++];\n\t\t\t\t\tif (typeof arg === 'bigint') {\n\t\t\t\t\t\tresult += arg.toString();\n\t\t\t\t\t} else {\n\t\t\t\t\t\tresult += Math.floor(Number(arg));\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tcase 'f': {\n\t\t\t\t\tconst arg = args[argIndex++];\n\t\t\t\t\tif (typeof arg === 'bigint') {\n\t\t\t\t\t\tresult += Number(arg);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tresult += Number(arg);\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tcase 'x': {\n\t\t\t\t\tconst arg = args[argIndex++];\n\t\t\t\t\tif (typeof arg === 'bigint') {\n\t\t\t\t\t\tresult += arg.toString(16);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tresult += Math.floor(Number(arg)).toString(16);\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tcase '%': {\n\t\t\t\t\tresult += '%';\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tdefault: {\n\t\t\t\t\tresult += '%' + specifier;\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tresult += format[i];\n\t\t}\n\t}\n\n\treturn result;\n}\n","import type { PHP, SupportedPHPVersion } from '@php-wasm/universal';\nimport { PHPWorker, consumeAPI, exposeAPI } from '@php-wasm/universal';\nimport type { FileLockManager } from '@php-wasm/node';\nimport { createNodeFsMountHandler, loadNodeRuntime } from '@php-wasm/node';\nimport { EmscriptenDownloadMonitor } from '@php-wasm/progress';\nimport { bootWordPress } from '@wp-playground/wordpress';\nimport { sprintf } from '@php-wasm/util';\nimport { parentPort } from 'worker_threads';\nimport { rootCertificates } from 'tls';\n\nexport interface Mount {\n\thostPath: string;\n\tvfsPath: string;\n}\n\nexport type PrimaryWorkerBootOptions = {\n\twpVersion?: string;\n\tphpVersion?: SupportedPHPVersion;\n\tabsoluteUrl: string;\n\tmountsBeforeWpInstall: Array<Mount>;\n\tmountsAfterWpInstall: Array<Mount>;\n\twordPressZip?: ArrayBuffer;\n\tsqliteIntegrationPluginZip?: ArrayBuffer;\n\tfirstProcessId: number;\n\tprocessIdSpaceLength: number;\n\tdataSqlPath?: string;\n\tfollowSymlinks: boolean;\n\ttrace: boolean;\n};\n\nfunction mountResources(php: PHP, mounts: Mount[]) {\n\tfor (const mount of mounts) {\n\t\tphp.mkdir(mount.vfsPath);\n\t\tphp.mount(mount.vfsPath, createNodeFsMountHandler(mount.hostPath));\n\t}\n}\n\n/**\n * Print trace messages from PHP-WASM.\n *\n * @param {number} processId - The process ID.\n * @param {string} format - The format string.\n * @param {...any} args - The arguments.\n */\nfunction tracePhpWasm(processId: number, format: string, ...args: any[]) {\n\t// eslint-disable-next-line no-console\n\tconsole.log(\n\t\tperformance.now().toFixed(6).padStart(15, '0'),\n\t\tprocessId.toString().padStart(16, '0'),\n\t\tsprintf(format, ...args)\n\t);\n}\n\nexport class PlaygroundCliWorker extends PHPWorker {\n\tbooted = false;\n\n\tconstructor(monitor: EmscriptenDownloadMonitor) {\n\t\tsuper(undefined, monitor);\n\t}\n\n\tasync boot({\n\t\tabsoluteUrl,\n\t\tmountsBeforeWpInstall,\n\t\tmountsAfterWpInstall,\n\t\tphpVersion = '8.0',\n\t\twordPressZip,\n\t\tsqliteIntegrationPluginZip,\n\t\tfirstProcessId,\n\t\tprocessIdSpaceLength,\n\t\tdataSqlPath,\n\t\tfollowSymlinks,\n\t\ttrace,\n\t}: PrimaryWorkerBootOptions) {\n\t\tif (this.booted) {\n\t\t\tthrow new Error('Playground already booted');\n\t\t}\n\t\tthis.booted = true;\n\n\t\tlet nextProcessId = firstProcessId;\n\t\tconst lastProcessId = firstProcessId + processIdSpaceLength - 1;\n\t\tconst fileLockManager = consumeAPI<FileLockManager>(parentPort!);\n\t\tawait fileLockManager.isConnected();\n\n\t\ttry {\n\t\t\tconst constants: Record<string, string | number | boolean | null> =\n\t\t\t\t{\n\t\t\t\t\tWP_DEBUG: true,\n\t\t\t\t\tWP_DEBUG_LOG: true,\n\t\t\t\t\tWP_DEBUG_DISPLAY: false,\n\t\t\t\t};\n\n\t\t\tconst requestHandler = await bootWordPress({\n\t\t\t\tsiteUrl: absoluteUrl,\n\t\t\t\tcreatePhpRuntime: async () => {\n\t\t\t\t\tconst processId = nextProcessId;\n\n\t\t\t\t\tif (nextProcessId < lastProcessId) {\n\t\t\t\t\t\tnextProcessId++;\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// We've reached the end of the process ID space. Start over.\n\t\t\t\t\t\tnextProcessId = firstProcessId;\n\t\t\t\t\t}\n\n\t\t\t\t\treturn await loadNodeRuntime(phpVersion, {\n\t\t\t\t\t\temscriptenOptions: {\n\t\t\t\t\t\t\tfileLockManager,\n\t\t\t\t\t\t\tprocessId,\n\t\t\t\t\t\t\ttrace: trace ? tracePhpWasm : undefined,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tfollowSymlinks,\n\t\t\t\t\t});\n\t\t\t\t},\n\t\t\t\twordPressZip:\n\t\t\t\t\twordPressZip !== undefined\n\t\t\t\t\t\t? new File([wordPressZip], 'wordpress.zip')\n\t\t\t\t\t\t: undefined,\n\t\t\t\tsqliteIntegrationPluginZip:\n\t\t\t\t\tsqliteIntegrationPluginZip !== undefined\n\t\t\t\t\t\t? new File(\n\t\t\t\t\t\t\t\t[sqliteIntegrationPluginZip],\n\t\t\t\t\t\t\t\t'sqlite-integration-plugin.zip'\n\t\t\t\t\t\t )\n\t\t\t\t\t\t: undefined,\n\t\t\t\tsapiName: 'cli',\n\t\t\t\tcreateFiles: {\n\t\t\t\t\t'/internal/shared/ca-bundle.crt':\n\t\t\t\t\t\trootCertificates.join('\\n'),\n\t\t\t\t},\n\t\t\t\tconstants,\n\t\t\t\tphpIniEntries: {\n\t\t\t\t\t'openssl.cafile': '/internal/shared/ca-bundle.crt',\n\t\t\t\t\tallow_url_fopen: '1',\n\t\t\t\t\tdisable_functions: '',\n\t\t\t\t},\n\t\t\t\thooks: {\n\t\t\t\t\tasync beforeWordPressFiles(php) {\n\t\t\t\t\t\tmountResources(php, mountsBeforeWpInstall);\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\tcookieStore: false,\n\t\t\t\tdataSqlPath,\n\t\t\t});\n\t\t\tthis.__internal_setRequestHandler(requestHandler);\n\n\t\t\tconst primaryPhp = await requestHandler.getPrimaryPhp();\n\t\t\tawait this.setPrimaryPHP(primaryPhp);\n\n\t\t\tmountResources(primaryPhp, mountsAfterWpInstall);\n\n\t\t\tsetApiReady();\n\t\t} catch (e) {\n\t\t\tsetAPIError(e as Error);\n\t\t\tthrow e;\n\t\t}\n\t}\n\n\t// Provide a named disposal method that can be invoked via comlink.\n\tasync dispose() {\n\t\tawait this[Symbol.asyncDispose]();\n\t}\n}\n\nconst [setApiReady, setAPIError] = exposeAPI(\n\tnew PlaygroundCliWorker(new EmscriptenDownloadMonitor()),\n\tundefined,\n\tparentPort!\n);\n\n// Confirm that the worker script has initialized.\nparentPort!.postMessage('worker-script-initialized');\n"],"names":["sprintf","format","args","result","argIndex","specifier","arg","str","key","value","mountResources","php","mounts","mount","createNodeFsMountHandler","tracePhpWasm","processId","PlaygroundCliWorker","PHPWorker","monitor","absoluteUrl","mountsBeforeWpInstall","mountsAfterWpInstall","phpVersion","wordPressZip","sqliteIntegrationPluginZip","firstProcessId","processIdSpaceLength","dataSqlPath","followSymlinks","trace","nextProcessId","lastProcessId","fileLockManager","consumeAPI","parentPort","constants","requestHandler","bootWordPress","loadNodeRuntime","rootCertificates","primaryPhp","setApiReady","e","setAPIError","exposeAPI","EmscriptenDownloadMonitor"],"mappings":"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"}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const a=require("@php-wasm/universal"),w=require("@php-wasm/node"),k=require("@php-wasm/progress"),W=require("@wp-playground/wordpress"),S=require("@php-wasm/util"),c=require("worker_threads"),E=require("tls");function h(o,e){for(const t of e)o.mkdir(t.vfsPath),o.mount(t.vfsPath,w.createNodeFsMountHandler(t.hostPath))}function D(o,e,...t){console.log(performance.now().toFixed(6).padStart(15,"0"),o.toString().padStart(16,"0"),S.sprintf(e,...t))}class f extends a.PHPWorker{constructor(e){super(void 0,e),this.booted=!1}async boot({absoluteUrl:e,mountsBeforeWpInstall:t,mountsAfterWpInstall:m,phpVersion:y="8.0",wordPressZip:l,sqliteIntegrationPluginZip:d,firstProcessId:n,processIdSpaceLength:b,dataSqlPath:g,followSymlinks:_,trace:v}){if(this.booted)throw new Error("Playground already booted");this.booted=!0;let r=n;const q=n+b-1,u=a.consumeAPI(c.parentPort);await u.isConnected();try{const s={WP_DEBUG:!0,WP_DEBUG_LOG:!0,WP_DEBUG_DISPLAY:!1},p=await W.bootWordPress({siteUrl:e,createPhpRuntime:async()=>{const i=r;return r<q?r++:r=n,await w.loadNodeRuntime(y,{emscriptenOptions:{fileLockManager:u,processId:i,trace:v?D:void 0},followSymlinks:_})},wordPressZip:l!==void 0?new File([l],"wordpress.zip"):void 0,sqliteIntegrationPluginZip:d!==void 0?new File([d],"sqlite-integration-plugin.zip"):void 0,sapiName:"cli",createFiles:{"/internal/shared/ca-bundle.crt":E.rootCertificates.join(`
|
|
2
|
+
`)},constants:s,phpIniEntries:{"openssl.cafile":"/internal/shared/ca-bundle.crt",allow_url_fopen:"1",disable_functions:""},hooks:{async beforeWordPressFiles(i){h(i,t)}},cookieStore:!1,dataSqlPath:g});this.__internal_setRequestHandler(p);const P=await p.getPrimaryPhp();await this.setPrimaryPHP(P),h(P,m),F()}catch(s){throw I(s),s}}async dispose(){await this[Symbol.asyncDispose]()}}const[F,I]=a.exposeAPI(new f(new k.EmscriptenDownloadMonitor),void 0,c.parentPort);c.parentPort.postMessage("worker-script-initialized");exports.PlaygroundCliWorker=f;
|
|
3
|
+
//# sourceMappingURL=worker-thread.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"worker-thread.cjs","sources":["../../../../packages/playground/cli/src/worker-thread.ts"],"sourcesContent":["import type { PHP, SupportedPHPVersion } from '@php-wasm/universal';\nimport { PHPWorker, consumeAPI, exposeAPI } from '@php-wasm/universal';\nimport type { FileLockManager } from '@php-wasm/node';\nimport { createNodeFsMountHandler, loadNodeRuntime } from '@php-wasm/node';\nimport { EmscriptenDownloadMonitor } from '@php-wasm/progress';\nimport { bootWordPress } from '@wp-playground/wordpress';\nimport { sprintf } from '@php-wasm/util';\nimport { parentPort } from 'worker_threads';\nimport { rootCertificates } from 'tls';\n\nexport interface Mount {\n\thostPath: string;\n\tvfsPath: string;\n}\n\nexport type PrimaryWorkerBootOptions = {\n\twpVersion?: string;\n\tphpVersion?: SupportedPHPVersion;\n\tabsoluteUrl: string;\n\tmountsBeforeWpInstall: Array<Mount>;\n\tmountsAfterWpInstall: Array<Mount>;\n\twordPressZip?: ArrayBuffer;\n\tsqliteIntegrationPluginZip?: ArrayBuffer;\n\tfirstProcessId: number;\n\tprocessIdSpaceLength: number;\n\tdataSqlPath?: string;\n\tfollowSymlinks: boolean;\n\ttrace: boolean;\n};\n\nfunction mountResources(php: PHP, mounts: Mount[]) {\n\tfor (const mount of mounts) {\n\t\tphp.mkdir(mount.vfsPath);\n\t\tphp.mount(mount.vfsPath, createNodeFsMountHandler(mount.hostPath));\n\t}\n}\n\n/**\n * Print trace messages from PHP-WASM.\n *\n * @param {number} processId - The process ID.\n * @param {string} format - The format string.\n * @param {...any} args - The arguments.\n */\nfunction tracePhpWasm(processId: number, format: string, ...args: any[]) {\n\t// eslint-disable-next-line no-console\n\tconsole.log(\n\t\tperformance.now().toFixed(6).padStart(15, '0'),\n\t\tprocessId.toString().padStart(16, '0'),\n\t\tsprintf(format, ...args)\n\t);\n}\n\nexport class PlaygroundCliWorker extends PHPWorker {\n\tbooted = false;\n\n\tconstructor(monitor: EmscriptenDownloadMonitor) {\n\t\tsuper(undefined, monitor);\n\t}\n\n\tasync boot({\n\t\tabsoluteUrl,\n\t\tmountsBeforeWpInstall,\n\t\tmountsAfterWpInstall,\n\t\tphpVersion = '8.0',\n\t\twordPressZip,\n\t\tsqliteIntegrationPluginZip,\n\t\tfirstProcessId,\n\t\tprocessIdSpaceLength,\n\t\tdataSqlPath,\n\t\tfollowSymlinks,\n\t\ttrace,\n\t}: PrimaryWorkerBootOptions) {\n\t\tif (this.booted) {\n\t\t\tthrow new Error('Playground already booted');\n\t\t}\n\t\tthis.booted = true;\n\n\t\tlet nextProcessId = firstProcessId;\n\t\tconst lastProcessId = firstProcessId + processIdSpaceLength - 1;\n\t\tconst fileLockManager = consumeAPI<FileLockManager>(parentPort!);\n\t\tawait fileLockManager.isConnected();\n\n\t\ttry {\n\t\t\tconst constants: Record<string, string | number | boolean | null> =\n\t\t\t\t{\n\t\t\t\t\tWP_DEBUG: true,\n\t\t\t\t\tWP_DEBUG_LOG: true,\n\t\t\t\t\tWP_DEBUG_DISPLAY: false,\n\t\t\t\t};\n\n\t\t\tconst requestHandler = await bootWordPress({\n\t\t\t\tsiteUrl: absoluteUrl,\n\t\t\t\tcreatePhpRuntime: async () => {\n\t\t\t\t\tconst processId = nextProcessId;\n\n\t\t\t\t\tif (nextProcessId < lastProcessId) {\n\t\t\t\t\t\tnextProcessId++;\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// We've reached the end of the process ID space. Start over.\n\t\t\t\t\t\tnextProcessId = firstProcessId;\n\t\t\t\t\t}\n\n\t\t\t\t\treturn await loadNodeRuntime(phpVersion, {\n\t\t\t\t\t\temscriptenOptions: {\n\t\t\t\t\t\t\tfileLockManager,\n\t\t\t\t\t\t\tprocessId,\n\t\t\t\t\t\t\ttrace: trace ? tracePhpWasm : undefined,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tfollowSymlinks,\n\t\t\t\t\t});\n\t\t\t\t},\n\t\t\t\twordPressZip:\n\t\t\t\t\twordPressZip !== undefined\n\t\t\t\t\t\t? new File([wordPressZip], 'wordpress.zip')\n\t\t\t\t\t\t: undefined,\n\t\t\t\tsqliteIntegrationPluginZip:\n\t\t\t\t\tsqliteIntegrationPluginZip !== undefined\n\t\t\t\t\t\t? new File(\n\t\t\t\t\t\t\t\t[sqliteIntegrationPluginZip],\n\t\t\t\t\t\t\t\t'sqlite-integration-plugin.zip'\n\t\t\t\t\t\t )\n\t\t\t\t\t\t: undefined,\n\t\t\t\tsapiName: 'cli',\n\t\t\t\tcreateFiles: {\n\t\t\t\t\t'/internal/shared/ca-bundle.crt':\n\t\t\t\t\t\trootCertificates.join('\\n'),\n\t\t\t\t},\n\t\t\t\tconstants,\n\t\t\t\tphpIniEntries: {\n\t\t\t\t\t'openssl.cafile': '/internal/shared/ca-bundle.crt',\n\t\t\t\t\tallow_url_fopen: '1',\n\t\t\t\t\tdisable_functions: '',\n\t\t\t\t},\n\t\t\t\thooks: {\n\t\t\t\t\tasync beforeWordPressFiles(php) {\n\t\t\t\t\t\tmountResources(php, mountsBeforeWpInstall);\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\tcookieStore: false,\n\t\t\t\tdataSqlPath,\n\t\t\t});\n\t\t\tthis.__internal_setRequestHandler(requestHandler);\n\n\t\t\tconst primaryPhp = await requestHandler.getPrimaryPhp();\n\t\t\tawait this.setPrimaryPHP(primaryPhp);\n\n\t\t\tmountResources(primaryPhp, mountsAfterWpInstall);\n\n\t\t\tsetApiReady();\n\t\t} catch (e) {\n\t\t\tsetAPIError(e as Error);\n\t\t\tthrow e;\n\t\t}\n\t}\n\n\t// Provide a named disposal method that can be invoked via comlink.\n\tasync dispose() {\n\t\tawait this[Symbol.asyncDispose]();\n\t}\n}\n\nconst [setApiReady, setAPIError] = exposeAPI(\n\tnew PlaygroundCliWorker(new EmscriptenDownloadMonitor()),\n\tundefined,\n\tparentPort!\n);\n\n// Confirm that the worker script has initialized.\nparentPort!.postMessage('worker-script-initialized');\n"],"names":["mountResources","php","mounts","mount","createNodeFsMountHandler","tracePhpWasm","processId","format","args","sprintf","PlaygroundCliWorker","PHPWorker","monitor","absoluteUrl","mountsBeforeWpInstall","mountsAfterWpInstall","phpVersion","wordPressZip","sqliteIntegrationPluginZip","firstProcessId","processIdSpaceLength","dataSqlPath","followSymlinks","trace","nextProcessId","lastProcessId","fileLockManager","consumeAPI","parentPort","constants","requestHandler","bootWordPress","loadNodeRuntime","rootCertificates","primaryPhp","setApiReady","e","setAPIError","exposeAPI","EmscriptenDownloadMonitor"],"mappings":"kSA8BA,SAASA,EAAeC,EAAUC,EAAiB,CAClD,UAAWC,KAASD,EACfD,EAAA,MAAME,EAAM,OAAO,EACvBF,EAAI,MAAME,EAAM,QAASC,EAAAA,yBAAyBD,EAAM,QAAQ,CAAC,CAEnE,CASA,SAASE,EAAaC,EAAmBC,KAAmBC,EAAa,CAEhE,QAAA,IACP,YAAY,MAAM,QAAQ,CAAC,EAAE,SAAS,GAAI,GAAG,EAC7CF,EAAU,SAAW,EAAA,SAAS,GAAI,GAAG,EACrCG,EAAA,QAAQF,EAAQ,GAAGC,CAAI,CACxB,CACD,CAEO,MAAME,UAA4BC,EAAAA,SAAU,CAGlD,YAAYC,EAAoC,CAC/C,MAAM,OAAWA,CAAO,EAHhB,KAAA,OAAA,EAAA,CAMT,MAAM,KAAK,CACV,YAAAC,EACA,sBAAAC,EACA,qBAAAC,EACA,WAAAC,EAAa,MACb,aAAAC,EACA,2BAAAC,EACA,eAAAC,EACA,qBAAAC,EACA,YAAAC,EACA,eAAAC,EACA,MAAAC,CAAA,EAC4B,CAC5B,GAAI,KAAK,OACF,MAAA,IAAI,MAAM,2BAA2B,EAE5C,KAAK,OAAS,GAEd,IAAIC,EAAgBL,EACd,MAAAM,EAAgBN,EAAiBC,EAAuB,EACxDM,EAAkBC,aAA4BC,YAAW,EAC/D,MAAMF,EAAgB,YAAY,EAE9B,GAAA,CACH,MAAMG,EACL,CACC,SAAU,GACV,aAAc,GACd,iBAAkB,EACnB,EAEKC,EAAiB,MAAMC,gBAAc,CAC1C,QAASlB,EACT,iBAAkB,SAAY,CAC7B,MAAMP,EAAYkB,EAElB,OAAIA,EAAgBC,EACnBD,IAGgBA,EAAAL,EAGV,MAAMa,kBAAgBhB,EAAY,CACxC,kBAAmB,CAClB,gBAAAU,EACA,UAAApB,EACA,MAAOiB,EAAQlB,EAAe,MAC/B,EACA,eAAAiB,CAAA,CACA,CACF,EACA,aACCL,IAAiB,OACd,IAAI,KAAK,CAACA,CAAY,EAAG,eAAe,EACxC,OACJ,2BACCC,IAA+B,OAC5B,IAAI,KACJ,CAACA,CAA0B,EAC3B,+BAEA,EAAA,OACJ,SAAU,MACV,YAAa,CACZ,iCACCe,EAAAA,iBAAiB,KAAK;AAAA,CAAI,CAC5B,EACA,UAAAJ,EACA,cAAe,CACd,iBAAkB,iCAClB,gBAAiB,IACjB,kBAAmB,EACpB,EACA,MAAO,CACN,MAAM,qBAAqB5B,EAAK,CAC/BD,EAAeC,EAAKa,CAAqB,CAAA,CAE3C,EACA,YAAa,GACb,YAAAO,CAAA,CACA,EACD,KAAK,6BAA6BS,CAAc,EAE1C,MAAAI,EAAa,MAAMJ,EAAe,cAAc,EAChD,MAAA,KAAK,cAAcI,CAAU,EAEnClC,EAAekC,EAAYnB,CAAoB,EAEnCoB,EAAA,QACJC,EAAG,CACX,MAAAC,EAAYD,CAAU,EAChBA,CAAA,CACP,CAID,MAAM,SAAU,CACT,MAAA,KAAK,OAAO,YAAY,EAAE,CAAA,CAElC,CAEA,KAAM,CAACD,EAAaE,CAAW,EAAIC,EAAA,UAClC,IAAI5B,EAAoB,IAAI6B,EAAAA,yBAA2B,EACvD,OACAX,EAAAA,UACD,EAGAA,EAAAA,WAAY,YAAY,2BAA2B"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { SupportedPHPVersion } from '@php-wasm/universal';
|
|
2
|
+
import { PHPWorker } from '@php-wasm/universal';
|
|
3
|
+
import { EmscriptenDownloadMonitor } from '@php-wasm/progress';
|
|
4
|
+
export interface Mount {
|
|
5
|
+
hostPath: string;
|
|
6
|
+
vfsPath: string;
|
|
7
|
+
}
|
|
8
|
+
export type PrimaryWorkerBootOptions = {
|
|
9
|
+
wpVersion?: string;
|
|
10
|
+
phpVersion?: SupportedPHPVersion;
|
|
11
|
+
absoluteUrl: string;
|
|
12
|
+
mountsBeforeWpInstall: Array<Mount>;
|
|
13
|
+
mountsAfterWpInstall: Array<Mount>;
|
|
14
|
+
wordPressZip?: ArrayBuffer;
|
|
15
|
+
sqliteIntegrationPluginZip?: ArrayBuffer;
|
|
16
|
+
firstProcessId: number;
|
|
17
|
+
processIdSpaceLength: number;
|
|
18
|
+
dataSqlPath?: string;
|
|
19
|
+
followSymlinks: boolean;
|
|
20
|
+
trace: boolean;
|
|
21
|
+
};
|
|
22
|
+
export declare class PlaygroundCliWorker extends PHPWorker {
|
|
23
|
+
booted: boolean;
|
|
24
|
+
constructor(monitor: EmscriptenDownloadMonitor);
|
|
25
|
+
boot({ absoluteUrl, mountsBeforeWpInstall, mountsAfterWpInstall, phpVersion, wordPressZip, sqliteIntegrationPluginZip, firstProcessId, processIdSpaceLength, dataSqlPath, followSymlinks, trace, }: PrimaryWorkerBootOptions): Promise<void>;
|
|
26
|
+
dispose(): Promise<void>;
|
|
27
|
+
}
|
package/worker-thread.js
ADDED
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import { exposeAPI as g, PHPWorker as v, consumeAPI as W } from "@php-wasm/universal";
|
|
2
|
+
import { loadNodeRuntime as k, createNodeFsMountHandler as E } from "@php-wasm/node";
|
|
3
|
+
import { EmscriptenDownloadMonitor as D } from "@php-wasm/progress";
|
|
4
|
+
import { bootWordPress as F } from "@wp-playground/wordpress";
|
|
5
|
+
import { sprintf as I } from "@php-wasm/util";
|
|
6
|
+
import { parentPort as a } from "worker_threads";
|
|
7
|
+
import { rootCertificates as S } from "tls";
|
|
8
|
+
function u(t, e) {
|
|
9
|
+
for (const o of e)
|
|
10
|
+
t.mkdir(o.vfsPath), t.mount(o.vfsPath, E(o.hostPath));
|
|
11
|
+
}
|
|
12
|
+
function x(t, e, ...o) {
|
|
13
|
+
console.log(
|
|
14
|
+
performance.now().toFixed(6).padStart(15, "0"),
|
|
15
|
+
t.toString().padStart(16, "0"),
|
|
16
|
+
I(e, ...o)
|
|
17
|
+
);
|
|
18
|
+
}
|
|
19
|
+
class A extends v {
|
|
20
|
+
constructor(e) {
|
|
21
|
+
super(void 0, e), this.booted = !1;
|
|
22
|
+
}
|
|
23
|
+
async boot({
|
|
24
|
+
absoluteUrl: e,
|
|
25
|
+
mountsBeforeWpInstall: o,
|
|
26
|
+
mountsAfterWpInstall: P,
|
|
27
|
+
phpVersion: f = "8.0",
|
|
28
|
+
wordPressZip: c,
|
|
29
|
+
sqliteIntegrationPluginZip: l,
|
|
30
|
+
firstProcessId: i,
|
|
31
|
+
processIdSpaceLength: h,
|
|
32
|
+
dataSqlPath: w,
|
|
33
|
+
followSymlinks: y,
|
|
34
|
+
trace: b
|
|
35
|
+
}) {
|
|
36
|
+
if (this.booted)
|
|
37
|
+
throw new Error("Playground already booted");
|
|
38
|
+
this.booted = !0;
|
|
39
|
+
let r = i;
|
|
40
|
+
const _ = i + h - 1, d = W(a);
|
|
41
|
+
await d.isConnected();
|
|
42
|
+
try {
|
|
43
|
+
const s = {
|
|
44
|
+
WP_DEBUG: !0,
|
|
45
|
+
WP_DEBUG_LOG: !0,
|
|
46
|
+
WP_DEBUG_DISPLAY: !1
|
|
47
|
+
}, p = await F({
|
|
48
|
+
siteUrl: e,
|
|
49
|
+
createPhpRuntime: async () => {
|
|
50
|
+
const n = r;
|
|
51
|
+
return r < _ ? r++ : r = i, await k(f, {
|
|
52
|
+
emscriptenOptions: {
|
|
53
|
+
fileLockManager: d,
|
|
54
|
+
processId: n,
|
|
55
|
+
trace: b ? x : void 0
|
|
56
|
+
},
|
|
57
|
+
followSymlinks: y
|
|
58
|
+
});
|
|
59
|
+
},
|
|
60
|
+
wordPressZip: c !== void 0 ? new File([c], "wordpress.zip") : void 0,
|
|
61
|
+
sqliteIntegrationPluginZip: l !== void 0 ? new File(
|
|
62
|
+
[l],
|
|
63
|
+
"sqlite-integration-plugin.zip"
|
|
64
|
+
) : void 0,
|
|
65
|
+
sapiName: "cli",
|
|
66
|
+
createFiles: {
|
|
67
|
+
"/internal/shared/ca-bundle.crt": S.join(`
|
|
68
|
+
`)
|
|
69
|
+
},
|
|
70
|
+
constants: s,
|
|
71
|
+
phpIniEntries: {
|
|
72
|
+
"openssl.cafile": "/internal/shared/ca-bundle.crt",
|
|
73
|
+
allow_url_fopen: "1",
|
|
74
|
+
disable_functions: ""
|
|
75
|
+
},
|
|
76
|
+
hooks: {
|
|
77
|
+
async beforeWordPressFiles(n) {
|
|
78
|
+
u(n, o);
|
|
79
|
+
}
|
|
80
|
+
},
|
|
81
|
+
cookieStore: !1,
|
|
82
|
+
dataSqlPath: w
|
|
83
|
+
});
|
|
84
|
+
this.__internal_setRequestHandler(p);
|
|
85
|
+
const m = await p.getPrimaryPhp();
|
|
86
|
+
await this.setPrimaryPHP(m), u(m, P), H();
|
|
87
|
+
} catch (s) {
|
|
88
|
+
throw R(s), s;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
// Provide a named disposal method that can be invoked via comlink.
|
|
92
|
+
async dispose() {
|
|
93
|
+
await this[Symbol.asyncDispose]();
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
const [H, R] = g(
|
|
97
|
+
new A(new D()),
|
|
98
|
+
void 0,
|
|
99
|
+
a
|
|
100
|
+
);
|
|
101
|
+
a.postMessage("worker-script-initialized");
|
|
102
|
+
export {
|
|
103
|
+
A as PlaygroundCliWorker
|
|
104
|
+
};
|
|
105
|
+
//# sourceMappingURL=worker-thread.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"worker-thread.js","sources":["../../../../packages/playground/cli/src/worker-thread.ts"],"sourcesContent":["import type { PHP, SupportedPHPVersion } from '@php-wasm/universal';\nimport { PHPWorker, consumeAPI, exposeAPI } from '@php-wasm/universal';\nimport type { FileLockManager } from '@php-wasm/node';\nimport { createNodeFsMountHandler, loadNodeRuntime } from '@php-wasm/node';\nimport { EmscriptenDownloadMonitor } from '@php-wasm/progress';\nimport { bootWordPress } from '@wp-playground/wordpress';\nimport { sprintf } from '@php-wasm/util';\nimport { parentPort } from 'worker_threads';\nimport { rootCertificates } from 'tls';\n\nexport interface Mount {\n\thostPath: string;\n\tvfsPath: string;\n}\n\nexport type PrimaryWorkerBootOptions = {\n\twpVersion?: string;\n\tphpVersion?: SupportedPHPVersion;\n\tabsoluteUrl: string;\n\tmountsBeforeWpInstall: Array<Mount>;\n\tmountsAfterWpInstall: Array<Mount>;\n\twordPressZip?: ArrayBuffer;\n\tsqliteIntegrationPluginZip?: ArrayBuffer;\n\tfirstProcessId: number;\n\tprocessIdSpaceLength: number;\n\tdataSqlPath?: string;\n\tfollowSymlinks: boolean;\n\ttrace: boolean;\n};\n\nfunction mountResources(php: PHP, mounts: Mount[]) {\n\tfor (const mount of mounts) {\n\t\tphp.mkdir(mount.vfsPath);\n\t\tphp.mount(mount.vfsPath, createNodeFsMountHandler(mount.hostPath));\n\t}\n}\n\n/**\n * Print trace messages from PHP-WASM.\n *\n * @param {number} processId - The process ID.\n * @param {string} format - The format string.\n * @param {...any} args - The arguments.\n */\nfunction tracePhpWasm(processId: number, format: string, ...args: any[]) {\n\t// eslint-disable-next-line no-console\n\tconsole.log(\n\t\tperformance.now().toFixed(6).padStart(15, '0'),\n\t\tprocessId.toString().padStart(16, '0'),\n\t\tsprintf(format, ...args)\n\t);\n}\n\nexport class PlaygroundCliWorker extends PHPWorker {\n\tbooted = false;\n\n\tconstructor(monitor: EmscriptenDownloadMonitor) {\n\t\tsuper(undefined, monitor);\n\t}\n\n\tasync boot({\n\t\tabsoluteUrl,\n\t\tmountsBeforeWpInstall,\n\t\tmountsAfterWpInstall,\n\t\tphpVersion = '8.0',\n\t\twordPressZip,\n\t\tsqliteIntegrationPluginZip,\n\t\tfirstProcessId,\n\t\tprocessIdSpaceLength,\n\t\tdataSqlPath,\n\t\tfollowSymlinks,\n\t\ttrace,\n\t}: PrimaryWorkerBootOptions) {\n\t\tif (this.booted) {\n\t\t\tthrow new Error('Playground already booted');\n\t\t}\n\t\tthis.booted = true;\n\n\t\tlet nextProcessId = firstProcessId;\n\t\tconst lastProcessId = firstProcessId + processIdSpaceLength - 1;\n\t\tconst fileLockManager = consumeAPI<FileLockManager>(parentPort!);\n\t\tawait fileLockManager.isConnected();\n\n\t\ttry {\n\t\t\tconst constants: Record<string, string | number | boolean | null> =\n\t\t\t\t{\n\t\t\t\t\tWP_DEBUG: true,\n\t\t\t\t\tWP_DEBUG_LOG: true,\n\t\t\t\t\tWP_DEBUG_DISPLAY: false,\n\t\t\t\t};\n\n\t\t\tconst requestHandler = await bootWordPress({\n\t\t\t\tsiteUrl: absoluteUrl,\n\t\t\t\tcreatePhpRuntime: async () => {\n\t\t\t\t\tconst processId = nextProcessId;\n\n\t\t\t\t\tif (nextProcessId < lastProcessId) {\n\t\t\t\t\t\tnextProcessId++;\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// We've reached the end of the process ID space. Start over.\n\t\t\t\t\t\tnextProcessId = firstProcessId;\n\t\t\t\t\t}\n\n\t\t\t\t\treturn await loadNodeRuntime(phpVersion, {\n\t\t\t\t\t\temscriptenOptions: {\n\t\t\t\t\t\t\tfileLockManager,\n\t\t\t\t\t\t\tprocessId,\n\t\t\t\t\t\t\ttrace: trace ? tracePhpWasm : undefined,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tfollowSymlinks,\n\t\t\t\t\t});\n\t\t\t\t},\n\t\t\t\twordPressZip:\n\t\t\t\t\twordPressZip !== undefined\n\t\t\t\t\t\t? new File([wordPressZip], 'wordpress.zip')\n\t\t\t\t\t\t: undefined,\n\t\t\t\tsqliteIntegrationPluginZip:\n\t\t\t\t\tsqliteIntegrationPluginZip !== undefined\n\t\t\t\t\t\t? new File(\n\t\t\t\t\t\t\t\t[sqliteIntegrationPluginZip],\n\t\t\t\t\t\t\t\t'sqlite-integration-plugin.zip'\n\t\t\t\t\t\t )\n\t\t\t\t\t\t: undefined,\n\t\t\t\tsapiName: 'cli',\n\t\t\t\tcreateFiles: {\n\t\t\t\t\t'/internal/shared/ca-bundle.crt':\n\t\t\t\t\t\trootCertificates.join('\\n'),\n\t\t\t\t},\n\t\t\t\tconstants,\n\t\t\t\tphpIniEntries: {\n\t\t\t\t\t'openssl.cafile': '/internal/shared/ca-bundle.crt',\n\t\t\t\t\tallow_url_fopen: '1',\n\t\t\t\t\tdisable_functions: '',\n\t\t\t\t},\n\t\t\t\thooks: {\n\t\t\t\t\tasync beforeWordPressFiles(php) {\n\t\t\t\t\t\tmountResources(php, mountsBeforeWpInstall);\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\tcookieStore: false,\n\t\t\t\tdataSqlPath,\n\t\t\t});\n\t\t\tthis.__internal_setRequestHandler(requestHandler);\n\n\t\t\tconst primaryPhp = await requestHandler.getPrimaryPhp();\n\t\t\tawait this.setPrimaryPHP(primaryPhp);\n\n\t\t\tmountResources(primaryPhp, mountsAfterWpInstall);\n\n\t\t\tsetApiReady();\n\t\t} catch (e) {\n\t\t\tsetAPIError(e as Error);\n\t\t\tthrow e;\n\t\t}\n\t}\n\n\t// Provide a named disposal method that can be invoked via comlink.\n\tasync dispose() {\n\t\tawait this[Symbol.asyncDispose]();\n\t}\n}\n\nconst [setApiReady, setAPIError] = exposeAPI(\n\tnew PlaygroundCliWorker(new EmscriptenDownloadMonitor()),\n\tundefined,\n\tparentPort!\n);\n\n// Confirm that the worker script has initialized.\nparentPort!.postMessage('worker-script-initialized');\n"],"names":["mountResources","php","mounts","mount","createNodeFsMountHandler","tracePhpWasm","processId","format","args","sprintf","PlaygroundCliWorker","PHPWorker","monitor","absoluteUrl","mountsBeforeWpInstall","mountsAfterWpInstall","phpVersion","wordPressZip","sqliteIntegrationPluginZip","firstProcessId","processIdSpaceLength","dataSqlPath","followSymlinks","trace","nextProcessId","lastProcessId","fileLockManager","consumeAPI","parentPort","constants","requestHandler","bootWordPress","loadNodeRuntime","rootCertificates","primaryPhp","setApiReady","e","setAPIError","exposeAPI","EmscriptenDownloadMonitor"],"mappings":"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"}
|
package/run-cli-BSw9FKSW.cjs
DELETED
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
"use strict";const p=require("@php-wasm/logger"),H=require("@php-wasm/node"),x=require("@php-wasm/progress"),z=require("@php-wasm/universal"),b=require("@wp-playground/blueprints"),q=require("@wp-playground/common"),B=require("@wp-playground/wordpress"),d=require("fs"),f=require("path"),L=require("tls"),P=require("fs-extra"),T=require("os"),U=require("express");function Z(e){const t=process.cwd(),n=[...e.mount||[]],o=[...e.mountBeforeInstall||[]];if(M(t)){const r=f.basename(t);n.push({hostPath:t,vfsPath:`/wordpress/wp-content/plugins/${r}`})}else if(F(t)){const r=f.basename(t);n.push({hostPath:t,vfsPath:`/wordpress/wp-content/themes/${r}`})}else if(C(t))n.push(...E(t));else if(S(t)){const r=d.readdirSync(t),l=[];for(const s of r)s.startsWith("wp-content")||l.push({hostPath:`${t}/${s}`,vfsPath:`/wordpress/${s}`});o.push(...l,...E(f.join(t,"wp-content")))}else n.push({hostPath:t,vfsPath:"/wordpress"});const i=e.blueprint||{};i.steps=[...i.steps||[],...j(t)];const a=e.skipWordPressSetup||S(t);return{...e,blueprint:i,mount:n,mountBeforeInstall:o,skipWordPressSetup:a}}function S(e){const t=d.readdirSync(e);return t.includes("wp-admin")&&t.includes("wp-includes")&&t.includes("wp-content")}function C(e){const t=d.readdirSync(e);return t.includes("themes")||t.includes("plugins")||t.includes("mu-plugins")||t.includes("uploads")}function F(e){if(!d.readdirSync(e).includes("style.css"))return!1;const n=d.readFileSync(f.join(e,"style.css"),"utf8");return!!/^(?:[ \t]*<\?php)?[ \t/*#@]*Theme Name:(.*)$/im.exec(n)}function M(e){const t=d.readdirSync(e),n=/^(?:[ \t]*<\?php)?[ \t/*#@]*Plugin Name:(.*)$/im;return!!t.filter(i=>i.endsWith(".php")).find(i=>{const a=d.readFileSync(f.join(e,i),"utf8");return!!n.exec(a)})}function E(e){return d.readdirSync(e).filter(n=>!n.startsWith("index.php")).map(n=>({hostPath:`${e}/${n}`,vfsPath:`/wordpress/wp-content/${n}`}))}function j(e){return M(e)?[{step:"activatePlugin",pluginPath:`/wordpress/wp-content/plugins/${f.basename(e)}`}]:F(e)?[{step:"activateTheme",themeFolderName:f.basename(e)}]:C(e)||S(e)?[{step:"runPHP",code:`<?php
|
|
2
|
-
require_once '/wordpress/wp-load.php';
|
|
3
|
-
$theme = wp_get_theme();
|
|
4
|
-
if (!$theme->exists()) {
|
|
5
|
-
$themes = wp_get_themes();
|
|
6
|
-
if (count($themes) > 0) {
|
|
7
|
-
$themeName = array_keys($themes)[0];
|
|
8
|
-
switch_theme($themeName);
|
|
9
|
-
}
|
|
10
|
-
}
|
|
11
|
-
`}]:[]}const W=f.join(T.homedir(),".wordpress-playground");async function V(e){return await D("https://github.com/WordPress/sqlite-database-integration/archive/refs/heads/develop.zip","sqlite.zip",e)}async function D(e,t,n){const o=f.join(W,t);return P.existsSync(o)||(P.ensureDirSync(W),await G(e,o,n)),_(o)}async function G(e,t,n){const i=(await n.monitorFetch(fetch(e))).body.getReader(),a=`${t}.partial`,r=P.createWriteStream(a);for(;;){const{done:l,value:s}=await i.read();if(s&&r.write(s),l)break}r.close(),r.closed||await new Promise((l,s)=>{r.on("finish",()=>{P.renameSync(a,t),l(null)}),r.on("error",c=>{P.removeSync(a),s(c)})})}function _(e,t){return new File([P.readFileSync(e)],f.basename(e))}async function O(e){const t=U(),n=await new Promise((a,r)=>{const l=t.listen(e.port,()=>{const s=l.address();s===null||typeof s=="string"?r(new Error("Server address is not available")):a(l)})});t.use("/",async(a,r)=>{const l=await e.handleRequest({url:a.url,headers:J(a),method:a.method,body:await Y(a)});r.statusCode=l.httpStatusCode;for(const s in l.headers)r.setHeader(s,l.headers[s]);r.end(l.bytes)});const i=n.address().port;return await e.onBind(n,i)}const Y=async e=>await new Promise(t=>{const n=[];e.on("data",o=>{n.push(o)}),e.on("end",()=>{t(new Uint8Array(Buffer.concat(n)))})}),J=e=>{const t={};if(e.rawHeaders&&e.rawHeaders.length)for(let n=0;n<e.rawHeaders.length;n+=2)t[e.rawHeaders[n].toLowerCase()]=e.rawHeaders[n+1];return t};function K(e){const t=[];for(const n of e){const o=n.split(":");if(o.length!==2)throw new Error(`Invalid mount format: ${n}.
|
|
12
|
-
Expected format: /host/path:/vfs/path.
|
|
13
|
-
If your path contains a colon, e.g. C:\\myplugin, use the --mount-dir option instead.
|
|
14
|
-
Example: --mount-dir C:\\my-plugin /wordpress/wp-content/plugins/my-plugin`);const[i,a]=o;if(!d.existsSync(i))throw new Error(`Host path does not exist: ${i}`);t.push({hostPath:i,vfsPath:a})}return t}function Q(e){if(e.length%2!==0)throw new Error("Invalid mount format. Expected: /host/path /vfs/path");const t=[];for(let n=0;n<e.length;n+=2){const o=e[n],i=e[n+1];if(!d.existsSync(o))throw new Error(`Host path does not exist: ${o}`);t.push({hostPath:f.resolve(process.cwd(),o),vfsPath:i})}return t}function I(e,t){for(const n of t)e.mkdir(n.vfsPath),e.mount(n.vfsPath,H.createNodeFsMountHandler(n.hostPath))}async function X(e){e.autoMount&&(e=Z(e));async function t(s){const{php:c,reap:h}=await r.processManager.acquirePHPInstance();try{await c.run({code:`<?php
|
|
15
|
-
$zip = new ZipArchive();
|
|
16
|
-
if(false === $zip->open('/tmp/build.zip', ZipArchive::CREATE | ZipArchive::OVERWRITE)) {
|
|
17
|
-
throw new Exception('Failed to create ZIP');
|
|
18
|
-
}
|
|
19
|
-
$files = new RecursiveIteratorIterator(
|
|
20
|
-
new RecursiveDirectoryIterator('/wordpress')
|
|
21
|
-
);
|
|
22
|
-
foreach ($files as $file) {
|
|
23
|
-
echo $file . PHP_EOL;
|
|
24
|
-
if (!$file->isFile()) {
|
|
25
|
-
continue;
|
|
26
|
-
}
|
|
27
|
-
$zip->addFile($file->getPathname(), $file->getPathname());
|
|
28
|
-
}
|
|
29
|
-
$zip->close();
|
|
30
|
-
|
|
31
|
-
`});const u=c.readFileAsBuffer("/tmp/build.zip");d.writeFileSync(s,u)}finally{h()}}async function n(){const s=b.isBlueprintBundle(e.blueprint)?e.blueprint:{login:e.login,...e.blueprint,preferredVersions:{php:e.php??e?.blueprint?.preferredVersions?.php??q.RecommendedPHPVersion,wp:e.wp??e?.blueprint?.preferredVersions?.wp??"latest",...e.blueprint?.preferredVersions||{}}},c=new x.ProgressTracker;let h="",u=!1;return c.addEventListener("progress",m=>{if(u)return;u=m.detail.progress===100;const g=Math.floor(m.detail.progress);h=m.detail.caption||h||"Running the Blueprint";const v=`${h.trim()} – ${g}%`;e.quiet||i(process.stdout,v,u)}),await b.compileBlueprint(s,{progress:c})}let o="";function i(s,c,h){c!==o&&(o=c,s.isTTY?(s.cursorTo(0),s.write(c),s.clearLine(1),h&&s.write(`
|
|
32
|
-
`)):s.write(`${c}
|
|
33
|
-
`))}e.quiet&&(p.logger.handlers=[]);const a=await n();let r,l=!1;return p.logger.log("Starting a PHP server..."),O({port:e.port,onBind:async(s,c)=>{const h=`http://127.0.0.1:${c}`;p.logger.log(`Setting up WordPress ${e.wp}`);let u;const m=new x.EmscriptenDownloadMonitor;if(!e.skipWordPressSetup){let w=!1;m.addEventListener("progress",y=>{if(w)return;const{loaded:A,total:k}=y.detail,R=Math.floor(Math.min(100,100*A/k));w=R===100,e.quiet||i(process.stdout,`Downloading WordPress ${R}%...`,w)}),u=await B.resolveWordPressRelease(e.wp)}p.logger.log(`Resolved WordPress release URL: ${u?.releaseUrl}`);const g=u&&f.join(W,`prebuilt-wp-content-for-wp-${u.version}.zip`),v=u?d.existsSync(g)?_(g):await D(u.releaseUrl,`${u.version}.zip`,m):void 0,N={WP_DEBUG:!0,WP_DEBUG_LOG:!0,WP_DEBUG_DISPLAY:!1};p.logger.log("Booting WordPress..."),r=await B.bootWordPress({siteUrl:h,createPhpRuntime:async()=>await H.loadNodeRuntime(a.versions.php,{followSymlinks:e.followSymlinks===!0}),wordPressZip:v,sqliteIntegrationPluginZip:e.skipSqliteSetup?void 0:V(m),sapiName:"cli",createFiles:{"/internal/shared/ca-bundle.crt":L.rootCertificates.join(`
|
|
34
|
-
`)},constants:N,phpIniEntries:{"openssl.cafile":"/internal/shared/ca-bundle.crt",allow_url_fopen:"1",disable_functions:""},hooks:{async beforeWordPressFiles(w){e.mountBeforeInstall&&I(w,e.mountBeforeInstall)}},cookieStore:!1}),p.logger.log("Booted!");const $=await r.getPrimaryPhp();try{if(u&&!e.mountBeforeInstall&&!d.existsSync(g)&&(p.logger.log("Caching preinstalled WordPress for the next boot..."),d.writeFileSync(g,await q.zipDirectory($,"/wordpress")),p.logger.log("Cached!")),e.mount&&I($,e.mount),l=!0,a){const{php:w,reap:y}=await r.processManager.acquirePHPInstance();try{p.logger.log("Running the Blueprint..."),await b.runBlueprintSteps(a,w),p.logger.log("Finished running the blueprint")}finally{y()}}return e.command==="build-snapshot"?(await t(e.outfile),p.logger.log(`WordPress exported to ${e.outfile}`),process.exit(0)):e.command==="run-blueprint"?(p.logger.log("Blueprint executed"),process.exit(0)):p.logger.log(`WordPress is running on ${h}`),{requestHandler:r,server:s}}catch(w){if(!e.debug)throw w;const y=$.readFileAsText(p.errorLogPath);throw new Error(y,{cause:w})}},async handleRequest(s){return l?await r.request(s):z.PHPResponse.forHttpCode(502,"WordPress is not ready yet")}})}exports.parseMountDirArguments=Q;exports.parseMountWithDelimiterArguments=K;exports.runCLI=X;
|
|
35
|
-
//# sourceMappingURL=run-cli-BSw9FKSW.cjs.map
|