From 565092c718c8e4532fffecc3784a50b6c67eb222 Mon Sep 17 00:00:00 2001 From: Abhinav R <76396917+Abhinav-ark@users.noreply.github.com> Date: Wed, 18 Sep 2024 11:30:37 +0530 Subject: [PATCH 1/5] Initial setup, basic template, init and clear commands. --- .gitignore | 3 + bin/configs.js | 7 ++ bin/index.js | 134 ++++++++++++++++++++++++++++++++++++++ package-lock.json | 109 +++++++++++++++++++++++++++++++ package.json | 21 ++++++ templates/basic/server.js | 11 ++++ 6 files changed, 285 insertions(+) create mode 100644 .gitignore create mode 100644 bin/configs.js create mode 100644 bin/index.js create mode 100644 package-lock.json create mode 100644 package.json create mode 100644 templates/basic/server.js diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..28f2292 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +# Node Modules + +/node_modules/ \ No newline at end of file diff --git a/bin/configs.js b/bin/configs.js new file mode 100644 index 0000000..8706727 --- /dev/null +++ b/bin/configs.js @@ -0,0 +1,7 @@ +export const templates = { + basic: { + name:"basic", + dependencies:[{name:"express",version:"^4.17.1"}] + } +}; + diff --git a/bin/index.js b/bin/index.js new file mode 100644 index 0000000..136e1e7 --- /dev/null +++ b/bin/index.js @@ -0,0 +1,134 @@ +#!/usr/bin/env node + +import { program } from 'commander'; +import fs from 'fs-extra'; +import path from 'path'; +import { fileURLToPath } from 'url'; +import { execSync } from 'child_process'; +import figlet from 'figlet'; +import chalk from 'chalk'; +import { createSpinner } from 'nanospinner'; +import { templates } from './configs.js'; + +const __filename = fileURLToPath(import.meta.url); +const __dirname = path.dirname(__filename); + +const template = templates.basic; + +program + .version('v1.0.0','-v, --version') + .description('A simple Express server generator'); + +program + .command('init') + .description('Initialize a new Express server') + .action(() => { + + toolIntro(); + + console.log('Starting server initialization...'); + + const targetDir = process.cwd(); + const parentDir = path.dirname(__dirname) + const templatePath = path.join(parentDir, 'templates',template.name); + const destinationPath = path.join(targetDir); + + const initSpinner = createSpinner('Running npm init...').start() + try { + // execSync('npm init -y', { stdio: 'inherit', cwd: targetDir }); + execSync('npm init -y', { stdio: 'ignore', cwd: targetDir }); + initSpinner.success({ text: 'npm init completed successfully.' }); + } catch (error) { + initSpinner.error({ text: `Error running npm init:\n` }); + console.error(error.message); + return; + } + + //console.log(`Copying server template from ${templatePath} to ${destinationPath}`); + + const copySpinner = createSpinner('Creating server files...').start(); + try { + fs.copySync(templatePath, destinationPath); + copySpinner.success({text:"Created server files successfully."}); + } catch (error) { + copySpinner.error({text:"Error creating server files.\n"}) + console.error(error.message); + } + + + const addDependencies = createSpinner("Adding dependency packages...").start(); + try { + // Update package.json to add express as a dependency + const packageJsonPath = path.join(targetDir, 'package.json'); + const packageJsonContent = fs.readFileSync(packageJsonPath, 'utf8'); + const packageJson = JSON.parse(packageJsonContent); + packageJson.dependencies = packageJson.dependencies || {}; + // packageJson.dependencies.express = "^4.17.1"; + template.dependencies.forEach((dependency)=>{ + packageJson.dependencies[`${dependency.name}`] = dependency.version; + }); + fs.writeFileSync(packageJsonPath, JSON.stringify(packageJson, null, 2)); + + addDependencies.success({text:'Added dependency packages successfully.'}); + } catch(error) { + addDependencies.error("Error adding dependency packages.\n"); + console.error(error.message); + } + + + const installDependencies = createSpinner("Installing dependency packages...").start(); + try { + //execSync('npm i', { stdio: 'inherit', cwd: targetDir }); + execSync('npm i', { stdio: 'ignore', cwd: targetDir }); + + installDependencies.success({text:'Installed dependencies successfully.'}); + + console.log(chalk.green.bold('\nSetup complete! To run your server:')); + console.log(chalk.yellow('Run:'), chalk.white.bold('npm start')); + } catch (error) { + installDependencies.error({text:'Error installing dependencies.\n'}) + console.error(error); + } + }); + +program + .command('clear') + .description('Clear the directory') + .action(()=>{ + const targetDir = process.cwd(); + console.log('Clearing Directory...',chalk.bgRed.white(targetDir)); + const clearingDirectory = createSpinner('Deleting All Files').start(); + try { + // Read the directory + const files = fs.readdirSync(targetDir); + + // Remove each file/directory except . and .. + for (const file of files) { + const filePath = path.join(targetDir, file); + // if (file !== '.' && file !== '..') { + fs.removeSync(filePath); + // } + } + + clearingDirectory.success({text:'Successfully cleared project directory'}); + } catch (error) { + clearingDirectory.error({text:'Error clearing project directory'}); + console.error(error); + } + }); + +const toolIntro = () => { + console.log( + figlet.textSync("Quick Start Express", { + font: "Standard", + horizontalLayout: "default", + verticalLayout: "default", + width: 90, + whitespaceBreak: true, + }) + ); + + console.log(chalk.green.bold('A simple Express server generator CLI tool')); +}; + +program.parse(process.argv); \ No newline at end of file diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..069353b --- /dev/null +++ b/package-lock.json @@ -0,0 +1,109 @@ +{ + "name": "qse", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "qse", + "version": "1.0.0", + "license": "ISC", + "dependencies": { + "chalk": "^5.3.0", + "commander": "^12.1.0", + "figlet": "^1.7.0", + "fs-extra": "^11.2.0", + "nanospinner": "^1.1.0" + } + }, + "node_modules/chalk": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz", + "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==", + "license": "MIT", + "engines": { + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/commander": { + "version": "12.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-12.1.0.tgz", + "integrity": "sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==", + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/figlet": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/figlet/-/figlet-1.7.0.tgz", + "integrity": "sha512-gO8l3wvqo0V7wEFLXPbkX83b7MVjRrk1oRLfYlZXol8nEpb/ON9pcKLI4qpBv5YtOTfrINtqb7b40iYY2FTWFg==", + "license": "MIT", + "bin": { + "figlet": "bin/index.js" + }, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/fs-extra": { + "version": "11.2.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.2.0.tgz", + "integrity": "sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==", + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=14.14" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "license": "ISC" + }, + "node_modules/jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "license": "MIT", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/nanospinner": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/nanospinner/-/nanospinner-1.1.0.tgz", + "integrity": "sha512-yFvNYMig4AthKYfHFl1sLj7B2nkHL4lzdig4osvl9/LdGbXwrdFRoqBS98gsEsOakr0yH+r5NZ/1Y9gdVB8trA==", + "license": "ISC", + "dependencies": { + "picocolors": "^1.0.0" + } + }, + "node_modules/picocolors": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.0.tgz", + "integrity": "sha512-TQ92mBOW0l3LeMeyLV6mzy/kWr8lkd/hp3mTg7wYK7zJhuBStmGMBG0BdeDZS/dZx1IukaX6Bk11zcln25o1Aw==", + "license": "ISC" + }, + "node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "license": "MIT", + "engines": { + "node": ">= 10.0.0" + } + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..ac6c697 --- /dev/null +++ b/package.json @@ -0,0 +1,21 @@ +{ + "name": "qse", + "version": "1.0.0", + "description": "A cli tool to quickstart express apps", + "type": "module", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1", + "dev": "node bin/index.js init" + }, + "author": "Abhinav Ramakrishnan, Ashwin Narayanan S", + "license": "ISC", + "bin":"./bin/index.js", + "dependencies": { + "chalk": "^5.3.0", + "commander": "^12.1.0", + "figlet": "^1.7.0", + "fs-extra": "^11.2.0", + "nanospinner": "^1.1.0" + } +} diff --git a/templates/basic/server.js b/templates/basic/server.js new file mode 100644 index 0000000..2bec675 --- /dev/null +++ b/templates/basic/server.js @@ -0,0 +1,11 @@ +const express = require('express') +const app = express() +const port = 3000 + +app.get('/', (req, res) => { + res.send('Hello World!') +}) + +app.listen(port, () => { + console.log(`Example app listening on port ${port}`) +}) \ No newline at end of file From 7a275294a4b2a6d15d8063292e25422ad52beaed Mon Sep 17 00:00:00 2001 From: Abhinav R <76396917+Abhinav-ark@users.noreply.github.com> Date: Thu, 19 Sep 2024 15:56:28 +0530 Subject: [PATCH 2/5] Resolve suggested changes in basic template. --- templates/basic/server.js | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/templates/basic/server.js b/templates/basic/server.js index 2bec675..94cd768 100644 --- a/templates/basic/server.js +++ b/templates/basic/server.js @@ -1,11 +1,11 @@ -const express = require('express') -const app = express() -const port = 3000 +const express = require("express"); +const app = express(); +const port = 3000; -app.get('/', (req, res) => { - res.send('Hello World!') -}) +app.get("/", (req, res) => { + return res.send("Hello World!"); +}); app.listen(port, () => { - console.log(`Example app listening on port ${port}`) -}) \ No newline at end of file + console.log(`Example app listening on port ${port}.`); +}); From 2b951801c86244d5722dfc4c5de223b4475c2c14 Mon Sep 17 00:00:00 2001 From: Abhinav R <76396917+Abhinav-ark@users.noreply.github.com> Date: Thu, 19 Sep 2024 20:33:06 +0530 Subject: [PATCH 3/5] Resolved Suggested changes --- bin/configs.js | 36 +++++++++++-- bin/index.js | 137 ++++++++++++++++++++++++++----------------------- package.json | 3 +- 3 files changed, 104 insertions(+), 72 deletions(-) diff --git a/bin/configs.js b/bin/configs.js index 8706727..b0f06c3 100644 --- a/bin/configs.js +++ b/bin/configs.js @@ -1,7 +1,33 @@ -export const templates = { - basic: { - name:"basic", - dependencies:[{name:"express",version:"^4.17.1"}] - } +export const metadata = { + name: "Quick Start Express", + version: "v1.0.0", + description: + "A simple CLI tool to generate Express servers from multiple available templates.", + oneLineDescription: "A simple Express.js server generator CLI tool.", +}; + +export const commands = { + version: { + versionFlags: "-v, --version", + }, + init: { + command: "init", + description: "Initialize a new Express server.", + }, + clear: { + command: "clear", + description: "Clear the directory.", + }, }; +export const templates = { + basic: { + name: "basic", + dependencies: [ + { + name: "express", + version: "^4.17.1", + }, + ], + }, +}; diff --git a/bin/index.js b/bin/index.js index 136e1e7..bec539d 100644 --- a/bin/index.js +++ b/bin/index.js @@ -1,14 +1,14 @@ #!/usr/bin/env node -import { program } from 'commander'; -import fs from 'fs-extra'; -import path from 'path'; -import { fileURLToPath } from 'url'; -import { execSync } from 'child_process'; -import figlet from 'figlet'; -import chalk from 'chalk'; -import { createSpinner } from 'nanospinner'; -import { templates } from './configs.js'; +import { program } from "commander"; +import fs from "fs-extra"; +import path from "path"; +import { fileURLToPath } from "url"; +import { execSync } from "child_process"; +import figlet from "figlet"; +import chalk from "chalk"; +import { createSpinner } from "nanospinner"; +import { metadata, commands, templates } from "./configs.js"; const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); @@ -16,110 +16,117 @@ const __dirname = path.dirname(__filename); const template = templates.basic; program - .version('v1.0.0','-v, --version') - .description('A simple Express server generator'); + .version(metadata.version, commands.version.versionFlags) + .description(metadata.description); program - .command('init') - .description('Initialize a new Express server') + .command(commands.init.command) + .description(commands.init.description) .action(() => { - toolIntro(); - console.log('Starting server initialization...'); - + console.log("Starting server initialization..."); + const targetDir = process.cwd(); - const parentDir = path.dirname(__dirname) - const templatePath = path.join(parentDir, 'templates',template.name); + const parentDir = path.dirname(__dirname); + const templatePath = path.join(parentDir, "templates", template.name); const destinationPath = path.join(targetDir); + const npmInit = chalk.bgWhite.black("npm init"); - const initSpinner = createSpinner('Running npm init...').start() + const initSpinner = createSpinner(`Running ${npmInit}...`).start(); try { // execSync('npm init -y', { stdio: 'inherit', cwd: targetDir }); - execSync('npm init -y', { stdio: 'ignore', cwd: targetDir }); - initSpinner.success({ text: 'npm init completed successfully.' }); - } catch (error) { - initSpinner.error({ text: `Error running npm init:\n` }); - console.error(error.message); + execSync("npm init -y", { stdio: "ignore", cwd: targetDir }); + initSpinner.success({ text: `${npmInit} completed successfully.` }); + } catch (err) { + initSpinner.error({ text: `Error running ${npmInit}:\n` }); + console.error(err.message); return; } //console.log(`Copying server template from ${templatePath} to ${destinationPath}`); - const copySpinner = createSpinner('Creating server files...').start(); + const copySpinner = createSpinner("Creating server files...").start(); try { fs.copySync(templatePath, destinationPath); - copySpinner.success({text:"Created server files successfully."}); - } catch (error) { - copySpinner.error({text:"Error creating server files.\n"}) - console.error(error.message); + copySpinner.success({ text: "Created server files successfully." }); + } catch (err) { + copySpinner.error({ text: "Error creating server files.\n" }); + console.error(err.message); } - - const addDependencies = createSpinner("Adding dependency packages...").start(); + const addDependencies = createSpinner( + "Adding dependency packages..." + ).start(); try { - // Update package.json to add express as a dependency - const packageJsonPath = path.join(targetDir, 'package.json'); - const packageJsonContent = fs.readFileSync(packageJsonPath, 'utf8'); + // Update package.json to add express as a dependency. + const packageJsonPath = path.join(targetDir, "package.json"); + const packageJsonContent = fs.readFileSync(packageJsonPath, "utf8"); const packageJson = JSON.parse(packageJsonContent); packageJson.dependencies = packageJson.dependencies || {}; // packageJson.dependencies.express = "^4.17.1"; - template.dependencies.forEach((dependency)=>{ + template.dependencies.forEach((dependency) => { packageJson.dependencies[`${dependency.name}`] = dependency.version; }); fs.writeFileSync(packageJsonPath, JSON.stringify(packageJson, null, 2)); - addDependencies.success({text:'Added dependency packages successfully.'}); - } catch(error) { + addDependencies.success({ + text: "Added dependency packages successfully.", + }); + } catch (err) { addDependencies.error("Error adding dependency packages.\n"); - console.error(error.message); + console.error(err.message); } - - - const installDependencies = createSpinner("Installing dependency packages...").start(); + + const installDependencies = createSpinner( + "Installing dependency packages..." + ).start(); try { //execSync('npm i', { stdio: 'inherit', cwd: targetDir }); - execSync('npm i', { stdio: 'ignore', cwd: targetDir }); - - installDependencies.success({text:'Installed dependencies successfully.'}); + execSync("npm i", { stdio: "ignore", cwd: targetDir }); - console.log(chalk.green.bold('\nSetup complete! To run your server:')); - console.log(chalk.yellow('Run:'), chalk.white.bold('npm start')); - } catch (error) { - installDependencies.error({text:'Error installing dependencies.\n'}) - console.error(error); + installDependencies.success({ + text: "Installed dependencies successfully.", + }); + + console.log(chalk.green.bold("\nSetup complete! To run your server:")); + console.log(chalk.yellow("Run:"), chalk.white.bold("npm start")); + } catch (err) { + installDependencies.error({ text: "Error installing dependencies.\n" }); + console.error(err); } }); program - .command('clear') - .description('Clear the directory') - .action(()=>{ + .command(commands.clear.command) + .description(commands.clear.description) + .action(() => { const targetDir = process.cwd(); - console.log('Clearing Directory...',chalk.bgRed.white(targetDir)); - const clearingDirectory = createSpinner('Deleting All Files').start(); + console.log("Clearing Directory...", chalk.bgRed.white(targetDir)); + const clearingDirectory = createSpinner("Deleting All Files...").start(); try { - // Read the directory + // Read the directory. const files = fs.readdirSync(targetDir); - - // Remove each file/directory except . and .. + for (const file of files) { const filePath = path.join(targetDir, file); // if (file !== '.' && file !== '..') { - fs.removeSync(filePath); + fs.removeSync(filePath); // } } - - clearingDirectory.success({text:'Successfully cleared project directory'}); + + clearingDirectory.success({ + text: "Successfully cleared project directory.", + }); } catch (error) { - clearingDirectory.error({text:'Error clearing project directory'}); + clearingDirectory.error({ text: "Error clearing project directory" }); console.error(error); } }); const toolIntro = () => { console.log( - figlet.textSync("Quick Start Express", { + figlet.textSync(metadata.name, { font: "Standard", horizontalLayout: "default", verticalLayout: "default", @@ -127,8 +134,8 @@ const toolIntro = () => { whitespaceBreak: true, }) ); - - console.log(chalk.green.bold('A simple Express server generator CLI tool')); + + console.log(chalk.green.bold(metadata.oneLineDescription)); }; -program.parse(process.argv); \ No newline at end of file +program.parse(process.argv); diff --git a/package.json b/package.json index ac6c697..09a809b 100644 --- a/package.json +++ b/package.json @@ -1,11 +1,10 @@ { "name": "qse", "version": "1.0.0", - "description": "A cli tool to quickstart express apps", + "description": "A simple CLI tool to generate Express servers from multiple available templates", "type": "module", "main": "index.js", "scripts": { - "test": "echo \"Error: no test specified\" && exit 1", "dev": "node bin/index.js init" }, "author": "Abhinav Ramakrishnan, Ashwin Narayanan S", From db182ddbfd4b44f025f5f97e9994085818495d9a Mon Sep 17 00:00:00 2001 From: Abhinav R <76396917+Abhinav-ark@users.noreply.github.com> Date: Thu, 19 Sep 2024 20:45:51 +0530 Subject: [PATCH 4/5] chalk added for "npm init" command status indicator. --- bin/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/index.js b/bin/index.js index bec539d..7f6a1b1 100644 --- a/bin/index.js +++ b/bin/index.js @@ -31,7 +31,7 @@ program const parentDir = path.dirname(__dirname); const templatePath = path.join(parentDir, "templates", template.name); const destinationPath = path.join(targetDir); - const npmInit = chalk.bgWhite.black("npm init"); + const npmInit = chalk.yellow.bold("npm init"); const initSpinner = createSpinner(`Running ${npmInit}...`).start(); try { From f242313f42f75d3658dac4d1373b1dc46a4cc5da Mon Sep 17 00:00:00 2001 From: Ashrockzzz2003 Date: Thu, 19 Sep 2024 21:00:14 +0530 Subject: [PATCH 5/5] Add full stop to description in --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 09a809b..ba30861 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "qse", "version": "1.0.0", - "description": "A simple CLI tool to generate Express servers from multiple available templates", + "description": "A simple CLI tool to generate Express servers from multiple available templates.", "type": "module", "main": "index.js", "scripts": {