@marianmeres/http-utils 1.9.0 → 1.11.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.
package/README.md CHANGED
@@ -32,7 +32,7 @@ try {
32
32
  assert(e.statusText === HTTP_STATUS.ERROR_CLIENT.NOT_FOUND.TEXT);
33
33
  // `body` is a custom prop containing the raw http response body text (JSON.parse-d if available)
34
34
  assert(e.body.message === 'hey');
35
- // `cause` is a standart Error prop, containg here some default debug info
35
+ // `cause` is a standart Error prop, containing here some default debug info
36
36
  assert(err.cause.response.headers)
37
37
  }
38
38
 
package/dist/api.d.ts CHANGED
@@ -12,11 +12,15 @@ interface FetchParams {
12
12
  assert?: null | boolean;
13
13
  }
14
14
  type BaseFetchParams = BaseParams & FetchParams;
15
- export declare const createHttpApi: (base?: string | null, defaults?: Partial<BaseFetchParams> | (() => Promise<Partial<BaseFetchParams>>)) => {
16
- get(path: string, params?: FetchParams, respHeaders?: any, _dumpParams?: boolean): Promise<any>;
17
- post(path: string, data?: any, params?: FetchParams, respHeaders?: any, _dumpParams?: boolean): Promise<any>;
18
- put(path: string, data?: any, params?: FetchParams, respHeaders?: any, _dumpParams?: boolean): Promise<any>;
19
- patch(path: string, data?: any, params?: FetchParams, respHeaders?: any, _dumpParams?: boolean): Promise<any>;
20
- del(path: string, data?: any, params?: FetchParams, respHeaders?: any, _dumpParams?: boolean): Promise<any>;
15
+ type ErrorMessageExtractor = (body: any, response: Response) => any;
16
+ export declare function createHttpApi(base?: string | null, defaults?: Partial<BaseFetchParams> | (() => Promise<Partial<BaseFetchParams>>), factoryErrorMessageExtractor?: ErrorMessageExtractor | null | undefined): {
17
+ get(path: string, params?: FetchParams, respHeaders?: any, errorMessageExtractor?: ErrorMessageExtractor | null | undefined, _dumpParams?: boolean): Promise<any>;
18
+ post(path: string, data?: any, params?: FetchParams, respHeaders?: any, errorMessageExtractor?: ErrorMessageExtractor | null | undefined, _dumpParams?: boolean): Promise<any>;
19
+ put(path: string, data?: any, params?: FetchParams, respHeaders?: any, errorMessageExtractor?: ErrorMessageExtractor | null | undefined, _dumpParams?: boolean): Promise<any>;
20
+ patch(path: string, data?: any, params?: FetchParams, respHeaders?: any, errorMessageExtractor?: ErrorMessageExtractor | null | undefined, _dumpParams?: boolean): Promise<any>;
21
+ del(path: string, data?: any, params?: FetchParams, respHeaders?: any, errorMessageExtractor?: ErrorMessageExtractor | null | undefined, _dumpParams?: boolean): Promise<any>;
21
22
  };
23
+ export declare namespace createHttpApi {
24
+ var defaultErrorMessageExtractor: ErrorMessageExtractor | null | undefined;
25
+ }
22
26
  export {};
package/dist/index.cjs CHANGED
@@ -297,7 +297,7 @@ const _fetchRaw = async ({ method, path, data = null, token = null, headers = nu
297
297
  }
298
298
  return await fetch(path, opts);
299
299
  };
300
- const _fetch = async (params, respHeaders = null, _dumpParams = false) => {
300
+ const _fetch = async (params, respHeaders = null, errorMessageExtractor = null, _dumpParams = false) => {
301
301
  if (_dumpParams)
302
302
  return params;
303
303
  const r = await _fetchRaw(params);
@@ -319,7 +319,24 @@ const _fetch = async (params, respHeaders = null, _dumpParams = false) => {
319
319
  catch (e) { }
320
320
  params.assert ??= true; // default is true
321
321
  if (!r.ok && params.assert) {
322
- throw createHttpError(r.status, null, body, {
322
+ // now we need to extract error message from an unknown response... this is obviously
323
+ // impossible unless we know what to expect, but we'll do some educated tries...
324
+ const extractor = errorMessageExtractor ?? // provided arg
325
+ createHttpApi.defaultErrorMessageExtractor ?? // static default
326
+ // educated guess fallback
327
+ function (_body, _response) {
328
+ let msg =
329
+ // try opinionated convention first
330
+ _body?.error?.message ||
331
+ _body?.message ||
332
+ _response?.statusText ||
333
+ 'Unknown error';
334
+ if (msg.length > 255)
335
+ msg = `[Shortened]: ${msg.slice(0, 255)}`;
336
+ return msg;
337
+ };
338
+ // adding `cause` describing more details
339
+ throw createHttpError(r.status, extractor(body, r), body, {
323
340
  method: params.method,
324
341
  path: params.path,
325
342
  response: {
@@ -331,7 +348,7 @@ const _fetch = async (params, respHeaders = null, _dumpParams = false) => {
331
348
  }
332
349
  return body;
333
350
  };
334
- const createHttpApi = (base, defaults) => {
351
+ function createHttpApi(base, defaults, factoryErrorMessageExtractor) {
335
352
  const _merge = (a, b) => {
336
353
  const wrap = { result: a };
337
354
  merge.dset(wrap, 'result', b);
@@ -347,33 +364,34 @@ const createHttpApi = (base, defaults) => {
347
364
  });
348
365
  return {
349
366
  // GET
350
- async get(path, params, respHeaders = null, _dumpParams = false) {
367
+ async get(path, params, respHeaders = null, errorMessageExtractor = null, _dumpParams = false) {
351
368
  path = `${base || ''}${path || ''}`;
352
- return _fetch(_merge(await _getDefs(), { ...params, method: 'GET', path }), respHeaders, _dumpParams);
369
+ return _fetch(_merge(await _getDefs(), { ...params, method: 'GET', path }), respHeaders, errorMessageExtractor ?? factoryErrorMessageExtractor, _dumpParams);
353
370
  },
354
371
  // POST
355
- async post(path, data = null, params, respHeaders = null, _dumpParams = false) {
372
+ async post(path, data = null, params, respHeaders = null, errorMessageExtractor = null, _dumpParams = false) {
356
373
  path = `${base || ''}${path || ''}`;
357
- return _fetch(_merge(await _getDefs(), { ...(params || {}), data, method: 'POST', path }), respHeaders, _dumpParams);
374
+ return _fetch(_merge(await _getDefs(), { ...(params || {}), data, method: 'POST', path }), respHeaders, errorMessageExtractor ?? factoryErrorMessageExtractor, _dumpParams);
358
375
  },
359
376
  // PUT
360
- async put(path, data = null, params, respHeaders = null, _dumpParams = false) {
377
+ async put(path, data = null, params, respHeaders = null, errorMessageExtractor = null, _dumpParams = false) {
361
378
  path = `${base || ''}${path || ''}`;
362
- return _fetch(_merge(await _getDefs(), { ...(params || {}), data, method: 'PUT', path }), respHeaders, _dumpParams);
379
+ return _fetch(_merge(await _getDefs(), { ...(params || {}), data, method: 'PUT', path }), respHeaders, errorMessageExtractor ?? factoryErrorMessageExtractor, _dumpParams);
363
380
  },
364
381
  // PATCH
365
- async patch(path, data = null, params, respHeaders = null, _dumpParams = false) {
382
+ async patch(path, data = null, params, respHeaders = null, errorMessageExtractor = null, _dumpParams = false) {
366
383
  path = `${base || ''}${path || ''}`;
367
- return _fetch(_merge(await _getDefs(), { ...(params || {}), data, method: 'PATCH', path }), respHeaders, _dumpParams);
384
+ return _fetch(_merge(await _getDefs(), { ...(params || {}), data, method: 'PATCH', path }), respHeaders, errorMessageExtractor ?? factoryErrorMessageExtractor, _dumpParams);
368
385
  },
369
386
  // DELETE
370
387
  // https://stackoverflow.com/questions/299628/is-an-entity-body-allowed-for-an-http-delete-request
371
- async del(path, data = null, params, respHeaders = null, _dumpParams = false) {
388
+ async del(path, data = null, params, respHeaders = null, errorMessageExtractor = null, _dumpParams = false) {
372
389
  path = `${base || ''}${path || ''}`;
373
- return _fetch(_merge(await _getDefs(), { ...(params || {}), data, method: 'DELETE', path }), respHeaders, _dumpParams);
390
+ return _fetch(_merge(await _getDefs(), { ...(params || {}), data, method: 'DELETE', path }), respHeaders, errorMessageExtractor ?? factoryErrorMessageExtractor, _dumpParams);
374
391
  },
375
392
  };
376
- };
393
+ }
394
+ createHttpApi.defaultErrorMessageExtractor = null;
377
395
 
378
396
  exports.HTTP_ERROR = HTTP_ERROR;
379
397
  exports.HTTP_STATUS = HTTP_STATUS;
package/dist/index.js CHANGED
@@ -295,7 +295,7 @@ const _fetchRaw = async ({ method, path, data = null, token = null, headers = nu
295
295
  }
296
296
  return await fetch(path, opts);
297
297
  };
298
- const _fetch = async (params, respHeaders = null, _dumpParams = false) => {
298
+ const _fetch = async (params, respHeaders = null, errorMessageExtractor = null, _dumpParams = false) => {
299
299
  if (_dumpParams)
300
300
  return params;
301
301
  const r = await _fetchRaw(params);
@@ -317,7 +317,24 @@ const _fetch = async (params, respHeaders = null, _dumpParams = false) => {
317
317
  catch (e) { }
318
318
  params.assert ??= true; // default is true
319
319
  if (!r.ok && params.assert) {
320
- throw createHttpError(r.status, null, body, {
320
+ // now we need to extract error message from an unknown response... this is obviously
321
+ // impossible unless we know what to expect, but we'll do some educated tries...
322
+ const extractor = errorMessageExtractor ?? // provided arg
323
+ createHttpApi.defaultErrorMessageExtractor ?? // static default
324
+ // educated guess fallback
325
+ function (_body, _response) {
326
+ let msg =
327
+ // try opinionated convention first
328
+ _body?.error?.message ||
329
+ _body?.message ||
330
+ _response?.statusText ||
331
+ 'Unknown error';
332
+ if (msg.length > 255)
333
+ msg = `[Shortened]: ${msg.slice(0, 255)}`;
334
+ return msg;
335
+ };
336
+ // adding `cause` describing more details
337
+ throw createHttpError(r.status, extractor(body, r), body, {
321
338
  method: params.method,
322
339
  path: params.path,
323
340
  response: {
@@ -329,7 +346,7 @@ const _fetch = async (params, respHeaders = null, _dumpParams = false) => {
329
346
  }
330
347
  return body;
331
348
  };
332
- const createHttpApi = (base, defaults) => {
349
+ function createHttpApi(base, defaults, factoryErrorMessageExtractor) {
333
350
  const _merge = (a, b) => {
334
351
  const wrap = { result: a };
335
352
  dset(wrap, 'result', b);
@@ -345,32 +362,33 @@ const createHttpApi = (base, defaults) => {
345
362
  });
346
363
  return {
347
364
  // GET
348
- async get(path, params, respHeaders = null, _dumpParams = false) {
365
+ async get(path, params, respHeaders = null, errorMessageExtractor = null, _dumpParams = false) {
349
366
  path = `${base || ''}${path || ''}`;
350
- return _fetch(_merge(await _getDefs(), { ...params, method: 'GET', path }), respHeaders, _dumpParams);
367
+ return _fetch(_merge(await _getDefs(), { ...params, method: 'GET', path }), respHeaders, errorMessageExtractor ?? factoryErrorMessageExtractor, _dumpParams);
351
368
  },
352
369
  // POST
353
- async post(path, data = null, params, respHeaders = null, _dumpParams = false) {
370
+ async post(path, data = null, params, respHeaders = null, errorMessageExtractor = null, _dumpParams = false) {
354
371
  path = `${base || ''}${path || ''}`;
355
- return _fetch(_merge(await _getDefs(), { ...(params || {}), data, method: 'POST', path }), respHeaders, _dumpParams);
372
+ return _fetch(_merge(await _getDefs(), { ...(params || {}), data, method: 'POST', path }), respHeaders, errorMessageExtractor ?? factoryErrorMessageExtractor, _dumpParams);
356
373
  },
357
374
  // PUT
358
- async put(path, data = null, params, respHeaders = null, _dumpParams = false) {
375
+ async put(path, data = null, params, respHeaders = null, errorMessageExtractor = null, _dumpParams = false) {
359
376
  path = `${base || ''}${path || ''}`;
360
- return _fetch(_merge(await _getDefs(), { ...(params || {}), data, method: 'PUT', path }), respHeaders, _dumpParams);
377
+ return _fetch(_merge(await _getDefs(), { ...(params || {}), data, method: 'PUT', path }), respHeaders, errorMessageExtractor ?? factoryErrorMessageExtractor, _dumpParams);
361
378
  },
362
379
  // PATCH
363
- async patch(path, data = null, params, respHeaders = null, _dumpParams = false) {
380
+ async patch(path, data = null, params, respHeaders = null, errorMessageExtractor = null, _dumpParams = false) {
364
381
  path = `${base || ''}${path || ''}`;
365
- return _fetch(_merge(await _getDefs(), { ...(params || {}), data, method: 'PATCH', path }), respHeaders, _dumpParams);
382
+ return _fetch(_merge(await _getDefs(), { ...(params || {}), data, method: 'PATCH', path }), respHeaders, errorMessageExtractor ?? factoryErrorMessageExtractor, _dumpParams);
366
383
  },
367
384
  // DELETE
368
385
  // https://stackoverflow.com/questions/299628/is-an-entity-body-allowed-for-an-http-delete-request
369
- async del(path, data = null, params, respHeaders = null, _dumpParams = false) {
386
+ async del(path, data = null, params, respHeaders = null, errorMessageExtractor = null, _dumpParams = false) {
370
387
  path = `${base || ''}${path || ''}`;
371
- return _fetch(_merge(await _getDefs(), { ...(params || {}), data, method: 'DELETE', path }), respHeaders, _dumpParams);
388
+ return _fetch(_merge(await _getDefs(), { ...(params || {}), data, method: 'DELETE', path }), respHeaders, errorMessageExtractor ?? factoryErrorMessageExtractor, _dumpParams);
372
389
  },
373
390
  };
374
- };
391
+ }
392
+ createHttpApi.defaultErrorMessageExtractor = null;
375
393
 
376
394
  export { HTTP_ERROR, HTTP_STATUS, createHttpApi, createHttpError };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@marianmeres/http-utils",
3
- "version": "1.9.0",
3
+ "version": "1.11.0",
4
4
  "description": "Misc DRY http fetch related helpers",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",
@@ -32,6 +32,7 @@
32
32
  },
33
33
  "homepage": "https://github.com/marianmeres/http-utils#readme",
34
34
  "devDependencies": {
35
+ "@marianmeres/clog": "^1.0.1",
35
36
  "@marianmeres/release": "^1.1.2",
36
37
  "@marianmeres/test-runner": "^2.0.16",
37
38
  "@rollup/plugin-typescript": "^11.1.6",