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
data/bin/parse-console ADDED
@@ -0,0 +1,136 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'optparse'
4
+ require 'json'
5
+ require 'open-uri'
6
+ require 'active_support'
7
+ require 'active_support/core_ext'
8
+
9
+ DEFAULT_CONFIG_FILE = 'config.json'
10
+ DEFAULT_CONFIG_CONTENTS = {
11
+ "apps": [{
12
+ "serverURL": "http://localhost:1337/parse",
13
+ "appId": "myAppId",
14
+ "masterKey": "myMasterKey",
15
+ "restAPIKey": "myRestAPIKey",
16
+ "javascriptKey": "myJavascriptKey",
17
+ "appName": "Parse Server App"
18
+ }]
19
+ }.freeze
20
+
21
+ opts = { verbose: false, pry: false }
22
+ opt_parser = OptionParser.new do |o|
23
+
24
+ o.banner = "Usage: #{File.basename($0)} [options] SERVER_URL"
25
+ o.separator ""
26
+ o.separator "Example:"
27
+ o.separator "#{File.basename($0)} -a APP_ID -m MASTER_KEY https://your-parse-server-url"
28
+ o.separator "#{File.basename($0)} -c ./config.json"
29
+ o.separator ""
30
+ o.separator "If you use the -m option, parse-console will automatically"
31
+ o.separator "import your schema as ruby models."
32
+ o.separator ""
33
+ o.separator "Options"
34
+ o.on('-a APP_ID', '--appId APP_ID', 'Parse App ID (required)') { |a| opts[:app_id] = a }
35
+ o.on('-k REST_API_KEY', '--restAPIKey REST_API_KEY', 'Parse REST API Key') { |a| opts[:api_key] = a }
36
+ o.on('-m MASTER_KEY', '--masterKey MASTER_KEY', 'Parse Master Key') { |a| opts[:master_key] = a }
37
+ o.on('-s SERVER_URL', '--serverURL SERVER_URL', 'The Parse server url.', 'Defaults to http://localhost:1337/parse') { |a| opts[:server_url] = a }
38
+ o.on('-v','--[no-]verbose', 'Run verbosely') { |v| opts[:verbose] ||= v }
39
+ o.on('--pry', 'Use Pry instead of IRB') { |v| opts[:pry] = v }
40
+ o.on('--version', 'Parse Stack version') do |v|
41
+ require 'parse/stack/version'
42
+ puts "Parse Stack : #{Parse::Stack::VERSION}"
43
+ exit 1
44
+ end
45
+ o.on('--config-sample', "Create a sample config file to use. See --config.") do
46
+ contents = JSON.pretty_generate(DEFAULT_CONFIG_CONTENTS)
47
+ File.open(DEFAULT_CONFIG_FILE, 'w') { |f| f.write(contents) }
48
+ puts "Created #{DEFAULT_CONFIG_FILE} : \n"
49
+ puts contents
50
+ puts "Edit #{DEFAULT_CONFIG_FILE} with your information and run: \n"
51
+ puts "\n\tparse-console -c ./#{DEFAULT_CONFIG_FILE}\n\n"
52
+ exit 1
53
+ end
54
+ o.on('-c','--config CONFIG_JSON', "Load config from a parse-dashboard.json compatible file.") do |filepath|
55
+ unless File.exist?(filepath)
56
+ $stderr.puts "File #{filepath} does not exist."
57
+ exit 1
58
+ end
59
+
60
+ begin
61
+ puts "Loading config: #{filepath}"
62
+ file = File.read(filepath)
63
+ config = JSON.parse file
64
+ app = config["apps"].is_a?(Array) ? config["apps"].first : config["apps"]
65
+ app = config if app.nil? # uses parse-server config.json
66
+ opts[:server_url] ||= app["serverURL"]
67
+ opts[:app_id] ||= app["appId"]
68
+ opts[:api_key] ||= app["restAPIKey"]
69
+ opts[:master_key] ||= app["masterKey"]
70
+ rescue Exception => e
71
+ $stderr.puts "Error: Incompatible JSON format for #{filepath} (#{e})"
72
+ exit 1
73
+ end
74
+
75
+ end
76
+ o.on('--url URL', 'Load the env config from a url.') do |url|
77
+ begin
78
+ puts "Loading config: #{url}"
79
+ json = JSON.load open(url)
80
+ raise "Contents not a JSON hash." unless json.is_a?(Hash)
81
+ json.each { |k,v| ENV[k.upcase] = v }
82
+ opts[:server_url] ||= ENV['PARSE_SERVER_URL']
83
+ opts[:app_id] ||= ENV['PARSE_SERVER_APPLICATION_ID'] || ENV['PARSE_APP_ID']
84
+ opts[:api_key] ||= ENV['PARSE_SERVER_REST_API_KEY'] || ENV['PARSE_API_KEY']
85
+ opts[:master_key] ||= ENV['PARSE_SERVER_MASTER_KEY'] || ENV['PARSE_MASTER_KEY']
86
+ rescue Exception => e
87
+ $stderr.puts "Error: Invalid JSON format for #{url} (#{e})"
88
+ exit 1
89
+ end
90
+ end
91
+ end
92
+ opt_parser.parse!
93
+
94
+ opts[:server_url] ||= ARGV.shift || 'http://localhost:1337/parse'
95
+
96
+ if opts[:app_id].nil?
97
+ $stderr.puts "Error: Option --app_id missing\n"
98
+ $stderr.puts opt_parser
99
+ exit 1
100
+ end
101
+
102
+ if opts[:api_key].nil? && opts[:master_key].nil?
103
+ $stderr.puts "Error: You must supply either --api_key (REST API Key) or --master_key (Parse Master key).\n"
104
+ $stderr.puts opt_parser
105
+ exit 1
106
+ end
107
+
108
+ # lazy loading
109
+ require "parse/stack"
110
+ Parse.setup server_url: opts[:server_url],
111
+ app_id: opts[:app_id],
112
+ api_key: opts[:api_key],
113
+ master_key: opts[:master_key]
114
+ Parse.logging = true if opts[:verbose]
115
+ puts "Server : #{Parse.client.server_url}"
116
+ puts "App Id : #{Parse.client.app_id}"
117
+ puts "Master : #{Parse.client.master_key.present?}"
118
+
119
+ if Parse.client.master_key.present?
120
+ puts "Schema : imported"
121
+ Parse.auto_generate_models!.each do |model|
122
+ puts "Generated #{model}" if opts[:verbose]
123
+ end
124
+ else
125
+ puts "Schema : skipped (requires master key)"
126
+ end
127
+ # Create shortnames
128
+ Parse.use_shortnames!
129
+
130
+ if opts[:pry]
131
+ require "pry"
132
+ Pry.start
133
+ else
134
+ require "irb"
135
+ IRB.start
136
+ end
data/bin/server ADDED
@@ -0,0 +1,17 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "parse/stack"
5
+
6
+ require "rack"
7
+ require "puma"
8
+
9
+ # For Rack v3 compatibility, Rack::Server has been moved to rackup gem
10
+ # Using a simple Puma server directly instead
11
+ puts "Starting Parse::Webhooks server on port 9292..."
12
+ puts "Visit http://localhost:9292"
13
+
14
+ app = Parse::Webhooks
15
+ server = Puma::Server.new(app)
16
+ server.add_tcp_listener "0.0.0.0", 9292
17
+ server.run
data/bin/setup ADDED
@@ -0,0 +1,7 @@
1
+ #!/bin/bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+
5
+ bundle install
6
+
7
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,12 @@
1
+ {
2
+ "appId": "myAppId",
3
+ "masterKey": "myMasterKey",
4
+ "restAPIKey": "test-rest-key",
5
+ "databaseURI": "mongodb://admin:password@mongo:27017/parse?authSource=admin",
6
+ "serverURL": "http://localhost:1337/parse",
7
+ "mountPath": "/parse",
8
+ "cloud": "/parse-server/cloud/main.js",
9
+ "logLevel": "info",
10
+ "allowClientClassCreation": true,
11
+ "allowCustomObjectId": true
12
+ }
@@ -0,0 +1,271 @@
1
+ # Parse Stack Test Server Setup
2
+
3
+ This document explains how to set up a local Parse Server for testing the parse-stack Ruby SDK.
4
+
5
+ ## Quick Start
6
+
7
+ ### Option 1: Using Make (Recommended)
8
+
9
+ ```bash
10
+ # Start the test server
11
+ make test-server-start
12
+
13
+ # Test the connection
14
+ make test-connection
15
+
16
+ # Run integration tests
17
+ make test-integration
18
+
19
+ # Stop the test server
20
+ make test-server-stop
21
+ ```
22
+
23
+ ### Option 2: Docker Compose
24
+
25
+ 1. **Start the test server:**
26
+ ```bash
27
+ docker-compose -f docker-compose.test.yml up -d
28
+ ```
29
+
30
+ 2. **Test the connection:**
31
+ ```bash
32
+ ruby test_server_connection.rb
33
+ ```
34
+
35
+ 3. **Run integration tests:**
36
+ ```bash
37
+ PARSE_TEST_USE_DOCKER=true bundle exec rake test
38
+ ```
39
+
40
+ 4. **Stop the test server:**
41
+ ```bash
42
+ docker-compose -f docker-compose.test.yml down
43
+ ```
44
+
45
+ ### Option 3: Use Your Own Parse Server
46
+
47
+ Set environment variables to point to your Parse Server:
48
+
49
+ ```bash
50
+ export PARSE_TEST_SERVER_URL="http://your-server:1337/parse"
51
+ export PARSE_TEST_APP_ID="your-app-id"
52
+ export PARSE_TEST_API_KEY="your-rest-key"
53
+ export PARSE_TEST_MASTER_KEY="your-master-key"
54
+ ```
55
+
56
+ ## Services Included
57
+
58
+ The Docker Compose setup provides:
59
+
60
+ - **MongoDB** (port 27017): Database backend
61
+ - **Parse Server** (port 1337): Main API server with custom startup script
62
+ - **Parse Dashboard** (port 4040): Web interface for data management
63
+
64
+ ## Technical Implementation
65
+
66
+ ### Custom Parse Server Image
67
+
68
+ The setup uses a custom Docker image built on top of `parseplatform/parse-server:8.2.3` that includes:
69
+
70
+ - **Custom startup script** (`scripts/start-parse.sh`) that sets the `PARSE_SERVER_MASTER_KEY_IPS` environment variable
71
+ - **IP restriction bypass** allowing requests from any IP address (`0.0.0.0/0,::/0`)
72
+ - **Automatic environment variable setup** for proper master key authentication
73
+
74
+ ### Master Key Authentication
75
+
76
+ The setup resolves Parse Server's IP restriction for master key usage by:
77
+
78
+ 1. Using a custom Docker image with an embedded startup script
79
+ 2. Setting `PARSE_SERVER_MASTER_KEY_IPS=0.0.0.0/0,::/0` to allow all IP addresses
80
+ 3. This enables schema operations and full master key functionality for testing
81
+
82
+ ### File Structure
83
+
84
+ ```
85
+ parse-stack-next/
86
+ ├── scripts/
87
+ │ ├── docker/
88
+ │ │ ├── docker-compose.test.yml # Main Docker Compose configuration
89
+ │ │ └── Dockerfile.parse # Custom Parse Server image
90
+ │ ├── start-parse.sh # Startup script with environment setup
91
+ │ └── test_server_connection.rb # Connection test script
92
+ ├── config/
93
+ │ └── parse-config.json # Parse Server configuration (unused)
94
+ ├── test/
95
+ │ ├── cloud/
96
+ │ │ └── main.js # Cloud Code for testing
97
+ │ └── support/
98
+ │ ├── test_server.rb # Ruby test helper utilities
99
+ │ └── docker_helper.rb # Docker container management
100
+ └── .env.test # Environment variable defaults
101
+ ```
102
+
103
+ ## Test Configuration
104
+
105
+ ### Environment Variables
106
+
107
+ | Variable | Default | Description |
108
+ |----------|---------|-------------|
109
+ | `PARSE_TEST_SERVER_URL` | `http://localhost:1337/parse` | Parse Server URL |
110
+ | `PARSE_TEST_APP_ID` | `myAppId` | Application ID |
111
+ | `PARSE_TEST_API_KEY` | `test-rest-key` | REST API Key |
112
+ | `PARSE_TEST_MASTER_KEY` | `myMasterKey` | Master Key |
113
+ | `PARSE_TEST_USE_DOCKER` | `false` | Auto-manage Docker containers |
114
+ | `PARSE_TEST_AUTO_START` | `false` | Start containers automatically |
115
+ | `PARSE_TEST_AUTO_STOP` | `false` | Stop containers on exit |
116
+
117
+ ### Using `.env.test`
118
+
119
+ Copy and customize the test environment file:
120
+
121
+ ```bash
122
+ cp .env.test .env.test.local
123
+ # Edit .env.test.local with your settings
124
+ ```
125
+
126
+ ## Writing Integration Tests
127
+
128
+ ### Basic Setup
129
+
130
+ ```ruby
131
+ require_relative 'test_helper_integration'
132
+
133
+ class MyIntegrationTest < Minitest::Test
134
+ include ParseStackIntegrationTest
135
+
136
+ def test_user_creation
137
+ with_parse_server do
138
+ user = create_test_user(username: 'testuser')
139
+ assert user.id.present?
140
+ assert_equal 'testuser', user.username
141
+ end
142
+ end
143
+ end
144
+ ```
145
+
146
+ ### Test Helpers Available
147
+
148
+ - `with_parse_server { }` - Skip test if server unavailable
149
+ - `create_test_user(attributes)` - Create and track test user
150
+ - `create_test_object(class_name, attributes)` - Create and track test object
151
+ - `reset_database!` - Clear all non-system data
152
+ - `@test_context.track(object)` - Track object for cleanup
153
+
154
+ ### Manual Server Management
155
+
156
+ ```ruby
157
+ # In your tests or console
158
+ require 'test/support/docker_helper'
159
+
160
+ # Start containers
161
+ Parse::Test::DockerHelper.start!
162
+
163
+ # Check if running
164
+ Parse::Test::DockerHelper.running?
165
+
166
+ # View logs
167
+ puts Parse::Test::DockerHelper.logs
168
+
169
+ # Stop containers
170
+ Parse::Test::DockerHelper.stop!
171
+ ```
172
+
173
+ ## Dashboard Access
174
+
175
+ When using Docker Compose, you can access the Parse Dashboard at:
176
+ - URL: http://localhost:4040
177
+ - Username: `admin`
178
+ - Password: `admin`
179
+
180
+ ## Cloud Code Testing
181
+
182
+ Sample cloud functions are provided in `test/cloud/main.js`:
183
+
184
+ ```ruby
185
+ # Test cloud functions
186
+ result = Parse::CloudFunction.call('hello', name: 'World')
187
+ assert_equal 'Hello World!', result
188
+ ```
189
+
190
+ ## Troubleshooting
191
+
192
+ ### Docker Issues
193
+
194
+ ```bash
195
+ # Check container status
196
+ docker-compose -f docker-compose.test.yml ps
197
+
198
+ # View Parse Server logs
199
+ docker logs parse-stack-test-server
200
+
201
+ # Reset everything
202
+ docker-compose -f docker-compose.test.yml down -v
203
+ docker-compose -f docker-compose.test.yml up -d
204
+ ```
205
+
206
+ ### Master Key Authentication Issues
207
+
208
+ If you see `Request using master key rejected as the request IP address ... is not set in Parse Server option 'masterKeyIps'`:
209
+
210
+ 1. **Verify the custom image is built**:
211
+ ```bash
212
+ docker-compose -f docker-compose.test.yml build parse
213
+ ```
214
+
215
+ 2. **Check startup script execution**:
216
+ ```bash
217
+ docker logs parse-stack-test-server | grep "PARSE_SERVER_MASTER_KEY_IPS"
218
+ ```
219
+ Should show: `PARSE_SERVER_MASTER_KEY_IPS: 0.0.0.0/0,::/0`
220
+
221
+ 3. **Test master key directly**:
222
+ ```bash
223
+ curl -X GET \
224
+ -H "X-Parse-Application-Id: myAppId" \
225
+ -H "X-Parse-Master-Key: myMasterKey" \
226
+ http://localhost:1337/parse/schemas
227
+ ```
228
+
229
+ ### Connection Issues
230
+
231
+ ```ruby
232
+ # Test connectivity in console
233
+ require 'test/support/test_server'
234
+ Parse::Test::ServerHelper.setup
235
+ Parse::Test::ServerHelper.server_available?
236
+ ```
237
+
238
+ ### Port Conflicts
239
+
240
+ If ports 1337, 4040, or 27017 are in use, modify `docker-compose.test.yml`:
241
+
242
+ ```yaml
243
+ services:
244
+ parse:
245
+ ports:
246
+ - "1338:1337" # Use port 1338 instead
247
+ ```
248
+
249
+ Then update your environment variables accordingly.
250
+
251
+ ## Production vs Test Differences
252
+
253
+ The test server configuration includes:
254
+ - Relaxed security settings for testing
255
+ - Auto-creation of classes
256
+ - Verbose logging
257
+ - Sample cloud code
258
+
259
+ **Never use these settings in production!**
260
+
261
+ ## Status
262
+
263
+ ✅ **Working Setup**: This test server configuration has been verified to work with:
264
+ - Parse Server 8.2.3
265
+ - MongoDB 5.0
266
+ - Master key authentication for schema operations
267
+ - Basic CRUD operations via REST API
268
+ - Ruby Parse Stack SDK connection
269
+ - Cloud Code execution
270
+
271
+ The setup successfully resolves Parse Server's IP restriction issues that typically prevent master key usage in Docker environments.
data/docs/_config.yml ADDED
@@ -0,0 +1 @@
1
+ theme: jekyll-theme-midnight