@internetarchive/fetch-handler 1.1.0-webdev-7731.9 → 1.1.0-webdev-7731.11

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/dist/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
- export { FetchHandler, IaFetchHandler } from './src/fetch-handler';
1
+ export { FetchHandler, IaFetchHandler, type FetchHandlerConstructorOptions, } from './src/fetch-handler';
2
2
  export type { FetchHandlerInterface } from './src/fetch-handler-interface';
3
- export type { FetchOptions } from './src/fetch-options';
3
+ export type { ApiFetchOptions, FetchOptions } from './src/fetch-options';
4
4
  export type { Milliseconds } from './src/fetch-retry/configuration/milliseconds';
5
5
  export { FetchRetryConfig } from './src/fetch-retry/configuration/configurations';
6
6
  export { DefaultRetryConfiguration } from './src/fetch-retry/configuration/default-retry-configuration';
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- export { FetchHandler, IaFetchHandler } from './src/fetch-handler';
1
+ export { FetchHandler, IaFetchHandler, } from './src/fetch-handler';
2
2
  export { FetchRetryConfig } from './src/fetch-retry/configuration/configurations';
3
3
  export { DefaultRetryConfiguration } from './src/fetch-retry/configuration/default-retry-configuration';
4
4
  export { NoRetryConfiguration } from './src/fetch-retry/configuration/no-retry-configuration';
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAKnE,OAAO,EAAE,gBAAgB,EAAE,MAAM,gDAAgD,CAAC;AAClF,OAAO,EAAE,yBAAyB,EAAE,MAAM,6DAA6D,CAAC;AACxG,OAAO,EAAE,oBAAoB,EAAE,MAAM,wDAAwD,CAAC;AAE9F,OAAO,EACL,YAAY,GAEb,MAAM,iCAAiC,CAAC","sourcesContent":["export { FetchHandler, IaFetchHandler } from './src/fetch-handler';\nexport type { FetchHandlerInterface } from './src/fetch-handler-interface';\nexport type { FetchOptions } from './src/fetch-options';\nexport type { Milliseconds } from './src/fetch-retry/configuration/milliseconds';\n\nexport { FetchRetryConfig } from './src/fetch-retry/configuration/configurations';\nexport { DefaultRetryConfiguration } from './src/fetch-retry/configuration/default-retry-configuration';\nexport { NoRetryConfiguration } from './src/fetch-retry/configuration/no-retry-configuration';\nexport type { RetryConfiguring } from './src/fetch-retry/configuration/retry-configuring';\nexport {\n FetchRetrier,\n FetchRetrierInterface,\n} from './src/fetch-retry/fetch-retrier';\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,YAAY,EACZ,cAAc,GAEf,MAAM,qBAAqB,CAAC;AAK7B,OAAO,EAAE,gBAAgB,EAAE,MAAM,gDAAgD,CAAC;AAClF,OAAO,EAAE,yBAAyB,EAAE,MAAM,6DAA6D,CAAC;AACxG,OAAO,EAAE,oBAAoB,EAAE,MAAM,wDAAwD,CAAC;AAE9F,OAAO,EACL,YAAY,GAEb,MAAM,iCAAiC,CAAC","sourcesContent":["export {\n FetchHandler,\n IaFetchHandler,\n type FetchHandlerConstructorOptions,\n} from './src/fetch-handler';\nexport type { FetchHandlerInterface } from './src/fetch-handler-interface';\nexport type { ApiFetchOptions, FetchOptions } from './src/fetch-options';\nexport type { Milliseconds } from './src/fetch-retry/configuration/milliseconds';\n\nexport { FetchRetryConfig } from './src/fetch-retry/configuration/configurations';\nexport { DefaultRetryConfiguration } from './src/fetch-retry/configuration/default-retry-configuration';\nexport { NoRetryConfiguration } from './src/fetch-retry/configuration/no-retry-configuration';\nexport type { RetryConfiguring } from './src/fetch-retry/configuration/retry-configuring';\nexport {\n FetchRetrier,\n FetchRetrierInterface,\n} from './src/fetch-retry/fetch-retrier';\n"]}
@@ -1,5 +1,4 @@
1
- import type { FetchOptions } from './fetch-options';
2
- import type { RetryConfiguring } from './fetch-retry/configuration/retry-configuring';
1
+ import type { ApiFetchOptions, FetchOptions } from './fetch-options';
3
2
  export interface FetchHandlerInterface {
4
3
  /**
5
4
  * Generic fetch function that handles retries and common IA parameters like `reCache=1`
@@ -12,15 +11,9 @@ export interface FetchHandlerInterface {
12
11
  * A helper function to fetch a response from an API and get a JSON object
13
12
  *
14
13
  * @param path string
15
- * @param options?: { includeCredentials?: boolean }
14
+ * @param options?: ApiFetchOptions
16
15
  */
17
- fetchApiResponse<T>(url: string, options?: {
18
- includeCredentials?: boolean;
19
- method?: string;
20
- body?: BodyInit;
21
- headers?: HeadersInit;
22
- retryConfig?: RetryConfiguring;
23
- }): Promise<T>;
16
+ fetchApiResponse<T>(url: string, options?: ApiFetchOptions): Promise<T>;
24
17
  /**
25
18
  * A helper function to fetch a response from the IA API and get a JSON object
26
19
  *
@@ -30,27 +23,15 @@ export interface FetchHandlerInterface {
30
23
  * ie `fetchApiPathResponse('/items/123')` will fetch from `${apiBaseUrl}/items/123`
31
24
  *
32
25
  * @param path - Path to API endpoint
33
- * @param options - Options including credentials, method, body, headers, and retryConfig
26
+ * @param options - ApiFetchOptions
34
27
  */
35
- fetchApiPathResponse<T>(path: string, options?: {
36
- includeCredentials?: boolean;
37
- method?: string;
38
- body?: BodyInit;
39
- headers?: HeadersInit;
40
- retryConfig?: RetryConfiguring;
41
- }): Promise<T>;
28
+ fetchApiPathResponse<T>(path: string, options?: ApiFetchOptions): Promise<T>;
42
29
  /**
43
30
  * Fetch a response from the IA API by path
44
31
  *
45
32
  * @deprecated Use `fetchApiPathResponse` instead.
46
33
  * @param path - Path to API endpoint
47
- * @param options - Options including credentials, method, body, headers, and retryConfig
34
+ * @param options - ApiFetchOptions
48
35
  */
49
- fetchIAApiResponse<T>(path: string, options?: {
50
- includeCredentials?: boolean;
51
- method?: string;
52
- body?: BodyInit;
53
- headers?: HeadersInit;
54
- retryConfig?: RetryConfiguring;
55
- }): Promise<T>;
36
+ fetchIAApiResponse<T>(path: string, options?: ApiFetchOptions): Promise<T>;
56
37
  }
