JSPM

  • ESM via JSPM
  • ES Module Entrypoint
  • Export Map
  • Keywords
  • License
  • Repository URL
  • TypeScript Types
  • README
  • Created
  • Published
  • Downloads 212
  • Score
    100M100P100Q109534F
  • License MIT

Testing out trpc for durable objects

Package Exports

    This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (trpc-durable-objects) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.

    Readme

    TRPC Durable Objects

    After playing around with Durable Objects for a while I realized that this conceptually really is an RPC setup, you create a stub and want to interact with a remote object. I had a look at (itty-durable)[https://github.com/kwhitley/itty-durable] which is a cool solution, but it doesn't provide strict typing. A few weeks ago I bumped into the (TRPC)[https://trpc.io/] framework that seems to be the perfect solution for doing typesafe RPC.

    This package provides a factory for creating both the strictly typed stub and server for a durable object using a TRPC-router.

    Usage

    The first step is to create a TRPC router:

    import { initTRPC } from '@trpc/server';
    import { z } from 'zod';
    import { Context } from '../../src/context';
    
    const t = initTRPC.context<Context>().create();
    
    const publicProcedure = t.procedure;
    
    const router = t.router;
    
    export const counterRouter = router({
      up: publicProcedure
        .input(z.string().nullish())
        .query(async ({ input, ctx }) => {
          const count: number | undefined = await ctx.state.storage.get('count');
          const newCount = (count || 0) + 1;
    
          await ctx.state.storage.put('count', newCount);
          return `Count: ${newCount}`;
        }),
      down: publicProcedure
        .input(z.string().nullish())
        .query(async ({ input, ctx }) => {
          const count: number | undefined = await ctx.state.storage.get('count');
          const newCount = (count || 0) - 1;
    
          await ctx.state.storage.put('count', newCount);
          return `Count: ${newCount}`;
        }),
    });
    
    export type CounterRouter = typeof counterRouter;

    The router will be executed within a durable object but the types are exposed so the stub or proxy will be strictly typed.

    The router is then passed to the factory method:

    import { CounterRouter, counterRouter } from './Counter';
    import { createProxy } from 'trpc-durable-object';
    
    export const Counter = createProxy<CounterRouter>(counterRouter);
    
    export default {
      async fetch(
        request: Request,
        env: Env,
        ctx: ExecutionContext,
      ): Promise<Response> {
        const counter = Counter.getInstance(env.COUNTER, 'dummy-id');
    
        // increase the counter value
        const body = await counter.up.query();
    
        ...
      },
    };