@internetarchive/fetch-handler 1.1.0-webdev-7731.8 → 1.1.0-webdev-7731.10
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 +32 -3
- package/dist/src/fetch-handler.js +35 -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 +81 -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 +50 -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 +95 -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
|
@@ -1,22 +1,22 @@
|
|
|
1
1
|
import { promisedSleep } from '../utils/promised-sleep';
|
|
2
2
|
import { legacyArgsAsFetchOptions } from './legacy-args';
|
|
3
|
-
import {
|
|
3
|
+
import { FetchRetryConfig } from './configuration/configurations';
|
|
4
4
|
/** @inheritdoc */
|
|
5
5
|
export class FetchRetrier {
|
|
6
6
|
constructor(options) {
|
|
7
|
-
this.
|
|
7
|
+
this.retryConfig = FetchRetryConfig.default;
|
|
8
8
|
this.eventCategory = 'offshootFetchRetry';
|
|
9
9
|
if (options === null || options === void 0 ? void 0 : options.analyticsHandler)
|
|
10
10
|
this.analyticsHandler = options.analyticsHandler;
|
|
11
|
-
if (options === null || options === void 0 ? void 0 : options.
|
|
12
|
-
this.
|
|
11
|
+
if (options === null || options === void 0 ? void 0 : options.retryConfig)
|
|
12
|
+
this.retryConfig = options.retryConfig;
|
|
13
13
|
}
|
|
14
14
|
/** @inheritdoc */
|
|
15
15
|
async fetchRetry(request, options) {
|
|
16
16
|
const fetchOptions = legacyArgsAsFetchOptions(options);
|
|
17
|
-
return await this.
|
|
17
|
+
return await this.doFetchRetry(request, 0, fetchOptions);
|
|
18
18
|
}
|
|
19
|
-
async
|
|
19
|
+
async doFetchRetry(request, retryNumber, options) {
|
|
20
20
|
var _a, _b;
|
|
21
21
|
const urlString = typeof request === 'string' ? request : request.url;
|
|
22
22
|
try {
|
|
@@ -26,12 +26,15 @@ export class FetchRetrier {
|
|
|
26
26
|
if (response.status >= 400 && response.status < 600) {
|
|
27
27
|
this.log4xx5xxResponse(response);
|
|
28
28
|
}
|
|
29
|
-
const retryConfig = (_a = options === null || options === void 0 ? void 0 : options.retryConfig) !== null && _a !== void 0 ? _a : this.
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
29
|
+
const retryConfig = (_a = options === null || options === void 0 ? void 0 : options.retryConfig) !== null && _a !== void 0 ? _a : this.retryConfig;
|
|
30
|
+
const shouldRetry = retryConfig.shouldRetry(response, retryNumber);
|
|
31
|
+
if (shouldRetry) {
|
|
32
|
+
const retryDelay = retryConfig.retryDelay(retryNumber, response);
|
|
33
|
+
if (retryDelay !== null) {
|
|
34
|
+
await promisedSleep(retryDelay);
|
|
35
|
+
this.logRetryEvent(urlString, retryNumber, response.statusText, response.status);
|
|
36
|
+
return this.doFetchRetry(request, retryNumber + 1, options);
|
|
37
|
+
}
|
|
35
38
|
}
|
|
36
39
|
this.logFailureEvent(urlString, response.status);
|
|
37
40
|
return response;
|
|
@@ -42,12 +45,15 @@ export class FetchRetrier {
|
|
|
42
45
|
this.logContentBlockingEvent(urlString, error);
|
|
43
46
|
throw error;
|
|
44
47
|
}
|
|
45
|
-
const retryConfig = (_b = options === null || options === void 0 ? void 0 : options.retryConfig) !== null && _b !== void 0 ? _b : this.
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
48
|
+
const retryConfig = (_b = options === null || options === void 0 ? void 0 : options.retryConfig) !== null && _b !== void 0 ? _b : this.retryConfig;
|
|
49
|
+
const shouldRetry = retryConfig.shouldRetry(null, retryNumber);
|
|
50
|
+
if (shouldRetry) {
|
|
51
|
+
const retryDelay = retryConfig.retryDelay(retryNumber);
|
|
52
|
+
if (retryDelay !== null) {
|
|
53
|
+
await promisedSleep(retryDelay);
|
|
54
|
+
this.logRetryEvent(urlString, retryNumber, error, error);
|
|
55
|
+
return this.doFetchRetry(request, retryNumber + 1, options);
|
|
56
|
+
}
|
|
51
57
|
}
|
|
52
58
|
this.logFailureEvent(urlString, error);
|
|
53
59
|
throw error;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fetch-retrier.js","sourceRoot":"","sources":["../../../src/fetch-retry/fetch-retrier.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AAExD,OAAO,EAAE,wBAAwB,EAAE,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"fetch-retrier.js","sourceRoot":"","sources":["../../../src/fetch-retry/fetch-retrier.ts"],"names":[],"mappings":"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","sourcesContent":["import type { AnalyticsHandlerInterface } from '@internetarchive/analytics-manager';\nimport { promisedSleep } from '../utils/promised-sleep';\nimport { type FetchOptions } from '../fetch-options';\nimport { legacyArgsAsFetchOptions } from './legacy-args';\nimport { DefaultRetryConfiguration } from './configuration/default-retry-configuration';\nimport type { RetryConfiguring } from './configuration/retry-configuring';\nimport { FetchRetryConfig } from './configuration/configurations';\n\n/**\n * A class that retries a fetch request.\n */\nexport interface FetchRetrierInterface {\n /**\n * Execute a fetch with retry.\n *\n * @param request RequestInfo\n * @param options Optional RequestInit | FetchOptions\n * @returns Promise<Response>\n */\n fetchRetry(\n request: RequestInfo,\n options?: RequestInit | FetchOptions,\n ): Promise<Response>;\n}\n\n/** @inheritdoc */\nexport class FetchRetrier implements FetchRetrierInterface {\n private analyticsHandler?: AnalyticsHandlerInterface;\n\n private retryConfig: RetryConfiguring = FetchRetryConfig.default;\n\n constructor(options?: {\n analyticsHandler?: AnalyticsHandlerInterface;\n retryConfig?: RetryConfiguring;\n }) {\n if (options?.analyticsHandler)\n this.analyticsHandler = options.analyticsHandler;\n if (options?.retryConfig) this.retryConfig = options.retryConfig;\n }\n\n /** @inheritdoc */\n public async fetchRetry(\n request: RequestInfo,\n options?: RequestInit | FetchOptions,\n ): Promise<Response> {\n const fetchOptions = legacyArgsAsFetchOptions(options);\n return await this.doFetchRetry(request, 0, fetchOptions);\n }\n\n private async doFetchRetry(\n request: RequestInfo,\n retryNumber: number,\n options?: FetchOptions,\n ): Promise<Response> {\n const urlString = typeof request === 'string' ? request : request.url;\n\n try {\n const response = await fetch(request, options?.requestInit);\n if (response.ok) return response;\n\n if (response.status >= 400 && response.status < 600) {\n this.log4xx5xxResponse(response);\n }\n\n const retryConfig = options?.retryConfig ?? this.retryConfig;\n const shouldRetry = retryConfig.shouldRetry(response, retryNumber);\n if (shouldRetry) {\n const retryDelay = retryConfig.retryDelay(retryNumber, response);\n if (retryDelay !== null) {\n await promisedSleep(retryDelay);\n this.logRetryEvent(\n urlString,\n retryNumber,\n response.statusText,\n response.status,\n );\n return this.doFetchRetry(request, retryNumber + 1, options);\n }\n }\n this.logFailureEvent(urlString, response.status);\n return response;\n } catch (error) {\n // if a content blocker is detected, log it and don't retry\n if (this.isContentBlockerError(error)) {\n this.logContentBlockingEvent(urlString, error);\n throw error;\n }\n\n const retryConfig = options?.retryConfig ?? this.retryConfig;\n const shouldRetry = retryConfig.shouldRetry(null, retryNumber);\n if (shouldRetry) {\n const retryDelay = retryConfig.retryDelay(retryNumber);\n if (retryDelay !== null) {\n await promisedSleep(retryDelay);\n this.logRetryEvent(urlString, retryNumber, error, error);\n return this.doFetchRetry(request, retryNumber + 1, options);\n }\n }\n this.logFailureEvent(urlString, error);\n throw error;\n }\n }\n\n private isContentBlockerError(error: unknown): boolean {\n // all of the content blocker errors are `TypeError`\n if (!(error instanceof TypeError)) return false;\n const message = error.message.toLowerCase();\n return message.includes('content blocker');\n }\n\n private readonly eventCategory = 'offshootFetchRetry';\n\n private logRetryEvent(\n urlString: string,\n retryNumber: number,\n status: unknown,\n code: unknown,\n ) {\n this.analyticsHandler?.sendEvent({\n category: this.eventCategory,\n action: 'retryingFetch',\n label: `retryNumber: ${retryNumber}, code: ${code}, status: ${status}, url: ${urlString}`,\n });\n }\n\n private logFailureEvent(urlString: string, error: unknown) {\n this.analyticsHandler?.sendEvent({\n category: this.eventCategory,\n action: 'fetchFailed',\n label: `error: ${error}, url: ${urlString}`,\n });\n }\n\n private log4xx5xxResponse(response: Response) {\n const status = response.status;\n\n this.analyticsHandler?.sendEvent({\n category: this.eventCategory,\n action: `status${status}Response`,\n label: `url: ${response.url}`,\n });\n }\n\n private logContentBlockingEvent(urlString: string, error: unknown) {\n this.analyticsHandler?.sendEvent({\n category: this.eventCategory,\n action: 'contentBlockerDetectedNotRetrying',\n label: `error: ${error}, url: ${urlString}`,\n });\n }\n}\n"]}
|
|
@@ -1,12 +1,41 @@
|
|
|
1
1
|
import { expect } from '@open-wc/testing';
|
|
2
|
-
import { IaFetchHandler } from '../src/fetch-handler';
|
|
2
|
+
import { FetchHandler, IaFetchHandler } 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
|
describe('Fetch Handler', () => {
|
|
6
|
+
describe('constructor', () => {
|
|
7
|
+
it('has no default apiBaseUrl', () => {
|
|
8
|
+
const fetchHandler = new FetchHandler();
|
|
9
|
+
// @ts-expect-error Accessing private property for test
|
|
10
|
+
expect(fetchHandler.apiBaseUrl).to.equal('');
|
|
11
|
+
});
|
|
12
|
+
it('sets iaApiBaseUrl if provided', () => {
|
|
13
|
+
const fetchHandler = new FetchHandler({
|
|
14
|
+
iaApiBaseUrl: 'https://example.org',
|
|
15
|
+
});
|
|
16
|
+
// @ts-expect-error Accessing private property for test
|
|
17
|
+
expect(fetchHandler.apiBaseUrl).to.equal('https://example.org');
|
|
18
|
+
});
|
|
19
|
+
it('sets apiBaseUrl if provided', () => {
|
|
20
|
+
const fetchHandler = new FetchHandler({
|
|
21
|
+
apiBaseUrl: 'https://api.example.org',
|
|
22
|
+
});
|
|
23
|
+
// @ts-expect-error Accessing private property for test
|
|
24
|
+
expect(fetchHandler.apiBaseUrl).to.equal('https://api.example.org');
|
|
25
|
+
});
|
|
26
|
+
it('uses apiBaseUrl over iaApiBaseUrl if both provided', () => {
|
|
27
|
+
const fetchHandler = new FetchHandler({
|
|
28
|
+
iaApiBaseUrl: 'https://example.org',
|
|
29
|
+
apiBaseUrl: 'https://api.example.org',
|
|
30
|
+
});
|
|
31
|
+
// @ts-expect-error Accessing private property for test
|
|
32
|
+
expect(fetchHandler.apiBaseUrl).to.equal('https://api.example.org');
|
|
33
|
+
});
|
|
34
|
+
});
|
|
6
35
|
describe('fetch', () => {
|
|
7
36
|
it('adds reCache=1 if it is in the current url', async () => {
|
|
8
37
|
const fetchRetrier = new MockFetchRetrier();
|
|
9
|
-
const fetchHandler = new
|
|
38
|
+
const fetchHandler = new FetchHandler({
|
|
10
39
|
fetchRetrier: fetchRetrier,
|
|
11
40
|
searchParams: '?reCache=1',
|
|
12
41
|
});
|
|
@@ -15,7 +44,7 @@ describe('Fetch Handler', () => {
|
|
|
15
44
|
});
|
|
16
45
|
it('appends reCache=1 when request is a Request object', async () => {
|
|
17
46
|
const fetchRetrier = new MockFetchRetrier();
|
|
18
|
-
const fetchHandler = new
|
|
47
|
+
const fetchHandler = new FetchHandler({
|
|
19
48
|
fetchRetrier,
|
|
20
49
|
searchParams: '?reCache=1',
|
|
21
50
|
});
|
|
@@ -25,7 +54,7 @@ describe('Fetch Handler', () => {
|
|
|
25
54
|
});
|
|
26
55
|
it('does not append reCache when not present', async () => {
|
|
27
56
|
const fetchRetrier = new MockFetchRetrier();
|
|
28
|
-
const fetchHandler = new
|
|
57
|
+
const fetchHandler = new FetchHandler({
|
|
29
58
|
fetchRetrier,
|
|
30
59
|
searchParams: '?foo=bar',
|
|
31
60
|
});
|
|
@@ -33,24 +62,33 @@ describe('Fetch Handler', () => {
|
|
|
33
62
|
expect(fetchRetrier.requestInfo).to.equal('https://foo.org/api/v1/snoot');
|
|
34
63
|
});
|
|
35
64
|
});
|
|
36
|
-
describe('
|
|
65
|
+
describe('fetchApiPathResponse', () => {
|
|
37
66
|
it('prepends the IA basehost to the url when making a request', async () => {
|
|
38
67
|
const endpoint = '/foo/service/endpoint.php';
|
|
39
68
|
const fetchRetrier = new MockFetchRetrier();
|
|
40
|
-
const fetchHandler = new
|
|
41
|
-
|
|
69
|
+
const fetchHandler = new FetchHandler({
|
|
70
|
+
apiBaseUrl: 'www.example.com',
|
|
42
71
|
fetchRetrier: fetchRetrier,
|
|
43
72
|
});
|
|
44
|
-
await fetchHandler.
|
|
73
|
+
await fetchHandler.fetchApiPathResponse(endpoint);
|
|
45
74
|
expect(fetchRetrier.requestInfo).to.equal('www.example.com/foo/service/endpoint.php');
|
|
46
75
|
});
|
|
76
|
+
it('defaults to no apiBaseUrl', async () => {
|
|
77
|
+
const endpoint = '/foo/service/endpoint.php';
|
|
78
|
+
const fetchRetrier = new MockFetchRetrier();
|
|
79
|
+
const fetchHandler = new FetchHandler({
|
|
80
|
+
fetchRetrier: fetchRetrier,
|
|
81
|
+
});
|
|
82
|
+
await fetchHandler.fetchApiPathResponse(endpoint);
|
|
83
|
+
expect(fetchRetrier.requestInfo).to.equal('/foo/service/endpoint.php');
|
|
84
|
+
});
|
|
47
85
|
});
|
|
48
86
|
describe('fetchApiResponse', () => {
|
|
49
87
|
it('adds credentials: include if requested', async () => {
|
|
50
88
|
const endpoint = '/foo/service/endpoint.php';
|
|
51
89
|
const fetchRetrier = new MockFetchRetrier();
|
|
52
|
-
const fetchHandler = new
|
|
53
|
-
|
|
90
|
+
const fetchHandler = new FetchHandler({
|
|
91
|
+
apiBaseUrl: 'www.example.com',
|
|
54
92
|
fetchRetrier: fetchRetrier,
|
|
55
93
|
});
|
|
56
94
|
await fetchHandler.fetchApiResponse(endpoint, {
|
|
@@ -60,7 +98,7 @@ describe('Fetch Handler', () => {
|
|
|
60
98
|
});
|
|
61
99
|
it('passes method, body, and headers to RequestInit', async () => {
|
|
62
100
|
const fetchRetrier = new MockFetchRetrier();
|
|
63
|
-
const fetchHandler = new
|
|
101
|
+
const fetchHandler = new FetchHandler({ fetchRetrier });
|
|
64
102
|
const body = JSON.stringify({ hello: 'world' });
|
|
65
103
|
await fetchHandler.fetchApiResponse('https://example.org/api', {
|
|
66
104
|
method: 'POST',
|
|
@@ -76,12 +114,43 @@ describe('Fetch Handler', () => {
|
|
|
76
114
|
it('passes retryConfig through to retrier', async () => {
|
|
77
115
|
const fetchRetrier = new MockFetchRetrier();
|
|
78
116
|
const retryConfig = new NoRetryConfiguration();
|
|
79
|
-
const fetchHandler = new
|
|
117
|
+
const fetchHandler = new FetchHandler({ fetchRetrier });
|
|
80
118
|
await fetchHandler.fetchApiResponse('https://example.org/api', {
|
|
81
119
|
retryConfig,
|
|
82
120
|
});
|
|
83
121
|
expect(fetchRetrier.retryConfig).to.equal(retryConfig);
|
|
84
122
|
});
|
|
85
123
|
});
|
|
124
|
+
describe('fetchIAApiResponse', () => {
|
|
125
|
+
it('is an alias for fetchApiPathResponse', async () => {
|
|
126
|
+
const endpoint = '/foo/service/endpoint.php';
|
|
127
|
+
const fetchRetrier = new MockFetchRetrier();
|
|
128
|
+
const fetchHandler = new IaFetchHandler({
|
|
129
|
+
iaApiBaseUrl: 'www.example.com',
|
|
130
|
+
fetchRetrier: fetchRetrier,
|
|
131
|
+
});
|
|
132
|
+
await fetchHandler.fetchIAApiResponse(endpoint);
|
|
133
|
+
expect(fetchRetrier.requestInfo).to.equal('www.example.com/foo/service/endpoint.php');
|
|
134
|
+
});
|
|
135
|
+
it('defaults the baseUrl to https://archive.org', async () => {
|
|
136
|
+
const endpoint = '/foo/service/endpoint.php';
|
|
137
|
+
const fetchRetrier = new MockFetchRetrier();
|
|
138
|
+
const fetchHandler = new IaFetchHandler({
|
|
139
|
+
fetchRetrier: fetchRetrier,
|
|
140
|
+
});
|
|
141
|
+
await fetchHandler.fetchIAApiResponse(endpoint);
|
|
142
|
+
expect(fetchRetrier.requestInfo).to.equal('https://archive.org/foo/service/endpoint.php');
|
|
143
|
+
});
|
|
144
|
+
it('passes iaApiBaseUrl if provided', async () => {
|
|
145
|
+
const endpoint = '/foo/service/endpoint.php';
|
|
146
|
+
const fetchRetrier = new MockFetchRetrier();
|
|
147
|
+
const fetchHandler = new IaFetchHandler({
|
|
148
|
+
iaApiBaseUrl: 'www.example.com',
|
|
149
|
+
fetchRetrier: fetchRetrier,
|
|
150
|
+
});
|
|
151
|
+
await fetchHandler.fetchIAApiResponse(endpoint);
|
|
152
|
+
expect(fetchRetrier.requestInfo).to.equal('www.example.com/foo/service/endpoint.php');
|
|
153
|
+
});
|
|
154
|
+
});
|
|
86
155
|
});
|
|
87
156
|
//# sourceMappingURL=fetch-handler.test.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fetch-handler.test.js","sourceRoot":"","sources":["../../test/fetch-handler.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { expect } from '@open-wc/testing';\nimport { IaFetchHandler } from '../src/fetch-handler';\nimport { MockFetchRetrier } from './mocks/mock-fetch-retrier';\nimport { NoRetryConfiguration } from '../src/fetch-retry/configuration/no-retry-configuration';\n\ndescribe('Fetch Handler', () => {\n describe('fetch', () => {\n it('adds reCache=1 if it is in the current url', async () => {\n const fetchRetrier = new MockFetchRetrier();\n const fetchHandler = new IaFetchHandler({\n fetchRetrier: fetchRetrier,\n searchParams: '?reCache=1',\n });\n await fetchHandler.fetch('https://foo.org/api/v1/snoot');\n expect(fetchRetrier.requestInfo).to.equal(\n 'https://foo.org/api/v1/snoot?reCache=1',\n );\n });\n\n it('appends reCache=1 when request is a Request object', async () => {\n const fetchRetrier = new MockFetchRetrier();\n const fetchHandler = new IaFetchHandler({\n fetchRetrier,\n searchParams: '?reCache=1',\n });\n const req = new Request('https://foo.org/api/v1/snoot');\n await fetchHandler.fetch(req);\n expect(fetchRetrier.requestInfo).to.equal(\n 'https://foo.org/api/v1/snoot?reCache=1',\n );\n });\n\n it('does not append reCache when not present', async () => {\n const fetchRetrier = new MockFetchRetrier();\n const fetchHandler = new IaFetchHandler({\n fetchRetrier,\n searchParams: '?foo=bar',\n });\n await fetchHandler.fetch('https://foo.org/api/v1/snoot');\n expect(fetchRetrier.requestInfo).to.equal('https://foo.org/api/v1/snoot');\n });\n });\n\n describe('fetchIAApiResponse', () => {\n it('prepends the IA basehost to the url when making a request', async () => {\n const endpoint = '/foo/service/endpoint.php';\n const fetchRetrier = new MockFetchRetrier();\n const fetchHandler = new IaFetchHandler({\n iaApiBaseUrl: 'www.example.com',\n fetchRetrier: fetchRetrier,\n });\n await fetchHandler.fetchIAApiResponse(endpoint);\n expect(fetchRetrier.requestInfo).to.equal(\n 'www.example.com/foo/service/endpoint.php',\n );\n });\n });\n\n describe('fetchApiResponse', () => {\n it('adds credentials: include if requested', async () => {\n const endpoint = '/foo/service/endpoint.php';\n const fetchRetrier = new MockFetchRetrier();\n const fetchHandler = new IaFetchHandler({\n iaApiBaseUrl: 'www.example.com',\n fetchRetrier: fetchRetrier,\n });\n await fetchHandler.fetchApiResponse(endpoint, {\n includeCredentials: true,\n });\n expect(fetchRetrier.init).to.deep.equal({ credentials: 'include' });\n });\n\n it('passes method, body, and headers to RequestInit', async () => {\n const fetchRetrier = new MockFetchRetrier();\n const fetchHandler = new IaFetchHandler({ fetchRetrier });\n const body = JSON.stringify({ hello: 'world' });\n await fetchHandler.fetchApiResponse('https://example.org/api', {\n method: 'POST',\n body,\n headers: { 'x-test': '1', 'content-type': 'application/json' },\n });\n expect(fetchRetrier.init).to.deep.equal({\n method: 'POST',\n body,\n headers: { 'x-test': '1', 'content-type': 'application/json' },\n });\n });\n\n it('passes retryConfig through to retrier', async () => {\n const fetchRetrier = new MockFetchRetrier();\n const retryConfig = new NoRetryConfiguration();\n const fetchHandler = new IaFetchHandler({ fetchRetrier });\n await fetchHandler.fetchApiResponse('https://example.org/api', {\n retryConfig,\n });\n expect(fetchRetrier.retryConfig).to.equal(retryConfig);\n });\n });\n});\n"]}
|
|
1
|
+
{"version":3,"file":"fetch-handler.test.js","sourceRoot":"","sources":["../../test/fetch-handler.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { expect } from '@open-wc/testing';\nimport { FetchHandler, IaFetchHandler } from '../src/fetch-handler';\nimport { MockFetchRetrier } from './mocks/mock-fetch-retrier';\nimport { NoRetryConfiguration } from '../src/fetch-retry/configuration/no-retry-configuration';\n\ndescribe('Fetch Handler', () => {\n describe('constructor', () => {\n it('has no default apiBaseUrl', () => {\n const fetchHandler = new FetchHandler();\n // @ts-expect-error Accessing private property for test\n expect(fetchHandler.apiBaseUrl).to.equal('');\n });\n\n it('sets iaApiBaseUrl if provided', () => {\n const fetchHandler = new FetchHandler({\n iaApiBaseUrl: 'https://example.org',\n });\n // @ts-expect-error Accessing private property for test\n expect(fetchHandler.apiBaseUrl).to.equal('https://example.org');\n });\n\n it('sets apiBaseUrl if provided', () => {\n const fetchHandler = new FetchHandler({\n apiBaseUrl: 'https://api.example.org',\n });\n // @ts-expect-error Accessing private property for test\n expect(fetchHandler.apiBaseUrl).to.equal('https://api.example.org');\n });\n\n it('uses apiBaseUrl over iaApiBaseUrl if both provided', () => {\n const fetchHandler = new FetchHandler({\n iaApiBaseUrl: 'https://example.org',\n apiBaseUrl: 'https://api.example.org',\n });\n // @ts-expect-error Accessing private property for test\n expect(fetchHandler.apiBaseUrl).to.equal('https://api.example.org');\n });\n });\n\n describe('fetch', () => {\n it('adds reCache=1 if it is in the current url', async () => {\n const fetchRetrier = new MockFetchRetrier();\n const fetchHandler = new FetchHandler({\n fetchRetrier: fetchRetrier,\n searchParams: '?reCache=1',\n });\n await fetchHandler.fetch('https://foo.org/api/v1/snoot');\n expect(fetchRetrier.requestInfo).to.equal(\n 'https://foo.org/api/v1/snoot?reCache=1',\n );\n });\n\n it('appends reCache=1 when request is a Request object', async () => {\n const fetchRetrier = new MockFetchRetrier();\n const fetchHandler = new FetchHandler({\n fetchRetrier,\n searchParams: '?reCache=1',\n });\n const req = new Request('https://foo.org/api/v1/snoot');\n await fetchHandler.fetch(req);\n expect(fetchRetrier.requestInfo).to.equal(\n 'https://foo.org/api/v1/snoot?reCache=1',\n );\n });\n\n it('does not append reCache when not present', async () => {\n const fetchRetrier = new MockFetchRetrier();\n const fetchHandler = new FetchHandler({\n fetchRetrier,\n searchParams: '?foo=bar',\n });\n await fetchHandler.fetch('https://foo.org/api/v1/snoot');\n expect(fetchRetrier.requestInfo).to.equal('https://foo.org/api/v1/snoot');\n });\n });\n\n describe('fetchApiPathResponse', () => {\n it('prepends the IA basehost to the url when making a request', async () => {\n const endpoint = '/foo/service/endpoint.php';\n const fetchRetrier = new MockFetchRetrier();\n const fetchHandler = new FetchHandler({\n apiBaseUrl: 'www.example.com',\n fetchRetrier: fetchRetrier,\n });\n await fetchHandler.fetchApiPathResponse(endpoint);\n expect(fetchRetrier.requestInfo).to.equal(\n 'www.example.com/foo/service/endpoint.php',\n );\n });\n\n it('defaults to no apiBaseUrl', async () => {\n const endpoint = '/foo/service/endpoint.php';\n const fetchRetrier = new MockFetchRetrier();\n const fetchHandler = new FetchHandler({\n fetchRetrier: fetchRetrier,\n });\n await fetchHandler.fetchApiPathResponse(endpoint);\n expect(fetchRetrier.requestInfo).to.equal('/foo/service/endpoint.php');\n });\n });\n\n describe('fetchApiResponse', () => {\n it('adds credentials: include if requested', async () => {\n const endpoint = '/foo/service/endpoint.php';\n const fetchRetrier = new MockFetchRetrier();\n const fetchHandler = new FetchHandler({\n apiBaseUrl: 'www.example.com',\n fetchRetrier: fetchRetrier,\n });\n await fetchHandler.fetchApiResponse(endpoint, {\n includeCredentials: true,\n });\n expect(fetchRetrier.init).to.deep.equal({ credentials: 'include' });\n });\n\n it('passes method, body, and headers to RequestInit', async () => {\n const fetchRetrier = new MockFetchRetrier();\n const fetchHandler = new FetchHandler({ fetchRetrier });\n const body = JSON.stringify({ hello: 'world' });\n await fetchHandler.fetchApiResponse('https://example.org/api', {\n method: 'POST',\n body,\n headers: { 'x-test': '1', 'content-type': 'application/json' },\n });\n expect(fetchRetrier.init).to.deep.equal({\n method: 'POST',\n body,\n headers: { 'x-test': '1', 'content-type': 'application/json' },\n });\n });\n\n it('passes retryConfig through to retrier', async () => {\n const fetchRetrier = new MockFetchRetrier();\n const retryConfig = new NoRetryConfiguration();\n const fetchHandler = new FetchHandler({ fetchRetrier });\n await fetchHandler.fetchApiResponse('https://example.org/api', {\n retryConfig,\n });\n expect(fetchRetrier.retryConfig).to.equal(retryConfig);\n });\n });\n\n describe('fetchIAApiResponse', () => {\n it('is an alias for fetchApiPathResponse', async () => {\n const endpoint = '/foo/service/endpoint.php';\n const fetchRetrier = new MockFetchRetrier();\n const fetchHandler = new IaFetchHandler({\n iaApiBaseUrl: 'www.example.com',\n fetchRetrier: fetchRetrier,\n });\n await fetchHandler.fetchIAApiResponse(endpoint);\n expect(fetchRetrier.requestInfo).to.equal(\n 'www.example.com/foo/service/endpoint.php',\n );\n });\n\n it('defaults the baseUrl to https://archive.org', async () => {\n const endpoint = '/foo/service/endpoint.php';\n const fetchRetrier = new MockFetchRetrier();\n const fetchHandler = new IaFetchHandler({\n fetchRetrier: fetchRetrier,\n });\n await fetchHandler.fetchIAApiResponse(endpoint);\n expect(fetchRetrier.requestInfo).to.equal(\n 'https://archive.org/foo/service/endpoint.php',\n );\n });\n\n it('passes iaApiBaseUrl if provided', async () => {\n const endpoint = '/foo/service/endpoint.php';\n const fetchRetrier = new MockFetchRetrier();\n const fetchHandler = new IaFetchHandler({\n iaApiBaseUrl: 'www.example.com',\n fetchRetrier: fetchRetrier,\n });\n await fetchHandler.fetchIAApiResponse(endpoint);\n expect(fetchRetrier.requestInfo).to.equal(\n 'www.example.com/foo/service/endpoint.php',\n );\n });\n });\n});\n"]}
|
|
@@ -17,7 +17,7 @@ describe('FetchRetrier', () => {
|
|
|
17
17
|
fetchStub.resolves(new Response('ok', { status: 200 }));
|
|
18
18
|
const retrier = new FetchRetrier({
|
|
19
19
|
analyticsHandler: analytics,
|
|
20
|
-
|
|
20
|
+
retryConfig: new MockRetryConfig(),
|
|
21
21
|
});
|
|
22
22
|
const res = await retrier.fetchRetry('https://foo.org/data');
|
|
23
23
|
expect(res.status).to.equal(200);
|
|
@@ -63,7 +63,7 @@ describe('FetchRetrier', () => {
|
|
|
63
63
|
fetchStub.onCall(2).resolves(new Response('still fail', { status: 500 }));
|
|
64
64
|
const retrier = new FetchRetrier({
|
|
65
65
|
analyticsHandler: analytics,
|
|
66
|
-
|
|
66
|
+
retryConfig: new MockRetryConfig(),
|
|
67
67
|
});
|
|
68
68
|
const res = await retrier.fetchRetry('https://foo.org/fail');
|
|
69
69
|
expect(res.status).to.equal(500);
|
|
@@ -76,7 +76,7 @@ describe('FetchRetrier', () => {
|
|
|
76
76
|
fetchStub.onCall(1).resolves(new Response('ok', { status: 200 }));
|
|
77
77
|
const retrier = new FetchRetrier({
|
|
78
78
|
analyticsHandler: analytics,
|
|
79
|
-
|
|
79
|
+
retryConfig: new MockRetryConfig(),
|
|
80
80
|
});
|
|
81
81
|
const res = await retrier.fetchRetry('https://foo.org/retry');
|
|
82
82
|
expect(res.status).to.equal(200);
|
|
@@ -87,7 +87,7 @@ describe('FetchRetrier', () => {
|
|
|
87
87
|
fetchStub.rejects(new Error('Boom'));
|
|
88
88
|
const retrier = new FetchRetrier({
|
|
89
89
|
analyticsHandler: analytics,
|
|
90
|
-
|
|
90
|
+
retryConfig: new MockRetryConfig(),
|
|
91
91
|
});
|
|
92
92
|
try {
|
|
93
93
|
await retrier.fetchRetry('https://foo.org/networkfail');
|
|
@@ -121,7 +121,7 @@ describe('FetchRetrier', () => {
|
|
|
121
121
|
fetchStub.resolves(new Response(null, { status: 500 }));
|
|
122
122
|
const retrier = new FetchRetrier({
|
|
123
123
|
analyticsHandler: analytics,
|
|
124
|
-
|
|
124
|
+
retryConfig: retryConfig,
|
|
125
125
|
});
|
|
126
126
|
const res = await retrier.fetchRetry('https://foo.org/retry-fail');
|
|
127
127
|
expect(res.status).to.equal(500);
|
|
@@ -132,7 +132,7 @@ describe('FetchRetrier', () => {
|
|
|
132
132
|
fetchStub.resolves(new Response('server error', { status: 500 }));
|
|
133
133
|
const retrier = new FetchRetrier({
|
|
134
134
|
analyticsHandler: analytics,
|
|
135
|
-
|
|
135
|
+
retryConfig: new (class {
|
|
136
136
|
shouldRetry() {
|
|
137
137
|
return false;
|
|
138
138
|
}
|
|
@@ -150,7 +150,7 @@ describe('FetchRetrier', () => {
|
|
|
150
150
|
fetchStub.rejects(new Error('Immediate failure'));
|
|
151
151
|
const retrier = new FetchRetrier({
|
|
152
152
|
analyticsHandler: analytics,
|
|
153
|
-
|
|
153
|
+
retryConfig: new (class {
|
|
154
154
|
shouldRetry() {
|
|
155
155
|
return false;
|
|
156
156
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fetch-retrier.test.js","sourceRoot":"","sources":["../../test/fetch-retrier.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { expect } from '@open-wc/testing';\nimport sinon from 'sinon';\nimport { FetchRetrier } from '../src/fetch-retry/fetch-retrier';\nimport { MockAnalyticsHandler } from './mocks/mock-analytics-handler';\nimport { MockRetryConfig } from './mocks/mock-retry-config';\n\ndescribe('FetchRetrier', () => {\n let fetchStub: sinon.SinonStub;\n let analytics: MockAnalyticsHandler;\n\n beforeEach(() => {\n analytics = new MockAnalyticsHandler();\n fetchStub = sinon.stub(globalThis, 'fetch');\n });\n\n afterEach(() => {\n fetchStub.restore();\n });\n\n it('returns response on first success', async () => {\n fetchStub.resolves(new Response('ok', { status: 200 }));\n const retrier = new FetchRetrier({\n analyticsHandler: analytics,\n retryConfiguration: new MockRetryConfig(),\n });\n\n const res = await retrier.fetchRetry('https://foo.org/data');\n\n expect(res.status).to.equal(200);\n expect(fetchStub.callCount).to.equal(1);\n expect(analytics.events.length).to.equal(0);\n });\n\n it('does not retry on 4xx and logs event', async () => {\n fetchStub.resolves(new Response('forbidden', { status: 403 }));\n const retrier = new FetchRetrier({\n analyticsHandler: analytics,\n });\n\n const res = await retrier.fetchRetry('https://foo.org/403');\n\n expect(res.status).to.equal(403);\n expect(fetchStub.callCount).to.equal(1);\n expect(analytics.events[0].action).to.equal('status403Response');\n });\n\n it('does not retry on 404 and logs event', async () => {\n fetchStub.resolves(new Response('not found', { status: 404 }));\n const retrier = new FetchRetrier({\n analyticsHandler: analytics,\n });\n\n const res = await retrier.fetchRetry('https://foo.org/404');\n\n expect(res.status).to.equal(404);\n expect(fetchStub.callCount).to.equal(1);\n expect(analytics.events[0].action).to.equal('status404Response');\n });\n\n it('retries on 4xx if shouldRetry is true in ApiRequestInit', async () => {\n fetchStub.onCall(0).resolves(new Response('bad request', { status: 400 }));\n fetchStub.onCall(1).resolves(new Response('ok', { status: 200 }));\n\n const retrier = new FetchRetrier({\n analyticsHandler: analytics,\n });\n\n const res = await retrier.fetchRetry('https://foo.org/should-retry', {\n retryConfig: new MockRetryConfig(),\n });\n\n expect(res.status).to.equal(200);\n expect(fetchStub.callCount).to.equal(2);\n expect(analytics.events.some(e => e.action === 'retryingFetch')).to.be.true;\n });\n\n it('retries on 500 and logs retry/failure events', async () => {\n fetchStub.onCall(0).resolves(new Response('fail', { status: 500 }));\n fetchStub.onCall(1).resolves(new Response('fail again', { status: 500 }));\n fetchStub.onCall(2).resolves(new Response('still fail', { status: 500 }));\n\n const retrier = new FetchRetrier({\n analyticsHandler: analytics,\n retryConfiguration: new MockRetryConfig(),\n });\n\n const res = await retrier.fetchRetry('https://foo.org/fail');\n\n expect(res.status).to.equal(500);\n expect(fetchStub.callCount).to.equal(3);\n expect(analytics.events.some(e => e.action === 'retryingFetch')).to.be.true;\n expect(analytics.events.some(e => e.action === 'fetchFailed')).to.be.true;\n });\n\n it('retries on fetch error and eventually succeeds', async () => {\n fetchStub.onCall(0).rejects(new Error('Network error'));\n fetchStub.onCall(1).resolves(new Response('ok', { status: 200 }));\n\n const retrier = new FetchRetrier({\n analyticsHandler: analytics,\n retryConfiguration: new MockRetryConfig(),\n });\n\n const res = await retrier.fetchRetry('https://foo.org/retry');\n\n expect(res.status).to.equal(200);\n expect(fetchStub.callCount).to.equal(2);\n expect(analytics.events.some(e => e.action === 'retryingFetch')).to.be.true;\n });\n\n it('throws and logs when retries are exhausted due to network error', async () => {\n fetchStub.rejects(new Error('Boom'));\n\n const retrier = new FetchRetrier({\n analyticsHandler: analytics,\n retryConfiguration: new MockRetryConfig(),\n });\n\n try {\n await retrier.fetchRetry('https://foo.org/networkfail');\n throw new Error('Should have thrown');\n } catch (err: unknown) {\n expect((err as Error).message).to.equal('Boom');\n }\n\n expect(fetchStub.callCount).to.equal(3);\n expect(analytics.events.some(e => e.action === 'fetchFailed')).to.be.true;\n });\n\n it('detects content blocker error and does not retry', async () => {\n const blockerError = new TypeError('Content Blocker denied request');\n fetchStub.rejects(blockerError);\n\n const retrier = new FetchRetrier({\n analyticsHandler: analytics,\n });\n\n try {\n await retrier.fetchRetry('https://foo.org/blocked');\n throw new Error('Should have thrown');\n } catch (err: unknown) {\n expect(err).to.equal(blockerError);\n }\n\n expect(fetchStub.callCount).to.equal(1);\n expect(\n analytics.events.some(\n e => e.action === 'contentBlockerDetectedNotRetrying',\n ),\n ).to.be.true;\n });\n\n it('sleeps for each retry attempt', async () => {\n const retryConfig = new MockRetryConfig();\n const retryDelaySpy = sinon.spy(retryConfig, 'retryDelay');\n fetchStub.resolves(new Response(null, { status: 500 }));\n\n const retrier = new FetchRetrier({\n analyticsHandler: analytics,\n retryConfiguration: retryConfig,\n });\n\n const res = await retrier.fetchRetry('https://foo.org/retry-fail');\n\n expect(res.status).to.equal(500);\n expect(fetchStub.callCount).to.equal(3);\n expect(retryDelaySpy.callCount).to.equal(2);\n });\n\n it('does not retry 5xx when NoRetryConfiguration is used', async () => {\n fetchStub.resolves(new Response('server error', { status: 500 }));\n const retrier = new FetchRetrier({\n analyticsHandler: analytics,\n retryConfiguration: new (class {\n shouldRetry() {\n return false;\n }\n retryDelay() {\n return 0;\n }\n })(),\n });\n\n const res = await retrier.fetchRetry('https://foo.org/no-retry-500');\n expect(res.status).to.equal(500);\n expect(fetchStub.callCount).to.equal(1);\n expect(analytics.events.some(e => e.action === 'fetchFailed')).to.be.true;\n });\n\n it('does not retry on error when configuration disables retries', async () => {\n fetchStub.rejects(new Error('Immediate failure'));\n const retrier = new FetchRetrier({\n analyticsHandler: analytics,\n retryConfiguration: new (class {\n shouldRetry() {\n return false;\n }\n retryDelay() {\n return 0;\n }\n })(),\n });\n\n try {\n await retrier.fetchRetry('https://foo.org/no-retry-error');\n throw new Error('Should have thrown');\n } catch (err: unknown) {\n expect((err as Error).message).to.equal('Immediate failure');\n }\n\n expect(fetchStub.callCount).to.equal(1);\n expect(analytics.events.some(e => e.action === 'fetchFailed')).to.be.true;\n });\n});\n"]}
|
|
1
|
+
{"version":3,"file":"fetch-retrier.test.js","sourceRoot":"","sources":["../../test/fetch-retrier.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { expect } from '@open-wc/testing';\nimport sinon from 'sinon';\nimport { FetchRetrier } from '../src/fetch-retry/fetch-retrier';\nimport { MockAnalyticsHandler } from './mocks/mock-analytics-handler';\nimport { MockRetryConfig } from './mocks/mock-retry-config';\n\ndescribe('FetchRetrier', () => {\n let fetchStub: sinon.SinonStub;\n let analytics: MockAnalyticsHandler;\n\n beforeEach(() => {\n analytics = new MockAnalyticsHandler();\n fetchStub = sinon.stub(globalThis, 'fetch');\n });\n\n afterEach(() => {\n fetchStub.restore();\n });\n\n it('returns response on first success', async () => {\n fetchStub.resolves(new Response('ok', { status: 200 }));\n const retrier = new FetchRetrier({\n analyticsHandler: analytics,\n retryConfig: new MockRetryConfig(),\n });\n\n const res = await retrier.fetchRetry('https://foo.org/data');\n\n expect(res.status).to.equal(200);\n expect(fetchStub.callCount).to.equal(1);\n expect(analytics.events.length).to.equal(0);\n });\n\n it('does not retry on 4xx and logs event', async () => {\n fetchStub.resolves(new Response('forbidden', { status: 403 }));\n const retrier = new FetchRetrier({\n analyticsHandler: analytics,\n });\n\n const res = await retrier.fetchRetry('https://foo.org/403');\n\n expect(res.status).to.equal(403);\n expect(fetchStub.callCount).to.equal(1);\n expect(analytics.events[0].action).to.equal('status403Response');\n });\n\n it('does not retry on 404 and logs event', async () => {\n fetchStub.resolves(new Response('not found', { status: 404 }));\n const retrier = new FetchRetrier({\n analyticsHandler: analytics,\n });\n\n const res = await retrier.fetchRetry('https://foo.org/404');\n\n expect(res.status).to.equal(404);\n expect(fetchStub.callCount).to.equal(1);\n expect(analytics.events[0].action).to.equal('status404Response');\n });\n\n it('retries on 4xx if shouldRetry is true in ApiRequestInit', async () => {\n fetchStub.onCall(0).resolves(new Response('bad request', { status: 400 }));\n fetchStub.onCall(1).resolves(new Response('ok', { status: 200 }));\n\n const retrier = new FetchRetrier({\n analyticsHandler: analytics,\n });\n\n const res = await retrier.fetchRetry('https://foo.org/should-retry', {\n retryConfig: new MockRetryConfig(),\n });\n\n expect(res.status).to.equal(200);\n expect(fetchStub.callCount).to.equal(2);\n expect(analytics.events.some(e => e.action === 'retryingFetch')).to.be.true;\n });\n\n it('retries on 500 and logs retry/failure events', async () => {\n fetchStub.onCall(0).resolves(new Response('fail', { status: 500 }));\n fetchStub.onCall(1).resolves(new Response('fail again', { status: 500 }));\n fetchStub.onCall(2).resolves(new Response('still fail', { status: 500 }));\n\n const retrier = new FetchRetrier({\n analyticsHandler: analytics,\n retryConfig: new MockRetryConfig(),\n });\n\n const res = await retrier.fetchRetry('https://foo.org/fail');\n\n expect(res.status).to.equal(500);\n expect(fetchStub.callCount).to.equal(3);\n expect(analytics.events.some(e => e.action === 'retryingFetch')).to.be.true;\n expect(analytics.events.some(e => e.action === 'fetchFailed')).to.be.true;\n });\n\n it('retries on fetch error and eventually succeeds', async () => {\n fetchStub.onCall(0).rejects(new Error('Network error'));\n fetchStub.onCall(1).resolves(new Response('ok', { status: 200 }));\n\n const retrier = new FetchRetrier({\n analyticsHandler: analytics,\n retryConfig: new MockRetryConfig(),\n });\n\n const res = await retrier.fetchRetry('https://foo.org/retry');\n\n expect(res.status).to.equal(200);\n expect(fetchStub.callCount).to.equal(2);\n expect(analytics.events.some(e => e.action === 'retryingFetch')).to.be.true;\n });\n\n it('throws and logs when retries are exhausted due to network error', async () => {\n fetchStub.rejects(new Error('Boom'));\n\n const retrier = new FetchRetrier({\n analyticsHandler: analytics,\n retryConfig: new MockRetryConfig(),\n });\n\n try {\n await retrier.fetchRetry('https://foo.org/networkfail');\n throw new Error('Should have thrown');\n } catch (err: unknown) {\n expect((err as Error).message).to.equal('Boom');\n }\n\n expect(fetchStub.callCount).to.equal(3);\n expect(analytics.events.some(e => e.action === 'fetchFailed')).to.be.true;\n });\n\n it('detects content blocker error and does not retry', async () => {\n const blockerError = new TypeError('Content Blocker denied request');\n fetchStub.rejects(blockerError);\n\n const retrier = new FetchRetrier({\n analyticsHandler: analytics,\n });\n\n try {\n await retrier.fetchRetry('https://foo.org/blocked');\n throw new Error('Should have thrown');\n } catch (err: unknown) {\n expect(err).to.equal(blockerError);\n }\n\n expect(fetchStub.callCount).to.equal(1);\n expect(\n analytics.events.some(\n e => e.action === 'contentBlockerDetectedNotRetrying',\n ),\n ).to.be.true;\n });\n\n it('sleeps for each retry attempt', async () => {\n const retryConfig = new MockRetryConfig();\n const retryDelaySpy = sinon.spy(retryConfig, 'retryDelay');\n fetchStub.resolves(new Response(null, { status: 500 }));\n\n const retrier = new FetchRetrier({\n analyticsHandler: analytics,\n retryConfig: retryConfig,\n });\n\n const res = await retrier.fetchRetry('https://foo.org/retry-fail');\n\n expect(res.status).to.equal(500);\n expect(fetchStub.callCount).to.equal(3);\n expect(retryDelaySpy.callCount).to.equal(2);\n });\n\n it('does not retry 5xx when NoRetryConfiguration is used', async () => {\n fetchStub.resolves(new Response('server error', { status: 500 }));\n const retrier = new FetchRetrier({\n analyticsHandler: analytics,\n retryConfig: new (class {\n shouldRetry() {\n return false;\n }\n retryDelay() {\n return 0;\n }\n })(),\n });\n\n const res = await retrier.fetchRetry('https://foo.org/no-retry-500');\n expect(res.status).to.equal(500);\n expect(fetchStub.callCount).to.equal(1);\n expect(analytics.events.some(e => e.action === 'fetchFailed')).to.be.true;\n });\n\n it('does not retry on error when configuration disables retries', async () => {\n fetchStub.rejects(new Error('Immediate failure'));\n const retrier = new FetchRetrier({\n analyticsHandler: analytics,\n retryConfig: new (class {\n shouldRetry() {\n return false;\n }\n retryDelay() {\n return 0;\n }\n })(),\n });\n\n try {\n await retrier.fetchRetry('https://foo.org/no-retry-error');\n throw new Error('Should have thrown');\n } catch (err: unknown) {\n expect((err as Error).message).to.equal('Immediate failure');\n }\n\n expect(fetchStub.callCount).to.equal(1);\n expect(analytics.events.some(e => e.action === 'fetchFailed')).to.be.true;\n });\n});\n"]}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { expect } from '@open-wc/testing';
|
|
2
2
|
import { legacyArgsAsFetchOptions } from '../src/fetch-retry/legacy-args';
|
|
3
|
+
import { MockRetryConfig } from './mocks/mock-retry-config';
|
|
3
4
|
describe('legacyArgsAsFetchOptions', () => {
|
|
4
5
|
it('wraps RequestInit into FetchOptions', () => {
|
|
5
6
|
const init = { method: 'PUT' };
|
|
@@ -7,8 +8,10 @@ describe('legacyArgsAsFetchOptions', () => {
|
|
|
7
8
|
expect(fo).to.deep.equal({ requestInit: init });
|
|
8
9
|
});
|
|
9
10
|
it('returns FetchOptions unchanged', () => {
|
|
11
|
+
const retryConfig = new MockRetryConfig();
|
|
10
12
|
const options = {
|
|
11
13
|
requestInit: { headers: { foo: 'bar' } },
|
|
14
|
+
retryConfig: retryConfig,
|
|
12
15
|
};
|
|
13
16
|
const fo = legacyArgsAsFetchOptions(options);
|
|
14
17
|
expect(fo).to.equal(options);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"legacy-args.test.js","sourceRoot":"","sources":["../../test/legacy-args.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAC1C,OAAO,EAAE,wBAAwB,EAAE,MAAM,gCAAgC,CAAC;
|
|
1
|
+
{"version":3,"file":"legacy-args.test.js","sourceRoot":"","sources":["../../test/legacy-args.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAC1C,OAAO,EAAE,wBAAwB,EAAE,MAAM,gCAAgC,CAAC;AAE1E,OAAO,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAC;AAE5D,QAAQ,CAAC,0BAA0B,EAAE,GAAG,EAAE;IACxC,EAAE,CAAC,qCAAqC,EAAE,GAAG,EAAE;QAC7C,MAAM,IAAI,GAAgB,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC;QAC5C,MAAM,EAAE,GAAG,wBAAwB,CAAC,IAAI,CAAC,CAAC;QAC1C,MAAM,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,WAAW,EAAE,IAAI,EAAE,CAAC,CAAC;IAClD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,gCAAgC,EAAE,GAAG,EAAE;QACxC,MAAM,WAAW,GAAG,IAAI,eAAe,EAAE,CAAC;QAC1C,MAAM,OAAO,GAAiB;YAC5B,WAAW,EAAE,EAAE,OAAO,EAAE,EAAE,GAAG,EAAE,KAAK,EAAE,EAAE;YACxC,WAAW,EAAE,WAAW;SACzB,CAAC;QACF,MAAM,EAAE,GAAG,wBAAwB,CAAC,OAAO,CAAC,CAAC;QAC7C,MAAM,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IAC/B,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,4CAA4C,EAAE,GAAG,EAAE;QACpD,MAAM,EAAE,GAAG,wBAAwB,CAAC,SAAS,CAAC,CAAC;QAC/C,MAAM,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;IACjC,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC","sourcesContent":["import { expect } from '@open-wc/testing';\nimport { legacyArgsAsFetchOptions } from '../src/fetch-retry/legacy-args';\nimport type { FetchOptions } from '../src/fetch-options';\nimport { MockRetryConfig } from './mocks/mock-retry-config';\n\ndescribe('legacyArgsAsFetchOptions', () => {\n it('wraps RequestInit into FetchOptions', () => {\n const init: RequestInit = { method: 'PUT' };\n const fo = legacyArgsAsFetchOptions(init);\n expect(fo).to.deep.equal({ requestInit: init });\n });\n\n it('returns FetchOptions unchanged', () => {\n const retryConfig = new MockRetryConfig();\n const options: FetchOptions = {\n requestInit: { headers: { foo: 'bar' } },\n retryConfig: retryConfig,\n };\n const fo = legacyArgsAsFetchOptions(options);\n expect(fo).to.equal(options);\n });\n\n it('returns undefined when no options provided', () => {\n const fo = legacyArgsAsFetchOptions(undefined);\n expect(fo).to.equal(undefined);\n });\n});\n"]}
|
|
@@ -2,6 +2,6 @@ import type { RetryConfiguring } from '../../src/fetch-retry/configuration/retry
|
|
|
2
2
|
export declare class MockRetryConfig implements RetryConfiguring {
|
|
3
3
|
mockRetryCount: number;
|
|
4
4
|
mockRetryDelay: number;
|
|
5
|
-
shouldRetry(response: Response | null, retryNumber: number
|
|
5
|
+
shouldRetry(response: Response | null, retryNumber: number): boolean;
|
|
6
6
|
retryDelay(): number;
|
|
7
7
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mock-retry-config.js","sourceRoot":"","sources":["../../../test/mocks/mock-retry-config.ts"],"names":[],"mappings":"AAEA,MAAM,OAAO,eAAe;IAA5B;QACE,mBAAc,GAAW,CAAC,CAAC;QAE3B,mBAAc,GAAW,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"mock-retry-config.js","sourceRoot":"","sources":["../../../test/mocks/mock-retry-config.ts"],"names":[],"mappings":"AAEA,MAAM,OAAO,eAAe;IAA5B;QACE,mBAAc,GAAW,CAAC,CAAC;QAE3B,mBAAc,GAAW,CAAC,CAAC;IAS7B,CAAC;IAPC,WAAW,CAAC,QAAyB,EAAE,WAAmB;QACxD,OAAO,WAAW,GAAG,IAAI,CAAC,cAAc,CAAC;IAC3C,CAAC;IAED,UAAU;QACR,OAAO,IAAI,CAAC,cAAc,CAAC;IAC7B,CAAC;CACF","sourcesContent":["import type { RetryConfiguring } from '../../src/fetch-retry/configuration/retry-configuring';\n\nexport class MockRetryConfig implements RetryConfiguring {\n mockRetryCount: number = 2;\n\n mockRetryDelay: number = 0;\n\n shouldRetry(response: Response | null, retryNumber: number): boolean {\n return retryNumber < this.mockRetryCount;\n }\n\n retryDelay(): number {\n return this.mockRetryDelay;\n }\n}\n"]}
|
|
@@ -7,7 +7,7 @@ describe('NoRetryConfiguration', () => {
|
|
|
7
7
|
});
|
|
8
8
|
it('has no delay', async () => {
|
|
9
9
|
const config = new NoRetryConfiguration();
|
|
10
|
-
expect(config.retryDelay()).to.
|
|
10
|
+
expect(config.retryDelay()).to.be.null;
|
|
11
11
|
});
|
|
12
12
|
});
|
|
13
13
|
//# sourceMappingURL=no-retry-config.test.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"no-retry-config.test.js","sourceRoot":"","sources":["../../test/no-retry-config.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAC1C,OAAO,EAAE,oBAAoB,EAAE,MAAM,yDAAyD,CAAC;AAE/F,QAAQ,CAAC,sBAAsB,EAAE,GAAG,EAAE;IACpC,EAAE,CAAC,kBAAkB,EAAE,KAAK,IAAI,EAAE;QAChC,MAAM,MAAM,GAAG,IAAI,oBAAoB,EAAE,CAAC;QAC1C,MAAM,CAAC,MAAM,CAAC,WAAW,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC;IAC3C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,cAAc,EAAE,KAAK,IAAI,EAAE;QAC5B,MAAM,MAAM,GAAG,IAAI,oBAAoB,EAAE,CAAC;QAC1C,MAAM,CAAC,MAAM,CAAC,UAAU,EAAE,CAAC,CAAC,EAAE,CAAC,
|
|
1
|
+
{"version":3,"file":"no-retry-config.test.js","sourceRoot":"","sources":["../../test/no-retry-config.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAC1C,OAAO,EAAE,oBAAoB,EAAE,MAAM,yDAAyD,CAAC;AAE/F,QAAQ,CAAC,sBAAsB,EAAE,GAAG,EAAE;IACpC,EAAE,CAAC,kBAAkB,EAAE,KAAK,IAAI,EAAE;QAChC,MAAM,MAAM,GAAG,IAAI,oBAAoB,EAAE,CAAC;QAC1C,MAAM,CAAC,MAAM,CAAC,WAAW,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC;IAC3C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,cAAc,EAAE,KAAK,IAAI,EAAE;QAC5B,MAAM,MAAM,GAAG,IAAI,oBAAoB,EAAE,CAAC;QAC1C,MAAM,CAAC,MAAM,CAAC,UAAU,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC;IACzC,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC","sourcesContent":["import { expect } from '@open-wc/testing';\nimport { NoRetryConfiguration } from '../src/fetch-retry/configuration/no-retry-configuration';\n\ndescribe('NoRetryConfiguration', () => {\n it('should not retry', async () => {\n const config = new NoRetryConfiguration();\n expect(config.shouldRetry()).to.be.false;\n });\n\n it('has no delay', async () => {\n const config = new NoRetryConfiguration();\n expect(config.retryDelay()).to.be.null;\n });\n});\n"]}
|
package/index.ts
CHANGED
|
@@ -1,11 +1,13 @@
|
|
|
1
|
-
export { IaFetchHandler } from './src/fetch-handler';
|
|
2
|
-
export { FetchHandlerInterface } from './src/fetch-handler-interface';
|
|
1
|
+
export { FetchHandler, IaFetchHandler } from './src/fetch-handler';
|
|
2
|
+
export type { FetchHandlerInterface } from './src/fetch-handler-interface';
|
|
3
|
+
export type { FetchOptions } from './src/fetch-options';
|
|
4
|
+
export type { Milliseconds } from './src/fetch-retry/configuration/milliseconds';
|
|
5
|
+
|
|
6
|
+
export { FetchRetryConfig } from './src/fetch-retry/configuration/configurations';
|
|
7
|
+
export { DefaultRetryConfiguration } from './src/fetch-retry/configuration/default-retry-configuration';
|
|
8
|
+
export { NoRetryConfiguration } from './src/fetch-retry/configuration/no-retry-configuration';
|
|
9
|
+
export type { RetryConfiguring } from './src/fetch-retry/configuration/retry-configuring';
|
|
3
10
|
export {
|
|
4
11
|
FetchRetrier,
|
|
5
12
|
FetchRetrierInterface,
|
|
6
13
|
} from './src/fetch-retry/fetch-retrier';
|
|
7
|
-
export { DefaultRetryConfiguration } from './src/fetch-retry/configuration/default-retry-configuration';
|
|
8
|
-
export { NoRetryConfiguration } from './src/fetch-retry/configuration/no-retry-configuration';
|
|
9
|
-
export type { RetryConfiguring } from './src/fetch-retry/configuration/retry-configuring';
|
|
10
|
-
export type { FetchOptions } from './src/fetch-options';
|
|
11
|
-
export { FetchRetryConfig } from './src/fetch-retry/configuration/configurations';
|
package/package.json
CHANGED
|
@@ -36,14 +36,28 @@ export interface FetchHandlerInterface {
|
|
|
36
36
|
* This allows you to just pass the path to the API and get the response instead
|
|
37
37
|
* of the full URL. If you need a full URL, use `fetchApiResponse` instead.
|
|
38
38
|
*
|
|
39
|
-
*
|
|
40
|
-
*
|
|
41
|
-
*
|
|
42
|
-
*
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
39
|
+
* ie `fetchApiPathResponse('/items/123')` will fetch from `${apiBaseUrl}/items/123`
|
|
40
|
+
*
|
|
41
|
+
* @param path - Path to API endpoint
|
|
42
|
+
* @param options - Options including credentials, method, body, headers, and retryConfig
|
|
43
|
+
*/
|
|
44
|
+
fetchApiPathResponse<T>(
|
|
45
|
+
path: string,
|
|
46
|
+
options?: {
|
|
47
|
+
includeCredentials?: boolean;
|
|
48
|
+
method?: string;
|
|
49
|
+
body?: BodyInit;
|
|
50
|
+
headers?: HeadersInit;
|
|
51
|
+
retryConfig?: RetryConfiguring;
|
|
52
|
+
},
|
|
53
|
+
): Promise<T>;
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Fetch a response from the IA API by path
|
|
57
|
+
*
|
|
58
|
+
* @deprecated Use `fetchApiPathResponse` instead.
|
|
59
|
+
* @param path - Path to API endpoint
|
|
60
|
+
* @param options - Options including credentials, method, body, headers, and retryConfig
|
|
47
61
|
*/
|
|
48
62
|
fetchIAApiResponse<T>(
|
|
49
63
|
path: string,
|