rails-api-docs 0.1.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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 73547bf7e093c1c31aec89795cccd24af94e197e4e9873d74203416dd9814a0e
4
+ data.tar.gz: 56b12f232d112a9acf5ceee20bba9fc29c6ae2c00019f2ab27ba0a51c114107c
5
+ SHA512:
6
+ metadata.gz: abe7d84faabd80caa57004d13fe0f74e304567d5e0d5df85557f1506a81a8a5ed83c76a4f61c8600cb1d387ccee811b1221f6d1014dd5a68ed7658dc5c9b48c8
7
+ data.tar.gz: e570a94a46be252cb60f6e110866239c99e9c26735a8d0150f6f80f9bde8e2a09cd1787cb67696b03c5d4b9aa68402126433ebf47011d35292fa8eb58fb8bb51
data/CHANGELOG.md ADDED
@@ -0,0 +1,156 @@
1
+ # Changelog
2
+
3
+ ## [0.1.1] - 2026-06-03
4
+
5
+ ### Fixed
6
+
7
+ - **Critical packaging bug.** `lib/rails-api-docs/doc/` files
8
+ (`curl_renderer`, `renderer`, `responder`, `file_builder`) were
9
+ silently excluded from the 0.1.0 release because the `doc/` pattern
10
+ in `.gitignore` matched **any** `doc/` directory at any depth, not
11
+ just the repository root. Installing 0.1.0 produced
12
+ `cannot load such file -- …/lib/rails-api-docs/doc/curl_renderer`
13
+ at boot. Tightened the gitignore pattern to `/doc/` so it only
14
+ ignores the top-level `doc/` directory (RDoc/YARD output). 0.1.0 has
15
+ been yanked from RubyGems.
16
+
17
+ ## [0.1.0] - 2026-06-02 [YANKED]
18
+
19
+ Initial release — **yanked**. See 0.1.1 for the first usable version.
20
+
21
+ ### Inspection & inference
22
+
23
+ - **`Inspectors::RouteInspector`**: walks `Rails.application.routes`,
24
+ normalizes paths (strips `(.:format)`), filters Rails internals
25
+ (`/rails/info`, `/rails/active_storage`, …), groups by controller,
26
+ supports multi-verb `match` and namespaced paths (`api/v1/users`).
27
+ - **`Inspectors::ControllerInspector`** (Prism AST): extracts permitted
28
+ attribute names from `params.permit(:a, :b, …)` calls anywhere in the
29
+ controller file. Handles flat permits, hash-rocket form, and nested
30
+ permits (top-level keys only).
31
+ - **`Inspectors::SchemaInspector`**: resolves controller → ActiveRecord
32
+ model and reads `columns_hash` for type and nullability metadata.
33
+ Best-effort — returns `{}` when the model can't be resolved.
34
+ - **`Inspectors::BodyInferrer`**: composes Controller + Schema to produce
35
+ typed `body:` field lists for `create`/`update` actions, with sensible
36
+ fallbacks (`string` type, `required: false`) when inspectors come up
37
+ empty.
38
+ - **`Inspectors::JsonRouteDetector`** (Prism AST): decides if an endpoint
39
+ is JSON-returning. Walks the controller's superclass chain looking for
40
+ `ActionController::API`; falls back to per-action `render json:`
41
+ detection inside `DefNode` bodies (kwarg and hash-rocket form, inside
42
+ `respond_to` blocks too). Cached per-controller.
43
+
44
+ ### YAML generation & merge
45
+
46
+ - **`Config::Builder`**: assembles the full config — `general_configurations`
47
+ with Rails-themed defaults (`#CC0000` primary), `sections` grouped by
48
+ controller, endpoints with method/path/name/description/show, inferred
49
+ path params, body fields from the inferrer, and a response stub.
50
+ - **`Config::Appender` (append-only re-runs)**: re-running
51
+ `rails g rails-api-docs:update` only adds new routes; existing entries —
52
+ including user edits to descriptions, body fields, examples, headers,
53
+ responses — are never modified. Endpoint identity is `"#{method} #{path}"`.
54
+ - **`Config::Loader`**: parses existing YAML; `Loader.header` extracts
55
+ the leading `#`-comment block so it survives re-runs verbatim.
56
+ - **`RailsApiDocs::SampleValue`**: single source of truth for
57
+ type-derived placeholder values (`integer → 1`, `string → "example"`,
58
+ `date → "2026-01-01"`, …). Shared between inferrer, builder, curl
59
+ renderer, and HTML renderer.
60
+
61
+ ### Generators
62
+
63
+ - **Two generator commands** (one implementation): `rails-api-docs:init`
64
+ for the first scaffold and `rails-api-docs:update` for re-runs.
65
+ `UpdateGenerator < InitGenerator` aliases the namespace; same code, same
66
+ flags, semantically distinct invocation.
67
+ - **`--api-only`**: filters scaffold to JSON-returning routes only,
68
+ via `JsonRouteDetector`. Persistent via
69
+ `RailsApiDocs.configuration.api_only = true`.
70
+ - **`--only-controllers`**: whitelist controllers by name. Accepts
71
+ space-, comma-, or bracket-separated forms
72
+ (`users posts`, `users,posts`, `[users,posts]`). Bare names match
73
+ across namespaces (`users` matches `users` and `api/v1/users`);
74
+ slash-qualified names are exact. Persistent via
75
+ `RailsApiDocs.configuration.only_controllers = […]`.
76
+ - **`--verbose-yaml`**: emits every possible YAML key per endpoint and
77
+ field with defaults (full discoverability at the cost of file size).
78
+ Persistent via `RailsApiDocs.configuration.verbose_yaml = true`.
79
+ Composes with all other flags.
80
+ - **Other filtering knobs**: `Configuration#ignored_path_prefixes`,
81
+ `#ignored_controllers` (strings or regexps; same boundary-aware
82
+ matching as `only_controllers`), `#ignored_actions`. Blacklist wins
83
+ over whitelist when both apply.
84
+
85
+ ### YAML schema
86
+
87
+ - **Pragmatic default**: every inferred body field and path param ships
88
+ with `description: ""` and `example: <type-sample>` — users edit
89
+ values without remembering key names. A minimal `responses["200"]`
90
+ stub is included for every endpoint.
91
+ - **Verbose mode** additionally emits `format`, `enum`, `default`,
92
+ `min`/`max`, `min_length`/`max_length`, `pattern`, `read_only`,
93
+ `write_only`, `nullable` per field; and `deprecated`, `auth`, `tags`,
94
+ `headers`, `request_example`, plus a full `responses["200"]` with
95
+ `headers: []` and `schema: []`.
96
+ - **Response shape**: `responses["XXX"]` accepts `description`,
97
+ `example` (raw string), `headers` (array of field hashes), and
98
+ `schema` (typed response fields rendered as field rows).
99
+
100
+ ### HTML renderer
101
+
102
+ - **Three-column self-contained output**: sidebar, central column with
103
+ field tables, right column with cURL and response examples. All CSS
104
+ and JS inlined — no external assets, no asset pipeline.
105
+ - **CSS variables driven by `general_configurations`**: changing
106
+ `primary_color` / `secondary_color` re-themes the whole page.
107
+ - **Unified `render_field` helper**: single source of truth for field
108
+ rendering. Used by body, params, request headers, response headers,
109
+ and response schema. Renders all field-level attributes as badges,
110
+ metas, descriptions, and inline `Example:` lines.
111
+ - **Endpoint-level badges**: `deprecated` (red badge + strikethrough
112
+ title), `auth` (dark monospace badge: "Bearer auth", "Basic auth",
113
+ custom), `tags` (clickable chips).
114
+ - **`Doc::CurlRenderer`**: multi-line cURL with proper shell escaping
115
+ (single quotes via the `'\''` block-form `gsub`). Supports
116
+ `request_example` overrides, per-param `example:` substitution in the
117
+ URL, and auto-injects user-declared `headers:` plus an `Authorization`
118
+ placeholder when `auth:` is set.
119
+ - **Multi-response support**: `responses:` keyed by status code with
120
+ per-status tabs in the right column (2xx green, 4xx amber, 5xx red);
121
+ the central column renders headers + schema per status when present.
122
+ - **Response title + copy buttons**: every cURL block and response
123
+ block has a `<button>` copy icon that copies the currently-active
124
+ `<pre>` content (curl command or active response tab). Uses
125
+ `navigator.clipboard.writeText` with `document.execCommand('copy')`
126
+ fallback for non-secure contexts. Visual flash + checkmark on success.
127
+ - **Tag click filtering**: clicking a tag pill filters the sidebar to
128
+ endpoints carrying that tag. Single-tag exclusive with toggle (same
129
+ tag = clear, different tag = switch). Combines with the text search
130
+ via AND. "Filtered by: <tag> ×" pill shown between search and section
131
+ list. Accessible: `<button>` elements, `aria-pressed`, `aria-live`.
132
+ - **Field example propagation**: `field["example"]` is the single
133
+ source of truth for sample values — it flows into the cURL `--data`
134
+ body and into the default response example block, with the
135
+ type-derived sample as fallback.
136
+
137
+ ### Distribution
138
+
139
+ - **Dev mount at `/rails/api-docs`**: `Rails::Engine` mounts a
140
+ `DocsController` in `development` that re-renders the HTML from the
141
+ current YAML on every request — no build step while iterating.
142
+ Friendly setup page when YAML doesn't exist yet.
143
+ - **`rake rails-api-docs:build`**: reads the YAML and writes
144
+ `public/api-docs.html`. Supports `CONFIG=` and `OUTPUT=` env overrides.
145
+ - **Publish-ready gemspec metadata**: `homepage_uri`, `source_code_uri`
146
+ (pointing at `/tree/main` so RubyGems shows both), `changelog_uri`,
147
+ `bug_tracker_uri`, `documentation_uri`, and
148
+ `rubygems_mfa_required = "true"` (enforces MFA on every `gem push`).
149
+
150
+ ### Tests
151
+
152
+ - 185 minitest cases covering inspectors, config build/append/load,
153
+ renderer, curl renderer, file builder, responder, init/update
154
+ generators, and JSON route detector. Uses
155
+ `ActionDispatch::Routing::RouteSet` directly — no dummy Rails app
156
+ required.
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Jackson Pires
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 all
13
+ 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 THE
21
+ SOFTWARE.