# Fiber

Source code is hosted on [GitHub](https://github.com/corets/fiber)

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**

{% tabs %}
{% tab title="yarn" %}

```bash
yarn add @corets/fiber
```

{% endtab %}

{% tab title="npm" %}

```bash
npm install --save @corets/fiber
```

{% endtab %}
{% endtabs %}

## Quick start <a href="#quick-start" id="quick-start"></a>

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

```typescript
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:

```typescript
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:

```typescript
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:

```typescript
import { client } from "./client"

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

## createFiber() <a href="#createfiber" id="createfiber"></a>

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

```typescript
import { createFiber } from "@corets/fiber"

const myMethod = () => "hallo"

const fiber = createFiber({ myMethod })
```

## createFiberClient()

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

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

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

## SimpleFiber.call() <a href="#simplefibercall" id="simplefibercall"></a>

Call a registered fiber method on the producer side:

```typescript
import { createFiber } from "@corets/fiber"

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

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

## SimpleFiberClient.call() <a href="#simplefiberclientcall" id="simplefiberclientcall"></a>

```typescript
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")
```
