@saboosanket/code-generator
Version:
This npm package is a versatile setup tool tailored for Node.js projects, enabling users to generate customized project structures and functionalities. It supports integration with Google Cloud Platform (GCP), RabbitMQ, Redis, a Prisma query generator, an
149 lines (137 loc) • 5.17 kB
JavaScript
// createModuleAndFile.mjs
import fs from 'fs/promises'
import inquirer from 'inquirer'
import path from 'path'
import { createLogger, transports, format } from 'winston'
import { workingDirectory} from '../constants.js'
// Configure winston logger
const logger = createLogger({
level: 'info',
format: format.combine(
format.timestamp(),
format.printf(({ timestamp, level, message }) => `${timestamp} [${level}]: ${message}`)
),
transports: [
new transports.Console(),
new transports.File({ filename: 'app.log' })
]
})
/**
* Validate the types of inputs.
* @param {string} folderPath - The path to the folder.
* @param {string} filePath - The path to the file.
* @param {string} fileContent - The content to write to the file.
* @throws Will throw an error if inputs are not strings.
*/
function validateInputs(folderPath, filePath, fileContent) {
if (typeof folderPath !== 'string' || typeof filePath !== 'string' || typeof fileContent !== 'string') {
throw new Error('Invalid input types. Expected strings.')
}
}
/**
* Resolve relative paths to absolute paths.
* @param {string} folderPath - The folder path.
* @param {string} filePath - The file path.
* @returns {Object} - An object containing resolved folder and file paths.
*/
function resolvePaths(folderPath, filePath) {
return {
resolvedFolderPath: path.resolve(folderPath),
resolvedFilePath: path.resolve(filePath)
}
}
/**
* Create a directory if it doesn't exist.
* @param {string} folderPath - The path to the folder.
*/
async function createDirectory(folderPath) {
await fs.mkdir(folderPath, { recursive: true })
logger.info('Folder created successfully')
}
/**
* Prompts the user to decide whether to overwrite an existing file.
* If the user chooses to overwrite, the file is written with the specified content.
* If the user chooses not to overwrite, the operation is aborted.
*
* @param {string} filePath - The path to the file to be overwritten.
* @param {string} fileContent - The content to write to the file if the user chooses to overwrite.
* @throws {Error} Throws an error if there is an issue writing the file.
*/
async function overwritePrompt(filePath, fileContent) {
try {
const { overwrite } = await inquirer.prompt([
{
type: 'confirm',
name: 'overwrite',
message: 'File already exists. Do you want to overwrite it?',
default: false
}
])
if (overwrite) {
await fs.writeFile(filePath, fileContent)
logger.info('File overwritten successfully')
} else {
logger.info('File not overwritten. Operation aborted.')
}
} catch (err) {
logger.error('Error handling file overwrite prompt:', err.message)
throw err // Re-throw the error after logging
}
}
/**
* Write to a file and prompt for overwrite if the file already exists.
* @param {string} filePath - The path to the file.
* @param {string} fileContent - The content to write to the file.
*/
async function writeFileWithPrompt(filePath, fileContent) {
try {
await fs.writeFile(filePath, fileContent, { flag: 'wx' })
logger.info('File written successfully')
} catch (err) {
if (err.code === 'EEXIST') {
overwritePrompt(filePath, fileContent)
} else {
logger.error('Failed to write file:', err.message)
throw err
}
}
}
/**
* Write to a file if it doesn't exist.
* @param {string} folderName - The name of the folder where the file should be written.
* @param {string} fileName - The name of the file to write.
* @param {string} fileContent - The content to write to the file.
*/
async function writeFileWithoutPrompt(folderName, fileName, fileContent) {
try {
const folderPath = path.join(workingDirectory, folderName)
const filePath = path.join(folderPath, fileName)
const {resolvedFilePath } = resolvePaths(folderPath, filePath)
await fs.writeFile(resolvedFilePath, fileContent, { flag: 'wx' })
logger.info('File written successfully')
} catch (err) {
logger.warn(`File ${fileName} already exists.`)
}
}
/**
* Main function to create a module and file.
* @param {string} folderName - The name to the folder.
* @param {string} fileName - The name to the file.
* @param {string} fileContent - The content to write to the file.
*/
async function createModuleAndFile(folderName, fileName, fileContent) {
try {
const folderPath = path.join(workingDirectory, folderName)
const filePath = path.join(folderPath, fileName)
validateInputs(folderPath, filePath, fileContent)
const { resolvedFolderPath, resolvedFilePath } = resolvePaths(folderPath, filePath)
await createDirectory(resolvedFolderPath)
await writeFileWithPrompt(resolvedFilePath, fileContent)
} catch (err) {
logger.error('An error occurred:', err.message)
}
}
export {
createModuleAndFile,
writeFileWithoutPrompt
}