rapitapir 0.1.1 โ†’ 2.0.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 (110) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +7 -7
  3. data/.rubocop_todo.yml +83 -0
  4. data/README.md +1319 -235
  5. data/RUBY_WEEKLY_LAUNCH_POST.md +219 -0
  6. data/docs/RAILS_INTEGRATION_IMPLEMENTATION.md +209 -0
  7. data/docs/SINATRA_EXTENSION.md +399 -348
  8. data/docs/STRICT_VALIDATION.md +229 -0
  9. data/docs/VALIDATION_IMPROVEMENTS.md +218 -0
  10. data/docs/ai-integration-plan.md +112 -0
  11. data/docs/auto-derivation.md +505 -92
  12. data/docs/endpoint-definition.md +536 -129
  13. data/docs/n8n-integration.md +212 -0
  14. data/docs/observability.md +810 -500
  15. data/docs/using-mcp.md +93 -0
  16. data/examples/ai/knowledge_base_rag.rb +83 -0
  17. data/examples/ai/user_management_mcp.rb +92 -0
  18. data/examples/ai/user_validation_llm.rb +187 -0
  19. data/examples/rails/RAILS_8_GUIDE.md +165 -0
  20. data/examples/rails/RAILS_LOADING_FIX.rb +35 -0
  21. data/examples/rails/README.md +497 -0
  22. data/examples/rails/comprehensive_test.rb +91 -0
  23. data/examples/rails/config/routes.rb +48 -0
  24. data/examples/rails/debug_controller.rb +63 -0
  25. data/examples/rails/detailed_test.rb +46 -0
  26. data/examples/rails/enhanced_users_controller.rb +278 -0
  27. data/examples/rails/final_server_test.rb +50 -0
  28. data/examples/rails/hello_world_app.rb +116 -0
  29. data/examples/rails/hello_world_controller.rb +186 -0
  30. data/examples/rails/hello_world_routes.rb +28 -0
  31. data/examples/rails/rails8_minimal_demo.rb +132 -0
  32. data/examples/rails/rails8_simple_demo.rb +140 -0
  33. data/examples/rails/rails8_working_demo.rb +255 -0
  34. data/examples/rails/real_world_blog_api.rb +510 -0
  35. data/examples/rails/server_test.rb +46 -0
  36. data/examples/rails/test_direct_processing.rb +41 -0
  37. data/examples/rails/test_hello_world.rb +80 -0
  38. data/examples/rails/test_rails_integration.rb +54 -0
  39. data/examples/rails/traditional_app/Gemfile +37 -0
  40. data/examples/rails/traditional_app/README.md +265 -0
  41. data/examples/rails/traditional_app/app/controllers/api/v1/posts_controller.rb +254 -0
  42. data/examples/rails/traditional_app/app/controllers/api/v1/users_controller.rb +220 -0
  43. data/examples/rails/traditional_app/app/controllers/application_controller.rb +86 -0
  44. data/examples/rails/traditional_app/app/controllers/application_controller_simplified.rb +87 -0
  45. data/examples/rails/traditional_app/app/controllers/documentation_controller.rb +149 -0
  46. data/examples/rails/traditional_app/app/controllers/health_controller.rb +42 -0
  47. data/examples/rails/traditional_app/config/routes.rb +25 -0
  48. data/examples/rails/traditional_app/config/routes_best_practice.rb +25 -0
  49. data/examples/rails/traditional_app/config/routes_simplified.rb +36 -0
  50. data/examples/rails/traditional_app_runnable.rb +406 -0
  51. data/examples/rails/users_controller.rb +4 -1
  52. data/examples/serverless/Gemfile +43 -0
  53. data/examples/serverless/QUICKSTART.md +331 -0
  54. data/examples/serverless/README.md +520 -0
  55. data/examples/serverless/aws_lambda_example.rb +307 -0
  56. data/examples/serverless/aws_sam_template.yaml +215 -0
  57. data/examples/serverless/azure_functions_example.rb +407 -0
  58. data/examples/serverless/deploy.rb +204 -0
  59. data/examples/serverless/gcp_cloud_functions_example.rb +367 -0
  60. data/examples/serverless/gcp_function.yaml +23 -0
  61. data/examples/serverless/host.json +24 -0
  62. data/examples/serverless/package.json +32 -0
  63. data/examples/serverless/spec/aws_lambda_spec.rb +196 -0
  64. data/examples/serverless/spec/spec_helper.rb +89 -0
  65. data/examples/serverless/vercel.json +31 -0
  66. data/examples/serverless/vercel_example.rb +404 -0
  67. data/examples/strict_validation_examples.rb +104 -0
  68. data/examples/validation_error_examples.rb +173 -0
  69. data/lib/rapitapir/ai/llm_instruction.rb +456 -0
  70. data/lib/rapitapir/ai/mcp.rb +134 -0
  71. data/lib/rapitapir/ai/rag.rb +287 -0
  72. data/lib/rapitapir/ai/rag_middleware.rb +147 -0
  73. data/lib/rapitapir/auth/oauth2.rb +43 -57
  74. data/lib/rapitapir/cli/command.rb +362 -2
  75. data/lib/rapitapir/cli/mcp_export.rb +18 -0
  76. data/lib/rapitapir/cli/validator.rb +2 -6
  77. data/lib/rapitapir/core/endpoint.rb +59 -6
  78. data/lib/rapitapir/core/enhanced_endpoint.rb +2 -6
  79. data/lib/rapitapir/dsl/fluent_endpoint_builder.rb +53 -0
  80. data/lib/rapitapir/endpoint_registry.rb +47 -0
  81. data/lib/rapitapir/observability/health_check.rb +4 -4
  82. data/lib/rapitapir/observability/logging.rb +10 -10
  83. data/lib/rapitapir/schema.rb +2 -2
  84. data/lib/rapitapir/server/rack_adapter.rb +1 -3
  85. data/lib/rapitapir/server/rails/configuration.rb +77 -0
  86. data/lib/rapitapir/server/rails/controller_base.rb +185 -0
  87. data/lib/rapitapir/server/rails/documentation_helpers.rb +76 -0
  88. data/lib/rapitapir/server/rails/resource_builder.rb +181 -0
  89. data/lib/rapitapir/server/rails/routes.rb +114 -0
  90. data/lib/rapitapir/server/rails_adapter.rb +10 -3
  91. data/lib/rapitapir/server/rails_adapter_class.rb +1 -3
  92. data/lib/rapitapir/server/rails_controller.rb +1 -3
  93. data/lib/rapitapir/server/rails_integration.rb +67 -0
  94. data/lib/rapitapir/server/rails_response_handler.rb +16 -3
  95. data/lib/rapitapir/server/sinatra_adapter.rb +29 -5
  96. data/lib/rapitapir/server/sinatra_integration.rb +4 -4
  97. data/lib/rapitapir/sinatra/extension.rb +2 -2
  98. data/lib/rapitapir/sinatra/oauth2_helpers.rb +34 -40
  99. data/lib/rapitapir/types/array.rb +4 -0
  100. data/lib/rapitapir/types/auto_derivation.rb +4 -18
  101. data/lib/rapitapir/types/datetime.rb +1 -3
  102. data/lib/rapitapir/types/float.rb +2 -6
  103. data/lib/rapitapir/types/hash.rb +40 -2
  104. data/lib/rapitapir/types/integer.rb +4 -12
  105. data/lib/rapitapir/types/object.rb +6 -2
  106. data/lib/rapitapir/types.rb +6 -2
  107. data/lib/rapitapir/version.rb +1 -1
  108. data/lib/rapitapir.rb +5 -3
  109. data/rapitapir.gemspec +7 -5
  110. metadata +116 -16
