swagger_autogenerate 1.2.9 → 2.0.1

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: dafd89e33e58235dea22170057658250e81904936e750d53990d91e2de2f624c
4
- data.tar.gz: d52401f1dd5aaeaef3a0fbf37ec9d78c924f3b78b2ef529f8169c50ce009566a
3
+ metadata.gz: 82b7c6523f9a6f361c4f78be66068aab528b9707419a11ae61b5264878706ef1
4
+ data.tar.gz: f7671a245cb3a4a89452db82f6d5ba48a1f5b810c1a52d2323cee1a94f76726a
5
5
  SHA512:
6
- metadata.gz: 9c25c49469a803b38ce2e06804ab3c9eeeb74deceb8153c4291d7c988ebf66066ac9eda0213b25a83bbb1645ff7c6de4f5f56445061e3650fd1226b94948640e
7
- data.tar.gz: 87d9405997af4cadb9cdfc552ff9bffc89fb65caa22c725d4248253264a50e9aa53dbfd1c18d78ffe5fe19cd0824ee2e5cd8836a73d3e607abb79ae41ba2e906
6
+ metadata.gz: 2e4b21d768fcbd45e6a082f3caf0c437079d535d53c5fa9466aa1c7b70c69e289de2fadc9d440d2c9128cfbcf99dabeb1cf1f5742154ede03d203cc86c3a8cac
7
+ data.tar.gz: 4e0b9ce2a3cc3d9dae32383b8980d4b31e70b0f7611c8e3769e0ef7360da94e42ef060aa62860366698fafdb8bd0dbdf3b2bc475e4ad6d257b5f41a2c202c8eb
data/CHANGELOG.md CHANGED
@@ -1,25 +1,47 @@
1
1
  ## [Unreleased]
2
2
 
3
- ## [0.1.1] - 2024-05-27
4
- ## [1.0.2] - 2024-05-31
5
- ## [1.0.3] - 2024-05-31
6
- ## [1.0.4] - 2024-06-01
7
- ## [1.0.5] - 2024-06-01
8
- ## [1.0.6] - 2024-06-01
9
- ## [1.0.7] - 2024-06-01
10
- ## [1.0.8] - 2024-06-03
11
- ## [1.0.9] - 2024-06-04
12
- ## [1.1.0] - 2024-06-23
13
- ## [1.1.1] - 2024-06-26
14
- ## [1.1.2] - 2024-08-17
15
- ## [1.2.0] - 2024-09-08
16
- ## [1.2.1] - 2024-09-08
17
- ## [1.2.2] - 2024-09-12
18
- ## [1.2.3] - 2024-09-12
19
- ## [1.2.4] - 2024-09-15
20
- ## [1.2.5] - 2024-09-15
21
- ## [1.2.6] - 2024-11-05
22
- ## [1.2.8] - 2024-11-05
3
+ ### Improved
4
+ - README documents full Rails + rswag host setup (routes, initializers, SwaggerCombiner, rake/bin)
5
+
6
+ ## [2.0.1] - 2026-09-03
7
+ ## [2.0.0] - 2026-09-03
8
+
9
+ ### Breaking
10
+ - Default `security` is now `[]` (no project-specific `org_slug` / `locale` schemes)
11
+ - Default OpenAPI document is built from app name + empty `securitySchemes`
12
+ - Env-gated generation helpers renamed conceptually to `SwaggerAutogenerate.generate?` (`allow_swagger?` still works)
13
+ - Internal code split into focused classes (public configure API unchanged in spirit)
14
+
15
+ ### Added
16
+ - Railtie auto-includes into `ApplicationController` in the configured test environment
17
+ - RSpec test suite for configuration, helpers, schema/params/responses, and YAML generation
18
+ - rswag-friendly `default_path` resolution (`swagger` / `swagger/v1`)
19
+ - Ergonomic config: `info_title`, `servers`, `security_schemes`, `auto_include`
20
+
21
+ ### Improved
22
+ - README for rswag-api / rswag-ui usage
23
+ - Clearer module layout under `lib/swagger_autogenerate/`
24
+
23
25
  ## [1.2.9] - 2025-11-24
