title: build API methods as angular service
body: <p>As I started using AngularJS a couple of days ago, I discovered a lot of useful stuff and I realized that it's easier using it in your web applications rather than building everything from scratch ( sometimes that is necessary but not in most cases ) or using a lot of libraries that may clutter the load time of the app.</p>
  
  <p>So, I had a php API wrapper for an online shop with a lot of methods ( I tried to mimic REST, but the API only offers POST and GET ) and I started building a JS script for it that can be used to call of the methods without any knowledge of PHP or having to touch any PHP code.</p>
  
  <p>Using AngularJS I came up with this :</p>
  
  <pre><code>var Application = Application || {};
  
  ;(function($, window, document, undefined) {
  
  "use strict";
  
  var Envato = {};
  
  Application.Envato = angular.module("Envato", []);
  
  Application.Envato.constant("API", {
  
      Path : {
          Private : "api/envato/private/",
          Public : "api/envato/public/"
      }
  });
  
  })(jQuery, window, document);
  </code></pre>
  
  <p>The above would be my module, placed inside a <code>modules</code> folder. The next, would be the factory build around the module ( placed in the same folder as the above module ) :</p>
  
  <pre><code>var Application = Application || {};
  
  ;(function($, window, document, undefined) {
  
  "use strict";
  
  Application.Envato.factory("APIXHRService", function($http, $timeout, $q) {
  
      return function(method, url, data) {
  
          var deferred = $q.defer(),
              headers = {
                  "Content-Type" : "Application/JSON"
              };
  
          $http({ method : method, url : url, data : data, headers : headers }).success(function(_data) {
  
              deferred.resolve(_data);
              deferred = $q.defer();
          }).error(function(_data) {
  
              deferred.resolve(_data || "Request [ Failed ]");
              deferred = $q.defer();
          });
  
          return deferred.promise;
      };
  });
  
  Application.Envato.factory("Envato", function(APIXHRService, API) {
  
      return {
  
          API : {
  
              Private : {
  
                  User : {
  
                      Account : function(user){
                          return APIXHRService("POST", API.Path.Private + "get-account-information.php", { user : user });
                      },
  
                      Statement : function(user) {
                          return APIXHRService("POST", API.Path.Private + "get-statement.php", { user : user });
                      },
  
                      Sales : function(user) {
                          return APIXHRService("POST", API.Path.Private + "get-recent-sales.php", { user : user });
                      },
  
                      Transactions : function(user) {
                          return APIXHRService("POST", API.Path.Private + "get-earnings-and-sales-by-month.php", { user : user });
                      },
  
                      Vitals : function(user) {
                          return APIXHRService("POST", API.Path.Private + "get-user-vitals.php", { user : user });
                      }
                  },
  
                  Purchases : {
  
                      Download : function(user, token) {
                          return APIXHRService("POST", API.Path.Private + "get-item-download-url.php", { user : user, token : token });
                      },
  
                      Information : function(user, token) {
                          return APIXHRService("POST", API.Path.Private + "get-purchase-information.php", { user : user, token : token });
                      }
                  }
              },
  
              Public : {
  
                  API : {
  
                      Releases : function() {
                          return APIXHRService("GET", API.Path.Public + "get-api-releases.php");
                      }
                  },
  
                  Blog : {
  
                      Posts : function(marketplaces) {
                          return APIXHRService("POST", API.Path.Public + "get-blog-posts.php", { marketplaces : marketplaces });
                      },
  
                      Threads : {
  
                          Active : function(marketplaces) {
                              return APIXHRService("POST", API.Path.Public + "get-active-threads.php", { marketplaces : marketplaces });
                          },
  
                          Status : function(threads) {
                              return APIXHRService("POST", API.Path.Public + "get-thread-status.php", { threads : threads });
                          }
                      }
                  },
  
                  Collections : function(collections) {
                      return APIXHRService("POST", API.Path.Public + "get-collections.php", { collections : collections });
                  },
  
                  Items : {
  
                      Count : function(marketplaces) {
                          return APIXHRService("POST", API.Path.Public + "get-items-count.php", { marketplaces : marketplaces });
                      },
  
                      Featured : function(marketplaces) {
                          return APIXHRService("POST", API.Path.Public + "get-featured-items.php", { marketplaces : marketplaces });
                      },
  
                      Information : function(items) {
                          return APIXHRService("POST", API.Path.Public + "get-item-information.php", { items : items });
                      },
  
                      Latest : {
  
                          Marketplace : function(marketplaces) {
                              return APIXHRService("POST", API.Path.Public + "get-new-items-from-market.php", { marketplaces : marketplaces });
                          },
  
                          Random : function(marketplaces) {
                              return APIXHRService("POST", API.Path.Public + "get-random-new-items.php", { marketplaces : marketplaces });
                          },
  
                          User : function(users) {
                              return APIXHRService("POST", API.Path.Public + "get-new-items-from-user.php", { users : users });
                          }
                      },
  
                      Popular : function(marketplaces) {
                          return APIXHRService("POST", API.Path.Public + "get-popular-items.php", { marketplaces : marketplaces });
                      },
  
                      Price : function(items) {
                          return APIXHRService("POST", API.Path.Public + "get-item-price.php", { items : items });
                      }
                  },
  
                  Users : {
  
                      Information : function(users) {
                          return APIXHRService("POST", API.Path.Public + "get-user-information.php", { users : users });
                      },
  
                      Items : {
  
                          Count : function(users) {
                              return APIXHRService("POST", API.Path.Public + "get-user-items-by-site.php", { users : users });
                          }
                      },
  
                      Total : function() {
                          return APIXHRService("GET", API.Path.Public + "get-total-users-count.php");
                      },
                  },
  
                  Search : function(expression, marketplace, categories) {
                      return APIXHRService("POST", API.Path.Public + "get-search-results.php", { expression : expression, marketplace : ( marketplace === undefined ? "" : marketplace ), categories : ( categories === undefined ? "" : categories ) });
                  }
              }
          }
      };
  });
  
  })(jQuery, window, document);
  </code></pre>
  
  <p>And lastly, if needed, I had a controller that allows me to check if the methods work properly :</p>
  
  <pre><code>var Application = Application || {};
  
  ;(function($, window, document, undefined) {
  
  "use strict";
  
  Application.controller("EnvatoAPIController", ["$scope", "_debounce", "Envato", function($scope, _debounce, Envato) {
  
      $scope.getData = _debounce(function($event) {
  
          $event.preventDefault();
  
          return Envato.API.Private.Purchases.Download("chaoscod3r", "52dfdscb1-dada-4ff8-bfcb-d3fdsbn55mda").then(function(data) {
              $scope.data = JSON.stringify(data, undefined, 4);
          });
  
      }, 250, false);
  
  }]);
  
  })(jQuery, window, document);
  </code></pre>
  
  <p>The reason why I'm posting this is that I'm looking for some insights on how I could improve my code, as it seems to me that it's a bit to much going on in there. Maybe there's a better way of doing it with Angular ? I haven't got the chance to get through all the AngularJS API docs, so I guess there must be a lot of developers here that are using Angular and could give me some tips :)</p>
  
  <p><strong>EDIT :</strong> The question is how can I refractor the <code>Envato</code> factory ? Which way would be the best ?</p>