Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,7 @@ export type BatchMiddlewareOpts = {
maxBatchSize?: number;
maxRequestsPerBatch?: number;
allowMutations?: boolean;
allowOperation?: (operation: ConcreteBatch) => boolean;
method?: 'POST' | 'GET';
headers?: Headers | Promise<Headers> | ((req: RelayRequestBatch) => Headers | Promise<Headers>);
// Available request modes in fetch options. For details see https://fetch.spec.whatwg.org/#requests
Expand Down
54 changes: 54 additions & 0 deletions src/middlewares/__tests__/batch-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -438,6 +438,60 @@ describe('middlewares/batch', () => {
});
});

describe('option `allowOperation`', () => {
beforeEach(() => {
fetchMock.restore();
});

it('should not batch requests that return false', async () => {
fetchMock.mock({
matcher: '/graphql',
response: {
status: 200,
body: { data: {} },
},
method: 'POST',
});
fetchMock.mock({
matcher: '/graphql/batch',
response: {
status: 200,
body: [{ data: {} }, { data: {} }, { data: {} }],
},
method: 'POST',
});

const req1 = mockReq(1, {
query: 'abc',
});
const req2 = mockReq(2);
const req3 = mockReq(3);
const req4 = mockReq(4, {
query: 'def',
});
const req5 = mockReq(4, {
query: 'no',
});

const rnl = new RelayNetworkLayer([
batchMiddleware({
allowOperation: (op) => !['abc', 'def'].includes(op.text),
}),
]);
await Promise.all([
req1.execute(rnl),
req2.execute(rnl),
req3.execute(rnl),
req4.execute(rnl),
req5.execute(rnl),
]);
const batchReqs = fetchMock.calls('/graphql/batch');
const singleReqs = fetchMock.calls('/graphql');
expect(batchReqs).toHaveLength(1);
expect(singleReqs).toHaveLength(2);
});
});

it('should pass fetch options', async () => {
fetchMock.mock({
matcher: '/graphql/batch',
Expand Down
9 changes: 8 additions & 1 deletion src/middlewares/batch.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { isFunction } from '../utils';
import RelayRequestBatch from '../RelayRequestBatch';
import RelayRequest from '../RelayRequest';
import type RelayResponse from '../RelayResponse';
import type { Middleware, FetchOpts } from '../definition';
import type { Middleware, FetchOpts, ConcreteBatch } from '../definition';
import RRNLError from '../RRNLError';

// Max out at roughly 100kb (express-graphql imposed max)
Expand All @@ -22,6 +22,7 @@ export type BatchMiddlewareOpts = {|
maxBatchSize?: number,
maxRequestsPerBatch?: number,
allowMutations?: boolean,
allowOperation?: (operation: ConcreteBatch) => boolean,
method?: 'POST' | 'GET',
headers?: Headers | Promise<Headers> | ((req: RelayRequestBatch) => Headers | Promise<Headers>),
// Avaliable request modes in fetch options. For details see https://fetch.spec.whatwg.org/#requests
Expand Down Expand Up @@ -59,6 +60,7 @@ export default function batchMiddleware(options?: BatchMiddlewareOpts): Middlewa
const batchUrl = opts.batchUrl || '/graphql/batch';
const maxBatchSize = opts.maxBatchSize || DEFAULT_BATCH_SIZE;
const maxRequestsPerBatch = opts.maxRequestsPerBatch || 0; // 0 is the same as no limit
const allowOperation = opts.allowOperation || true;
const singleton = {};

const fetchOpts = {};
Expand All @@ -81,6 +83,10 @@ export default function batchMiddleware(options?: BatchMiddlewareOpts): Middlewa
);
}

if (isFunction(opts.allowOperation) && !opts.allowOperation(req.operation)) {
return next(req);
}

// req with FormData can not be batched
if (req.isFormData()) {
return next(req);
Expand All @@ -97,6 +103,7 @@ export default function batchMiddleware(options?: BatchMiddlewareOpts): Middlewa
singleton,
maxBatchSize,
maxRequestsPerBatch,
allowOperation,
fetchOpts,
});
};
Expand Down
Loading