0.0.1-alpha.3

This commit is contained in:
2026-09-27 22:23:43 +02:00
parent 8cd187b700
commit 6b6bdcfc71
29 changed files with 1973 additions and 32 deletions

View File

@@ -0,0 +1,13 @@
// file: crates/knowledge-domain-lib/src/content_family.rs
// version: 1
//! Content-family identities owned by the Knowledge domain.
/// Semantic family of knowledge content.
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
pub enum ContentFamily {
Pgr,
Howto,
Snippet,
ProjectLocal,
}

View File

@@ -1,8 +1,16 @@
// file: crates/knowledge-domain-lib/src/lib.rs
// version: 1
// version: 2
//! Domain boundary for SaseDev Knowledge.
//! Shared domain contracts for SaseDev Knowledge.
//!
//! The crate is intentionally minimal in `0.0.1-alpha.2`: it establishes ownership of shared
//! domain contracts without introducing the Git/synchronization contracts reserved for the next
//! tranche.
//! The crate owns content-family and source identities that are independent of HTTP, PostgreSQL,
//! forge providers and concrete Git implementations.
mod content_family;
mod source;
pub use crate::content_family::ContentFamily;
pub use crate::source::{ContentSource, SourceId, SourceIdError};
#[cfg(test)]
mod unit_tests;

View File

@@ -0,0 +1,68 @@
// file: crates/knowledge-domain-lib/src/source.rs
// version: 1
//! Source identities independent of repository and forge providers.
/// Error returned when constructing an invalid source identifier.
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum SourceIdError {
/// The identifier is empty or contains only whitespace.
Empty,
}
impl std::fmt::Display for crate::SourceIdError {
fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
crate::SourceIdError::Empty => return formatter.write_str("source identifier must not be empty"),
}
}
}
impl std::error::Error for crate::SourceIdError {}
/// Stable logical identifier of one configured content source.
#[derive(Clone, Debug, Eq, Hash, PartialEq)]
pub struct SourceId(String);
impl crate::SourceId {
/// Build a source identifier without imposing a fixed repository count or provider syntax.
pub fn new(value: &str) -> Result<crate::SourceId, crate::SourceIdError> {
if value.trim().is_empty() {
return Err(crate::SourceIdError::Empty);
}
return Ok(crate::SourceId(value.to_owned()));
}
/// Return the identifier as text.
pub fn as_str(&self) -> &str {
return self.0.as_str();
}
}
/// One logical content source associated with a semantic family.
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct ContentSource {
id: crate::SourceId,
family: crate::ContentFamily,
}
impl crate::ContentSource {
/// Build a content source from a textual source identifier.
pub fn new(id: &str, family: crate::ContentFamily) -> Result<crate::ContentSource, crate::SourceIdError> {
let source_id = match crate::SourceId::new(id) {
Ok(value) => value,
Err(error) => return Err(error),
};
return Ok(crate::ContentSource { id: source_id, family });
}
/// Return the logical source identifier.
pub fn id(&self) -> &crate::SourceId {
return &self.id;
}
/// Return the semantic content family.
pub fn family(&self) -> crate::ContentFamily {
return self.family;
}
}

View File

@@ -0,0 +1,20 @@
// file: crates/knowledge-domain-lib/src/unit_tests.rs
// version: 1
#[test]
fn source_id_rejects_empty_values() {
assert_eq!(crate::SourceId::new(" "), Err(crate::SourceIdError::Empty));
return;
}
#[test]
fn content_sources_are_not_limited_to_three_repositories() {
let sources = [
crate::ContentSource::new("pgr", crate::ContentFamily::Pgr),
crate::ContentSource::new("howtos", crate::ContentFamily::Howto),
crate::ContentSource::new("snippets", crate::ContentFamily::Snippet),
crate::ContentSource::new("project-extra", crate::ContentFamily::ProjectLocal),
];
assert!(sources.iter().all(Result::is_ok));
return;
}