nhb-scripts
Version:
A collection of Node.js scripts to use in TypeScript & JavaScript projects
68 lines (53 loc) • 1.95 kB
JavaScript
// @ts-check
import { outro } from '@clack/prompts';
import chalk from 'chalk';
import fs from 'fs/promises';
import { isNotEmptyObject, isValidArray } from 'nhb-toolbox';
import path from 'path';
import { showCancelMessage } from './clack-utils.mjs';
/** @import { FileEntry, ModuleConfig } from '../types/index.d.ts'; */
/**
* Generate a module with given name and config.
* @param {string} moduleName
* @param {ModuleConfig} config
*/
export async function generateModule(moduleName, config) {
/** @type {Array<FileEntry>} */
let files = [];
let createFolder = config?.createFolder;
let destination = config.destination || 'src/modules';
const template = config.defaultTemplate;
if (!template) {
showCancelMessage('No template specified!');
return;
}
if (isNotEmptyObject(config.templates) && config.templates?.[template]) {
const tpl = config.templates[template];
files = typeof tpl.files === 'function' ? tpl.files(moduleName) : tpl.files;
destination = config.destination || tpl.destination || 'src/modules';
createFolder = tpl.createFolder !== false;
}
if (!isValidArray(files)) {
showCancelMessage(`No files defined for template "${template}"!`);
}
const moduleDir =
createFolder ? path.resolve(destination, moduleName) : path.resolve(destination);
try {
await fs.access(moduleDir);
} catch {
await fs.mkdir(moduleDir, { recursive: true });
}
// Write all files
await Promise.all(
files.map(async ({ name, content }) => {
const normalizedName = path.normalize(name);
if (normalizedName.startsWith('..') || path.isAbsolute(normalizedName)) {
throw new Error(`Unsafe file path: ${normalizedName}`);
}
const fullPath = path.join(moduleDir, normalizedName);
await fs.mkdir(path.dirname(fullPath), { recursive: true });
await fs.writeFile(fullPath, content);
})
);
outro(chalk.green(`🎉 Module "${moduleName}" generated successfully in ${destination}`));
}