apollo-link-timeout 5.0.3 → 5.1.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/README.md +64 -3
- package/lib/cjs/TimeoutError.js +6 -25
- package/lib/cjs/TimeoutError.js.map +1 -1
- package/lib/cjs/cjs.js +1 -1
- package/lib/cjs/cjs.js.map +1 -1
- package/lib/cjs/timeoutLink.js +32 -62
- package/lib/cjs/timeoutLink.js.map +1 -1
- package/lib/esm/TimeoutError.js +6 -26
- package/lib/esm/TimeoutError.js.map +1 -1
- package/lib/esm/timeoutLink.js +30 -61
- package/lib/esm/timeoutLink.js.map +1 -1
- package/lib/types/timeoutLink.d.ts +3 -2
- package/package.json +1 -1
- package/src/timeoutLink.ts +8 -4
package/README.md
CHANGED
|
@@ -3,15 +3,19 @@
|
|
|
3
3
|
An [Apollo Link](https://www.apollographql.com/docs/link/) that aborts requests that aren't completed within a specified timeout period. Note that timeouts are enforced for query and mutation operations only (not subscriptions).
|
|
4
4
|
|
|
5
5
|
## Installation
|
|
6
|
-
|
|
6
|
+
|
|
7
|
+
```bash
|
|
7
8
|
npm install apollo-link-timeout
|
|
8
9
|
```
|
|
10
|
+
|
|
9
11
|
or
|
|
10
|
-
|
|
12
|
+
|
|
13
|
+
```bash
|
|
11
14
|
yarn add apollo-link-timeout
|
|
12
15
|
```
|
|
13
16
|
|
|
14
17
|
## Usage
|
|
18
|
+
|
|
15
19
|
```javascript
|
|
16
20
|
import ApolloLinkTimeout from 'apollo-link-timeout';
|
|
17
21
|
import { createHttpLink } from 'apollo-link-http';
|
|
@@ -29,7 +33,7 @@ const apolloClient = new ApolloClient({ link: timeoutHttpLink });
|
|
|
29
33
|
|
|
30
34
|
// use timeout-enabled Apollo client...
|
|
31
35
|
|
|
32
|
-
// Override timeout from any query
|
|
36
|
+
// Override timeout from any query
|
|
33
37
|
<Query
|
|
34
38
|
query={SOME_QUERY}
|
|
35
39
|
variables={{
|
|
@@ -41,4 +45,61 @@ const apolloClient = new ApolloClient({ link: timeoutHttpLink });
|
|
|
41
45
|
// ...
|
|
42
46
|
```
|
|
43
47
|
|
|
48
|
+
## API
|
|
49
|
+
|
|
50
|
+
**`new ApolloLinkTimeout(timeout?, statusCode?)`**
|
|
51
|
+
|
|
52
|
+
Creates a new TimeoutLink instance that aborts requests if the timeout expires before the response is received.
|
|
53
|
+
|
|
54
|
+
**Parameters:**
|
|
55
|
+
|
|
56
|
+
- `timeout` (optional): The timeout in milliseconds for the request. Defaults to 15000ms (15 seconds) if omitted.
|
|
57
|
+
- `statusCode` (optional): The HTTP status code to return when a timeout occurs. Defaults to 408 (Request Timeout) if omitted.
|
|
58
|
+
|
|
59
|
+
## Overriding Timeout Per Operation
|
|
60
|
+
|
|
61
|
+
You can override the default timeout for individual operations by setting a `timeout` value in the operation context:
|
|
62
|
+
|
|
63
|
+
```javascript
|
|
64
|
+
// Override timeout in a query
|
|
65
|
+
<Query
|
|
66
|
+
query={SOME_QUERY}
|
|
67
|
+
variables={{
|
|
68
|
+
someVar1: "foo",
|
|
69
|
+
someVar2: "bar",
|
|
70
|
+
}}
|
|
71
|
+
context={{ timeout: 3000 }} // 3 second timeout for this query
|
|
72
|
+
>
|
|
73
|
+
// ...
|
|
74
|
+
</Query>
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
// Or when calling the client directly
|
|
78
|
+
apolloClient.query({
|
|
79
|
+
query: SOME_QUERY,
|
|
80
|
+
context: { timeout: 5000 } // 5 second timeout
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
// Or via a prior link
|
|
84
|
+
const link = new ApolloLink((operation, forward) => {
|
|
85
|
+
operation.setContext({ timeout: 5000 });
|
|
86
|
+
});
|
|
87
|
+
link.concat(timeoutLink);
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
The timeout resolution follows this priority: operation-level context timeout > link-level timeout > default (15000ms).
|
|
91
|
+
|
|
92
|
+
## Disabling Timeout
|
|
93
|
+
|
|
94
|
+
To disable the timeout for a specific operation, set the timeout to a negative value in the operation context:
|
|
95
|
+
|
|
96
|
+
```javascript
|
|
97
|
+
apolloClient.query({
|
|
98
|
+
query: SOME_QUERY,
|
|
99
|
+
context: { timeout: -1 } // Disable timeout for this query
|
|
100
|
+
});
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
When a negative timeout is provided, the timeout link will be skipped and the operation will proceed without any timeout enforcement.
|
|
104
|
+
|
|
44
105
|
See [Apollo documentation](https://www.apollographql.com/client) for information on using the Apollo client.
|
package/lib/cjs/TimeoutError.js
CHANGED
|
@@ -1,30 +1,11 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __extends = (this && this.__extends) || (function () {
|
|
3
|
-
var extendStatics = function (d, b) {
|
|
4
|
-
extendStatics = Object.setPrototypeOf ||
|
|
5
|
-
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
|
|
6
|
-
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
|
|
7
|
-
return extendStatics(d, b);
|
|
8
|
-
};
|
|
9
|
-
return function (d, b) {
|
|
10
|
-
if (typeof b !== "function" && b !== null)
|
|
11
|
-
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
|
|
12
|
-
extendStatics(d, b);
|
|
13
|
-
function __() { this.constructor = d; }
|
|
14
|
-
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
|
|
15
|
-
};
|
|
16
|
-
})();
|
|
17
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
_this.timeout = timeout;
|
|
24
|
-
_this.statusCode = statusCode;
|
|
25
|
-
return _this;
|
|
3
|
+
class TimeoutError extends Error {
|
|
4
|
+
constructor(message, timeout, statusCode = 408) {
|
|
5
|
+
super(message);
|
|
6
|
+
this.timeout = timeout;
|
|
7
|
+
this.statusCode = statusCode;
|
|
26
8
|
}
|
|
27
|
-
|
|
28
|
-
}(Error));
|
|
9
|
+
}
|
|
29
10
|
exports.default = TimeoutError;
|
|
30
11
|
//# sourceMappingURL=TimeoutError.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TimeoutError.js","sourceRoot":"","sources":["../../src/TimeoutError.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"TimeoutError.js","sourceRoot":"","sources":["../../src/TimeoutError.ts"],"names":[],"mappings":";;AAAA,MAAqB,YAAa,SAAQ,KAAK;IAI7C,YAAY,OAAe,EAAE,OAAe,EAAE,aAAqB,GAAG;QACpE,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;QACvB,IAAI,CAAC,UAAU,GAAG,UAAU,CAAC;IAC/B,CAAC;CACF;AATD,+BASC"}
|
package/lib/cjs/cjs.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
|
|
3
|
+
const timeoutLink_js_1 = require("./timeoutLink.js");
|
|
4
4
|
module.exports = timeoutLink_js_1.default;
|
|
5
5
|
module.exports.default = timeoutLink_js_1.default;
|
|
6
6
|
//# sourceMappingURL=cjs.js.map
|
package/lib/cjs/cjs.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cjs.js","sourceRoot":"","sources":["../../src/cjs.ts"],"names":[],"mappings":";;AAAA,
|
|
1
|
+
{"version":3,"file":"cjs.js","sourceRoot":"","sources":["../../src/cjs.ts"],"names":[],"mappings":";;AAAA,qDAA2C;AAE3C,MAAM,CAAC,OAAO,GAAG,wBAAW,CAAC;AAC7B,MAAM,CAAC,OAAO,CAAC,OAAO,GAAG,wBAAW,CAAC"}
|
package/lib/cjs/timeoutLink.js
CHANGED
|
@@ -1,40 +1,13 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __extends = (this && this.__extends) || (function () {
|
|
3
|
-
var extendStatics = function (d, b) {
|
|
4
|
-
extendStatics = Object.setPrototypeOf ||
|
|
5
|
-
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
|
|
6
|
-
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
|
|
7
|
-
return extendStatics(d, b);
|
|
8
|
-
};
|
|
9
|
-
return function (d, b) {
|
|
10
|
-
if (typeof b !== "function" && b !== null)
|
|
11
|
-
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
|
|
12
|
-
extendStatics(d, b);
|
|
13
|
-
function __() { this.constructor = d; }
|
|
14
|
-
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
|
|
15
|
-
};
|
|
16
|
-
})();
|
|
17
|
-
var __assign = (this && this.__assign) || function () {
|
|
18
|
-
__assign = Object.assign || function(t) {
|
|
19
|
-
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
|
20
|
-
s = arguments[i];
|
|
21
|
-
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
|
|
22
|
-
t[p] = s[p];
|
|
23
|
-
}
|
|
24
|
-
return t;
|
|
25
|
-
};
|
|
26
|
-
return __assign.apply(this, arguments);
|
|
27
|
-
};
|
|
28
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
29
3
|
// note, this import is modified when building for ESM via `script/fix_apollo_import.mjs`
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
4
|
+
const core_1 = require("@apollo/client/core");
|
|
5
|
+
const TimeoutError_js_1 = require("./TimeoutError.js");
|
|
6
|
+
const DEFAULT_TIMEOUT = 15000;
|
|
33
7
|
/**
|
|
34
8
|
* Aborts the request if the timeout expires before the response is received.
|
|
35
9
|
*/
|
|
36
|
-
|
|
37
|
-
__extends(TimeoutLink, _super);
|
|
10
|
+
class TimeoutLink extends core_1.ApolloLink {
|
|
38
11
|
/**
|
|
39
12
|
* Creates a new TimeoutLink instance.
|
|
40
13
|
* Aborts the request if the timeout expires before the response is received.
|
|
@@ -42,48 +15,46 @@ var TimeoutLink = /** @class */ (function (_super) {
|
|
|
42
15
|
* @param timeout - The timeout in milliseconds for the request. Default is 15000ms (15 seconds).
|
|
43
16
|
* @param statusCode - The HTTP status code to return when a timeout occurs. Default is 408 (Request Timeout).
|
|
44
17
|
*/
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
return _this;
|
|
18
|
+
constructor(timeout, statusCode) {
|
|
19
|
+
super();
|
|
20
|
+
this.timeout = timeout || DEFAULT_TIMEOUT;
|
|
21
|
+
this.statusCode = statusCode;
|
|
50
22
|
}
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
var ourController;
|
|
23
|
+
request(operation, forward) {
|
|
24
|
+
let controller;
|
|
25
|
+
let ourController;
|
|
55
26
|
// override timeout from query context
|
|
56
|
-
|
|
57
|
-
|
|
27
|
+
const requestTimeout = operation.getContext().timeout || this.timeout;
|
|
28
|
+
const operationType = operation.query.definitions.find((def) => def.kind === 'OperationDefinition').operation;
|
|
58
29
|
if (requestTimeout <= 0 || operationType === 'subscription') {
|
|
59
30
|
return forward(operation); // skip this link if timeout is zero or it's a subscription request
|
|
60
31
|
}
|
|
61
32
|
// add abort controller and signal object to fetchOptions if they don't already exist
|
|
62
33
|
if (typeof AbortController !== 'undefined') {
|
|
63
|
-
|
|
64
|
-
|
|
34
|
+
const context = operation.getContext();
|
|
35
|
+
let fetchOptions = context.fetchOptions || {};
|
|
65
36
|
ourController = new AbortController();
|
|
66
37
|
controller = fetchOptions.controller || ourController;
|
|
67
|
-
fetchOptions =
|
|
68
|
-
operation.setContext({ fetchOptions
|
|
38
|
+
fetchOptions = Object.assign(Object.assign({}, fetchOptions), { controller, signal: controller.signal });
|
|
39
|
+
operation.setContext({ fetchOptions });
|
|
69
40
|
}
|
|
70
|
-
|
|
41
|
+
const chainObservable = forward(operation); // observable for remaining link chain
|
|
71
42
|
// create local observable with timeout functionality (unsubscibe from chain observable and
|
|
72
43
|
// return an error if the timeout expires before chain observable resolves)
|
|
73
|
-
|
|
74
|
-
|
|
44
|
+
const localObservable = new core_1.Observable((observer) => {
|
|
45
|
+
let timer;
|
|
75
46
|
// listen to chainObservable for result and pass to localObservable if received before timeout
|
|
76
|
-
|
|
47
|
+
const subscription = chainObservable.subscribe((result) => {
|
|
77
48
|
clearTimeout(timer);
|
|
78
49
|
observer.next(result);
|
|
79
50
|
observer.complete();
|
|
80
|
-
},
|
|
51
|
+
}, (error) => {
|
|
81
52
|
clearTimeout(timer);
|
|
82
53
|
observer.error(error);
|
|
83
54
|
observer.complete();
|
|
84
55
|
});
|
|
85
56
|
// if timeout expires before observable completes, abort call, unsubscribe, and return error
|
|
86
|
-
timer = setTimeout(
|
|
57
|
+
timer = setTimeout(() => {
|
|
87
58
|
if (controller) {
|
|
88
59
|
if (controller.signal.aborted) {
|
|
89
60
|
// already aborted from somewhere else
|
|
@@ -93,33 +64,32 @@ var TimeoutLink = /** @class */ (function (_super) {
|
|
|
93
64
|
// if the AbortController in the operation context is one we created,
|
|
94
65
|
// it's now "used up", so we need to remove it to avoid blocking any
|
|
95
66
|
// future retry of the operation.
|
|
96
|
-
|
|
97
|
-
|
|
67
|
+
const context = operation.getContext();
|
|
68
|
+
const fetchOptions = context.fetchOptions || {};
|
|
98
69
|
if (fetchOptions.controller === ourController && fetchOptions.signal === ourController.signal) {
|
|
99
|
-
operation.setContext(
|
|
70
|
+
operation.setContext(Object.assign(Object.assign({}, fetchOptions), { controller: undefined, signal: undefined }));
|
|
100
71
|
}
|
|
101
72
|
}
|
|
102
|
-
observer.error(new TimeoutError_js_1.default('Timeout exceeded', requestTimeout,
|
|
73
|
+
observer.error(new TimeoutError_js_1.default('Timeout exceeded', requestTimeout, this.statusCode));
|
|
103
74
|
subscription.unsubscribe();
|
|
104
75
|
}, requestTimeout);
|
|
105
|
-
|
|
76
|
+
const cancelTimeout = () => {
|
|
106
77
|
clearTimeout(timer);
|
|
107
78
|
subscription.unsubscribe();
|
|
108
79
|
};
|
|
109
|
-
|
|
80
|
+
const ctxRef = operation.getContext().timeoutRef;
|
|
110
81
|
if (ctxRef) {
|
|
111
82
|
ctxRef({ unsubscribe: cancelTimeout });
|
|
112
83
|
}
|
|
113
84
|
// cancel timeout if aborted from somewhere else
|
|
114
|
-
controller.signal.addEventListener("abort",
|
|
85
|
+
controller.signal.addEventListener("abort", () => {
|
|
115
86
|
cancelTimeout();
|
|
116
87
|
}, { once: true });
|
|
117
88
|
// this function is called when a client unsubscribes from localObservable
|
|
118
89
|
return cancelTimeout;
|
|
119
90
|
});
|
|
120
91
|
return localObservable;
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
}(core_1.ApolloLink));
|
|
92
|
+
}
|
|
93
|
+
}
|
|
124
94
|
exports.default = TimeoutLink;
|
|
125
95
|
//# sourceMappingURL=timeoutLink.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"timeoutLink.js","sourceRoot":"","sources":["../../src/timeoutLink.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"timeoutLink.js","sourceRoot":"","sources":["../../src/timeoutLink.ts"],"names":[],"mappings":"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"}
|
package/lib/esm/TimeoutError.js
CHANGED
|
@@ -1,28 +1,8 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
return extendStatics(d, b);
|
|
7
|
-
};
|
|
8
|
-
return function (d, b) {
|
|
9
|
-
if (typeof b !== "function" && b !== null)
|
|
10
|
-
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
|
|
11
|
-
extendStatics(d, b);
|
|
12
|
-
function __() { this.constructor = d; }
|
|
13
|
-
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
|
|
14
|
-
};
|
|
15
|
-
})();
|
|
16
|
-
var TimeoutError = /** @class */ (function (_super) {
|
|
17
|
-
__extends(TimeoutError, _super);
|
|
18
|
-
function TimeoutError(message, timeout, statusCode) {
|
|
19
|
-
if (statusCode === void 0) { statusCode = 408; }
|
|
20
|
-
var _this = _super.call(this, message) || this;
|
|
21
|
-
_this.timeout = timeout;
|
|
22
|
-
_this.statusCode = statusCode;
|
|
23
|
-
return _this;
|
|
1
|
+
export default class TimeoutError extends Error {
|
|
2
|
+
constructor(message, timeout, statusCode = 408) {
|
|
3
|
+
super(message);
|
|
4
|
+
this.timeout = timeout;
|
|
5
|
+
this.statusCode = statusCode;
|
|
24
6
|
}
|
|
25
|
-
|
|
26
|
-
}(Error));
|
|
27
|
-
export default TimeoutError;
|
|
7
|
+
}
|
|
28
8
|
//# sourceMappingURL=TimeoutError.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TimeoutError.js","sourceRoot":"","sources":["../../src/TimeoutError.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"TimeoutError.js","sourceRoot":"","sources":["../../src/TimeoutError.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,OAAO,OAAO,YAAa,SAAQ,KAAK;IAI7C,YAAY,OAAe,EAAE,OAAe,EAAE,aAAqB,GAAG;QACpE,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;QACvB,IAAI,CAAC,UAAU,GAAG,UAAU,CAAC;IAC/B,CAAC;CACF"}
|
package/lib/esm/timeoutLink.js
CHANGED
|
@@ -1,38 +1,11 @@
|
|
|
1
|
-
var __extends = (this && this.__extends) || (function () {
|
|
2
|
-
var extendStatics = function (d, b) {
|
|
3
|
-
extendStatics = Object.setPrototypeOf ||
|
|
4
|
-
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
|
|
5
|
-
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
|
|
6
|
-
return extendStatics(d, b);
|
|
7
|
-
};
|
|
8
|
-
return function (d, b) {
|
|
9
|
-
if (typeof b !== "function" && b !== null)
|
|
10
|
-
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
|
|
11
|
-
extendStatics(d, b);
|
|
12
|
-
function __() { this.constructor = d; }
|
|
13
|
-
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
|
|
14
|
-
};
|
|
15
|
-
})();
|
|
16
|
-
var __assign = (this && this.__assign) || function () {
|
|
17
|
-
__assign = Object.assign || function(t) {
|
|
18
|
-
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
|
19
|
-
s = arguments[i];
|
|
20
|
-
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
|
|
21
|
-
t[p] = s[p];
|
|
22
|
-
}
|
|
23
|
-
return t;
|
|
24
|
-
};
|
|
25
|
-
return __assign.apply(this, arguments);
|
|
26
|
-
};
|
|
27
1
|
// note, this import is modified when building for ESM via `script/fix_apollo_import.mjs`
|
|
28
2
|
import { ApolloLink, Observable } from '@apollo/client/core/index.js';
|
|
29
3
|
import TimeoutError from './TimeoutError.js';
|
|
30
|
-
|
|
4
|
+
const DEFAULT_TIMEOUT = 15000;
|
|
31
5
|
/**
|
|
32
6
|
* Aborts the request if the timeout expires before the response is received.
|
|
33
7
|
*/
|
|
34
|
-
|
|
35
|
-
__extends(TimeoutLink, _super);
|
|
8
|
+
export default class TimeoutLink extends ApolloLink {
|
|
36
9
|
/**
|
|
37
10
|
* Creates a new TimeoutLink instance.
|
|
38
11
|
* Aborts the request if the timeout expires before the response is received.
|
|
@@ -40,48 +13,46 @@ var TimeoutLink = /** @class */ (function (_super) {
|
|
|
40
13
|
* @param timeout - The timeout in milliseconds for the request. Default is 15000ms (15 seconds).
|
|
41
14
|
* @param statusCode - The HTTP status code to return when a timeout occurs. Default is 408 (Request Timeout).
|
|
42
15
|
*/
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
return _this;
|
|
16
|
+
constructor(timeout, statusCode) {
|
|
17
|
+
super();
|
|
18
|
+
this.timeout = timeout || DEFAULT_TIMEOUT;
|
|
19
|
+
this.statusCode = statusCode;
|
|
48
20
|
}
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
var ourController;
|
|
21
|
+
request(operation, forward) {
|
|
22
|
+
let controller;
|
|
23
|
+
let ourController;
|
|
53
24
|
// override timeout from query context
|
|
54
|
-
|
|
55
|
-
|
|
25
|
+
const requestTimeout = operation.getContext().timeout || this.timeout;
|
|
26
|
+
const operationType = operation.query.definitions.find((def) => def.kind === 'OperationDefinition').operation;
|
|
56
27
|
if (requestTimeout <= 0 || operationType === 'subscription') {
|
|
57
28
|
return forward(operation); // skip this link if timeout is zero or it's a subscription request
|
|
58
29
|
}
|
|
59
30
|
// add abort controller and signal object to fetchOptions if they don't already exist
|
|
60
31
|
if (typeof AbortController !== 'undefined') {
|
|
61
|
-
|
|
62
|
-
|
|
32
|
+
const context = operation.getContext();
|
|
33
|
+
let fetchOptions = context.fetchOptions || {};
|
|
63
34
|
ourController = new AbortController();
|
|
64
35
|
controller = fetchOptions.controller || ourController;
|
|
65
|
-
fetchOptions =
|
|
66
|
-
operation.setContext({ fetchOptions
|
|
36
|
+
fetchOptions = Object.assign(Object.assign({}, fetchOptions), { controller, signal: controller.signal });
|
|
37
|
+
operation.setContext({ fetchOptions });
|
|
67
38
|
}
|
|
68
|
-
|
|
39
|
+
const chainObservable = forward(operation); // observable for remaining link chain
|
|
69
40
|
// create local observable with timeout functionality (unsubscibe from chain observable and
|
|
70
41
|
// return an error if the timeout expires before chain observable resolves)
|
|
71
|
-
|
|
72
|
-
|
|
42
|
+
const localObservable = new Observable((observer) => {
|
|
43
|
+
let timer;
|
|
73
44
|
// listen to chainObservable for result and pass to localObservable if received before timeout
|
|
74
|
-
|
|
45
|
+
const subscription = chainObservable.subscribe((result) => {
|
|
75
46
|
clearTimeout(timer);
|
|
76
47
|
observer.next(result);
|
|
77
48
|
observer.complete();
|
|
78
|
-
},
|
|
49
|
+
}, (error) => {
|
|
79
50
|
clearTimeout(timer);
|
|
80
51
|
observer.error(error);
|
|
81
52
|
observer.complete();
|
|
82
53
|
});
|
|
83
54
|
// if timeout expires before observable completes, abort call, unsubscribe, and return error
|
|
84
|
-
timer = setTimeout(
|
|
55
|
+
timer = setTimeout(() => {
|
|
85
56
|
if (controller) {
|
|
86
57
|
if (controller.signal.aborted) {
|
|
87
58
|
// already aborted from somewhere else
|
|
@@ -91,33 +62,31 @@ var TimeoutLink = /** @class */ (function (_super) {
|
|
|
91
62
|
// if the AbortController in the operation context is one we created,
|
|
92
63
|
// it's now "used up", so we need to remove it to avoid blocking any
|
|
93
64
|
// future retry of the operation.
|
|
94
|
-
|
|
95
|
-
|
|
65
|
+
const context = operation.getContext();
|
|
66
|
+
const fetchOptions = context.fetchOptions || {};
|
|
96
67
|
if (fetchOptions.controller === ourController && fetchOptions.signal === ourController.signal) {
|
|
97
|
-
operation.setContext(
|
|
68
|
+
operation.setContext(Object.assign(Object.assign({}, fetchOptions), { controller: undefined, signal: undefined }));
|
|
98
69
|
}
|
|
99
70
|
}
|
|
100
|
-
observer.error(new TimeoutError('Timeout exceeded', requestTimeout,
|
|
71
|
+
observer.error(new TimeoutError('Timeout exceeded', requestTimeout, this.statusCode));
|
|
101
72
|
subscription.unsubscribe();
|
|
102
73
|
}, requestTimeout);
|
|
103
|
-
|
|
74
|
+
const cancelTimeout = () => {
|
|
104
75
|
clearTimeout(timer);
|
|
105
76
|
subscription.unsubscribe();
|
|
106
77
|
};
|
|
107
|
-
|
|
78
|
+
const ctxRef = operation.getContext().timeoutRef;
|
|
108
79
|
if (ctxRef) {
|
|
109
80
|
ctxRef({ unsubscribe: cancelTimeout });
|
|
110
81
|
}
|
|
111
82
|
// cancel timeout if aborted from somewhere else
|
|
112
|
-
controller.signal.addEventListener("abort",
|
|
83
|
+
controller.signal.addEventListener("abort", () => {
|
|
113
84
|
cancelTimeout();
|
|
114
85
|
}, { once: true });
|
|
115
86
|
// this function is called when a client unsubscribes from localObservable
|
|
116
87
|
return cancelTimeout;
|
|
117
88
|
});
|
|
118
89
|
return localObservable;
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
}(ApolloLink));
|
|
122
|
-
export default TimeoutLink;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
123
92
|
//# sourceMappingURL=timeoutLink.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"timeoutLink.js","sourceRoot":"","sources":["../../src/timeoutLink.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"timeoutLink.js","sourceRoot":"","sources":["../../src/timeoutLink.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
import { ApolloLink, Observable, type Operation, type FetchResult } from '@apollo/client/core';
|
|
2
|
+
type NextLink = (operation: Operation) => Observable<FetchResult>;
|
|
3
3
|
/**
|
|
4
4
|
* Aborts the request if the timeout expires before the response is received.
|
|
5
5
|
*/
|
|
@@ -16,3 +16,4 @@ export default class TimeoutLink extends ApolloLink {
|
|
|
16
16
|
constructor(timeout?: number, statusCode?: number);
|
|
17
17
|
request(operation: Operation, forward: NextLink): Observable<FetchResult>;
|
|
18
18
|
}
|
|
19
|
+
export {};
|
package/package.json
CHANGED
package/src/timeoutLink.ts
CHANGED
|
@@ -1,8 +1,12 @@
|
|
|
1
1
|
// note, this import is modified when building for ESM via `script/fix_apollo_import.mjs`
|
|
2
|
-
import { ApolloLink, Observable, type Operation, type
|
|
2
|
+
import { ApolloLink, Observable, type Operation, type FetchResult } from '@apollo/client/core';
|
|
3
3
|
import type { DefinitionNode } from 'graphql';
|
|
4
4
|
import TimeoutError from './TimeoutError.js';
|
|
5
5
|
|
|
6
|
+
// NextLink was removed from apollo-client in v4 and replaced by ApolloLink.ForwardFunction,
|
|
7
|
+
// but to maintain compatibility with both v3 and v4, we re-declare it here.
|
|
8
|
+
type NextLink = (operation: Operation) => Observable<FetchResult>;
|
|
9
|
+
|
|
6
10
|
const DEFAULT_TIMEOUT: number = 15000;
|
|
7
11
|
|
|
8
12
|
/**
|
|
@@ -56,17 +60,17 @@ export default class TimeoutLink extends ApolloLink {
|
|
|
56
60
|
|
|
57
61
|
// create local observable with timeout functionality (unsubscibe from chain observable and
|
|
58
62
|
// return an error if the timeout expires before chain observable resolves)
|
|
59
|
-
const localObservable = new Observable<FetchResult>(observer => {
|
|
63
|
+
const localObservable = new Observable<FetchResult>((observer) => {
|
|
60
64
|
let timer: any;
|
|
61
65
|
|
|
62
66
|
// listen to chainObservable for result and pass to localObservable if received before timeout
|
|
63
67
|
const subscription = chainObservable.subscribe(
|
|
64
|
-
result => {
|
|
68
|
+
(result) => {
|
|
65
69
|
clearTimeout(timer);
|
|
66
70
|
observer.next(result);
|
|
67
71
|
observer.complete();
|
|
68
72
|
},
|
|
69
|
-
error => {
|
|
73
|
+
(error) => {
|
|
70
74
|
clearTimeout(timer);
|
|
71
75
|
observer.error(error);
|
|
72
76
|
observer.complete();
|