parse-stack-next 4.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (178) hide show
  1. checksums.yaml +7 -0
  2. data/.bundle/config +2 -0
  3. data/.env.sample +112 -0
  4. data/.env.test +10 -0
  5. data/.github/workflows/ruby.yml +36 -0
  6. data/.gitignore +49 -0
  7. data/.ruby-version +1 -0
  8. data/.solargraph.yml +22 -0
  9. data/CHANGELOG.md +5816 -0
  10. data/Gemfile +30 -0
  11. data/Gemfile.lock +175 -0
  12. data/LICENSE.txt +23 -0
  13. data/Makefile +63 -0
  14. data/README.md +5655 -0
  15. data/Rakefile +573 -0
  16. data/bin/console +38 -0
  17. data/bin/parse-console +136 -0
  18. data/bin/server +17 -0
  19. data/bin/setup +7 -0
  20. data/config/parse-config.json +12 -0
  21. data/docs/TEST_SERVER.md +271 -0
  22. data/docs/_config.yml +1 -0
  23. data/docs/mcp_guide.md +3484 -0
  24. data/docs/mongodb_direct_guide.md +1348 -0
  25. data/docs/mongodb_index_optimization_guide.md +631 -0
  26. data/examples/transaction_example.rb +219 -0
  27. data/lib/parse/acl_scope.rb +728 -0
  28. data/lib/parse/agent/cancellation_token.rb +80 -0
  29. data/lib/parse/agent/constraint_translator.rb +480 -0
  30. data/lib/parse/agent/describe.rb +420 -0
  31. data/lib/parse/agent/errors.rb +133 -0
  32. data/lib/parse/agent/mcp_client.rb +557 -0
  33. data/lib/parse/agent/mcp_dispatcher.rb +1023 -0
  34. data/lib/parse/agent/mcp_rack_app.rb +1143 -0
  35. data/lib/parse/agent/mcp_server.rb +376 -0
  36. data/lib/parse/agent/metadata_audit.rb +259 -0
  37. data/lib/parse/agent/metadata_dsl.rb +733 -0
  38. data/lib/parse/agent/metadata_registry.rb +794 -0
  39. data/lib/parse/agent/pipeline_validator.rb +82 -0
  40. data/lib/parse/agent/prompts.rb +351 -0
  41. data/lib/parse/agent/rate_limiter.rb +158 -0
  42. data/lib/parse/agent/relation_graph.rb +162 -0
  43. data/lib/parse/agent/result_formatter.rb +453 -0
  44. data/lib/parse/agent/tools.rb +5489 -0
  45. data/lib/parse/agent.rb +3249 -0
  46. data/lib/parse/api/aggregate.rb +79 -0
  47. data/lib/parse/api/all.rb +26 -0
  48. data/lib/parse/api/analytics.rb +18 -0
  49. data/lib/parse/api/batch.rb +33 -0
  50. data/lib/parse/api/cloud_functions.rb +58 -0
  51. data/lib/parse/api/config.rb +125 -0
  52. data/lib/parse/api/files.rb +29 -0
  53. data/lib/parse/api/hooks.rb +117 -0
  54. data/lib/parse/api/objects.rb +146 -0
  55. data/lib/parse/api/path_segment.rb +75 -0
  56. data/lib/parse/api/push.rb +20 -0
  57. data/lib/parse/api/schema.rb +49 -0
  58. data/lib/parse/api/server.rb +50 -0
  59. data/lib/parse/api/sessions.rb +24 -0
  60. data/lib/parse/api/users.rb +250 -0
  61. data/lib/parse/atlas_search/index_manager.rb +353 -0
  62. data/lib/parse/atlas_search/result.rb +204 -0
  63. data/lib/parse/atlas_search/search_builder.rb +604 -0
  64. data/lib/parse/atlas_search/session.rb +253 -0
  65. data/lib/parse/atlas_search.rb +995 -0
  66. data/lib/parse/client/authentication.rb +97 -0
  67. data/lib/parse/client/batch.rb +234 -0
  68. data/lib/parse/client/body_builder.rb +240 -0
  69. data/lib/parse/client/caching.rb +203 -0
  70. data/lib/parse/client/logging.rb +293 -0
  71. data/lib/parse/client/profiling.rb +181 -0
  72. data/lib/parse/client/protocol.rb +91 -0
  73. data/lib/parse/client/request.rb +233 -0
  74. data/lib/parse/client/response.rb +208 -0
  75. data/lib/parse/client.rb +1104 -0
  76. data/lib/parse/clp_scope.rb +361 -0
  77. data/lib/parse/live_query/circuit_breaker.rb +256 -0
  78. data/lib/parse/live_query/client.rb +1001 -0
  79. data/lib/parse/live_query/configuration.rb +224 -0
  80. data/lib/parse/live_query/event.rb +115 -0
  81. data/lib/parse/live_query/event_queue.rb +272 -0
  82. data/lib/parse/live_query/health_monitor.rb +214 -0
  83. data/lib/parse/live_query/logging.rb +149 -0
  84. data/lib/parse/live_query/subscription.rb +294 -0
  85. data/lib/parse/live_query.rb +163 -0
  86. data/lib/parse/lookup_rewriter.rb +445 -0
  87. data/lib/parse/model/acl.rb +968 -0
  88. data/lib/parse/model/associations/belongs_to.rb +275 -0
  89. data/lib/parse/model/associations/collection_proxy.rb +435 -0
  90. data/lib/parse/model/associations/has_many.rb +597 -0
  91. data/lib/parse/model/associations/has_one.rb +158 -0
  92. data/lib/parse/model/associations/pointer_collection_proxy.rb +134 -0
  93. data/lib/parse/model/associations/relation_collection_proxy.rb +177 -0
  94. data/lib/parse/model/bytes.rb +62 -0
  95. data/lib/parse/model/classes/audience.rb +262 -0
  96. data/lib/parse/model/classes/installation.rb +363 -0
  97. data/lib/parse/model/classes/job_schedule.rb +153 -0
  98. data/lib/parse/model/classes/job_status.rb +264 -0
  99. data/lib/parse/model/classes/product.rb +75 -0
  100. data/lib/parse/model/classes/push_status.rb +263 -0
  101. data/lib/parse/model/classes/role.rb +751 -0
  102. data/lib/parse/model/classes/session.rb +201 -0
  103. data/lib/parse/model/classes/user.rb +943 -0
  104. data/lib/parse/model/clp.rb +544 -0
  105. data/lib/parse/model/core/actions.rb +1268 -0
  106. data/lib/parse/model/core/builder.rb +139 -0
  107. data/lib/parse/model/core/create_lock.rb +386 -0
  108. data/lib/parse/model/core/describe.rb +382 -0
  109. data/lib/parse/model/core/enhanced_change_tracking.rb +159 -0
  110. data/lib/parse/model/core/errors.rb +38 -0
  111. data/lib/parse/model/core/fetching.rb +566 -0
  112. data/lib/parse/model/core/field_guards.rb +220 -0
  113. data/lib/parse/model/core/indexing.rb +382 -0
  114. data/lib/parse/model/core/parse_reference.rb +407 -0
  115. data/lib/parse/model/core/properties.rb +809 -0
  116. data/lib/parse/model/core/querying.rb +491 -0
  117. data/lib/parse/model/core/schema.rb +202 -0
  118. data/lib/parse/model/core/search_indexing.rb +174 -0
  119. data/lib/parse/model/date.rb +88 -0
  120. data/lib/parse/model/email.rb +213 -0
  121. data/lib/parse/model/file.rb +527 -0
  122. data/lib/parse/model/geojson.rb +271 -0
  123. data/lib/parse/model/geopoint.rb +261 -0
  124. data/lib/parse/model/model.rb +260 -0
  125. data/lib/parse/model/object.rb +2068 -0
  126. data/lib/parse/model/phone.rb +520 -0
  127. data/lib/parse/model/pointer.rb +443 -0
  128. data/lib/parse/model/polygon.rb +406 -0
  129. data/lib/parse/model/push.rb +975 -0
  130. data/lib/parse/model/shortnames.rb +8 -0
  131. data/lib/parse/model/time_zone.rb +141 -0
  132. data/lib/parse/model/validations/uniqueness_validator.rb +97 -0
  133. data/lib/parse/model/validations.rb +96 -0
  134. data/lib/parse/mongodb.rb +2300 -0
  135. data/lib/parse/pipeline_security.rb +554 -0
  136. data/lib/parse/query/constraint.rb +198 -0
  137. data/lib/parse/query/constraints.rb +3279 -0
  138. data/lib/parse/query/cursor.rb +434 -0
  139. data/lib/parse/query/n_plus_one_detector.rb +445 -0
  140. data/lib/parse/query/operation.rb +104 -0
  141. data/lib/parse/query/ordering.rb +66 -0
  142. data/lib/parse/query.rb +7028 -0
  143. data/lib/parse/schema/index_migrator.rb +291 -0
  144. data/lib/parse/schema/search_index_migrator.rb +289 -0
  145. data/lib/parse/schema.rb +494 -0
  146. data/lib/parse/stack/generators/rails.rb +40 -0
  147. data/lib/parse/stack/generators/templates/model.erb +51 -0
  148. data/lib/parse/stack/generators/templates/model_installation.rb +4 -0
  149. data/lib/parse/stack/generators/templates/model_role.rb +4 -0
  150. data/lib/parse/stack/generators/templates/model_session.rb +4 -0
  151. data/lib/parse/stack/generators/templates/model_user.rb +11 -0
  152. data/lib/parse/stack/generators/templates/parse.rb +12 -0
  153. data/lib/parse/stack/generators/templates/webhooks.rb +10 -0
  154. data/lib/parse/stack/railtie.rb +18 -0
  155. data/lib/parse/stack/tasks.rb +563 -0
  156. data/lib/parse/stack/version.rb +11 -0
  157. data/lib/parse/stack.rb +455 -0
  158. data/lib/parse/two_factor_auth/user_extension.rb +449 -0
  159. data/lib/parse/two_factor_auth.rb +310 -0
  160. data/lib/parse/webhooks/payload.rb +360 -0
  161. data/lib/parse/webhooks/registration.rb +199 -0
  162. data/lib/parse/webhooks/replay_protection.rb +189 -0
  163. data/lib/parse/webhooks.rb +510 -0
  164. data/lib/parse-stack-next.rb +5 -0
  165. data/lib/parse-stack.rb +5 -0
  166. data/parse-stack-next.gemspec +82 -0
  167. data/parse-stack.png +0 -0
  168. data/scripts/debug-ips.js +35 -0
  169. data/scripts/docker/Dockerfile.parse +13 -0
  170. data/scripts/docker/atlas-init.js +284 -0
  171. data/scripts/docker/docker-compose.atlas.yml +76 -0
  172. data/scripts/docker/docker-compose.test.yml +106 -0
  173. data/scripts/docker/mongo-init.js +21 -0
  174. data/scripts/eval_mcp_with_lm_studio.rb +274 -0
  175. data/scripts/start-parse.sh +90 -0
  176. data/scripts/start_mcp_server.rb +78 -0
  177. data/scripts/test_server_connection.rb +82 -0
  178. metadata +377 -0
