@wp-playground/cli 1.2.2 → 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 (63) hide show
  1. package/README.md +3 -0
  2. package/blueprints-BQYAZ9gc.js +9 -0
  3. package/blueprints-BQYAZ9gc.js.map +1 -0
  4. package/blueprints-DLntJtVr.js +9 -0
  5. package/blueprints-DLntJtVr.js.map +1 -0
  6. package/blueprints-ZBrY1bvK.cjs +2 -0
  7. package/blueprints-ZBrY1bvK.cjs.map +1 -0
  8. package/blueprints-v1/blueprints-v1-handler.d.ts +31 -0
  9. package/{worker-thread.d.ts → blueprints-v1/worker-thread-v1.d.ts} +5 -3
  10. package/blueprints-v2/blueprint-v2-declaration.d.ts +10 -0
  11. package/blueprints-v2/blueprints-v2-handler.d.ts +31 -0
  12. package/blueprints-v2/get-v2-runner.d.ts +1 -0
  13. package/blueprints-v2/run-blueprint-v2.d.ts +35 -0
  14. package/blueprints-v2/worker-thread-v2.d.ts +49 -0
  15. package/blueprints.phar +0 -0
  16. package/cli.cjs +1 -1
  17. package/cli.cjs.map +1 -1
  18. package/cli.js +2 -4
  19. package/cli.js.map +1 -1
  20. package/index.cjs +1 -1
  21. package/index.js +1 -1
  22. package/load-balancer.d.ts +3 -1
  23. package/mounts-B-Qdcyyt.js +124 -0
  24. package/mounts-B-Qdcyyt.js.map +1 -0
  25. package/mounts-D7bhhGq3.cjs +15 -0
  26. package/mounts-D7bhhGq3.cjs.map +1 -0
  27. package/{mount.d.ts → mounts.d.ts} +10 -1
  28. package/package.json +11 -11
  29. package/run-cli-CY1lYIJH.js +674 -0
  30. package/run-cli-CY1lYIJH.js.map +1 -0
  31. package/run-cli-opqDVXKw.cjs +27 -0
  32. package/run-cli-opqDVXKw.cjs.map +1 -0
  33. package/run-cli.d.ts +30 -6
  34. package/worker-thread-v1-BTJIbQLy.js +133 -0
  35. package/worker-thread-v1-BTJIbQLy.js.map +1 -0
  36. package/worker-thread-v1.cjs +3 -0
  37. package/worker-thread-v1.cjs.map +1 -0
  38. package/worker-thread-v1.js +128 -0
  39. package/worker-thread-v1.js.map +1 -0
  40. package/worker-thread-v2-Pfv6UYF4.js +429 -0
  41. package/worker-thread-v2-Pfv6UYF4.js.map +1 -0
  42. package/worker-thread-v2.cjs +92 -0
  43. package/worker-thread-v2.cjs.map +1 -0
  44. package/worker-thread-v2.js +432 -0
  45. package/worker-thread-v2.js.map +1 -0
  46. package/cli-auto-mount.d.ts +0 -19
  47. package/index-CddYZc1x.js +0 -5
  48. package/index-CddYZc1x.js.map +0 -1
  49. package/index-CyPmrjJv.cjs +0 -2
  50. package/index-CyPmrjJv.cjs.map +0 -1
  51. package/reportable-error.d.ts +0 -5
  52. package/run-cli-Bon3Rz_F.cjs +0 -43
  53. package/run-cli-Bon3Rz_F.cjs.map +0 -1
  54. package/run-cli-DyJ6_Vj8.js +0 -8449
  55. package/run-cli-DyJ6_Vj8.js.map +0 -1
  56. package/worker-thread-CQBM_bGk.js +0 -171
  57. package/worker-thread-CQBM_bGk.js.map +0 -1
  58. package/worker-thread.cjs +0 -3
  59. package/worker-thread.cjs.map +0 -1
  60. package/worker-thread.js +0 -124
  61. package/worker-thread.js.map +0 -1
  62. /package/{download.d.ts → blueprints-v1/download.d.ts} +0 -0
  63. /package/{server.d.ts → start-server.d.ts} +0 -0
