fusion-plugin-rpc
Version:
Fetch data on the server and client with an RPC style interface.
118 lines (116 loc) • 14.7 kB
JavaScript
/** Copyright (c) 2018 Uber Technologies, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
*/
/* eslint-env browser */
import { createPlugin, memoize } from 'fusion-core';
import { UniversalEventsToken } from 'fusion-plugin-universal-events';
import { I18nToken } from 'fusion-plugin-i18n';
import { FetchToken } from 'fusion-tokens';
import { RPCHandlersConfigToken, RPCQueryParamsToken } from './tokens';
import { formatApiPath } from './utils';
const statKey = 'rpc:method-client';
class RPC {
constructor({
fetch,
emitter,
rpcConfig,
queryParams
}) {
this.fetch = fetch;
this.config = rpcConfig || {};
this.emitter = emitter;
this.queryParams = queryParams;
this.apiPath = formatApiPath(rpcConfig && rpcConfig.apiPath ? rpcConfig.apiPath : 'api');
}
request(rpcId, args, headers, options) {
if (!this.fetch) {
throw new Error('fusion-plugin-rpc requires `fetch`');
}
if (!this.emitter) {
throw new Error('Missing emitter registered to UniversalEventsToken');
}
const fetch = this.fetch;
const emitter = this.emitter;
const apiPath = this.apiPath;
const startTime = Date.now();
const queryParams = this.queryParams.length > 0 ? `?${this.queryParams.map(([k, v]) => `${encodeURIComponent(k)}=${encodeURIComponent(v)}`).join('&')}` : '';
return fetch(`${apiPath}${rpcId}${queryParams}`, args instanceof FormData ? {
...options,
method: 'POST',
headers: {
// Content-Type will be set automatically
...(headers || {})
},
body: args
} : {
...options,
method: 'POST',
// $FlowFixMe
headers: {
'Content-Type': 'application/json',
...(headers || {})
},
body: JSON.stringify(args || {})
}).then(r => r.json()).then(args => {
const {
status,
data
} = args;
if (status === 'success') {
emitter.emit(statKey, {
method: rpcId,
status: 'success',
timing: Date.now() - startTime
});
return data;
} else {
emitter.emit(statKey, {
method: rpcId,
error: data,
status: 'failure',
timing: Date.now() - startTime
});
return Promise.reject(data ? data : {});
}
});
}
}
const pluginFactory = () => createPlugin({
deps: {
fetch: FetchToken,
emitter: UniversalEventsToken,
i18n: I18nToken.optional,
rpcConfig: RPCHandlersConfigToken.optional,
queryParams: RPCQueryParamsToken.optional
},
provides: deps => {
const {
fetch = window.fetch,
emitter,
rpcConfig,
i18n,
queryParams
} = deps;
return {
from: memoize(ctx => {
const queryParamsValue = queryParams && queryParams.from(ctx) || [];
const locale = i18n && i18n.from(ctx).locale || '';
const localeCode = typeof locale === 'string' ? locale : locale.code;
if (localeCode) {
queryParamsValue.push(['localeCode', localeCode]);
}
return new RPC({
fetch,
emitter,
rpcConfig,
queryParams: queryParamsValue
});
})
};
}
});
export default true && pluginFactory();
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJjcmVhdGVQbHVnaW4iLCJtZW1vaXplIiwiVW5pdmVyc2FsRXZlbnRzVG9rZW4iLCJJMThuVG9rZW4iLCJGZXRjaFRva2VuIiwiUlBDSGFuZGxlcnNDb25maWdUb2tlbiIsIlJQQ1F1ZXJ5UGFyYW1zVG9rZW4iLCJmb3JtYXRBcGlQYXRoIiwic3RhdEtleSIsIlJQQyIsImNvbnN0cnVjdG9yIiwiZmV0Y2giLCJlbWl0dGVyIiwicnBjQ29uZmlnIiwicXVlcnlQYXJhbXMiLCJjb25maWciLCJhcGlQYXRoIiwicmVxdWVzdCIsInJwY0lkIiwiYXJncyIsImhlYWRlcnMiLCJvcHRpb25zIiwiRXJyb3IiLCJzdGFydFRpbWUiLCJEYXRlIiwibm93IiwibGVuZ3RoIiwibWFwIiwiayIsInYiLCJlbmNvZGVVUklDb21wb25lbnQiLCJqb2luIiwiRm9ybURhdGEiLCJtZXRob2QiLCJib2R5IiwiSlNPTiIsInN0cmluZ2lmeSIsInRoZW4iLCJyIiwianNvbiIsInN0YXR1cyIsImRhdGEiLCJlbWl0IiwidGltaW5nIiwiZXJyb3IiLCJQcm9taXNlIiwicmVqZWN0IiwicGx1Z2luRmFjdG9yeSIsImRlcHMiLCJpMThuIiwib3B0aW9uYWwiLCJwcm92aWRlcyIsIndpbmRvdyIsImZyb20iLCJjdHgiLCJxdWVyeVBhcmFtc1ZhbHVlIiwibG9jYWxlIiwibG9jYWxlQ29kZSIsImNvZGUiLCJwdXNoIl0sInNvdXJjZXMiOlsic3JjL2Jyb3dzZXIudHMiXSwic291cmNlc0NvbnRlbnQiOlsiLyoqIENvcHlyaWdodCAoYykgMjAxOCBVYmVyIFRlY2hub2xvZ2llcywgSW5jLlxuICpcbiAqIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuICogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuICpcbiAqL1xuXG4vKiBlc2xpbnQtZW52IGJyb3dzZXIgKi9cblxuaW1wb3J0IHtjcmVhdGVQbHVnaW4sIG1lbW9pemUsIHR5cGUgQ29udGV4dH0gZnJvbSAnZnVzaW9uLWNvcmUnO1xuaW1wb3J0IHtVbml2ZXJzYWxFdmVudHNUb2tlbn0gZnJvbSAnZnVzaW9uLXBsdWdpbi11bml2ZXJzYWwtZXZlbnRzJztcbmltcG9ydCB7STE4blRva2VufSBmcm9tICdmdXNpb24tcGx1Z2luLWkxOG4nO1xuaW1wb3J0IHtGZXRjaFRva2VufSBmcm9tICdmdXNpb24tdG9rZW5zJztcbmltcG9ydCB0eXBlIHtGZXRjaH0gZnJvbSAnZnVzaW9uLXRva2Vucyc7XG5cbmltcG9ydCB7XG4gIHR5cGUgSGFuZGxlclR5cGUsXG4gIFJQQ0hhbmRsZXJzQ29uZmlnVG9rZW4sXG4gIFJQQ1F1ZXJ5UGFyYW1zVG9rZW4sXG59IGZyb20gJy4vdG9rZW5zJztcbmltcG9ydCB0eXBlIHtSUENQbHVnaW5UeXBlLCBJRW1pdHRlciwgUlBDQ29uZmlnVHlwZX0gZnJvbSAnLi90eXBlcyc7XG5pbXBvcnQge2Zvcm1hdEFwaVBhdGh9IGZyb20gJy4vdXRpbHMnO1xuXG50eXBlIEluaXRpYWxpemF0aW9uT3B0cyA9IHtcbiAgZmV0Y2g6IEZldGNoO1xuICBlbWl0dGVyOiBJRW1pdHRlcjtcbiAgcXVlcnlQYXJhbXM6IEFycmF5PFtzdHJpbmcsIHN0cmluZ10+O1xuICBycGNDb25maWc6IFJQQ0NvbmZpZ1R5cGUgfCB1bmRlZmluZWQgfCBudWxsO1xufTtcblxuY29uc3Qgc3RhdEtleSA9ICdycGM6bWV0aG9kLWNsaWVudCc7XG5cbmNsYXNzIFJQQyB7XG4gIGN0eDogQ29udGV4dCB8IHVuZGVmaW5lZCB8IG51bGw7XG4gIGVtaXR0ZXI6IElFbWl0dGVyIHwgdW5kZWZpbmVkIHwgbnVsbDtcbiAgaGFuZGxlcnM6IEhhbmRsZXJUeXBlIHwgdW5kZWZpbmVkIHwgbnVsbDtcbiAgcXVlcnlQYXJhbXM6IEFycmF5PFtzdHJpbmcsIHN0cmluZ10+O1xuICBmZXRjaDogRmV0Y2ggfCB1bmRlZmluZWQgfCBudWxsO1xuICBjb25maWc6IFJQQ0NvbmZpZ1R5cGUgfCB1bmRlZmluZWQgfCBudWxsO1xuICBhcGlQYXRoOiBzdHJpbmc7XG4gIGNvbnN0cnVjdG9yKHtmZXRjaCwgZW1pdHRlciwgcnBjQ29uZmlnLCBxdWVyeVBhcmFtc306IEluaXRpYWxpemF0aW9uT3B0cykge1xuICAgIHRoaXMuZmV0Y2ggPSBmZXRjaDtcbiAgICB0aGlzLmNvbmZpZyA9IHJwY0NvbmZpZyB8fCB7fTtcbiAgICB0aGlzLmVtaXR0ZXIgPSBlbWl0dGVyO1xuICAgIHRoaXMucXVlcnlQYXJhbXMgPSBxdWVyeVBhcmFtcztcblxuICAgIHRoaXMuYXBpUGF0aCA9IGZvcm1hdEFwaVBhdGgoXG4gICAgICBycGNDb25maWcgJiYgcnBjQ29uZmlnLmFwaVBhdGggPyBycGNDb25maWcuYXBpUGF0aCA6ICdhcGknXG4gICAgKTtcbiAgfVxuXG4gIHJlcXVlc3Q8VEFyZ3MsIFRSZXN1bHQ+KFxuICAgIHJwY0lkOiBzdHJpbmcsXG4gICAgYXJnczogVEFyZ3MsXG4gICAgaGVhZGVycz86IHtcbiAgICAgIFt4OiBzdHJpbmddOiBzdHJpbmc7XG4gICAgfSB8IG51bGwsXG4gICAgb3B0aW9ucz86IFJlcXVlc3RJbml0IHwgbnVsbFxuICApOiBQcm9taXNlPFRSZXN1bHQ+IHtcbiAgICBpZiAoIXRoaXMuZmV0Y2gpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignZnVzaW9uLXBsdWdpbi1ycGMgcmVxdWlyZXMgYGZldGNoYCcpO1xuICAgIH1cbiAgICBpZiAoIXRoaXMuZW1pdHRlcikge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdNaXNzaW5nIGVtaXR0ZXIgcmVnaXN0ZXJlZCB0byBVbml2ZXJzYWxFdmVudHNUb2tlbicpO1xuICAgIH1cbiAgICBjb25zdCBmZXRjaCA9IHRoaXMuZmV0Y2g7XG4gICAgY29uc3QgZW1pdHRlciA9IHRoaXMuZW1pdHRlcjtcbiAgICBjb25zdCBhcGlQYXRoID0gdGhpcy5hcGlQYXRoO1xuXG4gICAgY29uc3Qgc3RhcnRUaW1lID0gRGF0ZS5ub3coKTtcbiAgICBjb25zdCBxdWVyeVBhcmFtcyA9XG4gICAgICB0aGlzLnF1ZXJ5UGFyYW1zLmxlbmd0aCA+IDBcbiAgICAgICAgPyBgPyR7dGhpcy5xdWVyeVBhcmFtc1xuICAgICAgICAgICAgLm1hcChcbiAgICAgICAgICAgICAgKFtrLCB2XSkgPT4gYCR7ZW5jb2RlVVJJQ29tcG9uZW50KGspfT0ke2VuY29kZVVSSUNvbXBvbmVudCh2KX1gXG4gICAgICAgICAgICApXG4gICAgICAgICAgICAuam9pbignJicpfWBcbiAgICAgICAgOiAnJztcblxuICAgIHJldHVybiBmZXRjaChcbiAgICAgIGAke2FwaVBhdGh9JHtycGNJZH0ke3F1ZXJ5UGFyYW1zfWAsXG4gICAgICBhcmdzIGluc3RhbmNlb2YgRm9ybURhdGFcbiAgICAgICAgPyB7XG4gICAgICAgICAgICAuLi5vcHRpb25zLFxuICAgICAgICAgICAgbWV0aG9kOiAnUE9TVCcsXG4gICAgICAgICAgICBoZWFkZXJzOiB7XG4gICAgICAgICAgICAgIC8vIENvbnRlbnQtVHlwZSB3aWxsIGJlIHNldCBhdXRvbWF0aWNhbGx5XG4gICAgICAgICAgICAgIC4uLihoZWFkZXJzIHx8IHt9KSxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBib2R5OiBhcmdzLFxuICAgICAgICAgIH1cbiAgICAgICAgOiB7XG4gICAgICAgICAgICAuLi5vcHRpb25zLFxuICAgICAgICAgICAgbWV0aG9kOiAnUE9TVCcsXG4gICAgICAgICAgICAvLyAkRmxvd0ZpeE1lXG4gICAgICAgICAgICBoZWFkZXJzOiB7XG4gICAgICAgICAgICAgICdDb250ZW50LVR5cGUnOiAnYXBwbGljYXRpb24vanNvbicsXG4gICAgICAgICAgICAgIC4uLihoZWFkZXJzIHx8IHt9KSxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBib2R5OiBKU09OLnN0cmluZ2lmeShhcmdzIHx8IHt9KSxcbiAgICAgICAgICB9XG4gICAgKVxuICAgICAgLnRoZW4oKHIpID0+IHIuanNvbigpKVxuICAgICAgLnRoZW4oKGFyZ3MpID0+IHtcbiAgICAgICAgY29uc3Qge3N0YXR1cywgZGF0YX0gPSBhcmdzO1xuICAgICAgICBpZiAoc3RhdHVzID09PSAnc3VjY2VzcycpIHtcbiAgICAgICAgICBlbWl0dGVyLmVtaXQoc3RhdEtleSwge1xuICAgICAgICAgICAgbWV0aG9kOiBycGNJZCxcbiAgICAgICAgICAgIHN0YXR1czogJ3N1Y2Nlc3MnLFxuICAgICAgICAgICAgdGltaW5nOiBEYXRlLm5vdygpIC0gc3RhcnRUaW1lLFxuICAgICAgICAgIH0pO1xuICAgICAgICAgIHJldHVybiBkYXRhO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGVtaXR0ZXIuZW1pdChzdGF0S2V5LCB7XG4gICAgICAgICAgICBtZXRob2Q6IHJwY0lkLFxuICAgICAgICAgICAgZXJyb3I6IGRhdGEsXG4gICAgICAgICAgICBzdGF0dXM6ICdmYWlsdXJlJyxcbiAgICAgICAgICAgIHRpbWluZzogRGF0ZS5ub3coKSAtIHN0YXJ0VGltZSxcbiAgICAgICAgICB9KTtcbiAgICAgICAgICByZXR1cm4gUHJvbWlzZS5yZWplY3QoZGF0YSA/IGRhdGEgOiB7fSk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICB9XG59XG5cbmNvbnN0IHBsdWdpbkZhY3Rvcnk6ICgpID0+IFJQQ1BsdWdpblR5cGUgPSAoKSA9PlxuICBjcmVhdGVQbHVnaW4oe1xuICAgIGRlcHM6IHtcbiAgICAgIGZldGNoOiBGZXRjaFRva2VuLFxuICAgICAgZW1pdHRlcjogVW5pdmVyc2FsRXZlbnRzVG9rZW4sXG4gICAgICBpMThuOiBJMThuVG9rZW4ub3B0aW9uYWwsXG4gICAgICBycGNDb25maWc6IFJQQ0hhbmRsZXJzQ29uZmlnVG9rZW4ub3B0aW9uYWwsXG4gICAgICBxdWVyeVBhcmFtczogUlBDUXVlcnlQYXJhbXNUb2tlbi5vcHRpb25hbCxcbiAgICB9LFxuICAgIHByb3ZpZGVzOiAoZGVwcykgPT4ge1xuICAgICAgY29uc3Qge1xuICAgICAgICBmZXRjaCA9IHdpbmRvdy5mZXRjaCxcbiAgICAgICAgZW1pdHRlcixcbiAgICAgICAgcnBjQ29uZmlnLFxuICAgICAgICBpMThuLFxuICAgICAgICBxdWVyeVBhcmFtcyxcbiAgICAgIH0gPSBkZXBzO1xuXG4gICAgICByZXR1cm4ge1xuICAgICAgICBmcm9tOiBtZW1vaXplKChjdHgpID0+IHtcbiAgICAgICAgICBjb25zdCBxdWVyeVBhcmFtc1ZhbHVlID0gKHF1ZXJ5UGFyYW1zICYmIHF1ZXJ5UGFyYW1zLmZyb20oY3R4KSkgfHwgW107XG4gICAgICAgICAgY29uc3QgbG9jYWxlID0gKGkxOG4gJiYgaTE4bi5mcm9tKGN0eCkubG9jYWxlKSB8fCAnJztcbiAgICAgICAgICBjb25zdCBsb2NhbGVDb2RlID0gdHlwZW9mIGxvY2FsZSA9PT0gJ3N0cmluZycgPyBsb2NhbGUgOiBsb2NhbGUuY29kZTtcbiAgICAgICAgICBpZiAobG9jYWxlQ29kZSkge1xuICAgICAgICAgICAgcXVlcnlQYXJhbXNWYWx1ZS5wdXNoKFsnbG9jYWxlQ29kZScsIGxvY2FsZUNvZGVdKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgcmV0dXJuIG5ldyBSUEMoe1xuICAgICAgICAgICAgZmV0Y2gsXG4gICAgICAgICAgICBlbWl0dGVyLFxuICAgICAgICAgICAgcnBjQ29uZmlnLFxuICAgICAgICAgICAgcXVlcnlQYXJhbXM6IHF1ZXJ5UGFyYW1zVmFsdWUsXG4gICAgICAgICAgfSk7XG4gICAgICAgIH0pLFxuICAgICAgfTtcbiAgICB9LFxuICB9KTtcblxuZXhwb3J0IGRlZmF1bHQgX19CUk9XU0VSX18gJiYgKHBsdWdpbkZhY3RvcnkoKSBhcyBhbnkgYXMgUlBDUGx1Z2luVHlwZSk7XG4iXSwibWFwcGluZ3MiOiJBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQSxTQUFRQSxZQUFZLEVBQUVDLE9BQU8sUUFBcUIsYUFBYTtBQUMvRCxTQUFRQyxvQkFBb0IsUUFBTyxnQ0FBZ0M7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