Guide for AI coding agents working with this Node.js REST API codebase.
# Install dependencies
bun install
# Start server (requires environment variables)
node index.jsRequired Environment Variables:
HOST=<mysql-host>
USER=<mysql-user>
PASSWORD=<mysql-password>
DATABASE=<mysql-database>
TOKEN_KEY=<jwt-secret-key>nodejs-api/
├── index.js # Entry point: HTTPS server, Express, Socket.io, MySQL
├── controllers/
│ └── db.js # Database CRUD abstraction layer
├── middleware/
│ ├── auth.js # JWT auth, CORS, Socket.io authentication
│ └── formidable.js # Form data parsing
├── routes/
│ ├── auth.js # Login/signup endpoints (/auth/*)
│ ├── animations.js # /api/animations CRUD
│ ├── animateurs.js # /api/animateurs CRUD
│ ├── clients.js # /api/clients CRUD
│ └── lieux.js # /api/lieux CRUD
└── certificates/ # SSL certificates for HTTPS
- Files: lowercase (
db.js,auth.js) - Functions: camelCase (
sendData,putEntry,handleDisconnect) - Variables: camelCase, use
varfor module-level,const/letfor block scope - Environment vars: UPPERCASE (
TOKEN_KEY,DATABASE)
// Route factory pattern - all route files export a function
module.exports = (app, db) => {
const router = require('express').Router();
const dbController = require('../controllers/db')(db, 'tablename');
const io = app.get('io');
// Define routes...
return router;
};
// Async/await with try-catch-finally for database operations
const getData = async (fields = '*', callback = false, table = dbTable) => {
let res = null;
let results = [];
try {
results = await query(`SELECT ${fields} FROM ${table}`);
} catch (err) {
await db.rollback();
res = { statut: false, error: err, results: null };
} finally {
res = { statut: true, error: false, results: results };
}
if (callback && typeof callback == 'function') callback(res);
return res;
};
// Arrow functions for middleware and handlers
const myMiddleware = (req, res, next) => {
// logic
next();
};Always use this structure for database operations:
{
statut: boolean, // NOTE: French spelling - maintain consistency
error: false|Error,
results: array
}200- Success400- Bad request / validation error401- Unauthorized (invalid token)403- Forbidden (no token)409- Conflict (duplicate entry)500- Server error
Write error messages in French to maintain consistency:
res.status(400).send('Veuillez remplir tous les champs.');
res.status(401).send('Token non valide.');
res.status(403).send('Un token est requis pour vous connecter.');Use asterisk blocks for section headers:
/* ******************************************************************* */
/* *********************** SECTION NAME ******************************* */
/* ******************************************************************* */Protected routes always use: authMiddleware -> fieldsMiddleware -> handler
router.post('/endpoint', [authMiddleware, fieldsMiddleware], (req, res) => {
// req.fields contains parsed form data
});Emit events on data mutations for real-time updates:
const sendData = (statut, res, results, error, io = false) => {
if (statut) {
if (io) io.emit('subscribeAnimations'); // Notify subscribers
res.status(200).send({ statut: 'success', results: results });
} else res.status(500).send({ statut: 'failed', results: 'API error' });
};Located in controllers/db.js. All methods return { statut, error, results }:
| Method | Purpose | Signature |
|---|---|---|
get |
SELECT all | get(fields, callback, table) |
post |
INSERT | post(fields, callback, table) |
searchEntry |
SELECT WHERE | searchEntry(value, fields, callback, key, table) |
putEntry |
UPDATE | putEntry(value, fields, callback, key, table) |
deleteEntry |
DELETE | deleteEntry(value, callback, key, table) |
- Create
routes/newentity.jsfollowing the factory pattern - Import in
index.js:const newRouter = require('./routes/newentity'); - Mount route:
.use('/api', newRouter(app, db)) - Add Socket.io event (e.g.,
subscribeNewEntity)
- Create
middleware/name.jsexporting a function(req, res, next) => {} - Import and apply in route definitions
- JWT tokens expire in 30 days
- Bcrypt uses 10 salt rounds for password hashing
- Rate limiting: 5 requests per 60 minutes on
/auth/login - Socket.io auth timeout: 5 seconds
- All
/api/*routes require valid JWT token
From .cursor/rules/snyk_rules.mdc:
- Run Snyk code scan for new code in supported languages
- Fix security issues found by Snyk before committing
- Rescan after fixes to ensure no new issues introduced
- Use
statut(French) notstatusfor consistency - No build process - code runs directly with Node.js
- Always emit Socket.io events on data mutations
- Form data is parsed into
req.fieldsby formidable middleware - MySQL connection has auto-reconnect logic in
index.js