briefcase-node 2.4.1

Node.js bindings for Briefcase AI
Documentation
//! Node.js bindings for PII sanitization

use napi::{Result, bindgen_prelude::*};
use briefcase_core::{Sanitizer, SanitizationResult, Redaction, PiiType};

/// Node.js wrapper for Sanitizer
#[napi]
pub struct JsSanitizer {
    inner: Sanitizer,
}

#[napi]
impl JsSanitizer {
    #[napi(constructor)]
    pub fn new() -> Self {
        Self {
            inner: Sanitizer::new(),
        }
    }

    #[napi(factory)]
    pub fn disabled() -> Self {
        Self {
            inner: Sanitizer::disabled(),
        }
    }

    #[napi]
    pub fn sanitize(&self, text: String) -> JsSanitizationResult {
        let result = self.inner.sanitize(&text);
        JsSanitizationResult { inner: result }
    }

    #[napi]
    pub fn sanitize_json(&self, data: serde_json::Value) -> JsSanitizationResult {
        let result = self.inner.sanitize_json(&data);
        JsSanitizationResult { inner: result }
    }

    #[napi]
    pub fn contains_pii(&self, text: String) -> bool {
        self.inner.contains_pii(&text)
    }

    #[napi]
    pub fn add_pattern(&mut self, name: String, pattern: String) -> Result<()> {
        self.inner.add_pattern(&name, &pattern)
            .map_err(|e| napi::Error::from_reason(e.to_string()))
    }

    #[napi]
    pub fn set_enabled(&mut self, enabled: bool) {
        self.inner.set_enabled(enabled);
    }
}

/// Node.js wrapper for SanitizationResult
#[napi]
pub struct JsSanitizationResult {
    inner: SanitizationResult,
}

#[napi]
impl JsSanitizationResult {
    #[napi(getter)]
    pub fn sanitized(&self) -> serde_json::Value {
        self.inner.sanitized.clone()
    }

    #[napi(getter)]
    pub fn redactions(&self) -> Vec<JsRedaction> {
        self.inner.redactions.iter()
            .map(|r| JsRedaction { inner: r.clone() })
            .collect()
    }

    #[napi(getter)]
    pub fn redaction_count(&self) -> u32 {
        self.inner.redactions.len() as u32
    }

    #[napi(getter)]
    pub fn has_redactions(&self) -> bool {
        !self.inner.redactions.is_empty()
    }
}

/// Node.js wrapper for Redaction
#[napi]
pub struct JsRedaction {
    inner: Redaction,
}

#[napi]
impl JsRedaction {
    #[napi(getter)]
    pub fn pii_type(&self) -> String {
        match &self.inner.pii_type {
            PiiType::Ssn => "ssn".to_string(),
            PiiType::CreditCard => "credit_card".to_string(),
            PiiType::Email => "email".to_string(),
            PiiType::Phone => "phone".to_string(),
            PiiType::ApiKey => "api_key".to_string(),
            PiiType::IpAddress => "ip_address".to_string(),
            PiiType::Custom(name) => name.clone(),
        }
    }

    #[napi(getter)]
    pub fn start_position(&self) -> u32 {
        self.inner.start_position as u32
    }

    #[napi(getter)]
    pub fn end_position(&self) -> u32 {
        self.inner.end_position as u32
    }

    #[napi(getter)]
    pub fn original_length(&self) -> u32 {
        self.inner.original_length as u32
    }
}