UNPKG

6.83 kBJavaScriptView Raw
1import { createToken, createPlugin } from 'fusion-core';
2import { UniversalEventsToken } from 'fusion-plugin-universal-events';
3import { FetchToken } from 'fusion-tokens';
4import mapObject from 'just-map-object';
5import isEqual from 'just-compare';
6
7/** Copyright (c) 2018 Uber Technologies, Inc.
8 *
9 * This source code is licensed under the MIT license found in the
10 * LICENSE file in the root directory of this source tree.
11 *
12 *
13 */
14const RPCToken = createToken('RPCToken');
15const RPCHandlersToken = createToken('RPCHandlersToken');
16const BodyParserOptionsToken = createToken('BodyParserOptionsToken');
17const RPCHandlersConfigToken = createToken('RPCHandlersConfigToken');
18
19const formatApiPath = apiPath => `/${apiPath}/`.replace(/\/{2,}/g, '/');
20
21function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; var ownKeys = Object.keys(source); if (typeof Object.getOwnPropertySymbols === 'function') { ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function (sym) { return Object.getOwnPropertyDescriptor(source, sym).enumerable; })); } ownKeys.forEach(function (key) { _defineProperty(target, key, source[key]); }); } return target; }
22
23function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
24
25/** Copyright (c) 2018 Uber Technologies, Inc.
26 *
27 * This source code is licensed under the MIT license found in the
28 * LICENSE file in the root directory of this source tree.
29 *
30 *
31 */
32
33/* eslint-env browser */
34const statKey = 'rpc:method-client';
35
36class RPC {
37 constructor({
38 fetch,
39 emitter,
40 rpcConfig
41 }) {
42 this.fetch = fetch;
43 this.config = rpcConfig || {};
44 this.emitter = emitter;
45 this.apiPath = formatApiPath(rpcConfig && rpcConfig.apiPath ? rpcConfig.apiPath : 'api');
46 }
47
48 request(rpcId, args, headers) {
49 if (!this.fetch) {
50 throw new Error('fusion-plugin-rpc requires `fetch`');
51 }
52
53 if (!this.emitter) {
54 throw new Error('Missing emitter registered to UniversalEventsToken');
55 }
56
57 const fetch = this.fetch;
58 const emitter = this.emitter;
59 const apiPath = this.apiPath;
60 const startTime = Date.now(); // TODO(#3) handle args instanceof FormData
61
62 return fetch(`${apiPath}${rpcId}`, {
63 method: 'POST',
64 headers: _objectSpread({
65 'Content-Type': 'application/json'
66 }, headers || {}),
67 body: JSON.stringify(args || {})
68 }).then(r => r.json()).then(args => {
69 const {
70 status,
71 data
72 } = args;
73
74 if (status === 'success') {
75 emitter.emit(statKey, {
76 method: rpcId,
77 status: 'success',
78 timing: Date.now() - startTime
79 });
80 return data;
81 } else {
82 emitter.emit(statKey, {
83 method: rpcId,
84 error: data,
85 status: 'failure',
86 timing: Date.now() - startTime
87 });
88 return Promise.reject(data);
89 }
90 });
91 }
92
93}
94
95const pluginFactory = () => createPlugin({
96 deps: {
97 fetch: FetchToken,
98 emitter: UniversalEventsToken,
99 rpcConfig: RPCHandlersConfigToken.optional
100 },
101 provides: deps => {
102 const {
103 fetch = window.fetch,
104 emitter,
105 rpcConfig
106 } = deps;
107 return {
108 from: () => new RPC({
109 fetch,
110 emitter,
111 rpcConfig
112 })
113 };
114 }
115});
116
117var browserDataFetching = true && pluginFactory();
118
119/** Copyright (c) 2018 Uber Technologies, Inc.
120 *
121 * This source code is licensed under the MIT license found in the
122 * LICENSE file in the root directory of this source tree.
123 *
124 *
125 */
126class MissingHandlerError extends Error {
127 constructor(method) {
128 super(`Missing RPC handler for ${method}`);
129 this.code = 'ERR_MISSING_HANDLER';
130 Error.captureStackTrace(this, MissingHandlerError);
131 }
132
133}
134
135/** Copyright (c) 2018 Uber Technologies, Inc.
136 *
137 * This source code is licensed under the MIT license found in the
138 * LICENSE file in the root directory of this source tree.
139 *
140 *
141 */
142class ResponseError extends Error {
143 constructor(message) {
144 super(message);
145 this.code = null;
146 this.meta = null;
147 Error.captureStackTrace(this, ResponseError);
148 }
149
150}
151
152/** Copyright (c) 2018 Uber Technologies, Inc.
153 *
154 * This source code is licensed under the MIT license found in the
155 * LICENSE file in the root directory of this source tree.
156 *
157 *
158 */
159
160/* eslint-env node */
161
162/** Copyright (c) 2018 Uber Technologies, Inc.
163 *
164 * This source code is licensed under the MIT license found in the
165 * LICENSE file in the root directory of this source tree.
166 *
167 *
168 */
169class RPC$2 {
170 constructor(handlers) {
171 this.handlers = handlers;
172 }
173
174 async request(method, args) {
175 if (!this.handlers) {
176 throw new Error('fusion-plugin-rpc requires `handlers`');
177 }
178
179 if (!this.handlers[method]) {
180 throw new MissingHandlerError(method);
181 }
182
183 return this.handlers[method](args);
184 }
185
186}
187
188const plugin = createPlugin({
189 deps: {
190 handlers: RPCHandlersToken,
191 emitter: UniversalEventsToken
192 },
193 provides: ({
194 handlers
195 } = {}) => {
196 return {
197 from: () => new RPC$2(handlers)
198 };
199 }
200});
201
202function _objectSpread$1(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; var ownKeys = Object.keys(source); if (typeof Object.getOwnPropertySymbols === 'function') { ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function (sym) { return Object.getOwnPropertyDescriptor(source, sym).enumerable; })); } ownKeys.forEach(function (key) { _defineProperty$1(target, key, source[key]); }); } return target; }
203
204function _defineProperty$1(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
205
206const getMockRpcHandlers = (fixtures, onMockRpc) => fixtures.reduce((rpcHandlers, fixture) => _objectSpread$1({}, rpcHandlers, mapObject(fixture, (rpcId, responseDetails) => async (...args) => {
207 const response = Array.isArray(responseDetails) ? responseDetails.filter(item => isEqual(item.args, args))[0].response : responseDetails;
208 onMockRpc && onMockRpc(rpcId, args, response);
209
210 if (response instanceof Error) {
211 throw response;
212 }
213
214 return response;
215})), {});
216
217/** Copyright (c) 2018 Uber Technologies, Inc.
218 *
219 * This source code is licensed under the MIT license found in the
220 * LICENSE file in the root directory of this source tree.
221 *
222 *
223 */
224var index = browserDataFetching;
225
226export default index;
227export { plugin as mock, ResponseError, BodyParserOptionsToken, RPCToken, RPCHandlersToken, RPCHandlersConfigToken, getMockRpcHandlers };