npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@cyia/vscode-trpc

v1.0.8

Published

tRPC integration for VS Code Extension-Webview communication

Readme

@cyia/vscode-trpc

🌐 English | 中文

tRPC integration for communication between VS Code extension host and Webview, enabling end-to-end type-safe RPC calls.

Features

  • Type Safe: Leverage tRPC's end-to-end type safety with shared Router type definitions between extension host and Webview
  • IPC Link: Custom tRPC transport layer based on VS Code postMessage API
  • Message Compression: Built-in snappyjs compression support with fine-grained control over which procedures need compression
  • Subscription Support: Supports tRPC Subscription (Observable / AsyncGenerator) for real-time bidirectional communication
  • Flexible Context: Inject custom context via createContext (e.g., webview instance, extension state, etc.)

Installation

npm install @cyia/vscode-trpc
# or
pnpm add @cyia/vscode-trpc

Dependency: This package requires @trpc/server and @trpc/client as peer dependencies.

Exports

| Import Path | Description | | -------------------------- | ------------------------------------ | | @cyia/vscode-trpc/server | Server utilities: createIPCHandler | | @cyia/vscode-trpc/client | Client utilities: ipcLink |


Quick Start

1. Define Router

First, define the tRPC Router in code shared between extension host and Webview:

import { initTRPC } from '@trpc/server';
import * as v from 'valibot';

const t = initTRPC.create();

export const appRouter = t.router({
  // Simple query
  hello: t.procedure.query(() => 'Hello World'),

  // Query with input validation
  getUser: t.procedure
    .input(v.object({ id: v.string() }))
    .query(({ input }) => ({ name: 'Alice', id: input.id })),

  // Nested router
  posts: t.router({
    list: t.procedure.query(() => [{ id: 1, title: 'First Post' }]),
  }),
});

export type AppRouter = typeof appRouter;

The Router definition file should be located in the module shared between extension host and Webview to ensure end-to-end TypeScript type inference.

2. Extension Host — Register IPC Handler

import { Disposable } from 'vscode';
import { createIPCHandler } from '@cyia/vscode-trpc/server';
import { appRouter, AppRouter } from './shared/router';

// Create IPC Handler
const ipcHandler = createIPCHandler<AppRouter>({
  router: appRouter,

  // Optional: custom context, can access webview instance
  createContext: async (options) => ({
    ...options,
  }),
});

// When activating extension, register Webview to Handler
function registerWebviewPanel(context: vscode.ExtensionContext) {
  const panel = vscode.window.createWebviewPanel(
    'myPanel',
    'My Panel',
    vscode.ViewColumn.One,
    { enableScripts: true },
  );

  // Register webview (automatically binds message listener)
  ipcHandler.addWebView(panel.webview);

  // Can also pass extra context and compression config
  // ipcHandler.addWebView(panel.webview, { userId: '123' }, { 'posts.list': true });

  panel.onDidDispose(() => {
    // Remove registration when panel is closed, clean up subscriptions
    ipcHandler.removeWebView(panel.webview);
  });

  return panel;
}

3. Webview — Create tRPC Client

import { createTRPCProxyClient } from '@trpc/client';
import { ipcLink } from '@cyia/vscode-trpc/client';
import type { AppRouter } from '../shared/router';

// Create client in Webview
const trpc = createTRPCProxyClient<AppRouter>({
  links: [ipcLink()],
});

// Call query
async function loadHello() {
  const result = await trpc.hello.query();
  console.log(result); // 'Hello World'
}

// Query with input
async function loadUser() {
  const user = await trpc.getUser.query({ id: '42' });
  console.log(user.name); // 'Alice'
}

// Nested router call
const posts = await trpc.posts.list.query();

4. Subscribe to Real-time Data

// Define Subscription in extension host's Router
const appRouter = t.router({
  counter: t.procedure.subscription(() => {
    return new Promise((resolve) => {
      let count = 0;
      const interval = setInterval(() => {
        observer.next(count++);
      }, 1000);
      resolve({
        unsubscribe() {
          clearInterval(interval);
        },
      });
    });
  }),
});

// Subscribe in Webview
const unsubscribe = trpc.counter.subscribe(undefined, {
  onNext(value) {
    console.log('Count:', value);
  }, // Increments every second
  onError(error) {
    console.error('Subscription error:', error);
  },
  onCompleted() {
    console.log('Subscription completed');
  },
});

// Call unsubscribe() when no longer needed to stop subscription

5. Enable Message Compression

Server: Response Data Compression

// Specify when calling addWebView
ipcHandler.addWebView(webview, undefined, {
  largeQuery: true,
  'aaa.bbb': true, // Nested router
});

Client: Request Data Compression

// Object compression
const largeData = await trpc.largeQuery.query(
  {},
  {
    context: { compress: true }, // Mark this request for compression
  },
);

// Uint8Array compression
await trpc.importData.query(new Uint8Array(largeBuffer), {
  context: { compress: true },
});

API Reference

Server

createIPCHandler<TRouter>(options)

Create an IPC Handler to manage tRPC procedures in the extension host.

| Parameter | Type | Description | | ---------------- | -------------------------------------------------- | ----------------------------------- | | router | TRouter | tRPC App Router instance (required) | | createContext? | (opts: CreateContextOptions) => Promise<Context> | Optional context factory function |

CreateContextOptions parameters:

interface CreateContextOptions {
  webview: vscode.Webview; // Webview instance
  [key: string]: any; // extraContext passed from addWebView
}

IPCHandler.addWebView(webview, extraContext?, compressPathObj?)

Register a Webview to handle tRPC requests.

| Parameter | Type | Description | | ------------------ | ------------------------- | ---------------------------------------------------- | | webview | vscode.Webview | Webview instance to register | | extraContext? | Record<string, any> | Extra fields to inject into createContext context | | compressPathObj? | Record<string, boolean> | Enable server response compression by procedure path |

Compression path configuration example:

ipcHandler.addWebView(webview, undefined, {
  largeQuery: true,
  'aaa.bbb': true, // Nested router
});

IPCHandler.removeWebView(webview)

Remove Webview registration and clean up all related subscriptions and listeners.

import { createIPCHandler } from '@cyia/vscode-trpc/server';

// Create Handler
const handler = createIPCHandler<AppRouter>({
  router,
  createContext: async ({ webview, ...ctx }) => ({ ...ctx }),
});

// Register/Remove Webview
handler.addWebView(webview, extraContext?, compressPaths?);
handler.removeWebView(webview);

Client

import { ipcLink } from '@cyia/vscode-trpc/client';

// Optional: Configure Transformer (custom serialization/deserialization)
ipcLink({ transformer: myTransformer });

// Use in tRPC client
const trpc = createTRPCProxyClient<AppRouter>({
  links: [ipcLink()],
});