├── LICENSE ├── README.md ├── angular-resource.js ├── angular-resource.min.js ├── component.json └── composer.json /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2013 Components 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | AngularJS ngResource 2 | ==================== 3 | 4 | Shim repository for the [ngResource](http://docs.angularjs.org/api/ngResource) module. 5 | 6 | Package Managers 7 | ---------------- 8 | 9 | * [Component](https://github.com/component/component): `components/angular-resource` 10 | * [Composer](http://packagist.org/packages/components/angular-resource): `components/angular-resource` 11 | -------------------------------------------------------------------------------- /angular-resource.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @license AngularJS v1.2.0 3 | * (c) 2010-2012 Google, Inc. http://angularjs.org 4 | * License: MIT 5 | */ 6 | (function(window, angular, undefined) {'use strict'; 7 | 8 | var $resourceMinErr = angular.$$minErr('$resource'); 9 | 10 | /** 11 | * @ngdoc overview 12 | * @name ngResource 13 | * @description 14 | * 15 | * # ngResource 16 | * 17 | * The `ngResource` module provides interaction support with RESTful services 18 | * via the $resource service. 19 | * 20 | * {@installModule resource} 21 | * 22 | *
23 | * 24 | * See {@link ngResource.$resource `$resource`} for usage. 25 | */ 26 | 27 | /** 28 | * @ngdoc object 29 | * @name ngResource.$resource 30 | * @requires $http 31 | * 32 | * @description 33 | * A factory which creates a resource object that lets you interact with 34 | * [RESTful](http://en.wikipedia.org/wiki/Representational_State_Transfer) server-side data sources. 35 | * 36 | * The returned resource object has action methods which provide high-level behaviors without 37 | * the need to interact with the low level {@link ng.$http $http} service. 38 | * 39 | * Requires the {@link ngResource `ngResource`} module to be installed. 40 | * 41 | * @param {string} url A parametrized URL template with parameters prefixed by `:` as in 42 | * `/user/:username`. If you are using a URL with a port number (e.g. 43 | * `http://example.com:8080/api`), it will be respected. 44 | * 45 | * If you are using a url with a suffix, just add the suffix, like this: 46 | * `$resource('http://example.com/resource.json')` or `$resource('http://example.com/:id.json')` 47 | * or even `$resource('http://example.com/resource/:resource_id.:format')` 48 | * If the parameter before the suffix is empty, :resource_id in this case, then the `/.` will be 49 | * collapsed down to a single `.`. If you need this sequence to appear and not collapse then you 50 | * can escape it with `/\.`. 51 | * 52 | * @param {Object=} paramDefaults Default values for `url` parameters. These can be overridden in 53 | * `actions` methods. If any of the parameter value is a function, it will be executed every time 54 | * when a param value needs to be obtained for a request (unless the param was overridden). 55 | * 56 | * Each key value in the parameter object is first bound to url template if present and then any 57 | * excess keys are appended to the url search query after the `?`. 58 | * 59 | * Given a template `/path/:verb` and parameter `{verb:'greet', salutation:'Hello'}` results in 60 | * URL `/path/greet?salutation=Hello`. 61 | * 62 | * If the parameter value is prefixed with `@` then the value of that parameter is extracted from 63 | * the data object (useful for non-GET operations). 64 | * 65 | * @param {Object.=} actions Hash with declaration of custom action that should extend the 66 | * default set of resource actions. The declaration should be created in the format of {@link 67 | * ng.$http#usage_parameters $http.config}: 68 | * 69 | * {action1: {method:?, params:?, isArray:?, headers:?, ...}, 70 | * action2: {method:?, params:?, isArray:?, headers:?, ...}, 71 | * ...} 72 | * 73 | * Where: 74 | * 75 | * - **`action`** – {string} – The name of action. This name becomes the name of the method on 76 | * your resource object. 77 | * - **`method`** – {string} – HTTP request method. Valid methods are: `GET`, `POST`, `PUT`, 78 | * `DELETE`, and `JSONP`. 79 | * - **`params`** – {Object=} – Optional set of pre-bound parameters for this action. If any of 80 | * the parameter value is a function, it will be executed every time when a param value needs to 81 | * be obtained for a request (unless the param was overridden). 82 | * - **`url`** – {string} – action specific `url` override. The url templating is supported just 83 | * like for the resource-level urls. 84 | * - **`isArray`** – {boolean=} – If true then the returned object for this action is an array, 85 | * see `returns` section. 86 | * - **`transformRequest`** – 87 | * `{function(data, headersGetter)|Array.}` – 88 | * transform function or an array of such functions. The transform function takes the http 89 | * request body and headers and returns its transformed (typically serialized) version. 90 | * - **`transformResponse`** – 91 | * `{function(data, headersGetter)|Array.}` – 92 | * transform function or an array of such functions. The transform function takes the http 93 | * response body and headers and returns its transformed (typically deserialized) version. 94 | * - **`cache`** – `{boolean|Cache}` – If true, a default $http cache will be used to cache the 95 | * GET request, otherwise if a cache instance built with 96 | * {@link ng.$cacheFactory $cacheFactory}, this cache will be used for 97 | * caching. 98 | * - **`timeout`** – `{number|Promise}` – timeout in milliseconds, or {@link ng.$q promise} that 99 | * should abort the request when resolved. 100 | * - **`withCredentials`** - `{boolean}` - whether to set the `withCredentials` flag on the 101 | * XHR object. See {@link https://developer.mozilla.org/en/http_access_control#section_5 102 | * requests with credentials} for more information. 103 | * - **`responseType`** - `{string}` - see {@link 104 | * https://developer.mozilla.org/en-US/docs/DOM/XMLHttpRequest#responseType requestType}. 105 | * - **`interceptor`** - `{Object=}` - The interceptor object has two optional methods - 106 | * `response` and `responseError`. Both `response` and `responseError` interceptors get called 107 | * with `http response` object. See {@link ng.$http $http interceptors}. 108 | * 109 | * @returns {Object} A resource "class" object with methods for the default set of resource actions 110 | * optionally extended with custom `actions`. The default set contains these actions: 111 | * 112 | * { 'get': {method:'GET'}, 113 | * 'save': {method:'POST'}, 114 | * 'query': {method:'GET', isArray:true}, 115 | * 'remove': {method:'DELETE'}, 116 | * 'delete': {method:'DELETE'} }; 117 | * 118 | * Calling these methods invoke an {@link ng.$http} with the specified http method, 119 | * destination and parameters. When the data is returned from the server then the object is an 120 | * instance of the resource class. The actions `save`, `remove` and `delete` are available on it 121 | * as methods with the `$` prefix. This allows you to easily perform CRUD operations (create, 122 | * read, update, delete) on server-side data like this: 123 | *
124 |         var User = $resource('/user/:userId', {userId:'@id'});
125 |         var user = User.get({userId:123}, function() {
126 |           user.abc = true;
127 |           user.$save();
128 |         });
129 |      
130 | * 131 | * It is important to realize that invoking a $resource object method immediately returns an 132 | * empty reference (object or array depending on `isArray`). Once the data is returned from the 133 | * server the existing reference is populated with the actual data. This is a useful trick since 134 | * usually the resource is assigned to a model which is then rendered by the view. Having an empty 135 | * object results in no rendering, once the data arrives from the server then the object is 136 | * populated with the data and the view automatically re-renders itself showing the new data. This 137 | * means that in most case one never has to write a callback function for the action methods. 138 | * 139 | * The action methods on the class object or instance object can be invoked with the following 140 | * parameters: 141 | * 142 | * - HTTP GET "class" actions: `Resource.action([parameters], [success], [error])` 143 | * - non-GET "class" actions: `Resource.action([parameters], postData, [success], [error])` 144 | * - non-GET instance actions: `instance.$action([parameters], [success], [error])` 145 | * 146 | * Success callback is called with (value, responseHeaders) arguments. Error callback is called 147 | * with (httpResponse) argument. 148 | * 149 | * Class actions return empty instance (with additional properties below). 150 | * Instance actions return promise of the action. 151 | * 152 | * The Resource instances and collection have these additional properties: 153 | * 154 | * - `$promise`: the {@link ng.$q promise} of the original server interaction that created this 155 | * instance or collection. 156 | * 157 | * On success, the promise is resolved with the same resource instance or collection object, 158 | * updated with data from server. This makes it easy to use in 159 | * {@link ngRoute.$routeProvider resolve section of $routeProvider.when()} to defer view 160 | * rendering until the resource(s) are loaded. 161 | * 162 | * On failure, the promise is resolved with the {@link ng.$http http response} object, without 163 | * the `resource` property. 164 | * 165 | * - `$resolved`: `true` after first server interaction is completed (either with success or 166 | * rejection), `false` before that. Knowing if the Resource has been resolved is useful in 167 | * data-binding. 168 | * 169 | * @example 170 | * 171 | * # Credit card resource 172 | * 173 | *
174 |      // Define CreditCard class
175 |      var CreditCard = $resource('/user/:userId/card/:cardId',
176 |       {userId:123, cardId:'@id'}, {
177 |        charge: {method:'POST', params:{charge:true}}
178 |       });
179 | 
180 |      // We can retrieve a collection from the server
181 |      var cards = CreditCard.query(function() {
182 |        // GET: /user/123/card
183 |        // server returns: [ {id:456, number:'1234', name:'Smith'} ];
184 | 
185 |        var card = cards[0];
186 |        // each item is an instance of CreditCard
187 |        expect(card instanceof CreditCard).toEqual(true);
188 |        card.name = "J. Smith";
189 |        // non GET methods are mapped onto the instances
190 |        card.$save();
191 |        // POST: /user/123/card/456 {id:456, number:'1234', name:'J. Smith'}
192 |        // server returns: {id:456, number:'1234', name: 'J. Smith'};
193 | 
194 |        // our custom method is mapped as well.
195 |        card.$charge({amount:9.99});
196 |        // POST: /user/123/card/456?amount=9.99&charge=true {id:456, number:'1234', name:'J. Smith'}
197 |      });
198 | 
199 |      // we can create an instance as well
200 |      var newCard = new CreditCard({number:'0123'});
201 |      newCard.name = "Mike Smith";
202 |      newCard.$save();
203 |      // POST: /user/123/card {number:'0123', name:'Mike Smith'}
204 |      // server returns: {id:789, number:'01234', name: 'Mike Smith'};
205 |      expect(newCard.id).toEqual(789);
206 |  * 
207 | * 208 | * The object returned from this function execution is a resource "class" which has "static" method 209 | * for each action in the definition. 210 | * 211 | * Calling these methods invoke `$http` on the `url` template with the given `method`, `params` and 212 | * `headers`. 213 | * When the data is returned from the server then the object is an instance of the resource type and 214 | * all of the non-GET methods are available with `$` prefix. This allows you to easily support CRUD 215 | * operations (create, read, update, delete) on server-side data. 216 | 217 |
218 |      var User = $resource('/user/:userId', {userId:'@id'});
219 |      var user = User.get({userId:123}, function() {
220 |        user.abc = true;
221 |        user.$save();
222 |      });
223 |    
224 | * 225 | * It's worth noting that the success callback for `get`, `query` and other methods gets passed 226 | * in the response that came from the server as well as $http header getter function, so one 227 | * could rewrite the above example and get access to http headers as: 228 | * 229 |
230 |      var User = $resource('/user/:userId', {userId:'@id'});
231 |      User.get({userId:123}, function(u, getResponseHeaders){
232 |        u.abc = true;
233 |        u.$save(function(u, putResponseHeaders) {
234 |          //u => saved user object
235 |          //putResponseHeaders => $http header getter
236 |        });
237 |      });
238 |    
239 | 240 | * # Buzz client 241 | 242 | Let's look at what a buzz client created with the `$resource` service looks like: 243 | 244 | 245 | 268 | 269 |
270 | 271 | 272 |
273 |
274 |

275 | 276 | {{item.actor.name}} 277 | Expand replies: 278 | {{item.links.replies[0].count}} 279 |

280 | {{item.object.content | html}} 281 |
282 | 283 | {{reply.actor.name}}: {{reply.content | html}} 284 |
285 |
286 |
287 |
288 | 289 | 290 |
291 | */ 292 | angular.module('ngResource', ['ng']). 293 | factory('$resource', ['$http', '$parse', '$q', function($http, $parse, $q) { 294 | var DEFAULT_ACTIONS = { 295 | 'get': {method:'GET'}, 296 | 'save': {method:'POST'}, 297 | 'query': {method:'GET', isArray:true}, 298 | 'remove': {method:'DELETE'}, 299 | 'delete': {method:'DELETE'} 300 | }; 301 | var noop = angular.noop, 302 | forEach = angular.forEach, 303 | extend = angular.extend, 304 | copy = angular.copy, 305 | isFunction = angular.isFunction, 306 | getter = function(obj, path) { 307 | return $parse(path)(obj); 308 | }; 309 | 310 | /** 311 | * We need our custom method because encodeURIComponent is too aggressive and doesn't follow 312 | * http://www.ietf.org/rfc/rfc3986.txt with regards to the character set (pchar) allowed in path 313 | * segments: 314 | * segment = *pchar 315 | * pchar = unreserved / pct-encoded / sub-delims / ":" / "@" 316 | * pct-encoded = "%" HEXDIG HEXDIG 317 | * unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~" 318 | * sub-delims = "!" / "$" / "&" / "'" / "(" / ")" 319 | * / "*" / "+" / "," / ";" / "=" 320 | */ 321 | function encodeUriSegment(val) { 322 | return encodeUriQuery(val, true). 323 | replace(/%26/gi, '&'). 324 | replace(/%3D/gi, '='). 325 | replace(/%2B/gi, '+'); 326 | } 327 | 328 | 329 | /** 330 | * This method is intended for encoding *key* or *value* parts of query component. We need a 331 | * custom method because encodeURIComponent is too aggressive and encodes stuff that doesn't 332 | * have to be encoded per http://tools.ietf.org/html/rfc3986: 333 | * query = *( pchar / "/" / "?" ) 334 | * pchar = unreserved / pct-encoded / sub-delims / ":" / "@" 335 | * unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~" 336 | * pct-encoded = "%" HEXDIG HEXDIG 337 | * sub-delims = "!" / "$" / "&" / "'" / "(" / ")" 338 | * / "*" / "+" / "," / ";" / "=" 339 | */ 340 | function encodeUriQuery(val, pctEncodeSpaces) { 341 | return encodeURIComponent(val). 342 | replace(/%40/gi, '@'). 343 | replace(/%3A/gi, ':'). 344 | replace(/%24/g, '$'). 345 | replace(/%2C/gi, ','). 346 | replace(/%20/g, (pctEncodeSpaces ? '%20' : '+')); 347 | } 348 | 349 | function Route(template, defaults) { 350 | this.template = template; 351 | this.defaults = defaults || {}; 352 | this.urlParams = {}; 353 | } 354 | 355 | Route.prototype = { 356 | setUrlParams: function(config, params, actionUrl) { 357 | var self = this, 358 | url = actionUrl || self.template, 359 | val, 360 | encodedVal; 361 | 362 | var urlParams = self.urlParams = {}; 363 | forEach(url.split(/\W/), function(param){ 364 | if (param === 'hasOwnProperty') { 365 | throw $resourceMinErr('badname', "hasOwnProperty is not a valid parameter name."); 366 | } 367 | if (!(new RegExp("^\\d+$").test(param)) && param && 368 | (new RegExp("(^|[^\\\\]):" + param + "(\\W|$)").test(url))) { 369 | urlParams[param] = true; 370 | } 371 | }); 372 | url = url.replace(/\\:/g, ':'); 373 | 374 | params = params || {}; 375 | forEach(self.urlParams, function(_, urlParam){ 376 | val = params.hasOwnProperty(urlParam) ? params[urlParam] : self.defaults[urlParam]; 377 | if (angular.isDefined(val) && val !== null) { 378 | encodedVal = encodeUriSegment(val); 379 | url = url.replace(new RegExp(":" + urlParam + "(\\W|$)", "g"), encodedVal + "$1"); 380 | } else { 381 | url = url.replace(new RegExp("(\/?):" + urlParam + "(\\W|$)", "g"), function(match, 382 | leadingSlashes, tail) { 383 | if (tail.charAt(0) == '/') { 384 | return tail; 385 | } else { 386 | return leadingSlashes + tail; 387 | } 388 | }); 389 | } 390 | }); 391 | 392 | // strip trailing slashes and set the url 393 | url = url.replace(/\/+$/, ''); 394 | // then replace collapse `/.` if found in the last URL path segment before the query 395 | // E.g. `http://url.com/id./format?q=x` becomes `http://url.com/id.format?q=x` 396 | url = url.replace(/\/\.(?=\w+($|\?))/, '.'); 397 | // replace escaped `/\.` with `/.` 398 | config.url = url.replace(/\/\\\./, '/.'); 399 | 400 | 401 | // set params - delegate param encoding to $http 402 | forEach(params, function(value, key){ 403 | if (!self.urlParams[key]) { 404 | config.params = config.params || {}; 405 | config.params[key] = value; 406 | } 407 | }); 408 | } 409 | }; 410 | 411 | 412 | function resourceFactory(url, paramDefaults, actions) { 413 | var route = new Route(url); 414 | 415 | actions = extend({}, DEFAULT_ACTIONS, actions); 416 | 417 | function extractParams(data, actionParams){ 418 | var ids = {}; 419 | actionParams = extend({}, paramDefaults, actionParams); 420 | forEach(actionParams, function(value, key){ 421 | if (isFunction(value)) { value = value(); } 422 | ids[key] = value && value.charAt && value.charAt(0) == '@' ? 423 | getter(data, value.substr(1)) : value; 424 | }); 425 | return ids; 426 | } 427 | 428 | function defaultResponseInterceptor(response) { 429 | return response.resource; 430 | } 431 | 432 | function Resource(value){ 433 | copy(value || {}, this); 434 | } 435 | 436 | forEach(actions, function(action, name) { 437 | var hasBody = /^(POST|PUT|PATCH)$/i.test(action.method); 438 | 439 | Resource[name] = function(a1, a2, a3, a4) { 440 | var params = {}, data, success, error; 441 | 442 | /* jshint -W086 */ /* (purposefully fall through case statements) */ 443 | switch(arguments.length) { 444 | case 4: 445 | error = a4; 446 | success = a3; 447 | //fallthrough 448 | case 3: 449 | case 2: 450 | if (isFunction(a2)) { 451 | if (isFunction(a1)) { 452 | success = a1; 453 | error = a2; 454 | break; 455 | } 456 | 457 | success = a2; 458 | error = a3; 459 | //fallthrough 460 | } else { 461 | params = a1; 462 | data = a2; 463 | success = a3; 464 | break; 465 | } 466 | case 1: 467 | if (isFunction(a1)) success = a1; 468 | else if (hasBody) data = a1; 469 | else params = a1; 470 | break; 471 | case 0: break; 472 | default: 473 | throw $resourceMinErr('badargs', 474 | "Expected up to 4 arguments [params, data, success, error], got {0} arguments", 475 | arguments.length); 476 | } 477 | /* jshint +W086 */ /* (purposefully fall through case statements) */ 478 | 479 | var isInstanceCall = data instanceof Resource; 480 | var value = isInstanceCall ? data : (action.isArray ? [] : new Resource(data)); 481 | var httpConfig = {}; 482 | var responseInterceptor = action.interceptor && action.interceptor.response || 483 | defaultResponseInterceptor; 484 | var responseErrorInterceptor = action.interceptor && action.interceptor.responseError || 485 | undefined; 486 | 487 | forEach(action, function(value, key) { 488 | if (key != 'params' && key != 'isArray' && key != 'interceptor') { 489 | httpConfig[key] = copy(value); 490 | } 491 | }); 492 | 493 | if (hasBody) httpConfig.data = data; 494 | route.setUrlParams(httpConfig, 495 | extend({}, extractParams(data, action.params || {}), params), 496 | action.url); 497 | 498 | var promise = $http(httpConfig).then(function(response) { 499 | var data = response.data, 500 | promise = value.$promise; 501 | 502 | if (data) { 503 | // Need to convert action.isArray to boolean in case it is undefined 504 | // jshint -W018 505 | if ( angular.isArray(data) !== (!!action.isArray) ) { 506 | throw $resourceMinErr('badcfg', 'Error in resource configuration. Expected ' + 507 | 'response to contain an {0} but got an {1}', 508 | action.isArray?'array':'object', angular.isArray(data)?'array':'object'); 509 | } 510 | // jshint +W018 511 | if (action.isArray) { 512 | value.length = 0; 513 | forEach(data, function(item) { 514 | value.push(new Resource(item)); 515 | }); 516 | } else { 517 | copy(data, value); 518 | value.$promise = promise; 519 | } 520 | } 521 | 522 | value.$resolved = true; 523 | 524 | response.resource = value; 525 | 526 | return response; 527 | }, function(response) { 528 | value.$resolved = true; 529 | 530 | (error||noop)(response); 531 | 532 | return $q.reject(response); 533 | }); 534 | 535 | promise = promise.then( 536 | function(response) { 537 | var value = responseInterceptor(response); 538 | (success||noop)(value, response.headers); 539 | return value; 540 | }, 541 | responseErrorInterceptor); 542 | 543 | if (!isInstanceCall) { 544 | // we are creating instance / collection 545 | // - set the initial promise 546 | // - return the instance / collection 547 | value.$promise = promise; 548 | value.$resolved = false; 549 | 550 | return value; 551 | } 552 | 553 | // instance call 554 | return promise; 555 | }; 556 | 557 | 558 | Resource.prototype['$' + name] = function(params, success, error) { 559 | if (isFunction(params)) { 560 | error = success; success = params; params = {}; 561 | } 562 | var result = Resource[name](params, this, success, error); 563 | return result.$promise || result; 564 | }; 565 | }); 566 | 567 | Resource.bind = function(additionalParamDefaults){ 568 | return resourceFactory(url, extend({}, paramDefaults, additionalParamDefaults), actions); 569 | }; 570 | 571 | return Resource; 572 | } 573 | 574 | return resourceFactory; 575 | }]); 576 | 577 | 578 | })(window, window.angular); 579 | -------------------------------------------------------------------------------- /angular-resource.min.js: -------------------------------------------------------------------------------- 1 | /* 2 | AngularJS v1.2.0 3 | (c) 2010-2012 Google, Inc. http://angularjs.org 4 | License: MIT 5 | */ 6 | (function(H,h,C){'use strict';var x=h.$$minErr("$resource");h.module("ngResource",["ng"]).factory("$resource",["$http","$parse","$q",function(D,y,E){function n(h,k){this.template=h;this.defaults=k||{};this.urlParams={}}function t(e,k,f){function q(b,c){var d={};c=u({},k,c);r(c,function(a,c){s(a)&&(a=a());var m;a&&a.charAt&&"@"==a.charAt(0)?(m=a.substr(1),m=y(m)(b)):m=a;d[c]=m});return d}function d(b){return b.resource}function g(b){z(b||{},this)}var F=new n(e);f=u({},G,f);r(f,function(b,c){var A= 7 | /^(POST|PUT|PATCH)$/i.test(b.method);g[c]=function(a,c,m,k){var p={},e,f,v;switch(arguments.length){case 4:v=k,f=m;case 3:case 2:if(s(c)){if(s(a)){f=a;v=c;break}f=c;v=m}else{p=a;e=c;f=m;break}case 1:s(a)?f=a:A?e=a:p=a;break;case 0:break;default:throw x("badargs",arguments.length);}var n=e instanceof g,l=n?e:b.isArray?[]:new g(e),w={},t=b.interceptor&&b.interceptor.response||d,y=b.interceptor&&b.interceptor.responseError||C;r(b,function(a,c){"params"!=c&&("isArray"!=c&&"interceptor"!=c)&&(w[c]=z(a))}); 8 | A&&(w.data=e);F.setUrlParams(w,u({},q(e,b.params||{}),p),b.url);p=D(w).then(function(c){var a=c.data,d=l.$promise;if(a){if(h.isArray(a)!==!!b.isArray)throw x("badcfg",b.isArray?"array":"object",h.isArray(a)?"array":"object");b.isArray?(l.length=0,r(a,function(a){l.push(new g(a))})):(z(a,l),l.$promise=d)}l.$resolved=!0;c.resource=l;return c},function(a){l.$resolved=!0;(v||B)(a);return E.reject(a)});p=p.then(function(a){var c=t(a);(f||B)(c,a.headers);return c},y);return n?p:(l.$promise=p,l.$resolved= 9 | !1,l)};g.prototype["$"+c]=function(a,b,d){s(a)&&(d=b,b=a,a={});a=g[c](a,this,b,d);return a.$promise||a}});g.bind=function(b){return t(e,u({},k,b),f)};return g}var G={get:{method:"GET"},save:{method:"POST"},query:{method:"GET",isArray:!0},remove:{method:"DELETE"},"delete":{method:"DELETE"}},B=h.noop,r=h.forEach,u=h.extend,z=h.copy,s=h.isFunction;n.prototype={setUrlParams:function(e,k,f){var q=this,d=f||q.template,g,n,b=q.urlParams={};r(d.split(/\W/),function(c){if("hasOwnProperty"===c)throw x("badname"); 10 | !/^\d+$/.test(c)&&(c&&RegExp("(^|[^\\\\]):"+c+"(\\W|$)").test(d))&&(b[c]=!0)});d=d.replace(/\\:/g,":");k=k||{};r(q.urlParams,function(c,b){g=k.hasOwnProperty(b)?k[b]:q.defaults[b];h.isDefined(g)&&null!==g?(n=encodeURIComponent(g).replace(/%40/gi,"@").replace(/%3A/gi,":").replace(/%24/g,"$").replace(/%2C/gi,",").replace(/%20/g,"%20").replace(/%26/gi,"&").replace(/%3D/gi,"=").replace(/%2B/gi,"+"),d=d.replace(RegExp(":"+b+"(\\W|$)","g"),n+"$1")):d=d.replace(RegExp("(/?):"+b+"(\\W|$)","g"),function(a, 11 | c,b){return"/"==b.charAt(0)?b:c+b})});d=d.replace(/\/+$/,"");d=d.replace(/\/\.(?=\w+($|\?))/,".");e.url=d.replace(/\/\\\./,"/.");r(k,function(c,b){q.urlParams[b]||(e.params=e.params||{},e.params[b]=c)})}};return t}])})(window,window.angular); 12 | //# sourceMappingURL=angular-resource.min.js.map 13 | -------------------------------------------------------------------------------- /component.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "angular-resource", 3 | "repo": "components/angular-resource", 4 | "version": "1.2.0", 5 | "main": "angular-resource.js", 6 | "scripts": [ 7 | "angular-resource.js" 8 | ], 9 | "files": [ 10 | "angular-resource.min.js" 11 | ], 12 | "dependencies": { 13 | "components/angular.js": "1.2.0" 14 | }, 15 | "license": "MIT" 16 | } 17 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "components/angular-resource", 3 | "description": "Resource module for AngularJS", 4 | "type": "component", 5 | "homepage": "http://angularjs.org", 6 | "license": "MIT", 7 | "require": { 8 | "components/angular.js": "1.2.0" 9 | }, 10 | "extra": { 11 | "component": { 12 | "name": "angular-resource", 13 | "scripts": [ 14 | "angular-resource.js" 15 | ], 16 | "files": [ 17 | "angular-resource.min.js" 18 | ] 19 | } 20 | } 21 | } 22 | --------------------------------------------------------------------------------