🏗️
A flexible Node.js project scaffolding tool with support for templating, dry-run previews, conditional generation, backups, and more. 🚀
📦 Installation
1npm install hbh-psm
✨ Features
- 🗂 Flexible Project Generation: Define folder/file structures in an easy, visual tree format.
- 🔧 Templating: Replace variables in files dynamically using
{{variable}}. - 👀 Dry-run Mode: Preview the generated project without writing files.
- 🛡 File Backup: Automatically backup existing files before overriding.
- ⚡ Conditional Generation: Generate certain files/folders only if conditions are met.
- 📝 Callbacks: Hook into file/folder creation events.
- 📄 Append Mode: Add content to existing files instead of overwriting.
- 🌟 Verbose Logging: Monitor the generation process step by step.
🛠️ Usage
Import the package
1import { Maker, Parser } from 'hbh-psm';
Maker→ Project generator class.Parser→ Text-based tree parser.
1️⃣ Define a Project Structure
You can define a structure using nested objects or parse from a text-based visual tree:
1const structure = {2 "src": {3 "index.js.template": "console.log('Hello {{name}}!');",4 "utils.js": "// utility functions"5 },6 "README.md": "# {{projectName}}"7};
Or parse from text:
1const textTree = `2src/3├── index.js.template console.log('Hello {{name}}!');4├── utils.js5README.md # Project README6`;8const structure = Parser(textTree, true, { separator: null, metadata: true });
2️⃣ Generate the Project
1const generator = new Maker('./my-project', structure, {2 variables: { name: 'World', projectName: 'AwesomeProject' },3 dryRun: false, // true for preview only4 override: true, // overwrite existing files5 addBackup: true, // create backups if file exists6 verbose: true7});9generator.generate()10 .then(() => console.log('✅ Project created!'))11 .catch(err => console.error('❌ Error:', err));
3️⃣ Dry-Run Preview
1const generator = new Maker('./my-project', structure, { dryRun: true });2const preview = await generator.generate();4console.log(preview);5/*6[7 { type: 'folder', path: './my-project/src' },8 { type: 'file', path: './my-project/src/index.js', content: "console.log('Hello World!');" },9 { type: 'file', path: './my-project/README.md', content: '# AwesomeProject' }10]11*/
4️⃣ Conditional Generation
You can skip certain files or folders dynamically:
1const generator = new Maker('./my-project', structure, {2 conditions: { "utils.js": false } // will not generate utils.js3});
5️⃣ Callbacks on Creation
1const generator = new Maker('./my-project', structure, {2 onCreate: ({ type, path }) => console.log(`Created ${type}: ${path}`)3});
6️⃣ Ignore Patterns
Skip files/folders by name or regex:
1const generator = new Maker('./my-project', structure, {2 ignore: ['README.md', /\.log$/]3});
7️⃣ File Append Mode
Append content to existing files instead of overwriting:
1const generator = new Maker('./my-project', structure, {2 append: true3});
⚡ Quick Example
1import { Maker, Parser } from 'hbh-psm';3(async () => {4 // 1️⃣ Define project structure using text tree5 const textTree = `6src/7├── index.js.template console.log('Hello {{name}}!');8├── utils.js // Utility functions9README.md # {{projectName}} Project10.env NODE_ENV=development11`;13 // 2️⃣ Parse the text tree into an object structure14 const structure = Parser(textTree, true, { separator: null, metadata: true });16 // 3️⃣ Configure generator options17 const generator = new Maker('./my-project', structure, {18 variables: { name: 'World', projectName: 'AwesomeProject' },19 dryRun: false, // Set true to preview only20 override: true, // Overwrite existing files21 append: false, // Append content to files instead of overwriting22 addBackup: true, // Backup existing files before overwriting23 verbose: true, // Enable step-by-step logging24 ignore: ['.env'], // Example: ignore environment file25 conditions: { 'utils.js': true }, // Conditionally generate utils.js26 onCreate: ({ type, path }) => console.log(`Created ${type}: ${path}`)27 });29 // 4️⃣ Generate the project30 try {31 const result = await generator.generate();32 console.log('✅ Project generation complete!');34 // 5️⃣ Optional: preview result in dry-run mode35 if (generator.options.dryRun) {36 console.log('Preview of files/folders:', result);37 }38 } catch (err) {39 console.error('❌ Error generating project:', err);40 }41})();
✅ What this example do:
- Parses a text-based project tree into structured objects.
- Supports template variables (
{{name}},{{projectName}}) in files. - Uses dry-run / verbose / backup options safely.
- Skips files dynamically via ignore patterns.
- Supports conditional file generation.
- Hooks into creation callbacks for logging.
- Includes append mode as optional behavior.
🧩 Options Reference
| Option | Type | Default | Description |
|---|---|---|---|
dryRun |
boolean | false |
Preview without creating files |
override |
boolean | false |
Overwrite existing files |
append |
boolean | false |
Append content to files |
verbose |
boolean | false |
Enable logging |
ignore |
array | [] |
List of names or regex to ignore |
onCreate |
function | () => {} |
Callback after file/folder creation |
templateExt |
string | .template |
Extension used for template files |
mode |
number | 0o644 |
File/folder permissions |
conditions |
object | {} |
Conditional generation map |
addBackup |
boolean | false |
Backup existing files before overwriting |
variables |
object | {} |
Variables for template substitution |
🌳 Text Tree Format Example
1src/2├── index.js.template console.log('Hello {{name}}!');3├── utils.js4README.md # Project README
- Folders end with
/. - Template files end with
.template. - Use spaces or separators to define inline content.
💡 Tips
- Combine
Parser+Makerfor a full text-to-project workflow. - Use
dryRun: truefirst to avoid accidental overwrites. - Leverage
variablesfor dynamic scaffolding.
🔑 Keywords
project-generator, project-scaffold, nodejs, boilerplate, templating, automation, file-structure, project-init, dry-run, backup-files
📄 License
ISC © HBH