parse-stack 1.7.4 → 1.8.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: adfaf3f682758219d766199934910e0f885bbe3770d5aba4ceb73e575b29a236
4
- data.tar.gz: 0ae3f2fba6aa06d1ecc9eb01fd1110066813eed944ec610b1b76c31e55a4a7da
3
+ metadata.gz: fb8e8c64fc1b8ada3c5746964e7e0cb122a14b6285c40bad92ca99940784ea58
4
+ data.tar.gz: 52e4ef4525970ec793f7bd309d6fb9c679c3e7ff433cad8b94329c49c8d40c43
5
5
  SHA512:
6
- metadata.gz: 182fba0ec6563b3c3946d5fdb10d6ad66d9a6777a1c8df8e048935f786c2be1c08e1291b6f586e7cb81b304826cf30581fd5aa1a05be060033c4a21279551264
7
- data.tar.gz: 5184b7124197babce5fd543c04096b4ca1284be8be44b0f1df2167b8a8ba813709a11d08007c73194f6c7ca321d97056ac9fd41fdbe7d8da6bf27de825cd17af
6
+ metadata.gz: ca5320827dbb4fa24950f2fd65dbf7f45d5661e1de379706eb29cb8c3b6a8651b8109eacd6224988455112aaf5b9eba7e0a996281cf79c5ca36db9aedcef160c
7
+ data.tar.gz: d24aa327c2c77513e26d9a5993ce039ef3a790474dd3c23d8a5a12649d9e24aedc4888da74fd52312ff631800b8be91460e16f5447f84ea7fde4bcd02f5aeb4d
@@ -1,7 +1,7 @@
1
1
  language: ruby
2
2
  rvm:
3
- - 2.2.2
4
- - 2.3.2
5
- - 2.4.1
3
+ - 2.3.7
4
+ - 2.4.4
6
5
  - 2.5.1
7
- before_install: gem install bundler -v 1.16.2
6
+ - 2.6.0
7
+ before_install: gem install bundler
data/Changes.md CHANGED
@@ -1,5 +1,10 @@
1
1
  ## Parse-Stack Changelog
2
2
 
