@equinor/fusion-framework-module-http 7.0.8 → 8.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.
Files changed (41) hide show
  1. package/CHANGELOG.md +34 -27
  2. package/README.md +141 -925
  3. package/dist/esm/configurator.js +5 -5
  4. package/dist/esm/configurator.js.map +1 -1
  5. package/dist/esm/lib/client/client-msal.js +3 -2
  6. package/dist/esm/lib/client/client-msal.js.map +1 -1
  7. package/dist/esm/lib/client/client.js +8 -7
  8. package/dist/esm/lib/client/client.js.map +1 -1
  9. package/dist/esm/lib/operators/index.js +1 -0
  10. package/dist/esm/lib/operators/index.js.map +1 -1
  11. package/dist/esm/lib/selectors/index.js +1 -0
  12. package/dist/esm/lib/selectors/index.js.map +1 -1
  13. package/dist/esm/module.js +18 -9
  14. package/dist/esm/module.js.map +1 -1
  15. package/dist/esm/provider.js +38 -27
  16. package/dist/esm/provider.js.map +1 -1
  17. package/dist/esm/version.js +1 -1
  18. package/dist/tsconfig.tsbuildinfo +1 -1
  19. package/dist/types/configurator.d.ts +49 -26
  20. package/dist/types/lib/client/client.d.ts +7 -7
  21. package/dist/types/lib/operators/index.d.ts +1 -0
  22. package/dist/types/lib/selectors/index.d.ts +2 -0
  23. package/dist/types/module.d.ts +18 -9
  24. package/dist/types/provider.d.ts +24 -19
  25. package/dist/types/version.d.ts +1 -1
  26. package/docs/client-configuration.md +175 -0
  27. package/docs/observable-patterns.md +103 -0
  28. package/docs/selectors-and-handlers.md +112 -0
  29. package/docs/server-sent-events.md +125 -0
  30. package/package.json +6 -6
  31. package/src/configurator.ts +54 -26
  32. package/src/lib/client/client-msal.ts +3 -2
  33. package/src/lib/client/client.ts +8 -9
  34. package/src/lib/operators/index.ts +1 -0
  35. package/src/lib/selectors/index.ts +7 -0
  36. package/src/module.ts +18 -9
  37. package/src/provider.ts +56 -34
  38. package/src/version.ts +1 -1
  39. package/tests/HttpClient.test.ts +90 -11
  40. package/tests/operators.test.ts +24 -0
  41. package/tests/sse.selector.test.ts +6 -7
