Skip to content

Commit 89dc440

Browse files
authored
Merge pull request #69 from prisma/update-inquirer
feat(inquirer): update codebase from inquirer to @inquirer/prompts
2 parents e35439c + 4d920a7 commit 89dc440

File tree

10 files changed

+623
-1073
lines changed

10 files changed

+623
-1073
lines changed

package-lock.json

Lines changed: 526 additions & 916 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -41,10 +41,7 @@
4141
"provenance": true
4242
},
4343
"devDependencies": {
44-
"@types/dedent": "^0.7.0",
45-
"@types/inquirer": "9.0.1",
46-
"@types/node": "18.7.1",
47-
"@types/node-fetch": "2.6.2",
44+
"@types/node": "^22.8.6",
4845
"@types/tar-fs": "2.0.1",
4946
"@typescript-eslint/eslint-plugin": "5.36.2",
5047
"@typescript-eslint/parser": "5.36.2",
@@ -59,15 +56,12 @@
5956
"vitest": "0.23.1"
6057
},
6158
"dependencies": {
59+
"@inquirer/prompts": "^7.0.1",
6260
"@molt/command": "^0.7.0",
6361
"chalk": "^5.0.1",
64-
"dedent": "^0.7.0",
6562
"gunzip-maybe": "^1.4.2",
66-
"inquirer": "^9.1.0",
67-
"inquirer-search-list": "^1.2.6",
68-
"node-fetch": "^3.2.10",
6963
"ora": "^6.1.2",
70-
"tar-fs": "^2.1.1",
64+
"tar-fs": "^3.0.6",
7165
"valid-filename": "^4.0.0",
7266
"zod": "^3.21.2"
7367
},
@@ -76,4 +70,4 @@
7670
"path": "./node_modules/cz-conventional-changelog"
7771
}
7872
}
79-
}
73+
}

