CRBT-Team/Purplet

View on GitHub
packages/create-purplet/src/index.ts

Summary

Maintainability
A
0 mins
Test Coverage
/* eslint-disable no-console */
import c from 'chalk';
import dedent from 'dedent';
import ora from 'ora';
import path from 'path';
import yargs from 'yargs';
import { existsSync } from 'node:fs';
import { realpath } from 'node:fs/promises';
import { fileURLToPath } from 'node:url';
import { hideBin } from 'yargs/helpers';
import { mkdirp } from './fs';
import { createConfig } from './prompts';
import { writeAll } from './writeAll';
import { version } from '../package.json';

export const cli = await yargs(hideBin(process.argv))
  .scriptName('create-purplet')
  .usage('$0 [options]')
  .version(version)
  .positional('root', {
    alias: 'r',
    describe: 'Where do you want to create your project?',
    type: 'string',
  })
  .option('allow-empty', {
    type: 'boolean',
  })
  .option('template', {
    alias: 't',
    type: 'string',
    describe: 'Which template do you want to use?',
  })
  .option('lang', {
    alias: 'l',
    type: 'string',
    describe: 'Either "ts" | "jsdoc" | "js". TS and JSDoc will enable type-checking ',
  })
  .option('eslint', {
    type: 'boolean',
  })
  .option('prettier', {
    type: 'boolean',
  })
  .option('no-install', {
    type: 'boolean',
  })
  .parse();

// Assign the first positional argument as 'root' if it is available.
if (cli._[0]) {
  cli.root = cli._[0] as string;
}

/*
Here lies my beautiful ASCII art of the Purplet logo. 
Dave does not approve of it, regardless of the beauty that it undeniably is.
Thus, I have no other choice but to comment it out and not add publish it,
So whereas this work of art is not going to ship with the create-purplet CLI,
it will forever remain deep in our hearts (and in the commit history and in the source code)

RIP Purplet ASCII logo
2022 - 2022
*/

// console.log(
//   c.magentaBright(
//     `
//                         *****
//                    ****************
//                 *********************
//               *************************
//               **************************
//              ***************************
//   ***********            ***************
// **************            **************
// ***************           **************
// *****************         **************
// *******************       **************
//               ************
//   *********   ************
//     ********  ************
//        *****  ************
//          ***  ************
// `
//   )
// );
// console.log();
console.log(c.magentaBright('Welcome to Purplet!'));
console.log(c.grey(`Next-gen framework to build modern Discord apps.`));
console.log();

console.log(c.yellowBright('⚠️  Purplet is beta software! ⚠️'));
console.log(c.yellowBright('Report issues to https://github.com/CRBT-Team/purplet/issues'));
console.log();

const cliRoot = path.resolve(fileURLToPath(import.meta.url), '../../');

let templatesRoot = [
  path.join(cliRoot, 'dist/templates'), // Published Case
  path.join(cliRoot, '../../examples'), // Monorepo case
].find(dir => existsSync(dir))!;

if (!templatesRoot) {
  console.error(c.redBright(`Could not find templates directory.`));
  console.error(c.redBright(`This is a build issue with Purplet, and should be reported to them:`));
  console.error(c.redBright(`https://github.com/CRBT-Team/purplet/issues`));
  process.exit(2);
}

templatesRoot = (await realpath(templatesRoot)) ?? templatesRoot;

const config = await createConfig(templatesRoot);

// Detect Package Manager
let packageManager = 'npm';
if (process.env.npm_config_user_agent) {
  if (process.env.npm_config_user_agent.includes('pnpm')) {
    packageManager = 'pnpm';
  } else if (process.env.npm_config_user_agent.includes('yarn')) {
    packageManager = 'yarn';
  }
}

// END OF PROMPTING
console.log();

const spinner = ora('Creating new Purplet project... May take a minute.').start();

await mkdirp(config.root);

await writeAll(config, templatesRoot);

// TODO: stylize a better readme / use from template
// await writeFile(path.join(root, 'README.md'), `# ${path.basename(root)}`);

spinner.succeed('Created Project');

console.log();
console.log(dedent`
  ${c.magentaBright.bold(
    `Your bot has been created inside of the ${path.basename(config.root)} directory.`
  )}

    ${c.whiteBright('$')} ${c.cyanBright('cd')} ${c.greenBright(
  path.relative(process.cwd(), config.root)
)}
    ${c.whiteBright('$')} ${c.cyanBright(packageManager)}${c.greenBright(
  `${packageManager === 'yarn' ? '' : ' install'}`
)}

  Before you can run your bot, you need to create an ${c.cyanBright('.env')} file with a Discord
  bot token, which can be created at ${c.magentaBright(
    'https://discord.com/developers/applications'
  )}.
  Your ${c.cyanBright('.env')} file should look something like this:

    ${c.cyanBright('DISCORD_TOKEN')}=${c.grey('<your bot token>')}

  Once that is setup, you can start developing your bot by running:

    ${c.whiteBright('$')} ${c.cyanBright(packageManager)} ${c.greenBright(
  `${packageManager === 'npm' ? 'run ' : ''}dev`
)}

  Purplet Documentation: ${c.magentaBright('https://purplet.js.org/docs/getting-started')}
  Discord Server: ${c.magentaBright('https://discord.gg/BFkHA8P7rh')}
`);
console.log();