@equinor/fusion-framework-module-http 5.2.3 → 6.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,7 +1,7 @@
1
1
  import { Subject } from 'rxjs';
2
2
  import type { Observable, ObservableInput } from 'rxjs';
3
3
  import type { IHttpRequestHandler, IHttpResponseHandler } from '../operators';
4
- import type { FetchRequest, FetchRequestInit, FetchResponse, IHttpClient, JsonRequest, StreamResponse } from '.';
4
+ import type { BlobResult, FetchRequest, FetchRequestInit, FetchResponse, IHttpClient, JsonRequest, StreamResponse } from './types';
5
5
  export type HttpClientCreateOptions<TRequest extends FetchRequest = FetchRequest, TResponse = Response> = {
6
6
  requestHandler: IHttpRequestHandler<TRequest>;
7
7
  responseHandler: IHttpResponseHandler<TResponse>;
@@ -22,8 +22,8 @@ export declare class HttpClient<TRequest extends FetchRequest = FetchRequest, TR
22
22
  fetchAsync<T = TResponse>(path: string, args?: FetchRequestInit<T, TRequest, TResponse>): Promise<T>;
23
23
  json$<T = unknown>(path: string, args?: FetchRequestInit<T, JsonRequest<TRequest>, TResponse>): StreamResponse<T>;
24
24
  json<T = unknown>(path: string, args?: FetchRequestInit<T, JsonRequest<TRequest>, TResponse>): Promise<T>;
25
- blob$(path: string, args?: FetchRequestInit<Blob, TRequest, TResponse>): StreamResponse<Blob>;
26
- blob(path: string, args?: FetchRequestInit<Blob, TRequest, TResponse>): Promise<Blob>;
25
+ blob$<T = BlobResult>(path: string, args?: FetchRequestInit<T, TRequest, TResponse>): StreamResponse<T>;
26
+ blob<T = BlobResult>(path: string, args?: FetchRequestInit<T, TRequest, TResponse>): Promise<T>;
27
27
  jsonAsync<T = unknown>(path: string, args?: FetchRequestInit<T, JsonRequest<TRequest>, TResponse>): Promise<T>;
28
28
  execute<T = TResponse, TMethod extends 'fetch' | 'fetch$' | 'json' | 'json$' = 'fetch'>(method: TMethod, path: string, init?: FetchRequestInit<T, TRequest, TResponse>): ReturnType<IHttpClient[TMethod]>;
29
29
  abort(): void;
@@ -8,6 +8,10 @@ export type FetchRequest = RequestInit & {
8
8
  export type JsonRequest<TRequest extends FetchRequest = FetchRequest> = Omit<TRequest, 'body'> & {
9
9
  body?: object | string | null;
10
10
  };
11
+ export type BlobResult = {
12
+ filename?: string;
13
+ blob: Blob;
14
+ };
11
15
  export type FetchResponse<T = unknown> = Response & {
12
16
  json(): Promise<T>;
13
17
  };
@@ -30,7 +34,7 @@ export interface IHttpClient<TRequest extends FetchRequest = FetchRequest, TResp
30
34
  json$<T = unknown>(path: string, init?: FetchRequestInit<T, JsonRequest<TRequest>, TResponse>): StreamResponse<T>;
31
35
  json<T = unknown>(path: string, init?: FetchRequestInit<T, JsonRequest<TRequest>, TResponse>): Promise<T>;
32
36
  jsonAsync<T = unknown>(path: string, args?: FetchRequestInit<T, JsonRequest<TRequest>, TResponse>): Promise<T>;
33
- blob(path: string, args?: FetchRequestInit<Blob, JsonRequest<TRequest>, TResponse>): Promise<Blob>;
34
- blob$(path: string, args?: FetchRequestInit<Blob, JsonRequest<TRequest>, TResponse>): StreamResponse<Blob>;
37
+ blob<T = BlobResult>(path: string, args?: FetchRequestInit<T, JsonRequest<TRequest>, TResponse>): Promise<T>;
38
+ blob$<T = BlobResult>(path: string, args?: FetchRequestInit<T, JsonRequest<TRequest>, TResponse>): StreamResponse<T>;
35
39
  abort(): void;
36
40
  }
@@ -1,2 +1,3 @@
1
- export declare const blobSelector: <TResponse extends Response = Response>(response: TResponse) => Promise<Blob>;
1
+ import { type BlobResult } from '../client/types';
2
+ export declare const blobSelector: <TResponse extends Response = Response>(response: TResponse) => Promise<BlobResult>;
2
3
  export default blobSelector;
@@ -1 +1 @@
1
- export declare const version = "5.2.3";
1
+ export declare const version = "6.0.0";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@equinor/fusion-framework-module-http",
3
- "version": "5.2.3",
3
+ "version": "6.0.0",
4
4
  "description": "",
5
5
  "main": "dist/esm/index.js",
6
6
  "types": "index.d.ts",
@@ -8,13 +8,14 @@ import { blobSelector, jsonSelector } from '../selectors';
8
8
  import type { Observable, ObservableInput } from 'rxjs';
9
9
  import type { IHttpRequestHandler, IHttpResponseHandler } from '../operators';
10
10
  import type {
11
+ BlobResult,
11
12
  FetchRequest,
12
13
  FetchRequestInit,
13
14
  FetchResponse,
14
15
  IHttpClient,
15
16
  JsonRequest,
16
17
  StreamResponse,
17
- } from '.';
18
+ } from './types';
18
19
  import { HttpResponseError } from '../../errors';