26
+ ## [1.2.8] - 2024-11-05
27
+ ## [1.2.6] - 2024-11-05
28
+ ## [1.2.5] - 2024-09-15
29
+ ## [1.2.4] - 2024-09-15
30
+ ## [1.2.3] - 2024-09-12
31
+ ## [1.2.2] - 2024-09-12
32
+ ## [1.2.1] - 2024-09-08
33
+ ## [1.2.0] - 2024-09-08
34
+ ## [1.1.2] - 2024-08-17
35
+ ## [1.1.1] - 2024-06-26
36
+ ## [1.1.0] - 2024-06-23
37
+ ## [1.0.9] - 2024-06-04
38
+ ## [1.0.8] - 2024-06-03
39
+ ## [1.0.7] - 2024-06-01
40
+ ## [1.0.6] - 2024-06-01
41
+ ## [1.0.5] - 2024-06-01
42
+ ## [1.0.4] - 2024-06-01
43
+ ## [1.0.3] - 2024-05-31
44
+ ## [1.0.2] - 2024-05-31
45
+ ## [0.1.1] - 2024-05-27
24
46
 
25
47
  - Initial release
data/README.md CHANGED
@@ -1,77 +1,381 @@
1
- # SwaggerAutogenerate
2
- automating Swagger YAML generation in Ruby on Rails offers a range of benefits for API documentation. By leveraging the power of the swagger_autogenerate gem, developers can:
3
- 1) save time and effort
4
- 2) (up to date) reducing the chances of inconsistencies between the actual API implementation and its documentation.
5
- 3) improves the overall development workflow by providing a seamless integration with testing frameworks like RSpec.
6
- 4) resulting in better communication and understanding of the APIs.
1
+ # Swagger Autogenerate
7
2
 
8
- The gem automatically observes the request/response patterns during the execution of test scenarios, generating accurate Swagger YAML files that reflect the API's behavior. developers and consumers can better understand and interact with the APIs.
3
+ Generate **OpenAPI / Swagger YAML** from your existing Rails RSpec request (or controller) specs.
4
+
5
+ Designed to drop into projects that use **`rswag-api`** and **`rswag-ui`**:
6
+
7
+ 1. Run specs with `SWAGGER_GENERATE=1` → one YAML fragment per resource under `swagger/v1/`
8
+ 2. Combine fragments into `swagger/v1/swagger.yaml`
9
+ 3. Rswag serves that file at `/api-docs`
9
10
 
10
11
  ## Dependencies
11
12
 
12
- The SwaggerAutogenerate gem depends on the rspec-rails gem, which brings the RSpec testing framework to Ruby on Rails.
13
- Please install rspec-rails first: https://github.com/rspec/rspec-rails
14
- Then continue the installation process.
13
+ - Ruby `>= 2.7`
14
+ - Rails `>= 5.2`
15
+ - [rspec-rails](https://github.com/rspec/rspec-rails) in the host app
16
+ - Recommended: [`rswag-api`](https://github.com/rswag/rswag) + [`rswag-ui`](https://github.com/rswag/rswag)
15
17
 
16
18
  ## Installation
17
19
 
18
- 1) Open your Gemfile located at ./Gemfile
19
- 2) Add the following line to the Gemfile within the appropriate group (e.g., :test):
20
+ ```ruby
21
+ # Gemfile
22
+ gem 'rswag-api'
23
+ gem 'rswag-ui'
20
24
 
21
- ```
22
- group :test do
23
- gem 'swagger_autogenerate'
24
- end
25
- ```
26
- 3) Install the gem and add to the application's Gemfile by executing:
27
- ```
28
- bundle install
29
- ```
25
+ group :test do
26
+ gem 'rspec-rails'
27
+ gem 'swagger_autogenerate'
28
+ end
29
+ ```
30
30
 
31
- ## Configuration
31
+ ```bash
32
+ bundle install
33
+ ```
32
34
 
33
- To configure the swagger_autogenerate gem in your Rails application, follow these steps:
35
+ Then add the host-app files below (copy-paste and adjust titles / URLs for your API).
34
36
 
