Skip to content

Commit f3648e1

Browse files
committed
Draft php command
1 parent 563d5a8 commit f3648e1

File tree

5 files changed

+80
-44
lines changed

5 files changed

+80
-44
lines changed

packages/playground/cli/src/blueprints-v1/worker-thread-v1.ts

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,18 +3,18 @@ import { loadNodeRuntime } from '@php-wasm/node';
33
import { EmscriptenDownloadMonitor } from '@php-wasm/progress';
44
import type { RemoteAPI, SupportedPHPVersion } from '@php-wasm/universal';
55
import {
6-
PHPWorker,
76
consumeAPI,
87
consumeAPISync,
98
exposeAPI,
109
sandboxedSpawnHandlerFactory,
1110
} from '@php-wasm/universal';
1211
import { sprintf } from '@php-wasm/util';
1312
import { RecommendedPHPVersion } from '@wp-playground/common';
14-
import { bootWordPress, bootRequestHandler } from '@wp-playground/wordpress';
13+
import { bootRequestHandler, bootWordPress } from '@wp-playground/wordpress';
1514
import { rootCertificates } from 'tls';
1615
import { jspi } from 'wasm-feature-detect';
17-
import { MessageChannel, type MessagePort, parentPort } from 'worker_threads';
16+
import { MessageChannel, parentPort, type MessagePort } from 'worker_threads';
17+
import { PlaygroundCliWorker } from '../playground-cli-worker';
1818
import { mountResources } from '../mounts';
1919

2020
export interface Mount {
@@ -78,7 +78,7 @@ function tracePhpWasm(processId: number, format: string, ...args: any[]) {
7878
);
7979
}
8080

81-
export class PlaygroundCliBlueprintV1Worker extends PHPWorker {
81+
export class PlaygroundCliBlueprintV1Worker extends PlaygroundCliWorker {
8282
booted = false;
8383
fileLockManager: RemoteAPI<FileLockManager> | FileLockManager | undefined;
8484

@@ -293,11 +293,6 @@ export class PlaygroundCliBlueprintV1Worker extends PHPWorker {
293293
throw e;
294294
}
295295
}
296-
297-
// Provide a named disposal method that can be invoked via comlink.
298-
async dispose() {
299-
await this[Symbol.asyncDispose]();
300-
}
301296
}
302297

303298
const phpChannel = new MessageChannel();

packages/playground/cli/src/blueprints-v2/worker-thread-v2.ts

Lines changed: 11 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -3,41 +3,39 @@ import type { FileLockManager } from '@php-wasm/node';
33
import { createNodeFsMountHandler, loadNodeRuntime } from '@php-wasm/node';
44
import { EmscriptenDownloadMonitor } from '@php-wasm/progress';
55
import type {
6-
PHP,
76
FileTree,
7+
PHP,
88
RemoteAPI,
99
SupportedPHPVersion,
1010
} from '@php-wasm/universal';
1111
import {
1212
PHPExecutionFailureError,
1313
PHPResponse,
14-
PHPWorker,
1514
consumeAPI,
1615
consumeAPISync,
1716
exposeAPI,
1817
sandboxedSpawnHandlerFactory,
1918
} from '@php-wasm/universal';
2019
import { sprintf } from '@php-wasm/util';
2120
import {
22-
type BlueprintMessage,
2321
runBlueprintV2,
24-
} from '@wp-playground/blueprints';
25-
import {
26-
type ParsedBlueprintV2Declaration,
22+
type BlueprintMessage,
2723
type BlueprintV2Declaration,
24+
type ParsedBlueprintV2Declaration,
2825
} from '@wp-playground/blueprints';
26+
import type {
27+
PHPInstanceCreatedHook,
28+
PhpIniOptions,
29+
} from '@wp-playground/wordpress';
2930
import { bootRequestHandler } from '@wp-playground/wordpress';
3031
import { existsSync } from 'fs';
3132
import path from 'path';
3233
import { rootCertificates } from 'tls';
33-
import { MessageChannel, type MessagePort, parentPort } from 'worker_threads';
34-
import type { Mount } from '../mounts';
3534
import { jspi } from 'wasm-feature-detect';
35+
import { MessageChannel, parentPort, type MessagePort } from 'worker_threads';
36+
import { PlaygroundCliWorker } from '../playground-cli-worker';
37+
import type { Mount } from '../mounts';
3638
import { type RunCLIArgs } from '../run-cli';
37-
import type {
38-
PhpIniOptions,
39-
PHPInstanceCreatedHook,
40-
} from '@wp-playground/wordpress';
4139

