rkyv_js_codegen/lib.rs
1//! # rkyv-js-codegen
2//!
3//! TypeScript codec-binding generator for [rkyv](https://rkyv.org) types,
4//! targeting the `rkyv-js` runtime.
5//!
6//! The generator parses Rust sources with `syn`, extracts every type marked
7//! with `#[derive(Archive)]` (or a custom marker), and emits one
8//! `export const Archived{Name} = ...` codec per type. TypeScript types are
9//! always derived from the codecs via `r.Infer<typeof Archived{Name}>`.
10//!
11//! ## build.rs
12//!
13//! ```no_run
14//! use rkyv_js_codegen::CodeGenerator;
15//!
16//! fn main() -> Result<(), rkyv_js_codegen::Error> {
17//! CodeGenerator::new()
18//! .add_source_file("src/lib.rs")?
19//! .write_to_file("generated/bindings.ts")?;
20//!
21//! println!("cargo:rerun-if-changed=src/lib.rs");
22//! Ok(())
23//! }
24//! ```
25//!
26//! ## Expressions instead of format strings
27//!
28//! Codec expressions are a typed tree ([`CodecExpr`]) with builders that
29//! mirror the runtime combinators ([`codec`]):
30//!
31//! ```
32//! use rkyv_js_codegen::{CodeGenerator, codec};
33//!
34//! let mut generator = CodeGenerator::new();
35//! generator.add_struct("Person", [
36//! ("name", codec::string()),
37//! ("age", codec::u32()),
38//! ("email", codec::option(codec::string())),
39//! ]);
40//! let code = generator.generate()?;
41//! assert!(code.contains("email: r.option(r.string),"));
42//! # Ok::<(), rkyv_js_codegen::Error>(())
43//! ```
44//!
45//! ## Extending the registry
46//!
47//! External crate types are registered by fully-qualified Rust path:
48//!
49//! ```
50//! use rkyv_js_codegen::{CodeGenerator, CodecExpr, ExternalType, WithWrapper};
51//!
52//! let mut generator = CodeGenerator::new();
53//!
54//! // `my_crate::MyVec<T>` → `myVec(T)` from a custom module.
55//! generator.register_external(
56//! "my_crate::MyVec",
57//! ExternalType::generic1(|t| {
58//! CodecExpr::call(CodecExpr::import_from("my-package/codecs", "myVec"), [t])
59//! }),
60//! );
61//!
62//! // `#[rkyv(with = AsJson)]` fields → a hand-written codec.
63//! generator.register_with(
64//! "AsJson",
65//! WithWrapper::replace(CodecExpr::import_from("./custom.ts", "asJson")),
66//! );
67//! ```
68//!
69//! ## Error handling
70//!
71//! Parse failures surface immediately from `add_source_*`; everything else
72//! is validated in [`CodeGenerator::generate`], which aggregates all
73//! [`Diagnostic`]s into a single [`Error::Codegen`]. Set
74//! [`OnUnknown::SkipContainingType`] to emit `cargo:warning`s and omit
75//! affected types instead of failing.
76
77mod error;
78mod expr;
79mod extractor;
80mod generator;
81mod registry;
82
83pub use error::{Diagnostic, DiagnosticKind, Error, SourceLocation};
84pub use expr::{CodecExpr, Import, codec, generate_import_block};
85pub use generator::{CodeGenerator, Direction, EnumVariant, OnUnknown};
86pub use registry::{ExternalType, WithWrapper};