35
- ### Step 1:
36
- 1) Open the app/controllers/application_controller.rb
37
- 2) Inside the class ApplicationController block.
38
- 3) Add the following code:
39
- ```
40
- include SwaggerAutogenerate if Rails.env.test?
37
+ ---
38
+
39
+ ## Host app setup (required for rswag UI)
40
+
41
+ ### 1. Mount rswag in `config/routes.rb`
42
+
43
+ ```ruby
44
+ mount Rswag::Ui::Engine => "/api-docs"
45
+ mount Rswag::Api::Engine => "/api-docs"
41
46
  ```
42
47
 
43
- ### Step 2 (optional)
44
- 1) Create a file called swagger_autogenerate.rb in the ./config/initializers
45
- 2) Open the ./config/initializers/swagger_autogenerate.rb
46
- 3) Add the following code to the swagger_autogenerate.rb
48
+ ### 2. `config/initializers/rswag_api.rb`
49
+
50
+ Serves `swagger/v1/swagger.yaml` at `/api-docs/v1/swagger.yaml`.
51
+
52
+ ```ruby
53
+ # frozen_string_literal: true
54
+
55
+ Rswag::Api.configure do |c|
56
+ # Serves files from swagger/ — so swagger/v1/swagger.yaml → /api-docs/v1/swagger.yaml
57
+ c.openapi_root = Rails.root.join("swagger").to_s
58
+ end
59
+
60
+ Rswag::Ui.configure do |c|
61
+ c.openapi_endpoint "/api-docs/v1/swagger.yaml", "My API V1"
62
+ end
47
63
  ```
64
+
65
+ ### 3. `config/initializers/swagger_autogenerate.rb`
66
+
67
+ Guard with `defined?` so `rails s` does not crash when the gem is only in the `:test` group.
68
+
69
+ ```ruby
70
+ # frozen_string_literal: true
71
+
72
+ # swagger_autogenerate is only loaded in the test (and optionally development) group.
73
+ # Guard so `rails s` in development does not crash when the gem is not required.
74
+ return unless defined?(SwaggerAutogenerate)
75
+
48
76
  SwaggerAutogenerate.configure do |config|
77
+ # Where SWAGGER_GENERATE writes files (rswag default layout)
78
+ config.default_path = "swagger/v1"
79
+
80
+ # OpenAPI info
81
+ config.info_title = "My API"
82
+ config.info_description = "Public HTTP API"
83
+ config.info_version = "1.0.0"
84
+ config.openapi_version = "3.0.1"
85
+ config.servers = [{ "url" => "http://localhost:3000" }]
86
+
87
+ # Auth for rswag / OpenAPI (optional — remove if you have no auth)
88
+ config.security_schemes = {
89
+ "bearerAuth" => {
90
+ "type" => "http",
91
+ "scheme" => "bearer",
92
+ "bearerFormat" => "JWT"
93
+ }
94
+ }
95
+ config.security = [{ "bearerAuth" => [] }]
96
+
97
+ # Behavior flags
49
98
  config.with_config = true
50
99
  config.with_multiple_examples = true
51
- action_for_old_examples = :append # :replace or :append
100
+ config.with_rspec_examples = true
52
101
  config.with_response_description = true
102
+ config.with_payload_properties = true
103
+ config.action_for_old_examples = :append
104
+
105
+ # Env var names / environment gate
106
+ config.swagger_path_environment_variable = "SWAGGER_GENERATE_PATH"
107
+ config.generate_swagger_environment_variable = "SWAGGER_GENERATE"
108
+ config.environment_name = :test
109
+ config.auto_include = true
53
110
  end
