Skip to content

Commit

Permalink
feat: Update interface of search.run().
Browse files Browse the repository at this point in the history
  • Loading branch information
vxern committed Jun 11, 2024
1 parent 4237984 commit 9f980c0
Show file tree
Hide file tree
Showing 3 changed files with 26 additions and 20 deletions.
11 changes: 11 additions & 0 deletions src/tatoeba/api.gleam
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import gleam/dynamic.{type Dynamic}
import gleam/http.{type Header}
import gleam/http/request.{type Request}
import gleam/json
import gleam/list
import gleam/option.{None, Some}
import gleam/uri.{type Uri, Uri}
Expand All @@ -22,6 +24,15 @@ pub const headers: List(Header) = [
#("User-Agent", "tatoeba.gleam (https://github.com/vxern/tatoeba)"),
]

/// The possible errors API calls can fail with.
///
pub type ApiError {
/// Failed to make a request to Tatoeba.
RequestError(Dynamic)
/// Failed to decode the response data.
DecodeError(json.DecodeError)
}

/// Creates a new request to the given endpoint.
///
/// This function is used over the bare `request.from_uri()` to add a step
Expand Down
18 changes: 11 additions & 7 deletions src/tatoeba/search.gleam
Original file line number Diff line number Diff line change
Expand Up @@ -319,22 +319,26 @@ fn results(

/// Runs a search query using the passed `options` to filter the results.
///
pub fn run(options: SearchOptions) -> Result(SearchResults, String) {
pub fn run(options: SearchOptions) -> Result(SearchResults, api.ApiError) {
let request =
api.new_request_to("/search")
|> request.set_method(http.Get)
|> request.set_query(to_query_parameters(options))

use response <- result.try(
httpc.send(request)
|> result.map_error(fn(_) { "Failed to send request to Tatoeba." }),
|> result.map_error(fn(error) { api.RequestError(error) }),
)

response.body |> decode_payload()
}

/// Decodes the received search payload.
///
fn decode_payload(payload: String) -> Result(SearchResults, api.ApiError) {
use results <- result.try(
json.decode(response.body, results)
|> result.map_error(fn(error) {
"Failed to decode sentence data: "
<> dynamic.classify(dynamic.from(error))
}),
json.decode(payload, results)
|> result.map_error(fn(error) { api.DecodeError(error) }),
)

Ok(results)
Expand Down
17 changes: 4 additions & 13 deletions src/tatoeba/sentence.gleam
Original file line number Diff line number Diff line change
Expand Up @@ -562,25 +562,16 @@ pub fn new_id(id: Int) -> Result(SentenceId, IdError) {
}
}

/// The possible errors sentence retrieval can fail with.
///
pub type SentenceError {
/// Failed to make a request to Tatoeba.
RequestError(Dynamic)
/// Failed to decode the response data.
DecodeError(json.DecodeError)
}

/// Gets data of a single sentence in the Tatoeba corpus.
///
pub fn get(id id: SentenceId) -> Result(Option(Sentence), SentenceError) {
pub fn get(id id: SentenceId) -> Result(Option(Sentence), api.ApiError) {
let request =
api.new_request_to("/sentence/" <> int.to_string(id.value))
|> request.set_method(http.Get)

use response <- result.try(
httpc.send(request)
|> result.map_error(fn(error) { RequestError(error) }),
|> result.map_error(fn(error) { api.RequestError(error) }),
)

case response.body |> string.length() {
Expand All @@ -591,10 +582,10 @@ pub fn get(id id: SentenceId) -> Result(Option(Sentence), SentenceError) {

/// Decodes the received sentence payload.
///
fn decode_payload(payload: String) -> Result(Sentence, SentenceError) {
fn decode_payload(payload: String) -> Result(Sentence, api.ApiError) {
use sentence <- result.try(
json.decode(payload, sentence)
|> result.map_error(fn(error) { DecodeError(error) }),
|> result.map_error(fn(error) { api.DecodeError(error) }),
)

Ok(sentence)
Expand Down

0 comments on commit 9f980c0

Please sign in to comment.