import { stripAnsiCode } from "jsr:@std/fmt@0.225.4/colors";
export type CommandOptions = {
args?: string[];
};
type ServeCommandParams = {
command: string;
env?: Record<string, string>;
args?: string[] | boolean;
};
export function serveCommand(
params: ServeCommandParams,
): (req: Request) => Response | Promise<Response> {
return async (req: Request) => {
const url = new URL(req.url);
if (url.pathname === "/favicon.ico") {
return new Response(null, {
status: 404,
});
}
let pathname = url.pathname.slice(1);
if (pathname.endsWith("/")) {
pathname = pathname.slice(0, -1);
}
const requestArgs = pathname == ""
? []
: pathname.split("/").map(decodeURIComponent);
for (const [key, value] of url.searchParams.entries()) {
if (!value) {
if (key.length === 1) {
requestArgs.push(`-${key}`);
} else {
requestArgs.push(`--${key}`);
}
continue;
}
if (key.length === 1) {
requestArgs.push(`-${key}=${value}`);
} else {
requestArgs.push(`--${key}=${value}`);
}
}
const args: string[] = [];
if (Array.isArray(params.args)) {
if (requestArgs.length > 0) {
return new Response("Invalid arguments", {
status: 400,
headers: {
"content-type": "text/plain",
},
});
}
for (const arg of params.args) {
args.push(arg);
}
if (requestArgs.length) {
return new Response("Invalid arguments", {
status: 400,
headers: {
"content-type": "text/plain; charset=utf-8",
},
});
}
} else if (params.args) {
args.push(...requestArgs);
} else {
if (args.length > 0) {
return new Response("Invalid arguments", {
status: 400,
headers: {
"content-type": "text/plain; charset=utf-8",
},
});
}
}
const command = new Deno.Command(params.command, {
args,
env: params.env,
stdin: req.method === "POST" ? "piped" : "null",
stderr: "piped",
stdout: "piped",