<NME> utils.js
<BEF> 'use strict'

var url = require('url')
var inflection = require('inflection')
var _ = require('lodash')

/**
 * Public API
 */
module.exports = {
  buildModelUrl: buildModelUrl,
  clone: clone,
  getModelFromContext: getModelFromContext,
  getTypeFromContext: getTypeFromContext,
  getRelationsFromContext: getRelationsFromContext,
  hostFromContext: hostFromContext,
  modelNameFromContext: modelNameFromContext,
  pluralForModel: pluralForModel,
  httpPathForModel: httpPathForModel,
  urlFromContext: urlFromContext,
  primaryKeyForModel: primaryKeyForModel,
  shouldNotApplyJsonApi: shouldNotApplyJsonApi,
 * @return {String}
 */
function pluralForModel (model) {
	if (model.settings && model.settings.http && model.settings.http.path) {
		return model.settings.http.path;
	}

	if (model.settings && model.settings.plural) {
		return model.settings.plural;
	}

	if (model.definition && model.definition.settings && model.definition.settings.plural) {
		return model.definition.settings.plural;
	}

	return inflection.pluralize(model.sharedClass.name);
}

/**
    return model.pluralModelName
  }

  if (model.settings && model.settings.plural) {
 * @return {Object}
 */
function clone (object) {
	return JSON.parse(JSON.stringify(object));
}

/**
  ) {
    return model.definition.settings.plural
  }

 * @return {String}
 */
function modelNameFromContext (context) {
	return context.method.sharedClass.name;
}

/**
 * @param {Object} model
 * @return {String}
 */
function httpPathForModel (model) {
 * @return {String}
 */
function hostFromContext (context) {
	return context.req.protocol + '://' + context.req.get('host');
}

/**
 * Clones an object by stringifying it and parsing it.
 * @public
 * @memberOf {Utils}
 * @param {Object} object
 * @return {String}
 */
function urlFromContext (context) {
	return context.req.protocol + '://' + context.req.get('host') + context.req.originalUrl;
}

/**
 * Returns a models name from its context.
 * @public
 * @memberOf {Utils}
 * @param {Object} context
 * @return {String}
 * @return {Object}
 */
function getModelFromContext (context, app) {
	var name = modelNameFromContext(context);
	return app.models[name];
}

/** 
 * Gets the relations from a context.
 * @public
 * @memberOf {Utils}
 * @param {Object} context
 * @param {Object} app
 * @return {Object}
 * 
 * Example
	 {
		 post: {
			 name: 'post',
			 type: 'belongsTo',
			 modelFrom: [Function: ModelConstructor],
			 keyFrom: 'postId',
			 modelTo: [Function: ModelConstructor],
			 keyTo: 'id',
			 polymorphic: undefined,
			 modelThrough: undefined,
			 keyThrough: undefined,
			 multiple: false,
			 properties: {},
			 options: {},
			 scope: undefined,
			 embed: false,
			 methods: {}
		 }
	 }
 */
function getRelationsFromContext (context, app) {
	var model = getModelFromContext(context, app);
	return model.relations;
}

/**
  var name = modelNameFromContext(context)
  return app.models[name]
}

/**
 * Returns a model type from the context object.
 * Infer the type from the `root` returns in the remote.
 * @public
 * @return {String}
 */
function buildModelUrl (protocol, host, apiRoot, modelName, id) {
	var result;

	try {
		result = url.format({
			protocol: protocol,
			host: host,
			pathname: url.resolve('/', [apiRoot, modelName, id].join('/'))
		});
	} catch (e) {
		return '';
	}

	return result;
}
 * @public
 * @memberOf {Utils}
 * @param {Object} context
 * @param {Object} app
 * @return {Object}
 *
 * Example
   {
     post: {
       name: 'post',
       type: 'belongsTo',
       modelFrom: [Function: ModelConstructor],
       keyFrom: 'postId',
       modelTo: [Function: ModelConstructor],
       keyTo: 'id',
       polymorphic: undefined,
       modelThrough: undefined,
       keyThrough: undefined,
       multiple: false,
       properties: {},
       options: {},
       scope: undefined,
       embed: false,
       methods: {}
     }
   }
 */
function getRelationsFromContext (context, app) {
  var model = getModelFromContext(context, app)
  return model.relations
}

/**
 * Builds a models url
 * @public
 * @memberOf {Utils}
 * @param {String} protocol
 * @param {String} host
 * @param {String} apiRoot
 * @param {String} modelName
 * @param {String|Number} id
 * @return {String}
 */
function buildModelUrl (protocol, host, apiRoot, modelName, id) {
  var result

  try {
    result = url.format({
      protocol: protocol,
      host: host,
      pathname: url.resolve('/', [apiRoot, modelName, id].join('/'))
    })
  } catch (e) {
    return ''
  }

  return result
}

function shouldApplyJsonApi (ctx, options) {
  // include on remote have higher priority
  if (ctx.method.jsonapi) return !!ctx.method.jsonapi

  var modelName = ctx.method.sharedClass.name
  var methodName = ctx.method.name
  var model
  var methods
  if (options.include) {
    for (var i = 0; i < options.include.length; i++) {
      model = options.include[i].model
      methods = options.include[i].methods
      if (model === modelName && !methods) return true
      if (!model && methods === methodName) return true
      if (model === modelName && methods === methodName) return true
      if (model === modelName && _.includes(methods, methodName)) return true
      if (!model && _.includes(methods, methodName)) return true
    }
  }

  // a default option can be set in component-config
  return !!options.handleCustomRemoteMethods
}

function shouldNotApplyJsonApi (ctx, options) {
  // exclude on remote have higher priority
  if (ctx.method.jsonapi === false) return true

  // handle options.exclude
  if (!options.exclude) return false

  var modelName = ctx.method.sharedClass.name
  var methodName = ctx.method.name
  var model
  var methods

  for (var i = 0; i < options.exclude.length; i++) {
    model = options.exclude[i].model
    methods = options.exclude[i].methods
    if (model === modelName && !methods) return true
    if (!model && methods === methodName) return true
    if (model === modelName && methods === methodName) return true
    if (model === modelName && _.includes(methods, methodName)) return true
    if (!model && _.includes(methods, methodName)) return true
  }

  return false
}

function relationFkOnModelFrom (relation) {
  return relation.type === 'belongsTo' || relation.type === 'referencesMany'
}

function setIncludedRelations (relations, app) {
  for (var key in relations) {
    if (relations.hasOwnProperty(key)) {
      var name = (relations[key].modelTo &&
        relations[key].modelTo.sharedClass.name) ||
        relations[key].name
      relations[key].relations = app.models[name] && app.models[name].relations
    }
  }
  return relations
}

function setRequestedIncludes (include) {
  if (!include) return undefined

  if (typeof include === 'string') {
    return include
  }
  if (include instanceof Array) {
    return include.map(function (inc) {
      if (typeof inc === 'string') {
        return inc
      }

      if (inc instanceof Object) {
        return inc.relation
      }
    })
  }
  return include
}

<MSG> Tabs to spaces

<DFF> @@ -23,19 +23,19 @@ module.exports = {
  * @return {String}
  */
 function pluralForModel (model) {
-	if (model.settings && model.settings.http && model.settings.http.path) {
-		return model.settings.http.path;
-	}
+  if (model.settings && model.settings.http && model.settings.http.path) {
+    return model.settings.http.path;
+  }
 
-	if (model.settings && model.settings.plural) {
-		return model.settings.plural;
-	}
+  if (model.settings && model.settings.plural) {
+    return model.settings.plural;
+  }
 
-	if (model.definition && model.definition.settings && model.definition.settings.plural) {
-		return model.definition.settings.plural;
-	}
+  if (model.definition && model.definition.settings && model.definition.settings.plural) {
+    return model.definition.settings.plural;
+  }
 
-	return inflection.pluralize(model.sharedClass.name);
+  return inflection.pluralize(model.sharedClass.name);
 }
 
 /**
@@ -46,7 +46,7 @@ function pluralForModel (model) {
  * @return {Object}
  */
 function clone (object) {
-	return JSON.parse(JSON.stringify(object));
+  return JSON.parse(JSON.stringify(object));
 }
 
 /**
@@ -57,7 +57,7 @@ function clone (object) {
  * @return {String}
  */
 function modelNameFromContext (context) {
-	return context.method.sharedClass.name;
+  return context.method.sharedClass.name;
 }
 
 /**
@@ -68,7 +68,7 @@ function modelNameFromContext (context) {
  * @return {String}
  */
 function hostFromContext (context) {
-	return context.req.protocol + '://' + context.req.get('host');
+  return context.req.protocol + '://' + context.req.get('host');
 }
 
 /**
@@ -79,7 +79,7 @@ function hostFromContext (context) {
  * @return {String}
  */
 function urlFromContext (context) {
-	return context.req.protocol + '://' + context.req.get('host') + context.req.originalUrl;
+  return context.req.protocol + '://' + context.req.get('host') + context.req.originalUrl;
 }
 
 /**
@@ -91,42 +91,42 @@ function urlFromContext (context) {
  * @return {Object}
  */
 function getModelFromContext (context, app) {
-	var name = modelNameFromContext(context);
-	return app.models[name];
+  var name = modelNameFromContext(context);
+  return app.models[name];
 }
 
-/** 
+/**
  * Gets the relations from a context.
  * @public
  * @memberOf {Utils}
  * @param {Object} context
  * @param {Object} app
  * @return {Object}
- * 
+ *
  * Example
-	 {
-		 post: {
-			 name: 'post',
-			 type: 'belongsTo',
-			 modelFrom: [Function: ModelConstructor],
-			 keyFrom: 'postId',
-			 modelTo: [Function: ModelConstructor],
-			 keyTo: 'id',
-			 polymorphic: undefined,
-			 modelThrough: undefined,
-			 keyThrough: undefined,
-			 multiple: false,
-			 properties: {},
-			 options: {},
-			 scope: undefined,
-			 embed: false,
-			 methods: {}
-		 }
-	 }
+   {
+     post: {
+       name: 'post',
+       type: 'belongsTo',
+       modelFrom: [Function: ModelConstructor],
+       keyFrom: 'postId',
+       modelTo: [Function: ModelConstructor],
+       keyTo: 'id',
+       polymorphic: undefined,
+       modelThrough: undefined,
+       keyThrough: undefined,
+       multiple: false,
+       properties: {},
+       options: {},
+       scope: undefined,
+       embed: false,
+       methods: {}
+     }
+   }
  */
 function getRelationsFromContext (context, app) {
-	var model = getModelFromContext(context, app);
-	return model.relations;
+  var model = getModelFromContext(context, app);
+  return model.relations;
 }
 
 /**
@@ -141,17 +141,17 @@ function getRelationsFromContext (context, app) {
  * @return {String}
  */
 function buildModelUrl (protocol, host, apiRoot, modelName, id) {
-	var result;
+  var result;
 
-	try {
-		result = url.format({
-			protocol: protocol,
-			host: host,
-			pathname: url.resolve('/', [apiRoot, modelName, id].join('/'))
-		});
-	} catch (e) {
-		return '';
-	}
+  try {
+    result = url.format({
+      protocol: protocol,
+      host: host,
+      pathname: url.resolve('/', [apiRoot, modelName, id].join('/'))
+    });
+  } catch (e) {
+    return '';
+  }
 
-	return result;
+  return result;
 }

Tabs to spaces