
Api.pudu
Pudu103 lines5.1 KB
1/** @Test.Support.Placeholder.Api.Module — a typed client of the placeholder service over named clients */2module Support.Placeholder.Api34import Std.Http as Http5import Std.Json as Json6import Std.Option as Option7import Std.Url as Url8import PuduLangHttpClient.Client as Client9import PuduLangHttpClient.Client.Json as JsonClient10import PuduLangHttpClient.Endpoint as Endpoint11import PuduLangHttpClient as HttpClient12import PuduLangHttpClient.Response as Response1314/** @Test.Support.Placeholder.Api.Post — a post */15export type Post = { userId: Int, id: Int, title: Str, body: Str } derives Json.Encode, Json.Decode1617/** @Test.Support.Placeholder.Api.Comment — a comment on a post */18export type Comment = { postId: Int, id: Int, name: Str, email: Str, body: Str } derives Json.Encode, Json.Decode1920/** @Test.Support.Placeholder.Api.Album — an album */21export type Album = { userId: Int, id: Int, title: Str } derives Json.Encode, Json.Decode2223/** @Test.Support.Placeholder.Api.Photo — a photo in an album */24export type Photo = { albumId: Int, id: Int, title: Str, url: Str, thumbnailUrl: Str } derives Json.Encode, Json.Decode2526/** @Test.Support.Placeholder.Api.Todo — a todo */27export type Todo = { userId: Int, id: Int, title: Str, completed: Bool } derives Json.Encode, Json.Decode2829/** @Test.Support.Placeholder.Api.Geo — a position */30export type Geo = { lat: Str, lng: Str } derives Json.Encode, Json.Decode3132/** @Test.Support.Placeholder.Api.Address — a postal address */33export type Address = { street: Str, suite: Str, city: Str, zipcode: Str, geo: Geo } derives Json.Encode, Json.Decode3435/** @Test.Support.Placeholder.Api.Company — an employer */36export type Company = { name: Str, catchPhrase: Str, bs: Str } derives Json.Encode, Json.Decode3738/** @Test.Support.Placeholder.Api.User — a user */39export type User = { id: Int, name: Str, username: Str, email: Str, address: Address, phone: Str, website: Str, company: Company } derives Json.Encode, Json.Decode4041/** @Test.Support.Placeholder.Api.Api — the typed client: one named client of the service */42export type Api = { client: Client.Client }4344/** @Test.Support.Placeholder.Api.Page — one page of a listing and how many records matched in all */45export type Page[T] = { items: Array[T], total: Int }464748const COLLECTION: Endpoint.Endpoint = Endpoint.Endpoint{method: Http.Post, template: ":resource"}495051const MEMBER: Endpoint.Endpoint = Endpoint.Endpoint{method: Http.Get, template: ":resource/:id"}525354const NESTED: Endpoint.Endpoint = Endpoint.Endpoint{method: Http.Get, template: ":parent/:id/:child"}555657export fn list[T: Json.Decode](api: &Api, resource: Str, query: &Array[(Str, Str)]) -> HttpClient.Outcome[Array[T]] {58 JsonClient.getFromJson(&api.client, resource + queryOf(query))59}606162export fn page[T: Json.Decode](api: &Api, resource: Str, query: &Array[(Str, Str)]) -> HttpClient.Outcome[Page[T]] {63 let response = Response.ensureSuccess(Client.get(&api.client, resource + queryOf(query)) ?) ?64 let items: Array[T] = Response.readAs(&response) ?65 Ok(Page{items: items, total: Option.unwrapOr(Option.andThen(Response.header(&response, "x-total-count"), |text: Str| text.toInt()), 0)})66}676869export fn find[T: Json.Decode](api: &Api, resource: Str, id: Int) -> HttpClient.Outcome[T] {70 Endpoint.call(&api.client, &MEMBER, &[("resource", resource), ("id", show(id))])71}727374export fn children[T: Json.Decode](api: &Api, parent: Str, id: Int, child: Str) -> HttpClient.Outcome[Array[T]] {75 Endpoint.call(&api.client, &NESTED, &[("parent", parent), ("id", show(id)), ("child", child)])76}777879export fn create[T: Json.Encode + Json.Decode](api: &Api, resource: Str, record: &T) -> HttpClient.Outcome[T] {80 Endpoint.callWith(&api.client, &COLLECTION, &[("resource", resource)], record)81}828384export fn replace[T: Json.Encode + Json.Decode](api: &Api, resource: Str, id: Int, record: &T) -> HttpClient.Outcome[T] {85 Endpoint.callWith(&api.client, &Endpoint.Endpoint{..MEMBER, method: Http.Put}, &[("resource", resource), ("id", show(id))], record)86}878889export fn patch[T: Json.Decode](api: &Api, resource: Str, id: Int, fields: &Json.Json) -> HttpClient.Outcome[T] {90 Endpoint.callWith(&api.client, &Endpoint.Endpoint{..MEMBER, method: Http.Patch}, &[("resource", resource), ("id", show(id))], fields)91}929394export fn remove(api: &Api, resource: Str, id: Int) -> HttpClient.Outcome[Int] {95 let response = Response.ensureSuccess(Endpoint.send(&api.client, &Endpoint.Endpoint{..MEMBER, method: Http.Delete}, &[("resource", resource), ("id", show(id))]) ?) ?96 Ok(response.status.code)97}9899100fn queryOf(query: &Array[(Str, Str)]) -> Str {101 if query.isEmpty() { "" } else { "?" + Url.renderQuery(query) }102}103