@odata2ts/http-client-fetch 0.4.0 → 0.6.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/CHANGELOG.md CHANGED
@@ -3,6 +3,32 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
5
 
6
+ # [0.6.0](https://github.com/odata2ts/http-client/compare/@odata2ts/http-client-fetch@0.4.0...@odata2ts/http-client-fetch@0.6.0) (2023-09-13)
7
+
8
+ ### Code Refactoring
9
+
10
+ * expand additionalHeaders param to internalConfig ([#15](https://github.com/odata2ts/http-client/issues/15)) ([7fe1d73](https://github.com/odata2ts/http-client/commit/7fe1d73a7436f64b84a060bd1dbf9e121ef901ce))
11
+
12
+ ### Features
13
+
14
+ * **fetch:** allow for query params ([#13](https://github.com/odata2ts/http-client/issues/13)) ([1507ed1](https://github.com/odata2ts/http-client/commit/1507ed13c2020de051827db516ae1fc9c7f4b0ac))
15
+
16
+ ### BREAKING CHANGES
17
+
18
+ * additional headers are now part of the config parameter
19
+
20
+ * fix: don't lose configuration when CSRF token is active
21
+
22
+ * add new option which prevents FetchClient from evaluating response body (not needed for fetching csrf tokens & makes trouble with SAP's mockServer)
23
+
24
+ * fix: add headers for content-type and accept for main methods
25
+
26
+ # [0.5.0](https://github.com/odata2ts/http-client/compare/@odata2ts/http-client-fetch@0.4.0...@odata2ts/http-client-fetch@0.5.0) (2023-09-05)
27
+
28
+ ### Features
29
+
30
+ * **fetch:** allow for query params ([#13](https://github.com/odata2ts/http-client/issues/13)) ([1507ed1](https://github.com/odata2ts/http-client/commit/1507ed13c2020de051827db516ae1fc9c7f4b0ac))
31
+
6
32
  # [0.4.0](https://github.com/odata2ts/http-client/compare/@odata2ts/http-client-fetch@0.3.1...@odata2ts/http-client-fetch@0.4.0) (2023-08-03)
7
33
 
8
34
  ### Code Refactoring
@@ -32,6 +58,7 @@ See [Conventional Commits](https://conventionalcommits.org) for commit guideline
32
58
  ### Features
33
59
 
34
60
  * switch to http-client-api ([52d1b86](https://github.com/odata2ts/http-client/commit/52d1b868ee82dbaf45486da6b22fdcf4c773dfb8))
61
+
35
62
  * switch to http-client-api ([5a6da23](https://github.com/odata2ts/http-client/commit/5a6da23053b3ea5adb866bb7e30b469f1b8ed260))
36
63
 
37
64
  # 0.1.0 (2023-05-29)
package/README.md CHANGED
@@ -1,50 +1,50 @@
1
- [![npm (scoped)](https://img.shields.io/npm/v/@odata2ts/http-client-fetch?style=for-the-badge)](https://www.npmjs.com/package/@odata2ts/http-client-fetch)
2
-
3
- # Fetch HTTP Client
4
-
5
- Fetch based HTTP client for [odata2ts](https://github.com/odata2ts/odata2ts).
6
- This client uses - as its name suggests - [fetch](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API)
7
- for realizing the HTTP communication.
8
-
9
- It supports:
10
-
11
- - request configuration
12
- - automatic CSRF token handling
13
-
14
- Works also for Node.js v18+, but is still marked as **experimental**.
15
-
16
- ## Installation
17
-
18
- Install package `@odata2ts/http-client-fetch` as runtime dependency:
19
-
20
- ```bash
21
- npm install --save @odata2ts/http-client-fetch
22
- ```
23
-
24
- ## Documentation
25
-
26
- [Fetch Client Documentation](https://odata2ts.github.io/docs/odata-client/http-client/fetch)
27
-
28
- Main documentation for the odata2ts eco system:
29
- [https://odata2ts.github.io](https://odata2ts.github.io/)
30
-
31
- ## Tests
32
-
33
- See folder [test](https://github.com/odata2ts/http-client/tree/main/packages/fetch/test)
34
- for unit tests.
35
-
36
- See folder [int-test](https://github.com/odata2ts/http-client/tree/main/packages/fetch/int-test) for
37
- integration tests.
38
-
39
- ## Support, Feedback, Contributing
40
-
41
- This project is open to feature requests, suggestions, bug reports, usage questions etc.
42
- via [GitHub issues](https://github.com/odata2ts/http-client/issues).
43
-
44
- Contributions and feedback are encouraged and always welcome.
45
-
46
- See the [contribution guidelines](https://github.com/odata2ts/http-client/blob/main/CONTRIBUTING.md) for further information.
47
-
48
- ## License
49
-
50
- MIT - see [License](./LICENSE).
1
+ [![npm (scoped)](https://img.shields.io/npm/v/@odata2ts/http-client-fetch?style=for-the-badge)](https://www.npmjs.com/package/@odata2ts/http-client-fetch)
2
+
3
+ # Fetch HTTP Client
4
+
5
+ Fetch based HTTP client for [odata2ts](https://github.com/odata2ts/odata2ts).
6
+ This client uses - as its name suggests - [fetch](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API)
7
+ for realizing the HTTP communication.
8
+
9
+ It supports:
10
+
11
+ - request configuration
12
+ - automatic CSRF token handling
13
+
14
+ Works also for Node.js v18+, but is still marked as **experimental**.
15
+
16
+ ## Installation
17
+
18
+ Install package `@odata2ts/http-client-fetch` as runtime dependency:
19
+
20
+ ```bash
21
+ npm install --save @odata2ts/http-client-fetch
22
+ ```
23
+
24
+ ## Documentation
25
+
26
+ [Fetch Client Documentation](https://odata2ts.github.io/docs/odata-client/http-client/fetch)
27
+
28
+ Main documentation for the odata2ts eco system:
29
+ [https://odata2ts.github.io](https://odata2ts.github.io/)
30
+
31
+ ## Tests
32
+
33
+ See folder [test](https://github.com/odata2ts/http-client/tree/main/packages/fetch/test)
34
+ for unit tests.
35
+
36
+ See folder [int-test](https://github.com/odata2ts/http-client/tree/main/packages/fetch/int-test) for
37
+ integration tests.
38
+
39
+ ## Support, Feedback, Contributing
40
+
41
+ This project is open to feature requests, suggestions, bug reports, usage questions etc.
42
+ via [GitHub issues](https://github.com/odata2ts/http-client/issues).
43
+
44
+ Contributions and feedback are encouraged and always welcome.
45
+
46
+ See the [contribution guidelines](https://github.com/odata2ts/http-client/blob/main/CONTRIBUTING.md) for further information.
47
+
48
+ ## License
49
+
50
+ MIT - see [License](./LICENSE).
@@ -1,4 +1,4 @@
1
- import { HttpResponseModel } from "@odata2ts/http-client-api";
1
+ import { HttpResponseModel, InternalHttpClientConfig } from "@odata2ts/http-client-api";
2
2
  import { BaseHttpClient, BaseHttpClientOptions, HttpMethods } from "@odata2ts/http-client-base";
3
3
  import { FetchRequestConfig } from "./FetchRequestConfig";
4
4
  export interface ClientOptions extends BaseHttpClientOptions {
@@ -7,8 +7,7 @@ export declare const DEFAULT_ERROR_MESSAGE = "No error message!";
7
7
  export declare class FetchClient extends BaseHttpClient<FetchRequestConfig> {
8
8
  protected readonly config: RequestInit;
9
9
  constructor(config?: FetchRequestConfig, clientOptions?: ClientOptions);
10
- protected addHeaderToRequestConfig(headers: Record<string, string>, config: FetchRequestConfig | undefined): FetchRequestConfig;
11
- protected executeRequest<ResponseModel>(method: HttpMethods, url: string, data: any, requestConfig?: FetchRequestConfig | undefined): Promise<HttpResponseModel<ResponseModel>>;
10
+ protected executeRequest<ResponseModel>(method: HttpMethods, url: string, data: any, requestConfig?: FetchRequestConfig | undefined, internalConfig?: InternalHttpClientConfig): Promise<HttpResponseModel<ResponseModel>>;
12
11
  protected getResponseBody(response: Response, isFailedJsonFatal: boolean): Promise<any>;
13
12
  protected mapHeaders(headers: Headers): Record<string, string>;
14
13
  }
@@ -18,20 +18,25 @@ class FetchClient extends http_client_base_1.BaseHttpClient {
18
18
  super(clientOptions);
19
19
  this.config = (0, FetchRequestConfig_1.getDefaultConfig)(config);
20
20
  }
21
- addHeaderToRequestConfig(headers, config) {
22
- return (0, FetchRequestConfig_1.mergeFetchConfig)({ headers }, config);
23
- }
24
- executeRequest(method, url, data, requestConfig = {}) {
21
+ executeRequest(method, url, data, requestConfig = {}, internalConfig = {}) {
25
22
  return tslib_1.__awaiter(this, void 0, void 0, function* () {
26
- const config = (0, FetchRequestConfig_1.mergeFetchConfig)(this.config, requestConfig);
23
+ const { headers, noBodyEvaluation } = internalConfig;
24
+ const _a = (0, FetchRequestConfig_1.mergeFetchConfig)(this.config, { headers }, requestConfig), { params } = _a, config = tslib_1.__rest(_a, ["params"]);
27
25
  config.method = method;
28
26
  if (typeof data !== "undefined") {
29
27
  config.body = JSON.stringify(data);
30
28
  }
29
+ let finalUrl = url;
30
+ if (params && Object.values(params).length) {
31
+ finalUrl +=
32
+ (url.match(/\?/) ? "&" : "?") +
33
+ // @ts-ignore
34
+ new URLSearchParams(params).toString();
35
+ }
31
36
  // the actual request
32
37
  let response;
33
38
  try {
34
- response = yield fetch(url, config);
39
+ response = yield fetch(finalUrl, config);
35
40
  }
36
41
  catch (fetchError) {
37
42
  throw new FetchClientError_1.FetchClientError(buildErrorMessage(FETCH_FAILURE_MESSAGE, fetchError), undefined, undefined, fetchError);
@@ -42,7 +47,7 @@ class FetchClient extends http_client_base_1.BaseHttpClient {
42
47
  const errMsg = this.retrieveErrorMessage(responseData);
43
48
  throw new FetchClientError_1.FetchClientError(buildErrorMessage(RESPONSE_FAILURE_MESSAGE, errMsg), response.status, this.mapHeaders(response.headers), new Error(errMsg || exports.DEFAULT_ERROR_MESSAGE), response);
44
49
  }
45
- const responseData = yield this.getResponseBody(response, true);
50
+ const responseData = noBodyEvaluation ? undefined : yield this.getResponseBody(response, true);
46
51
  return {
47
52
  status: response.status,
48
53
  statusText: response.statusText,
@@ -1 +1 @@
1
- {"version":3,"file":"FetchClient.js","sourceRoot":"","sources":["../src/FetchClient.ts"],"names":[],"mappings":"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","sourcesContent":["import { HttpResponseModel } from \"@odata2ts/http-client-api\";\nimport { BaseHttpClient, BaseHttpClientOptions, HttpMethods } from \"@odata2ts/http-client-base\";\n\nimport { FetchClientError } from \"./FetchClientError\";\nimport { FetchRequestConfig, getDefaultConfig, mergeFetchConfig } from \"./FetchRequestConfig\";\n\nexport interface ClientOptions extends BaseHttpClientOptions {}\n\nexport const DEFAULT_ERROR_MESSAGE = \"No error message!\";\nconst FETCH_FAILURE_MESSAGE = \"OData request failed entirely: \";\nconst JSON_RETRIEVAL_FAILURE_MESSAGE = \"Retrieving JSON body from OData response failed: \";\nconst RESPONSE_FAILURE_MESSAGE = \"OData server responded with error: \";\n\nfunction buildErrorMessage(prefix: string, error: any) {\n const msg = typeof error === \"string\" ? error : (error as Error)?.message;\n return prefix + (msg || DEFAULT_ERROR_MESSAGE);\n}\n\nexport class FetchClient extends BaseHttpClient<FetchRequestConfig> {\n protected readonly config: RequestInit;\n\n constructor(config?: FetchRequestConfig, clientOptions?: ClientOptions) {\n super(clientOptions);\n this.config = getDefaultConfig(config);\n }\n\n protected addHeaderToRequestConfig(\n headers: Record<string, string>,\n config: FetchRequestConfig | undefined\n ): FetchRequestConfig {\n return mergeFetchConfig({ headers }, config);\n }\n\n protected async executeRequest<ResponseModel>(\n method: HttpMethods,\n url: string,\n data: any,\n requestConfig: FetchRequestConfig | undefined = {}\n ): Promise<HttpResponseModel<ResponseModel>> {\n const config = mergeFetchConfig(this.config, requestConfig);\n config.method = method;\n if (typeof data !== \"undefined\") {\n config.body = JSON.stringify(data);\n }\n\n // the actual request\n let response: Response;\n try {\n response = await fetch(url, config);\n } catch (fetchError) {\n throw new FetchClientError(\n buildErrorMessage(FETCH_FAILURE_MESSAGE, fetchError),\n undefined,\n undefined,\n fetchError as Error\n );\n }\n\n // error response\n if (!response.ok) {\n let responseData = await this.getResponseBody(response, false);\n const errMsg = this.retrieveErrorMessage(responseData);\n\n throw new FetchClientError(\n buildErrorMessage(RESPONSE_FAILURE_MESSAGE, errMsg),\n response.status,\n this.mapHeaders(response.headers),\n new Error(errMsg || DEFAULT_ERROR_MESSAGE),\n response\n );\n }\n\n const responseData = await this.getResponseBody(response, true);\n\n return {\n status: response.status,\n statusText: response.statusText,\n headers: this.mapHeaders(response.headers),\n data: responseData,\n };\n }\n\n protected async getResponseBody(response: Response, isFailedJsonFatal: boolean) {\n if (response.status === 204) {\n return undefined;\n }\n try {\n return await response.json();\n } catch (error) {\n if (isFailedJsonFatal) {\n throw new FetchClientError(\n buildErrorMessage(JSON_RETRIEVAL_FAILURE_MESSAGE, error),\n response.status,\n this.mapHeaders(response.headers),\n error as Error\n );\n }\n return undefined;\n }\n }\n\n protected mapHeaders(headers: Headers): Record<string, string> {\n const result: Record<string, string> = {};\n headers.forEach((value, key) => (result[key] = value));\n\n return result;\n }\n}\n"]}
1
+ {"version":3,"file":"FetchClient.js","sourceRoot":"","sources":["../src/FetchClient.ts"],"names":[],"mappings":"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","sourcesContent":["import { HttpResponseModel, InternalHttpClientConfig } from \"@odata2ts/http-client-api\";\r\nimport { BaseHttpClient, BaseHttpClientOptions, HttpMethods } from \"@odata2ts/http-client-base\";\r\n\r\nimport { FetchClientError } from \"./FetchClientError\";\r\nimport { FetchRequestConfig, getDefaultConfig, mergeFetchConfig } from \"./FetchRequestConfig\";\r\n\r\nexport interface ClientOptions extends BaseHttpClientOptions {}\r\n\r\nexport const DEFAULT_ERROR_MESSAGE = \"No error message!\";\r\nconst FETCH_FAILURE_MESSAGE = \"OData request failed entirely: \";\r\nconst JSON_RETRIEVAL_FAILURE_MESSAGE = \"Retrieving JSON body from OData response failed: \";\r\nconst RESPONSE_FAILURE_MESSAGE = \"OData server responded with error: \";\r\n\r\nfunction buildErrorMessage(prefix: string, error: any) {\r\n const msg = typeof error === \"string\" ? error : (error as Error)?.message;\r\n return prefix + (msg || DEFAULT_ERROR_MESSAGE);\r\n}\r\n\r\nexport class FetchClient extends BaseHttpClient<FetchRequestConfig> {\r\n protected readonly config: RequestInit;\r\n\r\n constructor(config?: FetchRequestConfig, clientOptions?: ClientOptions) {\r\n super(clientOptions);\r\n this.config = getDefaultConfig(config);\r\n }\r\n\r\n protected async executeRequest<ResponseModel>(\r\n method: HttpMethods,\r\n url: string,\r\n data: any,\r\n requestConfig: FetchRequestConfig | undefined = {},\r\n internalConfig: InternalHttpClientConfig = {}\r\n ): Promise<HttpResponseModel<ResponseModel>> {\r\n const { headers, noBodyEvaluation } = internalConfig;\r\n const { params, ...config } = mergeFetchConfig(this.config, { headers }, requestConfig);\r\n config.method = method;\r\n if (typeof data !== \"undefined\") {\r\n config.body = JSON.stringify(data);\r\n }\r\n let finalUrl = url;\r\n if (params && Object.values(params).length) {\r\n finalUrl +=\r\n (url.match(/\\?/) ? \"&\" : \"?\") +\r\n // @ts-ignore\r\n new URLSearchParams(params).toString();\r\n }\r\n\r\n // the actual request\r\n let response: Response;\r\n try {\r\n response = await fetch(finalUrl, config);\r\n } catch (fetchError) {\r\n throw new FetchClientError(\r\n buildErrorMessage(FETCH_FAILURE_MESSAGE, fetchError),\r\n undefined,\r\n undefined,\r\n fetchError as Error\r\n );\r\n }\r\n\r\n // error response\r\n if (!response.ok) {\r\n let responseData = await this.getResponseBody(response, false);\r\n const errMsg = this.retrieveErrorMessage(responseData);\r\n\r\n throw new FetchClientError(\r\n buildErrorMessage(RESPONSE_FAILURE_MESSAGE, errMsg),\r\n response.status,\r\n this.mapHeaders(response.headers),\r\n new Error(errMsg || DEFAULT_ERROR_MESSAGE),\r\n response\r\n );\r\n }\r\n\r\n const responseData = noBodyEvaluation ? undefined : await this.getResponseBody(response, true);\r\n\r\n return {\r\n status: response.status,\r\n statusText: response.statusText,\r\n headers: this.mapHeaders(response.headers),\r\n data: responseData,\r\n };\r\n }\r\n\r\n protected async getResponseBody(response: Response, isFailedJsonFatal: boolean) {\r\n if (response.status === 204) {\r\n return undefined;\r\n }\r\n try {\r\n return await response.json();\r\n } catch (error) {\r\n if (isFailedJsonFatal) {\r\n throw new FetchClientError(\r\n buildErrorMessage(JSON_RETRIEVAL_FAILURE_MESSAGE, error),\r\n response.status,\r\n this.mapHeaders(response.headers),\r\n error as Error\r\n );\r\n }\r\n return undefined;\r\n }\r\n }\r\n\r\n protected mapHeaders(headers: Headers): Record<string, string> {\r\n const result: Record<string, string> = {};\r\n headers.forEach((value, key) => (result[key] = value));\r\n\r\n return result;\r\n }\r\n}\r\n"]}
@@ -3,8 +3,12 @@
3
3
  */
4
4
  export interface FetchRequestConfig extends Pick<RequestInit, "credentials" | "cache" | "mode" | "redirect" | "referrerPolicy"> {
5
5
  headers?: Record<string, string> | Headers;
6
+ /**
7
+ * Add query params.
8
+ */
9
+ params?: Record<string, string | number | boolean | Array<string | number | boolean>>;
6
10
  }
7
- export interface InternalFetchConfig extends Omit<RequestInit, "headers"> {
11
+ export interface InternalFetchConfig extends Omit<RequestInit, "headers">, Pick<FetchRequestConfig, "params"> {
8
12
  headers: Headers;
9
13
  }
10
14
  export declare function getDefaultConfig(config?: FetchRequestConfig): RequestInit;
@@ -1 +1 @@
1
- {"version":3,"file":"FetchRequestConfig.js","sourceRoot":"","sources":["../src/FetchRequestConfig.ts"],"names":[],"mappings":";;;;AAAA,MAAM,cAAc,GAAgB;IAClC,+EAA+E;IAC/E,KAAK,EAAE,UAAU;CAClB,CAAC;AAcF,SAAgB,gBAAgB,CAAC,MAA2B;IAC1D,OAAO,gBAAgB,CAAC,cAAc,EAAE,MAAM,CAAC,CAAC;AAClD,CAAC;AAFD,4CAEC;AAID,SAAgB,gBAAgB,CAAC,GAAG,OAAuC;IACzE,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE;QACnB,OAAO,SAAS,CAAC;KAClB;IACD,OAAO,OAAO;SACX,MAAM,CAAC,CAAC,CAAC,EAAoB,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;SACpC,MAAM,CACL,CAAC,SAAS,EAAE,OAAO,EAAE,EAAE;QACrB,MAAM,EAAE,OAAO,KAAqB,OAAO,EAAvB,WAAW,kBAAK,OAAO,EAArC,WAA2B,CAAU,CAAC;QAC5C,MAAM,gBAAgB,GAAG,SAAS,CAAC,OAAkB,CAAC;QAEtD,4BAA4B;QAC5B,IAAI,OAAO,IAAI,OAAO,YAAY,OAAO,EAAE;YACzC,OAAO,CAAC,OAAO,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,CAAC,gBAAgB,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC;SAC/D;QACD,yCAAyC;aACpC,IAAI,OAAO,EAAE;YAChB,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,EAAE,GAAG,CAAC,EAAE,EAAE,CAAC,gBAAgB,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC;SACjF;QAED,uCAAY,SAAS,GAAK,WAAW,EAAG;IAC1C,CAAC,EACD,EAAE,OAAO,EAAE,IAAI,OAAO,EAAE,EAAE,CAC3B,CAAC;AACN,CAAC;AAxBD,4CAwBC","sourcesContent":["const DEFAULT_CONFIG: RequestInit = {\n // headers: { Accept: \"application/json\", \"Content-Type\": \"application/json\" },\n cache: \"no-store\",\n};\n\n/**\n * Available config options for end user when making a given request.\n */\nexport interface FetchRequestConfig\n extends Pick<RequestInit, \"credentials\" | \"cache\" | \"mode\" | \"redirect\" | \"referrerPolicy\"> {\n headers?: Record<string, string> | Headers;\n}\n\nexport interface InternalFetchConfig extends Omit<RequestInit, \"headers\"> {\n headers: Headers;\n}\n\nexport function getDefaultConfig(config?: FetchRequestConfig): RequestInit {\n return mergeFetchConfig(DEFAULT_CONFIG, config);\n}\n\nexport function mergeFetchConfig(): undefined;\nexport function mergeFetchConfig(...configs: Array<RequestInit | undefined>): InternalFetchConfig;\nexport function mergeFetchConfig(...configs: Array<RequestInit | undefined>) {\n if (!configs.length) {\n return undefined;\n }\n return configs\n .filter((c): c is RequestInit => !!c)\n .reduce<InternalFetchConfig>(\n (collector, current) => {\n const { headers, ...passThrough } = current;\n const collectedHeaders = collector.headers as Headers;\n\n // headers as Headers object\n if (headers && headers instanceof Headers) {\n headers.forEach((val, key) => collectedHeaders.set(key, val));\n }\n // headers as plain Record<string,string>\n else if (headers) {\n Object.entries(headers).forEach(([key, val]) => collectedHeaders.set(key, val));\n }\n\n return { ...collector, ...passThrough };\n },\n { headers: new Headers() }\n );\n}\n"]}
1
+ {"version":3,"file":"FetchRequestConfig.js","sourceRoot":"","sources":["../src/FetchRequestConfig.ts"],"names":[],"mappings":";;;;AAAA,MAAM,cAAc,GAAgB;IAClC,+EAA+E;IAC/E,KAAK,EAAE,UAAU;CAClB,CAAC;AAkBF,SAAgB,gBAAgB,CAAC,MAA2B;IAC1D,OAAO,gBAAgB,CAAC,cAAc,EAAE,MAAM,CAAC,CAAC;AAClD,CAAC;AAFD,4CAEC;AAID,SAAgB,gBAAgB,CAAC,GAAG,OAAuC;IACzE,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE;QACnB,OAAO,SAAS,CAAC;KAClB;IACD,OAAO,OAAO;SACX,MAAM,CAAC,CAAC,CAAC,EAAoB,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;SACpC,MAAM,CACL,CAAC,SAAS,EAAE,OAAO,EAAE,EAAE;QACrB,MAAM,EAAE,OAAO,KAAqB,OAAO,EAAvB,WAAW,kBAAK,OAAO,EAArC,WAA2B,CAAU,CAAC;QAC5C,MAAM,gBAAgB,GAAG,SAAS,CAAC,OAAkB,CAAC;QAEtD,4BAA4B;QAC5B,IAAI,OAAO,IAAI,OAAO,YAAY,OAAO,EAAE;YACzC,OAAO,CAAC,OAAO,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,CAAC,gBAAgB,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC;SAC/D;QACD,yCAAyC;aACpC,IAAI,OAAO,EAAE;YAChB,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,EAAE,GAAG,CAAC,EAAE,EAAE,CAAC,gBAAgB,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC;SACjF;QAED,uCAAY,SAAS,GAAK,WAAW,EAAG;IAC1C,CAAC,EACD,EAAE,OAAO,EAAE,IAAI,OAAO,EAAE,EAAE,CAC3B,CAAC;AACN,CAAC;AAxBD,4CAwBC","sourcesContent":["const DEFAULT_CONFIG: RequestInit = {\r\n // headers: { Accept: \"application/json\", \"Content-Type\": \"application/json\" },\r\n cache: \"no-store\",\r\n};\r\n\r\n/**\r\n * Available config options for end user when making a given request.\r\n */\r\nexport interface FetchRequestConfig\r\n extends Pick<RequestInit, \"credentials\" | \"cache\" | \"mode\" | \"redirect\" | \"referrerPolicy\"> {\r\n headers?: Record<string, string> | Headers;\r\n /**\r\n * Add query params.\r\n */\r\n params?: Record<string, string | number | boolean | Array<string | number | boolean>>;\r\n}\r\n\r\nexport interface InternalFetchConfig extends Omit<RequestInit, \"headers\">, Pick<FetchRequestConfig, \"params\"> {\r\n headers: Headers;\r\n}\r\n\r\nexport function getDefaultConfig(config?: FetchRequestConfig): RequestInit {\r\n return mergeFetchConfig(DEFAULT_CONFIG, config);\r\n}\r\n\r\nexport function mergeFetchConfig(): undefined;\r\nexport function mergeFetchConfig(...configs: Array<RequestInit | undefined>): InternalFetchConfig;\r\nexport function mergeFetchConfig(...configs: Array<RequestInit | undefined>) {\r\n if (!configs.length) {\r\n return undefined;\r\n }\r\n return configs\r\n .filter((c): c is RequestInit => !!c)\r\n .reduce<InternalFetchConfig>(\r\n (collector, current) => {\r\n const { headers, ...passThrough } = current;\r\n const collectedHeaders = collector.headers as Headers;\r\n\r\n // headers as Headers object\r\n if (headers && headers instanceof Headers) {\r\n headers.forEach((val, key) => collectedHeaders.set(key, val));\r\n }\r\n // headers as plain Record<string,string>\r\n else if (headers) {\r\n Object.entries(headers).forEach(([key, val]) => collectedHeaders.set(key, val));\r\n }\r\n\r\n return { ...collector, ...passThrough };\r\n },\r\n { headers: new Headers() }\r\n );\r\n}\r\n"]}
package/lib/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;AAAA,wDAA8B;AAC9B,uDAAsD;AAA7C,oHAAA,gBAAgB,OAAA","sourcesContent":["export * from \"./FetchClient\";\nexport { FetchClientError } from \"./FetchClientError\";\nexport { FetchRequestConfig } from \"./FetchRequestConfig\";\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;AAAA,wDAA8B;AAC9B,uDAAsD;AAA7C,oHAAA,gBAAgB,OAAA","sourcesContent":["export * from \"./FetchClient\";\r\nexport { FetchClientError } from \"./FetchClientError\";\r\nexport { FetchRequestConfig } from \"./FetchRequestConfig\";\r\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@odata2ts/http-client-fetch",
3
- "version": "0.4.0",
3
+ "version": "0.6.0",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },
@@ -31,7 +31,7 @@
31
31
  "odata2ts"
32
32
  ],
33
33
  "dependencies": {
34
- "@odata2ts/http-client-base": "^0.3.0"
34
+ "@odata2ts/http-client-base": "^0.4.0"
35
35
  },
36
36
  "devDependencies": {
37
37
  "@odata2ts/odata-core": "^0.3.7",
@@ -44,5 +44,5 @@
44
44
  "typescript": "5.0.4"
45
45
  },
46
46
  "types": "./lib/index.d.ts",
47
- "gitHead": "dc6e29cef27b2f5fca6e838e4a22766b90249e8e"
47
+ "gitHead": "67c7fc10f25461c33baf4e35694a457a03b81b78"
48
48
  }