@odata2ts/http-client-jquery 0.13.0 → 0.14.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,24 @@
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.14.0](https://github.com/odata2ts/http-client/compare/@odata2ts/http-client-jquery-v0.13.0...@odata2ts/http-client-jquery-v0.14.0) (2026-08-08)
7
+
8
+
9
+ ### ⚠ BREAKING CHANGES
10
+
11
+ * the responseData of an error thrown for a binary request is no longer the Blob or the ReadableStream the successful response would have carried, but the parsed error document - or its text, if it is not JSON. Code decoding that Blob itself has to stop doing so.
12
+
13
+ ### Bug Fixes
14
+
15
+ * surface the server's message when a binary request fails ([#47](https://github.com/odata2ts/http-client/issues/47)) ([c69ef66](https://github.com/odata2ts/http-client/commit/c69ef662171e7f2480fc928474b831fd18855133))
16
+
17
+
18
+ ### Dependencies
19
+
20
+ * The following workspace dependencies were updated
21
+ * dependencies
22
+ * @odata2ts/http-client-base bumped from ^0.5.8 to ^0.6.0
23
+
6
24
  ## [0.13.0](https://github.com/odata2ts/http-client/compare/@odata2ts/http-client-jquery-v0.12.0...@odata2ts/http-client-jquery-v0.13.0) (2026-08-02)
7
25
 
8
26
 
@@ -9,5 +9,14 @@ export declare class JQueryClient extends BaseHttpClient<JQueryRequestConfig> im
9
9
  private readonly config;
10
10
  constructor(jquery: JQueryStatic, config?: JQueryRequestConfig, clientOptions?: ODataHttpClientOptions);
11
11
  protected mapHeaders(jqXhr: jqXHR): Record<string, string>;
12
+ /**
13
+ * Turns a failed request into the error to reject with.
14
+ *
15
+ * `responseJSON` is jQuery's own parsing of the response and covers the ordinary case. It stays empty
16
+ * for a binary request though: with `responseType: "blob"` XmlHttpRequest offers neither `responseText`
17
+ * nor anything jQuery could have parsed, and the server's error document sits in `response` as binary.
18
+ * Reading it there is what keeps a failing `getBlob` from reporting the default message.
19
+ */
20
+ private buildFailure;
12
21
  protected executeRequest<ResponseModel>(method: ODataHttpMethods, url: string, data: any, requestConfig: JQueryRequestConfig | undefined, internalConfig: BaseRequestConfig): Promise<HttpResponseModel<ResponseModel>>;
13
22
  }
@@ -31,6 +31,32 @@ class JQueryClient extends http_client_base_1.BaseHttpClient {
31
31
  return collector;
32
32
  }, {});
33
33
  }
34
+ /**
35
+ * Turns a failed request into the error to reject with.
36
+ *
37
+ * `responseJSON` is jQuery's own parsing of the response and covers the ordinary case. It stays empty
38
+ * for a binary request though: with `responseType: "blob"` XmlHttpRequest offers neither `responseText`
39
+ * nor anything jQuery could have parsed, and the server's error document sits in `response` as binary.
40
+ * Reading it there is what keeps a failing `getBlob` from reporting the default message.
41
+ */
42
+ buildFailure(jqXHR, thrownError) {
43
+ return tslib_1.__awaiter(this, void 0, void 0, function* () {
44
+ var _a;
45
+ let responseData;
46
+ try {
47
+ // `response` belongs to XmlHttpRequest itself, which jQuery's typing does not carry over
48
+ const rawResponse = jqXHR === null || jqXHR === void 0 ? void 0 : jqXHR.response;
49
+ responseData = (_a = jqXHR === null || jqXHR === void 0 ? void 0 : jqXHR.responseJSON) !== null && _a !== void 0 ? _a : (yield (0, http_client_base_1.parseErrorResponseBody)(rawResponse));
50
+ }
51
+ catch (e) {
52
+ responseData = undefined;
53
+ }
54
+ const responseMessage = this.retrieveErrorMessage(responseData);
55
+ const failMsg = responseMessage || thrownError || exports.DEFAULT_ERROR_MESSAGE;
56
+ const errorMessage = responseMessage ? "OData server responded with error: " + responseMessage : failMsg;
57
+ return new JQueryClientError_1.JQueryClientError(errorMessage, jqXHR.status, this.mapHeaders(jqXHR), new Error(failMsg), jqXHR);
58
+ });
59
+ }
34
60
  executeRequest(method, url, data, requestConfig, internalConfig) {
35
61
  return tslib_1.__awaiter(this, void 0, void 0, function* () {
36
62
  const { headers } = internalConfig;
@@ -69,11 +95,8 @@ class JQueryClient extends http_client_base_1.BaseHttpClient {
69
95
  data: response,
70
96
  });
71
97
  }, error: (jqXHR, textStatus, thrownError) => {
72
- const responseMessage = this.retrieveErrorMessage(jqXHR === null || jqXHR === void 0 ? void 0 : jqXHR.responseJSON);
73
- const failMsg = responseMessage || thrownError || exports.DEFAULT_ERROR_MESSAGE;
74
- const errorMessage = responseMessage ? "OData server responded with error: " + responseMessage : failMsg;
75
- const responseHeaders = this.mapHeaders(jqXHR);
76
- reject(new JQueryClientError_1.JQueryClientError(errorMessage, jqXHR.status, responseHeaders, new Error(failMsg), jqXHR));
98
+ // decoding the error document may take a turn of the event loop, hence the detour
99
+ this.buildFailure(jqXHR, thrownError).then(reject, reject);
77
100
  } }));
