npm.io
1.0.7 • Published 4d ago

@suamnkayal/react-fusion

Licence
MIT
Version
1.0.7
Deps
5
Size
83 kB
Vulns
0
Weekly
0

React Fusion

npm version npm downloads TypeScript License: MIT

React Fusion is a lightweight, database-agnostic React library + Vite plugin for building full-stack applications with zero API boilerplate.

Write backend server functions and call them directly from your React components, with end-to-end type safety and no code generation step.

Not a framework. React Fusion doesn't enforce file-based routing, a custom bundler, or SSR. It connects your React frontend to your Node backend through Vite. Bring your own database (Prisma, Drizzle, Mongoose, etc.) and your own routing (React Router, Wouter, etc.).


Table of Contents


Features

  • Zero API boilerplate — no fetch calls, no endpoint config, no manual JSON parsing.
  • End-to-end type safety — types flow from your server functions into your React hooks automatically, no CLI code-gen step.
  • Familiar hooksuseServer and useMutation, modeled after the React Query mental model.
  • Smart caching — in-memory request deduplication, TTL caching, and manual cache invalidation.
  • First-class auth — built-in JWT auth, refresh tokens, and role-based access control (RBAC).
  • Devtools — a floating panel for inspecting queries, mutations, cache state, and events.
  • Zod validation — validate incoming arguments on the server before your handler runs.
  • Database-agnostic — works with PostgreSQL, MongoDB, MySQL, or any data source via your ORM of choice.

Requirements

Dependency Minimum version
Node.js 18.x or later
React 18.x or later
Vite 4.x or later
TypeScript (optional, recommended) 5.x

React Fusion assumes a Vite + Node setup. It does not currently support webpack, Next.js, or other non-Vite bundlers.


Installation

Install React Fusion and its peer dependency, Zod:

# npm
npm install @suamnkayal/react-fusion zod

# yarn
yarn add @suamnkayal/react-fusion zod

# pnpm
pnpm add @suamnkayal/react-fusion zod

Quick Start

1. Add the Vite plugin

Add React Fusion to your vite.config.ts. The plugin strips server-only code out of the client bundle and wires up the RPC endpoints automatically.

import { defineConfig } from "vite";
import react from "@vitejs/plugin-react";
import fusion from "@suamnkayal/react-fusion/vite";

export default defineConfig({
  plugins: [react(), fusion()],
});
2. Write a server function

Create a file under src/fusion/server/. React Fusion discovers these files automatically — no manual route registration needed.

// src/fusion/server/users.ts
import { server } from "@suamnkayal/react-fusion/runtime";

// Replace this with your real data layer (Prisma, Drizzle, etc.)
const users = [
  { id: 1, name: "Alice" },
  { id: 2, name: "Bob" },
];

export const getUsers = server("getUsers", async () => {
  return users;
});

export const createUser = server("createUser", async (name: string) => {
  const user = { id: users.length + 1, name };
  users.push(user);
  return user;
});
3. Call it from React

Import the server functions directly into your components. The Vite plugin ensures only the type information — never the server logic itself — reaches the browser.

// src/App.tsx
import { useServer, useMutation } from "@suamnkayal/react-fusion/react";
import { getUsers, createUser } from "./fusion/server/users";

export default function App() {
  const { data: users, isLoading } = useServer(getUsers);
  const { mutate, isLoading: isCreating } = useMutation(createUser);

  if (isLoading) return <p>Loading...</p>;

  return (
    <div>
      <ul>
        {users?.map((user) => (
          <li key={user.id}>{user.name}</li>
        ))}
      </ul>
      <button onClick={() => mutate("Charlie")} disabled={isCreating}>
        Add User
      </button>
    </div>
  );
}

Advanced Usage

Input validation with Zod

Validate incoming arguments before your handler runs. Validation errors are caught automatically and returned to the client as a structured error — your handler body never has to check for malformed input.

import { z } from "zod";
import { server } from "@suamnkayal/react-fusion/runtime";
import { db } from "../db"; // your own database client (Prisma, Drizzle, etc.)