@@ -1 +1 @@
1
- {"version":3,"file":"fetch-handler-interface.js","sourceRoot":"","sources":["../../src/fetch-handler-interface.ts"],"names":[],"mappings":"","sourcesContent":["import type { FetchOptions } from './fetch-options';\nimport type { RetryConfiguring } from './fetch-retry/configuration/retry-configuring';\n\nexport interface FetchHandlerInterface {\n /**\n * Generic fetch function that handles retries and common IA parameters like `reCache=1`\n *\n * @param input RequestInfo\n * @param options RequestInit | FetchOptions\n */\n fetch(\n request: RequestInfo,\n options?: RequestInit | FetchOptions,\n ): Promise<Response>;\n\n /**\n * A helper function to fetch a response from an API and get a JSON object\n *\n * @param path string\n * @param options?: { includeCredentials?: boolean }\n */\n fetchApiResponse<T>(\n url: string,\n options?: {\n includeCredentials?: boolean;\n method?: string;\n body?: BodyInit;\n headers?: HeadersInit;\n retryConfig?: RetryConfiguring;\n },\n ): Promise<T>;\n\n /**\n * A helper function to fetch a response from the IA API and get a JSON object\n *\n * This allows you to just pass the path to the API and get the response instead\n * of the full URL. If you need a full URL, use `fetchApiResponse` instead.\n *\n * ie `fetchApiPathResponse('/items/123')` will fetch from `${apiBaseUrl}/items/123`\n *\n * @param path - Path to API endpoint\n * @param options - Options including credentials, method, body, headers, and retryConfig\n */\n fetchApiPathResponse<T>(\n path: string,\n options?: {\n includeCredentials?: boolean;\n method?: string;\n body?: BodyInit;\n headers?: HeadersInit;\n retryConfig?: RetryConfiguring;\n },\n ): Promise<T>;\n\n /**\n * Fetch a response from the IA API by path\n *\n * @deprecated Use `fetchApiPathResponse` instead.\n * @param path - Path to API endpoint\n * @param options - Options including credentials, method, body, headers, and retryConfig\n */\n fetchIAApiResponse<T>(\n path: string,\n options?: {\n includeCredentials?: boolean;\n method?: string;\n body?: BodyInit;\n headers?: HeadersInit;\n retryConfig?: RetryConfiguring;\n },\n ): Promise<T>;\n}\n"]}
1
+ {"version":3,"file":"fetch-handler-interface.js","sourceRoot":"","sources":["../../src/fetch-handler-interface.ts"],"names":[],"mappings":"","sourcesContent":["import type { ApiFetchOptions, FetchOptions } from './fetch-options';\n\nexport interface FetchHandlerInterface {\n /**\n * Generic fetch function that handles retries and common IA parameters like `reCache=1`\n *\n * @param input RequestInfo\n * @param options RequestInit | FetchOptions\n */\n fetch(\n request: RequestInfo,\n options?: RequestInit | FetchOptions,\n ): Promise<Response>;\n\n /**\n * A helper function to fetch a response from an API and get a JSON object\n *\n * @param path string\n * @param options?: ApiFetchOptions\n */\n fetchApiResponse<T>(url: string, options?: ApiFetchOptions): Promise<T>;\n\n /**\n * A helper function to fetch a response from the IA API and get a JSON object\n *\n * This allows you to just pass the path to the API and get the response instead\n * of the full URL. If you need a full URL, use `fetchApiResponse` instead.\n *\n * ie `fetchApiPathResponse('/items/123')` will fetch from `${apiBaseUrl}/items/123`\n *\n * @param path - Path to API endpoint\n * @param options - ApiFetchOptions\n */\n fetchApiPathResponse<T>(path: string, options?: ApiFetchOptions): Promise<T>;\n\n /**\n * Fetch a response from the IA API by path\n *\n * @deprecated Use `fetchApiPathResponse` instead.\n * @param path - Path to API endpoint\n * @param options - ApiFetchOptions\n */\n fetchIAApiResponse<T>(path: string, options?: ApiFetchOptions): Promise<T>;\n}\n"]}
@@ -1,7 +1,13 @@
1
1
  import { FetchRetrierInterface } from './fetch-retry/fetch-retrier';
2
2
  import type { FetchHandlerInterface } from './fetch-handler-interface';
3
- import type { FetchOptions } from './fetch-options';
4
- import type { RetryConfiguring } from './fetch-retry/configuration/retry-configuring';
3
+ import type { ApiFetchOptions, FetchOptions } from './fetch-options';
4
+ export type FetchHandlerConstructorOptions = {
5
+ /** @deprecated Use `apiBaseUrl` instead. */
6
+ iaApiBaseUrl?: string;
7
+ apiBaseUrl?: string;
8
+ fetchRetrier?: FetchRetrierInterface;
9
+ searchParams?: string;
10
+ };
5
11
  /**
6
12
  * The FetchHandler adds some common helpers:
7
13
  * - retry the request if it fails
@@ -12,49 +18,21 @@ export declare class FetchHandler implements FetchHandlerInterface {
12
18
  private apiBaseUrl;
13
19
  private fetchRetrier;
14
20
  private searchParams?;
15
- /**
16
- *
17
- * @param options {
18
- * iaApiBaseUrl - deprecated Use `apiBaseUrl` instead.
19
- * apiBaseUrl - The base URL for API requests for `fetchApiPathResponse`
20
- * fetchRetrier - FetchRetrier to use instead of the default
21
- * searchParams - Search params to check for `reCache=1` (defaults to current window location)
22
- */
23
- constructor(options?: {
24
- iaApiBaseUrl?: string;
25
- apiBaseUrl?: string;
26
- fetchRetrier?: FetchRetrierInterface;
27
- searchParams?: string;
28
- });
21
+ constructor(options?: FetchHandlerConstructorOptions);
29
22
  /** @inheritdoc */
30
- fetchApiPathResponse<T>(path: string, options?: {
31
- includeCredentials?: boolean;
32
- method?: string;
33
- body?: BodyInit;
34
- headers?: HeadersInit;
35
- retryConfig?: RetryConfiguring;
36
- }): Promise<T>;
23
+ fetch(request: RequestInfo, options?: RequestInit | FetchOptions): Promise<Response>;
37
24
  /** @inheritdoc */
38
- fetchIAApiResponse<T>(path: string, options?: {
39
- includeCredentials?: boolean;
40
- method?: string;
41
- body?: BodyInit;
42
- headers?: HeadersInit;
43
- retryConfig?: RetryConfiguring;
44
- }): Promise<T>;
25
+ fetchApiResponse<T>(url: string, options?: ApiFetchOptions): Promise<T>;
45
26
  /** @inheritdoc */
46
- fetchApiResponse<T>(url: string, options?: {
47
- includeCredentials?: boolean;
48
- method?: string;
49
- body?: BodyInit;
50
- headers?: HeadersInit;
51
- retryConfig?: RetryConfiguring;
52
- }): Promise<T>;
27
+ fetchApiPathResponse<T>(path: string, options?: ApiFetchOptions): Promise<T>;
53
28
  /** @inheritdoc */
