@openmrs/esm-api 10.0.1-pre.5607 → 10.0.1-pre.5616

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.
@@ -109,19 +109,17 @@ export function openmrsFetch<T = any>(path: string, fetchInit: FetchConfig = {})
109
109
  fetchInit.headers = {};
110
110
  }
111
111
 
112
- /* Automatically stringify javascript objects being sent in the
113
- * request body.
114
- */
112
+ // Automatically stringify javascript objects being sent in the
113
+ // request body.
115
114
  if (isPlainObject(fetchInit.body)) {
116
115
  fetchInit.body = JSON.stringify(fetchInit.body);
117
116
  }
118
117
 
119
- /* Add a request header to tell the server to respond with json,
120
- * since frontend code almost always wants json and the OpenMRS
121
- * server won't give you json unless you explicitly ask for it.
122
- * If a different Accept header is preferred, pass it into the fetchInit.
123
- * If no Accept header is desired, pass it in explicitly as null.
124
- */
118
+ // Add a request header to tell the server to respond with json,
119
+ // since frontend code almost always wants json and the OpenMRS
120
+ // server won't give you json unless you explicitly ask for it.
121
+ // If a different Accept header is preferred, pass it into the fetchInit.
122
+ // If no Accept header is desired, pass it in explicitly as null.
125
123
  if (typeof fetchInit.headers.Accept === 'undefined') {
126
124
  fetchInit.headers.Accept = 'application/json';
127
125
  }
@@ -130,10 +128,9 @@ export function openmrsFetch<T = any>(path: string, fetchInit: FetchConfig = {})
130
128
  delete fetchInit.headers.Accept;
131
129
  }
132
130
 
133
- /* This tells the OpenMRS REST API not to return a WWW-Authenticate
134
- * header. Returning that header is useful when using the API, but
135
- * not from a UI.
136
- */
131
+ // This tells the OpenMRS REST API not to return a WWW-Authenticate
132
+ // header. Returning that header is useful when using the API, but
133
+ // not from a UI.
137
134
  let isRestRequest = false;
138
135
  try {
139
136
  const requestUrl = new URL(url, window.location.href);
@@ -173,11 +170,10 @@ export function openmrsFetch<T = any>(path: string, fetchInit: FetchConfig = {})
173
170
  }
174
171
  }
175
172
 
176
- /* We capture the stacktrace before making the request, so that if an error occurs we can
177
- * log a full stacktrace that includes the code that made the request and handled the response
178
- * Otherwise, we could run into situations where the stacktrace doesn't even show which code
179
- * called @openmrs/api.
180
- */
173
+ // We capture the stacktrace before making the request, so that if an error occurs we can
174
+ // log a full stacktrace that includes the code that made the request and handled the response
175
+ // Otherwise, we could run into situations where the stacktrace doesn't even show which code
176
+ // called @openmrs/api.
181
177
  const requestStacktrace = Error();
182
178
 
183
179
  return window.fetch(url, fetchInit as RequestInit).then(async (r) => {
@@ -185,13 +181,11 @@ export function openmrsFetch<T = any>(path: string, fetchInit: FetchConfig = {})
185
181
  const { redirectAuthFailure, followRedirects } = await getConfig<EsmApiConfigObject>('@openmrs/esm-api');
186
182
 
187
183
  if (response.ok) {
188
- /*
189
- * Backend modules can trigger SPA redirects by returning a `Location` header.
190
- * This is required because `fetch()` hides HTTP redirects from the application.
191
- *
192
- * - Session endpoint (2xx): Authentication challenge URLs (e.g. TOTP,2FA).
193
- * - HTTP 204: Logout redirect URLs (e.g. Keycloak IdP logout). Refer: OA-41 #1231
194
- */
184
+ // Backend modules can trigger SPA redirects by returning a `Location` header.
185
+ // This is required because `fetch()` hides HTTP redirects from the application.
186
+
187
+ // Session endpoint (2xx): Authentication challenge URLs (e.g. TOTP,2FA).
188
+ // HTTP 204: Logout redirect URLs (e.g. Keycloak IdP logout). Refer: OA-41 #1231
195
189
  const location = response.headers.get('location');
196
190
  const shouldRedirect =
197
191
  followRedirects && location && (url === makeUrl(sessionEndpoint) || response.status === 204);
@@ -201,10 +195,9 @@ export function openmrsFetch<T = any>(path: string, fetchInit: FetchConfig = {})
201
195
  }
202
196
 
203
197
  if (response.status === 204) {
204
- /* HTTP 204 - No Content
205
- * We should not try to download the empty response as json. Instead,
206
- * we return null since there is no response body.
207
- */
198
+ // HTTP 204 - No Content
199
+ // We should not try to download the empty response as json. Instead,
200
+ // we return null since there is no response body.
208
201
  response.data = null as unknown as T;
209
202
  return response;
210
203
  } else {
@@ -224,15 +217,12 @@ export function openmrsFetch<T = any>(path: string, fetchInit: FetchConfig = {})
224
217
  });
225
218
  }