@@ -0,0 +1,112 @@
1
+ # Selectors And Handlers
2
+
3
+ Selectors and handlers are related, but they solve different problems.
4
+
5
+ - selectors transform a `Response` into the value your application consumes
6
+ - request handlers shape or validate the outgoing request
7
+ - response handlers apply transport-level response rules before selector parsing runs
8
+
9
+ Use this split to keep parsing logic separate from transport policy.
10
+
11
+ ## Choose The Right Tool
12
+
13
+ | Need | Use |
14
+ | --- | --- |
15
+ | Parse JSON, blobs, or SSE events | selector |
16
+ | Add headers, normalize methods, validate request shape | request handler |
17
+ | Reject certain responses before parsing | response handler |
18
+ | Reuse parsing rules across multiple calls | selector |
19
+ | Reuse transport behavior across a client configuration | handler |
20
+
21
+ ## Built-In Selectors
22
+
23
+ | Selector | What it returns | Notes |
24
+ | --- | --- | --- |
25
+ | `jsonSelector` | parsed JSON or `undefined` for `204` | Throws `HttpJsonResponseError` on non-OK responses and includes parsed error payloads when possible |
26
+ | `blobSelector` | `{ filename?, blob }` | Extracts `filename` from the `content-disposition` header when present |
27
+ | `createSseSelector` | `Observable<ServerSentEvent<T>>` | Lower-level SSE selector used by `client.sse$()` |
28
+
29
+ ## Custom Selector Example
30
+
31
+ ```typescript
32
+ import {
33
+ jsonSelector,
34
+ type ResponseSelector,
35
+ } from '@equinor/fusion-framework-module-http/selectors';
36
+
37
+ type User = {
38
+ id: string;
39
+ name: string;
40
+ };
41
+
42
+ const userSelector: ResponseSelector<User> = async (response) => {
43
+ const data = await jsonSelector<User>(response);
44
+ return {
45
+ ...data,
46
+ name: data.name.trim(),
47
+ };
48
+ };
49
+ ```
50
+
51
+ That selector can then be passed to `client.fetch('/users/42', { selector: userSelector })`.
52
+
53
+ ## Request And Response Handlers
54
+
55
+ Handlers are sequential operator pipelines attached to each client instance.
56
+
57
+ - `add(key, operator)` throws if the key already exists
58
+ - `set(key, operator)` adds or replaces an operator
59
+ - `remove(key)` removes an operator
60
+ - returning `void` keeps the previous value flowing through the pipeline
61
+ - operators run in insertion order
62
+
63
+ The public handler types and utilities are exported from `@equinor/fusion-framework-module-http/operators`.
64
+
65
+ ## Default Request Pipeline
66
+
67
+ Each created client starts with a default request pipeline containing:
68
+
69
+ 1. `capitalizeRequestMethodOperator()`
70
+ 2. `requestValidationOperator()`
71
+
72
+ That means lowercase methods are normalized to uppercase and request options are validated in non-throwing mode by default.
73
+
74
+ ## Built-In Request Operators
75
+
76
+ - `capitalizeRequestMethodOperator(options?)` uppercases `request.method` and can suppress warnings with `silent: true`
77
+ - `requestValidationOperator(options?)` validates the request against the package schema and can optionally return parsed values
78
+
79
+ ## Example: Configure Both Parsing And Transport
80
+
81
+ ```typescript
82
+ import {
83
+ capitalizeRequestMethodOperator,
84
+ requestValidationOperator,
85
+ } from '@equinor/fusion-framework-module-http/operators';
86
+
87
+ configurator.configureHttpClient('catalog', {
88
+ baseUri: '/api/catalog',
89
+ onCreate: (client) => {
90
+ client.requestHandler.set('validate-strict', requestValidationOperator({
91
+ parse: true,
92
+ strict: true,
93
+ }));
94
+
95
+ client.requestHandler.add('normalize-method', capitalizeRequestMethodOperator());
96
+
97
+ client.responseHandler.add('reject-server-errors', (response) => {
98
+ if (response.status >= 500) {
99
+ throw new Error(`Unexpected response status: ${response.status}`);
100
+ }
101
+ });
102
+ },
103
+ });
104
+ ```
105
+
106
+ ## Rule Of Thumb
107
+
108
+ - use handlers for cross-cutting transport concerns such as headers, validation, logging, token behavior, or rejecting bad responses
109
+ - use selectors for parsing a response into a domain shape
110
+ - use observables for orchestration and composition
111
+
112
+ When a piece of logic changes how the request travels, it usually belongs in a handler. When it changes what value the caller receives, it usually belongs in a selector.
@@ -0,0 +1,125 @@
1
+ # Server-Sent Events
2
+
3
+ Use `client.sse$()` when an endpoint returns `text/event-stream` and you want parsed `ServerSentEvent<T>` objects instead of manually reading the response body.
4
+
5
+ This is the highest-level SSE API in the package. If you need lower-level composition, use `createSseSelector` or `sseMap`.
6
+
7
+ ## Quick Start
8
+
9
+ ```typescript
10
+ const events$ = client.sse$<{ message: string }>('/events', undefined, {
11
+ eventFilter: 'message',
12
+ skipHeartbeats: true,
13
+ });
14
+ ```
15
+
16
+ Subscribe to the result the same way you would any other observable HTTP call.
17
+
18
+ ## `sse$()` Inputs
19
+
20
+ | Input | Where it goes | Purpose |
21
+ | --- | --- | --- |
22
+ | request init | second argument to `sse$()` | HTTP method, body, headers, and `signal` |
23
+ | SSE selector options | third argument to `sse$()` | `eventFilter`, `skipHeartbeats`, and custom parsing |
24
+
25
+ `client.sse$()` uses the request `signal` as the abort signal for the underlying SSE reader.
26
+
27
+ ## SSE Options
28
+
29
+ | Option | Type | What it does |
30
+ | --- | --- | --- |
31
+ | `eventFilter` | `string | string[]` | Emits only matching named SSE events |
32
+ | `skipHeartbeats` | `boolean` | Skips empty heartbeat events and named `heartbeat` or `ping` events |
33
+ | `dataParser` | `(data: string) => T` | Overrides the default parser for the `data:` field |
34
+
35
+ By default, the parser tries `JSON.parse(...)` first and falls back to the raw string when parsing fails.
36
+
37
+ ## What `sse$()` Does For You
38
+
39
+ - adds `Accept: text/event-stream`
40
+ - adds `Content-Type: text/event-stream`
41
+ - adds `Cache-Control: no-cache` and `Connection: keep-alive`
42
+ - validates that the response is a readable `text/event-stream`
43
+ - parses `data:` fields into `ServerSentEvent<T>` objects
44
+ - honors `retry:` directives by delaying before continuing to read
45
+ - stops reading when the observable is unsubscribed or the abort signal fires
46
+
47
+ ## Abort Behavior
48
+
49
+ Pass an `AbortSignal` through the request init when you need explicit cancellation.
50
+
51
+ ```typescript
52
+ const abortController = new AbortController();
53
+
54
+ const events$ = client.sse$<{ message: string }>(
55
+ '/events',
56
+ { signal: abortController.signal },
57
+ { skipHeartbeats: true },
58
+ );
59
+
60
+ abortController.abort();
61
+ ```
62
+
63
+ Unsubscribing from the observable also stops the underlying stream.
64
+
65
+ ## Lower-Level SSE APIs
66
+
67
+ ### `createSseSelector`
68
+
69
+ Use `createSseSelector` when you want to compose SSE handling with `fetch()` or `fetch$()` yourself.
70
+
71
+ Unlike `client.sse$()`, the lower-level SSE APIs do not add SSE request headers for you. Add the headers your endpoint expects, especially `Accept: text/event-stream`.
72
+
73
+ ```typescript
74
+ import { createSseSelector } from '@equinor/fusion-framework-module-http/selectors';
75
+
76
+ const selector = createSseSelector<{ message: string }>({
77
+ eventFilter: ['message', 'update'],
78
+ skipHeartbeats: true,
79
+ });
80
+
81
+ const events$ = client.fetch$('/events', {
82
+ headers: {
83
+ Accept: 'text/event-stream',
84
+ 'Cache-Control': 'no-cache',
85
+ Connection: 'keep-alive',
86
+ },
87
+ selector,
88
+ });
89
+ ```
90
+
91
+ ### `sseMap`
92
+
93
+ Use `sseMap` when you already have a response observable and want to transform that stream into SSE events.
94
+
95
+ ```typescript
96
+ import { sseMap } from '@equinor/fusion-framework-module-http/operators';
97
+
98
+ const events$ = client.fetch$('/events', {
99
+ headers: {
100
+ Accept: 'text/event-stream',
101
+ 'Cache-Control': 'no-cache',
102
+ Connection: 'keep-alive',
103
+ },
104
+ }).pipe(
105
+ sseMap<{ message: string }>({
106
+ skipHeartbeats: true,
107
+ }),
108
+ );
109
+ ```
110
+
111
+ ## Error Handling
112
+
113
+ The SSE APIs throw `ServerSentEventResponseError` when:
114
+
115
+ - the response is not OK
116
+ - the response body is not readable
117
+ - the response does not advertise `text/event-stream`
118
+
119
+ Handle SSE errors the same way you handle any other observable request error.
120
+
121
+ ## Rule Of Thumb
122
+
123
+ - use `sse$()` for normal application code
124
+ - use `createSseSelector` when you want selector-level control
125
+ - use `sseMap` when you already have a response observable pipeline
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@equinor/fusion-framework-module-http",
3
- "version": "7.0.8",
3
+ "version": "8.0.0",
4
4
  "description": "",
