text: // # Tag API
  // RESTful API for the Tag resource
  var Promise      = require('bluebird'),
      _            = require('lodash'),
      dataProvider = require('../models'),
      errors       = require('../errors'),
      utils        = require('./utils'),
      pipeline     = require('../utils/pipeline'),
      i18n         = require('../i18n'),
  
      docName      = 'tags',
      allowedIncludes = ['count.posts'],
      tags;
  
  /**
   * ### Tags API Methods
   *
   * **See:** [API Methods](index.js.html#api%20methods)
   */
  tags = {
      /**
       * ## Browse
       * @param {{context}} options
       * @returns {Promise<Tags>} Tags Collection
       */
      browse: function browse(options) {
          var tasks;
  
          /**
           * ### Model Query
           * Make the call to the Model layer
           * @param {Object} options
           * @returns {Object} options
           */
          function doQuery(options) {
              return dataProvider.Tag.findPage(options);
          }
  
          // Push all of our tasks into a `tasks` array in the correct order
          tasks = [
              utils.validate(docName, {opts: utils.browseDefaultOptions}),
              utils.handlePublicPermissions(docName, 'browse'),
              utils.convertOptions(allowedIncludes),
              doQuery
          ];
  
          // Pipeline calls each task passing the result of one to be the arguments for the next
          return pipeline(tasks, options);
      },
  
      /**
       * ## Read
       * @param {{id}} options
       * @return {Promise<Tag>} Tag
       */
      read: function read(options) {
          var attrs = ['id', 'slug', 'visibility'],
              tasks;
  
          /**
           * ### Model Query
           * Make the call to the Model layer
           * @param {Object} options
           * @returns {Object} options
           */
          function doQuery(options) {
              return dataProvider.Tag.findOne(options.data, _.omit(options, ['data']));
          }
  
          // Push all of our tasks into a `tasks` array in the correct order
          tasks = [
              utils.validate(docName, {attrs: attrs}),
              utils.handlePublicPermissions(docName, 'read'),
              utils.convertOptions(allowedIncludes),
              doQuery
          ];
  
          // Pipeline calls each task passing the result of one to be the arguments for the next
          return pipeline(tasks, options).then(function formatResponse(result) {
              if (result) {
                  return {tags: [result.toJSON(options)]};
              }
  
              return Promise.reject(new errors.NotFoundError(i18n.t('errors.api.tags.tagNotFound')));
          });
      },
  
      /**
       * ## Add
       * @param {Tag} object the tag to create
       * @returns {Promise(Tag)} Newly created Tag
       */
      add: function add(object, options) {
          var tasks;
  
          /**
           * ### Model Query
           * Make the call to the Model layer
           * @param {Object} options
           * @returns {Object} options
           */
          function doQuery(options) {
              return dataProvider.Tag.add(options.data.tags[0], _.omit(options, ['data']));
          }
  
          // Push all of our tasks into a `tasks` array in the correct order
          tasks = [
              utils.validate(docName),
              utils.handlePermissions(docName, 'add'),
              utils.convertOptions(allowedIncludes),
              doQuery
          ];
  
          // Pipeline calls each task passing the result of one to be the arguments for the next
          return pipeline(tasks, object, options).then(function formatResponse(result) {
              var tag = result.toJSON(options);
  
              return {tags: [tag]};
          });
      },
  
      /**
       * ## Edit
       *
       * @public
       * @param {Tag} object Tag or specific properties to update
       * @param {{id, context, include}} options
       * @return {Promise<Tag>} Edited Tag
       */
      edit: function edit(object, options) {
          var tasks;
  
          /**
           * Make the call to the Model layer
           * @param {Object} options
           * @returns {Object} options
           */
          function doQuery(options) {
              return dataProvider.Tag.edit(options.data.tags[0], _.omit(options, ['data']));
          }
  
          // Push all of our tasks into a `tasks` array in the correct order
          tasks = [
              utils.validate(docName, {opts: utils.idDefaultOptions}),
              utils.handlePermissions(docName, 'edit'),
              utils.convertOptions(allowedIncludes),
              doQuery
          ];
  
          // Pipeline calls each task passing the result of one to be the arguments for the next
          return pipeline(tasks, object, options).then(function formatResponse(result) {
              if (result) {
                  var tag = result.toJSON(options);
  
                  return {tags: [tag]};
              }
  
              return Promise.reject(new errors.NotFoundError(i18n.t('errors.api.tags.tagNotFound')));
          });
      },
  
      /**
       * ## Destroy
       *
       * @public
       * @param {{id, context}} options
       * @return {Promise}
       */
      destroy: function destroy(options) {
          var tasks;
  
          /**
           * ### Delete Tag
           * Make the call to the Model layer
           * @param {Object} options
           */
          function deleteTag(options) {
              return dataProvider.Tag.destroy(options).return(null);
          }
  
          // Push all of our tasks into a `tasks` array in the correct order
          tasks = [
              utils.validate(docName, {opts: utils.idDefaultOptions}),
              utils.handlePermissions(docName, 'destroy'),
              utils.convertOptions(allowedIncludes),
              deleteTag
          ];
  
          // Pipeline calls each task passing the result of one to be the arguments for the next
          return pipeline(tasks, options);
      }
  };
  
  module.exports = tags;
  