NecrassRS

Your schema leads.
Rust delivers.

cargo install --git https://github.com/Necrass-Dev/NecrassRs.git necrassrs-cli --locked

Meet NecrassRs
SDL-first. Built for Rust.Scroll to see it happen necrass.rs

The contract comes first.

You write the schema.
Rust gets the shape.

Define your GraphQL API in SDL.
Cargo generates the contracts.
You bring the implementation.

schema.graphqlGraphQL SDL
Initial schema
type Query {
    hello(name: String!): String!
}
Add a field
type Query {
    hello(name: String!): String!
    version: String!
}

The source of truth.
Your API starts here.

Your public contract
resolvers.rsRust
Existing implementation
pub struct Query;

impl<C: Sync> crate::generated::resolvers::QueryResolver<C> for Query {}

impl<C: Sync> necrassrs::Resolver<crate::generated::fields::Query::hello, C> for Query {
    type Output = String;

    async fn resolve(
        &self,
        _context: &C,
        args: crate::generated::types::Query::hello::Args,
    ) -> Result<Self::Output, necrassrs::ResolverError> {
        Ok(format!("Hello, {}", args.name))
    }
}
After cargo build: a new stub, existing body preserved
pub struct Query;

impl<C: Sync> crate::generated::resolvers::QueryResolver<C> for Query {}

impl<C: Sync> necrassrs::Resolver<crate::generated::fields::Query::hello, C> for Query {
    type Output = String;

    async fn resolve(
        &self,
        _context: &C,
        args: crate::generated::types::Query::hello::Args,
    ) -> Result<Self::Output, necrassrs::ResolverError> {
        Ok(format!("Hello, {}", args.name))
    }
}

impl<C: Sync> necrassrs::Resolver<crate::generated::fields::Query::version, C> for Query {
    type Output = String;

    async fn resolve(
        &self,
        _context: &C,
        _args: crate::generated::types::Query::version::Args,
    ) -> Result<Self::Output, necrassrs::ResolverError> {
        ::core::unimplemented!()
    }
}
Your implementation
cargo buildSDL → Rust contracts + resolver scaffolding

Keep scrolling to evolve your schema.