This commit is contained in:
@@ -303,7 +303,7 @@
|
||||
<li class="md-nav__item">
|
||||
<a href="#openapi_first--quick-start" class="md-nav__link">
|
||||
<span class="md-ellipsis">
|
||||
Quick start
|
||||
Quick Start
|
||||
</span>
|
||||
</a>
|
||||
|
||||
@@ -693,7 +693,7 @@
|
||||
<li class="md-nav__item">
|
||||
<a href="#openapi_first--quick-start" class="md-nav__link">
|
||||
<span class="md-ellipsis">
|
||||
Quick start
|
||||
Quick Start
|
||||
</span>
|
||||
</a>
|
||||
|
||||
@@ -762,71 +762,70 @@
|
||||
|
||||
<div class="doc doc-contents first">
|
||||
|
||||
<p>FastAPI OpenAPI First — strict OpenAPI-first application bootstrap for FastAPI.</p>
|
||||
<hr />
|
||||
<h4 id="openapi_first--summary">Summary</h4>
|
||||
<h3 id="openapi_first--summary">Summary</h3>
|
||||
<p>FastAPI OpenAPI First — strict OpenAPI-first application bootstrap for FastAPI.</p>
|
||||
<p>FastAPI OpenAPI First is a <strong>contract-first infrastructure library</strong> that
|
||||
enforces OpenAPI as the single source of truth for FastAPI services.</p>
|
||||
<p>The library removes decorator-driven routing and replaces it with
|
||||
deterministic, spec-driven application assembly. Every HTTP route,
|
||||
method, and operation is defined in OpenAPI first and bound to Python
|
||||
handlers explicitly via operationId.</p>
|
||||
handlers explicitly via <code>operationId</code>.</p>
|
||||
<hr />
|
||||
<h4 id="openapi_first--installation">Installation</h4>
|
||||
<h3 id="openapi_first--installation">Installation</h3>
|
||||
<p>Install using pip:</p>
|
||||
<div class="language-text highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span></span><span class="normal">1</span></pre></div></td><td class="code"><div><pre><span></span><code>pip install openapi-first
|
||||
</code></pre></div></td></tr></table></div>
|
||||
<div class="language-bash highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span></span><span class="normal"><a href="#__codelineno-0-1">1</a></span></pre></div></td><td class="code"><div><pre><span></span><code><span id="__span-0-1"><a id="__codelineno-0-1" name="__codelineno-0-1"></a>pip<span class="w"> </span>install<span class="w"> </span>openapi-first
|
||||
</span></code></pre></div></td></tr></table></div>
|
||||
<p>Or with Poetry:</p>
|
||||
<div class="language-text highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span></span><span class="normal">1</span></pre></div></td><td class="code"><div><pre><span></span><code>poetry add openapi-first
|
||||
</code></pre></div></td></tr></table></div>
|
||||
<div class="language-bash highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span></span><span class="normal"><a href="#__codelineno-1-1">1</a></span></pre></div></td><td class="code"><div><pre><span></span><code><span id="__span-1-1"><a id="__codelineno-1-1" name="__codelineno-1-1"></a>poetry<span class="w"> </span>add<span class="w"> </span>openapi-first
|
||||
</span></code></pre></div></td></tr></table></div>
|
||||
<hr />
|
||||
<h4 id="openapi_first--quick-start">Quick start</h4>
|
||||
<h3 id="openapi_first--quick-start">Quick Start</h3>
|
||||
<p>Minimal OpenAPI-first FastAPI application:</p>
|
||||
<div class="language-text highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span></span><span class="normal">1</span>
|
||||
<span class="normal">2</span>
|
||||
<span class="normal">3</span>
|
||||
<span class="normal">4</span>
|
||||
<span class="normal">5</span>
|
||||
<span class="normal">6</span>
|
||||
<span class="normal">7</span>
|
||||
<span class="normal">8</span>
|
||||
<span class="normal">9</span></pre></div></td><td class="code"><div><pre><span></span><code>from openapi_first import app
|
||||
import my_service.routes as routes
|
||||
|
||||
api = app.OpenAPIFirstApp(
|
||||
openapi_path="openapi.yaml",
|
||||
routes_module=routes,
|
||||
title="My Service",
|
||||
version="1.0.0",
|
||||
)
|
||||
</code></pre></div></td></tr></table></div>
|
||||
<div class="language-python highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span></span><span class="normal"><a href="#__codelineno-2-1">1</a></span>
|
||||
<span class="normal"><a href="#__codelineno-2-2">2</a></span>
|
||||
<span class="normal"><a href="#__codelineno-2-3">3</a></span>
|
||||
<span class="normal"><a href="#__codelineno-2-4">4</a></span>
|
||||
<span class="normal"><a href="#__codelineno-2-5">5</a></span>
|
||||
<span class="normal"><a href="#__codelineno-2-6">6</a></span>
|
||||
<span class="normal"><a href="#__codelineno-2-7">7</a></span>
|
||||
<span class="normal"><a href="#__codelineno-2-8">8</a></span>
|
||||
<span class="normal"><a href="#__codelineno-2-9">9</a></span></pre></div></td><td class="code"><div><pre><span></span><code><span id="__span-2-1"><a id="__codelineno-2-1" name="__codelineno-2-1"></a><span class="kn">from</span><span class="w"> </span><span class="nn">openapi_first</span><span class="w"> </span><span class="kn">import</span> <span class="n">app</span>
|
||||
</span><span id="__span-2-2"><a id="__codelineno-2-2" name="__codelineno-2-2"></a><span class="kn">import</span><span class="w"> </span><span class="nn">my_service.routes</span><span class="w"> </span><span class="k">as</span><span class="w"> </span><span class="nn">routes</span>
|
||||
</span><span id="__span-2-3"><a id="__codelineno-2-3" name="__codelineno-2-3"></a>
|
||||
</span><span id="__span-2-4"><a id="__codelineno-2-4" name="__codelineno-2-4"></a><span class="n">api</span> <span class="o">=</span> <span class="n">app</span><span class="o">.</span><span class="n">OpenAPIFirstApp</span><span class="p">(</span>
|
||||
</span><span id="__span-2-5"><a id="__codelineno-2-5" name="__codelineno-2-5"></a> <span class="n">openapi_path</span><span class="o">=</span><span class="s2">"openapi.yaml"</span><span class="p">,</span>
|
||||
</span><span id="__span-2-6"><a id="__codelineno-2-6" name="__codelineno-2-6"></a> <span class="n">routes_module</span><span class="o">=</span><span class="n">routes</span><span class="p">,</span>
|
||||
</span><span id="__span-2-7"><a id="__codelineno-2-7" name="__codelineno-2-7"></a> <span class="n">title</span><span class="o">=</span><span class="s2">"My Service"</span><span class="p">,</span>
|
||||
</span><span id="__span-2-8"><a id="__codelineno-2-8" name="__codelineno-2-8"></a> <span class="n">version</span><span class="o">=</span><span class="s2">"1.0.0"</span><span class="p">,</span>
|
||||
</span><span id="__span-2-9"><a id="__codelineno-2-9" name="__codelineno-2-9"></a><span class="p">)</span>
|
||||
</span></code></pre></div></td></tr></table></div>
|
||||
<p>OperationId-driven HTTP client:</p>
|
||||
<div class="language-text highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span></span><span class="normal">1</span>
|
||||
<span class="normal">2</span>
|
||||
<span class="normal">3</span>
|
||||
<span class="normal">4</span>
|
||||
<span class="normal">5</span>
|
||||
<span class="normal">6</span>
|
||||
<span class="normal">7</span></pre></div></td><td class="code"><div><pre><span></span><code>from openapi_first.loader import load_openapi
|
||||
from openapi_first.client import OpenAPIClient
|
||||
|
||||
spec = load_openapi("openapi.yaml")
|
||||
client = OpenAPIClient(spec)
|
||||
|
||||
response = client.get_health()
|
||||
</code></pre></div></td></tr></table></div>
|
||||
<div class="language-python highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span></span><span class="normal"><a href="#__codelineno-3-1">1</a></span>
|
||||
<span class="normal"><a href="#__codelineno-3-2">2</a></span>
|
||||
<span class="normal"><a href="#__codelineno-3-3">3</a></span>
|
||||
<span class="normal"><a href="#__codelineno-3-4">4</a></span>
|
||||
<span class="normal"><a href="#__codelineno-3-5">5</a></span>
|
||||
<span class="normal"><a href="#__codelineno-3-6">6</a></span>
|
||||
<span class="normal"><a href="#__codelineno-3-7">7</a></span></pre></div></td><td class="code"><div><pre><span></span><code><span id="__span-3-1"><a id="__codelineno-3-1" name="__codelineno-3-1"></a><span class="kn">from</span><span class="w"> </span><span class="nn">openapi_first.loader</span><span class="w"> </span><span class="kn">import</span> <span class="n">load_openapi</span>
|
||||
</span><span id="__span-3-2"><a id="__codelineno-3-2" name="__codelineno-3-2"></a><span class="kn">from</span><span class="w"> </span><span class="nn">openapi_first.client</span><span class="w"> </span><span class="kn">import</span> <span class="n">OpenAPIClient</span>
|
||||
</span><span id="__span-3-3"><a id="__codelineno-3-3" name="__codelineno-3-3"></a>
|
||||
</span><span id="__span-3-4"><a id="__codelineno-3-4" name="__codelineno-3-4"></a><span class="n">spec</span> <span class="o">=</span> <span class="n">load_openapi</span><span class="p">(</span><span class="s2">"openapi.yaml"</span><span class="p">)</span>
|
||||
</span><span id="__span-3-5"><a id="__codelineno-3-5" name="__codelineno-3-5"></a><span class="n">client</span> <span class="o">=</span> <span class="n">OpenAPIClient</span><span class="p">(</span><span class="n">spec</span><span class="p">)</span>
|
||||
</span><span id="__span-3-6"><a id="__codelineno-3-6" name="__codelineno-3-6"></a>
|
||||
</span><span id="__span-3-7"><a id="__codelineno-3-7" name="__codelineno-3-7"></a><span class="n">response</span> <span class="o">=</span> <span class="n">client</span><span class="o">.</span><span class="n">get_health</span><span class="p">()</span>
|
||||
</span></code></pre></div></td></tr></table></div>
|
||||
<hr />
|
||||
<h4 id="openapi_first--architecture">Architecture</h4>
|
||||
<h3 id="openapi_first--architecture">Architecture</h3>
|
||||
<p>The library is structured around four core responsibilities:</p>
|
||||
<ul>
|
||||
<li><strong>loader</strong>: Load and validate OpenAPI 3.x specifications (JSON/YAML)</li>
|
||||
<li><strong>binder</strong>: Bind OpenAPI operations to FastAPI routes via operationId</li>
|
||||
<li><strong>app</strong>: OpenAPI-first FastAPI application bootstrap</li>
|
||||
<li><strong>client</strong>: OpenAPI-first HTTP client driven by the same specification</li>
|
||||
<li><strong>errors</strong>: Explicit error hierarchy for contract violations</li>
|
||||
<li><code>loader</code>: Load and validate OpenAPI 3.x specifications (JSON/YAML).</li>
|
||||
<li><code>binder</code>: Bind OpenAPI operations to FastAPI routes via <code>operationId</code>.</li>
|
||||
<li><code>app</code>: OpenAPI-first FastAPI application bootstrap.</li>
|
||||
<li><code>client</code>: OpenAPI-first HTTP client driven by the same specification.</li>
|
||||
<li><code>errors</code>: Explicit error hierarchy for contract violations.</li>
|
||||
</ul>
|
||||
<hr />
|
||||
<h4 id="openapi_first--public-api">Public API</h4>
|
||||
<h3 id="openapi_first--public-api">Public API</h3>
|
||||
<p>The supported public API consists of the following top-level modules:</p>
|
||||
<ul>
|
||||
<li><code>openapi_first.app</code></li>
|
||||
@@ -836,14 +835,14 @@ response = client.get_health()
|
||||
<li><code>openapi_first.errors</code></li>
|
||||
</ul>
|
||||
<hr />
|
||||
<h4 id="openapi_first--design-guarantees">Design Guarantees</h4>
|
||||
<h3 id="openapi_first--design-guarantees">Design Guarantees</h3>
|
||||
<ul>
|
||||
<li>OpenAPI is the single source of truth</li>
|
||||
<li>No undocumented routes can exist</li>
|
||||
<li>No OpenAPI operation can exist without a handler or client callable</li>
|
||||
<li>All contract violations fail at application startup or client creation</li>
|
||||
<li>No hidden FastAPI magic or implicit behavior</li>
|
||||
<li>Deterministic, testable application assembly</li>
|
||||
<li>OpenAPI is the single source of truth.</li>
|
||||
<li>No undocumented routes can exist.</li>
|
||||
<li>No OpenAPI operation can exist without a handler or client callable.</li>
|
||||
<li>All contract violations fail at application startup or client creation.</li>
|
||||
<li>No hidden FastAPI magic or implicit behavior.</li>
|
||||
<li>Deterministic, testable application assembly.</li>
|
||||
</ul>
|
||||
<hr />
|
||||
|
||||
@@ -865,9 +864,7 @@ response = client.get_health()
|
||||
|
||||
</div>
|
||||
|
||||
</div><ul>
|
||||
<li><a href="openapi_first/">Openapi First</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user