use serde::{Deserialize, Serialize};
use serde_json::{Map, Value};
use std::collections::HashMap;
pub type Properties = Map<String, Value>;
pub type Groups = HashMap<String, String>;
#[derive(Debug, Clone)]
pub struct BilldogEngOptions {
pub host: String,
pub flush_at: usize,
pub flush_interval_ms: u64,
pub max_queue_size: usize,
pub gzip: bool,
pub local_evaluation: bool,
pub request_timeout_ms: u64,
pub max_retries: u32,
pub enable_logging: bool,
pub group_type_index: Option<HashMap<String, u8>>,
}
impl Default for BilldogEngOptions {
fn default() -> Self {
Self {
host: "https://api.billdog.io/v1".to_string(),
flush_at: 20,
flush_interval_ms: 10_000,
max_queue_size: 1000,
gzip: true,
local_evaluation: false,
request_timeout_ms: 10_000,
max_retries: 3,
enable_logging: false,
group_type_index: None,
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct WireEvent {
pub event_name: String,
pub event_timestamp: u64,
pub properties: Properties,
pub user_id: String,
}
#[derive(Debug, Clone, Default)]
pub struct FlagEvalOptions {
pub groups: Option<Groups>,
pub person_properties: Option<Properties>,
}
#[derive(Debug, Clone, PartialEq)]
pub enum FlagValue {
Bool(bool),
Variant(String),
}
impl FlagValue {
pub fn is_enabled(&self) -> bool {
match self {
FlagValue::Bool(b) => *b,
FlagValue::Variant(_) => true,
}
}
pub fn to_json(&self) -> Value {
match self {
FlagValue::Bool(b) => Value::Bool(*b),
FlagValue::Variant(s) => Value::String(s.clone()),
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct FlagVariant {
pub key: String,
pub rollout_percentage: u32,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub payload: Option<Value>,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
#[serde(rename_all = "snake_case")]
pub enum Operator {
Exists,
NotExists,
Is,
Equals,
IsNot,
NotEquals,
AnyOf,
NotAnyOf,
Contains,
NotContains,
GreaterThan,
Gt,
LessThan,
Lt,
GreaterThanOrEqual,
Gte,
LessThanOrEqual,
Lte,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct TargetingRule {
pub attribute: String,
pub operator: Operator,
pub value: Value,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct FeatureFlagDefinition {
pub key: String,
pub active: bool,
pub rollout_percentage: u32,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub variants: Option<Vec<FlagVariant>>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub targeting_rules: Option<Vec<TargetingRule>>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub payload: Option<Value>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SurveyListItem {
pub id: String,
pub name: String,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub description: Option<String>,
#[serde(default, rename = "type", skip_serializing_if = "Option::is_none")]
pub survey_type: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub status: Option<String>,
}
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
pub struct SurveyAnswer {
pub question_id: String,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub choice_id: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub answer_text: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub answer_number: Option<f64>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub answer_json: Option<Value>,
}
#[derive(Debug, Clone, Default)]
pub struct SurveyContext {
pub respondent_id: Option<String>,
pub customer_id: Option<String>,
pub anonymous_id: Option<String>,
pub session_id: Option<String>,
pub platform: Option<String>,
pub device_info: Option<Properties>,
pub duration_ms: Option<u64>,
pub context: Option<Properties>,
pub collector_id: Option<String>,
pub collector_type: Option<String>,
pub idempotency_key: Option<String>,
}
#[derive(Debug, Clone, Default, Serialize)]
pub struct MessagingTargeting {
#[serde(default, rename = "type", skip_serializing_if = "Option::is_none")]
pub targeting_type: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub conditions: Option<Value>,
#[serde(rename = "segmentIds", default, skip_serializing_if = "Option::is_none")]
pub segment_ids: Option<Vec<String>>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub tags: Option<Vec<String>>,
#[serde(
rename = "subscriberIds",
default,
skip_serializing_if = "Option::is_none"
)]
pub subscriber_ids: Option<Vec<String>>,
}
#[derive(Debug, Clone, Default, Serialize)]
pub struct MessagingScheduling {
#[serde(
rename = "deliveryType",
default,
skip_serializing_if = "Option::is_none"
)]
pub delivery_type: Option<String>,
#[serde(rename = "scheduledAt", default, skip_serializing_if = "Option::is_none")]
pub scheduled_at: Option<String>,
#[serde(rename = "windowStart", default, skip_serializing_if = "Option::is_none")]
pub window_start: Option<String>,
#[serde(rename = "windowEnd", default, skip_serializing_if = "Option::is_none")]
pub window_end: Option<String>,
}
#[derive(Debug, Clone)]
pub struct DispatchParams {
pub project_id: String,
pub channel: String,
pub content: Properties,
pub targeting: Option<MessagingTargeting>,
pub scheduling: Option<MessagingScheduling>,
pub template_id: Option<String>,
pub access_token: String,
}
#[derive(Debug, Clone, Default)]
pub struct LlmTraceParams {
pub trace_id: String,
pub span_id: String,
pub parent_span_id: Option<String>,
pub model: String,
pub input_text: String,
pub output_text: String,
pub prompt_tokens: Option<u64>,
pub completion_tokens: Option<u64>,
pub duration_ms: Option<u64>,
pub cost_usd: Option<f64>,
pub properties: Option<Properties>,
pub metadata: Option<Properties>,
pub timestamp: Option<String>,
}