@internetarchive/fetch-handler 1.1.0-webdev-7731.8 → 1.1.0-webdev-7731.9
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 +75 -5
- package/demo/app-root.ts +6 -6
- package/dist/demo/app-root.d.ts +1 -1
- package/dist/demo/app-root.js +4 -4
- package/dist/demo/app-root.js.map +1 -1
- package/dist/index.d.ts +6 -5
- package/dist/index.js +3 -3
- package/dist/index.js.map +1 -1
- package/dist/src/fetch-handler-interface.d.ts +18 -8
- package/dist/src/fetch-handler-interface.js.map +1 -1
- package/dist/src/fetch-handler.d.ts +26 -3
- package/dist/src/fetch-handler.js +29 -5
- package/dist/src/fetch-handler.js.map +1 -1
- package/dist/src/fetch-retry/configuration/configurations.d.ts +21 -0
- package/dist/src/fetch-retry/configuration/configurations.js +21 -0
- package/dist/src/fetch-retry/configuration/configurations.js.map +1 -1
- package/dist/src/fetch-retry/configuration/default-retry-configuration.d.ts +5 -1
- package/dist/src/fetch-retry/configuration/default-retry-configuration.js +4 -0
- package/dist/src/fetch-retry/configuration/default-retry-configuration.js.map +1 -1
- package/dist/src/fetch-retry/configuration/no-retry-configuration.d.ts +4 -1
- package/dist/src/fetch-retry/configuration/no-retry-configuration.js +4 -1
- package/dist/src/fetch-retry/configuration/no-retry-configuration.js.map +1 -1
- package/dist/src/fetch-retry/configuration/retry-configuring.d.ts +1 -1
- package/dist/src/fetch-retry/configuration/retry-configuring.js.map +1 -1
- package/dist/src/fetch-retry/fetch-retrier.d.ts +3 -3
- package/dist/src/fetch-retry/fetch-retrier.js +24 -18
- package/dist/src/fetch-retry/fetch-retrier.js.map +1 -1
- package/dist/test/fetch-handler.test.js +62 -12
- package/dist/test/fetch-handler.test.js.map +1 -1
- package/dist/test/fetch-retrier.test.js +7 -7
- package/dist/test/fetch-retrier.test.js.map +1 -1
- package/dist/test/legacy-args.test.js +3 -0
- package/dist/test/legacy-args.test.js.map +1 -1
- package/dist/test/mocks/mock-retry-config.d.ts +1 -1
- package/dist/test/mocks/mock-retry-config.js +1 -1
- package/dist/test/mocks/mock-retry-config.js.map +1 -1
- package/dist/test/no-retry-config.test.js +1 -1
- package/dist/test/no-retry-config.test.js.map +1 -1
- package/index.ts +9 -7
- package/package.json +1 -1
- package/src/fetch-handler-interface.ts +22 -8
- package/src/fetch-handler.ts +39 -6
- package/src/fetch-retry/configuration/configurations.ts +21 -0
- package/src/fetch-retry/configuration/default-retry-configuration.ts +8 -1
- package/src/fetch-retry/configuration/no-retry-configuration.ts +5 -2
- package/src/fetch-retry/configuration/retry-configuring.ts +4 -1
- package/src/fetch-retry/fetch-retrier.ts +29 -24
- package/test/fetch-handler.test.ts +70 -12
- package/test/fetch-retrier.test.ts +7 -7
- package/test/legacy-args.test.ts +3 -0
- package/test/mocks/mock-retry-config.ts +1 -5
- package/test/no-retry-config.test.ts +1 -1
- package/dist/test/retrier-legacy-args.test.d.ts +0 -1
- package/dist/test/retrier-legacy-args.test.js +0 -27
- package/dist/test/retrier-legacy-args.test.js.map +0 -1
- package/test/retrier-legacy-args.test.ts +0 -28
package/src/fetch-handler.ts
CHANGED
|
@@ -12,20 +12,32 @@ import type { RetryConfiguring } from './fetch-retry/configuration/retry-configu
|
|
|
12
12
|
* - add `reCache=1` to the request if it's in the current url so the backend sees it
|
|
13
13
|
* - add convenience method for fetching/decoding an API response by just the path
|
|
14
14
|
*/
|
|
15
|
-
export class
|
|
16
|
-
private
|
|
15
|
+
export class FetchHandler implements FetchHandlerInterface {
|
|
16
|
+
private apiBaseUrl: string = '';
|
|
17
17
|
|
|
18
18
|
private fetchRetrier: FetchRetrierInterface = new FetchRetrier();
|
|
19
19
|
|
|
20
20
|
private searchParams?: string;
|
|
21
21
|
|
|
22
|
+
/**
|
|
23
|
+
*
|
|
24
|
+
* @param options {
|
|
25
|
+
* iaApiBaseUrl - deprecated Use `apiBaseUrl` instead.
|
|
26
|
+
* apiBaseUrl - The base URL for API requests for `fetchApiPathResponse`
|
|
27
|
+
* fetchRetrier - FetchRetrier to use instead of the default
|
|
28
|
+
* searchParams - Search params to check for `reCache=1` (defaults to current window location)
|
|
29
|
+
*/
|
|
22
30
|
constructor(options?: {
|
|
23
31
|
iaApiBaseUrl?: string;
|
|
32
|
+
apiBaseUrl?: string;
|
|
24
33
|
fetchRetrier?: FetchRetrierInterface;
|
|
25
34
|
searchParams?: string;
|
|
26
|
-
defaultRetryConfiguration?: RetryConfiguring;
|
|
27
35
|
}) {
|
|
28
|
-
if (options?.
|
|
36
|
+
if (options?.apiBaseUrl) {
|
|
37
|
+
this.apiBaseUrl = options.apiBaseUrl;
|
|
38
|
+
} else if (options?.iaApiBaseUrl) {
|
|
39
|
+
this.apiBaseUrl = options.iaApiBaseUrl;
|
|
40
|
+
}
|
|
29
41
|
if (options?.fetchRetrier) this.fetchRetrier = options.fetchRetrier;
|
|
30
42
|
if (options?.searchParams) {
|
|
31
43
|
this.searchParams = options.searchParams;
|
|
@@ -35,7 +47,7 @@ export class IaFetchHandler implements FetchHandlerInterface {
|
|
|
35
47
|
}
|
|
36
48
|
|
|
37
49
|
/** @inheritdoc */
|
|
38
|
-
async
|
|
50
|
+
async fetchApiPathResponse<T>(
|
|
39
51
|
path: string,
|
|
40
52
|
options?: {
|
|
41
53
|
includeCredentials?: boolean;
|
|
@@ -45,10 +57,24 @@ export class IaFetchHandler implements FetchHandlerInterface {
|
|
|
45
57
|
retryConfig?: RetryConfiguring;
|
|
46
58
|
},
|
|
47
59
|
): Promise<T> {
|
|
48
|
-
const url = `${this.
|
|
60
|
+
const url = `${this.apiBaseUrl}${path}`;
|
|
49
61
|
return this.fetchApiResponse(url, options);
|
|
50
62
|
}
|
|
51
63
|
|
|
64
|
+
/** @inheritdoc */
|
|
65
|
+
async fetchIAApiResponse<T>(
|
|
66
|
+
path: string,
|
|
67
|
+
options?: {
|
|
68
|
+
includeCredentials?: boolean;
|
|
69
|
+
method?: string;
|
|
70
|
+
body?: BodyInit;
|
|
71
|
+
headers?: HeadersInit;
|
|
72
|
+
retryConfig?: RetryConfiguring;
|
|
73
|
+
},
|
|
74
|
+
): Promise<T> {
|
|
75
|
+
return this.fetchApiPathResponse(path, options);
|
|
76
|
+
}
|
|
77
|
+
|
|
52
78
|
/** @inheritdoc */
|
|
53
79
|
async fetchApiResponse<T>(
|
|
54
80
|
url: string,
|
|
@@ -104,3 +130,10 @@ export class IaFetchHandler implements FetchHandlerInterface {
|
|
|
104
130
|
return url.href;
|
|
105
131
|
}
|
|
106
132
|
}
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* Backwards compatibility class
|
|
136
|
+
*
|
|
137
|
+
* @deprecated Use `FetchHandler` instead.
|
|
138
|
+
*/
|
|
139
|
+
export class IaFetchHandler extends FetchHandler {}
|
|
@@ -2,10 +2,31 @@ import { DefaultRetryConfiguration } from './default-retry-configuration';
|
|
|
2
2
|
import { NoRetryConfiguration } from './no-retry-configuration';
|
|
3
3
|
import type { RetryConfiguring } from './retry-configuring';
|
|
4
4
|
|
|
5
|
+
/**
|
|
6
|
+
* This class provides easy access to common retry configurations.
|
|
7
|
+
*
|
|
8
|
+
* ie `FetchRetryConfig.default` or `FetchRetryConfig.noRetry` vs
|
|
9
|
+
* `new DefaultRetryConfiguration()` or `new NoRetryConfiguration()`
|
|
10
|
+
*/
|
|
5
11
|
export class FetchRetryConfig {
|
|
12
|
+
/**
|
|
13
|
+
* A retry configuration that retries twice for transient errors
|
|
14
|
+
* with exponential retry delay as well as `Retry-After` header support.
|
|
15
|
+
*
|
|
16
|
+
* @static
|
|
17
|
+
* @type {Readonly<RetryConfiguring>}
|
|
18
|
+
* @memberof FetchRetryConfig
|
|
19
|
+
*/
|
|
6
20
|
static readonly default: Readonly<RetryConfiguring> =
|
|
7
21
|
DefaultRetryConfiguration.shared;
|
|
8
22
|
|
|
23
|
+
/**
|
|
24
|
+
* A retry configuration that does not perform any retries.
|
|
25
|
+
*
|
|
26
|
+
* @static
|
|
27
|
+
* @type {Readonly<RetryConfiguring>}
|
|
28
|
+
* @memberof FetchRetryConfig
|
|
29
|
+
*/
|
|
9
30
|
static readonly noRetry: Readonly<RetryConfiguring> =
|
|
10
31
|
NoRetryConfiguration.shared;
|
|
11
32
|
}
|
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
import type { RetryConfiguring } from './retry-configuring';
|
|
2
2
|
import type { Milliseconds } from './milliseconds';
|
|
3
3
|
|
|
4
|
+
/**
|
|
5
|
+
* A retry configuration that retries twice for transient errors
|
|
6
|
+
* with exponential retry delay as well as `Retry-After` header support.
|
|
7
|
+
*/
|
|
4
8
|
export class DefaultRetryConfiguration implements RetryConfiguring {
|
|
5
9
|
static readonly shared: Readonly<RetryConfiguring> =
|
|
6
10
|
new DefaultRetryConfiguration();
|
|
@@ -36,7 +40,10 @@ export class DefaultRetryConfiguration implements RetryConfiguring {
|
|
|
36
40
|
return isTransient;
|
|
37
41
|
}
|
|
38
42
|
|
|
39
|
-
retryDelay(
|
|
43
|
+
retryDelay(
|
|
44
|
+
retryNumber: number,
|
|
45
|
+
response?: Response | null,
|
|
46
|
+
): Milliseconds | null {
|
|
40
47
|
// If we have a Retry-After header, use that
|
|
41
48
|
const retryAfter = response?.headers.get('Retry-After');
|
|
42
49
|
if (retryAfter) {
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import type { RetryConfiguring } from './retry-configuring';
|
|
2
2
|
import type { Milliseconds } from './milliseconds';
|
|
3
3
|
|
|
4
|
+
/**
|
|
5
|
+
* A retry configuration that does not perform any retries.
|
|
6
|
+
*/
|
|
4
7
|
export class NoRetryConfiguration implements RetryConfiguring {
|
|
5
8
|
static readonly shared: Readonly<RetryConfiguring> =
|
|
6
9
|
new NoRetryConfiguration();
|
|
@@ -9,7 +12,7 @@ export class NoRetryConfiguration implements RetryConfiguring {
|
|
|
9
12
|
return false;
|
|
10
13
|
}
|
|
11
14
|
|
|
12
|
-
retryDelay(): Milliseconds {
|
|
13
|
-
return
|
|
15
|
+
retryDelay(): Milliseconds | null {
|
|
16
|
+
return null;
|
|
14
17
|
}
|
|
15
18
|
}
|
|
@@ -4,6 +4,7 @@ import { type FetchOptions } from '../fetch-options';
|
|
|
4
4
|
import { legacyArgsAsFetchOptions } from './legacy-args';
|
|
5
5
|
import { DefaultRetryConfiguration } from './configuration/default-retry-configuration';
|
|
6
6
|
import type { RetryConfiguring } from './configuration/retry-configuring';
|
|
7
|
+
import { FetchRetryConfig } from './configuration/configurations';
|
|
7
8
|
|
|
8
9
|
/**
|
|
9
10
|
* A class that retries a fetch request.
|
|
@@ -26,17 +27,15 @@ export interface FetchRetrierInterface {
|
|
|
26
27
|
export class FetchRetrier implements FetchRetrierInterface {
|
|
27
28
|
private analyticsHandler?: AnalyticsHandlerInterface;
|
|
28
29
|
|
|
29
|
-
private
|
|
30
|
-
new DefaultRetryConfiguration();
|
|
30
|
+
private retryConfig: RetryConfiguring = FetchRetryConfig.default;
|
|
31
31
|
|
|
32
32
|
constructor(options?: {
|
|
33
33
|
analyticsHandler?: AnalyticsHandlerInterface;
|
|
34
|
-
|
|
34
|
+
retryConfig?: RetryConfiguring;
|
|
35
35
|
}) {
|
|
36
36
|
if (options?.analyticsHandler)
|
|
37
37
|
this.analyticsHandler = options.analyticsHandler;
|
|
38
|
-
if (options?.
|
|
39
|
-
this.retryConfiguration = options.retryConfiguration;
|
|
38
|
+
if (options?.retryConfig) this.retryConfig = options.retryConfig;
|
|
40
39
|
}
|
|
41
40
|
|
|
42
41
|
/** @inheritdoc */
|
|
@@ -45,10 +44,10 @@ export class FetchRetrier implements FetchRetrierInterface {
|
|
|
45
44
|
options?: RequestInit | FetchOptions,
|
|
46
45
|
): Promise<Response> {
|
|
47
46
|
const fetchOptions = legacyArgsAsFetchOptions(options);
|
|
48
|
-
return await this.
|
|
47
|
+
return await this.doFetchRetry(request, 0, fetchOptions);
|
|
49
48
|
}
|
|
50
49
|
|
|
51
|
-
private async
|
|
50
|
+
private async doFetchRetry(
|
|
52
51
|
request: RequestInfo,
|
|
53
52
|
retryNumber: number,
|
|
54
53
|
options?: FetchOptions,
|
|
@@ -63,17 +62,20 @@ export class FetchRetrier implements FetchRetrierInterface {
|
|
|
63
62
|
this.log4xx5xxResponse(response);
|
|
64
63
|
}
|
|
65
64
|
|
|
66
|
-
const retryConfig = options?.retryConfig ?? this.
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
65
|
+
const retryConfig = options?.retryConfig ?? this.retryConfig;
|
|
66
|
+
const shouldRetry = retryConfig.shouldRetry(response, retryNumber);
|
|
67
|
+
if (shouldRetry) {
|
|
68
|
+
const retryDelay = retryConfig.retryDelay(retryNumber, response);
|
|
69
|
+
if (retryDelay !== null) {
|
|
70
|
+
await promisedSleep(retryDelay);
|
|
71
|
+
this.logRetryEvent(
|
|
72
|
+
urlString,
|
|
73
|
+
retryNumber,
|
|
74
|
+
response.statusText,
|
|
75
|
+
response.status,
|
|
76
|
+
);
|
|
77
|
+
return this.doFetchRetry(request, retryNumber + 1, options);
|
|
78
|
+
}
|
|
77
79
|
}
|
|
78
80
|
this.logFailureEvent(urlString, response.status);
|
|
79
81
|
return response;
|
|
@@ -84,12 +86,15 @@ export class FetchRetrier implements FetchRetrierInterface {
|
|
|
84
86
|
throw error;
|
|
85
87
|
}
|
|
86
88
|
|
|
87
|
-
const retryConfig = options?.retryConfig ?? this.
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
89
|
+
const retryConfig = options?.retryConfig ?? this.retryConfig;
|
|
90
|
+
const shouldRetry = retryConfig.shouldRetry(null, retryNumber);
|
|
91
|
+
if (shouldRetry) {
|
|
92
|
+
const retryDelay = retryConfig.retryDelay(retryNumber);
|
|
93
|
+
if (retryDelay !== null) {
|
|
94
|
+
await promisedSleep(retryDelay);
|
|
95
|
+
this.logRetryEvent(urlString, retryNumber, error, error);
|
|
96
|
+
return this.doFetchRetry(request, retryNumber + 1, options);
|
|
97
|
+
}
|
|
93
98
|
}
|
|
94
99
|
this.logFailureEvent(urlString, error);
|
|
95
100
|
throw error;
|
|
@@ -1,13 +1,46 @@
|
|
|
1
1
|
import { expect } from '@open-wc/testing';
|
|
2
|
-
import {
|
|
2
|
+
import { FetchHandler } from '../src/fetch-handler';
|
|
3
3
|
import { MockFetchRetrier } from './mocks/mock-fetch-retrier';
|
|
4
4
|
import { NoRetryConfiguration } from '../src/fetch-retry/configuration/no-retry-configuration';
|
|
5
5
|
|
|
6
6
|
describe('Fetch Handler', () => {
|
|
7
|
+
describe('constructor', () => {
|
|
8
|
+
it('has no default apiBaseUrl', () => {
|
|
9
|
+
const fetchHandler = new FetchHandler();
|
|
10
|
+
// @ts-expect-error Accessing private property for test
|
|
11
|
+
expect(fetchHandler.apiBaseUrl).to.equal('');
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
it('sets iaApiBaseUrl if provided', () => {
|
|
15
|
+
const fetchHandler = new FetchHandler({
|
|
16
|
+
iaApiBaseUrl: 'https://example.org',
|
|
17
|
+
});
|
|
18
|
+
// @ts-expect-error Accessing private property for test
|
|
19
|
+
expect(fetchHandler.apiBaseUrl).to.equal('https://example.org');
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
it('sets apiBaseUrl if provided', () => {
|
|
23
|
+
const fetchHandler = new FetchHandler({
|
|
24
|
+
apiBaseUrl: 'https://api.example.org',
|
|
25
|
+
});
|
|
26
|
+
// @ts-expect-error Accessing private property for test
|
|
27
|
+
expect(fetchHandler.apiBaseUrl).to.equal('https://api.example.org');
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
it('uses apiBaseUrl over iaApiBaseUrl if both provided', () => {
|
|
31
|
+
const fetchHandler = new FetchHandler({
|
|
32
|
+
iaApiBaseUrl: 'https://example.org',
|
|
33
|
+
apiBaseUrl: 'https://api.example.org',
|
|
34
|
+
});
|
|
35
|
+
// @ts-expect-error Accessing private property for test
|
|
36
|
+
expect(fetchHandler.apiBaseUrl).to.equal('https://api.example.org');
|
|
37
|
+
});
|
|
38
|
+
});
|
|
39
|
+
|
|
7
40
|
describe('fetch', () => {
|
|
8
41
|
it('adds reCache=1 if it is in the current url', async () => {
|
|
9
42
|
const fetchRetrier = new MockFetchRetrier();
|
|
10
|
-
const fetchHandler = new
|
|
43
|
+
const fetchHandler = new FetchHandler({
|
|
11
44
|
fetchRetrier: fetchRetrier,
|
|
12
45
|
searchParams: '?reCache=1',
|
|
13
46
|
});
|
|
@@ -19,7 +52,7 @@ describe('Fetch Handler', () => {
|
|
|
19
52
|
|
|
20
53
|
it('appends reCache=1 when request is a Request object', async () => {
|
|
21
54
|
const fetchRetrier = new MockFetchRetrier();
|
|
22
|
-
const fetchHandler = new
|
|
55
|
+
const fetchHandler = new FetchHandler({
|
|
23
56
|
fetchRetrier,
|
|
24
57
|
searchParams: '?reCache=1',
|
|
25
58
|
});
|
|
@@ -32,7 +65,7 @@ describe('Fetch Handler', () => {
|
|
|
32
65
|
|
|
33
66
|
it('does not append reCache when not present', async () => {
|
|
34
67
|
const fetchRetrier = new MockFetchRetrier();
|
|
35
|
-
const fetchHandler = new
|
|
68
|
+
const fetchHandler = new FetchHandler({
|
|
36
69
|
fetchRetrier,
|
|
37
70
|
searchParams: '?foo=bar',
|
|
38
71
|
});
|
|
@@ -41,27 +74,37 @@ describe('Fetch Handler', () => {
|
|
|
41
74
|
});
|
|
42
75
|
});
|
|
43
76
|
|
|
44
|
-
describe('
|
|
77
|
+
describe('fetchApiPathResponse', () => {
|
|
45
78
|
it('prepends the IA basehost to the url when making a request', async () => {
|
|
46
79
|
const endpoint = '/foo/service/endpoint.php';
|
|
47
80
|
const fetchRetrier = new MockFetchRetrier();
|
|
48
|
-
const fetchHandler = new
|
|
49
|
-
|
|
81
|
+
const fetchHandler = new FetchHandler({
|
|
82
|
+
apiBaseUrl: 'www.example.com',
|
|
50
83
|
fetchRetrier: fetchRetrier,
|
|
51
84
|
});
|
|
52
|
-
await fetchHandler.
|
|
85
|
+
await fetchHandler.fetchApiPathResponse(endpoint);
|
|
53
86
|
expect(fetchRetrier.requestInfo).to.equal(
|
|
54
87
|
'www.example.com/foo/service/endpoint.php',
|
|
55
88
|
);
|
|
56
89
|
});
|
|
90
|
+
|
|
91
|
+
it('defaults to no apiBaseUrl', async () => {
|
|
92
|
+
const endpoint = '/foo/service/endpoint.php';
|
|
93
|
+
const fetchRetrier = new MockFetchRetrier();
|
|
94
|
+
const fetchHandler = new FetchHandler({
|
|
95
|
+
fetchRetrier: fetchRetrier,
|
|
96
|
+
});
|
|
97
|
+
await fetchHandler.fetchApiPathResponse(endpoint);
|
|
98
|
+
expect(fetchRetrier.requestInfo).to.equal('/foo/service/endpoint.php');
|
|
99
|
+
});
|
|
57
100
|
});
|
|
58
101
|
|
|
59
102
|
describe('fetchApiResponse', () => {
|
|
60
103
|
it('adds credentials: include if requested', async () => {
|
|
61
104
|
const endpoint = '/foo/service/endpoint.php';
|
|
62
105
|
const fetchRetrier = new MockFetchRetrier();
|
|
63
|
-
const fetchHandler = new
|
|
64
|
-
|
|
106
|
+
const fetchHandler = new FetchHandler({
|
|
107
|
+
apiBaseUrl: 'www.example.com',
|
|
65
108
|
fetchRetrier: fetchRetrier,
|
|
66
109
|
});
|
|
67
110
|
await fetchHandler.fetchApiResponse(endpoint, {
|
|
@@ -72,7 +115,7 @@ describe('Fetch Handler', () => {
|
|
|
72
115
|
|
|
73
116
|
it('passes method, body, and headers to RequestInit', async () => {
|
|
74
117
|
const fetchRetrier = new MockFetchRetrier();
|
|
75
|
-
const fetchHandler = new
|
|
118
|
+
const fetchHandler = new FetchHandler({ fetchRetrier });
|
|
76
119
|
const body = JSON.stringify({ hello: 'world' });
|
|
77
120
|
await fetchHandler.fetchApiResponse('https://example.org/api', {
|
|
78
121
|
method: 'POST',
|
|
@@ -89,11 +132,26 @@ describe('Fetch Handler', () => {
|
|
|
89
132
|
it('passes retryConfig through to retrier', async () => {
|
|
90
133
|
const fetchRetrier = new MockFetchRetrier();
|
|
91
134
|
const retryConfig = new NoRetryConfiguration();
|
|
92
|
-
const fetchHandler = new
|
|
135
|
+
const fetchHandler = new FetchHandler({ fetchRetrier });
|
|
93
136
|
await fetchHandler.fetchApiResponse('https://example.org/api', {
|
|
94
137
|
retryConfig,
|
|
95
138
|
});
|
|
96
139
|
expect(fetchRetrier.retryConfig).to.equal(retryConfig);
|
|
97
140
|
});
|
|
98
141
|
});
|
|
142
|
+
|
|
143
|
+
describe('fetchIAApiResponse', () => {
|
|
144
|
+
it('is an alias for fetchApiPathResponse', async () => {
|
|
145
|
+
const endpoint = '/foo/service/endpoint.php';
|
|
146
|
+
const fetchRetrier = new MockFetchRetrier();
|
|
147
|
+
const fetchHandler = new FetchHandler({
|
|
148
|
+
iaApiBaseUrl: 'www.example.com',
|
|
149
|
+
fetchRetrier: fetchRetrier,
|
|
150
|
+
});
|
|
151
|
+
await fetchHandler.fetchIAApiResponse(endpoint);
|
|
152
|
+
expect(fetchRetrier.requestInfo).to.equal(
|
|
153
|
+
'www.example.com/foo/service/endpoint.php',
|
|
154
|
+
);
|
|
155
|
+
});
|
|
156
|
+
});
|
|
99
157
|
});
|
|
@@ -21,7 +21,7 @@ describe('FetchRetrier', () => {
|
|
|
21
21
|
fetchStub.resolves(new Response('ok', { status: 200 }));
|
|
22
22
|
const retrier = new FetchRetrier({
|
|
23
23
|
analyticsHandler: analytics,
|
|
24
|
-
|
|
24
|
+
retryConfig: new MockRetryConfig(),
|
|
25
25
|
});
|
|
26
26
|
|
|
27
27
|
const res = await retrier.fetchRetry('https://foo.org/data');
|
|
@@ -81,7 +81,7 @@ describe('FetchRetrier', () => {
|
|
|
81
81
|
|
|
82
82
|
const retrier = new FetchRetrier({
|
|
83
83
|
analyticsHandler: analytics,
|
|
84
|
-
|
|
84
|
+
retryConfig: new MockRetryConfig(),
|
|
85
85
|
});
|
|
86
86
|
|
|
87
87
|
const res = await retrier.fetchRetry('https://foo.org/fail');
|
|
@@ -98,7 +98,7 @@ describe('FetchRetrier', () => {
|
|
|
98
98
|
|
|
99
99
|
const retrier = new FetchRetrier({
|
|
100
100
|
analyticsHandler: analytics,
|
|
101
|
-
|
|
101
|
+
retryConfig: new MockRetryConfig(),
|
|
102
102
|
});
|
|
103
103
|
|
|
104
104
|
const res = await retrier.fetchRetry('https://foo.org/retry');
|
|
@@ -113,7 +113,7 @@ describe('FetchRetrier', () => {
|
|
|
113
113
|
|
|
114
114
|
const retrier = new FetchRetrier({
|
|
115
115
|
analyticsHandler: analytics,
|
|
116
|
-
|
|
116
|
+
retryConfig: new MockRetryConfig(),
|
|
117
117
|
});
|
|
118
118
|
|
|
119
119
|
try {
|
|
@@ -157,7 +157,7 @@ describe('FetchRetrier', () => {
|
|
|
157
157
|
|
|
158
158
|
const retrier = new FetchRetrier({
|
|
159
159
|
analyticsHandler: analytics,
|
|
160
|
-
|
|
160
|
+
retryConfig: retryConfig,
|
|
161
161
|
});
|
|
162
162
|
|
|
163
163
|
const res = await retrier.fetchRetry('https://foo.org/retry-fail');
|
|
@@ -171,7 +171,7 @@ describe('FetchRetrier', () => {
|
|
|
171
171
|
fetchStub.resolves(new Response('server error', { status: 500 }));
|
|
172
172
|
const retrier = new FetchRetrier({
|
|
173
173
|
analyticsHandler: analytics,
|
|
174
|
-
|
|
174
|
+
retryConfig: new (class {
|
|
175
175
|
shouldRetry() {
|
|
176
176
|
return false;
|
|
177
177
|
}
|
|
@@ -191,7 +191,7 @@ describe('FetchRetrier', () => {
|
|
|
191
191
|
fetchStub.rejects(new Error('Immediate failure'));
|
|
192
192
|
const retrier = new FetchRetrier({
|
|
193
193
|
analyticsHandler: analytics,
|
|
194
|
-
|
|
194
|
+
retryConfig: new (class {
|
|
195
195
|
shouldRetry() {
|
|
196
196
|
return false;
|
|
197
197
|
}
|
package/test/legacy-args.test.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { expect } from '@open-wc/testing';
|
|
2
2
|
import { legacyArgsAsFetchOptions } from '../src/fetch-retry/legacy-args';
|
|
3
3
|
import type { FetchOptions } from '../src/fetch-options';
|
|
4
|
+
import { MockRetryConfig } from './mocks/mock-retry-config';
|
|
4
5
|
|
|
5
6
|
describe('legacyArgsAsFetchOptions', () => {
|
|
6
7
|
it('wraps RequestInit into FetchOptions', () => {
|
|
@@ -10,8 +11,10 @@ describe('legacyArgsAsFetchOptions', () => {
|
|
|
10
11
|
});
|
|
11
12
|
|
|
12
13
|
it('returns FetchOptions unchanged', () => {
|
|
14
|
+
const retryConfig = new MockRetryConfig();
|
|
13
15
|
const options: FetchOptions = {
|
|
14
16
|
requestInit: { headers: { foo: 'bar' } },
|
|
17
|
+
retryConfig: retryConfig,
|
|
15
18
|
};
|
|
16
19
|
const fo = legacyArgsAsFetchOptions(options);
|
|
17
20
|
expect(fo).to.equal(options);
|
|
@@ -5,11 +5,7 @@ export class MockRetryConfig implements RetryConfiguring {
|
|
|
5
5
|
|
|
6
6
|
mockRetryDelay: number = 0;
|
|
7
7
|
|
|
8
|
-
shouldRetry(
|
|
9
|
-
response: Response | null,
|
|
10
|
-
retryNumber: number,
|
|
11
|
-
error?: unknown,
|
|
12
|
-
): boolean {
|
|
8
|
+
shouldRetry(response: Response | null, retryNumber: number): boolean {
|
|
13
9
|
return retryNumber < this.mockRetryCount;
|
|
14
10
|
}
|
|
15
11
|
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
import { expect } from '@open-wc/testing';
|
|
2
|
-
import { legacyArgsAsFetchOptions } from '../src/fetch-retry/legacy-args';
|
|
3
|
-
import { MockRetryConfig } from './mocks/mock-retry-config';
|
|
4
|
-
describe('FetchRetrier Legacy Args', () => {
|
|
5
|
-
it('can convert RequestInit to FetchOptions', async () => {
|
|
6
|
-
const options = legacyArgsAsFetchOptions({ method: 'GET' });
|
|
7
|
-
expect(options).to.deep.equal({
|
|
8
|
-
requestInit: {
|
|
9
|
-
method: 'GET',
|
|
10
|
-
},
|
|
11
|
-
});
|
|
12
|
-
});
|
|
13
|
-
it('leaves FetchOptions unchanged', async () => {
|
|
14
|
-
const retryConfig = new MockRetryConfig();
|
|
15
|
-
const options = legacyArgsAsFetchOptions({
|
|
16
|
-
requestInit: { method: 'POST' },
|
|
17
|
-
retryConfig: retryConfig,
|
|
18
|
-
});
|
|
19
|
-
expect(options).to.deep.equal({
|
|
20
|
-
requestInit: {
|
|
21
|
-
method: 'POST',
|
|
22
|
-
},
|
|
23
|
-
retryConfig: retryConfig,
|
|
24
|
-
});
|
|
25
|
-
});
|
|
26
|
-
});
|
|
27
|
-
//# sourceMappingURL=retrier-legacy-args.test.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"retrier-legacy-args.test.js","sourceRoot":"","sources":["../../test/retrier-legacy-args.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAC1C,OAAO,EAAE,wBAAwB,EAAE,MAAM,gCAAgC,CAAC;AAC1E,OAAO,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAC;AAE5D,QAAQ,CAAC,0BAA0B,EAAE,GAAG,EAAE;IACxC,EAAE,CAAC,yCAAyC,EAAE,KAAK,IAAI,EAAE;QACvD,MAAM,OAAO,GAAG,wBAAwB,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC;QAC5D,MAAM,CAAC,OAAO,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC;YAC5B,WAAW,EAAE;gBACX,MAAM,EAAE,KAAK;aACd;SACF,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,+BAA+B,EAAE,KAAK,IAAI,EAAE;QAC7C,MAAM,WAAW,GAAG,IAAI,eAAe,EAAE,CAAC;QAC1C,MAAM,OAAO,GAAG,wBAAwB,CAAC;YACvC,WAAW,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE;YAC/B,WAAW,EAAE,WAAW;SACzB,CAAC,CAAC;QACH,MAAM,CAAC,OAAO,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC;YAC5B,WAAW,EAAE;gBACX,MAAM,EAAE,MAAM;aACf;YACD,WAAW,EAAE,WAAW;SACzB,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC","sourcesContent":["import { expect } from '@open-wc/testing';\nimport { legacyArgsAsFetchOptions } from '../src/fetch-retry/legacy-args';\nimport { MockRetryConfig } from './mocks/mock-retry-config';\n\ndescribe('FetchRetrier Legacy Args', () => {\n it('can convert RequestInit to FetchOptions', async () => {\n const options = legacyArgsAsFetchOptions({ method: 'GET' });\n expect(options).to.deep.equal({\n requestInit: {\n method: 'GET',\n },\n });\n });\n\n it('leaves FetchOptions unchanged', async () => {\n const retryConfig = new MockRetryConfig();\n const options = legacyArgsAsFetchOptions({\n requestInit: { method: 'POST' },\n retryConfig: retryConfig,\n });\n expect(options).to.deep.equal({\n requestInit: {\n method: 'POST',\n },\n retryConfig: retryConfig,\n });\n });\n});\n"]}
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
import { expect } from '@open-wc/testing';
|
|
2
|
-
import { legacyArgsAsFetchOptions } from '../src/fetch-retry/legacy-args';
|
|
3
|
-
import { MockRetryConfig } from './mocks/mock-retry-config';
|
|
4
|
-
|
|
5
|
-
describe('FetchRetrier Legacy Args', () => {
|
|
6
|
-
it('can convert RequestInit to FetchOptions', async () => {
|
|
7
|
-
const options = legacyArgsAsFetchOptions({ method: 'GET' });
|
|
8
|
-
expect(options).to.deep.equal({
|
|
9
|
-
requestInit: {
|
|
10
|
-
method: 'GET',
|
|
11
|
-
},
|
|
12
|
-
});
|
|
13
|
-
});
|
|
14
|
-
|
|
15
|
-
it('leaves FetchOptions unchanged', async () => {
|
|
16
|
-
const retryConfig = new MockRetryConfig();
|
|
17
|
-
const options = legacyArgsAsFetchOptions({
|
|
18
|
-
requestInit: { method: 'POST' },
|
|
19
|
-
retryConfig: retryConfig,
|
|
20
|
-
});
|
|
21
|
-
expect(options).to.deep.equal({
|
|
22
|
-
requestInit: {
|
|
23
|
-
method: 'POST',
|
|
24
|
-
},
|
|
25
|
-
retryConfig: retryConfig,
|
|
26
|
-
});
|
|
27
|
-
});
|
|
28
|
-
});
|