Fiber

Build a statically typed SDK for your backend in minutes.

Source code is hosted on GitHub

Create a statically typed client for remote, RPC style communication. Consume your backend API through a statically typed facade, without any code generation, without writing any custom API calls or duplicating your backend types on the client side. Fiber works in any TypeScript setup and is fully implementation agnostic.

  • Full static typing from tail to toe

  • You control the implementation

  • Works for client to server and server to server communication

  • Build an SDK for your backend in minutes

  • No code generation, plain TypeScript

yarn add @corets/fiber

Quick start

First you create a fiber instance and register all the methods that you want to expose to consumers:

import { createFiber } from "@corets/fiber"

const makeResponse = (status: number, result: any) => {  
    return { status, result }
}

const pingPong = (input: string) => {  
    return makeResponse(200, input === "ping" ? "pong" : "ping")
}

export const fiber = createFiber({ pingPong })

export type MyFiber = typeof fiber

Next you need to setup your server, we'll be using express in this example:

import express from "express"
import { fiber } from "./fiber"

const app = express()

app.post("/fiber/:method", async (req, res) => {  
    try {    
        const method = req.params?.method    
        const args = Object.values(req?.body)    
        const response = await fiber.call(method, ...args)    
        
        res.status(response.status).json(response.result)  
    } catch (err) {    
        console.error(err)    
        res.status(500).send()  
    }
})

app.listen(1337)

Next you create a consumer for your fiber, on the client side, we'll use axios in this example:

import { createFiberClient } from "@corets/fiber"
import axios from "axios"
import type { MyFiber } from "./fiber"

export const client = createFiberClient<MyFiber>(async (method, ...args) => {  
    const res = await axios.post(`http://localhost:1337/fiber/${method}`, args)  

    return res.data
})

Now you have a statically typed, RPC style client, that you can consume immediately:

import { client } from "./client"

const answer = await client.pingPong("ping")

createFiber()

Create a new fiber instance on the producer side, returns an instance of SimpleFiber:

import { createFiber } from "@corets/fiber"

const myMethod = () => "hallo"

const fiber = createFiber({ myMethod })

createFiberClient()

Create a statically typed fiber client, returns an instance of SimpleFiberClient:

import { createFiberClient } from "@corets/fiber"
import type { fiber } from "./fiber"

const client = createFiberClient<typeof fiber>((method, ...args) => { ... })

SimpleFiber.call()

Call a registered fiber method on the producer side:

import { createFiber } from "@corets/fiber"

const fiber = createFiber({  
    greet (name: string) {    
        return `Hallo ${name}!`  
    }
})

const greeting = await fiber.call("greet", "John")

SimpleFiberClient.call()

import { createFiberClient } from "@corets/fiber"
import type { MyFiber } from "./fiber"

const client = createFiberClient<MyFiber>((method, ...args) => { ... })

const response = await client.call("greeting", "John")
// same as
const response = await client.greeting("John")

Last updated