Skip to content

Commit

Permalink
refactor request to api_request
Browse files Browse the repository at this point in the history
  • Loading branch information
dmmulroy committed Mar 18, 2024
1 parent d041260 commit 0aa6a67
Show file tree
Hide file tree
Showing 7 changed files with 79 additions and 66 deletions.
1 change: 1 addition & 0 deletions gleam.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ gleam_json = "~> 1.0"
gleam_httpc = "~> 2.1"
gleam_http = "~> 3.5"
dot_env = "~> 0.2"
pprint = "~> 1.0"

[dev-dependencies]
gleeunit = "~> 1.0"
17 changes: 16 additions & 1 deletion manifest.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,29 @@
# You typically do not need to edit this file

packages = [
{ name = "dot_env", version = "0.2.4", build_tools = ["gleam"], requirements = ["gleam_stdlib", "simplifile"], otp_app = "dot_env", source = "hex", outer_checksum = "FFAC6F89A2BB6896A10128E5850496C372821BFDB807C837A1404BEBDD1AB2B9" },
{ name = "argv", version = "1.0.1", build_tools = ["gleam"], requirements = [], otp_app = "argv", source = "hex", outer_checksum = "A6E9009E50BBE863EB37D963E4315398D41A3D87D0075480FC244125808F964A" },
{ name = "birdie", version = "1.1.0", build_tools = ["gleam"], requirements = ["argv", "filepath", "gap", "glance", "gleam_community_ansi", "gleam_erlang", "gleam_stdlib", "gleeunit", "justin", "rank", "simplifile", "trie_again"], otp_app = "birdie", source = "hex", outer_checksum = "DE7BEE4C76A52E91E72800531B6E5B41093D06FA90C7F6D9FDE768BCE714FAA7" },
{ name = "dot_env", version = "0.3.0", build_tools = ["gleam"], requirements = ["gleam_stdlib", "simplifile"], otp_app = "dot_env", source = "hex", outer_checksum = "FA7DC31F86FD2F64AEBD4868F3F357F93E1147946F5631CBAEBA29EAC0A2BBB3" },
{ name = "filepath", version = "0.2.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "filepath", source = "hex", outer_checksum = "FC1B1B29438A5BA6C990F8047A011430BEC0C5BA638BFAA62718C4EAEFE00435" },
{ name = "gap", version = "1.1.3", build_tools = ["gleam"], requirements = ["gleam_community_ansi", "gleam_stdlib"], otp_app = "gap", source = "hex", outer_checksum = "6EF5E3B523FDFBC317E9EA28D5163EE04744A97C007106F90207569789612291" },
{ name = "glam", version = "2.0.0", build_tools = ["gleam"], requirements = ["birdie", "gleam_stdlib"], otp_app = "glam", source = "hex", outer_checksum = "1C10BE5EA72659E409DC2325BA5E94E0CC92C6C50B2A1DBADE6D07E8C9484D51" },
{ name = "glance", version = "0.8.2", build_tools = ["gleam"], requirements = ["gleam_stdlib", "glexer"], otp_app = "glance", source = "hex", outer_checksum = "ACF09457E8B564AD7A0D823DAFDD326F58263C01ACB0D432A9BEFDEDD1DA8E73" },
{ name = "gleam_community_ansi", version = "1.4.0", build_tools = ["gleam"], requirements = ["gleam_community_colour", "gleam_stdlib"], otp_app = "gleam_community_ansi", source = "hex", outer_checksum = "FE79E08BF97009729259B6357EC058315B6FBB916FAD1C2FF9355115FEB0D3A4" },
{ name = "gleam_community_colour", version = "1.3.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleam_community_colour", source = "hex", outer_checksum = "A49A5E3AE8B637A5ACBA80ECB9B1AFE89FD3D5351FF6410A42B84F666D40D7D5" },
{ name = "gleam_erlang", version = "0.24.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleam_erlang", source = "hex", outer_checksum = "26BDB52E61889F56A291CB34167315780EE4AA20961917314446542C90D1C1A0" },
{ name = "gleam_http", version = "3.6.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleam_http", source = "hex", outer_checksum = "8C07DF9DF8CC7F054C650839A51C30A7D3C26482AC241C899C1CEA86B22DBE51" },
{ name = "gleam_httpc", version = "2.1.2", build_tools = ["gleam"], requirements = ["gleam_http", "gleam_stdlib"], otp_app = "gleam_httpc", source = "hex", outer_checksum = "ACD05CA3BAC7780DF5FFAE334621FD199D1B490FAF6ECDFF74316CAA61CE88E6" },
{ name = "gleam_json", version = "1.0.0", build_tools = ["gleam"], requirements = ["gleam_stdlib", "thoas"], otp_app = "gleam_json", source = "hex", outer_checksum = "8B197DD5D578EA6AC2C0D4BDC634C71A5BCA8E7DB5F47091C263ECB411A60DF3" },
{ name = "gleam_stdlib", version = "0.36.0", build_tools = ["gleam"], requirements = [], otp_app = "gleam_stdlib", source = "hex", outer_checksum = "C0D14D807FEC6F8A08A7C9EF8DFDE6AE5C10E40E21325B2B29365965D82EB3D4" },
{ name = "gleeunit", version = "1.0.2", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleeunit", source = "hex", outer_checksum = "D364C87AFEB26BDB4FB8A5ABDE67D635DC9FA52D6AB68416044C35B096C6882D" },
{ name = "glexer", version = "0.7.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "glexer", source = "hex", outer_checksum = "4484942A465482A0A100936E1E5F12314DB4B5AC0D87575A7B9E9062090B96BE" },
{ name = "justin", version = "1.0.1", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "justin", source = "hex", outer_checksum = "7FA0C6DB78640C6DC5FBFD59BF3456009F3F8B485BF6825E97E1EB44E9A1E2CD" },
{ name = "logging", version = "1.0.1", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "logging", source = "hex", outer_checksum = "82C112ED9B6C30C1772A6FE2613B94B13F62EA35F5869A2630D13948D297BD39" },
{ name = "pprint", version = "1.0.0", build_tools = ["gleam"], requirements = ["glam", "gleam_stdlib"], otp_app = "pprint", source = "hex", outer_checksum = "2764575188B81F2AE1F9AFE57308B7078CA27EBE2AC797EBA272017550B5CF31" },
{ name = "rank", version = "1.0.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "rank", source = "hex", outer_checksum = "5660E361F0E49CBB714CC57CC4C89C63415D8986F05B2DA0C719D5642FAD91C9" },
{ name = "simplifile", version = "1.5.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "simplifile", source = "hex", outer_checksum = "EB9AA8E65E5C1E3E0FDCFC81BC363FD433CB122D7D062750FFDF24DE4AC40116" },
{ name = "thoas", version = "0.4.1", build_tools = ["rebar3"], requirements = [], otp_app = "thoas", source = "hex", outer_checksum = "4918D50026C073C4AB1388437132C77A6F6F7C8AC43C60C13758CC0ADCE2134E" },
{ name = "trie_again", version = "1.1.2", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "trie_again", source = "hex", outer_checksum = "5B19176F52B1BD98831B57FDC97BD1F88C8A403D6D8C63471407E78598E27184" },
]

[requirements]
Expand All @@ -21,3 +35,4 @@ gleam_json = { version = "~> 1.0" }
gleam_stdlib = { version = "~> 0.34 or ~> 1.0" }
gleeunit = { version = "~> 1.0" }
logging = { version = "~> 1.0" }
pprint = { version = "~> 1.0" }
4 changes: 2 additions & 2 deletions src/glitch.gleam
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import gleam/io
import gleam/option.{None, Some}
import gleam/result
import dot_env/env
import pprint
import glitch/api/client.{Options}
import glitch/api/user.{GetUsersRequest}

Expand All @@ -16,6 +16,6 @@ pub fn main() {

let result = user.get_users(client, get_users_request)

io.debug(result)
pprint.debug(result)
Ok(Nil)
}
19 changes: 19 additions & 0 deletions src/glitch/api/api_request.gleam
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import gleam/http.{Https}
import gleam/http/request.{type Request}
import gleam/json.{type Json}

pub type TwitchApiRequest =
Request(String)

const host = "api.twitch.tv/helix"

pub fn from_request(request: Request(Json)) -> TwitchApiRequest {
let body =
request.body
|> json.to_string

request
|> request.set_scheme(Https)
|> request.set_host(host)
|> request.set_body(body)
}
30 changes: 30 additions & 0 deletions src/glitch/api/api_response.gleam
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import gleam/dynamic.{type Decoder}
import gleam/json
import gleam/http/response.{type Response}
import glitch/extended/function_ext

pub type TwitchApiResponse(data) {
TwitchApiResponse(data: List(data))
}

fn decoder(of data_decoder: Decoder(data)) -> Decoder(TwitchApiResponse(data)) {
dynamic.decode1(
TwitchApiResponse,
dynamic.field("data", dynamic.list(of: data_decoder)),
)
}

pub fn from_json(json_string: String, of data_decoder: Decoder(data)) {
json.decode(json_string, decoder(data_decoder))
}

pub fn get_data(api_response: TwitchApiResponse(data)) -> List(data) {
api_response.data
}

pub fn get_data_from_response(
response: Response(TwitchApiResponse(data)),
) -> Result(Response(List(data)), error) {
response
|> response.try_map(function_ext.compose(get_data, Ok))
}
35 changes: 7 additions & 28 deletions src/glitch/api/client.gleam
Original file line number Diff line number Diff line change
@@ -1,14 +1,12 @@
import gleam/dynamic.{type Dynamic}
import gleam/list
import gleam/pair
import gleam/http.{type Header, type Method, Get, Https}
import gleam/http/request.{type Request}
import gleam/http.{type Header, Get}
import gleam/http/request.{type Request, Request}
import gleam/http/response.{type Response}
import gleam/httpc
import gleam/json.{type Json}
import glitch/extended/request_ext

const host = "api.twitch.tv/helix"
import glitch/api/api_request

pub opaque type Client {
Client(options: Options)
Expand Down Expand Up @@ -50,35 +48,16 @@ fn merge_headers(
})
}

fn prepare_request(
pub fn get(
client: Client,
method: Method,
request: Request(Json),
) -> Request(String) {
) -> Result(Response(String), Dynamic) {
let headers =
client
|> headers
|> merge_headers(request.headers)

let body =
request.body
|> json.to_string

request.new()
|> request.set_method(method)
|> request_ext.set_headers(headers)
|> request.set_scheme(Https)
|> request.set_host(host)
|> request.set_body(body)
|> request.set_path(request.path)
|> request_ext.set_query_string(request.query)
}

pub fn get(
client: Client,
request: Request(Json),
) -> Result(Response(String), Dynamic) {
client
|> prepare_request(Get, request)
Request(..request, method: Get, headers: headers)
|> api_request.from_request
|> httpc.send
}
39 changes: 4 additions & 35 deletions src/glitch/api/user.gleam
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ import gleam/http/request
import gleam/http/response.{type Response}
import glitch/api/client.{type Client}
import glitch/extended/dynamic_ext
import glitch/extended/function_ext
import glitch/extended/json_ext
import glitch/api/api_response

pub type User {
User(
Expand Down Expand Up @@ -39,7 +39,7 @@ fn decoder() -> Decoder(User) {
dynamic.field("profile_image_url", dynamic_ext.uri),
dynamic.field("offline_image_url", dynamic_ext.uri),
dynamic.field("view_count", dynamic.int),
dynamic.field("email", dynamic.optional(dynamic.string)),
dynamic.optional_field("email", dynamic.string),
dynamic.field("created_at", dynamic.string),
)
}
Expand Down Expand Up @@ -101,37 +101,6 @@ pub type GetUsersError {
RequestError
}

pub type TwitchApiResponse(data) {
TwitchApiResponse(data: List(data))
}

fn twitch_api_response_decoder(
of data_decoder: Decoder(data),
) -> Decoder(TwitchApiResponse(data)) {
dynamic.decode1(
TwitchApiResponse,
dynamic.field("data", dynamic.list(of: data_decoder)),
)
}

fn twitch_api_response_from_json(
json_string: String,
of data_decoder: Decoder(data),
) {
json.decode(json_string, twitch_api_response_decoder(data_decoder))
}

fn twitch_api_response_data(api_response: TwitchApiResponse(data)) -> List(data) {
api_response.data
}

fn twitch_api_response_from_response(
response: Response(TwitchApiResponse(data)),
) -> Result(Response(List(data)), error) {
response
|> response.try_map(function_ext.compose(twitch_api_response_data, Ok))
}

pub fn get_users(
client: Client,
request: GetUsersRequest,
Expand All @@ -149,7 +118,7 @@ pub fn get_users(
)

response
|> response.try_map(twitch_api_response_from_json(_, of: decoder()))
|> result.try(twitch_api_response_from_response)
|> response.try_map(api_response.from_json(_, of: decoder()))
|> result.try(api_response.get_data_from_response)
|> result.map_error(DecodeError)
}

0 comments on commit 0aa6a67

Please sign in to comment.