@wp-playground/cli 1.2.3 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (49) hide show
  1. package/blueprints-BQYAZ9gc.js +9 -0
  2. package/blueprints-BQYAZ9gc.js.map +1 -0
  3. package/blueprints-DLntJtVr.js +9 -0
  4. package/blueprints-DLntJtVr.js.map +1 -0
  5. package/blueprints-ZBrY1bvK.cjs +2 -0
  6. package/blueprints-ZBrY1bvK.cjs.map +1 -0
  7. package/blueprints-v1/blueprints-v1-handler.d.ts +31 -0
  8. package/{worker-thread.d.ts → blueprints-v1/worker-thread-v1.d.ts} +4 -3
  9. package/blueprints-v2/blueprint-v2-declaration.d.ts +10 -0
  10. package/blueprints-v2/blueprints-v2-handler.d.ts +31 -0
  11. package/blueprints-v2/get-v2-runner.d.ts +1 -0
  12. package/{v2.d.ts → blueprints-v2/run-blueprint-v2.d.ts} +1 -11
  13. package/blueprints-v2/worker-thread-v2.d.ts +49 -0
  14. package/cli.cjs +1 -1
  15. package/cli.cjs.map +1 -1
  16. package/cli.js +2 -4
  17. package/cli.js.map +1 -1
  18. package/index.cjs +1 -1
  19. package/index.js +1 -1
  20. package/load-balancer.d.ts +3 -1
  21. package/package.json +11 -11
  22. package/run-cli-CY1lYIJH.js +674 -0
  23. package/run-cli-CY1lYIJH.js.map +1 -0
  24. package/run-cli-opqDVXKw.cjs +27 -0
  25. package/run-cli-opqDVXKw.cjs.map +1 -0
  26. package/run-cli.d.ts +27 -5
  27. package/{worker-thread-CYvRK9UX.js → worker-thread-v1-BTJIbQLy.js} +47 -44
  28. package/worker-thread-v1-BTJIbQLy.js.map +1 -0
  29. package/worker-thread-v1.cjs +3 -0
  30. package/worker-thread-v1.cjs.map +1 -0
  31. package/{worker-thread.js → worker-thread-v1.js} +34 -31
  32. package/worker-thread-v1.js.map +1 -0
  33. package/worker-thread-v2-Pfv6UYF4.js +429 -0
  34. package/worker-thread-v2-Pfv6UYF4.js.map +1 -0
  35. package/worker-thread-v2.cjs +92 -0
  36. package/worker-thread-v2.cjs.map +1 -0
  37. package/worker-thread-v2.js +432 -0
  38. package/worker-thread-v2.js.map +1 -0
  39. package/reportable-error.d.ts +0 -5
  40. package/run-cli-B5BfXxxJ.cjs +0 -24
  41. package/run-cli-B5BfXxxJ.cjs.map +0 -1
  42. package/run-cli-W9VNXESj.js +0 -586
  43. package/run-cli-W9VNXESj.js.map +0 -1
  44. package/worker-thread-CYvRK9UX.js.map +0 -1
  45. package/worker-thread.cjs +0 -3
  46. package/worker-thread.cjs.map +0 -1
  47. package/worker-thread.js.map +0 -1
  48. /package/{download.d.ts → blueprints-v1/download.d.ts} +0 -0
  49. /package/{server.d.ts → start-server.d.ts} +0 -0
@@ -1,29 +1,29 @@
1
- import { createNodeFsMountHandler as k, loadNodeRuntime as v } from "@php-wasm/node";
2
- import { EmscriptenDownloadMonitor as M } from "@php-wasm/progress";
3
- import { exposeAPI as F, PHPWorker as H, consumeAPI as S, consumeAPISync as W, sandboxedSpawnHandlerFactory as E } from "@php-wasm/universal";
4
- import { sprintf as I } from "@php-wasm/util";
5
- import { RecommendedPHPVersion as L } from "@wp-playground/common";
6
- import { bootWordPress as A } from "@wp-playground/wordpress";
1
+ import { createNodeFsMountHandler as W, loadNodeRuntime as _ } from "@php-wasm/node";
2
+ import { EmscriptenDownloadMonitor as v } from "@php-wasm/progress";
3
+ import { exposeAPI as A, PHPWorker as M, consumeAPI as S, consumeAPISync as F, sandboxedSpawnHandlerFactory as H } from "@php-wasm/universal";
4
+ import { sprintf as E } from "@php-wasm/util";
5
+ import { RecommendedPHPVersion as I } from "@wp-playground/common";
6
+ import { bootWordPress as L } from "@wp-playground/wordpress";
7
7
  import { rootCertificates as D } from "tls";
8
8
  import { jspi as R } from "wasm-feature-detect";
9
- import { MessageChannel as x, parentPort as C } from "worker_threads";
9
+ import { MessageChannel as x, parentPort as B } from "worker_threads";
10
10
  import "fs";
11
11
  import "path";