54
- fetch(request: RequestInfo, options?: RequestInit | FetchOptions): Promise<Response>;
29
+ fetchIAApiResponse<T>(path: string, options?: ApiFetchOptions): Promise<T>;
55
30
  /**
56
- * Since RequestInfo can be either a `Request` or `string`, we need to change
57
- * the way we add search params to it depending on the input.
31
+ * Construct a new URL with the given search params added
32
+ *
33
+ * @param urlString - Original URL string
34
+ * @param params - Params to add
35
+ * @returns New URL string with params added
58
36
  */
59
37
  private addSearchParams;
60
38
  }
@@ -64,4 +42,10 @@ export declare class FetchHandler implements FetchHandlerInterface {
64
42
  * @deprecated Use `FetchHandler` instead.
65
43
  */
66
44
  export declare class IaFetchHandler extends FetchHandler {
45
+ constructor(options?: {
46
+ iaApiBaseUrl?: string;
47
+ apiBaseUrl?: string;
48
+ fetchRetrier?: FetchRetrierInterface;
49
+ searchParams?: string;
50
+ });
67
51
  }
@@ -6,14 +6,6 @@ import { FetchRetrier, } from './fetch-retry/fetch-retrier';
6
6
  * - add convenience method for fetching/decoding an API response by just the path
7
7
  */
8
8
  export class FetchHandler {
9
- /**
10
- *
11
- * @param options {
12
- * iaApiBaseUrl - deprecated Use `apiBaseUrl` instead.
13
- * apiBaseUrl - The base URL for API requests for `fetchApiPathResponse`
14
- * fetchRetrier - FetchRetrier to use instead of the default
15
- * searchParams - Search params to check for `reCache=1` (defaults to current window location)
16
- */
17
9
  constructor(options) {
18
10
  this.apiBaseUrl = '';
19
11
  this.fetchRetrier = new FetchRetrier();
@@ -33,13 +25,14 @@ export class FetchHandler {
33
25
  }
34
26
  }
35
27
  /** @inheritdoc */
36
- async fetchApiPathResponse(path, options) {
37
- const url = `${this.apiBaseUrl}${path}`;
38
- return this.fetchApiResponse(url, options);
39
- }
40
- /** @inheritdoc */
41
- async fetchIAApiResponse(path, options) {
42
- return this.fetchApiPathResponse(path, options);
28
+ async fetch(request, options) {
29
+ let finalRequest = request;
30
+ const urlParams = new URLSearchParams(this.searchParams);
31
+ if (urlParams.get('reCache') === '1') {
32
+ const urlString = typeof request === 'string' ? request : request.url;
33
+ finalRequest = this.addSearchParams(urlString, { reCache: '1' });
34
+ }
35
+ return this.fetchRetrier.fetchRetry(finalRequest, options);
43
36
  }
44
37
  /** @inheritdoc */
45
38
  async fetchApiResponse(url, options) {
@@ -60,18 +53,20 @@ export class FetchHandler {
60
53
  return json;
61
54
  }
62
55
  /** @inheritdoc */
63
- async fetch(request, options) {
64
- let finalRequest = request;
65
- const urlParams = new URLSearchParams(this.searchParams);
66
- if (urlParams.get('reCache') === '1') {
67
- const urlString = typeof request === 'string' ? request : request.url;
68
- finalRequest = this.addSearchParams(urlString, { reCache: '1' });
69
- }
70
- return this.fetchRetrier.fetchRetry(finalRequest, options);
56
+ async fetchApiPathResponse(path, options) {
57
+ const url = `${this.apiBaseUrl}${path}`;
58
+ return this.fetchApiResponse(url, options);
59
+ }
60
+ /** @inheritdoc */
61
+ async fetchIAApiResponse(path, options) {
62
+ return this.fetchApiPathResponse(path, options);
71
63
  }
72
64
  /**
73
- * Since RequestInfo can be either a `Request` or `string`, we need to change
74
- * the way we add search params to it depending on the input.
65
+ * Construct a new URL with the given search params added
66
+ *
67
+ * @param urlString - Original URL string
68
+ * @param params - Params to add
69
+ * @returns New URL string with params added
75
70
  */
76
71
  addSearchParams(urlString, params) {
77
72
  const url = new URL(urlString, window.location.href);
@@ -87,5 +82,11 @@ export class FetchHandler {
87
82
  * @deprecated Use `FetchHandler` instead.
88
83
  */
89
84
  export class IaFetchHandler extends FetchHandler {
85
+ constructor(options) {
86
+ var _a;
87
+ const superOptions = { ...options };
88
+ superOptions.iaApiBaseUrl = (_a = options === null || options === void 0 ? void 0 : options.iaApiBaseUrl) !== null && _a !== void 0 ? _a : 'https://archive.org';
89
+ super(superOptions);
90
+ }
90
91
  }
91
92
  //# sourceMappingURL=fetch-handler.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"fetch-handler.js","sourceRoot":"","sources":["../../src/fetch-handler.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n FetchRetrier,\n FetchRetrierInterface,\n} from './fetch-retry/fetch-retrier';\nimport type { FetchHandlerInterface } from './fetch-handler-interface';\nimport type { FetchOptions } from './fetch-options';\nimport type { RetryConfiguring } from './fetch-retry/configuration/retry-configuring';\n\n/**\n * The FetchHandler adds some common helpers:\n * - retry the request if it fails\n * - add `reCache=1` to the request if it's in the current url so the backend sees it\n * - add convenience method for fetching/decoding an API response by just the path\n */\nexport class FetchHandler implements FetchHandlerInterface {\n private apiBaseUrl: string = '';\n\n private fetchRetrier: FetchRetrierInterface = new FetchRetrier();\n\n private searchParams?: string;\n\n /**\n *\n * @param options {\n * iaApiBaseUrl - deprecated Use `apiBaseUrl` instead.\n * apiBaseUrl - The base URL for API requests for `fetchApiPathResponse`\n * fetchRetrier - FetchRetrier to use instead of the default\n * searchParams - Search params to check for `reCache=1` (defaults to current window location)\n */\n constructor(options?: {\n iaApiBaseUrl?: string;\n apiBaseUrl?: string;\n fetchRetrier?: FetchRetrierInterface;\n searchParams?: string;\n }) {\n if (options?.apiBaseUrl) {\n this.apiBaseUrl = options.apiBaseUrl;\n } else if (options?.iaApiBaseUrl) {\n this.apiBaseUrl = options.iaApiBaseUrl;\n }\n if (options?.fetchRetrier) this.fetchRetrier = options.fetchRetrier;\n if (options?.searchParams) {\n this.searchParams = options.searchParams;\n } else {\n this.searchParams = window.location.search;\n }\n }\n\n /** @inheritdoc */\n async fetchApiPathResponse<T>(\n path: string,\n options?: {\n includeCredentials?: boolean;\n method?: string;\n body?: BodyInit;\n headers?: HeadersInit;\n retryConfig?: RetryConfiguring;\n },\n ): Promise<T> {\n const url = `${this.apiBaseUrl}${path}`;\n return this.fetchApiResponse(url, options);\n }\n\n /** @inheritdoc */\n async fetchIAApiResponse<T>(\n path: string,\n options?: {\n includeCredentials?: boolean;\n method?: string;\n body?: BodyInit;\n headers?: HeadersInit;\n retryConfig?: RetryConfiguring;\n },\n ): Promise<T> {\n return this.fetchApiPathResponse(path, options);\n }\n\n /** @inheritdoc */\n async fetchApiResponse<T>(\n url: string,\n options?: {\n includeCredentials?: boolean;\n method?: string;\n body?: BodyInit;\n headers?: HeadersInit;\n retryConfig?: RetryConfiguring;\n },\n ): Promise<T> {\n const requestInit: RequestInit = {};\n if (options?.includeCredentials) requestInit.credentials = 'include';\n if (options?.method) requestInit.method = options.method;\n if (options?.body) requestInit.body = options.body;\n if (options?.headers) requestInit.headers = options.headers;\n const response = await this.fetch(url, {\n requestInit: requestInit,\n retryConfig: options?.retryConfig,\n });\n const json = await response.json();\n return json as T;\n }\n\n /** @inheritdoc */\n async fetch(\n request: RequestInfo,\n options?: RequestInit | FetchOptions,\n ): Promise<Response> {\n let finalRequest = request;\n const urlParams = new URLSearchParams(this.searchParams);\n if (urlParams.get('reCache') === '1') {\n const urlString = typeof request === 'string' ? request : request.url;\n finalRequest = this.addSearchParams(urlString, { reCache: '1' });\n }\n return this.fetchRetrier.fetchRetry(finalRequest, options);\n }\n\n /**\n * Since RequestInfo can be either a `Request` or `string`, we need to change\n * the way we add search params to it depending on the input.\n */\n private addSearchParams(\n urlString: string,\n params: Record<string, string>,\n ): string {\n const url = new URL(urlString, window.location.href);\n\n for (const [key, value] of Object.entries(params)) {\n url.searchParams.set(key, value);\n }\n\n return url.href;\n }\n}\n\n/**\n * Backwards compatibility class\n *\n * @deprecated Use `FetchHandler` instead.\n */\nexport class IaFetchHandler extends FetchHandler {}\n"]}
1
+ {"version":3,"file":"fetch-handler.js","sourceRoot":"","sources":["../../src/fetch-handler.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,YAAY,GAEb,MAAM,6BAA6B,CAAC;AAYrC;;;;;GAKG;AACH,MAAM,OAAO,YAAY;IAOvB,YAAY,OAAwC;QAN5C,eAAU,GAAW,EAAE,CAAC;QAExB,iBAAY,GAA0B,IAAI,YAAY,EAAE,CAAC;QAK/D,IAAI,OAAO,aAAP,OAAO,uBAAP,OAAO,CAAE,UAAU,EAAE,CAAC;YACxB,IAAI,CAAC,UAAU,GAAG,OAAO,CAAC,UAAU,CAAC;QACvC,CAAC;aAAM,IAAI,OAAO,aAAP,OAAO,uBAAP,OAAO,CAAE,YAAY,EAAE,CAAC;YACjC,IAAI,CAAC,UAAU,GAAG,OAAO,CAAC,YAAY,CAAC;QACzC,CAAC;QACD,IAAI,OAAO,aAAP,OAAO,uBAAP,OAAO,CAAE,YAAY;YAAE,IAAI,CAAC,YAAY,GAAG,OAAO,CAAC,YAAY,CAAC;QACpE,IAAI,OAAO,aAAP,OAAO,uBAAP,OAAO,CAAE,YAAY,EAAE,CAAC;YAC1B,IAAI,CAAC,YAAY,GAAG,OAAO,CAAC,YAAY,CAAC;QAC3C,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,YAAY,GAAG,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC;QAC7C,CAAC;IACH,CAAC;IAED,kBAAkB;IAClB,KAAK,CAAC,KAAK,CACT,OAAoB,EACpB,OAAoC;QAEpC,IAAI,YAAY,GAAG,OAAO,CAAC;QAC3B,MAAM,SAAS,GAAG,IAAI,eAAe,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;QACzD,IAAI,SAAS,CAAC,GAAG,CAAC,SAAS,CAAC,KAAK,GAAG,EAAE,CAAC;YACrC,MAAM,SAAS,GAAG,OAAO,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC;YACtE,YAAY,GAAG,IAAI,CAAC,eAAe,CAAC,SAAS,EAAE,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC,CAAC;QACnE,CAAC;QACD,OAAO,IAAI,CAAC,YAAY,CAAC,UAAU,CAAC,YAAY,EAAE,OAAO,CAAC,CAAC;IAC7D,CAAC;IAED,kBAAkB;IAClB,KAAK,CAAC,gBAAgB,CACpB,GAAW,EACX,OAAyB;QAEzB,MAAM,WAAW,GAAgB,EAAE,CAAC;QACpC,IAAI,OAAO,aAAP,OAAO,uBAAP,OAAO,CAAE,kBAAkB;YAAE,WAAW,CAAC,WAAW,GAAG,SAAS,CAAC;QACrE,IAAI,OAAO,aAAP,OAAO,uBAAP,OAAO,CAAE,MAAM;YAAE,WAAW,CAAC,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;QACzD,IAAI,OAAO,aAAP,OAAO,uBAAP,OAAO,CAAE,IAAI;YAAE,WAAW,CAAC,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;QACnD,IAAI,OAAO,aAAP,OAAO,uBAAP,OAAO,CAAE,OAAO;YAAE,WAAW,CAAC,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC;QAC5D,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,GAAG,EAAE;YACrC,WAAW,EAAE,WAAW;YACxB,WAAW,EAAE,OAAO,aAAP,OAAO,uBAAP,OAAO,CAAE,WAAW;SAClC,CAAC,CAAC;QACH,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;QACnC,OAAO,IAAS,CAAC;IACnB,CAAC;IAED,kBAAkB;IAClB,KAAK,CAAC,oBAAoB,CACxB,IAAY,EACZ,OAAyB;QAEzB,MAAM,GAAG,GAAG,GAAG,IAAI,CAAC,UAAU,GAAG,IAAI,EAAE,CAAC;QACxC,OAAO,IAAI,CAAC,gBAAgB,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;IAC7C,CAAC;IAED,kBAAkB;IAClB,KAAK,CAAC,kBAAkB,CACtB,IAAY,EACZ,OAAyB;QAEzB,OAAO,IAAI,CAAC,oBAAoB,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;IAClD,CAAC;IAED;;;;;;OAMG;IACK,eAAe,CACrB,SAAiB,EACjB,MAA8B;QAE9B,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,SAAS,EAAE,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;QAErD,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;YAClD,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;QACnC,CAAC;QAED,OAAO,GAAG,CAAC,IAAI,CAAC;IAClB,CAAC;CACF;AAED;;;;GAIG;AACH,MAAM,OAAO,cAAe,SAAQ,YAAY;IAC9C,YAAY,OAKX;;QACC,MAAM,YAAY,GAAG,EAAE,GAAG,OAAO,EAAE,CAAC;QACpC,YAAY,CAAC,YAAY,GAAG,MAAA,OAAO,aAAP,OAAO,uBAAP,OAAO,CAAE,YAAY,mCAAI,qBAAqB,CAAC;QAC3E,KAAK,CAAC,YAAY,CAAC,CAAC;IACtB,CAAC;CACF","sourcesContent":["import {\n FetchRetrier,\n FetchRetrierInterface,\n} from './fetch-retry/fetch-retrier';\nimport type { FetchHandlerInterface } from './fetch-handler-interface';\nimport type { ApiFetchOptions, FetchOptions } from './fetch-options';\n\nexport type FetchHandlerConstructorOptions = {\n /** @deprecated Use `apiBaseUrl` instead. */\n iaApiBaseUrl?: string;\n apiBaseUrl?: string;\n fetchRetrier?: FetchRetrierInterface;\n searchParams?: string;\n};\n\n/**\n * The FetchHandler adds some common helpers:\n * - retry the request if it fails\n * - add `reCache=1` to the request if it's in the current url so the backend sees it\n * - add convenience method for fetching/decoding an API response by just the path\n */\nexport class FetchHandler implements FetchHandlerInterface {\n private apiBaseUrl: string = '';\n\n private fetchRetrier: FetchRetrierInterface = new FetchRetrier();\n\n private searchParams?: string;\n\n constructor(options?: FetchHandlerConstructorOptions) {\n if (options?.apiBaseUrl) {\n this.apiBaseUrl = options.apiBaseUrl;\n } else if (options?.iaApiBaseUrl) {\n this.apiBaseUrl = options.iaApiBaseUrl;\n }\n if (options?.fetchRetrier) this.fetchRetrier = options.fetchRetrier;\n if (options?.searchParams) {\n this.searchParams = options.searchParams;\n } else {\n this.searchParams = window.location.search;\n }\n }\n\n /** @inheritdoc */\n async fetch(\n request: RequestInfo,\n options?: RequestInit | FetchOptions,\n ): Promise<Response> {\n let finalRequest = request;\n const urlParams = new URLSearchParams(this.searchParams);\n if (urlParams.get('reCache') === '1') {\n const urlString = typeof request === 'string' ? request : request.url;\n finalRequest = this.addSearchParams(urlString, { reCache: '1' });\n }\n return this.fetchRetrier.fetchRetry(finalRequest, options);\n }\n\n /** @inheritdoc */\n async fetchApiResponse<T>(\n url: string,\n options?: ApiFetchOptions,\n ): Promise<T> {\n const requestInit: RequestInit = {};\n if (options?.includeCredentials) requestInit.credentials = 'include';\n if (options?.method) requestInit.method = options.method;\n if (options?.body) requestInit.body = options.body;\n if (options?.headers) requestInit.headers = options.headers;\n const response = await this.fetch(url, {\n requestInit: requestInit,\n retryConfig: options?.retryConfig,\n });\n const json = await response.json();\n return json as T;\n }\n\n /** @inheritdoc */\n async fetchApiPathResponse<T>(\n path: string,\n options?: ApiFetchOptions,\n ): Promise<T> {\n const url = `${this.apiBaseUrl}${path}`;\n return this.fetchApiResponse(url, options);\n }\n\n /** @inheritdoc */\n async fetchIAApiResponse<T>(\n path: string,\n options?: ApiFetchOptions,\n ): Promise<T> {\n return this.fetchApiPathResponse(path, options);\n }\n\n /**\n * Construct a new URL with the given search params added\n *\n * @param urlString - Original URL string\n * @param params - Params to add\n * @returns New URL string with params added\n */\n private addSearchParams(\n urlString: string,\n params: Record<string, string>,\n ): string {\n const url = new URL(urlString, window.location.href);\n\n for (const [key, value] of Object.entries(params)) {\n url.searchParams.set(key, value);\n }\n\n return url.href;\n }\n}\n\n/**\n * Backwards compatibility class\n *\n * @deprecated Use `FetchHandler` instead.\n */\nexport class IaFetchHandler extends FetchHandler {\n constructor(options?: {\n iaApiBaseUrl?: string;\n apiBaseUrl?: string;\n fetchRetrier?: FetchRetrierInterface;\n searchParams?: string;\n }) {\n const superOptions = { ...options };\n superOptions.iaApiBaseUrl = options?.iaApiBaseUrl ?? 'https://archive.org';\n super(superOptions);\n }\n}\n"]}
@@ -1,5 +1,18 @@
1
1
  import type { RetryConfiguring } from './fetch-retry/configuration/retry-configuring';
2
+ /**
3
+ * Base fetch options for FetchHandler
4
+ */
2
5
  export type FetchOptions = {
3
6
  requestInit?: RequestInit;
4
7
  retryConfig?: RetryConfiguring;
5
8
  };
9
+ /**
10
+ * A convenience type for FetchHandler methods with common API fetch options.
11
+ */
12
+ export type ApiFetchOptions = {
13
+ includeCredentials?: boolean;
14
+ method?: string;
15
+ body?: BodyInit;
16
+ headers?: HeadersInit;
17
+ retryConfig?: RetryConfiguring;
18
+ };
@@ -1 +1 @@
1
- {"version":3,"file":"fetch-options.js","sourceRoot":"","sources":["../../src/fetch-options.ts"],"names":[],"mappings":"","sourcesContent":["import type { RetryConfiguring } from './fetch-retry/configuration/retry-configuring';\n\nexport type FetchOptions = {\n requestInit?: RequestInit;\n retryConfig?: RetryConfiguring;\n};\n"]}
1
+ {"version":3,"file":"fetch-options.js","sourceRoot":"","sources":["../../src/fetch-options.ts"],"names":[],"mappings":"","sourcesContent":["import type { RetryConfiguring } from './fetch-retry/configuration/retry-configuring';\n\n/**\n * Base fetch options for FetchHandler\n */\nexport type FetchOptions = {\n requestInit?: RequestInit;\n retryConfig?: RetryConfiguring;\n};\n\n/**\n * A convenience type for FetchHandler methods with common API fetch options.\n */\nexport type ApiFetchOptions = {\n includeCredentials?: boolean;\n method?: string;\n body?: BodyInit;\n headers?: HeadersInit;\n retryConfig?: RetryConfiguring;\n};\n"]}
@@ -1,6 +1,6 @@
1
1
  import { promisedSleep } from '../utils/promised-sleep';
2
- import { legacyArgsAsFetchOptions } from './legacy-args';
3
2
  import { FetchRetryConfig } from './configuration/configurations';
3
+ import { legacyArgsAsFetchOptions } from './legacy-args';
4
4
  /** @inheritdoc */
5
5
  export class FetchRetrier {
6
6
  constructor(options) {
@@ -1 +1 @@
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
+ {"version":3,"file":"fetch-retrier.js","sourceRoot":"","sources":["../../../src/fetch-retry/fetch-retrier.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AACxD,OAAO,EAAE,gBAAgB,EAAE,MAAM,gCAAgC,CAAC;AAElE,OAAO,EAAE,wBAAwB,EAAE,MAAM,eAAe,CAAC;AAmBzD,kBAAkB;AAClB,MAAM,OAAO,YAAY;IAKvB,YAAY,OAGX;QALO,gBAAW,GAAqB,gBAAgB,CAAC,OAAO,CAAC;QAiFhD,kBAAa,GAAG,oBAAoB,CAAC;QA3EpD,IAAI,OAAO,aAAP,OAAO,uBAAP,OAAO,CAAE,gBAAgB;YAC3B,IAAI,CAAC,gBAAgB,GAAG,OAAO,CAAC,gBAAgB,CAAC;QACnD,IAAI,OAAO,aAAP,OAAO,uBAAP,OAAO,CAAE,WAAW;YAAE,IAAI,CAAC,WAAW,GAAG,OAAO,CAAC,WAAW,CAAC;IACnE,CAAC;IAED,kBAAkB;IACX,KAAK,CAAC,UAAU,CACrB,OAAoB,EACpB,OAAoC;QAEpC,MAAM,YAAY,GAAG,wBAAwB,CAAC,OAAO,CAAC,CAAC;QACvD,OAAO,MAAM,IAAI,CAAC,YAAY,CAAC,OAAO,EAAE,CAAC,EAAE,YAAY,CAAC,CAAC;IAC3D,CAAC;IAEO,KAAK,CAAC,YAAY,CACxB,OAAoB,EACpB,WAAmB,EACnB,OAAsB;;QAEtB,MAAM,SAAS,GAAG,OAAO,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC;QAEtE,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,OAAO,EAAE,OAAO,aAAP,OAAO,uBAAP,OAAO,CAAE,WAAW,CAAC,CAAC;YAC5D,IAAI,QAAQ,CAAC,EAAE;gBAAE,OAAO,QAAQ,CAAC;YAEjC,IAAI,QAAQ,CAAC,MAAM,IAAI,GAAG,IAAI,QAAQ,CAAC,MAAM,GAAG,GAAG,EAAE,CAAC;gBACpD,IAAI,CAAC,iBAAiB,CAAC,QAAQ,CAAC,CAAC;YACnC,CAAC;YAED,MAAM,WAAW,GAAG,MAAA,OAAO,aAAP,OAAO,uBAAP,OAAO,CAAE,WAAW,mCAAI,IAAI,CAAC,WAAW,CAAC;YAC7D,MAAM,WAAW,GAAG,WAAW,CAAC,WAAW,CAAC,QAAQ,EAAE,WAAW,CAAC,CAAC;YACnE,IAAI,WAAW,EAAE,CAAC;gBAChB,MAAM,UAAU,GAAG,WAAW,CAAC,UAAU,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAC;gBACjE,IAAI,UAAU,KAAK,IAAI,EAAE,CAAC;oBACxB,MAAM,aAAa,CAAC,UAAU,CAAC,CAAC;oBAChC,IAAI,CAAC,aAAa,CAChB,SAAS,EACT,WAAW,EACX,QAAQ,CAAC,UAAU,EACnB,QAAQ,CAAC,MAAM,CAChB,CAAC;oBACF,OAAO,IAAI,CAAC,YAAY,CAAC,OAAO,EAAE,WAAW,GAAG,CAAC,EAAE,OAAO,CAAC,CAAC;gBAC9D,CAAC;YACH,CAAC;YACD,IAAI,CAAC,eAAe,CAAC,SAAS,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC;YACjD,OAAO,QAAQ,CAAC;QAClB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,2DAA2D;YAC3D,IAAI,IAAI,CAAC,qBAAqB,CAAC,KAAK,CAAC,EAAE,CAAC;gBACtC,IAAI,CAAC,uBAAuB,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;gBAC/C,MAAM,KAAK,CAAC;YACd,CAAC;YAED,MAAM,WAAW,GAAG,MAAA,OAAO,aAAP,OAAO,uBAAP,OAAO,CAAE,WAAW,mCAAI,IAAI,CAAC,WAAW,CAAC;YAC7D,MAAM,WAAW,GAAG,WAAW,CAAC,WAAW,CAAC,IAAI,EAAE,WAAW,CAAC,CAAC;YAC/D,IAAI,WAAW,EAAE,CAAC;gBAChB,MAAM,UAAU,GAAG,WAAW,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC;gBACvD,IAAI,UAAU,KAAK,IAAI,EAAE,CAAC;oBACxB,MAAM,aAAa,CAAC,UAAU,CAAC,CAAC;oBAChC,IAAI,CAAC,aAAa,CAAC,SAAS,EAAE,WAAW,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC;oBACzD,OAAO,IAAI,CAAC,YAAY,CAAC,OAAO,EAAE,WAAW,GAAG,CAAC,EAAE,OAAO,CAAC,CAAC;gBAC9D,CAAC;YACH,CAAC;YACD,IAAI,CAAC,eAAe,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;YACvC,MAAM,KAAK,CAAC;QACd,CAAC;IACH,CAAC;IAEO,qBAAqB,CAAC,KAAc;QAC1C,oDAAoD;QACpD,IAAI,CAAC,CAAC,KAAK,YAAY,SAAS,CAAC;YAAE,OAAO,KAAK,CAAC;QAChD,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC,WAAW,EAAE,CAAC;QAC5C,OAAO,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAC,CAAC;IAC7C,CAAC;IAIO,aAAa,CACnB,SAAiB,EACjB,WAAmB,EACnB,MAAe,EACf,IAAa;;QAEb,MAAA,IAAI,CAAC,gBAAgB,0CAAE,SAAS,CAAC;YAC/B,QAAQ,EAAE,IAAI,CAAC,aAAa;YAC5B,MAAM,EAAE,eAAe;YACvB,KAAK,EAAE,gBAAgB,WAAW,WAAW,IAAI,aAAa,MAAM,UAAU,SAAS,EAAE;SAC1F,CAAC,CAAC;IACL,CAAC;IAEO,eAAe,CAAC,SAAiB,EAAE,KAAc;;QACvD,MAAA,IAAI,CAAC,gBAAgB,0CAAE,SAAS,CAAC;YAC/B,QAAQ,EAAE,IAAI,CAAC,aAAa;YAC5B,MAAM,EAAE,aAAa;YACrB,KAAK,EAAE,UAAU,KAAK,UAAU,SAAS,EAAE;SAC5C,CAAC,CAAC;IACL,CAAC;IAEO,iBAAiB,CAAC,QAAkB;;QAC1C,MAAM,MAAM,GAAG,QAAQ,CAAC,MAAM,CAAC;QAE/B,MAAA,IAAI,CAAC,gBAAgB,0CAAE,SAAS,CAAC;YAC/B,QAAQ,EAAE,IAAI,CAAC,aAAa;YAC5B,MAAM,EAAE,SAAS,MAAM,UAAU;YACjC,KAAK,EAAE,QAAQ,QAAQ,CAAC,GAAG,EAAE;SAC9B,CAAC,CAAC;IACL,CAAC;IAEO,uBAAuB,CAAC,SAAiB,EAAE,KAAc;;QAC/D,MAAA,IAAI,CAAC,gBAAgB,0CAAE,SAAS,CAAC;YAC/B,QAAQ,EAAE,IAAI,CAAC,aAAa;YAC5B,MAAM,EAAE,mCAAmC;YAC3C,KAAK,EAAE,UAAU,KAAK,UAAU,SAAS,EAAE;SAC5C,CAAC,CAAC;IACL,CAAC;CACF","sourcesContent":["import type { AnalyticsHandlerInterface } from '@internetarchive/analytics-manager';\nimport { type FetchOptions } from '../fetch-options';\nimport { promisedSleep } from '../utils/promised-sleep';\nimport { FetchRetryConfig } from './configuration/configurations';\nimport type { RetryConfiguring } from './configuration/retry-configuring';\nimport { legacyArgsAsFetchOptions } from './legacy-args';\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,5 +1,5 @@
1
1
  import { expect } from '@open-wc/testing';
2
- import { FetchHandler } 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', () => {
@@ -125,7 +125,26 @@ describe('Fetch Handler', () => {
125
125
  it('is an alias for fetchApiPathResponse', async () => {
126
126
  const endpoint = '/foo/service/endpoint.php';
127
127
  const fetchRetrier = new MockFetchRetrier();
128
- const fetchHandler = new FetchHandler({
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({
129
148
  iaApiBaseUrl: 'www.example.com',
130
149
  fetchRetrier: fetchRetrier,
131
150
  });
@@ -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 { FetchHandler } 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 FetchHandler({\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"]}
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"]}
package/index.ts CHANGED
@@ -1,6 +1,10 @@
1
- export { FetchHandler, IaFetchHandler } from './src/fetch-handler';
1
+ export {
2
+ FetchHandler,
3
+ IaFetchHandler,
4
+ type FetchHandlerConstructorOptions,
5
+ } from './src/fetch-handler';
2
6
  export type { FetchHandlerInterface } from './src/fetch-handler-interface';
3
- export type { FetchOptions } from './src/fetch-options';
7
+ export type { ApiFetchOptions, FetchOptions } from './src/fetch-options';
4
8
  export type { Milliseconds } from './src/fetch-retry/configuration/milliseconds';
5
9
 
6
10
  export { FetchRetryConfig } from './src/fetch-retry/configuration/configurations';
package/package.json CHANGED
@@ -7,7 +7,7 @@
7
7
  },
8
8
  "license": "AGPL-3.0-only",
9
9
  "author": "Internet Archive",
10
- "version": "1.1.0-webdev-7731.9",
10
+ "version": "1.1.0-webdev-7731.11",
11
11
  "main": "dist/index.js",
12
12
  "module": "dist/index.js",
13
13
  "scripts": {
@@ -1,5 +1,4 @@
1
- import type { FetchOptions } from './fetch-options';
2
- import type { RetryConfiguring } from './fetch-retry/configuration/retry-configuring';
1
+ import type { ApiFetchOptions, FetchOptions } from './fetch-options';
3
2
 
4
3
  export interface FetchHandlerInterface {
5
4
  /**
@@ -17,18 +16,9 @@ export interface FetchHandlerInterface {
17
16
  * A helper function to fetch a response from an API and get a JSON object
18
17
  *
19
18
  * @param path string
20
- * @param options?: { includeCredentials?: boolean }
19
+ * @param options?: ApiFetchOptions
21
20
  */
22
- fetchApiResponse<T>(
23
- url: string,
24
- options?: {
25
- includeCredentials?: boolean;
26
- method?: string;
27
- body?: BodyInit;
28
- headers?: HeadersInit;
29
- retryConfig?: RetryConfiguring;
30
- },
31
- ): Promise<T>;
21
+ fetchApiResponse<T>(url: string, options?: ApiFetchOptions): Promise<T>;
32
22
 
33
23
  /**
34
24
  * A helper function to fetch a response from the IA API and get a JSON object
@@ -39,34 +29,16 @@ export interface FetchHandlerInterface {
39
29
  * ie `fetchApiPathResponse('/items/123')` will fetch from `${apiBaseUrl}/items/123`
40
30
  *
41
31
  * @param path - Path to API endpoint
42
- * @param options - Options including credentials, method, body, headers, and retryConfig
32
+ * @param options - ApiFetchOptions
43
33
  */
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>;
34
+ fetchApiPathResponse<T>(path: string, options?: ApiFetchOptions): Promise<T>;
54
35
 
55
36
  /**
56
37
  * Fetch a response from the IA API by path
57
38
  *
58
39
  * @deprecated Use `fetchApiPathResponse` instead.
59
40
  * @param path - Path to API endpoint
60
- * @param options - Options including credentials, method, body, headers, and retryConfig
41
+ * @param options - ApiFetchOptions
61
42
  */
62
- fetchIAApiResponse<T>(
63
- path: string,
64
- options?: {
65
- includeCredentials?: boolean;
66
- method?: string;
67
- body?: BodyInit;
68
- headers?: HeadersInit;
69
- retryConfig?: RetryConfiguring;
70
- },
71
- ): Promise<T>;
43
+ fetchIAApiResponse<T>(path: string, options?: ApiFetchOptions): Promise<T>;
72
44
  }
@@ -3,8 +3,15 @@ import {
3
3
  FetchRetrierInterface,
4
4
  } from './fetch-retry/fetch-retrier';
5
5
  import type { FetchHandlerInterface } from './fetch-handler-interface';
6
- import type { FetchOptions } from './fetch-options';
7
- import type { RetryConfiguring } from './fetch-retry/configuration/retry-configuring';
6
+ import type { ApiFetchOptions, FetchOptions } from './fetch-options';
7
+
8
+ export type FetchHandlerConstructorOptions = {
9
+ /** @deprecated Use `apiBaseUrl` instead. */
10
+ iaApiBaseUrl?: string;
11
+ apiBaseUrl?: string;
12
+ fetchRetrier?: FetchRetrierInterface;
13
+ searchParams?: string;
14
+ };
8
15
 
9
16
  /**
10
17
  * The FetchHandler adds some common helpers:
@@ -19,20 +26,7 @@ export class FetchHandler implements FetchHandlerInterface {
19
26
 
20
27
  private searchParams?: string;
21
28
 
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
- */
30
- constructor(options?: {
31
- iaApiBaseUrl?: string;
32
- apiBaseUrl?: string;
33
- fetchRetrier?: FetchRetrierInterface;
34
- searchParams?: string;
35
- }) {
29
+ constructor(options?: FetchHandlerConstructorOptions) {
36
30
  if (options?.apiBaseUrl) {
37
31
  this.apiBaseUrl = options.apiBaseUrl;
38
32
  } else if (options?.iaApiBaseUrl) {
@@ -47,44 +41,23 @@ export class FetchHandler implements FetchHandlerInterface {
47
41
  }
48
42
 
49
43
  /** @inheritdoc */
50
- async fetchApiPathResponse<T>(
51
- path: string,
52
- options?: {
53
- includeCredentials?: boolean;
54
- method?: string;
55
- body?: BodyInit;
56
- headers?: HeadersInit;
57
- retryConfig?: RetryConfiguring;
58
- },
59
- ): Promise<T> {
60
- const url = `${this.apiBaseUrl}${path}`;
61
- return this.fetchApiResponse(url, options);
62
- }
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);
44
+ async fetch(
45
+ request: RequestInfo,
46
+ options?: RequestInit | FetchOptions,
47
+ ): Promise<Response> {
48
+ let finalRequest = request;
49
+ const urlParams = new URLSearchParams(this.searchParams);
50
+ if (urlParams.get('reCache') === '1') {
51
+ const urlString = typeof request === 'string' ? request : request.url;
52
+ finalRequest = this.addSearchParams(urlString, { reCache: '1' });
53
+ }
54
+ return this.fetchRetrier.fetchRetry(finalRequest, options);
76
55
  }
77
56
 
78
57
  /** @inheritdoc */
79
58
  async fetchApiResponse<T>(
80
59
  url: string,
81
- options?: {
82
- includeCredentials?: boolean;
83
- method?: string;
84
- body?: BodyInit;
85
- headers?: HeadersInit;
86
- retryConfig?: RetryConfiguring;
87
- },
60
+ options?: ApiFetchOptions,
88
61
  ): Promise<T> {
89
62
  const requestInit: RequestInit = {};
90
63
  if (options?.includeCredentials) requestInit.credentials = 'include';
@@ -100,22 +73,28 @@ export class FetchHandler implements FetchHandlerInterface {
100
73
  }
101
74
 
102
75
  /** @inheritdoc */
103
- async fetch(
104
- request: RequestInfo,
105
- options?: RequestInit | FetchOptions,
106
- ): Promise<Response> {
107
- let finalRequest = request;
108
- const urlParams = new URLSearchParams(this.searchParams);
109
- if (urlParams.get('reCache') === '1') {
110
- const urlString = typeof request === 'string' ? request : request.url;
111
- finalRequest = this.addSearchParams(urlString, { reCache: '1' });
112
- }
113
- return this.fetchRetrier.fetchRetry(finalRequest, options);
76
+ async fetchApiPathResponse<T>(
77
+ path: string,
78
+ options?: ApiFetchOptions,
79
+ ): Promise<T> {
80
+ const url = `${this.apiBaseUrl}${path}`;
81
+ return this.fetchApiResponse(url, options);
82
+ }
83
+
84
+ /** @inheritdoc */
85
+ async fetchIAApiResponse<T>(
86
+ path: string,
87
+ options?: ApiFetchOptions,
88
+ ): Promise<T> {
89
+ return this.fetchApiPathResponse(path, options);
114
90
  }
115
91
 
116
92
  /**
117
- * Since RequestInfo can be either a `Request` or `string`, we need to change
118
- * the way we add search params to it depending on the input.
93
+ * Construct a new URL with the given search params added
94
+ *
95
+ * @param urlString - Original URL string
96
+ * @param params - Params to add
97
+ * @returns New URL string with params added
119
98
  */
120
99
  private addSearchParams(
121
100
  urlString: string,
@@ -136,4 +115,15 @@ export class FetchHandler implements FetchHandlerInterface {
136
115
  *
137
116
  * @deprecated Use `FetchHandler` instead.
138
117
  */
139
- export class IaFetchHandler extends FetchHandler {}
118
+ export class IaFetchHandler extends FetchHandler {
119
+ constructor(options?: {
120
+ iaApiBaseUrl?: string;
121
+ apiBaseUrl?: string;
122
+ fetchRetrier?: FetchRetrierInterface;
123
+ searchParams?: string;
124
+ }) {
125
+ const superOptions = { ...options };
126
+ superOptions.iaApiBaseUrl = options?.iaApiBaseUrl ?? 'https://archive.org';
127
+ super(superOptions);
128
+ }
129
+ }
@@ -1,6 +1,20 @@
1
1
  import type { RetryConfiguring } from './fetch-retry/configuration/retry-configuring';
2
2
 
3
+ /**
4
+ * Base fetch options for FetchHandler
5
+ */
3
6
  export type FetchOptions = {
4
7
  requestInit?: RequestInit;
5
8
  retryConfig?: RetryConfiguring;
6
9
  };
10
+
11
+ /**
12
+ * A convenience type for FetchHandler methods with common API fetch options.
13
+ */
14
+ export type ApiFetchOptions = {
15
+ includeCredentials?: boolean;
16
+ method?: string;
17
+ body?: BodyInit;
18
+ headers?: HeadersInit;
19
+ retryConfig?: RetryConfiguring;
20
+ };
@@ -1,10 +1,9 @@
1
1
  import type { AnalyticsHandlerInterface } from '@internetarchive/analytics-manager';
2
- import { promisedSleep } from '../utils/promised-sleep';
3
2
  import { type FetchOptions } from '../fetch-options';
4
- import { legacyArgsAsFetchOptions } from './legacy-args';
5
- import { DefaultRetryConfiguration } from './configuration/default-retry-configuration';
6
- import type { RetryConfiguring } from './configuration/retry-configuring';
3
+ import { promisedSleep } from '../utils/promised-sleep';
7
4
  import { FetchRetryConfig } from './configuration/configurations';
5
+ import type { RetryConfiguring } from './configuration/retry-configuring';
6
+ import { legacyArgsAsFetchOptions } from './legacy-args';
8
7
 
9
8
  /**
10
9
  * A class that retries a fetch request.
@@ -1,5 +1,5 @@
1
1
  import { expect } from '@open-wc/testing';
2
- import { FetchHandler } 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
 
@@ -144,7 +144,32 @@ describe('Fetch Handler', () => {
144
144
  it('is an alias for fetchApiPathResponse', async () => {
145
145
  const endpoint = '/foo/service/endpoint.php';
146
146
  const fetchRetrier = new MockFetchRetrier();
147
- const fetchHandler = new FetchHandler({
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(
153
+ 'www.example.com/foo/service/endpoint.php',
154
+ );
155
+ });
156
+
157
+ it('defaults the baseUrl to https://archive.org', async () => {
158
+ const endpoint = '/foo/service/endpoint.php';
159
+ const fetchRetrier = new MockFetchRetrier();
160
+ const fetchHandler = new IaFetchHandler({
161
+ fetchRetrier: fetchRetrier,
162
+ });
163
+ await fetchHandler.fetchIAApiResponse(endpoint);
164
+ expect(fetchRetrier.requestInfo).to.equal(
165
+ 'https://archive.org/foo/service/endpoint.php',
166
+ );
167
+ });
168
+
169
+ it('passes iaApiBaseUrl if provided', async () => {
170
+ const endpoint = '/foo/service/endpoint.php';
171
+ const fetchRetrier = new MockFetchRetrier();
172
+ const fetchHandler = new IaFetchHandler({
148
173
  iaApiBaseUrl: 'www.example.com',
149
174
  fetchRetrier: fetchRetrier,
150
175
  });