import gleam/dynamic.{type Dynamic} import gleam/dynamic/decode.{type Decoder} import gleam/http/request.{type Request} import gleam/httpc.{type HttpError} import gleam/json.{type DecodeError} import gleam/option.{type Option} import gleam/result import spacetraders_models/meta.{type Meta} import spacetraders_sdk/internal/jwt pub type ErrorResponse { ErrorResponse( code: Int, message: String, data: Option(Dynamic), request_id: Option(String), ) } pub type ApiError { HttpcError(HttpError) JsonDecodeError(DecodeError) ResponseError(ErrorResponse) } pub type ApiResponse(a) = Result(a, ApiError) pub type PagedData(data) { PagedData(data: data, meta: Meta) } pub opaque type AccountToken { AccountToken(token: String) } pub opaque type AgentToken { AgentToken(token: String) } pub type TokenParseError { InvalidToken IncorrectType } pub type AuthMethod { AccountAuth(AccountToken) AgentAuth(AgentToken) NoAuth } pub fn parse_account_token( value: String, ) -> Result(AccountToken, TokenParseError) { use jwt <- result.try(jwt.parse(value) |> result.replace_error(InvalidToken)) case jwt.payload.subject { "account-token" -> Ok(AccountToken(value)) _ -> Error(IncorrectType) } } pub fn account_token_decoder() -> Decoder(AccountToken) { use value <- decode.then(decode.string) case parse_account_token(value) { Ok(token) -> decode.success(token) Error(_) -> decode.failure(AccountToken("invalid"), "AccountToken") } } pub fn parse_agent_token(value: String) -> Result(AgentToken, TokenParseError) { use jwt <- result.try(jwt.parse(value) |> result.replace_error(InvalidToken)) case jwt.payload.subject { "agent-token" -> Ok(AgentToken(value)) _ -> Error(IncorrectType) } } pub fn agent_token_decoder() -> Decoder(AgentToken) { use value <- decode.then(decode.string) case parse_agent_token(value) { Ok(token) -> decode.success(token) Error(_) -> decode.failure(AgentToken("invalid"), "AgentToken") } } @internal pub fn set_request_auth(req: Request(a), auth_method: AuthMethod) -> Request(a) { case auth_method { NoAuth -> req AccountAuth(AccountToken(token)) | AgentAuth(AgentToken(token)) -> req |> request.set_header("Authorization", "Bearer " <> token) } }