@@ -0,0 +1,31 @@
1
+ /// <reference types="node" />
2
+ /// <reference types="node" />
3
+ import type { PlaygroundCliBlueprintV1Worker } from './worker-thread-v1';
4
+ import type { MessagePort as NodeMessagePort } from 'worker_threads';
5
+ import type { RunCLIArgs, SpawnedWorker } from '../run-cli';
6
+ /**
7
+ * Boots Playground CLI workers using Blueprint version 1.
8
+ *
9
+ * Progress tracking, downloads, steps, and all other features are
10
+ * implemented in TypeScript and orchestrated by this class.
11
+ */
12
+ export declare class BlueprintsV1Handler {
13
+ private phpVersion;
14
+ private lastProgressMessage;
15
+ private siteUrl;
16
+ private processIdSpaceLength;
17
+ private args;
18
+ constructor(args: RunCLIArgs, options: {
19
+ siteUrl: string;
20
+ processIdSpaceLength: number;
21
+ });
22
+ getWorkerUrl(): any;
23
+ bootPrimaryWorker(phpPort: NodeMessagePort, fileLockManagerPort: NodeMessagePort): Promise<import("@php-wasm/universal").RemoteAPI<PlaygroundCliBlueprintV1Worker>>;
24
+ bootSecondaryWorker({ worker, fileLockManagerPort, firstProcessId, }: {
25
+ worker: SpawnedWorker;
26
+ fileLockManagerPort: NodeMessagePort;
27
+ firstProcessId: number;
28
+ }): Promise<import("@php-wasm/universal").RemoteAPI<PlaygroundCliBlueprintV1Worker>>;
29
+ compileInputBlueprint(additionalBlueprintSteps: any[]): Promise<import("@wp-playground/blueprints").CompiledBlueprint>;
30
+ writeProgressUpdate(writeStream: NodeJS.WriteStream, message: string, finalUpdate: boolean): void;
31
+ }
@@ -8,7 +8,7 @@ export interface Mount {
8
8
  hostPath: string;
9
9
  vfsPath: string;
10
10
  }
