///|
/// OpenList 客户端:认证状态的持有者,也是六个 API 域子模块的入口。
///
/// 由一个服务器信息(`Settings`)与一份凭证(`Credentials`)创建,
/// 创建时就把六个子模块派生好——`auth` / `user` / `admin` / `fs` /
/// `public` / `share`。它们共享同一份认证状态:用账号密码登录后拿到的限时
/// token 对所有子模块立即生效,`set_token` 也一样。
///
/// 子模块的字段是私有的,只能由客户端派生(见 `docs/00-architecture.md`)。
pub struct OpenListClient {
priv core : @core.Client
priv auth : @auth.Auth
priv user : @user.UserApi
priv admin : @admin.AdminApi
priv fs : @fs.FileSystem
priv public : @public.PublicApi
priv share : @share.ShareApi
}
///|
/// 创建客户端:服务器信息 + 凭证。
///
/// 凭证支持 OpenList 的两种认证方式:
///
/// ```moonbit nocheck
/// // 1. 永久 token(后台生成的,直接拿来用)
/// let client = create_open_list_client(
/// Settings::new("https://openlist.example.com"),
/// Credentials::token("..."),
/// )
///
/// // 2. 账号密码:第一次需要认证的请求前自动登录,换取限时 token
///
/// let client = create_open_list_client(
/// Settings::new("https://openlist.example.com"),
/// Credentials::password("admin", "secret"),
/// )
///
/// let files = client.fs().list("/")
/// ```
///
pub fn create_open_list_client(
settings : Settings,
credentials : Credentials,
) -> OpenListClient {
new_client(settings, credentials)
}
///|
/// 真正的构造函数:比公开版本多一个传输层注入点,只给同包的白盒测试用
/// (生产代码不要传 `transport`)。
fn new_client(
settings : Settings,
credentials : Credentials,
transport? : &@moonhttp.Transport,
) -> OpenListClient {
let core = @core.Client::new(settings, credentials, transport?)
{
core,
auth: @auth.Auth::new(core),
user: @user.UserApi::new(core),
admin: @admin.AdminApi::new(core),
fs: @fs.FileSystem::new(core),
public: @public.PublicApi::new(core),
share: @share.ShareApi::new(core),
}
}
///|
/// 用永久 token 创建客户端(`create_open_list_client` 的常用简写)。
pub fn create_open_list_client_with_token(
base_url : String,
token : String,
) -> OpenListClient {
create_open_list_client(Settings::new(base_url), Credentials::token(token))
}
///|
/// 认证子模块:登录(明文 / 预哈希 / LDAP)、退出、token 与两步验证。
pub fn OpenListClient::auth(self : OpenListClient) -> @auth.Auth {
self.auth
}
///|
/// 当前用户子模块:`/api/me` 与自己的 SSH 公钥。
pub fn OpenListClient::user(self : OpenListClient) -> @user.UserApi {
self.user
}
///|
/// 管理子模块:元信息、用户、存储、驱动、设置与索引(需要管理员权限)。
pub fn OpenListClient::admin(self : OpenListClient) -> @admin.AdminApi {
self.admin
}
///|
/// 文件子模块:列目录、读写、管理、上传(含分片)与归档。
pub fn OpenListClient::fs(self : OpenListClient) -> @fs.FileSystem {
self.fs
}
///|
/// 公共子模块:站点设置、离线下载工具、归档扩展名与站点初始化。
pub fn OpenListClient::public(self : OpenListClient) -> @public.PublicApi {
self.public
}
///|
/// 分享子模块:创建 / 查询 / 启停分享链接。
pub fn OpenListClient::share(self : OpenListClient) -> @share.ShareApi {
self.share
}
///|
/// 连接设置(创建时固化进客户端)。
pub fn OpenListClient::settings(self : OpenListClient) -> Settings {
self.core.settings()
}
///|
/// 当前 token:永久凭证就是它本身;账号密码凭证在登录成功前是 `None`。
pub fn OpenListClient::token(self : OpenListClient) -> String? {
self.core.token()
}
///|
/// 直接覆盖 token,用于从本地持久化状态恢复会话,或主动让 token 失效。
pub fn OpenListClient::set_token(
self : OpenListClient,
token : String?,
) -> Unit {
self.core.set_token(token)
}
///|
/// 是否已持有可用 token(永久 token,或账号密码换来的限时 token)。
pub fn OpenListClient::is_logged_in(self : OpenListClient) -> Bool {
self.core.is_logged_in()
}
///|
/// 逃生通道:直接请求任意 `/api/...` 端点,返回信封里的 `data`(原样 `Json`)。
///
/// 官方客户端没有把它封装成方法的端点(SSO、WebAuthn、`/api/task/*` 等,
/// 清单见 `docs/08-unsupported-endpoints.md`)都可以用它调用。认证、账号密码
/// 凭证的 401 重登、信封检查与 `code != 200` 抛 `Api` 都在这一层自动完成:
///
/// ```moonbit nocheck
/// let status = client.request(Method::Get, "/api/public/init_status")
/// ```
pub async fn OpenListClient::request(
self : OpenListClient,
http_method : @moonhttp.Method,
path : String,
query? : Json,
body? : Json,
headers? : Array[(String, String)],
) -> Json raise OpenListError {
self.core.request(http_method, path, query?, body?, headers?)
}