#![allow(clippy::all, unused_imports, dead_code)]
use crate::{Actor, ActorBehavior, Message, Port};
use anyhow::{Error, Result};
use reflow_actor::{message::EncodableValue, ActorContext};
use reflow_actor_macro::actor;
use serde_json::{json, Value};
use std::collections::HashMap;
use std::time::Duration;
const BASE_URL: &str = "https://{project_ref}.supabase.co/rest/v1";
const ENV_KEY: &str = "SUPABASE_API_KEY";
fn apply_auth(
config: &reflow_actor::ActorConfig,
mut builder: reqwest::RequestBuilder,
) -> Result<reqwest::RequestBuilder> {
let credential = config
.get_config_or_env(ENV_KEY)
.ok_or_else(|| anyhow::anyhow!("Missing env var: {}", ENV_KEY))?;
builder = builder.header("apikey", &credential);
Ok(builder)
}
#[actor(
SupabaseCreateRecordActor,
inports::<100>(table),
outports::<50>(response, error),
state(MemoryState)
)]
pub async fn supabase_create_record(
context: ActorContext,
) -> Result<HashMap<String, Message>, Error> {
let inputs = context.get_payload();
let actor_config = context.get_config();
let mut endpoint = "/{table}".to_string();
if let Some(val) = inputs.get("table") {
endpoint = endpoint.replace("{{table}}", &super::message_to_str(val));
}
let url = format!("{}{}", BASE_URL.trim_end_matches('/'), endpoint);
let client = reqwest::Client::builder()
.timeout(Duration::from_secs(30))
.build()?;
let mut builder = client.post(&url);
builder = builder.header("Content-Type", "application/json");
builder = apply_auth(actor_config, builder)?;
let mut output = HashMap::new();
match builder.send().await {
Ok(resp) => {
let status = resp.status().as_u16();
let headers: HashMap<String, String> = resp
.headers()
.iter()
.filter_map(|(k, v)| v.to_str().ok().map(|val| (k.to_string(), val.to_string())))
.collect();
let body_text = resp.text().await.unwrap_or_default();
let body_value: Value =
serde_json::from_str(&body_text).unwrap_or(Value::String(body_text));
output.insert(
"response".to_string(),
Message::object(EncodableValue::from(json!({
"status": status,
"headers": headers,
"body": body_value,
}))),
);
}
Err(e) => {
output.insert(
"error".to_string(),
Message::Error(format!("POST /{{table}} failed: {}", e).into()),
);
}
}
Ok(output)
}
#[actor(
SupabaseReadRecordsActor,
inports::<100>(table, select),
outports::<50>(response, error),
state(MemoryState)
)]
pub async fn supabase_read_records(
context: ActorContext,
) -> Result<HashMap<String, Message>, Error> {
let inputs = context.get_payload();
let actor_config = context.get_config();
let mut endpoint = "/{table}".to_string();
if let Some(val) = inputs.get("table") {
endpoint = endpoint.replace("{{table}}", &super::message_to_str(val));
}
let url = format!("{}{}", BASE_URL.trim_end_matches('/'), endpoint);
let client = reqwest::Client::builder()
.timeout(Duration::from_secs(30))
.build()?;
let mut builder = client.get(&url);
builder = builder.header("Content-Type", "application/json");
builder = apply_auth(actor_config, builder)?;
let mut query_pairs: Vec<(&str, String)> = Vec::new();
if let Some(val) = inputs.get("select") {
query_pairs.push(("select", super::message_to_str(val)));
}
if !query_pairs.is_empty() {
builder = builder.query(&query_pairs);
}
let mut output = HashMap::new();
match builder.send().await {
Ok(resp) => {
let status = resp.status().as_u16();
let headers: HashMap<String, String> = resp
.headers()
.iter()
.filter_map(|(k, v)| v.to_str().ok().map(|val| (k.to_string(), val.to_string())))
.collect();
let body_text = resp.text().await.unwrap_or_default();
let body_value: Value =
serde_json::from_str(&body_text).unwrap_or(Value::String(body_text));
output.insert(
"response".to_string(),
Message::object(EncodableValue::from(json!({
"status": status,
"headers": headers,
"body": body_value,
}))),
);
}
Err(e) => {
output.insert(
"error".to_string(),
Message::Error(format!("GET /{{table}} failed: {}", e).into()),
);
}
}
Ok(output)
}
#[actor(
SupabaseListRowsActor,
inports::<100>(table, select, order, limit, offset, apikey, Authorization),
outports::<50>(response, error),
state(MemoryState)
)]
pub async fn supabase_list_rows(context: ActorContext) -> Result<HashMap<String, Message>, Error> {
let inputs = context.get_payload();
let actor_config = context.get_config();
let mut endpoint = "/{table}".to_string();
if let Some(val) = inputs.get("table") {
endpoint = endpoint.replace("{{table}}", &super::message_to_str(val));
}
let url = format!("{}{}", BASE_URL.trim_end_matches('/'), endpoint);
let client = reqwest::Client::builder()
.timeout(Duration::from_secs(30))
.build()?;
let mut builder = client.get(&url);
builder = builder.header("Content-Type", "application/json");
builder = apply_auth(actor_config, builder)?;
let mut query_pairs: Vec<(&str, String)> = Vec::new();
if let Some(val) = inputs.get("select") {
query_pairs.push(("select", super::message_to_str(val)));
}
if let Some(val) = inputs.get("order") {
query_pairs.push(("order", super::message_to_str(val)));
}
if let Some(val) = inputs.get("limit") {
query_pairs.push(("limit", super::message_to_str(val)));
}
if let Some(val) = inputs.get("offset") {
query_pairs.push(("offset", super::message_to_str(val)));
}
if !query_pairs.is_empty() {
builder = builder.query(&query_pairs);
}
if let Some(val) = inputs.get("apikey") {
builder = builder.header("apikey", super::message_to_str(val));
}
if let Some(val) = inputs.get("Authorization") {
builder = builder.header("Authorization", super::message_to_str(val));
}
let mut output = HashMap::new();
match builder.send().await {
Ok(resp) => {
let status = resp.status().as_u16();
let headers: HashMap<String, String> = resp
.headers()
.iter()
.filter_map(|(k, v)| v.to_str().ok().map(|val| (k.to_string(), val.to_string())))
.collect();
let body_text = resp.text().await.unwrap_or_default();
let body_value: Value =
serde_json::from_str(&body_text).unwrap_or(Value::String(body_text));
output.insert(
"response".to_string(),
Message::object(EncodableValue::from(json!({
"status": status,
"headers": headers,
"body": body_value,
}))),
);
}
Err(e) => {
output.insert(
"error".to_string(),
Message::Error(format!("GET /{{table}} failed: {}", e).into()),
);
}
}
Ok(output)
}
#[actor(
SupabaseCreateRowActor,
inports::<100>(table, Prefer, apikey),
outports::<50>(response, error),
state(MemoryState)
)]
pub async fn supabase_create_row(context: ActorContext) -> Result<HashMap<String, Message>, Error> {
let inputs = context.get_payload();
let actor_config = context.get_config();
let mut endpoint = "/{table}".to_string();
if let Some(val) = inputs.get("table") {
endpoint = endpoint.replace("{{table}}", &super::message_to_str(val));
}
let url = format!("{}{}", BASE_URL.trim_end_matches('/'), endpoint);
let client = reqwest::Client::builder()
.timeout(Duration::from_secs(30))
.build()?;
let mut builder = client.post(&url);
builder = builder.header("Content-Type", "application/json");
builder = apply_auth(actor_config, builder)?;
if let Some(val) = inputs.get("Prefer") {
builder = builder.header("Prefer", super::message_to_str(val));
}
if let Some(val) = inputs.get("apikey") {
builder = builder.header("apikey", super::message_to_str(val));
}
let mut output = HashMap::new();
match builder.send().await {
Ok(resp) => {
let status = resp.status().as_u16();
let headers: HashMap<String, String> = resp
.headers()
.iter()
.filter_map(|(k, v)| v.to_str().ok().map(|val| (k.to_string(), val.to_string())))
.collect();
let body_text = resp.text().await.unwrap_or_default();
let body_value: Value =
serde_json::from_str(&body_text).unwrap_or(Value::String(body_text));
output.insert(
"response".to_string(),
Message::object(EncodableValue::from(json!({
"status": status,
"headers": headers,
"body": body_value,
}))),
);
}
Err(e) => {
output.insert(
"error".to_string(),
Message::Error(format!("POST /{{table}} failed: {}", e).into()),
);
}
}
Ok(output)
}
#[actor(
SupabaseUpdateRowActor,
inports::<100>(table, Prefer, apikey),
outports::<50>(response, error),
state(MemoryState)
)]
pub async fn supabase_update_row(context: ActorContext) -> Result<HashMap<String, Message>, Error> {
let inputs = context.get_payload();
let actor_config = context.get_config();
let mut endpoint = "/{table}".to_string();
if let Some(val) = inputs.get("table") {
endpoint = endpoint.replace("{{table}}", &super::message_to_str(val));
}
let url = format!("{}{}", BASE_URL.trim_end_matches('/'), endpoint);
let client = reqwest::Client::builder()
.timeout(Duration::from_secs(30))
.build()?;
let mut builder = client.patch(&url);
builder = builder.header("Content-Type", "application/json");
builder = apply_auth(actor_config, builder)?;
if let Some(val) = inputs.get("Prefer") {
builder = builder.header("Prefer", super::message_to_str(val));
}
if let Some(val) = inputs.get("apikey") {
builder = builder.header("apikey", super::message_to_str(val));
}
let mut output = HashMap::new();
match builder.send().await {
Ok(resp) => {
let status = resp.status().as_u16();
let headers: HashMap<String, String> = resp
.headers()
.iter()
.filter_map(|(k, v)| v.to_str().ok().map(|val| (k.to_string(), val.to_string())))
.collect();
let body_text = resp.text().await.unwrap_or_default();
let body_value: Value =
serde_json::from_str(&body_text).unwrap_or(Value::String(body_text));
output.insert(
"response".to_string(),
Message::object(EncodableValue::from(json!({
"status": status,
"headers": headers,
"body": body_value,
}))),
);
}
Err(e) => {
output.insert(
"error".to_string(),
Message::Error(format!("PATCH /{{table}} failed: {}", e).into()),
);
}
}
Ok(output)
}
#[actor(
SupabaseDeleteRowActor,
inports::<100>(table, Prefer, apikey),
outports::<50>(response, error),
state(MemoryState)
)]
pub async fn supabase_delete_row(context: ActorContext) -> Result<HashMap<String, Message>, Error> {
let inputs = context.get_payload();
let actor_config = context.get_config();
let mut endpoint = "/{table}".to_string();
if let Some(val) = inputs.get("table") {
endpoint = endpoint.replace("{{table}}", &super::message_to_str(val));
}
let url = format!("{}{}", BASE_URL.trim_end_matches('/'), endpoint);
let client = reqwest::Client::builder()
.timeout(Duration::from_secs(30))
.build()?;
let mut builder = client.delete(&url);
builder = builder.header("Content-Type", "application/json");
builder = apply_auth(actor_config, builder)?;
if let Some(val) = inputs.get("Prefer") {
builder = builder.header("Prefer", super::message_to_str(val));
}
if let Some(val) = inputs.get("apikey") {
builder = builder.header("apikey", super::message_to_str(val));
}
let mut output = HashMap::new();
match builder.send().await {
Ok(resp) => {
let status = resp.status().as_u16();
let headers: HashMap<String, String> = resp
.headers()
.iter()
.filter_map(|(k, v)| v.to_str().ok().map(|val| (k.to_string(), val.to_string())))
.collect();
let body_text = resp.text().await.unwrap_or_default();
let body_value: Value =
serde_json::from_str(&body_text).unwrap_or(Value::String(body_text));
output.insert(
"response".to_string(),
Message::object(EncodableValue::from(json!({
"status": status,
"headers": headers,
"body": body_value,
}))),
);
}
Err(e) => {
output.insert(
"error".to_string(),
Message::Error(format!("DELETE /{{table}} failed: {}", e).into()),
);
}
}
Ok(output)
}
#[actor(
SupabaseCreateAuthUserActor,
inports::<100>(email, password, data, apikey),
outports::<50>(response, error),
state(MemoryState)
)]
pub async fn supabase_create_auth_user(
context: ActorContext,
) -> Result<HashMap<String, Message>, Error> {
let inputs = context.get_payload();
let actor_config = context.get_config();
let endpoint = "/auth/v1/signup".to_string();
let url = format!("{}{}", BASE_URL.trim_end_matches('/'), endpoint);
let client = reqwest::Client::builder()
.timeout(Duration::from_secs(30))
.build()?;
let mut builder = client.post(&url);
builder = builder.header("Content-Type", "application/json");
builder = apply_auth(actor_config, builder)?;
if let Some(val) = inputs.get("apikey") {
builder = builder.header("apikey", super::message_to_str(val));
}
let mut body = serde_json::Map::new();
if let Some(val) = inputs.get("email") {
body.insert("email".to_string(), val.clone().into());
}
if let Some(val) = inputs.get("password") {
body.insert("password".to_string(), val.clone().into());
}
if let Some(val) = inputs.get("data") {
body.insert("data".to_string(), val.clone().into());
}
if !body.is_empty() {
builder = builder.json(&serde_json::Value::Object(body));
}
let mut output = HashMap::new();
match builder.send().await {
Ok(resp) => {
let status = resp.status().as_u16();
let headers: HashMap<String, String> = resp
.headers()
.iter()
.filter_map(|(k, v)| v.to_str().ok().map(|val| (k.to_string(), val.to_string())))
.collect();
let body_text = resp.text().await.unwrap_or_default();
let body_value: Value =
serde_json::from_str(&body_text).unwrap_or(Value::String(body_text));
output.insert(
"response".to_string(),
Message::object(EncodableValue::from(json!({
"status": status,
"headers": headers,
"body": body_value,
}))),
);
}
Err(e) => {
output.insert(
"error".to_string(),
Message::Error(format!("POST /auth/v1/signup failed: {}", e).into()),
);
}
}
Ok(output)
}
#[actor(
SupabaseCreateAuthSessionActor,
inports::<100>(grant_type, email, password, refresh_token, apikey),
outports::<50>(response, error),
state(MemoryState)
)]
pub async fn supabase_create_auth_session(
context: ActorContext,
) -> Result<HashMap<String, Message>, Error> {
let inputs = context.get_payload();
let actor_config = context.get_config();
let endpoint = "/auth/v1/token".to_string();
let url = format!("{}{}", BASE_URL.trim_end_matches('/'), endpoint);
let client = reqwest::Client::builder()
.timeout(Duration::from_secs(30))
.build()?;
let mut builder = client.post(&url);
builder = builder.header("Content-Type", "application/json");
builder = apply_auth(actor_config, builder)?;
let mut query_pairs: Vec<(&str, String)> = Vec::new();
if let Some(val) = inputs.get("grant_type") {
query_pairs.push(("grant_type", super::message_to_str(val)));
}
if !query_pairs.is_empty() {
builder = builder.query(&query_pairs);
}
if let Some(val) = inputs.get("apikey") {
builder = builder.header("apikey", super::message_to_str(val));
}
let mut body = serde_json::Map::new();
if let Some(val) = inputs.get("email") {
body.insert("email".to_string(), val.clone().into());
}
if let Some(val) = inputs.get("password") {
body.insert("password".to_string(), val.clone().into());
}
if let Some(val) = inputs.get("refresh_token") {
body.insert("refresh_token".to_string(), val.clone().into());
}
if !body.is_empty() {
builder = builder.json(&serde_json::Value::Object(body));
}
let mut output = HashMap::new();
match builder.send().await {
Ok(resp) => {
let status = resp.status().as_u16();
let headers: HashMap<String, String> = resp
.headers()
.iter()
.filter_map(|(k, v)| v.to_str().ok().map(|val| (k.to_string(), val.to_string())))
.collect();
let body_text = resp.text().await.unwrap_or_default();
let body_value: Value =
serde_json::from_str(&body_text).unwrap_or(Value::String(body_text));
output.insert(
"response".to_string(),
Message::object(EncodableValue::from(json!({
"status": status,
"headers": headers,
"body": body_value,
}))),
);
}
Err(e) => {
output.insert(
"error".to_string(),
Message::Error(format!("POST /auth/v1/token failed: {}", e).into()),
);
}
}
Ok(output)
}
#[actor(
SupabaseDeleteAuthSessionActor,
inports::<100>(Authorization, apikey),
outports::<50>(response, error),
state(MemoryState)
)]
pub async fn supabase_delete_auth_session(
context: ActorContext,
) -> Result<HashMap<String, Message>, Error> {
let inputs = context.get_payload();
let actor_config = context.get_config();
let endpoint = "/auth/v1/logout".to_string();
let url = format!("{}{}", BASE_URL.trim_end_matches('/'), endpoint);
let client = reqwest::Client::builder()
.timeout(Duration::from_secs(30))
.build()?;
let mut builder = client.post(&url);
builder = builder.header("Content-Type", "application/json");
builder = apply_auth(actor_config, builder)?;
if let Some(val) = inputs.get("Authorization") {
builder = builder.header("Authorization", super::message_to_str(val));
}
if let Some(val) = inputs.get("apikey") {
builder = builder.header("apikey", super::message_to_str(val));
}
let mut output = HashMap::new();
match builder.send().await {
Ok(resp) => {
let status = resp.status().as_u16();
let headers: HashMap<String, String> = resp
.headers()
.iter()
.filter_map(|(k, v)| v.to_str().ok().map(|val| (k.to_string(), val.to_string())))
.collect();
let body_text = resp.text().await.unwrap_or_default();
let body_value: Value =
serde_json::from_str(&body_text).unwrap_or(Value::String(body_text));
output.insert(
"response".to_string(),
Message::object(EncodableValue::from(json!({
"status": status,
"headers": headers,
"body": body_value,
}))),
);
}
Err(e) => {
output.insert(
"error".to_string(),
Message::Error(format!("POST /auth/v1/logout failed: {}", e).into()),
);
}
}
Ok(output)
}
#[actor(
SupabaseReadAuthUserActor,
inports::<100>(Authorization, apikey),
outports::<50>(response, error),
state(MemoryState)
)]
pub async fn supabase_read_auth_user(
context: ActorContext,
) -> Result<HashMap<String, Message>, Error> {
let inputs = context.get_payload();
let actor_config = context.get_config();
let endpoint = "/auth/v1/user".to_string();
let url = format!("{}{}", BASE_URL.trim_end_matches('/'), endpoint);
let client = reqwest::Client::builder()
.timeout(Duration::from_secs(30))
.build()?;
let mut builder = client.get(&url);
builder = builder.header("Content-Type", "application/json");
builder = apply_auth(actor_config, builder)?;
if let Some(val) = inputs.get("Authorization") {
builder = builder.header("Authorization", super::message_to_str(val));
}
if let Some(val) = inputs.get("apikey") {
builder = builder.header("apikey", super::message_to_str(val));
}
let mut output = HashMap::new();
match builder.send().await {
Ok(resp) => {
let status = resp.status().as_u16();
let headers: HashMap<String, String> = resp
.headers()
.iter()
.filter_map(|(k, v)| v.to_str().ok().map(|val| (k.to_string(), val.to_string())))
.collect();
let body_text = resp.text().await.unwrap_or_default();
let body_value: Value =
serde_json::from_str(&body_text).unwrap_or(Value::String(body_text));
output.insert(
"response".to_string(),
Message::object(EncodableValue::from(json!({
"status": status,
"headers": headers,
"body": body_value,
}))),
);
}
Err(e) => {
output.insert(
"error".to_string(),
Message::Error(format!("GET /auth/v1/user failed: {}", e).into()),
);
}
}
Ok(output)
}
#[actor(
SupabaseUpdateAuthUserActor,
inports::<100>(email, password, data, Authorization, apikey),
outports::<50>(response, error),
state(MemoryState)
)]
pub async fn supabase_update_auth_user(
context: ActorContext,
) -> Result<HashMap<String, Message>, Error> {
let inputs = context.get_payload();
let actor_config = context.get_config();
let endpoint = "/auth/v1/user".to_string();
let url = format!("{}{}", BASE_URL.trim_end_matches('/'), endpoint);
let client = reqwest::Client::builder()
.timeout(Duration::from_secs(30))
.build()?;
let mut builder = client.put(&url);
builder = builder.header("Content-Type", "application/json");
builder = apply_auth(actor_config, builder)?;
if let Some(val) = inputs.get("Authorization") {
builder = builder.header("Authorization", super::message_to_str(val));
}
if let Some(val) = inputs.get("apikey") {
builder = builder.header("apikey", super::message_to_str(val));
}
let mut body = serde_json::Map::new();
if let Some(val) = inputs.get("email") {
body.insert("email".to_string(), val.clone().into());
}
if let Some(val) = inputs.get("password") {
body.insert("password".to_string(), val.clone().into());
}
if let Some(val) = inputs.get("data") {
body.insert("data".to_string(), val.clone().into());
}
if !body.is_empty() {
builder = builder.json(&serde_json::Value::Object(body));
}
let mut output = HashMap::new();
match builder.send().await {
Ok(resp) => {
let status = resp.status().as_u16();
let headers: HashMap<String, String> = resp
.headers()
.iter()
.filter_map(|(k, v)| v.to_str().ok().map(|val| (k.to_string(), val.to_string())))
.collect();
let body_text = resp.text().await.unwrap_or_default();
let body_value: Value =
serde_json::from_str(&body_text).unwrap_or(Value::String(body_text));
output.insert(
"response".to_string(),
Message::object(EncodableValue::from(json!({
"status": status,
"headers": headers,
"body": body_value,
}))),
);
}
Err(e) => {
output.insert(
"error".to_string(),
Message::Error(format!("PUT /auth/v1/user failed: {}", e).into()),
);
}
}
Ok(output)
}
#[actor(
SupabaseCreatePasswordRecoveryActor,
inports::<100>(email, apikey),
outports::<50>(response, error),
state(MemoryState)
)]
pub async fn supabase_create_password_recovery(
context: ActorContext,
) -> Result<HashMap<String, Message>, Error> {
let inputs = context.get_payload();
let actor_config = context.get_config();
let endpoint = "/auth/v1/recover".to_string();
let url = format!("{}{}", BASE_URL.trim_end_matches('/'), endpoint);
let client = reqwest::Client::builder()
.timeout(Duration::from_secs(30))
.build()?;
let mut builder = client.post(&url);
builder = builder.header("Content-Type", "application/json");
builder = apply_auth(actor_config, builder)?;
if let Some(val) = inputs.get("apikey") {
builder = builder.header("apikey", super::message_to_str(val));
}
let mut body = serde_json::Map::new();
if let Some(val) = inputs.get("email") {
body.insert("email".to_string(), val.clone().into());
}
if !body.is_empty() {
builder = builder.json(&serde_json::Value::Object(body));
}
let mut output = HashMap::new();
match builder.send().await {
Ok(resp) => {
let status = resp.status().as_u16();
let headers: HashMap<String, String> = resp
.headers()
.iter()
.filter_map(|(k, v)| v.to_str().ok().map(|val| (k.to_string(), val.to_string())))
.collect();
let body_text = resp.text().await.unwrap_or_default();
let body_value: Value =
serde_json::from_str(&body_text).unwrap_or(Value::String(body_text));
output.insert(
"response".to_string(),
Message::object(EncodableValue::from(json!({
"status": status,
"headers": headers,
"body": body_value,
}))),
);
}
Err(e) => {
output.insert(
"error".to_string(),
Message::Error(format!("POST /auth/v1/recover failed: {}", e).into()),
);
}
}
Ok(output)
}
#[actor(
SupabaseCreateMagicLinkActor,
inports::<100>(email, apikey),
outports::<50>(response, error),
state(MemoryState)
)]
pub async fn supabase_create_magic_link(
context: ActorContext,
) -> Result<HashMap<String, Message>, Error> {
let inputs = context.get_payload();
let actor_config = context.get_config();
let endpoint = "/auth/v1/magiclink".to_string();
let url = format!("{}{}", BASE_URL.trim_end_matches('/'), endpoint);
let client = reqwest::Client::builder()
.timeout(Duration::from_secs(30))
.build()?;
let mut builder = client.post(&url);
builder = builder.header("Content-Type", "application/json");
builder = apply_auth(actor_config, builder)?;
if let Some(val) = inputs.get("apikey") {
builder = builder.header("apikey", super::message_to_str(val));
}
let mut body = serde_json::Map::new();
if let Some(val) = inputs.get("email") {
body.insert("email".to_string(), val.clone().into());
}
if !body.is_empty() {
builder = builder.json(&serde_json::Value::Object(body));
}
let mut output = HashMap::new();
match builder.send().await {
Ok(resp) => {
let status = resp.status().as_u16();
let headers: HashMap<String, String> = resp
.headers()
.iter()
.filter_map(|(k, v)| v.to_str().ok().map(|val| (k.to_string(), val.to_string())))
.collect();
let body_text = resp.text().await.unwrap_or_default();
let body_value: Value =
serde_json::from_str(&body_text).unwrap_or(Value::String(body_text));
output.insert(
"response".to_string(),
Message::object(EncodableValue::from(json!({
"status": status,
"headers": headers,
"body": body_value,
}))),
);
}
Err(e) => {
output.insert(
"error".to_string(),
Message::Error(format!("POST /auth/v1/magiclink failed: {}", e).into()),
);
}
}
Ok(output)
}
#[actor(
SupabaseCreateOtpActor,
inports::<100>(phone, email, apikey),
outports::<50>(response, error),
state(MemoryState)
)]
pub async fn supabase_create_otp(context: ActorContext) -> Result<HashMap<String, Message>, Error> {
let inputs = context.get_payload();
let actor_config = context.get_config();
let endpoint = "/auth/v1/otp".to_string();
let url = format!("{}{}", BASE_URL.trim_end_matches('/'), endpoint);
let client = reqwest::Client::builder()
.timeout(Duration::from_secs(30))
.build()?;
let mut builder = client.post(&url);
builder = builder.header("Content-Type", "application/json");
builder = apply_auth(actor_config, builder)?;
if let Some(val) = inputs.get("apikey") {
builder = builder.header("apikey", super::message_to_str(val));
}
let mut body = serde_json::Map::new();
if let Some(val) = inputs.get("phone") {
body.insert("phone".to_string(), val.clone().into());
}
if let Some(val) = inputs.get("email") {
body.insert("email".to_string(), val.clone().into());
}
if !body.is_empty() {
builder = builder.json(&serde_json::Value::Object(body));
}
let mut output = HashMap::new();
match builder.send().await {
Ok(resp) => {
let status = resp.status().as_u16();
let headers: HashMap<String, String> = resp
.headers()
.iter()
.filter_map(|(k, v)| v.to_str().ok().map(|val| (k.to_string(), val.to_string())))
.collect();
let body_text = resp.text().await.unwrap_or_default();
let body_value: Value =
serde_json::from_str(&body_text).unwrap_or(Value::String(body_text));
output.insert(
"response".to_string(),
Message::object(EncodableValue::from(json!({
"status": status,
"headers": headers,
"body": body_value,
}))),
);
}
Err(e) => {
output.insert(
"error".to_string(),
Message::Error(format!("POST /auth/v1/otp failed: {}", e).into()),
);
}
}
Ok(output)
}
#[actor(
SupabaseListStorageBucketsActor,
inports::<100>(Authorization, apikey),
outports::<50>(response, error),
state(MemoryState)
)]
pub async fn supabase_list_storage_buckets(
context: ActorContext,
) -> Result<HashMap<String, Message>, Error> {
let inputs = context.get_payload();
let actor_config = context.get_config();
let endpoint = "/storage/v1/bucket".to_string();
let url = format!("{}{}", BASE_URL.trim_end_matches('/'), endpoint);
let client = reqwest::Client::builder()
.timeout(Duration::from_secs(30))
.build()?;
let mut builder = client.get(&url);
builder = builder.header("Content-Type", "application/json");
builder = apply_auth(actor_config, builder)?;
if let Some(val) = inputs.get("Authorization") {
builder = builder.header("Authorization", super::message_to_str(val));
}
if let Some(val) = inputs.get("apikey") {
builder = builder.header("apikey", super::message_to_str(val));
}
let mut output = HashMap::new();
match builder.send().await {
Ok(resp) => {
let status = resp.status().as_u16();
let headers: HashMap<String, String> = resp
.headers()
.iter()
.filter_map(|(k, v)| v.to_str().ok().map(|val| (k.to_string(), val.to_string())))
.collect();
let body_text = resp.text().await.unwrap_or_default();
let body_value: Value =
serde_json::from_str(&body_text).unwrap_or(Value::String(body_text));
output.insert(
"response".to_string(),
Message::object(EncodableValue::from(json!({
"status": status,
"headers": headers,
"body": body_value,
}))),
);
}
Err(e) => {
output.insert(
"error".to_string(),
Message::Error(format!("GET /storage/v1/bucket failed: {}", e).into()),
);
}
}
Ok(output)
}
#[actor(
SupabaseCreateStorageBucketActor,
inports::<100>(id, name, public, file_size_limit, allowed_mime_types, apikey),
outports::<50>(response, error),
state(MemoryState)
)]
pub async fn supabase_create_storage_bucket(
context: ActorContext,
) -> Result<HashMap<String, Message>, Error> {
let inputs = context.get_payload();
let actor_config = context.get_config();
let endpoint = "/storage/v1/bucket".to_string();
let url = format!("{}{}", BASE_URL.trim_end_matches('/'), endpoint);
let client = reqwest::Client::builder()
.timeout(Duration::from_secs(30))
.build()?;
let mut builder = client.post(&url);
builder = builder.header("Content-Type", "application/json");
builder = apply_auth(actor_config, builder)?;
if let Some(val) = inputs.get("apikey") {
builder = builder.header("apikey", super::message_to_str(val));
}
let mut body = serde_json::Map::new();
if let Some(val) = inputs.get("id") {
body.insert("id".to_string(), val.clone().into());
}
if let Some(val) = inputs.get("name") {
body.insert("name".to_string(), val.clone().into());
}
if let Some(val) = inputs.get("public") {
body.insert("public".to_string(), val.clone().into());
}
if let Some(val) = inputs.get("file_size_limit") {
body.insert("file_size_limit".to_string(), val.clone().into());
}
if let Some(val) = inputs.get("allowed_mime_types") {
body.insert("allowed_mime_types".to_string(), val.clone().into());
}
if !body.is_empty() {
builder = builder.json(&serde_json::Value::Object(body));
}
let mut output = HashMap::new();
match builder.send().await {
Ok(resp) => {
let status = resp.status().as_u16();
let headers: HashMap<String, String> = resp
.headers()
.iter()
.filter_map(|(k, v)| v.to_str().ok().map(|val| (k.to_string(), val.to_string())))
.collect();
let body_text = resp.text().await.unwrap_or_default();
let body_value: Value =
serde_json::from_str(&body_text).unwrap_or(Value::String(body_text));
output.insert(
"response".to_string(),
Message::object(EncodableValue::from(json!({
"status": status,
"headers": headers,
"body": body_value,
}))),
);
}
Err(e) => {
output.insert(
"error".to_string(),
Message::Error(format!("POST /storage/v1/bucket failed: {}", e).into()),
);
}
}
Ok(output)
}
#[actor(
SupabaseReadStorageBucketActor,
inports::<100>(bucket_id, apikey),
outports::<50>(response, error),
state(MemoryState)
)]
pub async fn supabase_read_storage_bucket(
context: ActorContext,
) -> Result<HashMap<String, Message>, Error> {
let inputs = context.get_payload();
let actor_config = context.get_config();
let mut endpoint = "/storage/v1/bucket/{bucket_id}".to_string();
if let Some(val) = inputs.get("bucket_id") {
endpoint = endpoint.replace("{{bucket_id}}", &super::message_to_str(val));
}
let url = format!("{}{}", BASE_URL.trim_end_matches('/'), endpoint);
let client = reqwest::Client::builder()
.timeout(Duration::from_secs(30))
.build()?;
let mut builder = client.get(&url);
builder = builder.header("Content-Type", "application/json");
builder = apply_auth(actor_config, builder)?;
if let Some(val) = inputs.get("apikey") {
builder = builder.header("apikey", super::message_to_str(val));
}
let mut output = HashMap::new();
match builder.send().await {
Ok(resp) => {
let status = resp.status().as_u16();
let headers: HashMap<String, String> = resp
.headers()
.iter()
.filter_map(|(k, v)| v.to_str().ok().map(|val| (k.to_string(), val.to_string())))
.collect();
let body_text = resp.text().await.unwrap_or_default();
let body_value: Value =
serde_json::from_str(&body_text).unwrap_or(Value::String(body_text));
output.insert(
"response".to_string(),
Message::object(EncodableValue::from(json!({
"status": status,
"headers": headers,
"body": body_value,
}))),
);
}
Err(e) => {
output.insert(
"error".to_string(),
Message::Error(
format!("GET /storage/v1/bucket/{{bucket_id}} failed: {}", e).into(),
),
);
}
}
Ok(output)
}
#[actor(
SupabaseUpdateStorageBucketActor,
inports::<100>(bucket_id, public, file_size_limit, allowed_mime_types, apikey),
outports::<50>(response, error),
state(MemoryState)
)]
pub async fn supabase_update_storage_bucket(
context: ActorContext,
) -> Result<HashMap<String, Message>, Error> {
let inputs = context.get_payload();
let actor_config = context.get_config();
let mut endpoint = "/storage/v1/bucket/{bucket_id}".to_string();
if let Some(val) = inputs.get("bucket_id") {
endpoint = endpoint.replace("{{bucket_id}}", &super::message_to_str(val));
}
let url = format!("{}{}", BASE_URL.trim_end_matches('/'), endpoint);
let client = reqwest::Client::builder()
.timeout(Duration::from_secs(30))
.build()?;
let mut builder = client.put(&url);
builder = builder.header("Content-Type", "application/json");
builder = apply_auth(actor_config, builder)?;
if let Some(val) = inputs.get("apikey") {
builder = builder.header("apikey", super::message_to_str(val));
}
let mut body = serde_json::Map::new();
if let Some(val) = inputs.get("public") {
body.insert("public".to_string(), val.clone().into());
}
if let Some(val) = inputs.get("file_size_limit") {
body.insert("file_size_limit".to_string(), val.clone().into());
}
if let Some(val) = inputs.get("allowed_mime_types") {
body.insert("allowed_mime_types".to_string(), val.clone().into());
}
if !body.is_empty() {
builder = builder.json(&serde_json::Value::Object(body));
}
let mut output = HashMap::new();
match builder.send().await {
Ok(resp) => {
let status = resp.status().as_u16();
let headers: HashMap<String, String> = resp
.headers()
.iter()
.filter_map(|(k, v)| v.to_str().ok().map(|val| (k.to_string(), val.to_string())))
.collect();
let body_text = resp.text().await.unwrap_or_default();
let body_value: Value =
serde_json::from_str(&body_text).unwrap_or(Value::String(body_text));
output.insert(
"response".to_string(),
Message::object(EncodableValue::from(json!({
"status": status,
"headers": headers,
"body": body_value,
}))),
);
}
Err(e) => {
output.insert(
"error".to_string(),
Message::Error(
format!("PUT /storage/v1/bucket/{{bucket_id}} failed: {}", e).into(),
),
);
}
}
Ok(output)
}
#[actor(
SupabaseDeleteStorageBucketActor,
inports::<100>(bucket_id, apikey),
outports::<50>(response, error),
state(MemoryState)
)]
pub async fn supabase_delete_storage_bucket(
context: ActorContext,
) -> Result<HashMap<String, Message>, Error> {
let inputs = context.get_payload();
let actor_config = context.get_config();
let mut endpoint = "/storage/v1/bucket/{bucket_id}".to_string();
if let Some(val) = inputs.get("bucket_id") {
endpoint = endpoint.replace("{{bucket_id}}", &super::message_to_str(val));
}
let url = format!("{}{}", BASE_URL.trim_end_matches('/'), endpoint);
let client = reqwest::Client::builder()
.timeout(Duration::from_secs(30))
.build()?;
let mut builder = client.delete(&url);
builder = builder.header("Content-Type", "application/json");
builder = apply_auth(actor_config, builder)?;
if let Some(val) = inputs.get("apikey") {
builder = builder.header("apikey", super::message_to_str(val));
}
let mut output = HashMap::new();
match builder.send().await {
Ok(resp) => {
let status = resp.status().as_u16();
let headers: HashMap<String, String> = resp
.headers()
.iter()
.filter_map(|(k, v)| v.to_str().ok().map(|val| (k.to_string(), val.to_string())))
.collect();
let body_text = resp.text().await.unwrap_or_default();
let body_value: Value =
serde_json::from_str(&body_text).unwrap_or(Value::String(body_text));
output.insert(
"response".to_string(),
Message::object(EncodableValue::from(json!({
"status": status,
"headers": headers,
"body": body_value,
}))),
);
}
Err(e) => {
output.insert(
"error".to_string(),
Message::Error(
format!("DELETE /storage/v1/bucket/{{bucket_id}} failed: {}", e).into(),
),
);
}
}
Ok(output)
}
#[actor(
SupabaseUploadStorageObjectActor,
inports::<100>(bucket_id, object_path, Content_Type, x_upsert, apikey),
outports::<50>(response, error),
state(MemoryState)
)]
pub async fn supabase_upload_storage_object(
context: ActorContext,
) -> Result<HashMap<String, Message>, Error> {
let inputs = context.get_payload();
let actor_config = context.get_config();
let mut endpoint = "/storage/v1/object/{bucket_id}/{object_path}".to_string();
if let Some(val) = inputs.get("bucket_id") {
endpoint = endpoint.replace("{{bucket_id}}", &super::message_to_str(val));
}
if let Some(val) = inputs.get("object_path") {
endpoint = endpoint.replace("{{object_path}}", &super::message_to_str(val));
}
let url = format!("{}{}", BASE_URL.trim_end_matches('/'), endpoint);
let client = reqwest::Client::builder()
.timeout(Duration::from_secs(30))
.build()?;
let mut builder = client.post(&url);
builder = builder.header("Content-Type", "application/json");
builder = apply_auth(actor_config, builder)?;
if let Some(val) = inputs.get("Content_Type") {
builder = builder.header("Content-Type", super::message_to_str(val));
}
if let Some(val) = inputs.get("x_upsert") {
builder = builder.header("x-upsert", super::message_to_str(val));
}
if let Some(val) = inputs.get("apikey") {
builder = builder.header("apikey", super::message_to_str(val));
}
let mut output = HashMap::new();
match builder.send().await {
Ok(resp) => {
let status = resp.status().as_u16();
let headers: HashMap<String, String> = resp
.headers()
.iter()
.filter_map(|(k, v)| v.to_str().ok().map(|val| (k.to_string(), val.to_string())))
.collect();
let body_text = resp.text().await.unwrap_or_default();
let body_value: Value =
serde_json::from_str(&body_text).unwrap_or(Value::String(body_text));
output.insert(
"response".to_string(),
Message::object(EncodableValue::from(json!({
"status": status,
"headers": headers,
"body": body_value,
}))),
);
}
Err(e) => {
output.insert(
"error".to_string(),
Message::Error(
format!(
"POST /storage/v1/object/{{bucket_id}}/{{object_path}} failed: {}",
e
)
.into(),
),
);
}
}
Ok(output)
}
#[actor(
SupabaseDownloadStorageObjectActor,
inports::<100>(bucket_id, object_path, apikey),
outports::<50>(response, error),
state(MemoryState)
)]
pub async fn supabase_download_storage_object(
context: ActorContext,
) -> Result<HashMap<String, Message>, Error> {
let inputs = context.get_payload();
let actor_config = context.get_config();
let mut endpoint = "/storage/v1/object/{bucket_id}/{object_path}".to_string();
if let Some(val) = inputs.get("bucket_id") {
endpoint = endpoint.replace("{{bucket_id}}", &super::message_to_str(val));
}
if let Some(val) = inputs.get("object_path") {
endpoint = endpoint.replace("{{object_path}}", &super::message_to_str(val));
}
let url = format!("{}{}", BASE_URL.trim_end_matches('/'), endpoint);
let client = reqwest::Client::builder()
.timeout(Duration::from_secs(30))
.build()?;
let mut builder = client.get(&url);
builder = builder.header("Content-Type", "application/json");
builder = apply_auth(actor_config, builder)?;
if let Some(val) = inputs.get("apikey") {
builder = builder.header("apikey", super::message_to_str(val));
}
let mut output = HashMap::new();
match builder.send().await {
Ok(resp) => {
let status = resp.status().as_u16();
let headers: HashMap<String, String> = resp
.headers()
.iter()
.filter_map(|(k, v)| v.to_str().ok().map(|val| (k.to_string(), val.to_string())))
.collect();
let body_text = resp.text().await.unwrap_or_default();
let body_value: Value =
serde_json::from_str(&body_text).unwrap_or(Value::String(body_text));
output.insert(
"response".to_string(),
Message::object(EncodableValue::from(json!({
"status": status,
"headers": headers,
"body": body_value,
}))),
);
}
Err(e) => {
output.insert(
"error".to_string(),
Message::Error(
format!(
"GET /storage/v1/object/{{bucket_id}}/{{object_path}} failed: {}",
e
)
.into(),
),
);
}
}
Ok(output)
}
#[actor(
SupabaseDeleteStorageObjectActor,
inports::<100>(bucket_id, prefixes, apikey),
outports::<50>(response, error),
state(MemoryState)
)]
pub async fn supabase_delete_storage_object(
context: ActorContext,
) -> Result<HashMap<String, Message>, Error> {
let inputs = context.get_payload();
let actor_config = context.get_config();
let mut endpoint = "/storage/v1/object/{bucket_id}".to_string();
if let Some(val) = inputs.get("bucket_id") {
endpoint = endpoint.replace("{{bucket_id}}", &super::message_to_str(val));
}
let url = format!("{}{}", BASE_URL.trim_end_matches('/'), endpoint);
let client = reqwest::Client::builder()
.timeout(Duration::from_secs(30))
.build()?;
let mut builder = client.delete(&url);
builder = builder.header("Content-Type", "application/json");
builder = apply_auth(actor_config, builder)?;
if let Some(val) = inputs.get("apikey") {
builder = builder.header("apikey", super::message_to_str(val));
}
let mut output = HashMap::new();
match builder.send().await {
Ok(resp) => {
let status = resp.status().as_u16();
let headers: HashMap<String, String> = resp
.headers()
.iter()
.filter_map(|(k, v)| v.to_str().ok().map(|val| (k.to_string(), val.to_string())))
.collect();
let body_text = resp.text().await.unwrap_or_default();
let body_value: Value =
serde_json::from_str(&body_text).unwrap_or(Value::String(body_text));
output.insert(
"response".to_string(),
Message::object(EncodableValue::from(json!({
"status": status,
"headers": headers,
"body": body_value,
}))),
);
}
Err(e) => {
output.insert(
"error".to_string(),
Message::Error(
format!("DELETE /storage/v1/object/{{bucket_id}} failed: {}", e).into(),
),
);
}
}
Ok(output)
}
#[actor(
SupabaseListStorageObjectsActor,
inports::<100>(bucket_id, prefix, limit, offset, sortBy, apikey),
outports::<50>(response, error),
state(MemoryState)
)]
pub async fn supabase_list_storage_objects(
context: ActorContext,
) -> Result<HashMap<String, Message>, Error> {
let inputs = context.get_payload();
let actor_config = context.get_config();
let mut endpoint = "/storage/v1/object/list/{bucket_id}".to_string();
if let Some(val) = inputs.get("bucket_id") {
endpoint = endpoint.replace("{{bucket_id}}", &super::message_to_str(val));
}
let url = format!("{}{}", BASE_URL.trim_end_matches('/'), endpoint);
let client = reqwest::Client::builder()
.timeout(Duration::from_secs(30))
.build()?;
let mut builder = client.post(&url);
builder = builder.header("Content-Type", "application/json");
builder = apply_auth(actor_config, builder)?;
if let Some(val) = inputs.get("apikey") {
builder = builder.header("apikey", super::message_to_str(val));
}
let mut body = serde_json::Map::new();
if let Some(val) = inputs.get("prefix") {
body.insert("prefix".to_string(), val.clone().into());
}
if let Some(val) = inputs.get("limit") {
body.insert("limit".to_string(), val.clone().into());
}
if let Some(val) = inputs.get("offset") {
body.insert("offset".to_string(), val.clone().into());
}
if let Some(val) = inputs.get("sortBy") {
body.insert("sortBy".to_string(), val.clone().into());
}
if !body.is_empty() {
builder = builder.json(&serde_json::Value::Object(body));
}
let mut output = HashMap::new();
match builder.send().await {
Ok(resp) => {
let status = resp.status().as_u16();
let headers: HashMap<String, String> = resp
.headers()
.iter()
.filter_map(|(k, v)| v.to_str().ok().map(|val| (k.to_string(), val.to_string())))
.collect();
let body_text = resp.text().await.unwrap_or_default();
let body_value: Value =
serde_json::from_str(&body_text).unwrap_or(Value::String(body_text));
output.insert(
"response".to_string(),
Message::object(EncodableValue::from(json!({
"status": status,
"headers": headers,
"body": body_value,
}))),
);
}
Err(e) => {
output.insert(
"error".to_string(),
Message::Error(
format!("POST /storage/v1/object/list/{{bucket_id}} failed: {}", e).into(),
),
);
}
}
Ok(output)
}
#[actor(
SupabaseCreateStorageSignedUrlActor,
inports::<100>(bucket_id, object_path, expiresIn, apikey),
outports::<50>(response, error),
state(MemoryState)
)]
pub async fn supabase_create_storage_signed_url(
context: ActorContext,
) -> Result<HashMap<String, Message>, Error> {
let inputs = context.get_payload();
let actor_config = context.get_config();
let mut endpoint = "/storage/v1/object/sign/{bucket_id}/{object_path}".to_string();
if let Some(val) = inputs.get("bucket_id") {
endpoint = endpoint.replace("{{bucket_id}}", &super::message_to_str(val));
}
if let Some(val) = inputs.get("object_path") {
endpoint = endpoint.replace("{{object_path}}", &super::message_to_str(val));
}
let url = format!("{}{}", BASE_URL.trim_end_matches('/'), endpoint);
let client = reqwest::Client::builder()
.timeout(Duration::from_secs(30))
.build()?;
let mut builder = client.post(&url);
builder = builder.header("Content-Type", "application/json");
builder = apply_auth(actor_config, builder)?;
if let Some(val) = inputs.get("apikey") {
builder = builder.header("apikey", super::message_to_str(val));
}
let mut body = serde_json::Map::new();
if let Some(val) = inputs.get("expiresIn") {
body.insert("expiresIn".to_string(), val.clone().into());
}
if !body.is_empty() {
builder = builder.json(&serde_json::Value::Object(body));
}
let mut output = HashMap::new();
match builder.send().await {
Ok(resp) => {
let status = resp.status().as_u16();
let headers: HashMap<String, String> = resp
.headers()
.iter()
.filter_map(|(k, v)| v.to_str().ok().map(|val| (k.to_string(), val.to_string())))
.collect();
let body_text = resp.text().await.unwrap_or_default();
let body_value: Value =
serde_json::from_str(&body_text).unwrap_or(Value::String(body_text));
output.insert(
"response".to_string(),
Message::object(EncodableValue::from(json!({
"status": status,
"headers": headers,
"body": body_value,
}))),
);
}
Err(e) => {
output.insert(
"error".to_string(),
Message::Error(
format!(
"POST /storage/v1/object/sign/{{bucket_id}}/{{object_path}} failed: {}",
e
)
.into(),
),
);
}
}
Ok(output)
}
#[actor(
SupabaseCreateRpcActor,
inports::<100>(function_name, apikey),
outports::<50>(response, error),
state(MemoryState)
)]
pub async fn supabase_create_rpc(context: ActorContext) -> Result<HashMap<String, Message>, Error> {
let inputs = context.get_payload();
let actor_config = context.get_config();
let mut endpoint = "/rpc/{function_name}".to_string();
if let Some(val) = inputs.get("function_name") {
endpoint = endpoint.replace("{{function_name}}", &super::message_to_str(val));
}
let url = format!("{}{}", BASE_URL.trim_end_matches('/'), endpoint);
let client = reqwest::Client::builder()
.timeout(Duration::from_secs(30))
.build()?;
let mut builder = client.post(&url);
builder = builder.header("Content-Type", "application/json");
builder = apply_auth(actor_config, builder)?;
if let Some(val) = inputs.get("apikey") {
builder = builder.header("apikey", super::message_to_str(val));
}
let mut output = HashMap::new();
match builder.send().await {
Ok(resp) => {
let status = resp.status().as_u16();
let headers: HashMap<String, String> = resp
.headers()
.iter()
.filter_map(|(k, v)| v.to_str().ok().map(|val| (k.to_string(), val.to_string())))
.collect();
let body_text = resp.text().await.unwrap_or_default();
let body_value: Value =
serde_json::from_str(&body_text).unwrap_or(Value::String(body_text));
output.insert(
"response".to_string(),
Message::object(EncodableValue::from(json!({
"status": status,
"headers": headers,
"body": body_value,
}))),
);
}
Err(e) => {
output.insert(
"error".to_string(),
Message::Error(format!("POST /rpc/{{function_name}} failed: {}", e).into()),
);
}
}
Ok(output)
}
#[actor(
SupabaseListAuthUsersActor,
inports::<100>(page, per_page, apikey),
outports::<50>(response, error),
state(MemoryState)
)]
pub async fn supabase_list_auth_users(
context: ActorContext,
) -> Result<HashMap<String, Message>, Error> {
let inputs = context.get_payload();
let actor_config = context.get_config();
let endpoint = "/auth/v1/admin/users".to_string();
let url = format!("{}{}", BASE_URL.trim_end_matches('/'), endpoint);
let client = reqwest::Client::builder()
.timeout(Duration::from_secs(30))
.build()?;
let mut builder = client.get(&url);
builder = builder.header("Content-Type", "application/json");
builder = apply_auth(actor_config, builder)?;
let mut query_pairs: Vec<(&str, String)> = Vec::new();
if let Some(val) = inputs.get("page") {
query_pairs.push(("page", super::message_to_str(val)));
}
if let Some(val) = inputs.get("per_page") {
query_pairs.push(("per_page", super::message_to_str(val)));
}
if !query_pairs.is_empty() {
builder = builder.query(&query_pairs);
}
if let Some(val) = inputs.get("apikey") {
builder = builder.header("apikey", super::message_to_str(val));
}
let mut output = HashMap::new();
match builder.send().await {
Ok(resp) => {
let status = resp.status().as_u16();
let headers: HashMap<String, String> = resp
.headers()
.iter()
.filter_map(|(k, v)| v.to_str().ok().map(|val| (k.to_string(), val.to_string())))
.collect();
let body_text = resp.text().await.unwrap_or_default();
let body_value: Value =
serde_json::from_str(&body_text).unwrap_or(Value::String(body_text));
output.insert(
"response".to_string(),
Message::object(EncodableValue::from(json!({
"status": status,
"headers": headers,
"body": body_value,
}))),
);
}
Err(e) => {
output.insert(
"error".to_string(),
Message::Error(format!("GET /auth/v1/admin/users failed: {}", e).into()),
);
}
}
Ok(output)
}
#[actor(
SupabaseDeleteAuthUserActor,
inports::<100>(uid, apikey),
outports::<50>(response, error),
state(MemoryState)
)]
pub async fn supabase_delete_auth_user(
context: ActorContext,
) -> Result<HashMap<String, Message>, Error> {
let inputs = context.get_payload();
let actor_config = context.get_config();
let mut endpoint = "/auth/v1/admin/users/{uid}".to_string();
if let Some(val) = inputs.get("uid") {
endpoint = endpoint.replace("{{uid}}", &super::message_to_str(val));
}
let url = format!("{}{}", BASE_URL.trim_end_matches('/'), endpoint);
let client = reqwest::Client::builder()
.timeout(Duration::from_secs(30))
.build()?;
let mut builder = client.delete(&url);
builder = builder.header("Content-Type", "application/json");
builder = apply_auth(actor_config, builder)?;
if let Some(val) = inputs.get("apikey") {
builder = builder.header("apikey", super::message_to_str(val));
}
let mut output = HashMap::new();
match builder.send().await {
Ok(resp) => {
let status = resp.status().as_u16();
let headers: HashMap<String, String> = resp
.headers()
.iter()
.filter_map(|(k, v)| v.to_str().ok().map(|val| (k.to_string(), val.to_string())))
.collect();
let body_text = resp.text().await.unwrap_or_default();
let body_value: Value =
serde_json::from_str(&body_text).unwrap_or(Value::String(body_text));
output.insert(
"response".to_string(),
Message::object(EncodableValue::from(json!({
"status": status,
"headers": headers,
"body": body_value,
}))),
);
}
Err(e) => {
output.insert(
"error".to_string(),
Message::Error(format!("DELETE /auth/v1/admin/users/{{uid}} failed: {}", e).into()),
);
}
}
Ok(output)
}