226
219
  } else {
227
- /* HTTP response status is not in 200s. Usually this will mean
228
- * either HTTP 400s (bad request from browser) or HTTP 500s (server error)
229
- * Our goal is to come up with best possible stacktrace and error message
230
- * to help developers understand the problem and debug
231
- */
220
+ // HTTP response status is not in 200s. Usually this will mean
221
+ // either HTTP 400s (bad request from browser) or HTTP 500s (server error)
222
+ // Our goal is to come up with best possible stacktrace and error message
223
+ // to help developers understand the problem and debug
232
224
 
233
- /*
234
- * Redirect to given url when redirect on auth failure is enabled
235
- */
225
+ // Redirect to given url when redirect on auth failure is enabled
236
226
  if (
237
227
  (url === makeUrl(sessionEndpoint) && response.status === 403) ||
238
228
  (redirectAuthFailure.enabled && redirectAuthFailure.errors.includes(response.status))
@@ -244,40 +234,37 @@ export function openmrsFetch<T = any>(path: string, fetchInit: FetchConfig = {})
244
234
  const location = redirectAuthFailure.url || response.headers.get('location') || defaultRedirectAuthFailureUrl;
245
235
  navigate({ to: location });
246
236
 
247
- /* We sometimes don't really want this promise to resolve since there's no response data,
248
- * nor do we want it to reject because that would trigger error handling. We instead
249
- * want it to remain in pending status while the navigation occurs.
250
- */
251
- return redirectAuthFailure.resolvePromise
252
- ? (Promise.resolve() as unknown as Promise<FetchResponse>)
253
- : new Promise<FetchResponse>(() => {});
254
- } else {
255
- // Attempt to download a response body, if it has one
256
- return response
257
- .clone()
258
- .text()
259
- .then(
260
- (responseText) => {
261
- let responseBody = responseText;
262
- try {
263
- responseBody = JSON.parse(responseText);
264
- } catch (err) {
265
- // Server didn't respond with json, so just go with the response text string
266
- }
267
-
268
- /* Make the fetch promise go into "rejected" status, with the best
269
- * possible stacktrace and error message.
270
- */
271
- throw new OpenmrsFetchError(url, response, responseBody, requestStacktrace);
272
- },
273
- (err) => {
274
- /* We weren't able to download a response body for this error.
275
- * Time to just give the best possible stacktrace and error message.
276
- */
277
- throw new OpenmrsFetchError(url, response, null, requestStacktrace);
278
- },
279
- );
237
+ const rejectAuthFailures = fetchInit.rejectAuthFailure === true;
238
+ if (!rejectAuthFailures) {
239
+ return redirectAuthFailure.resolvePromise
240
+ ? (Promise.resolve() as unknown as Promise<FetchResponse>)
241
+ : new Promise<FetchResponse>(() => {});
242
+ }
280
243
  }
244
+
245
+ // Attempt to download a response body, if it has one
246
+ return response
247
+ .clone()
248
+ .text()
249
+ .then(
250
+ (responseText) => {
251
+ let responseBody = responseText;
252
+ try {
253
+ responseBody = JSON.parse(responseText);
254
+ } catch (err) {
255
+ // Server didn't respond with json, so just go with the response text string
256
+ }
257
+
258
+ // Make the fetch promise go into "rejected" status, with the best
259
+ // possible stacktrace and error message.
260
+ throw new OpenmrsFetchError(url, response, responseBody, requestStacktrace);
261
+ },
262
+ () => {
263
+ // We weren't able to download a response body for this error.
264
+ // Time to just give the best possible stacktrace and error message.
265
+ throw new OpenmrsFetchError(url, response, null, requestStacktrace);
266
+ },
267
+ );
281
268
  }
282
269
  });
283
270
  }
@@ -298,6 +285,11 @@ export class OpenmrsFetchError extends Error implements FetchError {
298
285
  export interface FetchConfig extends Omit<RequestInit, 'body' | 'headers'> {
299
286
  headers?: FetchHeaders;
300
287
  body?: FetchBody | string;
288
+ /**
289
+ * When `true`, a response that triggers the auth-failure redirect still navigates, but the
290
+ * returned promise rejects with an `OpenmrsFetchError` instead of staying pending.
291
+ */
292
+ rejectAuthFailure?: boolean;
301
293
  }
302
294
 
303
295
  type ResponseBody = string | FetchResponseJson;
package/src/public.ts CHANGED
@@ -15,5 +15,16 @@ export {
15
15
  } from './current-user';
16
16
  export * from './environment';
17
17
  export * from './types';
18
- export * from './openmrs-fetch';
18
+ export {
19
+ fhirBaseUrl,
20
+ makeUrl,
21
+ openmrsFetch,
22
+ OpenmrsFetchError,
23
+ restBaseUrl,
24
+ sessionEndpoint,
25
+ type FetchConfig,
26
+ type FetchError,
27
+ type FetchHeaders,
28
+ type FetchResponseJson,
29
+ } from './openmrs-fetch';
19
30
  export * from './openmrs-backend-dependencies';