Nourishing Pear Medley

    hapi-holiday

    0.4.6 • Public • Published

    hapi-holiday

    Circle CI dependencies

    Create REST API with hapi

    NPM

    Usage

    $ npm install hapi-holiday --save
    

    Example usage

    Holiday.define(schemeName, scheme);

    Define a scheme for the API routes.

    • schemeName string (required)
    • scheme object (required)
      • scheme.index function(Model, request, done) {} (required)
      • scheme.show function(Model, request, done) {} (required)
      • scheme.save function(Model, request, done) {} (required)
      • scheme.update function(Model, request, done) {} (required)
      • scheme.destroy function(Model, request, done) {} (required)
    Example scheme using sequelize
    Holiday.define('sequelize', {
     
      // GET all records
      index: (Model, request, done) => {
        Model.findAll({
          offset: request.query.offset,
          limit: request.query.limit,
        })
        .then((records) => {
          done(null, records);
        })
        .catch((err) => {
          done(err, null);
        });
      },
     
      // GET one record
      show: (Model, request, done) => {
        Model.findById(request.params.id)
        .then((records) => {
          done(null, records);
        })
        .catch((err) => {
          done(err, null);
        });
      },
     
      // POST a new record
      save: (Model, request, done) => {
        Model.create(request.payload).then((result) => {
          done(null, result);
        })
        .catch((err) => {
          done(err, null);
        });
      },
     
      // PUT an updated record
      update: (Model, request, done) => {
        Model.update(request.payload, {
          where: {
            id: request.params.id,
          },
        })
        .then((result) => {
          done(null, result);
        })
        .catch((err) => {
          done(err, null);
        });
      },
     
      // DELETE a record
      destroy: (Model, request, done) => {
        Model.destroy({
          where: {
            id: request.params.id,
          },
        })
        .then((affected) => {
          done(null, affected);
        })
        .catch((err) => {
          done(err, null);
        });
      },
    });

    Holiday.configure(config);

    Optional. Overrides default configurations for hapi routes.

    // Set default hapi route configs(optional)
    Holiday.configure({
      tags: ['api'],
      auth: ['jwt'],
      ...etc.
    });

    Create routes

    new Holiday(schemeName, routeName, Model);

    Creates a new instance of routes.

    • schemeName string (required) - name of scheme defined
    • routeName string (required) - name of routes (i.e. /routeName/{id})
    • Model Any (required) - Any kind of model to use
    An example for posts model
    const PostApi = new Holiday('sequelize', 'posts', Models.Posts);

    Validation

    Api.validate.index(validationObj)

    Api.validate.show(validationObj)

    Api.validate.save(validationObj)

    Api.validate.update(validationObj)

    Api.validate.destroy(validationObj)

    Set custom validations for specific route type.

    • validationObj Object (required)
    method validates on
    Api.validate.index() request.query
    Api.validate.show() request.query
    Api.validate.save() request.payload
    Api.validate.update() request.payload
    Api.validate.destroy() request.query
    // Example validation to use on 'save'
    PostApi.validate.save({
      title: Joi.string().required(),
      content: Joi.string().required(),
    });
     
    // Example validation to use on 'update'
    PostApi.validate.update({
      title: Joi.string(),
      content: Joi.string(),
    });

    See hapi's validation tutorial for more information.

    Mount routes on hapi

    Api.all();

    Get all routes

    Api.index(config, schemeOverride, callback);

    Get route for index

    • config object (optional)
    • schemeOverride function (optional) - overrides scheme
      • function(Model, request, done)
    • callback function (optional)
      • function(err, result, reply)
        • err - error from model
        • result - result from Model
        • reply - reply object of hapi

    Api.show(config, schemeOverride, callback);

    Get route for show

    • config object (optional)
    • schemeOverride function (optional) - overrides scheme
      • function(Model, request, done)
    • callback function (optional)
      • function(err, result, reply)
        • err - error from model
        • result - result from Model
        • reply - reply object of hapi

    Api.save(config, schemeOverride, callback);

    Get route for save

    • config object (optional)
    • schemeOverride function (optional) - overrides scheme
      • function(Model, request, done)
    • callback function (optional)
      • function(err, result, reply)
        • err - error from model
        • result - result from Model
        • reply - reply object of hapi

    Api.update(config, schemeOverride, callback);

    Get route for update

    • config object (optional)
    • schemeOverride function (optional) - overrides scheme
      • function(Model, request, done)
    • callback function (optional)
      • function(err, result, reply)
        • err - error from model
        • result - result from Model
        • reply - reply object of hapi

    Api.destroy(config, schemeOverride, callback);

    Get route for destroy

    • config object (optional)
    • schemeOverride function (optional) - overrides scheme
      • function(Model, request, done)
    • callback function (optional)
      • function(err, result, reply)
        • err - error from model
        • result - result from Model
        • reply - reply object of hapi
    // mount routes
    server.route(PostApi.all());
     
    // same as...
    server.route([
      PostApi.index(),
      PostApi.show(),
      PostApi.save(),
      PostApi.update(),
      PostApi.destroy(),
    ]);
     

    Example above creates:

    • GET /posts
    • GET /posts/{id}
    • POST /posts
    • PUT /posts/{id}
    • DELETE /posts/{id}

    Customizing specific routes

    server.route([
      PostApi.index({
        /* can override any configuration here */
        tags: ['api', 'get'],
        auth: ['jwt'],
        // ...
      }, (Model, request, done) => {
        /* can override scheme for this route only */
        // Model = Model given as third param of 'new Holiday()'
        // request = request object of hapi
        // done = callback function to execute when done
      }, (err, result, reply) => {
        /* can customize replies and status codes here */
        // err = error of model
        // result = result of model
        // reply = reply object of hapi
      }),
      PostApi.show({
        /* can override any configuration here */
        tags: ['api', 'post'],
        auth: ['jwt'],
        // ...
      }, (Model, request, done) => {
        /* can override scheme for this route only */
        // Model = Model given as third param of 'new Holiday()'
        // request = request object of hapi
        // done = callback function to execute when done
      }, (err, result, reply) => {
        /* can customize replies and status codes here */
        // err = error of model
        // result = result of model
        // reply = reply object of hapi
      }),
     
      // ... and so on
    ]);

    Adding a route for 1:1 or 1:n models

    Api.has(resourceName, scheme);

    Creates a new route under GET /modelName/{id}/resourceName

    Cannot use index, show, save, update, destroy for resourceName

    • resourceName string (required) - name for the association
    • scheme function (required)
      • function(Model, request, done) {}
        • Model - error from model
        • request - request object of hapi
        • done - a function to execute when done.
          • done(err, result)
            • err - Error message or null
            • result - result of model
    // This adds GET /posts/{id}/author
    PostApi.has('author', (Models, request, done) => {
      Model.find({
        where: {id: request.params.id},
        include: ['Author']
      })
      .then((records) => {
        done(null, records);
      })
      .catch((err) => {
        done(err, null);
      });
    });

    Api.validate.resource[resourceName](validationObj);

    Set validations for association routes.

    Validation set with this method validates on request.query

    // NOTE: always validate after executing Api.has()
    PostApi.validate.resource.author({
      name: Joi.string(),
      // ...
    });

    Api.resource[resourceName](config, schemeOverride, callback)

    Get route for association

    • config object (optional)
    • schemeOverride function (optional) - overrides scheme
      • function(Model, request, done)
    • callback function (optional)
      • function(err, result, reply)
        • err - error from model
        • result - result from Model
        • reply - reply object of hapi
    // mount association route
    server.route(PostApi.resource.author());
     
    // all routes including resource gets mounted by using Api.all()
    server.route(PostApi.all());

    More examples...

    var Hapi = require('hapi');
    var Holiday = require('hapi-holiday');
    var Joi = require('joi');
     
    var server = new Hapi.Server();
    server.connection({ port: 3000 });
     
    Holiday.define('testScheme', {
      index: function(Model, request, done) {
        done(null, {test: 'index'});
      },
      show: function(Model, request, done) {
        done(null, {test: 'show', id: request.params.id});
      },
      save: function(Model, request, done) {
        done(null, {test: 'save'});
      },
      update: function (Model, request, done) {
        done(null, {test: 'update', id: request.params.id});
      },
      destroy: function(Model, request, done) {
        done(null, {test: 'destroy', id: request.params.id});
      },
    });
     
    var Api = new Holiday('testScheme', 'test', {a: 'model'});
     
    Api.has('photo', function(Model, request, done) {
      done(null, {
        a: 'photo',
        name: request.query.name,
        someId: request.query.someId,
      });
    });
     
    Api.validate.resource.photo({
      name: Joi.string(),
      someId: Joi.number(),
    });
     
    server.route(Api.all());
     
    server.start(function () {
      console.log('Server running at:', server.info.uri);
    });
     
    // GET http://localhost:3000/test
    // will return...
    // {
    //   "test": "index"
    // }
    // with a status code 200 OK
     
    // GET http://localhost:3000/test/11
    // will return...
    // {
    //   "test": "show",
    //   "id": 11
    // }
    // with a status code 200 OK
     
    // POST http://localhost:3000/test
    // will return...
    // {
    //   "test": "save"
    // }
    // with a status code 201 Created
     
    // PUT http://localhost:3000/test/22
    // will return...
    // {
    //   "test": "update",
    //   "id": 22
    // }
    // with a status code 200 OK
     
    // DELETE http://localhost:3000/test/33
    // will return nothing with a status code 204 No Content
     
    // GET http://localhost:3000/test/1/photo?name=nano&someId=100
    // will return...
    // {
    //   "a": "photo",
    //   "name": "nano",
    //   "someId": 100
    // }
    // with a status code 200 OK
     
    // GET http://localhost:3000/test/1/photo?name=nano&someId=hello
    // will return...
    // {
    //   "statusCode": 400,
    //   "error": "Bad Request",
    //   "message": "child \"someId\" fails because [\"someId\" must be a number]",
    //   "validation": {
    //     "source": "query",
    //     "keys": [
    //       "someId"
    //     ]
    //   }
    // }
    // with a status code 400 Bad Request

    Dependencies

    dependencies

    devDependencies

    License

    MIT

    Install

    npm i hapi-holiday

    DownloadsWeekly Downloads

    49

    Version

    0.4.6

    License

    MIT

    Last publish

    Collaborators

    • nanopx