Skip to main content

alef_core/config/
languages.rs

1use serde::{Deserialize, Serialize};
2use std::collections::HashMap;
3use std::path::PathBuf;
4
5use super::extras::Language;
6
7#[derive(Debug, Clone, Serialize, Deserialize)]
8pub struct PythonConfig {
9    pub module_name: Option<String>,
10    pub async_runtime: Option<String>,
11    pub stubs: Option<StubsConfig>,
12    /// PyPI package name (e.g. `"html-to-markdown"`). Used as the `[project] name` in
13    /// `pyproject.toml` and to derive the `python-packages` list for maturin.
14    /// Defaults to the crate name.
15    #[serde(default)]
16    pub pip_name: Option<String>,
17    /// Per-language feature override. When set, these features are used instead of
18    /// `[crate] features` for this language's binding crate.
19    #[serde(default)]
20    pub features: Option<Vec<String>>,
21    /// Override the serde rename_all strategy for JSON field names (e.g. "camelCase", "snake_case").
22    /// When set, this takes priority over the IR type-level serde_rename_all.
23    #[serde(default)]
24    pub serde_rename_all: Option<String>,
25    /// Map of type name -> PyCapsule name for raw pointer wrapping.
26    /// When a function returns one of these types, alef generates PyCapsule_New instead of Arc wrapping.
27    // TODO: Wire into gen_bindings.rs to emit PyCapsule_New / PyCapsule_GetPointer at call sites.
28    #[serde(default)]
29    pub capsule_types: HashMap<String, String>,
30    /// When true, wrap blocking function bodies in py.allow_threads() to release the GIL.
31    // TODO: Wire into gen_bindings.rs to emit py.allow_threads(|| { ... }) for non-async functions.
32    #[serde(default)]
33    pub release_gil: bool,
34    /// Functions to exclude from Python binding generation.
35    #[serde(default)]
36    pub exclude_functions: Vec<String>,
37    /// Types to exclude from Python binding generation.
38    #[serde(default)]
39    pub exclude_types: Vec<String>,
40    /// Additional Cargo dependencies for this language's binding crate only.
41    #[serde(default)]
42    pub extra_dependencies: HashMap<String, toml::Value>,
43    /// Override the scaffold output directory for this language's Cargo.toml and package files.
44    #[serde(default)]
45    pub scaffold_output: Option<PathBuf>,
46    /// Per-field name remapping for this language. Key is `TypeName.field_name` (e.g.
47    /// `"LayoutDetection.class"`), value is the desired binding field name. Applied after
48    /// automatic keyword escaping, so an explicit entry takes priority.
49    #[serde(default)]
50    pub rename_fields: HashMap<String, String>,
51    /// Prefix wrapper for default tool invocations. When set, prepends this string to default
52    /// commands across all pipelines (lint, test, build, etc.).
53    /// E.g., `run_wrapper = "uv run --no-sync"` turns `ruff format packages/python` into
54    /// `uv run --no-sync ruff format packages/python`.
55    #[serde(default)]
56    pub run_wrapper: Option<String>,
57    /// Extra paths to append to default lint commands (format, check, typecheck).
58    /// Space-separated paths are appended to the command.
59    #[serde(default)]
60    pub extra_lint_paths: Vec<String>,
61}
62
63#[derive(Debug, Clone, Serialize, Deserialize)]
64pub struct StubsConfig {
65    pub output: PathBuf,
66}
67
68#[derive(Debug, Clone, Serialize, Deserialize)]
69pub struct NodeConfig {
70    pub package_name: Option<String>,
71    /// Per-language feature override. When set, these features are used instead of
72    /// `[crate] features` for this language's binding crate.
73    #[serde(default)]
74    pub features: Option<Vec<String>>,
75    /// Override the serde rename_all strategy for JSON field names (e.g. "camelCase", "snake_case").
76    /// When set, this takes priority over the IR type-level serde_rename_all.
77    #[serde(default)]
78    pub serde_rename_all: Option<String>,
79    /// Prefix for generated type names (e.g. "Js" produces `JsConversionOptions`).
80    /// Defaults to `"Js"`.
81    #[serde(default)]
82    pub type_prefix: Option<String>,
83    /// Functions to exclude from Node binding generation.
84    #[serde(default)]
85    pub exclude_functions: Vec<String>,
86    /// Types to exclude from Node binding generation.
87    #[serde(default)]
88    pub exclude_types: Vec<String>,
89    /// Additional Cargo dependencies for this language's binding crate only.
90    #[serde(default)]
91    pub extra_dependencies: HashMap<String, toml::Value>,
92    /// Override the scaffold output directory for this language's Cargo.toml and package files.
93    #[serde(default)]
94    pub scaffold_output: Option<PathBuf>,
95    /// Per-field name remapping for this language. Key is `TypeName.field_name`, value is the
96    /// desired binding field name. Applied after automatic keyword escaping.
97    #[serde(default)]
98    pub rename_fields: HashMap<String, String>,
99    /// Prefix wrapper for default tool invocations. When set, prepends this string to default
100    /// commands across all pipelines (lint, test, build, etc.).
101    #[serde(default)]
102    pub run_wrapper: Option<String>,
103    /// Extra paths to append to default lint commands (format, check, typecheck).
104    #[serde(default)]
105    pub extra_lint_paths: Vec<String>,
106}
107
108#[derive(Debug, Clone, Serialize, Deserialize)]
109pub struct RubyConfig {
110    pub gem_name: Option<String>,
111    pub stubs: Option<StubsConfig>,
112    /// Per-language feature override. When set, these features are used instead of
113    /// `[crate] features` for this language's binding crate.
114    #[serde(default)]
115    pub features: Option<Vec<String>>,
116    /// Override the serde rename_all strategy for JSON field names (e.g. "camelCase", "snake_case").
117    /// When set, this takes priority over the IR type-level serde_rename_all.
118    #[serde(default)]
119    pub serde_rename_all: Option<String>,
120    /// Functions to exclude from Ruby binding generation.
121    #[serde(default)]
122    pub exclude_functions: Vec<String>,
123    /// Types to exclude from Ruby binding generation.
124    #[serde(default)]
125    pub exclude_types: Vec<String>,
126    /// Additional Cargo dependencies for this language's binding crate only.
127    #[serde(default)]
128    pub extra_dependencies: HashMap<String, toml::Value>,
129    /// Override the scaffold output directory for this language's Cargo.toml and package files.
130    #[serde(default)]
131    pub scaffold_output: Option<PathBuf>,
132    /// Per-field name remapping for this language. Key is `TypeName.field_name`, value is the
133    /// desired binding field name. Applied after automatic keyword escaping.
134    #[serde(default)]
135    pub rename_fields: HashMap<String, String>,
136    /// Prefix wrapper for default tool invocations. When set, prepends this string to default
137    /// commands across all pipelines (lint, test, build, etc.).
138    #[serde(default)]
139    pub run_wrapper: Option<String>,
140    /// Extra paths to append to default lint commands (format, check, typecheck).
141    #[serde(default)]
142    pub extra_lint_paths: Vec<String>,
143}
144
145#[derive(Debug, Clone, Serialize, Deserialize)]
146pub struct PhpConfig {
147    pub extension_name: Option<String>,
148    /// Cargo crate name for the PHP binding (e.g. `"ts-pack-core-php"`).
149    /// Used to derive the shared library filename in the e2e test runner.
150    /// When absent, the lib name is derived from `extension_name` by appending `_php`.
151    #[serde(default)]
152    pub cargo_crate_name: Option<String>,
153    /// Override the PHP namespace used for class registration and PSR-4 autoloading.
154    ///
155    /// When set, this value is used verbatim as the PHP namespace (e.g. `"HtmlToMarkdown"`).
156    /// When absent, the namespace is derived from `extension_name` by splitting on `_` and
157    /// converting each segment to PascalCase (e.g. `html_to_markdown` → `Html\To\Markdown`).
158    #[serde(default)]
159    pub namespace: Option<String>,
160    /// Feature gate for ext-php-rs (default: "extension-module").
161    /// All generated code is wrapped in `#[cfg(feature = "...")]`.
162    #[serde(default)]
163    pub feature_gate: Option<String>,
164    /// Output directory for generated PHP facade / stubs (e.g., `packages/php/src/`).
165    #[serde(default)]
166    pub stubs: Option<StubsConfig>,
167    #[serde(default)]
168    pub features: Option<Vec<String>>,
169    /// Override the serde rename_all strategy for JSON field names (e.g. "camelCase", "snake_case").
170    /// When set, this takes priority over the IR type-level serde_rename_all.
171    #[serde(default)]
172    pub serde_rename_all: Option<String>,
173    /// Functions to exclude from PHP binding generation.
174    #[serde(default)]
175    pub exclude_functions: Vec<String>,
176    /// Types to exclude from PHP binding generation.
177    #[serde(default)]
178    pub exclude_types: Vec<String>,
179    /// Additional Cargo dependencies for this language's binding crate only.
180    #[serde(default)]
181    pub extra_dependencies: HashMap<String, toml::Value>,
182    /// Override the scaffold output directory for this language's Cargo.toml and package files.
183    #[serde(default)]
184    pub scaffold_output: Option<PathBuf>,
185    /// Per-field name remapping for this language. Key is `TypeName.field_name`, value is the
186    /// desired binding field name. Applied after automatic keyword escaping.
187    #[serde(default)]
188    pub rename_fields: HashMap<String, String>,
189    /// Prefix wrapper for default tool invocations. When set, prepends this string to default
190    /// commands across all pipelines (lint, test, build, etc.).
191    #[serde(default)]
192    pub run_wrapper: Option<String>,
193    /// Extra paths to append to default lint commands (format, check, typecheck).
194    #[serde(default)]
195    pub extra_lint_paths: Vec<String>,
196}
197
198#[derive(Debug, Clone, Serialize, Deserialize)]
199pub struct ElixirConfig {
200    pub app_name: Option<String>,
201    #[serde(default)]
202    pub features: Option<Vec<String>>,
203    /// Override the serde rename_all strategy for JSON field names (e.g. "camelCase", "snake_case").
204    /// When set, this takes priority over the IR type-level serde_rename_all.
205    #[serde(default)]
206    pub serde_rename_all: Option<String>,
207    /// Functions to exclude from Elixir NIF generation.
208    #[serde(default)]
209    pub exclude_functions: Vec<String>,
210    /// Types to exclude from Elixir NIF generation.
211    #[serde(default)]
212    pub exclude_types: Vec<String>,
213    /// Additional Cargo dependencies for this language's binding crate only.
214    #[serde(default)]
215    pub extra_dependencies: HashMap<String, toml::Value>,
216    /// Override the scaffold output directory for this language's Cargo.toml and package files.
217    #[serde(default)]
218    pub scaffold_output: Option<PathBuf>,
219    /// Per-field name remapping for this language. Key is `TypeName.field_name`, value is the
220    /// desired binding field name. Applied after automatic keyword escaping.
221    #[serde(default)]
222    pub rename_fields: HashMap<String, String>,
223    /// Prefix wrapper for default tool invocations. When set, prepends this string to default
224    /// commands across all pipelines (lint, test, build, etc.).
225    #[serde(default)]
226    pub run_wrapper: Option<String>,
227    /// Extra paths to append to default lint commands (format, check, typecheck).
228    #[serde(default)]
229    pub extra_lint_paths: Vec<String>,
230    /// Functions that should be scheduled on the dirty CPU scheduler.
231    /// HTML parsing and other CPU-intensive NIFs should be listed here to avoid
232    /// blocking BEAM scheduler threads.
233    #[serde(default)]
234    pub cpu_bound_functions: Vec<String>,
235}
236
237#[derive(Debug, Clone, Serialize, Deserialize)]
238pub struct WasmConfig {
239    #[serde(default)]
240    pub exclude_functions: Vec<String>,
241    #[serde(default)]
242    pub exclude_types: Vec<String>,
243    #[serde(default)]
244    pub type_overrides: HashMap<String, String>,
245    #[serde(default)]
246    pub features: Option<Vec<String>>,
247    /// Override the serde rename_all strategy for JSON field names (e.g. "camelCase", "snake_case").
248    /// When set, this takes priority over the IR type-level serde_rename_all.
249    #[serde(default)]
250    pub serde_rename_all: Option<String>,
251    /// Prefix for generated type names (e.g. "Wasm" produces `WasmConversionOptions`).
252    /// Defaults to `"Wasm"`.
253    #[serde(default)]
254    pub type_prefix: Option<String>,
255    /// Functions to exclude from the public TypeScript re-export (index.ts) while still
256    /// generating the Rust binding. Use this when a custom module provides a wrapper.
257    #[serde(default)]
258    pub exclude_reexports: Vec<String>,
259    /// Wide-character C functions to shim for WASM external scanner interop.
260    #[serde(default)]
261    pub env_shims: Vec<String>,
262    /// Additional Cargo dependencies for the WASM binding crate only.
263    #[serde(default)]
264    pub extra_dependencies: HashMap<String, toml::Value>,
265    /// Per-field name remapping for this language. Key is `TypeName.field_name`, value is the
266    /// desired binding field name. Applied after automatic keyword escaping.
267    #[serde(default)]
268    pub rename_fields: HashMap<String, String>,
269    /// Prefix wrapper for default tool invocations. When set, prepends this string to default
270    /// commands across all pipelines (lint, test, build, etc.).
271    #[serde(default)]
272    pub run_wrapper: Option<String>,
273    /// Extra paths to append to default lint commands (format, check, typecheck).
274    #[serde(default)]
275    pub extra_lint_paths: Vec<String>,
276    /// Override the core Cargo dependency name and path for the WASM binding crate.
277    /// When set, the binding `Cargo.toml` depends on this crate (resolved as
278    /// `../<override>`) instead of the umbrella `[crate.name]`. Use this to point
279    /// the WASM binding at a wasm-safe sub-crate while other languages keep the
280    /// facade. Defaults to unset.
281    #[serde(default)]
282    pub core_crate_override: Option<String>,
283    /// Keys to subtract from the merged `extra_dependencies` set for this
284    /// language only. Useful when `[crate.extra_dependencies]` lists sibling
285    /// crates that the WASM target cannot link.
286    #[serde(default)]
287    pub exclude_extra_dependencies: Vec<String>,
288    /// Hand-written Rust modules to declare in the generated lib.rs with `pub mod <name>;`
289    /// and re-export with `pub use <name>::*;`. Separate from `[custom_modules].wasm` which
290    /// only adds TypeScript `export *` re-exports. Use this for Rust-side dispatch/glue modules.
291    #[serde(default)]
292    pub custom_rust_modules: Vec<String>,
293    /// Per-type field exclusions for the generated From impls and binding struct.
294    /// Key is the type name (e.g. "ServerConfig"), value is a list of field names to skip.
295    /// Use when source fields are gated behind `#[cfg(not(target_arch = "wasm32"))]` and
296    /// therefore don't exist in the wasm32 compilation environment.
297    #[serde(default)]
298    pub exclude_fields: HashMap<String, Vec<String>>,
299    /// Source crate names whose types are re-exported by the `core_crate_override`
300    /// crate. References to `<original_crate>::TypeName` in generated code are
301    /// rewritten to `<override_crate>::TypeName`. Only meaningful when
302    /// `core_crate_override` is set.
303    /// Example: with `core_crate_override = "mylib-http"`, setting
304    /// `source_crate_remaps = ["mylib-core", "mylib"]` rewrites
305    /// `mylib_core::Method` and `mylib::Method` references to
306    /// `mylib_http::Method` (assumes `mylib-http` re-exports them via
307    /// `pub use mylib_core::*`).
308    #[serde(default)]
309    pub source_crate_remaps: Vec<String>,
310}
311
312#[derive(Debug, Clone, Serialize, Deserialize)]
313pub struct FfiConfig {
314    pub prefix: Option<String>,
315    #[serde(default = "default_error_style")]
316    pub error_style: String,
317    pub header_name: Option<String>,
318    /// Native library name for Go cgo/Java Panama/C# P/Invoke (e.g., "ts_pack_ffi").
319    /// Defaults to `{prefix}_ffi`.
320    #[serde(default)]
321    pub lib_name: Option<String>,
322    /// If true, generate visitor/callback FFI support.
323    #[serde(default)]
324    pub visitor_callbacks: bool,
325    #[serde(default)]
326    pub features: Option<Vec<String>>,
327    /// Override the serde rename_all strategy for JSON field names (e.g. "camelCase", "snake_case").
328    /// When set, this takes priority over the IR type-level serde_rename_all.
329    #[serde(default)]
330    pub serde_rename_all: Option<String>,
331    /// Functions to exclude from FFI binding generation.
332    #[serde(default)]
333    pub exclude_functions: Vec<String>,
334    /// Types to exclude from FFI binding generation.
335    #[serde(default)]
336    pub exclude_types: Vec<String>,
337    /// Per-field name remapping for this language. Key is `TypeName.field_name`, value is the
338    /// desired binding field name. Applied after automatic keyword escaping.
339    #[serde(default)]
340    pub rename_fields: HashMap<String, String>,
341    /// Rust expression used to construct an error value of this crate's
342    /// `error_type` from a runtime `String` message inside generated FFI
343    /// trait-bridge plugin shims (`plugin_impl_initialize`, `plugin_impl_shutdown`).
344    ///
345    /// The expression has access to a local variable `msg: String` containing
346    /// the underlying error message and is interpolated verbatim. Example
347    /// values:
348    ///
349    /// ```toml
350    /// # downstream whose error type has a struct variant with two fields:
351    /// plugin_error_constructor = """
352    /// kreuzberg::KreuzbergError::Plugin { message: msg, plugin_name: String::new() }
353    /// """
354    ///
355    /// # downstream whose error type implements `From<String>`:
356    /// plugin_error_constructor = "MyError::from(msg)"
357    /// ```
358    ///
359    /// Defaults to `None`. When unset, the plugin shim still emits — backends
360    /// fall back to a `format!("{}: {}", prefix, msg)`-style construction via
361    /// the configured `error_constructor`. Downstreams that don't expose
362    /// trait-bridged plugins can ignore this knob entirely.
363    #[serde(default)]
364    pub plugin_error_constructor: Option<String>,
365}
366
367fn default_error_style() -> String {
368    "last_error".to_string()
369}
370
371#[derive(Debug, Clone, Serialize, Deserialize)]
372pub struct GoConfig {
373    pub module: Option<String>,
374    /// Override the Go package name (default: derived from module path)
375    pub package_name: Option<String>,
376    #[serde(default)]
377    pub features: Option<Vec<String>>,
378    /// Override the serde rename_all strategy for JSON field names (e.g. "camelCase", "snake_case").
379    /// When set, this takes priority over the IR type-level serde_rename_all.
380    #[serde(default)]
381    pub serde_rename_all: Option<String>,
382    /// Per-field name remapping for this language. Key is `TypeName.field_name`, value is the
383    /// desired binding field name. Applied after automatic keyword escaping.
384    #[serde(default)]
385    pub rename_fields: HashMap<String, String>,
386    /// Prefix wrapper for default tool invocations. When set, prepends this string to default
387    /// commands across all pipelines (lint, test, build, etc.).
388    #[serde(default)]
389    pub run_wrapper: Option<String>,
390    /// Extra paths to append to default lint commands (format, check, typecheck).
391    #[serde(default)]
392    pub extra_lint_paths: Vec<String>,
393}
394
395#[derive(Debug, Clone, Serialize, Deserialize)]
396pub struct JavaConfig {
397    pub package: Option<String>,
398    #[serde(default = "default_java_ffi_style")]
399    pub ffi_style: String,
400    #[serde(default)]
401    pub features: Option<Vec<String>>,
402    /// Override the serde rename_all strategy for JSON field names (e.g. "camelCase", "snake_case").
403    /// When set, this takes priority over the IR type-level serde_rename_all.
404    #[serde(default)]
405    pub serde_rename_all: Option<String>,
406    /// Per-field name remapping for this language. Key is `TypeName.field_name`, value is the
407    /// desired binding field name. Applied after automatic keyword escaping.
408    #[serde(default)]
409    pub rename_fields: HashMap<String, String>,
410    /// Prefix wrapper for default tool invocations. When set, prepends this string to default
411    /// commands across all pipelines (lint, test, build, etc.).
412    #[serde(default)]
413    pub run_wrapper: Option<String>,
414    /// Extra paths to append to default lint commands (format, check, typecheck).
415    /// Ignored when project_file is set.
416    #[serde(default)]
417    pub extra_lint_paths: Vec<String>,
418    /// Project file for Maven/Gradle (e.g., "pom.xml", "build.gradle"). When set, default
419    /// lint/build/test commands target this file instead of the output directory.
420    #[serde(default)]
421    pub project_file: Option<String>,
422}
423
424fn default_java_ffi_style() -> String {
425    "panama".to_string()
426}
427
428/// Target platform for Kotlin code generation.
429///
430/// - `"jvm"` (default): emits source consuming the Java/Panama FFM facade.
431/// - `"native"`: emits Kotlin/Native source consuming the cbindgen C FFI library.
432/// - `"multiplatform"`: reserved for the KMP stage (Phase 3 follow-up).
433#[derive(Debug, Clone, Copy, Default, Serialize, Deserialize, PartialEq, Eq)]
434#[serde(rename_all = "lowercase")]
435pub enum KotlinTarget {
436    #[default]
437    Jvm,
438    Native,
439    // Multiplatform — Phase 3 KMP stage; placeholder so the enum is forward-compatible.
440    Multiplatform,
441}
442
443#[derive(Debug, Clone, Serialize, Deserialize)]
444pub struct KotlinConfig {
445    pub package: Option<String>,
446    #[serde(default)]
447    pub features: Option<Vec<String>>,
448    /// Override the serde rename_all strategy for JSON field names (e.g. "camelCase", "snake_case").
449    /// When set, this takes priority over the IR type-level serde_rename_all.
450    #[serde(default)]
451    pub serde_rename_all: Option<String>,
452    /// Per-field name remapping for this language. Key is `TypeName.field_name`, value is the
453    /// desired binding field name. Applied after automatic keyword escaping.
454    #[serde(default)]
455    pub rename_fields: HashMap<String, String>,
456    /// Functions to exclude from Kotlin binding generation.
457    #[serde(default)]
458    pub exclude_functions: Vec<String>,
459    /// Types to exclude from Kotlin binding generation.
460    #[serde(default)]
461    pub exclude_types: Vec<String>,
462    /// Prefix wrapper for default tool invocations. When set, prepends this string to default
463    /// commands across all pipelines (lint, test, build, etc.).
464    #[serde(default)]
465    pub run_wrapper: Option<String>,
466    /// Extra paths to append to default lint commands (format, check, typecheck).
467    #[serde(default)]
468    pub extra_lint_paths: Vec<String>,
469    /// Target platform for Kotlin output. `"jvm"` (default) emits source consuming
470    /// the Java/Panama FFM facade; `"native"` emits Kotlin/Native source consuming
471    /// the cbindgen C FFI library. `"multiplatform"` is reserved for the KMP stage.
472    #[serde(default)]
473    pub target: KotlinTarget,
474}
475
476/// Dart bridging style: FRB (default) or raw `dart:ffi`.
477#[derive(Debug, Clone, Copy, Default, Serialize, Deserialize, PartialEq, Eq)]
478#[serde(rename_all = "lowercase")]
479pub enum DartStyle {
480    /// flutter_rust_bridge — emits a Rust crate plus Dart wrappers using
481    /// FRB-generated bridge symbols. Default.
482    #[default]
483    Frb,
484    /// Raw `dart:ffi` over the cbindgen C ABI — emits Dart-only source that
485    /// loads the shared library at runtime. Cheaper to ship; loses FRB's
486    /// async ergonomics and freezed-style data classes.
487    Ffi,
488}
489
490#[derive(Debug, Clone, Default, Serialize, Deserialize)]
491pub struct DartConfig {
492    /// Dart pub.dev package name (e.g. `"my_package"`). Used as the `name` in
493    /// `pubspec.yaml`. Defaults to a snake_case derivation of the crate name.
494    #[serde(default)]
495    pub pubspec_name: Option<String>,
496    /// Dart library name (the `library` declaration). Defaults to the pubspec name.
497    #[serde(default)]
498    pub lib_name: Option<String>,
499    /// Dart package name override (e.g. for pub.dev scoped packages).
500    #[serde(default)]
501    pub package_name: Option<String>,
502    /// Bridging style. `"frb"` (default) uses flutter_rust_bridge; `"ffi"` emits
503    /// raw `dart:ffi` source over the cbindgen C library.
504    #[serde(default)]
505    pub style: DartStyle,
506    /// flutter_rust_bridge version to pin in generated pubspec.yaml.
507    /// Defaults to `template_versions::cargo::FLUTTER_RUST_BRIDGE` when unset.
508    #[serde(default)]
509    pub frb_version: Option<String>,
510    /// Cargo features to enable on the binding crate.
511    #[serde(default)]
512    pub features: Option<Vec<String>>,
513    /// Override the serde rename_all strategy for JSON field names (e.g. "camelCase", "snake_case").
514    #[serde(default)]
515    pub serde_rename_all: Option<String>,
516    /// Per-field name remapping. Key is `TypeName.field_name`, value is the
517    /// desired binding field name. Applied after automatic keyword escaping.
518    #[serde(default)]
519    pub rename_fields: HashMap<String, String>,
520    /// Functions to exclude from Dart binding generation.
521    #[serde(default)]
522    pub exclude_functions: Vec<String>,
523    /// Types to exclude from Dart binding generation.
524    #[serde(default)]
525    pub exclude_types: Vec<String>,
526    /// Prefix wrapper for default tool invocations.
527    #[serde(default)]
528    pub run_wrapper: Option<String>,
529    /// Extra paths to append to default lint commands.
530    #[serde(default)]
531    pub extra_lint_paths: Vec<String>,
532    /// Override the core Cargo dependency name and path for the Dart binding crate.
533    /// When set, the binding `Cargo.toml` depends on this crate (resolved as
534    /// `../../../crates/<override>`) instead of the umbrella `[crate.name]`.
535    /// Defaults to unset.
536    #[serde(default)]
537    pub core_crate_override: Option<String>,
538    /// Keys to subtract from the merged `extra_dependencies` set for this
539    /// language only.
540    #[serde(default)]
541    pub exclude_extra_dependencies: Vec<String>,
542}
543
544#[derive(Debug, Clone, Default, Serialize, Deserialize)]
545pub struct SwiftConfig {
546    /// Swift module name (e.g. `"MyLibrary"`). Defaults to PascalCase of the crate name.
547    #[serde(default)]
548    pub module_name: Option<String>,
549    /// Swift package name. Defaults to the module name.
550    #[serde(default)]
551    pub package_name: Option<String>,
552    /// swift-bridge version. Defaults to `template_versions::cargo::SWIFT_BRIDGE` when unset.
553    #[serde(default)]
554    pub swift_bridge_version: Option<String>,
555    /// Minimum macOS deployment target. Defaults to `template_versions::toolchain::SWIFT_MIN_MACOS` when unset.
556    #[serde(default)]
557    pub min_macos_version: Option<String>,
558    /// Minimum iOS deployment target. Defaults to `template_versions::toolchain::SWIFT_MIN_IOS` when unset.
559    #[serde(default)]
560    pub min_ios_version: Option<String>,
561    /// Cargo features to enable on the binding crate.
562    #[serde(default)]
563    pub features: Option<Vec<String>>,
564    /// Override the serde rename_all strategy for JSON field names (e.g. "camelCase", "snake_case").
565    #[serde(default)]
566    pub serde_rename_all: Option<String>,
567    /// Per-field name remapping. Key is `TypeName.field_name`, value is the
568    /// desired binding field name. Applied after automatic keyword escaping.
569    #[serde(default)]
570    pub rename_fields: HashMap<String, String>,
571    /// Functions to exclude from Swift binding generation.
572    #[serde(default)]
573    pub exclude_functions: Vec<String>,
574    /// Types to exclude from Swift binding generation.
575    #[serde(default)]
576    pub exclude_types: Vec<String>,
577    /// Fields to exclude from Swift binding generation.
578    /// Format: `"TypeName.field_name"`.
579    #[serde(default)]
580    pub exclude_fields: Vec<String>,
581    /// Prefix wrapper for default tool invocations.
582    #[serde(default)]
583    pub run_wrapper: Option<String>,
584    /// Extra paths to append to default lint commands.
585    #[serde(default)]
586    pub extra_lint_paths: Vec<String>,
587    /// Override the core Cargo dependency name and path for the Swift binding crate.
588    /// When set, the binding `Cargo.toml` depends on this crate (resolved as
589    /// `../../../crates/<override>`) instead of the umbrella `[crate.name]`.
590    /// Defaults to unset.
591    #[serde(default)]
592    pub core_crate_override: Option<String>,
593    /// Keys to subtract from the merged `extra_dependencies` set for this
594    /// language only.
595    #[serde(default)]
596    pub exclude_extra_dependencies: Vec<String>,
597}
598
599#[derive(Debug, Clone, Serialize, Deserialize)]
600pub struct GleamConfig {
601    pub app_name: Option<String>,
602    /// Erlang atom name for @external(erlang, "<nif>", ...) lookups (e.g., "my_app_nif").
603    /// Defaults to the app_name.
604    #[serde(default)]
605    pub nif_module: Option<String>,
606    #[serde(default)]
607    pub features: Option<Vec<String>>,
608    /// Override the serde rename_all strategy for JSON field names (e.g. "camelCase", "snake_case").
609    /// When set, this takes priority over the IR type-level serde_rename_all.
610    #[serde(default)]
611    pub serde_rename_all: Option<String>,
612    /// Per-field name remapping for this language. Key is `TypeName.field_name`, value is the
613    /// desired binding field name. Applied after automatic keyword escaping.
614    #[serde(default)]
615    pub rename_fields: HashMap<String, String>,
616    /// Functions to exclude from Gleam binding generation.
617    #[serde(default)]
618    pub exclude_functions: Vec<String>,
619    /// Types to exclude from Gleam binding generation.
620    #[serde(default)]
621    pub exclude_types: Vec<String>,
622    /// Prefix wrapper for default tool invocations.
623    #[serde(default)]
624    pub run_wrapper: Option<String>,
625    /// Extra paths to append to default lint commands.
626    #[serde(default)]
627    pub extra_lint_paths: Vec<String>,
628    /// Per-`element_type` Gleam record-constructor recipes used by the e2e
629    /// generator when emitting `json_object` arg literals. Each entry maps a
630    /// fixture-side `element_type` string (e.g. `"BatchFileItem"`) to a
631    /// structured constructor description that the codegen interpolates per
632    /// JSON-array item. Without an entry the codegen falls back to the
633    /// `json_object_wrapper` (or a plain `json_to_gleam`).
634    ///
635    /// Example:
636    ///
637    /// ```toml
638    /// [[crates.gleam.element_constructors]]
639    /// element_type = "BatchFileItem"
640    /// constructor = "kreuzberg.BatchFileItem"
641    /// [[crates.gleam.element_constructors.fields]]
642    /// gleam_field = "path"
643    /// kind = "file_path"
644    /// json_field = "path"
645    /// [[crates.gleam.element_constructors.fields]]
646    /// gleam_field = "config"
647    /// kind = "literal"
648    /// value = "option.None"
649    /// ```
650    #[serde(default)]
651    pub element_constructors: Vec<GleamElementConstructor>,
652    /// Optional Gleam expression template used to wrap `json_object` arg
653    /// values when no `element_type` recipe matches. The placeholder
654    /// `{json}` is replaced with a Gleam string literal containing the JSON
655    /// form of the arg value, allowing the downstream's Gleam binding to do
656    /// its own parsing.
657    ///
658    /// Example:
659    ///
660    /// ```toml
661    /// [crates.gleam]
662    /// json_object_wrapper = "kreuzberg.config_from_json_string({json})"
663    /// ```
664    ///
665    /// When `None`, the codegen emits `{json}` verbatim (a plain Gleam
666    /// string), matching the iter15 default.
667    #[serde(default)]
668    pub json_object_wrapper: Option<String>,
669}
670
671/// One per-`element_type` Gleam record-constructor recipe. Keyed by the
672/// fixture-side `element_type` string and consumed by the e2e Gleam codegen
673/// when building `json_object` arg literals.
674#[derive(Debug, Clone, Serialize, Deserialize)]
675pub struct GleamElementConstructor {
676    /// Fixture-side `element_type` value this recipe applies to (e.g.
677    /// `"BatchFileItem"`).
678    pub element_type: String,
679    /// Fully-qualified Gleam constructor identifier (e.g.
680    /// `"kreuzberg.BatchFileItem"`). Emitted verbatim before the `(...)` field
681    /// list.
682    pub constructor: String,
683    /// Ordered list of fields to emit inside the constructor's `(...)` block,
684    /// in argument-position order. Each field describes how its value is
685    /// derived from the per-item JSON object.
686    pub fields: Vec<GleamElementField>,
687}
688
689/// One field inside a [`GleamElementConstructor`]'s argument list.
690///
691/// `kind` selects the source/encoding strategy:
692/// * `"file_path"` — read `json_field` from the JSON object as a string,
693///   prefix with the configured `test_documents_dir` when the value does not
694///   start with `/`, and emit as a Gleam string literal.
695/// * `"byte_array"` — read `json_field` from the JSON object as a JSON
696///   `Array(Number)` and emit as a Gleam BitArray literal `<<n1, n2, …>>`.
697/// * `"string"` — read `json_field` as a string, emit as a Gleam string
698///   literal; falls back to `default` (or empty) if missing.
699/// * `"literal"` — emit `value` verbatim (no JSON lookup). Use for
700///   constant fields like `config: option.None`.
701#[derive(Debug, Clone, Serialize, Deserialize)]
702pub struct GleamElementField {
703    /// Gleam record field name (e.g. `"path"`, `"config"`).
704    pub gleam_field: String,
705    /// Source/encoding strategy. See struct doc.
706    pub kind: String,
707    /// JSON object key to read, when `kind` is one of the JSON-driven
708    /// strategies. Required for `"file_path"`, `"byte_array"`, `"string"`;
709    /// ignored for `"literal"`.
710    #[serde(default)]
711    pub json_field: Option<String>,
712    /// Default Gleam expression when `json_field` is missing/null. Only
713    /// honoured by the `"string"` strategy today.
714    #[serde(default)]
715    pub default: Option<String>,
716    /// Verbatim Gleam expression to emit when `kind = "literal"`.
717    #[serde(default)]
718    pub value: Option<String>,
719}
720
721#[derive(Debug, Clone, Serialize, Deserialize)]
722pub struct ZigConfig {
723    pub module_name: Option<String>,
724    #[serde(default)]
725    pub features: Option<Vec<String>>,
726    /// Override the serde rename_all strategy for JSON field names (e.g. "camelCase", "snake_case").
727    /// When set, this takes priority over the IR type-level serde_rename_all.
728    #[serde(default)]
729    pub serde_rename_all: Option<String>,
730    /// Per-field name remapping for this language. Key is `TypeName.field_name`, value is the
731    /// desired binding field name. Applied after automatic keyword escaping.
732    #[serde(default)]
733    pub rename_fields: HashMap<String, String>,
734    /// Functions to exclude from Zig binding generation.
735    #[serde(default)]
736    pub exclude_functions: Vec<String>,
737    /// Types to exclude from Zig binding generation.
738    #[serde(default)]
739    pub exclude_types: Vec<String>,
740    /// Prefix wrapper for default tool invocations.
741    #[serde(default)]
742    pub run_wrapper: Option<String>,
743    /// Extra paths to append to default lint commands.
744    #[serde(default)]
745    pub extra_lint_paths: Vec<String>,
746}
747
748#[derive(Debug, Clone, Serialize, Deserialize)]
749pub struct CSharpConfig {
750    pub namespace: Option<String>,
751    /// NuGet `<PackageId>` to publish under. When unset, falls back to `namespace`.
752    /// Use this when the published artifact id must differ from the C# `RootNamespace` —
753    /// e.g. when the unprefixed name is owned by a third party on nuget.org and
754    /// you publish under a vendor-prefixed id like `KreuzbergDev.<Lib>`.
755    #[serde(default)]
756    pub package_id: Option<String>,
757    pub target_framework: Option<String>,
758    #[serde(default)]
759    pub features: Option<Vec<String>>,
760    /// Override the serde rename_all strategy for JSON field names (e.g. "camelCase", "snake_case").
761    /// When set, this takes priority over the IR type-level serde_rename_all.
762    #[serde(default)]
763    pub serde_rename_all: Option<String>,
764    /// Per-field name remapping for this language. Key is `TypeName.field_name`, value is the
765    /// desired binding field name. Applied after automatic keyword escaping.
766    #[serde(default)]
767    pub rename_fields: HashMap<String, String>,
768    /// Prefix wrapper for default tool invocations. When set, prepends this string to default
769    /// commands across all pipelines (lint, test, build, etc.).
770    #[serde(default)]
771    pub run_wrapper: Option<String>,
772    /// Extra paths to append to default lint commands (format, check, typecheck).
773    /// Ignored when project_file is set.
774    #[serde(default)]
775    pub extra_lint_paths: Vec<String>,
776    /// Project file for C# (e.g., "MyProject.csproj", "MySolution.sln"). When set, default
777    /// lint/build/test commands target this file instead of the output directory.
778    #[serde(default)]
779    pub project_file: Option<String>,
780    /// Functions to exclude from C# binding generation (e.g., functions not present in the
781    /// C FFI layer). Excluded functions are omitted from both NativeMethods.cs and the
782    /// wrapper class.
783    #[serde(default)]
784    pub exclude_functions: Vec<String>,
785}
786
787#[derive(Debug, Clone, Serialize, Deserialize)]
788pub struct RConfig {
789    pub package_name: Option<String>,
790    #[serde(default)]
791    pub features: Option<Vec<String>>,
792    /// Override the serde rename_all strategy for JSON field names (e.g. "camelCase", "snake_case").
793    /// When set, this takes priority over the IR type-level serde_rename_all.
794    #[serde(default)]
795    pub serde_rename_all: Option<String>,
796    /// Per-field name remapping for this language. Key is `TypeName.field_name`, value is the
797    /// desired binding field name. Applied after automatic keyword escaping.
798    #[serde(default)]
799    pub rename_fields: HashMap<String, String>,
800    /// Prefix wrapper for default tool invocations. When set, prepends this string to default
801    /// commands across all pipelines (lint, test, build, etc.).
802    #[serde(default)]
803    pub run_wrapper: Option<String>,
804    /// Extra paths to append to default lint commands (format, check, typecheck).
805    #[serde(default)]
806    pub extra_lint_paths: Vec<String>,
807}
808
809/// Custom modules that alef should declare (mod X;) but not generate.
810/// These are hand-written modules imported by the generated lib.rs.
811#[derive(Debug, Clone, Default, Serialize, Deserialize)]
812pub struct CustomModulesConfig {
813    #[serde(default)]
814    pub python: Vec<String>,
815    #[serde(default)]
816    pub node: Vec<String>,
817    #[serde(default)]
818    pub ruby: Vec<String>,
819    #[serde(default)]
820    pub php: Vec<String>,
821    #[serde(default)]
822    pub elixir: Vec<String>,
823    #[serde(default)]
824    pub wasm: Vec<String>,
825    #[serde(default)]
826    pub ffi: Vec<String>,
827    #[serde(default)]
828    pub go: Vec<String>,
829    #[serde(default)]
830    pub java: Vec<String>,
831    #[serde(default)]
832    pub csharp: Vec<String>,
833    #[serde(default)]
834    pub r: Vec<String>,
835}
836
837impl CustomModulesConfig {
838    pub fn for_language(&self, lang: Language) -> &[String] {
839        match lang {
840            Language::Python => &self.python,
841            Language::Node => &self.node,
842            Language::Ruby => &self.ruby,
843            Language::Php => &self.php,
844            Language::Elixir => &self.elixir,
845            Language::Wasm => &self.wasm,
846            Language::Ffi => &self.ffi,
847            Language::Go => &self.go,
848            Language::Java => &self.java,
849            Language::Csharp => &self.csharp,
850            Language::R => &self.r,
851            Language::Rust => &[], // Rust doesn't need custom modules (no binding crate)
852            Language::Kotlin | Language::Swift | Language::Dart | Language::Gleam | Language::Zig | Language::C => &[],
853        }
854    }
855}
856
857/// Custom classes/functions from hand-written modules to register in module init.
858#[derive(Debug, Clone, Default, Serialize, Deserialize)]
859pub struct CustomRegistration {
860    #[serde(default)]
861    pub classes: Vec<String>,
862    #[serde(default)]
863    pub functions: Vec<String>,
864    #[serde(default)]
865    pub init_calls: Vec<String>,
866}
867
868/// Per-language custom registrations.
869#[derive(Debug, Clone, Default, Serialize, Deserialize)]
870pub struct CustomRegistrationsConfig {
871    #[serde(default)]
872    pub python: Option<CustomRegistration>,
873    #[serde(default)]
874    pub node: Option<CustomRegistration>,
875    #[serde(default)]
876    pub ruby: Option<CustomRegistration>,
877    #[serde(default)]
878    pub php: Option<CustomRegistration>,
879    #[serde(default)]
880    pub elixir: Option<CustomRegistration>,
881    #[serde(default)]
882    pub wasm: Option<CustomRegistration>,
883}
884
885impl CustomRegistrationsConfig {
886    pub fn for_language(&self, lang: Language) -> Option<&CustomRegistration> {
887        match lang {
888            Language::Python => self.python.as_ref(),
889            Language::Node => self.node.as_ref(),
890            Language::Ruby => self.ruby.as_ref(),
891            Language::Php => self.php.as_ref(),
892            Language::Elixir => self.elixir.as_ref(),
893            Language::Wasm => self.wasm.as_ref(),
894            _ => None,
895        }
896    }
897}