npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@makay/rpc

v0.4.0

Published

An RPC library for quick development of seamless full-stack applications.

Downloads

14

Readme

🌐 @makay/rpc

An RPC library for quick development of seamless full-stack applications.

Powered by a Vite plugin and inspired by Telefunc, tRPC and other similar libraries.


✨ Features 🔧 Installation and setup 🚀 Usage

📝 Input validation 🚨 Errors 📦 Async server state 👍 Results 📡 Subscriptions

🔌 Adapters 🔥 Hono 💎 Zod

🧑🏻‍💻 Contributing 📄 License


✨ Features:

  • 🎉 End-to-end TypeScript
  • 🚫 Zero boilerplate
  • 📡 Optional server-sent events support for real-time subscriptions
  • 🪶 Extremely small client bundle size addition
  • 🔗 Directly import and call tailored server functions from client code
  • 📄 Colocate server and client files (or don't)
  • 📦 Front-end and back-end framework agnostic
  • 📦 Validation library agnostic
  • 🚫 Low server overhead with no implicit run-time validations
  • 🪝 Use the composables/hooks pattern in server code
  • 🔌 Includes adapters for popular libraries like Hono and Zod
  • 🧰 Includes utilities for async server state and results

🔧 Installation and setup

  1. Install a single package:

    npm i @makay/rpc
    yarn add @makay/rpc
    pnpm add @makay/rpc
    bun add @makay/rpc

    Everything is included out-of-the-box!

  2. Set up the Vite plugin:

    // vite.config.ts
    import { rpc } from "@makay/rpc/vite"
    import { defineConfig } from "vite"
    
    export default defineConfig({
      plugins: [rpc()],
    })

    You can run both vite to start a dev server or vite build to build for production.

  3. Set up the RPC server (example using the included Hono adapter):

    // src/server.ts
    import { serve } from "@hono/node-server"
    import { createRpc } from "@makay/rpc/hono"
    import { Hono } from "hono"
    import { cors } from "hono/cors"
    
    const app = new Hono()
    
    app.use(
      "/rpc",
      cors({ origin: "http://localhost:5173", credentials: true }),
      await createRpc()
    )
    
    serve(app, (info) => {
      console.log(`Server is running on http://localhost:${info.port}`)
    })

    You can run the above file with something like npx tsx src/server.ts.

    You can also run npx tsx watch src/server.ts to auto-reload during development.

  4. Configure your client:

    // src/main.ts
    import { config } from "@makay/rpc/client"
    
    config.url = "http://localhost:3000/rpc"
    config.credentials = "include"

🚀 Usage

Create client and server files and seamlessly import server types and functions from client code with full TypeScript support!

// src/components/Todos.ts
import { createTodo, getTodos, type Todo } from "./Todos.server"

let todos: Todo[] = []

async function main() {
  todos = await getTodos()

  console.log(todos)

  const newTodo = await createTodo("New Todo")

  console.log(newTodo)
}

main()
// src/components/Todos.server.ts
export type Todo = {
  id: string
  text: string
}

const todos: Todo[] = []

export async function getTodos() {
  return todos
}

export async function createTodo(text: string) {
  const todo = {
    id: crypto.randomUUID(),
    text,
  }

  todos.push(todo)

  return todo
}

Serve the above src/components/Todos.ts through Vite and you should see the array of todos printed to your browser console. Reload the page a bunch of times and you should see the array grow since the state is persisted in the server!

In a real scenario you would store your data in a database rather than in the server memory, of course. The snippets above are merely illustrative.

📝 Input validation

There is no implicit run-time validation of inputs in the server. In the example above, the function createTodo expects a single string argument. However, if your server is exposed publicly, bad actors or misconfigured clients might send something unexpected which can cause undefined behavior in you program.

Therefore, it is extremely recommended that you validate all function inputs. You can use any validation library you want for this.

Here's a basic example using Zod:

// src/components/Todos.server.ts
import { z } from "zod"

const TextSchema = z.string().min(1).max(256)

export async function createTodo(text: string) {
  TextSchema.parse(text)

  // `text` is now safe to use since Zod would have
  // thrown an error if it was invalid
}

When using the Hono adapter, for instance, the code above will result in a 500 Internal Server Error when you send an invalid input. In order to return the expected 400 Bad Request instead, you have many options depending on the libraries, frameworks, and adapters you are using. Here are a few examples:

  1. Catch the Zod error and throw a ValidationError from @makay/rpc/server instead:

    import { ValidationError } from "@makay/rpc/server"
    
    const TextSchema = z.string().min(1).max(256)
    
    export async function createTodo(text: string) {
      try {
        TextSchema.parse(text)
      } catch (error) {
        if (error instanceof ZodError) {
          throw new ValidationError(error.error.format())
        }
        throw error
      }
    
      // `text` is now safe to use
    }

    This is of course a bit too verbose to be practical.

  2. Use the included Zod adapter:

    import { z, zv } from "@makay/rpc/zod"
    
    const TextSchema = z.string().min(1).max(256)
    
    export async function createTodo(text: string) {
      zv(text, TextSchema)
    
      // `text` is now safe to use
    }

    This is much less verbose than the previous option.

  3. Use the onError callback of the Hono adapter:

    import { serve } from "@hono/node-server"
    import { createRpc } from "@makay/rpc/hono"
    import { Hono } from "hono"
    import { cors } from "hono/cors"
    import { ZodError } from "zod"
    
    const app = new Hono()
    
    const rpc = await createRpc({
      onError(ctx, error) {
        if (error instanceof ZodError) {
          return ctx.json(error.error.format(), 400)
        }
        throw error
      },
    })
    
    app.use(
      "/rpc",
      cors({ origin: "http://localhost:5173", credentials: true }),
      rpc
    )
    
    serve(app, (info) => {
      console.log(`Server is running on http://localhost:${info.port}`)
    })

    This allows you to catch any unhandled Zod errors and return 400 Bad Request regardless of which server function threw the error.

You can easily adapt any of the examples above to work with any libraries and frameworks you are using. Remember that @makay/rpc is completely agnostic.

🚨 Errors

WIP

📦 Async server state

WIP

👍 Results

WIP

📡 Subscriptions

WIP

🔌 Adapters

🔥 Hono

WIP

💎 Zod

WIP

🧑🏻‍💻 Contributing

Contributions, issues, suggestions, ideas and discussions are all welcome!

This is an extremely young library and a lot can still change, be added and removed.

📄 License

MPL-2.0