5
5
  "main": "dist/esm/index.js",
6
6
  "types": "dist/types/index.d.ts",
@@ -58,13 +58,13 @@
58
58
  },
59
59
  "dependencies": {
60
60
  "rxjs": "^7.8.1",
61
- "zod": "^4.1.8",
62
- "@equinor/fusion-framework-module": "^5.0.6",
63
- "@equinor/fusion-framework-module-msal": "^7.3.1"
61
+ "zod": "^4.3.6",
62
+ "@equinor/fusion-framework-module": "^6.0.0",
63
+ "@equinor/fusion-framework-module-msal": "^8.0.0"
64
64
  },
65
65
  "devDependencies": {
66
- "typescript": "^5.8.2",
67
- "vitest": "^3.2.4"
66
+ "typescript": "^5.9.3",
67
+ "vitest": "^4.1.0"
68
68
  },
69
69
  "scripts": {
70
70
  "build": "tsc -b",
@@ -11,10 +11,13 @@ import type { IHttpRequestHandler, IHttpResponseHandler } from './lib/operators'
11
11
  * Represents the options for constructing an `IHttpClient` instance.
12
12
  *
13
13
  * @template TInit - The type of the initial request object used by the `IHttpClient` instance.
14
+ * @template TResponse - The type of the response object used by the `IHttpClient` instance.
14
15
  * @property {IHttpRequestHandler<TInit>} requestHandler - The request handler to be used by the `IHttpClient` instance.
16
+ * @property {IHttpResponseHandler<TResponse>} [responseHandler] - The response handler to be used by the `IHttpClient` instance.
15
17
  */
16
- interface HttpClientConstructorOptions<TInit extends FetchRequest> {
18
+ interface HttpClientConstructorOptions<TInit extends FetchRequest, TResponse = Response> {
17
19
  requestHandler: IHttpRequestHandler<TInit>;
20
+ responseHandler?: IHttpResponseHandler<TResponse>;
18
21
  }
19
22
 
20
23
  /**
@@ -28,14 +31,20 @@ interface HttpClientConstructorOptions<TInit extends FetchRequest> {
28
31
  interface HttpClientConstructor<TClient extends IHttpClient> {
29
32
  new (
30
33
  uri: string,
31
- options: HttpClientConstructorOptions<HttpClientRequestInitType<TClient>>,
34
+ options: HttpClientConstructorOptions<
35
+ HttpClientRequestInitType<TClient>,
36
+ HttpClientResponseType<TClient>
37
+ >,
32
38
  ): TClient;
33
39
  }
34
40
 
35
41
  /**
36
- * Represents the options for configuring an `IHttpClient` instance.
42
+ * Configures how the provider creates a named `IHttpClient` instance.
37
43
  *
38
- * @template TClient - The type of the `IHttpClient` instance to be configured.
44
+ * Use these options to define a base URL, MSAL scopes, shared request or response handlers,
45
+ * a custom client constructor, or per-instance setup through `onCreate`.
46
+ *
47
+ * @template TClient - The client type created from this configuration.
39
48
  */
40
49
  export interface HttpClientOptions<TClient extends IHttpClient = IHttpClient> {
41
50
  /** The base URI for the `IHttpClient` instance. */
@@ -54,7 +63,7 @@ export interface HttpClientOptions<TClient extends IHttpClient = IHttpClient> {
54
63
  requestHandler?: IHttpRequestHandler<HttpClientRequestInitType<TClient>>;
55
64
 
56
65
  /** The response handler to be used by the `IHttpClient` instance. */
57
- responseHandler?: IHttpResponseHandler<HttpClientRequestInitType<TClient>>;
66
+ responseHandler?: IHttpResponseHandler<HttpClientResponseType<TClient>>;
58
67
  }
59
68
 
60
69
  /**
@@ -68,8 +77,21 @@ export type HttpClientRequestInitType<T extends IHttpClient> =
68
77
  T extends IHttpClient<infer U> ? U : never;
69
78
 
70
79
  /**
71
- * Instance for configuring http client
72
- * @template TClient base type of client that the provider will create
80
+ * Utility type that extracts the response type from an `IHttpClient` implementation.
81
+ * This is useful for ensuring type safety when configuring response handlers for an `IHttpClient` instance.
82
+ *
83
+ * @template T - The type of the `IHttpClient` implementation.
84
+ * @returns The response type for the `IHttpClient` implementation.
85
+ */
86
+ export type HttpClientResponseType<T extends IHttpClient> =
87
+ T extends IHttpClient<infer _TRequest, infer TResponse> ? TResponse : never;
88
+
89
+ /**
90
+ * Registers and looks up named HTTP client configurations for the HTTP module.
91
+ *
92
+ * Each named configuration can later be turned into a fresh client instance by the provider.
93
+ *
94
+ * @template TClient - The base client type the provider creates.
73
95
  */
74
96
  export interface IHttpClientConfigurator<TClient extends IHttpClient = IHttpClient> {
75
97
  readonly clients: Record<string, HttpClientOptions<TClient>>;
@@ -77,14 +99,15 @@ export interface IHttpClientConfigurator<TClient extends IHttpClient = IHttpClie
77
99
  readonly defaultHttpRequestHandler: IHttpRequestHandler<HttpClientRequestInitType<TClient>>;
78
100
 
79
101
  /**
80
- * Configure a client with arguments
81
- * @param name name of the client
82
- * @param args option that are used cor creating a client
102
+ * Registers or updates a named client configuration.
103
+ * @param name - The client key used later with `createClient(name)`.
104
+ * @param args - The configuration used when creating a client instance.
105
+ * @returns The configurator so registrations can be chained.
83
106
  * @example
84
107
  * ```ts
85
- * configurator.http.configureClient('foo',{
86
- * baseUri: 'https://foo.bar',
87
- * defaultScopes: ['foobar/.default']
108
+ * configurator.http.configureClient('catalog', {
109
+ * baseUri: 'https://api.example.com',
110
+ * defaultScopes: ['api://catalog-api/.default'],
88
111
  * });
89
112
  * ```
90
113
  */
@@ -94,18 +117,21 @@ export interface IHttpClientConfigurator<TClient extends IHttpClient = IHttpClie
94
117
  ): IHttpClientConfigurator<TClient>;
95
118
 
96
119
  /**
97
- * Configure a simple client by name to an endpoint
98
- * @param name name of the client
99
- * @param uri base endpoint for the client
120
+ * Registers a named client with only a base URI.
121
+ * @param name - The client key used later with `createClient(name)`.
122
+ * @param uri - The base endpoint for the client.
123
+ * @returns The configurator so registrations can be chained.
100
124
  */
101
125
  configureClient(name: string, uri: string): IHttpClientConfigurator<TClient>;
102
126
 
103
127
  /**
104
- * Creates a client with callback configuration
105
- * @param name name of the client
106
- * @param onCreate callback when a client is created
128
+ * Registers a named client using only an `onCreate` callback.
129
+ * @param name - The client key used later with `createClient(name)`.
130
+ * @param onCreate - The callback that runs for every created client instance.
131
+ * @returns The configurator so registrations can be chained.
132
+ * @example
107
133
  * ```ts
108
- * configurator.http.configureClient('foo',(client) => {
134
+ * configurator.http.configureClient('catalog', (client) => {
109
135
  * client.requestHandler.add('logger', (request) => console.log(request));
110
136
  * });
111
137
  * ```
@@ -116,7 +142,9 @@ export interface IHttpClientConfigurator<TClient extends IHttpClient = IHttpClie
116
142
  ): HttpClientConfigurator<TClient>;
117
143
 
118
144
  /**
119
- * Check if there is a configuration for provided name
145
+ * Checks whether a named client configuration exists.
146
+ * @param name - The client key to check.
147
+ * @returns `true` when a configuration exists for the key.
120
148
  */
121
149
  hasClient(name: string): boolean;
122
150
  }
@@ -127,15 +155,15 @@ export class HttpClientConfigurator<TClient extends IHttpClient>
127
155
  {
128
156
  protected _clients: Record<string, HttpClientOptions<TClient>> = {};
129
157
 
130
- /** Get a clone of all configured clients */
158
+ /** Gets a shallow clone of all named client configurations. */
131
159
  public get clients(): Record<string, HttpClientOptions<TClient>> {
132
160
  return { ...this._clients };
133
161
  }
134
162
 
135
- /** default class for creation of http clients */
163
+ /** Default constructor used when a client configuration does not provide `ctor`. */
136
164
  readonly defaultHttpClientCtor: HttpClientConstructor<TClient>;
137
165
 
138
- /** default request handler for http clients, applied on creation */
166
+ /** Default request handler pipeline cloned into each created client instance. */
139
167
  readonly defaultHttpRequestHandler = new HttpRequestHandler<HttpClientRequestInitType<TClient>>({
140
168
  // convert all request methods to uppercase
141
169
  'capitalize-method': capitalizeRequestMethodOperator(),
@@ -144,8 +172,8 @@ export class HttpClientConfigurator<TClient extends IHttpClient>
144
172
  });
145
173
 
146
174
  /**
147
- * Create a instance of http configuration
148
- * @param client defaultHttpRequestHandler
175
+ * Creates a configurator with the default client constructor.
176
+ * @param client - The default client constructor used when `ctor` is not configured per client.
149
177
  */
150
178
  constructor(client: HttpClientConstructor<TClient>) {
151
179
  this.defaultHttpClientCtor = client;
@@ -67,9 +67,10 @@ export class HttpClientMsal<
67
67
  * Merges the default scopes defined in the `HttpClientMsal` class with the scopes provided in the `init` parameter, if any.
68
68
  * This ensures that the request includes the necessary scopes for MSAL authentication.
69
69
  */
70
- const args = Object.assign(init || {}, {
70
+ const args = {
71
+ ...init,
71
72
  scopes: this.defaultScopes.concat(init?.scopes || []),
72
- }) as FetchRequestInit<T, TRequest, TResponse>;
73
+ } as FetchRequestInit<T, TRequest, TResponse>;
73
74
 
74
75
  return super._fetch$(path, args);
75
76
  }
@@ -14,14 +14,12 @@ import type {
14
14
  FetchResponse,
15
15
  IHttpClient,
16
16
  JsonRequest,
17
- ResponseSelector,
18
17
  StreamResponse,
19
18
  } from './types';
20
19
 
21
20
  import { HttpResponseError } from '../../errors';
22
21
  import {
23
22
  createSseSelector,
24
- SseSelector,
25
23
  type ServerSentEvent,
26
24
  type SseSelectorOptions,
27
25
  } from '../selectors/sse-selector';
@@ -240,15 +238,15 @@ export class HttpClient<
240
238
  * @returns A `StreamResponse` that emits `ServerSentEvent<T>` objects as they are received from the server.
241
239
  *
242
240
  * @example
243
- * const sse$ = httpClient.sse(
244
- * '/events',
245
- * { method: 'POST', body: JSON.stringify({ prompt: 'tell me a joke' }) },
246
- * { eventFilter: ['message'] }
241
+ * const sse$ = httpClient.sse$(
242
+ * '/events',
243
+ * { method: 'POST', body: JSON.stringify({ prompt: 'tell me a joke' }) },
244
+ * { eventFilter: ['message'] },
247
245
  * );
248
246
  * sse$.subscribe({
249
- * next: (event) => console.log(event),
250
- * error: (err) => console.error(err),
251
- * complete: () => console.log('Completed'),
247
+ * next: (event) => console.log(event),
248
+ * error: (err) => console.error(err),
249
+ * complete: () => console.log('Completed'),
252
250
  * });
253
251
  */
254
252
  public sse$<T = unknown>(
@@ -329,6 +327,7 @@ export class HttpClient<
329
327
  const { selector, ...options } = args || {};
330
328
  const response$ = of({
331
329
  ...options,
330
+ path,
332
331
  uri: this._resolveUrl(path),
333
332
  } as TRequest).pipe(
334
333
  /** prepare request, allow extensions to modify request */
@@ -3,5 +3,6 @@ export { HttpResponseHandler } from './http-response-handler';
3
3
  export { ProcessOperators } from './process-operators';
4
4
  export { capitalizeRequestMethodOperator } from './capitalize-request-method.operator';
5
5
  export { requestValidationOperator } from './request-validation.operator';
6
+ export { sseMap } from './sse.operator';
6
7
 
7
8
  export * from './types';
@@ -1,4 +1,11 @@
1
1
  export { jsonSelector } from './json-selector';
2
2
  export { blobSelector } from './blob-selector';
3
+ export { createSseSelector } from './sse-selector';
3
4
 
4
5
  export type { ResponseSelector } from '../client/types';
6
+ export type {
7
+ DataParser,
8
+ ServerSentEvent,
9
+ SseSelector,
10
+ SseSelectorOptions,
11
+ } from './sse-selector';
package/src/module.ts CHANGED
@@ -40,7 +40,11 @@ export type HttpMsalModule = Module<
40
40
  >;
41
41
 
42
42
  /**
43
- * HTTP module with MSAL authentication.
43
+ * Default HTTP module definition for Fusion Framework applications.
44
+ *
45
+ * The module uses `HttpClientMsal` as the default client implementation and,
46
+ * when the auth module is available, installs a request handler that can acquire
47
+ * bearer tokens for scoped requests.
44
48
  */
45
49
  export const module: HttpMsalModule = {
46
50
  name: 'http',
@@ -95,7 +99,13 @@ export const module: HttpMsalModule = {
95
99
  };
96
100
 
97
101
  /**
98
- * Configures the HTTP module with MSAL authentication.
102
+ * Creates a module configurator for the HTTP module.
103
+ *
104
+ * Use this when you need lower-level access to the module configuration callback,
105
+ * for example when registering several named clients in one setup step.
106
+ *
107
+ * @param configure - The callback that receives the HTTP module configuration.
108
+ * @returns A module configurator for the HTTP module.
99
109
  */
100
110
  export const configureHttp = <TRef = unknown>(
101
111
  configure: (config: ModuleConfigType<HttpMsalModule>, ref?: TRef) => void,
@@ -105,15 +115,14 @@ export const configureHttp = <TRef = unknown>(
105
115
  });
106
116
 
107
117
  /**
108
- * Configures the HTTP client with MSAL authentication.
118
+ * Creates a module configurator that registers one named HTTP client.
109
119
  *
110
- * This function creates a module configurator that can be used to configure the HTTP module
111
- * with MSAL authentication. The configurator takes a name and a set of HTTP client options,
112
- * and returns a module configurator that can be used to configure the HTTP module.
120
+ * This is the convenience API for the common case where a setup step only needs to
121
+ * register one client with `baseUri`, `defaultScopes`, handlers, or a custom constructor.
113
122
  *
114
- * @param name - The name of the HTTP client configuration.
115
- * @param args - The HTTP client options, including the MSAL configuration.
116
- * @returns A module configurator that can be used to configure the HTTP module.
123
+ * @param name - The client key used later with `createClient(name)`.
124
+ * @param args - The named client configuration.
125
+ * @returns A module configurator that registers the named client.
117
126
  */
118
127
  export const configureHttpClient = <TRef = unknown>(
119
128
  name: string,