12
- async function m(t, e) {
12
+ async function m(r, e) {
13
13
  for (const o of e)
14
- await t.mount(
14
+ await r.mount(
15
15
  o.vfsPath,
16
- k(o.hostPath)
16
+ W(o.hostPath)
17
17
  );
18
18
  }
19
- function G(t, e, ...o) {
19
+ function C(r, e, ...o) {
20
20
  console.log(
21
21
  performance.now().toFixed(6).padStart(15, "0"),
22
- t.toString().padStart(16, "0"),
23
- I(e, ...o)
22
+ r.toString().padStart(16, "0"),
23
+ E(e, ...o)
24
24
  );
25
25
  }
26
- class U extends H {
26
+ class G extends M {
27
27
  constructor(e) {
28
28
  super(void 0, e), this.booted = !1;
29
29
  }
@@ -37,45 +37,45 @@ class U extends H {
37
37
  * @see phpwasm-emscripten-library-file-locking-for-node.js
38
38
  */
39
39
  async useFileLockManager(e) {
40
- await R() ? this.fileLockManager = S(e) : this.fileLockManager = await W(e);
40
+ await R() ? this.fileLockManager = S(e) : this.fileLockManager = await F(e);
41
41
  }
42
- async boot({
42
+ async bootAsPrimaryWorker({
43
43
  absoluteUrl: e,
44
44
  mountsBeforeWpInstall: o,
45
- mountsAfterWpInstall: f,
46
- phpVersion: P = L,
45
+ mountsAfterWpInstall: P,
46
+ phpVersion: f = I,
47
47
  wordPressZip: c,
48
48
  sqliteIntegrationPluginZip: p,
49
49
  firstProcessId: n,
50
- processIdSpaceLength: h,
51
- dataSqlPath: u,
50
+ processIdSpaceLength: u,
51
+ dataSqlPath: h,
52
52
  followSymlinks: w,
53
53
  trace: y,
54
- internalCookieStore: g,
55
- withXdebug: b
54
+ internalCookieStore: b,
55
+ withXdebug: g
56
56
  }) {
57
57
  if (this.booted)
58
58
  throw new Error("Playground already booted");
59
59
  this.booted = !0;
60
- let r = n;
61
- const _ = n + h - 1;
60
+ let t = n;
61
+ const k = n + u - 1;
62
62
  try {
63
63
  const a = {
64
64
  WP_DEBUG: !0,
65
65
  WP_DEBUG_LOG: !0,
66
66
  WP_DEBUG_DISPLAY: !1
67
- }, l = await A({
67
+ }, l = await L({
68
68
  siteUrl: e,
69
69
  createPhpRuntime: async () => {
70
- const i = r;
71
- return r < _ ? r++ : r = n, await v(P, {
70
+ const s = t;
71
+ return t < k ? t++ : t = n, await _(f, {
72
72
  emscriptenOptions: {
73
73
  fileLockManager: this.fileLockManager,
74
- processId: i,
75
- trace: y ? G : void 0
74
+ processId: s,
75
+ trace: y ? C : void 0
76
76
  },
77
77
  followSymlinks: w,
78
- withXdebug: b
78
+ withXdebug: g
79
79
  });
80
80
  },
81
81
  wordPressZip: c !== void 0 ? new File([c], "wordpress.zip") : void 0,
@@ -95,36 +95,39 @@ class U extends H {
95
95
  disable_functions: ""
96
96
  },
97
97
  hooks: {
98
- async beforeWordPressFiles(i) {
99
- m(i, o);
98
+ async beforeWordPressFiles(s) {
99
+ m(s, o);
100
100
  }
101
101
  },
102
- cookieStore: g ? void 0 : !1,
103
- dataSqlPath: u,
104
- spawnHandler: E
102
+ cookieStore: b ? void 0 : !1,
103
+ dataSqlPath: h,
104
+ spawnHandler: H
105
105
  });
106
106
  this.__internal_setRequestHandler(l);
107
107
  const d = await l.getPrimaryPhp();
108
- await this.setPrimaryPHP(d), m(d, f), q();
108
+ await this.setPrimaryPHP(d), m(d, P), U();
109
109
  } catch (a) {
110
- throw z(a), a;
110
+ throw q(a), a;
111
111
  }
112
112
  }
113
+ async bootAsSecondaryWorker(e) {
114
+ return this.bootAsPrimaryWorker(e);
115
+ }
113
116
  // Provide a named disposal method that can be invoked via comlink.
114
117
  async dispose() {
115
118
  await this[Symbol.asyncDispose]();
116
119
  }
117
120
  }
118
- const s = new x(), [q, z] = F(
119
- new U(new M()),
121
+ const i = new x(), [U, q] = A(
122
+ new G(new v()),
120
123
  void 0,
121
- s.port1
124
+ i.port1
122
125
  );
123
- C.postMessage(
126
+ B.postMessage(
124
127
  {
125
128
  command: "worker-script-initialized",
126
- phpPort: s.port2
129
+ phpPort: i.port2
127
130
  },
128
- [s.port2]
131
+ [i.port2]
129
132
  );
130
- //# sourceMappingURL=worker-thread-CYvRK9UX.js.map
133
+ //# sourceMappingURL=worker-thread-v1-BTJIbQLy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"worker-thread-v1-BTJIbQLy.js","sources":["packages/playground/cli/src/mounts.ts","packages/playground/cli/src/blueprints-v1/worker-thread-v1.ts"],"sourcesContent":["import { createNodeFsMountHandler } from '@php-wasm/node';\nimport type { PHP } from '@php-wasm/universal';\nimport fs, { existsSync } from 'fs';\nimport path, { basename, join } from 'path';\nimport type { RunCLIArgs } from './run-cli';\n\nexport interface Mount {\n\thostPath: string;\n\tvfsPath: string;\n}\n\n/**\n * Parse an array of mount argument strings where the host path and VFS path\n * are separated by a colon.\n *\n * Example:\n * parseMountWithDelimiterArguments( [ '/host/path:/vfs/path', '/host/path:/vfs/path' ] )\n * // returns:\n * [\n * { hostPath: '/host/path', vfsPath: '/vfs/path' },\n * { hostPath: '/host/path', vfsPath: '/vfs/path' }\n * ]\n *\n * @param mounts - An array of mount argument strings separated by a colon.\n * @returns An array of Mount objects.\n */\nexport function parseMountWithDelimiterArguments(mounts: string[]): Mount[] {\n\tconst parsedMounts = [];\n\tfor (const mount of mounts) {\n\t\tconst mountParts = mount.split(':');\n\t\tif (mountParts.length !== 2) {\n\t\t\tthrow new Error(`Invalid mount format: ${mount}.\n\t\t\t\tExpected format: /host/path:/vfs/path.\n\t\t\t\tIf your path contains a colon, e.g. C:\\\\myplugin, use the --mount-dir option instead.\n\t\t\t\tExample: --mount-dir C:\\\\my-plugin /wordpress/wp-content/plugins/my-plugin`);\n\t\t}\n\t\tconst [hostPath, vfsPath] = mountParts;\n\t\tif (!existsSync(hostPath)) {\n\t\t\tthrow new Error(`Host path does not exist: ${hostPath}`);\n\t\t}\n\t\tparsedMounts.push({ hostPath, vfsPath });\n\t}\n\treturn parsedMounts;\n}\n\n/**\n * Parse an array of mount argument strings where each odd array element is a host path\n * and each even element is the VFS path.\n * e.g. [ '/host/path', '/vfs/path', '/host/path2', '/vfs/path2' ]\n *\n * The result will be an array of Mount objects for each host path the\n * following element is it's VFS path.\n * e.g. [\n * { hostPath: '/host/path', vfsPath: '/vfs/path' },\n * { hostPath: '/host/path2', vfsPath: '/vfs/path2' }\n * ]\n *\n * @param mounts - An array of paths\n * @returns An array of Mount objects.\n */\nexport function parseMountDirArguments(mounts: string[]): Mount[] {\n\tif (mounts.length % 2 !== 0) {\n\t\tthrow new Error('Invalid mount format. Expected: /host/path /vfs/path');\n\t}\n\n\tconst parsedMounts = [];\n\tfor (let i = 0; i < mounts.length; i += 2) {\n\t\tconst source = mounts[i];\n\t\tconst vfsPath = mounts[i + 1];\n\t\tif (!existsSync(source)) {\n\t\t\tthrow new Error(`Host path does not exist: ${source}`);\n\t\t}\n\t\tparsedMounts.push({\n\t\t\thostPath: path.resolve(process.cwd(), source),\n\t\t\tvfsPath,\n\t\t});\n\t}\n\treturn parsedMounts;\n}\n\nexport async function mountResources(php: PHP, mounts: Mount[]) {\n\tfor (const mount of mounts) {\n\t\tawait php.mount(\n\t\t\tmount.vfsPath,\n\t\t\tcreateNodeFsMountHandler(mount.hostPath)\n\t\t);\n\t}\n}\n\nconst ACTIVATE_FIRST_THEME_STEP = {\n\tstep: 'runPHP',\n\tcode: {\n\t\tfilename: 'activate-theme.php',\n\t\tcontent: `<?php\n\t\t\trequire_once getenv('DOCROOT') . '/wp-load.php';\n\t\t\t$theme = wp_get_theme();\n\t\t\tif (!$theme->exists()) {\n\t\t\t\t$themes = wp_get_themes();\n\t\t\t\tif (count($themes) > 0) {\n\t\t\t\t\t$themeName = array_keys($themes)[0];\n\t\t\t\t\tswitch_theme($themeName);\n\t\t\t\t}\n\t\t\t}\n\t\t`,\n\t},\n};\n\n/**\n * Auto-mounts resolution logic:\n */\nexport function expandAutoMounts(args: RunCLIArgs): RunCLIArgs {\n\tconst path = process.cwd();\n\n\tconst mount = [...(args.mount || [])];\n\tconst mountBeforeInstall = [...(args['mount-before-install'] || [])];\n\n\tconst newArgs = {\n\t\t...args,\n\t\tmount,\n\t\t'mount-before-install': mountBeforeInstall,\n\t\t'additional-blueprint-steps': [\n\t\t\t...((args as any)['additional-blueprint-steps'] || []),\n\t\t],\n\t};\n\n\tif (isPluginFilename(path)) {\n\t\tconst pluginName = basename(path);\n\t\tmount.push({\n\t\t\thostPath: path,\n\t\t\tvfsPath: `/wordpress/wp-content/plugins/${pluginName}`,\n\t\t});\n\t\tnewArgs['additional-blueprint-steps'].push({\n\t\t\tstep: 'activatePlugin',\n\t\t\tpluginPath: `/wordpress/wp-content/plugins/${basename(path)}`,\n\t\t});\n\t} else if (isThemeDirectory(path)) {\n\t\tconst themeName = basename(path);\n\t\tmount.push({\n\t\t\thostPath: path,\n\t\t\tvfsPath: `/wordpress/wp-content/themes/${themeName}`,\n\t\t});\n\t\tnewArgs['additional-blueprint-steps'].push({\n\t\t\tstep: 'activateTheme',\n\t\t\tthemeDirectoryName: themeName,\n\t\t});\n\t} else if (containsWpContentDirectories(path)) {\n\t\t/**\n\t\t * Mount each wp-content file and directory individually.\n\t\t */\n\t\tconst files = fs.readdirSync(path);\n\t\tfor (const file of files) {\n\t\t\t/**\n\t\t\t * WordPress already ships with the wp-content/index.php file\n\t\t\t * and Playground does not support overriding existing VFS files\n\t\t\t * with mounts.\n\t\t\t */\n\t\t\tif (file === 'index.php') {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tmount.push({\n\t\t\t\thostPath: `${path}/${file}`,\n\t\t\t\tvfsPath: `/wordpress/wp-content/${file}`,\n\t\t\t});\n\t\t}\n\t\tnewArgs['additional-blueprint-steps'].push(ACTIVATE_FIRST_THEME_STEP);\n\t} else if (containsFullWordPressInstallation(path)) {\n\t\tmountBeforeInstall.push({ hostPath: path, vfsPath: '/wordpress' });\n\t\t// @TODO: Uncomment when merging Blueprints v2 support\n\t\t// newArgs.mode = 'apply-to-existing-site';\n\t\tnewArgs['additional-blueprint-steps'].push(ACTIVATE_FIRST_THEME_STEP);\n\t} else {\n\t\t/**\n\t\t * By default, mount the current working directory as the Playground root.\n\t\t * This allows users to run and PHP or HTML files using the Playground CLI.\n\t\t */\n\t\tmount.push({ hostPath: path, vfsPath: '/wordpress' });\n\t\t// @TODO: Uncomment when merging Blueprints v2 support\n\t\t// newArgs.mode = 'mount-only';\n\t}\n\n\treturn newArgs as RunCLIArgs;\n}\n\nexport function containsFullWordPressInstallation(path: string): boolean {\n\tconst files = fs.readdirSync(path);\n\treturn (\n\t\tfiles.includes('wp-admin') &&\n\t\tfiles.includes('wp-includes') &&\n\t\tfiles.includes('wp-content')\n\t);\n}\n\nexport function containsWpContentDirectories(path: string): boolean {\n\tconst files = fs.readdirSync(path);\n\treturn (\n\t\tfiles.includes('themes') ||\n\t\tfiles.includes('plugins') ||\n\t\tfiles.includes('mu-plugins') ||\n\t\tfiles.includes('uploads')\n\t);\n}\n\nexport function isThemeDirectory(path: string): boolean {\n\tconst files = fs.readdirSync(path);\n\tif (!files.includes('style.css')) {\n\t\treturn false;\n\t}\n\tconst styleCssContent = fs.readFileSync(join(path, 'style.css'), 'utf8');\n\tconst themeNameRegex = /^(?:[ \\t]*<\\?php)?[ \\t/*#@]*Theme Name:(.*)$/im;\n\treturn !!themeNameRegex.exec(styleCssContent);\n}\n\nexport function isPluginFilename(path: string): boolean {\n\tconst files = fs.readdirSync(path);\n\tconst pluginNameRegex = /^(?:[ \\t]*<\\?php)?[ \\t/*#@]*Plugin Name:(.*)$/im;\n\tconst pluginNameMatch = files\n\t\t.filter((file) => file.endsWith('.php'))\n\t\t.find((file) => {\n\t\t\tconst fileContent = fs.readFileSync(join(path, file), 'utf8');\n\t\t\treturn !!pluginNameRegex.exec(fileContent);\n\t\t});\n\treturn !!pluginNameMatch;\n}\n","import type { FileLockManager } from '@php-wasm/node';\nimport { loadNodeRuntime } from '@php-wasm/node';\nimport { EmscriptenDownloadMonitor } from '@php-wasm/progress';\nimport type { RemoteAPI, SupportedPHPVersion } from '@php-wasm/universal';\nimport {\n\tPHPWorker,\n\tconsumeAPI,\n\tconsumeAPISync,\n\texposeAPI,\n\tsandboxedSpawnHandlerFactory,\n} from '@php-wasm/universal';\nimport { sprintf } from '@php-wasm/util';\nimport { RecommendedPHPVersion } from '@wp-playground/common';\nimport { bootWordPress } from '@wp-playground/wordpress';\nimport { rootCertificates } from 'tls';\nimport { jspi } from 'wasm-feature-detect';\nimport { MessageChannel, type MessagePort, parentPort } from 'worker_threads';\nimport { mountResources } from '../mounts';\n\nexport interface Mount {\n\thostPath: string;\n\tvfsPath: string;\n}\n\nexport type WorkerBootOptions = {\n\twpVersion?: string;\n\tphpVersion?: SupportedPHPVersion;\n\tabsoluteUrl: string;\n\tmountsBeforeWpInstall: Array<Mount>;\n\tmountsAfterWpInstall: Array<Mount>;\n\twordPressZip?: ArrayBuffer;\n\tsqliteIntegrationPluginZip?: ArrayBuffer;\n\tfirstProcessId: number;\n\tprocessIdSpaceLength: number;\n\tdataSqlPath?: string;\n\tfollowSymlinks: boolean;\n\ttrace: boolean;\n\t/**\n\t * When true, Playground will not send cookies to the client but will manage\n\t * them internally. This can be useful in environments that can't store cookies,\n\t * e.g. VS Code WebView.\n\t *\n\t * Default: false.\n\t */\n\tinternalCookieStore?: boolean;\n\twithXdebug?: boolean;\n};\n\n/**\n * Print trace messages from PHP-WASM.\n *\n * @param {number} processId - The process ID.\n * @param {string} format - The format string.\n * @param {...any} args - The arguments.\n */\nfunction tracePhpWasm(processId: number, format: string, ...args: any[]) {\n\t// eslint-disable-next-line no-console\n\tconsole.log(\n\t\tperformance.now().toFixed(6).padStart(15, '0'),\n\t\tprocessId.toString().padStart(16, '0'),\n\t\tsprintf(format, ...args)\n\t);\n}\n\nexport class PlaygroundCliBlueprintV1Worker extends PHPWorker {\n\tbooted = false;\n\tfileLockManager: RemoteAPI<FileLockManager> | FileLockManager | undefined;\n\n\tconstructor(monitor: EmscriptenDownloadMonitor) {\n\t\tsuper(undefined, monitor);\n\t}\n\n\t/**\n\t * Call this method before boot() to use file locking.\n\t *\n\t * This method is separate from boot() to simplify the related Comlink.transferHandlers\n\t * setup – if an argument is a MessagePort, we're transferring it, not copying it.\n\t *\n\t * @see comlink-sync.ts\n\t * @see phpwasm-emscripten-library-file-locking-for-node.js\n\t */\n\tasync useFileLockManager(port: MessagePort) {\n\t\tif (await jspi()) {\n\t\t\t/**\n\t\t\t * If JSPI is available, php.js supports both synchronous and asynchronous locking syscalls.\n\t\t\t * Web browsers, however, only support asynchronous message passing so let's use the\n\t\t\t * asynchronous API. Every method call will return a promise.\n\t\t\t *\n\t\t\t * @see comlink-sync.ts\n\t\t\t * @see phpwasm-emscripten-library-file-locking-for-node.js\n\t\t\t */\n\t\t\tthis.fileLockManager = consumeAPI<FileLockManager>(port);\n\t\t} else {\n\t\t\t/**\n\t\t\t * If JSPI is not available, php.js only supports synchronous locking syscalls.\n\t\t\t * Let's use the synchronous API. Every method call will block this thread\n\t\t\t * until the result is available.\n\t\t\t *\n\t\t\t * @see comlink-sync.ts\n\t\t\t * @see phpwasm-emscripten-library-file-locking-for-node.js\n\t\t\t */\n\t\t\tthis.fileLockManager = await consumeAPISync<FileLockManager>(port);\n\t\t}\n\t}\n\n\tasync bootAsPrimaryWorker({\n\t\tabsoluteUrl,\n\t\tmountsBeforeWpInstall,\n\t\tmountsAfterWpInstall,\n\t\tphpVersion = RecommendedPHPVersion,\n\t\twordPressZip,\n\t\tsqliteIntegrationPluginZip,\n\t\tfirstProcessId,\n\t\tprocessIdSpaceLength,\n\t\tdataSqlPath,\n\t\tfollowSymlinks,\n\t\ttrace,\n\t\tinternalCookieStore,\n\t\twithXdebug,\n\t}: WorkerBootOptions) {\n\t\tif (this.booted) {\n\t\t\tthrow new Error('Playground already booted');\n\t\t}\n\t\tthis.booted = true;\n\n\t\tlet nextProcessId = firstProcessId;\n\t\tconst lastProcessId = firstProcessId + processIdSpaceLength - 1;\n\n\t\ttry {\n\t\t\tconst constants: Record<string, string | number | boolean | null> =\n\t\t\t\t{\n\t\t\t\t\tWP_DEBUG: true,\n\t\t\t\t\tWP_DEBUG_LOG: true,\n\t\t\t\t\tWP_DEBUG_DISPLAY: false,\n\t\t\t\t};\n\n\t\t\tconst requestHandler = await bootWordPress({\n\t\t\t\tsiteUrl: absoluteUrl,\n\t\t\t\tcreatePhpRuntime: async () => {\n\t\t\t\t\tconst processId = nextProcessId;\n\n\t\t\t\t\tif (nextProcessId < lastProcessId) {\n\t\t\t\t\t\tnextProcessId++;\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// We've reached the end of the process ID space. Start over.\n\t\t\t\t\t\tnextProcessId = firstProcessId;\n\t\t\t\t\t}\n\n\t\t\t\t\treturn await loadNodeRuntime(phpVersion, {\n\t\t\t\t\t\temscriptenOptions: {\n\t\t\t\t\t\t\tfileLockManager: 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},\n\t\t\t\t\t\tfollowSymlinks,\n\t\t\t\t\t\twithXdebug,\n\t\t\t\t\t});\n\t\t\t\t},\n\t\t\t\twordPressZip:\n\t\t\t\t\twordPressZip !== undefined\n\t\t\t\t\t\t? new File([wordPressZip], 'wordpress.zip')\n\t\t\t\t\t\t: undefined,\n\t\t\t\tsqliteIntegrationPluginZip:\n\t\t\t\t\tsqliteIntegrationPluginZip !== undefined\n\t\t\t\t\t\t? new File(\n\t\t\t\t\t\t\t\t[sqliteIntegrationPluginZip],\n\t\t\t\t\t\t\t\t'sqlite-integration-plugin.zip'\n\t\t\t\t\t\t )\n\t\t\t\t\t\t: undefined,\n\t\t\t\tsapiName: 'cli',\n\t\t\t\tcreateFiles: {\n\t\t\t\t\t'/internal/shared/ca-bundle.crt':\n\t\t\t\t\t\trootCertificates.join('\\n'),\n\t\t\t\t},\n\t\t\t\tconstants,\n\t\t\t\tphpIniEntries: {\n\t\t\t\t\t'openssl.cafile': '/internal/shared/ca-bundle.crt',\n\t\t\t\t\tallow_url_fopen: '1',\n\t\t\t\t\tdisable_functions: '',\n\t\t\t\t},\n\t\t\t\thooks: {\n\t\t\t\t\tasync beforeWordPressFiles(php) {\n\t\t\t\t\t\tmountResources(php, mountsBeforeWpInstall);\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\tcookieStore: internalCookieStore ? undefined : false,\n\t\t\t\tdataSqlPath,\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\tmountResources(primaryPhp, mountsAfterWpInstall);\n\n\t\t\tsetApiReady();\n\t\t} catch (e) {\n\t\t\tsetAPIError(e as Error);\n\t\t\tthrow e;\n\t\t}\n\t}\n\n\tasync bootAsSecondaryWorker(args: WorkerBootOptions) {\n\t\treturn this.bootAsPrimaryWorker(args);\n\t}\n\n\t// Provide a named disposal method that can be invoked via comlink.\n\tasync dispose() {\n\t\tawait this[Symbol.asyncDispose]();\n\t}\n}\n\nconst phpChannel = new MessageChannel();\n\nconst [setApiReady, setAPIError] = exposeAPI(\n\tnew PlaygroundCliBlueprintV1Worker(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","tracePhpWasm","processId","format","args","sprintf","PlaygroundCliBlueprintV1Worker","PHPWorker","monitor","port","jspi","consumeAPI","consumeAPISync","absoluteUrl","mountsBeforeWpInstall","mountsAfterWpInstall","phpVersion","RecommendedPHPVersion","wordPressZip","sqliteIntegrationPluginZip","firstProcessId","processIdSpaceLength","dataSqlPath","followSymlinks","trace","internalCookieStore","withXdebug","nextProcessId","lastProcessId","constants","requestHandler","bootWordPress","loadNodeRuntime","rootCertificates","sandboxedSpawnHandlerFactory","primaryPhp","setApiReady","e","setAPIError","phpChannel","MessageChannel","exposeAPI","EmscriptenDownloadMonitor","parentPort"],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const S=require("@php-wasm/node"),v=require("@php-wasm/progress"),r=require("@php-wasm/universal"),A=require("@php-wasm/util"),M=require("@wp-playground/common"),F=require("@wp-playground/wordpress"),D=require("tls"),E=require("wasm-feature-detect"),h=require("worker_threads"),P=require("./mounts-D7bhhGq3.cjs");function H(c,e,...s){console.log(performance.now().toFixed(6).padStart(15,"0"),c.toString().padStart(16,"0"),A.sprintf(e,...s))}class m extends r.PHPWorker{constructor(e){super(void 0,e),this.booted=!1}async useFileLockManager(e){await E.jspi()?this.fileLockManager=r.consumeAPI(e):this.fileLockManager=await r.consumeAPISync(e)}async bootAsPrimaryWorker({absoluteUrl:e,mountsBeforeWpInstall:s,mountsAfterWpInstall:w,phpVersion:y=M.RecommendedPHPVersion,wordPressZip:l,sqliteIntegrationPluginZip:d,firstProcessId:n,processIdSpaceLength:g,dataSqlPath:f,followSymlinks:b,trace:k,internalCookieStore:q,withXdebug:W}){if(this.booted)throw new Error("Playground already booted");this.booted=!0;let o=n;const _=n+g-1;try{const t={WP_DEBUG:!0,WP_DEBUG_LOG:!0,WP_DEBUG_DISPLAY:!1},u=await F.bootWordPress({siteUrl:e,createPhpRuntime:async()=>{const i=o;return o<_?o++:o=n,await S.loadNodeRuntime(y,{emscriptenOptions:{fileLockManager:this.fileLockManager,processId:i,trace:k?H:void 0},followSymlinks:b,withXdebug:W})},wordPressZip:l!==void 0?new File([l],"wordpress.zip"):void 0,sqliteIntegrationPluginZip:d!==void 0?new File([d],"sqlite-integration-plugin.zip"):void 0,sapiName:"cli",createFiles:{"/internal/shared/ca-bundle.crt":D.rootCertificates.join(`
2
+ `)},constants:t,phpIniEntries:{"openssl.cafile":"/internal/shared/ca-bundle.crt",allow_url_fopen:"1",disable_functions:""},hooks:{async beforeWordPressFiles(i){P.mountResources(i,s)}},cookieStore:q?void 0:!1,dataSqlPath:f,spawnHandler:r.sandboxedSpawnHandlerFactory});this.__internal_setRequestHandler(u);const p=await u.getPrimaryPhp();await this.setPrimaryPHP(p),P.mountResources(p,w),I()}catch(t){throw L(t),t}}async bootAsSecondaryWorker(e){return this.bootAsPrimaryWorker(e)}async dispose(){await this[Symbol.asyncDispose]()}}const a=new h.MessageChannel,[I,L]=r.exposeAPI(new m(new v.EmscriptenDownloadMonitor),void 0,a.port1);h.parentPort.postMessage({command:"worker-script-initialized",phpPort:a.port2},[a.port2]);exports.PlaygroundCliBlueprintV1Worker=m;
3
+ //# sourceMappingURL=worker-thread-v1.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"worker-thread-v1.cjs","sources":["../../../../packages/playground/cli/src/blueprints-v1/worker-thread-v1.ts"],"sourcesContent":["import type { FileLockManager } from '@php-wasm/node';\nimport { loadNodeRuntime } from '@php-wasm/node';\nimport { EmscriptenDownloadMonitor } from '@php-wasm/progress';\nimport type { RemoteAPI, SupportedPHPVersion } from '@php-wasm/universal';\nimport {\n\tPHPWorker,\n\tconsumeAPI,\n\tconsumeAPISync,\n\texposeAPI,\n\tsandboxedSpawnHandlerFactory,\n} from '@php-wasm/universal';\nimport { sprintf } from '@php-wasm/util';\nimport { RecommendedPHPVersion } from '@wp-playground/common';\nimport { bootWordPress } from '@wp-playground/wordpress';\nimport { rootCertificates } from 'tls';\nimport { jspi } from 'wasm-feature-detect';\nimport { MessageChannel, type MessagePort, parentPort } from 'worker_threads';\nimport { mountResources } from '../mounts';\n\nexport interface Mount {\n\thostPath: string;\n\tvfsPath: string;\n}\n\nexport type WorkerBootOptions = {\n\twpVersion?: string;\n\tphpVersion?: SupportedPHPVersion;\n\tabsoluteUrl: string;\n\tmountsBeforeWpInstall: Array<Mount>;\n\tmountsAfterWpInstall: Array<Mount>;\n\twordPressZip?: ArrayBuffer;\n\tsqliteIntegrationPluginZip?: ArrayBuffer;\n\tfirstProcessId: number;\n\tprocessIdSpaceLength: number;\n\tdataSqlPath?: string;\n\tfollowSymlinks: boolean;\n\ttrace: boolean;\n\t/**\n\t * When true, Playground will not send cookies to the client but will manage\n\t * them internally. This can be useful in environments that can't store cookies,\n\t * e.g. VS Code WebView.\n\t *\n\t * Default: false.\n\t */\n\tinternalCookieStore?: boolean;\n\twithXdebug?: boolean;\n};\n\n/**\n * Print trace messages from PHP-WASM.\n *\n * @param {number} processId - The process ID.\n * @param {string} format - The format string.\n * @param {...any} args - The arguments.\n */\nfunction tracePhpWasm(processId: number, format: string, ...args: any[]) {\n\t// eslint-disable-next-line no-console\n\tconsole.log(\n\t\tperformance.now().toFixed(6).padStart(15, '0'),\n\t\tprocessId.toString().padStart(16, '0'),\n\t\tsprintf(format, ...args)\n\t);\n}\n\nexport class PlaygroundCliBlueprintV1Worker extends PHPWorker {\n\tbooted = false;\n\tfileLockManager: RemoteAPI<FileLockManager> | FileLockManager | undefined;\n\n\tconstructor(monitor: EmscriptenDownloadMonitor) {\n\t\tsuper(undefined, monitor);\n\t}\n\n\t/**\n\t * Call this method before boot() to use file locking.\n\t *\n\t * This method is separate from boot() to simplify the related Comlink.transferHandlers\n\t * setup – if an argument is a MessagePort, we're transferring it, not copying it.\n\t *\n\t * @see comlink-sync.ts\n\t * @see phpwasm-emscripten-library-file-locking-for-node.js\n\t */\n\tasync useFileLockManager(port: MessagePort) {\n\t\tif (await jspi()) {\n\t\t\t/**\n\t\t\t * If JSPI is available, php.js supports both synchronous and asynchronous locking syscalls.\n\t\t\t * Web browsers, however, only support asynchronous message passing so let's use the\n\t\t\t * asynchronous API. Every method call will return a promise.\n\t\t\t *\n\t\t\t * @see comlink-sync.ts\n\t\t\t * @see phpwasm-emscripten-library-file-locking-for-node.js\n\t\t\t */\n\t\t\tthis.fileLockManager = consumeAPI<FileLockManager>(port);\n\t\t} else {\n\t\t\t/**\n\t\t\t * If JSPI is not available, php.js only supports synchronous locking syscalls.\n\t\t\t * Let's use the synchronous API. Every method call will block this thread\n\t\t\t * until the result is available.\n\t\t\t *\n\t\t\t * @see comlink-sync.ts\n\t\t\t * @see phpwasm-emscripten-library-file-locking-for-node.js\n\t\t\t */\n\t\t\tthis.fileLockManager = await consumeAPISync<FileLockManager>(port);\n\t\t}\n\t}\n\n\tasync bootAsPrimaryWorker({\n\t\tabsoluteUrl,\n\t\tmountsBeforeWpInstall,\n\t\tmountsAfterWpInstall,\n\t\tphpVersion = RecommendedPHPVersion,\n\t\twordPressZip,\n\t\tsqliteIntegrationPluginZip,\n\t\tfirstProcessId,\n\t\tprocessIdSpaceLength,\n\t\tdataSqlPath,\n\t\tfollowSymlinks,\n\t\ttrace,\n\t\tinternalCookieStore,\n\t\twithXdebug,\n\t}: WorkerBootOptions) {\n\t\tif (this.booted) {\n\t\t\tthrow new Error('Playground already booted');\n\t\t}\n\t\tthis.booted = true;\n\n\t\tlet nextProcessId = firstProcessId;\n\t\tconst lastProcessId = firstProcessId + processIdSpaceLength - 1;\n\n\t\ttry {\n\t\t\tconst constants: Record<string, string | number | boolean | null> =\n\t\t\t\t{\n\t\t\t\t\tWP_DEBUG: true,\n\t\t\t\t\tWP_DEBUG_LOG: true,\n\t\t\t\t\tWP_DEBUG_DISPLAY: false,\n\t\t\t\t};\n\n\t\t\tconst requestHandler = await bootWordPress({\n\t\t\t\tsiteUrl: absoluteUrl,\n\t\t\t\tcreatePhpRuntime: async () => {\n\t\t\t\t\tconst processId = nextProcessId;\n\n\t\t\t\t\tif (nextProcessId < lastProcessId) {\n\t\t\t\t\t\tnextProcessId++;\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// We've reached the end of the process ID space. Start over.\n\t\t\t\t\t\tnextProcessId = firstProcessId;\n\t\t\t\t\t}\n\n\t\t\t\t\treturn await loadNodeRuntime(phpVersion, {\n\t\t\t\t\t\temscriptenOptions: {\n\t\t\t\t\t\t\tfileLockManager: 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},\n\t\t\t\t\t\tfollowSymlinks,\n\t\t\t\t\t\twithXdebug,\n\t\t\t\t\t});\n\t\t\t\t},\n\t\t\t\twordPressZip:\n\t\t\t\t\twordPressZip !== undefined\n\t\t\t\t\t\t? new File([wordPressZip], 'wordpress.zip')\n\t\t\t\t\t\t: undefined,\n\t\t\t\tsqliteIntegrationPluginZip:\n\t\t\t\t\tsqliteIntegrationPluginZip !== undefined\n\t\t\t\t\t\t? new File(\n\t\t\t\t\t\t\t\t[sqliteIntegrationPluginZip],\n\t\t\t\t\t\t\t\t'sqlite-integration-plugin.zip'\n\t\t\t\t\t\t )\n\t\t\t\t\t\t: undefined,\n\t\t\t\tsapiName: 'cli',\n\t\t\t\tcreateFiles: {\n\t\t\t\t\t'/internal/shared/ca-bundle.crt':\n\t\t\t\t\t\trootCertificates.join('\\n'),\n\t\t\t\t},\n\t\t\t\tconstants,\n\t\t\t\tphpIniEntries: {\n\t\t\t\t\t'openssl.cafile': '/internal/shared/ca-bundle.crt',\n\t\t\t\t\tallow_url_fopen: '1',\n\t\t\t\t\tdisable_functions: '',\n\t\t\t\t},\n\t\t\t\thooks: {\n\t\t\t\t\tasync beforeWordPressFiles(php) {\n\t\t\t\t\t\tmountResources(php, mountsBeforeWpInstall);\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\tcookieStore: internalCookieStore ? undefined : false,\n\t\t\t\tdataSqlPath,\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\tmountResources(primaryPhp, mountsAfterWpInstall);\n\n\t\t\tsetApiReady();\n\t\t} catch (e) {\n\t\t\tsetAPIError(e as Error);\n\t\t\tthrow e;\n\t\t}\n\t}\n\n\tasync bootAsSecondaryWorker(args: WorkerBootOptions) {\n\t\treturn this.bootAsPrimaryWorker(args);\n\t}\n\n\t// Provide a named disposal method that can be invoked via comlink.\n\tasync dispose() {\n\t\tawait this[Symbol.asyncDispose]();\n\t}\n}\n\nconst phpChannel = new MessageChannel();\n\nconst [setApiReady, setAPIError] = exposeAPI(\n\tnew PlaygroundCliBlueprintV1Worker(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":["tracePhpWasm","processId","format","args","sprintf","PlaygroundCliBlueprintV1Worker","PHPWorker","monitor","port","jspi","consumeAPI","consumeAPISync","absoluteUrl","mountsBeforeWpInstall","mountsAfterWpInstall","phpVersion","RecommendedPHPVersion","wordPressZip","sqliteIntegrationPluginZip","firstProcessId","processIdSpaceLength","dataSqlPath","followSymlinks","trace","internalCookieStore","withXdebug","nextProcessId","lastProcessId","constants","requestHandler","bootWordPress","loadNodeRuntime","rootCertificates","php","mountResources","sandboxedSpawnHandlerFactory","primaryPhp","setApiReady","e","setAPIError","phpChannel","MessageChannel","exposeAPI","EmscriptenDownloadMonitor","parentPort"],"mappings":"yYAuDA,SAASA,EAAaC,EAAmBC,KAAmBC,EAAa,CAEhE,QAAA,IACP,YAAY,MAAM,QAAQ,CAAC,EAAE,SAAS,GAAI,GAAG,EAC7CF,EAAU,SAAW,EAAA,SAAS,GAAI,GAAG,EACrCG,EAAA,QAAQF,EAAQ,GAAGC,CAAI,CACxB,CACD,CAEO,MAAME,UAAuCC,EAAAA,SAAU,CAI7D,YAAYC,EAAoC,CAC/C,MAAM,OAAWA,CAAO,EAJhB,KAAA,OAAA,EAAA,CAgBT,MAAM,mBAAmBC,EAAmB,CACvC,MAAMC,SASJ,KAAA,gBAAkBC,aAA4BF,CAAI,EAUlD,KAAA,gBAAkB,MAAMG,EAAA,eAAgCH,CAAI,CAClE,CAGD,MAAM,oBAAoB,CACzB,YAAAI,EACA,sBAAAC,EACA,qBAAAC,EACA,WAAAC,EAAaC,EAAA,sBACb,aAAAC,EACA,2BAAAC,EACA,eAAAC,EACA,qBAAAC,EACA,YAAAC,EACA,eAAAC,EACA,MAAAC,EACA,oBAAAC,EACA,WAAAC,CAAA,EACqB,CACrB,GAAI,KAAK,OACF,MAAA,IAAI,MAAM,2BAA2B,EAE5C,KAAK,OAAS,GAEd,IAAIC,EAAgBP,EACd,MAAAQ,EAAgBR,EAAiBC,EAAuB,EAE1D,GAAA,CACH,MAAMQ,EACL,CACC,SAAU,GACV,aAAc,GACd,iBAAkB,EACnB,EAEKC,EAAiB,MAAMC,gBAAc,CAC1C,QAASlB,EACT,iBAAkB,SAAY,CAC7B,MAAMX,EAAYyB,EAElB,OAAIA,EAAgBC,EACnBD,IAGgBA,EAAAP,EAGV,MAAMY,kBAAgBhB,EAAY,CACxC,kBAAmB,CAClB,gBAAiB,KAAK,gBACtB,UAAAd,EACA,MAAOsB,EAAQvB,EAAe,MAC/B,EACA,eAAAsB,EACA,WAAAG,CAAA,CACA,CACF,EACA,aACCR,IAAiB,OACd,IAAI,KAAK,CAACA,CAAY,EAAG,eAAe,EACxC,OACJ,2BACCC,IAA+B,OAC5B,IAAI,KACJ,CAACA,CAA0B,EAC3B,+BAEA,EAAA,OACJ,SAAU,MACV,YAAa,CACZ,iCACCc,EAAAA,iBAAiB,KAAK;AAAA,CAAI,CAC5B,EACA,UAAAJ,EACA,cAAe,CACd,iBAAkB,iCAClB,gBAAiB,IACjB,kBAAmB,EACpB,EACA,MAAO,CACN,MAAM,qBAAqBK,EAAK,CAC/BC,EAAA,eAAeD,EAAKpB,CAAqB,CAAA,CAE3C,EACA,YAAaW,EAAsB,OAAY,GAC/C,YAAAH,EACA,aAAcc,EAAAA,4BAAA,CACd,EACD,KAAK,6BAA6BN,CAAc,EAE1C,MAAAO,EAAa,MAAMP,EAAe,cAAc,EAChD,MAAA,KAAK,cAAcO,CAAU,EAEnCF,EAAA,eAAeE,EAAYtB,CAAoB,EAEnCuB,EAAA,QACJC,EAAG,CACX,MAAAC,EAAYD,CAAU,EAChBA,CAAA,CACP,CAGD,MAAM,sBAAsBnC,EAAyB,CAC7C,OAAA,KAAK,oBAAoBA,CAAI,CAAA,CAIrC,MAAM,SAAU,CACT,MAAA,KAAK,OAAO,YAAY,EAAE,CAAA,CAElC,CAEA,MAAMqC,EAAa,IAAIC,EAAAA,eAEjB,CAACJ,EAAaE,CAAW,EAAIG,EAAA,UAClC,IAAIrC,EAA+B,IAAIsC,EAAAA,yBAA2B,EAClE,OACAH,EAAW,KACZ,EAEAI,EAAAA,WAAY,YACX,CACC,QAAS,4BACT,QAASJ,EAAW,KACrB,EACA,CAACA,EAAW,KAAY,CACzB"}
@@ -1,21 +1,21 @@
1
- import { loadNodeRuntime as k } from "@php-wasm/node";
2
- import { EmscriptenDownloadMonitor as v } from "@php-wasm/progress";
3
- import { exposeAPI as M, PHPWorker as S, consumeAPI as W, consumeAPISync as E, sandboxedSpawnHandlerFactory as F } from "@php-wasm/universal";
4
- import { sprintf as H } from "@php-wasm/util";
5
- import { RecommendedPHPVersion as I } from "@wp-playground/common";
6
- import { bootWordPress as L } from "@wp-playground/wordpress";
7
- import { rootCertificates as x } from "tls";
8
- import { jspi as A } from "wasm-feature-detect";
1
+ import { loadNodeRuntime as W } from "@php-wasm/node";
2
+ import { EmscriptenDownloadMonitor as _ } from "@php-wasm/progress";
3
+ import { exposeAPI as A, PHPWorker as S, consumeAPI as v, consumeAPISync as M, sandboxedSpawnHandlerFactory as E } from "@php-wasm/universal";
4
+ import { sprintf as F } from "@php-wasm/util";
5
+ import { RecommendedPHPVersion as H } from "@wp-playground/common";
6
+ import { bootWordPress as I } from "@wp-playground/wordpress";
7
+ import { rootCertificates as L } from "tls";
8
+ import { jspi as x } from "wasm-feature-detect";
9
9
  import { MessageChannel as D, parentPort as R } from "worker_threads";
10
10
  import { m } from "./mounts-B-Qdcyyt.js";
11
- function C(n, e, ...t) {
11
+ function B(n, e, ...t) {
12
12
  console.log(
13
13
  performance.now().toFixed(6).padStart(15, "0"),
14
14
  n.toString().padStart(16, "0"),
15
- H(e, ...t)
15
+ F(e, ...t)
16
16
  );
17
17
  }
18
- class G extends S {
18
+ class C extends S {
19
19
  constructor(e) {
20
20
  super(void 0, e), this.booted = !1;
21
21
  }
@@ -29,13 +29,13 @@ class G extends S {
29
29
  * @see phpwasm-emscripten-library-file-locking-for-node.js
30
30
  */
31
31
  async useFileLockManager(e) {
32
- await A() ? this.fileLockManager = W(e) : this.fileLockManager = await E(e);
32
+ await x() ? this.fileLockManager = v(e) : this.fileLockManager = await M(e);
33
33
  }
34
- async boot({
34
+ async bootAsPrimaryWorker({
35
35
  absoluteUrl: e,
36
36
  mountsBeforeWpInstall: t,
37
- mountsAfterWpInstall: f,
38
- phpVersion: P = I,
37
+ mountsAfterWpInstall: P,
38
+ phpVersion: f = H,
39
39
  wordPressZip: c,
40
40
  sqliteIntegrationPluginZip: p,
41
41
  firstProcessId: i,
@@ -43,31 +43,31 @@ class G extends S {
43
43
  dataSqlPath: u,
44
44
  followSymlinks: w,
45
45
  trace: y,
46
- internalCookieStore: g,
47
- withXdebug: b
46
+ internalCookieStore: b,
47
+ withXdebug: g
48
48
  }) {
49
49
  if (this.booted)
50
50
  throw new Error("Playground already booted");
51
51
  this.booted = !0;
52
52
  let o = i;
53
- const _ = i + h - 1;
53
+ const k = i + h - 1;
54
54
  try {
55
55
  const r = {
56
56
  WP_DEBUG: !0,
57
57
  WP_DEBUG_LOG: !0,
58
58
  WP_DEBUG_DISPLAY: !1
59
- }, l = await L({
59
+ }, l = await I({
60
60
  siteUrl: e,
61
61
  createPhpRuntime: async () => {
62
62
  const s = o;
63
- return o < _ ? o++ : o = i, await k(P, {
63
+ return o < k ? o++ : o = i, await W(f, {
64
64
  emscriptenOptions: {
65
65
  fileLockManager: this.fileLockManager,
66
66
  processId: s,
67
- trace: y ? C : void 0
67
+ trace: y ? B : void 0
68
68
  },
69
69
  followSymlinks: w,
70
- withXdebug: b
70
+ withXdebug: g
71
71
  });
72
72
  },
73
73
  wordPressZip: c !== void 0 ? new File([c], "wordpress.zip") : void 0,
@@ -77,7 +77,7 @@ class G extends S {
77
77
  ) : void 0,
78
78
  sapiName: "cli",
79
79
  createFiles: {
80
- "/internal/shared/ca-bundle.crt": x.join(`
80
+ "/internal/shared/ca-bundle.crt": L.join(`
81
81
  `)
82
82
  },
83
83
  constants: r,
@@ -91,24 +91,27 @@ class G extends S {
91
91
  m(s, t);
92
92
  }
93
93
  },
94
- cookieStore: g ? void 0 : !1,
94
+ cookieStore: b ? void 0 : !1,
95
95
  dataSqlPath: u,
96
- spawnHandler: F
96
+ spawnHandler: E
97
97
  });
98
98
  this.__internal_setRequestHandler(l);
99
99
  const d = await l.getPrimaryPhp();
100
- await this.setPrimaryPHP(d), m(d, f), U();
100
+ await this.setPrimaryPHP(d), m(d, P), G();
101
101
  } catch (r) {
102
- throw q(r), r;
102
+ throw U(r), r;
103
103
  }
104
104
  }
105
+ async bootAsSecondaryWorker(e) {
106
+ return this.bootAsPrimaryWorker(e);
107
+ }
105
108
  // Provide a named disposal method that can be invoked via comlink.
106
109
  async dispose() {
107
110
  await this[Symbol.asyncDispose]();
108
111
  }
109
112
  }
110
- const a = new D(), [U, q] = M(
111
- new G(new v()),
113
+ const a = new D(), [G, U] = A(
114
+ new C(new _()),
112
115
  void 0,
113
116
  a.port1
114
117
  );
@@ -120,6 +123,6 @@ R.postMessage(
120
123
  [a.port2]
121
124
  );
122
125
  export {
123
- G as PlaygroundCliWorker
126
+ C as PlaygroundCliBlueprintV1Worker
124
127
  };
125
- //# sourceMappingURL=worker-thread.js.map
128
+ //# sourceMappingURL=worker-thread-v1.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"worker-thread-v1.js","sources":["../../../../packages/playground/cli/src/blueprints-v1/worker-thread-v1.ts"],"sourcesContent":["import type { FileLockManager } from '@php-wasm/node';\nimport { loadNodeRuntime } from '@php-wasm/node';\nimport { EmscriptenDownloadMonitor } from '@php-wasm/progress';\nimport type { RemoteAPI, SupportedPHPVersion } from '@php-wasm/universal';\nimport {\n\tPHPWorker,\n\tconsumeAPI,\n\tconsumeAPISync,\n\texposeAPI,\n\tsandboxedSpawnHandlerFactory,\n} from '@php-wasm/universal';\nimport { sprintf } from '@php-wasm/util';\nimport { RecommendedPHPVersion } from '@wp-playground/common';\nimport { bootWordPress } from '@wp-playground/wordpress';\nimport { rootCertificates } from 'tls';\nimport { jspi } from 'wasm-feature-detect';\nimport { MessageChannel, type MessagePort, parentPort } from 'worker_threads';\nimport { mountResources } from '../mounts';\n\nexport interface Mount {\n\thostPath: string;\n\tvfsPath: string;\n}\n\nexport type WorkerBootOptions = {\n\twpVersion?: string;\n\tphpVersion?: SupportedPHPVersion;\n\tabsoluteUrl: string;\n\tmountsBeforeWpInstall: Array<Mount>;\n\tmountsAfterWpInstall: Array<Mount>;\n\twordPressZip?: ArrayBuffer;\n\tsqliteIntegrationPluginZip?: ArrayBuffer;\n\tfirstProcessId: number;\n\tprocessIdSpaceLength: number;\n\tdataSqlPath?: string;\n\tfollowSymlinks: boolean;\n\ttrace: boolean;\n\t/**\n\t * When true, Playground will not send cookies to the client but will manage\n\t * them internally. This can be useful in environments that can't store cookies,\n\t * e.g. VS Code WebView.\n\t *\n\t * Default: false.\n\t */\n\tinternalCookieStore?: boolean;\n\twithXdebug?: boolean;\n};\n\n/**\n * Print trace messages from PHP-WASM.\n *\n * @param {number} processId - The process ID.\n * @param {string} format - The format string.\n * @param {...any} args - The arguments.\n */\nfunction tracePhpWasm(processId: number, format: string, ...args: any[]) {\n\t// eslint-disable-next-line no-console\n\tconsole.log(\n\t\tperformance.now().toFixed(6).padStart(15, '0'),\n\t\tprocessId.toString().padStart(16, '0'),\n\t\tsprintf(format, ...args)\n\t);\n}\n\nexport class PlaygroundCliBlueprintV1Worker extends PHPWorker {\n\tbooted = false;\n\tfileLockManager: RemoteAPI<FileLockManager> | FileLockManager | undefined;\n\n\tconstructor(monitor: EmscriptenDownloadMonitor) {\n\t\tsuper(undefined, monitor);\n\t}\n\n\t/**\n\t * Call this method before boot() to use file locking.\n\t *\n\t * This method is separate from boot() to simplify the related Comlink.transferHandlers\n\t * setup – if an argument is a MessagePort, we're transferring it, not copying it.\n\t *\n\t * @see comlink-sync.ts\n\t * @see phpwasm-emscripten-library-file-locking-for-node.js\n\t */\n\tasync useFileLockManager(port: MessagePort) {\n\t\tif (await jspi()) {\n\t\t\t/**\n\t\t\t * If JSPI is available, php.js supports both synchronous and asynchronous locking syscalls.\n\t\t\t * Web browsers, however, only support asynchronous message passing so let's use the\n\t\t\t * asynchronous API. Every method call will return a promise.\n\t\t\t *\n\t\t\t * @see comlink-sync.ts\n\t\t\t * @see phpwasm-emscripten-library-file-locking-for-node.js\n\t\t\t */\n\t\t\tthis.fileLockManager = consumeAPI<FileLockManager>(port);\n\t\t} else {\n\t\t\t/**\n\t\t\t * If JSPI is not available, php.js only supports synchronous locking syscalls.\n\t\t\t * Let's use the synchronous API. Every method call will block this thread\n\t\t\t * until the result is available.\n\t\t\t *\n\t\t\t * @see comlink-sync.ts\n\t\t\t * @see phpwasm-emscripten-library-file-locking-for-node.js\n\t\t\t */\n\t\t\tthis.fileLockManager = await consumeAPISync<FileLockManager>(port);\n\t\t}\n\t}\n\n\tasync bootAsPrimaryWorker({\n\t\tabsoluteUrl,\n\t\tmountsBeforeWpInstall,\n\t\tmountsAfterWpInstall,\n\t\tphpVersion = RecommendedPHPVersion,\n\t\twordPressZip,\n\t\tsqliteIntegrationPluginZip,\n\t\tfirstProcessId,\n\t\tprocessIdSpaceLength,\n\t\tdataSqlPath,\n\t\tfollowSymlinks,\n\t\ttrace,\n\t\tinternalCookieStore,\n\t\twithXdebug,\n\t}: WorkerBootOptions) {\n\t\tif (this.booted) {\n\t\t\tthrow new Error('Playground already booted');\n\t\t}\n\t\tthis.booted = true;\n\n\t\tlet nextProcessId = firstProcessId;\n\t\tconst lastProcessId = firstProcessId + processIdSpaceLength - 1;\n\n\t\ttry {\n\t\t\tconst constants: Record<string, string | number | boolean | null> =\n\t\t\t\t{\n\t\t\t\t\tWP_DEBUG: true,\n\t\t\t\t\tWP_DEBUG_LOG: true,\n\t\t\t\t\tWP_DEBUG_DISPLAY: false,\n\t\t\t\t};\n\n\t\t\tconst requestHandler = await bootWordPress({\n\t\t\t\tsiteUrl: absoluteUrl,\n\t\t\t\tcreatePhpRuntime: async () => {\n\t\t\t\t\tconst processId = nextProcessId;\n\n\t\t\t\t\tif (nextProcessId < lastProcessId) {\n\t\t\t\t\t\tnextProcessId++;\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// We've reached the end of the process ID space. Start over.\n\t\t\t\t\t\tnextProcessId = firstProcessId;\n\t\t\t\t\t}\n\n\t\t\t\t\treturn await loadNodeRuntime(phpVersion, {\n\t\t\t\t\t\temscriptenOptions: {\n\t\t\t\t\t\t\tfileLockManager: 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},\n\t\t\t\t\t\tfollowSymlinks,\n\t\t\t\t\t\twithXdebug,\n\t\t\t\t\t});\n\t\t\t\t},\n\t\t\t\twordPressZip:\n\t\t\t\t\twordPressZip !== undefined\n\t\t\t\t\t\t? new File([wordPressZip], 'wordpress.zip')\n\t\t\t\t\t\t: undefined,\n\t\t\t\tsqliteIntegrationPluginZip:\n\t\t\t\t\tsqliteIntegrationPluginZip !== undefined\n\t\t\t\t\t\t? new File(\n\t\t\t\t\t\t\t\t[sqliteIntegrationPluginZip],\n\t\t\t\t\t\t\t\t'sqlite-integration-plugin.zip'\n\t\t\t\t\t\t )\n\t\t\t\t\t\t: undefined,\n\t\t\t\tsapiName: 'cli',\n\t\t\t\tcreateFiles: {\n\t\t\t\t\t'/internal/shared/ca-bundle.crt':\n\t\t\t\t\t\trootCertificates.join('\\n'),\n\t\t\t\t},\n\t\t\t\tconstants,\n\t\t\t\tphpIniEntries: {\n\t\t\t\t\t'openssl.cafile': '/internal/shared/ca-bundle.crt',\n\t\t\t\t\tallow_url_fopen: '1',\n\t\t\t\t\tdisable_functions: '',\n\t\t\t\t},\n\t\t\t\thooks: {\n\t\t\t\t\tasync beforeWordPressFiles(php) {\n\t\t\t\t\t\tmountResources(php, mountsBeforeWpInstall);\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\tcookieStore: internalCookieStore ? undefined : false,\n\t\t\t\tdataSqlPath,\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\tmountResources(primaryPhp, mountsAfterWpInstall);\n\n\t\t\tsetApiReady();\n\t\t} catch (e) {\n\t\t\tsetAPIError(e as Error);\n\t\t\tthrow e;\n\t\t}\n\t}\n\n\tasync bootAsSecondaryWorker(args: WorkerBootOptions) {\n\t\treturn this.bootAsPrimaryWorker(args);\n\t}\n\n\t// Provide a named disposal method that can be invoked via comlink.\n\tasync dispose() {\n\t\tawait this[Symbol.asyncDispose]();\n\t}\n}\n\nconst phpChannel = new MessageChannel();\n\nconst [setApiReady, setAPIError] = exposeAPI(\n\tnew PlaygroundCliBlueprintV1Worker(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":["tracePhpWasm","processId","format","args","sprintf","PlaygroundCliBlueprintV1Worker","PHPWorker","monitor","port","jspi","consumeAPI","consumeAPISync","absoluteUrl","mountsBeforeWpInstall","mountsAfterWpInstall","phpVersion","RecommendedPHPVersion","wordPressZip","sqliteIntegrationPluginZip","firstProcessId","processIdSpaceLength","dataSqlPath","followSymlinks","trace","internalCookieStore","withXdebug","nextProcessId","lastProcessId","constants","requestHandler","bootWordPress","loadNodeRuntime","rootCertificates","php","mountResources","sandboxedSpawnHandlerFactory","primaryPhp","setApiReady","e","setAPIError","phpChannel","MessageChannel","exposeAPI","EmscriptenDownloadMonitor","parentPort"],"mappings":"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"}