1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
//! Code generation for vox RPC bindings across multiple languages.
//!
//! # This Is Where Code Generation Actually Happens
//!
//! While [`vox-macros`] parses your service traits and emits metadata, this crate
//! consumes that metadata and generates actual protocol implementations for:
//!
//! - **TypeScript** — Browser and Node.js clients
//! - **Swift** — iOS/macOS clients
//! - **Go** — Server and client implementations
//! - **Java** — Android and server implementations
//! - **Python** — Client bindings
//! - **Rust** — Extended codegen beyond what the proc macro provides
//!
//! # Usage: In Your build.rs
//!
//! ```ignore
//! // In your service crate's build.rs
//! use my_service::calculator_service_detail;
//!
//! fn main() {
//! let detail = calculator_service_detail();
//!
//! // Generate TypeScript client
//! let ts_code = vox_codegen::targets::typescript::generate(&detail);
//! std::fs::write("generated/calculator.ts", ts_code).unwrap();
//!
//! // Generate Go server
//! let go_code = vox_codegen::targets::go::generate(&detail);
//! std::fs::write("generated/calculator.go", go_code).unwrap();
//! }
//! ```
//!
//! # The Pipeline
//!
//! ```text
//! #[service] trait → ServiceDescriptor → vox-codegen → .ts, .go, .swift, ...
//! (your code) (runtime metadata) (build script) (generated code)
//! ```
//!
//! # Why Build Scripts? (The Technical Reason)
//!
//! Code generation happens in build scripts (not proc macros) because **proc macros
//! cannot see into the type system**.
//!
//! When a proc macro sees `Tx<String>` in a method signature, it sees tokens — it has
//! no idea if `Tx` refers to `vox::channel::Tx` or some user-defined type. It cannot
//! resolve type aliases, follow generic parameters, or inspect nested types.
//!
//! But here, with `facet::Shape`, we have **full type introspection**:
//!
//! ```ignore
//! // We can identify vox's Tx vs user-defined types
//! let shape = <Tx<String> as facet::Facet>::SHAPE;
//!
//! // We can traverse nested types like Result<Vec<Tx<T>>, Error>
//! // and find the Tx buried inside
//! ```
//!
//! This is why validation happens here:
//! - Is this actually vox's `Tx`/`Rx` channel type?
//! - Are channel types incorrectly used in error positions?
//! - What serialization does this nested type require?
//!
//! Additional benefits of build scripts:
//!
//! 1. **File I/O** — Build scripts can write files; proc macros cannot
//! 2. **Configuration** — Build scripts can read config files, env vars, etc.
//! 3. **Flexibility** — Different projects can generate different subsets of bindings
//!
//! [`vox-macros`]: https://docs.rs/vox-service-macros
use MethodDescriptor;