@@ -0,0 +1,260 @@
1
+ # encoding: UTF-8
2
+ # frozen_string_literal: true
3
+
4
+ require "active_model"
5
+ require "active_support"
6
+ require "active_support/inflector"
7
+ require "active_support/core_ext/object"
8
+ require "active_model/serializers/json"
9
+ require_relative "../client"
10
+
11
+ module Parse
12
+ # Find a corresponding Parse::Object subclass for this string or symbol
13
+ # @param className [String] The name of the Parse class as string (ex. "_User")
14
+ # @return [Class] The proper subclass matching the className.
15
+ def self.classify(className)
16
+ Parse::Model.find_class className.to_parse_class
17
+ end
18
+
19
+ # The core model of all Parse-Stack classes. This class works by providing a
20
+ # baseline for all subclass objects to support ActiveModel features such as
21
+ # serialization, dirty tracking, callbacks, etc.
22
+ # @see ActiveModel
23
+ class Model
24
+ include Client::Connectable # allows easy default Parse::Client access
25
+ include ::ActiveModel::Model
26
+ include ::ActiveModel::Serializers::JSON # support for JSON Serializers
27
+ include ::ActiveModel::Dirty # adds dirty tracking support
28
+ include ::ActiveModel::Conversion
29
+ extend ::ActiveModel::Callbacks # callback support on save, update, delete, etc.
30
+ extend ::ActiveModel::Naming # provides the methods for getting class names from Model classes
31
+
32
+ # Add dirty? methods as aliases for changed? methods
33
+ # These provide compatibility with expected API
34
+ def dirty?(field = nil)
35
+ if field.nil?
36
+ changed?
37
+ else
38
+ field_changed = "#{field}_changed?"
39
+ respond_to?(field_changed) ? send(field_changed) : false
40
+ end
41
+ end
42
+
43
+ # The name of the field in a hash that contains information about the type
44
+ # of data the hash represents.
45
+ TYPE_FIELD = "__type".freeze
46
+
47
+ # The objectId field in Parse Objects.
48
+ OBJECT_ID = "objectId".freeze
49
+ # @see OBJECT_ID
50
+ ID = "id".freeze
51
+
52
+ # The key field for getting class information.
53
+ KEY_CLASS_NAME = "className".freeze
54
+ # @deprecated Use OBJECT_ID instead.
55
+ KEY_OBJECT_ID = "objectId".freeze
56
+ # The key field for getting the created at date of an object hash.
57
+ KEY_CREATED_AT = "createdAt"
58
+ # The key field for getting the updated at date of an object hash.
59
+ KEY_UPDATED_AT = "updatedAt"
60
+ # The collection for Users in Parse. Used by Parse::User.
61
+ CLASS_USER = "_User"
62
+ # The collection for Installations in Parse. Used by Parse::Installation.
63
+ CLASS_INSTALLATION = "_Installation"
64
+ # The collection for revocable Sessions in Parse. Used by Parse::Session.
65
+ CLASS_SESSION = "_Session"
66
+ # The collection for Roles in Parse. Used by Parse::Role.
67
+ CLASS_ROLE = "_Role"
68
+ # The collection for to store Products (in-App purchases) in Parse. Used by Parse::Product.
69
+ CLASS_PRODUCT = "_Product"
70
+ # The collection for Audiences in Parse. Used by Parse::Audience.
71
+ CLASS_AUDIENCE = "_Audience"
72
+ # The collection for Push Status in Parse. Used by Parse::PushStatus.
73
+ CLASS_PUSH_STATUS = "_PushStatus"
74
+ # The collection for background job status in Parse. Used by Parse::JobStatus.
75
+ CLASS_JOB_STATUS = "_JobStatus"
76
+ # The collection for scheduled background jobs in Parse. Used by Parse::JobSchedule.
77
+ CLASS_JOB_SCHEDULE = "_JobSchedule"
78
+ # The internal schema collection in Parse. Managed by Parse Server.
79
+ CLASS_SCHEMA = "_SCHEMA"
80
+ # The type label for hashes containing file data. Used by Parse::File.
81
+ TYPE_FILE = "File"
82
+ # The type label for hashes containing geopoints. Used by Parse::GeoPoint.
83
+ TYPE_GEOPOINT = "GeoPoint"
84
+ # The type label for hashes containing polygons. Used by Parse::Polygon.
85
+ TYPE_POLYGON = "Polygon"
86
+ # The type label for hashes containing a Parse object. Used by Parse::Object and subclasses.
87
+ TYPE_OBJECT = "Object"
88
+ # The type label for hashes containing a Parse date object. Used by Parse::Date.
89
+ TYPE_DATE = "Date"
90
+ # The type label for hashes containing 'byte' data. Used by Parse::Bytes.
91
+ TYPE_BYTES = "Bytes"
92
+ # The type label for hashes containing ACL data. Used by Parse::ACL
93
+ TYPE_ACL = "ACL"
94
+ # The type label for hashes storing numeric data.
95
+ TYPE_NUMBER = "Number"
96
+ # The type label for hashes containing a Parse pointer.
97
+ TYPE_POINTER = "Pointer"
98
+ # The type label for hashes representing relational data.
99
+ TYPE_RELATION = "Relation"
100
+
101
+ # To support being able to have different ruby class names from the 'table'
102
+ # names used in Parse, we will need to have a dynamic lookup system where
103
+ # when a parse class name received, we go through all of our subclasses to determine
104
+ # which Parse::Object subclass is responsible for handling this Parse table class.
105
+ # we use @@model_cache to cache the results of the algorithm since we do this frequently
106
+ # when encoding and decoding objects.
107
+ # @!visibility private
108
+ @@model_cache = {}
109
+
110
+ class << self
111
+ # @!attribute self.raise_on_save_failure
112
+ # By default, we return `true` or `false` for save and destroy operations.
113
+ # If you prefer to have `Parse::Object` raise an exception instead, you
114
+ # can tell to do so either globally or on a per-model basis. When a save
115
+ # fails, it will raise a `Parse::RecordNotSaved`.
116
+ #
117
+ # @example
118
+ # Parse::Model.raise_on_save_failure = true # globally across all models
119
+ # Song.raise_on_save_failure = true # per-model
120
+ #
121
+ # # or per-instance raise on failure
122
+ # song.save!
123
+ #
124
+ # When enabled, if an error is returned by Parse due to saving or
125
+ # destroying a record, due to your `before_save` or `before_delete`
126
+ # validation cloud code triggers, `Parse::Object` will return the a
127
+ # `Parse::RecordNotSaved` exception type. This exception has an
128
+ # instance method of `#object` which contains the object that failed to save.
129
+ #
130
+ # @return [Boolean]
131
+
132
+ def raise_on_save_failure
133
+ @global_raise_on_save_failure ||= false
134
+ end
135
+
136
+ def raise_on_save_failure=(bool)
137
+ @global_raise_on_save_failure = bool
138
+ end
139
+ end
140
+
141
+ # Find a Parse::Model subclass matching this type or Pares collection name.
142
+ # This helper method is useful to find the corresponding class ruby Parse::Object subclass that handles
143
+ # the provided parse class.
144
+ #
145
+ # @example
146
+ # Parse::Model.find_class('_User') # => Parse::User
147
+ # Parse::Model.find_class('_Date') # => Parse::Date
148
+ # Parse::Model.find_class('Installation') # => Parse::Installation
149
+ #
150
+ # class Artist < Parse::Object
151
+ # parse_class "Musician"
152
+ # end
153
+ #
154
+ # Parse::Model.find_class("Musician") # => Artist
155
+ #
156
+ # @param str [String] the class name
157
+ # @return [Parse::Object] a Parse::Object subclass or a specific Parse type.
158
+ def self.find_class(str)
159
+ return Parse::File if str == TYPE_FILE
160
+ return Parse::GeoPoint if str == TYPE_GEOPOINT
161
+ return Parse::Polygon if str == TYPE_POLYGON
162
+ return Parse::Date if str == TYPE_DATE
163
+ return Parse::Bytes if str == TYPE_BYTES
164
+ # return Parse::User if str == "User"
165
+ # return Parse::Installation if str == "Installation"
166
+
167
+ str = str.to_s
168
+ # Basically go through all Parse::Object subclasses and see who is has a parse_class
169
+ # set to this string. We will cache the results for future use.
170
+ #
171
+ # Anonymous descendants (`Class.new(Parse::Object)` without an
172
+ # assigned constant) have `model_name.name == nil`, and the default
173
+ # `parse_class` implementation calls `model_name.name` and raises
174
+ # `ActiveModel::Name: Class name cannot be blank`. An unrescued
175
+ # raise here poisons every subsequent `find_class` call (cf.
176
+ # canonical-filter lookups, hidden-class registry, ACLScope role
177
+ # expansion). Some tests, however, override `parse_class` on an
178
+ # anonymous subclass to return a literal String — those are still
179
+ # legitimate findables. Rescue per-descendant so the iteration
180
+ # continues past the unnamed-and-default-parse_class case while
181
+ # still considering anonymous-but-overridden ones.
182
+ @@model_cache[str] ||= Parse::Object.descendants.find do |f|
183
+ begin
184
+ cls = f.parse_class
185
+ rescue StandardError
186
+ next false
187
+ end
188
+ cls == str || cls == "_#{str}"
189
+ end
190
+ end
191
+ end
192
+ end
193
+
194
+ # Add extensions to the String class.
195
+ class String
196
+ # This method returns a camel-cased version of the string with the first letter
197
+ # of the string in lower case. This is the standard naming convention for Parse columns
198
+ # and property fields. This has special exception to the string "id", which returns
199
+ # "objectId". This is the default name filtering method for all defined properties and
200
+ # query keys in Parse::Query.
201
+ #
202
+ # @example
203
+ # "my_field".columnize # => "myField"
204
+ # "MyDataColumn".columnize # => "myDataColumn"
205
+ # "id".columnize # => "objectId" (special)
206
+ #
207
+ # @return [String]
208
+ # @see Parse::Query.field_formatter
209
+ def columnize
210
+ return Parse::Model::OBJECT_ID if self == Parse::Model::ID
211
+ u = "_".freeze
212
+ (first == u ? sub(u, "") : self).camelize(:lower)
213
+ end
214
+
215
+ # Convert a string to a Parse class name. This method tries to find a
216
+ # responsible Parse::Object subclass that potentially matches the given string.
217
+ # If no match is found, it returns the camelized version of the string. This method
218
+ # is used internally for matching association attributes to registered
219
+ # Parse::Object subclasses. The method can also singularize the name before
220
+ # performing conversion.
221
+ #
222
+ # @example
223
+ # "users".to_parse_class(singularize: true) # => "_User"
224
+ # "users".to_parse_class # => "Users"
225
+ # "song_data".to_parse_class # => "SongData"
226
+ #
227
+ # @param singularize [Boolean] whether the string should be singularized first before performing conversion.
228
+ # @return [String] the matching Parse class for this string.
229
+ def to_parse_class(singularize: false)
230
+ final_class = singularize ? self.singularize.camelize : self.camelize
231
+ klass = Parse::Model.find_class(final_class) || Parse::Model.find_class(self)
232
+ #handles the case that a class has a custom parse table
233
+ final_class = klass.parse_class if klass.present?
234
+ final_class
235
+ end
236
+ end
237
+
238
+ # Add extensions to the Symbol class.
239
+ class Symbol
240
+ # @return [String] a lower-first-camelcased version of the symbol
241
+ # @see String#columnize
242
+ def columnize
243
+ to_s.columnize.to_sym
244
+ end
245
+
246
+ # @see String#singularize
247
+ def singularize
248
+ to_s.singularize
249
+ end
250
+
251
+ # @see String#camelize
252
+ def camelize
253
+ to_s.camelize
254
+ end
255
+
256
+ # @see String#to_parse_class
257
+ def to_parse_class(singularize: false)
258
+ to_s.to_parse_class(singularize: singularize)
259
+ end
260
+ end