Provider-neutral synchronous OpenFeature SDK core for MoonBit
moon add chenliyi-cly/moonopenfeature@0.1.1import {
"chenliyi-cly/moonopenfeature" @feature,
}let sdk = @feature.Sdk::new()
let provider = @feature.Provider::new("application", (key, kind, default, context) => {
if key == "checkout-v2" && kind == Boolean {
@feature.Resolution::success(Boolean(context.targeting_key() == Some("demo")), reason="STATIC")
} else {
@feature.Resolution::failure(default, @feature.SdkError::new(FlagNotFound, "unknown key"))
}
})
sdk.set_provider(provider).unwrap()
let client = sdk.client(name="checkout", version="1")
client.set_context(@feature.EvaluationContext::empty().with_targeting_key("demo"))
let result = client.boolean_details("checkout-v2", false)
println(result.details.to_json().stringify())
sdk.shutdown().unwrap()moon run examples/multitenant --deny-warn
moon run examples/typed_provider --deny-warn
moon run examples/observability --deny-warn| API | 约束与行为 |
|---|---|
| FlagValue / FlagType | 五种精确类型,不隐式转换数值;Int64 序列化为 JSON 时保留精确十进制表示 |
| EvaluationContext | 经校验的 JSON 属性与可选 targeting key;不可变的按键覆盖,以及深拷贝访问器 |
| Resolution / EvaluationDetails | 包含 reason、variant、错误和标量 metadata;类型不匹配或供应方失败时返回调用者默认值 |
| Sdk / Client | SDK 实例相互独立;支持默认供应方回退、显式域绑定,以及共享供应方的生命周期管理 |
| Hook / HookPlan | before 正序,after/error/finally 逆序;按支持的类型筛选;每个钩子、每次评估使用独立 JSON 暂存数据 |
| Provider | 使用 Result 回调与显式生命周期事件;初始化和关闭只执行一次;可选择限制为单域绑定 |
| TrackingEvent | 可选有限数值和 JSON 详情;Client.track 记录错误而不抛错,track_checked 是返回 Result 的扩展接口 |
moon info
moon fmt --check
python3 scripts/verify.py # 三个可执行目标的验证,以及 native 静态检查
python3 scripts/verify.py --native # 同时构建、测试和运行 native,需要本机 C 编译器pub struct Client {
// private fields
}fn Client::boolean_details(self : Client, key : String, default : Bool, options? : EvaluationOptions) -> Evaluation[Bool]fn Client::boolean_value(self : Client, key : String, default : Bool, options? : EvaluationOptions) -> Boolfn Client::evaluate(self : Client, key : String, default : FlagValue, options? : EvaluationOptions) -> EvaluationDetailsfn Client::float_details(self : Client, key : String, default : Double, options? : EvaluationOptions) -> Evaluation[Double]fn Client::float_value(self : Client, key : String, default : Double, options? : EvaluationOptions) -> Doublefn Client::integer_details(self : Client, key : String, default : Int64, options? : EvaluationOptions) -> Evaluation[Int64]fn Client::integer_value(self : Client, key : String, default : Int64, options? : EvaluationOptions) -> Int64fn Client::on(self : Client, event_type : EventType, callback : (ProviderEvent) -> Result[Unit, SdkError]) -> Intfn Client::string_details(self : Client, key : String, default : String, options? : EvaluationOptions) -> Evaluation[String]fn Client::string_value(self : Client, key : String, default : String, options? : EvaluationOptions) -> Stringfn Client::structure_details(self : Client, key : String, default : Json, options? : EvaluationOptions) -> Evaluation[Json]fn Client::structure_value(self : Client, key : String, default : Json, options? : EvaluationOptions) -> Jsonfn Client::track(self : Client, event : TrackingEvent, context? : EvaluationContext, transaction_context? : EvaluationContext) -> Unitfn Client::track_checked(self : Client, event : TrackingEvent, context? : EvaluationContext, transaction_context? : EvaluationContext) -> Result[Unit, SdkError]pub(all) struct ClientMetadata {
name : String
version : String
domain : String
}pub(all) enum ErrorCode {
ProviderNotReady
ProviderFatal
FlagNotFound
ParseError
TypeMismatch
TargetingKeyMissing
InvalidContext
General
} derive(Eq)pub struct EvaluationContext {
// private fields
}fn EvaluationContext::from_attributes(attributes : Map[String, Json]) -> Result[EvaluationContext, SdkError]fn EvaluationContext::merge(self : EvaluationContext, later : EvaluationContext) -> EvaluationContextfn EvaluationContext::with_attribute(self : EvaluationContext, key : String, value : Json) -> Result[EvaluationContext, SdkError]fn EvaluationContext::with_targeting_key(self : EvaluationContext, targeting_key : String) -> EvaluationContextfn EvaluationContext::without_attribute(self : EvaluationContext, key : String) -> EvaluationContextpub(all) struct EvaluationDetails {
flag_key : String
value : FlagValue
reason : String
variant : String?
error : SdkError?
metadata : FlagMetadata
}fn EvaluationDetails::from_resolution(flag_key : String, resolution : Resolution) -> EvaluationDetailspub struct EvaluationOptions {
// private fields
}fn EvaluationOptions::new(context? : EvaluationContext, transaction_context? : EvaluationContext, hooks? : Array[Hook], hints? : EvaluationContext) -> EvaluationOptionspub struct EventBus {
// private fields
}fn EventBus::on(self : EventBus, callback : (ProviderEvent) -> Result[Unit, SdkError], event_type? : EventType?, domain? : String?) -> Intpub(all) enum EventType {
ProviderReady
ProviderError
ProviderStale
ProviderConfigurationChanged
} derive(Eq)pub struct FlagMetadata {
// private fields
}fn FlagMetadata::with_value(self : FlagMetadata, key : String, value : Json) -> Result[FlagMetadata, SdkError]pub(all) enum FlagValue {
Boolean(Bool)
Integer(Int64)
Float(Double)
String(String)
Structure(Json)
}pub struct Hook {
// private fields
}fn Hook::new(name : String, types? : Array[FlagType]?, before? : (HookContext, EvaluationContext) -> Result[EvaluationContext?, SdkError], after? : (HookContext, EvaluationDetails, EvaluationContext) -> Result[Unit, SdkError], error? : (HookContext, SdkError, EvaluationContext) -> Result[Unit, SdkError], on_finally? : (HookContext, EvaluationDetails, EvaluationContext) -> Result[Unit, SdkError]) -> Hookpub(all) struct HookContext {
flag_key : String
flag_type : FlagType
default_value : FlagValue
evaluation_context : EvaluationContext
client : ClientMetadata
provider_name : String
data : HookData
}pub struct HookData {
// private fields
}pub struct HookPlan {
// private fields
}fn HookPlan::after(self : HookPlan, context : HookContext, details : EvaluationDetails, hints : EvaluationContext) -> Result[Unit, SdkError]fn HookPlan::before(self : HookPlan, context : HookContext, hints : EvaluationContext) -> BeforeResultfn HookPlan::on_error(self : HookPlan, context : HookContext, error : SdkError, hints : EvaluationContext) -> Array[SdkError]fn HookPlan::run_finally(self : HookPlan, context : HookContext, details : EvaluationDetails, hints : EvaluationContext) -> Array[SdkError]pub struct Provider {
// private fields
}fn Provider::new(name : String, resolver : (String, FlagType, FlagValue, EvaluationContext) -> Resolution, domain_scoped? : Bool, initialize? : (Provider, EvaluationContext) -> Result[Unit, SdkError]?, shutdown? : (Provider) -> Result[Unit, SdkError]?, track? : (TrackingEvent, EvaluationContext) -> Result[Unit, SdkError]?, context_changed? : (Provider, EvaluationContext, EvaluationContext) -> Result[Unit, SdkError]?) -> Providerfn Provider::on_context_changed(self : Provider, old : EvaluationContext, new : EvaluationContext) -> Result[Unit, SdkError]fn Provider::resolve(self : Provider, key : String, kind : FlagType, default : FlagValue, context : EvaluationContext) -> Resolutionfn Provider::track(self : Provider, event : TrackingEvent, context : EvaluationContext) -> Result[Unit, SdkError]fn ProviderEvent::new(event_type : EventType, provider_name : String, domain? : String?, message? : String, error? : SdkError?, flags? : Array[String]) -> ProviderEventpub(all) struct Resolution {
value : FlagValue
reason : String
variant : String?
error : SdkError?
metadata : FlagMetadata
}fn Resolution::success(value : FlagValue, reason? : String, variant? : String?, metadata? : FlagMetadata) -> Resolutionpub struct Sdk {
// private fields
}fn Sdk::on(self : Sdk, event_type : EventType, callback : (ProviderEvent) -> Result[Unit, SdkError]) -> Intpub(all) enum StandardReason {
Static
Default
TargetingMatch
Split
Cached
Disabled
Unknown
Stale
Error
} derive(Eq)fn TrackingEvent::new(key : String, value? : Double?, details? : EvaluationContext) -> Result[TrackingEvent, SdkError]Install
Download zipProvider-neutral synchronous OpenFeature SDK core for MoonBit