Skip to content

Commit ad729ee

Browse files
authored
Regenerate API spec during docs build (#551)
1 parent bdda657 commit ad729ee

File tree

19 files changed

+1941
-979
lines changed

19 files changed

+1941
-979
lines changed

backend/api/exports.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
from api.security import require_write_token
2525
from api.storage_dependencies import get_storage_client
2626
from backend.services.storage import StorageClient, StoredObject
27-
from services.cnc_service import CNCService
27+
from backend.services.cnc_service import CNCService
2828

2929
logger = logging.getLogger(__name__)
3030
router = APIRouter(

backend/api/routes_orders.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010

1111
from api import models
1212
from api.db import get_db
13-
from api.schemas import Order, OrderCreate, OrderUpdate
13+
from api.schemas import Order, OrderCreate, OrderResponse, OrderUpdate
1414
from schemas.pricing import QuoteTotals
1515

1616
router = APIRouter(prefix="/api/orders", tags=["orders"])

backend/api/schemas.py

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,23 @@ class OrderCheckoutPreferences(BaseModel):
183183
cancel_url: AnyUrl | None = None
184184

185185

186+
class OrderPayment(BaseModel):
187+
provider: str | None = Field(default=None, max_length=50)
188+
reference: str | None = Field(default=None, max_length=128)
189+
status: str | None = Field(default=None, max_length=50)
190+
amount: float | None = None
191+
currency: str | None = Field(default=None, max_length=3)
192+
processed_at: datetime | None = None
193+
metadata: dict[str, Any] | None = Field(default=None, alias="metadata_", serialization_alias="metadata")
194+
195+
196+
class OrderDesign(BaseModel):
197+
step_url: AnyUrl | None = Field(default=None, alias="step_url")
198+
ifc_url: AnyUrl | None = Field(default=None, alias="ifc_url")
199+
preview_url: AnyUrl | None = Field(default=None, alias="preview_url")
200+
metadata: dict[str, Any] | None = Field(default=None, alias="metadata_", serialization_alias="metadata")
201+
202+
186203
class OrderBase(BaseModel):
187204
quote_id: str
188205
channel: OrderChannel = Field(default=OrderChannel.SHOPIFY)
@@ -249,12 +266,12 @@ class Order(OrderBase):
249266
status: str | None = None
250267
checkout_url: str | None = None
251268
shopify_order_id: str | None = None
252-
totals: OrderTotals
269+
totals: QuoteTotals
253270
created_at: datetime
254271
updated_at: datetime
255272

256273

257-
class OrderResponse(OrderSummary):
274+
class OrderResponse(Order):
258275
customer: OrderCustomer | None = None
259276
shipping_address: OrderAddress | None = None
260277
billing_address: OrderAddress | None = None
@@ -267,5 +284,13 @@ class OrderResponse(OrderSummary):
267284

268285

269286
class OrderListResponse(BaseModel):
270-
items: List[OrderSummary]
287+
items: List[Order]
271288
next_cursor: str | None = None
289+
290+
291+
# Ensure forward references between order schemas are resolved for OpenAPI generation
292+
Order.model_rebuild()
293+
OrderCreate.model_rebuild()
294+
OrderUpdate.model_rebuild()
295+
OrderResponse.model_rebuild()
296+
OrderListResponse.model_rebuild()

backend/models/order.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
import uuid
66
from datetime import datetime
77
from enum import Enum
8-
from typing import Any
8+
from typing import Any, TYPE_CHECKING
99

1010
from sqlalchemy import (
1111
Enum as SqlEnum,
Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,23 @@
11
#!/usr/bin/env python3
22
from __future__ import annotations
3+
34
import json
5+
from pathlib import Path
6+
import sys
7+
8+
# Ensure the project root is on the Python path when executing directly
9+
PROJECT_ROOT = Path(__file__).resolve().parents[2]
10+
BACKEND_ROOT = PROJECT_ROOT / "backend"
11+
12+
for path in (PROJECT_ROOT, BACKEND_ROOT):
13+
path_str = str(path)
14+
if path_str in sys.path:
15+
sys.path.remove(path_str)
16+
sys.path.insert(0, path_str)
17+
418
from api.main import app
519

620
if __name__ == "__main__":
721
# Use FastAPI's baked schema to include all route/reg metadata
822
spec = app.openapi()
9-
print(json.dumps(spec, indent=2))
23+
print(json.dumps(spec, indent=2))

build-docs.sh

Lines changed: 41 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -8,32 +8,59 @@ npm install
88
npm run build
99
cd ..
1010

11-
# Create template-ui directory in docs/assets
12-
echo "Setting up template UI in docs..."
13-
mkdir -p docs/assets/template-ui
14-
cp -r frontend/out/* docs/assets/template-ui/
11+
# Create template-ui directory in docs/assets if static export exists
12+
if [ -d frontend/out ]; then
13+
echo "Setting up template UI in docs..."
14+
mkdir -p docs/assets/template-ui
15+
cp -r frontend/out/* docs/assets/template-ui/
1516

16-
# Ensure images are available in multiple locations
17-
mkdir -p docs/assets/template-ui/images
18-
cp -r frontend/public/images/* docs/assets/template-ui/images/
17+
# Ensure images are available in multiple locations
18+
mkdir -p docs/assets/template-ui/images
19+
cp -r frontend/public/images/* docs/assets/template-ui/images/
1920

20-
# Also copy images to root of template-ui
21-
cp -r frontend/public/images/* docs/assets/template-ui/
21+
# Also copy images to root of template-ui
22+
cp -r frontend/public/images/* docs/assets/template-ui/
2223

23-
# And to assets directory
24-
mkdir -p docs/assets/images
25-
cp -r frontend/public/images/* docs/assets/images/
24+
# And to assets directory
25+
mkdir -p docs/assets/images
26+
cp -r frontend/public/images/* docs/assets/images/
27+
else
28+
echo "Warning: frontend/out not found; skipping template UI asset copy." >&2
29+
fi
2630

2731
# Build MkDocs site (which will include the template UI)
2832
echo "Building MkDocs site..."
33+
34+
# Ensure the backend virtualenv is activated before generating the OpenAPI spec
35+
if [ -d "backend/.venv" ]; then
36+
# shellcheck disable=SC1091
37+
source backend/.venv/bin/activate
38+
else
39+
echo "Error: backend virtualenv not found at backend/.venv" >&2
40+
exit 1
41+
fi
42+
43+
export HYGRAPH_WEBHOOK_SECRET="${HYGRAPH_WEBHOOK_SECRET:-dummy-hygraph-secret}"
44+
export SHOPIFY_STORE="${SHOPIFY_STORE:-dummy-store}"
45+
export SHOPIFY_TOKEN="${SHOPIFY_TOKEN:-dummy-shopify-token}"
46+
export SHOPIFY_WEBHOOK_SECRET="${SHOPIFY_WEBHOOK_SECRET:-dummy-shopify-webhook}"
47+
export PYTHONPATH="${PWD}${PYTHONPATH:+:$PYTHONPATH}"
48+
49+
python backend/scripts/generate_openapi.py > docs/API_SPEC.md
50+
51+
# Deactivate the virtualenv to avoid affecting subsequent commands
52+
deactivate
53+
2954
mkdocs build
3055

3156
# Copy images to multiple locations in the site directory
3257
mkdir -p site/assets/template-ui/images
3358
cp -r frontend/public/images/* site/assets/template-ui/images/
3459

35-
# Copy to root of template-ui
36-
cp -r frontend/public/images/* site/assets/template-ui/
60+
# Copy to root of template-ui if available
61+
if [ -d frontend/out ]; then
62+
cp -r frontend/public/images/* site/assets/template-ui/
63+
fi
3764

3865
# Copy to site/assets/images
3966
mkdir -p site/assets/images

0 commit comments

Comments
 (0)