all files / eslint-plugin-angular/rules/ no-services.js

100% Statements 40/40
96.55% Branches 28/29
100% Functions 7/7
100% Lines 40/40
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96                              119× 119× 119× 119×   238×     119×     119×     119× 75×     119× 36×     119× 36× 36× 36×   36× 108× 108×       36×     111× 36×   75×     119×     122×   122× 111× 54× 54× 45×         111× 57× 114× 45×                            
/**
 * disallow DI of specified services
 *
 * Some services should be used only in a specific AngularJS service (Ajax-based service for example), in order to follow the separation of concerns paradigm.
 * The second parameter specifies the services.
 * The third parameter can be a list of angular objects (controller, factory, etc.).
 * Or second parameter can be an object, where keys are angular object names and value is a list of services (like {controller: ['$http'], factory: ['$q']})
 *
 * @linkDescription disallow DI of specified services for other angular components (`$http` for controllers, filters and directives)
 * @version 0.1.0
 * @category bestPractice
 */
'use strict';
 
var utils = require('./utils/utils');
 
module.exports = function(context) {
    var angularObjectList = ['controller', 'filter', 'directive'];
    var badServices;
    var map;
    var message = 'REST API calls should be implemented in a specific service';
 
    function isArray(item) {
        return Object.prototype.toString.call(item) === '[object Array]';
    }
 
    function isObject(item) {
        return Object.prototype.toString.call(item) === '[object Object]';
    }
 
    if (context.options[0] === undefined) {
        badServices = ['$http', '$resource', 'Restangular', '$q', '$filter'];
    }
 
    if (isArray(context.options[0])) {
        badServices = context.options[0];
    }
 
    if (isArray(context.options[1])) {
        angularObjectList = context.options[1];
    }
 
    if (isObject(context.options[0])) {
        map = context.options[0];
        var result = [];
        var prop;
 
        for (prop in map) {
            Eif (map.hasOwnProperty(prop)) {
                result.push(prop);
            }
        }
 
        angularObjectList = result;
    }
 
    function isSetBedService(serviceName, angularObjectName) {
        if (map) {
            return map[angularObjectName].indexOf(serviceName) >= 0;
        }
        return badServices.indexOf(serviceName) >= 0;
    }
 
    return {
 
        CallExpression: function(node) {
            var callee = node.callee;
 
            if (utils.isAngularComponent(node) && callee.type === 'MemberExpression' && angularObjectList.indexOf(callee.property.name) >= 0) {
                if (utils.isFunctionType(node.arguments[1])) {
                    node.arguments[1].params.forEach(function(service) {
                        if (service.type === 'Identifier' && isSetBedService(service.name, callee.property.name)) {
                            context.report(node, message + ' (' + service.name + ' in ' + callee.property.name + ')', {});
                        }
                    });
                }
 
                if (utils.isArrayType(node.arguments[1])) {
                    node.arguments[1].elements.forEach(function(service) {
                        if (service.type === 'Literal' && isSetBedService(service.value, callee.property.name)) {
                            context.report(node, message + ' (' + service.value + ' in ' + callee.property.name + ')', {});
                        }
                    });
                }
            }
        }
    };
};
 
 
module.exports.schema = [{
    type: ['array', 'object']
}, {
    type: 'array'
}];