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
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
//! # rkyv-js-codegen
//!
//! TypeScript codec-binding generator for [rkyv](https://rkyv.org) types, targeting the `rkyv-js` runtime.
//!
//! The generator parses Rust sources with `syn`,
//! extracts every type marked with `#[derive(Archive)]` (or a custom marker),
//! and emits one `export const Archived{Name} = ...` codec per type.
//!
//! TypeScript types are always derived from the codecs via `r.Infer<typeof Archived{Name}>`.
//!
//! ## build.rs
//!
//! ```no_run
//! use rkyv_js_codegen::CodeGenerator;
//!
//! fn main() -> Result<(), rkyv_js_codegen::Error> {
//! CodeGenerator::new()
//! .add_source_file("src/lib.rs")?
//! .write_to_file("generated/bindings.ts")?;
//!
//! println!("cargo:rerun-if-changed=src/lib.rs");
//! Ok(())
//! }
//! ```
//!
//! ## Source extraction
//!
//! [`add_source_file`](CodeGenerator::add_source_file),
//! [`add_source_dir`](CodeGenerator::add_source_dir) (recursive), and
//! [`add_source_str`](CodeGenerator::add_source_str) all extract every type carrying the marker derive.
//! `use` imports are resolved to fully-qualified paths — aliases and globs included —
//! so registry lookups never depend on local names:
//!
//! ```
//! use rkyv_js_codegen::CodeGenerator;
//!
//! let mut generator = CodeGenerator::new();
//! generator.add_source_str(r#"
//! use rkyv::Archive;
//!
//! #[derive(Archive)]
//! pub struct Point { pub x: f64, pub y: f64 }
//! "#)?;
//!
//! assert_eq!(generator.archived_name_of("Point").as_deref(), Some("ArchivedPoint"));
//! # Ok::<(), rkyv_js_codegen::Error>(())
//! ```
//!
//! `#[derive(Archive)]` must be resolvable — through `use rkyv::Archive`, an
//! alias, a `use rkyv::*` glob, or an extra marker registered with
//! [`add_marker_path`](CodeGenerator::add_marker_path).
//!
//! ## Output options
//!
//! | Method | Effect |
//! |--------|--------|
//! | [`set_header`](CodeGenerator::set_header) | Replace the generated file's header comment |
//! | [`set_archived_name`](CodeGenerator::set_archived_name) | Override an export name, matching `#[rkyv(archived = Name)]` |
//! | [`set_direction`](CodeGenerator::set_direction) | Emit full, decode-only, or encode-only bindings |
//! | [`set_format`](CodeGenerator::set_format) | Target a non-default rkyv wire format |
//! | [`set_jit`](CodeGenerator::set_jit) | Wrap every export in the direction-matched `rkyv-js/jit` compile function |
//! | [`set_field_casing`](CodeGenerator::set_field_casing) | Rewrite field names, e.g. Rust's `snake_case` to JavaScript's `camelCase` |
//! | [`set_variant_casing`](CodeGenerator::set_variant_casing) | Rewrite enum variant tags |
//! | [`allow_typescript_syntax`](CodeGenerator::allow_typescript_syntax) | Drop `export type` lines, emitting plain JavaScript |
//! | [`on_unknown_type`](CodeGenerator::on_unknown_type) | Fail, or warn and omit, on unmappable types |
//!
//! ```
//! use rkyv_js_codegen::{Casing, CodeGenerator, Direction};
//!
//! let mut generator = CodeGenerator::new();
//! generator
//! .set_direction(Direction::Decode) // imports become `rkyv-js/decode`
//! .set_format("big", 64, true) // mirrors rkyv's feature flags
//! .set_field_casing(Casing::Camel) // `created_at` is emitted as `createdAt`
//! .allow_typescript_syntax(false);
//! ```
//!
//! Casing is a pure relabelling: rkyv structs are laid out positionally,
//! so the keys of an emitted `r.struct({ ... })` never affect the wire bytes.
//!
//! [`Direction`] rewrites only the `rkyv-js` import specifiers.
//!
//! Factory names and type exports are unchanged, and modules registered through
//! [`register_external`](CodeGenerator::register_external) are left alone,
//! so one schema can produce direction-matched bundles for a browser client and a Rust-facing service.
//!
//! Emission is deterministic: dependency-ordered, alphabetical within ties, so generated files diff cleanly.
//!
//! ## Expressions instead of format strings
//!
//! Codec expressions are a typed tree ([`CodecExpr`]) with builders that mirror the runtime combinators ([`codec`]):
//!
//! ```
//! use rkyv_js_codegen::{CodeGenerator, codec};
//!
//! let mut generator = CodeGenerator::new();
//! generator.add_struct("Person", [
//! ("name", codec::string()),
//! ("age", codec::u32()),
//! ("email", codec::option(codec::string())),
//! ]);
//! let code = generator.generate()?;
//! assert!(code.contains("email: r.option(r.string),"));
//! # Ok::<(), rkyv_js_codegen::Error>(())
//! ```
//!
//! ## Extending the registry
//!
//! External crate types are registered by fully-qualified Rust path:
//!
//! ```
//! use rkyv_js_codegen::{CodeGenerator, CodecExpr, ExternalType, WithWrapper};
//!
//! let mut generator = CodeGenerator::new();
//!
//! // `my_crate::MyVec<T>` → `myVec(T)` from a custom module.
//! generator.register_external(
//! "my_crate::MyVec",
//! ExternalType::generic1(|t| {
//! CodecExpr::call(CodecExpr::import_from("my-package/codecs", "myVec"), [t])
//! }),
//! );
//!
//! // `#[rkyv(with = AsJson)]` fields → a hand-written codec.
//! generator.register_with(
//! "AsJson",
//! WithWrapper::replace(CodecExpr::import_from("./custom.ts", "asJson")),
//! );
//! ```
//!
//! ## Error handling
//!
//! Parse failures surface immediately from `add_source_*`; everything else is validated in [`CodeGenerator::generate`],
//! which aggregates all [`Diagnostic`]s into a single [`Error::Codegen`].
//!
//! Set [`OnUnknown::SkipContainingType`] to emit `cargo:warning`s and omit affected types instead of failing.
pub use Casing;
pub use ;
pub use ;
pub use ;
pub use ;