Aroma.js Documentation

Welcome to Aroma.js — a lightweight and expressive framework for building modern web servers in Node.js. This guide will walk you through the installation, core concepts, and advanced features with simple examples.

1. Installation

To get started, install Aroma.js via npm:

npm install aroma.js

2. Getting Started

Once installed, import Aroma and create your first app instance. Here's a basic example with a middleware and a route:

import Aroma from 'aroma.js';

const app = new Aroma();

// Middleware example
app.use((req, res, next) => {
  console.log(`Request received: ${req.method} ${req.url}`);
  next();
});

// Simple route
app.get('/', (req, res) => {
  res.send({ message: 'Hello, world!' });
});

// Start server
app.listen(3000, () => {
  console.log('Aroma.js server running on http://localhost:3000');
});

3. Working with Routes & Middleware

Aroma.js supports multiple HTTP methods like GET, POST, PUT, and DELETE. You can also use middlewares to handle tasks such as authentication or logging:

// Define multiple routes
app.get('/about', (req, res) => {
  res.send({ message: 'About page' });
});

app.post('/submit', (req, res) => {
  res.send({ message: 'Data received' });
});

// Middleware example for authentication
app.use((req, res, next) => {
  if (!req.headers.authorization) {
    return res.status(403).send({ error: 'Unauthorized' });
  }
  next();
});

4. Template Rendering

You can render HTML views using engines like EJS. Just set your views directory and the template engine.

import Aroma from 'aroma.js';
import path from 'path';

const app = new Aroma();

// Set up template rendering
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');

app.get('/', (req, res) => {
  res.render('index', { title: 'Welcome to Aroma.js' });
});

app.listen(3000, () => {
  console.log('Server running on http://localhost:3000');
});

5. Error Handling

Use a global error-handling middleware to catch and respond to server-side issues in a clean and consistent way.

// Global error handling middleware
app.use((err, req, res, next) => {
  console.error(err.stack);
  res.status(500).send({ error: 'Something went wrong!' });
});

6. Database Integration (MongoDB)

Aroma.js can easily be used with MongoDB and other databases. Here’s how to connect and fetch data using the MongoDB client:

import Aroma from 'aroma.js';
import { MongoClient } from 'mongodb';

const app = new Aroma();
const client = new MongoClient('mongodb://localhost:27017');

app.get('/users', async (req, res) => {
  try {
    await client.connect();
    const db = client.db('mydatabase');
    const users = await db.collection('users').find().toArray();
    res.send(users);
  } catch (error) {
    res.status(500).send({ error: 'Database connection error' });
  }
});

app.listen(3000, () => {
  console.log('Server running on http://localhost:3000');
});

7. Using Routers

Modularize your application using Router instances. It helps you group related routes under a single path.

import Aroma from 'aroma.js';

const app = new Aroma();
const router = app.Router();

// Define routes
router.get('/home', (req, res) => {
  res.send({ message: 'Welcome to Home Page' });
});

router.post('/login', (req, res) => {
  res.send({ message: 'Login Successful' });
});

router.put('/update', (req, res) => {
  res.send({ message: 'Update Successful' });
});

router.delete('/delete', (req, res) => {
  res.send({ message: 'Delete Successful' });
});

// Use router in app
app.use('/api', router);

app.listen(3000, () => {
  console.log('Server running on http://localhost:3000');
});

8. Cookie Handling

With useCookies() and manageCookies(), Aroma.js makes setting and reading cookies easy:

import Aroma from 'aroma.js';

const app = new Aroma();
app.useCookies();
app.get('/set-cookie', (req, res) => {
  // Set a cookie
  res.manageCookies('username', 'AromaUser', { httpOnly: true, maxAge: 3600 });
  res.send('Cookie has been set');
});

app.get('/get-cookie', (req, res) => {
  // Retrieve a cookie
  const username = req.cookies.username;
  res.send(`Username from cookie: ${username}`);
});

app.listen(3000, () => {
  console.log('Server running on http://localhost:3000');
});

9. Serving Static Files

Use serveStatic() to serve assets like CSS, JS, or images from a public directory:

import Aroma from 'aroma.js';
import path from 'path';

const app = new Aroma();

// Serve static files from the 'public' directory
app.serveStatic(path.join(__dirname, 'public'));

app.listen(3000, () => {
  console.log('Server running on http://localhost:3000');
});

10. Rate Limiting

Protect your APIs from abuse by enabling basic rate limiting using rateLimiter():

import Aroma from 'aroma.js';

const app = new Aroma();

// define a rate limit
app.rateLimiter({ windowMs: 60000, max: 2 });

app.get('/', (req, res) => {
  res.send({ message: 'Hello, world!' });
});

// Start server
app.listen(3000, () => {
  console.log('Aroma.js server running on http://localhost:3000');
});

11. Body Parsing

Parse JSON and form bodies

app.parseBody();

app.post('/data', (req, res) => {
  res.send(req.body);
});

12. Metrics

Enable real-time health data

app.metrics();

13. Logging

Log each request easily

app.logger();

14. Error Handling

Define global error handlers

app.handleErrors((err, req, res) => {
  console.error('Error:', err);
  res.status(500).send('Something broke!');
});

15. Response Helpers

Use status(), send(), json()

res.status(404).send("Not found");
res.send("Plain text or JSON");
res.json({ success: true });

16. Mounting Routes from Folder

Use mount() to automatically load and register route files from a directory. Each route file should export a function that receives the Aroma instance.

import Aroma from 'aroma.js';

const app = new Aroma();

// Automatically mount all routes from the 'routes' folder
app.mount('./routes');

app.listen(3000, () => {
  console.log('Server running on http://localhost:3000');
});

Example route file: routes/home.js

// routes/home.js
module.exports = (app) => {
  app.get('/', (req, res) => {
    res.send('Hello from mounted route!');
  });
};

🚀 More features and plugins coming soon — stay tuned!