Skip to content

Commit 347597a

Browse files
committed
wip: swagger api docs
1 parent ecd2c9c commit 347597a

File tree

77 files changed

+27930
-1
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

77 files changed

+27930
-1
lines changed

OPENAPI_SETUP.md

Lines changed: 302 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,302 @@
1+
# OpenAPI Automatic Generation Setup
2+
3+
This document explains how to use OpenApiSpex to automatically generate OpenAPI
4+
specifications from your Lightning API code.
5+
6+
## Overview
7+
8+
OpenApiSpex is integrated to provide:
9+
10+
- Automatic OpenAPI spec generation from code annotations
11+
- Request/response validation
12+
- Interactive API documentation
13+
- Type-safe API contracts
14+
15+
## Setup Complete
16+
17+
The following has been configured:
18+
19+
1. **Dependency Added**: `open_api_spex ~> 3.22` in `mix.exs`
20+
2. **API Spec Module**: `lib/lightning_web/api_spec.ex`
21+
3. **Schema Definitions**: `lib/lightning_web/schemas.ex`
22+
4. **Example Controller Specs**:
23+
`lib/lightning_web/controllers/api/project_controller_spec.ex`
24+
5. **Mix Alias**: `mix api.docs` to generate and update docs
25+
26+
## Quick Start
27+
28+
### 1. Install Dependencies
29+
30+
```bash
31+
mix deps.get
32+
```
33+
34+
### 2. Add OpenAPI Route (Optional)
35+
36+
To serve the OpenAPI spec at `/api/openapi`, add to
37+
`lib/lightning_web/router.ex`:
38+
39+
```elixir
40+
scope "/api" do
41+
pipe_through :api
42+
43+
# Existing routes...
44+
45+
# Add this line:
46+
get "/openapi", OpenApiSpex.Plug.RenderSpec, []
47+
end
48+
```
49+
50+
### 3. Generate OpenAPI Spec
51+
52+
```bash
53+
# Generate the spec file
54+
mix openapi.spec.yaml --spec LightningWeb.ApiSpec --output docs/static/openapi.yaml
55+
56+
# Or use the convenience alias that also regenerates docs:
57+
mix api.docs
58+
```
59+
60+
## Annotating Controllers
61+
62+
### Step 1: Add OpenApiSpex to a Controller
63+
64+
```elixir
65+
defmodule LightningWeb.API.ProjectController do
66+
use LightningWeb, :controller
67+
use OpenApiSpex.ControllerSpecs # Add this line
68+
69+
alias LightningWeb.Schemas
70+
71+
# Specify the API tag
72+
tags ["Projects"]
73+
74+
# ... rest of controller
75+
end
76+
```
77+
78+
### Step 2: Annotate Actions
79+
80+
Add `operation` macro before each controller action:
81+
82+
```elixir
83+
operation :index,
84+
summary: "List all accessible projects",
85+
parameters: [
86+
page: [in: :query, type: :integer, description: "Page number"],
87+
page_size: [in: :query, type: :integer, description: "Items per page"]
88+
],
89+
responses: [
90+
ok: {"Projects response", "application/json", Schemas.ProjectListResponse},
91+
unauthorized: {"Auth required", "application/json", Schemas.ErrorResponse}
92+
]
93+
94+
def index(conn, params) do
95+
# Your existing implementation
96+
end
97+
```
98+
99+
### Step 3: Define Request/Response Schemas
100+
101+
Add schemas to `lib/lightning_web/schemas.ex`:
102+
103+
```elixir
104+
defmodule ProjectListResponse do
105+
require OpenApiSpex
106+
107+
OpenApiSpex.schema(%{
108+
title: "ProjectListResponse",
109+
type: :object,
110+
properties: %{
111+
data: %Schema{type: :array, items: Project},
112+
page_number: %Schema{type: :integer},
113+
page_size: %Schema{type: :integer},
114+
total_entries: %Schema{type: :integer}
115+
}
116+
})
117+
end
118+
```
119+
120+
## Example: Fully Annotated Controller
121+
122+
See `lib/lightning_web/controllers/api/project_controller_spec.ex` for a
123+
complete example.
124+
125+
### Inline Annotation
126+
127+
```elixir
128+
defmodule LightningWeb.API.ProjectController do
129+
use LightningWeb, :controller
130+
use OpenApiSpex.ControllerSpecs
131+
132+
alias LightningWeb.Schemas
133+
134+
tags ["Projects"]
135+
136+
operation :index,
137+
summary: "List all accessible projects",
138+
parameters: [
139+
page: [in: :query, type: :integer, description: "Page number", default: 1],
140+
page_size: [in: :query, type: :integer, description: "Items per page", default: 10]
141+
],
142+
responses: [
143+
ok: {"Projects list", "application/json", Schemas.ProjectListResponse},
144+
unauthorized: {"Unauthorized", "application/json", Schemas.ErrorResponse}
145+
]
146+
147+
def index(conn, params) do
148+
# Implementation
149+
end
150+
151+
operation :show,
152+
summary: "Get project by ID",
153+
parameters: [
154+
id: [in: :path, type: :string, format: :uuid, description: "Project ID"]
155+
],
156+
responses: [
157+
ok: {"Project details", "application/json", Schemas.ProjectResponse},
158+
not_found: {"Not found", "application/json", Schemas.ErrorResponse}
159+
]
160+
161+
def show(conn, %{"id" => id}) do
162+
# Implementation
163+
end
164+
end
165+
```
166+
167+
## Request Validation
168+
169+
To enable request validation, add plugs to your controller:
170+
171+
```elixir
172+
plug OpenApiSpex.Plug.CastAndValidate,
173+
json_render_error_v2: true,
174+
operation_id: "ProjectController.index"
175+
176+
def index(conn, params) do
177+
# params are now cast to the types defined in the operation spec
178+
end
179+
```
180+
181+
## Response Validation (Development Only)
182+
183+
Add response validation in development:
184+
185+
```elixir
186+
if Mix.env() == :dev do
187+
plug OpenApiSpex.Plug.ValidateResponse
188+
end
189+
```
190+
191+
## Migration Path
192+
193+
### Phase 1: Co-existence (Current)
194+
195+
- Manual OpenAPI spec in `docs/static/openapi.yaml` (already done)
196+
- OpenApiSpex infrastructure in place
197+
- Both can coexist
198+
199+
### Phase 2: Incremental Migration
200+
201+
1. Start with one controller (e.g., ProjectController)
202+
2. Add annotations
203+
3. Generate spec and verify
204+
4. Compare with manual spec
205+
5. Move to next controller
206+
207+
### Phase 3: Full Migration
208+
209+
- All controllers annotated
210+
- Remove manual spec
211+
- Use `mix api.docs` in CI/CD
212+
213+
## Workflow
214+
215+
### Development
216+
217+
```bash
218+
# 1. Modify controller annotations
219+
vim lib/lightning_web/controllers/api/project_controller.ex
220+
221+
# 2. Regenerate spec and docs
222+
mix api.docs
223+
224+
# 3. Review generated spec
225+
cat docs/static/openapi.yaml
226+
227+
# 4. Test documentation locally
228+
cd docs && npm start
229+
```
230+
231+
### CI/CD Integration
232+
233+
```yaml
234+
# .github/workflows/docs.yml
235+
- name: Generate API docs
236+
run: |
237+
mix deps.get
238+
mix api.docs
239+
240+
- name: Deploy docs
241+
run: |
242+
cd docs
243+
npm install
244+
npm run build
245+
```
246+
247+
## Benefits
248+
249+
1. **Single Source of Truth**: API docs live in code
250+
2. **Type Safety**: Request/response validation
251+
3. **Always Up-to-Date**: Docs regenerate from code
252+
4. **Less Maintenance**: No manual spec updates
253+
5. **Better DX**: IDE autocomplete for schemas
254+
255+
## Troubleshooting
256+
257+
### Spec Generation Fails
258+
259+
```bash
260+
# Ensure deps are installed
261+
mix deps.get
262+
263+
# Clear build artifacts
264+
mix clean
265+
266+
# Regenerate
267+
mix api.docs
268+
```
269+
270+
### Schema Not Found
271+
272+
Ensure schema modules are compiled before spec generation:
273+
274+
```bash
275+
mix compile
276+
mix api.docs
277+
```
278+
279+
### Route Not Recognized
280+
281+
Check that routes are properly defined in `router.ex` and the controller is
282+
using the correct path.
283+
284+
## Resources
285+
286+
- [OpenApiSpex Documentation](https://hexdocs.pm/open_api_spex)
287+
- [OpenAPI 3.0 Specification](https://swagger.io/specification/)
288+
- [Docusaurus OpenAPI Plugin](https://github.com/PaloAltoNetworks/docusaurus-openapi-docs)
289+
290+
## Next Steps
291+
292+
1. **Try It Out**: Annotate `ProjectController` with specs
293+
2. **Generate**: Run `mix api.docs`
294+
3. **Review**: Check the generated `docs/static/openapi.yaml`
295+
4. **Test**: Start docs server with `cd docs && npm start`
296+
5. **Iterate**: Refine annotations and repeat
297+
298+
## Getting Help
299+
300+
- Check example in `project_controller_spec.ex`
301+
- Review `schemas.ex` for schema patterns
302+
- See OpenApiSpex docs for advanced usage

docs/.gitignore

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
# Dependencies
2+
/node_modules
3+
4+
# Production
5+
/build
6+
7+
# Generated files
8+
.docusaurus
9+
.cache-loader
10+
11+
# Misc
12+
.DS_Store
13+
.env.local
14+
.env.development.local
15+
.env.test.local
16+
.env.production.local
17+
18+
npm-debug.log*
19+
yarn-debug.log*
20+
yarn-error.log*

0 commit comments

Comments
 (0)