trailbase-wasm-common 0.3.1

WASM runtime for the TrailBase framework
Documentation
#![forbid(unsafe_code, clippy::unwrap_used)]
#![allow(clippy::needless_return)]
#![warn(clippy::await_holding_lock, clippy::inefficient_to_string)]

use serde::{Deserialize, Serialize};
use trailbase_sqlvalue::SqlValue;
use ts_rs::TS;

pub mod manifest;

#[derive(Clone, Debug, Deserialize, Serialize, TS)]
#[ts(export)]
pub struct SqliteRequest {
  pub query: String,
  pub params: Vec<SqlValue>,
}

#[derive(Clone, Debug, Deserialize, Serialize, TS)]
#[ts(export)]
pub enum SqliteResponse {
  Query { rows: Vec<Vec<SqlValue>> },
  Execute { rows_affected: usize },
  Error(String),
  TxBegin,
  TxCommit,
  TxRollback,
}

#[derive(Clone, Debug, Deserialize, Serialize)]
pub enum PrefsRequest {
  Get { key: String },
  Set { key: String, value: Option<String> },
}

#[derive(Clone, Debug, Deserialize, Serialize, TS)]
pub enum PrefsResponse {
  Ok,
  Value(Option<String>),
  Error(String),
}

/// Used to pass extra information from host to guest via an HTTP request header "__context".
#[derive(Clone, Debug, Deserialize, Serialize, TS)]
#[ts(export)]
pub struct HttpContext {
  pub kind: HttpContextKind,
  pub registered_path: String,
  pub path_params: Vec<(String, String)>,
  pub user: Option<HttpContextUser>,
}

#[derive(Clone, Debug, Deserialize, Serialize, TS)]
pub enum HttpContextKind {
  /// An incoming http request.
  Http,
  /// An incoming job request.
  Job,
  // Fallback
  #[serde(other)]
  Unknown,
}

#[derive(Clone, Debug, Deserialize, Serialize, TS)]
pub struct HttpContextUser {
  // Host encodes with padded BASE64_URL_SAFE, but the guest's `is_admin` decodes
  // with URL_SAFE_NO_PAD which rejects trailing `=`. Strip on deserialize.
  pub id: String,
  /// E-mail of the current user.
  pub email: Option<String>,
  /// Username of the current user.
  pub username: Option<String>,
  /// The "expected" CSRF token as included in the auth token claims [User] was constructed from.
  pub csrf_token: String,
}

#[inline]
pub fn component_path_to_name(path: &std::path::Path) -> Result<String, String> {
  return Ok(
    path
      .file_stem()
      .and_then(|s| s.to_str())
      .ok_or_else(|| format!("failed to get component name from '{path:?}'"))?
      .to_string(),
  );
}