@lescd/tipc
v0.5.0
Published
Type-safe IPC for Electron with end-to-end type safety, built on Zod schemas.
Downloads
851
Readme
TIPC
Type-safe IPC for Electron with end-to-end type safety, built on Zod schemas.
Features
- End-to-end type safety - From main process to renderer, types are preserved
- Zod validation - Runtime validation with Zod schemas for inputs and outputs
- Result types - No thrown exceptions, explicit error handling with
Result<T, E> - Middleware support - Composable middleware for auth, logging, caching, etc.
- Event system - Type-safe events from main to renderer
- React integration - React hooks and React Query integration for seamless UI updates
- Zero boilerplate - Minimal setup, maximum type inference
Installation
npm install @lescd/tipc zodQuick Start
Main Process
import { tipc } from '@lescd/tipc/main'
import { z } from 'zod'
const t = tipc.create()
export const router = {
greet: t.procedure
.input(z.object({ name: z.string() }))
.action(({ input }) => `Hello, ${input.name}!`),
getUser: t.procedure
.input(z.object({ id: z.number() }))
.action(async ({ input }) => {
const user = await db.users.findOne({ id: input.id })
return user
}),
}
export const events = tipc.events({
userUpdated: z.object({
userId: z.number(),
name: z.string(),
}),
})
tipc.register({ router, events })Renderer Process
import { createClient } from '@lescd/tipc/react'
import type { router, events } from '../main'
export const tipc = createClient<typeof router, typeof events>()
// Call procedures
const result = await tipc.greet({ name: 'World' })
if (result.ok) {
console.log(result.data) // "Hello, World!"
} else {
console.error(result.error.message)
}
// React hook
function UserProfile({ userId }: { userId: number }) {
const userQuery = tipc.useQuery('getUser', { id: userId })
if (userQuery.isLoading) return <div>Loading...</div>
if (userQuery.isError) return <div>Error: {userQuery.error.message}</div>
return <div>Welcome, {userQuery.data.name}!</div>
}Documentation
Comprehensive documentation is included in this package:
- Introduction - Overview and core concepts
- Getting Started - Installation and setup guide
- Procedures - Defining type-safe procedures
- Validation - Zod schemas and validation
- Middleware - Composable middleware patterns
- Events - Type-safe event system
- Error Handling - Result types and error patterns
- Best Practices - Architecture and patterns
- Troubleshooting - Common issues and solutions
Start with the Introduction or jump to Getting Started.
API Overview
Main Process
tipc.create()- Create a TIPC instancet.procedure- Define a type-safe procedure.input(schema)- Define input validation (optional).output(schema)- Define output validation (optional).action(handler)- Implement the procedure logic.use(middleware)- Add middleware
tipc.events(schemas)- Define event schemastipc.register({ router, events })- Register procedures and events with Electron
Renderer Process
createClient<Router, Events>()- Create typed clienttipc.procedureName(input)- Call a procedure, returnsPromise<Result<T, E>>tipc.useQuery(name, input)- React Query hook for procedurestipc.useMutation(name)- React Query mutation hooktipc.useEvent(name, handler)- React hook for events
Examples
See the examples directory for a complete working example.
Result Type
TIPC uses explicit Result types instead of throwing exceptions:
type Result<T, E extends Error> =
| { ok: true; data: T }
| { ok: false; error: E }This forces explicit error handling and makes errors part of the type signature.
Middleware
Middleware can be used for cross-cutting concerns:
const authMiddleware = t.middleware
.context<{ userId: number }>()
.build(async ({ context, next }) => {
const userId = await validateSession(context.sender)
return next({ ...context, userId })
})
const protectedProcedure = t.procedure
.use(authMiddleware)
.action(({ context }) => {
// context.userId is available here
return { success: true }
})TypeScript
TIPC is built with TypeScript and provides complete type safety:
- Input/output types are inferred from Zod schemas
- Procedure calls are type-checked in the renderer
- Event payloads are typed
- Middleware context is typed
License
MIT
Contributing
Contributions are welcome! Please see the documentation for architecture details and best practices.
