Skip to content
This repository has been archived by the owner on Sep 16, 2024. It is now read-only.

Commit

Permalink
feat: api versioning (#96)
Browse files Browse the repository at this point in the history
* feat: API versioning

* feat: Add versioning logic to root level

* Add type; fix todo

* Disable token refresh on dev

* Make the api versioning backward compatible; keep v1 route active
  • Loading branch information
hvinder authored Jun 20, 2023
1 parent b7f65a0 commit 7b4b2dc
Show file tree
Hide file tree
Showing 16 changed files with 96 additions and 37 deletions.
33 changes: 33 additions & 0 deletions packages/backend/helpers/versionMiddleware.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { Request, Response, NextFunction } from 'express';

type API_VERSIONS = 'v1' | 'v2' | 'latest';

const DEFAULT_API_VERSION: API_VERSIONS = 'v1';

declare global {
namespace Express {
interface Request {
version: API_VERSIONS;
}
}
}

const versionMiddleware = () => async (req: Request, _res: Response, next: () => any) => {
const version = (req.headers['x-api-version'] as API_VERSIONS) || DEFAULT_API_VERSION;
req.version = version;
next();
};

type VersionMap = {
[k in API_VERSIONS]?: any;
};

export const manageRouterVersioning = (versionMap: VersionMap) => {
return (req: Request, res: Response, next: NextFunction) => {
const { version } = req;
const fn = versionMap[version] || versionMap[DEFAULT_API_VERSION]; // call the v1 function as default
fn.call(this, req, res, next);
};
};

export default versionMiddleware;
38 changes: 28 additions & 10 deletions packages/backend/index.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,12 @@
import express, { Express } from 'express';
import express, { Express, Request, Response } from 'express';
// Note: Sentry should be initialized as early in your app as possible.
import * as Sentry from '@sentry/node';
import config from './config';
import indexRouter, { crmRouter } from './routes/index';
import revertAuthMiddleware from './helpers/authMiddleware';
import indexRouter from './routes/index';
import cors from 'cors';
import cron from 'node-cron';
import AuthService from './services/auth';
import { connectionRouter } from './routes/connection';
import metadataRouter from './routes/metadata';
import versionMiddleware, { manageRouterVersioning } from './helpers/versionMiddleware';

const rateLimit = require('express-rate-limit');
const limiter = rateLimit({
Expand Down Expand Up @@ -38,6 +36,7 @@ Sentry.init({
// of transactions for performance monitoring.
// We recommend adjusting this value in production
tracesSampleRate: 0.1,
enabled: process.env.NODE_ENV !== 'development',
});

// RequestHandler creates a separate execution context, so that all
Expand All @@ -50,10 +49,27 @@ app.use(express.json());
app.use(express.urlencoded({ extended: true }));
app.use(cors());
app.use(limiter);
app.use('/', indexRouter);
app.use('/v1/crm', cors(), revertAuthMiddleware(), crmRouter);
app.use('/v1/connection', cors(), revertAuthMiddleware(), connectionRouter);
app.use('/v1/metadata', cors(), metadataRouter);
app.use(versionMiddleware());

// TODO: Just to test versions. Remove later
const testv2Router = (_req: Request, res: Response) => {
res.send({ data: 'v2 hit' });
};

app.use(
'/',
manageRouterVersioning({
v1: indexRouter,
v2: testv2Router,
})
);
app.use(
'/v1',
manageRouterVersioning({
v1: indexRouter,
v2: testv2Router,
})
);

// The error handler must be before any other error middleware and after all controllers
app.use(Sentry.Handlers.errorHandler());
Expand All @@ -63,6 +79,8 @@ app.listen(config.PORT, () => {
// Refresh tokens on a schedule.
// TODO: do this optimistically.
cron.schedule(`*/2 * * * *`, async () => {
await AuthService.refreshOAuthTokensForThirdParty();
if (process.env.NODE_ENV !== 'development') {
await AuthService.refreshOAuthTokensForThirdParty();
}
});
}).setTimeout(600000);
12 changes: 10 additions & 2 deletions packages/backend/routes/index.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
import prisma from '../prisma/client';
import axios from 'axios';
import express from 'express';
import crmRouter from './crm';
import cors from 'cors';

import crmRouter from './v1/crm';
import config from '../config';
import revertAuthMiddleware from '../helpers/authMiddleware';
import connectionRouter from './v1/connection';
import metadataRouter from './v1/metadata';

const router = express.Router();

Expand Down Expand Up @@ -52,5 +57,8 @@ router.post('/slack-alert', async (req, res) => {
}
});

router.use('/crm', cors(), revertAuthMiddleware(), crmRouter);
router.use('/connection', cors(), revertAuthMiddleware(), connectionRouter);
router.use('/metadata', cors(), metadataRouter);

export default router;
export { crmRouter };
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import express from 'express';

import tenantMiddleware from '../../helpers/tenantIdMiddleware';
import ConnectionService from '../../services/connection';
import tenantMiddleware from '../../../helpers/tenantIdMiddleware';
import ConnectionService from '../../../services/connection';

const connectionRouter = express.Router({ mergeParams: true });

Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import axios from 'axios';
import express from 'express';
import config from '../../config';
import config from '../../../config';
import qs from 'qs';
import AuthService from '../../services/auth';
import prisma, { Prisma } from '../../prisma/client';
import ConnectionService from '../../services/connection';
import AuthService from '../../../services/auth';
import prisma, { Prisma } from '../../../prisma/client';
import ConnectionService from '../../../services/connection';

const authRouter = express.Router({ mergeParams: true });

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import express from 'express';

import tenantMiddleware from '../../helpers/tenantIdMiddleware';
import CompanyService from '../../services/company';
import tenantMiddleware from '../../../helpers/tenantIdMiddleware';
import CompanyService from '../../../services/company';

const companyRouter = express.Router({ mergeParams: true });

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import express from 'express';

import tenantMiddleware from '../../helpers/tenantIdMiddleware';
import ContactService from '../../services/contact';
import tenantMiddleware from '../../../helpers/tenantIdMiddleware';
import ContactService from '../../../services/contact';

const contactRouter = express.Router({ mergeParams: true });

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import express from 'express';

import tenantMiddleware from '../../helpers/tenantIdMiddleware';
import DealService from '../../services/deal';
import tenantMiddleware from '../../../helpers/tenantIdMiddleware';
import DealService from '../../../services/deal';

const dealRouter = express.Router({ mergeParams: true });

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import express from 'express';
import tenantMiddleware from '../../helpers/tenantIdMiddleware';
import EventService from '../../services/event';
import tenantMiddleware from '../../../helpers/tenantIdMiddleware';
import EventService from '../../../services/event';

const eventRouter = express.Router({ mergeParams: true });

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import express from 'express';

import tenantMiddleware from '../../helpers/tenantIdMiddleware';
import LeadService from '../../services/lead';
import tenantMiddleware from '../../../helpers/tenantIdMiddleware';
import LeadService from '../../../services/lead';

const leadRouter = express.Router({ mergeParams: true });

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import express from 'express';

import tenantMiddleware from '../../helpers/tenantIdMiddleware';
import NoteService from '../../services/note';
import tenantMiddleware from '../../../helpers/tenantIdMiddleware';
import NoteService from '../../../services/note';

const noteRouter = express.Router({ mergeParams: true });

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import express from 'express';
import tenantMiddleware from '../../helpers/tenantIdMiddleware';
import ProxyService from '../../services/proxy';
import tenantMiddleware from '../../../helpers/tenantIdMiddleware';
import ProxyService from '../../../services/proxy';

const proxyRouter = express.Router({ mergeParams: true });

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import express from 'express';

import tenantMiddleware from '../../helpers/tenantIdMiddleware';
import TaskService from '../../services/task';
import tenantMiddleware from '../../../helpers/tenantIdMiddleware';
import TaskService from '../../../services/task';

const taskRouter = express.Router({ mergeParams: true });

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import express from 'express';

import tenantMiddleware from '../../helpers/tenantIdMiddleware';
import UserService from '../../services/user';
import tenantMiddleware from '../../../helpers/tenantIdMiddleware';
import UserService from '../../../services/user';

const userRouter = express.Router({ mergeParams: true });

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import express from 'express';
import prisma from '../prisma/client';
import prisma from '../../prisma/client';

const metadataRouter = express.Router();

Expand Down

2 comments on commit 7b4b2dc

@vercel
Copy link

@vercel vercel bot commented on 7b4b2dc Jun 20, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

revert-react – ./packages/react

revert-react.vercel.app
revert-react-git-main-revertdev.vercel.app
revert-react-revertdev.vercel.app

@vercel
Copy link

@vercel vercel bot commented on 7b4b2dc Jun 20, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.