
Security News
Deno 2.2 Improves Dependency Management and Expands Node.js Compatibility
Deno 2.2 enhances Node.js compatibility, improves dependency management, adds OpenTelemetry support, and expands linting and task automation for developers.
TypeScript-powered HTTP RPC library for your own server and client
proz is a functional RPC-based API Layer for your Client-Server-Apps, which allows you to call your fully typed API methods directly inside your client.
tl;dr: just scroll down for a complete example.
This Library is currently a work in progress and not ready for production.
proz empowers you to move parts of your business logic from your client to your server, so your client can take care of the UI, and your server can do the data crunching.
Info: This package is native ESM.
proz consists of a Resolver and Client.
The Resolver is the server part, where you define your API methods as Queries and Mutations. The Resolver takes a request, resolves which API method should be executed, executes it (with its middleware), and returns the result.
The Client is an easy-to-use fully typed and tiny Client, which calls the Resolver. The Client doesn't need any autogeneration or babel plugin. It's a JavaScript Proxy , which knows about all the type definitions of your Resolver. So it knows which methods are defined, what parameters they expect, and what data they return. Because it's only powered by types, it's a measly 250 Bytes (150 Bytes gzipped).
import { proz } from 'proz'
// Define Queries
// Use pipe() to create middlewares for your API methods.
const todosCtx = proz.pipe(
// use your own authentication middlewares
async (ctx) => {
const user = await db.user.findById(ctx.req.cookies['user_id'])
return { ...ctx, user }
},
// Validate and sanitize the request's query params.
// Supports zod, yup out of the box. Or use your own validator.
proz.params(yup.object({
status: yup.string().oneOf(['todo', 'done']),
limit: yup.number().max(20)
}))
)
// proz.query() creates a query handlers (GET request) for your API.
const todos = proz.query(todosCtx, async (ctx) => {
const todos = await db.todo.findMany({
where: { status: ctx.params.status }
limit: ctx.params.limit || 10
})
return todos
})
// You can define as many queries as you like. This is just an example and not
// a guideline. Nothing prohibits you from defining separate queries for
// `allTodos()`, `openTodos()`, `doneTodos()`.
const openTodos = proz.query(async () => {
const todos = await db.todo.findMany({
where: { status: 'open' }
})
return todos
})
const doneTodos = proz.query(async () => {
const todos = await db.todo.findMany({
where: { status: 'done' }
})
return todos
})
// Define Mutations
const addTodoCtx = proz.pipe(
authentication,
// Validate and sanitize the request's body with yup, zod, ...
proz.body(yup.object({ id: yup.string().required() }))
)
// proz.mutation() creates a mutation resolver (POST request) for your API.
const addTodo = proz.mutation(addTodoCtx, async (ctx) => {
// ctx.body is validated!
const todo = await db.todo.create({
...ctx.body,
userId: ctx.user.id // ctx is typesafe from your middlewares
})
return todo
)
// Create your proz instance and use your queries and mutations.
// Use this for example in Next.js inside a file: api/rpc/[...proz].ts
import { createProzResolver } from 'proz'
const resolver = createProzResolver({
todos,
openTodos,
doneTodos,
addTodo
})
// We need this later for our client.
export type Resolver = typeof resolver
export default async (req, res) => {
const data = resolver.handleRequest(req, res)
// Put this in a try-catch for error handling
res.json(data)
}
// lib/api-client.ts
import { createProzClient } from 'proz'
import type { Resolver } from './whatever'
// Create your api client and feed it with the type of the prozServer.
const api = createProzClient<Resolver>({
fetch: ({ proc, method, body, params }) => {
// Use your favorite HTTP library.
return ky(`/api/${proc}`, {
method,
json: body,
searchParams: params
}).json()
}
})
// client/ui-component.ts
// Simply use your API client inside your UI.
// The responses and query params are automatically fully typed,
// using the schemas and return type from your API handlers.
// Queries are GET-Requests and use the Request query (URL Params) as input.
const todos = await api.query.todos({ status: 'todo' })
const openTodos = await api.query.openTodos()
const doneTodos = await api.query.doneTodos()
async function handleAddClick() {
// Mutations are POST-Requests and use the Request body as input.
const newTodo = await api.mutate.addTodo({
name: 'Buy Milk' // body is fully typed using your TodoSchema
})
console.log(newTodo) // Of course, newTodo is fully typed!
}
<button onClick={handleAddClick}>
Add Todo
</button>
What I'm thinking about adding...
FAQs
TypeScript-powered HTTP RPC library for your own server and client
We found that proz demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
Deno 2.2 enhances Node.js compatibility, improves dependency management, adds OpenTelemetry support, and expands linting and task automation for developers.
Security News
React's CRA deprecation announcement sparked community criticism over framework recommendations, leading to quick updates acknowledging build tools like Vite as valid alternatives.
Security News
Ransomware payment rates hit an all-time low in 2024 as law enforcement crackdowns, stronger defenses, and shifting policies make attacks riskier and less profitable.