///|
/// Default base URL for mooncakes.io
let default_base_url : String = "https://mooncakes.io"
///|
/// Default API URL for mooncakes.io
let default_api_url : String = "https://mooncakes.io/api/v0"
///|
/// HTTP error
pub(all) suberror HttpError {
/// Network error
NetworkError(String)
/// JSON parse error
ParseError(String)
/// HTTP status error
StatusError(code~ : Int, message~ : String)
} derive(Show)
///|
/// Fetch JSON from URL and parse it
pub async fn[T : FromJson] fetch_json(url : String) -> T {
let result = @http.get(url)
let response = result.0
let body = result.1
if response.code != 200 {
raise HttpError::StatusError(code=response.code, message=response.reason)
}
let text = body.text()
let json : Json = @json.parse(text) catch {
e => raise HttpError::ParseError("Failed to parse JSON: \{e}")
}
@json.from_json(json) catch {
e => raise HttpError::ParseError("Failed to deserialize: \{e}")
}
}
///|
/// Fetch text from URL
pub async fn fetch_text(url : String) -> String {
let result = @http.get(url)
let response = result.0
let body = result.1
if response.code != 200 {
raise HttpError::StatusError(code=response.code, message=response.reason)
}
body.text()
}
///|
/// Mooncakes API client
pub(all) struct MooncakesClient {
/// Base URL for static assets
base_url : String
/// API URL
api_url : String
}
///|
/// Create a new MooncakesClient with default URLs
pub fn MooncakesClient::new() -> MooncakesClient {
MooncakesClient::{ base_url: default_base_url, api_url: default_api_url }
}
///|
/// Create a new MooncakesClient with custom URLs
pub fn MooncakesClient::with_urls(
base_url? : String = default_base_url,
api_url? : String = default_api_url,
) -> MooncakesClient {
MooncakesClient::{ base_url, api_url }
}
///|
/// Get recent modules
pub async fn MooncakesClient::get_recent_modules(
self : MooncakesClient,
) -> Array[ModuleSummary] {
fetch_json("\{self.api_url}/modules/all")
}
///|
/// Get statistics
pub async fn MooncakesClient::get_statistics(
self : MooncakesClient,
) -> Statistics {
fetch_json("\{self.api_url}/modules/statistics")
}
///|
/// Get user info
pub async fn MooncakesClient::get_user(
self : MooncakesClient,
username : String,
) -> UserInfo {
fetch_json("\{self.api_url}/users/\{username}")
}
///|
/// Get resource for a module or package
pub async fn MooncakesClient::get_resource(
self : MooncakesClient,
path : String,
) -> Resource {
fetch_json("\{self.base_url}/assets/\{path}/resource.json")
}
///|
/// Get package data
pub async fn MooncakesClient::get_package_data(
self : MooncakesClient,
path : String,
) -> PackageData {
fetch_json("\{self.base_url}/assets/\{path}/package_data.json")
}
///|
/// Get module index
pub async fn MooncakesClient::get_module_index(
self : MooncakesClient,
path : String,
) -> IndexNode {
fetch_json("\{self.base_url}/assets/\{path}/module_index.json")
}
///|
/// Get README content
pub async fn MooncakesClient::get_readme(
self : MooncakesClient,
path : String,
) -> String {
let resource : Resource = self.get_resource(path)
resource.readme_content
}
///|
/// Batch fetch package data for multiple paths
pub async fn MooncakesClient::get_package_data_batch(
self : MooncakesClient,
paths : Array[String],
) -> Map[String, PackageData] {
let results : Map[String, PackageData] = {}
for path in paths {
let data = self.get_package_data(path)
results[path] = data
}
results
}
///|
/// Get full module data including all packages
pub async fn MooncakesClient::get_full_module_data(
self : MooncakesClient,
path : String,
) -> FullModuleData {
let resource = self.get_resource(path)
let index = self.get_module_index(path)
let all_paths = get_all_package_paths(index)
let packages = self.get_package_data_batch(all_paths)
FullModuleData::{ path, resource, index, packages }
}
///|
/// Convenience function: get recent modules
pub async fn get_recent_modules() -> Array[ModuleSummary] {
MooncakesClient::new().get_recent_modules()
}
///|
/// Convenience function: get statistics
pub async fn get_statistics() -> Statistics {
MooncakesClient::new().get_statistics()
}
///|
/// Convenience function: get user info
pub async fn get_user(username : String) -> UserInfo {
MooncakesClient::new().get_user(username)
}
///|
/// Convenience function: get resource
pub async fn get_resource(path : String) -> Resource {
MooncakesClient::new().get_resource(path)
}
///|
/// Convenience function: get package data
pub async fn get_package_data(path : String) -> PackageData {
MooncakesClient::new().get_package_data(path)
}
///|
/// Convenience function: get module index
pub async fn get_module_index(path : String) -> IndexNode {
MooncakesClient::new().get_module_index(path)
}