78
101
  });
79
102
  });
@@ -1 +1 @@
1
- {"version":3,"file":"JQueryClient.js","sourceRoot":"","sources":["../src/JQueryClient.ts"],"names":[],"mappings":"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","sourcesContent":["/// <reference path=\"../../../node_modules/@types/jquery/JQueryStatic.d.ts\" />\n\nimport {\n HttpResponseModel,\n ODataHttpClient,\n ODataHttpClientOptions,\n ODataHttpMethods,\n} from \"@odata2ts/http-client-api\";\nimport { BaseHttpClient, BaseRequestConfig } from \"@odata2ts/http-client-base\";\nimport { JQueryClientError } from \"./JQueryClientError\";\nimport { JQueryRequestConfig, mergeConfigs } from \"./JQueryRequestConfig\";\n\nimport jqXHR = JQuery.jqXHR;\n\nexport const DEFAULT_ERROR_MESSAGE = \"No error message!\";\nexport const FAILURE_STREAM_UNSUPPORTED =\n \"Streaming is not supported by the JqueryClient! XmlHttpRequest, which jQuery's ajax method builds \" +\n \"upon, has no streaming API at all - neither for reading a response nor for sending a request body. \" +\n \"Use the FetchClient for streams.\";\n\ninterface InternalRequestConfig\n extends\n JQueryRequestConfig,\n Pick<JQuery.AjaxSettings, \"url\" | \"data\" | \"dataType\" | \"method\" | \"xhrFields\" | \"processData\" | \"contentType\"> {}\n\nexport class JQueryClient extends BaseHttpClient<JQueryRequestConfig> implements ODataHttpClient<JQueryRequestConfig> {\n private readonly client: JQueryStatic;\n private readonly config: JQueryRequestConfig;\n\n constructor(jquery: JQueryStatic, config?: JQueryRequestConfig, clientOptions?: ODataHttpClientOptions) {\n super(clientOptions);\n this.client = jquery;\n this.config = config ?? {};\n }\n\n protected mapHeaders(jqXhr: jqXHR): Record<string, string> {\n return jqXhr\n .getAllResponseHeaders()\n .trim()\n .split(/[\\r\\n]+/)\n .reduce((collector: Record<string, string>, line: string) => {\n const parts = line.split(\": \");\n const header = parts.shift();\n const value = parts.join(\": \");\n\n if (header) {\n collector[header.toLowerCase()] = value;\n }\n return collector;\n }, {});\n }\n\n protected async executeRequest<ResponseModel>(\n method: ODataHttpMethods,\n url: string,\n data: any,\n requestConfig: JQueryRequestConfig | undefined,\n internalConfig: BaseRequestConfig,\n ): Promise<HttpResponseModel<ResponseModel>> {\n const { headers } = internalConfig;\n const { params, ...mergedConfig } = mergeConfigs(this.config, mergeConfigs({ headers }, requestConfig));\n const isBinary = internalConfig.dataType === \"blob\";\n\n // set core inputs for request\n const resultConfig: InternalRequestConfig = {\n ...mergedConfig,\n method,\n // only binary data and an explicitly plain text body are passed through as they are\n data: isBinary || this.isPlainTextBody(internalConfig.headers) ? data : JSON.stringify(data),\n url,\n };\n\n // apply additional query params to the URL\n if (params && Object.values(params).length) {\n resultConfig.url +=\n (url.match(/\\?/) ? \"&\" : \"?\") +\n // @ts-ignore\n new URLSearchParams(params).toString();\n }\n\n // handling of extra data types: blob and stream (not supported)\n if (isBinary) {\n resultConfig.xhrFields = { responseType: \"blob\" };\n // jQuery would otherwise turn the blob into a query string (processData defaults to true)\n // and add its own urlencoded content type; the actual mime type is already part of the headers\n resultConfig.processData = false;\n resultConfig.contentType = false;\n } else if (internalConfig.dataType === \"stream\") {\n // a refusal is a failure of this client like any other, hence it carries the same error type\n throw new JQueryClientError(FAILURE_STREAM_UNSUPPORTED);\n }\n\n // the actual request\n return new Promise((resolve, reject) => {\n this.client.ajax({\n ...resultConfig,\n success: (response: any, textStatus: string, jqXHR: JQuery.jqXHR) => {\n resolve({\n status: jqXHR.status,\n statusText: jqXHR.statusText,\n headers: this.mapHeaders(jqXHR),\n data: response,\n });\n },\n error: (jqXHR: JQuery.jqXHR, textStatus: string, thrownError: string) => {\n const responseMessage = this.retrieveErrorMessage(jqXHR?.responseJSON);\n const failMsg = responseMessage || thrownError || DEFAULT_ERROR_MESSAGE;\n const errorMessage = responseMessage ? \"OData server responded with error: \" + responseMessage : failMsg;\n const responseHeaders = this.mapHeaders(jqXHR);\n reject(new JQueryClientError(errorMessage, jqXHR.status, responseHeaders, new Error(failMsg), jqXHR));\n },\n });\n });\n }\n}\n"]}
1
+ {"version":3,"file":"JQueryClient.js","sourceRoot":"","sources":["../src/JQueryClient.ts"],"names":[],"mappings":"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","sourcesContent":["/// <reference path=\"../../../node_modules/@types/jquery/JQueryStatic.d.ts\" />\n\nimport {\n HttpResponseModel,\n ODataHttpClient,\n ODataHttpClientOptions,\n ODataHttpMethods,\n} from \"@odata2ts/http-client-api\";\nimport { BaseHttpClient, BaseRequestConfig, parseErrorResponseBody } from \"@odata2ts/http-client-base\";\nimport { JQueryClientError } from \"./JQueryClientError\";\nimport { JQueryRequestConfig, mergeConfigs } from \"./JQueryRequestConfig\";\n\nimport jqXHR = JQuery.jqXHR;\n\nexport const DEFAULT_ERROR_MESSAGE = \"No error message!\";\nexport const FAILURE_STREAM_UNSUPPORTED =\n \"Streaming is not supported by the JqueryClient! XmlHttpRequest, which jQuery's ajax method builds \" +\n \"upon, has no streaming API at all - neither for reading a response nor for sending a request body. \" +\n \"Use the FetchClient for streams.\";\n\ninterface InternalRequestConfig\n extends\n JQueryRequestConfig,\n Pick<JQuery.AjaxSettings, \"url\" | \"data\" | \"dataType\" | \"method\" | \"xhrFields\" | \"processData\" | \"contentType\"> {}\n\nexport class JQueryClient extends BaseHttpClient<JQueryRequestConfig> implements ODataHttpClient<JQueryRequestConfig> {\n private readonly client: JQueryStatic;\n private readonly config: JQueryRequestConfig;\n\n constructor(jquery: JQueryStatic, config?: JQueryRequestConfig, clientOptions?: ODataHttpClientOptions) {\n super(clientOptions);\n this.client = jquery;\n this.config = config ?? {};\n }\n\n protected mapHeaders(jqXhr: jqXHR): Record<string, string> {\n return jqXhr\n .getAllResponseHeaders()\n .trim()\n .split(/[\\r\\n]+/)\n .reduce((collector: Record<string, string>, line: string) => {\n const parts = line.split(\": \");\n const header = parts.shift();\n const value = parts.join(\": \");\n\n if (header) {\n collector[header.toLowerCase()] = value;\n }\n return collector;\n }, {});\n }\n\n /**\n * Turns a failed request into the error to reject with.\n *\n * `responseJSON` is jQuery's own parsing of the response and covers the ordinary case. It stays empty\n * for a binary request though: with `responseType: \"blob\"` XmlHttpRequest offers neither `responseText`\n * nor anything jQuery could have parsed, and the server's error document sits in `response` as binary.\n * Reading it there is what keeps a failing `getBlob` from reporting the default message.\n */\n private async buildFailure(jqXHR: jqXHR, thrownError: string): Promise<JQueryClientError> {\n let responseData: unknown;\n try {\n // `response` belongs to XmlHttpRequest itself, which jQuery's typing does not carry over\n const rawResponse = (jqXHR as unknown as Partial<XMLHttpRequest> | undefined)?.response;\n responseData = jqXHR?.responseJSON ?? (await parseErrorResponseBody(rawResponse));\n } catch (e) {\n responseData = undefined;\n }\n\n const responseMessage = this.retrieveErrorMessage(responseData);\n const failMsg = responseMessage || thrownError || DEFAULT_ERROR_MESSAGE;\n const errorMessage = responseMessage ? \"OData server responded with error: \" + responseMessage : failMsg;\n\n return new JQueryClientError(errorMessage, jqXHR.status, this.mapHeaders(jqXHR), new Error(failMsg), jqXHR);\n }\n\n protected async executeRequest<ResponseModel>(\n method: ODataHttpMethods,\n url: string,\n data: any,\n requestConfig: JQueryRequestConfig | undefined,\n internalConfig: BaseRequestConfig,\n ): Promise<HttpResponseModel<ResponseModel>> {\n const { headers } = internalConfig;\n const { params, ...mergedConfig } = mergeConfigs(this.config, mergeConfigs({ headers }, requestConfig));\n const isBinary = internalConfig.dataType === \"blob\";\n\n // set core inputs for request\n const resultConfig: InternalRequestConfig = {\n ...mergedConfig,\n method,\n // only binary data and an explicitly plain text body are passed through as they are\n data: isBinary || this.isPlainTextBody(internalConfig.headers) ? data : JSON.stringify(data),\n url,\n };\n\n // apply additional query params to the URL\n if (params && Object.values(params).length) {\n resultConfig.url +=\n (url.match(/\\?/) ? \"&\" : \"?\") +\n // @ts-ignore\n new URLSearchParams(params).toString();\n }\n\n // handling of extra data types: blob and stream (not supported)\n if (isBinary) {\n resultConfig.xhrFields = { responseType: \"blob\" };\n // jQuery would otherwise turn the blob into a query string (processData defaults to true)\n // and add its own urlencoded content type; the actual mime type is already part of the headers\n resultConfig.processData = false;\n resultConfig.contentType = false;\n } else if (internalConfig.dataType === \"stream\") {\n // a refusal is a failure of this client like any other, hence it carries the same error type\n throw new JQueryClientError(FAILURE_STREAM_UNSUPPORTED);\n }\n\n // the actual request\n return new Promise((resolve, reject) => {\n this.client.ajax({\n ...resultConfig,\n success: (response: any, textStatus: string, jqXHR: JQuery.jqXHR) => {\n resolve({\n status: jqXHR.status,\n statusText: jqXHR.statusText,\n headers: this.mapHeaders(jqXHR),\n data: response,\n });\n },\n error: (jqXHR: JQuery.jqXHR, textStatus: string, thrownError: string) => {\n // decoding the error document may take a turn of the event loop, hence the detour\n this.buildFailure(jqXHR, thrownError).then(reject, reject);\n },\n });\n });\n }\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@odata2ts/http-client-jquery",
3
- "version": "0.13.0",
3
+ "version": "0.14.0",
4
4
  "description": "JQuery based http client usable by odata2ts",
5
5
  "keywords": [
6
6
  "http client",
@@ -26,20 +26,22 @@
26
26
  "check-circular-deps": "madge ./src --extensions ts --circular",
27
27
  "clean": "rimraf lib coverage",
28
28
  "compile": "tsc",
29
- "int-test": "vitest run --dir int-test",
30
29
  "test": "vitest run",
31
30
  "unit-test": "vitest run --dir test"
32
31
  },
33
32
  "dependencies": {
34
- "@odata2ts/http-client-base": "^0.5.8",
33
+ "@odata2ts/http-client-base": "^0.6.0",
35
34
  "tslib": "^2.8.1"
36
35
  },
37
36
  "devDependencies": {
38
37
  "@types/jquery": "^3.5.34",
39
38
  "@types/node": "^24",
40
39
  "jquery": "~3.6.4",
40
+ "jsdom": "^30.0.0",
41
+ "madge": "^8.0.0",
41
42
  "rimraf": "^6.1.3",
42
- "typescript": "6.0.3"
43
+ "typescript": "6.0.3",
44
+ "vitest": "^4.1.10"
43
45
  },
44
46
  "peerDependencies": {
45
47
  "jquery": ">1.0"