@wp-playground/cli 1.2.3 → 2.0.0

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.
Files changed (49) hide show
  1. package/blueprints-BQYAZ9gc.js +9 -0
  2. package/blueprints-BQYAZ9gc.js.map +1 -0
  3. package/blueprints-DLntJtVr.js +9 -0
  4. package/blueprints-DLntJtVr.js.map +1 -0
  5. package/blueprints-ZBrY1bvK.cjs +2 -0
  6. package/blueprints-ZBrY1bvK.cjs.map +1 -0
  7. package/blueprints-v1/blueprints-v1-handler.d.ts +31 -0
  8. package/{worker-thread.d.ts → blueprints-v1/worker-thread-v1.d.ts} +4 -3
  9. package/blueprints-v2/blueprint-v2-declaration.d.ts +10 -0
  10. package/blueprints-v2/blueprints-v2-handler.d.ts +31 -0
  11. package/blueprints-v2/get-v2-runner.d.ts +1 -0
  12. package/{v2.d.ts → blueprints-v2/run-blueprint-v2.d.ts} +1 -11
  13. package/blueprints-v2/worker-thread-v2.d.ts +49 -0
  14. package/cli.cjs +1 -1
  15. package/cli.cjs.map +1 -1
  16. package/cli.js +2 -4
  17. package/cli.js.map +1 -1
  18. package/index.cjs +1 -1
  19. package/index.js +1 -1
  20. package/load-balancer.d.ts +3 -1
  21. package/package.json +11 -11
  22. package/run-cli-CY1lYIJH.js +674 -0
  23. package/run-cli-CY1lYIJH.js.map +1 -0
  24. package/run-cli-opqDVXKw.cjs +27 -0
  25. package/run-cli-opqDVXKw.cjs.map +1 -0
  26. package/run-cli.d.ts +27 -5
  27. package/{worker-thread-CYvRK9UX.js → worker-thread-v1-BTJIbQLy.js} +47 -44
  28. package/worker-thread-v1-BTJIbQLy.js.map +1 -0
  29. package/worker-thread-v1.cjs +3 -0
  30. package/worker-thread-v1.cjs.map +1 -0
  31. package/{worker-thread.js → worker-thread-v1.js} +34 -31
  32. package/worker-thread-v1.js.map +1 -0
  33. package/worker-thread-v2-Pfv6UYF4.js +429 -0
  34. package/worker-thread-v2-Pfv6UYF4.js.map +1 -0
  35. package/worker-thread-v2.cjs +92 -0
  36. package/worker-thread-v2.cjs.map +1 -0
  37. package/worker-thread-v2.js +432 -0
  38. package/worker-thread-v2.js.map +1 -0
  39. package/reportable-error.d.ts +0 -5
  40. package/run-cli-B5BfXxxJ.cjs +0 -24
  41. package/run-cli-B5BfXxxJ.cjs.map +0 -1
  42. package/run-cli-W9VNXESj.js +0 -586
  43. package/run-cli-W9VNXESj.js.map +0 -1
  44. package/worker-thread-CYvRK9UX.js.map +0 -1
  45. package/worker-thread.cjs +0 -3
  46. package/worker-thread.cjs.map +0 -1
  47. package/worker-thread.js.map +0 -1
  48. /package/{download.d.ts → blueprints-v1/download.d.ts} +0 -0
  49. /package/{server.d.ts → start-server.d.ts} +0 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"worker-thread-v2.cjs","sources":["../../../../packages/playground/cli/src/blueprints-v2/get-v2-runner.ts","../../../../packages/playground/cli/src/blueprints-v2/blueprint-v2-declaration.ts","../../../../packages/playground/cli/src/blueprints-v2/run-blueprint-v2.ts","../../../../packages/playground/cli/src/blueprints-v2/worker-thread-v2.ts"],"sourcesContent":["export async function getV2Runner(): Promise<File> {\n\tlet data = null;\n\n\t/**\n\t * Avoid a static dependency for now.\n\t *\n\t * Playground.wordpress.net does not need to know about the new runner yet, and\n\t * a static import would force it to download the v2 runner even when it's not needed.\n\t * This breaks the offline mode as the static assets list is not yet updated to accommodate\n\t * for the new .phar file.\n\t */\n\t// @ts-ignore\n\tconst v2_runner_url = (await import('../../public/blueprints.phar?url'))\n\t\t.default;\n\n\t/**\n\t * Only load the v2 runner via node:fs when running in Node.js.\n\t */\n\tif (typeof process !== 'undefined' && process.versions?.node) {\n\t\tlet path = v2_runner_url;\n\t\tif (path.startsWith('/@fs/')) {\n\t\t\tpath = path.slice('/@fs'.length);\n\t\t}\n\t\tif (path.startsWith('file://')) {\n\t\t\tpath = path.slice('file://'.length);\n\t\t}\n\n\t\tconst { readFile } = await import('node:fs/promises');\n\t\tdata = await readFile(path);\n\t} else {\n\t\tconst response = await fetch(v2_runner_url);\n\t\tdata = await response.blob();\n\t}\n\treturn new File([data], `blueprints.phar`, {\n\t\ttype: 'application/zip',\n\t});\n}\n","import type { BlueprintDeclaration } from '@wp-playground/blueprints';\n\nexport type BlueprintV2Declaration = string | BlueprintDeclaration | undefined;\nexport type ParsedBlueprintV2Declaration =\n\t| { type: 'inline-file'; contents: string }\n\t| { type: 'file-reference'; reference: string };\n\nexport function parseBlueprintDeclaration(\n\tsource: BlueprintV2Declaration | ParsedBlueprintV2Declaration\n): ParsedBlueprintV2Declaration {\n\tif (\n\t\ttypeof source === 'object' &&\n\t\t'type' in source &&\n\t\t['inline-file', 'file-reference'].includes(source.type)\n\t) {\n\t\treturn source;\n\t}\n\tif (!source) {\n\t\treturn {\n\t\t\ttype: 'inline-file',\n\t\t\tcontents: '{}',\n\t\t};\n\t}\n\tif (typeof source !== 'string') {\n\t\t// If source is an object, assume it's a Blueprint declaration object and\n\t\t// convert it to a JSON string.\n\t\treturn {\n\t\t\ttype: 'inline-file',\n\t\t\tcontents: JSON.stringify(source),\n\t\t};\n\t}\n\ttry {\n\t\t// If source is valid JSON, return it as is.\n\t\tJSON.parse(source);\n\t\treturn {\n\t\t\ttype: 'inline-file',\n\t\t\tcontents: source,\n\t\t};\n\t} catch {\n\t\treturn {\n\t\t\ttype: 'file-reference',\n\t\t\treference: source,\n\t\t};\n\t}\n}\n","import { logger } from '@php-wasm/logger';\nimport {\n\ttype StreamedPHPResponse,\n\ttype UniversalPHP,\n} from '@php-wasm/universal';\nimport { phpVar } from '@php-wasm/util';\nimport { getV2Runner } from './get-v2-runner';\nimport {\n\ttype BlueprintV2Declaration,\n\ttype ParsedBlueprintV2Declaration,\n\tparseBlueprintDeclaration,\n} from './blueprint-v2-declaration';\n\nexport type PHPExceptionDetails = {\n\texception: string;\n\tmessage: string;\n\tfile: string;\n\tline: number;\n\ttrace: string;\n};\n\nexport type BlueprintMessage =\n\t| { type: 'blueprint.target_resolved' }\n\t| { type: 'blueprint.progress'; progress: number; caption: string }\n\t| {\n\t\t\ttype: 'blueprint.error';\n\t\t\tmessage: string;\n\t\t\tdetails?: PHPExceptionDetails;\n\t }\n\t| { type: 'blueprint.completion'; message: string };\n\ninterface RunV2Options {\n\tphp: UniversalPHP;\n\tcliArgs?: string[];\n\tblueprint: BlueprintV2Declaration | ParsedBlueprintV2Declaration;\n\tblueprintOverrides?: {\n\t\twordpressVersion?: string;\n\t\tadditionalSteps?: any[];\n\t};\n\tonMessage?: (message: BlueprintMessage) => void | Promise<void>;\n}\n\nexport async function runBlueprintV2(\n\toptions: RunV2Options\n): Promise<StreamedPHPResponse> {\n\tconst cliArgs = options.cliArgs || [];\n\tfor (const arg of cliArgs) {\n\t\tif (arg.startsWith('--site-path=')) {\n\t\t\tthrow new Error(\n\t\t\t\t'The --site-path CLI argument must not be provided. In Playground, it is always set to /wordpress.'\n\t\t\t);\n\t\t}\n\t}\n\tcliArgs.push('--site-path=/wordpress');\n\n\t/**\n\t * Divergence from blueprints.phar – the default database engine is\n\t * SQLite. Why? Because in Playground we'll use SQLite far more often than\n\t * MySQL.\n\t */\n\tconst dbEngine = cliArgs.find((arg) => arg.startsWith('--db-engine='));\n\tif (!dbEngine) {\n\t\tcliArgs.push('--db-engine=sqlite');\n\t}\n\n\tconst php = options.php;\n\tconst onMessage = options?.onMessage || (() => {});\n\n\tconst file = await getV2Runner();\n\tphp.writeFile(\n\t\t'/tmp/blueprints.phar',\n\t\tnew Uint8Array(await file.arrayBuffer())\n\t);\n\n\tconst parsedBlueprintDeclaration = parseBlueprintDeclaration(\n\t\toptions.blueprint\n\t);\n\tlet blueprintReference = '';\n\tswitch (parsedBlueprintDeclaration.type) {\n\t\tcase 'inline-file':\n\t\t\tphp.writeFile(\n\t\t\t\t'/tmp/blueprint.json',\n\t\t\t\tparsedBlueprintDeclaration.contents\n\t\t\t);\n\t\t\tblueprintReference = '/tmp/blueprint.json';\n\t\t\tbreak;\n\t\tcase 'file-reference':\n\t\t\tblueprintReference = parsedBlueprintDeclaration.reference;\n\t\t\tbreak;\n\t}\n\n\tconst unbindMessageListener = await php.onMessage(async (message) => {\n\t\ttry {\n\t\t\tconst parsed =\n\t\t\t\ttypeof message === 'string' ? JSON.parse(message) : message;\n\t\t\tif (!parsed) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Make sure stdout and stderr data is emited before the next message is processed.\n\t\t\t// Otherwise a code such as `echo \"Hello\"; post_message_to_js(json_encode([\n\t\t\t// 'type' => 'blueprint.error',\n\t\t\t// 'message' => 'Error'\n\t\t\t// ]));`\n\t\t\t// might emit the message before we process the stdout data.\n\t\t\t//\n\t\t\t// This is a workaround to ensure that the message is emitted after the stdout data is processed.\n\t\t\t// @TODO: Remove this workaround. Find the root cause why stdout data is delayed and address it\n\t\t\t// directly.\n\t\t\tawait new Promise((resolve) => setTimeout(resolve, 0));\n\n\t\t\tif (parsed.type.startsWith('blueprint.')) {\n\t\t\t\tawait onMessage(parsed);\n\t\t\t}\n\t\t} catch (e) {\n\t\t\tlogger.warn('Failed to parse message as JSON:', message, e);\n\t\t}\n\t});\n\n\t/**\n\t * Prepare hooks, filters, and run the Blueprint:\n\t */\n\tawait php?.writeFile(\n\t\t'/tmp/run-blueprints.php',\n\t\t`<?php\nfunction playground_http_client_factory() {\n\treturn new WordPress\\\\HttpClient\\\\Client([\n\t\t// sockets transport is somehow faster than curl in Playground. Maybe\n\t\t// it uses a larger chunk size?\n\t\t'transport' => 'sockets',\n\t]);\n}\nplayground_add_filter('blueprint.http_client', 'playground_http_client_factory');\n\nfunction playground_on_blueprint_target_resolved() {\n\tpost_message_to_js(json_encode([\n\t\t'type' => 'blueprint.target_resolved',\n\t]));\n}\nplayground_add_filter('blueprint.target_resolved', 'playground_on_blueprint_target_resolved');\n\nplayground_add_filter('blueprint.resolved', 'playground_on_blueprint_resolved');\nfunction playground_on_blueprint_resolved($blueprint) {\n\t$additional_blueprint_steps = json_decode(${phpVar(\n\t\tJSON.stringify(options.blueprintOverrides?.additionalSteps || [])\n\t)}, true);\n\tif(count($additional_blueprint_steps) > 0) {\n\t\t$blueprint['additionalStepsAfterExecution'] = array_merge(\n\t\t\t$blueprint['additionalStepsAfterExecution'] ?? [],\n\t\t\t$additional_blueprint_steps\n\t\t);\n\t}\n\n\t$wp_version_override = json_decode(${phpVar(\n\t\tJSON.stringify(options.blueprintOverrides?.wordpressVersion || null)\n\t)}, true);\n\tif($wp_version_override) {\n\t\t$blueprint['wordpressVersion'] = $wp_version_override;\n\t}\n\treturn $blueprint;\n}\n\nfunction playground_progress_reporter() {\n\tclass PlaygroundProgressReporter implements ProgressReporter {\n\n\t\tpublic function reportProgress(float $progress, string $caption): void {\n\t\t\t$this->writeJsonMessage([\n\t\t\t\t'type' => 'blueprint.progress',\n\t\t\t\t'progress' => round($progress, 2),\n\t\t\t\t'caption' => $caption\n\t\t\t]);\n\t\t}\n\n\t\tpublic function reportError(string $message, ?Throwable $exception = null): void {\n\t\t\t$errorData = [\n\t\t\t\t'type' => 'blueprint.error',\n\t\t\t\t'message' => $message\n\t\t\t];\n\n\t\t\tif ($exception) {\n\t\t\t\t$errorData['details'] = [\n\t\t\t\t\t'exception' => get_class($exception),\n\t\t\t\t\t'message' => $exception->getMessage(),\n\t\t\t\t\t'file' => $exception->getFile(),\n\t\t\t\t\t'line' => $exception->getLine(),\n\t\t\t\t\t'trace' => $exception->getTraceAsString()\n\t\t\t\t];\n\t\t\t}\n\n\t\t\t$this->writeJsonMessage($errorData);\n\t\t}\n\n\t\tpublic function reportCompletion(string $message): void {\n\t\t\t$this->writeJsonMessage([\n\t\t\t\t'type' => 'blueprint.completion',\n\t\t\t\t'message' => $message\n\t\t\t]);\n\t\t}\n\n\t\tpublic function close(): void {}\n\n\t\tprivate function writeJsonMessage(array $data): void {\n\t\t\tpost_message_to_js(json_encode($data));\n\t\t}\n\t}\n\treturn new PlaygroundProgressReporter();\n}\nplayground_add_filter('blueprint.progress_reporter', 'playground_progress_reporter');\nrequire( \"/tmp/blueprints.phar\" );\n`\n\t);\n\tconst streamedResponse = (await (php as any).cli([\n\t\t'/internal/shared/bin/php',\n\t\t'/tmp/run-blueprints.php',\n\t\t'exec',\n\t\tblueprintReference,\n\t\t...cliArgs,\n\t])) as StreamedPHPResponse;\n\n\tstreamedResponse.finished.finally(unbindMessageListener);\n\n\treturn streamedResponse;\n}\n","import { errorLogPath } from '@php-wasm/logger';\nimport type { FileLockManager } from '@php-wasm/node';\nimport { createNodeFsMountHandler, loadNodeRuntime } from '@php-wasm/node';\nimport { EmscriptenDownloadMonitor } from '@php-wasm/progress';\nimport type { PHP, RemoteAPI, SupportedPHPVersion } from '@php-wasm/universal';\nimport {\n\tPHPExecutionFailureError,\n\tPHPResponse,\n\tPHPWorker,\n\tconsumeAPI,\n\tconsumeAPISync,\n\texposeAPI,\n\tsandboxedSpawnHandlerFactory,\n} from '@php-wasm/universal';\nimport { sprintf } from '@php-wasm/util';\nimport { type BlueprintMessage, runBlueprintV2 } from './run-blueprint-v2';\nimport {\n\ttype ParsedBlueprintV2Declaration,\n\ttype BlueprintV2Declaration,\n} from './blueprint-v2-declaration';\nimport { bootRequestHandler } from '@wp-playground/wordpress';\nimport { existsSync } from 'fs';\nimport path from 'path';\nimport { rootCertificates } from 'tls';\nimport { MessageChannel, type MessagePort, parentPort } from 'worker_threads';\nimport type { Mount } from '../mounts';\nimport { jspi } from 'wasm-feature-detect';\nimport { type RunCLIArgs } from '../run-cli';\n\nasync function mountResources(php: PHP, mounts: Mount[]) {\n\tfor (const mount of mounts) {\n\t\ttry {\n\t\t\tphp.mkdir(mount.vfsPath);\n\t\t\tawait php.mount(\n\t\t\t\tmount.vfsPath,\n\t\t\t\tcreateNodeFsMountHandler(mount.hostPath)\n\t\t\t);\n\t\t} catch {\n\t\t\toutput.stderr(\n\t\t\t\t`\\x1b[31m\\x1b[1mError mounting path ${mount.hostPath} at ${mount.vfsPath}\\x1b[0m\\n`\n\t\t\t);\n\t\t\tprocess.exit(1);\n\t\t}\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\n/**\n * Force TTY status to preserve ANSI control codes in the output.\n *\n * This script is spawned as `new Worker()` and process.stdout and process.stderr are\n * WritableWorkerStdio objects. By default, they strip ANSI control codes from the output\n * causing every progress bar update to be printed in a new line instead of updating the\n * same line.\n */\nObject.defineProperty(process.stdout, 'isTTY', { value: true });\nObject.defineProperty(process.stderr, 'isTTY', { value: true });\n\n/**\n * Output writer that ensures that progress bars are not printed on the same line as other output.\n */\nconst output = {\n\tlastWriteWasProgress: false,\n\tprogress(data: string) {\n\t\tif (!process.stdout.isTTY) {\n\t\t\t// eslint-disable-next-line no-console\n\t\t\tconsole.log(data);\n\t\t} else {\n\t\t\tif (!output.lastWriteWasProgress) {\n\t\t\t\tprocess.stdout.write('\\n');\n\t\t\t}\n\t\t\tprocess.stdout.write('\\r\\x1b[K' + data);\n\t\t\toutput.lastWriteWasProgress = true;\n\t\t}\n\t},\n\tstdout(data: string) {\n\t\tif (output.lastWriteWasProgress) {\n\t\t\tprocess.stdout.write('\\n');\n\t\t\toutput.lastWriteWasProgress = false;\n\t\t}\n\t\tprocess.stdout.write(data);\n\t},\n\tstderr(data: string) {\n\t\tif (output.lastWriteWasProgress) {\n\t\t\tprocess.stdout.write('\\n');\n\t\t\toutput.lastWriteWasProgress = false;\n\t\t}\n\t\tprocess.stderr.write(data);\n\t},\n};\n\nexport type WorkerBootArgs = RunCLIArgs & {\n\tphp: SupportedPHPVersion;\n\tsiteUrl: string;\n\tfirstProcessId: number;\n\tprocessIdSpaceLength: number;\n\ttrace: boolean;\n\tblueprint: BlueprintV2Declaration | ParsedBlueprintV2Declaration;\n};\n\ntype WorkerRunBlueprintArgs = RunCLIArgs & {\n\tsiteUrl: string;\n\tblueprint: BlueprintV2Declaration | ParsedBlueprintV2Declaration;\n};\n\ninterface WorkerBootRequestHandlerOptions {\n\tsiteUrl: string;\n\tphp: SupportedPHPVersion;\n\tallow?: string;\n\tfirstProcessId: number;\n\tprocessIdSpaceLength: number;\n\ttrace: boolean;\n}\n\nexport class PlaygroundCliBlueprintV2Worker extends PHPWorker {\n\tbooted = false;\n\tfileLockManager: RemoteAPI<FileLockManager> | FileLockManager | undefined;\n\n\tconstructor(monitor: EmscriptenDownloadMonitor) {\n\t\tsuper(undefined, monitor);\n\t}\n\n\t/**\n\t * Call this method before boot() to use file locking.\n\t *\n\t * This method is separate from boot() to simplify the related Comlink.transferHandlers\n\t * setup – if an argument is a MessagePort, we're transferring it, not copying it.\n\t *\n\t * @see comlink-sync.ts\n\t * @see phpwasm-emscripten-library-file-locking-for-node.js\n\t */\n\tasync useFileLockManager(port: MessagePort) {\n\t\tif (await jspi()) {\n\t\t\t/**\n\t\t\t * If JSPI is available, php.js supports both synchronous and asynchronous locking syscalls.\n\t\t\t * Web browsers, however, only support asynchronous message passing so let's use the\n\t\t\t * asynchronous API. Every method call will return a promise.\n\t\t\t *\n\t\t\t * @see comlink-sync.ts\n\t\t\t * @see phpwasm-emscripten-library-file-locking-for-node.js\n\t\t\t */\n\t\t\tthis.fileLockManager = consumeAPI<FileLockManager>(port);\n\t\t} else {\n\t\t\t/**\n\t\t\t * If JSPI is not available, php.js only supports synchronous locking syscalls.\n\t\t\t * Let's use the synchronous API. Every method call will block this thread\n\t\t\t * until the result is available.\n\t\t\t *\n\t\t\t * @see comlink-sync.ts\n\t\t\t * @see phpwasm-emscripten-library-file-locking-for-node.js\n\t\t\t */\n\t\t\tthis.fileLockManager = await consumeAPISync<FileLockManager>(port);\n\t\t}\n\t}\n\n\tasync bootAsPrimaryWorker(args: WorkerBootArgs) {\n\t\tawait this.bootRequestHandler(args);\n\n\t\tconst primaryPhp = this.__internal_getPHP()!;\n\t\tawait mountResources(primaryPhp, args['mount-before-install'] || []);\n\n\t\tif (args.mode === 'mount-only') {\n\t\t\tawait mountResources(primaryPhp, args.mount || []);\n\t\t\treturn;\n\t\t}\n\n\t\tawait this.runBlueprintV2(args);\n\t}\n\n\tasync bootAsSecondaryWorker(args: WorkerBootArgs) {\n\t\tawait this.bootRequestHandler(args);\n\t\tconst primaryPhp = this.__internal_getPHP()!;\n\t\t// When secondary workers are spawned, WordPress is already installed.\n\t\tawait mountResources(primaryPhp, args['mount-before-install'] || []);\n\t\tawait mountResources(primaryPhp, args.mount || []);\n\t}\n\n\tasync runBlueprintV2(args: WorkerRunBlueprintArgs) {\n\t\tconst requestHandler = this.__internal_getRequestHandler()!;\n\t\tconst { php, reap } =\n\t\t\tawait requestHandler.processManager.acquirePHPInstance({\n\t\t\t\tconsiderPrimary: false,\n\t\t\t});\n\n\t\t// Mount the current working directory to the PHP runtime for the purposes of\n\t\t// Blueprint resolution.\n\t\tconst primaryPhp = this.__internal_getPHP()!;\n\t\tlet unmountCwd = () => {};\n\t\tif (typeof args.blueprint === 'string') {\n\t\t\tconst blueprintPath = path.resolve(process.cwd(), args.blueprint);\n\t\t\tif (existsSync(blueprintPath)) {\n\t\t\t\tprimaryPhp.mkdir('/internal/shared/cwd');\n\t\t\t\tunmountCwd = await primaryPhp.mount(\n\t\t\t\t\t'/internal/shared/cwd',\n\t\t\t\t\tcreateNodeFsMountHandler(path.dirname(blueprintPath))\n\t\t\t\t);\n\t\t\t\targs.blueprint = path.join(\n\t\t\t\t\t'/internal/shared/cwd',\n\t\t\t\t\tpath.basename(args.blueprint)\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\ttry {\n\t\t\tconst cliArgsToPass: (keyof WorkerRunBlueprintArgs)[] = [\n\t\t\t\t'mode',\n\t\t\t\t'db-engine',\n\t\t\t\t'db-host',\n\t\t\t\t'db-user',\n\t\t\t\t'db-pass',\n\t\t\t\t'db-name',\n\t\t\t\t'db-path',\n\t\t\t\t'truncate-new-site-directory',\n\t\t\t\t'allow',\n\t\t\t];\n\t\t\tconst cliArgs = cliArgsToPass\n\t\t\t\t.filter((arg) => arg in args)\n\t\t\t\t.map((arg) => `--${arg}=${args[arg]}`);\n\t\t\tcliArgs.push(`--site-url=${args.siteUrl}`);\n\n\t\t\tlet afterBlueprintTargetResolvedCalled = false;\n\n\t\t\tconst streamedResponse = await runBlueprintV2({\n\t\t\t\tphp,\n\t\t\t\tblueprint: args.blueprint,\n\t\t\t\tblueprintOverrides: {\n\t\t\t\t\tadditionalSteps: args['additional-blueprint-steps'],\n\t\t\t\t\twordpressVersion: args.wp,\n\t\t\t\t},\n\t\t\t\tcliArgs,\n\t\t\t\tonMessage: async (message: BlueprintMessage) => {\n\t\t\t\t\tswitch (message.type) {\n\t\t\t\t\t\tcase 'blueprint.target_resolved': {\n\t\t\t\t\t\t\tif (!afterBlueprintTargetResolvedCalled) {\n\t\t\t\t\t\t\t\tawait mountResources(\n\t\t\t\t\t\t\t\t\tprimaryPhp,\n\t\t\t\t\t\t\t\t\targs.mount || []\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\tafterBlueprintTargetResolvedCalled = true;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tcase 'blueprint.progress': {\n\t\t\t\t\t\t\tconst progressMessage = `${message.caption.trim()} – ${message.progress.toFixed(\n\t\t\t\t\t\t\t\t2\n\t\t\t\t\t\t\t)}%`;\n\t\t\t\t\t\t\toutput.progress(progressMessage);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tcase 'blueprint.error': {\n\t\t\t\t\t\t\tconst red = '\\x1b[31m';\n\t\t\t\t\t\t\tconst bold = '\\x1b[1m';\n\t\t\t\t\t\t\tconst reset = '\\x1b[0m';\n\t\t\t\t\t\t\tif (args.debug && message.details) {\n\t\t\t\t\t\t\t\toutput.stderr(\n\t\t\t\t\t\t\t\t\t`${red}${bold}Fatal error:${reset} Uncaught ${message.details.exception}: ${message.details.message}\\n` +\n\t\t\t\t\t\t\t\t\t\t` at ${message.details.file}:${message.details.line}\\n` +\n\t\t\t\t\t\t\t\t\t\t(message.details.trace\n\t\t\t\t\t\t\t\t\t\t\t? message.details.trace + '\\n'\n\t\t\t\t\t\t\t\t\t\t\t: '')\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\toutput.stderr(\n\t\t\t\t\t\t\t\t\t`${red}${bold}Error:${reset} ${message.message}\\n`\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tbreak;\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\t/**\n\t\t\t * When we're debugging, every bit of information matters – let's immediately output\n\t\t\t * everything we get from the PHP output streams.\n\t\t\t */\n\t\t\tif (args.debug) {\n\t\t\t\tstreamedResponse!.stdout.pipeTo(\n\t\t\t\t\tnew WritableStream({\n\t\t\t\t\t\twrite(chunk) {\n\t\t\t\t\t\t\tprocess.stdout.write(chunk);\n\t\t\t\t\t\t},\n\t\t\t\t\t})\n\t\t\t\t);\n\t\t\t\tstreamedResponse!.stderr.pipeTo(\n\t\t\t\t\tnew WritableStream({\n\t\t\t\t\t\twrite(chunk) {\n\t\t\t\t\t\t\tprocess.stderr.write(chunk);\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\tawait streamedResponse!.finished;\n\t\t\tif ((await streamedResponse!.exitCode) !== 0) {\n\t\t\t\t// exitCode != 1 means the blueprint execution failed. Let's throw an error.\n\t\t\t\t// and clean up.\n\t\t\t\tconst syncResponse = await PHPResponse.fromStreamedResponse(\n\t\t\t\t\tstreamedResponse\n\t\t\t\t);\n\t\t\t\tthrow new PHPExecutionFailureError(\n\t\t\t\t\t`PHP.run() failed with exit code ${syncResponse.exitCode}.`,\n\t\t\t\t\tsyncResponse,\n\t\t\t\t\t'request'\n\t\t\t\t);\n\t\t\t}\n\t\t} catch (error) {\n\t\t\t// Capture the PHP error log details to provide more context for debugging.\n\t\t\tlet phpLogs = '';\n\t\t\ttry {\n\t\t\t\t// @TODO: Don't assume errorLogPath starts with /wordpress/\n\t\t\t\t// ...or maybe we can assume that in Playground CLI?\n\t\t\t\tphpLogs = php.readFileAsText(errorLogPath);\n\t\t\t} catch {\n\t\t\t\t// Ignore errors reading the PHP error log.\n\t\t\t}\n\t\t\t(error as any).phpLogs = phpLogs;\n\t\t\tthrow error;\n\t\t} finally {\n\t\t\treap();\n\t\t\tunmountCwd();\n\t\t}\n\t}\n\n\tasync bootRequestHandler({\n\t\tsiteUrl,\n\t\tallow,\n\t\tphp,\n\t\tfirstProcessId,\n\t\tprocessIdSpaceLength,\n\t\ttrace,\n\t}: WorkerBootRequestHandlerOptions) {\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\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 bootRequestHandler({\n\t\t\t\tsiteUrl,\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(php!, {\n\t\t\t\t\t\temscriptenOptions: {\n\t\t\t\t\t\t\tfileLockManager: this.fileLockManager!,\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\tENV: {\n\t\t\t\t\t\t\t\tDOCROOT: '/wordpress',\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tfollowSymlinks: allow?.includes('follow-symlinks'),\n\t\t\t\t\t});\n\t\t\t\t},\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},\n\t\t\t\tcookieStore: false,\n\t\t\t\tspawnHandler: sandboxedSpawnHandlerFactory,\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\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 phpChannel = new MessageChannel();\n\nconst [setApiReady, setAPIError] = exposeAPI(\n\tnew PlaygroundCliBlueprintV2Worker(new EmscriptenDownloadMonitor()),\n\tundefined,\n\tphpChannel.port1\n);\n\nparentPort!.postMessage(\n\t{\n\t\tcommand: 'worker-script-initialized',\n\t\tphpPort: phpChannel.port2,\n\t},\n\t[phpChannel.port2 as any]\n);\n"],"names":["getV2Runner","data","v2_runner_url","path","readFile","parseBlueprintDeclaration","source","runBlueprintV2","options","cliArgs","arg","php","onMessage","file","parsedBlueprintDeclaration","blueprintReference","unbindMessageListener","message","parsed","resolve","e","logger","phpVar","streamedResponse","mountResources","mounts","mount","createNodeFsMountHandler","output","tracePhpWasm","processId","format","args","sprintf","PlaygroundCliBlueprintV2Worker","PHPWorker","monitor","port","jspi","consumeAPI","consumeAPISync","primaryPhp","requestHandler","reap","unmountCwd","blueprintPath","existsSync","afterBlueprintTargetResolvedCalled","progressMessage","red","bold","reset","chunk","syncResponse","PHPResponse","PHPExecutionFailureError","error","phpLogs","errorLogPath","siteUrl","allow","firstProcessId","processIdSpaceLength","trace","nextProcessId","lastProcessId","constants","bootRequestHandler","loadNodeRuntime","rootCertificates","sandboxedSpawnHandlerFactory","setApiReady","setAPIError","phpChannel","MessageChannel","exposeAPI","EmscriptenDownloadMonitor","parentPort"],"mappings":"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"}