19
20
 
20
21
  export type HttpClientCreateOptions<
@@ -111,18 +112,41 @@ export class HttpClient<
111
112
  return firstValueFrom(this.json$<T>(path, args));
112
113
  }
113
114
 
114
- public blob$(
115
+ /**
116
+ * Fetches a blob resource from the specified path and returns a stream response.
117
+ *
118
+ * @param path - The path to the blob resource.
119
+ * @param args - Optional request initialization options, including a custom selector function.
120
+ * @returns A stream response containing the fetched blob data.
121
+ */
122
+ public blob$<T = BlobResult>(
115
123
  path: string,
116
- args?: FetchRequestInit<Blob, TRequest, TResponse>,
117
- ): StreamResponse<Blob> {
124
+ args?: FetchRequestInit<T, TRequest, TResponse>,
125
+ ): StreamResponse<T> {
126
+ // Get the selector value from the provided args, or use the default blobSelector
118
127
  const selector = args?.selector ?? blobSelector;
119
- return this.fetch$(path, {
128
+
129
+ // Create the FetchRequestInit object with the provided args and the selector
130
+ const init = {
120
131
  ...args,
121
132
  selector,
122
- } as FetchRequestInit<Blob, TRequest, TResponse>);
133
+ } as FetchRequestInit<T, TRequest, TResponse>;
134
+
135
+ // Call the fetch$ method with the provided path and the constructed init object
136
+ return this.fetch$(path, init);
123
137
  }
124
138
 
125
- public blob(path: string, args?: FetchRequestInit<Blob, TRequest, TResponse>): Promise<Blob> {
139
+ /**
140
+ * Fetches a blob from the specified path and returns a Promise that resolves to the blob result.
141
+ *
142
+ * @param path - The path to fetch the blob from.
143
+ * @param args - Optional arguments for the fetch request, including request body, headers, and response type.
144
+ * @returns A Promise that resolves to the blob result.
145
+ */
146
+ public blob<T = BlobResult>(
147
+ path: string,
148
+ args?: FetchRequestInit<T, TRequest, TResponse>,
149
+ ): Promise<T> {
126
150
  return firstValueFrom(this.blob$(path, args));
127
151
  }
128
152
 
@@ -12,6 +12,13 @@ export type JsonRequest<TRequest extends FetchRequest = FetchRequest> = Omit<TRe
12
12
  body?: object | string | null;
13
13
  };
14
14
 
15
+ /**
16
+ * Represents the result of a blob operation, including the filename (if available) and the blob itself.
17
+ * @property {string} [filename] - The filename of the blob, if available.
18
+ * @property {Blob} blob - The blob data.
19
+ */
20
+ export type BlobResult = { filename?: string; blob: Blob };
21
+
15
22
  export type FetchResponse<T = unknown> = Response & {
16
23
  json(): Promise<T>;
17
24
  };
@@ -149,15 +156,29 @@ export interface IHttpClient<TRequest extends FetchRequest = FetchRequest, TResp
149
156
  args?: FetchRequestInit<T, JsonRequest<TRequest>, TResponse>,
150
157
  ): Promise<T>;
151
158
 
152
- blob(
159
+ /**
160
+ * Fetches a blob resource from the specified path.
161
+ *
162
+ * @param path - The path to the blob resource.
163
+ * @param args - Optional arguments for the fetch request, including the request body, headers, and response type.
164
+ * @returns A Promise that resolves to the fetched blob data.
165
+ */
166
+ blob<T = BlobResult>(
153
167
  path: string,
154
- args?: FetchRequestInit<Blob, JsonRequest<TRequest>, TResponse>,
155
- ): Promise<Blob>;
168
+ args?: FetchRequestInit<T, JsonRequest<TRequest>, TResponse>,
169
+ ): Promise<T>;
156
170
 
157
- blob$(
171
+ /**
172
+ * Fetches a blob from the specified path and returns a stream response.
173
+ *
174
+ * @param path - The path to fetch the blob from.
175
+ * @param args - Optional arguments for the fetch request, including the request body, headers, and response type.
176
+ * @returns A stream response containing the fetched blob.
177
+ */
178
+ blob$<T = BlobResult>(
158
179
  path: string,
159
- args?: FetchRequestInit<Blob, JsonRequest<TRequest>, TResponse>,
160
- ): StreamResponse<Blob>;
180
+ args?: FetchRequestInit<T, JsonRequest<TRequest>, TResponse>,
181
+ ): StreamResponse<T>;
161
182
 
