Skip to main content

Crate rkyv_js_codegen

Crate rkyv_js_codegen 

Source
Expand description

§rkyv-js-codegen

TypeScript codec-binding generator for rkyv 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

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, add_source_dir (recursive), and 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"));

#[derive(Archive)] must be resolvable — through use rkyv::Archive, an alias, a use rkyv::* glob, or an extra marker registered with add_marker_path.

§Output options

MethodEffect
set_headerReplace the generated file’s header comment
set_archived_nameOverride an export name, matching #[rkyv(archived = Name)]
set_directionEmit full, decode-only, or encode-only bindings
set_formatTarget a non-default rkyv wire format
set_jitWrap every export in the direction-matched rkyv-js/jit compile function
set_field_casingRewrite field names, e.g. Rust’s snake_case to JavaScript’s camelCase
set_variant_casingRewrite enum variant tags
allow_typescript_syntaxDrop export type lines, emitting plain JavaScript
on_unknown_typeFail, 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 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),"));

§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 Diagnostics into a single Error::Codegen.

Set OnUnknown::SkipContainingType to emit cargo:warnings and omit affected types instead of failing.

Modules§

codec
Builders mirroring the rkyv-js runtime combinators.

Structs§

CodeGenerator
Collects type definitions — from Rust sources or programmatically — and generates TypeScript codec bindings for the rkyv-js runtime.
Diagnostic
A single code-generation problem with optional provenance.
ExternalType
A codec template for an external Rust type.
Import
A named import contributed by a CodecExpr::Import node.
SourceLocation
A position in a parsed source file.
WithWrapper
A handler for a #[rkyv(with = W)] field wrapper.

Enums§

Casing
The identifier casing of emitted field and variant names.
CodecExpr
A TypeScript codec expression.
DiagnosticKind
The kinds of code-generation diagnostics.
Direction
Which half of the codec surface the generated bindings target.
EnumVariant
An enum variant for CodeGenerator::add_enum.
Error
Top-level error type for the code generator.
OnUnknown
How to handle a field whose type cannot be mapped to a codec.

Functions§

generate_import_block
Generate the import block for a set of expressions.