@odata2ts/http-client-jquery 0.4.0 → 0.5.1

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,16 @@
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.5.1](https://github.com/odata2ts/http-client/compare/@odata2ts/http-client-jquery@0.5.0...@odata2ts/http-client-jquery@0.5.1) (2023-07-26)
7
+
8
+ **Note:** Version bump only for package @odata2ts/http-client-jquery
9
+
10
+ # [0.5.0](https://github.com/odata2ts/http-client/compare/@odata2ts/http-client-jquery@0.4.0...@odata2ts/http-client-jquery@0.5.0) (2023-06-10)
11
+
12
+ ### Features
13
+
14
+ * conventionalize client errors ([#5](https://github.com/odata2ts/http-client/issues/5)) ([a8e8912](https://github.com/odata2ts/http-client/commit/a8e89125eeda47436d48507d6a71efc90953f878))
15
+
6
16
  # 0.4.0 (2023-06-03)
7
17
 
8
18
  ### Features
@@ -1,29 +1,16 @@
1
- /// <reference types="jquery/misc" />
2
1
  /// <reference types="jquery/jquerystatic" />
3
- import { HttpResponseModel, ODataHttpClient } from "@odata2ts/http-client-api";
2
+ import { HttpResponseModel } from "@odata2ts/http-client-api";
3
+ import { BaseHttpClient, BaseHttpClientOptions, HttpMethods } from "@odata2ts/http-client-base";
4
4
  import { AjaxRequestConfig } from "./AjaxRequestConfig";
5
- export type ErrorMessageRetriever = (errorResponse: any) => string | undefined;
6
- export interface ClientOptions {
7
- useCsrfProtection?: boolean;
8
- csrfTokenFetchUrl?: string;
5
+ import jqXHR = JQuery.jqXHR;
6
+ export interface ClientOptions extends BaseHttpClientOptions {
9
7
  }
10
- export declare const getV2OrV4ErrorMessage: ErrorMessageRetriever;
11
- export declare class JQueryClient implements ODataHttpClient<AjaxRequestConfig> {
8
+ export declare class JQueryClient extends BaseHttpClient<AjaxRequestConfig> {
12
9
  private clientOptions?;
13
10
  private readonly client;
14
11
  private readonly config;
15
- private csrfToken;
16
- private getErrorMessage;
17
12
  constructor(jquery: JQueryStatic, config?: AjaxRequestConfig, clientOptions?: ClientOptions | undefined);
18
- setErrorMessageRetriever(getErrorMsg: ErrorMessageRetriever): void;
19
- private setupSecurityToken;
20
- private fetchSecurityToken;
21
- private sendRequest;
22
- private prepareData;
23
- post<ResponseModel>(url: string, data: any, requestConfig?: AjaxRequestConfig): Promise<HttpResponseModel<ResponseModel>>;
24
- get<ResponseModel>(url: string, requestConfig?: AjaxRequestConfig): Promise<HttpResponseModel<ResponseModel>>;
25
- put<ResponseModel>(url: string, data: any, requestConfig?: AjaxRequestConfig): Promise<HttpResponseModel<ResponseModel>>;
26
- patch<ResponseModel>(url: string, data: any, requestConfig?: AjaxRequestConfig): Promise<HttpResponseModel<ResponseModel>>;
27
- merge<ResponseModel>(url: string, data: any, requestConfig?: AjaxRequestConfig): Promise<HttpResponseModel<ResponseModel>>;
28
- delete(url: string, requestConfig?: AjaxRequestConfig): Promise<HttpResponseModel<void>>;
13
+ protected mapHeaders(jqXhr: jqXHR): Record<string, string>;
14
+ protected addHeaderToRequestConfig(headers: Record<string, string>, config?: AjaxRequestConfig): AjaxRequestConfig;
15
+ protected executeRequest<ResponseModel>(method: HttpMethods, url: string, data: any, requestConfig?: JQuery.AjaxSettings): Promise<HttpResponseModel<ResponseModel>>;
29
16
  }
@@ -1,131 +1,58 @@
1
1
  "use strict";
2
- /// <reference path="../../../node_modules/@types/jquery/misc.d.ts" />
3
2
  /// <reference path="../../../node_modules/@types/jquery/JQueryStatic.d.ts" />
4
3
  Object.defineProperty(exports, "__esModule", { value: true });
5
- exports.JQueryClient = exports.getV2OrV4ErrorMessage = void 0;
6
- const tslib_1 = require("tslib");
4
+ exports.JQueryClient = void 0;
5
+ const http_client_base_1 = require("@odata2ts/http-client-base");
7
6
  const AjaxRequestConfig_1 = require("./AjaxRequestConfig");
8
7
  const JQueryClientError_1 = require("./JQueryClientError");
9
- const getV2OrV4ErrorMessage = (errorResponse) => {
10
- var _a;
11
- const eMsg = (_a = errorResponse === null || errorResponse === void 0 ? void 0 : errorResponse.error) === null || _a === void 0 ? void 0 : _a.message;
12
- return typeof (eMsg === null || eMsg === void 0 ? void 0 : eMsg.value) === "string" ? eMsg.value : eMsg;
13
- };
14
- exports.getV2OrV4ErrorMessage = getV2OrV4ErrorMessage;
15
- class JQueryClient {
8
+ class JQueryClient extends http_client_base_1.BaseHttpClient {
16
9
  constructor(jquery, config, clientOptions) {
10
+ super(clientOptions);
17
11
  this.clientOptions = clientOptions;
18
- this.getErrorMessage = exports.getV2OrV4ErrorMessage;
19
12
  this.client = jquery;
20
13
  this.config = (0, AjaxRequestConfig_1.getDefaultConfig)(config);
21
14
  }
22
- setErrorMessageRetriever(getErrorMsg) {
23
- this.getErrorMessage = getErrorMsg;
24
- }
25
- setupSecurityToken() {
26
- return tslib_1.__awaiter(this, void 0, void 0, function* () {
27
- if (!this.csrfToken) {
28
- this.csrfToken = yield this.fetchSecurityToken();
15
+ mapHeaders(jqXhr) {
16
+ return jqXhr
17
+ .getAllResponseHeaders()
18
+ .trim()
19
+ .split(/[\r\n]+/)
20
+ .reduce((collector, line) => {
21
+ const parts = line.split(": ");
22
+ const header = parts.shift();
23
+ const value = parts.join(": ");
24
+ if (header) {
25
+ collector[header.toLowerCase()] = value;
29
26
  }
30
- return this.csrfToken;
31
- });
32
- }
33
- fetchSecurityToken() {
34
- var _a, _b;
35
- return tslib_1.__awaiter(this, void 0, void 0, function* () {
36
- const fetchUrl = (_b = (_a = this.clientOptions) === null || _a === void 0 ? void 0 : _a.csrfTokenFetchUrl) !== null && _b !== void 0 ? _b : "/";
37
- const response = yield this.get(fetchUrl, { headers: { "x-csrf-token": "Fetch" } });
38
- return response.headers["x-csrf-token"];
39
- });
40
- }
41
- sendRequest(config, requestConfig) {
42
- var _a;
43
- return tslib_1.__awaiter(this, void 0, void 0, function* () {
44
- const mergedConfig = (0, AjaxRequestConfig_1.mergeAjaxConfig)((0, AjaxRequestConfig_1.mergeAjaxConfig)(this.config, requestConfig), config);
45
- // setup automatic CSRF token handling
46
- if (((_a = this.clientOptions) === null || _a === void 0 ? void 0 : _a.useCsrfProtection) &&
47
- mergedConfig.method &&
48
- ["POST", "PUT", "PATCH", "DELETE"].includes(mergedConfig.method.toUpperCase())) {
49
- const csrfToken = yield this.setupSecurityToken();
50
- if (!mergedConfig.headers) {
51
- mergedConfig.headers = {};
52
- }
53
- if (this.csrfToken) {
54
- mergedConfig.headers["x-csrf-token"] = csrfToken;
55
- }
56
- }
57
- // the actual request
58
- return new Promise((resolve, reject) => {
59
- this.client.ajax(Object.assign(Object.assign({}, mergedConfig), { success: (response, textStatus, jqXHR) => {
60
- // Convert the header string into an array of individual headers
61
- const headers = jqXHR
62
- .getAllResponseHeaders()
63
- .trim()
64
- .split(/[\r\n]+/)
65
- .reduce((collector, line) => {
66
- const parts = line.split(": ");
67
- const header = parts.shift();
68
- const value = parts.join(": ");
69
- if (header) {
70
- collector[header.toLowerCase()] = value;
71
- }
72
- return collector;
73
- }, {});
74
- resolve({
75
- status: jqXHR.status,
76
- statusText: jqXHR.statusText,
77
- headers,
78
- data: response,
79
- });
80
- }, error: (jqXHR, textStatus, thrownError) => {
81
- var _a;
82
- // automatic CSRF token handling
83
- if (((_a = this.clientOptions) === null || _a === void 0 ? void 0 : _a.useCsrfProtection) &&
84
- jqXHR.status === 403 &&
85
- jqXHR.getResponseHeader("x-csrf-token") === "Required") {
86
- // csrf token expired, let's reset it and perform the original request again
87
- this.csrfToken = undefined;
88
- this.sendRequest(config, requestConfig).then(resolve).catch(reject);
89
- }
90
- // actual error handling
91
- else {
92
- const message = this.getErrorMessage(jqXHR.responseJSON);
93
- if (message) {
94
- reject(new JQueryClientError_1.JQueryClientError("Server responded with error: " + message, jqXHR.status, jqXHR));
95
- }
96
- else {
97
- reject(new JQueryClientError_1.JQueryClientError(textStatus + " " + thrownError, jqXHR.status, jqXHR));
98
- }
99
- }
100
- } }));
101
- });
102
- });
103
- }
104
- prepareData(data) {
105
- return JSON.stringify(data);
106
- }
107
- post(url, data, requestConfig) {
108
- return this.sendRequest({ url, data: this.prepareData(data), method: "POST" }, requestConfig);
109
- }
110
- get(url, requestConfig) {
111
- return this.sendRequest({ url, method: "GET" }, requestConfig);
112
- }
113
- put(url, data, requestConfig) {
114
- return this.sendRequest({ url, data: this.prepareData(data), method: "PUT" }, requestConfig);
115
- }
116
- patch(url, data, requestConfig) {
117
- return this.sendRequest({ url, data: this.prepareData(data), method: "PATCH" }, requestConfig);
118
- }
119
- merge(url, data, requestConfig) {
120
- const config = (0, AjaxRequestConfig_1.mergeAjaxConfig)(requestConfig, {
121
- headers: {
122
- "X-Http-Method": "MERGE",
123
- },
27
+ return collector;
28
+ }, {});
29
+ }
30
+ addHeaderToRequestConfig(headers, config) {
31
+ return (0, AjaxRequestConfig_1.mergeAjaxConfig)(config, { headers });
32
+ }
33
+ executeRequest(method, url, data, requestConfig) {
34
+ const mergedConfig = (0, AjaxRequestConfig_1.mergeAjaxConfig)(this.config, requestConfig);
35
+ mergedConfig.method = method;
36
+ mergedConfig.url = url;
37
+ mergedConfig.data = JSON.stringify(data);
38
+ // the actual request
39
+ return new Promise((resolve, reject) => {
40
+ this.client.ajax(Object.assign(Object.assign({}, mergedConfig), { success: (response, textStatus, jqXHR) => {
41
+ resolve({
42
+ status: jqXHR.status,
43
+ statusText: jqXHR.statusText,
44
+ headers: this.mapHeaders(jqXHR),
45
+ data: response,
46
+ });
47
+ }, error: (jqXHR, textStatus, thrownError) => {
48
+ const responseMessage = this.retrieveErrorMessage(jqXHR.responseJSON);
49
+ const errorMessage = responseMessage
50
+ ? "Server responded with error: " + responseMessage
51
+ : textStatus + " " + thrownError;
52
+ const responseHeaders = this.mapHeaders(jqXHR);
53
+ reject(new JQueryClientError_1.JQueryClientError(errorMessage, jqXHR.status, responseHeaders, new Error(thrownError), jqXHR));
54
+ } }));
124
55
  });
125
- return this.sendRequest({ url, data: this.prepareData(data), method: "POST" }, config);
126
- }
127
- delete(url, requestConfig) {
128
- return this.sendRequest({ url, method: "DELETE" }, requestConfig);
129
56
  }
130
57
  }
131
58
  exports.JQueryClient = JQueryClient;
@@ -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/misc.d.ts\" />\n/// <reference path=\"../../../node_modules/@types/jquery/JQueryStatic.d.ts\" />\n\nimport { HttpResponseModel, ODataHttpClient } from \"@odata2ts/http-client-api\";\n\nimport { AjaxRequestConfig, getDefaultConfig, mergeAjaxConfig } from \"./AjaxRequestConfig\";\nimport { JQueryClientError } from \"./JQueryClientError\";\n\nexport type ErrorMessageRetriever = (errorResponse: any) => string | undefined;\n\nexport interface ClientOptions {\n useCsrfProtection?: boolean;\n csrfTokenFetchUrl?: string;\n}\n\nexport const getV2OrV4ErrorMessage: ErrorMessageRetriever = (errorResponse: any): string | undefined => {\n const eMsg = errorResponse?.error?.message;\n return typeof eMsg?.value === \"string\" ? eMsg.value : eMsg;\n};\n\nexport class JQueryClient implements ODataHttpClient<AjaxRequestConfig> {\n private readonly client: JQueryStatic;\n private readonly config: JQuery.AjaxSettings;\n private csrfToken: string | undefined;\n private getErrorMessage: ErrorMessageRetriever = getV2OrV4ErrorMessage;\n\n constructor(jquery: JQueryStatic, config?: AjaxRequestConfig, private clientOptions?: ClientOptions) {\n this.client = jquery;\n this.config = getDefaultConfig(config);\n }\n\n public setErrorMessageRetriever(getErrorMsg: ErrorMessageRetriever) {\n this.getErrorMessage = getErrorMsg;\n }\n\n private async setupSecurityToken() {\n if (!this.csrfToken) {\n this.csrfToken = await this.fetchSecurityToken();\n }\n return this.csrfToken;\n }\n\n private async fetchSecurityToken(): Promise<string | undefined> {\n const fetchUrl = this.clientOptions?.csrfTokenFetchUrl ?? \"/\";\n const response = await this.get(fetchUrl, { headers: { \"x-csrf-token\": \"Fetch\" } });\n\n return response.headers[\"x-csrf-token\"];\n }\n\n private async sendRequest<ResponseType>(\n config: JQuery.AjaxSettings,\n requestConfig?: AjaxRequestConfig\n ): Promise<HttpResponseModel<ResponseType>> {\n const mergedConfig = mergeAjaxConfig(mergeAjaxConfig(this.config, requestConfig), config);\n\n // setup automatic CSRF token handling\n if (\n this.clientOptions?.useCsrfProtection &&\n mergedConfig.method &&\n [\"POST\", \"PUT\", \"PATCH\", \"DELETE\"].includes(mergedConfig.method.toUpperCase())\n ) {\n const csrfToken = await this.setupSecurityToken();\n if (!mergedConfig.headers) {\n mergedConfig.headers = {};\n }\n if (this.csrfToken) {\n mergedConfig.headers[\"x-csrf-token\"] = csrfToken;\n }\n }\n\n // the actual request\n return new Promise((resolve, reject) => {\n this.client.ajax({\n ...mergedConfig,\n success: (response: any, textStatus: string, jqXHR: JQuery.jqXHR) => {\n // Convert the header string into an array of individual headers\n const headers = 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 resolve({\n status: jqXHR.status,\n statusText: jqXHR.statusText,\n headers,\n data: response,\n });\n },\n error: (jqXHR: JQuery.jqXHR, textStatus: string, thrownError: string) => {\n // automatic CSRF token handling\n if (\n this.clientOptions?.useCsrfProtection &&\n jqXHR.status === 403 &&\n jqXHR.getResponseHeader(\"x-csrf-token\") === \"Required\"\n ) {\n // csrf token expired, let's reset it and perform the original request again\n this.csrfToken = undefined;\n this.sendRequest<ResponseType>(config, requestConfig).then(resolve).catch(reject);\n }\n // actual error handling\n else {\n const message = this.getErrorMessage(jqXHR.responseJSON);\n if (message) {\n reject(new JQueryClientError(\"Server responded with error: \" + message, jqXHR.status, jqXHR));\n } else {\n reject(new JQueryClientError(textStatus + \" \" + thrownError, jqXHR.status, jqXHR));\n }\n }\n },\n });\n });\n }\n\n private prepareData(data: any): string {\n return JSON.stringify(data);\n }\n\n public post<ResponseModel>(\n url: string,\n data: any,\n requestConfig?: AjaxRequestConfig\n ): Promise<HttpResponseModel<ResponseModel>> {\n return this.sendRequest<ResponseModel>({ url, data: this.prepareData(data), method: \"POST\" }, requestConfig);\n }\n public get<ResponseModel>(url: string, requestConfig?: AjaxRequestConfig): Promise<HttpResponseModel<ResponseModel>> {\n return this.sendRequest<ResponseModel>({ url, method: \"GET\" }, requestConfig);\n }\n public put<ResponseModel>(\n url: string,\n data: any,\n requestConfig?: AjaxRequestConfig\n ): Promise<HttpResponseModel<ResponseModel>> {\n return this.sendRequest<ResponseModel>({ url, data: this.prepareData(data), method: \"PUT\" }, requestConfig);\n }\n public patch<ResponseModel>(\n url: string,\n data: any,\n requestConfig?: AjaxRequestConfig\n ): Promise<HttpResponseModel<ResponseModel>> {\n return this.sendRequest<ResponseModel>({ url, data: this.prepareData(data), method: \"PATCH\" }, requestConfig);\n }\n public merge<ResponseModel>(\n url: string,\n data: any,\n requestConfig?: AjaxRequestConfig\n ): Promise<HttpResponseModel<ResponseModel>> {\n const config = mergeAjaxConfig(requestConfig, {\n headers: {\n \"X-Http-Method\": \"MERGE\",\n },\n });\n return this.sendRequest<ResponseModel>({ url, data: this.prepareData(data), method: \"POST\" }, config);\n }\n public delete(url: string, requestConfig?: AjaxRequestConfig): Promise<HttpResponseModel<void>> {\n return this.sendRequest<void>({ url, method: \"DELETE\" }, requestConfig);\n }\n}\n"]}
1
+ {"version":3,"file":"JQueryClient.js","sourceRoot":"","sources":["../src/JQueryClient.ts"],"names":[],"mappings":";AAAA,8EAA8E;;;AAG9E,iEAAgG;AAEhG,2DAA2F;AAC3F,2DAAwD;AAMxD,MAAa,YAAa,SAAQ,iCAAiC;IAIjE,YAAY,MAAoB,EAAE,MAA0B,EAAU,aAA6B;QACjG,KAAK,CAAC,aAAa,CAAC,CAAC;QAD+C,kBAAa,GAAb,aAAa,CAAgB;QAEjG,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,MAAM,GAAG,IAAA,oCAAgB,EAAC,MAAM,CAAC,CAAC;IACzC,CAAC;IAES,UAAU,CAAC,KAAY;QAC/B,OAAO,KAAK;aACT,qBAAqB,EAAE;aACvB,IAAI,EAAE;aACN,KAAK,CAAC,SAAS,CAAC;aAChB,MAAM,CAAC,CAAC,SAAiC,EAAE,IAAY,EAAE,EAAE;YAC1D,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;YAC/B,MAAM,MAAM,GAAG,KAAK,CAAC,KAAK,EAAE,CAAC;YAC7B,MAAM,KAAK,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAE/B,IAAI,MAAM,EAAE;gBACV,SAAS,CAAC,MAAM,CAAC,WAAW,EAAE,CAAC,GAAG,KAAK,CAAC;aACzC;YACD,OAAO,SAAS,CAAC;QACnB,CAAC,EAAE,EAAE,CAAC,CAAC;IACX,CAAC;IAES,wBAAwB,CAAC,OAA+B,EAAE,MAA0B;QAC5F,OAAO,IAAA,mCAAe,EAAC,MAAM,EAAE,EAAE,OAAO,EAAE,CAAC,CAAC;IAC9C,CAAC;IAES,cAAc,CACtB,MAAmB,EACnB,GAAW,EACX,IAAS,EACT,aAAmC;QAEnC,MAAM,YAAY,GAAG,IAAA,mCAAe,EAAC,IAAI,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC;QACjE,YAAY,CAAC,MAAM,GAAG,MAAM,CAAC;QAC7B,YAAY,CAAC,GAAG,GAAG,GAAG,CAAC;QACvB,YAAY,CAAC,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;QAEzC,qBAAqB;QACrB,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;YACrC,IAAI,CAAC,MAAM,CAAC,IAAI,iCACX,YAAY,KACf,OAAO,EAAE,CAAC,QAAa,EAAE,UAAkB,EAAE,KAAmB,EAAE,EAAE;oBAClE,OAAO,CAAC;wBACN,MAAM,EAAE,KAAK,CAAC,MAAM;wBACpB,UAAU,EAAE,KAAK,CAAC,UAAU;wBAC5B,OAAO,EAAE,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC;wBAC/B,IAAI,EAAE,QAAQ;qBACf,CAAC,CAAC;gBACL,CAAC,EACD,KAAK,EAAE,CAAC,KAAmB,EAAE,UAAkB,EAAE,WAAmB,EAAE,EAAE;oBACtE,MAAM,eAAe,GAAG,IAAI,CAAC,oBAAoB,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC;oBACtE,MAAM,YAAY,GAAG,eAAe;wBAClC,CAAC,CAAC,+BAA+B,GAAG,eAAe;wBACnD,CAAC,CAAC,UAAU,GAAG,GAAG,GAAG,WAAW,CAAC;oBACnC,MAAM,eAAe,GAAG,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC;oBAC/C,MAAM,CAAC,IAAI,qCAAiB,CAAC,YAAY,EAAE,KAAK,CAAC,MAAM,EAAE,eAAe,EAAE,IAAI,KAAK,CAAC,WAAW,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC;gBAC5G,CAAC,IACD,CAAC;QACL,CAAC,CAAC,CAAC;IACL,CAAC;CACF;AAjED,oCAiEC","sourcesContent":["/// <reference path=\"../../../node_modules/@types/jquery/JQueryStatic.d.ts\" />\r\n\r\nimport { HttpResponseModel } from \"@odata2ts/http-client-api\";\r\nimport { BaseHttpClient, BaseHttpClientOptions, HttpMethods } from \"@odata2ts/http-client-base\";\r\n\r\nimport { AjaxRequestConfig, getDefaultConfig, mergeAjaxConfig } from \"./AjaxRequestConfig\";\r\nimport { JQueryClientError } from \"./JQueryClientError\";\r\n\r\nimport jqXHR = JQuery.jqXHR;\r\n\r\nexport interface ClientOptions extends BaseHttpClientOptions {}\r\n\r\nexport class JQueryClient extends BaseHttpClient<AjaxRequestConfig> {\r\n private readonly client: JQueryStatic;\r\n private readonly config: JQuery.AjaxSettings;\r\n\r\n constructor(jquery: JQueryStatic, config?: AjaxRequestConfig, private clientOptions?: ClientOptions) {\r\n super(clientOptions);\r\n this.client = jquery;\r\n this.config = getDefaultConfig(config);\r\n }\r\n\r\n protected mapHeaders(jqXhr: jqXHR): Record<string, string> {\r\n return jqXhr\r\n .getAllResponseHeaders()\r\n .trim()\r\n .split(/[\\r\\n]+/)\r\n .reduce((collector: Record<string, string>, line: string) => {\r\n const parts = line.split(\": \");\r\n const header = parts.shift();\r\n const value = parts.join(\": \");\r\n\r\n if (header) {\r\n collector[header.toLowerCase()] = value;\r\n }\r\n return collector;\r\n }, {});\r\n }\r\n\r\n protected addHeaderToRequestConfig(headers: Record<string, string>, config?: AjaxRequestConfig): AjaxRequestConfig {\r\n return mergeAjaxConfig(config, { headers });\r\n }\r\n\r\n protected executeRequest<ResponseModel>(\r\n method: HttpMethods,\r\n url: string,\r\n data: any,\r\n requestConfig?: JQuery.AjaxSettings\r\n ): Promise<HttpResponseModel<ResponseModel>> {\r\n const mergedConfig = mergeAjaxConfig(this.config, requestConfig);\r\n mergedConfig.method = method;\r\n mergedConfig.url = url;\r\n mergedConfig.data = JSON.stringify(data);\r\n\r\n // the actual request\r\n return new Promise((resolve, reject) => {\r\n this.client.ajax({\r\n ...mergedConfig,\r\n success: (response: any, textStatus: string, jqXHR: JQuery.jqXHR) => {\r\n resolve({\r\n status: jqXHR.status,\r\n statusText: jqXHR.statusText,\r\n headers: this.mapHeaders(jqXHR),\r\n data: response,\r\n });\r\n },\r\n error: (jqXHR: JQuery.jqXHR, textStatus: string, thrownError: string) => {\r\n const responseMessage = this.retrieveErrorMessage(jqXHR.responseJSON);\r\n const errorMessage = responseMessage\r\n ? \"Server responded with error: \" + responseMessage\r\n : textStatus + \" \" + thrownError;\r\n const responseHeaders = this.mapHeaders(jqXHR);\r\n reject(new JQueryClientError(errorMessage, jqXHR.status, responseHeaders, new Error(thrownError), jqXHR));\r\n },\r\n });\r\n });\r\n }\r\n}\r\n"]}
@@ -1,6 +1,9 @@
1
1
  /// <reference types="jquery/misc" />
2
- export declare class JQueryClientError extends Error {
2
+ import { ODataClientError } from "@odata2ts/http-client-api";
3
+ export declare class JQueryClientError extends Error implements ODataClientError {
3
4
  readonly status: number | undefined;
4
- readonly cause: Error | JQuery.jqXHR | undefined;
5
- constructor(msg: string, status: number | undefined, cause: Error | JQuery.jqXHR | undefined);
5
+ readonly headers: Record<string, string> | undefined;
6
+ readonly cause: Error | undefined;
7
+ readonly jqXHR: JQuery.jqXHR;
8
+ constructor(msg: string, status: number | undefined, headers: Record<string, string> | undefined, cause: Error | undefined, jqXHR: JQuery.jqXHR);
6
9
  }
@@ -3,10 +3,13 @@
3
3
  Object.defineProperty(exports, "__esModule", { value: true });
4
4
  exports.JQueryClientError = void 0;
5
5
  class JQueryClientError extends Error {
6
- constructor(msg, status, cause) {
6
+ constructor(msg, status, headers, cause, jqXHR) {
7
+ // @ts-ignore: fetch requires lib "dom" or "webworker", but then the "cause" property becomes unknown to TS
7
8
  super(msg, { cause });
8
9
  this.status = status;
10
+ this.headers = headers;
9
11
  this.cause = cause;
12
+ this.jqXHR = jqXHR;
10
13
  this.name = this.constructor.name;
11
14
  }
12
15
  }
@@ -1 +1 @@
1
- {"version":3,"file":"JQueryClientError.js","sourceRoot":"","sources":["../src/JQueryClientError.ts"],"names":[],"mappings":";AAAA,sEAAsE;;;AAEtE,MAAa,iBAAkB,SAAQ,KAAK;IAC1C,YACE,GAAW,EACK,MAA0B,EAC1B,KAAuC;QAEvD,KAAK,CAAC,GAAG,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC;QAHN,WAAM,GAAN,MAAM,CAAoB;QAC1B,UAAK,GAAL,KAAK,CAAkC;QAGvD,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC;IACpC,CAAC;CACF;AATD,8CASC","sourcesContent":["/// <reference path=\"../../../node_modules/@types/jquery/misc.d.ts\" />\r\n\r\nexport class JQueryClientError extends Error {\r\n constructor(\r\n msg: string,\r\n public readonly status: number | undefined,\r\n public readonly cause: Error | JQuery.jqXHR | undefined\r\n ) {\r\n super(msg, { cause });\r\n this.name = this.constructor.name;\r\n }\r\n}\r\n"]}
1
+ {"version":3,"file":"JQueryClientError.js","sourceRoot":"","sources":["../src/JQueryClientError.ts"],"names":[],"mappings":";AAAA,sEAAsE;;;AAItE,MAAa,iBAAkB,SAAQ,KAAK;IAC1C,YACE,GAAW,EACK,MAA0B,EAC1B,OAA2C,EAC3C,KAAwB,EACxB,KAAmB;QAEnC,2GAA2G;QAC3G,KAAK,CAAC,GAAG,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC;QANN,WAAM,GAAN,MAAM,CAAoB;QAC1B,YAAO,GAAP,OAAO,CAAoC;QAC3C,UAAK,GAAL,KAAK,CAAmB;QACxB,UAAK,GAAL,KAAK,CAAc;QAInC,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC;IACpC,CAAC;CACF;AAZD,8CAYC","sourcesContent":["/// <reference path=\"../../../node_modules/@types/jquery/misc.d.ts\" />\r\n\r\nimport { ODataClientError } from \"@odata2ts/http-client-api\";\r\n\r\nexport class JQueryClientError extends Error implements ODataClientError {\r\n constructor(\r\n msg: string,\r\n public readonly status: number | undefined,\r\n public readonly headers: Record<string, string> | undefined,\r\n public readonly cause: Error | undefined,\r\n public readonly jqXHR: JQuery.jqXHR\r\n ) {\r\n // @ts-ignore: fetch requires lib \"dom\" or \"webworker\", but then the \"cause\" property becomes unknown to TS\r\n super(msg, { cause });\r\n this.name = this.constructor.name;\r\n }\r\n}\r\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@odata2ts/http-client-jquery",
3
- "version": "0.4.0",
3
+ "version": "0.5.1",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },
@@ -34,7 +34,7 @@
34
34
  "jquery": ">1.0"
35
35
  },
36
36
  "dependencies": {
37
- "@odata2ts/http-client-api": "^0.1.0"
37
+ "@odata2ts/http-client-base": "^0.2.0"
38
38
  },
39
39
  "devDependencies": {
40
40
  "@types/jest": "^27.4.1",
@@ -49,5 +49,5 @@
49
49
  "typescript": "5.0.4"
50
50
  },
51
51
  "types": "./lib/index.d.ts",
52
- "gitHead": "a93b726286ef9a118fda63b0e7900d6b3e739dd2"
52
+ "gitHead": "9babd2df3010673249e7e3fa26705a8ba84f2cef"
53
53
  }