poolster-core 0.5.0-alpha.1

Language-neutral OpenAPI code generation primitives
Documentation
use poolster_core::adapter::openapi_sidecar::load_operations;
use poolster_core::openapi32::{parameter_content, request_content, response_content};
use poolster_core::{SchemaKind, SecuritySchemeKind};

#[test]
fn typed_content_preserves_query_stream_and_nested_encoding() {
    let root = tempfile::tempdir().unwrap();
    let dir = root.path();
    std::fs::create_dir(dir.join("operations")).unwrap();
    std::fs::write(
        dir.join("operations.json"),
        r#"{"GET /events":"events.json"}"#,
    )
    .unwrap();
    std::fs::write(dir.join("operations-order.json"), r#"["GET /events"]"#).unwrap();
    std::fs::write(dir.join("schemas.json"), r#"{"schemas":[]}"#).unwrap();
    std::fs::write(dir.join("security-schemes.json"),r#"{"schemes":[{"name":"device","type":"oauth2","oauth_flows":[{"type":"deviceAuthorization","device_authorization_url":"https://auth.example/device","token_url":"https://auth.example/token"}]}]}"#).unwrap();
    std::fs::write(dir.join("api-metadata.json"),r#"{"self":"https://example.test/api.json","tags":[{"name":"events","parent":"api","summary":"Events","kind":"resource"}]}"#).unwrap();
    std::fs::write(dir.join("operations/events.json"),r#"{"path":"/events","method":"GET","parameters":[{"name":"filter","in":"querystring","required":true,"content":[{"content_type":"application/json","schema_definition":{"type":"object"}}]}],"request_body":{"media_types":[{"content_type":"multipart/mixed","item_schema_definition":{"type":"string"},"prefix_encoding":[{"contentType":"multipart/mixed","prefixEncoding":[{"contentType":"image/png"}],"itemEncoding":{"contentType":"text/plain"}}],"item_encoding":{"contentType":"application/json"}}]},"responses":[{"code":"200","content_type":"application/json-seq","item_schema_definition":{"type":"integer"}},{"code":"200","content_type":"multipart/mixed; version=1","item_schema_definition":{"type":"string"}}]}"#).unwrap();
    let api = load_operations(dir, "API".into(), "1".into()).unwrap();
    let op = &api.operations[0];
    assert_eq!(op.parameters[0].location, "querystring");
    assert!(op.parameters[0].schema.is_some());
    assert_eq!(
        parameter_content(&op.parameters[0]).unwrap()[0].content_type,
        "application/json"
    );
    assert!(matches!(
        op.success_schema().unwrap().kind,
        SchemaKind::Array { .. }
    ));
    let responses = response_content(op).unwrap();
    assert_eq!(responses[0].status, "200");
    assert!(matches!(
        responses[0].content.item_schema().unwrap().kind,
        SchemaKind::Integer
    ));
    let binary = &op.responses[0].media_types[1].schema.as_ref().unwrap();
    assert!(matches!(binary.kind, SchemaKind::String));
    assert_eq!(binary.format.as_deref(), Some("binary"));
    assert!(matches!(
        response_content(op).unwrap()[1]
            .content
            .item_schema()
            .unwrap()
            .kind,
        SchemaKind::String
    ));
    let semantics = poolster_core::semantics::analyze_operation(op, None);
    assert_eq!(
        semantics.streaming,
        Some(poolster_core::semantics::StreamingKind::Binary)
    );
    assert_eq!(
        semantics.request_body,
        Some(poolster_core::semantics::RequestBodyKind::Multipart)
    );
    let body = request_content(op).unwrap();
    assert_eq!(
        body[0].prefix_encoding[0].prefix_encoding[0]
            .content_type
            .as_deref(),
        Some("image/png")
    );
    assert_eq!(
        body[0].prefix_encoding[0]
            .item_encoding
            .as_ref()
            .unwrap()
            .content_type
            .as_deref(),
        Some("text/plain")
    );
    assert_eq!(
        api.annotations["poolster.openapi.metadata"]["tags"][0]["parent"],
        "api"
    );
    let operation_path = dir.join("operations/events.json");
    let mut raw: serde_json::Value =
        serde_json::from_slice(&std::fs::read(&operation_path).unwrap()).unwrap();
    raw["responses"][0]["schema_definition"] = serde_json::json!({"type":"string"});
    std::fs::write(&operation_path, serde_json::to_vec(&raw).unwrap()).unwrap();
    let combined = load_operations(dir, "API".into(), "1".into()).unwrap();
    assert!(matches!(
        combined.operations[0].success_schema().unwrap().kind,
        SchemaKind::Array { .. }
    ));
    raw["responses"][0]["content_type"] = "text/event-stream".into();
    std::fs::write(&operation_path, serde_json::to_vec(&raw).unwrap()).unwrap();
    let streamed = load_operations(dir, "API".into(), "1".into()).unwrap();
    assert!(matches!(
        streamed.operations[0].success_schema().unwrap().kind,
        SchemaKind::Integer
    ));
    let security = poolster_core::adapter::openapi_sidecar::OpenApiSidecar::new(dir, "API", "1");
    let catalog = poolster_core::Adapter::adapt(&security)
        .unwrap()
        .security_schemes;
    let SecuritySchemeKind::OAuth2 { flows, .. } = &catalog.schemes[0].kind else {
        panic!("oauth metadata lost")
    };
    assert_eq!(
        flows[0].device_authorization_url.as_deref(),
        Some("https://auth.example/device")
    );
}