docit 0.4.0 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +10 -1
- data/README.md +412 -21
- data/app/controllers/docit/ui_controller.rb +57 -3
- data/config/routes.rb +3 -0
- data/lib/docit/ai/system_insight_generator.rb +127 -0
- data/lib/docit/ai.rb +1 -0
- data/lib/docit/configuration.rb +4 -1
- data/lib/docit/system_graph/edge.rb +29 -0
- data/lib/docit/system_graph/generator.rb +15 -0
- data/lib/docit/system_graph/graph.rb +55 -0
- data/lib/docit/system_graph/node.rb +32 -0
- data/lib/docit/system_graph/rails_analyzer.rb +251 -0
- data/lib/docit/system_graph/source_scanner.rb +77 -0
- data/lib/docit/system_graph.rb +8 -0
- data/lib/docit/ui/base_renderer.rb +54 -21
- data/lib/docit/ui/system_renderer.rb +113 -0
- data/lib/docit/ui/system_script.rb +1495 -0
- data/lib/docit/ui/system_styles.rb +582 -0
- data/lib/docit/version.rb +1 -1
- data/lib/docit.rb +4 -0
- data/lib/generators/docit/install/templates/initializer.rb +4 -0
- metadata +15 -4
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 85a7407aab5a5fea2aa0c679d469360f124884ebeac2e4479265cbcdd818210d
|
|
4
|
+
data.tar.gz: c946eea9c5a664931630b00726f33b8e5bb296c1493e799c67cd905f330cba1d
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 3dd0a62c6d0f138916839a7bcc445f98921abaf9e0ef477473e4dddba67f2033fd29ffb51a4803597d98f0807ee24c53d6b5a90a8d144d87c54669ee51155fef
|
|
7
|
+
data.tar.gz: d953ceef06cd91034fa79503a07da386dcefc7cdddabcb3567d1638d6546a2c484bdebd82f263d732a94b89447a9e9f6b659d7008c322d2e238e002aca286a1b
|
data/CHANGELOG.md
CHANGED
|
@@ -1,4 +1,13 @@
|
|
|
1
|
-
## [
|
|
1
|
+
## [0.5.0] - 2026-05-31
|
|
2
|
+
|
|
3
|
+
### Added
|
|
4
|
+
- **System Map**: a local, deterministic architecture graph at `/api-docs/system` (JSON at `/api-docs/system.json`), built from Rails routes, controllers, actions, Docit docs coverage, schemas, models, and source-derived service/job/mailer nodes — no external service required
|
|
5
|
+
- System Map navigation alongside the Scalar and Swagger UIs
|
|
6
|
+
- Light and dark themes for the System Map (light by default), with a toolbar toggle persisted across visits
|
|
7
|
+
- **Diagram view**: interactive architecture graph with drag-to-arrange, scroll-to-zoom, pan, fit-to-screen, and PNG export; click a node to inspect its connections, with neighbouring nodes highlighted; `/` focuses node search
|
|
8
|
+
- Endpoints-section filter for the diagram (Users, Orders, …) that narrows the graph to one resource and everything it touches
|
|
9
|
+
- **Docs view**: a request/response reference grouped by resource, with human-readable endpoint titles derived from doc summaries (falling back to REST conventions), a documentation-coverage indicator per section, and a detail panel showing parameters, request body, and responses
|
|
10
|
+
- AI section explanations in the Docs view: "Explain section" summarises how a resource's endpoints work together, gated by a coverage warning so undocumented sections don't silently spend tokens
|
|
2
11
|
|
|
3
12
|
## [0.4.0] - 2026-04-18
|
|
4
13
|
|
data/README.md
CHANGED
|
@@ -11,7 +11,47 @@ Decorator-style API documentation for Ruby on Rails. Write OpenAPI 3.0.3 docs wi
|
|
|
11
11
|
### Swagger
|
|
12
12
|

