mirror of
https://github.com/discordjs/discord.js.git
synced 2026-03-15 19:13:31 +01:00
feat(create-discord-bot): Add prompts, command handler and deployment script (#9570)
* feat(create-discord-bot): Add prompts, command handler and deployment script * fix: revert package template name * chore: make requested changes * chore: make requested changes * fix: remove uneeded listeners * fix: use `0` for eslint * fix: remaining requested changes * chore: requested changes * fix: remove redundant call
This commit is contained in:
@@ -1,70 +1,81 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
// eslint-disable-next-line n/shebang
|
||||
import { cpSync, existsSync, mkdirSync, readdirSync, readFileSync, writeFileSync } from 'node:fs';
|
||||
import { cp, stat, mkdir, readdir, readFile, writeFile } from 'node:fs/promises';
|
||||
import path from 'node:path';
|
||||
import process from 'node:process';
|
||||
import { URL } from 'node:url';
|
||||
import chalk from 'chalk';
|
||||
import { program } from 'commander';
|
||||
import validateProjectName from 'validate-npm-package-name';
|
||||
import { install, resolvePackageManager } from './helpers/packageManager.js';
|
||||
import { GUIDE_URL } from './util/constants.js';
|
||||
|
||||
program
|
||||
.description('Create a basic discord.js bot.')
|
||||
.option('--typescript', 'Whether to use the TypeScript template.')
|
||||
.argument('<directory>', 'The directory where this will be created.')
|
||||
.parse();
|
||||
|
||||
const { typescript } = program.opts();
|
||||
const [directory] = program.args;
|
||||
|
||||
if (!directory) {
|
||||
console.error(chalk.red('Please specify the project directory.'));
|
||||
process.exit(1);
|
||||
interface Options {
|
||||
directory: string;
|
||||
javascript?: boolean;
|
||||
typescript?: boolean;
|
||||
}
|
||||
|
||||
const root = path.resolve(directory);
|
||||
const directoryName = path.basename(root);
|
||||
|
||||
if (existsSync(root) && readdirSync(root).length > 0) {
|
||||
console.error(chalk.red(`The directory ${chalk.yellow(`"${directoryName}"`)} is not empty.`));
|
||||
console.error(chalk.red(`Please specify an empty directory.`));
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
// We'll use the directory name as the project name. Check npm name validity.
|
||||
const validationResult = validateProjectName(directoryName);
|
||||
|
||||
if (!validationResult.validForNewPackages) {
|
||||
console.error(
|
||||
chalk.red(
|
||||
`Cannot create a project named ${chalk.yellow(`"${directoryName}"`)} due to npm naming restrictions.\n\nErrors:`,
|
||||
),
|
||||
);
|
||||
|
||||
for (const error of [...(validationResult.errors ?? []), ...(validationResult.warnings ?? [])]) {
|
||||
console.error(chalk.red(`- ${error}`));
|
||||
export async function createDiscordBot({ typescript, javascript, directory }: Options) {
|
||||
if (!directory) {
|
||||
console.error(chalk.red('Please specify the project directory.'));
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
console.error(chalk.red('\nSee https://docs.npmjs.com/cli/configuring-npm/package-json for more details.'));
|
||||
process.exit(1);
|
||||
const root = path.resolve(directory);
|
||||
const directoryName = path.basename(root);
|
||||
|
||||
const directoryStats = await stat(root).catch(async (error) => {
|
||||
// Create a new directory if the specified one does not exist.
|
||||
if (error.code === 'ENOENT') {
|
||||
await mkdir(root, { recursive: true });
|
||||
return stat(root);
|
||||
}
|
||||
|
||||
throw error;
|
||||
});
|
||||
|
||||
// If a directory exists and it's not empty, throw an error.
|
||||
if (directoryStats.isDirectory() && (await readdir(root)).length > 0) {
|
||||
console.error(chalk.red(`The directory ${chalk.yellow(`"${directoryName}"`)} is not empty.`));
|
||||
console.error(chalk.red(`Please specify an empty directory.`));
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
// We'll use the directory name as the project name. Check npm name validity.
|
||||
const validationResult = validateProjectName(directoryName);
|
||||
|
||||
if (!validationResult.validForNewPackages) {
|
||||
console.error(
|
||||
chalk.red(
|
||||
`Cannot create a project named ${chalk.yellow(
|
||||
`"${directoryName}"`,
|
||||
)} due to npm naming restrictions.\n\nErrors:`,
|
||||
),
|
||||
);
|
||||
|
||||
for (const error of [...(validationResult.errors ?? []), ...(validationResult.warnings ?? [])]) {
|
||||
console.error(chalk.red(`- ${error}`));
|
||||
}
|
||||
|
||||
console.error(chalk.red('\nSee https://docs.npmjs.com/cli/configuring-npm/package-json for more details.'));
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
console.log(`Creating ${directoryName} in ${chalk.green(root)}.`);
|
||||
await cp(new URL(`../template/${typescript ? 'TypeScript' : 'JavaScript'}`, import.meta.url), root, {
|
||||
recursive: true,
|
||||
});
|
||||
|
||||
process.chdir(root);
|
||||
|
||||
const newPackageJSON = await readFile('./package.json', { encoding: 'utf8' }).then((str) =>
|
||||
str.replace('[REPLACE-NAME]', directoryName),
|
||||
);
|
||||
await writeFile('./package.json', newPackageJSON);
|
||||
|
||||
const packageManager = resolvePackageManager();
|
||||
install(packageManager);
|
||||
console.log(chalk.green('All done! Be sure to read through the discord.js guide for help on your journey.'));
|
||||
console.log(`Link: ${chalk.cyan(GUIDE_URL)}`);
|
||||
}
|
||||
|
||||
if (!existsSync(root)) {
|
||||
mkdirSync(root, { recursive: true });
|
||||
}
|
||||
|
||||
console.log(`Creating ${directoryName} in ${chalk.green(root)}.`);
|
||||
cpSync(new URL(`../template/${typescript ? 'TypeScript' : 'JavaScript'}`, import.meta.url), root, { recursive: true });
|
||||
|
||||
process.chdir(root);
|
||||
|
||||
const newPackageJSON = readFileSync('./package.json', { encoding: 'utf8' }).replace('[REPLACE-NAME]', directoryName);
|
||||
writeFileSync('./package.json', newPackageJSON);
|
||||
|
||||
const packageManager = resolvePackageManager();
|
||||
install(packageManager);
|
||||
console.log(chalk.green('All done! Be sure to read through the discord.js guide for help on your journey.'));
|
||||
console.log(`Link: ${chalk.cyan(GUIDE_URL)}`);
|
||||
|
||||
39
packages/create-discord-bot/src/index.ts
Normal file
39
packages/create-discord-bot/src/index.ts
Normal file
@@ -0,0 +1,39 @@
|
||||
import { program } from 'commander';
|
||||
import prompts from 'prompts';
|
||||
import { createDiscordBot } from './create-discord-bot.js';
|
||||
|
||||
program
|
||||
.description('Create a basic discord.js bot.')
|
||||
.option('--directory', 'The directory where this will be created.')
|
||||
.option('--typescript', 'Whether to use the TypeScript template.')
|
||||
.option('--javascript', 'Whether to use the JavaScript template.')
|
||||
.parse();
|
||||
|
||||
let { typescript, javascript, directory } = program.opts();
|
||||
|
||||
if (!directory) {
|
||||
directory = (
|
||||
await prompts({
|
||||
type: 'text',
|
||||
name: 'directory',
|
||||
initial: 'my-bot',
|
||||
message: 'What is the name of the directory you want to create this project in?',
|
||||
})
|
||||
).directory;
|
||||
}
|
||||
|
||||
if (typescript === undefined && javascript === undefined) {
|
||||
const { useTypescript } = await prompts({
|
||||
type: 'toggle',
|
||||
name: 'useTypescript',
|
||||
message: 'Do you want to use TypeScript?',
|
||||
initial: true,
|
||||
active: 'Yes',
|
||||
inactive: 'No',
|
||||
});
|
||||
|
||||
typescript = useTypescript;
|
||||
javascript = !useTypescript;
|
||||
}
|
||||
|
||||
await createDiscordBot({ typescript, javascript, directory });
|
||||
Reference in New Issue
Block a user