rapitapir 0.1.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/.rspec +3 -0
- data/.rubocop.yml +57 -0
- data/CHANGELOG.md +94 -0
- data/CLEANUP_SUMMARY.md +155 -0
- data/CONTRIBUTING.md +280 -0
- data/LICENSE +21 -0
- data/README.md +485 -0
- data/debug_hash.rb +20 -0
- data/docs/EXTENSION_COMPARISON.md +388 -0
- data/docs/SINATRA_EXTENSION.md +467 -0
- data/docs/archive/PHASE_1_2_COMPLETE.md +77 -0
- data/docs/archive/PHASE_1_3_COMPLETE.md +152 -0
- data/docs/archive/PHASE_2_1_OBSERVABILITY_COMPLETED.md +203 -0
- data/docs/archive/PHASE_2_SUMMARY.md +209 -0
- data/docs/archive/REFACTORING_SUMMARY.md +184 -0
- data/docs/archive/phase_1_3_plan.md +136 -0
- data/docs/archive/sinatra_extension_summary.md +188 -0
- data/docs/archive/sinatra_working_solution.md +113 -0
- data/docs/archive/typescript-client-generator-summary.md +259 -0
- data/docs/auto-derivation.md +146 -0
- data/docs/blueprint.md +1091 -0
- data/docs/endpoint-definition.md +211 -0
- data/docs/github_pages_fix.md +52 -0
- data/docs/github_pages_setup.md +49 -0
- data/docs/implementation-status.md +357 -0
- data/docs/observability.md +647 -0
- data/docs/phase3-plan.md +108 -0
- data/docs/sinatra_rapitapir.md +87 -0
- data/docs/type_shortcuts.md +146 -0
- data/examples/README_ENTERPRISE.md +202 -0
- data/examples/authentication_example.rb +192 -0
- data/examples/auto_derivation_ruby_friendly.rb +163 -0
- data/examples/cli/user_api_endpoints.rb +56 -0
- data/examples/client/typescript_client_example.rb +102 -0
- data/examples/client/user-api-client.ts +193 -0
- data/examples/demo_api.rb +41 -0
- data/examples/docs/documentation_example.rb +112 -0
- data/examples/docs/user-api-docs.html +789 -0
- data/examples/docs/user-api-docs.md +403 -0
- data/examples/enhanced_auto_derivation_test.rb +83 -0
- data/examples/enterprise_extension_demo.rb +417 -0
- data/examples/enterprise_rapitapir_api.rb +662 -0
- data/examples/getting_started_extension.rb +218 -0
- data/examples/hello_world.rb +74 -0
- data/examples/oauth2/.env.example +19 -0
- data/examples/oauth2/README.md +205 -0
- data/examples/oauth2/generic_oauth2_api.rb +226 -0
- data/examples/oauth2/get_token.rb +72 -0
- data/examples/oauth2/songs_api_with_auth0.rb +320 -0
- data/examples/oauth2/test_api.sh +16 -0
- data/examples/oauth2/test_songs_api.sh +110 -0
- data/examples/observability/.env.example +35 -0
- data/examples/observability/README.md +230 -0
- data/examples/observability/README_HONEYCOMB.md +332 -0
- data/examples/observability/advanced_setup.rb +384 -0
- data/examples/observability/basic_setup.rb +192 -0
- data/examples/observability/complete_test.rb +121 -0
- data/examples/observability/honeycomb_example.rb +523 -0
- data/examples/observability/honeycomb_rapitapir_clean.rb +488 -0
- data/examples/observability/honeycomb_rapitapir_example.rb +523 -0
- data/examples/observability/honeycomb_working_example.rb +489 -0
- data/examples/observability/quick_test.rb +78 -0
- data/examples/observability/simple_test.rb +14 -0
- data/examples/observability/test_honeycomb_demo.rb +354 -0
- data/examples/observability/test_live_honeycomb.rb +111 -0
- data/examples/observability/test_validation.rb +78 -0
- data/examples/observability/test_working_validation.rb +66 -0
- data/examples/openapi/user_api_schema.rb +132 -0
- data/examples/production_ready_example.rb +105 -0
- data/examples/rails/users_controller.rb +146 -0
- data/examples/readme/basic_sinatra_example.rb +128 -0
- data/examples/server/user_api.rb +179 -0
- data/examples/simple_auto_derivation_demo.rb +44 -0
- data/examples/simple_demo_api.rb +18 -0
- data/examples/sinatra/user_app.rb +127 -0
- data/examples/t_shortcut_demo.rb +59 -0
- data/examples/user_api.rb +190 -0
- data/examples/working_getting_started.rb +184 -0
- data/examples/working_simple_example.rb +195 -0
- data/lib/rapitapir/auth/configuration.rb +129 -0
- data/lib/rapitapir/auth/context.rb +122 -0
- data/lib/rapitapir/auth/errors.rb +104 -0
- data/lib/rapitapir/auth/middleware.rb +324 -0
- data/lib/rapitapir/auth/oauth2.rb +350 -0
- data/lib/rapitapir/auth/schemes.rb +420 -0
- data/lib/rapitapir/auth.rb +113 -0
- data/lib/rapitapir/cli/command.rb +535 -0
- data/lib/rapitapir/cli/server.rb +243 -0
- data/lib/rapitapir/cli/validator.rb +373 -0
- data/lib/rapitapir/client/generator_base.rb +272 -0
- data/lib/rapitapir/client/typescript_generator.rb +350 -0
- data/lib/rapitapir/core/endpoint.rb +158 -0
- data/lib/rapitapir/core/enhanced_endpoint.rb +235 -0
- data/lib/rapitapir/core/input.rb +182 -0
- data/lib/rapitapir/core/output.rb +164 -0
- data/lib/rapitapir/core/request.rb +19 -0
- data/lib/rapitapir/core/response.rb +17 -0
- data/lib/rapitapir/docs/html_generator.rb +780 -0
- data/lib/rapitapir/docs/markdown_generator.rb +464 -0
- data/lib/rapitapir/dsl/endpoint_dsl.rb +116 -0
- data/lib/rapitapir/dsl/enhanced_endpoint_dsl.rb +62 -0
- data/lib/rapitapir/dsl/enhanced_input.rb +73 -0
- data/lib/rapitapir/dsl/enhanced_output.rb +63 -0
- data/lib/rapitapir/dsl/enhanced_structures.rb +393 -0
- data/lib/rapitapir/dsl/fluent_dsl.rb +72 -0
- data/lib/rapitapir/dsl/fluent_endpoint_builder.rb +316 -0
- data/lib/rapitapir/dsl/http_verbs.rb +77 -0
- data/lib/rapitapir/dsl/input_methods.rb +47 -0
- data/lib/rapitapir/dsl/observability_methods.rb +81 -0
- data/lib/rapitapir/dsl/output_methods.rb +43 -0
- data/lib/rapitapir/dsl/type_resolution.rb +43 -0
- data/lib/rapitapir/observability/configuration.rb +108 -0
- data/lib/rapitapir/observability/health_check.rb +236 -0
- data/lib/rapitapir/observability/logging.rb +270 -0
- data/lib/rapitapir/observability/metrics.rb +203 -0
- data/lib/rapitapir/observability/middleware.rb +243 -0
- data/lib/rapitapir/observability/tracing.rb +143 -0
- data/lib/rapitapir/observability.rb +28 -0
- data/lib/rapitapir/openapi/schema_generator.rb +403 -0
- data/lib/rapitapir/schema.rb +136 -0
- data/lib/rapitapir/server/enhanced_rack_adapter.rb +379 -0
- data/lib/rapitapir/server/middleware.rb +120 -0
- data/lib/rapitapir/server/path_matcher.rb +45 -0
- data/lib/rapitapir/server/rack_adapter.rb +215 -0
- data/lib/rapitapir/server/rails_adapter.rb +17 -0
- data/lib/rapitapir/server/rails_adapter_class.rb +53 -0
- data/lib/rapitapir/server/rails_controller.rb +72 -0
- data/lib/rapitapir/server/rails_input_processor.rb +73 -0
- data/lib/rapitapir/server/rails_response_handler.rb +29 -0
- data/lib/rapitapir/server/sinatra_adapter.rb +200 -0
- data/lib/rapitapir/server/sinatra_integration.rb +93 -0
- data/lib/rapitapir/sinatra/configuration.rb +91 -0
- data/lib/rapitapir/sinatra/extension.rb +214 -0
- data/lib/rapitapir/sinatra/oauth2_helpers.rb +236 -0
- data/lib/rapitapir/sinatra/resource_builder.rb +152 -0
- data/lib/rapitapir/sinatra/swagger_ui_generator.rb +166 -0
- data/lib/rapitapir/sinatra_rapitapir.rb +40 -0
- data/lib/rapitapir/types/array.rb +163 -0
- data/lib/rapitapir/types/auto_derivation.rb +265 -0
- data/lib/rapitapir/types/base.rb +146 -0
- data/lib/rapitapir/types/boolean.rb +46 -0
- data/lib/rapitapir/types/date.rb +92 -0
- data/lib/rapitapir/types/datetime.rb +98 -0
- data/lib/rapitapir/types/email.rb +32 -0
- data/lib/rapitapir/types/float.rb +134 -0
- data/lib/rapitapir/types/hash.rb +161 -0
- data/lib/rapitapir/types/integer.rb +143 -0
- data/lib/rapitapir/types/object.rb +156 -0
- data/lib/rapitapir/types/optional.rb +65 -0
- data/lib/rapitapir/types/string.rb +185 -0
- data/lib/rapitapir/types/uuid.rb +32 -0
- data/lib/rapitapir/types.rb +155 -0
- data/lib/rapitapir/version.rb +5 -0
- data/lib/rapitapir.rb +173 -0
- data/rapitapir.gemspec +66 -0
- metadata +387 -0
@@ -0,0 +1,467 @@
|
|
1
|
+
# RapiTapir Sinatra Extension
|
2
|
+
|
3
|
+
**Zero-boilerplate, enterprise-grade API development with RapiTapir and Sinatra**
|
4
|
+
|
5
|
+
The RapiTapir Sinatra Extension provides a seamless, ergonomic experience for building production-ready APIs by eliminating repetitive configuration and following SOLID principles.
|
6
|
+
|
7
|
+
## ๐ Quick Start
|
8
|
+
|
9
|
+
```ruby
|
10
|
+
require 'sinatra/base'
|
11
|
+
require 'rapitapir'
|
12
|
+
require 'rapitapir/sinatra/extension'
|
13
|
+
|
14
|
+
class MyAPI < Sinatra::Base
|
15
|
+
register RapiTapir::Sinatra::Extension
|
16
|
+
|
17
|
+
rapitapir do
|
18
|
+
info title: 'My API', version: '1.0.0'
|
19
|
+
development_defaults!
|
20
|
+
end
|
21
|
+
|
22
|
+
# Define a simple endpoint
|
23
|
+
endpoint(
|
24
|
+
RapiTapir.get('/hello')
|
25
|
+
.ok(RapiTapir::Types.hash({ "message" => RapiTapir::Types.string }))
|
26
|
+
.build
|
27
|
+
) { { message: 'Hello, World!' } }
|
28
|
+
end
|
29
|
+
```
|
30
|
+
|
31
|
+
## ๐ Table of Contents
|
32
|
+
|
33
|
+
- [Features](#features)
|
34
|
+
- [Installation](#installation)
|
35
|
+
- [Configuration](#configuration)
|
36
|
+
- [Endpoint Definition](#endpoint-definition)
|
37
|
+
- [RESTful Resources](#restful-resources)
|
38
|
+
- [Authentication](#authentication)
|
39
|
+
- [Middleware](#middleware)
|
40
|
+
- [Documentation](#documentation)
|
41
|
+
- [Examples](#examples)
|
42
|
+
- [Architecture](#architecture)
|
43
|
+
|
44
|
+
## โจ Features
|
45
|
+
|
46
|
+
### Zero Boilerplate
|
47
|
+
- **One-line configuration**: Set up authentication, middleware, and documentation with minimal code
|
48
|
+
- **Smart defaults**: Production and development presets that just work
|
49
|
+
- **Automatic registration**: Endpoints are automatically registered with proper validation
|
50
|
+
|
51
|
+
### Enterprise-Ready
|
52
|
+
- **Built-in authentication**: Bearer token, API key, and custom schemes
|
53
|
+
- **Production middleware**: CORS, rate limiting, security headers
|
54
|
+
- **Auto-generated OpenAPI**: Beautiful Swagger UI documentation
|
55
|
+
- **Type-safe validation**: Automatic request/response validation
|
56
|
+
|
57
|
+
### Developer Experience
|
58
|
+
- **RESTful resource builder**: Create full CRUD APIs with a single block
|
59
|
+
- **Helpful error messages**: Clear validation and authentication errors
|
60
|
+
- **Hot reloading**: Development-friendly configuration
|
61
|
+
- **Extensive examples**: Get started quickly with working code
|
62
|
+
|
63
|
+
## ๐ง Installation
|
64
|
+
|
65
|
+
Add to your Gemfile:
|
66
|
+
|
67
|
+
```ruby
|
68
|
+
gem 'rapitapir'
|
69
|
+
```
|
70
|
+
|
71
|
+
Or install directly:
|
72
|
+
|
73
|
+
```bash
|
74
|
+
gem install rapitapir
|
75
|
+
```
|
76
|
+
|
77
|
+
## โ๏ธ Configuration
|
78
|
+
|
79
|
+
### Basic Configuration
|
80
|
+
|
81
|
+
```ruby
|
82
|
+
class MyAPI < Sinatra::Base
|
83
|
+
register RapiTapir::Sinatra::Extension
|
84
|
+
|
85
|
+
rapitapir do
|
86
|
+
# API metadata
|
87
|
+
info(
|
88
|
+
title: 'My API',
|
89
|
+
description: 'A fantastic API',
|
90
|
+
version: '1.0.0',
|
91
|
+
contact: { email: 'support@example.com' }
|
92
|
+
)
|
93
|
+
|
94
|
+
# Server configuration
|
95
|
+
server url: 'http://localhost:4567', description: 'Development'
|
96
|
+
server url: 'https://api.example.com', description: 'Production'
|
97
|
+
|
98
|
+
# Enable documentation
|
99
|
+
enable_docs path: '/docs', openapi_path: '/openapi.json'
|
100
|
+
end
|
101
|
+
end
|
102
|
+
```
|
103
|
+
|
104
|
+
### Environment-Specific Defaults
|
105
|
+
|
106
|
+
```ruby
|
107
|
+
rapitapir do
|
108
|
+
if development?
|
109
|
+
development_defaults! # Permissive CORS, high rate limits
|
110
|
+
else
|
111
|
+
production_defaults! # Secure defaults for production
|
112
|
+
end
|
113
|
+
end
|
114
|
+
```
|
115
|
+
|
116
|
+
## ๐ก๏ธ Authentication
|
117
|
+
|
118
|
+
### Bearer Token Authentication
|
119
|
+
|
120
|
+
```ruby
|
121
|
+
rapitapir do
|
122
|
+
bearer_auth :bearer, {
|
123
|
+
realm: 'My API',
|
124
|
+
token_validator: proc do |token|
|
125
|
+
user = User.find_by_token(token)
|
126
|
+
next nil unless user
|
127
|
+
|
128
|
+
{
|
129
|
+
user: user,
|
130
|
+
scopes: user.scopes
|
131
|
+
}
|
132
|
+
end
|
133
|
+
}
|
134
|
+
end
|
135
|
+
```
|
136
|
+
|
137
|
+
### API Key Authentication
|
138
|
+
|
139
|
+
```ruby
|
140
|
+
rapitapir do
|
141
|
+
api_key_auth :api_key, {
|
142
|
+
location: 'header',
|
143
|
+
name: 'X-API-Key',
|
144
|
+
key_validator: proc do |key|
|
145
|
+
# Validate API key
|
146
|
+
end
|
147
|
+
}
|
148
|
+
end
|
149
|
+
```
|
150
|
+
|
151
|
+
### Public Endpoints
|
152
|
+
|
153
|
+
```ruby
|
154
|
+
rapitapir do
|
155
|
+
public_paths '/health', '/docs', '/openapi.json'
|
156
|
+
end
|
157
|
+
```
|
158
|
+
|
159
|
+
## ๐ก Endpoint Definition
|
160
|
+
|
161
|
+
### Simple Endpoints
|
162
|
+
|
163
|
+
```ruby
|
164
|
+
endpoint(
|
165
|
+
RapiTapir.get('/users')
|
166
|
+
.summary('List users')
|
167
|
+
.ok(RapiTapir::Types.array(USER_SCHEMA))
|
168
|
+
.build
|
169
|
+
) do |inputs|
|
170
|
+
User.all
|
171
|
+
end
|
172
|
+
```
|
173
|
+
|
174
|
+
### With Authentication Requirements
|
175
|
+
|
176
|
+
```ruby
|
177
|
+
endpoint(
|
178
|
+
RapiTapir.post('/admin/users')
|
179
|
+
.summary('Create user (admin only)')
|
180
|
+
.json_body(USER_CREATE_SCHEMA)
|
181
|
+
.created(USER_SCHEMA)
|
182
|
+
.build
|
183
|
+
) do |inputs|
|
184
|
+
require_scope!('admin')
|
185
|
+
User.create(inputs[:body])
|
186
|
+
end
|
187
|
+
```
|
188
|
+
|
189
|
+
## ๐๏ธ RESTful Resources
|
190
|
+
|
191
|
+
The resource builder creates full CRUD APIs with minimal code:
|
192
|
+
|
193
|
+
```ruby
|
194
|
+
api_resource '/api/v1/tasks', schema: TASK_SCHEMA do
|
195
|
+
# Enable all CRUD operations
|
196
|
+
crud do
|
197
|
+
index { Task.all }
|
198
|
+
show { |inputs| Task.find(inputs[:id]) }
|
199
|
+
create { |inputs| Task.create(inputs[:body]) }
|
200
|
+
update { |inputs| Task.update(inputs[:id], inputs[:body]) }
|
201
|
+
destroy { |inputs| Task.delete(inputs[:id]) }
|
202
|
+
end
|
203
|
+
end
|
204
|
+
```
|
205
|
+
|
206
|
+
### Selective Operations
|
207
|
+
|
208
|
+
```ruby
|
209
|
+
api_resource '/books', schema: BOOK_SCHEMA do
|
210
|
+
crud(except: [:destroy]) do # All operations except delete
|
211
|
+
index { Book.published }
|
212
|
+
show { |inputs| Book.find(inputs[:id]) }
|
213
|
+
create { |inputs| Book.create(inputs[:body]) }
|
214
|
+
update { |inputs| Book.update(inputs[:id], inputs[:body]) }
|
215
|
+
end
|
216
|
+
end
|
217
|
+
```
|
218
|
+
|
219
|
+
### Custom Endpoints
|
220
|
+
|
221
|
+
```ruby
|
222
|
+
api_resource '/tasks', schema: TASK_SCHEMA do
|
223
|
+
crud { /* ... */ }
|
224
|
+
|
225
|
+
# Custom endpoint: /tasks/by-status/:status
|
226
|
+
custom(:get, 'by-status/:status',
|
227
|
+
summary: 'Get tasks by status',
|
228
|
+
configure: ->(endpoint) {
|
229
|
+
endpoint
|
230
|
+
.path_param(:status, RapiTapir::Types.string)
|
231
|
+
.ok(RapiTapir::Types.array(TASK_SCHEMA))
|
232
|
+
}
|
233
|
+
) do |inputs|
|
234
|
+
Task.where(status: inputs[:status])
|
235
|
+
end
|
236
|
+
end
|
237
|
+
```
|
238
|
+
|
239
|
+
### Different Scopes for Operations
|
240
|
+
|
241
|
+
```ruby
|
242
|
+
api_resource '/users', schema: USER_SCHEMA do
|
243
|
+
crud do
|
244
|
+
index(scopes: ['read']) { User.all }
|
245
|
+
show(scopes: ['read']) { |inputs| User.find(inputs[:id]) }
|
246
|
+
create(scopes: ['write']) { |inputs| User.create(inputs[:body]) }
|
247
|
+
update(scopes: ['write']) { |inputs| User.update(inputs[:id], inputs[:body]) }
|
248
|
+
destroy(scopes: ['admin']) { |inputs| User.delete(inputs[:id]) }
|
249
|
+
end
|
250
|
+
end
|
251
|
+
```
|
252
|
+
|
253
|
+
## ๐ Authentication Helpers
|
254
|
+
|
255
|
+
```ruby
|
256
|
+
endpoint(...) do |inputs|
|
257
|
+
# Check if user is authenticated
|
258
|
+
require_authentication!
|
259
|
+
|
260
|
+
# Check specific scope
|
261
|
+
require_scope!('admin')
|
262
|
+
|
263
|
+
# Get current user
|
264
|
+
user = current_user
|
265
|
+
|
266
|
+
# Check if authenticated (non-throwing)
|
267
|
+
if authenticated?
|
268
|
+
# User is logged in
|
269
|
+
end
|
270
|
+
|
271
|
+
# Check scope (non-throwing)
|
272
|
+
if has_scope?('write')
|
273
|
+
# User has write permission
|
274
|
+
end
|
275
|
+
end
|
276
|
+
```
|
277
|
+
|
278
|
+
## ๐ ๏ธ Middleware Configuration
|
279
|
+
|
280
|
+
### CORS
|
281
|
+
|
282
|
+
```ruby
|
283
|
+
rapitapir do
|
284
|
+
cors(
|
285
|
+
allowed_origins: ['https://myapp.com'],
|
286
|
+
allowed_methods: ['GET', 'POST', 'PUT', 'DELETE'],
|
287
|
+
allowed_headers: ['Authorization', 'Content-Type'],
|
288
|
+
allow_credentials: true
|
289
|
+
)
|
290
|
+
end
|
291
|
+
```
|
292
|
+
|
293
|
+
### Rate Limiting
|
294
|
+
|
295
|
+
```ruby
|
296
|
+
rapitapir do
|
297
|
+
rate_limiting(
|
298
|
+
requests_per_minute: 60,
|
299
|
+
requests_per_hour: 1000
|
300
|
+
)
|
301
|
+
end
|
302
|
+
```
|
303
|
+
|
304
|
+
### Security Headers
|
305
|
+
|
306
|
+
```ruby
|
307
|
+
rapitapir do
|
308
|
+
security_headers(
|
309
|
+
csp: "default-src 'self'",
|
310
|
+
hsts: true
|
311
|
+
)
|
312
|
+
end
|
313
|
+
```
|
314
|
+
|
315
|
+
## ๐ Documentation
|
316
|
+
|
317
|
+
### Automatic OpenAPI Generation
|
318
|
+
|
319
|
+
The extension automatically generates OpenAPI 3.0 specifications from your endpoint definitions:
|
320
|
+
|
321
|
+
- **Swagger UI**: Beautiful, interactive documentation
|
322
|
+
- **Type validation**: Schemas automatically derived from RapiTapir types
|
323
|
+
- **Authentication schemes**: Security requirements automatically added
|
324
|
+
- **Request/response examples**: Generated from your schemas
|
325
|
+
|
326
|
+
### Custom Documentation
|
327
|
+
|
328
|
+
```ruby
|
329
|
+
rapitapir do
|
330
|
+
info(
|
331
|
+
title: 'My API',
|
332
|
+
description: 'Comprehensive API documentation',
|
333
|
+
version: '1.0.0',
|
334
|
+
contact: {
|
335
|
+
name: 'Support Team',
|
336
|
+
email: 'support@example.com',
|
337
|
+
url: 'https://example.com/support'
|
338
|
+
},
|
339
|
+
license: {
|
340
|
+
name: 'MIT',
|
341
|
+
url: 'https://opensource.org/licenses/MIT'
|
342
|
+
}
|
343
|
+
)
|
344
|
+
end
|
345
|
+
```
|
346
|
+
|
347
|
+
## ๐ฏ Complete Examples
|
348
|
+
|
349
|
+
### Minimal Bookstore API
|
350
|
+
|
351
|
+
```ruby
|
352
|
+
require 'sinatra/base'
|
353
|
+
require 'rapitapir/sinatra/extension'
|
354
|
+
|
355
|
+
class BookstoreAPI < Sinatra::Base
|
356
|
+
register RapiTapir::Sinatra::Extension
|
357
|
+
|
358
|
+
rapitapir do
|
359
|
+
info title: 'Bookstore API', version: '1.0.0'
|
360
|
+
development_defaults!
|
361
|
+
public_paths '/books'
|
362
|
+
end
|
363
|
+
|
364
|
+
BOOK_SCHEMA = RapiTapir::Types.hash({
|
365
|
+
"id" => RapiTapir::Types.integer,
|
366
|
+
"title" => RapiTapir::Types.string,
|
367
|
+
"author" => RapiTapir::Types.string
|
368
|
+
})
|
369
|
+
|
370
|
+
api_resource '/books', schema: BOOK_SCHEMA do
|
371
|
+
crud do
|
372
|
+
index { Book.all }
|
373
|
+
show { |inputs| Book.find(inputs[:id]) }
|
374
|
+
create { |inputs| Book.create(inputs[:body]) }
|
375
|
+
update { |inputs| Book.update(inputs[:id], inputs[:body]) }
|
376
|
+
end
|
377
|
+
end
|
378
|
+
end
|
379
|
+
```
|
380
|
+
|
381
|
+
### Enterprise Task Management API
|
382
|
+
|
383
|
+
See `examples/enterprise_extension_demo.rb` for a comprehensive example with:
|
384
|
+
- Bearer token authentication
|
385
|
+
- Multiple resources
|
386
|
+
- Custom endpoints
|
387
|
+
- Admin-only operations
|
388
|
+
- Full middleware stack
|
389
|
+
|
390
|
+
## ๐๏ธ Architecture
|
391
|
+
|
392
|
+
The RapiTapir Sinatra Extension follows SOLID principles:
|
393
|
+
|
394
|
+
### Single Responsibility Principle
|
395
|
+
- **Extension**: Manages Sinatra integration only
|
396
|
+
- **Configuration**: Handles API configuration only
|
397
|
+
- **ResourceBuilder**: Creates RESTful endpoints only
|
398
|
+
- **SwaggerUIGenerator**: Generates documentation UI only
|
399
|
+
|
400
|
+
### Open/Closed Principle
|
401
|
+
- **Extensible**: Add new authentication schemes without modifying core
|
402
|
+
- **Pluggable**: Custom middleware can be added
|
403
|
+
- **Customizable**: Resource builder supports custom endpoints
|
404
|
+
|
405
|
+
### Liskov Substitution Principle
|
406
|
+
- **Endpoint compatibility**: Works with any RapiTapir endpoint
|
407
|
+
- **Authentication schemes**: All auth schemes follow same interface
|
408
|
+
|
409
|
+
### Interface Segregation Principle
|
410
|
+
- **Focused interfaces**: Each component has a specific, minimal interface
|
411
|
+
- **Optional features**: Documentation, authentication, middleware are optional
|
412
|
+
|
413
|
+
### Dependency Inversion Principle
|
414
|
+
- **Abstractions**: Depends on RapiTapir abstractions, not concrete implementations
|
415
|
+
- **Injection**: Authentication and validation logic is injected via procs
|
416
|
+
|
417
|
+
## ๐ Migration from Manual Implementation
|
418
|
+
|
419
|
+
Migrating from manual Sinatra routes to the extension:
|
420
|
+
|
421
|
+
### Before (Manual)
|
422
|
+
```ruby
|
423
|
+
class MyAPI < Sinatra::Base
|
424
|
+
use SomeMiddleware
|
425
|
+
use SomeOtherMiddleware
|
426
|
+
|
427
|
+
get '/tasks' do
|
428
|
+
# Manual authentication
|
429
|
+
# Manual validation
|
430
|
+
# Manual response formatting
|
431
|
+
end
|
432
|
+
|
433
|
+
post '/tasks' do
|
434
|
+
# Repeat authentication, validation, etc.
|
435
|
+
end
|
436
|
+
|
437
|
+
# Repeat for every endpoint...
|
438
|
+
end
|
439
|
+
```
|
440
|
+
|
441
|
+
### After (Extension)
|
442
|
+
```ruby
|
443
|
+
class MyAPI < Sinatra::Base
|
444
|
+
register RapiTapir::Sinatra::Extension
|
445
|
+
|
446
|
+
rapitapir do
|
447
|
+
bearer_auth { /* config */ }
|
448
|
+
development_defaults!
|
449
|
+
end
|
450
|
+
|
451
|
+
api_resource '/tasks', schema: TASK_SCHEMA do
|
452
|
+
crud { /* handlers */ }
|
453
|
+
end
|
454
|
+
end
|
455
|
+
```
|
456
|
+
|
457
|
+
## ๐ค Contributing
|
458
|
+
|
459
|
+
1. Fork the repository
|
460
|
+
2. Create a feature branch
|
461
|
+
3. Add tests for your changes
|
462
|
+
4. Ensure all tests pass
|
463
|
+
5. Submit a pull request
|
464
|
+
|
465
|
+
## ๐ License
|
466
|
+
|
467
|
+
MIT License - see LICENSE file for details.
|
@@ -0,0 +1,77 @@
|
|
1
|
+
# ๐ RapiTapir Phase 1.2 - Server Integration Foundation COMPLETE!
|
2
|
+
|
3
|
+
## โ
Accomplished in Phase 1.2
|
4
|
+
|
5
|
+
### 1. Enhanced Type System Integration
|
6
|
+
- **Complete type validation pipeline** working for all primitive and composite types
|
7
|
+
- **Robust constraint checking** with detailed error reporting
|
8
|
+
- **Type coercion system** for automatic data conversion
|
9
|
+
- **JSON Schema generation** for OpenAPI compatibility
|
10
|
+
|
11
|
+
### 2. Server Foundation Components
|
12
|
+
- **Enhanced Rack Adapter** (`lib/rapitapir/server/enhanced_rack_adapter.rb`)
|
13
|
+
- Request routing and endpoint mounting
|
14
|
+
- Input extraction and validation
|
15
|
+
- Response serialization
|
16
|
+
- Comprehensive error handling
|
17
|
+
- **Sinatra Integration** (`lib/rapitapir/server/sinatra_integration.rb`)
|
18
|
+
- Easy endpoint mounting in Sinatra apps
|
19
|
+
- Automatic OpenAPI spec generation
|
20
|
+
- Path format conversion
|
21
|
+
|
22
|
+
### 3. Enhanced Endpoint Architecture
|
23
|
+
- **Enhanced Endpoint class** extending basic endpoints with type system
|
24
|
+
- **Enhanced DSL integration** for input/output specification
|
25
|
+
- **Security scheme support** for authentication
|
26
|
+
- **OpenAPI specification generation**
|
27
|
+
|
28
|
+
### 4. Comprehensive Schema System
|
29
|
+
- **Schema definition DSL** for complex object structures
|
30
|
+
- **Field validation** with required/optional handling
|
31
|
+
- **Nested type support** for complex data structures
|
32
|
+
- **Builder pattern** for ergonomic schema construction
|
33
|
+
|
34
|
+
## ๐งช Validation Results
|
35
|
+
|
36
|
+
**All foundation components tested and working:**
|
37
|
+
- โ
Type validation: String, Integer, UUID, Email with constraints
|
38
|
+
- โ
Schema validation: Complex objects with multiple fields
|
39
|
+
- โ
Composite types: Arrays, Hashes, Optional types
|
40
|
+
- โ
Type coercion: StringโInteger, StringโBoolean, StringโDate
|
41
|
+
- โ
JSON Schema generation: Full OpenAPI-compatible schemas
|
42
|
+
- โ
Enhanced endpoints: Class loading and basic functionality
|
43
|
+
|
44
|
+
## ๐ Ready for Phase 1.3
|
45
|
+
|
46
|
+
The foundation is now solid for implementing Phase 1.3 - Enhanced Endpoint DSL:
|
47
|
+
|
48
|
+
### Next Priority Areas:
|
49
|
+
1. **Fluent DSL Implementation**
|
50
|
+
- Method chaining for endpoint building
|
51
|
+
- Simplified input/output specification
|
52
|
+
- Authentication integration
|
53
|
+
|
54
|
+
2. **Path Composition & Routing**
|
55
|
+
- Advanced path parameter handling
|
56
|
+
- Route matching optimization
|
57
|
+
- Middleware integration
|
58
|
+
|
59
|
+
3. **Advanced Authentication**
|
60
|
+
- Multiple auth scheme support
|
61
|
+
- Scope-based permissions
|
62
|
+
- JWT integration
|
63
|
+
|
64
|
+
4. **Error Handling Enhancement**
|
65
|
+
- oneOf response handling
|
66
|
+
- Custom error schemas
|
67
|
+
- Validation error mapping
|
68
|
+
|
69
|
+
## ๐ Phase 1 Progress
|
70
|
+
|
71
|
+
- **Phase 1.1**: โ
Advanced Type System (COMPLETE)
|
72
|
+
- **Phase 1.2**: โ
Server Integration Foundation (COMPLETE)
|
73
|
+
- **Phase 1.3**: ๐ก Enhanced Endpoint DSL (NEXT)
|
74
|
+
|
75
|
+
**Total Implementation**: 12 new type classes, 2 server adapters, enhanced endpoint system, comprehensive validation framework, JSON schema generation, and complete test coverage.
|
76
|
+
|
77
|
+
RapiTapir is now ready to move from a documentation tool to a production-ready API framework! ๐
|
@@ -0,0 +1,152 @@
|
|
1
|
+
# ๐ RapiTapir Phase 1.3 - Enhanced Fluent DSL COMPLETE!
|
2
|
+
|
3
|
+
## โ
Accomplished in Phase 1.3
|
4
|
+
|
5
|
+
### 1. Fluent Endpoint Builder
|
6
|
+
- **Chainable DSL methods** for elegant endpoint creation
|
7
|
+
- **Method chaining** with immutable builder pattern
|
8
|
+
- **Type-safe configuration** with compile-time validation
|
9
|
+
- **State management** for consistent endpoint building
|
10
|
+
|
11
|
+
### 2. Enhanced Input/Output DSL
|
12
|
+
- **Simplified input methods**: `.query()`, `.path_param()`, `.header()`, `.body()`, `.json_body()`
|
13
|
+
- **Output specification**: `.ok()`, `.created()`, `.responds_with()`, `.json_response()`, `.text_response()`
|
14
|
+
- **Status code helpers**: `.bad_request()`, `.unauthorized()`, `.forbidden()`, `.not_found()`, etc.
|
15
|
+
- **Content-type handling**: automatic JSON, explicit content types, multipart forms
|
16
|
+
|
17
|
+
### 3. Advanced Authentication DSL
|
18
|
+
- **Multiple auth schemes**: Bearer, API Key, Basic, OAuth2
|
19
|
+
- **Scope-based permissions**: `.requires_scope()` with multiple scopes
|
20
|
+
- **Optional authentication**: `.optional_auth()` for conditional features
|
21
|
+
- **Flexible configuration**: headers, query parameters, custom schemes
|
22
|
+
|
23
|
+
### 4. Namespace and Grouping
|
24
|
+
- **Path prefixes**: `.namespace("/api/v1/users")` with automatic path composition
|
25
|
+
- **Shared configuration**: authentication, error responses, middleware
|
26
|
+
- **Endpoint inheritance**: all endpoints inherit namespace configuration
|
27
|
+
- **Organization**: logical grouping of related endpoints
|
28
|
+
|
29
|
+
### 5. Enhanced Error Handling
|
30
|
+
- **Comprehensive error responses**: status codes with type schemas
|
31
|
+
- **Reusable error definitions**: shared across namespace
|
32
|
+
- **Validation error mapping**: automatic type validation to HTTP errors
|
33
|
+
- **Custom error schemas**: domain-specific error formats
|
34
|
+
|
35
|
+
### 6. Developer Experience Improvements
|
36
|
+
- **Intuitive API**: natural, readable endpoint definitions
|
37
|
+
- **IDE support**: method chaining with autocomplete
|
38
|
+
- **Type safety**: compile-time checks for configuration
|
39
|
+
- **Documentation integration**: built-in OpenAPI generation
|
40
|
+
|
41
|
+
## ๐งช Demo Results
|
42
|
+
|
43
|
+
**All Phase 1.3 features tested and working:**
|
44
|
+
|
45
|
+
### โ
Fluent Endpoint Creation
|
46
|
+
```ruby
|
47
|
+
RapiTapir.get("/users")
|
48
|
+
.summary("List all users")
|
49
|
+
.query(:limit, :integer, min: 1, max: 100, required: false)
|
50
|
+
.query(:offset, :integer, min: 0, required: false)
|
51
|
+
.bearer_auth("API access token required")
|
52
|
+
.ok(user_array_schema)
|
53
|
+
.bad_request(error_schema)
|
54
|
+
.tags("users", "public-api")
|
55
|
+
```
|
56
|
+
|
57
|
+
### โ
Multiple Authentication Schemes
|
58
|
+
```ruby
|
59
|
+
# Bearer token
|
60
|
+
.bearer_auth("API token required")
|
61
|
+
|
62
|
+
# API Key in header
|
63
|
+
.api_key_auth("X-API-Key", :header)
|
64
|
+
|
65
|
+
# Basic authentication
|
66
|
+
.basic_auth("Admin credentials required")
|
67
|
+
|
68
|
+
# OAuth2 with scopes
|
69
|
+
.oauth2_auth(["profile:read", "email:read"])
|
70
|
+
|
71
|
+
# Optional authentication
|
72
|
+
.bearer_auth().optional_auth
|
73
|
+
```
|
74
|
+
|
75
|
+
### โ
Namespace Configuration
|
76
|
+
```ruby
|
77
|
+
user_api = RapiTapir.namespace("/api/v1/users") do
|
78
|
+
bearer_auth("API access token")
|
79
|
+
tags("users", "api-v1")
|
80
|
+
|
81
|
+
error_responses do
|
82
|
+
unauthorized(401, error_schema)
|
83
|
+
forbidden(403, error_schema)
|
84
|
+
server_error(500, error_schema)
|
85
|
+
end
|
86
|
+
|
87
|
+
get("/") { summary("List users"); ok(user_array) }
|
88
|
+
get("/{id}") { path_param(:id, :uuid); ok(user_schema) }
|
89
|
+
post("/") { json_body(create_user_schema); created(user_schema) }
|
90
|
+
end
|
91
|
+
```
|
92
|
+
|
93
|
+
### โ
Advanced Response Types
|
94
|
+
```ruby
|
95
|
+
# JSON responses with schemas
|
96
|
+
.ok(user_schema)
|
97
|
+
.created(user_schema)
|
98
|
+
|
99
|
+
# File uploads/downloads
|
100
|
+
.body(Types.string, content_type: "multipart/form-data")
|
101
|
+
.responds_with(200, content_type: "application/octet-stream")
|
102
|
+
|
103
|
+
# Text responses
|
104
|
+
.text_response(200, Types.string)
|
105
|
+
|
106
|
+
# Status-only responses
|
107
|
+
.no_content()
|
108
|
+
.accepted()
|
109
|
+
```
|
110
|
+
|
111
|
+
## ๐ Phase 1 Complete Summary
|
112
|
+
|
113
|
+
### **Phase 1.1**: โ
Advanced Type System (COMPLETE)
|
114
|
+
- 12 type classes with validation and coercion
|
115
|
+
- Schema definition DSL
|
116
|
+
- JSON Schema generation
|
117
|
+
- Comprehensive constraint system
|
118
|
+
|
119
|
+
### **Phase 1.2**: โ
Server Integration Foundation (COMPLETE)
|
120
|
+
- Enhanced Rack adapter
|
121
|
+
- Sinatra integration
|
122
|
+
- Request/response validation
|
123
|
+
- Error handling pipeline
|
124
|
+
|
125
|
+
### **Phase 1.3**: โ
Enhanced Fluent DSL (COMPLETE)
|
126
|
+
- Chainable endpoint builder
|
127
|
+
- Multiple authentication schemes
|
128
|
+
- Namespace and grouping
|
129
|
+
- Advanced response handling
|
130
|
+
|
131
|
+
## ๐ Total Implementation Stats
|
132
|
+
|
133
|
+
- **15+ new classes**: FluentEndpointBuilder, EnhancedInput/Output/Error/Security, NamespaceBuilder
|
134
|
+
- **50+ DSL methods**: Fluent interface covering all endpoint configuration needs
|
135
|
+
- **4 authentication schemes**: Bearer, API Key, Basic, OAuth2
|
136
|
+
- **10+ response helpers**: ok, created, bad_request, unauthorized, etc.
|
137
|
+
- **Namespace system**: Shared configuration and path prefixes
|
138
|
+
- **Type integration**: Full integration with Phase 1.1 type system
|
139
|
+
|
140
|
+
## ๐ฏ Production Readiness
|
141
|
+
|
142
|
+
RapiTapir has successfully evolved from a documentation tool to a **production-ready API framework**:
|
143
|
+
|
144
|
+
โ
**Type-safe** endpoint definitions with validation
|
145
|
+
โ
**Fluent DSL** for elegant API design
|
146
|
+
โ
**Multiple authentication** schemes
|
147
|
+
โ
**Server integration** ready for deployment
|
148
|
+
โ
**OpenAPI 3.0.3** specification generation
|
149
|
+
โ
**Comprehensive error handling**
|
150
|
+
โ
**Framework integration** (Sinatra, ready for Rails)
|
151
|
+
|
152
|
+
**Next Steps**: RapiTapir is now ready for real-world usage, performance optimization, and additional framework integrations! ๐
|