|
|
13
13
|
|
|
14
|
-
> **Full documentation:** [
|
|
14
|
+
> **Full documentation:** [doc-it.dev/docs](https://doc-it.dev/docs)
|
|
15
|
+
|
|
16
|
+
## Table Of Contents
|
|
17
|
+
|
|
18
|
+
- Getting started
|
|
19
|
+
- [Installation](#installation)
|
|
20
|
+
- [Configuration](#configuration)
|
|
21
|
+
- [Usage](#usage)
|
|
22
|
+
- Documentation styles
|
|
23
|
+
- [Style 1: Inline (simple APIs)](#style-1-inline-simple-apis)
|
|
24
|
+
- [Style 2: Separate doc files (recommended for larger APIs)](#style-2-separate-doc-files-recommended-for-larger-apis)
|
|
25
|
+
- Endpoint DSL reference
|
|
26
|
+
- [Endpoint documentation DSL](#endpoint-documentation-dsl)
|
|
27
|
+
- [Request bodies](#request-bodies)
|
|
28
|
+
- [Path parameters](#path-parameters)
|
|
29
|
+
- [Enums](#enums)
|
|
30
|
+
- [Security](#security)
|
|
31
|
+
- [Deprecated endpoints](#deprecated-endpoints)
|
|
32
|
+
- [Nested objects and arrays](#nested-objects-and-arrays)
|
|
33
|
+
- [Response examples](#response-examples)
|
|
34
|
+
- [Shared schemas (`$ref`)](#shared-schemas-ref)
|
|
35
|
+
- [File uploads](#file-uploads)
|
|
36
|
+
- AI documentation
|
|
37
|
+
- [AI Automatic Documentation](#ai-automatic-documentation)
|
|
38
|
+
- [Quick start (included in install)](#quick-start-included-in-install)
|
|
39
|
+
- [Standalone commands](#standalone-commands)
|
|
40
|
+
- [Supported providers](#supported-providers)
|
|
41
|
+
- [What the AI generates](#what-the-ai-generates)
|
|
42
|
+
- Runtime and development
|
|
43
|
+
- [Documentation UIs](#documentation-uis)
|
|
44
|
+
- [System Map](#system-map)
|
|
45
|
+
- [How it works](#how-it-works)
|
|
46
|
+
- [Mounting at a different path](#mounting-at-a-different-path)
|
|
47
|
+
- [JSON spec only](#json-spec-only)
|
|
48
|
+
- [Development](#development)
|
|
49
|
+
- [Contributing](#contributing)
|
|
50
|
+
- [License](#license)
|
|
51
|
+
- Project docs
|
|
52
|
+
- [CHANGELOG](CHANGELOG.md)
|
|
53
|
+
- [CONTRIBUTING](CONTRIBUTING.md)
|
|
54
|
+
- [CODE OF CONDUCT](CODE_OF_CONDUCT.md)
|
|
15
55
|
|
|
16
56
|
## Installation
|
|
17
57
|
|
|
@@ -39,6 +79,8 @@ The install generator does everything in one step:
|
|
|
39
79
|
|
|
40
80
|
Visit `/api-docs` to see your interactive API documentation (Scalar by default, Swagger UI also available at `/api-docs/swagger`).
|
|
41
81
|
|
|
82
|
+
If you choose AI setup, Docit stores your provider config in `.docit_ai.yml` with restricted file permissions and adds that file to `.gitignore` when possible.
|
|
83
|
+
|
|
42
84
|
## Configuration
|
|
43
85
|
|
|
44
86
|
Edit `config/initializers/docit.rb`:
|
|
@@ -48,19 +90,39 @@ Docit.configure do |config|
|
|
|
48
90
|
config.title = "My API"
|
|
49
91
|
config.version = "1.0.0"
|
|
50
92
|
config.description = "Backend API documentation"
|
|
51
|
-
config.default_ui = :scalar # :scalar (default) or :swagger
|
|
52
93
|
|
|
53
|
-
|
|
94
|
+
# Documentation UI: :scalar (default) or :swagger
|
|
95
|
+
config.default_ui = :scalar
|
|
96
|
+
|
|
97
|
+
# Authentication: pick one (or multiple):
|
|
98
|
+
config.auth :bearer # Bearer token (JWT by default)
|
|
99
|
+
config.auth :basic # HTTP Basic
|
|
100
|
+
config.auth :api_key, name: "X-API-Key", # API key in header
|
|
101
|
+
location: "header"
|
|
102
|
+
|
|
103
|
+
# Tag descriptions (shown in the documentation sidebar):
|
|
54
104
|
config.tag "Users", description: "User account management"
|
|
105
|
+
config.tag "Auth", description: "Authentication endpoints"
|
|
106
|
+
|
|
107
|
+
# Server URLs (shown in the server dropdown):
|
|
55
108
|
config.server "https://api.example.com", description: "Production"
|
|
109
|
+
config.server "https://staging.example.com", description: "Staging"
|
|
110
|
+
config.server "http://localhost:3000", description: "Development"
|
|
111
|
+
|
|
112
|
+
# License information:
|
|
113
|
+
config.license name: "MIT", url: "https://opensource.org/licenses/MIT"
|
|
114
|
+
|
|
115
|
+
# Contact information:
|
|
116
|
+
config.contact name: "API Team", email: "api@example.com", url: "https://example.com/support"
|
|
117
|
+
|
|
118
|
+
# Terms of service:
|
|
119
|
+
config.terms_of_service "https://example.com/tos"
|
|
56
120
|
end
|
|
57
121
|
```
|
|
58
122
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
## Quick Start
|
|
123
|
+
## Usage
|
|
62
124
|
|
|
63
|
-
Docit supports two styles. Choose whichever fits your project or mix both.
|
|
125
|
+
Docit supports two styles for documenting endpoints. Choose whichever fits your project or mix both.
|
|
64
126
|
|
|
65
127
|
### Style 1: Inline (simple APIs)
|
|
66
128
|
|
|
@@ -73,7 +135,6 @@ class Api::V1::UsersController < ApplicationController
|
|
|
73
135
|
tags "Users"
|
|
74
136
|
response 200, "Users retrieved"
|
|
75
137
|
end
|
|
76
|
-
|
|
77
138
|
def index
|
|
78
139
|
# your code
|
|
79
140
|
end
|
|
@@ -93,62 +154,392 @@ module Api::V1::UsersDocs
|
|
|
93
154
|
|
|
94
155
|
doc :index do
|
|
95
156
|
summary "List all users"
|
|
157
|
+
description "Returns a paginated list of users"
|
|
96
158
|
tags "Users"
|
|
97
159
|
|
|
160
|
+
parameter :page, location: :query, type: :integer, description: "Page number"
|
|
161
|
+
|
|
98
162
|
response 200, "Users retrieved" do
|
|
99
163
|
property :users, type: :array, items: :object do
|
|
100
164
|
property :id, type: :integer, example: 1
|
|
101
165
|
property :email, type: :string, example: "user@example.com"
|
|
102
166
|
end
|
|
167
|
+
property :total, type: :integer, example: 42
|
|
168
|
+
end
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
doc :create do
|
|
172
|
+
summary "Create a user"
|
|
173
|
+
tags "Users"
|
|
174
|
+
|
|
175
|
+
request_body required: true do
|
|
176
|
+
property :email, type: :string, required: true
|
|
177
|
+
property :password, type: :string, required: true, format: :password
|
|
178
|
+
end
|
|
179
|
+
|
|
180
|
+
response 201, "User created" do
|
|
181
|
+
property :id, type: :integer
|
|
182
|
+
end
|
|
183
|
+
|
|
184
|
+
response 422, "Validation failed" do
|
|
185
|
+
property :errors, type: :object do
|
|
186
|
+
property :email, type: :array, items: :string
|
|
187
|
+
end
|
|
103
188
|
end
|
|
104
189
|
end
|
|
105
190
|
end
|
|
106
|
-
```
|
|
107
191
|
|
|
108
|
-
|
|
109
|
-
# app/controllers/api/v1/users_controller.rb
|
|
192
|
+
# app/controllers/api/v1/users_controller.rb — stays clean!
|
|
110
193
|
class Api::V1::UsersController < ApplicationController
|
|
111
194
|
use_docs Api::V1::UsersDocs
|
|
112
195
|
|
|
113
196
|
def index
|
|
114
197
|
# pure business logic
|
|
115
198
|
end
|
|
199
|
+
|
|
200
|
+
def create
|
|
201
|
+
# pure business logic
|
|
202
|
+
end
|
|
203
|
+
end
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
You can also mix both styles — use `use_docs` for most actions and add inline `doc_for` for one-offs:
|
|
207
|
+
|
|
208
|
+
```ruby
|
|
209
|
+
class Api::V1::UsersController < ApplicationController
|
|
210
|
+
use_docs Api::V1::UsersDocs # loads :index and :create from doc file
|
|
211
|
+
|
|
212
|
+
doc_for :destroy do # inline doc for this one action
|
|
213
|
+
summary "Delete user"
|
|
214
|
+
tags "Users"
|
|
215
|
+
response 204, "Deleted"
|
|
216
|
+
end
|
|
217
|
+
|
|
218
|
+
def index; end
|
|
219
|
+
def create; end
|
|
220
|
+
def destroy; end
|
|
116
221
|
end
|
|
117
222
|
```
|
|
118
223
|
|
|
119
|
-
|
|
224
|
+
### Endpoint documentation DSL
|
|
225
|
+
|
|
226
|
+
The following examples work in both `doc_for` blocks and `doc` blocks.
|
|
120
227
|
|
|
121
|
-
|
|
228
|
+
### Request bodies
|
|
122
229
|
|
|
123
|
-
|
|
230
|
+
```ruby
|
|
231
|
+
doc_for :create do
|
|
232
|
+
summary "Create a user"
|
|
233
|
+
tags "Users"
|
|
234
|
+
|
|
235
|
+
request_body required: true do
|
|
236
|
+
property :email, type: :string, required: true, example: "user@example.com"
|
|
237
|
+
property :password, type: :string, required: true, format: :password
|
|
238
|
+
property :name, type: :string, example: "Jane Doe"
|
|
239
|
+
property :profile, type: :object do
|
|
240
|
+
property :bio, type: :string
|
|
241
|
+
property :avatar_url, type: :string, format: :uri
|
|
242
|
+
end
|
|
243
|
+
end
|
|
124
244
|
|
|
125
|
-
|
|
245
|
+
response 201, "User created" do
|
|
246
|
+
property :id, type: :integer, example: 1
|
|
247
|
+
property :email, type: :string, example: "user@example.com"
|
|
248
|
+
end
|
|
249
|
+
|
|
250
|
+
response 422, "Validation failed" do
|
|
251
|
+
property :errors, type: :object do
|
|
252
|
+
property :email, type: :array, items: :string
|
|
253
|
+
end
|
|
254
|
+
end
|
|
255
|
+
end
|
|
256
|
+
def create
|
|
257
|
+
# your code
|
|
258
|
+
end
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
### Path parameters
|
|
262
|
+
|
|
263
|
+
```ruby
|
|
264
|
+
doc_for :show do
|
|
265
|
+
summary "Get a user"
|
|
266
|
+
tags "Users"
|
|
267
|
+
|
|
268
|
+
parameter :id, location: :path, type: :integer, required: true, description: "User ID"
|
|
269
|
+
|
|
270
|
+
response 200, "User found" do
|
|
271
|
+
property :id, type: :integer, example: 1
|
|
272
|
+
property :email, type: :string
|
|
273
|
+
property :name, type: :string
|
|
274
|
+
end
|
|
275
|
+
|
|
276
|
+
response 404, "User not found" do
|
|
277
|
+
property :error, type: :string, example: "Not found"
|
|
278
|
+
end
|
|
279
|
+
end
|
|
280
|
+
def show
|
|
281
|
+
# your code
|
|
282
|
+
end
|
|
283
|
+
```
|
|
284
|
+
|
|
285
|
+
### Enums
|
|
286
|
+
|
|
287
|
+
```ruby
|
|
288
|
+
doc_for :index do
|
|
289
|
+
summary "List orders"
|
|
290
|
+
tags "Orders"
|
|
291
|
+
|
|
292
|
+
parameter :status, location: :query, type: :string,
|
|
293
|
+
enum: %w[pending shipped delivered],
|
|
294
|
+
description: "Filter by status"
|
|
295
|
+
|
|
296
|
+
response 200, "Orders list" do
|
|
297
|
+
property :orders, type: :array do
|
|
298
|
+
property :id, type: :integer
|
|
299
|
+
property :status, type: :string, enum: %w[pending shipped delivered]
|
|
300
|
+
end
|
|
301
|
+
end
|
|
302
|
+
end
|
|
303
|
+
```
|
|
304
|
+
|
|
305
|
+
### Security
|
|
306
|
+
|
|
307
|
+
Mark endpoints as requiring authentication:
|
|
308
|
+
|
|
309
|
+
```ruby
|
|
310
|
+
doc_for :destroy do
|
|
311
|
+
summary "Delete a user"
|
|
312
|
+
tags "Users"
|
|
313
|
+
security :bearer_auth # references the scheme from your config
|
|
314
|
+
|
|
315
|
+
response 204, "User deleted"
|
|
316
|
+
response 401, "Unauthorized"
|
|
317
|
+
end
|
|
318
|
+
```
|
|
319
|
+
|
|
320
|
+
### Deprecated endpoints
|
|
321
|
+
|
|
322
|
+
```ruby
|
|
323
|
+
doc_for :legacy_search do
|
|
324
|
+
summary "Search (legacy)"
|
|
325
|
+
tags "Search"
|
|
326
|
+
deprecated
|
|
327
|
+
|
|
328
|
+
response 200, "Results"
|
|
329
|
+
end
|
|
330
|
+
```
|
|
331
|
+
|
|
332
|
+
### Nested objects and arrays
|
|
333
|
+
|
|
334
|
+
```ruby
|
|
335
|
+
response 200, "Success" do
|
|
336
|
+
property :user, type: :object do
|
|
337
|
+
property :id, type: :integer
|
|
338
|
+
property :name, type: :string
|
|
339
|
+
property :addresses, type: :array do
|
|
340
|
+
property :street, type: :string
|
|
341
|
+
property :city, type: :string
|
|
342
|
+
property :zip, type: :string
|
|
343
|
+
end
|
|
344
|
+
end
|
|
345
|
+
end
|
|
346
|
+
```
|
|
347
|
+
|
|
348
|
+
### Response examples
|
|
349
|
+
|
|
350
|
+
```ruby
|
|
351
|
+
response 200, "User found" do
|
|
352
|
+
property :id, type: :integer
|
|
353
|
+
property :email, type: :string
|
|
354
|
+
|
|
355
|
+
example "admin_user",
|
|
356
|
+
{ id: 1, email: "admin@example.com" },
|
|
357
|
+
description: "An admin user"
|
|
358
|
+
|
|
359
|
+
example "regular_user",
|
|
360
|
+
{ id: 2, email: "user@example.com" },
|
|
361
|
+
description: "A regular user"
|
|
362
|
+
end
|
|
363
|
+
```
|
|
364
|
+
|
|
365
|
+
### Shared schemas (`$ref`)
|
|
366
|
+
|
|
367
|
+
Define reusable schemas once and reference them across multiple endpoints:
|
|
368
|
+
|
|
369
|
+
```ruby
|
|
370
|
+
# In config/initializers/docit.rb or a dedicated file:
|
|
371
|
+
Docit.define_schema :User do
|
|
372
|
+
property :id, type: :integer, example: 1
|
|
373
|
+
property :email, type: :string, example: "user@example.com"
|
|
374
|
+
property :name, type: :string, example: "Jane Doe"
|
|
375
|
+
property :address, type: :object do
|
|
376
|
+
property :street, type: :string
|
|
377
|
+
property :city, type: :string
|
|
378
|
+
end
|
|
379
|
+
end
|
|
380
|
+
|
|
381
|
+
Docit.define_schema :Error do
|
|
382
|
+
property :error, type: :string, example: "Not found"
|
|
383
|
+
property :details, type: :array, items: :string
|
|
384
|
+
end
|
|
385
|
+
```
|
|
386
|
+
|
|
387
|
+
Reference them in any endpoint with `schema ref:`:
|
|
388
|
+
|
|
389
|
+
```ruby
|
|
390
|
+
doc_for :show do
|
|
391
|
+
summary "Get user"
|
|
392
|
+
tags "Users"
|
|
393
|
+
|
|
394
|
+
response 200, "User found" do
|
|
395
|
+
schema ref: :User
|
|
396
|
+
end
|
|
397
|
+
|
|
398
|
+
response 404, "Not found" do
|
|
399
|
+
schema ref: :Error
|
|
400
|
+
end
|
|
401
|
+
end
|
|
402
|
+
|
|
403
|
+
doc_for :create do
|
|
404
|
+
summary "Create user"
|
|
405
|
+
tags "Users"
|
|
406
|
+
|
|
407
|
+
request_body required: true do
|
|
408
|
+
schema ref: :User
|
|
409
|
+
end
|
|
410
|
+
|
|
411
|
+
response 201, "Created" do
|
|
412
|
+
schema ref: :User
|
|
413
|
+
end
|
|
414
|
+
end
|
|
415
|
+
```
|
|
416
|
+
|
|
417
|
+
This outputs `$ref: '#/components/schemas/User'` in the spec — Swagger UI resolves it automatically.
|
|
418
|
+
|
|
419
|
+
### File uploads
|
|
420
|
+
|
|
421
|
+
Use `type: :file` with `content_type: "multipart/form-data"` for file upload endpoints:
|
|
422
|
+
|
|
423
|
+
```ruby
|
|
424
|
+
doc_for :upload_avatar do
|
|
425
|
+
summary "Upload avatar"
|
|
426
|
+
tags "Users"
|
|
427
|
+
|
|
428
|
+
request_body required: true, content_type: "multipart/form-data" do
|
|
429
|
+
property :avatar, type: :file, required: true, description: "Avatar image"
|
|
430
|
+
property :caption, type: :string
|
|
431
|
+
end
|
|
432
|
+
|
|
433
|
+
response 201, "Avatar uploaded" do
|
|
434
|
+
property :url, type: :string, format: :uri
|
|
435
|
+
end
|
|
436
|
+
end
|
|
437
|
+
```
|
|
438
|
+
|
|
439
|
+
`type: :file` maps to `{ type: "string", format: "binary" }` in the OpenAPI spec.
|
|
440
|
+
|
|
441
|
+
## AI Automatic Documentation
|
|
442
|
+
|
|
443
|
+
Docit can generate complete API documentation using AI. This works with OpenAI, Anthropic, or Groq (free tier available).
|
|
444
|
+
|
|
445
|
+
### Quick start (included in install)
|
|
446
|
+
|
|
447
|
+
When you run `rails generate docit:install` and choose option 1 (AI automatic docs), everything is set up automatically — provider configuration, doc generation, controller wiring, and tag injection.
|
|
448
|
+
|
|
449
|
+
Before the first AI request, Docit warns that your controller source code will be sent to the selected provider and asks for confirmation in interactive terminals.
|
|
450
|
+
|
|
451
|
+
### Standalone commands
|
|
452
|
+
|
|
453
|
+
You can also set up AI docs separately:
|
|
126
454
|
|
|
127
455
|
```bash
|
|
128
|
-
#
|
|
456
|
+
# Configure your AI provider (one-time setup)
|
|
129
457
|
rails generate docit:ai_setup
|
|
458
|
+
|
|
459
|
+
# Generate docs for all undocumented endpoints
|
|
130
460
|
rails docit:autodoc
|
|
131
461
|
|
|
132
|
-
#
|
|
462
|
+
# Generate docs for a specific controller
|
|
463
|
+
rails docit:autodoc[Api::V1::UsersController]
|
|
464
|
+
|
|
465
|
+
# Preview what would be generated without writing files
|
|
133
466
|
DRY_RUN=1 rails docit:autodoc
|
|
134
467
|
```
|
|
135
468
|
|
|
136
|
-
|
|
469
|
+
### Supported providers
|
|
470
|
+
|
|
471
|
+
| Provider | Notes |
|
|
472
|
+
|------------|-------|
|
|
473
|
+
| OpenAI | Requires API key from platform.openai.com |
|
|
474
|
+
| Anthropic | Requires API key from console.anthropic.com |
|
|
475
|
+
| Groq | Free tier at console.groq.com |
|
|
476
|
+
|
|
477
|
+
All providers automatically retry on rate-limit (429) errors with exponential backoff, so free-tier usage works out of the box.
|
|
478
|
+
|
|
479
|
+
AI configuration is stored in `.docit_ai.yml`.
|
|
480
|
+
If your app does not have a `.gitignore`, add `.docit_ai.yml` manually.
|
|
481
|
+
|
|
482
|
+
### What the AI generates
|
|
483
|
+
|
|
484
|
+
For each undocumented endpoint, Docit:
|
|
485
|
+
|
|
486
|
+
1. Reads the controller source code
|
|
487
|
+
2. Inspects the route (HTTP method, path, parameters)
|
|
488
|
+
3. Writes the generated doc block to `app/docs/`
|
|
489
|
+
4. Injects `use_docs` into the controller
|
|
490
|
+
5. Adds tag descriptions to the initializer
|
|
491
|
+
|
|
492
|
+
Do not use AI autodoc on controllers that contain secrets, proprietary business rules, or internal comments you do not want sent to an external provider.
|
|
137
493
|
|
|
138
494
|
## Documentation UIs
|
|
139
495
|
|
|
496
|
+
Docit ships with two documentation UIs, both reading from the same OpenAPI spec:
|
|
497
|
+
|
|
140
498
|
| Path | UI | Notes |
|
|
141
499
|
|------|------|-------|
|
|
142
500
|
| `/api-docs` | Default (Scalar) | Configurable via `config.default_ui` |
|
|
143
|
-
| `/api-docs/scalar` | Scalar API Reference | Modern UI with API client, dark mode |
|
|
501
|
+
| `/api-docs/scalar` | Scalar API Reference | Modern UI with built-in API client, dark mode, code samples |
|
|
144
502
|
| `/api-docs/swagger` | Swagger UI | Classic OpenAPI explorer |
|
|
503
|
+
| `/api-docs/system` | System Map | Local architecture graph for routes, controllers, docs coverage, and app structure |
|
|
145
504
|
| `/api-docs/spec` | Raw JSON | OpenAPI 3.0.3 spec |
|
|
146
505
|
|
|
147
|
-
|
|
506
|
+
Both UIs include a navigation bar to switch between them. Set `config.default_ui = :swagger` to make Swagger the default at `/api-docs`.
|
|
507
|
+
|
|
508
|
+
## System Map
|
|
509
|
+
|
|
510
|
+
Docit includes a local system map for understanding how your Rails API fits together. It builds a **deterministic** graph from Rails routes, controller actions, Docit docs, schemas, models, and source references — no external service is required to view it.
|
|
511
|
+
|
|
512
|
+
Visit `/api-docs/system` to open it. It has two views, a light/dark theme toggle, and PNG export:
|
|
513
|
+
|
|
514
|
+
- **Diagram** — an interactive architecture graph. Drag nodes to rearrange, scroll to zoom, and click a node to inspect its connections (its neighbours highlight while the rest fade back). Filter to a single resource with the section dropdown, or press `/` to search nodes.
|
|
515
|
+
- **Docs** — a request/response reference grouped by resource. Each endpoint shows a human-readable title, its method and path, parameters, request body, and responses, drawn from your Docit docs. A coverage indicator shows how many endpoints in each section are documented.
|
|
516
|
+
|
|
517
|
+
If you have an AI provider configured, the Docs view's **Explain section** button summarises how a resource's endpoints work together. It warns before running on sections with undocumented endpoints, so documenting first gives a better result.
|
|
518
|
+
|
|
519
|
+
## How it works
|
|
148
520
|
|
|
149
521
|
1. `doc_for` registers an **Operation** for each controller action in a global **Registry**
|
|
150
522
|
2. When someone visits `/api-docs/spec`, Docit's **SchemaGenerator** combines all registered operations with your Rails routes (via **RouteInspector**) to produce an OpenAPI 3.0.3 JSON document
|
|
151
523
|
3. The **Engine** serves the configured documentation UI at `/api-docs`, pointing it at the generated spec
|
|
524
|
+
4. The **SystemGraph** builds a local architecture graph for `/api-docs/system`
|
|
525
|
+
|
|
526
|
+
The DSL is included in all controllers automatically via a Rails Engine initializer — no manual `include` needed if you're using `ActionController::API` or `ActionController::Base`.
|
|
527
|
+
|
|
528
|
+
## Mounting at a different path
|
|
529
|
+
|
|
530
|
+
In `config/routes.rb`:
|
|
531
|
+
|
|
532
|
+
```ruby
|
|
533
|
+
mount Docit::Engine => "/docs" # now at /docs instead of /api-docs
|
|
534
|
+
```
|
|
535
|
+
|
|
536
|
+
## JSON spec only
|
|
537
|
+
|
|
538
|
+
If you just want the raw OpenAPI JSON (e.g., for code generation):
|
|
539
|
+
|
|
540
|
+
```
|
|
541
|
+
GET /api-docs/spec
|
|
542
|
+
```
|
|
152
543
|
|
|
153
544
|
## Development
|
|
154
545
|
|
|
@@ -156,7 +547,7 @@ See the [full AI documentation guide](https://docitruby.dev/docs/ai-documentatio
|
|
|
156
547
|
git clone https://github.com/S13G/docit.git
|
|
157
548
|
cd docit
|
|
158
549
|
bundle install
|
|
159
|
-
bundle exec rspec
|
|
550
|
+
bundle exec rspec # run all tests
|
|
160
551
|
```
|
|
161
552
|
|
|
162
553
|
## Contributing
|
|
@@ -16,6 +16,31 @@ module Docit
|
|
|
16
16
|
render_ui(:scalar)
|
|
17
17
|
end
|
|
18
18
|
|
|
19
|
+
def system
|
|
20
|
+
render_ui(:system)
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def system_spec
|
|
24
|
+
unless Docit.configuration.system_graph_enabled
|
|
25
|
+
return render(json: { error: "System graph disabled" }, status: :not_found)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
RouteInspector.eager_load_controllers!
|
|
29
|
+
render json: SystemGraph::Generator.generate
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def system_insights
|
|
33
|
+
graph = system_graph
|
|
34
|
+
insight = Ai::SystemInsightGenerator.new(
|
|
35
|
+
graph: graph,
|
|
36
|
+
selected_node_ids: selected_node_ids,
|
|
37
|
+
mode: insight_mode
|
|
38
|
+
).generate
|
|
39
|
+
render json: { insight: insight }
|
|
40
|
+
rescue Docit::Error => e
|
|
41
|
+
render json: { error: e.message }, status: :unprocessable_entity
|
|
42
|
+
end
|
|
43
|
+
|
|
19
44
|
def spec
|
|
20
45
|
RouteInspector.eager_load_controllers!
|
|
21
46
|
render json: SchemaGenerator.generate
|
|
@@ -25,21 +50,50 @@ module Docit
|
|
|
25
50
|
|
|
26
51
|
RENDERERS = {
|
|
27
52
|
swagger: UI::SwaggerRenderer,
|
|
28
|
-
scalar: UI::ScalarRenderer
|
|
53
|
+
scalar: UI::ScalarRenderer,
|
|
54
|
+
system: UI::SystemRenderer
|
|
29
55
|
}.freeze
|
|
30
56
|
|
|
31
57
|
def render_ui(ui_name)
|
|
32
|
-
renderer = RENDERERS.fetch(ui_name).new(
|
|
58
|
+
renderer = RENDERERS.fetch(ui_name).new(
|
|
59
|
+
spec_url: spec_url,
|
|
60
|
+
system_url: system_url,
|
|
61
|
+
system_insights_url: system_insights_url,
|
|
62
|
+
nav_paths: nav_paths
|
|
63
|
+
)
|
|
33
64
|
render html: renderer.render.html_safe, layout: false
|
|
34
65
|
end
|
|
35
66
|
|
|
67
|
+
def system_graph
|
|
68
|
+
RouteInspector.eager_load_controllers!
|
|
69
|
+
SystemGraph::Generator.generate
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def selected_node_ids
|
|
73
|
+
params.fetch(:node_ids, "").to_s.split(",").reject(&:empty?)
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
# Validate at the boundary: only the known modes are honored, anything
|
|
77
|
+
# else falls back to the safe per-node default.
|
|
78
|
+
def insight_mode
|
|
79
|
+
params[:mode].to_s == "section" ? :section : :nodes
|
|
80
|
+
end
|
|
81
|
+
|
|
36
82
|
def spec_url
|
|
37
83
|
"#{request.base_url}#{Docit::Engine.routes.url_helpers.spec_path}"
|
|
38
84
|
end
|
|
39
85
|
|
|
86
|
+
def system_url
|
|
87
|
+
"#{request.base_url}#{Docit::Engine.routes.url_helpers.system_spec_path}"
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def system_insights_url
|
|
91
|
+
"#{request.base_url}#{Docit::Engine.routes.url_helpers.system_insights_path}"
|
|
92
|
+
end
|
|
93
|
+
|
|
40
94
|
def nav_paths
|
|
41
95
|
helpers = Docit::Engine.routes.url_helpers
|
|
42
|
-
{ swagger: helpers.swagger_path, scalar: helpers.scalar_path }
|
|
96
|
+
{ swagger: helpers.swagger_path, scalar: helpers.scalar_path, system: helpers.system_path }
|
|
43
97
|
end
|
|
44
98
|
end
|
|
45
99
|
end
|
data/config/routes.rb
CHANGED
|
@@ -4,5 +4,8 @@ Docit::Engine.routes.draw do
|
|
|
4
4
|
root to: "ui#index"
|
|
5
5
|
get "swagger", to: "ui#swagger"
|
|
6
6
|
get "scalar", to: "ui#scalar"
|
|
7
|
+
get "system.json", to: "ui#system_spec", defaults: { format: :json }, as: :system_spec
|
|
8
|
+
get "system/insights", to: "ui#system_insights", defaults: { format: :json }, as: :system_insights
|
|
9
|
+
get "system", to: "ui#system", as: :system
|
|
7
10
|
get "spec", to: "ui#spec", defaults: { format: :json }
|
|
8
11
|
end
|