global: snapshot

This commit is contained in:
nym21
2026-01-11 17:19:00 +01:00
parent 6f45ec13f3
commit ea70c381de
419 changed files with 38059 additions and 7653 deletions

View File

@@ -21,24 +21,29 @@ pub fn generate_api_methods(output: &mut String, endpoints: &[Endpoint]) {
if let Some(desc) = &endpoint.description
&& endpoint.summary.as_ref() != Some(desc)
{
writeln!(output, " * @description {}", desc).unwrap();
writeln!(output, " *").unwrap();
writeln!(output, " * {}", desc).unwrap();
}
if !endpoint.path_params.is_empty() || !endpoint.query_params.is_empty() {
writeln!(output, " *").unwrap();
}
for param in &endpoint.path_params {
let desc = param.description.as_deref().unwrap_or("");
let desc = format_param_desc(param.description.as_deref());
writeln!(
output,
" * @param {{{}}} {} {}",
" * @param {{{}}} {}{}",
param.param_type, param.name, desc
)
.unwrap();
}
for param in &endpoint.query_params {
let optional = if param.required { "" } else { "=" };
let desc = param.description.as_deref().unwrap_or("");
let desc = format_param_desc(param.description.as_deref());
writeln!(
output,
" * @param {{{}{}}} [{}] {}",
" * @param {{{}{}}} [{}]{}",
param.param_type, optional, param.name, desc
)
.unwrap();
@@ -119,3 +124,11 @@ fn normalize_return_type(return_type: &str) -> String {
}
result
}
/// Format param description with dash prefix, or empty string if no description.
fn format_param_desc(desc: Option<&str>) -> String {
match desc {
Some(d) if !d.is_empty() => format!(" - {}", d),
_ => String::new(),
}
}

View File

@@ -6,9 +6,8 @@ use std::fmt::Write;
use brk_types::TreeNode;
use crate::{
ClientMetadata, Endpoint, PatternField, child_type_name, get_fields_with_child_info,
get_first_leaf_name, get_node_fields, get_pattern_instance_base, infer_accumulated_name,
to_camel_case,
ClientMetadata, Endpoint, PatternField, child_type_name, get_first_leaf_name, get_node_fields,
get_pattern_instance_base, infer_accumulated_name, prepare_tree_node, to_camel_case,
};
use super::api::generate_api_methods;
@@ -38,36 +37,23 @@ fn generate_tree_typedef(
metadata: &ClientMetadata,
generated: &mut HashSet<String>,
) {
let TreeNode::Branch(children) = node else {
let Some(ctx) = prepare_tree_node(node, name, pattern_lookup, metadata, generated) else {
return;
};
let fields_with_child_info = get_fields_with_child_info(children, name, pattern_lookup);
let fields: Vec<PatternField> = fields_with_child_info
.iter()
.map(|(f, _)| f.clone())
.collect();
if pattern_lookup.contains_key(&fields)
&& pattern_lookup.get(&fields) != Some(&name.to_string())
{
return;
}
if generated.contains(name) {
return;
}
generated.insert(name.to_string());
writeln!(output, "/**").unwrap();
writeln!(output, " * @typedef {{Object}} {}", name).unwrap();
for (field, child_fields) in &fields_with_child_info {
let generic_value_type = child_fields
.as_ref()
.and_then(|cf| metadata.get_type_param(cf))
.map(String::as_str);
let js_type = field_type_with_generic(field, metadata, false, generic_value_type);
for ((field, child_fields), (child_name, _)) in
ctx.fields_with_child_info.iter().zip(ctx.children.iter())
{
let js_type = metadata.resolve_tree_field_type(
child_fields.as_deref(),
name,
child_name,
|generic| field_type_with_generic(field, metadata, false, generic),
);
writeln!(
output,
" * @property {{{}}} {}",
@@ -79,10 +65,11 @@ fn generate_tree_typedef(
writeln!(output, " */\n").unwrap();
for (child_name, child_node) in children {
for (child_name, child_node) in ctx.children {
if let TreeNode::Branch(grandchildren) = child_node {
let child_fields = get_node_fields(grandchildren, pattern_lookup);
if !pattern_lookup.contains_key(&child_fields) {
// Generate typedef if no pattern match OR pattern is not parameterizable
if !metadata.is_parameterizable_fields(&child_fields) {
let child_type = child_type_name(name, child_name);
generate_tree_typedef(
output,
@@ -183,22 +170,13 @@ fn generate_tree_initializer(
}
TreeNode::Branch(grandchildren) => {
let child_fields = get_node_fields(grandchildren, pattern_lookup);
if let Some(pattern_name) = pattern_lookup.get(&child_fields) {
let pattern = metadata
.structural_patterns
.iter()
.find(|p| &p.name == pattern_name);
let is_parameterizable =
pattern.map(|p| p.is_parameterizable()).unwrap_or(false);
let arg = if is_parameterizable {
get_pattern_instance_base(child_node)
} else if accumulated_name.is_empty() {
format!("/{}", child_name)
} else {
format!("{}/{}", accumulated_name, child_name)
};
// Only use pattern factory if pattern is parameterizable
let pattern_name = pattern_lookup
.get(&child_fields)
.filter(|name| metadata.is_parameterizable(name));
if let Some(pattern_name) = pattern_name {
let arg = get_pattern_instance_base(child_node);
writeln!(
output,
"{}{}: create{}(this, '{}'){}",

View File

@@ -21,10 +21,24 @@ pub fn generate_type_definitions(output: &mut String, schemas: &TypeSchemas) {
let js_type = schema_to_js_type(schema, Some(name));
let type_desc = schema.get("description").and_then(|d| d.as_str());
if is_primitive_alias(schema) {
writeln!(output, "/** @typedef {{{}}} {} */", js_type, name).unwrap();
if let Some(desc) = type_desc {
writeln!(output, "/**").unwrap();
write_jsdoc_description(output, desc);
writeln!(output, " *").unwrap();
writeln!(output, " * @typedef {{{}}} {}", js_type, name).unwrap();
writeln!(output, " */").unwrap();
} else {
writeln!(output, "/** @typedef {{{}}} {} */", js_type, name).unwrap();
}
} else if let Some(props) = schema.get("properties").and_then(|p| p.as_object()) {
writeln!(output, "/**").unwrap();
if let Some(desc) = type_desc {
write_jsdoc_description(output, desc);
writeln!(output, " *").unwrap();
}
writeln!(output, " * @typedef {{Object}} {}", name).unwrap();
for (prop_name, prop_schema) in props {
let prop_type = schema_to_js_type(prop_schema, Some(name));
@@ -35,14 +49,25 @@ pub fn generate_type_definitions(output: &mut String, schemas: &TypeSchemas) {
.unwrap_or(false);
let optional = if required { "" } else { "=" };
let safe_name = to_camel_case(prop_name);
let prop_desc = prop_schema
.get("description")
.and_then(|d| d.as_str())
.map(|d| format!(" - {}", d))
.unwrap_or_default();
writeln!(
output,
" * @property {{{}{}}} {}",
prop_type, optional, safe_name
" * @property {{{}{}}} {}{}",
prop_type, optional, safe_name, prop_desc
)
.unwrap();
}
writeln!(output, " */").unwrap();
} else if let Some(desc) = type_desc {
writeln!(output, "/**").unwrap();
write_jsdoc_description(output, desc);
writeln!(output, " *").unwrap();
writeln!(output, " * @typedef {{{}}} {}", js_type, name).unwrap();
writeln!(output, " */").unwrap();
} else {
writeln!(output, "/** @typedef {{{}}} {} */", js_type, name).unwrap();
}
@@ -50,6 +75,17 @@ pub fn generate_type_definitions(output: &mut String, schemas: &TypeSchemas) {
writeln!(output).unwrap();
}
/// Write a multi-line description with proper JSDoc formatting.
fn write_jsdoc_description(output: &mut String, desc: &str) {
for line in desc.lines() {
if line.is_empty() {
writeln!(output, " *").unwrap();
} else {
writeln!(output, " * {}", line).unwrap();
}
}
}
fn is_primitive_alias(schema: &Value) -> bool {
schema.get("properties").is_none()
&& schema.get("items").is_none()