API version control v1 v2 in NodeJs (loosely coupled)

Step 1: Create a Node.js Project

mkdir node-api-version-control
cd node-api-version-control
npm init -y

Step 2: Install Express.js

npm install express

Step 3: Create an Express App (app.js)

const express = require('express');
const app = express();
const port = 3000;

app.use(express.json());

app.get('/api/v1/resource', (req, res) => {
  res.json({ version: 'v1', data: 'Resource data for version 1' });
});

app.get('/api/v2/resource', (req, res) => {
  res.json({ version: 'v2', data: 'Resource data for version 2' });
});

app.listen(port, () => {
  console.log(`Server listening at http://localhost:${port}`);
});

Step 4: Run the Node.js Server

node app.js

Step 5: Test API Endpoints - Open a web browser or use tools like curl or Postman to test the following endpoints: - http://localhost:3000/api/v1/resource - http://localhost:3000/api/v2/resource

Step 6: Separate Route Handlers Create a folder named "routes" and create separate files for each version (v1.js and v2.js).

v1.js:

const express = require('express');
const router = express.Router();

router.get('/resource', (req, res) => {
  res.json({ version: 'v1', data: 'Resource data for version 1' });
});

module.exports = router;

v2.js:

const express = require('express');
const router = express.Router();

router.get('/resource', (req, res) => {
  res.json({ version: 'v2', data: 'Resource data for version 2' });
});

module.exports = router;

Update app.js:

const express = require('express');
const app = express();
const port = 3000;

app.use(express.json());

const v1Routes = require('./routes/v1');
const v2Routes = require('./routes/v2');

app.use('/api/v1', v1Routes);
app.use('/api/v2', v2Routes);

app.listen(port, () => {
  console.log(`Server listening at http://localhost:${port}`);
});

Step 7: Enhance Version Control (Middleware) Create a middleware function to handle versioning.

const express = require('express');
const app = express();
const port = 3000;

app.use(express.json());

const versionMiddleware = (req, res, next) => {
  const apiVersion = req.params.version;

  if (apiVersion === 'v1') {
    req.apiVersion = 'v1';
    next();
  } else if (apiVersion === 'v2') {
    req.apiVersion = 'v2';
    next();
  } else {
    res.status(400).json({ error: 'Invalid API version' });
  }
};

app.use('/api/:version/resource', versionMiddleware, (req, res) => {
  const { apiVersion } = req;
  res.json({ version: apiVersion, data: `Resource data for ${apiVersion}` });
});

app.listen(port, () => {
  console.log(`Server listening at http://localhost:${port}`);
});

Step 8: Test Enhanced Version Control - Update the routes in v1.js and v2.js to use /:version/resource. - Test the following endpoints: - http://localhost:3000/api/v1/resource - http://localhost:3000/api/v2/resource - http://localhost:3000/api/invalid/resource (should return a 400 error)

Step 9: Loose Coupling (Dependency Injection) Use dependency injection to make route handlers independent of the app object.

Update v1.js and v2.js:

const express = require('express');
const router = express.Router();

const resourceHandler = (req, res) => {
  const { apiVersion } = req;
  res.json({ version: apiVersion, data: `Resource data for ${apiVersion}` });
};

router.get('/resource', resourceHandler);

module.exports = { resourceHandler };

Update app.js:

const express = require('express');
const app = express();
const port = 3000;

app.use(express.json());

const versionMiddleware = (req, res, next) => {
  const apiVersion = req.params.version;

  if (apiVersion === 'v1') {
    req.apiVersion = 'v1';
    next();
  } else if (apiVersion === 'v2') {
    req.apiVersion = 'v2';
    next();
  } else {
    res.status(400).json({ error: 'Invalid API version' });
  }
};

const v1Routes = require('./routes/v1');
const v2Routes = require('./routes/v2');

app.use('/api/v1', versionMiddleware, v1Routes.resourceHandler);
app.use('/api/v2', versionMiddleware, v2Routes.resourceHandler);

app.listen(port, () => {
  console.log(`Server listening at http://localhost:${port}`);
});