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.
- checksums.yaml +7 -0
- data/.bundle/config +2 -0
- data/.env.sample +112 -0
- data/.env.test +10 -0
- data/.github/workflows/ruby.yml +36 -0
- data/.gitignore +49 -0
- data/.ruby-version +1 -0
- data/.solargraph.yml +22 -0
- data/CHANGELOG.md +5816 -0
- data/Gemfile +30 -0
- data/Gemfile.lock +175 -0
- data/LICENSE.txt +23 -0
- data/Makefile +63 -0
- data/README.md +5655 -0
- data/Rakefile +573 -0
- data/bin/console +38 -0
- data/bin/parse-console +136 -0
- data/bin/server +17 -0
- data/bin/setup +7 -0
- data/config/parse-config.json +12 -0
- data/docs/TEST_SERVER.md +271 -0
- data/docs/_config.yml +1 -0
- data/docs/mcp_guide.md +3484 -0
- data/docs/mongodb_direct_guide.md +1348 -0
- data/docs/mongodb_index_optimization_guide.md +631 -0
- data/examples/transaction_example.rb +219 -0
- data/lib/parse/acl_scope.rb +728 -0
- data/lib/parse/agent/cancellation_token.rb +80 -0
- data/lib/parse/agent/constraint_translator.rb +480 -0
- data/lib/parse/agent/describe.rb +420 -0
- data/lib/parse/agent/errors.rb +133 -0
- data/lib/parse/agent/mcp_client.rb +557 -0
- data/lib/parse/agent/mcp_dispatcher.rb +1023 -0
- data/lib/parse/agent/mcp_rack_app.rb +1143 -0
- data/lib/parse/agent/mcp_server.rb +376 -0
- data/lib/parse/agent/metadata_audit.rb +259 -0
- data/lib/parse/agent/metadata_dsl.rb +733 -0
- data/lib/parse/agent/metadata_registry.rb +794 -0
- data/lib/parse/agent/pipeline_validator.rb +82 -0
- data/lib/parse/agent/prompts.rb +351 -0
- data/lib/parse/agent/rate_limiter.rb +158 -0
- data/lib/parse/agent/relation_graph.rb +162 -0
- data/lib/parse/agent/result_formatter.rb +453 -0
- data/lib/parse/agent/tools.rb +5489 -0
- data/lib/parse/agent.rb +3249 -0
- data/lib/parse/api/aggregate.rb +79 -0
- data/lib/parse/api/all.rb +26 -0
- data/lib/parse/api/analytics.rb +18 -0
- data/lib/parse/api/batch.rb +33 -0
- data/lib/parse/api/cloud_functions.rb +58 -0
- data/lib/parse/api/config.rb +125 -0
- data/lib/parse/api/files.rb +29 -0
- data/lib/parse/api/hooks.rb +117 -0
- data/lib/parse/api/objects.rb +146 -0
- data/lib/parse/api/path_segment.rb +75 -0
- data/lib/parse/api/push.rb +20 -0
- data/lib/parse/api/schema.rb +49 -0
- data/lib/parse/api/server.rb +50 -0
- data/lib/parse/api/sessions.rb +24 -0
- data/lib/parse/api/users.rb +250 -0
- data/lib/parse/atlas_search/index_manager.rb +353 -0
- data/lib/parse/atlas_search/result.rb +204 -0
- data/lib/parse/atlas_search/search_builder.rb +604 -0
- data/lib/parse/atlas_search/session.rb +253 -0
- data/lib/parse/atlas_search.rb +995 -0
- data/lib/parse/client/authentication.rb +97 -0
- data/lib/parse/client/batch.rb +234 -0
- data/lib/parse/client/body_builder.rb +240 -0
- data/lib/parse/client/caching.rb +203 -0
- data/lib/parse/client/logging.rb +293 -0
- data/lib/parse/client/profiling.rb +181 -0
- data/lib/parse/client/protocol.rb +91 -0
- data/lib/parse/client/request.rb +233 -0
- data/lib/parse/client/response.rb +208 -0
- data/lib/parse/client.rb +1104 -0
- data/lib/parse/clp_scope.rb +361 -0
- data/lib/parse/live_query/circuit_breaker.rb +256 -0
- data/lib/parse/live_query/client.rb +1001 -0
- data/lib/parse/live_query/configuration.rb +224 -0
- data/lib/parse/live_query/event.rb +115 -0
- data/lib/parse/live_query/event_queue.rb +272 -0
- data/lib/parse/live_query/health_monitor.rb +214 -0
- data/lib/parse/live_query/logging.rb +149 -0
- data/lib/parse/live_query/subscription.rb +294 -0
- data/lib/parse/live_query.rb +163 -0
- data/lib/parse/lookup_rewriter.rb +445 -0
- data/lib/parse/model/acl.rb +968 -0
- data/lib/parse/model/associations/belongs_to.rb +275 -0
- data/lib/parse/model/associations/collection_proxy.rb +435 -0
- data/lib/parse/model/associations/has_many.rb +597 -0
- data/lib/parse/model/associations/has_one.rb +158 -0
- data/lib/parse/model/associations/pointer_collection_proxy.rb +134 -0
- data/lib/parse/model/associations/relation_collection_proxy.rb +177 -0
- data/lib/parse/model/bytes.rb +62 -0
- data/lib/parse/model/classes/audience.rb +262 -0
- data/lib/parse/model/classes/installation.rb +363 -0
- data/lib/parse/model/classes/job_schedule.rb +153 -0
- data/lib/parse/model/classes/job_status.rb +264 -0
- data/lib/parse/model/classes/product.rb +75 -0
- data/lib/parse/model/classes/push_status.rb +263 -0
- data/lib/parse/model/classes/role.rb +751 -0
- data/lib/parse/model/classes/session.rb +201 -0
- data/lib/parse/model/classes/user.rb +943 -0
- data/lib/parse/model/clp.rb +544 -0
- data/lib/parse/model/core/actions.rb +1268 -0
- data/lib/parse/model/core/builder.rb +139 -0
- data/lib/parse/model/core/create_lock.rb +386 -0
- data/lib/parse/model/core/describe.rb +382 -0
- data/lib/parse/model/core/enhanced_change_tracking.rb +159 -0
- data/lib/parse/model/core/errors.rb +38 -0
- data/lib/parse/model/core/fetching.rb +566 -0
- data/lib/parse/model/core/field_guards.rb +220 -0
- data/lib/parse/model/core/indexing.rb +382 -0
- data/lib/parse/model/core/parse_reference.rb +407 -0
- data/lib/parse/model/core/properties.rb +809 -0
- data/lib/parse/model/core/querying.rb +491 -0
- data/lib/parse/model/core/schema.rb +202 -0
- data/lib/parse/model/core/search_indexing.rb +174 -0
- data/lib/parse/model/date.rb +88 -0
- data/lib/parse/model/email.rb +213 -0
- data/lib/parse/model/file.rb +527 -0
- data/lib/parse/model/geojson.rb +271 -0
- data/lib/parse/model/geopoint.rb +261 -0
- data/lib/parse/model/model.rb +260 -0
- data/lib/parse/model/object.rb +2068 -0
- data/lib/parse/model/phone.rb +520 -0
- data/lib/parse/model/pointer.rb +443 -0
- data/lib/parse/model/polygon.rb +406 -0
- data/lib/parse/model/push.rb +975 -0
- data/lib/parse/model/shortnames.rb +8 -0
- data/lib/parse/model/time_zone.rb +141 -0
- data/lib/parse/model/validations/uniqueness_validator.rb +97 -0
- data/lib/parse/model/validations.rb +96 -0
- data/lib/parse/mongodb.rb +2300 -0
- data/lib/parse/pipeline_security.rb +554 -0
- data/lib/parse/query/constraint.rb +198 -0
- data/lib/parse/query/constraints.rb +3279 -0
- data/lib/parse/query/cursor.rb +434 -0
- data/lib/parse/query/n_plus_one_detector.rb +445 -0
- data/lib/parse/query/operation.rb +104 -0
- data/lib/parse/query/ordering.rb +66 -0
- data/lib/parse/query.rb +7028 -0
- data/lib/parse/schema/index_migrator.rb +291 -0
- data/lib/parse/schema/search_index_migrator.rb +289 -0
- data/lib/parse/schema.rb +494 -0
- data/lib/parse/stack/generators/rails.rb +40 -0
- data/lib/parse/stack/generators/templates/model.erb +51 -0
- data/lib/parse/stack/generators/templates/model_installation.rb +4 -0
- data/lib/parse/stack/generators/templates/model_role.rb +4 -0
- data/lib/parse/stack/generators/templates/model_session.rb +4 -0
- data/lib/parse/stack/generators/templates/model_user.rb +11 -0
- data/lib/parse/stack/generators/templates/parse.rb +12 -0
- data/lib/parse/stack/generators/templates/webhooks.rb +10 -0
- data/lib/parse/stack/railtie.rb +18 -0
- data/lib/parse/stack/tasks.rb +563 -0
- data/lib/parse/stack/version.rb +11 -0
- data/lib/parse/stack.rb +455 -0
- data/lib/parse/two_factor_auth/user_extension.rb +449 -0
- data/lib/parse/two_factor_auth.rb +310 -0
- data/lib/parse/webhooks/payload.rb +360 -0
- data/lib/parse/webhooks/registration.rb +199 -0
- data/lib/parse/webhooks/replay_protection.rb +189 -0
- data/lib/parse/webhooks.rb +510 -0
- data/lib/parse-stack-next.rb +5 -0
- data/lib/parse-stack.rb +5 -0
- data/parse-stack-next.gemspec +82 -0
- data/parse-stack.png +0 -0
- data/scripts/debug-ips.js +35 -0
- data/scripts/docker/Dockerfile.parse +13 -0
- data/scripts/docker/atlas-init.js +284 -0
- data/scripts/docker/docker-compose.atlas.yml +76 -0
- data/scripts/docker/docker-compose.test.yml +106 -0
- data/scripts/docker/mongo-init.js +21 -0
- data/scripts/eval_mcp_with_lm_studio.rb +274 -0
- data/scripts/start-parse.sh +90 -0
- data/scripts/start_mcp_server.rb +78 -0
- data/scripts/test_server_connection.rb +82 -0
- metadata +377 -0
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
# Transaction Example for Parse-Stack
|
|
3
|
+
#
|
|
4
|
+
# This example demonstrates how to use transactions to ensure atomic operations
|
|
5
|
+
# across multiple Parse objects.
|
|
6
|
+
|
|
7
|
+
require 'parse/stack'
|
|
8
|
+
|
|
9
|
+
# Configure your Parse application
|
|
10
|
+
Parse.setup(
|
|
11
|
+
app_id: ENV['PARSE_APP_ID'] || 'your-app-id',
|
|
12
|
+
api_key: ENV['PARSE_API_KEY'] || 'your-api-key',
|
|
13
|
+
server_url: ENV['PARSE_SERVER_URL'] || 'http://localhost:1337/parse'
|
|
14
|
+
)
|
|
15
|
+
|
|
16
|
+
# Define example models
|
|
17
|
+
class Team < Parse::Object
|
|
18
|
+
property :name
|
|
19
|
+
property :owner, :pointer, class_name: 'User'
|
|
20
|
+
property :member_count, :integer, default: 0
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
class Membership < Parse::Object
|
|
24
|
+
property :user, :pointer, class_name: 'User'
|
|
25
|
+
property :team, :pointer, class_name: 'Team'
|
|
26
|
+
property :access_level, :string
|
|
27
|
+
property :grant, :string
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
class Project < Parse::Object
|
|
31
|
+
property :name
|
|
32
|
+
property :team, :pointer, class_name: 'Team'
|
|
33
|
+
property :owner, :pointer, class_name: 'User'
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
# Example 1: Basic transaction with explicit batch operations
|
|
37
|
+
def transfer_project_ownership_basic(project, new_owner)
|
|
38
|
+
Parse::Object.transaction do |batch|
|
|
39
|
+
# Get old owner
|
|
40
|
+
old_owner = project.owner
|
|
41
|
+
|
|
42
|
+
# Find or create new owner membership
|
|
43
|
+
new_owner_membership = Membership.first(
|
|
44
|
+
project: project,
|
|
45
|
+
user: new_owner
|
|
46
|
+
)
|
|
47
|
+
|
|
48
|
+
if new_owner_membership.nil?
|
|
49
|
+
new_owner_membership = Membership.new(
|
|
50
|
+
project: project,
|
|
51
|
+
team: project.team,
|
|
52
|
+
user: new_owner,
|
|
53
|
+
grant: 'project',
|
|
54
|
+
access_level: 'owner'
|
|
55
|
+
)
|
|
56
|
+
batch.add(new_owner_membership)
|
|
57
|
+
else
|
|
58
|
+
new_owner_membership.access_level = 'owner'
|
|
59
|
+
batch.add(new_owner_membership)
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
# Demote old owner if they have a membership
|
|
63
|
+
if old_owner.present?
|
|
64
|
+
old_owner_membership = Membership.first(
|
|
65
|
+
project: project,
|
|
66
|
+
user: old_owner
|
|
67
|
+
)
|
|
68
|
+
|
|
69
|
+
if old_owner_membership.present?
|
|
70
|
+
old_owner_membership.access_level = 'admin'
|
|
71
|
+
batch.add(old_owner_membership)
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
# Update project owner
|
|
76
|
+
project.owner = new_owner
|
|
77
|
+
batch.add(project)
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
puts "Successfully transferred ownership"
|
|
81
|
+
rescue Parse::Error => e
|
|
82
|
+
puts "Transaction failed: #{e.message}"
|
|
83
|
+
false
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
# Example 2: Transaction with automatic batching via return value
|
|
87
|
+
def transfer_project_ownership_auto(project, new_owner)
|
|
88
|
+
results = Parse::Object.transaction do
|
|
89
|
+
old_owner = project.owner
|
|
90
|
+
objects_to_save = []
|
|
91
|
+
|
|
92
|
+
# Find or create new owner membership
|
|
93
|
+
new_owner_membership = Membership.first(
|
|
94
|
+
project: project,
|
|
95
|
+
user: new_owner
|
|
96
|
+
) || Membership.new(
|
|
97
|
+
project: project,
|
|
98
|
+
team: project.team,
|
|
99
|
+
user: new_owner,
|
|
100
|
+
grant: 'project'
|
|
101
|
+
)
|
|
102
|
+
|
|
103
|
+
new_owner_membership.access_level = 'owner'
|
|
104
|
+
objects_to_save << new_owner_membership
|
|
105
|
+
|
|
106
|
+
# Demote old owner
|
|
107
|
+
if old_owner.present?
|
|
108
|
+
old_owner_membership = Membership.first(
|
|
109
|
+
project: project,
|
|
110
|
+
user: old_owner
|
|
111
|
+
)
|
|
112
|
+
|
|
113
|
+
if old_owner_membership.present?
|
|
114
|
+
old_owner_membership.access_level = 'admin'
|
|
115
|
+
objects_to_save << old_owner_membership
|
|
116
|
+
end
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
# Update project
|
|
120
|
+
project.owner = new_owner
|
|
121
|
+
objects_to_save << project
|
|
122
|
+
|
|
123
|
+
# Return array of objects to be saved in transaction
|
|
124
|
+
objects_to_save
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
puts "Transaction completed with #{results.count} operations"
|
|
128
|
+
true
|
|
129
|
+
rescue Parse::Error => e
|
|
130
|
+
puts "Transaction failed: #{e.message}"
|
|
131
|
+
false
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
# Example 3: Complex transaction with validation
|
|
135
|
+
def complex_team_operation(team, new_members, new_owner)
|
|
136
|
+
Parse::Object.transaction(retries: 3) do |batch|
|
|
137
|
+
# Validate new owner is in new members list
|
|
138
|
+
unless new_members.include?(new_owner)
|
|
139
|
+
raise Parse::Error, "New owner must be in members list"
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
# Update team
|
|
143
|
+
team.owner = new_owner
|
|
144
|
+
team.member_count = new_members.count
|
|
145
|
+
batch.add(team)
|
|
146
|
+
|
|
147
|
+
# Create memberships for all new members
|
|
148
|
+
new_members.each do |member|
|
|
149
|
+
membership = Membership.new(
|
|
150
|
+
team: team,
|
|
151
|
+
user: member,
|
|
152
|
+
grant: 'team',
|
|
153
|
+
access_level: member == new_owner ? 'owner' : 'member'
|
|
154
|
+
)
|
|
155
|
+
batch.add(membership)
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
# Create a project for the team
|
|
159
|
+
project = Project.new(
|
|
160
|
+
name: "#{team.name} Project",
|
|
161
|
+
team: team,
|
|
162
|
+
owner: new_owner
|
|
163
|
+
)
|
|
164
|
+
batch.add(project)
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
puts "Complex operation completed successfully"
|
|
168
|
+
rescue Parse::Error => e
|
|
169
|
+
puts "Complex operation failed: #{e.message}"
|
|
170
|
+
raise # Re-raise to propagate error
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
# Example 4: Transaction with conflict retry
|
|
174
|
+
def increment_counters_with_retry(objects)
|
|
175
|
+
Parse::Object.transaction(retries: 10) do
|
|
176
|
+
objects.each do |obj|
|
|
177
|
+
obj.increment(:counter)
|
|
178
|
+
end
|
|
179
|
+
objects # Return objects to be saved
|
|
180
|
+
end
|
|
181
|
+
rescue Parse::Error => e
|
|
182
|
+
if e.message.include?("251")
|
|
183
|
+
puts "Transaction conflict after all retries"
|
|
184
|
+
else
|
|
185
|
+
puts "Transaction error: #{e.message}"
|
|
186
|
+
end
|
|
187
|
+
raise
|
|
188
|
+
end
|
|
189
|
+
|
|
190
|
+
# Main execution examples
|
|
191
|
+
if __FILE__ == $0
|
|
192
|
+
puts "Parse Transaction Examples"
|
|
193
|
+
puts "========================="
|
|
194
|
+
|
|
195
|
+
begin
|
|
196
|
+
# Example usage (requires actual Parse server and data)
|
|
197
|
+
# project = Project.first
|
|
198
|
+
# new_owner = Parse::User.first(username: "new_owner")
|
|
199
|
+
#
|
|
200
|
+
# if project && new_owner
|
|
201
|
+
# transfer_project_ownership_basic(project, new_owner)
|
|
202
|
+
# end
|
|
203
|
+
|
|
204
|
+
puts "\nTransaction support has been added to parse-stack!"
|
|
205
|
+
puts "\nKey features:"
|
|
206
|
+
puts "1. Atomic operations - all succeed or all fail"
|
|
207
|
+
puts "2. Automatic retry on transaction conflicts (error 251)"
|
|
208
|
+
puts "3. Two styles: explicit batch.add() or return array"
|
|
209
|
+
puts "4. Works with any Parse::Object subclass"
|
|
210
|
+
puts "\nUsage:"
|
|
211
|
+
puts " Parse::Object.transaction do |batch|"
|
|
212
|
+
puts " # Add operations to batch"
|
|
213
|
+
puts " end"
|
|
214
|
+
|
|
215
|
+
rescue => e
|
|
216
|
+
puts "Error: #{e.message}"
|
|
217
|
+
puts e.backtrace
|
|
218
|
+
end
|
|
219
|
+
end
|