JavaScript Usage
Using AzuraJS with plain JavaScript
JavaScript Usage ๐
AzuraJS works great with plain JavaScript! While the framework is TypeScript-first, you can use all features with JavaScript using the functional API.
Why JavaScript? ๐ค
- Simplicity - No transpilation needed for simple projects
- Familiar - Express-like API that JavaScript developers know
- Flexible - Use decorators in TypeScript, functions in JavaScript
- Progressive - Start with JS, migrate to TS when needed
Quick Start ๐
1. Install AzuraJS
npm install azurajs2. Create Configuration
const config = {
environment: "development",
server: {
port: 3000,
cluster: false,
},
logging: {
enabled: true,
showDetails: true,
},
};
export default config;3. Create Your Server
import { AzuraClient } from "azurajs";
import { createLoggingMiddleware } from "azurajs/middleware";
const app = new AzuraClient();
const logger = createLoggingMiddleware(app.getConfig());
app.use(logger);
app.get("/", (req, res) => {
res.json({ message: "Hello from JavaScript!" });
});
await app.listen();4. Run It
bun run index.js
# or
node index.jsFunctional API ๐ง
Defining Routes
import { AzuraClient } from "azurajs";
const app = new AzuraClient();
// GET route
app.get("/users", (req, res) => {
res.json({ users: [] });
});
// POST route
app.post("/users", (req, res) => {
const body = req.body;
res.status(201).json({ created: body });
});
// PUT route
app.put("/users/:id", (req, res) => {
const { id } = req.params;
res.json({ id, updated: true });
});
// DELETE route
app.delete("/users/:id", (req, res) => {
const { id } = req.params;
res.status(204).send();
});Request Parameters
// Path parameters
app.get("/users/:id/posts/:postId", (req, res) => {
const { id, postId } = req.params;
res.json({ userId: id, postId });
});
// Query parameters
app.get("/search", (req, res) => {
const { q, limit = 10, page = 1 } = req.query;
res.json({ query: q, limit: Number(limit), page: Number(page) });
});
// Request body
app.post("/data", (req, res) => {
const body = req.body;
res.json({ received: body });
});
// Headers
app.get("/info", (req, res) => {
const userAgent = req.headers["user-agent"];
res.json({ userAgent });
});Middleware in JavaScript ๐
Basic Middleware
// Simple logging
app.use((req, res, next) => {
console.log(`${req.method} ${req.url}`);
next();
});
// Request timing
app.use((req, res, next) => {
const start = Date.now();
next();
const duration = Date.now() - start;
console.log(`Request took ${duration}ms`);
});Authentication Middleware
const authMiddleware = (req, res, next) => {
const token = req.headers.authorization;
if (!token) {
return res.status(401).json({ error: "No token" });
}
// Verify token
req.user = { id: 1, name: "User" };
next();
};
// Apply to specific routes
app.get("/protected", authMiddleware, (req, res) => {
res.json({ user: req.user });
});Configurable Middleware
function createRateLimit(limit, windowMs) {
const requests = new Map();
return (req, res, next) => {
const ip = req.socket.remoteAddress;
const now = Date.now();
const userRequests = requests.get(ip) || [];
const recentRequests = userRequests.filter(time => now - time < windowMs);
if (recentRequests.length >= limit) {
return res.status(429).json({ error: "Too many requests" });
}
recentRequests.push(now);
requests.set(ip, recentRequests);
next();
};
}
// Use it
const rateLimit = createRateLimit(100, 60000); // 100 requests per minute
app.use(rateLimit);Complete Example ๐ฏ
Here's a complete REST API in JavaScript:
import { AzuraClient } from "azurajs";
import { createLoggingMiddleware } from "azurajs/middleware";
const app = new AzuraClient();
const logger = createLoggingMiddleware(app.getConfig());
app.use(logger);
// In-memory database
const users = [
{ id: 1, name: "Alice", email: "[email protected]" },
{ id: 2, name: "Bob", email: "[email protected]" },
];
let nextId = 3;
// List all users
app.get("/api/users", (req, res) => {
const { page = 1, limit = 10 } = req.query;
const startIndex = (page - 1) * limit;
const endIndex = startIndex + Number(limit);
res.json({
data: users.slice(startIndex, endIndex),
pagination: {
page: Number(page),
limit: Number(limit),
total: users.length,
},
});
});
// Get user by ID
app.get("/api/users/:id", (req, res) => {
const { id } = req.params;
const user = users.find(u => u.id === Number(id));
if (!user) {
return res.status(404).json({ error: "User not found" });
}
res.json({ data: user });
});
// Create user
app.post("/api/users", (req, res) => {
const { name, email } = req.body;
if (!name || !email) {
return res.status(400).json({ error: "Name and email required" });
}
const user = {
id: nextId++,
name,
email,
createdAt: new Date().toISOString(),
};
users.push(user);
res.status(201).json({ data: user });
});
// Update user
app.put("/api/users/:id", (req, res) => {
const { id } = req.params;
const { name, email } = req.body;
const user = users.find(u => u.id === Number(id));
if (!user) {
return res.status(404).json({ error: "User not found" });
}
if (name) user.name = name;
if (email) user.email = email;
user.updatedAt = new Date().toISOString();
res.json({ data: user });
});
// Delete user
app.delete("/api/users/:id", (req, res) => {
const { id } = req.params;
const index = users.findIndex(u => u.id === Number(id));
if (index === -1) {
return res.status(404).json({ error: "User not found" });
}
users.splice(index, 1);
res.status(204).send();
});
// Health check
app.get("/health", (req, res) => {
res.json({ status: "healthy", timestamp: new Date().toISOString() });
});
// Start server
await app.listen();Cookie Handling ๐ช
// Set cookie
app.get("/login", (req, res) => {
res.cookie("session", "abc123", {
httpOnly: true,
maxAge: 3600000, // 1 hour
secure: true,
});
res.json({ message: "Logged in" });
});
// Read cookie
app.get("/profile", (req, res) => {
const session = req.cookies.session;
if (!session) {
return res.status(401).json({ error: "Not authenticated" });
}
res.json({ session });
});
// Clear cookie
app.get("/logout", (req, res) => {
res.clearCookie("session");
res.json({ message: "Logged out" });
});Error Handling โ ๏ธ
// Custom error handler middleware
app.use((req, res, next) => {
try {
next();
} catch (error) {
console.error(error);
res.status(500).json({ error: "Internal server error" });
}
});
// Route-level error handling
app.get("/risky", (req, res) => {
try {
// Risky operation
throw new Error("Something went wrong");
} catch (error) {
res.status(500).json({ error: error.message });
}
});Migration to TypeScript ๐
When you're ready to add type safety:
- Rename files -
.jsโ.ts - Add types - Import types from
azurajs - Optional decorators - Use decorators for better organization
import { AzuraClient } from "azurajs";
import type { RequestHandler } from "azurajs/types";
const authMiddleware: RequestHandler = async (req, res, next) => {
// Your middleware logic
await next();
};Best Practices โจ
Use const - Prefer const over let when possible
Destructure - Use destructuring for cleaner code: const { id } = req.params
Async/await - Use async/await instead of callbacks
Error handling - Always handle errors properly
Performance Tips โก
// Avoid creating middleware in routes
// โ Bad
app.get("/data", (req, res, next) => {
const logger = createLogger(); // Created on every request!
next();
}, handler);
// โ
Good
const logger = createLogger(); // Created once
app.use(logger);
app.get("/data", handler);Next Steps ๐
Quick Start
Build your first API
Middleware
Learn about middleware
Routing
Advanced routing patterns
TypeScript
Migrate to TypeScript
