UNPKG

trpc-browser

Version:

tRPC adapters and links for everywhere in the browser

251 lines (184 loc) β€’ 9.5 kB
![trpc-browser](assets/trpc-browser-readme.png) <div align="center"> <h1>trpc-browser</h1> <a href="https://www.npmjs.com/package/trpc-browser"><img src="https://img.shields.io/npm/v/trpc-browser.svg?style=flat&color=brightgreen" target="_blank" /></a> <a href="./LICENSE"><img src="https://img.shields.io/badge/license-MIT-black" /></a> <a href="https://trpc.io/discord" target="_blank"><img src="https://img.shields.io/badge/chat-discord-blue.svg" /></a> <br /> <hr /> </div> ## **🌐 [tRPC](https://trpc.io/) for everything in the browser** - Typesafe messaging for extensions - between window, content & background scripts - ready for Manifest V3. - Typesafe messaging for windows - between window, any other window (eg iframe) or popups ## πŸ“– Table of contents - [**🌐 tRPC for everything in the browser**](#-trpc-for-everything-in-the-browser) - [πŸ“– Table of contents](#-table-of-contents) - [πŸ“¦ Installation](#-installation) - [🧩 Example usage for extensions](#-example-usage-for-extensions) - [πŸ•ΈοΈ Example usage for windows](#️-example-usage-for-windows) - [πŸ“” Requirements](#-requirements) - [πŸ“ Example](#-example) - [πŸ†Ž Types](#-types) - [ChromeLinkOptions](#chromelinkoptions) - [WindowLinkOptions](#windowlinkoptions) - [PopupLinkOptions](#popuplinkoptions) - [CreateChromeHandlerOptions](#createchromehandleroptions) - [CreateWindowHandlerOptions](#createwindowhandleroptions) - [Cross-origin support](#cross-origin-support) - [©️ License](#️-license) - [πŸ›ŽοΈ Contact](#️-contact) ## πŸ“¦ Installation **Install `trpc-browser`.** ```bash # npm npm install trpc-browser # yarn yarn add trpc-browser ``` ## 🧩 Example usage for extensions **1. Add `createChromeHandler` in your background script.** ```typescript // background.ts import { initTRPC } from '@trpc/server'; import { createChromeHandler } from 'trpc-browser/adapter'; const t = initTRPC.create({ isServer: false, allowOutsideOfServer: true, }); const appRouter = t.router({ // ...procedures }); export type AppRouter = typeof appRouter; createChromeHandler({ router: appRouter /* πŸ‘ˆ */, }); ``` **2. Add a `chromeLink` to the client in your content script.** ```typescript // content.ts import { createTRPCClient } from '@trpc/client'; import { chromeLink } from 'trpc-browser/link'; import type { AppRouter } from './background'; const port = chrome.runtime.connect(); export const chromeClient = createTRPCProxyClient<AppRouter>({ links: [/* πŸ‘‰ */ chromeLink({ port })], }); ``` **3. `(extra)` If you have an injected window script, hook it up too!.** ```typescript // inpage.ts import { createTRPCProxyClient } from '@trpc/client'; import { windowLink } from 'trpc-browser/link'; import type { AppRouter } from './background'; export const windowClient = createTRPCProxyClient<AppRouter>({ links: [/* πŸ‘‰ */ windowLink({ window })], }); ``` ```typescript // content.ts import { relay } from 'trpc-browser/relay'; const port = chrome.runtime.connect(); relay(window, port); ``` ## πŸ•ΈοΈ Example usage for windows **1. Add `createWindowHandler` in your main window.** ```typescript // main.ts import { initTRPC } from '@trpc/server'; import { createWindowHandler } from 'trpc-browser/adapter'; const t = initTRPC.create({ isServer: false, allowOutsideOfServer: true, }); const appRouter = t.router({ // ...procedures }); export type AppRouter = typeof appRouter; createWindowHandler({ router: appRouter /* πŸ‘ˆ */, window: window /* πŸ‘ˆ */, }); ``` **2. Add a `windowLink` or `popupLink` to the client** ```typescript import { createTRPCProxyClient } from '@trpc/client'; import { popupLink, windowLink } from 'trpc-browser/link'; import type { AppRouter } from './main'; /** iframe */ const iframeEl = document.querySelector('iframe'); export const iframeClient = createTRPCProxyClient<AppRouter>({ links: [/* πŸ‘‰ */ windowLink({ window: iframeEl.contentWindow })], }); /** popup */ export const popupClient = createTRPCProxyClient<AppRouter>({ links: [ /* πŸ‘‰ */ popupLink({ listenWindow: window, createPopup: () => { const w = window.open('/example/popup', 'popup', 'width=680,height=520'); if (!w) { throw new Error('Could not open popup'); } return w; }, }), ], }); ``` ## πŸ“” Requirements Peer dependencies: - [`tRPC`](https://github.com/trpc/trpc) Server v10 (`@trpc/server`) must be installed. - [`tRPC`](https://github.com/trpc/trpc) Client v10 (`@trpc/client`) must be installed. ## πŸ“ Example Please see [an extension example here](examples/with-plasmo). You can also find a [window example here](examples/on-web). _For advanced use-cases, please find examples in our [complete test suite](test)._ ## πŸ†Ž Types #### ChromeLinkOptions Please see [full typings here](src/link/chrome.ts). | Property | Type | Description | Required | | -------- | --------------------- | ---------------------------------------------------------------- | -------- | | `port` | `chrome.runtime.Port` | An open web extension port between content & background scripts. | `true` | ### WindowLinkOptions Please see [full typings here](src/link/window.ts). | Property | Type | Description | Required | | ------------ | -------- | --------------------------------------------------------- | -------- | | `window` | `Window` | A window object which is listened to | `true` | | `postWindow` | `Window` | A window object which is posted to (defaults to `window`) | `false` | | `postOrigin` | `string` | The targetOrigin passed to `opts.postWindow.postMessage` | `false` | ### PopupLinkOptions Please see [full typings here](src/link/popup.ts). | Property | Type | Description | Required | | -------------- | ---------- | ---------------------------------------------- | -------- | | `listenWindow` | `Window` | A window object which is listened to | `true` | | `createPopup` | `Function` | A function that returns a window object. | `true` | | `postOrigin` | `string` | The targetOrigin passed to `popup.postMessage` | `false` | ### CreateChromeHandlerOptions Please see [full typings here](src/adapter/chrome.ts). | Property | Type | Description | Required | | --------------- | ---------- | ------------------------------------------------------ | -------- | | `router` | `Router` | Your application tRPC router. | `true` | | `createContext` | `Function` | Passes contextual (`ctx`) data to procedure resolvers. | `false` | | `onError` | `Function` | Called if error occurs inside handler. | `false` | | `chrome` | `Object` | Chrome API object. (default: `global.chrome`) | `false` | ### CreateWindowHandlerOptions Please see [full typings here](src/adapter/window.ts). | Property | Type | Description | Required | | --------------- | ---------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- | | `router` | `Router` | Your application tRPC router. | `true` | | `createContext` | `Function` | Passes contextual (`ctx`) data to procedure resolvers. | `false` | | `onError` | `Function` | Called if error occurs inside handler. | `false` | | `window` | `Window` | Window object to subscribe to | `true` | | `postWindow` | `Window` | Window object to post messages to. (default: `MessageEvent.source` with fallback to `opts.window`) | `false` | | `postOrigin` | `string` | The targetOrigin passed to `opts.postWindow.postMessage`. If you want to answer to all messages from all origins you should pass `'*'`, by default it will only work on same origin | `false` | --- ## Cross-origin support When posting from a link you can specify the `postOrigin` option. This will be passed to `postMessage` as the `targetOrigin` argument. If you want to answer to all messages from all origins you should pass `'*'`, by default it will only work on same origin. ## ©️ License Distributed under the MIT License. See LICENSE for more information. ## πŸ›ŽοΈ Contact Janek Rahrt - Follow me on Twitter [@0xjanek](https://twitter.com/0xjanek) πŸ’œ James Berry - Follow me on Twitter [@jlalmes](https://twitter.com/jlalmes) πŸ’™