Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
074bfae
WIP on custom errors
TheRealMorgenfrue Feb 19, 2026
d61b706
WIP 2 on errors
TheRealMorgenfrue Feb 19, 2026
72c4f15
Merge branch 'main' into custom_error
TheRealMorgenfrue Feb 26, 2026
87f5b2e
Add custom error types handling
TheRealMorgenfrue Feb 26, 2026
8fd4d9f
Add strum
TheRealMorgenfrue Feb 26, 2026
9285258
Upate Cargo.lock
TheRealMorgenfrue Feb 26, 2026
4f39734
Update Cargo.lock
TheRealMorgenfrue Feb 28, 2026
bc4bd1e
Implement conversion functionality between other error types, ErrorRe…
TheRealMorgenfrue Feb 28, 2026
8549229
Fix Leptos version and test Leptos table gen
TheRealMorgenfrue Feb 28, 2026
4162439
Fix missing imports
TheRealMorgenfrue Feb 28, 2026
654b2db
Remove old error code
TheRealMorgenfrue Feb 28, 2026
40e921d
Fix: parse errors do not have access to a triple
TheRealMorgenfrue Feb 28, 2026
be93538
Use new error handling backend
TheRealMorgenfrue Feb 28, 2026
68a7ccb
Minor format! changes
TheRealMorgenfrue Feb 28, 2026
4f88068
Impl for our custom server error
TheRealMorgenfrue Feb 28, 2026
9fff2ab
Export our custom server error
TheRealMorgenfrue Feb 28, 2026
f6ae37e
Add table gen on server
TheRealMorgenfrue Feb 28, 2026
5df30a3
Expand error handling frontend with the new error handling backend
TheRealMorgenfrue Feb 28, 2026
4c69512
Begin using new error handling system
TheRealMorgenfrue Feb 28, 2026
b97cd6e
WIP 1 on tables
TheRealMorgenfrue Mar 4, 2026
bc040d6
Add type annotation
TheRealMorgenfrue Mar 5, 2026
caabb08
WIP on frontend table
TheRealMorgenfrue Mar 5, 2026
e8af2e8
Remove leptos-struct-table
TheRealMorgenfrue Mar 6, 2026
c7e1fc9
Fix typo
TheRealMorgenfrue Mar 6, 2026
2de8cd1
Add location tracking
TheRealMorgenfrue Mar 6, 2026
b3ac836
Use debug instead of info
TheRealMorgenfrue Mar 6, 2026
990a480
Rename VOWLRServerError to VOWLRError
TheRealMorgenfrue Mar 6, 2026
71a993c
Make error location an option
TheRealMorgenfrue Mar 6, 2026
ca5d7cd
Impl Display and extension
TheRealMorgenfrue Mar 6, 2026
53e1be9
Fix CSS
TheRealMorgenfrue Mar 6, 2026
e4af6d8
Add client errors
TheRealMorgenfrue Mar 6, 2026
180d3ad
Refactor error log
TheRealMorgenfrue Mar 6, 2026
f638130
Cleanup
TheRealMorgenfrue Mar 6, 2026
7fad57d
Refactor export menu to use new error handling system
TheRealMorgenfrue Mar 6, 2026
1590765
Remove severity description
TheRealMorgenfrue Mar 9, 2026
ce0ce36
Allow deprecated warn
TheRealMorgenfrue Mar 9, 2026
8da2fc6
Clippy fixes
TheRealMorgenfrue Mar 9, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 56 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 8 additions & 4 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -45,10 +45,12 @@
"webgl",
], git="https://github.com/WebVOWL/WasmGrapher"}
horned-owl={git="https://github.com/phillord/horned-owl", rev="c4f7835ecae70b5e7281dc23b9b7fc6daa497f1d"}
leptos={version="0.8.16", features=["nightly", "multipart", "rkyv"]}
log="0.4"
rdf-fusion="0.1.0"
rkyv="0.8.12"
smallvec={version="1.15.1", features=["union"]}
strum={version="0.27", features=["derive"]}
tokio="1.48.0"

