nhb-scripts
Version:
A collection of Node.js scripts to use in TypeScript & JavaScript projects
1,402 lines (1,054 loc) • 42.3 kB
Markdown
# NHB Scripts
<!-- markdownlint-disable-file MD024 -->
<p>
<a href="https://www.npmjs.com/package/nhb-scripts" aria-label="Downloads">
<img src="https://img.shields.io/npm/dm/nhb-scripts.svg?label=DOWNLOADS&style=flat&color=red&logo=npm" alt="Downloads" />
</a>
<a href="https://www.npmjs.com/package/nhb-scripts" aria-label="Version">
<img src="https://img.shields.io/npm/v/nhb-scripts.svg?label=nhb-scripts&style=flat&color=teal&logo=npm" alt="Latest Version" />
</a>
<!-- <a href="https://bundlephobia.com/result?p=nhb-scripts" aria-label="Bundle size">
<img src="https://img.shields.io/bundlephobia/minzip/nhb-scripts?style=flat&color=purple&label=SIZE&logo=nodedotjs" alt="Bundle Size" />
</a> -->
<a href="https://www.npmjs.com/package/nhb-scripts" aria-label="License">
<img src="https://img.shields.io/npm/l/nhb-scripts.svg?label=LICENSE&style=flat&color=orange&logo=open-source-initiative" alt="License" />
</a>
</p>
A **developer-first toolkit** to automate common dev tasks in JavaScript/TypeScript projects. Built to reduce repetitive boilerplate and improve developer velocity — no magic, just clean logic.
## Table of Contents
- [⚡ Compatibility](#-compatibility)
- [✅ Requirements](#-requirements)
- [⚙️ Unified Configuration System](#️-unified-configuration-system)
- [🧰 Included CLI Scripts](#-included-cli-scripts)
- [🔧 How to Use in Your Project](#-how-to-use-in-your-project)
- [🧱 nhb-module — Module Generator](#-nhb-module--module-generator)
- [⚙️ Setup in package.json](#️-setup-in-packagejson)
- [🛠️ What It Does](#️-what-it-does)
- [📦 Pre-built Template](#-pre-built-template)
- [📁 Custom Template Support](#-custom-template-support)
- [🧠 Why dynamic files?](#-why-dynamic-files)
- [🗂️ Template Files files](#️-template-files-files)
- [💡 CLI Flags](#-cli-flags)
- [🤖 What Happens Behind the Scenes](#-what-happens-behind-the-scenes)
- [📁 Output Example](#-output-example)
- [🧩 Template Shape](#-template-shape)
- [🔄 Lifecycle Hooks Optional](#-lifecycle-hooks-optional)
- [🛑 Cancel or Abort](#-cancel-or-abort)
- [🏗️ nhb-build — Customizable Build Runner with Progress Visualization](#️-nhb-build--customizable-build-runner-with-progress-visualization)
- [✨ Features](#-features)
- [⚙️ Configuration](#️-configuration)
- [🏗️ Options](#️-options)
- [📦 Usage](#-usage)
- [✅ Example Output](#-example-output)
- [🔧 Post‑Build Hooks](#-postbuild-hooks)
- [📝 nhb-commit — Commit Version Updates with Semver & Custom Message](#-nhb-commit--commit-version-updates-with-semver--custom-message)
- [⚙️ Setup in package.json](#️-setup-in-packagejson-1)
- [🚦 What It Does](#-what-it-does)
- [✨ Commit Format](#-commit-format)
- [🧩 Supported Types Predefined Choices](#-supported-types-predefined-choices)
- [💬 Prompt Flow](#-prompt-flow)
- [🧪 Semver Validations](#-semver-validations)
- [🔧 Behavior Summary](#-behavior-summary)
- [⚙️ Configuration](#️-configuration-1)
- [📌 Available Options](#-available-options)
- [✨ Formatter Integration Prettier](#-formatter-integration-prettier)
- [📁 Optional Formatter Config](#-optional-formatter-config)
- [📦 Combined Flow](#-combined-flow)
- [🛑 Cancel or Abort](#-cancel-or-abort-1)
- [🐕 nhb-husky - Setup Husky with Lint-Staged](#-nhb-husky---setup-husky-with-lint-staged)
- [📦 What It Does](#-what-it-does-1)
- [🎨 nhb-format — Code Formatter Prettier Runner](#-nhb-format--code-formatter-prettier-runner)
- [⚙️ Setup in package.json](#️-setup-in-packagejson-2)
- [📦 What It Does](#-what-it-does-2)
- [🛠️ Example Config](#️-example-config)
- [🔄 Automatic Integration with nhb-commit](#-automatic-integration-with-nhb-commit)
- [⚠️ Requirements](#️-requirements)
- [📁 Output Example](#-output-example-1)
- [✅ nhb-lint — ESLint Linter Runner](#-nhb-lint--eslint-linter-runner)
- [⚙️ Setup in package.json](#️-setup-in-packagejson-3)
- [✨ Features](#-features-1)
- [🛠️ Example Config](#️-example-config-1)
- [📦 Output Example](#-output-example-2)
- [🔧 nhb-fix — ESLint Auto‑Fix Runner](#-nhb-fix--eslint-autofix-runner)
- [⚙️ Setup in package.json](#️-setup-in-packagejson-4)
- [✨ Features](#-features-2)
- [📦 Output Example](#-output-example-3)
- [⚙️ Configuration](#️-configuration-2)
- [💡 Pro Tips](#-pro-tips)
- [📊 nhb-count — Export Counter CLI](#-nhb-count--export-counter-cli)
- [🔧 Usage](#-usage-1)
- [⚙️ Configuration](#️-configuration-3)
- [🧭 Interactive CLI Prompts](#-interactive-cli-prompts)
- [✅ Exactly What Happens](#-exactly-what-happens)
- [✅ Output Example](#-output-example-4)
- [📌 What It Detects](#-what-it-detects)
- [✅ Example](#-example)
- [🗑 nhb-delete – Interactive File & Folder Remover](#-nhb-delete--interactive-file--folder-remover)
- [🚀 Usage](#-usage-2)
- [✨ Features](#-features-3)
- [📌 Example](#-example-1)
- [📄 License](#-license)
<!-- /TOC -->
## ⚡ Compatibility
<img src="https://img.shields.io/badge/Node.js-Version%2022+-teal?style=flat&logo=node.js&logoColor=green" alt="Node.js 22+" />
> **Important:**
> `nhb-scripts` is designed **only for Node.js environments** (v22 or later).
> It is **not intended for browser environment**, so tools like [Bundlephobia](https://bundlephobia.com/) may report missing browser dependencies.
> This is expected behavior and does **not** affect usage in `Node.js`.
### ✅ Requirements
- Node.js **22 or newer**
- `npm`, `pnpm`, or `yarn` for installation
```bash
pnpm add -D nhb-scripts
# or
npm install -D nhb-scripts
# or
yarn add -D nhb-scripts
```
<details>
<summary>
## ⚙️ Unified Configuration System
</summary>
All scripts use a single configuration file `nhb.scripts.config.mjs` that is automatically created if not present. Available configuration options include:
```js
// @ts-check
import { defineScriptConfig, expressMongooseZodTemplate } from 'nhb-scripts';
export default defineScriptConfig({
format: {
args: ['--write'],
files: ['.'],
ignorePath: '.prettierignore',
},
lint: { folders: ['src'], patterns: ['**/*.ts'] }, // Optional, these are defaults
fix: { folders: ['src'], patterns: ['**/*.ts'] }, // Optional, these are defaults
commit: {
runFormatter: false, // do not run formatter, use `true` to format before committing
},
count: {
defaultPath: '.', // default path to scan
excludePaths: ['node_modules', 'dist', 'build'] // folders to exclude
},
build: {
distFolder: 'dist', // optional, default: "dist"
deleteDist: true, // delete dist folder before each build, set `false` to keep dist folder intact
showOutputs: true, // display output file list, default is `false`
commands: [ // default is [{cmd: 'tsc'}]
// Not default
{ cmd: 'tsc', args: ['-p', 'tsconfig.cjs.json'] },
// Not default
{
cmd: 'tsc',
args: ['-p', 'tsconfig.esm.json'],
options: { stdio: 'inherit' }
}
],
after: [
// Not default
async () => await fixJsExtensions('dist/esm'),
// Not default
async () => await fixTypeExports({
distPath: 'dist/dts',
packageJsonPath: 'package.json',
typeFileCandidates: ['types.d.ts', 'interfaces.d.ts'],
extraPatterns: [
{ pattern: 'plugins', folderName: 'plugins' },
],
extraStatic: {
'./types': {
types: './dist/dts/types/index.d.ts',
default: './dist/dts/types/index.d.ts'
},
'./constants': {
types: './dist/dts/constants.d.ts',
import: './dist/esm/constants.js',
require: './dist/cjs/constants.js'
},
}
}),
],
},
module: {
destination: 'src/modules', // optional, default: "src/modules"
defaultTemplate: 'my.template1', // selected by default, must match with the keys of `templates` object
force: false, // `true` if you want to override the existing module
templates: {
'express-mongoose-zod': {
createFolder: true,
destination: 'src/app/modules',
files: expressMongooseZodTemplate // pre-built module : function that receives moduleName as argument and creates pre-defined files and contents
},
'my.template1': {
createFolder: true, // if `false` does not create folder with the module name from cli
destination: 'src/app', // optional, will prioritize inputs from cli
// Use dynamic moduleName in filenames and contents
files: (moduleName) => [
{ name: `${moduleName}.controllers.ts`, content: `// controllers for ${moduleName}` },
{ name: `${moduleName}.services.ts`, content: `// services for ${moduleName}` }
]
},
'my_template2': {
destination: 'src/features', // optional, will prioritize inputs from cli
// Use static file list with contents
files: [
{ name: 'index.ts', content: '// content' },
{ name: 'dummy.js', content: '// dummy' }
]
},
},
// Optional hooks to inspect or execute something at the beginning or after the module generation
hooks: {
onGenerate(name) {
console.log('➡️ Generating:', name);
},
onComplete(name) {
console.log('✅ Complete:', name);
}
}
}
});
```
</details>
## 🧰 Included CLI Scripts
| Script | Description |
| --------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------- |
| [nhb-module](#-nhb-module--module-generator) | Scaffold module (folder with files) (e.g., Express + Mongoose + Zod by default) with templates. |
| [nhb-build](#️-nhb-build--customizable-build-runner-with-progress-visualization) | Customizable Build Runner with Progress Visualization. |
| [nhb-commit](#-nhb-commit--commit-version-updates-with-semver--custom-message) | Generate a conventional commit message interactively with validation. |
| [nhb-husky](#-nhb-husky---setup-husky-with-lint-staged) | Setup `husky` with `lint-staged` with `prettier` pre-commit hook. |
| [nhb-format](#-nhb-format--code-formatter-prettier-runner) | Format code with `prettier`. |
| [nhb-lint](#-nhb-lint--eslint-linter-runner) | Lint code with `eslint`. |
| [nhb-fix](#-nhb-fix--eslint-autofix-runner) | Fix linting errors in code with `eslint`. |
| [nhb-count](#-nhb-count--export-counter-cli) | Count export declarations (default, named, aliased) in JS/TS files/folders. |
| [nhb-delete](#-nhb-delete--interactive-file--folder-remover) | Interactive File(s)/Folder(s) Remover. |
> More Scripts Coming Soon...
<!-- > ✅ All scripts are available via **`pnpm/npm/yarn` scripts** or as **binaries** (if installed globally). -->
> Most of the examples here are shown using `pnpm` as package manager, you can use other package managers like `npm` or `yarn` or others.
## 🔧 How to Use in Your Project
Add to your `devDependencies`:
```bash
yarn add -D nhb-scripts
```
```bash
pnpm add -D nhb-scripts
```
```bash
npm i -D nhb-scripts
```
Then in your `package.json`:
```json
{
"scripts": {
"module": "nhb-module",
"commit": "nhb-commit",
"format": "nhb-format",
"count": "nhb-count"
}
}
```
Now run any script like:
```bash
pnpm module # 🧩 Generate a new module
pnpm commit # ✅ Bump version & commit changes
pnpm format # 🎨 Format code with prettier
pnpm count # 📦 Count exports in files
```
Or without `package.json` setup:
```bash
pnpm nhb-module # 🧩 Generate a new module
pnpm nhb-commit # ✅ Bump version & commit changes
pnpm nhb-format # 🎨 Format code with prettier
pnpm nhb-count # 📦 Count exports in files
```
> Replace `pnpm` with `npm run` or `yarn` if you're using those instead.
## 🧱 `nhb-module` — Module Generator
Scaffold consistent, production-ready API modules in your codebase using prebuilt or custom-defined templates.
This CLI simplifies creating module directories and boilerplate files with optional configuration, hooks, and folder override logic.
### ⚙️ Setup in `package.json`
```json
{
"scripts": {
"module": "nhb-module"
}
}
```
then use via:
```bash
pnpm module
```
```bash
yarn module
```
```bash
npm run module
```
or directly use as:
```bash
pnpm nhb-module
```
### 🛠️ What It Does
- Prompts for module name, destination, and template (unless passed as CLI flags).
- Uses a **pre-built template** (`express-mongoose-zod` : imported function `expressMongooseZodTemplate`) or your **custom templates** via a config file.
- Prevents overwriting by default unless `--force` is passed or set in config.
- Allows lifecycle hooks: `onGenerate`, `onComplete`.
### 📦 Pre-built Template
| Name | Description |
| ---------------------- | ----------------------------------------------------------------------------------------------------------------------- |
| `express-mongoose-zod` | Basic Express route + Mongoose model + Zod schema generator (built-in : imported function `expressMongooseZodTemplate`) |
### 📁 Custom Template Support
Configure templates in `nhb.scripts.config.mjs`:
```js
module: {
destination: 'src/modules', // optional, default: "src/modules"
defaultTemplate: 'my.template1', // selected by default, must match with the keys of `templates` object
force: false, // `true` if you want to override the existing module
templates: {
'express-mongoose-zod': {
createFolder: true,
destination: 'src/app/modules',
files: expressMongooseZodTemplate // pre-built module : function that receives moduleName as argument and creates pre-defined files and contents
},
'my.template1': {
createFolder: true, // if `false` does not create folder with the module name from cli
destination: 'src/app', // optional, will prioritize inputs from cli
// Use dynamic moduleName in filenames and contents
files: (moduleName) => [
{ name: `${moduleName}.controllers.ts`, content: `// controllers for ${moduleName}` },
{ name: `${moduleName}.services.ts`, content: `// services for ${moduleName}` }
]
},
'my_template2': {
destination: 'src/features', // optional, will prioritize inputs from cli
// Use static file list with contents
files: [
{ name: 'index.ts', content: '// content' },
{ name: 'dummy.js', content: '// dummy' }
]
},
},
// Optional hooks to inspect or execute something at the beginning or after the module generation
hooks: {
onGenerate(name) {
console.log('➡️ Generating:', name);
},
onComplete(name) {
console.log('✅ Complete:', name);
}
}
}
```
#### 🧠 Why dynamic `files()`?
> If your filenames or content need to reference the module name (e.g. `auth.controller.ts`), use the function form.
> It provides full flexibility for templates that depend on runtime values.
#### 🗂️ Template Files (`files`)
You can provide either of the following:
1. **Static array of file entries**:
```js
files: [
{ name: 'index.ts', content: '// content' },
{ name: 'routes.ts', content: 'export const route = "auth";' },
]
```
2. **Dynamic function (recommended for reusable templates)**:
```js
files: (moduleName) => [
{ name: `${moduleName}.controller.ts`, content: `// controller for ${moduleName}` },
{ name: `${moduleName}.service.ts`, content: `// service for ${moduleName}` },
]
```
> 💡 **Note:** You can and should write actual code inside the `content` field using template strings — works with any language!
> 💡 **File names** (`name`) can include folders like `{ name: 'utils/helper.ts' }`. Folders will be auto-created if missing.
### 💡 CLI Flags
You can also generate modules non-interactively using CLI flags to streamline automation or scripting:
| Flag | Alias | Description |
| ----------------- | ----- | -------------------------------------------- |
| `--name` | `-n` | Name of the module |
| `--template` | `-t` | Template to use |
| `--destination` | `-d` | Directory to generate module into |
| `--force` | `-f` | Overwrite existing module if already present |
| `--create-folder` | `-cf` | Create folder for module (default: `true`) |
Example:
```bash
# Using full flags
pnpm module --name=user --template=basic-app --destination=src/features --force
# Using full flags but without equal sign
pnpm module --name user --template basic-app --destination src/features --force
# Using aliases
pnpm module -n auth -t express-mongoose-zod -d src/modules
# Force overwrite if module exists
pnpm module -n blog -t express-mongoose-zod -d src/modules -f
# With create folder flag
pnpm module --name=user --template=basic-app --destination=src/features --force --create-folder=false
# Using aliases
pnpm module -n auth -t express-mongoose-zod -d src/modules -cf false
```
### 🤖 What Happens Behind the Scenes
1. 🔍 Looks for a config file (offers to create one if missing).
2. 🧱 Asks for module name, template, and destination (or use flags).
3. ⚙️ Merges CLI flags with config values.
4. 🚧 Warns if module exists — prompts overwrite unless `--force`.
5. 🏗️ Generates module files from the selected template.
6. 🔁 Runs `onGenerate` and `onComplete` hooks if configured.
### 📁 Output Example
Given:
```js
module: {
destination: 'src/features',
customTemplates: {
'basic-app': {
files: (name) => [
{ name: `${name}.ts`, content: `// module: ${name}` },
{ name: `${name}.routes.ts`, content: `// routes for ${name}` }
]
}
}
}
```
Run:
```bash
pnpm module -n user -t basic-app
```
**Result:**
```text
src/features/user/
├── user.ts → // module: user
└── user.routes.ts → // routes for user
```
### 🧩 Template Shape
```ts
type FileEntry = {
name: string; // file path relative to the module dir
content: string; // file contents
};
type CustomTemplate = {
destination?: string;
files: FileEntry[] | ((moduleName: string) => FileEntry[]);
};
```
You can define multiple templates and dynamically select one at CLI prompt or via `--template`.
### 🔄 Lifecycle Hooks (Optional)
| Hook | Signature | Purpose |
| ------------ | ------------------------------ | --------------------------- |
| `onGenerate` | `(moduleName: string) => void` | Before writing module files |
| `onComplete` | `(moduleName: string) => void` | After writing module files |
### 🛑 Cancel or Abort
- If a module already exists and `--force` is not used, the CLI prompts confirmation.
- You can abort at any step via keyboard interrupt (`Ctrl+C` or `Esc` on prompts).
## 🏗️ `nhb-build` — Customizable Build Runner with Progress Visualization
A configurable build runner with progress estimator that can execute your build commands in sequence (e.g., `tsc`, `rollup`, `vite`) and then run optional post‑build hooks like `fixTypeExports()` or `fixJsExtensions()`.
### ✨ Features
- ✅ Define any build commands in your `nhb.scripts.config.mjs` (defaults to `tsc`).
- ✅ Dynamically add multiple commands with arguments and `execa` options.
- ✅ Always cleans your specified dist folder (using `rimraf`) before each build to avoid conflicts. You can configure this behavior.
- ✅ Run post‑build hooks (`after`) as an array of async functions (e.g., `fixJsExtensions('dist/esm')`).
- ✅ Rich output: shows file sizes, count, and total build time.
- ✅ Optionally shows output file list. Set `showOutputs: true` in the config to display the list of output files.
### ⚙️ Configuration
Add a `build` section in your `nhb.scripts.config.mjs`:
```js
// @ts-check
import { defineScriptConfig, fixJsExtensions, fixTypeExports} from 'nhb-scripts';
export default defineScriptConfig({
// Other configs...
build: {
distFolder: 'output', // optional, default: "dist"
deleteDist: true, // delete dist folder before each build, set `false` to keep dist folder intact
showOutputs: true, // display output file list, default is `false`
commands: [
{ cmd: 'tsc', args: ['-p', 'tsconfig.cjs.json'] },
{ cmd: 'tsc', args: ['-p', 'tsconfig.esm.json'], options: { stdio: 'inherit' } }
],
after: [
async () => await fixJsExtensions('dist/esm'),
async () => await fixTypeExports({
distPath: 'dist/dts',
packageJsonPath: 'package.json',
typeFileCandidates: ['types.d.ts', 'interfaces.d.ts'],
extraPatterns: [
{ pattern: 'plugins', folderName: 'plugins' },
],
extraStatic: {
'./types': {
types: './dist/dts/types/index.d.ts',
default: './dist/dts/types/index.d.ts'
},
'./constants': {
types: './dist/dts/constants.d.ts',
import: './dist/esm/constants.js',
require: './dist/cjs/constants.js'
},
}
}),
],
}
});
```
#### 🏗️ **Options**
| Field | Type | Default | Description |
| ------------- | ---------------------- | --------- | ------------------------------------------------------------- |
| `distFolder` | `string` | `dist` | Output folder used for size reporting and cleanup. |
| `deleteDist` | `boolean` | `true` | Whether to delete the dist (output) folder before each build. |
| `showOutputs` | `boolean` | `false` | Whether to display the list of output files. |
| `commands` | `Array<BuildCommand>` | see below | Array of build commands. |
| `after` | `Array<Promise<void>>` | `[]` | Post‑build hooks to run sequentially after commands finish. |
**`BuildCommand` shape:**
```ts
{
cmd: string; // executable to run (e.g. "tsc", "rimraf")
args?: string[]; // arguments for the command
options?: import('execa').Options; // additional execa options
}
```
### 📦 Usage
Add to `package.json`:
```json
{
"scripts": {
"build": "nhb-build"
}
}
```
then run via:
```bash
pnpm build
# or
npm run build
# or
yarn build
```
or directly use as:
```bash
pnpm nhb-build
```
### ✅ Example Output
```bash
📦 Build Your Application
─────────────────────────────────────────────
Building...
✓ Transformed Files:
🟨 dist/esm/index.js 3.20 kB
🟦 dist/dts/index.d.ts 0.45 kB
🟩 dist/esm/index.js.map 1.15 kB
...
✓ Total Files: 25; Total Size: 89.42 kB
📦 Application was built in 3.27 seconds!
```
### 🔧 Post‑Build Hooks
`after` hooks run **after all build commands succeed**, in order.
You can pass any async function returning a Promise, for example:
```js
// @ts-check
import { fixJsExtensions, fixTypeExports} from 'nhb-scripts';
export default defineScriptConfig({
build: {
after: [
async () => await fixJsExtensions('dist/esm'),
async () => await fixTypeExports({
distPath: 'dist/dts',
packageJsonPath: 'package.json',
typeFileCandidates: ['types.d.ts', 'interfaces.d.ts'],
extraPatterns: [
{ pattern: 'plugins', folderName: 'plugins' },
],
extraStatic: {
'./types': {
types: './dist/dts/types/index.d.ts',
default: './dist/dts/types/index.d.ts'
},
'./constants': {
types: './dist/dts/constants.d.ts',
import: './dist/esm/constants.js',
require: './dist/cjs/constants.js'
},
}
}),
],
}
});
```
> ✨ **Tip:** Because `nhb-build` uses `execa`, all commands respect your local environment and `cwd`, so you can run any build tools your project needs.
## 📝 `nhb-commit` — Commit Version Updates with Semver & Custom Message
A simple, interactive CLI to:
- Safely bump the package version (`package.json`)
- Add a **conventional typed Git commit message** (with optional scope)
- Automatically commit and push
This ensures your version bumps and commit messages are semver-valid, consistent, and expressive.
### ⚙️ Setup in `package.json`
```json
{
"scripts": {
"commit": "nhb-commit"
}
}
```
then run via:
```bash
pnpm commit
```
or directly use as:
```bash
pnpm nhb-commit
```
### 🚦 What It Does
1. Prompts for **new version** (or skip to use the current).
2. Prompts for a **commit type** (e.g., `feat`, `fix`, `refactor`, etc.).
3. Prompts optionally for a **scope** (e.g., `auth`, `ui`, etc.).
4. Requires a **commit message**.
5. Updates `package.json` version.
6. Runs:
```bash
git add .
git commit -m "<type>(<scope>): <message>"
git push
```
### ✨ Commit Format
```bash
<type>(optional-scope): <message>
```
Examples:
```text
feat(api): add user registration flow
fix: resolve async deadlock issue
refactor(db): improve mongoose connection handling
```
### 🧩 Supported Types (Predefined Choices)
> Default type: **`update`**
| Type | Description |
| ---------- | ------------------------------------ |
| `update` | 🔧 General update (default) |
| `feat` | ✨ New feature |
| `fix` | 🐛 Bug fix |
| `chore` | 🛠️ Maintenance task (e.g., deps) |
| `refactor` | 🧼 Internal logic change |
| `test` | 🧪 Adding/fixing tests |
| `docs` | 📚 Documentation-only change |
| `style` | 💅 Code formatting, styling etc. |
| `perf` | ⚡ Performance improvement |
| `ci` | 🚀 CI-related changes |
| `build` | 🧱 Build system changes |
| `revert` | 🔁 Revert a previous commit |
| `release` | 🔖 Version bump or release |
| `deps` | 📦 Dependency updates |
| `cleanup` | 🧹 Minor cleanup tasks |
| `merge` | 🧭 Merge-related commits |
| `Custom` | ✍️ Manually enter your own |
### 💬 Prompt Flow
```bash
? Current version: 1.3.4
? Enter new version (or press Enter to keep): 1.4.0
? Select commit type: Custom
? Enter custom commit type: infra
? Enter commit scope (optional): devops
? Enter commit message (required): configure docker build
✔ Commit message → infra(devops): configure docker build
✔ Version updated to 1.4.0
✔ Committed and pushed!
```
### 🧪 Semver Validations
- Prevents invalid semver input
- Ensures new version is **equal to or greater** than current
- Allows skipping version bump by pressing `Enter`
### 🔧 Behavior Summary
> **Note:** Git must be installed, and your repository must be initialized with a remote named `origin`.
This is required because the script **automatically commits and pushes** version changes to your Git remote.
| Step | Behavior |
| ---------------- | ----------------------------------------------------------------------- |
| `version` prompt | Accepts semver (e.g., `1.2.3`, `2.0.0-beta.1`) or press `Enter` to skip |
| `type` prompt | Choose from predefined types or default (`update`) |
| `scope` prompt | Optional. If blank, excluded from final commit message |
| `message` prompt | Required. Validates non-empty |
| `git` operations | Adds all changes, commits, pushes with composed message |
### ⚙️ Configuration
In `nhb.scripts.config.mjs`:
```js
commit: {
runFormatter: false // set true to run Prettier before committing
}
```
#### 📌 Available Options
| Option | Type | Default | Description |
| -------------- | ------- | ------- | ------------------------------------------------------------ |
| `runFormatter` | boolean | `false` | Whether to **automatically run Prettier** before committing. |
### ✨ Formatter Integration (Prettier)
If `runFormatter: true` is enabled in the config:
- It **ensures** `.prettierrc.json` and `.prettierignore` exist.
- It runs `prettier --write .` or customized options from `nhb.format.config.mjs` (if present) **before** staging changes.
> 💡 This ensures your code is always formatted before being committed!
### 📁 Optional Formatter Config
You can also define a custom formatter config.
Please refer to [nhb-format](#-nhb-format--code-formatter-prettier-runner) for details.
> If you prefer `husky` and `lint-staged` follow the [instructions here](#-nhb-husky---setup-husky-with-lint-staged).
### 📦 Combined Flow
If both configs are present and `runFormatter` is `true`, `nhb-commit` will:
1. Load your `nhb.format.config.mjs` (if available).
2. Run Prettier formatting.
3. Proceed to version update and Git commit.
### 🛑 Cancel or Abort
You can abort at any time using `Ctrl+C` or `Esc`.
## 🐕 `nhb-husky` - Setup Husky with Lint-Staged
Setup `husky` with `lint-staged` with `prettier` pre-commit hook quickly.
> If you use husky with lint-staged make sure to set `runFormatter: false` in `nhb.scripts.config.mjs` file:
```js
commit: {
runFormatter: false,
}
```
directly run:
```bash
pnpm nhb-husky
```
### 📦 What It Does
1. Installs `husky` and `lint-staged` if not installed already.
2. Configures `.husky/pre-commit` file with proper `lint-staged` setup.
3. Creates `.lintstagedrc.json` file with following config:
```json
{
"*.+((c|m)?js(x)?|(c|m)?ts(x)?)": [
"prettier --write"
]
}
```
> If `.lintstagedrc.json` file already exists, it skips creating this file.
> For further configuration for these files, please refer to their official docs: [husky](https://typicode.github.io/husky/) and [lint-staged](https://www.npmjs.com/package/lint-staged)
## 🎨 `nhb-format` — Code Formatter (Prettier Runner)
A script that ensures clean and consistent formatting using **Prettier**, with optional config and auto-scaffolding support.
### ⚙️ Setup in `package.json`
```json
{
"scripts": {
"format": "nhb-format"
}
}
```
then run it via:
```bash
pnpm format
```
or directly use as:
```bash
pnpm nhb-format
```
### 📦 What It Does
1. Ensures `.prettierrc.json` and `.prettierignore` exist in the project root (auto-generates if missing).
2. Loads user config from:
- `nhb.scripts.config.mjs` or
- `nhb.scripts.config.js`
3. Executes Prettier with the defined args/files.
> 💡 If no config file exists, it runs Prettier with default args: `--write .`
### 🛠️ Example Config
Update format1 property in `nhb.scripts.config.mjs` file:
```js
format: {
args: ['--write'],
files: ['src', 'lib'],
ignorePath: '.prettierignore'
}
```
### 🔄 Automatic Integration with `nhb-commit`
If `runFormatter: true` is set in your `nhb.commit.config.mjs`, the formatter will be triggered **before committing**.
See [nhb-commit](#-nhb-commit--commit-version-updates-with-semver--custom-message) for more details.
### ⚠️ Requirements
Make sure `prettier` is installed in your `dependencies` or `devDependencies`:
```bash
pnpm add -D prettier
```
If missing, the script will exit with a warning and suggest installation.
### 📁 Output Example
```bash
pnpm format
🎨 Running Prettier...
# Scanned file-list
✅ Prettier formatting complete!
```
## ✅ `nhb-lint` — ESLint Linter Runner
Run ESLint across your project with a unified configuration system.
It **automatically detects your folders and patterns** from `nhb.scripts.config.mjs` and shows a **detailed lint summary** with all issues.
### ⚙️ Setup in `package.json`
```json
{
"scripts": {
"lint": "nhb-lint"
}
}
```
then run via:
```bash
pnpm lint
# or
npm run lint
# or
yarn lint
```
or directly use as:
```bash
pnpm nhb-lint
```
### ✨ Features
- ✅ Auto‑detects and ensures ESLint configuration (`.eslintrc.cjs` etc.)
- ✅ Loads lint config (`folders`, `patterns`) from `nhb.scripts.config.mjs`
- ✅ Rich output with a **bullet‑point summary** of all ESLint findings
- ✅ Shows scanned file count and total runtime
- ✅ Works with TypeScript & JavaScript projects (ESM only)
### 🛠️ Example Config
In `nhb.scripts.config.mjs`:
```js
lint: {
folders: ['src', 'tests'], // optional; default: ["src"]
patterns: ['**/*.ts', '**/*.tsx'] // optional; default: ["**/*.ts"]
}
```
### 📦 Output Example
```bash
🚀 Run ESLint Linter
⏳ Linting Your Code in src, tests...
✓ Lint Summary
• src/index.ts:12:3 warning Unexpected console statement no-console
• src/utils/helpers.ts:45:10 error Missing return type on function @typescript-eslint/explicit-module-boundary-types
• tests/app.spec.ts:5:1 error Prefer const over let prefer-const
✓ Scanned total 58 files in 2.43 seconds!
🎉 Linting completed in folders: src, tests
```
## 🔧 `nhb-fix` — ESLint Auto‑Fix Runner
Run ESLint with the `--fix` flag to **automatically fix** many common issues in your code.
### ⚙️ Setup in `package.json`
```json
{
"scripts": {
"fix": "nhb-fix"
}
}
```
then run via:
```bash
pnpm fix
# or
npm run fix
# or
yarn fix
```
or directly use as:
```bash
pnpm nhb-fix
```
### ✨ Features
- ✅ Same detection and configuration as `nhb-lint`
- ✅ Applies **auto‑fixable** rules (formatting, unused vars, etc.)
- ✅ Shows a **fix summary** with all changes applied
- ✅ Counts scanned files and shows runtime
### 📦 Output Example
```bash
🚀 Run ESLint Linter
⏳ Fixing Your Code in src...
✓ Fix Summary
• src/utils/array.ts:12:1 fixed Remove unused import
• src/components/Button.tsx:5:1 fixed Format JSX spacing
✓ Scanned total 58 files in 2.02 seconds!
🎉 Fixing completed in folders: src
```
### ⚙️ Configuration
`nhb-fix` use the `fix` section in `nhb.scripts.config.mjs`:
```js
fix: {
folders: ['src'], // Folders to lint
patterns: ['**/*.ts'] // Glob patterns per folder
}
```
### 💡 Pro Tips
- Run `pnpm lint` before pushing to catch errors early.
- Run `pnpm fix` to automatically resolve fixable issues.
- Combine with `nhb-commit` (`runFormatter` option) for a fully automated commit pipeline.
## 📊 `nhb-count` — Export Counter CLI
Analyze the structure of JavaScript/TypeScript modules to detect and count:
- Default exports
- Named exports
- Aliased named exports
- Type-only named exports (`export type { ... }`)
> ⚠ Only supports files that use **ES-style exports** (`export`, `export default`). *CommonJS-style* (`module.exports`, `exports.foo`) is not currently counted.
### 🔧 Usage
```bash
pnpm count
```
> **Note:** This must be configured in your `package.json` scripts:
```json
{
"scripts": {
"count": "nhb-count"
}
}
```
then run via:
```bash
pnpm count
```
or directly use as:
```bash
pnpm nhb-count
```
### ⚙️ Configuration
In `nhb.scripts.config.mjs`:
```js
count: {
defaultPath: '.', // Default path when no input is provided
excludePaths: [ // Directories automatically excluded
'node_modules',
'dist',
'build'
]
}
```
### 🧭 Interactive CLI Prompts
When executed, the script will prompt you:
```bash
📂 Export Counter
───────────────────────────────────────────────────────────────────────────────-----
🎯 Please specify the path to a "js/ts/mjs" file or folder containing "js/ts/mjs" files.
- Enter file path (with extension) to analyze one file
- Enter folder path to scan recursively
- Press Enter to use default path: [shows configured defaultPath]
```
### ✅ Exactly What Happens
1. If you **enter a file path**:
- Must be `.js`, `.ts`, or `.mjs`
- Analyzes only that file
2. If you **enter a folder path**:
- Recursively scans for matching files
- Automatically excludes `node_modules`, `dist`, `build`
- Respects additional `excludePaths` from config
3. If you **press Enter**:
- Uses `defaultPath` from config (defaults to `.`)
### ✅ Output Example
```bash
📦 Export Summary for "src/utils/math.ts":
🔸 Default Exports : 1
🔹 Named Exports (Total) : 5
┣ Direct : 3
┗ Aliased : 2
🔺 Total Type Exports : 4
```
Key Notes:
- No command-line arguments accepted
- Path must be entered interactively
- Default path comes from config
- Exclusion rules are automatic
### 📌 What It Detects
| Count Type | Description |
| --------------------- | ------------------------------------------------------------------ |
| `default` | Number of `export default` statements |
| `namedExportsTotal` | Total `export { x, y as z }` style exports, including aliased ones |
| `namedExportsDirect` | Named exports without aliases (e.g., `export { foo }`) |
| `namedExportsAliased` | Named exports using `as` keyword (e.g., `export { foo as bar }`) |
| `namedTypeExports` | Type-only exports (e.g., `export type { MyType }`) |
### ✅ Example
Given this file:
```ts
export default function main() {}
export const foo = 42;
export { bar as renamedBar };
export type { SomeType };
```
Output:
```bash
📦 Export Summary for "some/file.ts":
🔸 Default Exports : 1
🔹 Named Exports (Total) : 2
┣ Direct : 1
┗ Aliased : 1
🔺 Total Type Exports : 1
```
### 🗑 `nhb-delete` – Interactive File & Folder Remover
Safely clean up your project with a guided, prompt‑driven experience to browse and delete files or directories.
> Deleting large or deeply nested folders from VS Code often takes a long time or fails unexpectedly — `nhb-delete` offers a faster and more reliable solution.
✅ Navigate into sub-folders or go back anytime
✅ Multi‑select files and folders for deletion
✅ Empty folders immediately prompt for deletion
✅ Skips opening truly empty directories
#### 🚀 Usage
> **Note:** This must be configured in your `package.json` scripts:
```json
{
"scripts": {
"delete": "nhb-delete"
}
}
```
then run via:
```bash
pnpm delete
```
or directly use as:
```bash
pnpm nhb-delete
```
#### ✨ Features
- **Interactive navigation:** step through your folders with clear prompts.
- **Smart listings:** if only files exist, jump straight to multi‑select.
- **Empty folder handling:** offers deletion instead of opening.
- **Safe confirmation:** always double‑checks before removal.
#### 📌 Example
```bash
🗑 Delete Directory/File(s)
? Enter a base path or choose current directory ›
❯ 📂 Current Directory
✏️ Enter manually
```
Use **Space** to select and **Enter** to confirm — perfect for cleaning up scaffolds, build artifacts, or leftover files.
> Built with ❤️ to make developer lives easier – because every second saved is a second earned.
## 📄 License
[MIT](LICENSE) © [Nazmul Hassan](mailto:nazmulnhb@gmail.com)