@phpsandbox/sdk 0.0.27 → 0.0.28

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.
@@ -952,6 +952,14 @@ var PHPSandbox = (() => {
952
952
  };
953
953
 
954
954
  // src/shell.ts
955
+ function resolveExecInput(command, argsOrOpts = [], opts) {
956
+ const args = Array.isArray(argsOrOpts) ? argsOrOpts : [];
957
+ const resolvedOpts = Array.isArray(argsOrOpts) ? opts : argsOrOpts;
958
+ return {
959
+ command: Array.isArray(command) ? command : args.length > 0 ? [command, ...args] : command,
960
+ opts: resolvedOpts
961
+ };
962
+ }
955
963
  var CommandError = class extends Error {
956
964
  constructor(output, exitCode) {
957
965
  super(output);
@@ -975,10 +983,83 @@ var PHPSandbox = (() => {
975
983
  constructor(okra) {
976
984
  this.okra = okra;
977
985
  }
978
- async exec(command) {
979
- const result = await this.okra.invoke("shell.exec", { command });
986
+ onOutput(id, handler) {
987
+ this.okra.listen(`shell.output.${id}`, handler);
988
+ }
989
+ listen(event, handler) {
990
+ return this.okra.listen(event, handler);
991
+ }
992
+ async exec(command, argsOrOpts = [], opts) {
993
+ const input = resolveExecInput(command, argsOrOpts, opts);
994
+ const { abortSignal, ...payloadOpts } = input.opts ?? {};
995
+ const result = await this.okra.invoke(
996
+ "shell.exec",
997
+ {
998
+ command: input.command,
999
+ opts: Object.keys(payloadOpts).length > 0 ? payloadOpts : void 0
1000
+ },
1001
+ { abortSignal }
1002
+ );
980
1003
  return new Result(result.output, result.exitCode);
981
1004
  }
1005
+ execStream(command, argsOrOpts = [], opts) {
1006
+ const input = resolveExecInput(command, argsOrOpts, opts);
1007
+ const id = input.opts?.id || nanoid();
1008
+ const disposables = /* @__PURE__ */ new Set();
1009
+ let controller = null;
1010
+ let closed = false;
1011
+ const dispose = () => {
1012
+ for (const disposable of disposables) {
1013
+ disposable.dispose();
1014
+ }
1015
+ disposables.clear();
1016
+ };
1017
+ const close = () => {
1018
+ if (closed) {
1019
+ return;
1020
+ }
1021
+ closed = true;
1022
+ dispose();
1023
+ if (controller) {
1024
+ try {
1025
+ controller.close();
1026
+ } catch {
1027
+ }
1028
+ }
1029
+ };
1030
+ const fail = (error) => {
1031
+ if (closed) {
1032
+ return;
1033
+ }
1034
+ closed = true;
1035
+ dispose();
1036
+ if (controller) {
1037
+ controller.error(error);
1038
+ }
1039
+ };
1040
+ const output = new ReadableStream({
1041
+ start: (_controller) => {
1042
+ controller = _controller;
1043
+ disposables.add(
1044
+ this.listen(`shell.output.${id}`, (data) => {
1045
+ controller?.enqueue(data.output);
1046
+ })
1047
+ );
1048
+ },
1049
+ cancel: () => {
1050
+ closed = true;
1051
+ dispose();
1052
+ }
1053
+ });
1054
+ const result = this.exec(input.command, { ...input.opts, id }).then((response) => {
1055
+ close();
1056
+ return response;
1057
+ }).catch((error) => {
1058
+ fail(error);
1059
+ throw error;
1060
+ });
1061
+ return { output, result };
1062
+ }
982
1063
  };
983
1064
 
984
1065
  // node_modules/@msgpack/msgpack/dist.esm/utils/utf8.mjs