lenso-contract-codegen 0.8.0

Generates exact Rust, TypeScript, and WIT bindings from portable Lenso Capability contracts.
Documentation
use std::path::Path;

use lenso_contract_authoring::{CapabilitySnapshot, OperationSnapshot};
use lenso_contract_codegen::{
    CodegenError, check_source_snapshot, generate, write_source_snapshot,
};
use serde_json::json;

fn snapshot() -> CapabilitySnapshot {
    CapabilitySnapshot {
        capability_id: "example.derived@1".to_owned(),
        version: "1.0.0".to_owned(),
        portable: true,
        cross_lane_transfer: false,
        operations: vec![OperationSnapshot {
            name: "run".to_owned(),
            interaction: "request".to_owned(),
            request_schema: json!({
                "$schema": "https://json-schema.org/draft/2020-12/schema",
                "type": "object",
                "properties": {},
                "additionalProperties": false
            }),
            response_schema: json!({
                "$schema": "https://json-schema.org/draft/2020-12/schema",
                "type": "object",
                "properties": {},
                "additionalProperties": false
            }),
            domain_error_schema: json!({
                "$schema": "https://json-schema.org/draft/2020-12/schema",
                "oneOf": [{"const": "rejected"}]
            }),
        }],
    }
}

#[test]
fn source_snapshots_are_deterministic_and_drift_checked() {
    let root = tempfile::tempdir().unwrap();
    let descriptor = root.path().join("capability.json");
    write_source_snapshot(&snapshot(), &descriptor).unwrap();
    check_source_snapshot(&snapshot(), &descriptor).unwrap();
    let generated = generate(&descriptor).unwrap();
    assert_eq!(generated.metadata.capability_id, "example.derived@1");
    assert!(generated.rust.contains("pub trait DerivedProvider"));
    assert!(
        generated
            .typescript
            .contains("export interface DerivedProvider")
    );

    std::fs::write(root.path().join("schemas/run-request.schema.json"), "{}\n").unwrap();
    assert!(matches!(
        check_source_snapshot(&snapshot(), &descriptor),
        Err(CodegenError::GeneratedArtifactDrift { .. })
    ));
    assert!(Path::new(&descriptor).exists());
}

#[test]
fn stream_source_snapshots_use_open_and_message_artifacts() {
    let root = tempfile::tempdir().unwrap();
    let descriptor = root.path().join("capability.json");
    let mut snapshot = snapshot();
    snapshot.operations[0].interaction = "stream".to_owned();

    write_source_snapshot(&snapshot, &descriptor).unwrap();
    assert!(root.path().join("schemas/run-open.schema.json").is_file());
    assert!(
        root.path()
            .join("schemas/run-message.schema.json")
            .is_file()
    );
    assert!(!root.path().join("schemas/run-request.schema.json").exists());
    let generated = generate(&descriptor).unwrap();
    assert!(generated.rust.contains("NativeStreamSession"));
    assert!(generated.typescript.contains("StreamSession"));
}

#[test]
fn schema_titles_preserve_authored_type_names_across_projections() {
    let root = tempfile::tempdir().unwrap();
    let descriptor = root.path().join("capability.json");
    let mut snapshot = snapshot();
    snapshot.operations[0].request_schema = json!({
        "$schema": "https://json-schema.org/draft/2020-12/schema",
        "title": "CatalogRequest",
        "type": "object",
        "required": ["selected", "tools"],
        "properties": {
            "selected": {
                "anyOf": [
                    { "$ref": "#/$defs/ToolDefinition" },
                    { "type": "null" }
                ]
            },
            "tools": {
                "type": "array",
                "items": { "$ref": "#/$defs/ToolDefinition" }
            }
        },
        "additionalProperties": false,
        "$defs": {
            "ToolDefinition": {
                "type": "object",
                "required": ["name"],
                "properties": { "name": { "type": "string" } },
                "additionalProperties": false
            }
        }
    });

    write_source_snapshot(&snapshot, &descriptor).unwrap();
    let generated = generate(&descriptor).unwrap();
    assert!(generated.rust.contains("pub struct CatalogRequest"));
    assert!(generated.rust.contains("pub tools: Vec<ToolDefinition>"));
    assert!(
        generated
            .rust
            .contains("pub selected: Option<ToolDefinition>")
    );
    assert!(generated.rust.contains("pub struct ToolDefinition"));
    assert!(
        generated
            .typescript
            .contains("export interface ToolDefinition")
    );
}