afterburner_core/host.rs
1// SPDX-License-Identifier: BUSL-1.1
2// Copyright (c) 2026 vertexclique
3// Licensed under the Business Source License 1.1.
4// Change Date: 4 years after this version's release. Change License: Apache-2.0.
5
6//! Host function API surface exposed to JS scripts.
7//!
8//! This module declares the *shape* of every host function. The actual
9//! WASM-side wiring (Wasmtime `Linker` registration, WASI glue) lives in
10//! `afterburner-wasi`. Embedders implement `HostContext` to plug their own
11//! data into `ReadColumn` / `EmitRow`.
12//!
13//! `Log` and `GetEnv` are the commonly-wired variants; the rest are
14//! implemented by hosts that opt into richer integrations.
15
16use serde::{Deserialize, Serialize};
17use serde_json::Value;
18
19/// Log severity, mirroring `console.*` in JS.
20#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
21pub enum LogLevel {
22 Debug,
23 Info,
24 Warn,
25 Error,
26}
27
28/// HTTP method for `HostFunction::HttpRequest`. Present even when the
29/// `host-http` feature is off so the enum shape is stable.
30#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
31pub enum HttpMethod {
32 Get,
33 Post,
34 Put,
35 Delete,
36 Patch,
37}
38
39/// Response returned from `HostFunction::HttpRequest`.
40#[derive(Debug, Clone, Serialize, Deserialize)]
41pub struct HttpResponse {
42 pub status: u16,
43 pub body: String,
44}
45
46/// The full host-function set.
47///
48/// Variants map 1:1 to WASM imports that JS scripts can call. The enum is a
49/// convenience for dispatch; individual hooks live on the `HostContext` trait
50/// so callers only implement the pieces they need.
51#[derive(Debug, Clone)]
52pub enum HostFunction {
53 /// `console.log` / `console.error` bridge.
54 Log { level: LogLevel, message: String },
55
56 /// Read a named column from the current row batch. Wired by hosts
57 /// that run the engine in a tabular context; a no-op otherwise.
58 ReadColumn { name: String },
59
60 /// Emit a transformed row. Wired by hosts that run the engine in a
61 /// tabular context.
62 EmitRow { row: Value },
63
64 /// Read an allow-listed environment variable.
65 GetEnv { key: String },
66
67 /// HTTP out-call. Gated behind the `host-http` cargo feature in
68 /// `afterburner-wasi`.
69 HttpRequest {
70 url: String,
71 method: HttpMethod,
72 body: Option<String>,
73 },
74}
75
76/// Callbacks the host provides to the script runtime. Implementations supply
77/// whichever methods are relevant; defaults are intentionally no-ops or
78/// `None` so minimal hosts (e.g. tests) don't need to stub every variant.
79pub trait HostContext: Send + Sync {
80 fn log(&self, _level: LogLevel, _message: &str) {}
81
82 fn read_column(&self, _name: &str) -> Vec<Value> {
83 Vec::new()
84 }
85
86 fn emit_row(&self, _row: Value) {}
87
88 fn get_env(&self, _key: &str) -> Option<String> {
89 None
90 }
91
92 #[cfg(feature = "host-http")]
93 fn http_request(
94 &self,
95 _url: &str,
96 _method: HttpMethod,
97 _body: Option<&str>,
98 ) -> crate::error::Result<HttpResponse> {
99 Err(crate::error::AfterburnerError::Host(
100 "http_request not implemented".into(),
101 ))
102 }
103}
104
105/// Zero-capability host context - useful as a default for tests and for the
106/// minimal flow-engine path that only uses `Log`.
107pub struct NullHost;
108
109impl HostContext for NullHost {}