@wp-playground/cli 3.0.15 → 3.0.17

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.
@@ -1 +1 @@
1
- {"version":3,"file":"worker-thread-v2.cjs","sources":["../../../../packages/playground/cli/src/blueprints-v2/worker-thread-v2.ts"],"sourcesContent":["import { errorLogPath, logger } 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 {\n\tPHP,\n\tFileTree,\n\tRemoteAPI,\n\tSupportedPHPVersion,\n} 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 {\n\ttype BlueprintMessage,\n\trunBlueprintV2,\n\ttype BlueprintV1Declaration,\n} from '@wp-playground/blueprints';\nimport {\n\ttype ParsedBlueprintV2String,\n\ttype RawBlueprintV2Data,\n} from '@wp-playground/blueprints';\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';\nimport type {\n\tPhpIniOptions,\n\tPHPInstanceCreatedHook,\n} from '@wp-playground/wordpress';\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 PrimaryWorkerBootArgs = RunCLIArgs & {\n\tphpVersion: SupportedPHPVersion;\n\tsiteUrl: string;\n\tfirstProcessId: number;\n\tprocessIdSpaceLength: number;\n\ttrace: boolean;\n\tblueprint:\n\t\t| RawBlueprintV2Data\n\t\t| ParsedBlueprintV2String\n\t\t| BlueprintV1Declaration;\n\tnativeInternalDirPath: string;\n};\n\ntype WorkerRunBlueprintArgs = RunCLIArgs & {\n\tsiteUrl: string;\n\tblueprint:\n\t\t| RawBlueprintV2Data\n\t\t| ParsedBlueprintV2String\n\t\t| BlueprintV1Declaration;\n};\n\nexport type SecondaryWorkerBootArgs = {\n\tsiteUrl: string;\n\tallow?: string;\n\tphpVersion: SupportedPHPVersion;\n\tphpIniEntries?: PhpIniOptions;\n\tconstants?: Record<string, string | number | boolean | null>;\n\tcreateFiles?: FileTree;\n\tfirstProcessId: number;\n\tprocessIdSpaceLength: number;\n\ttrace: boolean;\n\tnativeInternalDirPath: string;\n\twithXdebug?: boolean;\n\tmountsBeforeWpInstall?: Array<Mount>;\n\tmountsAfterWpInstall?: Array<Mount>;\n};\n\nexport type WorkerBootRequestHandlerOptions = Omit<\n\tSecondaryWorkerBootArgs,\n\t'mountsBeforeWpInstall' | 'mountsAfterWpInstall'\n> & {\n\tonPHPInstanceCreated: PHPInstanceCreatedHook;\n};\n\nexport class PlaygroundCliBlueprintV2Worker extends PHPWorker {\n\tbooted = false;\n\tblueprintTargetResolved = false;\n\tphpInstancesThatNeedMountsAfterTargetResolved = new Set<PHP>();\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: PrimaryWorkerBootArgs) {\n\t\tconst constants = {\n\t\t\tWP_DEBUG: true,\n\t\t\tWP_DEBUG_LOG: true,\n\t\t\tWP_DEBUG_DISPLAY: false,\n\t\t};\n\t\tconst requestHandlerOptions: WorkerBootRequestHandlerOptions = {\n\t\t\t...args,\n\t\t\tcreateFiles: {\n\t\t\t\t'/internal/shared/ca-bundle.crt': rootCertificates.join('\\n'),\n\t\t\t},\n\t\t\tconstants,\n\t\t\tphpIniEntries: {\n\t\t\t\t'openssl.cafile': '/internal/shared/ca-bundle.crt',\n\t\t\t},\n\t\t\tonPHPInstanceCreated: async (php: PHP) => {\n\t\t\t\tawait mountResources(php, args['mount-before-install'] || []);\n\t\t\t\tif (this.blueprintTargetResolved) {\n\t\t\t\t\tawait mountResources(php, args.mount || []);\n\t\t\t\t} else {\n\t\t\t\t\t// NOTE: Today (2025-09-11), during boot with a plugin auto-mount,\n\t\t\t\t\t// the Blueprint runner fails unless post-resolution mounts are\n\t\t\t\t\t// added to existing PHP instances. So we track them here so they\n\t\t\t\t\t// can be mounted at the necessary time.\n\t\t\t\t\t// Only plugin auto-mounts seem to need this, so perhaps there\n\t\t\t\t\t// is a change we can make to the Blueprint runner so such\n\t\t\t\t\t// a dance is unnecessary.\n\t\t\t\t\tthis.phpInstancesThatNeedMountsAfterTargetResolved.add(php);\n\t\t\t\t\tphp.addEventListener('runtime.beforeExit', () => {\n\t\t\t\t\t\tthis.phpInstancesThatNeedMountsAfterTargetResolved.delete(\n\t\t\t\t\t\t\tphp\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\tawait this.bootRequestHandler(requestHandlerOptions);\n\n\t\tconst primaryPhp = this.__internal_getPHP()!;\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: SecondaryWorkerBootArgs) {\n\t\tawait this.bootRequestHandler({\n\t\t\t...args,\n\t\t\tonPHPInstanceCreated: async (php: PHP) => {\n\t\t\t\tawait mountResources(php, args.mountsBeforeWpInstall || []);\n\t\t\t\tawait mountResources(php, args.mountsAfterWpInstall || []);\n\t\t\t},\n\t\t});\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\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 (!this.blueprintTargetResolved) {\n\t\t\t\t\t\t\t\tthis.blueprintTargetResolved = true;\n\t\t\t\t\t\t\t\tfor (const php of this\n\t\t\t\t\t\t\t\t\t.phpInstancesThatNeedMountsAfterTargetResolved) {\n\t\t\t\t\t\t\t\t\t// console.log('mounting resources for php', php);\n\t\t\t\t\t\t\t\t\tthis.phpInstancesThatNeedMountsAfterTargetResolved.delete(\n\t\t\t\t\t\t\t\t\t\tphp\n\t\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\t\tawait mountResources(php, args.mount || []);\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\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\tphpVersion,\n\t\tcreateFiles,\n\t\tconstants,\n\t\tphpIniEntries,\n\t\tfirstProcessId,\n\t\tprocessIdSpaceLength,\n\t\ttrace,\n\t\tnativeInternalDirPath,\n\t\twithXdebug,\n\t\tonPHPInstanceCreated,\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 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(phpVersion, {\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\tphpWasmInitOptions: { nativeInternalDirPath },\n\t\t\t\t\t\t},\n\t\t\t\t\t\tfollowSymlinks: allow?.includes('follow-symlinks'),\n\t\t\t\t\t\twithXdebug,\n\t\t\t\t\t});\n\t\t\t\t},\n\t\t\t\tonPHPInstanceCreated,\n\t\t\t\tsapiName: 'cli',\n\t\t\t\tcreateFiles,\n\t\t\t\tconstants,\n\t\t\t\tphpIniEntries,\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\nprocess.on('unhandledRejection', (e: any) => {\n\tlogger.error('Unhandled rejection:', e);\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":["mountResources","php","mounts","mount","createNodeFsMountHandler","output","tracePhpWasm","processId","format","args","sprintf","data","PlaygroundCliBlueprintV2Worker","PHPWorker","monitor","port","jspi","consumeAPI","consumeAPISync","constants","requestHandlerOptions","rootCertificates","primaryPhp","requestHandler","reap","unmountCwd","blueprintPath","path","existsSync","cliArgs","arg","streamedResponse","runBlueprintV2","message","progressMessage","red","bold","reset","chunk","syncResponse","PHPResponse","PHPExecutionFailureError","error","phpLogs","errorLogPath","siteUrl","allow","phpVersion","createFiles","phpIniEntries","firstProcessId","processIdSpaceLength","trace","nativeInternalDirPath","withXdebug","onPHPInstanceCreated","nextProcessId","lastProcessId","bootRequestHandler","loadNodeRuntime","sandboxedSpawnHandlerFactory","setApiReady","e","setAPIError","logger","phpChannel","MessageChannel","exposeAPI","EmscriptenDownloadMonitor","parentPort"],"mappings":"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"}
1
+ {"version":3,"file":"worker-thread-v2.cjs","sources":["../../../../packages/playground/cli/src/blueprints-v2/worker-thread-v2.ts"],"sourcesContent":["import { errorLogPath, logger } 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 {\n\tPHP,\n\tFileTree,\n\tRemoteAPI,\n\tSupportedPHPVersion,\n} 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 {\n\ttype BlueprintMessage,\n\trunBlueprintV2,\n\ttype BlueprintV1Declaration,\n} from '@wp-playground/blueprints';\nimport {\n\ttype ParsedBlueprintV2String,\n\ttype RawBlueprintV2Data,\n} from '@wp-playground/blueprints';\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';\nimport type {\n\tPhpIniOptions,\n\tPHPInstanceCreatedHook,\n} from '@wp-playground/wordpress';\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 PrimaryWorkerBootArgs = RunCLIArgs & {\n\tphpVersion: SupportedPHPVersion;\n\tsiteUrl: string;\n\tfirstProcessId: number;\n\tprocessIdSpaceLength: number;\n\ttrace: boolean;\n\tblueprint:\n\t\t| RawBlueprintV2Data\n\t\t| ParsedBlueprintV2String\n\t\t| BlueprintV1Declaration;\n\tnativeInternalDirPath: string;\n};\n\ntype WorkerRunBlueprintArgs = RunCLIArgs & {\n\tsiteUrl: string;\n\tblueprint:\n\t\t| RawBlueprintV2Data\n\t\t| ParsedBlueprintV2String\n\t\t| BlueprintV1Declaration;\n};\n\nexport type SecondaryWorkerBootArgs = {\n\tsiteUrl: string;\n\tallow?: string;\n\tphpVersion: SupportedPHPVersion;\n\tphpIniEntries?: PhpIniOptions;\n\tconstants?: Record<string, string | number | boolean | null>;\n\tcreateFiles?: FileTree;\n\tfirstProcessId: number;\n\tprocessIdSpaceLength: number;\n\ttrace: boolean;\n\tnativeInternalDirPath: string;\n\twithXdebug?: boolean;\n\tmountsBeforeWpInstall?: Array<Mount>;\n\tmountsAfterWpInstall?: Array<Mount>;\n};\n\nexport type WorkerBootRequestHandlerOptions = Omit<\n\tSecondaryWorkerBootArgs,\n\t'mountsBeforeWpInstall' | 'mountsAfterWpInstall'\n> & {\n\tonPHPInstanceCreated: PHPInstanceCreatedHook;\n};\n\nexport class PlaygroundCliBlueprintV2Worker extends PHPWorker {\n\tbooted = false;\n\tblueprintTargetResolved = false;\n\tphpInstancesThatNeedMountsAfterTargetResolved = new Set<PHP>();\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: PrimaryWorkerBootArgs) {\n\t\tconst constants = {\n\t\t\tWP_DEBUG: true,\n\t\t\tWP_DEBUG_LOG: true,\n\t\t\tWP_DEBUG_DISPLAY: false,\n\t\t};\n\t\tconst requestHandlerOptions: WorkerBootRequestHandlerOptions = {\n\t\t\t...args,\n\t\t\tcreateFiles: {\n\t\t\t\t'/internal/shared/ca-bundle.crt': rootCertificates.join('\\n'),\n\t\t\t},\n\t\t\tconstants,\n\t\t\tphpIniEntries: {\n\t\t\t\t'openssl.cafile': '/internal/shared/ca-bundle.crt',\n\t\t\t},\n\t\t\tonPHPInstanceCreated: async (php: PHP) => {\n\t\t\t\tawait mountResources(php, args['mount-before-install'] || []);\n\t\t\t\tif (this.blueprintTargetResolved) {\n\t\t\t\t\tawait mountResources(php, args.mount || []);\n\t\t\t\t} else {\n\t\t\t\t\t// NOTE: Today (2025-09-11), during boot with a plugin auto-mount,\n\t\t\t\t\t// the Blueprint runner fails unless post-resolution mounts are\n\t\t\t\t\t// added to existing PHP instances. So we track them here so they\n\t\t\t\t\t// can be mounted at the necessary time.\n\t\t\t\t\t// Only plugin auto-mounts seem to need this, so perhaps there\n\t\t\t\t\t// is a change we can make to the Blueprint runner so such\n\t\t\t\t\t// a dance is unnecessary.\n\t\t\t\t\tthis.phpInstancesThatNeedMountsAfterTargetResolved.add(php);\n\t\t\t\t\tphp.addEventListener('runtime.beforeExit', () => {\n\t\t\t\t\t\tthis.phpInstancesThatNeedMountsAfterTargetResolved.delete(\n\t\t\t\t\t\t\tphp\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\tawait this.bootRequestHandler(requestHandlerOptions);\n\n\t\tconst primaryPhp = this.__internal_getPHP()!;\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: SecondaryWorkerBootArgs) {\n\t\tawait this.bootRequestHandler({\n\t\t\t...args,\n\t\t\tonPHPInstanceCreated: async (php: PHP) => {\n\t\t\t\tawait mountResources(php, args.mountsBeforeWpInstall || []);\n\t\t\t\tawait mountResources(php, args.mountsAfterWpInstall || []);\n\t\t\t},\n\t\t});\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\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 (!this.blueprintTargetResolved) {\n\t\t\t\t\t\t\t\tthis.blueprintTargetResolved = true;\n\t\t\t\t\t\t\t\tfor (const php of this\n\t\t\t\t\t\t\t\t\t.phpInstancesThatNeedMountsAfterTargetResolved) {\n\t\t\t\t\t\t\t\t\t// console.log('mounting resources for php', php);\n\t\t\t\t\t\t\t\t\tthis.phpInstancesThatNeedMountsAfterTargetResolved.delete(\n\t\t\t\t\t\t\t\t\t\tphp\n\t\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\t\tawait mountResources(php, args.mount || []);\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\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\tphpVersion,\n\t\tcreateFiles,\n\t\tconstants,\n\t\tphpIniEntries,\n\t\tfirstProcessId,\n\t\tprocessIdSpaceLength,\n\t\ttrace,\n\t\tnativeInternalDirPath,\n\t\twithXdebug,\n\t\tonPHPInstanceCreated,\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 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(phpVersion, {\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\tphpWasmInitOptions: { nativeInternalDirPath },\n\t\t\t\t\t\t},\n\t\t\t\t\t\tfollowSymlinks: allow?.includes('follow-symlinks'),\n\t\t\t\t\t\twithXdebug,\n\t\t\t\t\t});\n\t\t\t\t},\n\t\t\t\tonPHPInstanceCreated,\n\t\t\t\tsapiName: 'cli',\n\t\t\t\tcreateFiles,\n\t\t\t\tconstants,\n\t\t\t\tphpIniEntries,\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\nprocess.on('unhandledRejection', (e: any) => {\n\tlogger.error('Unhandled rejection:', e);\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":["mountResources","php","mounts","mount","createNodeFsMountHandler","output","tracePhpWasm","processId","format","args","sprintf","data","PlaygroundCliBlueprintV2Worker","PHPWorker","monitor","port","jspi","consumeAPI","consumeAPISync","constants","requestHandlerOptions","rootCertificates","primaryPhp","requestHandler","reap","unmountCwd","blueprintPath","path","existsSync","cliArgs","arg","streamedResponse","runBlueprintV2","message","progressMessage","red","bold","reset","chunk","syncResponse","PHPResponse","PHPExecutionFailureError","error","phpLogs","errorLogPath","siteUrl","allow","phpVersion","createFiles","phpIniEntries","firstProcessId","processIdSpaceLength","trace","nativeInternalDirPath","withXdebug","onPHPInstanceCreated","nextProcessId","lastProcessId","bootRequestHandler","loadNodeRuntime","sandboxedSpawnHandlerFactory","setApiReady","e","setAPIError","logger","phpChannel","MessageChannel","exposeAPI","EmscriptenDownloadMonitor","parentPort"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"worker-thread-v2.js","sources":["../../../../packages/playground/cli/src/blueprints-v2/worker-thread-v2.ts"],"sourcesContent":["import { errorLogPath, logger } 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 {\n\tPHP,\n\tFileTree,\n\tRemoteAPI,\n\tSupportedPHPVersion,\n} 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 {\n\ttype BlueprintMessage,\n\trunBlueprintV2,\n\ttype BlueprintV1Declaration,\n} from '@wp-playground/blueprints';\nimport {\n\ttype ParsedBlueprintV2String,\n\ttype RawBlueprintV2Data,\n} from '@wp-playground/blueprints';\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';\nimport type {\n\tPhpIniOptions,\n\tPHPInstanceCreatedHook,\n} from '@wp-playground/wordpress';\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 PrimaryWorkerBootArgs = RunCLIArgs & {\n\tphpVersion: SupportedPHPVersion;\n\tsiteUrl: string;\n\tfirstProcessId: number;\n\tprocessIdSpaceLength: number;\n\ttrace: boolean;\n\tblueprint:\n\t\t| RawBlueprintV2Data\n\t\t| ParsedBlueprintV2String\n\t\t| BlueprintV1Declaration;\n\tnativeInternalDirPath: string;\n};\n\ntype WorkerRunBlueprintArgs = RunCLIArgs & {\n\tsiteUrl: string;\n\tblueprint:\n\t\t| RawBlueprintV2Data\n\t\t| ParsedBlueprintV2String\n\t\t| BlueprintV1Declaration;\n};\n\nexport type SecondaryWorkerBootArgs = {\n\tsiteUrl: string;\n\tallow?: string;\n\tphpVersion: SupportedPHPVersion;\n\tphpIniEntries?: PhpIniOptions;\n\tconstants?: Record<string, string | number | boolean | null>;\n\tcreateFiles?: FileTree;\n\tfirstProcessId: number;\n\tprocessIdSpaceLength: number;\n\ttrace: boolean;\n\tnativeInternalDirPath: string;\n\twithXdebug?: boolean;\n\tmountsBeforeWpInstall?: Array<Mount>;\n\tmountsAfterWpInstall?: Array<Mount>;\n};\n\nexport type WorkerBootRequestHandlerOptions = Omit<\n\tSecondaryWorkerBootArgs,\n\t'mountsBeforeWpInstall' | 'mountsAfterWpInstall'\n> & {\n\tonPHPInstanceCreated: PHPInstanceCreatedHook;\n};\n\nexport class PlaygroundCliBlueprintV2Worker extends PHPWorker {\n\tbooted = false;\n\tblueprintTargetResolved = false;\n\tphpInstancesThatNeedMountsAfterTargetResolved = new Set<PHP>();\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: PrimaryWorkerBootArgs) {\n\t\tconst constants = {\n\t\t\tWP_DEBUG: true,\n\t\t\tWP_DEBUG_LOG: true,\n\t\t\tWP_DEBUG_DISPLAY: false,\n\t\t};\n\t\tconst requestHandlerOptions: WorkerBootRequestHandlerOptions = {\n\t\t\t...args,\n\t\t\tcreateFiles: {\n\t\t\t\t'/internal/shared/ca-bundle.crt': rootCertificates.join('\\n'),\n\t\t\t},\n\t\t\tconstants,\n\t\t\tphpIniEntries: {\n\t\t\t\t'openssl.cafile': '/internal/shared/ca-bundle.crt',\n\t\t\t},\n\t\t\tonPHPInstanceCreated: async (php: PHP) => {\n\t\t\t\tawait mountResources(php, args['mount-before-install'] || []);\n\t\t\t\tif (this.blueprintTargetResolved) {\n\t\t\t\t\tawait mountResources(php, args.mount || []);\n\t\t\t\t} else {\n\t\t\t\t\t// NOTE: Today (2025-09-11), during boot with a plugin auto-mount,\n\t\t\t\t\t// the Blueprint runner fails unless post-resolution mounts are\n\t\t\t\t\t// added to existing PHP instances. So we track them here so they\n\t\t\t\t\t// can be mounted at the necessary time.\n\t\t\t\t\t// Only plugin auto-mounts seem to need this, so perhaps there\n\t\t\t\t\t// is a change we can make to the Blueprint runner so such\n\t\t\t\t\t// a dance is unnecessary.\n\t\t\t\t\tthis.phpInstancesThatNeedMountsAfterTargetResolved.add(php);\n\t\t\t\t\tphp.addEventListener('runtime.beforeExit', () => {\n\t\t\t\t\t\tthis.phpInstancesThatNeedMountsAfterTargetResolved.delete(\n\t\t\t\t\t\t\tphp\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\tawait this.bootRequestHandler(requestHandlerOptions);\n\n\t\tconst primaryPhp = this.__internal_getPHP()!;\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: SecondaryWorkerBootArgs) {\n\t\tawait this.bootRequestHandler({\n\t\t\t...args,\n\t\t\tonPHPInstanceCreated: async (php: PHP) => {\n\t\t\t\tawait mountResources(php, args.mountsBeforeWpInstall || []);\n\t\t\t\tawait mountResources(php, args.mountsAfterWpInstall || []);\n\t\t\t},\n\t\t});\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\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 (!this.blueprintTargetResolved) {\n\t\t\t\t\t\t\t\tthis.blueprintTargetResolved = true;\n\t\t\t\t\t\t\t\tfor (const php of this\n\t\t\t\t\t\t\t\t\t.phpInstancesThatNeedMountsAfterTargetResolved) {\n\t\t\t\t\t\t\t\t\t// console.log('mounting resources for php', php);\n\t\t\t\t\t\t\t\t\tthis.phpInstancesThatNeedMountsAfterTargetResolved.delete(\n\t\t\t\t\t\t\t\t\t\tphp\n\t\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\t\tawait mountResources(php, args.mount || []);\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\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\tphpVersion,\n\t\tcreateFiles,\n\t\tconstants,\n\t\tphpIniEntries,\n\t\tfirstProcessId,\n\t\tprocessIdSpaceLength,\n\t\ttrace,\n\t\tnativeInternalDirPath,\n\t\twithXdebug,\n\t\tonPHPInstanceCreated,\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 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(phpVersion, {\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\tphpWasmInitOptions: { nativeInternalDirPath },\n\t\t\t\t\t\t},\n\t\t\t\t\t\tfollowSymlinks: allow?.includes('follow-symlinks'),\n\t\t\t\t\t\twithXdebug,\n\t\t\t\t\t});\n\t\t\t\t},\n\t\t\t\tonPHPInstanceCreated,\n\t\t\t\tsapiName: 'cli',\n\t\t\t\tcreateFiles,\n\t\t\t\tconstants,\n\t\t\t\tphpIniEntries,\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\nprocess.on('unhandledRejection', (e: any) => {\n\tlogger.error('Unhandled rejection:', e);\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":["mountResources","php","mounts","mount","createNodeFsMountHandler","output","tracePhpWasm","processId","format","args","sprintf","data","PlaygroundCliBlueprintV2Worker","PHPWorker","monitor","port","jspi","consumeAPI","consumeAPISync","constants","requestHandlerOptions","rootCertificates","primaryPhp","requestHandler","reap","unmountCwd","blueprintPath","path","existsSync","cliArgs","arg","streamedResponse","runBlueprintV2","message","progressMessage","red","bold","reset","chunk","syncResponse","PHPResponse","PHPExecutionFailureError","error","phpLogs","errorLogPath","siteUrl","allow","phpVersion","createFiles","phpIniEntries","firstProcessId","processIdSpaceLength","trace","nativeInternalDirPath","withXdebug","onPHPInstanceCreated","nextProcessId","lastProcessId","bootRequestHandler","loadNodeRuntime","sandboxedSpawnHandlerFactory","setApiReady","e","setAPIError","logger","phpChannel","MessageChannel","exposeAPI","EmscriptenDownloadMonitor","parentPort"],"mappings":";;;;;;;;;;;;AA0CA,eAAeA,EAAeC,GAAUC,GAAiB;AACxD,aAAWC,KAASD;AACf,QAAA;AACC,MAAAD,EAAA,MAAME,EAAM,OAAO,GACvB,MAAMF,EAAI;AAAA,QACTE,EAAM;AAAA,QACNC,EAAyBD,EAAM,QAAQ;AAAA,MACxC;AAAA,IAAA,QACO;AACA,MAAAE,EAAA;AAAA,QACN,sCAAsCF,EAAM,QAAQ,OAAOA,EAAM,OAAO;AAAA;AAAA,MACzE,GACA,QAAQ,KAAK,CAAC;AAAA,IAAA;AAGjB;AASA,SAASG,EAAaC,GAAmBC,MAAmBC,GAAa;AAEhE,UAAA;AAAA,IACP,YAAY,MAAM,QAAQ,CAAC,EAAE,SAAS,IAAI,GAAG;AAAA,IAC7CF,EAAU,SAAW,EAAA,SAAS,IAAI,GAAG;AAAA,IACrCG,EAAQF,GAAQ,GAAGC,CAAI;AAAA,EACxB;AACD;AAUA,OAAO,eAAe,QAAQ,QAAQ,SAAS,EAAE,OAAO,IAAM;AAC9D,OAAO,eAAe,QAAQ,QAAQ,SAAS,EAAE,OAAO,IAAM;AAK9D,MAAMJ,IAAS;AAAA,EACd,sBAAsB;AAAA,EACtB,SAASM,GAAc;AAClB,IAAC,QAAQ,OAAO,SAIdN,EAAO,wBACH,QAAA,OAAO,MAAM;AAAA,CAAI,GAElB,QAAA,OAAO,MAAM,aAAaM,CAAI,GACtCN,EAAO,uBAAuB,MAN9B,QAAQ,IAAIM,CAAI;AAAA,EAQlB;AAAA,EACA,OAAOA,GAAc;AACpB,IAAIN,EAAO,yBACF,QAAA,OAAO,MAAM;AAAA,CAAI,GACzBA,EAAO,uBAAuB,KAEvB,QAAA,OAAO,MAAMM,CAAI;AAAA,EAC1B;AAAA,EACA,OAAOA,GAAc;AACpB,IAAIN,EAAO,yBACF,QAAA,OAAO,MAAM;AAAA,CAAI,GACzBA,EAAO,uBAAuB,KAEvB,QAAA,OAAO,MAAMM,CAAI;AAAA,EAAA;AAE3B;AA8CO,MAAMC,UAAuCC,EAAU;AAAA,EAM7D,YAAYC,GAAoC;AAC/C,UAAM,QAAWA,CAAO,GANhB,KAAA,SAAA,IACiB,KAAA,0BAAA,IAC1B,KAAA,oEAAoD,IAAS;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAgB7D,MAAM,mBAAmBC,GAAmB;AACvC,IAAA,MAAMC,MASJ,KAAA,kBAAkBC,EAA4BF,CAAI,IAUlD,KAAA,kBAAkB,MAAMG,EAAgCH,CAAI;AAAA,EAClE;AAAA,EAGD,MAAM,oBAAoBN,GAA6B;AACtD,UAAMU,IAAY;AAAA,MACjB,UAAU;AAAA,MACV,cAAc;AAAA,MACd,kBAAkB;AAAA,IACnB,GACMC,IAAyD;AAAA,MAC9D,GAAGX;AAAA,MACH,aAAa;AAAA,QACZ,kCAAkCY,EAAiB,KAAK;AAAA,CAAI;AAAA,MAC7D;AAAA,MACA,WAAAF;AAAA,MACA,eAAe;AAAA,QACd,kBAAkB;AAAA,MACnB;AAAA,MACA,sBAAsB,OAAOlB,MAAa;AACzC,cAAMD,EAAeC,GAAKQ,EAAK,sBAAsB,KAAK,CAAA,CAAE,GACxD,KAAK,0BACR,MAAMT,EAAeC,GAAKQ,EAAK,SAAS,CAAA,CAAE,KASrC,KAAA,8CAA8C,IAAIR,CAAG,GACtDA,EAAA,iBAAiB,sBAAsB,MAAM;AAChD,eAAK,8CAA8C;AAAA,YAClDA;AAAA,UACD;AAAA,QAAA,CACA;AAAA,MACF;AAAA,IAEF;AACM,UAAA,KAAK,mBAAmBmB,CAAqB;AAE7C,UAAAE,IAAa,KAAK,kBAAkB;AAEtC,QAAAb,EAAK,SAAS,cAAc;AAC/B,YAAMT,EAAesB,GAAYb,EAAK,SAAS,CAAA,CAAE;AACjD;AAAA,IAAA;AAGK,UAAA,KAAK,eAAeA,CAAI;AAAA,EAAA;AAAA,EAG/B,MAAM,sBAAsBA,GAA+B;AAC1D,UAAM,KAAK,mBAAmB;AAAA,MAC7B,GAAGA;AAAA,MACH,sBAAsB,OAAOR,MAAa;AACzC,cAAMD,EAAeC,GAAKQ,EAAK,yBAAyB,CAAA,CAAE,GAC1D,MAAMT,EAAeC,GAAKQ,EAAK,wBAAwB,CAAA,CAAE;AAAA,MAAA;AAAA,IAC1D,CACA;AAAA,EAAA;AAAA,EAGF,MAAM,eAAeA,GAA8B;AAC5C,UAAAc,IAAiB,KAAK,6BAA6B,GACnD,EAAE,KAAAtB,GAAK,MAAAuB,EAAA,IACZ,MAAMD,EAAe,eAAe,mBAAmB;AAAA,MACtD,iBAAiB;AAAA,IAAA,CACjB,GAIID,IAAa,KAAK,kBAAkB;AAC1C,QAAIG,IAAa,MAAM;AAAA,IAAC;AACpB,QAAA,OAAOhB,EAAK,aAAc,UAAU;AACvC,YAAMiB,IAAgBC,EAAK,QAAQ,QAAQ,IAAI,GAAGlB,EAAK,SAAS;AAC5D,MAAAmB,EAAWF,CAAa,MAC3BJ,EAAW,MAAM,sBAAsB,GACvCG,IAAa,MAAMH,EAAW;AAAA,QAC7B;AAAA,QACAlB,EAAyBuB,EAAK,QAAQD,CAAa,CAAC;AAAA,MACrD,GACAjB,EAAK,YAAYkB,EAAK;AAAA,QACrB;AAAA,QACAA,EAAK,SAASlB,EAAK,SAAS;AAAA,MAC7B;AAAA,IACD;AAGG,QAAA;AAYH,YAAMoB,IAXkD;AAAA,QACvD;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACD,EAEE,OAAO,CAACC,MAAQA,KAAOrB,CAAI,EAC3B,IAAI,CAACqB,MAAQ,KAAKA,CAAG,IAAIrB,EAAKqB,CAAG,CAAC,EAAE;AACtC,MAAAD,EAAQ,KAAK,cAAcpB,EAAK,OAAO,EAAE;AAEnC,YAAAsB,IAAmB,MAAMC,EAAe;AAAA,QAC7C,KAAA/B;AAAA,QACA,WAAWQ,EAAK;AAAA,QAChB,oBAAoB;AAAA,UACnB,iBAAiBA,EAAK,4BAA4B;AAAA,UAClD,kBAAkBA,EAAK;AAAA,QACxB;AAAA,QACA,SAAAoB;AAAA,QACA,WAAW,OAAOI,MAA8B;AAC/C,kBAAQA,EAAQ,MAAM;AAAA,YACrB,KAAK,6BAA6B;AAC7B,kBAAA,CAAC,KAAK,yBAAyB;AAClC,qBAAK,0BAA0B;AACpBhC,2BAAAA,KAAO,KAChB;AAED,uBAAK,8CAA8C;AAAA,oBAClDA;AAAAA,kBACD,GACA,MAAMD,EAAeC,GAAKQ,EAAK,SAAS,CAAA,CAAE;AAAA,cAC3C;AAED;AAAA,YAAA;AAAA,YAED,KAAK,sBAAsB;AACpB,oBAAAyB,IAAkB,GAAGD,EAAQ,QAAQ,MAAM,MAAMA,EAAQ,SAAS;AAAA,gBACvE;AAAA,cACA,CAAA;AACD,cAAA5B,EAAO,SAAS6B,CAAe;AAC/B;AAAA,YAAA;AAAA,YAED,KAAK,mBAAmB;AACvB,oBAAMC,IAAM,YACNC,IAAO,WACPC,IAAQ;AACV,cAAA5B,EAAK,SAASwB,EAAQ,UAClB5B,EAAA;AAAA,gBACN,GAAG8B,CAAG,GAAGC,CAAI,eAAeC,CAAK,aAAaJ,EAAQ,QAAQ,SAAS,KAAKA,EAAQ,QAAQ,OAAO;AAAA,OAC1FA,EAAQ,QAAQ,IAAI,IAAIA,EAAQ,QAAQ,IAAI;AAAA,KACnDA,EAAQ,QAAQ,QACdA,EAAQ,QAAQ,QAAQ;AAAA,IACxB;AAAA,cACL,IAEO5B,EAAA;AAAA,gBACN,GAAG8B,CAAG,GAAGC,CAAI,SAASC,CAAK,IAAIJ,EAAQ,OAAO;AAAA;AAAA,cAC/C;AAED;AAAA,YAAA;AAAA,UACD;AAAA,QACD;AAAA,MACD,CACA;AAsBI,UAjBDxB,EAAK,UACRsB,EAAkB,OAAO;AAAA,QACxB,IAAI,eAAe;AAAA,UAClB,MAAMO,GAAO;AACJ,oBAAA,OAAO,MAAMA,CAAK;AAAA,UAAA;AAAA,QAE3B,CAAA;AAAA,MACF,GACAP,EAAkB,OAAO;AAAA,QACxB,IAAI,eAAe;AAAA,UAClB,MAAMO,GAAO;AACJ,oBAAA,OAAO,MAAMA,CAAK;AAAA,UAAA;AAAA,QAE3B,CAAA;AAAA,MACF,IAED,MAAMP,EAAkB,UACnB,MAAMA,EAAkB,aAAc,GAAG;AAGvC,cAAAQ,IAAe,MAAMC,EAAY;AAAA,UACtCT;AAAA,QACD;AACA,cAAM,IAAIU;AAAA,UACT,mCAAmCF,EAAa,QAAQ;AAAA,UACxDA;AAAA,UACA;AAAA,QACD;AAAA,MAAA;AAAA,aAEOG,GAAO;AAEf,UAAIC,IAAU;AACV,UAAA;AAGO,QAAAA,IAAA1C,EAAI,eAAe2C,CAAY;AAAA,MAAA,QAClC;AAAA,MAAA;AAGP,YAAAF,EAAc,UAAUC,GACnBD;AAAA,IAAA,UACL;AACI,MAAAlB,EAAA,GACMC,EAAA;AAAA,IAAA;AAAA,EACZ;AAAA,EAGD,MAAM,mBAAmB;AAAA,IACxB,SAAAoB;AAAA,IACA,OAAAC;AAAA,IACA,YAAAC;AAAA,IACA,aAAAC;AAAA,IACA,WAAA7B;AAAA,IACA,eAAA8B;AAAA,IACA,gBAAAC;AAAA,IACA,sBAAAC;AAAA,IACA,OAAAC;AAAA,IACA,uBAAAC;AAAA,IACA,YAAAC;AAAA,IACA,sBAAAC;AAAA,EAAA,GACmC;AACnC,QAAI,KAAK;AACF,YAAA,IAAI,MAAM,2BAA2B;AAE5C,SAAK,SAAS;AAEd,QAAIC,IAAgBN;AACd,UAAAO,IAAgBP,IAAiBC,IAAuB;AAE1D,QAAA;AACG,YAAA5B,IAAiB,MAAMmC,EAAmB;AAAA,QAC/C,SAAAb;AAAA,QACA,kBAAkB,YAAY;AAC7B,gBAAMtC,IAAYiD;AAElB,iBAAIA,IAAgBC,IACnBD,MAGgBA,IAAAN,GAGV,MAAMS,EAAgBZ,GAAY;AAAA,YACxC,mBAAmB;AAAA,cAClB,iBAAiB,KAAK;AAAA,cACtB,WAAAxC;AAAA,cACA,OAAO6C,IAAQ9C,IAAe;AAAA,cAC9B,KAAK;AAAA,gBACJ,SAAS;AAAA,cACV;AAAA,cACA,oBAAoB,EAAE,uBAAA+C,EAAsB;AAAA,YAC7C;AAAA,YACA,gBAAgBP,GAAO,SAAS,iBAAiB;AAAA,YACjD,YAAAQ;AAAA,UAAA,CACA;AAAA,QACF;AAAA,QACA,sBAAAC;AAAA,QACA,UAAU;AAAA,QACV,aAAAP;AAAA,QACA,WAAA7B;AAAA,QACA,eAAA8B;AAAA,QACA,aAAa;AAAA,QACb,cAAcW;AAAA,MAAA,CACd;AACD,WAAK,6BAA6BrC,CAAc;AAE1C,YAAAD,IAAa,MAAMC,EAAe,cAAc;AAChD,YAAA,KAAK,cAAcD,CAAU,GAEvBuC,EAAA;AAAA,aACJC,GAAG;AACX,YAAAC,EAAYD,CAAU,GAChBA;AAAA,IAAA;AAAA,EACP;AAAA;AAAA,EAID,MAAM,UAAU;AACT,UAAA,KAAK,OAAO,YAAY,EAAE;AAAA,EAAA;AAElC;AAEA,QAAQ,GAAG,sBAAsB,CAACA,MAAW;AACrC,EAAAE,EAAA,MAAM,wBAAwBF,CAAC;AACvC,CAAC;AAED,MAAMG,IAAa,IAAIC,EAAe,GAEhC,CAACL,GAAaE,CAAW,IAAII;AAAA,EAClC,IAAIvD,EAA+B,IAAIwD,GAA2B;AAAA,EAClE;AAAA,EACAH,EAAW;AACZ;AAEAI,GAAY;AAAA,EACX;AAAA,IACC,SAAS;AAAA,IACT,SAASJ,EAAW;AAAA,EACrB;AAAA,EACA,CAACA,EAAW,KAAY;AACzB;"}
1
+ {"version":3,"file":"worker-thread-v2.js","sources":["../../../../packages/playground/cli/src/blueprints-v2/worker-thread-v2.ts"],"sourcesContent":["import { errorLogPath, logger } 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 {\n\tPHP,\n\tFileTree,\n\tRemoteAPI,\n\tSupportedPHPVersion,\n} 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 {\n\ttype BlueprintMessage,\n\trunBlueprintV2,\n\ttype BlueprintV1Declaration,\n} from '@wp-playground/blueprints';\nimport {\n\ttype ParsedBlueprintV2String,\n\ttype RawBlueprintV2Data,\n} from '@wp-playground/blueprints';\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';\nimport type {\n\tPhpIniOptions,\n\tPHPInstanceCreatedHook,\n} from '@wp-playground/wordpress';\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 PrimaryWorkerBootArgs = RunCLIArgs & {\n\tphpVersion: SupportedPHPVersion;\n\tsiteUrl: string;\n\tfirstProcessId: number;\n\tprocessIdSpaceLength: number;\n\ttrace: boolean;\n\tblueprint:\n\t\t| RawBlueprintV2Data\n\t\t| ParsedBlueprintV2String\n\t\t| BlueprintV1Declaration;\n\tnativeInternalDirPath: string;\n};\n\ntype WorkerRunBlueprintArgs = RunCLIArgs & {\n\tsiteUrl: string;\n\tblueprint:\n\t\t| RawBlueprintV2Data\n\t\t| ParsedBlueprintV2String\n\t\t| BlueprintV1Declaration;\n};\n\nexport type SecondaryWorkerBootArgs = {\n\tsiteUrl: string;\n\tallow?: string;\n\tphpVersion: SupportedPHPVersion;\n\tphpIniEntries?: PhpIniOptions;\n\tconstants?: Record<string, string | number | boolean | null>;\n\tcreateFiles?: FileTree;\n\tfirstProcessId: number;\n\tprocessIdSpaceLength: number;\n\ttrace: boolean;\n\tnativeInternalDirPath: string;\n\twithXdebug?: boolean;\n\tmountsBeforeWpInstall?: Array<Mount>;\n\tmountsAfterWpInstall?: Array<Mount>;\n};\n\nexport type WorkerBootRequestHandlerOptions = Omit<\n\tSecondaryWorkerBootArgs,\n\t'mountsBeforeWpInstall' | 'mountsAfterWpInstall'\n> & {\n\tonPHPInstanceCreated: PHPInstanceCreatedHook;\n};\n\nexport class PlaygroundCliBlueprintV2Worker extends PHPWorker {\n\tbooted = false;\n\tblueprintTargetResolved = false;\n\tphpInstancesThatNeedMountsAfterTargetResolved = new Set<PHP>();\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: PrimaryWorkerBootArgs) {\n\t\tconst constants = {\n\t\t\tWP_DEBUG: true,\n\t\t\tWP_DEBUG_LOG: true,\n\t\t\tWP_DEBUG_DISPLAY: false,\n\t\t};\n\t\tconst requestHandlerOptions: WorkerBootRequestHandlerOptions = {\n\t\t\t...args,\n\t\t\tcreateFiles: {\n\t\t\t\t'/internal/shared/ca-bundle.crt': rootCertificates.join('\\n'),\n\t\t\t},\n\t\t\tconstants,\n\t\t\tphpIniEntries: {\n\t\t\t\t'openssl.cafile': '/internal/shared/ca-bundle.crt',\n\t\t\t},\n\t\t\tonPHPInstanceCreated: async (php: PHP) => {\n\t\t\t\tawait mountResources(php, args['mount-before-install'] || []);\n\t\t\t\tif (this.blueprintTargetResolved) {\n\t\t\t\t\tawait mountResources(php, args.mount || []);\n\t\t\t\t} else {\n\t\t\t\t\t// NOTE: Today (2025-09-11), during boot with a plugin auto-mount,\n\t\t\t\t\t// the Blueprint runner fails unless post-resolution mounts are\n\t\t\t\t\t// added to existing PHP instances. So we track them here so they\n\t\t\t\t\t// can be mounted at the necessary time.\n\t\t\t\t\t// Only plugin auto-mounts seem to need this, so perhaps there\n\t\t\t\t\t// is a change we can make to the Blueprint runner so such\n\t\t\t\t\t// a dance is unnecessary.\n\t\t\t\t\tthis.phpInstancesThatNeedMountsAfterTargetResolved.add(php);\n\t\t\t\t\tphp.addEventListener('runtime.beforeExit', () => {\n\t\t\t\t\t\tthis.phpInstancesThatNeedMountsAfterTargetResolved.delete(\n\t\t\t\t\t\t\tphp\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\tawait this.bootRequestHandler(requestHandlerOptions);\n\n\t\tconst primaryPhp = this.__internal_getPHP()!;\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: SecondaryWorkerBootArgs) {\n\t\tawait this.bootRequestHandler({\n\t\t\t...args,\n\t\t\tonPHPInstanceCreated: async (php: PHP) => {\n\t\t\t\tawait mountResources(php, args.mountsBeforeWpInstall || []);\n\t\t\t\tawait mountResources(php, args.mountsAfterWpInstall || []);\n\t\t\t},\n\t\t});\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\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 (!this.blueprintTargetResolved) {\n\t\t\t\t\t\t\t\tthis.blueprintTargetResolved = true;\n\t\t\t\t\t\t\t\tfor (const php of this\n\t\t\t\t\t\t\t\t\t.phpInstancesThatNeedMountsAfterTargetResolved) {\n\t\t\t\t\t\t\t\t\t// console.log('mounting resources for php', php);\n\t\t\t\t\t\t\t\t\tthis.phpInstancesThatNeedMountsAfterTargetResolved.delete(\n\t\t\t\t\t\t\t\t\t\tphp\n\t\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\t\tawait mountResources(php, args.mount || []);\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\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\tphpVersion,\n\t\tcreateFiles,\n\t\tconstants,\n\t\tphpIniEntries,\n\t\tfirstProcessId,\n\t\tprocessIdSpaceLength,\n\t\ttrace,\n\t\tnativeInternalDirPath,\n\t\twithXdebug,\n\t\tonPHPInstanceCreated,\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 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(phpVersion, {\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\tphpWasmInitOptions: { nativeInternalDirPath },\n\t\t\t\t\t\t},\n\t\t\t\t\t\tfollowSymlinks: allow?.includes('follow-symlinks'),\n\t\t\t\t\t\twithXdebug,\n\t\t\t\t\t});\n\t\t\t\t},\n\t\t\t\tonPHPInstanceCreated,\n\t\t\t\tsapiName: 'cli',\n\t\t\t\tcreateFiles,\n\t\t\t\tconstants,\n\t\t\t\tphpIniEntries,\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\nprocess.on('unhandledRejection', (e: any) => {\n\tlogger.error('Unhandled rejection:', e);\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":["mountResources","php","mounts","mount","createNodeFsMountHandler","output","tracePhpWasm","processId","format","args","sprintf","data","PlaygroundCliBlueprintV2Worker","PHPWorker","monitor","port","jspi","consumeAPI","consumeAPISync","constants","requestHandlerOptions","rootCertificates","primaryPhp","requestHandler","reap","unmountCwd","blueprintPath","path","existsSync","cliArgs","arg","streamedResponse","runBlueprintV2","message","progressMessage","red","bold","reset","chunk","syncResponse","PHPResponse","PHPExecutionFailureError","error","phpLogs","errorLogPath","siteUrl","allow","phpVersion","createFiles","phpIniEntries","firstProcessId","processIdSpaceLength","trace","nativeInternalDirPath","withXdebug","onPHPInstanceCreated","nextProcessId","lastProcessId","bootRequestHandler","loadNodeRuntime","sandboxedSpawnHandlerFactory","setApiReady","e","setAPIError","logger","phpChannel","MessageChannel","exposeAPI","EmscriptenDownloadMonitor","parentPort"],"mappings":"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"}
@@ -0,0 +1,90 @@
1
+ import { type Mount } from './mounts';
2
+ /**
3
+ * Create a symlink to temp dir for the Playground CLI.
4
+ *
5
+ * The symlink is created to access the system temp dir
6
+ * inside the current debugging directory.
7
+ *
8
+ * @param nativeDirPath The system temp dir path.
9
+ * @param symlinkPath The symlink name.
10
+ */
11
+ export declare function createPlaygroundCliTempDirSymlink(nativeDirPath: string, symlinkPath: string, platform: string): Promise<void>;
12
+ /**
13
+ * Remove the temp dir symlink if it exists.
14
+ *
15
+ * @param symlinkPath The symlink path.
16
+ */
17
+ export declare function removePlaygroundCliTempDirSymlink(symlinkPath: string): Promise<void>;
18
+ export type IDEConfig = {
19
+ /**
20
+ * The name of the configuration within the IDE configuration.
21
+ */
22
+ name: string;
23
+ /**
24
+ * The IDEs to configure.
25
+ */
26
+ ides: string[];
27
+ /**
28
+ * The web server host.
29
+ */
30
+ host: string;
31
+ /**
32
+ * The web server port.
33
+ */
34
+ port: number;
35
+ /**
36
+ * The current working directory to consider for debugger path mapping.
37
+ */
38
+ cwd: string;
39
+ /**
40
+ * The mounts to consider for debugger path mapping.
41
+ */
42
+ mounts: Mount[];
43
+ /**
44
+ * The IDE key to use for the debug configuration. Defaults to 'PLAYGROUNDCLI'.
45
+ */
46
+ ideKey?: string;
47
+ };
48
+ export type PhpStormConfigOptions = {
49
+ name: string;
50
+ host: string;
51
+ port: number;
52
+ mappings: Mount[];
53
+ ideKey: string;
54
+ };
55
+ /**
56
+ * Pure function to update PHPStorm XML config with XDebug server and run configuration.
57
+ *
58
+ * @param xmlContent The original XML content of workspace.xml
59
+ * @param options Configuration options for the server
60
+ * @returns Updated XML content
61
+ * @throws Error if XML is invalid or configuration is incompatible
62
+ */
63
+ export declare function updatePhpStormConfig(xmlContent: string, options: PhpStormConfigOptions): string;
64
+ export type VSCodeConfigOptions = {
65
+ name: string;
66
+ mappings: Mount[];
67
+ };
68
+ /**
69
+ * Pure function to update VS Code launch.json config with XDebug configuration.
70
+ *
71
+ * @param jsonContent The original JSON content of launch.json
72
+ * @param options Configuration options
73
+ * @returns Updated JSON content
74
+ * @throws Error if JSON is invalid
75
+ */
76
+ export declare function updateVSCodeConfig(jsonContent: string, options: VSCodeConfigOptions): string;
77
+ /**
78
+ * Implement necessary parameters and path mappings in IDE configuration files.
79
+ *
80
+ * @param name The configuration name.
81
+ * @param mounts The Playground CLI mount options.
82
+ */
83
+ export declare function addXdebugIDEConfig({ name, ides, host, port, cwd, mounts, ideKey, }: IDEConfig): Promise<string[]>;
84
+ /**
85
+ * Remove stale parameters and path mappings in IDE configuration files.
86
+ *
87
+ * @param name The configuration name.
88
+ * @param cwd The current working directory.
89
+ */
90
+ export declare function clearXdebugIDEConfig(name: string, cwd: string): Promise<void>;
@@ -1,27 +0,0 @@
1
- "use strict";var K=Object.create;var _=Object.defineProperty;var ee=Object.getOwnPropertyDescriptor;var te=Object.getOwnPropertyNames;var re=Object.getPrototypeOf,oe=Object.prototype.hasOwnProperty;var ie=(e,r,t,s)=>{if(r&&typeof r=="object"||typeof r=="function")for(let o of te(r))!oe.call(e,o)&&o!==t&&_(e,o,{get:()=>r[o],enumerable:!(s=ee(r,o))||s.enumerable});return e};var se=(e,r,t)=>(t=e!=null?K(re(e)):{},ie(r||!e||!e.__esModule?_(t,"default",{value:e,enumerable:!0}):t,e));const u=require("@php-wasm/logger"),m=require("@php-wasm/universal"),R=require("@wp-playground/blueprints"),F=require("@wp-playground/common"),d=require("fs"),A=require("worker_threads"),M=require("./mounts-BJFrPHGW.cjs"),ne=require("express"),ae=require("@php-wasm/node"),D=require("os"),le=require("wasm-feature-detect"),ue=require("yargs"),f=require("path"),B=require("@wp-playground/storage"),j=require("@php-wasm/progress"),ce=require("@wp-playground/wordpress"),x=require("fs-extra"),pe=require("@php-wasm/xdebug-bridge"),O=require("tmp-promise"),de=require("ps-man");var W=typeof document<"u"?document.currentScript:null;async function fe(e){const r=ne(),t=await new Promise((i,n)=>{const l=r.listen(e.port,()=>{const a=l.address();a===null||typeof a=="string"?n(new Error("Server address is not available")):i(l)})});r.use("/",async(i,n)=>{let l;try{l=await e.handleRequest({url:i.url,headers:me(i),method:i.method,body:await he(i)})}catch(a){u.logger.error(a),l=m.PHPResponse.forHttpCode(500)}n.statusCode=l.httpStatusCode;for(const a in l.headers)n.setHeader(a,l.headers[a]);n.end(l.bytes)});const o=t.address().port;return await e.onBind(t,o)}const he=async e=>await new Promise(r=>{const t=[];e.on("data",s=>{t.push(s)}),e.on("end",()=>{r(new Uint8Array(Buffer.concat(t)))})}),me=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};class we{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 i=this.workerLoads[o];i.activeRequests.size<t.activeRequests.size&&(t=i)}const s=t.worker.request(r);return t.activeRequests.add(s),s.url=r.url,s.finally(()=>{t.activeRequests.delete(s)})}}function ge(e){return/^latest$|^trunk$|^nightly$|^(?:(\d+)\.(\d+)(?:\.(\d+))?)((?:-beta(?:\d+)?)|(?:-RC(?:\d+)?))?$/.test(e)}async function ye({sourceString:e,blueprintMayReadAdjacentFiles:r}){if(!e)return;if(e.startsWith("http://")||e.startsWith("https://"))return await R.resolveRemoteBlueprint(e);let t=f.resolve(process.cwd(),e);if(!d.existsSync(t))throw new Error(`Blueprint file does not exist: ${t}`);const s=d.statSync(t);if(s.isDirectory()&&(t=f.join(t,"blueprint.json")),!s.isFile()&&s.isSymbolicLink())throw new Error(`Blueprint path is neither a file nor a directory: ${t}`);const o=f.extname(t);switch(o){case".zip":return B.ZipFilesystem.fromArrayBuffer(d.readFileSync(t).buffer);case".json":{const i=d.readFileSync(t,"utf-8");try{JSON.parse(i)}catch{throw new Error(`Blueprint file at ${t} is not a valid JSON file`)}const n=f.dirname(t),l=new B.NodeJsFilesystem(n);return new B.OverlayFilesystem([new B.InMemoryFilesystem({"blueprint.json":i}),{read(a){if(!r)throw new Error(`Error: Blueprint contained tried to read a local file at path "${a}" (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 l.read(a)}}])}default:throw new Error(`Unsupported blueprint file extension: ${o}. Only .zip and .json files are supported.`)}}class be{constructor(r,t){this.lastProgressMessage="",this.args=r,this.siteUrl=t.siteUrl,this.processIdSpaceLength=t.processIdSpaceLength,this.phpVersion=r.php}getWorkerType(){return"v2"}async bootPrimaryWorker(r,t,s){const o=m.consumeAPI(r);await o.useFileLockManager(t);const i={...this.args,phpVersion:this.phpVersion,siteUrl:this.siteUrl,firstProcessId:1,processIdSpaceLength:this.processIdSpaceLength,trace:this.args.debug||!1,blueprint:this.args.blueprint,nativeInternalDirPath:s};return await o.bootAsPrimaryWorker(i),o}async bootSecondaryWorker({worker:r,fileLockManagerPort:t,firstProcessId:s,nativeInternalDirPath:o}){const i=m.consumeAPI(r.phpPort);await i.useFileLockManager(t);const n={...this.args,phpVersion:this.phpVersion,siteUrl:this.siteUrl,firstProcessId:s,processIdSpaceLength:this.processIdSpaceLength,trace:this.args.debug||!1,nativeInternalDirPath:o,mountsBeforeWpInstall:this.args["mount-before-install"]||[],mountsAfterWpInstall:this.args.mount||[]};return await i.bootAsSecondaryWorker(n),i}writeProgressUpdate(r,t,s){t!==this.lastProgressMessage&&(this.lastProgressMessage=t,r.isTTY?(r.cursorTo(0),r.write(t),r.clearLine(1),s&&r.write(`
4
- `)):r.write(`${t}
5
- `))}}const q=f.join(D.homedir(),".wordpress-playground");async function Pe(e){return await N("https://github.com/WordPress/sqlite-database-integration/archive/refs/heads/develop.zip","sqlite.zip",e)}async function N(e,r,t){const s=f.join(q,r);return x.existsSync(s)||(x.ensureDirSync(q),await ve(e,s,t)),Z(s)}async function ve(e,r,t){const o=(await t.monitorFetch(fetch(e))).body.getReader(),i=`${r}.partial`,n=x.createWriteStream(i);for(;;){const{done:l,value:a}=await o.read();if(a&&n.write(a),l)break}n.close(),n.closed||await new Promise((l,a)=>{n.on("finish",()=>{x.renameSync(i,r),l(null)}),n.on("error",p=>{x.removeSync(i),a(p)})})}function Z(e,r){return new File([x.readFileSync(e)],f.basename(e))}class ke{constructor(r,t){this.lastProgressMessage="",this.args=r,this.siteUrl=t.siteUrl,this.processIdSpaceLength=t.processIdSpaceLength}getWorkerType(){return"v1"}async bootPrimaryWorker(r,t,s){let o;const i=new j.EmscriptenDownloadMonitor;if(!this.args.skipWordPressSetup){let y=!1;i.addEventListener("progress",T=>{if(y)return;const{loaded:H,total:U}=T.detail,v=Math.floor(Math.min(100,100*H/U));y=v===100,this.writeProgressUpdate(process.stdout,`Downloading WordPress ${v}%...`,y)}),o=await ce.resolveWordPressRelease(this.args.wp),u.logger.log(`Resolved WordPress release URL: ${o?.releaseUrl}`)}const n=o&&f.join(q,`prebuilt-wp-content-for-wp-${o.version}.zip`),l=o?d.existsSync(n)?Z(n):await N(o.releaseUrl,`${o.version}.zip`,i):void 0;u.logger.log("Fetching SQLite integration plugin...");const a=this.args.skipSqliteSetup?void 0:await Pe(i),p=this.args.followSymlinks===!0,b=this.args.experimentalTrace===!0,I=this.args["mount-before-install"]||[],P=this.args.mount||[],w=m.consumeAPI(r);await w.isConnected(),u.logger.log("Booting WordPress...");const L=await R.resolveRuntimeConfiguration(this.getEffectiveBlueprint());return await w.useFileLockManager(t),await w.bootAsPrimaryWorker({phpVersion:L.phpVersion,wpVersion:L.wpVersion,siteUrl:this.siteUrl,mountsBeforeWpInstall:I,mountsAfterWpInstall:P,wordPressZip:l&&await l.arrayBuffer(),sqliteIntegrationPluginZip:await a?.arrayBuffer(),firstProcessId:0,processIdSpaceLength:this.processIdSpaceLength,followSymlinks:p,trace:b,internalCookieStore:this.args.internalCookieStore,withXdebug:this.args.xdebug,nativeInternalDirPath:s}),o&&!this.args["mount-before-install"]&&!d.existsSync(n)&&(u.logger.log("Caching preinstalled WordPress for the next boot..."),d.writeFileSync(n,await F.zipDirectory(w,"/wordpress")),u.logger.log("Cached!")),w}async bootSecondaryWorker({worker:r,fileLockManagerPort:t,firstProcessId:s,nativeInternalDirPath:o}){const i=m.consumeAPI(r.phpPort);return await i.isConnected(),await i.useFileLockManager(t),await i.bootAsSecondaryWorker({phpVersion:this.phpVersion,siteUrl:this.siteUrl,mountsBeforeWpInstall:this.args["mount-before-install"]||[],mountsAfterWpInstall:this.args.mount||[],firstProcessId:s,processIdSpaceLength:this.processIdSpaceLength,followSymlinks:this.args.followSymlinks===!0,trace:this.args.experimentalTrace===!0,internalCookieStore:this.args.internalCookieStore,withXdebug:this.args.xdebug,nativeInternalDirPath:o}),await i.isReady(),i}async compileInputBlueprint(r){const t=this.getEffectiveBlueprint(),s=new j.ProgressTracker;let o="",i=!1;return s.addEventListener("progress",n=>{if(i)return;i=n.detail.progress===100;const l=Math.floor(n.detail.progress);o=n.detail.caption||o||"Running the Blueprint";const a=`${o.trim()} – ${l}%`;this.writeProgressUpdate(process.stdout,a,i)}),await R.compileBlueprintV1(t,{progress:s,additionalSteps:r})}getEffectiveBlueprint(){const r=this.args.blueprint;return R.isBlueprintBundle(r)?r:{login:this.args.login,...r||{},preferredVersions:{php:this.args.php??r?.preferredVersions?.php??F.RecommendedPHPVersion,wp:this.args.wp??r?.preferredVersions?.wp??"latest",...r?.preferredVersions||{}}}}writeProgressUpdate(r,t,s){this.args.verbosity!==E.Quiet.name&&t!==this.lastProgressMessage&&(this.lastProgressMessage=t,r.isTTY?(r.cursorTo(0),r.write(t),r.clearLine(1),s&&r.write(`
6
- `)):r.write(`${t}
7
- `))}}async function Se(e,r=!0){const s=`${f.basename(process.argv0)}${e}${process.pid}-`,o=(await O.dir({prefix:s,unsafeCleanup:!0})).path;return r&&O.setGracefulCleanup(),o}async function We(e,r,t){const o=(await xe(e,r,t)).map(i=>new Promise(n=>{d.rm(i,{recursive:!0},l=>{l?u.logger.warn(`Failed to delete stale Playground temp dir: ${i}`,l):u.logger.info(`Deleted stale Playground temp dir: ${i}`),n()})}));await Promise.all(o)}async function xe(e,r,t){try{const s=d.readdirSync(t).map(i=>f.join(t,i)),o=[];for(const i of s)await Le(e,r,i)&&o.push(i);return o}catch(s){return u.logger.warn(`Failed to find stale Playground temp dirs: ${s}`),[]}}async function Le(e,r,t){if(!d.lstatSync(t).isDirectory())return!1;const o=f.basename(t);if(!o.includes(e))return!1;const i=o.match(new RegExp(`^(.+)${e}(\\d+)-`));if(!i)return!1;const n={executableName:i[1],pid:i[2]};if(await Re(n.pid,n.executableName))return!1;const l=Date.now()-r;return d.statSync(t).mtime.getTime()<l}async function Re(e,r){const[t]=await new Promise((s,o)=>{de.list({pid:e,name:r,clean:!0},(i,n)=>{i?o(i):s(n)})});return!!t&&t.pid===e&&t.command===r}const E={Quiet:{name:"quiet",severity:u.LogSeverity.Fatal},Normal:{name:"normal",severity:u.LogSeverity.Info},Debug:{name:"debug",severity:u.LogSeverity.Debug}};async function Ie(){try{const e=ue(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("site-url",{describe:"Site URL to use for WordPress. Defaults to http://127.0.0.1:{port}",type:"string"}).option("php",{describe:"PHP version to use.",type:"string",default:F.RecommendedPHPVersion,choices:m.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:M.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:M.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:M.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,hidden:!0}).option("verbosity",{describe:"Output logs and progress messages.",type:"string",choices:Object.values(E).map(o=>o.name),default:"normal"}).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 specified directory. If no path is provided, 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:"string"}).option("follow-symlinks",{describe:`Allow Playground to follow symlinks by automatically mounting symlinked directories and files encountered in mounted directories.
8
- Warning: Following symlinks will expose files outside mounted directories to Playground and could be a security risk.`,type:"boolean",default:!1}).option("experimental-trace",{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("experimental-devtools",{describe:"Enable experimental browser development tools.",type:"boolean",default:!1}).option("experimental-multi-worker",{describe:"Enable experimental multi-worker support which requires 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??D.cpus().length-1}).option("experimental-blueprints-v2-runner",{describe:"Use the experimental Blueprint V2 runner.",type:"boolean",default:!1,hidden:!0}).option("mode",{describe:"Blueprints v2 runner mode to use. This option is required when using the --experimental-blueprints-v2-runner flag with a blueprint.",type:"string",choices:["create-new-site","apply-to-existing-site"],hidden:!0}).showHelpOnFail(!1).strictOptions().check(async o=>{if((o["skip-wordpress-setup"]||o.skipWordpressSetup)&&(o.skipWordPressSetup=!0),o.wp!==void 0&&!ge(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["site-url"]!==void 0&&o["site-url"]!=="")try{new URL(o["site-url"])}catch{throw new Error(`Invalid site-url "${o["site-url"]}". Please provide a valid URL (e.g., http://localhost:8080 or https://example.com)`)}if(o["auto-mount"]){let i=!1;try{i=d.statSync(o["auto-mount"]).isDirectory()}catch{i=!1}if(!i)throw new Error(`The specified --auto-mount path is not a directory: '${o["auto-mount"]}'.`)}if(o["experimental-multi-worker"]!==void 0&&o["experimental-multi-worker"]<=1)throw new Error("The --experimental-multi-worker flag must be a positive integer greater than 1.");if(o["experimental-blueprints-v2-runner"]===!0){if(o.mode!==void 0){if("skip-wordpress-setup"in o)throw new Error("The --skipWordPressSetup option cannot be used with the --mode option. Use one or the other.");if("skip-sqlite-setup"in o)throw new Error("The --skipSqliteSetup option is not supported in Blueprint V2 mode.");if(o["auto-mount"]!==void 0)throw new Error("The --mode option cannot be used with --auto-mount because --auto-mount automatically sets the mode.")}else o["skip-wordpress-setup"]===!0?o.mode="apply-to-existing-site":o.mode="create-new-site";const i=o.allow||[];o.followSymlinks===!0&&i.push("follow-symlinks"),o["blueprint-may-read-adjacent-files"]===!0&&i.push("read-local-fs"),o.allow=i}else if(o.mode!==void 0)throw new Error("The --mode option requires the --experimentalBlueprintsV2Runner 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 s={...r,command:t,mount:[...r.mount||[],...r["mount-dir"]||[]],"mount-before-install":[...r["mount-before-install"]||[],...r["mount-dir-before-install"]||[]]};await J(s)}catch(e){if(!(e instanceof Error))throw e;if(process.argv.includes("--debug"))m.printDebugDetails(e);else{const t=[];let s=e;do t.push(s.message),s=s.cause;while(s instanceof Error);console.error("\x1B[1m"+t.join(" caused by ")+"\x1B[0m")}process.exit(1)}}async function J(e){let r,t;const s=[];if(e.autoMount!==void 0&&(e.autoMount===""&&(e={...e,autoMount:process.cwd()}),e=M.expandAutoMounts(e)),e.quiet&&(e.verbosity="quiet",delete e.quiet),e.debug?e.verbosity="debug":e.verbosity==="debug"&&(e.debug=!0),e.verbosity){const a=Object.values(E).find(p=>p.name===e.verbosity).severity;u.logger.setSeverityFilterLevel(a)}const o=D.platform()==="win32"?void 0:await import("fs-ext").then(a=>a.flockSync).catch(()=>{u.logger.warn("The fs-ext package is not installed. Internal file locking will not be integrated with host OS file locking.")}),i=new ae.FileLockManagerForNode(o);let n=!1,l=!0;return u.logger.log("Starting a PHP server..."),fe({port:e.port,onBind:async(a,p)=>{const b=`http://127.0.0.1:${p}`,I=e["site-url"]||b,P=e.experimentalMultiWorker??1,w=Math.floor(Number.MAX_SAFE_INTEGER/P),L="-playground-cli-site-",y=await Se(L);u.logger.debug(`Native temp dir for VFS root: ${y}`);const T=f.dirname(y),U=2*24*60*60*1e3;We(L,U,T);const v=f.join(y,"internal");d.mkdirSync(v);const Q=["wordpress","tmp","home"];for(const c of Q){const g=h=>h.vfsPath===`/${c}`;if(!(e["mount-before-install"]?.some(g)||e.mount?.some(g))){const h=f.join(y,c);d.mkdirSync(h),e["mount-before-install"]===void 0&&(e["mount-before-install"]=[]),e["mount-before-install"].unshift({vfsPath:`/${c}`,hostPath:h})}}if(e["mount-before-install"])for(const c of e["mount-before-install"])u.logger.debug(`Mount before WP install: ${c.vfsPath} -> ${c.hostPath}`);if(e.mount)for(const c of e.mount)u.logger.debug(`Mount after WP install: ${c.vfsPath} -> ${c.hostPath}`);let k;e["experimental-blueprints-v2-runner"]?k=new be(e,{siteUrl:I,processIdSpaceLength:w}):(k=new ke(e,{siteUrl:I,processIdSpaceLength:w}),typeof e.blueprint=="string"&&(e.blueprint=await ye({sourceString:e.blueprint,blueprintMayReadAdjacentFiles:e["blueprint-may-read-adjacent-files"]===!0})));const X=$e(P,k.getWorkerType(),({exitCode:c,isMain:g,workerIndex:$})=>{c!==0&&(u.logger.error(`Worker ${$} exited with code ${c}
9
- `),g&&e.exitOnPrimaryWorkerCrash&&process.exit(1))});u.logger.log(`Setting up WordPress ${e.wp}`);try{const[c,...g]=await X,$=await z(i);if(t=await k.bootPrimaryWorker(c.phpPort,$,v),s.push({playground:t,worker:c.worker}),await t.isReady(),n=!0,u.logger.log("Booted!"),r=new we(t),!e["experimental-blueprints-v2-runner"]){const h=await k.compileInputBlueprint(e["additional-blueprint-steps"]||[]);h&&(u.logger.log("Running the Blueprint..."),await R.runBlueprintV1Steps(h,t),u.logger.log("Finished running the blueprint"))}if(e.command==="build-snapshot"?(await Me(t,e.outfile),u.logger.log(`WordPress exported to ${e.outfile}`),process.exit(0)):e.command==="run-blueprint"&&(u.logger.log("Blueprint executed"),process.exit(0)),e.experimentalMultiWorker&&e.experimentalMultiWorker>1){u.logger.log("Preparing additional workers...");const h=w;await Promise.all(g.map(async(S,C)=>{const Y=h+C*w,G=await z(i),V=await k.bootSecondaryWorker({worker:S,fileLockManagerPort:G,firstProcessId:Y,nativeInternalDirPath:v});s.push({playground:V,worker:S.worker}),r.addWorker(V)}))}return u.logger.log(`WordPress is running on ${b} with ${P} worker(s)`),e.experimentalDevtools&&e.xdebug&&(await pe.startBridge({phpInstance:t,phpRoot:"/wordpress"})).start(),{playground:t,server:a,serverUrl:b,[Symbol.asyncDispose]:async function(){await Promise.all(s.map(async({playground:S,worker:C})=>{await S.dispose(),await C.terminate()})),await new Promise(S=>a.close(S))},workerThreadCount:P}}catch(c){if(!e.debug)throw c;let g="";throw await t?.fileExists(u.errorLogPath)&&(g=await t.readFileAsText(u.errorLogPath)),new Error(g,{cause:c})}},async handleRequest(a){if(!n)return m.PHPResponse.forHttpCode(502,"WordPress is not ready yet");if(l){l=!1;const p={"Content-Type":["text/plain"],"Content-Length":["0"],Location:[a.url]};return a.headers?.cookie?.includes("playground_auto_login_already_happened")&&(p["Set-Cookie"]=["playground_auto_login_already_happened=1; Max-Age=0; Expires=Thu, 01 Jan 1970 00:00:00 GMT; Path=/"]),new m.PHPResponse(302,p,new Uint8Array)}return await r.handleRequest(a)}})}async function $e(e,r,t){const s=[];for(let o=0;o<e;o++){const i=await Be(r),n=l=>{t({exitCode:l,isMain:o===0,workerIndex:o})};s.push(new Promise((l,a)=>{i.once("message",function(p){p.command==="worker-script-initialized"&&l({worker:i,phpPort:p.phpPort})}),i.once("error",function(p){console.error(p);const b=new Error(`Worker failed to load worker. ${p.message?`Original error: ${p.message}`:""}`);a(b)}),i.once("exit",n)}))}return Promise.all(s)}async function Be(e){return e==="v1"?new A.Worker(new URL("./worker-thread-v1.cjs",typeof document>"u"?require("url").pathToFileURL(__filename).href:W&&W.tagName.toUpperCase()==="SCRIPT"&&W.src||new URL("run-cli-Bb8U_jz3.cjs",document.baseURI).href)):new A.Worker(new URL("./worker-thread-v2.cjs",typeof document>"u"?require("url").pathToFileURL(__filename).href:W&&W.tagName.toUpperCase()==="SCRIPT"&&W.src||new URL("run-cli-Bb8U_jz3.cjs",document.baseURI).href))}async function z(e){const{port1:r,port2:t}=new A.MessageChannel;return await le.jspi()?m.exposeAPI(e,null,r):await m.exposeSyncAPI(e,r),t}async function Me(e,r){await e.run({code:`<?php
10
- $zip = new ZipArchive();
11
- if(false === $zip->open('/tmp/build.zip', ZipArchive::CREATE | ZipArchive::OVERWRITE)) {
12
- throw new Exception('Failed to create ZIP');
13
- }
14
- $files = new RecursiveIteratorIterator(
15
- new RecursiveDirectoryIterator('/wordpress')
16
- );
17
- foreach ($files as $file) {
18
- echo $file . PHP_EOL;
19
- if (!$file->isFile()) {
20
- continue;
21
- }
22
- $zip->addFile($file->getPathname(), $file->getPathname());
23
- }
24
- $zip->close();
25
-
26
- `});const t=await e.readFileAsBuffer("/tmp/build.zip");d.writeFileSync(r,t)}exports.LogVerbosity=E;exports.parseOptionsAndRunCLI=Ie;exports.runCLI=J;
27
- //# sourceMappingURL=run-cli-Bb8U_jz3.cjs.map