poolster-plugin-java 0.5.0-alpha.1

Native Java SDK generator for Poolster
Documentation
use super::*;
use poolster_core::engine::{Meta, Plugin, PluginContext};
pub struct Webhooks {
    meta: Meta,
}
pub fn webhooks() -> Webhooks {
    Webhooks { meta: Meta::new() }
}
impl Plugin<Java> for Webhooks {
    fn kind(&self) -> &'static str {
        "java-webhooks"
    }
    fn meta(&self) -> &Meta {
        &self.meta
    }
    fn generate(&self, cx: &mut PluginContext<'_, Java>) -> Result<()> {
        let namespace = java_package_name(
            cx.settings
                .package_name
                .as_deref()
                .unwrap_or(&format!("io.poolster.{}", package_segment(&cx.api.name))),
        );
        cx.files.emit(GeneratedFile::new(
            format!(
                "src/main/java/{}/StandardWebhooks.java",
                namespace.replace('.', "/")
            ),
            include_str!("../templates/webhooks.java.tmpl").replace("__PACKAGE__", &namespace),
        )?)
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use poolster_core::engine::Packages;
    #[test]
    fn opt_in_emits_standard_webhook_verifier() {
        let tree = Packages::new()
            .package(crate::package("sdk").with(crate::sdk()).with(webhooks()))
            .generate(&Api::default(), None)
            .unwrap();
        let source = tree
            .iter()
            .find(|(path, _)| path.ends_with("StandardWebhooks.java"))
            .unwrap()
            .1;
        assert!(source.contains("HmacSHA256") || source.contains("HMACSHA256"));
        assert!(source.contains("does not match a trusted key"));
    }
    #[test]
    #[ignore = "requires native JDK17; canonical Standard Webhooks verification probes"]
    fn native_webhook_verification_executes_canonical_vectors() {
        let vector: serde_json::Value =
            serde_json::from_str(include_str!("../../python/testdata/webhook-vectors.json"))
                .unwrap();
        let dir = tempfile::tempdir().unwrap();
        std::fs::write(
            dir.path().join("StandardWebhooks.java"),
            include_str!("../templates/webhooks.java.tmpl").replace("__PACKAGE__", "probe"),
        )
        .unwrap();
        std::fs::write(
            dir.path().join("Probe.java"),
            include_str!("../tests/fixtures/webhooks_probe.java")
                .replace(
                    "__BODY__",
                    &serde_json::to_string(&vector["raw_body"]).unwrap(),
                )
                .replace(
                    "__SECRET__",
                    &serde_json::to_string(&vector["secret"]).unwrap(),
                )
                .replace(
                    "__SIGNATURE__",
                    &serde_json::to_string(&vector["headers"]["webhook-signature"]).unwrap(),
                ),
        )
        .unwrap();
        let result = std::process::Command::new("javac")
            .args(["-d", ".", "StandardWebhooks.java", "Probe.java"])
            .current_dir(dir.path())
            .output()
            .unwrap();
        assert!(
            result.status.success(),
            "{}",
            String::from_utf8_lossy(&result.stderr)
        );
        let result = std::process::Command::new("java")
            .args(["-cp", ".", "probe.Probe"])
            .current_dir(dir.path())
            .output()
            .unwrap();
        assert!(
            result.status.success(),
            "{}{}",
            String::from_utf8_lossy(&result.stdout),
            String::from_utf8_lossy(&result.stderr)
        );
    }
}