[t-005] Create graphql.py — Strawberry schema setup + Query.appData #5

Open
opened 2026-07-05 08:30:59 +00:00 by david · 0 comments
Owner

Goal

Set up the Strawberry GraphQL schema with the Query.appData resolver.

References

Reference

  • DESIGN.md §4 GraphQL Schema (AppData, AppInfo, Navigation, Tab types)
  • AGENT.md §9 GraphQL Schema Rules

Implementation Steps

Implementation Steps

1. Create src/models/app_data.py

Define all AppData-related Strawberry GraphQL types:

# src/models/app_data.py
import strawberry
from typing import Optional

@strawberry.type
class AppInfo:
    name: str
    version: str
    min_supported_version: str = "1.0.0"
    supported_versions: str = "^1.0.0"
    force_update_url: Optional[str] = None

@strawberry.type
class Tab:
    id: str
    icon: str
    label: str
    link: str

@strawberry.type
class Navigation:
    primary_tab: Tab
    tabs: list[Tab]

@strawberry.type
class Defaults:
    model: str = "deepseek-v4-flash"

@strawberry.type
class FeatureFlags:
    voice_input: bool = True
    drag_drop: bool = True

@strawberry.type
class AppData:
    app: AppInfo
    navigation: Navigation
    defaults: Defaults
    features: FeatureFlags

2. Create src/models/graphql.py

Define the Query root with appData resolver:

# src/models/graphql.py
import strawberry
from src.models.app_data import AppData, AppInfo, Tab, Navigation, Defaults, FeatureFlags

def _build_default_navigation() -> Navigation:
    return Navigation(
        primary_tab=Tab(id="sessions", icon="message.fill", label="Chats", link="keryx://sessions"),
        tabs=[
            Tab(id="sessions", icon="message.fill", label="Chats", link="keryx://sessions"),
            Tab(id="workspace", icon="folder.fill", label="Files", link="keryx://workspace"),
            Tab(id="settings", icon="gearshape.fill", label="Settings", link="keryx://settings"),
        ],
    )

@strawberry.type
class Query:
    @strawberry.field
    def app_data(self) -> AppData:
        return AppData(
            app=AppInfo(name="Keryx", version="0.1.0"),
            navigation=_build_default_navigation(),
            defaults=Defaults(model="deepseek-v4-flash"),
            features=FeatureFlags(voice_input=True, drag_drop=True),
        )

schema = strawberry.Schema(query=Query)

Verification Gate

Verification Gate

Run:

cd /home/david/Projects/keryx-bff && uv run python -c "
from src.models.graphql import schema
result = schema.execute_sync('{ appData { app { name version } navigation { primaryTab { label link } } } }')
data = result.data['appData']
assert data['app']['name'] == 'Keryx'
assert data['navigation']['primaryTab']['label'] == 'Chats'
print('OK')"
# Expected output: OK

STOP Conditions

STOP Conditions

  • If the GraphQL query returns unexpected values, stop and fix the schema.

Depends on: t-004

## Goal Set up the Strawberry GraphQL schema with the `Query.appData` resolver. ## References ## Reference - DESIGN.md §4 GraphQL Schema (AppData, AppInfo, Navigation, Tab types) - AGENT.md §9 GraphQL Schema Rules ## Implementation Steps ## Implementation Steps ### 1. Create `src/models/app_data.py` Define all AppData-related Strawberry GraphQL types: ```python # src/models/app_data.py import strawberry from typing import Optional @strawberry.type class AppInfo: name: str version: str min_supported_version: str = "1.0.0" supported_versions: str = "^1.0.0" force_update_url: Optional[str] = None @strawberry.type class Tab: id: str icon: str label: str link: str @strawberry.type class Navigation: primary_tab: Tab tabs: list[Tab] @strawberry.type class Defaults: model: str = "deepseek-v4-flash" @strawberry.type class FeatureFlags: voice_input: bool = True drag_drop: bool = True @strawberry.type class AppData: app: AppInfo navigation: Navigation defaults: Defaults features: FeatureFlags ``` ### 2. Create `src/models/graphql.py` Define the Query root with appData resolver: ```python # src/models/graphql.py import strawberry from src.models.app_data import AppData, AppInfo, Tab, Navigation, Defaults, FeatureFlags def _build_default_navigation() -> Navigation: return Navigation( primary_tab=Tab(id="sessions", icon="message.fill", label="Chats", link="keryx://sessions"), tabs=[ Tab(id="sessions", icon="message.fill", label="Chats", link="keryx://sessions"), Tab(id="workspace", icon="folder.fill", label="Files", link="keryx://workspace"), Tab(id="settings", icon="gearshape.fill", label="Settings", link="keryx://settings"), ], ) @strawberry.type class Query: @strawberry.field def app_data(self) -> AppData: return AppData( app=AppInfo(name="Keryx", version="0.1.0"), navigation=_build_default_navigation(), defaults=Defaults(model="deepseek-v4-flash"), features=FeatureFlags(voice_input=True, drag_drop=True), ) schema = strawberry.Schema(query=Query) ``` ## Verification Gate ## Verification Gate Run: ```bash cd /home/david/Projects/keryx-bff && uv run python -c " from src.models.graphql import schema result = schema.execute_sync('{ appData { app { name version } navigation { primaryTab { label link } } } }') data = result.data['appData'] assert data['app']['name'] == 'Keryx' assert data['navigation']['primaryTab']['label'] == 'Chats' print('OK')" # Expected output: OK ``` ## STOP Conditions ## STOP Conditions - If the GraphQL query returns unexpected values, stop and fix the schema. Depends on: t-004
Sign in to join this conversation.
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: david/keryx-bff#5
No description provided.