162
183
  /**
163
184
  * Abort all ongoing request for current client
@@ -1,17 +1,39 @@
1
- export const blobSelector = <TResponse extends Response = Response>(
1
+ import { type BlobResult } from '../client/types';
2
+
3
+ /**
4
+ * Extracts a blob and filename from a successful HTTP response.
5
+ *
6
+ * @param response - The HTTP response to extract the blob and filename from.
7
+ * @returns A promise that resolves to an object containing the extracted blob and filename.
8
+ * @throws {Error} If the response is not successful or if there is an error parsing the response.
9
+ */
10
+ export const blobSelector = async <TResponse extends Response = Response>(
2
11
  response: TResponse,
3
- ): Promise<Blob> => {
12
+ ): Promise<BlobResult> => {
4
13
  if (!response.ok) {
14
+ // Throw an error if the network response is not successful
5
15
  throw new Error('network response was not OK');
6
16
  }
7
- //Status code 204 is no content
17
+
18
+ // Status code 204 indicates no content, so throw an error
8
19
  if (response.status === 204) {
9
20
  throw new Error('no content');
10
21
  }
11
22
 
23
+ // Extract the filename from the 'content-disposition' header
24
+ const filename = response.headers
25
+ .get('content-disposition')
26
+ ?.split(';')
27
+ .find((n) => n.includes('filename='))
28
+ ?.replace('filename=', '')
29
+ ?.trim();
30
+
12
31
  try {
13
- return response.blob();
32
+ // Convert the response to a Blob and return the filename and Blob
33
+ const blob = await response.blob();
34
+ return { filename, blob };
14
35
  } catch (err) {
36
+ // Throw an error if there's a problem parsing the response
15
37
  throw Error('failed to parse response');
16
38
  }
17
39
  };
@@ -1,30 +1,46 @@
1
1
  import { HttpJsonResponseError } from '../../errors';
2
2
 
3
3
  /**
4
- * Converts the JSON response from an HTTP request into the specified type.
5
- * If the response is not OK or if there is an error parsing the response, an error is thrown.
6
- * If the response has a status code of 204 (No Content), a resolved Promise is returned.
4
+ * Asynchronously parses the JSON data from a given HTTP response.
7
5
  *
8
- * @param response The HTTP response object.
9
- * @returns A Promise that resolves to the parsed JSON data.
10
- * @throws {Error} If the network response is not OK.
11
- * @throws {HttpJsonResponseError} If there is an error parsing the response.
6
+ * If the response has a status code of 204 (No Content), this function will resolve with `undefined`.
7
+ *
8
+ * If the response is not successful (i.e. `response.ok` is `false`), this function will throw an `HttpJsonResponseError` with the response details and the parsed data (if any).
9
+ *
10
+ * If there is an error parsing the JSON data, this function will throw an `HttpJsonResponseError` with the parsing error and the original response.
11
+ *
12
+ * @template TType - The expected type of the parsed JSON data.
13
+ * @template TResponse - The type of the HTTP response object.
14
+ * @param response - The HTTP response to parse.
15
+ * @returns A promise that resolves with the parsed JSON data, or rejects with an `HttpJsonResponseError`.
12
16
  */
13
17
  export const jsonSelector = async <TType = unknown, TResponse extends Response = Response>(
14
18
  response: TResponse,
15
19
  ): Promise<TType> => {
16
- /** Status code 204 is no content */
20
+ /** Status code 204 indicates no content in the response */
17
21
  if (response.status === 204) {
18
22
  return Promise.resolve() as Promise<TType>;
19
23
  }
20
24
 
21
25
  try {
26
+ // Parse the response JSON data
22
27
  const data = await response.json();
28
+
29
+ // Check if the response was successful
23
30
  if (!response.ok) {
31
+ // Throw an error with the response details
24
32
  throw new HttpJsonResponseError('network response was not OK', response, { data });
25
33
  }
34
+
35
+ // Return the parsed data
26
36
  return data;
27
37
  } catch (cause) {
38
+ // If the cause is an HttpJsonResponseError, rethrow it
39
+ if (cause instanceof HttpJsonResponseError) {
40
+ throw cause;
41
+ }
42
+
43
+ // Otherwise, throw a new HttpJsonResponseError with the parsing error
28
44
  throw new HttpJsonResponseError('failed to parse response', response, { cause });
29
45
  }
30
46
  };
package/src/version.ts CHANGED
@@ -1,2 +1,2 @@
1
1
  // Generated by genversion.
2
- export const version = '5.2.3';
2
+ export const version = '6.0.0';