Skip to content
Snippets Groups Projects
utils.ts 3.92 KiB
Newer Older
  • Learn to ignore specific revisions
  • import { ChildProcess, exec } from "child_process";
    
    import crypto from "node:crypto";
    import { mkdir } from "node:fs/promises";
    
    import * as path from "path";
    
    import waitPort from "wait-port";
    
    import {
      TemplateEngine,
      TemplateFramework,
      TemplatePostInstallAction,
      TemplateType,
      TemplateUI,
    
    } from "../helpers";
    
    
    export type AppType = "--frontend" | "--no-frontend" | "";
    const MODEL = "gpt-3.5-turbo";
    
    const EMBEDDING_MODEL = "text-embedding-ada-002";
    
    export type CreateLlamaResult = {
      projectName: string;
      appProcess: ChildProcess;
    };
    
    Marcus Schiesser's avatar
    Marcus Schiesser committed
    // eslint-disable-next-line max-params
    
    export async function checkAppHasStarted(
      frontend: boolean,
      framework: TemplateFramework,
    
      port: number,
    
      timeout: number,
    ) {
      if (frontend) {
        await Promise.all([
          waitPort({
            host: "localhost",
            port: port,
            timeout,
          }),
          waitPort({
            host: "localhost",
            port: externalPort,
            timeout,
          }),
        ]).catch((err) => {
          console.error(err);
          throw err;
        });
      } else {
        let wPort: number;
        if (framework === "nextjs") {
          wPort = port;
        } else {
          wPort = externalPort;
    
        await waitPort({
          host: "localhost",
          port: wPort,
          timeout,
        }).catch((err) => {
          console.error(err);
          throw err;
        });
    
    Marcus Schiesser's avatar
    Marcus Schiesser committed
    // eslint-disable-next-line max-params
    
    export async function runCreateLlama(
    
      cwd: string,
    
      templateType: TemplateType,
      templateFramework: TemplateFramework,
      templateEngine: TemplateEngine,
      templateUI: TemplateUI,
    
      vectorDb: TemplateVectorDB,
    
      appType: AppType,
    
      port: number,
    
      postInstallAction: TemplatePostInstallAction,
    ): Promise<CreateLlamaResult> {
    
      const createLlama = path.join(
        __dirname,
        "..",
        "output",
        "package",
        "dist",
        "index.js",
      );
    
    
      const name = [
        templateType,
        templateFramework,
        templateEngine,
        templateUI,
        appType,
      ].join("-");
      const command = [
        "node",
        createLlama,
        name,
        "--template",
        templateType,
        "--framework",
        templateFramework,
        "--engine",
        templateEngine,
        "--ui",
        templateUI,
    
        "--model",
        MODEL,
    
        "--embedding-model",
        EMBEDDING_MODEL,
    
        "--open-ai-key",
    
        process.env.OPENAI_API_KEY || "testKey",
    
        appType,
        "--eslint",
        "--use-npm",
    
        "--port",
        port,
    
        "--external-port",
        externalPort,
    
        "--post-install-action",
        postInstallAction,
    
      ].join(" ");
      console.log(`running command '${command}' in ${cwd}`);
    
    Marcus Schiesser's avatar
    Marcus Schiesser committed
      const appProcess = exec(command, {
    
        env: {
          ...process.env,
        },
    
      appProcess.stderr?.on("data", (data) => {
    
        console.log(data.toString());
      });
    
      appProcess.on("exit", (code) => {
        if (code !== 0 && code !== null) {
          throw new Error(`create-llama command was failed!`);
        }
      });
    
    
      // Wait for app to start
      if (postInstallAction === "runApp") {
        await checkAppHasStarted(
          appType === "--frontend",
          templateFramework,
          port,
          externalPort,
          1000 * 60 * 5,
        );
    
      } else {
        // wait create-llama to exit
        // we don't test install dependencies for now, so just set timeout for 10 seconds
        await new Promise((resolve, reject) => {
          const timeout = setTimeout(() => {
            reject(new Error("create-llama timeout error"));
          }, 1000 * 10);
          appProcess.on("exit", (code) => {
            if (code !== 0 && code !== null) {
              clearTimeout(timeout);
              reject(new Error("create-llama command was failed!"));
            } else {
              clearTimeout(timeout);
              resolve(undefined);
            }
          });
        });
    
      }
    
      return {
        projectName: name,
        appProcess,
      };
    
    export async function createTestDir() {
    
      const cwd = path.join(__dirname, "cache", crypto.randomUUID());
    
      await mkdir(cwd, { recursive: true });
      return cwd;
    }