
Security News
Attackers Are Hunting High-Impact Node.js Maintainers in a Coordinated Social Engineering Campaign
Multiple high-impact npm maintainers confirm they have been targeted in the same social engineering campaign that compromised Axios.
A library to automatically generate Express.js routes, validation, and documentation from a config file.
An unopinionated, lightweight library for Express.js that accelerates API development by adopting a declarative, configuration-driven approach. It automatically generates routes, validates request payloads, and produces OpenAPI documentation from a single, centralized configuration file.
This library is designed to eliminate boilerplate, enforce consistency, and serve as a "single source of truth" for your API's structure.
In modern backend development, API endpoints often require a tedious combination of routing, validation, request handling, response formatting, and documentation. This logic is typically scattered across multiple files, leading to code duplication and architectural drift.
Express Dynamic API Generator treats your API's definition as a formal configuration. By defining your routes, validation schemas, and handler links in one place, you gain:
app.get(...), app.post(...) blocks.body, params, and query using a Joi-like syntax.{ status, data, message } envelope.npm install edag
The library operates on three core components:
routes.yaml): The heart of the library. A structured file where you declaratively define every aspect of your API endpoints.(req, res, next) and return data or throw errors. They are decoupled from the routing and validation layers.generateApi): The function that connects everything. It parses the configuration, dynamically creates Express routes, attaches middleware and validators, links handlers, and sets up the documentation endpoint.This example demonstrates a simple User API.
/my-api-project
|-- /handlers
| |-- userHandlers.js
|-- routes.yaml
|-- server.js
|-- package.json
routes.yaml# A list of all API endpoints for the application.
- path: /users
method: get
handler: userHandlers.getAllUsers
middleware: [logger]
summary: "Retrieves a list of all users"
successMessage: "Users retrieved successfully"
- path: /users/:id
method: get
handler: userHandlers.getUserById
middleware: [logger]
summary: "Retrieves a single user by their ID"
successMessage: "User found"
validate:
params:
id:
type: number
integer: true
required: true
- path: /users
method: post
handler: userHandlers.createUser
middleware: [logger]
summary: "Creates a new user"
successMessage: "User created successfully"
validate:
body:
name:
type: string
required: true
min: 2
email:
type: string
email: true
required: true
handlers/userHandlers.jsHandlers are kept clean and focused. They receive the request, perform an action, and either return data or throw a structured error.
// handlers/userHandlers.js
// This is a mock database. In a real application, this would be a database service.
const users = [{ id: 1, name: 'John Doe', email: 'john@example.com' }];
let nextId = 2;
module.exports = {
getAllUsers: async (req, res) => {
return users;
},
getUserById: async (req, res) => {
const user = users.find(u => u.id === parseInt(req.params.id));
if (!user) {
// Throw an error to be caught by the centralized handler.
// Setting a statusCode is a best practice.
const error = new Error('User not found');
error.statusCode = 404;
throw error;
}
return user;
},
createUser: async (req, res) => {
// req.body is already validated at this point.
const newUser = { id: nextId++, ...req.body };
users.push(newUser);
// Return the newly created resource.
return newUser;
},
};
server.jsconst express = require('express');
const path = require('path');
const morgan = require('morgan');
// Import from the library
const { generateApi, registerMiddleware, errorHandler } = require('edag');
const app = express();
const PORT = process.env.PORT || 3000;
// 1. Apply global middleware
app.use(express.json());
// 2. Register any named middleware you want to use in your YAML config
registerMiddleware('logger', morgan('dev'));
// 3. Generate the API from your configuration
generateApi(app, {
configPath: path.join(__dirname, 'routes.yaml'),
handlerPath: path.join(__dirname, 'handlers'),
});
// 4. Register the centralized error handler (must be placed after generateApi)
app.use(errorHandler);
// 5. Start the server
app.listen(PORT, () => {
console.log(`Server is running on http://localhost:${PORT}`);
console.log(`API documentation available at http://localhost:${PORT}/api-docs`);
});
generateApi(app, options)This is the primary function of the library.
app: An Express application instance.options: An object with the following properties:
configPath (string, required): The file path to your routes.yaml or routes.json file.handlerPath (string, required): The path to the directory containing your handler files.registerMiddleware(name, middleware)Registers a middleware function with a friendly name that can be referenced in routes.yaml.
name (string, required): The alias for the middleware (e.g., 'auth').middleware (function, required): An Express middleware function (req, res, next).errorHandlerA pre-built, centralized Express error handling middleware. It's highly recommended to register this last in your middleware stack.
routes.yaml)Each object in the root array defines a route. The following keys are supported:
| Key | Type | Required | Description |
|---|---|---|---|
path | string | Yes | The URL path for the route, supporting Express path parameters (e.g., /users/:id). |
method | string | Yes | An HTTP method: get, post, put, delete, or patch. |
handler | string | Yes | A string formatted as fileName.functionName that points to the handler function. fileName corresponds to a file in the handlerPath. |
summary | string | No | A brief description of the endpoint, used for generating API documentation. |
successMessage | string | No | A custom message to be included in the standardized success response. Defaults to 'Success'. |
middleware | array | No | An array of string names corresponding to middleware registered with registerMiddleware. They execute in order. |
validate | object | No | An object specifying validation rules for body, params, or query. See the validation schema below. |
The validate object can contain body, params, or query keys. Each of these is an object where keys are field names and values are rule objects.
validate:
body:
fieldName:
type: string # 'string', 'number', 'boolean', 'array', 'object'
required: true # boolean
# String-specific rules
email: true # boolean
min: 2 # number (min length)
max: 100 # number (max length)
# Number-specific rules
integer: true # boolean
Contributions, issues, and feature requests are welcome. Feel free to check the issues page. To contribute:
git checkout -b feature/AmazingFeature).git commit -m 'Add some AmazingFeature').git push origin feature/AmazingFeature).FAQs
A library to automatically generate Express.js routes, validation, and documentation from a config file.
We found that edag demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
Multiple high-impact npm maintainers confirm they have been targeted in the same social engineering campaign that compromised Axios.

Security News
Axios compromise traced to social engineering, showing how attacks on maintainers can bypass controls and expose the broader software supply chain.

Security News
Node.js has paused its bug bounty program after funding ended, removing payouts for vulnerability reports but keeping its security process unchanged.