TypeScript icon, indicating that this package has built-in type declarations

    1.2.9 • Public • Published

    A-Pea-Eye GitHub license npm version

    A strongly-typed RPC framework for client-server applications written in TypeScript.


    It helps to have correctness guarantees from your compiler when writing your programs. This is applicable when writing client-server applications, but requires some tooling to achieve.

    To this end, we can use an RPC client that is aware of the return type of the server response. We will encode the data type and error type into the return type of an RPC method. The client will infer the return type from the RPC method enabling the compiler to know about data and error types. The compiler will enforce appropriate error handling on the client: providing us strongly-typed client-server code.

    Our error propagation is inspired by Rust's Result type, which returns a tuple of Result<T, E> from a function. Here T is your data type and E is your error type.


    • [x] RPC Client that can propagate errors, data types, stack traces over a network boundary
    • [ ] Stack traces and errors are anonymized/hidden in production
    • [ ] Runtime type guards on client boundaries (with appropriate exception handling)


    We define our server methods as functions with a return type of Result<T, E>. This is equivalent to Ok<T> | Err<E>.

    Note: Our function's return type conforms with Ok(x/y) and Err('Divided by zero').

    // methods.ts
    import { Ok, Err, Result } from 'a-pea-eye'
    // Define methods for your server logic
    export const methods = {
        _req: Request,
        x: number,
        y: number
      ): Result<number, 'Divided by zero'> {
        if (y === 0) {
          return Err('Divided by zero')
        } else {
          return Ok(x / y)

    Create a client that is aware of the return types of your methods.

    // client.ts
    import { createClient } from 'a-pea-eye'
    import { methods } from './methods'
    // Create RPC client
    const client = createClient<typeof methods>(`http://localhost:8080/rpc'`)
    // Invoke method on RPC client
    const result = await client.divide(10, 0)
    // NOTE: TypeScript enforces error checking through type narrowing.
    if (result.ok) {
      const quotient = val // compiler knows `val` is of type 'number'
    } else {
      const err = val // compiler knows `val` is of type 'string'

    Finally, this is what configuring your server looks like.

    // server.ts
    import { createMiddleware } from 'a-pea-eye'
    import express from 'express'
    import { methods } from './methods'
    // Configure express server
    const app = express()
    app.post('/rpc', createMiddleware(methods))
    // Start server



    npm i a-pea-eye

    DownloadsWeekly Downloads






    Unpacked Size

    61.8 kB

    Total Files


    Last publish


    • abhayvatsa