feat(*): more questions, better handling, better ui

This commit is contained in:
EvolutionX
2022-04-21 21:50:47 +05:30
parent 0e97b7db8a
commit f9318024bb
7 changed files with 791 additions and 1677 deletions

99
dumpfiles.js Normal file
View File

@@ -0,0 +1,99 @@
//! message for sern devs: ignore this!!!
const SpinnerName = [
'dots',
'dots2',
'dots3',
'dots4',
'dots5',
'dots6',
'dots7',
'dots8',
'dots9',
'dots10',
'dots11',
'dots12',
'dots8Bit',
'line',
'line2',
'pipe',
'simpleDots',
'simpleDotsScrolling',
'star',
'star2',
'flip',
'hamburger',
'growVertical',
'growHorizontal',
'balloon',
'balloon2',
'noise',
'bounce',
'boxBounce',
'boxBounce2',
'triangle',
'arc',
'circle',
'squareCorners',
'circleQuarters',
'circleHalves',
'squish',
'toggle',
'toggle2',
'toggle3',
'toggle4',
'toggle5',
'toggle6',
'toggle7',
'toggle8',
'toggle9',
'toggle10',
'toggle11',
'toggle12',
'toggle13',
'arrow',
'arrow2',
'arrow3',
'bouncingBar',
'bouncingBall',
'smiley',
'monkey',
'hearts',
'clock',
'earth',
'material',
'moon',
'runner',
'pong',
'shark',
'dqpb',
'weather',
'christmas',
'grenade',
'point',
'layer',
'betaWave',
'fingerDance',
'fistBump',
'soccerHeader',
'mindblown',
'speaker',
'orangePulse',
'bluePulse',
'orangeBluePulse',
'timeTravel',
'aesthetic',
];
// const p = new Promise((resolve) => {
// SpinnerName.forEach((spin, i, ar) => {
// setTimeout(() => {
// spinner.spinner = spin;
// spinner.text = `Initializing... ${spin}`;
// if (i === ar.length - 1) {
// resolve();
// }
// }, i * 1000);
// });
// });
// p.then(() => spinner.succeed('Finished!'));