[dependencies]
Expand All @@ -67,16 +69,16 @@
futures={workspace=true}
getrandom={version="0.3", features=["wasm_js"]}
gloo-timers="0.2"
grapher={workspace=true}
grapher.workspace=true
http={version="1.3.1", optional=true}
leptos={version="0.8.16", features=["nightly", "multipart", "rkyv"]}
leptos.workspace=true
leptos_actix={version="0.8.7", optional=true}
leptos_meta={version="0.8.6"}
leptos_router={version="0.8.12", features=["nightly"]}
log={workspace=true}
log.workspace=true
rayon="1.10"
reqwest={version="0.12.24", optional=true, features=["json", "stream"]}
rkyv={workspace=true}
rkyv.workspace=true
tokio={workspace=true, optional=true}
vowlr-database={path="crates/database", optional=true}
vowlr-parser={path="crates/parser", optional=true}
Expand Down Expand Up @@ -113,6 +115,7 @@
"HtmlInputElement",
"HtmlCollection",
"Blob",
"BlobPropertyBag",
]


Expand All @@ -127,6 +130,7 @@
"dep:vowlr-database",
"dep:vowlr-parser",
"leptos-use/actix",
"vowlr-util/server",
]
ssr=[
"dep:actix-files",
Expand Down
73 changes: 73 additions & 0 deletions crates/database/src/errors.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
use std::panic::Location;

use crate::serializers::Triple;
use oxrdf::{BlankNodeIdParseError, IriParseError};
use vowlr_util::prelude::{ErrorRecord, ErrorSeverity, ErrorType};

#[derive(Debug)]
pub enum SerializationErrorKind {
/// An error raised when the object of a triple is required but missing.
MissingObject(Triple, String),
/// An error raised when the subject of a triple is required but missing.
MissingSubject(Triple, String),
/// An error raised when the serializer encountered an unrecoverable problem.
SerializationFailed(Triple, String),
/// An error raised during Iri or IriRef validation.
IriParseError(String, IriParseError),
/// An error raised during BlankNode IDs validation
BlankNodeParseError(String, BlankNodeIdParseError),
}

#[derive(Debug)]
pub struct SerializationError {
/// The contained error type.
inner: SerializationErrorKind,
/// The error's location in the source code.
location: &'static Location<'static>,
}
impl std::fmt::Display for SerializationError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{:?}", self.inner)
}
}

impl From<SerializationErrorKind> for SerializationError {
#[track_caller]
fn from(error: SerializationErrorKind) -> Self {
SerializationError {
inner: error,
location: Location::caller(),
}
}
}

impl From<SerializationError> for ErrorRecord {
fn from(value: SerializationError) -> Self {
let (message, severity) = match value.inner {
SerializationErrorKind::MissingObject(triple, e) => {
(format!("{e}:\n{triple}"), ErrorSeverity::Warning)
}
SerializationErrorKind::MissingSubject(triple, e) => {
(format!("{e}:\n{triple}"), ErrorSeverity::Warning)
}
SerializationErrorKind::SerializationFailed(triple, e) => {
(format!("{e}:\n{triple}"), ErrorSeverity::Critical)
}
SerializationErrorKind::IriParseError(iri, iri_parse_error) => (
format!("{iri_parse_error} (IRI: {iri})"),
ErrorSeverity::Error,
),
SerializationErrorKind::BlankNodeParseError(id, blank_node_id_parse_error) => (
format!("{blank_node_id_parse_error} (ID: {id})"),
ErrorSeverity::Error,
),
};
ErrorRecord::new(
severity,
ErrorType::Serializer,
message,
#[cfg(debug_assertions)]
Some(value.location.to_string()),
)
}
}
99 changes: 1 addition & 98 deletions crates/database/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,4 @@
use std::fmt::{Display, Formatter};

use grapher::prelude::{ElementType, OwlEdge, OwlType, RdfEdge, RdfType};
use oxrdf::{BlankNodeIdParseError, IriParseError};
use vowlr_parser::errors::VOWLRStoreError;

use crate::serializers::Triple;

mod errors;
pub mod serializers;
pub mod store;
pub mod vocab;
Expand All @@ -16,93 +9,3 @@ pub mod prelude {

pub use crate::store::VOWLRStore;
}

pub const SYMMETRIC_EDGE_TYPES: [ElementType; 1] =
[ElementType::Owl(OwlType::Edge(OwlEdge::DisjointWith))];

pub const PROPERTY_EDGE_TYPES: [ElementType; 7] = [
ElementType::Owl(OwlType::Edge(OwlEdge::ObjectProperty)),
ElementType::Owl(OwlType::Edge(OwlEdge::DatatypeProperty)),
ElementType::Owl(OwlType::Edge(OwlEdge::DeprecatedProperty)),
ElementType::Owl(OwlType::Edge(OwlEdge::ExternalProperty)),
ElementType::Owl(OwlType::Edge(OwlEdge::ValuesFrom)),
ElementType::Owl(OwlType::Edge(OwlEdge::InverseOf)),
ElementType::Rdf(RdfType::Edge(RdfEdge::RdfProperty)),
];

