npm install renraku
🔆 make smart typescript apis
🛎️ simply expose async functions
🛡 you set auth policies for groups of functions
🎭 easy mocks for testing and development
🧠 designed for good typescript types
🌐 make http json-rpc apis
🔁 make bidirectional websocket json-rpc apis
-
let's make an example api
import * as renraku from "renraku" export const exampleApi = renraku.api({ // we organize functions into services. greeter: renraku.service() // each service has its own auth policy. // a policy processes a "meta" object into an "auth" object. // this is where you might process access tokens, or verify permissions. // here's our contrived example policy. .policy(async(meta: {token: string}) => { if (meta.token) return {doctorate: meta.token === "doctor"} else throw new Error("invalid token") }) // here's where our functions get access to our "auth" object. .expose(auth => ({ // here's our silly example function. async greet(name: string) { return auth.doctorate // if the user's doctorate is valid, ? `hello dr. ${name}` // we greet them formally, : `hi ${name}` // otherwise, we greet them differently. }, })), })
-
now let's run our api on a node server
import * as renraku from "renraku" import {nodeServer} from "renraku/x/http/node-server.js" import {exampleApi} from "./example-api.js" const server = nodeServer({ api: exampleApi, exposeErrors: false, maxPayloadSize: renraku.megabytes(10), }) server.listen(8000)
-
now let's call that function from a browser
import * as renraku from "renraku" import type {exampleApi} from "./example-api.js" // let's start as a doctor let meta = {token: "doctor"} // we create a browser client const {greeter} = renraku.browserClient({ url: "http://localhost:8000/", metas: { // on the service, we specify which meta to use for api calls calculator: async() => meta, }, }) // hey look, we're a doctor! const result1 = await greeter.greet("chase") //> "hello, dr. chase" // okay let's stop being a doctor meta = {token: "not a doctor"} const result2 = await greeter.greet("chase") //> "hi chase" // now let's just fail to provide a valid meta meta = {token: undefined} const result3 = await greeter.greet("chase") //> ERROR! "invalid token"
-
let's test our example-api, locally, in our test suite
import * as renraku from "renraku" import {exampleApi} from "./example-api.js" // okay, let's start with a valid doctor token let meta = {token: "doctor"} // create a mock remote of our api const {greeter} = renraku.mock() .forApi(exampleApi) .withMetas({ greeter: async() => meta, }) // now we can call and test our api's functionality, // without running any servers, or clients, or any of that. const result1 = await greeter.greet("chase") //> "hello, dr. chase" meta = {token: "not a doctor"} const result2 = await greeter.greet("chase") //> "hi chase" // not only are we testing our api's business logic, // but we are also testing the auth policies too!
-
when making our mocks, we may choose to skip the auth policy logic
const {greeter} = renraku.mock() .forApi(exampleApi) // 👇 an auth map overrides auth policies .withAuths({ // we're forcing this auth result // 👇 greeter: async() => ({doctorate: true}), })
~ readme docs coming soon lol ~
~ readme docs coming soon lol ~
— RENRAKU means "contact" —