Skip to content

Instantly share code, notes, and snippets.

@ulve
Created March 13, 2018 14:14
Show Gist options
  • Save ulve/c5a4f619888f9c2bb20ccce9e038b90d to your computer and use it in GitHub Desktop.
Save ulve/c5a4f619888f9c2bb20ccce9e038b90d to your computer and use it in GitHub Desktop.
Using hopac as a api gateway in f#
#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