111
+ ```
54
112
 
113
+ ### 4. Combine fragments → single `swagger.yaml`
114
+
115
+ `SWAGGER_GENERATE=1` writes **one file per resource** (e.g. `swagger/v1/users.yaml`). Rswag UI expects a **single** file at `swagger/v1/swagger.yaml`. Add a small combiner in the host app.
116
+
117
+ #### `lib/swagger_combiner.rb`
118
+
119
+ ```ruby
120
+ # frozen_string_literal: true
121
+
122
+ require "yaml"
123
+ require "fileutils"
124
+
125
+ # Merges every OpenAPI fragment under swagger/v1/*.yaml (except swagger.yaml)
126
+ # into a single swagger/v1/swagger.yaml for Rswag UI.
127
+ module SwaggerCombiner
128
+ module_function
129
+
130
+ SOURCE_DIR = File.expand_path("../swagger/v1", __dir__)
131
+ OUTPUT_FILE = File.join(SOURCE_DIR, "swagger.yaml")
132
+ SKIP_BASENAMES = %w[swagger.yaml swagger.yml].freeze
133
+
134
+ DEFAULT_DOC = {
135
+ "openapi" => "3.0.1",
136
+ "info" => {
137
+ "title" => "My API",
138
+ "description" => "Public HTTP API",
139
+ "version" => "1.0.0"
140
+ },
141
+ "servers" => [
142
+ { "url" => "http://localhost:3000" }
143
+ ],
144
+ "components" => {
145
+ "securitySchemes" => {
146
+ "bearerAuth" => {
147
+ "type" => "http",
148
+ "scheme" => "bearer",
149
+ "bearerFormat" => "JWT"
150
+ }
151
+ }
152
+ },
153
+ "security" => [
154
+ { "bearerAuth" => [] }
155
+ ],
156
+ "paths" => {}
157
+ }.freeze
158
+
159
+ def combine!(source_dir: SOURCE_DIR, output_file: OUTPUT_FILE)
160
+ FileUtils.mkdir_p(source_dir)
161
+
162
+ fragments = Dir[File.join(source_dir, "*.{yaml,yml}")]
163
+ .reject { |path| SKIP_BASENAMES.include?(File.basename(path)) }
164
+ .sort
165
+
166
+ if fragments.empty?
167
+ warn "[SwaggerCombiner] no fragment files found in #{source_dir}"
168
+ write_yaml(output_file, DEFAULT_DOC.dup)
169
+ return output_file
170
+ end
171
+
172
+ merged = deep_dup(DEFAULT_DOC)
173
+
174
+ fragments.each do |path|
175
+ doc = load_yaml(path)
176
+ next unless doc.is_a?(Hash)
177
+
178
+ merged["paths"] = deep_merge(merged["paths"], stringify_keys(doc["paths"] || {}))
179
+ merged["components"] = deep_merge(merged["components"], stringify_keys(doc["components"] || {}))
180
+
181
+ if doc["tags"].is_a?(Array)
182
+ merged["tags"] = Array(merged["tags"]) | doc["tags"]
183
+ end
184
+ end
185
+
186
+ merged["paths"] = merged["paths"].sort.to_h
187
+
188
+ write_yaml(output_file, merged)
189
+ puts "[SwaggerCombiner] wrote #{output_file} (#{merged["paths"].size} paths from #{fragments.size} files)"
190
+ output_file
191
+ end
192
+
193
+ def load_yaml(path)
194
+ YAML.safe_load(
195
+ File.read(path),
196
+ permitted_classes: [Date, Time, Symbol],
197
+ aliases: true
198
+ )
199
+ rescue Psych::DisallowedClass, Psych::BadAlias
200
+ YAML.load_file(path) # fragments may contain complex examples
201
+ end
202
+
203
+ def write_yaml(path, data)
204
+ File.write(path, data.to_yaml)
205
+ end
206
+
207
+ def deep_merge(left, right)
208
+ left = {} unless left.is_a?(Hash)
209
+ right = {} unless right.is_a?(Hash)
210
+
211
+ left.merge(right) do |_key, old_val, new_val|
212
+ if old_val.is_a?(Hash) && new_val.is_a?(Hash)
213
+ deep_merge(old_val, new_val)
214
+ else
215
+ new_val.nil? ? old_val : new_val
216
+ end
217
+ end
218
+ end
219
+
220
+ def stringify_keys(value)
221
+ case value
222
+ when Hash
223
+ value.each_with_object({}) do |(k, v), memo|
224
+ memo[k.to_s] = stringify_keys(v)
225
+ end
226
+ when Array
227
+ value.map { |item| stringify_keys(item) }
228
+ else
229
+ value
230
+ end
231
+ end
232
+
233
+ def deep_dup(value)
234
+ Marshal.load(Marshal.dump(value))
235
+ end
236
+ end
237
+ ```
238
+
239
+ #### `config/initializers/combine_swagger.rb`
240
+
241
+ Rebuilds the combined file on every boot so `/api-docs` stays fresh.
242
+
243
+ ```ruby
244
+ # frozen_string_literal: true
245
+
246
+ # Rebuild swagger/v1/swagger.yaml from per-resource fragments on every boot.
247
+ # Rswag UI expects a single file at /api-docs/v1/swagger.yaml.
248
+ begin
249
+ require Rails.root.join("lib/swagger_combiner")
250
+ SwaggerCombiner.combine!(
251
+ source_dir: Rails.root.join("swagger/v1").to_s,
252
+ output_file: Rails.root.join("swagger/v1/swagger.yaml").to_s
253
+ )
254
+ rescue StandardError => e
255
+ warn "[SwaggerCombiner] failed to combine OpenAPI docs: #{e.class}: #{e.message}"
256
+ end
257
+ ```
258
+
259
+ #### `lib/tasks/swagger.rake`
260
+
261
+ ```ruby
262
+ # frozen_string_literal: true
263
+
264
+ namespace :swagger do
265
+ desc "Combine swagger/v1/*.yaml fragments into swagger/v1/swagger.yaml"
266
+ task combine: :environment do
267
+ require Rails.root.join("lib/swagger_combiner")
268
+ SwaggerCombiner.combine!
269
+ end
270
+ end
271
+ ```
272
+
273
+ #### `bin/combine_swagger`
274
+
275
+ ```ruby
276
+ #!/usr/bin/env ruby
277
+ # frozen_string_literal: true
278
+
279
+ require_relative "../lib/swagger_combiner"
280
+
281
+ SwaggerCombiner.combine!
282
+ ```
283
+
284
+ ```bash
285
+ chmod +x bin/combine_swagger
286
+ ```
287
+
288
+ ---
289
+
290
+ ## Generate docs
291
+
292
+ In **test**, the gem Railtie includes itself into `ApplicationController` automatically.
293
+
294
+ ```bash
295
+ # One YAML fragment per controller tag under swagger/v1/
296
+ SWAGGER_GENERATE=1 bundle exec rspec spec/requests/
297
+
298
+ # Then combine into swagger/v1/swagger.yaml
299
+ bin/combine_swagger
300
+ # or: bundle exec rake swagger:combine
55
301
  ```
56
- $ This file is optional and allows you to customize the behavior of the gem by providing additional options.
57
302
 
58
- ## Example
59
- To generate Swagger YAML documentation for the APIs implemented in the EmployeesController class, you can follow these steps:
60
- 1) Ensure that you have the swagger_autogenerate gem installed and configured in your Rails application, as described later.
61
- 2) Create a spec file for the EmployeesController class at the path:
62
- $ spec/your_path/employees_controller_spec.rb
63
- This file should contain the test scenarios for each action (e.g., index, show, create) of the controller.
303
+ Or write a single file directly:
64
304
 
65
- 3) Run the spec code using the rspec command and set the environment variable SWAGGER to the desired YAML file name. For example:
305
+ ```bash
306
+ SWAGGER_GENERATE_PATH='swagger/v1/swagger.yaml' bundle exec rspec spec/requests/users_spec.rb
66
307
  ```
67
- SWAGGER_GENERATE_PATH='employee_apis.yaml' rspec spec/your_path/employees_controller_spec.rb
308
+
309
+ Generation only runs when:
310
+
311
+ 1. `SWAGGER_GENERATE_PATH` or `SWAGGER_GENERATE` is set, and
312
+ 2. `Rails.env` matches `config.environment_name` (default `:test`)
313
+
314
+ Without those env vars, specs run normally and nothing is written.
315
+
316
+ Open the UI: `http://localhost:3000/api-docs`
317
+
318
+ ### Environment variables
319
+
320
+ | Variable | Purpose |
321
+ |---|---|
322
+ | `SWAGGER_GENERATE_PATH` | Exact `.yaml`/`.yml` file **or** a directory (one file per tag) |
323
+ | `SWAGGER_GENERATE` | Write under `config.default_path` (rswag-aware) |
324
+ | `tag` | Optional override for the OpenAPI tag / filename stem |
325
+
326
+ ### Manual include / disable auto-include
327
+
328
+ ```ruby
329
+ # app/controllers/application_controller.rb
330
+ include SwaggerAutogenerate if Rails.env.test?
331
+ ```
332
+
333
+ ```ruby
334
+ # config/initializers/swagger_autogenerate.rb
335
+ config.auto_include = false
68
336
  ```