src/cli/index.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ export default class Cli {
106106

107107
// select template from list of projects
108108
if (!this.args.template.length) {
109-
this.args.template = await prompts.getTemplate(this.projects);
109+
this.args.template = (await prompts.getTemplate(this.projects)) as string;
110110
}
111111

112112
if (!this.args.install) {
@@ -126,7 +126,7 @@ export default class Cli {
126126
}
127127

128128
if (!this.args.path.length) {
129-
this.args.path = await prompts.getProjectDirectory();
129+
this.args.path = ".";
130130
}
131131

132132
return this.args;

src/cli/prompts.ts

Lines changed: 28 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -1,124 +1,95 @@
1-
import logger from "../helpers/logger";
2-
import validate from "./validation";
1+
import { confirm, input, select } from "@inquirer/prompts";
32
import chalk from "chalk";
4-
import inquirer from "inquirer";
5-
import SearchList from "inquirer-search-list";
63

7-
inquirer.registerPrompt("search-list", SearchList);
4+
import logger from "../helpers/logger";
5+
import validate from "./validation";
86

97
const selectStarterOrExample = async (): Promise<string> => {
10-
const { starter } = await inquirer.prompt({
11-
type: "list",
8+
return await select({
129
message: `How would you like to start your new project?`,
13-
name: "starter",
1410
choices: [
1511
{
16-
name: `Prisma Starter (Recommended)\n\xa0\xa0- ${chalk.gray(
17-
"The Prisma Starter is pre-configured with Prisma ORM, Accelerate, Pulse, and a Prisma Postgres database.",
18-
)}`,
12+
name: `Prisma Starter (Recommended)`,
1913
value: "starter",
14+
description:
15+
"The Prisma Starter is pre-configured with Prisma ORM, Accelerate, Pulse, and a Prisma Postgres database.",
2016
},
2117
{
2218
name: "Explore other examples",
2319
value: "example",
20+
description:
21+
"Our curated list of examples from the prisma/prisma-examples GitHub repository, showing how to use Prisma ORM with various other tools and frameworks.",
2422
},
2523
],
2624
});
27-
return starter;
2825
};
2926

30-
const getTemplate = async (projects: string[]): Promise<string> => {
27+
const getTemplate = async (projects: string[]) => {
3128
logger.success(
3229
`\nDon't see what you're looking for? Request a new template here:\n\xa0\xa0➡ ${chalk.underline.gray(
3330
"https://pris.ly/prisma-examples-suggestion",
3431
)}\n`,
3532
);
36-
const { template } = await inquirer.prompt({
37-
// @ts-expect-error Inquirer doesn't register the type.
38-
type: "search-list",
33+
const result = await select({
3934
message: `Which template would you like to use?`,
40-
name: "template",
4135
choices: projects,
42-
validate: (answer) => {
43-
try {
44-
validate.project(projects, answer);
45-
} catch (e) {
46-
return false;
47-
}
48-
return true;
49-
},
5036
});
5137

52-
return template;
38+
return result;
5339
};
5440

55-
const selectORMorPDP = async (): Promise<string> => {
41+
const selectORMorPDP = async () => {
5642
logger.success(
5743
`\nThese options correspond to the root directories in the prisma-examples repository:\n`,
5844
);
59-
const { start } = await inquirer.prompt({
60-
type: "list",
45+
return await select({
6146
message: `Which Prisma examples would you like to explore?`,
62-
name: "start",
6347
choices: [
6448
{
65-
name: `Prisma ORM\n\xa0\xa0- ${chalk.gray(
66-
"Define Prisma schema and run queries",
67-
)}`,
49+
name: `Prisma ORM`,
6850
value: "orm",
51+
description: "Define Prisma schema and run queries",
6952
},
7053
{
71-
name: `Prisma Accelerate\n\xa0\xa0- ${chalk.gray(
72-
"Perform caching and connection pooling",
73-
)}`,
54+
name: `Prisma Accelerate`,
7455
value: "accelerate",
56+
description: "Perform caching and connection pooling",
7557
},
7658
{
77-
name: `Prisma Pulse\n\xa0\xa0- ${chalk.gray(
78-
"Monitor and react to real-time database changes",
79-
)}`,
59+
name: `Prisma Pulse`,
8060
value: "pulse",
61+
description: "Monitor and react to real-time database changes",
8162
},
8263
{
83-
name: `Prisma Optimize\n\xa0\xa0- ${chalk.gray(
84-
"Analyze and improve query performance",
85-
)}`,
64+
name: `Prisma Optimize`,
8665
value: "optimize",
66+
description: "Analyze and improve query performance",
8767
},
8868
],
8969
});
90-
91-
return start;
9270
};
9371

94-
const getInstallSelection = async (): Promise<boolean> => {
95-
const { packages } = await inquirer.prompt({
96-
type: "confirm",
72+
const getInstallSelection = async () => {
73+
return confirm({
9774
message: `Should we automatically install packages for you?`,
98-
name: "packages",
9975
default: true,
10076
});
101-
return Boolean(packages);
10277
};
10378

10479
const selectManager = async (): Promise<"npm" | "yarn" | "pnpm"> => {
105-
const { manager } = await inquirer.prompt({
106-
type: "list",
80+
return await select({
10781
message: "Which package manager do you prefer?",
108-
name: "manager",
10982
default: process.env.npm_config_user_agent,
11083
choices: ["npm", "yarn", "pnpm"],
11184
});
112-
return manager;
11385
};
11486

11587
const getProjectName = async (defaultValue = ""): Promise<string> => {
116-
const { dirname } = await inquirer.prompt({
117-
type: "input",
88+
return await input({
11889
message: "What should the project folder be named?",
119-
name: "dirname",
12090
default: defaultValue,
121-
filter: (input) => input.replace("/", "_").trim(),
91+
transformer: (input) => input.replace("/", "_").trim(),
92+
// filter: (input) => input.replace("/", "_").trim(),
12293
validate(answer) {
12394
try {
12495
validate.directoryName(answer);
@@ -129,18 +100,12 @@ const getProjectName = async (defaultValue = ""): Promise<string> => {
129100
return true;
130101
},
131102
});
132-
return dirname;
133-
};
134-
135-
const getProjectDirectory = async (): Promise<string> => {
136-
return ".";
137103
};
138104

139105
export default {
140106
selectStarterOrExample,
141107
selectORMorPDP,
142108
getInstallSelection,
143-
getProjectDirectory,
144109
getProjectName,
145110
selectManager,
146111
getTemplate,

src/constants.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,8 @@ export const EXAMPLES_REPO_URL =
44
export const EXAMPLES_REPO_TAR =
55
"https://codeload.github.com/prisma/prisma-examples/tar.gz/latest";
66

7-
export const EXAMPLES_REPO_INTERCEPTOR = // "http://localhost:3000/api/interceptor";
7+
export const EXAMPLES_REPO_INTERCEPTOR =
88
"https://www.try-prisma-analytics.com/api/interceptor";
9-
// "https://www.try-prisma-analytics.vercel.app/api/interceptor";
109

1110
export const EXAMPLES_DIR_ACCEPT = [
1211
"typescript",

src/helpers/download.ts

Lines changed: 38 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,11 @@
11
import { EXAMPLES_REPO_TAR, EXAMPLES_REPO_INTERCEPTOR } from "../constants";
22
import { CliInput } from "../types";
33
import gunzip from "gunzip-maybe";
4-
import fetch from "node-fetch";
54
import ora from "ora";
65
import path from "path";
7-
import stream from "stream";
6+
import { Readable } from "node:stream";
7+
import { pipeline } from "node:stream/promises";
88
import tar from "tar-fs";
9-
import { promisify } from "util";
10-
11-
const pipeline = promisify(stream.pipeline);
129

1310
export default async function download(options: CliInput): Promise<void> {
1411
if (!options.template.length) {
@@ -17,69 +14,69 @@ export default async function download(options: CliInput): Promise<void> {
1714
);
1815
}
1916

20-
const spinner = ora();
21-
spinner.start(`Downloading and extracting the ${options.template} project`);
17+
const templateName =
18+
options.template === "databases/prisma-postgres"
19+
? "Prisma Starter"
20+
: options.template;
2221

23-
// Download the repo via the interceptor
24-
let response = await fetch(EXAMPLES_REPO_INTERCEPTOR, {
25-
method: "POST",
26-
body: JSON.stringify(options),
27-
});
22+
const spinner = ora();
23+
spinner.start(`Downloading and extracting the ${templateName} project`);
2824

29-
if (response.status !== 200) {
30-
// Something went wrong with the interceptor,
31-
// try fetching from GitHub directly ...
32-
response = await fetch(EXAMPLES_REPO_TAR, {
33-
method: "GET",
25+
try {
26+
// Download the repo via the interceptor
27+
let response = await fetch(EXAMPLES_REPO_INTERCEPTOR, {
28+
method: "POST",
29+
body: JSON.stringify(options),
3430
});
3531

36-
if (response.status !== 200) {
37-
spinner.stopAndPersist();
32+
if (!response.ok) {
33+
// fallback to GitHub direct download
34+
response = await fetch(EXAMPLES_REPO_TAR, {
35+
method: "GET",
36+
});
37+
}
38+
39+
if (!response.ok || !response.body) {
3840
throw new Error(
39-
`Something went wrong when fetching prisma/prisma-examples. Received a status code ${response.status}.`,
41+
`Failed to fetch prisma/prisma-examples. Status: ${response.status}`,
4042
);
4143
}
42-
}
4344

44-
try {
4545
await pipeline(
46-
// Unzip it
47-
response.body?.pipe(gunzip()),
48-
// Extract the stuff into this directory
46+
Readable.from(response.body),
47+
gunzip(),
4948
tar.extract(`${options.path}/${options.name}`, {
5049
map(header) {
5150
const originalDirName = header.name.split("/")[0];
5251
header.name = header.name.replace(`${originalDirName}/`, "");
53-
options.template = options.template
52+
53+
const normalizedTemplate = options.template
5454
.split(path.sep)
5555
.join(path.posix.sep);
56-
if (options.template) {
57-
if (header.name.startsWith(`${options.template}/`)) {
58-
header.name = header.name.replace(options.template, "");
59-
} else {
60-
header.name = "[[ignore-me]]";
61-
}
56+
57+
if (header.name.startsWith(`${normalizedTemplate}/`)) {
58+
header.name = header.name.replace(normalizedTemplate, "");
59+
} else {
60+
header.name = "[[ignore-me]]";
6261
}
62+
6363
return header;
6464
},
6565
ignore(_filename, header) {
6666
if (!header) {
6767
throw new Error(`Header is undefined`);
6868
}
69-
7069
return header.name === "[[ignore-me]]";
7170
},
72-
readable: true,
73-
writable: true,
7471
}),
7572
);
76-
spinner.succeed(
77-
`Downloaded and extracted the ${options.template} project in ${options.path}/${options.name}.\n`,
78-
);
79-
} catch (e) {
80-
spinner.stopAndPersist();
73+
} catch (error) {
74+
spinner.fail();
8175
throw new Error(
82-
`Something went wrong when extracting the files from the repository tar file.`,
76+
`Failed to download or extract files: ${(error as Error).message}`,
8377
);
8478
}
79+
spinner.succeed(
80+
`Downloaded and extracted the ${options.template} project in ${options.path}/${options.name}.\n`,
81+
);
8582
}

src/helpers/getProjects.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import { EXAMPLES_DIR_ACCEPT, EXAMPLES_REPO_URL } from "../constants";
2-
import fetch from "node-fetch";
32

43
export default async function getProjects() {
54
const result = await fetch(EXAMPLES_REPO_URL);

src/helpers/logger.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
11
import chalk from "chalk";
2-
import dedent from "dedent";
32

43
export default {
54
error: (message: string) => {
6-
console.log(chalk.redBright(dedent(message)));
5+
console.log(chalk.redBright(message));
76
},
87
success: (message: string) => {
9-
console.log(dedent(message));
8+
console.log(message);
109
},
1110
};

0 commit comments

Comments
 (0)