Skip to content
Snippets Groups Projects
create-app.ts 3.43 KiB
Newer Older
/* eslint-disable import/no-extraneous-dependencies */
Marcus Schiesser's avatar
Marcus Schiesser committed
import path from "path";
import { green, yellow } from "picocolors";
Marcus Schiesser's avatar
Marcus Schiesser committed
import { tryGitInit } from "./helpers/git";
import { isFolderEmpty } from "./helpers/is-folder-empty";
import { getOnline } from "./helpers/is-online";
import { isWriteable } from "./helpers/is-writeable";
import { makeDir } from "./helpers/make-dir";
import fs from "fs";
import terminalLink from "terminal-link";
import type { InstallTemplateArgs } from "./helpers";
import { installTemplate } from "./helpers";
import { templatesDir } from "./helpers/dir";
import { toolsRequireConfig } from "./helpers/tools";
export type InstallAppArgs = Omit<
  InstallTemplateArgs,
  "appName" | "root" | "isOnline" | "customApiPath"
> & {
  appPath: string;
  frontend: boolean;
};

export async function createApp({
  appPath,
  packageManager,
  eslint,
  openAiKey,
  communityProjectPath,
  postInstallAction,
  dataSource,
}: InstallAppArgs): Promise<void> {
Marcus Schiesser's avatar
Marcus Schiesser committed
  const root = path.resolve(appPath);

  if (!(await isWriteable(path.dirname(root)))) {
    console.error(
Marcus Schiesser's avatar
Marcus Schiesser committed
      "The application path is not writable, please check folder permissions and try again.",
    );
    console.error(
Marcus Schiesser's avatar
Marcus Schiesser committed
      "It is likely you do not have write permissions for this folder.",
    );
    process.exit(1);
Marcus Schiesser's avatar
Marcus Schiesser committed
  const appName = path.basename(root);
Marcus Schiesser's avatar
Marcus Schiesser committed
  await makeDir(root);
  if (!isFolderEmpty(root, appName)) {
Marcus Schiesser's avatar
Marcus Schiesser committed
    process.exit(1);
Marcus Schiesser's avatar
Marcus Schiesser committed
  const useYarn = packageManager === "yarn";
  const isOnline = !useYarn || (await getOnline());
Marcus Schiesser's avatar
Marcus Schiesser committed
  console.log(`Creating a new LlamaIndex app in ${green(root)}.`);
  console.log();
  const args = {
    appName,
    root,
    template,
    framework,
    engine,
    ui,
    packageManager,
    isOnline,
    eslint,
    openAiKey,
    communityProjectPath,
    postInstallAction,
    dataSource,
  if (frontend) {
    // install backend
    const backendRoot = path.join(root, "backend");
    await makeDir(backendRoot);
    await installTemplate({ ...args, root: backendRoot, backend: true });
    // install frontend
    const frontendRoot = path.join(root, "frontend");
    await makeDir(frontendRoot);
    await installTemplate({
      ...args,
      root: frontendRoot,
      framework: "nextjs",
      customApiPath: `http://localhost:${externalPort ?? 8000}/api/chat`,
      backend: false,
    });
    // copy readme for fullstack
    await fs.promises.copyFile(
      path.join(templatesDir, "README-fullstack.md"),
      path.join(root, "README.md"),
    );
  } else {
    await installTemplate({ ...args, backend: true, forBackend: framework });
  if (tryGitInit(root)) {
Marcus Schiesser's avatar
Marcus Schiesser committed
    console.log("Initialized a git repository.");
    console.log();
  if (toolsRequireConfig(tools)) {
    console.log(
        `You have selected tools that require configuration. Please configure them in the ${terminalLink(
          "tools_config.json",
          `file://${root}/tools_config.json`,
        )} file.`,
      ),
    );
  }
  console.log("");
  console.log(`${green("Success!")} Created ${appName} at ${appPath}`);
  console.log(
    `Now have a look at the ${terminalLink(
      "README.md",
      `file://${root}/README.md`,
    )} and learn how to get started.`,
  );
Marcus Schiesser's avatar
Marcus Schiesser committed
  console.log();