proz
proz is a TypeScript-powered HTTP RPC library for your own server and client,
which empowers you to write typesafe client-server communication.
This Library is currently a work in progress and not ready for production.
proz allows you to write elegant API methods on your server, and generates you
an easy-to-use and fully typed API client – only using TypeScript and JavaScript
proxies, without any compilation steps or babel plugins. Calling an API method
with proz looks like calling any other async JavaScript function.
- It's tiny! Because proz' API client is a small JavaScript proxy, it's only
250 Bytes (and ~150 Bytes gzipped)!
- Makes heavy use of TypeScript's type inference, so you don't have to write
types at all.
- Groups your API methods into Queries and Mutations, which you might already
know from GraphQL or react-query.
- Uses es
But why not GraphQL or a RESTful API? Because for developing your own app, you
don't need it. Just use convenient Remote Procedure Calls (PRC).
Info: This package is native ESM.
Example
import { proz } from 'proz'
const addTodoCtx = proz.pipe(
async (ctx) => {
const user = await db.user.findById(ctx.req.cookies['user_id'])
return { ...ctx, user }
},
proz.yupBody({ id: yup.string().required })
)
const addTodo = proz.handler(addTodoCtx, async (ctx) => {
const todo = await db.todo.create({
...ctx.body,
userId: ctx.user.id
})
return todo
)
const todosCtx = proz.pipe(
authentication,
proz.yupParams({ status: yup.string().oneOf(['todo', 'done']) })
)
const todos = proz.handler(todosCtx, async (ctx) => {
const todos = await db.todo.getAll({
where: { status: ctx.params.status }
})
return todos
})
const prozServer = proz.createServer({
query: {
todos
},
mutate: {
addTodo
}
})
export type ProzServer = typeof prozServer
export default async (req, res) => {
const data = prozServer.handle(req, res)
res.json(data)
}
import type { ProzServer } from '...'
const api = proz.createClient<ProzServer>({
fetch: ({ proc, method, body, params }) => {
return ky(`/api/${proc}`, {
method,
json: body,
searchParams: params
}).json()
}
})
const todos = await api.query.todos({ status: 'todo' })
const doneTodos = await api.query.todos({ status: 'done' })
async function handleAddClick() {
const newTodo = await api.mutate.addTodo({
name: 'Buy Milk'
})
console.log(newTodo)
}
<button onClick={handleAddClick}>
Add Todo
</button>