export const createUser = server(
  "createUser",
  async (data: { name: string; age: number }) => {
    // `data` is guaranteed to match the schema below by the time this runs
    return await db.users.create(data);
  },
  {
    validate: z.object({
      name: z.string().min(2),
      age: z.number().min(18),
    }),
  }
);

The example above assumes a db client from your own ORM setup (Prisma, Drizzle, Mongoose, etc.). React Fusion does not ship a database client — see Database Agnostic.

Authentication & RBAC

Restrict routes to authenticated users, or to specific roles.

import { protectedRoute } from "@suamnkayal/react-fusion/runtime";

// Requires a logged-in user
export const getProfile = protectedRoute(async (ctx) => {
  return { userId: ctx.user.id, secretData: "This is private" };
});

// Requires the "admin" role
export const deleteUser = protectedRoute(
  ["admin"],
  async (userId: string) => {
    return await db.users.delete(userId);
  }
);
Middleware

Run custom logic before a route's handler executes, either globally or per-route.

import { server, getContext } from "@suamnkayal/react-fusion/runtime";

const logger = async (ctx, next) => {
  console.log(`[Request] ${ctx.routeName}`);
  await next();
};

export const myRoute = server(
  "myRoute",
  async () => {
    const ctx = getContext(); // req, res, cookies, and the authenticated user
    return "Hello World";
  },
  { middleware: [logger] }
);
Devtools

A passive, production-safe panel for inspecting queries, mutations, and the cache in real time.

import { FusionDevtools } from "@suamnkayal/react-fusion/devtools";

function App() {
  return (
    <>
      <YourApp />
      <FusionDevtools />
    </>
  );
}

Devtools are automatically stripped from production builds when NODE_ENV === "production", so it's safe to leave <FusionDevtools /> mounted in your tree.


API Reference

server(name, handler, options?)

Defines a server function callable from the client.

Param Type Description
name string Unique identifier for the function.
handler (...args) => Promise<T> Server-side logic. Runs only on the server.
options.validate ZodSchema Optional schema used to validate arguments before handler runs.
options.middleware Middleware[] Optional list of middleware to run before handler.
useServer(serverFunction, ...args)

React hook for reading data from a server function.

Returns { data, isLoading, error, refetch }. Automatically caches and deduplicates concurrent calls with the same arguments.

useMutation(serverFunction)

React hook for triggering side effects or writes.

Returns { mutate, isLoading, error, data }. mutate(...args) calls the underlying server function and updates data/error accordingly.

protectedRoute(roles?, handler, options?)

Wraps a server function so it requires authentication. Pass an array of role strings as the first argument to additionally restrict by role; omit it to require only that the user is logged in.


Architecture Under the Hood

  • Vite plugin — statically analyzes files under src/fusion/server/, strips server-only code from the client bundle, and generates the client-side RPC stubs at dev/build time.
  • RPC clientuseServer and useMutation call your server functions over POST /__fusion/:id under the hood and manage the resulting state for you.
  • Server cache — in-flight requests are deduplicated, and successful responses are cached with a configurable TTL.
  • Database-agnostic — React Fusion never talks to a database directly. Your server functions return plain, JSON-serializable data, so any ORM or query layer (Prisma, Drizzle, Mongoose, raw SQL, etc.) works as-is.

Troubleshooting

Module not found: @suamnkayal/react-fusion/runtime Make sure the Vite plugin is registered in vite.config.ts — the runtime and react entry points are generated at dev-server start.

Server function is undefined on the client Confirm the file lives under src/fusion/server/ and that the function is a named export. Files outside that directory aren't discovered.

Devtools showing up in a production build Check that NODE_ENV is actually set to "production" during your build step — some custom build pipelines override this.

Validation errors aren't surfacing in useMutation Check error on the object returned by useMutation, not a thrown exception — validation failures are returned as data, not thrown.

If your issue isn't covered here, please open an issue with a minimal reproduction.


Contributing

Contributions are welcome.

  1. Fork the repo and create a branch from main.
  2. Make your changes, with tests where applicable.
  3. Run the existing test suite and linter before opening a PR.
  4. Open a pull request describing what changed and why.

Please open an issue first for larger changes so we can discuss the approach.


License

MIT 2026

Keywords