UNPKG

5.64 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, {RPCToken, RPCHandlersToken, ResponseError} from 'fusion-plugin-rpc';
66import UniversalEvents, {UniversalEventsToken} from 'fusion-plugin-universal-events';
67import {FetchToken} from 'fusion-tokens';
68import fetch from 'unfetch';
69
70// Define your rpc methods server side
71const handlers = __NODE__ && {
72 getUser: async (args, ctx) => {
73 return {some: 'data' + args};
74 },
75 test: async (args, ctx) => {
76 // Error Handling Example
77 try {
78 doThing();
79 } catch(e) {
80 const error = new ResponseError('Failed to do thing');
81 error.code = 'DOTHING';
82 error.meta = {
83 custom: 'metadata'
84 };
85 throw error;
86 }
87 }
88};
89
90export default () => {
91 const app = new App(<div></div>);
92
93 app.register(RPCToken, RPC);
94 app.register(UniversalEventsToken, UniversalEvents);
95 __NODE__
96 ? app.register(RPCHandlersToken, handlers);
97 : app.register(FetchToken, fetch);
98
99 return app;
100}
101```
102
103---
104
105### API
106
107#### Registration API
108
109##### RPC
110
111```js
112import RPC from 'fusion-plugin-rpc';
113```
114
115The RPC plugin. Provides the RPC [service API](#service-api).
116
117###### `RPCToken`
118
119```js
120import {RPCToken} from 'fusion-plugin-rpc-redux-react';
121```
122
123The canonical token for the RPC plugin. Typically, it should be registered with
124the [RPC](#rpc) plugin.
125
126#### Dependencies
127
128##### `UniversalEventsToken`
129
130Required. See
131[https://github.com/fusionjs/fusion-plugin-universal-events#api](https://github.com/fusionjs/fusion-plugin-universal-events#api)
132
133##### `RPCHandlersToken`
134
135```js
136import {RPCHandlersToken} from 'fusion-plugin-rpc-redux-react';
137```
138
139Configures what RPC handlers exist. Required. Server-only.
140
141###### Types
142
143```flow
144type RPCHandlers = Object<string, () => any>
145```
146
147You can register a value of type `RPCHandlers` or a Plugin that provides a value
148of type `RPCHandlers`.
149
150##### `FetchToken`
151
152Required. Browser-only. See
153[https://github.com/fusionjs/fusion-tokens#fetchtoken](https://github.com/fusionjs/fusion-tokens#fetchtoken)
154
155##### `ReduxToken`
156
157Required. See
158[https://github.com/fusionjs/fusion-plugin-react-redux](https://github.com/fusionjs/fusion-plugin-react-redux)
159
160##### `ReducerToken`
161
162Required. See
163[https://github.com/fusionjs/fusion-plugin-react-redux](https://github.com/fusionjs/fusion-plugin-react-redux)
164
165---
166
167#### Service API
168
169```js
170const rpc: RPC = Rpc.from((ctx: Context));
171```
172
173* `ctx: Context` - Required. A
174 [Fusion.js context](https://github.com/fusionjs/fusion-core#context)
175* returns `rpc: {request: (method: string, args: any) => Promise<any>}`
176
177 * `request: (method: string, args: any) => Promise<any>` - Makes an RPC call
178 via an HTTP request. If on the server, this will directly call the `method`
179 handler with `(args, ctx)`.
180
181 If on the browser, this will `POST` to `/api/${method}` endpoint with JSON
182 serialized args as the request body. The server will then deserialize the
183 args and call the rpc handler. The response will be serialized and send back
184 to the browser.
185
186 * `method: string` - Required. The RPC method name
187 * `args: any` - Optional. Arguments to pass to the server-side RPC handler.
188 Must be JSON-serializable.
189
190### mock
191
192The package also exports a mock rpc plugin which can be useful for testing. For
193example:
194
195```js
196import {mock as MockRPC} from 'fusion-plugin-rpc';
197```
198
199The package also exports a mock RPC plugin which can be useful for testing. For
200example:
201
202```js
203app.register(RPCToken, mock);
204```
205
206### Error Handling
207
208Use the `ResponseError` error subclass for sending error responses. If this
209error class is not used, a generic message will be sent to the client.
210
211```js
212import {ResponseError} from 'fusion-plugin-rpc';
213
214function testHandler() {
215 try {
216 doThing();
217 } catch (e) {
218 const error = new ResponseError('Failed to do thing');
219 error.code = 'DOTHING';
220 error.meta = {
221 custom: 'metadata',
222 };
223 throw error;
224 }
225}
226```