The Swagger 2.0 specification was officially released today and at StrongLoop we are excited to announce that LoopBack is the first Node.js framework to support Swagger 2.0. Using LoopBack you can now take a Swagger 1.2 or 2.0 specification and automatically scaffold a Node-powered REST API. This should be especially useful for any developer wanting to easily describe their APIs using the leading enterprise standard for API specification and implement them in Node.js. Developers now have the ultimate flexibility in starting from a “bottoms up” approach – building APIs from existing data sources or a “top down” approach – starting with the leading enterprise API specification and scaffolding up a backend of generated models.

A community effort

We were invited by the project lead Tony Tam, to participate in the Swagger 2.0 workgroup a few months ago, which also included other leading API vendors like Apigee, 3Scale, PayPal and Microsoft.  The Swagger 2.0 specification is a great win in the effort to build APIs for the enterprise and to describe them in a uniform way so that they can be utilized by end users and developers. We’d like to congratulate everyone on all the hard work that went into this release!

What is Swagger?

If you are new to Swagger, it defines a standard, language-agnostic interface to REST APIs which allows both humans and computers to discover and understand the capabilities of the service without access to source code, documentation, or through network traffic inspection.

What is LoopBack?

If you are new to LoopBack, it is an open source Node.js API framework from StrongLoop. It is built on top of Express optimized for mobile, web, and other devices. LoopBack makes it really easy and productive for developers to:

  • Define, build and consume APIs
  • Define data models
  • Connect to multiple data sources
  • Write business logic in Node.js
  • Glue on top of your existing services and data
  • Consume services and data using JavaScript, iOS & Android SDKs
  • LoopBack + Swagger = API business

    loopback-swagger-integration

    LoopBack has come with a Swagger based API explorer since day one in order to provide instant visibility for REST APIs exposed by LoopBack models. So far with LoopBack, most developers define models and implement the API logic in Node.js. The JavaScript methods are annotated with remoting metadata so that they can be exposed as REST APIs. LoopBack publishes such definitions as Swagger specs in JSON format. The API explorer creates an API playground based on the specs.

    What about starting with an API design specification? API consumers and providers often want to discuss, understand, and agree on the APIs as a contract first, before building code for either the client or server. To support a API design first approach, we’re excited to announce the availability of the loopback:swagger generator which can generate a fully-functional application that provides the APIs conforming to the Swagger specification.

    In the next few sections of this blog we’ll show just how easy it is to create Node powered REST APIs that conform to the Swagger 2.0 specification using the LoopBack framework.

    Scaffolding a LoopBack application from Swagger specs

    Before we start, please make sure you have StrongLoop tools installed:

    npm install -g strongloop
    

    For more information, see:

    http://docs.strongloop.com/display/LB/Getting+Started+with+LoopBack

    Create a loopback application

    The first step is to create a blank LoopBack application.

    slc loopback
    

    loopback (1)

    Generate APIs from swagger spec

    Now let’s try to generate APIs from Swagger specs.

    cd swagger-demo
    slc loopback:swagger
    

    When prompted, first provide a url to the swagger spec. In this demo, we use:

    https://raw.githubusercontent.com/wordnik/swagger-spec/master/examples/v2.0/json/petstore-simple.json

    loopback-swagger

    The generator loads the spec and discovers models and apis. It then prompts youto select from the list of models to be created.

    loopback-swagger-full

    Check the project

    The models and corresponding JS files are generated into the server/models folder:

    demo-project

    • server/model-config.json: Config for all models
    • server/models:
      • swagger-api.json: model to host all swagger APIs
      • swagger-api.js: JS file containing all api methods
      • error-model.json: errorModel model definition
      • error-model.js: errorModel extension
      • pet.json: pet definition
      • pet.js: pet model extension
      • new-pet.json: newPet model definition
      • new-pet.js: newPet model extension

    Please note pet/newPet/errorModel models are now connected to the database selected.

    Run the application

    To run the application:

    slc run .
    

    Open your browser and points to http://localhost:3000/explorer.

    explorer-api

    As you see, the API endpoints defined by the Swagger spec is now available from LoopBack!

    You’ll also see a list of models generated too. As illustrated below, these models have the full CRUD capabilities and can be attached any of the databases that LoopBack supports.

    explorer-model

    Let’s give it a try:

    api-error

    Hmm, you get an error saying the api is not implemented. That is expected as the generated method is just a skeleton!

    How about adding your implementation?

    The file can be found at swagger-demo/server/models/swagger-api.js.

    module.exports = function(SwaggerApi) {
    
    /**
     * Returns all pets from the system that the user has access to
     * <a class='bp-suggestions-mention' href='https://strongloop.com/members/param/' rel='nofollow'>@param</a> {array} tags tags to filter by 
     * <a class='bp-suggestions-mention' href='https://strongloop.com/members/param/' rel='nofollow'>@param</a> {integer} limit maximum number of results to return
     * <a class='bp-suggestions-mention' href='https://strongloop.com/members/callback/' rel='nofollow'>@callback</a> {Function} callback Callback function
     * <a class='bp-suggestions-mention' href='https://strongloop.com/members/param/' rel='nofollow'>@param</a> {Error|String} err Error object
     * <a class='bp-suggestions-mention' href='https://strongloop.com/members/param/' rel='nofollow'>@param</a> {errorModel} result Result object
     */
    SwaggerApi.findPets = function (tags, limit, callback) {
      // Add your implementation here. Please make sure the callback is invoked
      process.nextTick(function() {
        var err = new Error('Not implemented');
        callback(err);
      });
    
    }
    ...
    SwaggerApi.remoteMethod('findPets',
      { isStatic: true,
      produces: [ 'application/json', 'application/xml', 'text/xml', 'text/html' ],
      accepts: 
       [ { arg: 'tags',
           type: [ 'string' ],
           description: 'tags to filter by',
           required: false,
           http: { source: 'query' } },
         { arg: 'limit',
           type: 'number',
           description: 'maximum number of results to return',
           required: false,
           http: { source: 'query' } } ],
      returns: 
       [ { description: 'unexpected error',
           type: 'errorModel',
           arg: 'data',
           root: true } ],
      http: { verb: 'get', path: '/pets' },
      description: 'Returns all pets from the system that the user has access to' }
    );
    

    Let’s use the Pet model to implement the corresponding methods:

    SwaggerApi.findPets = function(tags, limit, callback) {
      var filter = {limit: limit};
      if (tags &&; tags.length) {
        filter.where = {tag: {inq: tags}};
      }
      SwaggerApi.app.models.pet.find(filter, callback);
    }
    
    SwaggerApi.addPet = function (pet, callback) {
      SwaggerApi.app.models.pet.create(pet, callback);
    
    }
    
    SwaggerApi.findPetById = function (id, callback) {
      SwaggerApi.app.models.pet.findById(id, callback);
    
    }
    
    SwaggerApi.deletePet = function (id, callback) {
      SwaggerApi.app.models.pet.deleteById(id, callback);
    
    }
    

    Now you can restart the server and try again:

  • Try getPets. You’ll see an empty array coming back.
  • Try addPet to post one or more records to create new pets.
  • Try getPets again. You’ll see the newly created pets.
  • Try findPetById. You should be look up pets by id now.
  • Try deletePet. Pets can be deleted by id.
  • You can also use the pet model directly. It will provide you the full CRUD operations.

    Swagger versions

    The LoopBack swagger generator supports both 2.0 and 1.2 versions. Feel free to try it out with the Pet Store v1.2 spec at:

    http://petstore.swagger.wordnik.com/api/api-docs

    Please note in 1.2, the spec URL can be the resource listing or a specific API specification. For resource listing, all API specifications will be automatically fetched and processed.

    Summary

    With the Swagger generator, we’ve now completed a round trip of API creation:

    • Start with a Swagger spec
    • Generate corresponding models and methods for your application
    • Implement the remote methods
    • Play with the live APIs served by LoopBack using the explorer

    What’s next

    • Ready to develop APIs in Node.js and get them connected to your data? Check out the Node.js LoopBack framework>. We’ve made it easy to get started either locally or on your favorite cloud, with a simple npm install.