Module @cc-ts/crpc - v0.0.3

🚀 @cc-ts/crpc

Type-safe RPC for ComputerCraft that speaks TRPC!

CRPC is a TypeScript RPC framework specifically designed for ComputerCraft that maintains compatibility with tRPC. It enables end-to-end typesafe APIs between ComputerCraft computers and either other computers or external tRPC servers.

Think of it as tRPC's quirky cousin who lives in Minecraft! 🎮

  • 🔐 Full end-to-end type safety
  • 🤝 Compatible with tRPC servers via WebSocket
  • 🖥️ Native ComputerCraft Rednet support
  • 📡 Built-in subscriptions support
  • 🔌 Multiple transport options
bun add @cc-ts/crpc
import { initCRPC } from "@cc-ts/crpc";

const t = initCRPC.create();

const appRouter = t.router({
greeting: t.procedure.input(z.string()).query((opts) => {
return `Hello ${opts.input}!`;
}),

counter: t.procedure.subscription((opts) => {
return observable<number>((observer) => {
let count = 0;
const timer = setInterval(() => {
observer.next(count++);
}, 1000);

return () => clearInterval(timer);
});
}),
});

export type AppRouter = typeof appRouter;
import { createRednetCRPCServer } from "@cc-ts/crpc/adapter/rednet";

// Open modem
peripheral.find("modem", (name) => {
rednet.open(name);
});

// Create server
createRednetCRPCServer({
router: appRouter,
});

print("CRPC Server running!");
import { createCRPCClient } from "@cc-ts/crpc";
import { RednetCRPCTransport } from "@cc-ts/crpc/client/transports/rednet";

// Open modem
peripheral.find("modem", (name) => {
rednet.open(name);
});

const client = createCRPCClient<AppRouter>({
transport: new RednetCRPCTransport({
recipient: 1, // Computer ID to connect to
}),
});

// Make type-safe calls!
const greeting = await client.greeting.query("CRPC");
print(greeting); // "Hello CRPC!"

// Subscribe to updates
client.counter.subscribe(undefined, {
onData: (count) => {
print(`Count: ${count}`);
},
});
import { createCRPCClient } from "@cc-ts/crpc";
import { WebSocketCRPCTransport } from "@cc-ts/crpc/client/transports/websocket";

const transport = new WebSocketCRPCTransport({
url: "ws://localhost:3000",
reconnect: true,
keepAliveTimeout: 10_000,
maxReconnectAttempts: "infinite",
});

const client = createCRPCClient<AppRouter>({
transport,
});

// Same API as Rednet client!
const greeting = await client.greeting.query("CRPC");
try {
await client.greeting.query("");
} catch (err) {
if (err instanceof CRPCClientError) {
print("Something went wrong:", err.message);
}
}
interface Context {
user?: {
id: string;
name: string;
};
}

const t = initCRPC.context<Context>().create();

const appRouter = t.router({
me: t.procedure.query(({ ctx }) => {
return ctx.user;
}),
});
const authMiddleware = t.middleware(({ next, ctx }) => {
if (!ctx.user) {
throw new CRPCError({
code: "UNAUTHORIZED",
message: "Must be logged in",
});
}
return next();
});

const protectedProcedure = t.procedure.use(authMiddleware);

Contributions are welcome! Feel free to:

  1. Fork the repository
  2. Create your feature branch (git checkout -b feature/amazing-feature)
  3. Commit your changes (git commit -m 'Add some amazing feature')
  4. Push to the branch (git push origin feature/amazing-feature)
  5. Open a Pull Request
  • tRPC - For the amazing foundation this project builds upon
  • ComputerCraft - For making Minecraft programming fun
  • The TypeScript team - For giving us amazing type-safety

Made with ❤️ for the ComputerCraft community

Modules

client
server