···11-use wasm_bindgen::prelude::*;
22-use serde_json::Value;
33-41pub mod errors;
52pub mod types;
63pub mod validator;
···96pub use types::{LexiconDoc, StringFormat, ValidationContext};
107pub use validator::LexiconValidator;
1181212-// When the `console_error_panic_hook` feature is enabled, we can call the
1313-// `set_panic_hook` function at least once during initialization, and then
1414-// we will get better error messages if our code ever panics.
1515-//
1616-// For more details see
1717-// https://github.com/rustwasm/console_error_panic_hook#readme
1818-#[cfg(feature = "console_error_panic_hook")]
1919-#[wasm_bindgen(start)]
2020-pub fn main() {
2121- console_error_panic_hook::set_once();
2222-}
99+// WASM-specific code - only compiled when the wasm feature is enabled
1010+#[cfg(feature = "wasm")]
1111+mod wasm_bindings {
1212+ use wasm_bindgen::prelude::*;
1313+ use serde_json::Value;
1414+ use super::*;
23152424-// WASM-exposed LexiconValidator wrapper
2525-#[wasm_bindgen]
2626-pub struct WasmLexiconValidator {
2727- inner: LexiconValidator,
2828-}
1616+ // When the `console_error_panic_hook` feature is enabled, we can call the
1717+ // `set_panic_hook` function at least once during initialization, and then
1818+ // we will get better error messages if our code ever panics.
1919+ //
2020+ // For more details see
2121+ // https://github.com/rustwasm/console_error_panic_hook#readme
2222+ #[cfg(feature = "console_error_panic_hook")]
2323+ #[wasm_bindgen(start)]
2424+ pub fn main() {
2525+ console_error_panic_hook::set_once();
2626+ }
29273030-#[wasm_bindgen]
3131-impl WasmLexiconValidator {
3232- /// Create a new validator with the given lexicon documents
3333- /// Takes a JSON string containing an array of lexicon documents
3434- #[wasm_bindgen(constructor)]
3535- pub fn new(lexicons_json: &str) -> Result<WasmLexiconValidator, JsValue> {
3636- let lexicons: Vec<Value> = serde_json::from_str(lexicons_json)
3737- .map_err(|e| JsValue::from_str(&format!("Failed to parse lexicons JSON: {}", e)))?;
2828+ // WASM-exposed LexiconValidator wrapper
2929+ #[wasm_bindgen]
3030+ pub struct WasmLexiconValidator {
3131+ inner: LexiconValidator,
3232+ }
38333939- let validator = LexiconValidator::new(lexicons)
4040- .map_err(|e| JsValue::from_str(&format!("Failed to create validator: {}", e)))?;
3434+ #[wasm_bindgen]
3535+ impl WasmLexiconValidator {
3636+ /// Create a new validator with the given lexicon documents
3737+ /// Takes a JSON string containing an array of lexicon documents
3838+ #[wasm_bindgen(constructor)]
3939+ pub fn new(lexicons_json: &str) -> Result<WasmLexiconValidator, JsValue> {
4040+ let lexicons: Vec<Value> = serde_json::from_str(lexicons_json)
4141+ .map_err(|e| JsValue::from_str(&format!("Failed to parse lexicons JSON: {}", e)))?;
41424242- Ok(WasmLexiconValidator { inner: validator })
4343+ let validator = LexiconValidator::new(lexicons)
4444+ .map_err(|e| JsValue::from_str(&format!("Failed to create validator: {}", e)))?;
4545+4646+ Ok(WasmLexiconValidator { inner: validator })
4747+ }
4848+4949+ /// Validate a record against its collection's lexicon
5050+ /// Takes collection name and record as JSON strings
5151+ #[wasm_bindgen]
5252+ pub fn validate_record(&self, collection: &str, record_json: &str) -> Result<(), JsValue> {
5353+ let record: Value = serde_json::from_str(record_json)
5454+ .map_err(|e| JsValue::from_str(&format!("Failed to parse record JSON: {}", e)))?;
5555+5656+ self.inner
5757+ .validate_record(collection, &record)
5858+ .map_err(|e| JsValue::from_str(&format!("Validation failed: {}", e)))
5959+ }
6060+6161+ /// Validate that all cross-lexicon references can be resolved
6262+ #[wasm_bindgen]
6363+ pub fn validate_lexicon_set_completeness(&self) -> Result<(), JsValue> {
6464+ self.inner
6565+ .validate_lexicon_set_completeness()
6666+ .map_err(|e| JsValue::from_str(&format!("Lexicon set validation failed: {}", e)))
6767+ }
4368 }
44694545- /// Validate a record against its collection's lexicon
4646- /// Takes collection name and record as JSON strings
7070+ // Export individual validation functions for more granular use
4771 #[wasm_bindgen]
4848- pub fn validate_record(&self, collection: &str, record_json: &str) -> Result<(), JsValue> {
4949- let record: Value = serde_json::from_str(record_json)
5050- .map_err(|e| JsValue::from_str(&format!("Failed to parse record JSON: {}", e)))?;
7272+ pub fn validate_string_format(value: &str, format: &str) -> Result<(), JsValue> {
7373+ let format_enum = StringFormat::from_str(format)
7474+ .ok_or_else(|| JsValue::from_str(&format!("Unknown format: {}", format)))?;
7575+7676+ // Create a minimal validator for string format validation
7777+ let validator = LexiconValidator::new(vec![])
7878+ .map_err(|e| JsValue::from_str(&format!("Failed to create validator: {}", e)))?;
51795252- self.inner
5353- .validate_record(collection, &record)
5454- .map_err(|e| JsValue::from_str(&format!("Validation failed: {}", e)))
8080+ let ctx = ValidationContext::new();
8181+ validator
8282+ .validate_string_format(value, format_enum, &ctx)
8383+ .map_err(|e| JsValue::from_str(&format!("String format validation failed: {}", e)))
5584 }
56855757- /// Validate that all cross-lexicon references can be resolved
8686+ // Utility function to check if a string is a valid lexicon ID
5887 #[wasm_bindgen]
5959- pub fn validate_lexicon_set_completeness(&self) -> Result<(), JsValue> {
6060- self.inner
6161- .validate_lexicon_set_completeness()
6262- .map_err(|e| JsValue::from_str(&format!("Lexicon set validation failed: {}", e)))
8888+ pub fn is_valid_nsid(nsid: &str) -> bool {
8989+ use regex::Regex;
9090+ let nsid_regex = Regex::new(r"^[a-zA-Z]([a-zA-Z0-9-]*[a-zA-Z0-9])?(\.[a-zA-Z]([a-zA-Z0-9-]*[a-zA-Z0-9])?)*$").unwrap();
9191+ nsid_regex.is_match(nsid)
6392 }
6493}
65946666-// Export individual validation functions for more granular use
6767-#[wasm_bindgen]
6868-pub fn validate_string_format(value: &str, format: &str) -> Result<(), JsValue> {
6969- let format_enum = StringFormat::from_str(format)
7070- .ok_or_else(|| JsValue::from_str(&format!("Unknown format: {}", format)))?;
9595+// Re-export WASM bindings when the feature is enabled
9696+#[cfg(feature = "wasm")]
9797+pub use wasm_bindings::*;
71987272- // Create a minimal validator for string format validation
7373- let validator = LexiconValidator::new(vec![])
7474- .map_err(|e| JsValue::from_str(&format!("Failed to create validator: {}", e)))?;
7575-7676- let ctx = ValidationContext::new();
7777- validator
7878- .validate_string_format(value, format_enum, &ctx)
7979- .map_err(|e| JsValue::from_str(&format!("String format validation failed: {}", e)))
8080-}
8181-8282-// Utility function to check if a string is a valid lexicon ID
8383-#[wasm_bindgen]
9999+// Non-WASM utility functions that are always available
84100pub fn is_valid_nsid(nsid: &str) -> bool {
85101 use regex::Regex;
86102 let nsid_regex = Regex::new(r"^[a-zA-Z]([a-zA-Z0-9-]*[a-zA-Z0-9])?(\.[a-zA-Z]([a-zA-Z0-9-]*[a-zA-Z0-9])?)*$").unwrap();