4240
async function mountResources(php: PHP, mounts: Mount[]) {
4341
for (const mount of mounts) {
@@ -154,7 +152,7 @@ export type WorkerBootRequestHandlerOptions = Omit<
154152
onPHPInstanceCreated: PHPInstanceCreatedHook;
155153
};
156154

157-
export class PlaygroundCliBlueprintV2Worker extends PHPWorker {
155+
export class PlaygroundCliBlueprintV2Worker extends PlaygroundCliWorker {
158156
booted = false;
159157
blueprintTargetResolved = false;
160158
phpInstancesThatNeedMountsAfterTargetResolved = new Set<PHP>();
@@ -470,11 +468,6 @@ export class PlaygroundCliBlueprintV2Worker extends PHPWorker {
470468
throw e;
471469
}
472470
}
473-
474-
// Provide a named disposal method that can be invoked via comlink.
475-
async dispose() {
476-
await this[Symbol.asyncDispose]();
477-
}
478471
}
479472

480473
const phpChannel = new MessageChannel();

packages/playground/cli/src/load-balancer.ts

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,5 @@
11
import type { PHPRequest, PHPResponse, RemoteAPI } from '@php-wasm/universal';
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-
5-
type PlaygroundCliWorker = PlaygroundCliWorkerV1 | PlaygroundCliWorkerV2;
2+
import type { PlaygroundCliWorker } from './playground-cli-worker';
63

74
// TODO: Let's merge worker management into PHPProcessManager
85
// when we can have multiple workers in both CLI and web.
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import { PHPWorker } from '@php-wasm/universal';
2+
3+
export class PlaygroundCliWorker extends PHPWorker {
4+
async runCLIScript(
5+
argv: string[],
6+
options: { env?: Record<string, string> } = {}
7+
) {
8+
const streamedResponse = await this.cli(argv, options);
9+
streamedResponse.stdout.pipeTo(
10+
new WritableStream({
11+
write(chunk) {
12+
process.stdout.write(chunk);
13+
},
14+
})
15+
);
16+
streamedResponse.stderr.pipeTo(
17+
new WritableStream({
18+
write(chunk) {
19+
process.stderr.write(chunk);
20+
},
21+
})
22+
);
23+
return await streamedResponse.exitCode;
24+
}
25+
26+
// Provide a named disposal method that can be invoked via comlink.
27+
async dispose() {
28+
await this[Symbol.asyncDispose]();
29+
}
30+
}

packages/playground/cli/src/run-cli.ts

Lines changed: 34 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -26,11 +26,7 @@ import {
2626
parseMountWithDelimiterArguments,
2727
} from './mounts';
2828
import { startServer } from './start-server';
29-
import type {
30-
Mount,
31-
PlaygroundCliBlueprintV1Worker,
32-
} from './blueprints-v1/worker-thread-v1';
33-
import type { PlaygroundCliBlueprintV2Worker } from './blueprints-v2/worker-thread-v2';
29+
import type { Mount } from './blueprints-v1/worker-thread-v1';
3430
import { FileLockManagerForNode } from '@php-wasm/node';
3531
import { LoadBalancer } from './load-balancer';
3632
/* eslint-disable no-console */
@@ -49,6 +45,7 @@ import {
4945
cleanupStalePlaygroundTempDirs,
5046
createPlaygroundCliTempDir,
5147
} from './temp-dir';
48+
import type { PlaygroundCliWorker } from './playground-cli-worker';
5249

5350
// Inlined worker URLs for static analysis by downstream bundlers
5451
// These are replaced at build time by the Vite plugin in vite.config.ts
@@ -75,9 +72,18 @@ export async function parseOptionsAndRunCLI() {
7572
.usage('Usage: wp-playground <command> [options]')
7673
.positional('command', {
7774
describe: 'Command to run',
78-
choices: ['server', 'run-blueprint', 'build-snapshot'] as const,
75+
choices: [
76+
'server',
77+
'run-blueprint',
78+
'build-snapshot',
79+
'run-script',
80+
] as const,
7981
demandOption: true,
8082
})
83+
.option('script', {
84+
describe: 'PHP script to run',
85+
type: 'string',
86+
})
8187
.option('outfile', {
8288
describe: 'When building, write to this output file.',
8389
type: 'string',
@@ -354,7 +360,14 @@ export async function parseOptionsAndRunCLI() {
354360

355361
const command = args._[0] as string;
356362

357-
if (!['run-blueprint', 'server', 'build-snapshot'].includes(command)) {
363+
if (
364+
![
365+
'run-blueprint',
366+
'server',
367+
'build-snapshot',
368+
'run-script',
369+
].includes(command)
370+
) {
358371
yargsObject.showHelp();
359372
process.exit(1);
360373
}
@@ -394,12 +407,13 @@ export async function parseOptionsAndRunCLI() {
394407

395408
export interface RunCLIArgs {
396409
blueprint?: BlueprintDeclaration | BlueprintBundle;
397-
command: 'server' | 'run-blueprint' | 'build-snapshot';
410+
command: 'server' | 'run-blueprint' | 'build-snapshot' | 'run-script';
398411
debug?: boolean;
399412
login?: boolean;
400413
mount?: Mount[];
401414
'mount-before-install'?: Mount[];
402415
outfile?: string;
416+
script?: string;
403417
php?: SupportedPHPVersion;
404418
port?: number;
405419
'site-url'?: string;
@@ -436,10 +450,6 @@ export interface RunCLIArgs {
436450
allow?: string;
437451
}
438452

439-
type PlaygroundCliWorker =
440-
| PlaygroundCliBlueprintV1Worker
441-
| PlaygroundCliBlueprintV2Worker;
442-
443453
export interface RunCLIServer extends AsyncDisposable {
444454
playground: RemoteAPI<PlaygroundCliWorker>;
445455
server: Server;
@@ -690,6 +700,18 @@ export async function runCLI(args: RunCLIArgs): Promise<RunCLIServer> {
690700
} else if (args.command === 'run-blueprint') {
691701
logger.log(`Blueprint executed`);
692702
process.exit(0);
703+
} else if (args.command === 'run-script') {
704+
const exitCode = await playground.runCLIScript(
705+
['php', args.script as string],
706+
{
707+
env: {
708+
SHELL_PIPE: '0',
709+
},
710+
}
711+
);
712+
// Wait until the next tick before exiting to ensure the output is flushed.
713+
await new Promise((resolve) => setTimeout(resolve, 0));
714+
process.exit(exitCode);
693715
}
694716

695717
if (
@@ -836,7 +858,6 @@ async function spawnWorkerThreads(
836858
}
837859
});
838860
worker.once('error', function (e: Error) {
839-
console.error(e);
840861
const error = new Error(
841862
`Worker failed to load worker. ${
842863
e.message ? `Original error: ${e.message}` : ''

0 commit comments

Comments
 (0)