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}
260
261#[derive(Debug, Clone, Serialize, Deserialize)]
262pub struct FfiConfig {
263    pub prefix: Option<String>,
264    #[serde(default = "default_error_style")]
265    pub error_style: String,
266    pub header_name: Option<String>,
267    /// Native library name for Go cgo/Java Panama/C# P/Invoke (e.g., "ts_pack_ffi").
268    /// Defaults to `{prefix}_ffi`.
269    #[serde(default)]
270    pub lib_name: Option<String>,
271    /// If true, generate visitor/callback FFI support.
272    #[serde(default)]
273    pub visitor_callbacks: bool,
274    #[serde(default)]
275    pub features: Option<Vec<String>>,
276    /// Override the serde rename_all strategy for JSON field names (e.g. "camelCase", "snake_case").
277    /// When set, this takes priority over the IR type-level serde_rename_all.
278    #[serde(default)]
279    pub serde_rename_all: Option<String>,
280    /// Functions to exclude from FFI binding generation.
281    #[serde(default)]
282    pub exclude_functions: Vec<String>,
283    /// Types to exclude from FFI binding generation.
284    #[serde(default)]
285    pub exclude_types: Vec<String>,
286    /// Per-field name remapping for this language. Key is `TypeName.field_name`, value is the
287    /// desired binding field name. Applied after automatic keyword escaping.
288    #[serde(default)]
289    pub rename_fields: HashMap<String, String>,
290}
291
292fn default_error_style() -> String {
293    "last_error".to_string()
294}
295
296#[derive(Debug, Clone, Serialize, Deserialize)]
297pub struct GoConfig {
298    pub module: Option<String>,
299    /// Override the Go package name (default: derived from module path)
300    pub package_name: Option<String>,
301    #[serde(default)]
302    pub features: Option<Vec<String>>,
303    /// Override the serde rename_all strategy for JSON field names (e.g. "camelCase", "snake_case").
304    /// When set, this takes priority over the IR type-level serde_rename_all.
305    #[serde(default)]
306    pub serde_rename_all: Option<String>,
307    /// Per-field name remapping for this language. Key is `TypeName.field_name`, value is the
308    /// desired binding field name. Applied after automatic keyword escaping.
309    #[serde(default)]
310    pub rename_fields: HashMap<String, String>,
311    /// Prefix wrapper for default tool invocations. When set, prepends this string to default
312    /// commands across all pipelines (lint, test, build, etc.).
313    #[serde(default)]
314    pub run_wrapper: Option<String>,
315    /// Extra paths to append to default lint commands (format, check, typecheck).
316    #[serde(default)]
317    pub extra_lint_paths: Vec<String>,
318}
319
320#[derive(Debug, Clone, Serialize, Deserialize)]
321pub struct JavaConfig {
322    pub package: Option<String>,
323    #[serde(default = "default_java_ffi_style")]
324    pub ffi_style: String,
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    /// Per-field name remapping for this language. Key is `TypeName.field_name`, value is the
332    /// desired binding field name. Applied after automatic keyword escaping.
333    #[serde(default)]
334    pub rename_fields: HashMap<String, String>,
335    /// Prefix wrapper for default tool invocations. When set, prepends this string to default
336    /// commands across all pipelines (lint, test, build, etc.).
337    #[serde(default)]
338    pub run_wrapper: Option<String>,
339    /// Extra paths to append to default lint commands (format, check, typecheck).
340    /// Ignored when project_file is set.
341    #[serde(default)]
342    pub extra_lint_paths: Vec<String>,
343    /// Project file for Maven/Gradle (e.g., "pom.xml", "build.gradle"). When set, default
344    /// lint/build/test commands target this file instead of the output directory.
345    #[serde(default)]
346    pub project_file: Option<String>,
347}
348
349fn default_java_ffi_style() -> String {
350    "panama".to_string()
351}
352
353/// Target platform for Kotlin code generation.
354///
355/// - `"jvm"` (default): emits source consuming the Java/Panama FFM facade.
356/// - `"native"`: emits Kotlin/Native source consuming the cbindgen C FFI library.
357/// - `"multiplatform"`: reserved for the KMP stage (Phase 3 follow-up).
358#[derive(Debug, Clone, Copy, Default, Serialize, Deserialize, PartialEq, Eq)]
359#[serde(rename_all = "lowercase")]
360pub enum KotlinTarget {
361    #[default]
362    Jvm,
363    Native,
364    // Multiplatform — Phase 3 KMP stage; placeholder so the enum is forward-compatible.
365    Multiplatform,
366}
367
368#[derive(Debug, Clone, Serialize, Deserialize)]
369pub struct KotlinConfig {
370    pub package: Option<String>,
371    #[serde(default)]
372    pub features: Option<Vec<String>>,
373    /// Override the serde rename_all strategy for JSON field names (e.g. "camelCase", "snake_case").
374    /// When set, this takes priority over the IR type-level serde_rename_all.
375    #[serde(default)]
376    pub serde_rename_all: Option<String>,
377    /// Per-field name remapping for this language. Key is `TypeName.field_name`, value is the
378    /// desired binding field name. Applied after automatic keyword escaping.
379    #[serde(default)]
380    pub rename_fields: HashMap<String, String>,
381    /// Functions to exclude from Kotlin binding generation.
382    #[serde(default)]
383    pub exclude_functions: Vec<String>,
384    /// Types to exclude from Kotlin binding generation.
385    #[serde(default)]
386    pub exclude_types: Vec<String>,
387    /// Prefix wrapper for default tool invocations. When set, prepends this string to default
388    /// commands across all pipelines (lint, test, build, etc.).
389    #[serde(default)]
390    pub run_wrapper: Option<String>,
391    /// Extra paths to append to default lint commands (format, check, typecheck).
392    #[serde(default)]
393    pub extra_lint_paths: Vec<String>,
394    /// Target platform for Kotlin output. `"jvm"` (default) emits source consuming
395    /// the Java/Panama FFM facade; `"native"` emits Kotlin/Native source consuming
396    /// the cbindgen C FFI library. `"multiplatform"` is reserved for the KMP stage.
397    #[serde(default)]
398    pub target: KotlinTarget,
399}
400
401/// Dart bridging style: FRB (default) or raw `dart:ffi`.
402#[derive(Debug, Clone, Copy, Default, Serialize, Deserialize, PartialEq, Eq)]
403#[serde(rename_all = "lowercase")]
404pub enum DartStyle {
405    /// flutter_rust_bridge — emits a Rust crate plus Dart wrappers using
406    /// FRB-generated bridge symbols. Default.
407    #[default]
408    Frb,
409    /// Raw `dart:ffi` over the cbindgen C ABI — emits Dart-only source that
410    /// loads the shared library at runtime. Cheaper to ship; loses FRB's
411    /// async ergonomics and freezed-style data classes.
412    Ffi,
413}
414
415#[derive(Debug, Clone, Default, Serialize, Deserialize)]
416pub struct DartConfig {
417    /// Dart pub.dev package name (e.g. `"my_package"`). Used as the `name` in
418    /// `pubspec.yaml`. Defaults to a snake_case derivation of the crate name.
419    #[serde(default)]
420    pub pubspec_name: Option<String>,
421    /// Dart library name (the `library` declaration). Defaults to the pubspec name.
422    #[serde(default)]
423    pub lib_name: Option<String>,
424    /// Dart package name override (e.g. for pub.dev scoped packages).
425    #[serde(default)]
426    pub package_name: Option<String>,
427    /// Bridging style. `"frb"` (default) uses flutter_rust_bridge; `"ffi"` emits
428    /// raw `dart:ffi` source over the cbindgen C library.
429    #[serde(default)]
430    pub style: DartStyle,
431    /// flutter_rust_bridge version to pin in generated pubspec.yaml.
432    /// Defaults to `template_versions::cargo::FLUTTER_RUST_BRIDGE` when unset.
433    #[serde(default)]
434    pub frb_version: Option<String>,
435    /// Cargo features to enable on the binding crate.
436    #[serde(default)]
437    pub features: Option<Vec<String>>,
438    /// Override the serde rename_all strategy for JSON field names (e.g. "camelCase", "snake_case").
439    #[serde(default)]
440    pub serde_rename_all: Option<String>,
441    /// Per-field name remapping. Key is `TypeName.field_name`, value is the
442    /// desired binding field name. Applied after automatic keyword escaping.
443    #[serde(default)]
444    pub rename_fields: HashMap<String, String>,
445    /// Functions to exclude from Dart binding generation.
446    #[serde(default)]
447    pub exclude_functions: Vec<String>,
448    /// Types to exclude from Dart binding generation.
449    #[serde(default)]
450    pub exclude_types: Vec<String>,
451    /// Prefix wrapper for default tool invocations.
452    #[serde(default)]
453    pub run_wrapper: Option<String>,
454    /// Extra paths to append to default lint commands.
455    #[serde(default)]
456    pub extra_lint_paths: Vec<String>,
457}
458
459#[derive(Debug, Clone, Default, Serialize, Deserialize)]
460pub struct SwiftConfig {
461    /// Swift module name (e.g. `"MyLibrary"`). Defaults to PascalCase of the crate name.
462    #[serde(default)]
463    pub module_name: Option<String>,
464    /// Swift package name. Defaults to the module name.
465    #[serde(default)]
466    pub package_name: Option<String>,
467    /// swift-bridge version. Defaults to `template_versions::cargo::SWIFT_BRIDGE` when unset.
468    #[serde(default)]
469    pub swift_bridge_version: Option<String>,
470    /// Minimum macOS deployment target. Defaults to `template_versions::toolchain::SWIFT_MIN_MACOS` when unset.
471    #[serde(default)]
472    pub min_macos_version: Option<String>,
473    /// Minimum iOS deployment target. Defaults to `template_versions::toolchain::SWIFT_MIN_IOS` when unset.
474    #[serde(default)]
475    pub min_ios_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 Swift binding generation.
487    #[serde(default)]
488    pub exclude_functions: Vec<String>,
489    /// Types to exclude from Swift binding generation.
490    #[serde(default)]
491    pub exclude_types: Vec<String>,
492    /// Fields to exclude from Swift binding generation.
493    /// Format: `"TypeName.field_name"`.
494    #[serde(default)]
495    pub exclude_fields: Vec<String>,
496    /// Prefix wrapper for default tool invocations.
497    #[serde(default)]
498    pub run_wrapper: Option<String>,
499    /// Extra paths to append to default lint commands.
500    #[serde(default)]
501    pub extra_lint_paths: Vec<String>,
502}
503
504#[derive(Debug, Clone, Serialize, Deserialize)]
505pub struct GleamConfig {
506    pub app_name: Option<String>,
507    /// Erlang atom name for @external(erlang, "<nif>", ...) lookups (e.g., "my_app_nif").
508    /// Defaults to the app_name.
509    #[serde(default)]
510    pub nif_module: Option<String>,
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    /// When set, this takes priority over the IR type-level serde_rename_all.
515    #[serde(default)]
516    pub serde_rename_all: Option<String>,
517    /// Per-field name remapping for this language. Key is `TypeName.field_name`, value is the
518    /// desired binding field name. Applied after automatic keyword escaping.
519    #[serde(default)]
520    pub rename_fields: HashMap<String, String>,
521    /// Functions to exclude from Gleam binding generation.
522    #[serde(default)]
523    pub exclude_functions: Vec<String>,
524    /// Types to exclude from Gleam binding generation.
525    #[serde(default)]
526    pub exclude_types: Vec<String>,
527    /// Prefix wrapper for default tool invocations.
528    #[serde(default)]
529    pub run_wrapper: Option<String>,
530    /// Extra paths to append to default lint commands.
531    #[serde(default)]
532    pub extra_lint_paths: Vec<String>,
533}
534
535#[derive(Debug, Clone, Serialize, Deserialize)]
536pub struct ZigConfig {
537    pub module_name: Option<String>,
538    #[serde(default)]
539    pub features: Option<Vec<String>>,
540    /// Override the serde rename_all strategy for JSON field names (e.g. "camelCase", "snake_case").
541    /// When set, this takes priority over the IR type-level serde_rename_all.
542    #[serde(default)]
543    pub serde_rename_all: Option<String>,
544    /// Per-field name remapping for this language. Key is `TypeName.field_name`, value is the
545    /// desired binding field name. Applied after automatic keyword escaping.
546    #[serde(default)]
547    pub rename_fields: HashMap<String, String>,
548    /// Functions to exclude from Zig binding generation.
549    #[serde(default)]
550    pub exclude_functions: Vec<String>,
551    /// Types to exclude from Zig binding generation.
552    #[serde(default)]
553    pub exclude_types: Vec<String>,
554    /// Prefix wrapper for default tool invocations.
555    #[serde(default)]
556    pub run_wrapper: Option<String>,
557    /// Extra paths to append to default lint commands.
558    #[serde(default)]
559    pub extra_lint_paths: Vec<String>,
560}
561
562#[derive(Debug, Clone, Serialize, Deserialize)]
563pub struct CSharpConfig {
564    pub namespace: Option<String>,
565    pub target_framework: Option<String>,
566    #[serde(default)]
567    pub features: Option<Vec<String>>,
568    /// Override the serde rename_all strategy for JSON field names (e.g. "camelCase", "snake_case").
569    /// When set, this takes priority over the IR type-level serde_rename_all.
570    #[serde(default)]
571    pub serde_rename_all: Option<String>,
572    /// Per-field name remapping for this language. Key is `TypeName.field_name`, value is the
573    /// desired binding field name. Applied after automatic keyword escaping.
574    #[serde(default)]
575    pub rename_fields: HashMap<String, String>,
576    /// Prefix wrapper for default tool invocations. When set, prepends this string to default
577    /// commands across all pipelines (lint, test, build, etc.).
578    #[serde(default)]
579    pub run_wrapper: Option<String>,
580    /// Extra paths to append to default lint commands (format, check, typecheck).
581    /// Ignored when project_file is set.
582    #[serde(default)]
583    pub extra_lint_paths: Vec<String>,
584    /// Project file for C# (e.g., "MyProject.csproj", "MySolution.sln"). When set, default
585    /// lint/build/test commands target this file instead of the output directory.
586    #[serde(default)]
587    pub project_file: Option<String>,
588}
589
590#[derive(Debug, Clone, Serialize, Deserialize)]
591pub struct RConfig {
592    pub package_name: Option<String>,
593    #[serde(default)]
594    pub features: Option<Vec<String>>,
595    /// Override the serde rename_all strategy for JSON field names (e.g. "camelCase", "snake_case").
596    /// When set, this takes priority over the IR type-level serde_rename_all.
597    #[serde(default)]
598    pub serde_rename_all: Option<String>,
599    /// Per-field name remapping for this language. Key is `TypeName.field_name`, value is the
600    /// desired binding field name. Applied after automatic keyword escaping.
601    #[serde(default)]
602    pub rename_fields: HashMap<String, String>,
603    /// Prefix wrapper for default tool invocations. When set, prepends this string to default
604    /// commands across all pipelines (lint, test, build, etc.).
605    #[serde(default)]
606    pub run_wrapper: Option<String>,
607    /// Extra paths to append to default lint commands (format, check, typecheck).
608    #[serde(default)]
609    pub extra_lint_paths: Vec<String>,
610}
611
612/// Custom modules that alef should declare (mod X;) but not generate.
613/// These are hand-written modules imported by the generated lib.rs.
614#[derive(Debug, Clone, Default, Serialize, Deserialize)]
615pub struct CustomModulesConfig {
616    #[serde(default)]
617    pub python: Vec<String>,
618    #[serde(default)]
619    pub node: Vec<String>,
620    #[serde(default)]
621    pub ruby: Vec<String>,
622    #[serde(default)]
623    pub php: Vec<String>,
624    #[serde(default)]
625    pub elixir: Vec<String>,
626    #[serde(default)]
627    pub wasm: Vec<String>,
628    #[serde(default)]
629    pub ffi: Vec<String>,
630    #[serde(default)]
631    pub go: Vec<String>,
632    #[serde(default)]
633    pub java: Vec<String>,
634    #[serde(default)]
635    pub csharp: Vec<String>,
636    #[serde(default)]
637    pub r: Vec<String>,
638}
639
640impl CustomModulesConfig {
641    pub fn for_language(&self, lang: Language) -> &[String] {
642        match lang {
643            Language::Python => &self.python,
644            Language::Node => &self.node,
645            Language::Ruby => &self.ruby,
646            Language::Php => &self.php,
647            Language::Elixir => &self.elixir,
648            Language::Wasm => &self.wasm,
649            Language::Ffi => &self.ffi,
650            Language::Go => &self.go,
651            Language::Java => &self.java,
652            Language::Csharp => &self.csharp,
653            Language::R => &self.r,
654            Language::Rust => &[], // Rust doesn't need custom modules (no binding crate)
655            Language::Kotlin | Language::Swift | Language::Dart | Language::Gleam | Language::Zig => &[],
656        }
657    }
658}
659
660/// Custom classes/functions from hand-written modules to register in module init.
661#[derive(Debug, Clone, Default, Serialize, Deserialize)]
662pub struct CustomRegistration {
663    #[serde(default)]
664    pub classes: Vec<String>,
665    #[serde(default)]
666    pub functions: Vec<String>,
667    #[serde(default)]
668    pub init_calls: Vec<String>,
669}
670
671/// Per-language custom registrations.
672#[derive(Debug, Clone, Default, Serialize, Deserialize)]
673pub struct CustomRegistrationsConfig {
674    #[serde(default)]
675    pub python: Option<CustomRegistration>,
676    #[serde(default)]
677    pub node: Option<CustomRegistration>,
678    #[serde(default)]
679    pub ruby: Option<CustomRegistration>,
680    #[serde(default)]
681    pub php: Option<CustomRegistration>,
682    #[serde(default)]
683    pub elixir: Option<CustomRegistration>,
684    #[serde(default)]
685    pub wasm: Option<CustomRegistration>,
686}
687
688impl CustomRegistrationsConfig {
689    pub fn for_language(&self, lang: Language) -> Option<&CustomRegistration> {
690        match lang {
691            Language::Python => self.python.as_ref(),
692            Language::Node => self.node.as_ref(),
693            Language::Ruby => self.ruby.as_ref(),
694            Language::Php => self.php.as_ref(),
695            Language::Elixir => self.elixir.as_ref(),
696            Language::Wasm => self.wasm.as_ref(),
697            _ => None,
698        }
699    }
700}