@@ -0,0 +1,132 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Minimal Rails 8 + RapiTapir example
4
+ # This demonstrates the proper loading order and setup
5
+
6
+ require 'bundler/inline'
7
+
8
+ gemfile do
9
+ source 'https://rubygems.org'
10
+ gem 'rails', '~> 8.0'
11
+ gem 'sqlite3'
12
+ gem 'puma'
13
+ gem 'webrick' # Required for WEBrick server
14
+ end
15
+
16
+ # Load Rails first (this is crucial!)
17
+ require 'rails/all'
18
+
19
+ # Now load RapiTapir (this will work because Rails is loaded)
20
+ require_relative '../../lib/rapitapir'
21
+
22
+ # Rails 8 Application Setup
23
+ class Rails8Demo < Rails::Application
24
+ config.load_defaults 8.0
25
+ config.api_only = true
26
+ config.eager_load = false
27
+ config.logger = Logger.new(STDOUT)
28
+ config.log_level = :info
29
+ config.secret_key_base = 'rails8_demo_secret_key'
30
+ end
31
+
32
+ Rails.application.initialize!
33
+
34
+ # Simple in-memory data for demo
35
+ USERS = [
36
+ { id: 1, name: "Alice Johnson", email: "alice@example.com" },
37
+ { id: 2, name: "Bob Smith", email: "bob@example.com" }
38
+ ].freeze
39
+
40
+ # ApplicationController with RapiTapir
41
+ class ApplicationController < RapiTapir::Server::Rails::ControllerBase
42
+ rapitapir do
43
+ development_defaults!
44
+
45
+ # Health endpoint
46
+ GET('/health')
47
+ .out(json_body(
48
+ status: T.string,
49
+ timestamp: T.string,
50
+ rails_version: T.string,
51
+ ruby_version: T.string
52
+ ))
53
+ .summary("System health check")
54
+ .tag("System")
55
+ end
56
+
57
+ def health_check
58
+ render json: {
59
+ status: 'ok',
60
+ timestamp: Time.current.iso8601,
61
+ rails_version: Rails.version,
62
+ ruby_version: RUBY_VERSION
63
+ }
64
+ end
65
+ end
66
+
67
+ # Users API Controller
68
+ class UsersController < ApplicationController
69
+ rapitapir do
70
+ user_type = T.hash(
71
+ id: T.integer,
72
+ name: T.string,
73
+ email: T.string
74
+ )
75
+
76
+ GET('/users')
77
+ .out(json_body(users: T.array(user_type)))
78
+ .summary("List all users")
79
+ .description("Get a list of all users in the system")
80
+ .tag("Users")
81
+
82
+ GET('/users/:id')
83
+ .in(path(:id, T.integer))
84
+ .out(json_body(user: user_type))
85
+ .error_out(json_body(error: T.string), 404)
86
+ .summary("Get user by ID")
87
+ .tag("Users")
88
+ end
89
+
90
+ def list_users
91
+ render json: { users: USERS }
92
+ end
93
+
94
+ def get_user
95
+ user = USERS.find { |u| u[:id] == params[:id].to_i }
96
+
97
+ if user
98
+ render json: { user: user }
99
+ else
100
+ render json: { error: "User not found" }, status: 404
101
+ end
102
+ end
103
+ end
104
+
105
+ # Routes
106
+ Rails.application.routes.draw do
107
+ rapitapir_routes_for ApplicationController
108
+ rapitapir_routes_for UsersController
109
+ end
110
+
111
+ # Start server
112
+ if __FILE__ == $0
113
+ puts "๐Ÿš€ Rails 8 + RapiTapir Demo starting on http://localhost:3000"
114
+ puts "๐Ÿ“‹ Rails Version: #{Rails.version}"
115
+ puts "๐Ÿ“‹ Ruby Version: #{RUBY_VERSION}"
116
+ puts ""
117
+ puts "๐Ÿ“š Available endpoints:"
118
+ puts " GET /health - Health check"
119
+ puts " GET /users - List users"
120
+ puts " GET /users/1 - Get specific user"
121
+ puts " GET /docs - Swagger UI documentation"
122
+ puts " GET /openapi.json - OpenAPI specification"
123
+ puts ""
124
+ puts "๐Ÿงช Test commands:"
125
+ puts " curl http://localhost:3000/health"
126
+ puts " curl http://localhost:3000/users"
127
+ puts " curl http://localhost:3000/users/1"
128
+ puts ""
129
+
130
+ require 'rack'
131
+ Rack::Handler::WEBrick.run(Rails.application, Port: 3000)
132
+ end
@@ -0,0 +1,140 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Simple Rails 8 + RapiTapir example using system Rails
4
+ # Note: Requires Rails 8 to be installed: gem install rails
5
+
6
+ puts "๐Ÿš€ Loading Rails and RapiTapir..."
7
+
8
+ # Load Rails first (this is crucial!)
9
+ require 'rails/all'
10
+
11
+ # Now load RapiTapir (this will work because Rails is loaded)
12
+ require_relative '../../lib/rapitapir'
13
+
14
+ puts "โœ… Libraries loaded successfully"
15
+
16
+ # Rails 8 Application Setup
17
+ class Rails8Demo < Rails::Application
18
+ config.load_defaults 8.0
19
+ config.api_only = true
20
+ config.eager_load = false
21
+ config.logger = Logger.new(STDOUT)
22
+ config.log_level = :info
23
+ config.secret_key_base = 'rails8_demo_secret_key'
24
+ end
25
+
26
+ puts "๐Ÿ—๏ธ Initializing Rails application..."
27
+ Rails.application.initialize!
28
+ puts "โœ… Rails application initialized"
29
+
30
+ # Simple in-memory data for demo
31
+ USERS = [
32
+ { id: 1, name: "Alice Johnson", email: "alice@example.com" },
33
+ { id: 2, name: "Bob Smith", email: "bob@example.com" }
34
+ ].freeze
35
+
36
+ # ApplicationController with RapiTapir
37
+ class ApplicationController < RapiTapir::Server::Rails::ControllerBase
38
+ rapitapir do
39
+ development_defaults!
40
+
41
+ # Health endpoint
42
+ GET('/health')
43
+ .out(json_body(
44
+ status: T.string,
45
+ timestamp: T.string,
46
+ rails_version: T.string,
47
+ ruby_version: T.string
48
+ ))
49
+ .summary("System health check")
50
+ .tag("System")
51
+ end
52
+
53
+ def health_check
54
+ render json: {
55
+ status: 'ok',
56
+ timestamp: Time.current.iso8601,
57
+ rails_version: Rails.version,
58
+ ruby_version: RUBY_VERSION
59
+ }
60
+ end
61
+ end
62
+
63
+ puts "โœ… ApplicationController defined"
64
+
65
+ # Users API Controller
66
+ class UsersController < ApplicationController
67
+ rapitapir do
68
+ user_type = T.hash(
69
+ id: T.integer,
70
+ name: T.string,
71
+ email: T.string
72
+ )
73
+
74
+ GET('/users')
75
+ .out(json_body(users: T.array(user_type)))
76
+ .summary("List all users")
77
+ .description("Get a list of all users in the system")
78
+ .tag("Users")
79
+
80
+ GET('/users/:id')
81
+ .in(path(:id, T.integer))
82
+ .out(json_body(user: user_type))
83
+ .error_out(json_body(error: T.string), 404)
84
+ .summary("Get user by ID")
85
+ .tag("Users")
86
+ end
87
+
88
+ def list_users
89
+ render json: { users: USERS }
90
+ end
91
+
92
+ def get_user
93
+ user = USERS.find { |u| u[:id] == params[:id].to_i }
94
+
95
+ if user
96
+ render json: { user: user }
97
+ else
98
+ render json: { error: "User not found" }, status: 404
99
+ end
100
+ end
101
+ end
102
+
103
+ puts "โœ… UsersController defined"
104
+
105
+ # Routes
106
+ Rails.application.routes.draw do
107
+ rapitapir_routes_for ApplicationController
108
+ rapitapir_routes_for UsersController
109
+ end
110
+
111
+ puts "โœ… Routes configured"
112
+
113
+ # Start server
114
+ if __FILE__ == $0
115
+ puts ""
116
+ puts "๐Ÿš€ Rails 8 + RapiTapir Demo starting on http://localhost:3000"
117
+ puts "๐Ÿ“‹ Rails Version: #{Rails.version}"
118
+ puts "๐Ÿ“‹ Ruby Version: #{RUBY_VERSION}"
119
+ puts ""
120
+ puts "๐Ÿ“š Available endpoints:"
121
+ puts " GET /health - Health check"
122
+ puts " GET /users - List users"
123
+ puts " GET /users/1 - Get specific user"
124
+ puts " GET /docs - Swagger UI documentation"
125
+ puts " GET /openapi.json - OpenAPI specification"
126
+ puts ""
127
+ puts "๐Ÿงช Test commands:"
128
+ puts " curl http://localhost:3000/health"
129
+ puts " curl http://localhost:3000/users"
130
+ puts " curl http://localhost:3000/users/1"
131
+ puts ""
132
+
133
+ begin
134
+ require 'webrick'
135
+ Rack::Handler::WEBrick.run(Rails.application, Port: 3000)
136
+ rescue LoadError
137
+ puts "โŒ WEBrick not available. Install with: gem install webrick"
138
+ puts "Or use another server like Puma"
139
+ end
140
+ end
@@ -0,0 +1,255 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Working Rails 8 + RapiTapir example
4
+ # This uses only the core RapiTapir features that are known to work
5
+
6
+ puts "๐Ÿš€ Starting Rails 8 + RapiTapir Demo..."
7
+
8
+ # Check if Rails is available
9
+ begin
10
+ require 'rails/all'
11
+ puts "โœ… Rails #{Rails::VERSION::STRING} loaded"
12
+ rescue LoadError => e
13
+ puts "โŒ Rails not available: #{e.message}"
14
+ puts ""
15
+ puts "To run this demo, install Rails 8:"
16
+ puts " gem install rails"
17
+ puts ""
18
+ exit 1
19
+ end
20
+
21
+ # Load RapiTapir
22
+ begin
23
+ require_relative '../../lib/rapitapir'
24
+ puts "โœ… RapiTapir loaded"
25
+ rescue LoadError => e
26
+ puts "โŒ RapiTapir not available: #{e.message}"
27
+ exit 1
28
+ end
29
+
30
+ # Create Rails application
31
+ puts "๐Ÿ—๏ธ Setting up Rails application..."
32
+
33
+ class Rails8DemoApp < Rails::Application
34
+ config.load_defaults 8.0
35
+ config.api_only = true
36
+ config.eager_load = false
37
+ config.secret_key_base = 'rails8_demo_secret_key_for_rapitapir_integration'
38
+ config.log_level = :info
39
+ config.logger = Logger.new(STDOUT)
40
+ end
41
+
42
+ Rails.application.initialize!
43
+ puts "โœ… Rails application initialized"
44
+
45
+ # Sample data
46
+ DEMO_USERS = [
47
+ { id: 1, name: "Alice Johnson", email: "alice@example.com" },
48
+ { id: 2, name: "Bob Smith", email: "bob@example.com" }
49
+ ].freeze
50
+
51
+ # Define endpoints using standard RapiTapir DSL (not Rails integration)
52
+ puts "๐Ÿ“‹ Defining API endpoints..."
53
+
54
+ # Health check endpoint
55
+ HEALTH_ENDPOINT = RapiTapir.get('/health')
56
+ .out(status_code(200))
57
+ .out(json_body({
58
+ status: :string,
59
+ timestamp: :string,
60
+ rails_version: :string,
61
+ ruby_version: :string
62
+ }))
63
+ .summary("Health check")
64
+ .description("Check if the API is running")
65
+ .tag("System")
66
+
67
+ # List users endpoint
68
+ LIST_USERS_ENDPOINT = RapiTapir.get('/users')
69
+ .out(status_code(200))
70
+ .out(json_body({
71
+ users: [{
72
+ id: :integer,
73
+ name: :string,
74
+ email: :string
75
+ }]
76
+ }))
77
+ .summary("List users")
78
+ .description("Get all users")
79
+ .tag("Users")
80
+
81
+ # Get user endpoint
82
+ GET_USER_ENDPOINT = RapiTapir.get('/users/:id')
83
+ .in(path_param(:id, :integer))
84
+ .out(status_code(200))
85
+ .out(json_body({
86
+ user: {
87
+ id: :integer,
88
+ name: :string,
89
+ email: :string
90
+ }
91
+ }))
92
+ .error_out(404, json_body({ error: :string }))
93
+ .summary("Get user")
94
+ .description("Get a specific user by ID")
95
+ .tag("Users")
96
+
97
+ puts "โœ… Endpoints defined"
98
+
99
+ # Create a standard Rails controller (not using RapiTapir Rails integration)
100
+ puts "๐ŸŽฎ Creating Rails controllers..."
101
+
102
+ class ApplicationController < ActionController::API
103
+ def health_check
104
+ render json: {
105
+ status: 'ok',
106
+ timestamp: Time.current.iso8601,
107
+ rails_version: Rails.version,
108
+ ruby_version: RUBY_VERSION
109
+ }
110
+ end
111
+ end
112
+
113
+ class UsersController < ApplicationController
114
+ def index
115
+ render json: { users: DEMO_USERS }
116
+ end
117
+
118
+ def show
119
+ user = DEMO_USERS.find { |u| u[:id] == params[:id].to_i }
120
+
121
+ if user
122
+ render json: { user: user }
123
+ else
124
+ render json: { error: "User not found" }, status: 404
125
+ end
126
+ end
127
+ end
128
+
129
+ puts "โœ… Controllers created"
130
+
131
+ # Set up routes
132
+ puts "๐Ÿ›ฃ๏ธ Setting up routes..."
133
+
134
+ Rails.application.routes.draw do
135
+ get '/health', to: 'application#health_check'
136
+ get '/users', to: 'users#index'
137
+ get '/users/:id', to: 'users#show'
138
+
139
+ # Documentation routes (manual for now)
140
+ get '/docs', to: proc { |env|
141
+ [200, { 'Content-Type' => 'text/html' }, [<<~HTML
142
+ <!DOCTYPE html>
143
+ <html>
144
+ <head>
145
+ <title>Rails 8 + RapiTapir Demo API</title>
146
+ <style>
147
+ body { font-family: Arial, sans-serif; margin: 40px; }
148
+ h1 { color: #333; }
149
+ .endpoint { background: #f5f5f5; padding: 15px; margin: 10px 0; border-radius: 5px; }
150
+ .method { font-weight: bold; color: #007bff; }
151
+ .path { font-family: monospace; background: #eee; padding: 2px 4px; }
152
+ pre { background: #f8f9fa; padding: 10px; border-radius: 3px; overflow-x: auto; }
153
+ </style>
154
+ </head>
155
+ <body>
156
+ <h1>Rails 8 + RapiTapir Demo API</h1>
157
+ <p>This is a working demonstration of RapiTapir with Rails 8.</p>
158
+
159
+ <h2>Available Endpoints</h2>
160
+
161
+ <div class="endpoint">
162
+ <h3><span class="method">GET</span> <span class="path">/health</span></h3>
163
+ <p>Health check endpoint</p>
164
+ <h4>Example Response:</h4>
165
+ <pre>{"status":"ok","timestamp":"2025-08-06T10:30:00Z","rails_version":"8.0.2","ruby_version":"3.3.4"}</pre>
166
+ </div>
167
+
168
+ <div class="endpoint">
169
+ <h3><span class="method">GET</span> <span class="path">/users</span></h3>
170
+ <p>List all users</p>
171
+ <h4>Example Response:</h4>
172
+ <pre>{"users":[{"id":1,"name":"Alice Johnson","email":"alice@example.com"},{"id":2,"name":"Bob Smith","email":"bob@example.com"}]}</pre>
173
+ </div>
174
+
175
+ <div class="endpoint">
176
+ <h3><span class="method">GET</span> <span class="path">/users/:id</span></h3>
177
+ <p>Get a specific user by ID</p>
178
+ <h4>Example Response:</h4>
179
+ <pre>{"user":{"id":1,"name":"Alice Johnson","email":"alice@example.com"}}</pre>
180
+ <h4>Error Response (404):</h4>
181
+ <pre>{"error":"User not found"}</pre>
182
+ </div>
183
+
184
+ <h2>Test Commands</h2>
185
+ <pre>
186
+ curl http://localhost:3000/health
187
+ curl http://localhost:3000/users
188
+ curl http://localhost:3000/users/1
189
+ curl http://localhost:3000/users/999
190
+ </pre>
191
+
192
+ <h2>About</h2>
193
+ <p>This demo shows Rails 8 working with RapiTapir endpoints defined using the standard DSL.</p>
194
+ <p>While this example doesn't use the Rails integration features (which are still in development),
195
+ it demonstrates that RapiTapir and Rails 8 can work together successfully.</p>
196
+ </body>
197
+ </html>
198
+ HTML
199
+ ]]
200
+ }
201
+ end
202
+
203
+ puts "โœ… Routes configured"
204
+
205
+ # Register endpoints with RapiTapir (for documentation generation)
206
+ puts "๐Ÿ“ Registering endpoints with RapiTapir..."
207
+
208
+ RapiTapir.register_endpoint(HEALTH_ENDPOINT)
209
+ RapiTapir.register_endpoint(LIST_USERS_ENDPOINT)
210
+ RapiTapir.register_endpoint(GET_USER_ENDPOINT)
211
+
212
+ puts "โœ… Endpoints registered"
213
+
214
+ # Start the server
215
+ if __FILE__ == $0
216
+ puts ""
217
+ puts "๐Ÿš€ Rails 8 + RapiTapir Demo is ready!"
218
+ puts ""
219
+ puts "๐Ÿ“‹ System Info:"
220
+ puts " Rails Version: #{Rails.version}"
221
+ puts " Ruby Version: #{RUBY_VERSION}"
222
+ puts " RapiTapir: โœ… Loaded"
223
+ puts ""
224
+ puts "๐Ÿ“š Available endpoints:"
225
+ puts " GET /health - Health check"
226
+ puts " GET /users - List all users"
227
+ puts " GET /users/:id - Get specific user"
228
+ puts " GET /docs - API documentation"
229
+ puts ""
230
+ puts "๐Ÿงช Test commands:"
231
+ puts " curl http://localhost:3000/health"
232
+ puts " curl http://localhost:3000/users"
233
+ puts " curl http://localhost:3000/users/1"
234
+ puts ""
235
+ puts "Starting server on http://localhost:3000..."
236
+ puts ""
237
+
238
+ begin
239
+ require 'webrick'
240
+ puts "Using WEBrick server..."
241
+ Rack::Handler::WEBrick.run(Rails.application, Port: 3000, Host: '0.0.0.0')
242
+ rescue LoadError
243
+ puts "WEBrick not available. Trying Puma..."
244
+ begin
245
+ require 'puma'
246
+ puts "Using Puma server..."
247
+ Rack::Handler::Puma.run(Rails.application, Port: 3000, Host: '0.0.0.0')
248
+ rescue LoadError
249
+ puts "โŒ No web server available. Install webrick or puma:"
250
+ puts " gem install webrick"
251
+ puts " gem install puma"
252
+ exit 1
253
+ end
254
+ end
255
+ end