Backend Shared Crate in Rust
Go to file
RTSDA 0afe80ca8d
Some checks failed
iOS UniFFI Build / build-ios (push) Has been cancelled
Clean up repository structure
Move build scripts, test scripts, examples, and generated files to scripts/ directory.
Update .gitignore to exclude scripts/ from future commits to keep repository clean.
2025-08-16 19:28:17 -04:00
.github/workflows Initial commit: Church Core Rust library 2025-08-16 19:25:01 -04:00
bindings Initial commit: Church Core Rust library 2025-08-16 19:25:01 -04:00
RTSDA Initial commit: Church Core Rust library 2025-08-16 19:25:01 -04:00
src Initial commit: Church Core Rust library 2025-08-16 19:25:01 -04:00
tests Initial commit: Church Core Rust library 2025-08-16 19:25:01 -04:00
.gitignore Clean up repository structure 2025-08-16 19:28:17 -04:00
build.rs Initial commit: Church Core Rust library 2025-08-16 19:25:01 -04:00
Cargo.toml Initial commit: Church Core Rust library 2025-08-16 19:25:01 -04:00
Makefile Initial commit: Church Core Rust library 2025-08-16 19:25:01 -04:00
README.md Initial commit: Church Core Rust library 2025-08-16 19:25:01 -04:00

Church Core

A shared Rust crate providing unified API access and data models for church applications across multiple platforms (iOS, Android, Web, Desktop).

Overview

Church Core centralizes all church application logic, API communication, and data management into a single, well-tested Rust crate. This enables client applications to become "dumb display devices" while ensuring consistency across platforms.

Features

  • Unified API Client: Single interface for all church APIs
  • Consistent Data Models: Shared types for events, bulletins, sermons, etc.
  • Cross-Platform Support: Native bindings for iOS, Android, WASM, and FFI
  • Built-in Caching: Automatic response caching with TTL
  • Offline Support: Graceful offline operation with cached data
  • Authentication: PocketBase and Jellyfin integration
  • Error Handling: Comprehensive error types with retry logic
  • Type Safety: Rust's type system prevents API mismatches

Architecture

church-core/
├── src/
│   ├── client/          # HTTP client and API modules
│   │   ├── events.rs    # Event operations
│   │   ├── bulletins.rs # Bulletin operations
│   │   ├── sermons.rs   # Sermon operations
│   │   ├── contact.rs   # Contact form handling
│   │   └── config.rs    # Configuration management
│   ├── models/          # Data structures
│   │   ├── event.rs     # Event models
│   │   ├── bulletin.rs  # Bulletin models
│   │   ├── sermon.rs    # Sermon models
│   │   ├── contact.rs   # Contact models
│   │   └── auth.rs      # Authentication models
│   ├── auth/            # Authentication modules
│   ├── cache/           # Caching system
│   ├── utils/           # Utility functions
│   └── error.rs         # Error types
└── README.md

Quick Start

Basic Usage

use church_core::{ChurchApiClient, ChurchCoreConfig};

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    // Create client with default configuration
    let config = ChurchCoreConfig::default();
    let client = ChurchApiClient::new(config)?;
    
    // Get upcoming events
    let events = client.get_upcoming_events(Some(10)).await?;
    for event in events {
        println!("{}: {}", event.title, event.start_time);
    }
    
    // Get current bulletin
    if let Some(bulletin) = client.get_current_bulletin().await? {
        println!("Current bulletin: {}", bulletin.title);
    }
    
    // Submit contact form
    let contact = ContactForm::new(
        "John Doe".to_string(),
        "john@example.com".to_string(),
        "Prayer Request".to_string(),
        "Please pray for my family.".to_string()
    );
    let submission_id = client.submit_contact_form(contact).await?;
    println!("Contact form submitted: {}", submission_id);
    
    Ok(())
}

Custom Configuration

use church_core::{ChurchApiClient, ChurchCoreConfig};
use std::time::Duration;

let config = ChurchCoreConfig::new()
    .with_base_url("https://api.mychurch.org/api")
    .with_cache_ttl(Duration::from_secs(600))
    .with_timeout(Duration::from_secs(15))
    .with_retry_attempts(5)
    .with_offline_mode(true);

let client = ChurchApiClient::new(config)?;

Data Models

Event

use church_core::{Event, EventCategory, NewEvent};
use chrono::{DateTime, Utc};

// Create a new event
let new_event = NewEvent {
    title: "Bible Study".to_string(),
    description: "Weekly Bible study group".to_string(),
    start_time: Utc::now(),
    end_time: Utc::now() + chrono::Duration::hours(2),
    location: "Fellowship Hall".to_string(),
    location_url: Some("https://maps.google.com/...".to_string()),
    category: EventCategory::Education,
    is_featured: true,
    // ... other fields
};

let event_id = client.create_event(new_event).await?;

Bulletin

use church_core::{Bulletin, NewBulletin};
use chrono::NaiveDate;

