mirror of
https://github.com/sern-handler/cli
synced 2026-06-06 01:16:53 +00:00
feat(*): cli is now functional
This commit is contained in:
@@ -1,4 +1,3 @@
|
||||
import { findUp } from 'find-up';
|
||||
import prompts from 'prompts';
|
||||
import ora from 'ora';
|
||||
import { redBright, yellowBright } from 'colorette';
|
||||
@@ -6,18 +5,20 @@ import { execa } from 'execa';
|
||||
import {
|
||||
cmds_dir,
|
||||
default_prefix,
|
||||
intent,
|
||||
lang,
|
||||
main_dir,
|
||||
token,
|
||||
npmInit,
|
||||
gitInit,
|
||||
which_manager,
|
||||
name,
|
||||
} from '../prompts/init.js';
|
||||
import { npm } from '../utilities/npm.js';
|
||||
import { cloneRepo, installDeps } from '../utilities/install.js';
|
||||
import { editMain } from '../utilities/edits.js';
|
||||
const { prompt } = prompts;
|
||||
|
||||
// TODO make this functional and better!
|
||||
export async function init({ flags }) {
|
||||
if (flags?.includes('y')) {
|
||||
// TODO make this functional
|
||||
console.log("I see a flag there! Seems like you're lazy!\nBye!");
|
||||
process.exit(0);
|
||||
}
|
||||
@@ -32,75 +33,48 @@ export async function init({ flags }) {
|
||||
return process.exit(1);
|
||||
}
|
||||
|
||||
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?'
|
||||
/**
|
||||
* TODO edit main_dir and cmds_dir according to user input as well as default_prefix
|
||||
* will need help @Allyedge
|
||||
*/
|
||||
const data = await prompt([name, lang, main_dir, cmds_dir, default_prefix]);
|
||||
|
||||
await cloneRepo(data.lang, data.name);
|
||||
const git_init = await prompt([gitInit]);
|
||||
if (!git_init.gitinit) {
|
||||
console.log(`\nAlright\n`);
|
||||
} else {
|
||||
const spin = ora({
|
||||
text: 'Initializing git...',
|
||||
spinner: 'aesthetic',
|
||||
}).start();
|
||||
const exe = await execa('git', ['init', data.name]);
|
||||
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 {
|
||||
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!');
|
||||
}
|
||||
}
|
||||
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;
|
||||
}
|
||||
} else spin.succeed('Git initialized!');
|
||||
}
|
||||
await execa('cd', { cwd: `./${data.name}` });
|
||||
|
||||
const data = await prompt([
|
||||
lang,
|
||||
main_dir,
|
||||
cmds_dir,
|
||||
default_prefix,
|
||||
token,
|
||||
intent,
|
||||
]);
|
||||
console.log(data);
|
||||
const pm = await npm();
|
||||
let choice = '';
|
||||
if (pm === 'both') {
|
||||
const chosen = await prompt([which_manager]);
|
||||
choice = chosen.manager;
|
||||
} else choice = pm;
|
||||
await installDeps(choice, data.name);
|
||||
await editMain(data.name);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {number} ms
|
||||
* Wait for a specified number of milliseconds, then return a promise that resolves to undefined.
|
||||
* @param {number} ms - The number of milliseconds to wait.
|
||||
* @returns A function that takes a single argument, ms, and returns a promise that resolves after ms
|
||||
* milliseconds.
|
||||
*/
|
||||
async function wait(ms) {
|
||||
const wait = (await import('util')).promisify(setTimeout);
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import { blueBright } from 'colorette';
|
||||
|
||||
// TODO refactor the intents stuff and add more questions
|
||||
/**
|
||||
* @deprecated
|
||||
*/
|
||||
const Intents = [
|
||||
'DIRECT_MESSAGES',
|
||||
'DIRECT_MESSAGE_REACTIONS',
|
||||
@@ -29,14 +31,21 @@ export const lang = {
|
||||
{
|
||||
title: 'JavaScript',
|
||||
description: 'JS',
|
||||
value: 'javascript',
|
||||
},
|
||||
{
|
||||
title: 'TypeScript',
|
||||
description: 'TS',
|
||||
value: 'typescript',
|
||||
selected: true,
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
* ! Will be removed !
|
||||
*/
|
||||
export const intent = {
|
||||
message: 'What intents do you want to keep?',
|
||||
type: 'multiselect',
|
||||
@@ -56,16 +65,18 @@ export const default_prefix = {
|
||||
};
|
||||
|
||||
export const token = {
|
||||
message: 'What is your bot token?',
|
||||
message: 'What is your bot token? Type "no" to skip',
|
||||
name: 'token',
|
||||
type: 'password',
|
||||
|
||||
validate: (/** @type {string} */ token) =>
|
||||
token.match(
|
||||
validate: (/** @type {string} */ token) => {
|
||||
if (token === 'no') return true;
|
||||
return 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',
|
||||
: 'Invalid token';
|
||||
},
|
||||
};
|
||||
|
||||
export const main_dir = {
|
||||
@@ -84,13 +95,10 @@ export const cmds_dir = {
|
||||
dir === 'src' ? 'You can not use src as a directory' : true,
|
||||
};
|
||||
|
||||
/**
|
||||
* @type {import('prompts').PromptObject}
|
||||
*/
|
||||
export const npmInit = {
|
||||
name: 'npminit',
|
||||
export const projectInit = {
|
||||
name: 'projectinit',
|
||||
type: 'confirm',
|
||||
message: `Do you want to ${blueBright('me')} to initialize npm?`,
|
||||
message: `Do you want to ${blueBright('me')} to initialize project?`,
|
||||
initial: true,
|
||||
};
|
||||
|
||||
@@ -100,3 +108,31 @@ export const gitInit = {
|
||||
message: `Do you want to ${blueBright('me')} to initialize git?`,
|
||||
initial: true,
|
||||
};
|
||||
|
||||
export const which_manager = {
|
||||
message: `Which manager do you want to use?`,
|
||||
name: 'manager',
|
||||
type: 'select',
|
||||
choices: [
|
||||
{
|
||||
title: 'NPM',
|
||||
description: 'Default Package Manager',
|
||||
selected: true,
|
||||
value: 'npm',
|
||||
},
|
||||
{
|
||||
title: 'Yarn',
|
||||
description: 'Yarn Package Manager',
|
||||
value: 'yarn',
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
/**
|
||||
* @type {import('prompts').PromptObject}
|
||||
*/
|
||||
export const name = {
|
||||
message: 'What is your project name?',
|
||||
name: 'name',
|
||||
type: 'text',
|
||||
};
|
||||
|
||||
@@ -1,16 +1,22 @@
|
||||
//@ts-check
|
||||
import { readFile, writeFile } from 'node:fs/promises';
|
||||
import { findUp } from 'find-up';
|
||||
|
||||
|
||||
/**
|
||||
* @param {string} name
|
||||
* It takes a string, finds the package.json file in the directory of the string, and changes the name
|
||||
* of the package.json file to the string.
|
||||
* @param {string} name - The name of the project.
|
||||
* @returns A promise.
|
||||
*/
|
||||
export async function editMain(name) {
|
||||
const pjLocation = await findUp('package.json');
|
||||
const pjLocation = await findUp('package.json', {
|
||||
cwd: process.cwd() + '/' + name,
|
||||
});
|
||||
|
||||
const output = JSON.parse(await readFile(pjLocation, 'utf8'));
|
||||
if (!output) throw new Error("Can't read file.");
|
||||
|
||||
output.main = name;
|
||||
output.name = name;
|
||||
|
||||
const result = () => writeFile(pjLocation, JSON.stringify(output, null, 2));
|
||||
return result();
|
||||
78
src/utilities/install.js
Normal file
78
src/utilities/install.js
Normal file
@@ -0,0 +1,78 @@
|
||||
import { execa } from 'execa';
|
||||
import { redBright } from 'colorette';
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
import { readFile } from 'fs/promises';
|
||||
import { findUp } from 'find-up';
|
||||
import ora from 'ora';
|
||||
|
||||
/**
|
||||
* It installs dependencies from a package.json file
|
||||
* @param choice - The package manager to use.
|
||||
* @param name - The name of the project
|
||||
* @returns a promise.
|
||||
*/
|
||||
export async function installDeps(choice, name) {
|
||||
const pkg = await findUp('package.json', {
|
||||
cwd: process.cwd() + '/' + name,
|
||||
});
|
||||
if (!pkg) throw new Error('No package.json found!');
|
||||
const output = JSON.parse(await readFile(pkg, 'utf8'));
|
||||
if (!output) throw new Error("Can't read file.");
|
||||
const deps = output.dependencies;
|
||||
if (!deps) throw new Error("Can't find dependencies.");
|
||||
const spin = ora({
|
||||
text: `Installing dependencies...`,
|
||||
spinner: 'aesthetic',
|
||||
}).start();
|
||||
const result = await execa(choice, ['install'], {
|
||||
cwd: process.cwd() + '/' + name,
|
||||
}).catch(() => null);
|
||||
if (!result || result?.failed) {
|
||||
spin.fail(`${redBright('Failed')} to install dependencies!`);
|
||||
return process.exit(1);
|
||||
} else spin.succeed(`Dependencies installed!`);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clone the repo, copy the files from the repo to the new project directory, and delete the repo
|
||||
* @param {string} lang - The language of the template
|
||||
* @param {string} name - The name of the project
|
||||
*/
|
||||
export async function cloneRepo(lang, name) {
|
||||
await execa('git', [
|
||||
'clone',
|
||||
`https://github.com/sern-handler/templates.git`, // ? See the idea of @Allyedge having templates built in cli
|
||||
]);
|
||||
copyRecursiveSync(`templates/templates/${lang}`, name);
|
||||
fs.rmSync(`templates/`, { recursive: true, force: true });
|
||||
}
|
||||
|
||||
/**
|
||||
* If the source is a directory, create the destination directory and then recursively copy the
|
||||
* contents of the source directory to the destination directory. If the source is not a directory,
|
||||
* copy the source file to the destination file
|
||||
* @param {string} src - The source path.
|
||||
* @param {string} dest - The destination folder where the files will be copied to.
|
||||
*/
|
||||
function copyRecursiveSync(src, dest) {
|
||||
var exists = fs.existsSync(src);
|
||||
var stats = exists && fs.statSync(src);
|
||||
var isDirectory = exists && stats.isDirectory();
|
||||
if (isDirectory) {
|
||||
fs.mkdirSync(dest);
|
||||
fs.readdirSync(src).forEach(function (childItemName) {
|
||||
copyRecursiveSync(
|
||||
path.join(src, childItemName),
|
||||
path.join(dest, childItemName)
|
||||
);
|
||||
});
|
||||
} else {
|
||||
fs.copyFileSync(src, dest);
|
||||
}
|
||||
}
|
||||
|
||||
// async function wait(ms) {
|
||||
// const wait = (await import('util')).promisify(setTimeout);
|
||||
// return wait(ms);
|
||||
// }
|
||||
21
src/utilities/npm.js
Normal file
21
src/utilities/npm.js
Normal file
@@ -0,0 +1,21 @@
|
||||
import { execa } from 'execa';
|
||||
|
||||
/**
|
||||
* It checks if you have npm or yarn installed, and returns a string based on the result
|
||||
* @returns A promise that resolves to a string.
|
||||
*/
|
||||
export async function npm() {
|
||||
const npm = await execa('npm', ['-v']);
|
||||
const npm_version = npm?.stdout;
|
||||
const yarn = await execa('yarn', ['-v']);
|
||||
const yarn_version = yarn?.stdout;
|
||||
if (npm_version && !yarn_version) {
|
||||
return 'npm';
|
||||
}
|
||||
if (!npm_version && yarn_version) {
|
||||
return 'yarn';
|
||||
}
|
||||
if (npm_version && yarn_version) {
|
||||
return 'both';
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user