2019
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,5 +1,5 @@
{
"name": "@sern-handler/cli",
"name": "@sern/cli",
"version": "0.1.0",
"description": "A CLI for @sern-handler",
"exports": "./src/index.js",
@@ -8,7 +8,9 @@
},
"type": "module",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
"test": "echo \"Error: no test specified\" && exit 1",
"release": "standard-version",
"preview": "standard-version --dry-run"
},
"repository": {
"type": "git",
@@ -28,8 +30,11 @@
},
"homepage": "https://github.com/sern-handler/cli#readme",
"dependencies": {
"colorette": "^2.0.16",
"execa": "^6.1.0",
"find-up": "6.3.0",
"inquirer": "8.2.2"
"ora": "^6.1.0",
"prompts": "2.4.2"
},
"devDependencies": {
"cz-conventional-changelog": "3.3.0",

View File

@@ -1,130 +1,108 @@
import { findUp } from 'find-up';
import pkg from 'inquirer';
const { prompt } = pkg;
// TODO refactor the intents stuff and add more questions
const Intents = [
'DIRECT_MESSAGES',
'DIRECT_MESSAGE_REACTIONS',
'DIRECT_MESSAGE_TYPING',
'GUILDS',
'GUILD_BANS',
'GUILD_EMOJIS_AND_STICKERS',
'GUILD_INTEGRATIONS',
'GUILD_INVITES',
'GUILD_MEMBERS',
'GUILD_MESSAGES',
'GUILD_MESSAGE_REACTIONS',
'GUILD_MESSAGE_TYPING',
'GUILD_PRESENCES',
'GUILD_SCHEDULED_EVENTS',
'GUILD_VOICE_STATES',
'GUILD_VOICE_STATES',
'GUILD_WEBHOOKS',
].map((i, j) => ({ name: i, value: j, short: `${j}` }));
import prompts from 'prompts';
import ora from 'ora';
import { redBright, yellowBright } from 'colorette';
import { execa } from 'execa';
import {
cmds_dir,
default_prefix,
intent,
lang,
main_dir,
token,
npmInit,
gitInit,
} from '../prompts/init.js';
const { prompt } = prompts;
// TODO make this functional and better!
export async function init({ flags }) {
if (flags?.includes('y')) {
console.log("I see a flag there! Seems like you're lazy!\nBye!");
process.exit(0);
}
const pkg = await findUp('package.json');
if (!pkg) {
console.log('No package.json found');
const node = await execa('node', ['--version']);
if (node.stdout.match(/v1(([0-6]\.[2-9])|([0-5]\.[0-9]))/gm)?.length) {
console.log(
yellowBright(
`\nYou are using Node ${node.stdout}\nPlease upgrade to Node 16.10.x or higher!\n`
)
);
return process.exit(1);
}
await whichLang();
const input = await kindPrefix();
if (input.prefix !== 'app_cmds') {
await legacy();
const pkg = await findUp('package.json');
if (!pkg) {
console.log(`No ${redBright('package.json')} found!`);
const npm = await prompt([npmInit]);
if (!npm.npminit) {
console.log(
`${redBright('Failed')} to initialize Sern!` +
'\nMaybe you should run npm init?'
);
return process.exit(1);
} else {
const spin = ora({
text: 'Initializing npm...',
spinner: 'aesthetic',
}).start();
const exee = await execa('npm', ['init', '-y']).catch(
() => null
); /* .stdout.pipe(process.stdout) */
await wait(300);
if (!exee || exee?.failed) {
spin.fail(
`${redBright('Failed')} to initialize npm!` +
'\nMaybe you should run npm init?'
);
return process.exit(1);
} else spin.succeed('Npm initialized!');
}
}
await intents();
}
const lang = {
message: 'What language you want the project to be in?',
name: 'lang',
type: 'list',
choices: [
{
name: 'JavaScript',
value: 'js',
type: 'choice',
},
{
name: 'TypeScript',
value: 'ts',
type: 'choice',
},
],
};
const intent = {
message: 'What intents do you want to keep?',
type: 'checkbox',
name: 'intents',
choices: Intents,
validate(a) {
if (a.length < 1) {
return 'You must choose at least one intent!';
const git = await findUp('.git/config');
if (!git) {
console.log(`No ${redBright('Git Repository')} found!`);
const git_init = await prompt([gitInit]);
if (!git_init.gitinit) {
console.log(
'Maybe you should run git init?\n' + `Alright Moving on...`
);
} else {
const spin = ora({
text: 'Initializing git...',
spinner: 'aesthetic',
}).start();
const exe = await execa('git', [
'init',
]); /* .stdout.pipe(process.stdout) */
await wait(300);
if (!exe || exe?.failed) {
spin.fail(
`${redBright('Failed')} to initialize git!` +
'\nMaybe you should run git init?'
);
return process.exit(1);
} else spin.succeed('Git initialized!');
return;
}
if (a.length === 17) {
return 'You do NOT need all intents!';
}
return true;
},
default: [3, 9],
};
}
const legacy_prefix = {
message: 'What is the legacy prefix for your bot?',
name: 'prefix',
type: 'input',
default: '!',
validate(a) {
if (a.length < 1) {
return 'You must choose a prefix!';
}
return true;
},
};
const kind_prefix = {
message:
'What kind of prefix your bot will use? Select "Both" for both prefixes.',
name: 'prefix',
type: 'list',
choices: [
{
name: 'Prefix [Message Based]',
value: 'legacy',
},
{
name: 'Interactions [Slash Commands, Context Menu Commands]',
value: 'app_cmds',
},
{
name: 'Both',
value: 'both',
type: 'choice',
},
],
};
async function whichLang() {
const a = await prompt([lang]);
return a;
const data = await prompt([
lang,
main_dir,
cmds_dir,
default_prefix,
token,
intent,
]);
console.log(data);
}
async function kindPrefix() {
const a = await prompt([kind_prefix]);
return a;
}
async function legacy() {
const a = await prompt([legacy_prefix]);
return a;
}
async function intents() {
const a = await prompt([intent]);
return a;
/**
* @param {number} ms
*/
async function wait(ms) {
const wait = (await import('util')).promisify(setTimeout);
return wait(ms);
}

17
src/commands/test.js Normal file
View File

@@ -0,0 +1,17 @@
//@ts-check
import { readFile, writeFile } from 'node:fs/promises';
import { findUp } from 'find-up';
/**
* @param {string} name
*/
export async function editMain(name) {
const pjLocation = await findUp('package.json');
const output = JSON.parse(await readFile(pjLocation, 'utf8'));
if (!output) throw new Error("Can't read file.");
output.main = name;
const result = () => writeFile(pjLocation, JSON.stringify(output, null, 2));
return result();
}

View File

@@ -1,19 +1,21 @@
#!/usr/bin/env node
import { init } from './commands/init.js';
const regex = /(?<=--|-)\w+/gm;
const flags = process.argv.slice(2).join(' ').match(regex);
// TODO codegolf it maybe? @HighArcs @jacoobes
const args = process.argv
.slice(2)
const rawArgs = process.argv.slice(2);
const args = rawArgs
.join(' ')
.trim()
.split(/ +/)
.filter((e) => !/(--|-)\w+/gm.test(e));
const cmdName = args[0];
const commands = new Map([['init', init]]);
const found = commands.get(cmdName);
if (found) {
await found({ args, flags });
} else console.log('Unknown Command // in future help maybe??');
} else console.log('Unknown Command');

102
src/prompts/init.js Normal file
View File

@@ -0,0 +1,102 @@
import { blueBright } from 'colorette';
// TODO refactor the intents stuff and add more questions
const Intents = [
'DIRECT_MESSAGES',
'DIRECT_MESSAGE_REACTIONS',
'DIRECT_MESSAGE_TYPING',
'GUILDS',
'GUILD_BANS',
'GUILD_EMOJIS_AND_STICKERS',
'GUILD_INTEGRATIONS',
'GUILD_INVITES',
'GUILD_MEMBERS',
'GUILD_MESSAGES',
'GUILD_MESSAGE_REACTIONS',
'GUILD_MESSAGE_TYPING',
'GUILD_PRESENCES',
'GUILD_SCHEDULED_EVENTS',
'GUILD_VOICE_STATES',
'GUILD_VOICE_STATES',
'GUILD_WEBHOOKS',
].map((i, j) => ({ title: i, value: j, short: `${j}` })); //! bad way
export const lang = {
message: 'What language you want the project to be in?',
name: 'lang',
type: 'select',
choices: [
{
title: 'JavaScript',
description: 'JS',
},
{
title: 'TypeScript',
description: 'TS',
},
],
};
export const intent = {
message: 'What intents do you want to keep?',
type: 'multiselect',
name: 'intents',
choices: Intents,
min: 1,
max: 16, //? 17 is max, i dont allow all
};
export const default_prefix = {
message:
'What is the default prefix for your bot? Type "none" if it is completely based on Application Commands',
name: 'prefix',
type: 'text',
initial: '!',
};
export const token = {
message: 'What is your bot token?',
name: 'token',
type: 'password',
validate: (/** @type {string} */ token) =>
token.match(
/(?<mfaToken>mfa\.[a-z0-9_-]{20,})|(?<basicToken>[a-z0-9_-]{23,28}\.[a-z0-9_-]{6,7}\.[a-z0-9_-]{27})/i
)?.length
? true
: 'Invalid token',
};
export const main_dir = {
message: 'What is the main directory of your project?',
name: 'main_dir',
type: 'text',
initial: 'src',
};
export const cmds_dir = {
message: 'What is the directory of your commands?',
name: 'cmds_dir',
type: 'text',
initial: 'commands',
validate: (dir) =>
dir === 'src' ? 'You can not use src as a directory' : true,
};
/**
* @type {import('prompts').PromptObject}
*/
export const npmInit = {
name: 'npminit',
type: 'confirm',
message: `Do you want to ${blueBright('me')} to initialize npm?`,
initial: true,
};
export const gitInit = {
name: 'gitinit',
type: 'confirm',
message: `Do you want to ${blueBright('me')} to initialize git?`,
initial: true,
};