trpc-browser
Version:
tRPC adapters and links for everywhere in the browser
251 lines (184 loc) β’ 9.5 kB
Markdown

<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) π