UNPKG

@mahdiarjangi/phetch-cli

Version:

A CLI directory manager that can be used to create directories, list directory contents and create files

305 lines (265 loc) • 9.18 kB
#! /usr/bin/env node import chalk from 'chalk'; const pj = require('./../package.json') const { Command } = require("commander"); const fs = require("fs"); const path = require("path"); const figlet = require("figlet"); const { exec } = require('child_process'); import { ExecException } from "child_process"; const program = new Command(); console.log(figlet.textSync("PHETCH-CLI")); const pluginPattern = { name: 'api', extension: 'ts', type: 'plugin', content: ` import { $fetch, type FetchOptions } from 'ofetch' interface IApiInstance { } export default defineNuxtPlugin((nuxtApp) => { const config = useRuntimeConfig() const fetchOptions: FetchOptions = { baseURL: 'BASE URL', } const apiFetcher = $fetch.create(fetchOptions) const modules: IApiInstance = { } return { provide: { api: modules } } }) ` } const factoryPattern = { name: 'factory', extension: 'ts', type: 'factory', content: ` import type { $Fetch, FetchOptions } from 'ofetch' class FetchFactory<T> { private $fetch: $Fetch constructor($fetcher: $Fetch) { this.$fetch = $fetcher } async call( method: string, url: string, data?: object, fetchOptions?: FetchOptions<'json'> ): Promise<T> { return this.$fetch<T>(url, { method, body: data, ...fetchOptions }) } } export default FetchFactory ` } const patterns = [ { name: 'Transform', extension: 'ts', type: 'transform', content: ` export function [name]Transform(data: [input]) { // transformed data } ` }, { name: 'Interface', extension: 'ts', type: 'interface', content: ` export interface [name]Interface { // interface props } ` }, { name: 'Api', extension: 'ts', type: 'api', content: ` export class [name]Module extends FetchFactory<[name]Interface[]> { private RESOURCE: string = '/[lower-name]s' async get[name]s( asyncDataOptions?: AsyncDataOptions<[name]Interface[]> ) { return useAsyncData( () => { const fetchOptions: FetchOptions<'json'> = { headers: { 'Accept-Language': 'en-US' }, } return this.call( 'GET', this.RESOURCE, undefined, fetchOptions ) }, asyncDataOptions ) } } ` } ] program .name('phetch-cli') .description('Phetch-CLI is a dependency to create `phetch` modules and API layer') .option("init", 'create initial `phetch` functionalities') .option("create-module <name> [argument]", 'create new module') .option("-l, --ls [value]", "list directory content") .version(pj.version) .action((options: any) => { if (options.ls) { const filePath = typeof options.ls === "string" ? options.ls : __dirname; listDirContents(filePath); } }) program .command('init') .description('create initial functionalities') .action(() => { console.log(`Installing ofetch`); exec(`npm install ofetch --save-dev`, (error: ExecException | null, stdout: string, stderr: string) => { if (error) { console.error(chalk.red(`Error during installation: ${error.message}`)); return; } if (stderr) { console.error(chalk.red(`stderr: ${stderr}`)); return; } console.log(chalk.green(`stdout: ${stdout}`)); console.log(chalk.blue.bold('ofetch installed successfully!')); createPlugin('./plugins', pluginPattern) createFactory('./src', factoryPattern) }); }) program .command('create-module') .description('create new module') .argument('<name>', 'the name of module you want to create') .option('--crud', 'crud', 'create CRUD module') .option('--empty', 'empty', 'create empty module') .option('--default', 'default', 'create default module') .action((name: string, options: any) => { if (options.crud) { // CRUD } if (options.empty) { // empty } if (options.default) { const fullPath = path.resolve(path.join(__dirname, `/./plugins`), pluginPattern.name + '.' + pluginPattern.extension) const importContent = `import ${capitalize(name)}Module from '~/repository/modules/${name}' \n`; const fetcherContent = `\n \t\t${name}: new ${capitalize(name)}Module(apiFetcher)`; const interfaceContent = `\n \t${name}: ${capitalize(name)}Module`; insertTextBeforeString(fullPath, 'interface IApiInstance {', importContent) insertTextBetweenString(fullPath, 'interface IApiInstance {', interfaceContent) insertTextBetweenString(fullPath, 'const modules: IApiInstance = {', fetcherContent) console.log(chalk.redBright.bold('plugin added!')); } }) program.parse(process.argv) async function listDirContents(filePath: string) { try { const files = await fs.promises.readdir(filePath); const detailedFilePromises = files.map(async (file: string) => { const fileDetails = await fs.promises.lstat(path.resolve(filePath, file)); const { size, birthtime } = fileDetails; return { filename: file, "size(KB)": size, createdAt: birthtime, }; }); const detailedFiles = await Promise.all(detailedFilePromises); console.table(detailedFiles); } catch (error) { console.error(chalk.red("Error occurred while reading the directory!", error)); } } function capitalize(s: string) { return String(s[0]).toUpperCase() + String(s).slice(1); } function writeFile(filePath: string, content: string, parameter?: string) { const c = content.replace('[p]', parameter as string) fs.writeFile(filePath, c, function(err: string) { if (err) { return console.error(chalk.red(err)); } console.log("File created!"); }) } function createDir(dir: string) { if (!fs.existsSync(dir)) { fs.mkdirSync(dir); console.log("The directory has been created successfully"); } } function createFile(filePath: string) { const dir = path.dirname(filePath); if (!fs.existsSync(dir)) { fs.mkdirSync(dir, { recursive: true }); } fs.openSync(filePath, "w"); console.log("An empty file has been created at:", filePath); } function createFactory(p: string, pattern: any) { createDir(p) const fullPath = path.resolve(path.join(__dirname, `/${p}`), pattern.name + '.' + pattern.extension) createFile(fullPath) writeFile(fullPath, pattern.content) } function createPlugin(p: string, pattern: any) { createDir(p) const fullPath = path.resolve(path.join(__dirname, `/${p}`), pattern.name + '.' + pattern.extension) createFile(fullPath) writeFile(fullPath, pattern.content) } function insertTextBeforeString(filePath: string, searchString: string, insertText: string): string { try { const fileContent = fs.readFileSync(filePath, 'utf-8'); const startIndex = fileContent.indexOf(searchString); if (startIndex === -1) { return `The string "${searchString}" was not found in the file.`; } // Insert the new text before the search string const updatedContent = fileContent.slice(0, startIndex) + insertText + fileContent.slice(startIndex); fs.writeFileSync(filePath, updatedContent, 'utf-8'); return `The text "${insertText}" was successfully inserted before "${searchString}" in the file.`; } catch (error) { return `An error occurred while processing the file: ${error}`; } } function insertTextBetweenString(filePath: string, searchString: string, insertText: string): string { try { const fileContent = fs.readFileSync(filePath, 'utf-8'); const startIndex = fileContent.indexOf(searchString); const endIndex = startIndex + searchString.length; if (startIndex === -1) { return `The string "${searchString}" was not found in the file.`; } const updatedContent = fileContent.slice(0, startIndex + searchString.length) + insertText + fileContent.slice(endIndex); fs.writeFileSync(filePath, updatedContent, 'utf-8'); return `The text "${insertText}" was successfully inserted after "${searchString}" in the file.`; } catch (error) { return `An error occurred while processing the file: ${error}`; } }