@@ -0,0 +1,432 @@
1
+ import { logger as P, errorLogPath as $ } from "@php-wasm/logger";
2
+ import { createNodeFsMountHandler as _, loadNodeRuntime as v } from "@php-wasm/node";
3
+ import { EmscriptenDownloadMonitor as x } from "@php-wasm/progress";
4
+ import { exposeAPI as W, PHPWorker as S, consumeAPI as k, consumeAPISync as M, PHPResponse as R, PHPExecutionFailureError as H, sandboxedSpawnHandlerFactory as A } from "@php-wasm/universal";
5
+ import { phpVar as y, sprintf as B } from "@php-wasm/util";
6
+ import { bootRequestHandler as E } from "@wp-playground/wordpress";
7
+ import { existsSync as T } from "fs";
8
+ import w from "path";
9
+ import { rootCertificates as F } from "tls";
10
+ import { MessageChannel as O, parentPort as j } from "worker_threads";
11
+ import { jspi as C } from "wasm-feature-detect";
12
+ async function L() {
13
+ let t = null;
14
+ const e = (await import("./blueprints-BQYAZ9gc.js")).default;
15
+ if (typeof process < "u" && process.versions?.node) {
16
+ let s = e;
17
+ s.startsWith("/@fs/") && (s = s.slice(4)), s.startsWith("file://") && (s = s.slice(7));
18
+ const { readFile: o } = await import("node:fs/promises");
19
+ t = await o(s);
20
+ } else
21
+ t = await (await fetch(e)).blob();
22
+ return new File([t], "blueprints.phar", {
23
+ type: "application/zip"
24
+ });
25
+ }
26
+ function q(t) {
27
+ if (typeof t == "object" && "type" in t && ["inline-file", "file-reference"].includes(t.type))
28
+ return t;
29
+ if (!t)
30
+ return {
31
+ type: "inline-file",
32
+ contents: "{}"
33
+ };
34
+ if (typeof t != "string")
35
+ return {
36
+ type: "inline-file",
37
+ contents: JSON.stringify(t)
38
+ };
39
+ try {
40
+ return JSON.parse(t), {
41
+ type: "inline-file",
42
+ contents: t
43
+ };
44
+ } catch {
45
+ return {
46
+ type: "file-reference",
47
+ reference: t
48
+ };
49
+ }
50
+ }
51
+ async function D(t) {
52
+ const e = t.cliArgs || [];
53
+ for (const i of e)
54
+ if (i.startsWith("--site-path="))
55
+ throw new Error(
56
+ "The --site-path CLI argument must not be provided. In Playground, it is always set to /wordpress."
57
+ );
58
+ e.push("--site-path=/wordpress"), e.find((i) => i.startsWith("--db-engine=")) || e.push("--db-engine=sqlite");
59
+ const o = t.php, u = t?.onMessage || (() => {
60
+ }), f = await L();
61
+ o.writeFile(
62
+ "/tmp/blueprints.phar",
63
+ new Uint8Array(await f.arrayBuffer())
64
+ );
65
+ const c = q(
66
+ t.blueprint
67
+ );
68
+ let n = "";
69
+ switch (c.type) {
70
+ case "inline-file":
71
+ o.writeFile(
72
+ "/tmp/blueprint.json",
73
+ c.contents
74
+ ), n = "/tmp/blueprint.json";
75
+ break;
76
+ case "file-reference":
77
+ n = c.reference;
78
+ break;
79
+ }
80
+ const l = await o.onMessage(async (i) => {
81
+ try {
82
+ const r = typeof i == "string" ? JSON.parse(i) : i;
83
+ if (!r)
84
+ return;
85
+ await new Promise((d) => setTimeout(d, 0)), r.type.startsWith("blueprint.") && await u(r);
86
+ } catch (r) {
87
+ P.warn("Failed to parse message as JSON:", i, r);
88
+ }
89
+ });
90
+ await o?.writeFile(
91
+ "/tmp/run-blueprints.php",
92
+ `<?php
93
+ function playground_http_client_factory() {
94
+ return new WordPress\\HttpClient\\Client([
95
+ // sockets transport is somehow faster than curl in Playground. Maybe
96
+ // it uses a larger chunk size?
97
+ 'transport' => 'sockets',
98
+ ]);
99
+ }
100
+ playground_add_filter('blueprint.http_client', 'playground_http_client_factory');
101
+
102
+ function playground_on_blueprint_target_resolved() {
103
+ post_message_to_js(json_encode([
104
+ 'type' => 'blueprint.target_resolved',
105
+ ]));
106
+ }
107
+ playground_add_filter('blueprint.target_resolved', 'playground_on_blueprint_target_resolved');
108
+
109
+ playground_add_filter('blueprint.resolved', 'playground_on_blueprint_resolved');
110
+ function playground_on_blueprint_resolved($blueprint) {
111
+ $additional_blueprint_steps = json_decode(${y(
112
+ JSON.stringify(t.blueprintOverrides?.additionalSteps || [])
113
+ )}, true);
114
+ if(count($additional_blueprint_steps) > 0) {
115
+ $blueprint['additionalStepsAfterExecution'] = array_merge(
116
+ $blueprint['additionalStepsAfterExecution'] ?? [],
117
+ $additional_blueprint_steps
118
+ );
119
+ }
120
+
121
+ $wp_version_override = json_decode(${y(
122
+ JSON.stringify(t.blueprintOverrides?.wordpressVersion || null)
123
+ )}, true);
124
+ if($wp_version_override) {
125
+ $blueprint['wordpressVersion'] = $wp_version_override;
126
+ }
127
+ return $blueprint;
128
+ }
129
+
130
+ function playground_progress_reporter() {
131
+ class PlaygroundProgressReporter implements ProgressReporter {
132
+
133
+ public function reportProgress(float $progress, string $caption): void {
134
+ $this->writeJsonMessage([
135
+ 'type' => 'blueprint.progress',
136
+ 'progress' => round($progress, 2),
137
+ 'caption' => $caption
138
+ ]);
139
+ }
140
+
141
+ public function reportError(string $message, ?Throwable $exception = null): void {
142
+ $errorData = [
143
+ 'type' => 'blueprint.error',
144
+ 'message' => $message
145
+ ];
146
+
147
+ if ($exception) {
148
+ $errorData['details'] = [
149
+ 'exception' => get_class($exception),
150
+ 'message' => $exception->getMessage(),
151
+ 'file' => $exception->getFile(),
152
+ 'line' => $exception->getLine(),
153
+ 'trace' => $exception->getTraceAsString()
154
+ ];
155
+ }
156
+
157
+ $this->writeJsonMessage($errorData);
158
+ }
159
+
160
+ public function reportCompletion(string $message): void {
161
+ $this->writeJsonMessage([
162
+ 'type' => 'blueprint.completion',
163
+ 'message' => $message
164
+ ]);
165
+ }
166
+
167
+ public function close(): void {}
168
+
169
+ private function writeJsonMessage(array $data): void {
170
+ post_message_to_js(json_encode($data));
171
+ }
172
+ }
173
+ return new PlaygroundProgressReporter();
174
+ }
175
+ playground_add_filter('blueprint.progress_reporter', 'playground_progress_reporter');
176
+ require( "/tmp/blueprints.phar" );
177
+ `
178
+ );
179
+ const a = await o.cli([
180
+ "/internal/shared/bin/php",
181
+ "/tmp/run-blueprints.php",
182
+ "exec",
183
+ n,
184
+ ...e
185
+ ]);
186
+ return a.finished.finally(l), a;
187
+ }
188
+ async function h(t, e) {
189
+ for (const s of e)
190
+ try {
191
+ t.mkdir(s.vfsPath), await t.mount(
192
+ s.vfsPath,
193
+ _(s.hostPath)
194
+ );
195
+ } catch {
196
+ p.stderr(
197
+ `\x1B[31m\x1B[1mError mounting path ${s.hostPath} at ${s.vfsPath}\x1B[0m
198
+ `
199
+ ), process.exit(1);
200
+ }
201
+ }
202
+ function I(t, e, ...s) {
203
+ console.log(
204
+ performance.now().toFixed(6).padStart(15, "0"),
205
+ t.toString().padStart(16, "0"),
206
+ B(e, ...s)
207
+ );
208
+ }
209
+ Object.defineProperty(process.stdout, "isTTY", { value: !0 });
210
+ Object.defineProperty(process.stderr, "isTTY", { value: !0 });
211
+ const p = {
212
+ lastWriteWasProgress: !1,
213
+ progress(t) {
214
+ process.stdout.isTTY ? (p.lastWriteWasProgress || process.stdout.write(`
215
+ `), process.stdout.write("\r\x1B[K" + t), p.lastWriteWasProgress = !0) : console.log(t);
216
+ },
217
+ stdout(t) {
218
+ p.lastWriteWasProgress && (process.stdout.write(`
219
+ `), p.lastWriteWasProgress = !1), process.stdout.write(t);
220
+ },
221
+ stderr(t) {
222
+ p.lastWriteWasProgress && (process.stdout.write(`
223
+ `), p.lastWriteWasProgress = !1), process.stderr.write(t);
224
+ }
225
+ };
226
+ class J extends S {
227
+ constructor(e) {
228
+ super(void 0, e), this.booted = !1;
229
+ }
230
+ /**
231
+ * Call this method before boot() to use file locking.
232
+ *
233
+ * This method is separate from boot() to simplify the related Comlink.transferHandlers
234
+ * setup – if an argument is a MessagePort, we're transferring it, not copying it.
235
+ *
236
+ * @see comlink-sync.ts
237
+ * @see phpwasm-emscripten-library-file-locking-for-node.js
238
+ */
239
+ async useFileLockManager(e) {
240
+ await C() ? this.fileLockManager = k(e) : this.fileLockManager = await M(e);
241
+ }
242
+ async bootAsPrimaryWorker(e) {
243
+ await this.bootRequestHandler(e);
244
+ const s = this.__internal_getPHP();
245
+ if (await h(s, e["mount-before-install"] || []), e.mode === "mount-only") {
246
+ await h(s, e.mount || []);
247
+ return;
248
+ }
249
+ await this.runBlueprintV2(e);
250
+ }
251
+ async bootAsSecondaryWorker(e) {
252
+ await this.bootRequestHandler(e);
253
+ const s = this.__internal_getPHP();
254
+ await h(s, e["mount-before-install"] || []), await h(s, e.mount || []);
255
+ }
256
+ async runBlueprintV2(e) {
257
+ const s = this.__internal_getRequestHandler(), { php: o, reap: u } = await s.processManager.acquirePHPInstance({
258
+ considerPrimary: !1
259
+ }), f = this.__internal_getPHP();
260
+ let c = () => {
261
+ };
262
+ if (typeof e.blueprint == "string") {
263
+ const n = w.resolve(process.cwd(), e.blueprint);
264
+ T(n) && (f.mkdir("/internal/shared/cwd"), c = await f.mount(
265
+ "/internal/shared/cwd",
266
+ _(w.dirname(n))
267
+ ), e.blueprint = w.join(
268
+ "/internal/shared/cwd",
269
+ w.basename(e.blueprint)
270
+ ));
271
+ }
272
+ try {
273
+ const l = [
274
+ "mode",
275
+ "db-engine",
276
+ "db-host",
277
+ "db-user",
278
+ "db-pass",
279
+ "db-name",
280
+ "db-path",
281
+ "truncate-new-site-directory",
282
+ "allow"
283
+ ].filter((r) => r in e).map((r) => `--${r}=${e[r]}`);
284
+ l.push(`--site-url=${e.siteUrl}`);
285
+ let a = !1;
286
+ const i = await D({
287
+ php: o,
288
+ blueprint: e.blueprint,
289
+ blueprintOverrides: {
290
+ additionalSteps: e["additional-blueprint-steps"],
291
+ wordpressVersion: e.wp
292
+ },
293
+ cliArgs: l,
294
+ onMessage: async (r) => {
295
+ switch (r.type) {
296
+ case "blueprint.target_resolved": {
297
+ a || (await h(
298
+ f,
299
+ e.mount || []
300
+ ), a = !0);
301
+ break;
302
+ }
303
+ case "blueprint.progress": {
304
+ const d = `${r.caption.trim()} – ${r.progress.toFixed(
305
+ 2
306
+ )}%`;
307
+ p.progress(d);
308
+ break;
309
+ }
310
+ case "blueprint.error": {
311
+ const d = "\x1B[31m", g = "\x1B[1m", m = "\x1B[0m";
312
+ e.debug && r.details ? p.stderr(
313
+ `${d}${g}Fatal error:${m} Uncaught ${r.details.exception}: ${r.details.message}
314
+ at ${r.details.file}:${r.details.line}
315
+ ` + (r.details.trace ? r.details.trace + `
316
+ ` : "")
317
+ ) : p.stderr(
318
+ `${d}${g}Error:${m} ${r.message}
319
+ `
320
+ );
321
+ break;
322
+ }
323
+ }
324
+ }
325
+ });
326
+ if (e.debug && (i.stdout.pipeTo(
327
+ new WritableStream({
328
+ write(r) {
329
+ process.stdout.write(r);
330
+ }
331
+ })
332
+ ), i.stderr.pipeTo(
333
+ new WritableStream({
334
+ write(r) {
335
+ process.stderr.write(r);
336
+ }
337
+ })
338
+ )), await i.finished, await i.exitCode !== 0) {
339
+ const r = await R.fromStreamedResponse(
340
+ i
341
+ );
342
+ throw new H(
343
+ `PHP.run() failed with exit code ${r.exitCode}.`,
344
+ r,
345
+ "request"
346
+ );
347
+ }
348
+ } catch (n) {
349
+ let l = "";
350
+ try {
351
+ l = o.readFileAsText($);
352
+ } catch {
353
+ }
354
+ throw n.phpLogs = l, n;
355
+ } finally {
356
+ u(), c();
357
+ }
358
+ }
359
+ async bootRequestHandler({
360
+ siteUrl: e,
361
+ allow: s,
362
+ php: o,
363
+ firstProcessId: u,
364
+ processIdSpaceLength: f,
365
+ trace: c
366
+ }) {
367
+ if (this.booted)
368
+ throw new Error("Playground already booted");
369
+ this.booted = !0;
370
+ let n = u;
371
+ const l = u + f - 1;
372
+ try {
373
+ const a = {
374
+ WP_DEBUG: !0,
375
+ WP_DEBUG_LOG: !0,
376
+ WP_DEBUG_DISPLAY: !1
377
+ }, i = await E({
378
+ siteUrl: e,
379
+ createPhpRuntime: async () => {
380
+ const d = n;
381
+ return n < l ? n++ : n = u, await v(o, {
382
+ emscriptenOptions: {
383
+ fileLockManager: this.fileLockManager,
384
+ processId: d,
385
+ trace: c ? I : void 0,
386
+ ENV: {
387
+ DOCROOT: "/wordpress"
388
+ }
389
+ },
390
+ followSymlinks: s?.includes("follow-symlinks")
391
+ });
392
+ },
393
+ sapiName: "cli",
394
+ createFiles: {
395
+ "/internal/shared/ca-bundle.crt": F.join(`
396
+ `)
397
+ },
398
+ constants: a,
399
+ phpIniEntries: {
400
+ "openssl.cafile": "/internal/shared/ca-bundle.crt"
401
+ },
402
+ cookieStore: !1,
403
+ spawnHandler: A
404
+ });
405
+ this.__internal_setRequestHandler(i);
406
+ const r = await i.getPrimaryPhp();
407
+ await this.setPrimaryPHP(r), N();
408
+ } catch (a) {
409
+ throw V(a), a;
410
+ }
411
+ }
412
+ // Provide a named disposal method that can be invoked via comlink.
413
+ async dispose() {
414
+ await this[Symbol.asyncDispose]();
415
+ }
416
+ }
417
+ const b = new O(), [N, V] = W(
418
+ new J(new x()),
419
+ void 0,
420
+ b.port1
421
+ );
422
+ j.postMessage(
423
+ {
424
+ command: "worker-script-initialized",
425
+ phpPort: b.port2
426
+ },
427
+ [b.port2]
428
+ );
429
+ export {
430
+ J as PlaygroundCliBlueprintV2Worker
431
+ };
432
+ //# sourceMappingURL=worker-thread-v2.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"worker-thread-v2.js","sources":["../../../../packages/playground/cli/src/blueprints-v2/get-v2-runner.ts","../../../../packages/playground/cli/src/blueprints-v2/blueprint-v2-declaration.ts","../../../../packages/playground/cli/src/blueprints-v2/run-blueprint-v2.ts","../../../../packages/playground/cli/src/blueprints-v2/worker-thread-v2.ts"],"sourcesContent":["export async function getV2Runner(): Promise<File> {\n\tlet data = null;\n\n\t/**\n\t * Avoid a static dependency for now.\n\t *\n\t * Playground.wordpress.net does not need to know about the new runner yet, and\n\t * a static import would force it to download the v2 runner even when it's not needed.\n\t * This breaks the offline mode as the static assets list is not yet updated to accommodate\n\t * for the new .phar file.\n\t */\n\t// @ts-ignore\n\tconst v2_runner_url = (await import('../../public/blueprints.phar?url'))\n\t\t.default;\n\n\t/**\n\t * Only load the v2 runner via node:fs when running in Node.js.\n\t */\n\tif (typeof process !== 'undefined' && process.versions?.node) {\n\t\tlet path = v2_runner_url;\n\t\tif (path.startsWith('/@fs/')) {\n\t\t\tpath = path.slice('/@fs'.length);\n\t\t}\n\t\tif (path.startsWith('file://')) {\n\t\t\tpath = path.slice('file://'.length);\n\t\t}\n\n\t\tconst { readFile } = await import('node:fs/promises');\n\t\tdata = await readFile(path);\n\t} else {\n\t\tconst response = await fetch(v2_runner_url);\n\t\tdata = await response.blob();\n\t}\n\treturn new File([data], `blueprints.phar`, {\n\t\ttype: 'application/zip',\n\t});\n}\n","import type { BlueprintDeclaration } from '@wp-playground/blueprints';\n\nexport type BlueprintV2Declaration = string | BlueprintDeclaration | undefined;\nexport type ParsedBlueprintV2Declaration =\n\t| { type: 'inline-file'; contents: string }\n\t| { type: 'file-reference'; reference: string };\n\nexport function parseBlueprintDeclaration(\n\tsource: BlueprintV2Declaration | ParsedBlueprintV2Declaration\n): ParsedBlueprintV2Declaration {\n\tif (\n\t\ttypeof source === 'object' &&\n\t\t'type' in source &&\n\t\t['inline-file', 'file-reference'].includes(source.type)\n\t) {\n\t\treturn source;\n\t}\n\tif (!source) {\n\t\treturn {\n\t\t\ttype: 'inline-file',\n\t\t\tcontents: '{}',\n\t\t};\n\t}\n\tif (typeof source !== 'string') {\n\t\t// If source is an object, assume it's a Blueprint declaration object and\n\t\t// convert it to a JSON string.\n\t\treturn {\n\t\t\ttype: 'inline-file',\n\t\t\tcontents: JSON.stringify(source),\n\t\t};\n\t}\n\ttry {\n\t\t// If source is valid JSON, return it as is.\n\t\tJSON.parse(source);\n\t\treturn {\n\t\t\ttype: 'inline-file',\n\t\t\tcontents: source,\n\t\t};\n\t} catch {\n\t\treturn {\n\t\t\ttype: 'file-reference',\n\t\t\treference: source,\n\t\t};\n\t}\n}\n","import { logger } from '@php-wasm/logger';\nimport {\n\ttype StreamedPHPResponse,\n\ttype UniversalPHP,\n} from '@php-wasm/universal';\nimport { phpVar } from '@php-wasm/util';\nimport { getV2Runner } from './get-v2-runner';\nimport {\n\ttype BlueprintV2Declaration,\n\ttype ParsedBlueprintV2Declaration,\n\tparseBlueprintDeclaration,\n} from './blueprint-v2-declaration';\n\nexport type PHPExceptionDetails = {\n\texception: string;\n\tmessage: string;\n\tfile: string;\n\tline: number;\n\ttrace: string;\n};\n\nexport type BlueprintMessage =\n\t| { type: 'blueprint.target_resolved' }\n\t| { type: 'blueprint.progress'; progress: number; caption: string }\n\t| {\n\t\t\ttype: 'blueprint.error';\n\t\t\tmessage: string;\n\t\t\tdetails?: PHPExceptionDetails;\n\t }\n\t| { type: 'blueprint.completion'; message: string };\n\ninterface RunV2Options {\n\tphp: UniversalPHP;\n\tcliArgs?: string[];\n\tblueprint: BlueprintV2Declaration | ParsedBlueprintV2Declaration;\n\tblueprintOverrides?: {\n\t\twordpressVersion?: string;\n\t\tadditionalSteps?: any[];\n\t};\n\tonMessage?: (message: BlueprintMessage) => void | Promise<void>;\n}\n\nexport async function runBlueprintV2(\n\toptions: RunV2Options\n): Promise<StreamedPHPResponse> {\n\tconst cliArgs = options.cliArgs || [];\n\tfor (const arg of cliArgs) {\n\t\tif (arg.startsWith('--site-path=')) {\n\t\t\tthrow new Error(\n\t\t\t\t'The --site-path CLI argument must not be provided. In Playground, it is always set to /wordpress.'\n\t\t\t);\n\t\t}\n\t}\n\tcliArgs.push('--site-path=/wordpress');\n\n\t/**\n\t * Divergence from blueprints.phar – the default database engine is\n\t * SQLite. Why? Because in Playground we'll use SQLite far more often than\n\t * MySQL.\n\t */\n\tconst dbEngine = cliArgs.find((arg) => arg.startsWith('--db-engine='));\n\tif (!dbEngine) {\n\t\tcliArgs.push('--db-engine=sqlite');\n\t}\n\n\tconst php = options.php;\n\tconst onMessage = options?.onMessage || (() => {});\n\n\tconst file = await getV2Runner();\n\tphp.writeFile(\n\t\t'/tmp/blueprints.phar',\n\t\tnew Uint8Array(await file.arrayBuffer())\n\t);\n\n\tconst parsedBlueprintDeclaration = parseBlueprintDeclaration(\n\t\toptions.blueprint\n\t);\n\tlet blueprintReference = '';\n\tswitch (parsedBlueprintDeclaration.type) {\n\t\tcase 'inline-file':\n\t\t\tphp.writeFile(\n\t\t\t\t'/tmp/blueprint.json',\n\t\t\t\tparsedBlueprintDeclaration.contents\n\t\t\t);\n\t\t\tblueprintReference = '/tmp/blueprint.json';\n\t\t\tbreak;\n\t\tcase 'file-reference':\n\t\t\tblueprintReference = parsedBlueprintDeclaration.reference;\n\t\t\tbreak;\n\t}\n\n\tconst unbindMessageListener = await php.onMessage(async (message) => {\n\t\ttry {\n\t\t\tconst parsed =\n\t\t\t\ttypeof message === 'string' ? JSON.parse(message) : message;\n\t\t\tif (!parsed) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Make sure stdout and stderr data is emited before the next message is processed.\n\t\t\t// Otherwise a code such as `echo \"Hello\"; post_message_to_js(json_encode([\n\t\t\t// 'type' => 'blueprint.error',\n\t\t\t// 'message' => 'Error'\n\t\t\t// ]));`\n\t\t\t// might emit the message before we process the stdout data.\n\t\t\t//\n\t\t\t// This is a workaround to ensure that the message is emitted after the stdout data is processed.\n\t\t\t// @TODO: Remove this workaround. Find the root cause why stdout data is delayed and address it\n\t\t\t// directly.\n\t\t\tawait new Promise((resolve) => setTimeout(resolve, 0));\n\n\t\t\tif (parsed.type.startsWith('blueprint.')) {\n\t\t\t\tawait onMessage(parsed);\n\t\t\t}\n\t\t} catch (e) {\n\t\t\tlogger.warn('Failed to parse message as JSON:', message, e);\n\t\t}\n\t});\n\n\t/**\n\t * Prepare hooks, filters, and run the Blueprint:\n\t */\n\tawait php?.writeFile(\n\t\t'/tmp/run-blueprints.php',\n\t\t`<?php\nfunction playground_http_client_factory() {\n\treturn new WordPress\\\\HttpClient\\\\Client([\n\t\t// sockets transport is somehow faster than curl in Playground. Maybe\n\t\t// it uses a larger chunk size?\n\t\t'transport' => 'sockets',\n\t]);\n}\nplayground_add_filter('blueprint.http_client', 'playground_http_client_factory');\n\nfunction playground_on_blueprint_target_resolved() {\n\tpost_message_to_js(json_encode([\n\t\t'type' => 'blueprint.target_resolved',\n\t]));\n}\nplayground_add_filter('blueprint.target_resolved', 'playground_on_blueprint_target_resolved');\n\nplayground_add_filter('blueprint.resolved', 'playground_on_blueprint_resolved');\nfunction playground_on_blueprint_resolved($blueprint) {\n\t$additional_blueprint_steps = json_decode(${phpVar(\n\t\tJSON.stringify(options.blueprintOverrides?.additionalSteps || [])\n\t)}, true);\n\tif(count($additional_blueprint_steps) > 0) {\n\t\t$blueprint['additionalStepsAfterExecution'] = array_merge(\n\t\t\t$blueprint['additionalStepsAfterExecution'] ?? [],\n\t\t\t$additional_blueprint_steps\n\t\t);\n\t}\n\n\t$wp_version_override = json_decode(${phpVar(\n\t\tJSON.stringify(options.blueprintOverrides?.wordpressVersion || null)\n\t)}, true);\n\tif($wp_version_override) {\n\t\t$blueprint['wordpressVersion'] = $wp_version_override;\n\t}\n\treturn $blueprint;\n}\n\nfunction playground_progress_reporter() {\n\tclass PlaygroundProgressReporter implements ProgressReporter {\n\n\t\tpublic function reportProgress(float $progress, string $caption): void {\n\t\t\t$this->writeJsonMessage([\n\t\t\t\t'type' => 'blueprint.progress',\n\t\t\t\t'progress' => round($progress, 2),\n\t\t\t\t'caption' => $caption\n\t\t\t]);\n\t\t}\n\n\t\tpublic function reportError(string $message, ?Throwable $exception = null): void {\n\t\t\t$errorData = [\n\t\t\t\t'type' => 'blueprint.error',\n\t\t\t\t'message' => $message\n\t\t\t];\n\n\t\t\tif ($exception) {\n\t\t\t\t$errorData['details'] = [\n\t\t\t\t\t'exception' => get_class($exception),\n\t\t\t\t\t'message' => $exception->getMessage(),\n\t\t\t\t\t'file' => $exception->getFile(),\n\t\t\t\t\t'line' => $exception->getLine(),\n\t\t\t\t\t'trace' => $exception->getTraceAsString()\n\t\t\t\t];\n\t\t\t}\n\n\t\t\t$this->writeJsonMessage($errorData);\n\t\t}\n\n\t\tpublic function reportCompletion(string $message): void {\n\t\t\t$this->writeJsonMessage([\n\t\t\t\t'type' => 'blueprint.completion',\n\t\t\t\t'message' => $message\n\t\t\t]);\n\t\t}\n\n\t\tpublic function close(): void {}\n\n\t\tprivate function writeJsonMessage(array $data): void {\n\t\t\tpost_message_to_js(json_encode($data));\n\t\t}\n\t}\n\treturn new PlaygroundProgressReporter();\n}\nplayground_add_filter('blueprint.progress_reporter', 'playground_progress_reporter');\nrequire( \"/tmp/blueprints.phar\" );\n`\n\t);\n\tconst streamedResponse = (await (php as any).cli([\n\t\t'/internal/shared/bin/php',\n\t\t'/tmp/run-blueprints.php',\n\t\t'exec',\n\t\tblueprintReference,\n\t\t...cliArgs,\n\t])) as StreamedPHPResponse;\n\n\tstreamedResponse.finished.finally(unbindMessageListener);\n\n\treturn streamedResponse;\n}\n","import { errorLogPath } from '@php-wasm/logger';\nimport type { FileLockManager } from '@php-wasm/node';\nimport { createNodeFsMountHandler, loadNodeRuntime } from '@php-wasm/node';\nimport { EmscriptenDownloadMonitor } from '@php-wasm/progress';\nimport type { PHP, RemoteAPI, SupportedPHPVersion } from '@php-wasm/universal';\nimport {\n\tPHPExecutionFailureError,\n\tPHPResponse,\n\tPHPWorker,\n\tconsumeAPI,\n\tconsumeAPISync,\n\texposeAPI,\n\tsandboxedSpawnHandlerFactory,\n} from '@php-wasm/universal';\nimport { sprintf } from '@php-wasm/util';\nimport { type BlueprintMessage, runBlueprintV2 } from './run-blueprint-v2';\nimport {\n\ttype ParsedBlueprintV2Declaration,\n\ttype BlueprintV2Declaration,\n} from './blueprint-v2-declaration';\nimport { bootRequestHandler } from '@wp-playground/wordpress';\nimport { existsSync } from 'fs';\nimport path from 'path';\nimport { rootCertificates } from 'tls';\nimport { MessageChannel, type MessagePort, parentPort } from 'worker_threads';\nimport type { Mount } from '../mounts';\nimport { jspi } from 'wasm-feature-detect';\nimport { type RunCLIArgs } from '../run-cli';\n\nasync function mountResources(php: PHP, mounts: Mount[]) {\n\tfor (const mount of mounts) {\n\t\ttry {\n\t\t\tphp.mkdir(mount.vfsPath);\n\t\t\tawait php.mount(\n\t\t\t\tmount.vfsPath,\n\t\t\t\tcreateNodeFsMountHandler(mount.hostPath)\n\t\t\t);\n\t\t} catch {\n\t\t\toutput.stderr(\n\t\t\t\t`\\x1b[31m\\x1b[1mError mounting path ${mount.hostPath} at ${mount.vfsPath}\\x1b[0m\\n`\n\t\t\t);\n\t\t\tprocess.exit(1);\n\t\t}\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\n/**\n * Force TTY status to preserve ANSI control codes in the output.\n *\n * This script is spawned as `new Worker()` and process.stdout and process.stderr are\n * WritableWorkerStdio objects. By default, they strip ANSI control codes from the output\n * causing every progress bar update to be printed in a new line instead of updating the\n * same line.\n */\nObject.defineProperty(process.stdout, 'isTTY', { value: true });\nObject.defineProperty(process.stderr, 'isTTY', { value: true });\n\n/**\n * Output writer that ensures that progress bars are not printed on the same line as other output.\n */\nconst output = {\n\tlastWriteWasProgress: false,\n\tprogress(data: string) {\n\t\tif (!process.stdout.isTTY) {\n\t\t\t// eslint-disable-next-line no-console\n\t\t\tconsole.log(data);\n\t\t} else {\n\t\t\tif (!output.lastWriteWasProgress) {\n\t\t\t\tprocess.stdout.write('\\n');\n\t\t\t}\n\t\t\tprocess.stdout.write('\\r\\x1b[K' + data);\n\t\t\toutput.lastWriteWasProgress = true;\n\t\t}\n\t},\n\tstdout(data: string) {\n\t\tif (output.lastWriteWasProgress) {\n\t\t\tprocess.stdout.write('\\n');\n\t\t\toutput.lastWriteWasProgress = false;\n\t\t}\n\t\tprocess.stdout.write(data);\n\t},\n\tstderr(data: string) {\n\t\tif (output.lastWriteWasProgress) {\n\t\t\tprocess.stdout.write('\\n');\n\t\t\toutput.lastWriteWasProgress = false;\n\t\t}\n\t\tprocess.stderr.write(data);\n\t},\n};\n\nexport type WorkerBootArgs = RunCLIArgs & {\n\tphp: SupportedPHPVersion;\n\tsiteUrl: string;\n\tfirstProcessId: number;\n\tprocessIdSpaceLength: number;\n\ttrace: boolean;\n\tblueprint: BlueprintV2Declaration | ParsedBlueprintV2Declaration;\n};\n\ntype WorkerRunBlueprintArgs = RunCLIArgs & {\n\tsiteUrl: string;\n\tblueprint: BlueprintV2Declaration | ParsedBlueprintV2Declaration;\n};\n\ninterface WorkerBootRequestHandlerOptions {\n\tsiteUrl: string;\n\tphp: SupportedPHPVersion;\n\tallow?: string;\n\tfirstProcessId: number;\n\tprocessIdSpaceLength: number;\n\ttrace: boolean;\n}\n\nexport class PlaygroundCliBlueprintV2Worker extends PHPWorker {\n\tbooted = false;\n\tfileLockManager: RemoteAPI<FileLockManager> | FileLockManager | undefined;\n\n\tconstructor(monitor: EmscriptenDownloadMonitor) {\n\t\tsuper(undefined, monitor);\n\t}\n\n\t/**\n\t * Call this method before boot() to use file locking.\n\t *\n\t * This method is separate from boot() to simplify the related Comlink.transferHandlers\n\t * setup – if an argument is a MessagePort, we're transferring it, not copying it.\n\t *\n\t * @see comlink-sync.ts\n\t * @see phpwasm-emscripten-library-file-locking-for-node.js\n\t */\n\tasync useFileLockManager(port: MessagePort) {\n\t\tif (await jspi()) {\n\t\t\t/**\n\t\t\t * If JSPI is available, php.js supports both synchronous and asynchronous locking syscalls.\n\t\t\t * Web browsers, however, only support asynchronous message passing so let's use the\n\t\t\t * asynchronous API. Every method call will return a promise.\n\t\t\t *\n\t\t\t * @see comlink-sync.ts\n\t\t\t * @see phpwasm-emscripten-library-file-locking-for-node.js\n\t\t\t */\n\t\t\tthis.fileLockManager = consumeAPI<FileLockManager>(port);\n\t\t} else {\n\t\t\t/**\n\t\t\t * If JSPI is not available, php.js only supports synchronous locking syscalls.\n\t\t\t * Let's use the synchronous API. Every method call will block this thread\n\t\t\t * until the result is available.\n\t\t\t *\n\t\t\t * @see comlink-sync.ts\n\t\t\t * @see phpwasm-emscripten-library-file-locking-for-node.js\n\t\t\t */\n\t\t\tthis.fileLockManager = await consumeAPISync<FileLockManager>(port);\n\t\t}\n\t}\n\n\tasync bootAsPrimaryWorker(args: WorkerBootArgs) {\n\t\tawait this.bootRequestHandler(args);\n\n\t\tconst primaryPhp = this.__internal_getPHP()!;\n\t\tawait mountResources(primaryPhp, args['mount-before-install'] || []);\n\n\t\tif (args.mode === 'mount-only') {\n\t\t\tawait mountResources(primaryPhp, args.mount || []);\n\t\t\treturn;\n\t\t}\n\n\t\tawait this.runBlueprintV2(args);\n\t}\n\n\tasync bootAsSecondaryWorker(args: WorkerBootArgs) {\n\t\tawait this.bootRequestHandler(args);\n\t\tconst primaryPhp = this.__internal_getPHP()!;\n\t\t// When secondary workers are spawned, WordPress is already installed.\n\t\tawait mountResources(primaryPhp, args['mount-before-install'] || []);\n\t\tawait mountResources(primaryPhp, args.mount || []);\n\t}\n\n\tasync runBlueprintV2(args: WorkerRunBlueprintArgs) {\n\t\tconst requestHandler = this.__internal_getRequestHandler()!;\n\t\tconst { php, reap } =\n\t\t\tawait requestHandler.processManager.acquirePHPInstance({\n\t\t\t\tconsiderPrimary: false,\n\t\t\t});\n\n\t\t// Mount the current working directory to the PHP runtime for the purposes of\n\t\t// Blueprint resolution.\n\t\tconst primaryPhp = this.__internal_getPHP()!;\n\t\tlet unmountCwd = () => {};\n\t\tif (typeof args.blueprint === 'string') {\n\t\t\tconst blueprintPath = path.resolve(process.cwd(), args.blueprint);\n\t\t\tif (existsSync(blueprintPath)) {\n\t\t\t\tprimaryPhp.mkdir('/internal/shared/cwd');\n\t\t\t\tunmountCwd = await primaryPhp.mount(\n\t\t\t\t\t'/internal/shared/cwd',\n\t\t\t\t\tcreateNodeFsMountHandler(path.dirname(blueprintPath))\n\t\t\t\t);\n\t\t\t\targs.blueprint = path.join(\n\t\t\t\t\t'/internal/shared/cwd',\n\t\t\t\t\tpath.basename(args.blueprint)\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\ttry {\n\t\t\tconst cliArgsToPass: (keyof WorkerRunBlueprintArgs)[] = [\n\t\t\t\t'mode',\n\t\t\t\t'db-engine',\n\t\t\t\t'db-host',\n\t\t\t\t'db-user',\n\t\t\t\t'db-pass',\n\t\t\t\t'db-name',\n\t\t\t\t'db-path',\n\t\t\t\t'truncate-new-site-directory',\n\t\t\t\t'allow',\n\t\t\t];\n\t\t\tconst cliArgs = cliArgsToPass\n\t\t\t\t.filter((arg) => arg in args)\n\t\t\t\t.map((arg) => `--${arg}=${args[arg]}`);\n\t\t\tcliArgs.push(`--site-url=${args.siteUrl}`);\n\n\t\t\tlet afterBlueprintTargetResolvedCalled = false;\n\n\t\t\tconst streamedResponse = await runBlueprintV2({\n\t\t\t\tphp,\n\t\t\t\tblueprint: args.blueprint,\n\t\t\t\tblueprintOverrides: {\n\t\t\t\t\tadditionalSteps: args['additional-blueprint-steps'],\n\t\t\t\t\twordpressVersion: args.wp,\n\t\t\t\t},\n\t\t\t\tcliArgs,\n\t\t\t\tonMessage: async (message: BlueprintMessage) => {\n\t\t\t\t\tswitch (message.type) {\n\t\t\t\t\t\tcase 'blueprint.target_resolved': {\n\t\t\t\t\t\t\tif (!afterBlueprintTargetResolvedCalled) {\n\t\t\t\t\t\t\t\tawait mountResources(\n\t\t\t\t\t\t\t\t\tprimaryPhp,\n\t\t\t\t\t\t\t\t\targs.mount || []\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\tafterBlueprintTargetResolvedCalled = true;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tcase 'blueprint.progress': {\n\t\t\t\t\t\t\tconst progressMessage = `${message.caption.trim()} – ${message.progress.toFixed(\n\t\t\t\t\t\t\t\t2\n\t\t\t\t\t\t\t)}%`;\n\t\t\t\t\t\t\toutput.progress(progressMessage);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tcase 'blueprint.error': {\n\t\t\t\t\t\t\tconst red = '\\x1b[31m';\n\t\t\t\t\t\t\tconst bold = '\\x1b[1m';\n\t\t\t\t\t\t\tconst reset = '\\x1b[0m';\n\t\t\t\t\t\t\tif (args.debug && message.details) {\n\t\t\t\t\t\t\t\toutput.stderr(\n\t\t\t\t\t\t\t\t\t`${red}${bold}Fatal error:${reset} Uncaught ${message.details.exception}: ${message.details.message}\\n` +\n\t\t\t\t\t\t\t\t\t\t` at ${message.details.file}:${message.details.line}\\n` +\n\t\t\t\t\t\t\t\t\t\t(message.details.trace\n\t\t\t\t\t\t\t\t\t\t\t? message.details.trace + '\\n'\n\t\t\t\t\t\t\t\t\t\t\t: '')\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\toutput.stderr(\n\t\t\t\t\t\t\t\t\t`${red}${bold}Error:${reset} ${message.message}\\n`\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tbreak;\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\t/**\n\t\t\t * When we're debugging, every bit of information matters – let's immediately output\n\t\t\t * everything we get from the PHP output streams.\n\t\t\t */\n\t\t\tif (args.debug) {\n\t\t\t\tstreamedResponse!.stdout.pipeTo(\n\t\t\t\t\tnew WritableStream({\n\t\t\t\t\t\twrite(chunk) {\n\t\t\t\t\t\t\tprocess.stdout.write(chunk);\n\t\t\t\t\t\t},\n\t\t\t\t\t})\n\t\t\t\t);\n\t\t\t\tstreamedResponse!.stderr.pipeTo(\n\t\t\t\t\tnew WritableStream({\n\t\t\t\t\t\twrite(chunk) {\n\t\t\t\t\t\t\tprocess.stderr.write(chunk);\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\tawait streamedResponse!.finished;\n\t\t\tif ((await streamedResponse!.exitCode) !== 0) {\n\t\t\t\t// exitCode != 1 means the blueprint execution failed. Let's throw an error.\n\t\t\t\t// and clean up.\n\t\t\t\tconst syncResponse = await PHPResponse.fromStreamedResponse(\n\t\t\t\t\tstreamedResponse\n\t\t\t\t);\n\t\t\t\tthrow new PHPExecutionFailureError(\n\t\t\t\t\t`PHP.run() failed with exit code ${syncResponse.exitCode}.`,\n\t\t\t\t\tsyncResponse,\n\t\t\t\t\t'request'\n\t\t\t\t);\n\t\t\t}\n\t\t} catch (error) {\n\t\t\t// Capture the PHP error log details to provide more context for debugging.\n\t\t\tlet phpLogs = '';\n\t\t\ttry {\n\t\t\t\t// @TODO: Don't assume errorLogPath starts with /wordpress/\n\t\t\t\t// ...or maybe we can assume that in Playground CLI?\n\t\t\t\tphpLogs = php.readFileAsText(errorLogPath);\n\t\t\t} catch {\n\t\t\t\t// Ignore errors reading the PHP error log.\n\t\t\t}\n\t\t\t(error as any).phpLogs = phpLogs;\n\t\t\tthrow error;\n\t\t} finally {\n\t\t\treap();\n\t\t\tunmountCwd();\n\t\t}\n\t}\n\n\tasync bootRequestHandler({\n\t\tsiteUrl,\n\t\tallow,\n\t\tphp,\n\t\tfirstProcessId,\n\t\tprocessIdSpaceLength,\n\t\ttrace,\n\t}: WorkerBootRequestHandlerOptions) {\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\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 bootRequestHandler({\n\t\t\t\tsiteUrl,\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(php!, {\n\t\t\t\t\t\temscriptenOptions: {\n\t\t\t\t\t\t\tfileLockManager: this.fileLockManager!,\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\tENV: {\n\t\t\t\t\t\t\t\tDOCROOT: '/wordpress',\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tfollowSymlinks: allow?.includes('follow-symlinks'),\n\t\t\t\t\t});\n\t\t\t\t},\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},\n\t\t\t\tcookieStore: false,\n\t\t\t\tspawnHandler: sandboxedSpawnHandlerFactory,\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\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 phpChannel = new MessageChannel();\n\nconst [setApiReady, setAPIError] = exposeAPI(\n\tnew PlaygroundCliBlueprintV2Worker(new EmscriptenDownloadMonitor()),\n\tundefined,\n\tphpChannel.port1\n);\n\nparentPort!.postMessage(\n\t{\n\t\tcommand: 'worker-script-initialized',\n\t\tphpPort: phpChannel.port2,\n\t},\n\t[phpChannel.port2 as any]\n);\n"],"names":["getV2Runner","data","v2_runner_url","path","readFile","parseBlueprintDeclaration","source","runBlueprintV2","options","cliArgs","arg","php","onMessage","file","parsedBlueprintDeclaration","blueprintReference","unbindMessageListener","message","parsed","resolve","e","logger","phpVar","streamedResponse","mountResources","mounts","mount","createNodeFsMountHandler","output","tracePhpWasm","processId","format","args","sprintf","PlaygroundCliBlueprintV2Worker","PHPWorker","monitor","port","jspi","consumeAPI","consumeAPISync","primaryPhp","requestHandler","reap","unmountCwd","blueprintPath","existsSync","afterBlueprintTargetResolvedCalled","progressMessage","red","bold","reset","chunk","syncResponse","PHPResponse","PHPExecutionFailureError","error","phpLogs","errorLogPath","siteUrl","allow","firstProcessId","processIdSpaceLength","trace","nextProcessId","lastProcessId","constants","bootRequestHandler","loadNodeRuntime","rootCertificates","sandboxedSpawnHandlerFactory","setApiReady","setAPIError","phpChannel","MessageChannel","exposeAPI","EmscriptenDownloadMonitor","parentPort"],"mappings":"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"}
@@ -1,5 +0,0 @@
1
- export declare class ReportableError extends Error {
2
- isReportableInCLI: boolean;
3
- constructor(message: string, options?: ErrorOptions);
4
- static getReportableCause(error: unknown): Error | null;
5
- }
@@ -1,24 +0,0 @@
1
- "use strict";var ie=Object.create;var _=Object.defineProperty;var se=Object.getOwnPropertyDescriptor;var ae=Object.getOwnPropertyNames;var le=Object.getPrototypeOf,ce=Object.prototype.hasOwnProperty;var ue=(e,r,t,i)=>{if(r&&typeof r=="object"||typeof r=="function")for(let o of ae(r))!ce.call(e,o)&&o!==t&&_(e,o,{get:()=>r[o],enumerable:!(i=se(r,o))||i.enumerable});return e};var de=(e,r,t)=>(t=e!=null?ie(le(e)):{},ue(r||!e||!e.__esModule?_(t,"default",{value:e,enumerable:!0}):t,e));const a=require("@php-wasm/logger"),N=require("@php-wasm/progress"),v=require("@php-wasm/universal"),$=require("@wp-playground/blueprints"),L=require("@wp-playground/common"),g=require("fs"),b=require("path"),X=require("worker_threads"),pe=require("@wp-playground/wordpress"),E=require("./mounts-D7bhhGq3.cjs"),R=require("fs-extra"),J=require("os"),fe=require("express"),we=require("@php-wasm/node"),he=require("wasm-feature-detect"),me=require("yargs"),M=require("@wp-playground/storage");var H=typeof document<"u"?document.currentScript:null;const z=b.join(J.homedir(),".wordpress-playground");async function ye(e){return await Y("https://github.com/WordPress/sqlite-database-integration/archive/refs/heads/develop.zip","sqlite.zip",e)}async function Y(e,r,t){const i=b.join(z,r);return R.existsSync(i)||(R.ensureDirSync(z),await ge(e,i,t)),Q(i)}async function ge(e,r,t){const o=(await t.monitorFetch(fetch(e))).body.getReader(),n=`${r}.partial`,l=R.createWriteStream(n);for(;;){const{done:u,value:d}=await o.read();if(d&&l.write(d),u)break}l.close(),l.closed||await new Promise((u,d)=>{l.on("finish",()=>{R.renameSync(n,r),u(null)}),l.on("error",A=>{R.removeSync(n),d(A)})})}function Q(e,r){return new File([R.readFileSync(e)],b.basename(e))}async function be(e){const r=fe(),t=await new Promise((n,l)=>{const u=r.listen(e.port,()=>{const d=u.address();d===null||typeof d=="string"?l(new Error("Server address is not available")):n(u)})});r.use("/",async(n,l)=>{const u=await e.handleRequest({url:n.url,headers:ke(n),method:n.method,body:await Pe(n)});l.statusCode=u.httpStatusCode;for(const d in u.headers)l.setHeader(d,u.headers[d]);l.end(u.bytes)});const o=t.address().port;return await e.onBind(t,o)}const Pe=async e=>await new Promise(r=>{const t=[];e.on("data",i=>{t.push(i)}),e.on("end",()=>{r(new Uint8Array(Buffer.concat(t)))})}),ke=e=>{const r={};if(e.rawHeaders&&e.rawHeaders.length)for(let t=0;t<e.rawHeaders.length;t+=2)r[e.rawHeaders[t].toLowerCase()]=e.rawHeaders[t+1];return r},ve=""+(typeof document>"u"?require("url").pathToFileURL(__dirname+"/worker-thread-CYvRK9UX.js").href:new URL("worker-thread-CYvRK9UX.js",document.currentScript&&document.currentScript.tagName.toUpperCase()==="SCRIPT"&&document.currentScript.src||document.baseURI).href);class Re{constructor(r){this.workerLoads=[],this.addWorker(r)}addWorker(r){this.workerLoads.push({worker:r,activeRequests:new Set})}async handleRequest(r){let t=this.workerLoads[0];for(let o=1;o<this.workerLoads.length;o++){const n=this.workerLoads[o];n.activeRequests.size<t.activeRequests.size&&(t=n)}const i=t.worker.request(r);return t.activeRequests.add(i),i.url=r.url,i.finally(()=>{t.activeRequests.delete(i)})}}function We(e){return/^latest$|^trunk$|^nightly$|^(?:(\d+)\.(\d+)(?:\.(\d+))?)((?:-beta(?:\d+)?)|(?:-RC(?:\d+)?))?$/.test(e)}class K extends Error{constructor(r,t){super(r,{...t,cause:{isReportableInCLI:!0}}),this.isReportableInCLI=!0,this.isReportableInCLI=!0}static getReportableCause(r){let t=0;const i=15,o=[r];for(;o.length>0&&t<i;){const n=o.pop();if(n instanceof Error){if(n.isReportableInCLI)return n;Array.isArray(n.cause)?o.push(...n.cause):o.push(n.cause),t++,t>=i&&a.logger.warn("Recursion limit exceeded while checking if error is reportable")}}return null}}async function Se({sourceString:e,blueprintMayReadAdjacentFiles:r}){if(!e)return;if(e.startsWith("http://")||e.startsWith("https://"))return await $.resolveRemoteBlueprint(e);let t=b.resolve(process.cwd(),e);if(!g.existsSync(t))throw new Error(`Blueprint file does not exist: ${t}`);const i=g.statSync(t);if(i.isDirectory()&&(t=b.join(t,"blueprint.json")),!i.isFile()&&i.isSymbolicLink())throw new Error(`Blueprint path is neither a file nor a directory: ${t}`);const o=b.extname(t);switch(o){case".zip":return M.ZipFilesystem.fromArrayBuffer(g.readFileSync(t).buffer);case".json":{const n=g.readFileSync(t,"utf-8");try{JSON.parse(n)}catch{throw new Error(`Blueprint file at ${t} is not a valid JSON file`)}const l=b.dirname(t),u=new M.NodeJsFilesystem(l);return new M.OverlayFilesystem([new M.InMemoryFilesystem({"blueprint.json":n}),{read(d){if(!r)throw new K(`Error: Blueprint contained tried to read a local file at path "${d}" (via a resource of type "bundled"). Playground restricts access to local resources by default as a security measure.
2
-
3
- You can allow this Blueprint to read files from the same parent directory by explicitly adding the --blueprint-may-read-adjacent-files option to your command.`);return u.read(d)}}])}default:throw new Error(`Unsupported blueprint file extension: ${o}. Only .zip and .json files are supported.`)}}async function xe(){const e=me(process.argv.slice(2)).usage("Usage: wp-playground <command> [options]").positional("command",{describe:"Command to run",choices:["server","run-blueprint","build-snapshot"],demandOption:!0}).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:L.RecommendedPHPVersion,choices:v.SupportedPHPVersions}).option("wp",{describe:"WordPress version to use.",type:"string",default:"latest"}).option("mount",{describe:"Mount a directory to the PHP runtime (can be used multiple times). Format: /host/path:/vfs/path",type:"array",string:!0,coerce:E.parseMountWithDelimiterArguments}).option("mount-before-install",{describe:"Mount a directory to the PHP runtime before WordPress installation (can be used multiple times). Format: /host/path:/vfs/path",type:"array",string:!0,coerce:E.parseMountWithDelimiterArguments}).option("mount-dir",{describe:'Mount a directory to the PHP runtime (can be used multiple times). Format: "/host/path" "/vfs/path"',type:"array",nargs:2,array:!0}).option("mount-dir-before-install",{describe:'Mount a directory before WordPress installation (can be used multiple times). Format: "/host/path" "/vfs/path"',type:"string",nargs:2,array:!0,coerce:E.parseMountDirArguments}).option("login",{describe:"Should log the user in",type:"boolean",default:!1}).option("blueprint",{describe:"Blueprint to execute.",type:"string"}).option("blueprint-may-read-adjacent-files",{describe:'Consent flag: Allow "bundled" resources in a local blueprint to read files in the same directory as the blueprint file.',type:"boolean",default:!1}).option("skip-wordpress-setup",{describe:"Do not download, unzip, and install WordPress. Useful for mounting a pre-configured WordPress directory at /wordpress.",type:"boolean",default:!1}).option("skip-sqlite-setup",{describe:"Skip the SQLite integration plugin setup to allow the WordPress site to use MySQL.",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}).option("auto-mount",{describe:"Automatically mount the current working directory. You can mount a WordPress directory, a plugin directory, a theme directory, a wp-content directory, or any directory containing PHP and HTML files.",type:"boolean",default:!1}).option("follow-symlinks",{describe:`Allow Playground to follow symlinks by automatically mounting symlinked directories and files encountered in mounted directories.
4
- Warning: Following symlinks will expose files outside mounted directories to Playground and could be a security risk.`,type:"boolean",default:!1}).option("experimentalTrace",{describe:"Print detailed messages about system behavior to the console. Useful for troubleshooting.",type:"boolean",default:!1,hidden:!0}).option("internal-cookie-store",{describe:"Enable internal cookie handling. When enabled, Playground will manage cookies internally using an HttpCookieStore that persists cookies across requests. When disabled, cookies are handled externally (e.g., by a browser in Node.js environments).",type:"boolean",default:!1}).option("xdebug",{describe:"Enable Xdebug.",type:"boolean",default:!1}).option("experimentalMultiWorker",{describe:"Enable experimental multi-worker support which requires JSPI and a /wordpress directory backed by a real filesystem. Pass a positive number to specify the number of workers to use. Otherwise, default to the number of CPUs minus 1.",type:"number",coerce:o=>o??J.cpus().length-1}).showHelpOnFail(!1).check(async o=>{if(o.wp!==void 0&&!We(o.wp))try{new URL(o.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(o.experimentalMultiWorker!==void 0){if(o.experimentalMultiWorker<=1)throw new Error("The --experimentalMultiWorker flag must be a positive integer greater than 1.");const n=l=>l.vfsPath==="/wordpress";if(!o.mount?.some(n)&&!o["mount-before-install"]?.some(n))throw new Error("Please mount a real filesystem directory as the /wordpress directory before using the --experimentalMultiWorker flag.")}return!0});e.wrap(e.terminalWidth());const r=await e.argv,t=r._[0];["run-blueprint","server","build-snapshot"].includes(t)||(e.showHelp(),process.exit(1));const i={...r,command:t,blueprint:await Se({sourceString:r.blueprint,blueprintMayReadAdjacentFiles:r.blueprintMayReadAdjacentFiles}),mount:[...r.mount||[],...r["mount-dir"]||[]],"mount-before-install":[...r["mount-before-install"]||[],...r["mount-dir-before-install"]||[]]};try{return G(i)}catch(o){const n=K.getReportableCause(o);if(n)console.log(""),console.log(n.message),process.exit(1);else throw o}}async function G(e){let r,t;const i=[];e.autoMount&&(e=E.expandAutoMounts(e));async function o(s){await t.run({code:`<?php
5
- $zip = new ZipArchive();
6
- if(false === $zip->open('/tmp/build.zip', ZipArchive::CREATE | ZipArchive::OVERWRITE)) {
7
- throw new Exception('Failed to create ZIP');
8
- }
9
- $files = new RecursiveIteratorIterator(
10
- new RecursiveDirectoryIterator('/wordpress')
11
- );
12
- foreach ($files as $file) {
13
- echo $file . PHP_EOL;
14
- if (!$file->isFile()) {
15
- continue;
16
- }
17
- $zip->addFile($file->getPathname(), $file->getPathname());
18
- }
19
- $zip->close();
20
-
21
- `});const c=await t.readFileAsBuffer("/tmp/build.zip");g.writeFileSync(s,c)}async function n(s){const c=$.isBlueprintBundle(e.blueprint)?e.blueprint:{login:e.login,...e.blueprint,preferredVersions:{php:e.php??e?.blueprint?.preferredVersions?.php??L.RecommendedPHPVersion,wp:e.wp??e?.blueprint?.preferredVersions?.wp??"latest",...e.blueprint?.preferredVersions||{}}},f=new N.ProgressTracker;let h="",w=!1;return f.addEventListener("progress",p=>{if(w)return;w=p.detail.progress===100;const S=Math.floor(p.detail.progress);h=p.detail.caption||h||"Running the Blueprint";const P=`${h.trim()} – ${S}%`;e.quiet||u(process.stdout,P,w)}),await $.compileBlueprint(c,{progress:f,additionalSteps:s})}let l="";function u(s,c,f){c!==l&&(l=c,s.isTTY?(s.cursorTo(0),s.write(c),s.clearLine(1),f&&s.write(`
22
- `)):s.write(`${c}
23
- `))}async function d(s){const c=new X.Worker(s);return new Promise((f,h)=>{c.once("message",function(w){w.command==="worker-script-initialized"&&f({worker:c,phpPort:w.phpPort})}),c.once("error",function(w){console.error(w);const p=new Error(`Worker failed to load at ${s}. ${w.message?`Original error: ${w.message}`:""}`);p.filename=s,h(p)})})}function A(s){const c=new URL(ve,typeof document>"u"?require("url").pathToFileURL(__filename).href:H&&H.tagName.toUpperCase()==="SCRIPT"&&H.src||new URL("run-cli-B5BfXxxJ.cjs",document.baseURI).href),f=[];for(let h=0;h<s;h++)f.push(d(c));return Promise.all(f)}e.quiet&&(a.logger.handlers=[]);const W=await n(e["additional-blueprint-steps"]||[]),ee=await import("fs-ext").then(s=>s.flockSync).catch(()=>{a.logger.warn("The fs-ext package is not installed. Internal file locking will not be integrated with host OS file locking.")}),U=new we.FileLockManagerForNode(ee);async function T(){const{port1:s,port2:c}=new X.MessageChannel;return await he.jspi()?v.exposeAPI(U,null,s):await v.exposeSyncAPI(U,s),c}let j=!1;return a.logger.log("Starting a PHP server..."),be({port:e.port,onBind:async(s,c)=>{const f=`http://127.0.0.1:${c}`,h=e.experimentalMultiWorker??1,w=A(h);a.logger.log(`Setting up WordPress ${e.wp}`);let p;const S=new N.EmscriptenDownloadMonitor;if(!e.skipWordPressSetup){let m=!1;S.addEventListener("progress",k=>{if(m)return;const{loaded:C,total:B}=k.detail,F=Math.floor(Math.min(100,100*C/B));m=F===100,e.quiet||u(process.stdout,`Downloading WordPress ${F}%...`,m)}),p=await pe.resolveWordPressRelease(e.wp),a.logger.log(`Resolved WordPress release URL: ${p?.releaseUrl}`)}const P=p&&b.join(z,`prebuilt-wp-content-for-wp-${p.version}.zip`),D=p?g.existsSync(P)?Q(P):await Y(p.releaseUrl,`${p.version}.zip`,S):void 0;a.logger.log("Fetching SQLite integration plugin...");const te=e.skipSqliteSetup?void 0:await ye(S),O=e.followSymlinks===!0,Z=e.experimentalTrace===!0;try{const m=e["mount-before-install"]||[],k=e.mount||[],[C,...B]=await w;t=v.consumeAPI(C.phpPort),i.push({playground:t,worker:C.worker}),await t.isConnected();const F=await T();a.logger.log("Booting WordPress...");const I=Math.floor(Number.MAX_SAFE_INTEGER/h);if(await t.useFileLockManager(F),await t.boot({phpVersion:W.versions.php,wpVersion:W.versions.wp,absoluteUrl:f,mountsBeforeWpInstall:m,mountsAfterWpInstall:k,wordPressZip:D&&await D.arrayBuffer(),sqliteIntegrationPluginZip:await te.arrayBuffer(),firstProcessId:0,processIdSpaceLength:I,followSymlinks:O,trace:Z,internalCookieStore:e.internalCookieStore,withXdebug:e.xdebug}),p&&!e["mount-before-install"]&&!g.existsSync(P)&&(a.logger.log("Caching preinstalled WordPress for the next boot..."),g.writeFileSync(P,await L.zipDirectory(t,"/wordpress")),a.logger.log("Cached!")),r=new Re(t),await t.isReady(),j=!0,a.logger.log("Booted!"),W&&(a.logger.log("Running the Blueprint..."),await $.runBlueprintSteps(W,t),a.logger.log("Finished running the blueprint")),e.command==="build-snapshot"?(await o(e.outfile),a.logger.log(`WordPress exported to ${e.outfile}`),process.exit(0)):e.command==="run-blueprint"&&(a.logger.log("Blueprint executed"),process.exit(0)),e.experimentalMultiWorker&&e.experimentalMultiWorker>1){a.logger.log("Preparing additional workers...");const V=await L.zipDirectory(t,"/internal"),x=I;await Promise.all(B.map(async(q,re)=>{const y=v.consumeAPI(q.phpPort);i.push({playground:y,worker:q.worker}),await y.isConnected();const oe=x+re*I,ne=await T();await y.useFileLockManager(ne),await y.boot({phpVersion:W.versions.php,absoluteUrl:f,mountsBeforeWpInstall:m,mountsAfterWpInstall:k,wordPressZip:void 0,sqliteIntegrationPluginZip:void 0,dataSqlPath:"/wordpress/wp-content/database/.ht.sqlite",firstProcessId:oe,processIdSpaceLength:I,followSymlinks:O,trace:Z,internalCookieStore:e.internalCookieStore,withXdebug:e.xdebug}),await y.isReady(),await y.writeFile("/tmp/internal.zip",V),await L.unzipFile(y,"/tmp/internal.zip","/internal"),await y.unlink("/tmp/internal.zip"),r.addWorker(y)})),a.logger.log("Ready!")}return a.logger.log(`WordPress is running on ${f}`),{playground:t,server:s,[Symbol.asyncDispose]:async function(){await Promise.all(i.map(async({playground:x,worker:q})=>{await x.dispose(),await q.terminate()})),await new Promise(x=>s.close(x))}}}catch(m){if(!e.debug)throw m;const k=await t.readFileAsText(a.errorLogPath);throw new Error(k,{cause:m})}},async handleRequest(s){return j?await r.handleRequest(s):v.PHPResponse.forHttpCode(502,"WordPress is not ready yet")}})}exports.parseOptionsAndRunCLI=xe;exports.runCLI=G;
24
- //# sourceMappingURL=run-cli-B5BfXxxJ.cjs.map