69
- 4) This command runs the spec file and instructs the swagger_autogenerate gem to generate Swagger YAML documentation and save it to the file named employee_apis.yaml.
70
- 5) Once the command finishes executing, you will have the Swagger YAML documentation generated based on the test scenarios in the employees_controller_spec.rb file.
71
337
 
72
- ### Please note
73
- that the generated documentation will depend on the test scenarios defined in your employees_controller_spec.rb file. Make sure to have comprehensive test scenarios that cover different scenarios and expected responses for accurate and detailed Swagger documentation.
338
+ ---
339
+
340
+ ## Configuration reference
341
+
342
+ Only override what you need. Defaults are project-agnostic (empty security, app name as title, `swagger` output path).
343
+
344
+ ### Full document override
345
+
346
+ ```ruby
347
+ SwaggerAutogenerate.configure do |config|
348
+ config.swagger_config = {
349
+ "openapi" => "3.0.1",
350
+ "info" => { "title" => "Custom", "version" => "1.0.0" },
351
+ "components" => { "securitySchemes" => {} }
352
+ }
353
+ end
354
+ ```
355
+
356
+ ## Library layout
357
+
358
+ ```
359
+ lib/swagger_autogenerate/
360
+ configuration.rb # defaults + customization
361
+ swagger_trace.rb # orchestrates one request/response
362
+ path_normalizer.rb # /users/1 → /users/{id}
363
+ parameter_builder.rb # parameters + requestBody
364
+ response_builder.rb # responses + examples
365
+ schema_builder.rb # type inference
366
+ document_writer.rb # read/write YAML
367
+ yaml_merger.rb # merge into existing document
368
+ helpers.rb
369
+ railtie.rb # auto-include in test
370
+ ```
371
+
372
+ ## Development
373
+
374
+ ```bash
375
+ bundle install
376
+ bundle exec rspec
377
+ ```
74
378
 
75
379
  ## License
76
380
 
77
- The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
381
+ MIT see [LICENSE.txt](LICENSE.txt).
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copy to config/initializers/swagger_autogenerate.rb and adjust as needed.
4
+ # Everything is optional — omit this file to use project-agnostic defaults.
5
+
6
+ SwaggerAutogenerate.configure do |config|
7
+ # rswag-api / rswag-ui usually serve files from swagger/v1
8
+ config.default_path = 'swagger/v1'
9
+
10
+ config.info_title = 'My API'
11
+ config.info_description = 'API documentation generated from request specs'
12
+ config.info_version = '1.0.0'
13
+ config.servers = [{ 'url' => 'http://localhost:3000' }]
14
+
15
+ # Example JWT security for OpenAPI / rswag-ui "Authorize"
16
+ # config.security_schemes = {
17
+ # 'bearerAuth' => {
18
+ # 'type' => 'http',
19
+ # 'scheme' => 'bearer',
20
+ # 'bearerFormat' => 'JWT'
21
+ # }
22
+ # }
23
+ # config.security = [{ 'bearerAuth' => [] }]
24
+
25
+ config.with_multiple_examples = true
26
+ config.with_rspec_examples = true
27
+ config.action_for_old_examples = :append # :replace
28
+ end