Skip to main content

evenframe_derive/
lib.rs

1use proc_macro::TokenStream;
2use syn::{Data, DeriveInput, parse_macro_input};
3mod deserialization_impl;
4mod enum_impl;
5mod imports;
6mod struct_impl;
7mod union_impl;
8
9/// Which pipeline(s) the derived type participates in.
10/// This is a local mirror used to generate the correct `::evenframe::types::Pipeline` tokens.
11#[derive(Clone, Copy)]
12pub(crate) enum PipelineKind {
13    Both,
14    Typesync,
15    Schemasync,
16}
17
18impl PipelineKind {
19    pub fn to_tokens(self) -> proc_macro2::TokenStream {
20        use quote::quote;
21        match self {
22            PipelineKind::Both => quote! { ::evenframe::types::Pipeline::Both },
23            PipelineKind::Typesync => quote! { ::evenframe::types::Pipeline::Typesync },
24            PipelineKind::Schemasync => quote! { ::evenframe::types::Pipeline::Schemasync },
25        }
26    }
27}
28
29/// For structs it generates both:
30/// - A `table_schema()` function returning a `helpers::TableSchema`
31#[proc_macro_derive(
32    Evenframe,
33    attributes(
34        edge,
35        define_field_statement,
36        format,
37        permissions,
38        mock_data,
39        validators,
40        relation,
41        event,
42        doccom,
43        macroforge_derive,
44        annotation,
45        unique,
46        index
47    )
48)]
49pub fn evenframe_derive(input: TokenStream) -> TokenStream {
50    let input = parse_macro_input!(input as DeriveInput);
51
52    match input.data {
53        Data::Struct(_) => struct_impl::generate_struct_impl(input, PipelineKind::Both).into(),
54        Data::Enum(_) => enum_impl::generate_enum_impl(input, PipelineKind::Both).into(),
55        _ => syn::Error::new(
56            input.ident.span(),
57            "Evenframe can only be used on structs and enums",
58        )
59        .to_compile_error()
60        .into(),
61    }
62}
63
64/// Derive macro for unions of persistable structs
65/// Each variant must contain exactly one persistable struct type
66#[proc_macro_derive(EvenframeUnion, attributes(macroforge_derive, annotation))]
67pub fn evenframe_union_derive(input: TokenStream) -> TokenStream {
68    let input = parse_macro_input!(input as DeriveInput);
69
70    match input.data {
71        Data::Enum(_) => union_impl::generate_union_impl(input).into(),
72        _ => syn::Error::new(
73            input.ident.span(),
74            "EvenframeUnion can only be used on enums",
75        )
76        .to_compile_error()
77        .into(),
78    }
79}
80
81/// Derive macro for types that only participate in TypeScript type generation.
82#[proc_macro_derive(
83    Typesync,
84    attributes(
85        edge,
86        define_field_statement,
87        format,
88        permissions,
89        mock_data,
90        validators,
91        relation,
92        event,
93        doccom,
94        macroforge_derive,
95        annotation,
96        unique,
97        index
98    )
99)]
100pub fn typesync_derive(input: TokenStream) -> TokenStream {
101    let input = parse_macro_input!(input as DeriveInput);
102
103    match input.data {
104        Data::Struct(_) => struct_impl::generate_struct_impl(input, PipelineKind::Typesync).into(),
105        Data::Enum(_) => enum_impl::generate_enum_impl(input, PipelineKind::Typesync).into(),
106        _ => syn::Error::new(
107            input.ident.span(),
108            "Typesync can only be used on structs and enums",
109        )
110        .to_compile_error()
111        .into(),
112    }
113}
114
115/// Derive macro for types that only participate in database schema synchronization.
116#[proc_macro_derive(
117    Schemasync,
118    attributes(
119        edge,
120        define_field_statement,
121        format,
122        permissions,
123        mock_data,
124        validators,
125        relation,
126        event,
127        doccom,
128        macroforge_derive,
129        annotation,
130        unique,
131        index
132    )
133)]
134pub fn schemasync_derive(input: TokenStream) -> TokenStream {
135    let input = parse_macro_input!(input as DeriveInput);
136
137    match input.data {
138        Data::Struct(_) => {
139            struct_impl::generate_struct_impl(input, PipelineKind::Schemasync).into()
140        }
141        Data::Enum(_) => enum_impl::generate_enum_impl(input, PipelineKind::Schemasync).into(),
142        _ => syn::Error::new(
143            input.ident.span(),
144            "Schemasync can only be used on structs and enums",
145        )
146        .to_compile_error()
147        .into(),
148    }
149}