@nsxbet/react-relay-network-modern 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE.md +10 -0
- package/README.md +324 -0
- package/dist/RRNLError.cjs +9 -0
- package/dist/RRNLError.d.cts +6 -0
- package/dist/RRNLError.d.ts +6 -0
- package/dist/RRNLError.js +9 -0
- package/dist/RelayNetworkLayer.cjs +54 -0
- package/dist/RelayNetworkLayer.d.cts +21 -0
- package/dist/RelayNetworkLayer.d.ts +21 -0
- package/dist/RelayNetworkLayer.js +54 -0
- package/dist/RelayRequest.cjs +90 -0
- package/dist/RelayRequest.d.cts +26 -0
- package/dist/RelayRequest.d.ts +26 -0
- package/dist/RelayRequest.js +90 -0
- package/dist/RelayRequestBatch.cjs +56 -0
- package/dist/RelayRequestBatch.d.cts +23 -0
- package/dist/RelayRequestBatch.d.ts +23 -0
- package/dist/RelayRequestBatch.js +56 -0
- package/dist/RelayResponse.cjs +56 -0
- package/dist/RelayResponse.d.cts +27 -0
- package/dist/RelayResponse.d.ts +27 -0
- package/dist/RelayResponse.js +56 -0
- package/dist/createRequestError.cjs +48 -0
- package/dist/createRequestError.d.cts +18 -0
- package/dist/createRequestError.d.ts +18 -0
- package/dist/createRequestError.js +46 -0
- package/dist/definition.d.cts +95 -0
- package/dist/definition.d.ts +95 -0
- package/dist/express-middleware/graphqlBatchHTTPWrapper.cjs +60 -0
- package/dist/express-middleware/graphqlBatchHTTPWrapper.d.cts +5 -0
- package/dist/express-middleware/graphqlBatchHTTPWrapper.d.ts +5 -0
- package/dist/express-middleware/graphqlBatchHTTPWrapper.js +60 -0
- package/dist/fetchWithMiddleware.cjs +43 -0
- package/dist/fetchWithMiddleware.js +43 -0
- package/dist/index.cjs +49 -0
- package/dist/index.d.cts +21 -0
- package/dist/index.d.ts +21 -0
- package/dist/index.js +20 -0
- package/dist/middlewares/auth.cjs +47 -0
- package/dist/middlewares/auth.d.cts +18 -0
- package/dist/middlewares/auth.d.ts +18 -0
- package/dist/middlewares/auth.js +46 -0
- package/dist/middlewares/batch.cjs +136 -0
- package/dist/middlewares/batch.d.cts +34 -0
- package/dist/middlewares/batch.d.ts +34 -0
- package/dist/middlewares/batch.js +135 -0
- package/dist/middlewares/cache.cjs +43 -0
- package/dist/middlewares/cache.d.cts +17 -0
- package/dist/middlewares/cache.d.ts +17 -0
- package/dist/middlewares/cache.js +43 -0
- package/dist/middlewares/error.cjs +71 -0
- package/dist/middlewares/error.d.cts +11 -0
- package/dist/middlewares/error.d.ts +11 -0
- package/dist/middlewares/error.js +71 -0
- package/dist/middlewares/logger.cjs +43 -0
- package/dist/middlewares/logger.d.cts +9 -0
- package/dist/middlewares/logger.d.ts +9 -0
- package/dist/middlewares/logger.js +43 -0
- package/dist/middlewares/perf.cjs +13 -0
- package/dist/middlewares/perf.d.cts +9 -0
- package/dist/middlewares/perf.d.ts +9 -0
- package/dist/middlewares/perf.js +13 -0
- package/dist/middlewares/persistedQueries.cjs +33 -0
- package/dist/middlewares/persistedQueries.d.cts +9 -0
- package/dist/middlewares/persistedQueries.d.ts +9 -0
- package/dist/middlewares/persistedQueries.js +33 -0
- package/dist/middlewares/progress.cjs +35 -0
- package/dist/middlewares/progress.d.cts +10 -0
- package/dist/middlewares/progress.d.ts +10 -0
- package/dist/middlewares/progress.js +35 -0
- package/dist/middlewares/retry.cjs +146 -0
- package/dist/middlewares/retry.d.cts +34 -0
- package/dist/middlewares/retry.d.ts +34 -0
- package/dist/middlewares/retry.js +145 -0
- package/dist/middlewares/upload.cjs +32 -0
- package/dist/middlewares/upload.d.cts +6 -0
- package/dist/middlewares/upload.d.ts +6 -0
- package/dist/middlewares/upload.js +32 -0
- package/dist/middlewares/url.cjs +19 -0
- package/dist/middlewares/url.d.cts +19 -0
- package/dist/middlewares/url.d.ts +19 -0
- package/dist/middlewares/url.js +19 -0
- package/dist/utils.cjs +6 -0
- package/dist/utils.js +6 -0
- package/package.json +88 -0
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
const require_RRNLError = require("../RRNLError.cjs");
|
|
2
|
+
const require_RelayRequest = require("../RelayRequest.cjs");
|
|
3
|
+
const require_RelayRequestBatch = require("../RelayRequestBatch.cjs");
|
|
4
|
+
const require_utils = require("../utils.cjs");
|
|
5
|
+
//#region src/middlewares/batch.ts
|
|
6
|
+
const DEFAULT_BATCH_SIZE = 102400;
|
|
7
|
+
var RRNLBatchMiddlewareError = class extends require_RRNLError.default {
|
|
8
|
+
constructor(msg) {
|
|
9
|
+
super(msg);
|
|
10
|
+
this.name = "RRNLBatchMiddlewareError";
|
|
11
|
+
}
|
|
12
|
+
};
|
|
13
|
+
function batchMiddleware(options) {
|
|
14
|
+
const opts = options || {};
|
|
15
|
+
const batchTimeout = opts.batchTimeout || 0;
|
|
16
|
+
const allowMutations = opts.allowMutations || false;
|
|
17
|
+
const batchUrl = opts.batchUrl || "/graphql/batch";
|
|
18
|
+
const maxBatchSize = opts.maxBatchSize || DEFAULT_BATCH_SIZE;
|
|
19
|
+
const singleton = {};
|
|
20
|
+
const fetchOpts = {};
|
|
21
|
+
if (opts.method) fetchOpts.method = opts.method;
|
|
22
|
+
if (opts.credentials) fetchOpts.credentials = opts.credentials;
|
|
23
|
+
if (opts.mode) fetchOpts.mode = opts.mode;
|
|
24
|
+
if (opts.cache) fetchOpts.cache = opts.cache;
|
|
25
|
+
if (opts.redirect) fetchOpts.redirect = opts.redirect;
|
|
26
|
+
if (opts.headers) fetchOpts.headersOrThunk = opts.headers;
|
|
27
|
+
return (next) => (req) => {
|
|
28
|
+
if (req.isMutation() && !allowMutations) return next(req);
|
|
29
|
+
if (!(req instanceof require_RelayRequest.default)) throw new RRNLBatchMiddlewareError("Relay batch middleware accepts only simple RelayRequest. Did you add batchMiddleware twice?");
|
|
30
|
+
if (req.isFormData()) return next(req);
|
|
31
|
+
if (req.cacheConfig.skipBatch) return next(req);
|
|
32
|
+
return passThroughBatch(req, next, {
|
|
33
|
+
batchTimeout,
|
|
34
|
+
batchUrl,
|
|
35
|
+
singleton,
|
|
36
|
+
maxBatchSize,
|
|
37
|
+
fetchOpts
|
|
38
|
+
});
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
function passThroughBatch(req, next, opts) {
|
|
42
|
+
const { singleton } = opts;
|
|
43
|
+
const bodyLength = req.getBody().length;
|
|
44
|
+
if (!bodyLength) return next(req);
|
|
45
|
+
if (!singleton.batcher || !singleton.batcher.acceptRequests) singleton.batcher = prepareNewBatcher(next, opts);
|
|
46
|
+
if (singleton.batcher.bodySize + bodyLength + 1 > opts.maxBatchSize) singleton.batcher = prepareNewBatcher(next, opts);
|
|
47
|
+
singleton.batcher.bodySize += bodyLength + 1;
|
|
48
|
+
return new Promise((resolve, reject) => {
|
|
49
|
+
const { requestList } = singleton.batcher;
|
|
50
|
+
const requestWrapper = {
|
|
51
|
+
req,
|
|
52
|
+
completeOk: (res) => {
|
|
53
|
+
requestWrapper.done = true;
|
|
54
|
+
resolve(res);
|
|
55
|
+
requestWrapper.duplicates.forEach((r) => r.completeOk(res));
|
|
56
|
+
},
|
|
57
|
+
completeErr: (err) => {
|
|
58
|
+
requestWrapper.done = true;
|
|
59
|
+
reject(err);
|
|
60
|
+
requestWrapper.duplicates.forEach((r) => r.completeErr(err));
|
|
61
|
+
},
|
|
62
|
+
done: false,
|
|
63
|
+
duplicates: []
|
|
64
|
+
};
|
|
65
|
+
const duplicateIndex = requestList.findIndex((wrapper) => req.getBody() === wrapper.req.getBody());
|
|
66
|
+
if (duplicateIndex !== -1) requestList[duplicateIndex].duplicates.push(requestWrapper);
|
|
67
|
+
else requestList.push(requestWrapper);
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
function prepareNewBatcher(next, opts) {
|
|
71
|
+
const batcher = {
|
|
72
|
+
bodySize: 2,
|
|
73
|
+
requestList: [],
|
|
74
|
+
acceptRequests: true
|
|
75
|
+
};
|
|
76
|
+
setTimeout(() => {
|
|
77
|
+
batcher.acceptRequests = false;
|
|
78
|
+
sendRequests(batcher.requestList, next, opts).then(() => finalizeUncompleted(batcher.requestList)).catch((e) => {
|
|
79
|
+
if (e && e.name === "AbortError") finalizeCanceled(batcher.requestList, e);
|
|
80
|
+
else finalizeUncompleted(batcher.requestList);
|
|
81
|
+
});
|
|
82
|
+
}, opts.batchTimeout);
|
|
83
|
+
return batcher;
|
|
84
|
+
}
|
|
85
|
+
async function sendRequests(requestList, next, opts) {
|
|
86
|
+
if (requestList.length === 1) {
|
|
87
|
+
const wrapper = requestList[0];
|
|
88
|
+
const res = await next(wrapper.req);
|
|
89
|
+
wrapper.completeOk(res);
|
|
90
|
+
wrapper.duplicates.forEach((r) => r.completeOk(res));
|
|
91
|
+
return res;
|
|
92
|
+
} else if (requestList.length > 1) {
|
|
93
|
+
const batchRequest = new require_RelayRequestBatch.default(requestList.map((wrapper) => wrapper.req));
|
|
94
|
+
const url = await (require_utils.isFunction(opts.batchUrl) ? opts.batchUrl(requestList) : opts.batchUrl);
|
|
95
|
+
batchRequest.setFetchOption("url", url);
|
|
96
|
+
const { headersOrThunk, ...fetchOpts } = opts.fetchOpts;
|
|
97
|
+
batchRequest.setFetchOptions(fetchOpts);
|
|
98
|
+
if (headersOrThunk) {
|
|
99
|
+
const headers = await (require_utils.isFunction(headersOrThunk) ? headersOrThunk(batchRequest) : headersOrThunk);
|
|
100
|
+
batchRequest.setFetchOption("headers", headers);
|
|
101
|
+
}
|
|
102
|
+
try {
|
|
103
|
+
const batchResponse = await next(batchRequest);
|
|
104
|
+
if (!batchResponse || !Array.isArray(batchResponse.json)) throw new RRNLBatchMiddlewareError("Wrong response from server. Did your server support batch request?");
|
|
105
|
+
batchResponse.json.forEach((payload, index) => {
|
|
106
|
+
if (!payload) return;
|
|
107
|
+
const request = requestList[index];
|
|
108
|
+
if (request) {
|
|
109
|
+
const res = createSingleResponse(batchResponse, payload);
|
|
110
|
+
request.completeOk(res);
|
|
111
|
+
}
|
|
112
|
+
});
|
|
113
|
+
return batchResponse;
|
|
114
|
+
} catch (e) {
|
|
115
|
+
requestList.forEach((request) => request.completeErr(e));
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
return Promise.resolve();
|
|
119
|
+
}
|
|
120
|
+
function finalizeCanceled(requestList, error) {
|
|
121
|
+
requestList.forEach((request) => request.completeErr(error));
|
|
122
|
+
}
|
|
123
|
+
function finalizeUncompleted(requestList) {
|
|
124
|
+
requestList.forEach((request, index) => {
|
|
125
|
+
if (!request.done) request.completeErr(new RRNLBatchMiddlewareError(`Server does not return response for request at index ${index}.\nResponse should have an array with ${requestList.length} item(s).`));
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
function createSingleResponse(batchResponse, json) {
|
|
129
|
+
const data = json.payload || json;
|
|
130
|
+
const res = batchResponse.clone();
|
|
131
|
+
res.processJsonData(data);
|
|
132
|
+
return res;
|
|
133
|
+
}
|
|
134
|
+
//#endregion
|
|
135
|
+
exports.RRNLBatchMiddlewareError = RRNLBatchMiddlewareError;
|
|
136
|
+
exports.default = batchMiddleware;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { RelayRequest } from "../RelayRequest.cjs";
|
|
2
|
+
import { RelayRequestBatch } from "../RelayRequestBatch.cjs";
|
|
3
|
+
import { FetchOpts, Middleware } from "../definition.cjs";
|
|
4
|
+
import { RRNLError } from "../RRNLError.cjs";
|
|
5
|
+
|
|
6
|
+
//#region src/middlewares/batch.d.ts
|
|
7
|
+
type Headers = {
|
|
8
|
+
[name: string]: string;
|
|
9
|
+
};
|
|
10
|
+
interface BatchMiddlewareOpts {
|
|
11
|
+
batchUrl?: string | Promise<string> | ((requestList: RequestWrapper[]) => string | Promise<string>);
|
|
12
|
+
batchTimeout?: number;
|
|
13
|
+
maxBatchSize?: number;
|
|
14
|
+
allowMutations?: boolean;
|
|
15
|
+
method?: 'POST' | 'GET';
|
|
16
|
+
headers?: Headers | Promise<Headers> | ((req: RelayRequestBatch) => Headers | Promise<Headers>);
|
|
17
|
+
credentials?: FetchOpts['credentials'];
|
|
18
|
+
mode?: FetchOpts['mode'];
|
|
19
|
+
cache?: FetchOpts['cache'];
|
|
20
|
+
redirect?: FetchOpts['redirect'];
|
|
21
|
+
}
|
|
22
|
+
interface RequestWrapper {
|
|
23
|
+
req: RelayRequest;
|
|
24
|
+
completeOk: (res: any) => void;
|
|
25
|
+
completeErr: (e: Error) => void;
|
|
26
|
+
done: boolean;
|
|
27
|
+
duplicates: Array<RequestWrapper>;
|
|
28
|
+
}
|
|
29
|
+
declare class RRNLBatchMiddlewareError extends RRNLError {
|
|
30
|
+
constructor(msg: string);
|
|
31
|
+
}
|
|
32
|
+
declare function batchMiddleware(options?: BatchMiddlewareOpts): Middleware;
|
|
33
|
+
//#endregion
|
|
34
|
+
export { BatchMiddlewareOpts, RRNLBatchMiddlewareError, RequestWrapper, batchMiddleware };
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { RelayRequest } from "../RelayRequest.js";
|
|
2
|
+
import { RelayRequestBatch } from "../RelayRequestBatch.js";
|
|
3
|
+
import { FetchOpts, Middleware } from "../definition.js";
|
|
4
|
+
import { RRNLError } from "../RRNLError.js";
|
|
5
|
+
|
|
6
|
+
//#region src/middlewares/batch.d.ts
|
|
7
|
+
type Headers = {
|
|
8
|
+
[name: string]: string;
|
|
9
|
+
};
|
|
10
|
+
interface BatchMiddlewareOpts {
|
|
11
|
+
batchUrl?: string | Promise<string> | ((requestList: RequestWrapper[]) => string | Promise<string>);
|
|
12
|
+
batchTimeout?: number;
|
|
13
|
+
maxBatchSize?: number;
|
|
14
|
+
allowMutations?: boolean;
|
|
15
|
+
method?: 'POST' | 'GET';
|
|
16
|
+
headers?: Headers | Promise<Headers> | ((req: RelayRequestBatch) => Headers | Promise<Headers>);
|
|
17
|
+
credentials?: FetchOpts['credentials'];
|
|
18
|
+
mode?: FetchOpts['mode'];
|
|
19
|
+
cache?: FetchOpts['cache'];
|
|
20
|
+
redirect?: FetchOpts['redirect'];
|
|
21
|
+
}
|
|
22
|
+
interface RequestWrapper {
|
|
23
|
+
req: RelayRequest;
|
|
24
|
+
completeOk: (res: any) => void;
|
|
25
|
+
completeErr: (e: Error) => void;
|
|
26
|
+
done: boolean;
|
|
27
|
+
duplicates: Array<RequestWrapper>;
|
|
28
|
+
}
|
|
29
|
+
declare class RRNLBatchMiddlewareError extends RRNLError {
|
|
30
|
+
constructor(msg: string);
|
|
31
|
+
}
|
|
32
|
+
declare function batchMiddleware(options?: BatchMiddlewareOpts): Middleware;
|
|
33
|
+
//#endregion
|
|
34
|
+
export { BatchMiddlewareOpts, RRNLBatchMiddlewareError, RequestWrapper, batchMiddleware };
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
import RRNLError from "../RRNLError.js";
|
|
2
|
+
import RelayRequest from "../RelayRequest.js";
|
|
3
|
+
import RelayRequestBatch from "../RelayRequestBatch.js";
|
|
4
|
+
import { isFunction } from "../utils.js";
|
|
5
|
+
//#region src/middlewares/batch.ts
|
|
6
|
+
const DEFAULT_BATCH_SIZE = 102400;
|
|
7
|
+
var RRNLBatchMiddlewareError = class extends RRNLError {
|
|
8
|
+
constructor(msg) {
|
|
9
|
+
super(msg);
|
|
10
|
+
this.name = "RRNLBatchMiddlewareError";
|
|
11
|
+
}
|
|
12
|
+
};
|
|
13
|
+
function batchMiddleware(options) {
|
|
14
|
+
const opts = options || {};
|
|
15
|
+
const batchTimeout = opts.batchTimeout || 0;
|
|
16
|
+
const allowMutations = opts.allowMutations || false;
|
|
17
|
+
const batchUrl = opts.batchUrl || "/graphql/batch";
|
|
18
|
+
const maxBatchSize = opts.maxBatchSize || DEFAULT_BATCH_SIZE;
|
|
19
|
+
const singleton = {};
|
|
20
|
+
const fetchOpts = {};
|
|
21
|
+
if (opts.method) fetchOpts.method = opts.method;
|
|
22
|
+
if (opts.credentials) fetchOpts.credentials = opts.credentials;
|
|
23
|
+
if (opts.mode) fetchOpts.mode = opts.mode;
|
|
24
|
+
if (opts.cache) fetchOpts.cache = opts.cache;
|
|
25
|
+
if (opts.redirect) fetchOpts.redirect = opts.redirect;
|
|
26
|
+
if (opts.headers) fetchOpts.headersOrThunk = opts.headers;
|
|
27
|
+
return (next) => (req) => {
|
|
28
|
+
if (req.isMutation() && !allowMutations) return next(req);
|
|
29
|
+
if (!(req instanceof RelayRequest)) throw new RRNLBatchMiddlewareError("Relay batch middleware accepts only simple RelayRequest. Did you add batchMiddleware twice?");
|
|
30
|
+
if (req.isFormData()) return next(req);
|
|
31
|
+
if (req.cacheConfig.skipBatch) return next(req);
|
|
32
|
+
return passThroughBatch(req, next, {
|
|
33
|
+
batchTimeout,
|
|
34
|
+
batchUrl,
|
|
35
|
+
singleton,
|
|
36
|
+
maxBatchSize,
|
|
37
|
+
fetchOpts
|
|
38
|
+
});
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
function passThroughBatch(req, next, opts) {
|
|
42
|
+
const { singleton } = opts;
|
|
43
|
+
const bodyLength = req.getBody().length;
|
|
44
|
+
if (!bodyLength) return next(req);
|
|
45
|
+
if (!singleton.batcher || !singleton.batcher.acceptRequests) singleton.batcher = prepareNewBatcher(next, opts);
|
|
46
|
+
if (singleton.batcher.bodySize + bodyLength + 1 > opts.maxBatchSize) singleton.batcher = prepareNewBatcher(next, opts);
|
|
47
|
+
singleton.batcher.bodySize += bodyLength + 1;
|
|
48
|
+
return new Promise((resolve, reject) => {
|
|
49
|
+
const { requestList } = singleton.batcher;
|
|
50
|
+
const requestWrapper = {
|
|
51
|
+
req,
|
|
52
|
+
completeOk: (res) => {
|
|
53
|
+
requestWrapper.done = true;
|
|
54
|
+
resolve(res);
|
|
55
|
+
requestWrapper.duplicates.forEach((r) => r.completeOk(res));
|
|
56
|
+
},
|
|
57
|
+
completeErr: (err) => {
|
|
58
|
+
requestWrapper.done = true;
|
|
59
|
+
reject(err);
|
|
60
|
+
requestWrapper.duplicates.forEach((r) => r.completeErr(err));
|
|
61
|
+
},
|
|
62
|
+
done: false,
|
|
63
|
+
duplicates: []
|
|
64
|
+
};
|
|
65
|
+
const duplicateIndex = requestList.findIndex((wrapper) => req.getBody() === wrapper.req.getBody());
|
|
66
|
+
if (duplicateIndex !== -1) requestList[duplicateIndex].duplicates.push(requestWrapper);
|
|
67
|
+
else requestList.push(requestWrapper);
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
function prepareNewBatcher(next, opts) {
|
|
71
|
+
const batcher = {
|
|
72
|
+
bodySize: 2,
|
|
73
|
+
requestList: [],
|
|
74
|
+
acceptRequests: true
|
|
75
|
+
};
|
|
76
|
+
setTimeout(() => {
|
|
77
|
+
batcher.acceptRequests = false;
|
|
78
|
+
sendRequests(batcher.requestList, next, opts).then(() => finalizeUncompleted(batcher.requestList)).catch((e) => {
|
|
79
|
+
if (e && e.name === "AbortError") finalizeCanceled(batcher.requestList, e);
|
|
80
|
+
else finalizeUncompleted(batcher.requestList);
|
|
81
|
+
});
|
|
82
|
+
}, opts.batchTimeout);
|
|
83
|
+
return batcher;
|
|
84
|
+
}
|
|
85
|
+
async function sendRequests(requestList, next, opts) {
|
|
86
|
+
if (requestList.length === 1) {
|
|
87
|
+
const wrapper = requestList[0];
|
|
88
|
+
const res = await next(wrapper.req);
|
|
89
|
+
wrapper.completeOk(res);
|
|
90
|
+
wrapper.duplicates.forEach((r) => r.completeOk(res));
|
|
91
|
+
return res;
|
|
92
|
+
} else if (requestList.length > 1) {
|
|
93
|
+
const batchRequest = new RelayRequestBatch(requestList.map((wrapper) => wrapper.req));
|
|
94
|
+
const url = await (isFunction(opts.batchUrl) ? opts.batchUrl(requestList) : opts.batchUrl);
|
|
95
|
+
batchRequest.setFetchOption("url", url);
|
|
96
|
+
const { headersOrThunk, ...fetchOpts } = opts.fetchOpts;
|
|
97
|
+
batchRequest.setFetchOptions(fetchOpts);
|
|
98
|
+
if (headersOrThunk) {
|
|
99
|
+
const headers = await (isFunction(headersOrThunk) ? headersOrThunk(batchRequest) : headersOrThunk);
|
|
100
|
+
batchRequest.setFetchOption("headers", headers);
|
|
101
|
+
}
|
|
102
|
+
try {
|
|
103
|
+
const batchResponse = await next(batchRequest);
|
|
104
|
+
if (!batchResponse || !Array.isArray(batchResponse.json)) throw new RRNLBatchMiddlewareError("Wrong response from server. Did your server support batch request?");
|
|
105
|
+
batchResponse.json.forEach((payload, index) => {
|
|
106
|
+
if (!payload) return;
|
|
107
|
+
const request = requestList[index];
|
|
108
|
+
if (request) {
|
|
109
|
+
const res = createSingleResponse(batchResponse, payload);
|
|
110
|
+
request.completeOk(res);
|
|
111
|
+
}
|
|
112
|
+
});
|
|
113
|
+
return batchResponse;
|
|
114
|
+
} catch (e) {
|
|
115
|
+
requestList.forEach((request) => request.completeErr(e));
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
return Promise.resolve();
|
|
119
|
+
}
|
|
120
|
+
function finalizeCanceled(requestList, error) {
|
|
121
|
+
requestList.forEach((request) => request.completeErr(error));
|
|
122
|
+
}
|
|
123
|
+
function finalizeUncompleted(requestList) {
|
|
124
|
+
requestList.forEach((request, index) => {
|
|
125
|
+
if (!request.done) request.completeErr(new RRNLBatchMiddlewareError(`Server does not return response for request at index ${index}.\nResponse should have an array with ${requestList.length} item(s).`));
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
function createSingleResponse(batchResponse, json) {
|
|
129
|
+
const data = json.payload || json;
|
|
130
|
+
const res = batchResponse.clone();
|
|
131
|
+
res.processJsonData(data);
|
|
132
|
+
return res;
|
|
133
|
+
}
|
|
134
|
+
//#endregion
|
|
135
|
+
export { RRNLBatchMiddlewareError, batchMiddleware as default };
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
const require_utils = require("../utils.cjs");
|
|
2
|
+
let relay_runtime = require("relay-runtime");
|
|
3
|
+
//#region src/middlewares/cache.ts
|
|
4
|
+
function cacheMiddleware(opts) {
|
|
5
|
+
const { size, ttl, onInit, allowMutations, allowFormData, clearOnMutation, cacheErrors, updateTTLOnGet } = opts || {};
|
|
6
|
+
const cache = new relay_runtime.QueryResponseCache({
|
|
7
|
+
size: size || 100,
|
|
8
|
+
ttl: ttl || 900 * 1e3
|
|
9
|
+
});
|
|
10
|
+
if (require_utils.isFunction(onInit)) onInit(cache);
|
|
11
|
+
return (next) => async (req) => {
|
|
12
|
+
if (req.isMutation()) {
|
|
13
|
+
if (clearOnMutation) cache.clear();
|
|
14
|
+
if (!allowMutations) return next(req);
|
|
15
|
+
}
|
|
16
|
+
if (req.isFormData() && !allowFormData) return next(req);
|
|
17
|
+
const cacheConfig = req.cacheConfig;
|
|
18
|
+
if (cacheConfig && cacheConfig.force) {
|
|
19
|
+
const queryId = req.getID();
|
|
20
|
+
const variables = req.getVariables();
|
|
21
|
+
const res = await next(req);
|
|
22
|
+
if (!res.errors || res.errors && cacheErrors) cache.set(queryId, variables, res);
|
|
23
|
+
return res;
|
|
24
|
+
}
|
|
25
|
+
try {
|
|
26
|
+
const queryId = req.getID();
|
|
27
|
+
const variables = req.getVariables();
|
|
28
|
+
const cachedRes = cache.get(queryId, variables);
|
|
29
|
+
if (cachedRes) {
|
|
30
|
+
if (updateTTLOnGet) cache.set(queryId, variables, cachedRes);
|
|
31
|
+
return cachedRes;
|
|
32
|
+
}
|
|
33
|
+
const res = await next(req);
|
|
34
|
+
if (!res.errors || res.errors && cacheErrors) cache.set(queryId, variables, res);
|
|
35
|
+
return res;
|
|
36
|
+
} catch (e) {
|
|
37
|
+
console.log(e);
|
|
38
|
+
}
|
|
39
|
+
return next(req);
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
//#endregion
|
|
43
|
+
exports.default = cacheMiddleware;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { Middleware } from "../definition.cjs";
|
|
2
|
+
import { QueryResponseCache } from "relay-runtime";
|
|
3
|
+
|
|
4
|
+
//#region src/middlewares/cache.d.ts
|
|
5
|
+
interface CacheMiddlewareOpts {
|
|
6
|
+
size?: number;
|
|
7
|
+
ttl?: number;
|
|
8
|
+
onInit?: (cache: QueryResponseCache) => any;
|
|
9
|
+
allowMutations?: boolean;
|
|
10
|
+
allowFormData?: boolean;
|
|
11
|
+
clearOnMutation?: boolean;
|
|
12
|
+
cacheErrors?: boolean;
|
|
13
|
+
updateTTLOnGet?: boolean;
|
|
14
|
+
}
|
|
15
|
+
declare function cacheMiddleware(opts?: CacheMiddlewareOpts): Middleware;
|
|
16
|
+
//#endregion
|
|
17
|
+
export { CacheMiddlewareOpts, cacheMiddleware };
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { Middleware } from "../definition.js";
|
|
2
|
+
import { QueryResponseCache } from "relay-runtime";
|
|
3
|
+
|
|
4
|
+
//#region src/middlewares/cache.d.ts
|
|
5
|
+
interface CacheMiddlewareOpts {
|
|
6
|
+
size?: number;
|
|
7
|
+
ttl?: number;
|
|
8
|
+
onInit?: (cache: QueryResponseCache) => any;
|
|
9
|
+
allowMutations?: boolean;
|
|
10
|
+
allowFormData?: boolean;
|
|
11
|
+
clearOnMutation?: boolean;
|
|
12
|
+
cacheErrors?: boolean;
|
|
13
|
+
updateTTLOnGet?: boolean;
|
|
14
|
+
}
|
|
15
|
+
declare function cacheMiddleware(opts?: CacheMiddlewareOpts): Middleware;
|
|
16
|
+
//#endregion
|
|
17
|
+
export { CacheMiddlewareOpts, cacheMiddleware };
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { isFunction } from "../utils.js";
|
|
2
|
+
import { QueryResponseCache } from "relay-runtime";
|
|
3
|
+
//#region src/middlewares/cache.ts
|
|
4
|
+
function cacheMiddleware(opts) {
|
|
5
|
+
const { size, ttl, onInit, allowMutations, allowFormData, clearOnMutation, cacheErrors, updateTTLOnGet } = opts || {};
|
|
6
|
+
const cache = new QueryResponseCache({
|
|
7
|
+
size: size || 100,
|
|
8
|
+
ttl: ttl || 900 * 1e3
|
|
9
|
+
});
|
|
10
|
+
if (isFunction(onInit)) onInit(cache);
|
|
11
|
+
return (next) => async (req) => {
|
|
12
|
+
if (req.isMutation()) {
|
|
13
|
+
if (clearOnMutation) cache.clear();
|
|
14
|
+
if (!allowMutations) return next(req);
|
|
15
|
+
}
|
|
16
|
+
if (req.isFormData() && !allowFormData) return next(req);
|
|
17
|
+
const cacheConfig = req.cacheConfig;
|
|
18
|
+
if (cacheConfig && cacheConfig.force) {
|
|
19
|
+
const queryId = req.getID();
|
|
20
|
+
const variables = req.getVariables();
|
|
21
|
+
const res = await next(req);
|
|
22
|
+
if (!res.errors || res.errors && cacheErrors) cache.set(queryId, variables, res);
|
|
23
|
+
return res;
|
|
24
|
+
}
|
|
25
|
+
try {
|
|
26
|
+
const queryId = req.getID();
|
|
27
|
+
const variables = req.getVariables();
|
|
28
|
+
const cachedRes = cache.get(queryId, variables);
|
|
29
|
+
if (cachedRes) {
|
|
30
|
+
if (updateTTLOnGet) cache.set(queryId, variables, cachedRes);
|
|
31
|
+
return cachedRes;
|
|
32
|
+
}
|
|
33
|
+
const res = await next(req);
|
|
34
|
+
if (!res.errors || res.errors && cacheErrors) cache.set(queryId, variables, res);
|
|
35
|
+
return res;
|
|
36
|
+
} catch (e) {
|
|
37
|
+
console.log(e);
|
|
38
|
+
}
|
|
39
|
+
return next(req);
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
//#endregion
|
|
43
|
+
export { cacheMiddleware as default };
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
const require_RelayRequest = require("../RelayRequest.cjs");
|
|
2
|
+
const require_RelayRequestBatch = require("../RelayRequestBatch.cjs");
|
|
3
|
+
//#region src/middlewares/error.ts
|
|
4
|
+
function errorMiddleware(options) {
|
|
5
|
+
const opts = options || {};
|
|
6
|
+
const logger = opts.logger || console.error.bind(console);
|
|
7
|
+
const prefix = opts.prefix || "[RELAY-NETWORK] GRAPHQL SERVER ERROR:\n\n";
|
|
8
|
+
const disableServerMiddlewareTip = opts.disableServerMiddlewareTip || false;
|
|
9
|
+
function displayErrors(errors, reqRes) {
|
|
10
|
+
return errors.forEach((error) => {
|
|
11
|
+
const { message, stack, ...rest } = error;
|
|
12
|
+
let msg = `${prefix}`;
|
|
13
|
+
const fmt = [];
|
|
14
|
+
if (stack && Array.isArray(stack)) {
|
|
15
|
+
msg = `${msg}%c${stack.shift()}\n%c${stack.join("\n")}`;
|
|
16
|
+
fmt.push("font-weight: bold;", "font-weight: normal;");
|
|
17
|
+
} else {
|
|
18
|
+
msg = `${msg}%c${message} %c`;
|
|
19
|
+
fmt.push("font-weight: bold;", "font-weight: normal;");
|
|
20
|
+
}
|
|
21
|
+
if (rest && Object.keys(rest).length) {
|
|
22
|
+
msg = `${msg}\n %O`;
|
|
23
|
+
fmt.push(rest);
|
|
24
|
+
}
|
|
25
|
+
msg = `${msg}\n\n%cRequest Response data:\n %c%O`;
|
|
26
|
+
fmt.push("font-weight: bold;", "font-weight: normal;", reqRes);
|
|
27
|
+
if (!stack && !disableServerMiddlewareTip) {
|
|
28
|
+
msg = `${msg}\n\n%cNotice:%c${noticeAbsentStack()}`;
|
|
29
|
+
fmt.push("font-weight: bold;", "font-weight: normal;");
|
|
30
|
+
}
|
|
31
|
+
logger(`${msg}\n\n`, ...fmt);
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
return (next) => (req) => {
|
|
35
|
+
return next(req).then((res) => {
|
|
36
|
+
if (req instanceof require_RelayRequest.default) {
|
|
37
|
+
if (Array.isArray(res.errors)) displayErrors(res.errors, {
|
|
38
|
+
req,
|
|
39
|
+
res
|
|
40
|
+
});
|
|
41
|
+
} else if (req instanceof require_RelayRequestBatch.default) {
|
|
42
|
+
if (Array.isArray(res.json)) res.json.forEach((payload) => {
|
|
43
|
+
if (Array.isArray(payload.errors)) displayErrors(payload.errors, {
|
|
44
|
+
req,
|
|
45
|
+
res
|
|
46
|
+
});
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
return res;
|
|
50
|
+
});
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
function noticeAbsentStack() {
|
|
54
|
+
return `
|
|
55
|
+
If you using 'express-graphql', you may get server stack-trace for error.
|
|
56
|
+
Just tune 'formatError' to return 'stack' with stack-trace:
|
|
57
|
+
|
|
58
|
+
import graphqlHTTP from 'express-graphql';
|
|
59
|
+
|
|
60
|
+
const graphQLMiddleware = graphqlHTTP({
|
|
61
|
+
schema: myGraphQLSchema,
|
|
62
|
+
formatError: (error) => ({
|
|
63
|
+
message: error.message,
|
|
64
|
+
stack: process.env.NODE_ENV === 'development' ? error.stack.split('\\n') : null,
|
|
65
|
+
})
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
app.use('/graphql', graphQLMiddleware);`;
|
|
69
|
+
}
|
|
70
|
+
//#endregion
|
|
71
|
+
exports.default = errorMiddleware;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { Middleware } from "../definition.cjs";
|
|
2
|
+
|
|
3
|
+
//#region src/middlewares/error.d.ts
|
|
4
|
+
interface GqlErrorMiddlewareOpts {
|
|
5
|
+
logger?: Function;
|
|
6
|
+
prefix?: string;
|
|
7
|
+
disableServerMiddlewareTip?: boolean;
|
|
8
|
+
}
|
|
9
|
+
declare function errorMiddleware(options?: GqlErrorMiddlewareOpts): Middleware;
|
|
10
|
+
//#endregion
|
|
11
|
+
export { GqlErrorMiddlewareOpts, errorMiddleware };
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { Middleware } from "../definition.js";
|
|
2
|
+
|
|
3
|
+
//#region src/middlewares/error.d.ts
|
|
4
|
+
interface GqlErrorMiddlewareOpts {
|
|
5
|
+
logger?: Function;
|
|
6
|
+
prefix?: string;
|
|
7
|
+
disableServerMiddlewareTip?: boolean;
|
|
8
|
+
}
|
|
9
|
+
declare function errorMiddleware(options?: GqlErrorMiddlewareOpts): Middleware;
|
|
10
|
+
//#endregion
|
|
11
|
+
export { GqlErrorMiddlewareOpts, errorMiddleware };
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import RelayRequest from "../RelayRequest.js";
|
|
2
|
+
import RelayRequestBatch from "../RelayRequestBatch.js";
|
|
3
|
+
//#region src/middlewares/error.ts
|
|
4
|
+
function errorMiddleware(options) {
|
|
5
|
+
const opts = options || {};
|
|
6
|
+
const logger = opts.logger || console.error.bind(console);
|
|
7
|
+
const prefix = opts.prefix || "[RELAY-NETWORK] GRAPHQL SERVER ERROR:\n\n";
|
|
8
|
+
const disableServerMiddlewareTip = opts.disableServerMiddlewareTip || false;
|
|
9
|
+
function displayErrors(errors, reqRes) {
|
|
10
|
+
return errors.forEach((error) => {
|
|
11
|
+
const { message, stack, ...rest } = error;
|
|
12
|
+
let msg = `${prefix}`;
|
|
13
|
+
const fmt = [];
|
|
14
|
+
if (stack && Array.isArray(stack)) {
|
|
15
|
+
msg = `${msg}%c${stack.shift()}\n%c${stack.join("\n")}`;
|
|
16
|
+
fmt.push("font-weight: bold;", "font-weight: normal;");
|
|
17
|
+
} else {
|
|
18
|
+
msg = `${msg}%c${message} %c`;
|
|
19
|
+
fmt.push("font-weight: bold;", "font-weight: normal;");
|
|
20
|
+
}
|
|
21
|
+
if (rest && Object.keys(rest).length) {
|
|
22
|
+
msg = `${msg}\n %O`;
|
|
23
|
+
fmt.push(rest);
|
|
24
|
+
}
|
|
25
|
+
msg = `${msg}\n\n%cRequest Response data:\n %c%O`;
|
|
26
|
+
fmt.push("font-weight: bold;", "font-weight: normal;", reqRes);
|
|
27
|
+
if (!stack && !disableServerMiddlewareTip) {
|
|
28
|
+
msg = `${msg}\n\n%cNotice:%c${noticeAbsentStack()}`;
|
|
29
|
+
fmt.push("font-weight: bold;", "font-weight: normal;");
|
|
30
|
+
}
|
|
31
|
+
logger(`${msg}\n\n`, ...fmt);
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
return (next) => (req) => {
|
|
35
|
+
return next(req).then((res) => {
|
|
36
|
+
if (req instanceof RelayRequest) {
|
|
37
|
+
if (Array.isArray(res.errors)) displayErrors(res.errors, {
|
|
38
|
+
req,
|
|
39
|
+
res
|
|
40
|
+
});
|
|
41
|
+
} else if (req instanceof RelayRequestBatch) {
|
|
42
|
+
if (Array.isArray(res.json)) res.json.forEach((payload) => {
|
|
43
|
+
if (Array.isArray(payload.errors)) displayErrors(payload.errors, {
|
|
44
|
+
req,
|
|
45
|
+
res
|
|
46
|
+
});
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
return res;
|
|
50
|
+
});
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
function noticeAbsentStack() {
|
|
54
|
+
return `
|
|
55
|
+
If you using 'express-graphql', you may get server stack-trace for error.
|
|
56
|
+
Just tune 'formatError' to return 'stack' with stack-trace:
|
|
57
|
+
|
|
58
|
+
import graphqlHTTP from 'express-graphql';
|
|
59
|
+
|
|
60
|
+
const graphQLMiddleware = graphqlHTTP({
|
|
61
|
+
schema: myGraphQLSchema,
|
|
62
|
+
formatError: (error) => ({
|
|
63
|
+
message: error.message,
|
|
64
|
+
stack: process.env.NODE_ENV === 'development' ? error.stack.split('\\n') : null,
|
|
65
|
+
})
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
app.use('/graphql', graphQLMiddleware);`;
|
|
69
|
+
}
|
|
70
|
+
//#endregion
|
|
71
|
+
export { errorMiddleware as default };
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
const require_RelayRequest = require("../RelayRequest.cjs");
|
|
2
|
+
const require_RelayRequestBatch = require("../RelayRequestBatch.cjs");
|
|
3
|
+
//#region src/middlewares/logger.ts
|
|
4
|
+
function loggerMiddleware(opts) {
|
|
5
|
+
const logger = opts && opts.logger || console.log.bind(console, "[RELAY-NETWORK]");
|
|
6
|
+
return (next) => (req) => {
|
|
7
|
+
const start = (/* @__PURE__ */ new Date()).getTime();
|
|
8
|
+
logger(`Run ${req.getID()}`, req);
|
|
9
|
+
return next(req).then((res) => {
|
|
10
|
+
const end = (/* @__PURE__ */ new Date()).getTime();
|
|
11
|
+
let queryId;
|
|
12
|
+
let queryData;
|
|
13
|
+
if (req instanceof require_RelayRequest.default) {
|
|
14
|
+
queryId = req.getID();
|
|
15
|
+
queryData = {
|
|
16
|
+
query: req.getQueryString(),
|
|
17
|
+
variables: req.getVariables()
|
|
18
|
+
};
|
|
19
|
+
} else if (req instanceof require_RelayRequestBatch.default) {
|
|
20
|
+
queryId = req.getID();
|
|
21
|
+
queryData = {
|
|
22
|
+
requestList: req.requests,
|
|
23
|
+
responseList: res.json
|
|
24
|
+
};
|
|
25
|
+
} else {
|
|
26
|
+
queryId = "CustomRequest";
|
|
27
|
+
queryData = {};
|
|
28
|
+
}
|
|
29
|
+
logger(`Done ${queryId} in ${end - start}ms`, {
|
|
30
|
+
...queryData,
|
|
31
|
+
req,
|
|
32
|
+
res
|
|
33
|
+
});
|
|
34
|
+
if (res.status !== 200) logger(`Status ${res.status}: ${res.statusText || ""} for ${queryId}`);
|
|
35
|
+
return res;
|
|
36
|
+
}, (error) => {
|
|
37
|
+
if (error && error.name && error.name === "AbortError") logger(`Cancelled ${req.getID()}`);
|
|
38
|
+
throw error;
|
|
39
|
+
});
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
//#endregion
|
|
43
|
+
exports.default = loggerMiddleware;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { Middleware } from "../definition.cjs";
|
|
2
|
+
|
|
3
|
+
//#region src/middlewares/logger.d.ts
|
|
4
|
+
interface LoggerMiddlewareOpts {
|
|
5
|
+
logger?: Function;
|
|
6
|
+
}
|
|
7
|
+
declare function loggerMiddleware(opts?: LoggerMiddlewareOpts): Middleware;
|
|
8
|
+
//#endregion
|
|
9
|
+
export { LoggerMiddlewareOpts, loggerMiddleware };
|