From 1831bd39acfcf3a90415731ee945e86a19906c3b Mon Sep 17 00:00:00 2001 From: Dag Brattli Date: Tue, 16 Dec 2025 23:24:22 +0100 Subject: [PATCH] feat: FastAPI async handlers --- .config/dotnet-tools.json | 2 +- examples/fastapi/App.fs | 57 +++++++++++++++++++++++---------------- 2 files changed, 35 insertions(+), 24 deletions(-) diff --git a/.config/dotnet-tools.json b/.config/dotnet-tools.json index 9c39f94..f4f80c3 100644 --- a/.config/dotnet-tools.json +++ b/.config/dotnet-tools.json @@ -10,7 +10,7 @@ "rollForward": false }, "fable": { - "version": "5.0.0-alpha.20", + "version": "5.0.0-alpha.21", "commands": [ "fable" ], diff --git a/examples/fastapi/App.fs b/examples/fastapi/App.fs index a47b9ec..f0feb6e 100644 --- a/examples/fastapi/App.fs +++ b/examples/fastapi/App.fs @@ -2,6 +2,7 @@ /// Demonstrates how to use Fable.Python.FastAPI with decorator attributes module App +open System.Threading.Tasks open Fable.Core open Fable.Python.FastAPI open Fable.Python.Pydantic @@ -36,36 +37,42 @@ items.Add(item2) type API() = /// Root endpoint - welcome message [] - static member root() : obj = - {| message = "Welcome to Fable.Python + FastAPI!" + static member root() : Task = task { + return {| + message = "Welcome to Fable.Python + FastAPI!" version = "1.0.0" |} + } /// Health check endpoint [] - static member health() : obj = - {| status = "healthy" + static member health() : Task = task { + return {| + status = "healthy" users_count = users.Count items_count = items.Count |} + } /// Get all users [] - static member get_users() : ResizeArray = - users + static member get_users() : Task> = task { + return users + } /// Get a user by ID [] - static member get_user(user_id: int) : obj = + static member get_user(user_id: int) : Task = task { match users |> Seq.tryFind (fun u -> u.Id = user_id) with - | Some user -> user :> obj - | None -> {| error = "User not found" |} - + | Some user -> return user :> obj + | None -> return {| error = "User not found" |} + } /// Create a new user [] - static member create_user(request: CreateUserRequest) : obj = + static member create_user(request: CreateUserRequest) = task { let newId = if users.Count = 0 then 1 else (users |> Seq.map (fun u -> u.Id) |> Seq.max) + 1 let newUser = User(Id = newId, Name = request.Name, Email = request.Email) users.Add(newUser) - {| status = "created"; user = newUser |} + return {| status = "created"; user = newUser |} + } /// Get all items [] @@ -74,34 +81,38 @@ type API() = /// Get an item by ID [] - static member get_item(item_id: int) : obj = + static member get_item(item_id: int) : Task = task { match items |> Seq.tryFind (fun i -> i.Id = item_id) with - | Some item -> item :> obj - | None -> {| error = "Item not found" |} + | Some item -> return item :> obj + | None -> return {| error = "Item not found" |} + } /// Create a new item [] - static member create_item(request: CreateItemRequest) : obj = + static member create_item(request: CreateItemRequest) : Task = task { let newId = if items.Count = 0 then 1 else (items |> Seq.map (fun i -> i.Id) |> Seq.max) + 1 let newItem = Item(Id = newId, Name = request.Name, Price = request.Price, InStock = request.InStock) items.Add(newItem) - {| status = "created"; item = newItem |} + return {| status = "created"; item = newItem |} + } /// Update an item [] - static member update_item(item_id: int, request: CreateItemRequest) : obj = + static member update_item(item_id: int, request: CreateItemRequest) : Task = task { match items |> Seq.tryFindIndex (fun i -> i.Id = item_id) with | Some index -> let updatedItem = Item(Id = item_id, Name = request.Name, Price = request.Price, InStock = request.InStock) items.[index] <- updatedItem - {| status = "updated"; item = updatedItem |} - | None -> {| error = "Item not found" |} + return {| status = "updated"; item = updatedItem |} + | None -> return {| error = "Item not found" |} + } /// Delete an item [] - static member delete_item(item_id: int) : obj = + static member delete_item(item_id: int) : Task = task { match items |> Seq.tryFindIndex (fun i -> i.Id = item_id) with | Some index -> items.RemoveAt(index) - {| status = "deleted"; deleted_id = nativeint item_id |} - | None -> {| error = "Item not found" |} + return {| status = "deleted"; deleted_id = nativeint item_id |} + | None -> return {| error = "Item not found" |} + } \ No newline at end of file