Created
March 13, 2018 14:14
-
-
Save ulve/c5a4f619888f9c2bb20ccce9e038b90d to your computer and use it in GitHub Desktop.
Using hopac as a api gateway in f#
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#r "packages/Hopac/lib/net45/Hopac.dll" | |
#r "packages/Hopac/lib/net45/Hopac.Core.dll" | |
#r "packages/Hopac/lib/net45/Hopac.Platform.dll" | |
#r "packages/FSharp.Data/lib/net45/FSharp.Data.dll" | |
#r "packages/Http.fs/lib/net461/HttpFs.dll" | |
#r "packages/System.Net.Http/lib/net46/System.Net.Http.dll" | |
open Hopac | |
open Hopac.Infixes | |
open FSharp.Data | |
open HttpFs.Client | |
type UserTypeProvider = JsonProvider<"https://api.github.com/users/ulve"> | |
type User = UserTypeProvider.Root | |
type ReposTypeProvider = JsonProvider<"repos.json"> | |
type Repo = ReposTypeProvider.Root | |
type RepoDto = { | |
Name : string | |
StargazersCount : int | |
Languages : string [] | |
} | |
type UserDto = { | |
Name : string | |
AvatarUrl : string | |
TopThreeRepos : RepoDto [] | |
} | |
let httpGet url = | |
Request.createUrl Get url | |
|> Request.setHeader (UserAgent "FsHopac") | |
|> getResponse | |
|> Job.bind Response.readBodyAsString | |
let basePath = "https://api.github.com" | |
let userReposUrl = sprintf "%s/users/%s/repos?per_page=100" basePath | |
let languagesUrl userName repoName = | |
sprintf "%s/repos/%s/%s/languages" basePath userName repoName | |
let userUrl = sprintf "%s/users/%s" basePath | |
let getUser username : Job<User> = | |
userUrl username | |
|> httpGet | |
|> Job.map UserTypeProvider.Parse | |
let topThreeUserRepos (repos : Repo []) = | |
let takeCount = | |
let reposCount = Array.length repos | |
if reposCount > 3 then 3 else reposCount | |
repos | |
|> Array.filter (fun repo -> not repo.Fork) | |
|> Array.sortByDescending (fun repo -> repo.StargazersCount) | |
|> Array.take takeCount | |
let getTopThreeUserRepos username : Job<Repo []> = | |
userReposUrl username | |
|> httpGet | |
|> Job.map ReposTypeProvider.Parse | |
|> Job.map topThreeUserRepos | |
let parseLanguagesJson languagesJson = | |
languagesJson | |
|> JsonValue.Parse | |
|> JsonExtensions.Properties | |
|> Array.map fst | |
let getUserRepoLanguages username repoName = | |
languagesUrl username repoName | |
|> httpGet | |
|> Job.map parseLanguagesJson | |
let repoDto (repo : Repo) languages = { | |
Name = repo.Name | |
StargazersCount = repo.StargazersCount | |
Languages = languages | |
} | |
let getRepoDto username (repo : Repo) = | |
getUserRepoLanguages username repo.Name | |
|> Job.map (repoDto repo) | |
let getUserDto username = job { | |
let! user, repos = | |
getUser username <*> getTopThreeUserRepos username | |
let! repoDtos = | |
repos | |
|> Array.map (getRepoDto username) | |
|> Job.conCollect | |
return { | |
Name = user.Name | |
AvatarUrl = user.AvatarUrl | |
TopThreeRepos = repoDtos.ToArray() | |
} | |
} | |
getUserDto "ulve" |> run |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment