feat(openapi): add Scalar docs UI route generation#175
Conversation
When `OpenAPIConfig.ui` is set to a `Scalar(...)` instance and the output is a route, the build generator emits `src/_openapi_docs.dart` and injects a GET route at the configured path (default `/_docs`) that serves a Scalar API reference page pointing at the generated `openapi.json`. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
✅ Deploy Preview for dart-spry ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
📝 WalkthroughWalkthroughAdds optional Scalar-based OpenAPI UI support to the generator: config accepts Changes
Sequence Diagram(s)sequenceDiagram
participant Builder as Build Generator
participant Config as OpenAPI Config
participant FileGen as File Generator
participant AppModule as App Module
participant Client as HTTP Client
Builder->>Config: Read OpenAPIConfig (document, output, ui)
Config-->>Builder: Return config + Scalar settings
Builder->>Builder: Evaluate hasDocsUi (ui != null && output.type == 'route')
alt UI Enabled
Builder->>FileGen: _generateDocsFile(openapi) -> create src/_openapi_docs.dart (HTML + Scalar script)
FileGen-->>Builder: docs file created
Builder->>AppModule: add import '_openapi_docs.dart' as $docs and register GET ui.route -> $docs.handler
AppModule-->>Builder: route registered
else UI Disabled
Builder->>Builder: Skip docs generation and route injection
end
rect rgba(100, 150, 255, 0.5)
Client->>AppModule: GET /_docs (or configured route)
AppModule->>FileGen: dispatch to $docs.handler
FileGen-->>Client: Response handler returns HTML embedding Scalar viewer (data-url, data-theme, data-layout)
end
Estimated Code Review Effort🎯 4 (Complex) | ⏱️ ~45 minutes Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
There was a problem hiding this comment.
Actionable comments posted: 2
🧹 Nitpick comments (1)
test/generator_test.dart (1)
881-1002: Solid test coverage for the OpenAPI UI feature.The tests cover key configuration scenarios:
- Title override
- Theme and layout attributes
- Custom route path
- Custom output path
- Conditional skipping (null ui, local output)
One suggestion for future coverage: consider adding a test for edge cases like special characters in the route path or title (e.g.,
$or') to ensure the escaping in_dartStrand_escapeworks correctly under all conditions.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@test/generator_test.dart` around lines 881 - 1002, Add a new unit test in generator_test.dart that verifies OpenAPI UI handles special characters by exercising the string-escaping helpers: call scan/generate with a BuildConfig whose OpenAPIConfig.ui Scalar has a title containing characters like $ and ' and a route containing those characters as well, then assert the produced src/_openapi_docs.dart and src/app.dart contents include the correctly escaped title and route (targeting the functions that produce those strings, _dartStr and _escape, by checking the generated HTML title and data-url and the app route string). Ensure the test covers both docs present (when output is route) and that the singleWhere lookups use the same file paths as existing tests.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@lib/src/builder/generator.dart`:
- Around line 198-214: The generated HTML uses the variable title (from ui.title
/ openapi.document.info.title) which is later embedded into a
triple-single-quoted Dart string (the "'''$html'''" emission) and any occurrence
of ''' in the title will break the generated Dart code; fix by sanitizing the
title before writing HTML—either escape triple-single-quotes (replace "'''" with
"\\'\\'\\'") or emit the title using a safe Dart string literal (e.g., via
jsonEncode or an equivalent string-escaping helper) so that the code produced by
generator.dart (the StringBuffer/html emission and the place that writes
"'''$html'''") cannot be broken by user-provided titles.
- Around line 187-237: The spec URL for the docs file is built unconditionally
as '/${openapi.output.path}' which can produce a double slash when
openapi.output.path already starts with '/', so update _generateDocsFile to
normalize OpenAPIConfig.output.path before building specUrl: trim any leading
slashes from openapi.output.path (or ensure exactly one leading slash) when
constructing specUrl (used in variable specUrl and passed into _dartStr),
leaving _dartStr unchanged; this ensures data-url contains a single leading
slash regardless of how output.path was provided.
---
Nitpick comments:
In `@test/generator_test.dart`:
- Around line 881-1002: Add a new unit test in generator_test.dart that verifies
OpenAPI UI handles special characters by exercising the string-escaping helpers:
call scan/generate with a BuildConfig whose OpenAPIConfig.ui Scalar has a title
containing characters like $ and ' and a route containing those characters as
well, then assert the produced src/_openapi_docs.dart and src/app.dart contents
include the correctly escaped title and route (targeting the functions that
produce those strings, _dartStr and _escape, by checking the generated HTML
title and data-url and the app route string). Ensure the test covers both docs
present (when output is route) and that the singleWhere lookups use the same
file paths as existing tests.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 7718df52-6128-4a5e-95dc-87cc8ff7cd0b
📒 Files selected for processing (4)
example/openapi/spry.config.dartlib/src/builder/generator.dartlib/src/openapi/config.darttest/generator_test.dart
A title containing ''' would prematurely terminate the triple-quoted string literal in the generated _openapi_docs.dart. Extend _dartStr to replace ''' with \'\'\' before embedding any user-provided value. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
When OpenAPIOutput.route('/openapi.json') is passed with a leading
slash, prepending '/' produced '//openapi.json'. Strip any leading
slashes from output.path before constructing the spec URL.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…alization Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@lib/src/builder/generator.dart`:
- Around line 198-214: The title string is written into the HTML head unescaped
(see the StringBuffer named html and the variable title used in the writeln call
for '<title>$title</title>'); add HTML-escaping of special characters before
interpolation to prevent broken pages or script injection by creating/using a
helper (e.g., escapeHtml or htmlEscape) that replaces &, <, >, " (and optionally
') with entities, and call that helper where title is injected into the
'<title>…</title>' writeln (and any other places where title may be embedded,
such as scriptAttrs) so raw metacharacters are never written directly to the
output.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 26cd476a-52dc-4c8e-9089-2d0d457fde2f
📒 Files selected for processing (4)
lib/src/builder/generator.dartsites/spry.medz.dev/config.mdsites/spry.medz.dev/guide/openapi.mdtest/generator_test.dart
✅ Files skipped from review due to trivial changes (1)
- test/generator_test.dart
Resolves #172
Summary by CodeRabbit
New Features
Tests