UNPKG

5.66 kBMarkdownView Raw
1# fusion-plugin-rpc
2
3[![Build status](https://badge.buildkite.com/5165e82185b13861275cd0a69f29c2a13bc66dfb9461ee4af5.svg?branch=master)](https://buildkite.com/uberopensource/fusion-plugin-rpc)
4
5Fetch data on the server and client with an
6[RPC](https://en.wikipedia.org/wiki/Remote_procedure_call) style interface.
7
8RPC is a natural way of expressing that a server-side function should be run in
9response to a client-side function call. Unlike
10[RESTful architectures](https://en.wikipedia.org/wiki/Representational_state_transfer),
11RPC-based architectures are not required to conform to statelessness constraints
12and are free to return session-scoped data. Additionally, the semantics of RPC
13calls are not constrained by the availability of suitably-descriptive HTTP
14methods and RPC calls can express complex state change requests more naturally
15as verbs (e.g. `returnProduct(id)`) rather than object-orientation (e.g.
16`PATCH /api/orders/:id`).
17
18If you're using React/Redux, you should use
19[`fusion-plugin-rpc-redux-react`](https://github.com/fusionjs/fusion-plugin-rpc-redux-react)
20instead of this package.
21
22---
23
24### Table of contents
25
26- [Installation](#installation)
27- [Usage](#usage)
28- [Setup](#setup)
29- [API](#api)
30 - [Registration API](#registration-api)
31 - [Dependencies](#dependencies)
32 - [Service API](#service-api)
33 - [`mock`](#mock)
34
35---
36
37### Installation
38
39```
40yarn add fusion-plugin-rpc
41```
42
43---
44
45### Usage
46
47```js
48import {createPlugin} from 'fusion-core';
49export default createPlugin({
50 deps: {RPC: RPCToken},
51 middleware: ({RPCFactory}) => (ctx, next) => {
52 RPC.from(ctx).request('getUser', 1).then(console.log);
53 }
54);
55```
56
57---
58
59### Setup
60
61```js
62// src/main.js
63import React from 'react';
64import App, {createPlugin} from 'fusion-core';
65import RPC, {
66 RPCToken,
67 RPCHandlersToken,
68 ResponseError,
69} from 'fusion-plugin-rpc';
70import UniversalEvents, {
71 UniversalEventsToken,
72} from 'fusion-plugin-universal-events';
73import {FetchToken} from 'fusion-tokens';
74import fetch from 'unfetch';
75
76// Define your rpc methods server side
77const handlers = __NODE__ && {
78 getUser: async (args, ctx) => {
79 return {some: 'data' + args};
80 },
81 test: async (args, ctx) => {
82 // Error Handling Example
83 try {
84 doThing();
85 } catch (e) {
86 const error = new ResponseError('Failed to do thing');
87 error.code = 'DOTHING';
88 error.meta = {
89 custom: 'metadata',
90 };
91 throw error;
92 }
93 },
94};
95
96export default () => {
97 const app = new App(<div />);
98
99 app.register(RPCToken, RPC);
100 app.register(UniversalEventsToken, UniversalEvents);
101 __NODE__
102 ? app.register(RPCHandlersToken, handlers)
103 : app.register(FetchToken, fetch);
104
105 return app;
106};
107```
108
109---
110
111### API
112
113#### Registration API
114
115##### `RPC`
116
117```js
118import RPC from 'fusion-plugin-rpc';
119```
120
121The RPC plugin. Provides the RPC [service API](#service-api).
122
123##### `RPCToken`
124
125```js
126import {RPCToken} from 'fusion-plugin-rpc-redux-react';
127```
128
129The canonical token for the RPC plugin. Typically, it should be registered with
130the [RPC](#rpc) plugin.
131
132#### Dependencies
133
134##### `UniversalEventsToken`
135
136Required. See
137[https://github.com/fusionjs/fusion-plugin-universal-events#api](https://github.com/fusionjs/fusion-plugin-universal-events#api)
138
139##### `RPCHandlersToken`
140
141```js
142import {RPCHandlersToken} from 'fusion-plugin-rpc-redux-react';
143```
144
145Configures what RPC handlers exist. Required. Server-only.
146
147###### Types
148
149```flow
150type RPCHandlers = Object<string, () => any>
151```
152
153You can register a value of type `RPCHandlers` or a Plugin that provides a value
154of type `RPCHandlers`.
155
156##### `FetchToken`
157
158Required. Browser-only. See
159[https://github.com/fusionjs/fusion-tokens#fetchtoken](https://github.com/fusionjs/fusion-tokens#fetchtoken)
160
161##### `ReduxToken`
162
163Required. See
164[https://github.com/fusionjs/fusion-plugin-react-redux](https://github.com/fusionjs/fusion-plugin-react-redux)
165
166##### `ReducerToken`
167
168Required. See
169[https://github.com/fusionjs/fusion-plugin-react-redux](https://github.com/fusionjs/fusion-plugin-react-redux)
170
171---
172
173#### Service API
174
175```js
176const rpc: RPC = Rpc.from((ctx: Context));
177```
178
179- `ctx: Context` - Required. A
180 [Fusion.js context](https://github.com/fusionjs/fusion-core#context)
181- returns `rpc: {request: (method: string, args: any) => Promise<any>}`
182
183 - `request: (method: string, args: any) => Promise<any>` - Makes an RPC call
184 via an HTTP request. If on the server, this will directly call the `method`
185 handler with `(args, ctx)`.
186
187 If on the browser, this will `POST` to `/api/${method}` endpoint with JSON
188 serialized args as the request body. The server will then deserialize the
189 args and call the rpc handler. The response will be serialized and send back
190 to the browser.
191
192 - `method: string` - Required. The RPC method name
193 - `args: any` - Optional. Arguments to pass to the server-side RPC handler.
194 Must be JSON-serializable.
195
196### mock
197
198The package also exports a mock rpc plugin which can be useful for testing. For
199example:
200
201```js
202import {mock as MockRPC} from 'fusion-plugin-rpc';
203```
204
205The package also exports a mock RPC plugin which can be useful for testing. For
206example:
207
208```js
209app.register(RPCToken, mock);
210```
211
212### Error Handling
213
214Use the `ResponseError` error subclass for sending error responses. If this
215error class is not used, a generic message will be sent to the client.
216
217```js
218import {ResponseError} from 'fusion-plugin-rpc';
219
220function testHandler() {
221 try {
222 doThing();
223 } catch (e) {
224 const error = new ResponseError('Failed to do thing');
225 error.code = 'DOTHING';
226 error.meta = {
227 custom: 'metadata',
228 };
229 throw error;
230 }
231}
232```