pub trait SerializationErrorExt {
fn triple(&self) -> Option<&Triple>;
}

macro_rules! ser_err {
($variant:ident($triple:expr, $msg:expr)) => {
$crate::SerializationErrorKind::$variant(($triple).map(Box::new), $msg)
};
}
pub(crate) use ser_err;

#[derive(Debug)]
pub enum SerializationErrorKind {
MissingObject(Option<Box<Triple>>, String),
MissingSubject(Option<Box<Triple>>, String),
SerializationFailed(Option<Box<Triple>>, String),
IriParseError(Option<Box<Triple>>, Box<IriParseError>),
BlankNodeParseError(Option<Box<Triple>>, Box<BlankNodeIdParseError>),
}
impl SerializationErrorExt for SerializationErrorKind {
fn triple(&self) -> Option<&Triple> {
match &self {
SerializationErrorKind::MissingObject(triple, _)
| SerializationErrorKind::MissingSubject(triple, _)
| SerializationErrorKind::SerializationFailed(triple, _)
| SerializationErrorKind::IriParseError(triple, _)
| SerializationErrorKind::BlankNodeParseError(triple, _) => {
triple.as_ref().map(|t| &**t)
}
}
}
}

#[derive(Debug)]
pub struct SerializationError {
inner: SerializationErrorKind,
}
impl Display for SerializationError {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "SerializationError: {:?}", self.inner)
}
}

impl SerializationErrorExt for SerializationError {
fn triple(&self) -> Option<&Triple> {
self.inner.triple()
}
}

impl From<SerializationErrorKind> for SerializationError {
fn from(error: SerializationErrorKind) -> Self {
SerializationError { inner: error }
}
}

impl From<IriParseError> for SerializationError {
fn from(error: IriParseError) -> Self {
SerializationError {
inner: SerializationErrorKind::IriParseError(None, Box::new(error)),
}
}
}

impl From<SerializationError> for VOWLRStoreError {
fn from(error: SerializationError) -> Self {
VOWLRStoreError::from(error.to_string())
}
}

impl From<BlankNodeIdParseError> for SerializationError {
fn from(error: BlankNodeIdParseError) -> Self {
SerializationError {
inner: SerializationErrorKind::BlankNodeParseError(None, Box::new(error)),
}
}
}
28 changes: 7 additions & 21 deletions crates/database/src/serializers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,9 @@ use std::{
use grapher::prelude::{ElementType, GraphDisplayData, OwlEdge, OwlType};
use log::error;
use oxrdf::Term;
use vowlr_util::prelude::ErrorRecord;

use crate::{PROPERTY_EDGE_TYPES, SYMMETRIC_EDGE_TYPES};
use crate::serializers::util::{PROPERTY_EDGE_TYPES, SYMMETRIC_EDGE_TYPES};

pub mod frontend;
pub mod util;
Expand Down Expand Up @@ -221,15 +222,8 @@ pub struct SerializationDataBuffer {
/// can be either the subject, object or both (in this case, subject is used)
/// - Value = The unresolved triples.
unknown_buffer: HashMap<Term, HashSet<Triple>>,
/// Stores triples that are impossible to serialize.
///
/// This could be caused by various reasons, such as
/// visualization of the triple is not supported.
///
/// Each element is a tuple of:
/// - 0 = The triple (if any).
/// - 1 = The reason it failed to serialize (or the message if no triple is available).
failed_buffer: Vec<(Option<Triple>, String)>,
/// Stores errors encountered during serialization.
failed_buffer: Vec<ErrorRecord>,
/// The base IRI of the document.
///
/// For instance: `http://purl.obolibrary.org/obo/envo.owl`
Expand Down Expand Up @@ -409,17 +403,9 @@ impl Display for SerializationDataBuffer {
.join("\n")
)?;
}
writeln!(f, "\tfailed_buffer:")?;
for (triple, reason) in self.failed_buffer.iter() {
match triple {
Some(triple) => {
writeln!(f, "\t\t{} : {}", triple, reason)?;
}
None => {
writeln!(f, "\t\tNO TRIPLE : {}", reason)?;
}
}
}
// Not needed as it's displayed by the serializer
// writeln!(f, "\tfailed_buffer:")?;
// writeln!(f, "{}", ErrorRecord::format_records(&self.failed_buffer))?;
writeln!(f, "}}")
}
}
Expand Down
Loading