fix oauth

This commit is contained in:
2026-01-18 14:26:43 +09:00
parent 1fd619e32b
commit 6ef8780ac6
30 changed files with 3992 additions and 8 deletions

View File

@@ -21,7 +21,7 @@ struct EndpointInfo {
method: String, // GET or POST
}
/// Generate lexicon Rust code from ATProto lexicon JSON files
/// Generate lexicon code from ATProto lexicon JSON files
pub fn generate(input: &str, output: &str) -> Result<()> {
let input_path = Path::new(input);
@@ -47,14 +47,20 @@ pub fn generate(input: &str, output: &str) -> Result<()> {
}
// Generate Rust code
let code = generate_rust_code(&namespaces);
// Write output
let output_path = Path::new(output).join("mod.rs");
let rust_code = generate_rust_code(&namespaces);
let rust_output_path = Path::new(output).join("mod.rs");
fs::create_dir_all(output)?;
fs::write(&output_path, &code)?;
fs::write(&rust_output_path, &rust_code)?;
println!("Generated Rust: {}", rust_output_path.display());
// Generate TypeScript code
let ts_output = output.replace("src/lexicons", "src/web/lexicons");
let ts_code = generate_typescript_code(&namespaces);
let ts_output_path = Path::new(&ts_output).join("index.ts");
fs::create_dir_all(&ts_output)?;
fs::write(&ts_output_path, &ts_code)?;
println!("Generated TypeScript: {}", ts_output_path.display());
println!("Generated: {}", output_path.display());
println!("Total namespaces: {}", namespaces.len());
let total_endpoints: usize = namespaces.values().map(|v| v.len()).sum();
println!("Total endpoints: {}", total_endpoints);
@@ -178,6 +184,52 @@ fn generate_rust_code(namespaces: &BTreeMap<String, Vec<EndpointInfo>>) -> Strin
code
}
fn generate_typescript_code(namespaces: &BTreeMap<String, Vec<EndpointInfo>>) -> String {
let mut code = String::new();
// Header
code.push_str("// Auto-generated from ATProto lexicons\n");
code.push_str("// Run `ailog gen` to regenerate\n");
code.push_str("// Do not edit manually\n\n");
// Endpoint type
code.push_str("export interface Endpoint {\n");
code.push_str(" nsid: string\n");
code.push_str(" method: 'GET' | 'POST'\n");
code.push_str("}\n\n");
// URL helper function
code.push_str("/** Build XRPC URL for an endpoint */\n");
code.push_str("export function xrpcUrl(pds: string, endpoint: Endpoint): string {\n");
code.push_str(" return `https://${pds}/xrpc/${endpoint.nsid}`\n");
code.push_str("}\n\n");
// Generate namespaces
for (ns, endpoints) in namespaces {
// Convert namespace to object name: com.atproto.repo -> comAtprotoRepo
let obj_name = to_camel_case(&ns.replace('.', "_"));
code.push_str(&format!("export const {} = {{\n", obj_name));
for endpoint in endpoints {
// Extract the method name from NSID: com.atproto.repo.listRecords -> listRecords
let method_name = endpoint.nsid
.rsplit('.')
.next()
.unwrap_or(&endpoint.nsid);
code.push_str(&format!(
" {}: {{ nsid: '{}', method: '{}' }} as Endpoint,\n",
method_name, endpoint.nsid, endpoint.method
));
}
code.push_str("} as const\n\n");
}
code
}
fn to_screaming_snake_case(s: &str) -> String {
let mut result = String::new();
@@ -190,3 +242,23 @@ fn to_screaming_snake_case(s: &str) -> String {
result
}
fn to_camel_case(s: &str) -> String {
let mut result = String::new();
let mut capitalize_next = false;
for (i, c) in s.chars().enumerate() {
if c == '_' {
capitalize_next = true;
} else if capitalize_next {
result.push(c.to_ascii_uppercase());
capitalize_next = false;
} else if i == 0 {
result.push(c.to_ascii_lowercase());
} else {
result.push(c);
}
}
result
}