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