///|
/// A small machine-readable description of the stable public surface.
pub struct ApiEntry {
name : String
kind : String
description : String
since : String
} derive(Debug, Eq)
///|
pub fn ApiEntry::new(
name : String,
kind : String,
description : String,
since : String,
) -> ApiEntry {
{ name, kind, description, since }
}
///|
pub fn ApiEntry::to_markdown(self : ApiEntry) -> String {
"| `" +
self.name +
"` | " +
self.kind +
" | " +
self.description +
" | " +
self.since +
" |"
}
///|
pub fn ApiEntry::to_json(self : ApiEntry) -> String {
"{\"name\":\"" +
json_escape(self.name) +
"\",\"kind\":\"" +
json_escape(self.kind) +
"\",\"description\":\"" +
json_escape(self.description) +
"\",\"since\":\"" +
json_escape(self.since) +
"\"}"
}
///|
pub struct ApiContract {
module_name : String
version : String
entries : Array[ApiEntry]
} derive(Debug, Eq)
///|
pub fn ApiContract::brandbook() -> ApiContract {
{
module_name: "@cyypyhon123/moonbit-brandbook",
version: version(),
entries: [
ApiEntry::new(
"parse_brand_document", "import", "Parse JSON or YAML brand input", "0.2.0",
),
ApiEntry::new(
"BrandBook::audit", "validation", "Validate schema and references", "0.2.0",
),
ApiEntry::new(
"BrandBook::to_markdown", "render", "Render a human-readable guide", "0.2.0",
),
ApiEntry::new(
"BrandBook::to_theme_json", "export", "Export interoperable theme JSON",
"0.2.0",
),
ApiEntry::new(
"BrandBook::render_bundle", "export", "Build deterministic artifacts", "0.2.0",
),
ApiEntry::new(
"run_benchmarks", "benchmark", "Measure parser and render paths", "0.2.0",
),
],
}
}
///|
pub fn ApiContract::len(self : ApiContract) -> Int {
self.entries.length()
}
///|
pub fn ApiContract::contains(self : ApiContract, name : String) -> Bool {
self.entries.any(fn(entry) { entry.name == name })
}
///|
pub fn ApiContract::entry(self : ApiContract, name : String) -> ApiEntry? {
for entry in self.entries {
if entry.name == name {
return Some(entry)
}
}
None
}
///|
pub fn ApiContract::names(self : ApiContract) -> Array[String] {
self.entries.map(fn(entry) { entry.name })
}
///|
pub fn ApiContract::kinds(self : ApiContract) -> Array[String] {
let result : Array[String] = []
for entry in self.entries {
if !result.contains(entry.kind) {
result.push(entry.kind)
}
}
result
}
///|
pub fn ApiContract::to_markdown(self : ApiContract) -> String {
let lines : Array[String] = [
"# Public API contract",
"",
"Module: `" + self.module_name + "`",
"Version: `" + self.version + "`",
"",
"| Name | Kind | Description | Since |",
"| --- | --- | --- | --- |",
]
for entry in self.entries {
lines.push(entry.to_markdown())
}
lines.join("\n")
}
///|
pub fn ApiContract::to_json(self : ApiContract) -> String {
"{\"module\":\"" +
json_escape(self.module_name) +
"\",\"version\":\"" +
json_escape(self.version) +
"\",\"entries\":[" +
self.entries.map(fn(entry) { entry.to_json() }).join(",") +
"]}"
}
///|
pub fn ApiContract::release_notes(
self : ApiContract,
previous : ApiContract,
) -> Array[String] {
let changes : Array[String] = []
for entry in self.entries {
if !previous.contains(entry.name) {
changes.push("Added " + entry.name)
}
}
for entry in previous.entries {
if !self.contains(entry.name) {
changes.push("Removed " + entry.name)
}
}
changes
}
///|
pub fn public_api_contract() -> ApiContract {
ApiContract::brandbook()
}
///|
pub fn public_api_markdown() -> String {
public_api_contract().to_markdown()
}
///|
pub fn public_api_json() -> String {
public_api_contract().to_json()
}