aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/packages/create-turbo/src/commands/create/prompts.ts
blob: a5ed7bf8b20ec944a54d40616bae41d6f399767c (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
import path from "path";
import fs from "fs-extra";
import chalk from "chalk";
import type { PackageManager } from "@turbo/workspaces";
import type { CreateCommandArgument } from "./types";
import { getAvailablePackageManagers } from "@turbo/utils";
import { isFolderEmpty } from "../../utils/isFolderEmpty";
import inquirer from "inquirer";

function validateDirectory(directory: string): {
  valid: boolean;
  root: string;
  projectName: string;
  error?: string;
} {
  const root = path.resolve(directory);
  const projectName = path.basename(root);
  const exists = fs.existsSync(root);

  const stat = fs.lstatSync(root, { throwIfNoEntry: false });
  if (stat && !stat.isDirectory()) {
    return {
      valid: false,
      root,
      projectName,
      error: `${chalk.dim(
        projectName
      )} is not a directory - please try a different location`,
    };
  }

  if (exists) {
    const { isEmpty, conflicts } = isFolderEmpty(root);
    if (!isEmpty) {
      return {
        valid: false,
        root,
        projectName,
        error: `${chalk.dim(projectName)} has ${conflicts.length} conflicting ${
          conflicts.length === 1 ? "file" : "files"
        } - please try a different location`,
      };
    }
  }

  return { valid: true, root, projectName };
}

export async function directory({
  directory,
}: {
  directory: CreateCommandArgument;
}) {
  const projectDirectoryAnswer = await inquirer.prompt<{
    projectDirectory: string;
  }>({
    type: "input",
    name: "projectDirectory",
    message: "Where would you like to create your turborepo?",
    when: !directory,
    default: "./my-turborepo",
    validate: (directory: string) => {
      const { valid, error } = validateDirectory(directory);
      if (!valid && error) {
        return error;
      }
      return true;
    },
    filter: (directory: string) => directory.trim(),
  });

  const { projectDirectory: selectedProjectDirectory = directory as string } =
    projectDirectoryAnswer;

  return validateDirectory(selectedProjectDirectory);
}

export async function packageManager({
  packageManager,
  skipTransforms,
}: {
  packageManager: CreateCommandArgument;
  skipTransforms?: boolean;
}) {
  // if skip transforms is passed, we don't need to ask about the package manager (because that requires a transform)
  if (skipTransforms) {
    return undefined;
  }

  const availablePackageManagers = await getAvailablePackageManagers();
  const packageManagerAnswer = await inquirer.prompt<{
    packageManagerInput?: PackageManager;
  }>({
    name: "packageManagerInput",
    type: "list",
    message: "Which package manager do you want to use?",
    when:
      // prompt for package manager if it wasn't provided as an argument, or if it was
      // provided, but isn't available (always allow npm)
      !packageManager ||
      (packageManager as PackageManager) !== "npm" ||
      !Object.keys(availablePackageManagers).includes(packageManager),
    choices: ["npm", "pnpm", "yarn"].map((p) => ({
      name: p,
      value: p,
      disabled:
        // npm should always be available
        p === "npm" ||
        availablePackageManagers?.[p as PackageManager]?.available
          ? false
          : `not installed`,
    })),
  });

  const {
    packageManagerInput:
      selectedPackageManager = packageManager as PackageManager,
  } = packageManagerAnswer;

  return {
    name: selectedPackageManager,
    version: availablePackageManagers[selectedPackageManager].version,
  };
}