//! Shared utility functions used across routes and modules. //! //! Organized into focused submodules and re-exported flat, so existing //! `crate::helpers::*` imports keep working unchanged: //! //! - [`http`], shared outbound client, client-IP, HTMX/ETag, toast headers //! - [`db`], unique-violation (23505) mapping + unique-slug insert loop //! - [`render`], Askama fragment rendering + HTML escaping //! - [`billing`], Stripe fee estimation + timestamp conversion //! - [`datetime`], schedule-datetime parsing //! - [`integration`], CSRF-token convenience + MT discussion stats //! //! Formatting, crypto, and rate limiting live in their own top-level modules and //! are re-exported here too, for the same backward-compatibility reason. mod billing; mod datetime; mod db; mod http; mod integration; mod render; pub use billing::{estimate_stripe_fee, stripe_timestamp}; pub use datetime::parse_schedule_datetime; pub use db::{SLUG_SUFFIX_CAP, insert_with_unique_slug, is_unique_violation, map_unique_violation}; pub use http::{ HTTP_CLIENT, check_etag, extract_client_ip, htmx_toast_response, hx_toast, ip_advisory_lock_key, is_htmx_request, with_etag, }; pub use integration::{fetch_discussion_info, get_csrf_token}; pub use render::{escape_html, render_fragment}; pub use crate::crypto::{ constant_time_compare, generate_feed_url, generate_key_code, verify_feed_signature, }; pub use crate::formatting::{ format_bytes, format_file_size, format_price, format_revenue, get_initials, sanitize_csv_cell, slugify, }; pub use crate::rate_limit::{ CloudflareIpKeyExtractor, SyncAppKeyExtractor, rate_limiter_ms, rate_limiter_per_sec, synckit_app_rate_limiter_ms, };