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    /// Feature gate for ext-php-rs (default: "extension-module").
149    /// All generated code is wrapped in `#[cfg(feature = "...")]`.
150    #[serde(default)]
151    pub feature_gate: Option<String>,
152    /// Output directory for generated PHP facade / stubs (e.g., `packages/php/src/`).
153    #[serde(default)]
154    pub stubs: Option<StubsConfig>,
155    #[serde(default)]
156    pub features: Option<Vec<String>>,
157    /// Override the serde rename_all strategy for JSON field names (e.g. "camelCase", "snake_case").
158    /// When set, this takes priority over the IR type-level serde_rename_all.
159    #[serde(default)]
160    pub serde_rename_all: Option<String>,
161    /// Functions to exclude from PHP binding generation.
162    #[serde(default)]
163    pub exclude_functions: Vec<String>,
164    /// Types to exclude from PHP binding generation.
165    #[serde(default)]
166    pub exclude_types: Vec<String>,
167    /// Additional Cargo dependencies for this language's binding crate only.
168    #[serde(default)]
169    pub extra_dependencies: HashMap<String, toml::Value>,
170    /// Override the scaffold output directory for this language's Cargo.toml and package files.
171    #[serde(default)]
172    pub scaffold_output: Option<PathBuf>,
173    /// Per-field name remapping for this language. Key is `TypeName.field_name`, value is the
174    /// desired binding field name. Applied after automatic keyword escaping.
175    #[serde(default)]
176    pub rename_fields: HashMap<String, String>,
177    /// Prefix wrapper for default tool invocations. When set, prepends this string to default
178    /// commands across all pipelines (lint, test, build, etc.).
179    #[serde(default)]
180    pub run_wrapper: Option<String>,
181    /// Extra paths to append to default lint commands (format, check, typecheck).
182    #[serde(default)]
183    pub extra_lint_paths: Vec<String>,
184}
185
186#[derive(Debug, Clone, Serialize, Deserialize)]
187pub struct ElixirConfig {
188    pub app_name: Option<String>,
189    #[serde(default)]
190    pub features: Option<Vec<String>>,
191    /// Override the serde rename_all strategy for JSON field names (e.g. "camelCase", "snake_case").
192    /// When set, this takes priority over the IR type-level serde_rename_all.
193    #[serde(default)]
194    pub serde_rename_all: Option<String>,
195    /// Functions to exclude from Elixir NIF generation.
196    #[serde(default)]
197    pub exclude_functions: Vec<String>,
198    /// Types to exclude from Elixir NIF generation.
199    #[serde(default)]
200    pub exclude_types: Vec<String>,
201    /// Additional Cargo dependencies for this language's binding crate only.
202    #[serde(default)]
203    pub extra_dependencies: HashMap<String, toml::Value>,
204    /// Override the scaffold output directory for this language's Cargo.toml and package files.
205    #[serde(default)]
206    pub scaffold_output: Option<PathBuf>,
207    /// Per-field name remapping for this language. Key is `TypeName.field_name`, value is the
208    /// desired binding field name. Applied after automatic keyword escaping.
209    #[serde(default)]
210    pub rename_fields: HashMap<String, String>,
211    /// Prefix wrapper for default tool invocations. When set, prepends this string to default
212    /// commands across all pipelines (lint, test, build, etc.).
213    #[serde(default)]
214    pub run_wrapper: Option<String>,
215    /// Extra paths to append to default lint commands (format, check, typecheck).
216    #[serde(default)]
217    pub extra_lint_paths: Vec<String>,
218}
219
220#[derive(Debug, Clone, Serialize, Deserialize)]
221pub struct WasmConfig {
222    #[serde(default)]
223    pub exclude_functions: Vec<String>,
224    #[serde(default)]
225    pub exclude_types: Vec<String>,
226    #[serde(default)]
227    pub type_overrides: HashMap<String, String>,
228    #[serde(default)]
229    pub features: Option<Vec<String>>,
230    /// Override the serde rename_all strategy for JSON field names (e.g. "camelCase", "snake_case").
231    /// When set, this takes priority over the IR type-level serde_rename_all.
232    #[serde(default)]
233    pub serde_rename_all: Option<String>,
234    /// Prefix for generated type names (e.g. "Wasm" produces `WasmConversionOptions`).
235    /// Defaults to `"Wasm"`.
236    #[serde(default)]
237    pub type_prefix: Option<String>,
238    /// Functions to exclude from the public TypeScript re-export (index.ts) while still
239    /// generating the Rust binding. Use this when a custom module provides a wrapper.
240    #[serde(default)]
241    pub exclude_reexports: Vec<String>,
242    /// Wide-character C functions to shim for WASM external scanner interop.
243    #[serde(default)]
244    pub env_shims: Vec<String>,
245    /// Additional Cargo dependencies for the WASM binding crate only.
246    #[serde(default)]
247    pub extra_dependencies: HashMap<String, toml::Value>,
248    /// Per-field name remapping for this language. Key is `TypeName.field_name`, value is the
249    /// desired binding field name. Applied after automatic keyword escaping.
250    #[serde(default)]
251    pub rename_fields: HashMap<String, String>,
252    /// Prefix wrapper for default tool invocations. When set, prepends this string to default
253    /// commands across all pipelines (lint, test, build, etc.).
254    #[serde(default)]
255    pub run_wrapper: Option<String>,
256    /// Extra paths to append to default lint commands (format, check, typecheck).
257    #[serde(default)]
258    pub extra_lint_paths: Vec<String>,
259    /// Override the core Cargo dependency name and path for the WASM binding crate.
260    /// When set, the binding `Cargo.toml` depends on this crate (resolved as
261    /// `../<override>`) instead of the umbrella `[crate.name]`. Use this to point
262    /// the WASM binding at a wasm-safe sub-crate while other languages keep the
263    /// facade. Defaults to unset.
264    #[serde(default)]
265    pub core_crate_override: Option<String>,
266    /// Keys to subtract from the merged `extra_dependencies` set for this
267    /// language only. Useful when `[crate.extra_dependencies]` lists sibling
268    /// crates that the WASM target cannot link.
269    #[serde(default)]
270    pub exclude_extra_dependencies: Vec<String>,
271    /// Hand-written Rust modules to declare in the generated lib.rs with `pub mod <name>;`
272    /// and re-export with `pub use <name>::*;`. Separate from `[custom_modules].wasm` which
273    /// only adds TypeScript `export *` re-exports. Use this for Rust-side dispatch/glue modules.
274    #[serde(default)]
275    pub custom_rust_modules: Vec<String>,
276    /// Per-type field exclusions for the generated From impls and binding struct.
277    /// Key is the type name (e.g. "ServerConfig"), value is a list of field names to skip.
278    /// Use when source fields are gated behind `#[cfg(not(target_arch = "wasm32"))]` and
279    /// therefore don't exist in the wasm32 compilation environment.
280    #[serde(default)]
281    pub exclude_fields: HashMap<String, Vec<String>>,
282    /// Source crate names whose types are re-exported by the `core_crate_override`
283    /// crate. References to `<original_crate>::TypeName` in generated code are
284    /// rewritten to `<override_crate>::TypeName`. Only meaningful when
285    /// `core_crate_override` is set.
286    /// Example: with `core_crate_override = "spikard-http"`, setting
287    /// `source_crate_remaps = ["spikard-core", "spikard"]` rewrites
288    /// `spikard_core::Method` and `spikard::Method` references to
289    /// `spikard_http::Method` (assumes `spikard-http` re-exports them via
290    /// `pub use spikard_core::*`).
291    #[serde(default)]
292    pub source_crate_remaps: Vec<String>,
293}
294
295#[derive(Debug, Clone, Serialize, Deserialize)]
296pub struct FfiConfig {
297    pub prefix: Option<String>,
298    #[serde(default = "default_error_style")]
299    pub error_style: String,
300    pub header_name: Option<String>,
301    /// Native library name for Go cgo/Java Panama/C# P/Invoke (e.g., "ts_pack_ffi").
302    /// Defaults to `{prefix}_ffi`.
303    #[serde(default)]
304    pub lib_name: Option<String>,
305    /// If true, generate visitor/callback FFI support.
306    #[serde(default)]
307    pub visitor_callbacks: bool,
308    #[serde(default)]
309    pub features: Option<Vec<String>>,
310    /// Override the serde rename_all strategy for JSON field names (e.g. "camelCase", "snake_case").
311    /// When set, this takes priority over the IR type-level serde_rename_all.
312    #[serde(default)]
313    pub serde_rename_all: Option<String>,
314    /// Functions to exclude from FFI binding generation.
315    #[serde(default)]
316    pub exclude_functions: Vec<String>,
317    /// Types to exclude from FFI binding generation.
318    #[serde(default)]
319    pub exclude_types: Vec<String>,
320    /// Per-field name remapping for this language. Key is `TypeName.field_name`, value is the
321    /// desired binding field name. Applied after automatic keyword escaping.
322    #[serde(default)]
323    pub rename_fields: HashMap<String, String>,
324}
325
326fn default_error_style() -> String {
327    "last_error".to_string()
328}
329
330#[derive(Debug, Clone, Serialize, Deserialize)]
331pub struct GoConfig {
332    pub module: Option<String>,
333    /// Override the Go package name (default: derived from module path)
334    pub package_name: Option<String>,
335    #[serde(default)]
336    pub features: Option<Vec<String>>,
337    /// Override the serde rename_all strategy for JSON field names (e.g. "camelCase", "snake_case").
338    /// When set, this takes priority over the IR type-level serde_rename_all.
339    #[serde(default)]
340    pub serde_rename_all: Option<String>,
341    /// Per-field name remapping for this language. Key is `TypeName.field_name`, value is the
342    /// desired binding field name. Applied after automatic keyword escaping.
343    #[serde(default)]
344    pub rename_fields: HashMap<String, String>,
345    /// Prefix wrapper for default tool invocations. When set, prepends this string to default
346    /// commands across all pipelines (lint, test, build, etc.).
347    #[serde(default)]
348    pub run_wrapper: Option<String>,
349    /// Extra paths to append to default lint commands (format, check, typecheck).
350    #[serde(default)]
351    pub extra_lint_paths: Vec<String>,
352}
353
354#[derive(Debug, Clone, Serialize, Deserialize)]
355pub struct JavaConfig {
356    pub package: Option<String>,
357    #[serde(default = "default_java_ffi_style")]
358    pub ffi_style: String,
359    #[serde(default)]
360    pub features: Option<Vec<String>>,
361    /// Override the serde rename_all strategy for JSON field names (e.g. "camelCase", "snake_case").
362    /// When set, this takes priority over the IR type-level serde_rename_all.
363    #[serde(default)]
364    pub serde_rename_all: Option<String>,
365    /// Per-field name remapping for this language. Key is `TypeName.field_name`, value is the
366    /// desired binding field name. Applied after automatic keyword escaping.
367    #[serde(default)]
368    pub rename_fields: HashMap<String, String>,
369    /// Prefix wrapper for default tool invocations. When set, prepends this string to default
370    /// commands across all pipelines (lint, test, build, etc.).
371    #[serde(default)]
372    pub run_wrapper: Option<String>,
373    /// Extra paths to append to default lint commands (format, check, typecheck).
374    /// Ignored when project_file is set.
375    #[serde(default)]
376    pub extra_lint_paths: Vec<String>,
377    /// Project file for Maven/Gradle (e.g., "pom.xml", "build.gradle"). When set, default
378    /// lint/build/test commands target this file instead of the output directory.
379    #[serde(default)]
380    pub project_file: Option<String>,
381}
382
383fn default_java_ffi_style() -> String {
384    "panama".to_string()
385}
386
387/// Target platform for Kotlin code generation.
388///
389/// - `"jvm"` (default): emits source consuming the Java/Panama FFM facade.
390/// - `"native"`: emits Kotlin/Native source consuming the cbindgen C FFI library.
391/// - `"multiplatform"`: reserved for the KMP stage (Phase 3 follow-up).
392#[derive(Debug, Clone, Copy, Default, Serialize, Deserialize, PartialEq, Eq)]
393#[serde(rename_all = "lowercase")]
394pub enum KotlinTarget {
395    #[default]
396    Jvm,
397    Native,
398    // Multiplatform — Phase 3 KMP stage; placeholder so the enum is forward-compatible.
399    Multiplatform,
400}
401
402#[derive(Debug, Clone, Serialize, Deserialize)]
403pub struct KotlinConfig {
404    pub package: Option<String>,
405    #[serde(default)]
406    pub features: Option<Vec<String>>,
407    /// Override the serde rename_all strategy for JSON field names (e.g. "camelCase", "snake_case").
408    /// When set, this takes priority over the IR type-level serde_rename_all.
409    #[serde(default)]
410    pub serde_rename_all: Option<String>,
411    /// Per-field name remapping for this language. Key is `TypeName.field_name`, value is the
412    /// desired binding field name. Applied after automatic keyword escaping.
413    #[serde(default)]
414    pub rename_fields: HashMap<String, String>,
415    /// Functions to exclude from Kotlin binding generation.
416    #[serde(default)]
417    pub exclude_functions: Vec<String>,
418    /// Types to exclude from Kotlin binding generation.
419    #[serde(default)]
420    pub exclude_types: Vec<String>,
421    /// Prefix wrapper for default tool invocations. When set, prepends this string to default
422    /// commands across all pipelines (lint, test, build, etc.).
423    #[serde(default)]
424    pub run_wrapper: Option<String>,
425    /// Extra paths to append to default lint commands (format, check, typecheck).
426    #[serde(default)]
427    pub extra_lint_paths: Vec<String>,
428    /// Target platform for Kotlin output. `"jvm"` (default) emits source consuming
429    /// the Java/Panama FFM facade; `"native"` emits Kotlin/Native source consuming
430    /// the cbindgen C FFI library. `"multiplatform"` is reserved for the KMP stage.
431    #[serde(default)]
432    pub target: KotlinTarget,
433}
434
435/// Dart bridging style: FRB (default) or raw `dart:ffi`.
436#[derive(Debug, Clone, Copy, Default, Serialize, Deserialize, PartialEq, Eq)]
437#[serde(rename_all = "lowercase")]
438pub enum DartStyle {
439    /// flutter_rust_bridge — emits a Rust crate plus Dart wrappers using
440    /// FRB-generated bridge symbols. Default.
441    #[default]
442    Frb,
443    /// Raw `dart:ffi` over the cbindgen C ABI — emits Dart-only source that
444    /// loads the shared library at runtime. Cheaper to ship; loses FRB's
445    /// async ergonomics and freezed-style data classes.
446    Ffi,
447}
448
449#[derive(Debug, Clone, Default, Serialize, Deserialize)]
450pub struct DartConfig {
451    /// Dart pub.dev package name (e.g. `"my_package"`). Used as the `name` in
452    /// `pubspec.yaml`. Defaults to a snake_case derivation of the crate name.
453    #[serde(default)]
454    pub pubspec_name: Option<String>,
455    /// Dart library name (the `library` declaration). Defaults to the pubspec name.
456    #[serde(default)]
457    pub lib_name: Option<String>,
458    /// Dart package name override (e.g. for pub.dev scoped packages).
459    #[serde(default)]
460    pub package_name: Option<String>,
461    /// Bridging style. `"frb"` (default) uses flutter_rust_bridge; `"ffi"` emits
462    /// raw `dart:ffi` source over the cbindgen C library.
463    #[serde(default)]
464    pub style: DartStyle,
465    /// flutter_rust_bridge version to pin in generated pubspec.yaml.
466    /// Defaults to `template_versions::cargo::FLUTTER_RUST_BRIDGE` when unset.
467    #[serde(default)]
468    pub frb_version: Option<String>,
469    /// Cargo features to enable on the binding crate.
470    #[serde(default)]
471    pub features: Option<Vec<String>>,
472    /// Override the serde rename_all strategy for JSON field names (e.g. "camelCase", "snake_case").
473    #[serde(default)]
474    pub serde_rename_all: Option<String>,
475    /// Per-field name remapping. Key is `TypeName.field_name`, value is the
476    /// desired binding field name. Applied after automatic keyword escaping.
477    #[serde(default)]
478    pub rename_fields: HashMap<String, String>,
479    /// Functions to exclude from Dart binding generation.
480    #[serde(default)]
481    pub exclude_functions: Vec<String>,
482    /// Types to exclude from Dart binding generation.
483    #[serde(default)]
484    pub exclude_types: Vec<String>,
485    /// Prefix wrapper for default tool invocations.
486    #[serde(default)]
487    pub run_wrapper: Option<String>,
488    /// Extra paths to append to default lint commands.
489    #[serde(default)]
490    pub extra_lint_paths: Vec<String>,
491    /// Override the core Cargo dependency name and path for the Dart binding crate.
492    /// When set, the binding `Cargo.toml` depends on this crate (resolved as
493    /// `../../../crates/<override>`) instead of the umbrella `[crate.name]`.
494    /// Defaults to unset.
495    #[serde(default)]
496    pub core_crate_override: Option<String>,
497    /// Keys to subtract from the merged `extra_dependencies` set for this
498    /// language only.
499    #[serde(default)]
500    pub exclude_extra_dependencies: Vec<String>,
501}
502
503#[derive(Debug, Clone, Default, Serialize, Deserialize)]
504pub struct SwiftConfig {
505    /// Swift module name (e.g. `"MyLibrary"`). Defaults to PascalCase of the crate name.
506    #[serde(default)]
507    pub module_name: Option<String>,
508    /// Swift package name. Defaults to the module name.
509    #[serde(default)]
510    pub package_name: Option<String>,
511    /// swift-bridge version. Defaults to `template_versions::cargo::SWIFT_BRIDGE` when unset.
512    #[serde(default)]
513    pub swift_bridge_version: Option<String>,
514    /// Minimum macOS deployment target. Defaults to `template_versions::toolchain::SWIFT_MIN_MACOS` when unset.
515    #[serde(default)]
516    pub min_macos_version: Option<String>,
517    /// Minimum iOS deployment target. Defaults to `template_versions::toolchain::SWIFT_MIN_IOS` when unset.
518    #[serde(default)]
519    pub min_ios_version: Option<String>,
520    /// Cargo features to enable on the binding crate.
521    #[serde(default)]
522    pub features: Option<Vec<String>>,
523    /// Override the serde rename_all strategy for JSON field names (e.g. "camelCase", "snake_case").
524    #[serde(default)]
525    pub serde_rename_all: Option<String>,
526    /// Per-field name remapping. Key is `TypeName.field_name`, value is the
527    /// desired binding field name. Applied after automatic keyword escaping.
528    #[serde(default)]
529    pub rename_fields: HashMap<String, String>,
530    /// Functions to exclude from Swift binding generation.
531    #[serde(default)]
532    pub exclude_functions: Vec<String>,
533    /// Types to exclude from Swift binding generation.
534    #[serde(default)]
535    pub exclude_types: Vec<String>,
536    /// Fields to exclude from Swift binding generation.
537    /// Format: `"TypeName.field_name"`.
538    #[serde(default)]
539    pub exclude_fields: Vec<String>,
540    /// Prefix wrapper for default tool invocations.
541    #[serde(default)]
542    pub run_wrapper: Option<String>,
543    /// Extra paths to append to default lint commands.
544    #[serde(default)]
545    pub extra_lint_paths: Vec<String>,
546    /// Override the core Cargo dependency name and path for the Swift binding crate.
547    /// When set, the binding `Cargo.toml` depends on this crate (resolved as
548    /// `../../../crates/<override>`) instead of the umbrella `[crate.name]`.
549    /// Defaults to unset.
550    #[serde(default)]
551    pub core_crate_override: Option<String>,
552    /// Keys to subtract from the merged `extra_dependencies` set for this
553    /// language only.
554    #[serde(default)]
555    pub exclude_extra_dependencies: Vec<String>,
556}
557
558#[derive(Debug, Clone, Serialize, Deserialize)]
559pub struct GleamConfig {
560    pub app_name: Option<String>,
561    /// Erlang atom name for @external(erlang, "<nif>", ...) lookups (e.g., "my_app_nif").
562    /// Defaults to the app_name.
563    #[serde(default)]
564    pub nif_module: Option<String>,
565    #[serde(default)]
566    pub features: Option<Vec<String>>,
567    /// Override the serde rename_all strategy for JSON field names (e.g. "camelCase", "snake_case").
568    /// When set, this takes priority over the IR type-level serde_rename_all.
569    #[serde(default)]
570    pub serde_rename_all: Option<String>,
571    /// Per-field name remapping for this language. Key is `TypeName.field_name`, value is the
572    /// desired binding field name. Applied after automatic keyword escaping.
573    #[serde(default)]
574    pub rename_fields: HashMap<String, String>,
575    /// Functions to exclude from Gleam binding generation.
576    #[serde(default)]
577    pub exclude_functions: Vec<String>,
578    /// Types to exclude from Gleam binding generation.
579    #[serde(default)]
580    pub exclude_types: 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}
588
589#[derive(Debug, Clone, Serialize, Deserialize)]
590pub struct ZigConfig {
591    pub module_name: Option<String>,
592    #[serde(default)]
593    pub features: Option<Vec<String>>,
594    /// Override the serde rename_all strategy for JSON field names (e.g. "camelCase", "snake_case").
595    /// When set, this takes priority over the IR type-level serde_rename_all.
596    #[serde(default)]
597    pub serde_rename_all: Option<String>,
598    /// Per-field name remapping for this language. Key is `TypeName.field_name`, value is the
599    /// desired binding field name. Applied after automatic keyword escaping.
600    #[serde(default)]
601    pub rename_fields: HashMap<String, String>,
602    /// Functions to exclude from Zig binding generation.
603    #[serde(default)]
604    pub exclude_functions: Vec<String>,
605    /// Types to exclude from Zig binding generation.
606    #[serde(default)]
607    pub exclude_types: Vec<String>,
608    /// Prefix wrapper for default tool invocations.
609    #[serde(default)]
610    pub run_wrapper: Option<String>,
611    /// Extra paths to append to default lint commands.
612    #[serde(default)]
613    pub extra_lint_paths: Vec<String>,
614}
615
616#[derive(Debug, Clone, Serialize, Deserialize)]
617pub struct CSharpConfig {
618    pub namespace: Option<String>,
619    /// NuGet `<PackageId>` to publish under. When unset, falls back to `namespace`.
620    /// Use this when the published artifact id must differ from the C# `RootNamespace` —
621    /// e.g. when the unprefixed name is owned by a third party on nuget.org and
622    /// you publish under a vendor-prefixed id like `KreuzbergDev.<Lib>`.
623    #[serde(default)]
624    pub package_id: Option<String>,
625    pub target_framework: Option<String>,
626    #[serde(default)]
627    pub features: Option<Vec<String>>,
628    /// Override the serde rename_all strategy for JSON field names (e.g. "camelCase", "snake_case").
629    /// When set, this takes priority over the IR type-level serde_rename_all.
630    #[serde(default)]
631    pub serde_rename_all: Option<String>,
632    /// Per-field name remapping for this language. Key is `TypeName.field_name`, value is the
633    /// desired binding field name. Applied after automatic keyword escaping.
634    #[serde(default)]
635    pub rename_fields: HashMap<String, String>,
636    /// Prefix wrapper for default tool invocations. When set, prepends this string to default
637    /// commands across all pipelines (lint, test, build, etc.).
638    #[serde(default)]
639    pub run_wrapper: Option<String>,
640    /// Extra paths to append to default lint commands (format, check, typecheck).
641    /// Ignored when project_file is set.
642    #[serde(default)]
643    pub extra_lint_paths: Vec<String>,
644    /// Project file for C# (e.g., "MyProject.csproj", "MySolution.sln"). When set, default
645    /// lint/build/test commands target this file instead of the output directory.
646    #[serde(default)]
647    pub project_file: Option<String>,
648    /// Functions to exclude from C# binding generation (e.g., functions not present in the
649    /// C FFI layer). Excluded functions are omitted from both NativeMethods.cs and the
650    /// wrapper class.
651    #[serde(default)]
652    pub exclude_functions: Vec<String>,
653}
654
655#[derive(Debug, Clone, Serialize, Deserialize)]
656pub struct RConfig {
657    pub package_name: Option<String>,
658    #[serde(default)]
659    pub features: Option<Vec<String>>,
660    /// Override the serde rename_all strategy for JSON field names (e.g. "camelCase", "snake_case").
661    /// When set, this takes priority over the IR type-level serde_rename_all.
662    #[serde(default)]
663    pub serde_rename_all: Option<String>,
664    /// Per-field name remapping for this language. Key is `TypeName.field_name`, value is the
665    /// desired binding field name. Applied after automatic keyword escaping.
666    #[serde(default)]
667    pub rename_fields: HashMap<String, String>,
668    /// Prefix wrapper for default tool invocations. When set, prepends this string to default
669    /// commands across all pipelines (lint, test, build, etc.).
670    #[serde(default)]
671    pub run_wrapper: Option<String>,
672    /// Extra paths to append to default lint commands (format, check, typecheck).
673    #[serde(default)]
674    pub extra_lint_paths: Vec<String>,
675}
676
677/// Custom modules that alef should declare (mod X;) but not generate.
678/// These are hand-written modules imported by the generated lib.rs.
679#[derive(Debug, Clone, Default, Serialize, Deserialize)]
680pub struct CustomModulesConfig {
681    #[serde(default)]
682    pub python: Vec<String>,
683    #[serde(default)]
684    pub node: Vec<String>,
685    #[serde(default)]
686    pub ruby: Vec<String>,
687    #[serde(default)]
688    pub php: Vec<String>,
689    #[serde(default)]
690    pub elixir: Vec<String>,
691    #[serde(default)]
692    pub wasm: Vec<String>,
693    #[serde(default)]
694    pub ffi: Vec<String>,
695    #[serde(default)]
696    pub go: Vec<String>,
697    #[serde(default)]
698    pub java: Vec<String>,
699    #[serde(default)]
700    pub csharp: Vec<String>,
701    #[serde(default)]
702    pub r: Vec<String>,
703}
704
705impl CustomModulesConfig {
706    pub fn for_language(&self, lang: Language) -> &[String] {
707        match lang {
708            Language::Python => &self.python,
709            Language::Node => &self.node,
710            Language::Ruby => &self.ruby,
711            Language::Php => &self.php,
712            Language::Elixir => &self.elixir,
713            Language::Wasm => &self.wasm,
714            Language::Ffi => &self.ffi,
715            Language::Go => &self.go,
716            Language::Java => &self.java,
717            Language::Csharp => &self.csharp,
718            Language::R => &self.r,
719            Language::Rust => &[], // Rust doesn't need custom modules (no binding crate)
720            Language::Kotlin | Language::Swift | Language::Dart | Language::Gleam | Language::Zig => &[],
721        }
722    }
723}
724
725/// Custom classes/functions from hand-written modules to register in module init.
726#[derive(Debug, Clone, Default, Serialize, Deserialize)]
727pub struct CustomRegistration {
728    #[serde(default)]
729    pub classes: Vec<String>,
730    #[serde(default)]
731    pub functions: Vec<String>,
732    #[serde(default)]
733    pub init_calls: Vec<String>,
734}
735
736/// Per-language custom registrations.
737#[derive(Debug, Clone, Default, Serialize, Deserialize)]
738pub struct CustomRegistrationsConfig {
739    #[serde(default)]
740    pub python: Option<CustomRegistration>,
741    #[serde(default)]
742    pub node: Option<CustomRegistration>,
743    #[serde(default)]
744    pub ruby: Option<CustomRegistration>,
745    #[serde(default)]
746    pub php: Option<CustomRegistration>,
747    #[serde(default)]
748    pub elixir: Option<CustomRegistration>,
749    #[serde(default)]
750    pub wasm: Option<CustomRegistration>,
751}
752
753impl CustomRegistrationsConfig {
754    pub fn for_language(&self, lang: Language) -> Option<&CustomRegistration> {
755        match lang {
756            Language::Python => self.python.as_ref(),
757            Language::Node => self.node.as_ref(),
758            Language::Ruby => self.ruby.as_ref(),
759            Language::Php => self.php.as_ref(),
760            Language::Elixir => self.elixir.as_ref(),
761            Language::Wasm => self.wasm.as_ref(),
762            _ => None,
763        }
764    }
765}