<NME> api_endpoint.js
<BEF> import $cache from './cache';

class ApiEndpoint {
    constructor(baseRoute, httpParamSerializerJQLikeMode, endpointConfig, $httpParamSerializerJQLike,
                cacheDefaultLifetime, cacheDefaultStorageMode, $injector, $resource, $q, CacheFactory) {
        'ngInject';

        this.config = endpointConfig;
        this.httpParamSerializerJQLikeMode = httpParamSerializerJQLikeMode;
        this.$httpParamSerializerJQLike = $httpParamSerializerJQLike;
        this.CacheFactory = CacheFactory;

        if (angular.isString(this.config.modelClass)) {
            this.config.modelClass = $injector.get(this.config.modelClass);
            this.config.modelClass = $injector.get(this.config.modelClass);
        }

        // Set behavior for actions
        angular.forEach(endpointConfig.actions, (action, actionName, availableActions = {}) => {
            action.method = action.method.toUpperCase();

            let actionMethod = this.request,
                params = availableActions[actionName] ? availableActions[actionName] : {},
                actionParams = {
                    name: actionName,
                    instantiateModel: params.instantiateModel !== false,
                    headersForReading: params.headersForReading || false,
                    isSaveRequest: (action.method === 'PUT' || action.method === 'POST' || action.method === 'PATCH')
                };

            if (endpointConfig.model) {
                actionMethod = (actionParams.isSaveRequest) ? this.saveRequestWithModel : this.getRequestWithModel;
            }

            let lifetime = ((typeof params.$cache === 'object') ? params.$cache.lifetime : null);
            action['$cache'] = new $cache({
                name: `api.${actionName}`,
                active: !!params.$cache,
                lifetime: (typeof lifetime === 'number') ? lifetime : cacheDefaultLifetime,
                storageMode: ((typeof params.$cache === 'object') ? params.$cache.storageMode : null) || cacheDefaultStorageMode,
                Cache: CacheFactory
            });

            this[actionName] = angular.bind(this, actionMethod, actionParams);
            this[actionName]['$cache'] = action['$cache']
        });
    }

    instantiateModel(data) {
        let model = this.config.modelClass ? new this.config.modelClass(data) : data;

        if (model && angular.isFunction(model.afterLoad)) {
            model.afterLoad();
        }

        return model;
    };

    request(actionParams, params = {}, data = {}) {
        if ((this.httpParamSerializerJQLikeMode && actionParams.httpParamSerializerJQLikeMode !== false) || actionParams.httpParamSerializerJQLikeMode) {
            data = this.cleanObject(data);
            data = this.$httpParamSerializerJQLike(data);
        }


            return (actionParams.instantiateModel && response) ? angular.fromJson(response) : {data: response};
        };
        
        if (params.cache === 'angular-cache') {
            angular.extend(params, {cache: this.CacheFactory('ng-rest-api')});
        }

        return this.resource[actionParams.name](params, data).$promise
            .then((response) => {
                let data = response;
                let result = null;

                if (!actionParams.instantiateModel) {
                    result = response.data;
                } else if (angular.isArray(data)) {
                    result = data.map((element) => this.instantiateModel(element))
                } else {
                    result = (() => this.instantiateModel(data))()
                }

                return !!_headersForReturn ? [result, _headersForReturn] : result;
            });
    };

            if (!actionParams.instantiateModel) {
                result = response.data;
            } else if (angular.isArray(response)) {
                result = response.map((element) => this.instantiateModel(element))
            } else {
                result = (() => this.instantiateModel(response))()
            }

            result = !!_headersForReturn ? [result, _headersForReturn] : result;

            return result;
        });
    };

    // For GET requests
    getRequestWithModel(action, params) {
        return this.request(action, params);
    };

    // For POST and PUT request
    saveRequestWithModel(action, params, data) {

        // if empty data - assume that the parameters have not been transferred
        if (!data) {
            data = params;
            params = {};
        }

        let model = angular.copy(data);

        if (model && angular.isFunction(model.beforeSave)) {
            model.beforeSave();
        }

        return this.request(action, params, model);
    };

    // Remove undefined and null
    cleanObject(obj) {
        return Object.keys(obj)
            .filter(k => obj[k] !== null && obj[k] !== undefined)
            .reduce((newObj, k) => typeof obj[k] === 'object'
                ? Object.assign(newObj, {[k]: this.cleanObject(obj[k])})
                : Object.assign(newObj, {[k]: obj[k]}),
                {}
            );
    };
}

export default ApiEndpoint;
<MSG> Add angular-cache support fo rall request (include POST).

<DFF> @@ -9,6 +9,7 @@ class ApiEndpoint {
         this.httpParamSerializerJQLikeMode = httpParamSerializerJQLikeMode;
         this.$httpParamSerializerJQLike = $httpParamSerializerJQLike;
         this.CacheFactory = CacheFactory;
+        this.cacher = false;
 
         if (angular.isString(this.config.modelClass)) {
             this.config.modelClass = $injector.get(this.config.modelClass);
@@ -65,25 +66,36 @@ class ApiEndpoint {
 
             return (actionParams.instantiateModel && response) ? angular.fromJson(response) : {data: response};
         };
-        
-        if (params.cache === 'angular-cache') {
-            angular.extend(params, {cache: this.CacheFactory('ng-rest-api')});
+        let cacheResult = false;
+        let cacheKey = angular.isString(this.config.actions[actionParams.name].cache) ? this.config.actions[actionParams.name].cache : false;
+        if (cacheKey) {
+            if (params['force']) {
+                this.CacheFactory.destroy(cacheKey);
+                delete params['force'];
+            }
+            this.cacher = this.CacheFactory.get(cacheKey) || this.CacheFactory.createCache(cacheKey, {storageMode: 'localStorage'});
+            cacheResult = this.cacher.get(JSON.stringify(Object.assign({}, actionParams.name, params, data)));
         }
 
-        return this.resource[actionParams.name](params, data).$promise
+        return (cacheResult) ? new Promise((resolve) => resolve(cacheResult)) : this.resource[actionParams.name](params, data).$promise
             .then((response) => {
-                let data = response;
                 let result = null;
 
                 if (!actionParams.instantiateModel) {
                     result = response.data;
-                } else if (angular.isArray(data)) {
-                    result = data.map((element) => this.instantiateModel(element))
+                } else if (angular.isArray(response)) {
+                    result = response.map((element) => this.instantiateModel(element))
                 } else {
-                    result = (() => this.instantiateModel(data))()
+                    result = (() => this.instantiateModel(response))()
+                }
+
+                result = !!_headersForReturn ? [result, _headersForReturn] : result;
+
+                if (this.cacher) {
+                    this.cacher.put(JSON.stringify(Object.assign({}, actionParams.name, params, data)), result);
                 }
 
-                return !!_headersForReturn ? [result, _headersForReturn] : result;
+                return result;
             });
     };
 

Add angular-cache support fo rall request (include POST).