Files
APAW/.kilo/rules/nodejs.md
¨NW¨ 8fcd8f8a9b feat: add comprehensive NodeJS development skills and rules
Based on Planner and Memory Manager analysis:

New Skills (8):
- nodejs-express-patterns: App structure, routing, middleware
- nodejs-security-owasp: OWASP Top 10 security practices
- nodejs-testing-jest: Unit/integration tests, mocking
- nodejs-auth-jwt: JWT authentication, OAuth, sessions
- nodejs-error-handling: Error classes, middleware, async handlers
- nodejs-middleware-patterns: Auth, validation, rate limiting
- nodejs-db-patterns: SQLite, PostgreSQL, MongoDB patterns
- nodejs-npm-management: package.json, scripts, dependencies

New Rules:
- nodejs.md: Code style, security, best practices

Updated:
- backend-developer.md: Added skills reference table

Milestone: #48 NodeJS Development Coverage
Related: Planner & Memory Manager analysis results
2026-04-05 02:39:06 +01:00

5.5 KiB

NodeJS Development Rules

Essential rules for Node.js backend development.

Code Style

  • Use const and let, never var
  • Use arrow functions for callbacks
  • Use async/await instead of callbacks
  • Use template literals for string interpolation
  • Use object destructuring
  • Use spread operator for objects/arrays
// ✅ Good
const { id, name } = req.body;
const user = { ...req.body, createdAt: new Date() };
const users = await User.findAll();

// ❌ Bad
var id = req.body.id;
const user = Object.assign({}, req.body, { createdAt: new Date() });
User.findAll().then(users => {});

Error Handling

  • Always use try/catch with async/await
  • Use centralized error handling middleware
  • Never catch and swallow errors
  • Use custom AppError classes
  • Log errors with context
// ✅ Good
try {
  const user = await User.findById(id);
  if (!user) throw new NotFoundError('User');
  res.json({ user });
} catch (error) {
  next(error);
}

// ❌ Bad
User.findById(id).then(user => {
  if (!user) return res.status(404).json({ error: 'Not found' });
  res.json({ user });
}).catch(err => {}); // Swallowing error

Async Code

  • Always use async/await
  • Never mix callbacks and promises
  • Use Promise.all for parallel operations
  • Use async middleware wrapper
// ✅ Good
const [users, posts] = await Promise.all([
  User.findAll(),
  Post.findAll()
]);

// ❌ Bad
let users;
User.findAll().then(u => { users = u; });
console.log(users); // undefined

Security

  • Always validate and sanitize input
  • Use parameterized queries
  • Never expose sensitive data
  • Use HTTPS in production
  • Set security headers with helmet
  • Rate limit public endpoints
// ✅ Good
const user = await db.query('SELECT * FROM users WHERE id = ?', [id]);
app.use(helmet());

// ❌ Bad
const user = await db.query(`SELECT * FROM users WHERE id = ${id}`);
// SQL injection vulnerable

Authentication

  • Never store passwords in plain text
  • Use bcrypt for password hashing
  • Use short-lived access tokens
  • Use refresh tokens
  • Use httpOnly cookies
  • Never put secrets in JWT payload
// ✅ Good
const hashedPassword = await bcrypt.hash(password, 12);
const token = jwt.sign({ id: user.id }, process.env.JWT_SECRET, { expiresIn: '1h' });

// ❌ Bad
const hashedPassword = password; // No hash
const token = jwt.sign({ password: user.password }, 'secret'); // Secret in payload

Express Best Practices

  • Use express.Router() for route organization
  • Keep route handlers thin
  • Validate at route level
  • Put error handlers last
  • Use middleware for cross-cutting concerns
// ✅ Good
// routes/users.js
const router = express.Router();
router.get('/', authenticate, validate, controller.list);

// app.js
app.use('/api/users', routes.users);
app.use(errorHandler); // Last middleware

// ❌ Bad
app.get('/api/users', async (req, res) => {
  // All logic in route
});

Database

  • Use connection pooling
  • Close connections gracefully
  • Use transactions for writes
  • Index frequently queried fields
  • Use migrations for schema changes
// ✅ Good
await db.transaction(async (trx) => {
  await trx('users').insert(user);
  await trx('profiles').insert(profile);
});

// ❌ Bad
async function createUser(data) {
  const user = await db('users').insert(data);
  // No transaction, partial data on error
  await Profile.create({ userId: user.id });
}

Logging

  • Use structured logging (pino, winston)
  • Log levels: error, warn, info, debug
  • Include request ID for tracing
  • Log errors with stack traces
  • Don't log sensitive data
// ✅ Good
logger.info({ userId, action: 'login', ip: req.ip });

// ❌ Bad
console.log('User logged in:', user); // Logs entire user including password

Testing

  • Write tests for critical paths
  • Use Jest or Mocha
  • Mock external dependencies
  • Aim for 80%+ coverage
  • Test edge cases
// ✅ Good
describe('UserService', () => {
  it('should create user with hashed password', async () => {
    const user = await service.create({ email, password });
    expect(user.password).not.toBe(password);
  });
});

Environment

  • Use .env for secrets
  • Never commit secrets
  • Use different configs for environments
  • Validate required env vars
// ✅ Good
const config = {
  db: {
    url: process.env.DATABASE_URL
  }
};

if (!config.db.url) {
  throw new Error('DATABASE_URL is required');
}

// ❌ Bad
const config = {
  db: {
    url: 'postgres://user:pass@localhost/db' // Hardcoded
  }
};

Package Management

  • Use exact versions in production
  • Run npm audit regularly
  • Update dependencies regularly
  • Remove unused dependencies
# ✅ Good
npm audit
npx depcheck

# ❌ Bad
# Never running security audit
# Many unused dependencies

Performance

  • Use streaming for large files
  • Cache frequently accessed data
  • Use connection pooling
  • Implement pagination
  • Compress responses
// ✅ Good
app.use(compression());
app.get('/users', paginated, controller.list);

// ❌ Bad
app.get('/users', async (req, res) => {
  const users = await User.findAll(); // All users at once
  res.json(users);
});

Clean Code

  • No magic numbers, use constants
  • Meaningful variable names
  • One function, one responsibility
  • Comments only for "why", not "what"
  • DRY principle
// ✅ Good
const MAX_LOGIN_ATTEMPTS = 5;
const isLocked = user.loginAttempts >= MAX_LOGIN_ATTEMPTS;

// ❌ Bad
if (user.loginAttempts >= 5) { // Magic number
  // ...
}