2017-02-12 22:00:13 +08:00
|
|
|
import ApolloClient, { createNetworkInterface, createBatchingNetworkInterface } from 'apollo-client';
|
2017-02-06 14:33:34 +08:00
|
|
|
import 'isomorphic-fetch';
|
2017-02-12 22:00:13 +08:00
|
|
|
import { Meteor } from 'meteor/meteor';
|
2017-09-22 12:24:15 +02:00
|
|
|
import { getSetting, registerSetting } from './settings.js';
|
2017-09-14 10:06:41 +02:00
|
|
|
import { getFragmentMatcher } from './fragment_matcher.js';
|
|
|
|
import { Callbacks, runCallbacks } from './callbacks.js';
|
2017-02-06 14:33:34 +08:00
|
|
|
|
2017-09-22 12:24:15 +02:00
|
|
|
registerSetting('developmentServerIp', Meteor.absoluteUrl(), 'Development server IP');
|
|
|
|
|
2017-02-06 14:33:34 +08:00
|
|
|
const defaultNetworkInterfaceConfig = {
|
2017-02-12 22:00:13 +08:00
|
|
|
path: '/graphql', // default graphql server endpoint
|
|
|
|
opts: {}, // additional fetch options like `credentials` or `headers`
|
|
|
|
useMeteorAccounts: true, // if true, send an eventual Meteor login token to identify the current user with every request
|
2017-04-15 12:03:25 +09:00
|
|
|
batchingInterface: true, // use a BatchingNetworkInterface by default instead of a NetworkInterface
|
2017-02-12 22:00:13 +08:00
|
|
|
batchInterval: 10, // default batch interval
|
2017-02-06 14:33:34 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
const createMeteorNetworkInterface = (givenConfig = {}) => {
|
2017-02-12 22:00:13 +08:00
|
|
|
const config = { ...defaultNetworkInterfaceConfig, ...givenConfig };
|
2017-02-06 14:33:34 +08:00
|
|
|
|
|
|
|
// absoluteUrl adds a '/', so let's remove it first
|
|
|
|
let path = config.path;
|
|
|
|
if (path[0] === '/') {
|
|
|
|
path = path.slice(1);
|
|
|
|
}
|
|
|
|
|
2017-02-10 09:54:11 +01:00
|
|
|
const uri = Meteor.absoluteUrl(
|
2017-02-12 22:00:13 +08:00
|
|
|
path,
|
|
|
|
{ rootUrl: getSetting('developmentServerIp', Meteor.absoluteUrl()) },
|
2017-02-10 09:54:11 +01:00
|
|
|
);
|
2017-02-12 22:00:13 +08:00
|
|
|
|
|
|
|
// allow the use of a batching network interface; if the options.batchingInterface is not specified, fallback to the standard network interface
|
|
|
|
const interfaceToUse = config.batchingInterface ? createBatchingNetworkInterface : createNetworkInterface;
|
|
|
|
|
|
|
|
// default interface options
|
|
|
|
const interfaceOptions = {
|
2017-02-10 09:54:11 +01:00
|
|
|
uri,
|
2017-02-06 14:33:34 +08:00
|
|
|
opts: {
|
2017-02-12 22:00:13 +08:00
|
|
|
credentials: 'same-origin', // http://dev.apollodata.com/react/auth.html#Cookie
|
|
|
|
},
|
|
|
|
};
|
2017-02-06 14:33:34 +08:00
|
|
|
|
2017-02-12 22:00:13 +08:00
|
|
|
// if a BatchingNetworkInterface is used with a correct batch interval, add it to the options
|
|
|
|
if (config.batchingInterface && config.batchInterval) {
|
|
|
|
interfaceOptions.batchInterval = config.batchInterval;
|
|
|
|
}
|
2017-02-06 14:33:34 +08:00
|
|
|
|
2017-02-12 22:00:13 +08:00
|
|
|
// if 'fetch' has been configured to be called with specific opts, add it to the options
|
|
|
|
if (Object.keys(config.opts).length > 0) {
|
|
|
|
interfaceOptions.opts = config.opts;
|
|
|
|
}
|
2017-02-06 14:33:34 +08:00
|
|
|
|
2017-02-12 22:00:13 +08:00
|
|
|
const networkInterface = interfaceToUse(interfaceOptions);
|
2017-02-06 14:33:34 +08:00
|
|
|
|
2017-02-12 22:00:13 +08:00
|
|
|
if (config.useMeteorAccounts) {
|
|
|
|
networkInterface.use([{
|
2017-04-15 12:03:25 +09:00
|
|
|
applyBatchMiddleware(request, next) {
|
2017-02-12 22:00:13 +08:00
|
|
|
const currentUserToken = Meteor.isClient ? global.localStorage['Meteor.loginToken'] : config.loginToken;
|
2017-02-06 14:33:34 +08:00
|
|
|
|
2017-02-12 22:00:13 +08:00
|
|
|
if (!currentUserToken) {
|
|
|
|
next();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!request.options.headers) {
|
|
|
|
request.options.headers = new Headers();
|
|
|
|
}
|
|
|
|
|
|
|
|
request.options.headers.Authorization = currentUserToken;
|
|
|
|
|
|
|
|
next();
|
|
|
|
},
|
|
|
|
}]);
|
|
|
|
}
|
2017-02-06 14:33:34 +08:00
|
|
|
|
|
|
|
return networkInterface;
|
|
|
|
};
|
|
|
|
|
2017-09-14 10:06:41 +02:00
|
|
|
const meteorClientConfig = networkInterfaceConfig => {
|
|
|
|
|
|
|
|
return {
|
|
|
|
ssrMode: Meteor.isServer,
|
|
|
|
networkInterface: createMeteorNetworkInterface(networkInterfaceConfig),
|
|
|
|
queryDeduplication: true, // http://dev.apollodata.com/core/network.html#query-deduplication
|
|
|
|
addTypename: true,
|
|
|
|
fragmentMatcher: getFragmentMatcher(),
|
|
|
|
|
|
|
|
// Default to using Mongo _id, must use _id for queries.
|
|
|
|
dataIdFromObject(result) {
|
|
|
|
if (result._id && result.__typename) {
|
|
|
|
const dataId = result.__typename + result._id;
|
|
|
|
return dataId;
|
|
|
|
}
|
|
|
|
return null;
|
|
|
|
},
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
export const createApolloClient = options => {
|
|
|
|
|
|
|
|
runCallbacks('apolloclient.init.before');
|
|
|
|
|
|
|
|
return new ApolloClient(meteorClientConfig(options));
|
|
|
|
|
|
|
|
};
|