// Get current bulletin
if let Some(bulletin) = client.get_current_bulletin().await? {
    println!("Sabbath School: {}", bulletin.sabbath_school);
    println!("Divine Worship: {}", bulletin.divine_worship);
    
    // Check for announcements
    for announcement in bulletin.active_announcements() {
        println!("📢 {}: {}", announcement.title, announcement.content);
    }
}

Contact Form

use church_core::{ContactForm, ContactCategory, VisitorInfo};

let contact = ContactForm::new(
    "Jane Smith".to_string(),
    "jane@example.com".to_string(),
    "New Visitor".to_string(),
    "I'm interested in learning more about your church.".to_string()
)
.with_category(ContactCategory::Visitor)
.with_phone("555-123-4567".to_string())
.with_visitor_info(VisitorInfo {
    is_first_time: true,
    wants_follow_up: true,
    wants_newsletter: true,
    // ... other fields
});

let submission_id = client.submit_contact_form(contact).await?;

Authentication

PocketBase Authentication

use church_core::auth::{LoginRequest, AuthToken};

// Authenticate with PocketBase
let login = LoginRequest {
    identity: "admin@church.org".to_string(),
    password: "secure_password".to_string(),
};

// Note: Authentication methods would be implemented in auth module
// let token = client.authenticate_pocketbase(login).await?;
// client.set_auth_token(token).await;

Caching

The client automatically caches responses with configurable TTL:

// Cache is automatically used
let events = client.get_upcoming_events(None).await?; // Fetches from API
let events = client.get_upcoming_events(None).await?; // Returns from cache

// Manual cache management
client.clear_cache().await;
let (cache_size, max_size) = client.get_cache_stats().await;

Error Handling

use church_core::{ChurchApiError, Result};

match client.get_event("invalid-id").await {
    Ok(Some(event)) => println!("Found event: {}", event.title),
    Ok(None) => println!("Event not found"),
    Err(ChurchApiError::NotFound) => println!("Event does not exist"),
    Err(ChurchApiError::Network(_)) => println!("Network error - check connection"),
    Err(ChurchApiError::Auth(_)) => println!("Authentication required"),
    Err(e) => println!("Other error: {}", e),
}

Platform Integration

iOS (Swift)

// FFI bindings would be generated for iOS
import ChurchCore

let client = ChurchApiClient()
client.getUpcomingEvents(limit: 10) { events in
    // Handle events
}

Android (Kotlin/Java)

// JNI bindings for Android
import org.church.ChurchCore

val client = ChurchCore()
val events = client.getUpcomingEvents(10)

Web (WASM)

// WASM bindings for web
import { ChurchApiClient } from 'church-core-wasm';

const client = new ChurchApiClient();
const events = await client.getUpcomingEvents(10);

Testing

Run the test binary to verify API connectivity:

cargo run --bin church-core-test

This will test:

  • Health check endpoint
  • Upcoming events retrieval
  • Current bulletin fetching
  • Configuration loading
  • Cache statistics

API Endpoints

The client interfaces with these standard endpoints:

  • GET /events/upcoming - Get upcoming events
  • GET /events/{id} - Get single event
  • POST /events - Create event
  • GET /bulletins/current - Get current bulletin
  • GET /bulletins - List bulletins
  • GET /config - Get church configuration
  • POST /contact - Submit contact form
  • GET /sermons - List sermons
  • GET /sermons/search - Search sermons

Development

Building for iOS (No Python Required!)

# Quick build using Makefile
make ios

# Or use the build script directly
./build_ios.sh

# Install dependencies first time
make install-deps

# Development build (faster)
make dev

# Clean build artifacts
make clean

Building Steps Explained

  1. Install iOS targets: Adds Rust toolchains for iOS devices and simulators
  2. Build static libraries: Creates .a files for each iOS architecture
  3. Create universal library: Combines all architectures using lipo
  4. Generate Swift bindings: Uses uniffi-bindgen to create Swift interfaces
  5. Copy to iOS project: Moves all files to your Xcode project

Generated files:

  • church_core.swift - Swift interface to your Rust code
  • church_coreFFI.h - C header file
  • church_coreFFI.modulemap - Module map for Swift
  • libchurch_core.a - Universal static library

Standard Rust Building

# Standard build
cargo build

# Build with WASM support
cargo build --features wasm

# Build with UniFFI support
cargo build --features uniffi

# Run tests
cargo test --features uniffi

Features

  • default: Native Rust client
  • wasm: WebAssembly bindings
  • uniffi: UniFFI bindings for iOS/Android (replaces old ffi feature)
  • native: Native platform features

License

MIT License - see LICENSE file for details.

Contributing

  1. Fork the repository
  2. Create a feature branch
  3. Add tests for new functionality
  4. Ensure all tests pass
  5. Submit a pull request

Support

For issues and questions:

  • Check the API documentation
  • Review existing GitHub issues
  • Create a new issue with detailed information