11
- export type PrimaryWorkerBootOptions = {
11
+ export type WorkerBootOptions = {
12
12
  wpVersion?: string;
13
13
  phpVersion?: SupportedPHPVersion;
14
14
  absoluteUrl: string;
@@ -29,8 +29,9 @@ export type PrimaryWorkerBootOptions = {
29
29
  * Default: false.
30
30
  */
31
31
  internalCookieStore?: boolean;
32
+ withXdebug?: boolean;
32
33
  };
33
- export declare class PlaygroundCliWorker extends PHPWorker {
34
+ export declare class PlaygroundCliBlueprintV1Worker extends PHPWorker {
34
35
  booted: boolean;
35
36
  fileLockManager: RemoteAPI<FileLockManager> | FileLockManager | undefined;
36
37
  constructor(monitor: EmscriptenDownloadMonitor);
@@ -44,6 +45,7 @@ export declare class PlaygroundCliWorker extends PHPWorker {
44
45
  * @see phpwasm-emscripten-library-file-locking-for-node.js
45
46
  */
46
47
  useFileLockManager(port: MessagePort): Promise<void>;
47
- boot({ absoluteUrl, mountsBeforeWpInstall, mountsAfterWpInstall, phpVersion, wordPressZip, sqliteIntegrationPluginZip, firstProcessId, processIdSpaceLength, dataSqlPath, followSymlinks, trace, internalCookieStore, }: PrimaryWorkerBootOptions): Promise<void>;
48
+ bootAsPrimaryWorker({ absoluteUrl, mountsBeforeWpInstall, mountsAfterWpInstall, phpVersion, wordPressZip, sqliteIntegrationPluginZip, firstProcessId, processIdSpaceLength, dataSqlPath, followSymlinks, trace, internalCookieStore, withXdebug, }: WorkerBootOptions): Promise<void>;
49
+ bootAsSecondaryWorker(args: WorkerBootOptions): Promise<void>;
48
50
  dispose(): Promise<void>;
49
51
  }
@@ -0,0 +1,10 @@
1
+ import type { BlueprintDeclaration } from '@wp-playground/blueprints';
2
+ export type BlueprintV2Declaration = string | BlueprintDeclaration | undefined;
3
+ export type ParsedBlueprintV2Declaration = {
4
+ type: 'inline-file';
5
+ contents: string;
6
+ } | {
7
+ type: 'file-reference';
8
+ reference: string;
9
+ };
10
+ export declare function parseBlueprintDeclaration(source: BlueprintV2Declaration | ParsedBlueprintV2Declaration): ParsedBlueprintV2Declaration;
@@ -0,0 +1,31 @@
1
+ /// <reference types="node" />
2
+ /// <reference types="node" />
3
+ import type { RemoteAPI } from '@php-wasm/universal';
4
+ import type { PlaygroundCliBlueprintV2Worker } from './worker-thread-v2';
5
+ import type { MessagePort as NodeMessagePort } from 'worker_threads';
6
+ import type { RunCLIArgs, SpawnedWorker } from '../run-cli';
7
+ /**
8
+ * Boots Playground CLI workers using Blueprint version 2.
9
+ *
10
+ * Progress tracking, downloads, steps, and all other features are
11
+ * implemented in PHP and orchestrated by the worker thread.
12
+ */
13
+ export declare class BlueprintsV2Handler {
14
+ private phpVersion;
15
+ private lastProgressMessage;
16
+ private siteUrl;
17
+ private processIdSpaceLength;
18
+ private args;
19
+ constructor(args: RunCLIArgs, options: {
20
+ siteUrl: string;
21
+ processIdSpaceLength: number;
22
+ });
23
+ getWorkerUrl(): any;
24
+ bootPrimaryWorker(phpPort: NodeMessagePort, fileLockManagerPort: NodeMessagePort): Promise<RemoteAPI<PlaygroundCliBlueprintV2Worker>>;
25
+ bootSecondaryWorker({ worker, fileLockManagerPort, firstProcessId, }: {
26
+ worker: SpawnedWorker;
27
+ fileLockManagerPort: NodeMessagePort;
28
+ firstProcessId: number;
29
+ }): Promise<RemoteAPI<PlaygroundCliBlueprintV2Worker>>;
30
+ writeProgressUpdate(writeStream: NodeJS.WriteStream, message: string, finalUpdate: boolean): void;
31
+ }
@@ -0,0 +1 @@
1
+ export declare function getV2Runner(): Promise<File>;
@@ -0,0 +1,35 @@
1
+ import { type StreamedPHPResponse, type UniversalPHP } from '@php-wasm/universal';
2
+ import { type BlueprintV2Declaration, type ParsedBlueprintV2Declaration } from './blueprint-v2-declaration';
3
+ export type PHPExceptionDetails = {
4
+ exception: string;
5
+ message: string;
6
+ file: string;
7
+ line: number;
8
+ trace: string;
9
+ };
10
+ export type BlueprintMessage = {
11
+ type: 'blueprint.target_resolved';
12
+ } | {
13
+ type: 'blueprint.progress';
14
+ progress: number;
15
+ caption: string;
16
+ } | {
17
+ type: 'blueprint.error';
18
+ message: string;
19
+ details?: PHPExceptionDetails;
20
+ } | {
21
+ type: 'blueprint.completion';
22
+ message: string;
23
+ };
24
+ interface RunV2Options {
25
+ php: UniversalPHP;
26
+ cliArgs?: string[];
27
+ blueprint: BlueprintV2Declaration | ParsedBlueprintV2Declaration;
28
+ blueprintOverrides?: {
29
+ wordpressVersion?: string;
30
+ additionalSteps?: any[];
31
+ };
32
+ onMessage?: (message: BlueprintMessage) => void | Promise<void>;
33
+ }
34
+ export declare function runBlueprintV2(options: RunV2Options): Promise<StreamedPHPResponse>;
35
+ export {};
@@ -0,0 +1,49 @@
1
+ /// <reference types="node" />
2
+ import type { FileLockManager } from '@php-wasm/node';
3
+ import { EmscriptenDownloadMonitor } from '@php-wasm/progress';
4
+ import type { RemoteAPI, SupportedPHPVersion } from '@php-wasm/universal';
5
+ import { PHPWorker } from '@php-wasm/universal';
6
+ import { type ParsedBlueprintV2Declaration, type BlueprintV2Declaration } from './blueprint-v2-declaration';
7
+ import { type MessagePort } from 'worker_threads';
8
+ import { type RunCLIArgs } from '../run-cli';
9
+ export type WorkerBootArgs = RunCLIArgs & {
10
+ php: SupportedPHPVersion;
11
+ siteUrl: string;
12
+ firstProcessId: number;
13
+ processIdSpaceLength: number;
14
+ trace: boolean;
15
+ blueprint: BlueprintV2Declaration | ParsedBlueprintV2Declaration;
16
+ };
17
+ type WorkerRunBlueprintArgs = RunCLIArgs & {
18
+ siteUrl: string;
19
+ blueprint: BlueprintV2Declaration | ParsedBlueprintV2Declaration;
20
+ };
21
+ interface WorkerBootRequestHandlerOptions {
22
+ siteUrl: string;
23
+ php: SupportedPHPVersion;
24
+ allow?: string;
25
+ firstProcessId: number;
26
+ processIdSpaceLength: number;
27
+ trace: boolean;
28
+ }
29
+ export declare class PlaygroundCliBlueprintV2Worker extends PHPWorker {
30
+ booted: boolean;
31
+ fileLockManager: RemoteAPI<FileLockManager> | FileLockManager | undefined;
32
+ constructor(monitor: EmscriptenDownloadMonitor);
33
+ /**
34
+ * Call this method before boot() to use file locking.
35
+ *
36
+ * This method is separate from boot() to simplify the related Comlink.transferHandlers
37
+ * setup – if an argument is a MessagePort, we're transferring it, not copying it.
38
+ *
39
+ * @see comlink-sync.ts
40
+ * @see phpwasm-emscripten-library-file-locking-for-node.js
41
+ */
42
+ useFileLockManager(port: MessagePort): Promise<void>;
43
+ bootAsPrimaryWorker(args: WorkerBootArgs): Promise<void>;
44
+ bootAsSecondaryWorker(args: WorkerBootArgs): Promise<void>;
45
+ runBlueprintV2(args: WorkerRunBlueprintArgs): Promise<void>;
46
+ bootRequestHandler({ siteUrl, allow, php, firstProcessId, processIdSpaceLength, trace, }: WorkerBootRequestHandlerOptions): Promise<void>;
47
+ dispose(): Promise<void>;
48
+ }
49
+ export {};
Binary file
package/cli.cjs CHANGED
@@ -1,2 +1,2 @@
1
- "use strict";const s=require("./run-cli-Bon3Rz_F.cjs");s.parseOptionsAndRunCLI().catch(()=>{process.exit(1)});
1
+ "use strict";const n=require("./run-cli-opqDVXKw.cjs");n.parseOptionsAndRunCLI();
2
2
  //# sourceMappingURL=cli.cjs.map
package/cli.cjs.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"cli.cjs","sources":["../../../../packages/playground/cli/src/cli.ts"],"sourcesContent":["import { parseOptionsAndRunCLI } from './run-cli';\n\n// Do not await this as top-level await is not supported in all environments.\nparseOptionsAndRunCLI().catch(() => {\n\t// process.exit(1); is here and not in parseOptionsAndRunCLI()\n\t// so that we can unit test the failure modes with try/catch.\n\tprocess.exit(1);\n});\n"],"names":["parseOptionsAndRunCLI"],"mappings":"uDAGAA,EAAAA,sBAAsB,EAAE,MAAM,IAAM,CAGnC,QAAQ,KAAK,CAAC,CACf,CAAC"}
1
+ {"version":3,"file":"cli.cjs","sources":["../../../../packages/playground/cli/src/cli.ts"],"sourcesContent":["import { parseOptionsAndRunCLI } from './run-cli';\n\n// Do not await this as top-level await is not supported in all environments.\nparseOptionsAndRunCLI();\n"],"names":["parseOptionsAndRunCLI"],"mappings":"uDAGAA,EAAAA,sBAAsB"}
package/cli.js CHANGED
@@ -1,5 +1,3 @@
1
- import { p } from "./run-cli-DyJ6_Vj8.js";
2
- p().catch(() => {
3
- process.exit(1);
4
- });
1
+ import { p } from "./run-cli-CY1lYIJH.js";
2
+ p();
5
3
  //# sourceMappingURL=cli.js.map
package/cli.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"cli.js","sources":["../../../../packages/playground/cli/src/cli.ts"],"sourcesContent":["import { parseOptionsAndRunCLI } from './run-cli';\n\n// Do not await this as top-level await is not supported in all environments.\nparseOptionsAndRunCLI().catch(() => {\n\t// process.exit(1); is here and not in parseOptionsAndRunCLI()\n\t// so that we can unit test the failure modes with try/catch.\n\tprocess.exit(1);\n});\n"],"names":["parseOptionsAndRunCLI"],"mappings":";AAGAA,EAAsB,EAAE,MAAM,MAAM;AAGnC,UAAQ,KAAK,CAAC;AACf,CAAC;"}
1
+ {"version":3,"file":"cli.js","sources":["../../../../packages/playground/cli/src/cli.ts"],"sourcesContent":["import { parseOptionsAndRunCLI } from './run-cli';\n\n// Do not await this as top-level await is not supported in all environments.\nparseOptionsAndRunCLI();\n"],"names":["parseOptionsAndRunCLI"],"mappings":";AAGAA,EAAsB;"}
package/index.cjs CHANGED
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const n=require("./run-cli-Bon3Rz_F.cjs");exports.parseOptionsAndRunCLI=n.parseOptionsAndRunCLI;exports.runCLI=n.runCLI;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const n=require("./run-cli-opqDVXKw.cjs");exports.parseOptionsAndRunCLI=n.parseOptionsAndRunCLI;exports.runCLI=n.runCLI;
2
2
  //# sourceMappingURL=index.cjs.map
package/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import { p, r as s } from "./run-cli-DyJ6_Vj8.js";
1
+ import { p, r as s } from "./run-cli-CY1lYIJH.js";
2
2
  export {
3
3
  p as parseOptionsAndRunCLI,
4
4
  s as runCLI
@@ -1,5 +1,7 @@
1
1
  import type { PHPRequest, PHPResponse, RemoteAPI } from '@php-wasm/universal';
2
- import type { PlaygroundCliWorker } from './worker-thread';
2
+ import type { PlaygroundCliBlueprintV1Worker as PlaygroundCliWorkerV1 } from './blueprints-v1/worker-thread-v1';
3
+ import type { PlaygroundCliBlueprintV2Worker as PlaygroundCliWorkerV2 } from './blueprints-v2/worker-thread-v2';
4
+ type PlaygroundCliWorker = PlaygroundCliWorkerV1 | PlaygroundCliWorkerV2;
3
5
  type WorkerLoad = {
4
6
  worker: RemoteAPI<PlaygroundCliWorker>;
5
7
  activeRequests: Set<Promise<PHPResponse>>;
@@ -0,0 +1,124 @@
1
+ import { createNodeFsMountHandler as l } from "@php-wasm/node";
2
+ import r, { existsSync as c } from "fs";
3
+ import m, { basename as p, join as h } from "path";
4
+ function v(e) {
5
+ const t = [];
6
+ for (const n of e) {
7
+ const o = n.split(":");
8
+ if (o.length !== 2)
9
+ throw new Error(`Invalid mount format: ${n}.
10
+ Expected format: /host/path:/vfs/path.
11
+ If your path contains a colon, e.g. C:\\myplugin, use the --mount-dir option instead.
12
+ Example: --mount-dir C:\\my-plugin /wordpress/wp-content/plugins/my-plugin`);
13
+ const [s, i] = o;
14
+ if (!c(s))
15
+ throw new Error(`Host path does not exist: ${s}`);
16
+ t.push({ hostPath: s, vfsPath: i });
17
+ }
18
+ return t;
19
+ }
20
+ function x(e) {
21
+ if (e.length % 2 !== 0)
22
+ throw new Error("Invalid mount format. Expected: /host/path /vfs/path");
23
+ const t = [];
24
+ for (let n = 0; n < e.length; n += 2) {
25
+ const o = e[n], s = e[n + 1];
26
+ if (!c(o))
27
+ throw new Error(`Host path does not exist: ${o}`);
28
+ t.push({
29
+ hostPath: m.resolve(process.cwd(), o),
30
+ vfsPath: s
31
+ });
32
+ }
33
+ return t;
34
+ }
35
+ async function N(e, t) {
36
+ for (const n of t)
37
+ await e.mount(
38
+ n.vfsPath,
39
+ l(n.hostPath)
40
+ );
41
+ }
42
+ const u = {
43
+ step: "runPHP",
44
+ code: {
45
+ filename: "activate-theme.php",
46
+ content: `<?php
47
+ require_once getenv('DOCROOT') . '/wp-load.php';
48
+ $theme = wp_get_theme();
49
+ if (!$theme->exists()) {
50
+ $themes = wp_get_themes();
51
+ if (count($themes) > 0) {
52
+ $themeName = array_keys($themes)[0];
53
+ switch_theme($themeName);
54
+ }
55
+ }
56
+ `
57
+ }
58
+ };
59
+ function E(e) {
60
+ const t = process.cwd(), n = [...e.mount || []], o = [...e["mount-before-install"] || []], s = {
61
+ ...e,
62
+ mount: n,
63
+ "mount-before-install": o,
64
+ "additional-blueprint-steps": [
65
+ ...e["additional-blueprint-steps"] || []
66
+ ]
67
+ };
68
+ if (g(t)) {
69
+ const i = p(t);
70
+ n.push({
71
+ hostPath: t,
72
+ vfsPath: `/wordpress/wp-content/plugins/${i}`
73
+ }), s["additional-blueprint-steps"].push({
74
+ step: "activatePlugin",
75
+ pluginPath: `/wordpress/wp-content/plugins/${p(t)}`
76
+ });
77
+ } else if (w(t)) {
78
+ const i = p(t);
79
+ n.push({
80
+ hostPath: t,
81
+ vfsPath: `/wordpress/wp-content/themes/${i}`
82
+ }), s["additional-blueprint-steps"].push({
83
+ step: "activateTheme",
84
+ themeDirectoryName: i
85
+ });
86
+ } else if (f(t)) {
87
+ const i = r.readdirSync(t);
88
+ for (const a of i)
89
+ a !== "index.php" && n.push({
90
+ hostPath: `${t}/${a}`,
91
+ vfsPath: `/wordpress/wp-content/${a}`
92
+ });
93
+ s["additional-blueprint-steps"].push(u);
94
+ } else d(t) ? (o.push({ hostPath: t, vfsPath: "/wordpress" }), s["additional-blueprint-steps"].push(u)) : n.push({ hostPath: t, vfsPath: "/wordpress" });
95
+ return s;
96
+ }
97
+ function d(e) {
98
+ const t = r.readdirSync(e);
99
+ return t.includes("wp-admin") && t.includes("wp-includes") && t.includes("wp-content");
100
+ }
101
+ function f(e) {
102
+ const t = r.readdirSync(e);
103
+ return t.includes("themes") || t.includes("plugins") || t.includes("mu-plugins") || t.includes("uploads");
104
+ }
105
+ function w(e) {
106
+ if (!r.readdirSync(e).includes("style.css"))
107
+ return !1;
108
+ const n = r.readFileSync(h(e, "style.css"), "utf8");
109
+ return !!/^(?:[ \t]*<\?php)?[ \t/*#@]*Theme Name:(.*)$/im.exec(n);
110
+ }
111
+ function g(e) {
112
+ const t = r.readdirSync(e), n = /^(?:[ \t]*<\?php)?[ \t/*#@]*Plugin Name:(.*)$/im;
113
+ return !!t.filter((s) => s.endsWith(".php")).find((s) => {
114
+ const i = r.readFileSync(h(e, s), "utf8");
115
+ return !!n.exec(i);
116
+ });
117
+ }
118
+ export {
119
+ x as a,
120
+ E as e,
121
+ N as m,
122
+ v as p
123
+ };
124
+ //# sourceMappingURL=mounts-B-Qdcyyt.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mounts-B-Qdcyyt.js","sources":["../../../../packages/playground/cli/src/mounts.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"],"names":["parseMountWithDelimiterArguments","mounts","parsedMounts","mount","mountParts","hostPath","vfsPath","existsSync","parseMountDirArguments","i","source","path","mountResources","php","createNodeFsMountHandler","ACTIVATE_FIRST_THEME_STEP","expandAutoMounts","args","mountBeforeInstall","newArgs","isPluginFilename","pluginName","basename","isThemeDirectory","themeName","containsWpContentDirectories","files","fs","file","containsFullWordPressInstallation","styleCssContent","join","pluginNameRegex","fileContent"],"mappings":"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"}
@@ -0,0 +1,15 @@
1
+ "use strict";const p=require("@php-wasm/node"),r=require("fs"),a=require("path");function h(t){const e=[];for(const n of t){const o=n.split(":");if(o.length!==2)throw new Error(`Invalid mount format: ${n}.
2
+ Expected format: /host/path:/vfs/path.
3
+ If your path contains a colon, e.g. C:\\myplugin, use the --mount-dir option instead.
4
+ Example: --mount-dir C:\\my-plugin /wordpress/wp-content/plugins/my-plugin`);const[s,i]=o;if(!r.existsSync(s))throw new Error(`Host path does not exist: ${s}`);e.push({hostPath:s,vfsPath:i})}return e}function l(t){if(t.length%2!==0)throw new Error("Invalid mount format. Expected: /host/path /vfs/path");const e=[];for(let n=0;n<t.length;n+=2){const o=t[n],s=t[n+1];if(!r.existsSync(o))throw new Error(`Host path does not exist: ${o}`);e.push({hostPath:a.resolve(process.cwd(),o),vfsPath:s})}return e}async function d(t,e){for(const n of e)await t.mount(n.vfsPath,p.createNodeFsMountHandler(n.hostPath))}const c={step:"runPHP",code:{filename:"activate-theme.php",content:`<?php
5
+ require_once getenv('DOCROOT') . '/wp-load.php';
6
+ $theme = wp_get_theme();
7
+ if (!$theme->exists()) {
8
+ $themes = wp_get_themes();
9
+ if (count($themes) > 0) {
10
+ $themeName = array_keys($themes)[0];
11
+ switch_theme($themeName);
12
+ }
13
+ }
14
+ `}};function m(t){const e=process.cwd(),n=[...t.mount||[]],o=[...t["mount-before-install"]||[]],s={...t,mount:n,"mount-before-install":o,"additional-blueprint-steps":[...t["additional-blueprint-steps"]||[]]};if(P(e)){const i=a.basename(e);n.push({hostPath:e,vfsPath:`/wordpress/wp-content/plugins/${i}`}),s["additional-blueprint-steps"].push({step:"activatePlugin",pluginPath:`/wordpress/wp-content/plugins/${a.basename(e)}`})}else if(g(e)){const i=a.basename(e);n.push({hostPath:e,vfsPath:`/wordpress/wp-content/themes/${i}`}),s["additional-blueprint-steps"].push({step:"activateTheme",themeDirectoryName:i})}else if(w(e)){const i=r.readdirSync(e);for(const u of i)u!=="index.php"&&n.push({hostPath:`${e}/${u}`,vfsPath:`/wordpress/wp-content/${u}`});s["additional-blueprint-steps"].push(c)}else f(e)?(o.push({hostPath:e,vfsPath:"/wordpress"}),s["additional-blueprint-steps"].push(c)):n.push({hostPath:e,vfsPath:"/wordpress"});return s}function f(t){const e=r.readdirSync(t);return e.includes("wp-admin")&&e.includes("wp-includes")&&e.includes("wp-content")}function w(t){const e=r.readdirSync(t);return e.includes("themes")||e.includes("plugins")||e.includes("mu-plugins")||e.includes("uploads")}function g(t){if(!r.readdirSync(t).includes("style.css"))return!1;const n=r.readFileSync(a.join(t,"style.css"),"utf8");return!!/^(?:[ \t]*<\?php)?[ \t/*#@]*Theme Name:(.*)$/im.exec(n)}function P(t){const e=r.readdirSync(t),n=/^(?:[ \t]*<\?php)?[ \t/*#@]*Plugin Name:(.*)$/im;return!!e.filter(s=>s.endsWith(".php")).find(s=>{const i=r.readFileSync(a.join(t,s),"utf8");return!!n.exec(i)})}exports.expandAutoMounts=m;exports.mountResources=d;exports.parseMountDirArguments=l;exports.parseMountWithDelimiterArguments=h;
15
+ //# sourceMappingURL=mounts-D7bhhGq3.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mounts-D7bhhGq3.cjs","sources":["../../../../packages/playground/cli/src/mounts.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"],"names":["parseMountWithDelimiterArguments","mounts","parsedMounts","mount","mountParts","hostPath","vfsPath","existsSync","parseMountDirArguments","i","source","path","mountResources","php","createNodeFsMountHandler","ACTIVATE_FIRST_THEME_STEP","expandAutoMounts","args","mountBeforeInstall","newArgs","isPluginFilename","pluginName","basename","isThemeDirectory","themeName","containsWpContentDirectories","files","fs","file","containsFullWordPressInstallation","styleCssContent","join","pluginNameRegex","fileContent"],"mappings":"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"}
@@ -1,4 +1,5 @@
1
1
  import type { PHP } from '@php-wasm/universal';
2
+ import type { RunCLIArgs } from './run-cli';
2
3
  export interface Mount {
3
4
  hostPath: string;
4
5
  vfsPath: string;
@@ -35,4 +36,12 @@ export declare function parseMountWithDelimiterArguments(mounts: string[]): Moun
35
36
  * @returns An array of Mount objects.
36
37
  */
37
38
  export declare function parseMountDirArguments(mounts: string[]): Mount[];
38
- export declare function mountResources(php: PHP, mounts: Mount[]): void;
39
+ export declare function mountResources(php: PHP, mounts: Mount[]): Promise<void>;
40
+ /**
41
+ * Auto-mounts resolution logic:
42
+ */
43
+ export declare function expandAutoMounts(args: RunCLIArgs): RunCLIArgs;
44
+ export declare function containsFullWordPressInstallation(path: string): boolean;
45
+ export declare function containsWpContentDirectories(path: string): boolean;
46
+ export declare function isThemeDirectory(path: string): boolean;
47
+ export declare function isPluginFilename(path: string): boolean;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wp-playground/cli",
3
- "version": "1.2.2",
3
+ "version": "2.0.0",
4
4
  "description": "WordPress Playground CLI",
5
5
  "repository": {
6
6
  "type": "git",
@@ -32,7 +32,7 @@
32
32
  "module": "./index.js",
33
33
  "types": "index.d.ts",
34
34
  "bin": "wp-playground.js",
35
- "gitHead": "aca5a878610532b47b07a5922fb6056993df0642",
35
+ "gitHead": "4aa6ec4f0fe23920f735c0050228a509d94ce077",
36
36
  "dependencies": {
37
37
  "@zip.js/zip.js": "2.7.57",
38
38
  "ajv": "8.12.0",
@@ -55,15 +55,15 @@
55
55
  "wasm-feature-detect": "1.8.0",
56
56
  "ws": "8.18.1",
57
57
  "yargs": "17.7.2",
58
- "@wp-playground/blueprints": "1.2.2",
59
- "@php-wasm/progress": "1.2.2",
60
- "@php-wasm/universal": "1.2.2",
61
- "@php-wasm/node": "1.2.2",
62
- "@php-wasm/logger": "1.2.2",
63
- "@wp-playground/storage": "1.2.2",
64
- "@wp-playground/common": "1.2.2",
65
- "@wp-playground/wordpress": "1.2.2",
66
- "@php-wasm/util": "1.2.2"
58
+ "@php-wasm/logger": "2.0.0",
59
+ "@php-wasm/progress": "2.0.0",
60
+ "@php-wasm/universal": "2.0.0",
61
+ "@wp-playground/blueprints": "2.0.0",
62
+ "@wp-playground/common": "2.0.0",
63
+ "@wp-playground/wordpress": "2.0.0",
64
+ "@php-wasm/node": "2.0.0",
65
+ "@php-wasm/util": "2.0.0",
66
+ "@wp-playground/storage": "2.0.0"
67
67
  },
68
68
  "overrides": {
69
69
  "rollup": "^4.34.6",