API versioning with adonis


#1

Hi guys, does anyone have a good advice for API versioning with adonis?

So, we have an iOS app that is consuming REST API made with adonis. We are constantly updating codebase of api but application need to work even if user didn’t updated it.

Idea for now is to send x-api-version from inside ios app and add a bunch of if statements to our controllers…

Anyone knows a nice pattern to do this? Any suggestion is welcomed :smiley:

Thank you!


#2

Hello @hlozancic

I will structure it something like this.

  1. Move all of my code inside Service objects. They have version specific and shared code both.
  2. Use api/v{x} prefix in the routes to tell, which version of API it is.

So let’s say, we have a User, which has different API response for v1 and different response for v2.

Folder structure

└── app
	└── Services
		└── User
		    ├── index.js
		    ├── Version1.js
		    └── Version2.js
  1. I will keep all shared code inside index.js.
  2. Code related to v1 inside Version1.js
  3. Code related for v2 inside Version2.js.

Keeping code DRY

To keep my life simple, I will write couple of static methods inside index.js, which gives me instances of Version1.js and Version2.js.

class User {
  static v1 () {
    return new (use('App/Services/User/Version1'))()
  }

  static v2 () {
    return new (use('App/Services/User/Version2'))()
  }
}

Now Version1.js and respective classes can extend the Base class for shared functionality.

const UserBase = use('App/Services/User')

class Version1 extends UserBase {
  getUsers () {
  }
}

module.exports = Version1

Finally use it as following inside controllers

const User = use('App/Services/User')

class UserController {
  async index ({ req, res }) {
  	const isV1 = req.url.startsWith('/api/v1')
  	const user = isV1 ? User.v1() : User.v2()

  	const all = await user.getAll()
  	return all
  }
}

#3

Thank you very much for your structure. Will think about it!

I’ll post my final solution here when I figure it out :slight_smile: