api-regulator 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/.gitignore +16 -0
- data/.rspec +3 -0
- data/.ruby-version +1 -0
- data/.travis.yml +7 -0
- data/Gemfile +6 -0
- data/Gemfile.lock +221 -0
- data/LICENSE.txt +21 -0
- data/README.md +154 -0
- data/Rakefile +6 -0
- data/api-regulator.gemspec +48 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/lib/api-regulator.rb +35 -0
- data/lib/api_regulator/api.rb +82 -0
- data/lib/api_regulator/configuration.rb +18 -0
- data/lib/api_regulator/controller_mixin.rb +60 -0
- data/lib/api_regulator/dsl.rb +30 -0
- data/lib/api_regulator/formats.rb +11 -0
- data/lib/api_regulator/open_api_generator.rb +224 -0
- data/lib/api_regulator/param.rb +55 -0
- data/lib/api_regulator/shared_schema.rb +37 -0
- data/lib/api_regulator/validation_error.rb +11 -0
- data/lib/api_regulator/validator.rb +245 -0
- data/lib/api_regulator/version.rb +3 -0
- data/lib/api_regulator.rb +1 -0
- data/lib/tasks/api_regulator_tasks.rake +67 -0
- metadata +186 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 8474dc3c3898732b6e48a0b2c1722ecc13735e95474b01d9c4223be2cc461653
|
4
|
+
data.tar.gz: 541a39193368ff06b3932f869e75d27a50375ae5c2acd772e0276aa2c892bc8a
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 67f74a784f20dc965e53a838c6ea8d068242cf77fd7aa7508c6e7e427efd4fef9f29a8242ab737f375b7accc84192551acc40036cfeb9778c1899731510cc102
|
7
|
+
data.tar.gz: 732b45b1592042bc7259f82d84b396583a74acb92daac22636d1edddc9f2b41771eea4226459b6709ac109b8ed430a6838ef76a592d2c2742d6ae5dcae3e2b36
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/.ruby-version
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
3.3.6
|
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,221 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
api-regulator (0.1.0)
|
5
|
+
activemodel
|
6
|
+
activesupport
|
7
|
+
|
8
|
+
GEM
|
9
|
+
remote: https://rubygems.org/
|
10
|
+
specs:
|
11
|
+
actioncable (7.2.2)
|
12
|
+
actionpack (= 7.2.2)
|
13
|
+
activesupport (= 7.2.2)
|
14
|
+
nio4r (~> 2.0)
|
15
|
+
websocket-driver (>= 0.6.1)
|
16
|
+
zeitwerk (~> 2.6)
|
17
|
+
actionmailbox (7.2.2)
|
18
|
+
actionpack (= 7.2.2)
|
19
|
+
activejob (= 7.2.2)
|
20
|
+
activerecord (= 7.2.2)
|
21
|
+
activestorage (= 7.2.2)
|
22
|
+
activesupport (= 7.2.2)
|
23
|
+
mail (>= 2.8.0)
|
24
|
+
actionmailer (7.2.2)
|
25
|
+
actionpack (= 7.2.2)
|
26
|
+
actionview (= 7.2.2)
|
27
|
+
activejob (= 7.2.2)
|
28
|
+
activesupport (= 7.2.2)
|
29
|
+
mail (>= 2.8.0)
|
30
|
+
rails-dom-testing (~> 2.2)
|
31
|
+
actionpack (7.2.2)
|
32
|
+
actionview (= 7.2.2)
|
33
|
+
activesupport (= 7.2.2)
|
34
|
+
nokogiri (>= 1.8.5)
|
35
|
+
racc
|
36
|
+
rack (>= 2.2.4, < 3.2)
|
37
|
+
rack-session (>= 1.0.1)
|
38
|
+
rack-test (>= 0.6.3)
|
39
|
+
rails-dom-testing (~> 2.2)
|
40
|
+
rails-html-sanitizer (~> 1.6)
|
41
|
+
useragent (~> 0.16)
|
42
|
+
actiontext (7.2.2)
|
43
|
+
actionpack (= 7.2.2)
|
44
|
+
activerecord (= 7.2.2)
|
45
|
+
activestorage (= 7.2.2)
|
46
|
+
activesupport (= 7.2.2)
|
47
|
+
globalid (>= 0.6.0)
|
48
|
+
nokogiri (>= 1.8.5)
|
49
|
+
actionview (7.2.2)
|
50
|
+
activesupport (= 7.2.2)
|
51
|
+
builder (~> 3.1)
|
52
|
+
erubi (~> 1.11)
|
53
|
+
rails-dom-testing (~> 2.2)
|
54
|
+
rails-html-sanitizer (~> 1.6)
|
55
|
+
activejob (7.2.2)
|
56
|
+
activesupport (= 7.2.2)
|
57
|
+
globalid (>= 0.3.6)
|
58
|
+
activemodel (7.2.2)
|
59
|
+
activesupport (= 7.2.2)
|
60
|
+
activerecord (7.2.2)
|
61
|
+
activemodel (= 7.2.2)
|
62
|
+
activesupport (= 7.2.2)
|
63
|
+
timeout (>= 0.4.0)
|
64
|
+
activestorage (7.2.2)
|
65
|
+
actionpack (= 7.2.2)
|
66
|
+
activejob (= 7.2.2)
|
67
|
+
activerecord (= 7.2.2)
|
68
|
+
activesupport (= 7.2.2)
|
69
|
+
marcel (~> 1.0)
|
70
|
+
activesupport (7.2.2)
|
71
|
+
base64
|
72
|
+
benchmark (>= 0.3)
|
73
|
+
bigdecimal
|
74
|
+
concurrent-ruby (~> 1.0, >= 1.3.1)
|
75
|
+
connection_pool (>= 2.2.5)
|
76
|
+
drb
|
77
|
+
i18n (>= 1.6, < 2)
|
78
|
+
logger (>= 1.4.2)
|
79
|
+
minitest (>= 5.1)
|
80
|
+
securerandom (>= 0.3)
|
81
|
+
tzinfo (~> 2.0, >= 2.0.5)
|
82
|
+
base64 (0.2.0)
|
83
|
+
benchmark (0.4.0)
|
84
|
+
bigdecimal (3.1.8)
|
85
|
+
builder (3.3.0)
|
86
|
+
byebug (11.1.3)
|
87
|
+
concurrent-ruby (1.3.4)
|
88
|
+
connection_pool (2.4.1)
|
89
|
+
crass (1.0.6)
|
90
|
+
date (3.4.0)
|
91
|
+
diff-lcs (1.5.1)
|
92
|
+
drb (2.2.1)
|
93
|
+
erubi (1.13.0)
|
94
|
+
globalid (1.2.1)
|
95
|
+
activesupport (>= 6.1)
|
96
|
+
i18n (1.14.6)
|
97
|
+
concurrent-ruby (~> 1.0)
|
98
|
+
io-console (0.7.2)
|
99
|
+
irb (1.14.1)
|
100
|
+
rdoc (>= 4.0.0)
|
101
|
+
reline (>= 0.4.2)
|
102
|
+
logger (1.6.1)
|
103
|
+
loofah (2.23.1)
|
104
|
+
crass (~> 1.0.2)
|
105
|
+
nokogiri (>= 1.12.0)
|
106
|
+
mail (2.8.1)
|
107
|
+
mini_mime (>= 0.1.1)
|
108
|
+
net-imap
|
109
|
+
net-pop
|
110
|
+
net-smtp
|
111
|
+
marcel (1.0.4)
|
112
|
+
mini_mime (1.1.5)
|
113
|
+
mini_portile2 (2.8.8)
|
114
|
+
minitest (5.25.2)
|
115
|
+
net-imap (0.5.1)
|
116
|
+
date
|
117
|
+
net-protocol
|
118
|
+
net-pop (0.1.2)
|
119
|
+
net-protocol
|
120
|
+
net-protocol (0.2.2)
|
121
|
+
timeout
|
122
|
+
net-smtp (0.5.0)
|
123
|
+
net-protocol
|
124
|
+
nio4r (2.7.4)
|
125
|
+
nokogiri (1.16.8)
|
126
|
+
mini_portile2 (~> 2.8.2)
|
127
|
+
racc (~> 1.4)
|
128
|
+
nokogiri (1.16.8-arm64-darwin)
|
129
|
+
racc (~> 1.4)
|
130
|
+
psych (5.2.0)
|
131
|
+
stringio
|
132
|
+
racc (1.8.1)
|
133
|
+
rack (3.1.8)
|
134
|
+
rack-session (2.0.0)
|
135
|
+
rack (>= 3.0.0)
|
136
|
+
rack-test (2.1.0)
|
137
|
+
rack (>= 1.3)
|
138
|
+
rackup (2.2.1)
|
139
|
+
rack (>= 3)
|
140
|
+
rails (7.2.2)
|
141
|
+
actioncable (= 7.2.2)
|
142
|
+
actionmailbox (= 7.2.2)
|
143
|
+
actionmailer (= 7.2.2)
|
144
|
+
actionpack (= 7.2.2)
|
145
|
+
actiontext (= 7.2.2)
|
146
|
+
actionview (= 7.2.2)
|
147
|
+
activejob (= 7.2.2)
|
148
|
+
activemodel (= 7.2.2)
|
149
|
+
activerecord (= 7.2.2)
|
150
|
+
activestorage (= 7.2.2)
|
151
|
+
activesupport (= 7.2.2)
|
152
|
+
bundler (>= 1.15.0)
|
153
|
+
railties (= 7.2.2)
|
154
|
+
rails-dom-testing (2.2.0)
|
155
|
+
activesupport (>= 5.0.0)
|
156
|
+
minitest
|
157
|
+
nokogiri (>= 1.6)
|
158
|
+
rails-html-sanitizer (1.6.1)
|
159
|
+
loofah (~> 2.21)
|
160
|
+
nokogiri (>= 1.15.7, != 1.16.7, != 1.16.6, != 1.16.5, != 1.16.4, != 1.16.3, != 1.16.2, != 1.16.1, != 1.16.0.rc1, != 1.16.0)
|
161
|
+
railties (7.2.2)
|
162
|
+
actionpack (= 7.2.2)
|
163
|
+
activesupport (= 7.2.2)
|
164
|
+
irb (~> 1.13)
|
165
|
+
rackup (>= 1.0.0)
|
166
|
+
rake (>= 12.2)
|
167
|
+
thor (~> 1.0, >= 1.2.2)
|
168
|
+
zeitwerk (~> 2.6)
|
169
|
+
rake (13.2.1)
|
170
|
+
rdoc (6.8.1)
|
171
|
+
psych (>= 4.0.0)
|
172
|
+
reline (0.5.11)
|
173
|
+
io-console (~> 0.5)
|
174
|
+
rspec (3.13.0)
|
175
|
+
rspec-core (~> 3.13.0)
|
176
|
+
rspec-expectations (~> 3.13.0)
|
177
|
+
rspec-mocks (~> 3.13.0)
|
178
|
+
rspec-core (3.13.2)
|
179
|
+
rspec-support (~> 3.13.0)
|
180
|
+
rspec-expectations (3.13.3)
|
181
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
182
|
+
rspec-support (~> 3.13.0)
|
183
|
+
rspec-mocks (3.13.2)
|
184
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
185
|
+
rspec-support (~> 3.13.0)
|
186
|
+
rspec-rails (5.1.2)
|
187
|
+
actionpack (>= 5.2)
|
188
|
+
activesupport (>= 5.2)
|
189
|
+
railties (>= 5.2)
|
190
|
+
rspec-core (~> 3.10)
|
191
|
+
rspec-expectations (~> 3.10)
|
192
|
+
rspec-mocks (~> 3.10)
|
193
|
+
rspec-support (~> 3.10)
|
194
|
+
rspec-support (3.13.1)
|
195
|
+
securerandom (0.3.2)
|
196
|
+
stringio (3.1.2)
|
197
|
+
thor (1.3.2)
|
198
|
+
timeout (0.4.2)
|
199
|
+
tzinfo (2.0.6)
|
200
|
+
concurrent-ruby (~> 1.0)
|
201
|
+
useragent (0.16.10)
|
202
|
+
websocket-driver (0.7.6)
|
203
|
+
websocket-extensions (>= 0.1.0)
|
204
|
+
websocket-extensions (0.1.5)
|
205
|
+
zeitwerk (2.7.1)
|
206
|
+
|
207
|
+
PLATFORMS
|
208
|
+
arm64-darwin-23
|
209
|
+
ruby
|
210
|
+
|
211
|
+
DEPENDENCIES
|
212
|
+
api-regulator!
|
213
|
+
bundler (~> 2.5)
|
214
|
+
byebug (= 11.1.3)
|
215
|
+
rails (~> 7.0)
|
216
|
+
rake (>= 12.3)
|
217
|
+
rspec (~> 3.0)
|
218
|
+
rspec-rails (~> 5.0)
|
219
|
+
|
220
|
+
BUNDLED WITH
|
221
|
+
2.5.23
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2024 Geoff Massanek
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,154 @@
|
|
1
|
+
# ApiRegulator
|
2
|
+
|
3
|
+
ApiRegulator is a Ruby gem designed to **document** and **validate APIs** in Rails applications. It provides a clean DSL for defining API endpoints, parameter validations, and response schemas directly in your Rails controllers, while also generating OpenAPI 3.1.0-compliant documentation for tools like Swagger and ReadMe.
|
4
|
+
|
5
|
+
ApiRegulator relies on **Active Model validations** for parameter validation, making it familiar and intuitive for Rails developers.
|
6
|
+
|
7
|
+
## Features
|
8
|
+
|
9
|
+
- **API Documentation DSL**:
|
10
|
+
Define API endpoints, request parameters, and response schemas in an intuitive, Rails-friendly DSL.
|
11
|
+
|
12
|
+
- **Dynamic Validation**:
|
13
|
+
Automatically validate incoming requests against the defined parameters using **Active Model validations**, reducing boilerplate code.
|
14
|
+
|
15
|
+
- **OpenAPI Documentation**:
|
16
|
+
Generate fully compliant OpenAPI 3.1.0 JSON files, ready for use with documentation tools like Swagger or ReadMe.
|
17
|
+
|
18
|
+
- **Reusability**:
|
19
|
+
Share common response schemas across multiple endpoints for DRY definitions.
|
20
|
+
|
21
|
+
## ToDo
|
22
|
+
- [ ] More tests
|
23
|
+
- [ ] Invalid Configurations (errors for invalid types)
|
24
|
+
- [ ] Empty Shared Schemas
|
25
|
+
- [ ] Custom Length and Numericality Options
|
26
|
+
- [ ] Publish to rubygems
|
27
|
+
- [ ] See if we're missing any other OpenAPI directives we could use
|
28
|
+
- [ ] nullable params
|
29
|
+
- [ ] Handling of extra undocumented params
|
30
|
+
- [ ] Set up CI / CD
|
31
|
+
|
32
|
+
## Installation
|
33
|
+
|
34
|
+
Add ApiRegulator to your Gemfile:
|
35
|
+
|
36
|
+
```ruby
|
37
|
+
gem 'api_regulator'
|
38
|
+
```
|
39
|
+
|
40
|
+
Run `bundle install` to install the gem.
|
41
|
+
|
42
|
+
|
43
|
+
## Setup
|
44
|
+
|
45
|
+
1. **Create an Initializer**:
|
46
|
+
|
47
|
+
Add the following to `config/initializers/api_regulator.rb`:
|
48
|
+
|
49
|
+
```ruby
|
50
|
+
ApiRegulator.configure do |config|
|
51
|
+
config.base_controller = "Api::ApplicationController" # Set your base API controller
|
52
|
+
config.api_base_url = "/api/v1" # Set a common base path for your API endpoints
|
53
|
+
config.docs_path = Rails.root.join("doc", "openapi.json").to_s # Path for OpenAPI JSON file
|
54
|
+
config.app_name = "My API" # shows in docs
|
55
|
+
config.rdme_api_id = ENV["RDME_API_ID"] # Optional: ReadMe API ID for schema uploads
|
56
|
+
config.servers = [
|
57
|
+
{ url: "https://stg.example.com", description: "Staging", "x-default": true },
|
58
|
+
{ url: "https://example.com", description: "Production" }
|
59
|
+
]
|
60
|
+
end
|
61
|
+
```
|
62
|
+
|
63
|
+
2. **Include the DSL in Your Base Controller**:
|
64
|
+
|
65
|
+
Include the DSL and validation methods in your base API controller:
|
66
|
+
|
67
|
+
```ruby
|
68
|
+
class Api::ApplicationController < ActionController::API
|
69
|
+
include ApiRegulator::DSL
|
70
|
+
include ApiRegulator::ControllerMixin
|
71
|
+
end
|
72
|
+
```
|
73
|
+
|
74
|
+
## Usage
|
75
|
+
|
76
|
+
**Defining Endpoints**
|
77
|
+
|
78
|
+
Use the DSL in your controllers to define API endpoints, request parameters, and response schemas.
|
79
|
+
|
80
|
+
```ruby
|
81
|
+
class Api::V1::CustomersController < Api::ApplicationController
|
82
|
+
api self, :create, "Enroll a customer" do
|
83
|
+
param :customer, presence: true do
|
84
|
+
param :first_name, :string, presence: true
|
85
|
+
param :last_name, :string, presence: true
|
86
|
+
param :email, :string, presence: true, format: { with: URI::MailTo::EMAIL_REGEXP }
|
87
|
+
param :ssn, :string, presence: true, length: { minimum: 9, maximum: 9 }
|
88
|
+
end
|
89
|
+
|
90
|
+
response 200, "Customer successfully enrolled" do
|
91
|
+
param :customer do
|
92
|
+
param :id, :string, desc: "Customer ID"
|
93
|
+
param :email, :string, desc: "Customer email"
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
response 422, ref: :validation_errors
|
98
|
+
end
|
99
|
+
|
100
|
+
def create
|
101
|
+
validate_params! # Validate request params against the DSL definition
|
102
|
+
|
103
|
+
customer = Customer.create!(api_params[:customer]) # Use dynamically generated params
|
104
|
+
render json: customer, status: :ok
|
105
|
+
end
|
106
|
+
end
|
107
|
+
```
|
108
|
+
|
109
|
+
## Shared Schemas
|
110
|
+
|
111
|
+
Define reusable schemas for common responses in your initializer:
|
112
|
+
|
113
|
+
```ruby
|
114
|
+
ApiRegulator.shared_schema :validation_errors, "Validation error response" do
|
115
|
+
param :errors, :array, desc: "Array of validation errors", items_type: :string
|
116
|
+
end
|
117
|
+
```
|
118
|
+
|
119
|
+
Reference the shared schema in your responses:
|
120
|
+
```ruby
|
121
|
+
response 422, ref: :validation_errors
|
122
|
+
end
|
123
|
+
```
|
124
|
+
|
125
|
+
## Generating OpenAPI Documentation
|
126
|
+
|
127
|
+
Generate OpenAPI documentation using the provided Rake tasks:
|
128
|
+
|
129
|
+
|
130
|
+
1. **Generate the Schema:**
|
131
|
+
```bash
|
132
|
+
rake api_docs:generate
|
133
|
+
```
|
134
|
+
|
135
|
+
2. **Upload to ReadMe (Optional)**:
|
136
|
+
```bash
|
137
|
+
rake api_docs:upload
|
138
|
+
```
|
139
|
+
This uploads the OpenAPI file to ReadMe. Ensure you’ve configured the RDME_API_KEY and optional RDME_API_ID.
|
140
|
+
|
141
|
+
3. **Publish Both**:
|
142
|
+
```bash
|
143
|
+
rake api_docs:publish
|
144
|
+
```
|
145
|
+
|
146
|
+
## Contributing
|
147
|
+
1. Fork the repository.
|
148
|
+
2. Create your feature branch (git checkout -b feature/new-feature).
|
149
|
+
3. Commit your changes (git commit -am 'Add some feature').
|
150
|
+
4. Push to the branch (git push origin feature/new-feature).
|
151
|
+
5. Open a pull request.
|
152
|
+
|
153
|
+
## License
|
154
|
+
This gem is available as open-source software under the [MIT License](https://mit-license.org/).
|
data/Rakefile
ADDED
@@ -0,0 +1,48 @@
|
|
1
|
+
|
2
|
+
lib = File.expand_path("../lib", __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require "api_regulator/version"
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "api-regulator"
|
8
|
+
spec.version = ApiRegulator::VERSION
|
9
|
+
spec.authors = ["Geoff Massanek"]
|
10
|
+
spec.email = ["geoff@stellarfi.com"]
|
11
|
+
|
12
|
+
spec.summary = %q{Define, document, and validate your Rails APIs}
|
13
|
+
spec.description = %q{Define your Rails APIs with a clean, familiar DSL. Validate them with ActiveModel-like validations. Generate OpenAPI documentation.}
|
14
|
+
spec.homepage = "https://github.com/Stellarcred/stellar-gears"
|
15
|
+
spec.license = "MIT"
|
16
|
+
|
17
|
+
# Prevent pushing this gem to RubyGems.org. To allow pushes either set the 'allowed_push_host'
|
18
|
+
# to allow pushing to a single host or delete this section to allow pushing to any host.
|
19
|
+
if spec.respond_to?(:metadata)
|
20
|
+
spec.metadata["allowed_push_host"] = "https://rubygems.org"
|
21
|
+
|
22
|
+
spec.metadata["homepage_uri"] = spec.homepage
|
23
|
+
spec.metadata["source_code_uri"] = "https://github.com/Stellarcred/stellar-gears"
|
24
|
+
spec.metadata["changelog_uri"] = "https://github.com/Stellarcred/stellar-gears"
|
25
|
+
else
|
26
|
+
raise "RubyGems 2.0 or newer is required to protect against " \
|
27
|
+
"public gem pushes."
|
28
|
+
end
|
29
|
+
|
30
|
+
# Specify which files should be added to the gem when it is released.
|
31
|
+
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
32
|
+
spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
|
33
|
+
`git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
34
|
+
end
|
35
|
+
spec.bindir = "exe"
|
36
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
37
|
+
spec.require_paths = ["lib"]
|
38
|
+
|
39
|
+
spec.add_runtime_dependency "activesupport"
|
40
|
+
spec.add_runtime_dependency "activemodel"
|
41
|
+
|
42
|
+
spec.add_development_dependency "bundler", "~> 2.5"
|
43
|
+
spec.add_development_dependency "rake", ">= 12.3"
|
44
|
+
spec.add_development_dependency "rails", "~> 7.0"
|
45
|
+
spec.add_development_dependency "rspec", "~> 3.0"
|
46
|
+
spec.add_development_dependency "rspec-rails", "~> 5.0"
|
47
|
+
spec.add_development_dependency "byebug", "11.1.3"
|
48
|
+
end
|
data/bin/console
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "bundler/setup"
|
4
|
+
require "api/regulator"
|
5
|
+
|
6
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
7
|
+
# with your gem easier. You can also use a different console, if you like.
|
8
|
+
|
9
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
10
|
+
# require "pry"
|
11
|
+
# Pry.start
|
12
|
+
|
13
|
+
require "irb"
|
14
|
+
IRB.start(__FILE__)
|
data/bin/setup
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
require_relative 'api_regulator/api'
|
2
|
+
require_relative 'api_regulator/configuration'
|
3
|
+
require_relative 'api_regulator/controller_mixin'
|
4
|
+
require_relative 'api_regulator/dsl'
|
5
|
+
require_relative 'api_regulator/formats'
|
6
|
+
require_relative 'api_regulator/open_api_generator'
|
7
|
+
require_relative 'api_regulator/param'
|
8
|
+
require_relative 'api_regulator/shared_schema'
|
9
|
+
require_relative 'api_regulator/validation_error'
|
10
|
+
require_relative 'api_regulator/validator'
|
11
|
+
require_relative 'api_regulator/version'
|
12
|
+
|
13
|
+
# Load tasks if Rails is present
|
14
|
+
if defined?(Rake)
|
15
|
+
load 'tasks/api_regulator_tasks.rake'
|
16
|
+
end
|
17
|
+
|
18
|
+
module ApiRegulator
|
19
|
+
class Error < StandardError; end
|
20
|
+
|
21
|
+
class << self
|
22
|
+
attr_accessor :configuration
|
23
|
+
|
24
|
+
def configure
|
25
|
+
self.configuration ||= Configuration.new
|
26
|
+
yield(configuration)
|
27
|
+
end
|
28
|
+
|
29
|
+
def prepare_validators
|
30
|
+
Rails.application.eager_load! # Ensure all controllers and API definitions are loaded
|
31
|
+
api_definitions = ApiRegulator.configuration.base_controller_klass.descendants.flat_map(&:api_definitions)
|
32
|
+
ApiRegulator::Validator.build_all(api_definitions)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,82 @@
|
|
1
|
+
module ApiRegulator
|
2
|
+
class Api
|
3
|
+
attr_reader :controller_class, :controller_path, :controller_name, :action_name, :description, :params, :responses
|
4
|
+
|
5
|
+
def initialize(controller_class, action_name, description, &block)
|
6
|
+
@controller_class = controller_class
|
7
|
+
@controller_name = controller_class.name
|
8
|
+
@controller_path = controller_class.controller_path
|
9
|
+
@action_name = action_name.to_s
|
10
|
+
@description = description
|
11
|
+
|
12
|
+
@params = []
|
13
|
+
@responses = {}
|
14
|
+
|
15
|
+
instance_eval(&block) if block_given?
|
16
|
+
end
|
17
|
+
|
18
|
+
def param(name, type = nil, item_type: nil, desc: "", location: :body, **options, &block)
|
19
|
+
param = Param.new(name, type, item_type: item_type, desc: desc, location: location, **options, &block)
|
20
|
+
@params << param
|
21
|
+
end
|
22
|
+
|
23
|
+
def ref(ref_name)
|
24
|
+
shared_schema = ApiRegulator.shared_schemas[ref_name]
|
25
|
+
raise "Shared schema #{ref_name} not found" unless shared_schema
|
26
|
+
|
27
|
+
shared_schema.params.each do |shared_param|
|
28
|
+
@params << shared_param
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def response(status_code, description_or_options, &block)
|
33
|
+
if description_or_options.is_a?(Hash) && description_or_options[:ref]
|
34
|
+
# Reference to a shared schema
|
35
|
+
@responses[status_code] = Param.new(:root, :object, ref: description_or_options[:ref], &block)
|
36
|
+
else
|
37
|
+
# Inline schema definition
|
38
|
+
schema = Param.new(:root, :object, desc: description_or_options, &block)
|
39
|
+
@responses[status_code] = schema
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def path
|
44
|
+
rails_route.path.spec.to_s
|
45
|
+
.sub("(.:format)", "") # Remove optional format
|
46
|
+
.gsub(/:([\w_]+)/, '{\1}') # Replace `:param` with `{param}`
|
47
|
+
end
|
48
|
+
|
49
|
+
def http_method
|
50
|
+
rails_route.verb&.downcase
|
51
|
+
end
|
52
|
+
|
53
|
+
def rails_route
|
54
|
+
route = Rails.application.routes.routes.find do |r|
|
55
|
+
r.defaults[:controller] == controller_path &&
|
56
|
+
r.defaults[:action] == action_name
|
57
|
+
end
|
58
|
+
|
59
|
+
raise "HTTP method not found for #{controller_name}##{action_name}" unless route
|
60
|
+
|
61
|
+
route
|
62
|
+
end
|
63
|
+
|
64
|
+
def operation_id
|
65
|
+
"#{controller_path.gsub("/", "-")}-#{action_name}"
|
66
|
+
end
|
67
|
+
|
68
|
+
def tags
|
69
|
+
[
|
70
|
+
controller_name
|
71
|
+
.demodulize
|
72
|
+
.sub("Controller", "")
|
73
|
+
.underscore
|
74
|
+
.humanize
|
75
|
+
]
|
76
|
+
end
|
77
|
+
|
78
|
+
def allows_body?
|
79
|
+
http_method != "get"
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module ApiRegulator
|
2
|
+
class Configuration
|
3
|
+
attr_accessor :base_controller, :api_base_url, :app_name, :docs_path, :rdme_api_id, :servers
|
4
|
+
|
5
|
+
def initialize
|
6
|
+
# Set default values
|
7
|
+
@base_controller = "ApplicationController"
|
8
|
+
@api_base_url = "api/v1"
|
9
|
+
@app_name = "API Documentation"
|
10
|
+
@docs_path = "openapi.json"
|
11
|
+
@servers = []
|
12
|
+
end
|
13
|
+
|
14
|
+
def base_controller_klass
|
15
|
+
ApiRegulator.configuration.base_controller.constantize
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|