UNPKG

node-initdb

Version:

A CLI tool to create a folder and file with some code

186 lines (172 loc) 8.2 kB
const fs = require('fs'); // File system module for file operations const readline = require('readline'); // Module for reading line input from the console const path = require('path'); // Module for handling file paths const { exec } = require('child_process'); const mkdirp = require('mkdirp'); // Variables to hold folder and file structures and commands let folders; let files; let cmd; // Get the current directory name const currentDirectoryName = path.basename(process.cwd()); // Stores the name of the current working directory // Regular expressions for validation const semverRegex = /^(\d+\.)?(\d+\.)?(\*|\d+)$/; // Regex to validate semantic versioning const gitRepoRegex = /^(https?:\/\/|git@)([^:/]+)[:/]([^:/]+)\/([^:/]+)(\.git)?$/; // Regex to validate Git repository URLs const jsFileRegex = /^[a-zA-Z0-9-_]+\.js$/; // Regex to validate JavaScript file names const licenses = ['MIT', 'ISC', 'Apache-2.0', 'GPL-3.0']; // List of valid licenses const questions = [ // Array of questions for user input `Package name: (${currentDirectoryName}) `, "Version: (1.0.0) ", "Description: ", "Entry point: (index.js/index.ts) ", "Test command: ", "Git repository: ", "Keywords: ", "Author: ", `License: (ISC) [${licenses.join(', ')}] ` ]; const defaultValues = [ // Default values for each question if no input is provided currentDirectoryName, "1.0.0", "", "index.js", "echo \"Error: no test specified\" && exit 1", "", "", "", "ISC", "index.ts", ]; const answers = []; // Array to store user responses const validateAnswer = (index, answer) => { // Function to validate user input based on question index switch (index) { case 1: if (answer && !semverRegex.test(answer)) { console.log("Invalid version format. Please use semantic versioning (e.g., 1.0.0)."); return false; } break; case 3: if (answer && !jsFileRegex.test(answer)) { console.log("Invalid entry point. The file name must end with .js and contain only alphanumeric characters, dashes, or underscores."); return false; } break; case 5: if (answer && !gitRepoRegex.test(answer)) { console.log("Invalid Git repository URL."); return false; } break; case 8: if (answer && !licenses.includes(answer)) { console.log(`Invalid license. Choose one from: ${licenses.join(', ')}.`); return false; } break; } return true; }; const askQuestion = (index, options, rl) => { // Recursive function to ask each question to the user if (index >= questions.length) { // Check if all questions have been asked let rootFilename = options.javascript ? defaultValues[3] : defaultValues[9] const packageJson = { // Object to store the package.json data name: answers[0] || defaultValues[0], version: answers[1] || defaultValues[1], description: answers[2] || defaultValues[2], main: answers[3] || rootFilename, scripts: { start: options.bun ? `bun run --watch ${answers[3] || rootFilename}` : `node ${answers[3] || rootFilename} ` , dev: options.bun ? `bun run --watch ${answers[3] || rootFilename}` : `nodemon ${answers[3] || rootFilename} `, test: answers[4] || defaultValues[4] }, repository: answers[5] ? { type: "git", url: answers[5] } : undefined, keywords: answers[6] ? answers[6].split(',').map(keyword => keyword.trim()) : [], author: answers[7] || defaultValues[7], license: answers[8] || defaultValues[8] }; fs.writeFileSync('package.json', JSON.stringify(packageJson, null, 2)); // Write the package.json file console.log("package.json file has been generated"); rl.close(); let Mongo; let Seque; // Determine which database setup to initialize based on user input if(options.fastify){ if(options.javascript){ Mongo = require('./structures/JS/fastify/mongo-fastify'); // MongoDB structure configuration Seque = require('./structures/JS/fastify/sequelize-fastify'); // Sequelize structure configuration }else{ Mongo = require('./structures/TS/fastify/mongo-fastify'); // MongoDB structure configuration Seque = require('./structures/TS/fastify/sequelize-fastify'); // Sequelize structure configuration } } else if(options.elysia){ if(options.javascript){ Mongo = require('./structures/JS/elysia/mongo-elysia'); // MongoDB structure configuration Seque = require('./structures/JS/elysia/sequelize-elysia'); // Sequelize structure configuration }else{ Mongo = require('./structures/TS/elysia/mongo-elysia'); // MongoDB structure configuration Seque = require('./structures/TS/elysia/sequelize-elysia'); // Sequelize structure configuration } } else { if(options.javascript){ Mongo = require('./structures/JS/express/mongo-express'); // MongoDB structure configuration Seque = require('./structures/JS/express/sequelize-express'); // Sequelize structure configuration } else{ Mongo = require('./structures/TS/express/mongo-express'); // MongoDB structure configuration Seque = require('./structures/TS/express/sequelize-express'); // Sequelize structure configuration } } if(options.seque){ folders = Seque.folders; // Folders from Sequelize configuration files = Seque.files(answers[3] ||rootFilename,answers[0] || defaultValues[0]); // Files from Sequelize configuration cmd = Seque.cmd; // Command to execute from Sequelize configuration } else if(options.mongo) { folders = Mongo.folders; // Folders from MongoDB configuration files = Mongo.files(answers[3] || rootFilename,answers[0] || defaultValues[0]); // Files from MongoDB configuration cmd = Mongo.cmd; // Command to execute from MongoDB configuration } else { console.log('Please choose one of the following options: --mongo or --seque'); process.exit(1); // Exit if no valid option is provided } const rootPath = path.join(process.cwd()); // Root path of the project // Create directories as specified in folders array folders.forEach(folder => { mkdirp.sync(path.join(rootPath, folder)); // Create directory synchronously console.log(`Folder "${folder}" created successfully.`); }); // Create files as specified in files array files.forEach(file => { const filePath = file.folder ? path.join(rootPath, file.folder, file.name) : path.join(rootPath, file.name); fs.writeFileSync(filePath, file.content); // Write file synchronously console.log(`File "${file.name}" created successfully.`); }); // Execute command to install required packages console.log('Installing required packages...'); exec(`${options.npm ? "npm install "+ cmd: options.yarn ? "yarn add " + cmd : options.pnpm ? "pnpm add " + cmd : "bun add "+ cmd}`, (error, stdout, stderr) => { if (error) { console.error(`Error installing packages: ${error.message}`); process.exit(1); } if (stderr) { console.error(`stderr: ${stderr}`); process.exit(1); } console.log(`Packages installed successfully: ${stdout}`); process.exit(0); // Force process exit after installation completes }); // Close the readline interface return; } rl.question(questions[index], (answer) => { // Ask the next question answer = answer.trim(); // Trim whitespace from the input if (validateAnswer(index, answer)) { // Validate the input answers.push(answer); // Store valid input askQuestion(index + 1, options, rl); // Ask the next question } else { askQuestion(index, options, rl); // Re-ask the same question if validation fails } }); }; module.exports = askQuestion // Export the askQuestion function