1.1.2Updated a month ago
import { Command } from "jsr:@cliffy/command@1.0.0-rc.7";

import { HOST_URL, TOKEN } from "../config.ts";

export default new Command()
  .name('run')
  .alias('start')
  .description('Runs an application hosted on Viapak')
  .arguments('<name:string> [args...:string]')
  .option('-v, --version <version:string>', 'Runs a specific version')
  .example(
    'Run latest version',
    'run example'
  )
  .example(
    'Run specific version',
    'run example --version 1.0.0'
  )
  .action(async (_, name, ...args) => {
    let version = 'latest';

    const [ namespace ] = name.match(/@[^\/]+/) as string[];
    name = name.replace(namespace + '/', '');

    if(name.includes('@')) {
      [name, version] = name.split('@');
    }

    let package_info: Record<string, any> = {};

    try {
      package_info = await (
        await fetch(`${HOST_URL}/api/v1/packages/${namespace}/${name}`, {
          headers: {
            Authorization: `Bearer ${TOKEN}`
          }
        })
      ).json();
    } catch(_) { /**/ }

    if(!package_info.exists) {
      console.log(`${name} could not be found.`)
      console.log();
      Deno.exit(0);
    }

    await runScript(`${HOST_URL}/${namespace}/${name}@${version}`, {
      env: Deno.env.toObject(),
      args,
    });
  });

  const runScript = async (url: string, options?: Deno.CommandOptions) => {
  try {
    const command = new Deno.Command("deno", {
      args: ["run", "-A", "-r", "-q", url, ...(options?.args ?? [])],
      env: options?.env,
      stdout: "piped",
      stderr: "piped",
    });

    const process = command.spawn();

    const stdoutReader = process.stdout.getReader();
    const stderrReader = process.stderr.getReader();

    const readStream = async (reader: ReadableStreamDefaultReader<Uint8Array>, type: "stdout" | "stderr") => {
      while (true) {
        const { done, value } = await reader.read();
        if (done) break;
        const text = new TextDecoder().decode(value);
        if (type === "stdout") console.log(text);
        else console.error(text);
      }
    };

    await Promise.all([
      readStream(stdoutReader, "stdout"),
      readStream(stderrReader, "stderr"),
    ]);

    const status = await process.status;

    if (!status.success) {
      throw new Error();
    }
  } catch (_) {
    console.log();
    console.error('Viapak > The script did not exit gracefully!');
    console.log();
  }
}