Packages

CLI for vendoring Drip elements into a Lustre project.

Current section

Files

Jump to
drip src drip internal source.gleam
Raw

src/drip/internal/source.gleam

import drip/internal/error.{type Error}
import filepath
import gleam/http/request
import gleam/httpc
import gleam/result
import gleam/string
import simplifile
// --- Source ------------------------------------------------------------------
pub opaque type Source {
Http(base: String)
Local(root: String)
}
pub fn parse(raw: String) -> Result(Source, Error) {
case string.trim(raw) |> trim_trailing_slash {
"" -> Error(error.EmptySource)
source ->
case is_http(source) {
True ->
case request.to(source) {
Ok(_) -> Ok(Http(source))
Error(Nil) -> Error(error.InvalidSourceUrl(source))
}
False -> Ok(Local(source))
}
}
}
fn is_http(raw: String) -> Bool {
let lower = string.lowercase(raw)
string.starts_with(lower, "http://") || string.starts_with(lower, "https://")
}
fn trim_trailing_slash(raw: String) -> String {
case string.ends_with(raw, "/") {
True -> trim_trailing_slash(string.drop_end(raw, 1))
False -> raw
}
}
// --- Fetch -------------------------------------------------------------------
pub fn fetch(source: Source, filename: String) -> Result(String, Error) {
case source {
Http(base) -> http_get(base <> "/" <> filename)
Local(root) -> read_file(filepath.join(root, filename))
}
}
fn read_file(path: String) -> Result(String, Error) {
case simplifile.read(path) {
Ok(content) -> Ok(content)
Error(cause) -> Error(error.FailedToReadSourceFile(path:, cause:))
}
}
fn http_get(url: String) -> Result(String, Error) {
use request <- result.try(case request.to(url) {
Ok(request) -> Ok(request.set_header(request, "user-agent", "drip-cli"))
Error(Nil) -> Error(error.InvalidSourceUrl(url))
})
let config =
httpc.configure()
|> httpc.follow_redirects(True)
|> httpc.timeout(30_000)
case httpc.dispatch(config, request) {
Ok(response) -> {
case response.status {
status if status >= 200 && status < 300 -> Ok(response.body)
404 -> Error(error.SourceNotFound(url))
status -> Error(error.SourceReturnedBadStatus(url, status))
}
}
Error(cause) -> Error(error.FailedToFetchSourceFile(url, cause))
}
}