3
+ ### 1.8.0
4
+ - NEW: Support for Parse Server [full text search](https://github.com/modernistik/parse-stack#full-text-search-constraint) with the `text_search` operator. Related to [Issue#46](https://github.com/modernistik/parse-stack/issues/46).
5
+ - NEW: Support for `:distinct` aggregation query. Finds the distinct values for a specified field across a single collection or view and returns the results in an array.
6
+ For example, `User.distinct(:city, :created_at.after => 3.days.ago)` to return an array of unique city names for which records were created in the last 3 days.
7
+
3
8
  ### 1.7.4
4
9
  - NEW: Added `parse_object` extension to Hash classes to more easily call
5
10
  Parse::Object.build in `map` loops with symbol to proc.
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- parse-stack (1.7.4)
4
+ parse-stack (1.8.0)
5
5
  active_model_serializers (>= 0.9, < 1)
6
6
  activemodel (>= 4.2.1, < 6)
7
7
  activesupport (>= 4.2.1, < 6)
@@ -14,15 +14,15 @@ PATH
14
14
  GEM
15
15
  remote: https://rubygems.org/
16
16
  specs:
17
- actionpack (5.2.0)
18
- actionview (= 5.2.0)
19
- activesupport (= 5.2.0)
17
+ actionpack (5.2.1)
18
+ actionview (= 5.2.1)
19
+ activesupport (= 5.2.1)
20
20
  rack (~> 2.0)
21
21
  rack-test (>= 0.6.3)
22
22
  rails-dom-testing (~> 2.0)
23
23
  rails-html-sanitizer (~> 1.0, >= 1.0.2)
24
- actionview (5.2.0)
25
- activesupport (= 5.2.0)
24
+ actionview (5.2.1)
25
+ activesupport (= 5.2.1)
26
26
  builder (~> 3.1)
27
27
  erubi (~> 1.4)
28
28
  rails-dom-testing (~> 2.0)
@@ -32,9 +32,9 @@ GEM
32
32
  activemodel (>= 4.1, < 6)
33
33
  case_transform (>= 0.2)
34
34
  jsonapi-renderer (>= 0.1.1.beta1, < 0.3)
35
- activemodel (5.2.0)
36
- activesupport (= 5.2.0)
37
- activesupport (5.2.0)
35
+ activemodel (5.2.1)
36
+ activesupport (= 5.2.1)
37
+ activesupport (5.2.1)
38
38
  concurrent-ruby (~> 1.0, >= 1.0.2)
39
39
  i18n (>= 0.7, < 2)
40
40
  minitest (~> 5.1)
@@ -50,14 +50,14 @@ GEM
50
50
  crass (1.0.4)
51
51
  daemons (1.2.6)
52
52
  debug_inspector (0.0.3)
53
- dotenv (2.4.0)
53
+ dotenv (2.5.0)
54
54
  erubi (1.7.1)
55
55
  eventmachine (1.2.7)
56
- faraday (0.15.2)
56
+ faraday (0.15.3)
57
57
  multipart-post (>= 1.2, < 3)
58
58
  faraday_middleware (0.12.2)
59
59
  faraday (>= 0.7.4, < 1.0)
60
- i18n (1.0.1)
60
+ i18n (1.1.0)
61
61
  concurrent-ruby (~> 1.0)
62
62
  jsonapi-renderer (0.2.0)
63
63
  loofah (2.2.2)
@@ -68,7 +68,7 @@ GEM
68
68
  minitest (5.11.3)
69
69
  moneta (1.0.0)
70
70
  multipart-post (2.0.0)
71
- nokogiri (1.8.2)
71
+ nokogiri (1.8.4)
72
72
  mini_portile2 (~> 2.3.0)
73
73
  parallel (1.12.1)
74
74
  pry (0.10.4)
@@ -81,7 +81,7 @@ GEM
81
81
  binding_of_caller (>= 0.7)
82
82
  pry (>= 0.9.11)
83
83
  rack (2.0.5)
84
- rack-test (1.0.0)
84
+ rack-test (1.1.0)
85
85
  rack (>= 1.0, < 3)
86
86
  rails-dom-testing (2.0.3)
87
87
  activesupport (>= 4.2.0)
@@ -90,7 +90,7 @@ GEM
90
90
  loofah (~> 2.2, >= 2.2.2)
91
91
  rake (12.3.1)
92
92
  redcarpet (3.4.0)
93
- redis (4.0.1)
93
+ redis (4.0.2)
94
94
  slop (3.6.0)
95
95
  thin (1.7.2)
96
96
  daemons (~> 1.0, >= 1.0.9)
@@ -99,7 +99,7 @@ GEM
99
99
  thread_safe (0.3.6)
100
100
  tzinfo (1.2.5)
101
101
  thread_safe (~> 0.1)
102
- yard (0.9.13)
102
+ yard (0.9.16)
103
103
 
104
104
  PLATFORMS
105
105
  ruby
data/README.md CHANGED
@@ -6,6 +6,10 @@
6
6
 
7
7
  Below is a [quick start guide](https://github.com/modernistik/parse-stack#overview), but you can also check out the full *[API Reference](https://www.modernistik.com/gems/parse-stack/index.html)* for more detailed information about our Parse Server SDK.
8
8
 
9
+ ### Hire Us
10
+
11
+ Interested in our work? You can find us here: [https://www.modernistik.com](https://www.modernistik.com)
12
+
9
13
  ### Code Status
10
14
  [![Gem Version](https://img.shields.io/gem/v/parse-stack.svg)](https://github.com/modernistik/parse-stack)
11
15
  [![Downloads](https://img.shields.io/gem/dt/parse-stack.svg)](https://rubygems.org/gems/parse-stack)
@@ -134,7 +138,7 @@ result = Parse.call_function :myFunctionName, {param: value}
134
138
  <!-- START doctoc generated TOC please keep comment here to allow auto update -->
135
139
  <!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
136
140
 
137
- - [Overview](#overview)
141
+
138
142
  - [Architecture](#architecture)
139
143
  - [Parse::Client](#parseclient)
140
144
  - [Parse::Query](#parsequery)
@@ -203,6 +207,7 @@ result = Parse.call_function :myFunctionName, {param: value}
203
207
  - [Advanced Querying](#advanced-querying)
204
208
  - [Results Caching](#results-caching)
205
209
  - [Counting](#counting)
210
+ - [Distinct Aggregation](#distinct-aggregation)
206
211
  - [Query Expressions](#query-expressions)
207
212
  - [:order](#order)
208
213
  - [:keys](#keys)
@@ -235,6 +240,7 @@ result = Parse.call_function :myFunctionName, {param: value}
235
240
  - [Max Distance Constraint](#max-distance-constraint)
236
241
  - [Bounding Box Constraint](#bounding-box-constraint)
237
242
  - [Polygon Area Constraint](#polygon-area-constraint)
243
+ - [Full Text Search Constraint](#full-text-search-constraint)
238
244
  - [Relational Queries](#relational-queries)
239
245
  - [Compound Queries](#compound-queries)
240
246
  - [Query Scopes](#query-scopes)
@@ -1730,7 +1736,8 @@ When a query API is made, the results are cached in the query object in case you
1730
1736
  ```
1731
1737
 
1732
1738
  ### Counting
1733
- If you only need to know the result count for a query, provide count a non-zero value. However, if you need to perform a count query, use `count()` method instead.
1739
+ If you only need to know the result count for a query, provide count a
1740
+ non-zero value. However, if you need to perform a count query, use `count()` method instead.
1734
1741
 
1735
1742
  ```ruby
1736
1743
  # get number of songs with a play_count > 10
@@ -1743,6 +1750,23 @@ If you only need to know the result count for a query, provide count a non-zero
1743
1750
 
1744
1751
  ```
1745
1752
 
1753
+ ### Distinct Aggregation
1754
+ Finds the distinct values for a specified field across a single collection or
1755
+ view and returns the results in an array. You may mix this with additional query constraints.
1756
+
1757
+ ```ruby
1758
+ # Return a list of unique city names
1759
+ # for users created in the last 10 days.
1760
+ User.distinct :city, :created_at.after => 10.days.ago
1761
+ # ex. ["San Diego", "Los Angeles", "San Juan"]
1762
+
1763
+ # same
1764
+ query = Parse::Query.new("_User")
1765
+ query.where :created_at.after => 10.days.ago
1766
+ query.distinct(:city) #=> ["San Diego", "Los Angeles", "San Juan"]
1767
+
1768
+ ```
1769
+
1746
1770
  ### Query Expressions
1747
1771
  The set of supported expressions based on what is available through the Parse REST API. _For those who don't prefer the DataMapper style syntax, we have provided method accessors for each of the expressions._ A full description of supported query operations, please refer to the [`Parse::Query`](https://www.modernistik.com/gems/parse-stack/Parse/Query.html) API reference.
1748
1772
 
@@ -1785,16 +1809,16 @@ Use on Pointer columns to return the full object. You may chain multiple columns
1785
1809
  ```
1786
1810
 
1787
1811
  #### :limit
1788
- Limit the number of objects returned by the query. The default is 100, with Parse allowing a maximum of 1000. The framework also allows a value of `:max`. Utilizing this will have the framework continually intelligently utilize `:skip` to continue to paginate through results until an empty result set is received or the `:skip` limit is reached (10,000). When utilizing `all()`, `:max` is the default option for `:limit`.
1812
+ Limit the number of objects returned by the query. The default is 100, with Parse allowing a maximum of 1000. The framework also allows a value of `:max`. Utilizing this will have the framework continually intelligently utilize `:skip` to continue to paginate through results until an empty result set is received or the `:skip` limit is reached. When utilizing `all()`, `:max` is the default option for `:limit`.
1789
1813
 
1790
1814
  ```ruby
1791
1815
  Song.all :limit => 1 # same as Song.first
1792
1816
  Song.all :limit => 1000 # maximum allowed by Parse
1793
- Song.all :limit => :max # up to 11,000 records (theoretical).
1817
+ Song.all :limit => :max
1794
1818
  ```
1795
1819
 
1796
1820
  #### :skip
1797
- Use with limit to paginate through results. Default is 0 with maximum value being 10,000.
1821
+ Use with limit to paginate through results. Default is 0.
1798
1822
 
1799
1823
  ```ruby
1800
1824
  # get the next 3 songs after the first 10
@@ -2150,6 +2174,30 @@ Equivalent to the `$geoWithin` Parse query operation and `$polygon` geopoint con
2150
2174
  SunkenShip.all :location.within_polygon => [bermuda, san_juan, miami]
2151
2175
  ```
2152
2176
 
2177
+ #### [Full Text Search Constraint](https://www.modernistik.com/gems/parse-stack/Parse/Constraint/FullTextSearchQueryConstraint.html)
2178
+ Equivalent to the `$text` Parse query operation and `$search` parameter constraint for efficient search capabilities. By creating indexes on one or more columns your strings are turned into tokens for full text search functionality. The `$search` key can take any number of parameters in hash form. *Requires Parse Server 2.5.0 or later*
2179
+
2180
+ ```ruby
2181
+ # Do a full text search on "anthony"
2182
+ q.where :field.text_search => "anthony"
2183
+
2184
+ # perform advance searches
2185
+ q.where :field.text_search => {term: "anthony", case_insensitive: true}
2186
+ # equivalent
2187
+ q.where :field.text_search => {:$term => "anthony", :$caseInsensitive => true}
2188
+ ```
2189
+
2190
+ You may use the following keys for the parameters clause.
2191
+
2192
+ | Parameter | Use |
2193
+ | :--- | :----- |
2194
+ | `$term` | Specify a field to search (**Required**)|
2195
+ | `$language` | Determines the list of stop words and the rules for tokenizer.|
2196
+ | `$caseSensitive` | Enable or disable case sensitive search.|
2197
+ | `$diacriticSensitive` | Enable or disable diacritic sensitive search.|
2198
+
2199
+ For additional details, please see [Query on String Values](https://docs.parseplatform.org/rest/guide/#queries-on-string-values).
2200
+
2153
2201
  ### Relational Queries
2154
2202
  Equivalent to the `$relatedTo` Parse query operation. If you want to retrieve objects that are members of a `Relation` field in your Parse class.
2155
2203
 
@@ -2610,10 +2658,6 @@ end
2610
2658
 
2611
2659
  ```
2612
2660
 
2613
- ## Hire Us
2614
-
2615
- Interested in our consulting work? You can find us here: [https://www.modernistik.com](https://www.modernistik.com)
2616
-
2617
2661
  ## Contributing
2618
2662
 
2619
2663
  Bug reports and pull requests are welcome on GitHub at [https://github.com/modernistik/parse-stack](https://github.com/modernistik/parse-stack).
@@ -0,0 +1,62 @@
1
+ # encoding: UTF-8
2
+ # frozen_string_literal: true
3
+
4
+ require 'active_support'
5
+ require 'active_support/core_ext'
6
+ require_relative './objects'
7
+ module Parse
8
+
9
+ module API
10
+ # REST API methods for fetching CRUD operations on Parse objects.
11
+ module Aggregate
12
+ # The class prefix for fetching objects.
13
+ # @!visibility private
14
+ PATH_PREFIX = "aggregate/"
15
+
16
+ # @!visibility private
17
+ PREFIX_MAP = Parse::API::Objects::PREFIX_MAP
18
+
19
+ # @!visibility private
20
+ def self.included(base)
21
+ base.extend(ClassMethods)
22
+ end
23
+
24
+ # Class methods to be applied to {Parse::Client}
25
+ module ClassMethods
26
+ # Get the aggregate API path for this class.
27
+ # @param className [String] the name of the Parse collection.
28
+ # @return [String] the API uri path
29
+ def aggregate_uri_path(className)
30
+ if className.is_a?(Parse::Pointer)
31
+ id = className.id
32
+ className = className.parse_class
33
+ end
34
+ "#{PATH_PREFIX}#{className}"
35
+ end
36
+
37
+ end
38
+
39
+ # Get the API path for this class.
40
+ # @param className [String] the name of the Parse collection.
41
+ # @return [String] the API uri path
42
+ def aggregate_uri_path(className)
43
+ self.class.aggregate_uri_path(className)
44
+ end
45
+
46
+ # Aggregate a set of matching objects for a query.
47
+ # @param className [String] the name of the Parse collection.
48
+ # @param query [Hash] The set of query constraints.
49
+ # @param opts [Hash] additional options to pass to the {Parse::Client} request.
50
+ # @param headers [Hash] additional HTTP headers to send with the request.
51
+ # @return [Parse::Response]
52
+ # @see Parse::Query
53
+ def aggregate_objects(className, query = {}, headers: {}, **opts)
54
+ response = request :get, aggregate_uri_path(className), query: query, headers: headers, opts: opts
55
+ response.parse_class = className if response.present?
56
+ response
57
+ end
58
+
59
+ end #Aggregate
60
+ end #API
61
+
62
+ end
@@ -3,6 +3,7 @@
3
3
 
4
4
  require_relative '../client'
5
5
  require_relative "analytics"
6
+ require_relative "aggregate"
6
7
  require_relative "batch"
7
8
  require_relative "config"
8
9
  require_relative "files"
@@ -107,6 +107,7 @@ module Parse
107
107
  # features you'd like to implement.
108
108
  class Client
109
109
  include Parse::API::Analytics
110
+ include Parse::API::Aggregate
110
111
  include Parse::API::Batch
111
112
  include Parse::API::CloudFunctions
112
113
  include Parse::API::Config
@@ -252,6 +252,19 @@ module Parse
252
252
  query(constraints).count
253
253
  end
254
254
 
255
+ # Finds the distinct values for a specified field across a single
256
+ # collection or view and returns the results in an array.
257
+ # @example
258
+ # # get a list of unique city names for users who are older than 21.
259
+ # cities = User.distinct(:city, :age.gt => 21 )
260
+ # @param field The name of the field to use for unique aggregation.
261
+ # @param constraints (see #all)
262
+ # @return [Array] a list of distinct values
263
+ # @see Parse::Query#distinct
264
+ def distinct(field, constraints = {})
265
+ query(constraints).distinct(field)
266
+ end
267
+
255
268
  # Find objects matching the constraint ordered by the descending created_at date.
256
269
  # @param constraints (see #all)
257
270
  # @return [Array<Parse::Object>]
@@ -314,7 +314,7 @@ module Parse
314
314
  elsif expression == :keys
315
315
  keys value
316
316
  elsif expression == :key
317
- @key = value
317
+ keys [value]
318
318
  elsif expression == :skip
319
319
  skip value
320
320
  elsif expression == :limit
@@ -434,7 +434,7 @@ module Parse
434
434
  # Song.all :limit => 2025 # large limits supported.
435
435
  # Song.all :limit => :max # as many records as possible.
436
436
  # @param count [Integer,Symbol] The number of records to return. You may pass :max
437
- # to get as many as 11_000 records with the aid if skipping.
437
+ # to get as many records as possible (Parse-Server dependent).
438
438
  # @return [self]
439
439
  def limit(count)
440
440
  if count.is_a?(Numeric)
@@ -497,10 +497,15 @@ module Parse
497
497
  # # add where :like_count is greater than 20
498
498
  # query.add_constraint(:like_count.gt, 20)
499
499
  #
500
+ # # same, but ignore field formatting
501
+ # query.add_constraint(:like_count.gt, 20, filter: false)
502
+ #
500
503
  # @param operator [Parse::Operator] an operator object containing the operation and operand.
501
504
  # @param value [Object] the value for the constraint.
505
+ # @param opts [Object] A set of options. Passing :filter with false, will skip field formatting.
506
+ # @see Query#format_field
502
507
  # @return [self]
503
- def add_constraint(operator, value = nil, **opts)
508
+ def add_constraint(operator, value = nil, opts = {})
504
509
  @where ||= []
505
510
  constraint = operator # assume Parse::Constraint
506
511
  unless constraint.is_a?(Parse::Constraint)
@@ -607,6 +612,35 @@ module Parse
607
612
  copy_query
608
613
  end
609
614
 
615
+ # Queries can be made using distinct, allowing you find unique values for a specified field.
616
+ # For this to be performant, please remember to index your database.
617
+ # @example
618
+ # # Return a set of unique city names
619
+ # # for users who are greater than 21 years old
620
+ # Parse::Query.all(distinct: :age)
621
+ # query = Parse::Query.new("_User")
622
+ # query.where :age.gt => 21
623
+ # # triggers query
624
+ # query.distinct(:city) #=> ["San Diego", "Los Angeles", "San Juan"]
625
+ # @note This feature requires use of the Master Key in the API.
626
+ # @param field [Symbol|String] The name of the field used for filtering.
627
+ # @version 1.8.0
628
+ def distinct(field)
629
+ if field.nil? == false && field.respond_to?(:to_s)
630
+ # disable counting if it was enabled.
631
+ old_count_value = @count
632
+ @count = nil
633
+ compile_query = compile # temporary store
634
+ # add distinct field
635
+ compile_query[:distinct] = Query.format_field(field).to_sym
636
+ @count = old_count_value
637
+ # perform aggregation
638
+ return client.aggregate_objects(@table, compile_query.as_json, _opts ).result
639
+ else
640
+ raise ArgumentError, "Invalid field name passed to `distinct`."
641
+ end
642
+ end
643
+
610
644
  # Perform a count query.
611
645
  # @example
612
646
  # # get number of songs with a play_count > 10
@@ -714,6 +714,56 @@ module Parse
714
714
  end
715
715
  end
716
716
 
717
+
718
+ class FullTextSearchQueryConstraint < Constraint
719
+ # @!method text_search
720
+ # A registered method on a symbol to create the constraint. Maps to Parse
721
+ # operator "$text" with "$search" subconstraint. Takes a hash of parameters.
722
+ # @example
723
+ # # As many points as you want
724
+ # q.where :field.text_search => {parameters}
725
+ #
726
+ # Where `parameters` can be one of:
727
+ # $term : Specify a field to search (Required)
728
+ # $language : Determines the list of stop words and the rules for tokenizer.
729
+ # $caseSensitive : Enable or disable case sensitive search.
730
+ # $diacriticSensitive : Enable or disable diacritic sensitive search
731
+ #
732
+ # @note This method will automatically add `$` to each key of the parameters
733
+ # hash if it doesn't already have it.
734
+ # @return [WithinPolygonQueryConstraint]
735
+ # @version 1.8.0 (requires Server v2.5.0 or later)
736
+ contraint_keyword :$text
737
+ register :text_search
738
+
739
+ # @return [Hash] the compiled constraint.
740
+ def build
741
+ params = formatted_value
742
+
743
+ params = { :$term => params.to_s } if params.is_a?(String) || params.is_a?(Symbol)
744
+
745
+ unless params.is_a?(Hash)
746
+ raise ArgumentError, '[Parse::Query] Invalid query value parameter passed to'\
747
+ ' `text_search` constraint: Value must be a string or a hash of parameters.'
748
+ end
749
+
750
+ params = params.inject({}) do |h,(k,v)|
751
+ u = k.to_s
752
+ u = u.columnize.prepend('$') unless u.start_with?('$')
753
+ h[u] = v
754
+ h
755
+ end
756
+
757
+ unless params["$term"].present?
758
+ raise ArgumentError, "[Parse::Query] Invalid query value parameter passed to"\
759
+ " `text_search` constraint: Missing required `$term` subkey.\n"\
760
+ "\tExample: #{@operation.operand}.text_search => { term: 'text to search' }"
761
+ end
762
+
763
+ { @operation.operand => { :$text => { :$search => params } } }
764
+ end
765
+ end
766
+
717
767
  end
718
768
 
719
769
  end
@@ -6,6 +6,6 @@ module Parse
6
6
  # The Parse Server SDK for Ruby
7
7
  module Stack
8
8
  # The current version.
9
- VERSION = "1.7.4"
9
+ VERSION = "1.8.0"
10
10
  end
11
11
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: parse-stack
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.7.4
4
+ version: 1.8.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Anthony Persaud
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-05-29 00:00:00.000000000 Z
11
+ date: 2018-09-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activemodel
@@ -184,6 +184,7 @@ files:
184
184
  - bin/server
185
185
  - bin/setup
186
186
  - lib/parse-stack.rb
187
+ - lib/parse/api/aggregate.rb
187
188
  - lib/parse/api/all.rb
188
189
  - lib/parse/api/analytics.rb
189
190
  - lib/parse/api/batch.rb