@odata2ts/http-client-jquery 0.4.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 ADDED
@@ -0,0 +1,46 @@
1
+ # Change Log
2
+
3
+ All notable changes to this project will be documented in this file.
4
+ See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
+
6
+ # 0.4.0 (2023-06-03)
7
+
8
+ ### Features
9
+
10
+ * **jquery:** copy over jquery-client and rename ([#3](https://github.com/odata2ts/http-client/issues/3)) ([55deb6c](https://github.com/odata2ts/http-client/commit/55deb6c75159bfc46b0ae87cb3c0ec3afda9508e))
11
+ * switch to http-client-api ([52d1b86](https://github.com/odata2ts/http-client/commit/52d1b868ee82dbaf45486da6b22fdcf4c773dfb8))
12
+ * switch to http-client-api ([5a6da23](https://github.com/odata2ts/http-client/commit/5a6da23053b3ea5adb866bb7e30b469f1b8ed260))
13
+
14
+ ## [0.3.1](https://github.com/odata2ts/odata2ts/compare/@odata2ts/jquery-odata-client@0.3.0...@odata2ts/jquery-odata-client@0.3.1) (2023-05-02)
15
+
16
+ ### Bug Fixes
17
+
18
+ * **jquery-client:** stringify request body & parse response headers ([#159](https://github.com/odata2ts/odata2ts/issues/159)) ([4d5217f](https://github.com/odata2ts/odata2ts/commit/4d5217f6f168b8b906cb07cc9be90a13374ed681))
19
+
20
+ # [0.3.0](https://github.com/odata2ts/odata2ts/compare/@odata2ts/jquery-odata-client@0.2.0...@odata2ts/jquery-odata-client@0.3.0) (2023-04-27)
21
+
22
+ ### Features
23
+
24
+ * **jquery-client:** automatic CSRF token handling ([c86fe0c](https://github.com/odata2ts/odata2ts/commit/c86fe0c96a347afc7a3525de718bf266fd6a4da0))
25
+
26
+ # [0.2.0](https://github.com/odata2ts/odata2ts/compare/@odata2ts/jquery-odata-client@0.1.2...@odata2ts/jquery-odata-client@0.2.0) (2023-04-20)
27
+
28
+ ### Features
29
+
30
+ * better errors for jquery and axios odata clients ([#139](https://github.com/odata2ts/odata2ts/issues/139)) ([bb74514](https://github.com/odata2ts/odata2ts/commit/bb745144fb37235ad9864ab78eebbecf1d69107c))
31
+
32
+ ## [0.1.2](https://github.com/odata2ts/odata2ts/compare/@odata2ts/jquery-odata-client@0.1.1...@odata2ts/jquery-odata-client@0.1.2) (2023-04-08)
33
+
34
+ **Note:** Version bump only for package @odata2ts/jquery-odata-client
35
+
36
+ ## [0.1.1](https://github.com/odata2ts/odata2ts/compare/@odata2ts/jquery-odata-client@0.1.0...@odata2ts/jquery-odata-client@0.1.1) (2023-02-24)
37
+
38
+ ### Bug Fixes
39
+
40
+ * **jquery-odata-client:** better typings and version for jquery ([#136](https://github.com/odata2ts/odata2ts/issues/136)) ([de29772](https://github.com/odata2ts/odata2ts/commit/de297722113c16e0bf48255d4108ee29daf70fa2))
41
+
42
+ # 0.1.0 (2023-02-24)
43
+
44
+ ### Features
45
+
46
+ * jquery based OData client ([#135](https://github.com/odata2ts/odata2ts/issues/135)) ([183602f](https://github.com/odata2ts/odata2ts/commit/183602f9686b36e23679091ed8223088b4591192))
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2021 odata2ts
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,46 @@
1
+ [![npm (scoped)](https://img.shields.io/npm/v/@odata2ts/http-client-jquery?style=for-the-badge)](https://www.npmjs.com/package/@odata2ts/http-client-jquery)
2
+
3
+ # JQuery HTTP Client
4
+
5
+ [odata2ts](https://github.com/odata2ts/odata2ts) compatible odata client based on [JQuery](https://jquery.com/)
6
+ and its [ajax method](https://api.jquery.com/Jquery.ajax/).
7
+
8
+ JQuery is used by this client but not installed (declared as peer dependency).
9
+ The existing JQuery instance must be provided when initializing the client.
10
+
11
+ The whole client is meant to support usage of `odata2ts` in UI5 apps, which use Jquery for HTTP communication.
12
+
13
+ ## Installation
14
+
15
+ Install package `@odata2ts/http-client-jquery` as runtime dependency:
16
+
17
+ ```bash
18
+ npm install --save @odata2ts/http-client-jquery
19
+ ```
20
+
21
+ JQuery is a peer-dependency of this package, so it's not contained in or installed through this package.
22
+
23
+ ## Documentation
24
+
25
+ [JQuery Client Documentation](https://odata2ts.github.io/docs/odata-client/http-client/jquery)
26
+
27
+ Main documentation for the odata2ts eco system:
28
+ [https://odata2ts.github.io](https://odata2ts.github.io/)
29
+
30
+ ## Tests
31
+
32
+ See folder [test](https://github.com/odata2ts/http-client/tree/main/packages/jquery/test)
33
+ for unit tests.
34
+
35
+ ## Support, Feedback, Contributing
36
+
37
+ This project is open to feature requests, suggestions, bug reports, usage questions etc.
38
+ via [GitHub issues](https://github.com/odata2ts/odata2ts/issues).
39
+
40
+ Contributions and feedback are encouraged and always welcome.
41
+
42
+ See the [contribution guidelines](https://github.com/odata2ts/odata2ts/blob/main/CONTRIBUTING.md) for further information.
43
+
44
+ ## License
45
+
46
+ MIT - see [License](./LICENSE).
@@ -0,0 +1,44 @@
1
+ /**
2
+ * Available config options for end user when making a given request.
3
+ */
4
+ export type AjaxRequestConfig = Pick<JQuery.AjaxSettings, "complete" | "beforeSend" | "headers" | "statusCode" | "timeout">;
5
+ export declare function getDefaultConfig(config?: AjaxRequestConfig): JQuery.AjaxSettings;
6
+ export declare function mergeAjaxConfig(config?: JQuery.AjaxSettings, toMerge?: JQuery.AjaxSettings): {
7
+ headers: {
8
+ [x: string]: string | null | undefined;
9
+ };
10
+ url?: string | undefined;
11
+ accepts?: JQuery.PlainObject<string> | undefined;
12
+ async?: boolean | undefined;
13
+ beforeSend?: ((this: any, jqXHR: JQuery.jqXHR<any>, settings: JQuery.AjaxSettings<any>) => false | void) | undefined;
14
+ cache?: boolean | undefined;
15
+ complete?: JQuery.TypeOrArray<JQuery.Ajax.CompleteCallback<any>> | undefined;
16
+ contents?: JQuery.PlainObject<RegExp> | undefined;
17
+ contentType?: string | false | undefined;
18
+ context?: any;
19
+ converters?: JQuery.PlainObject<true | ((value: any) => any)> | undefined;
20
+ crossDomain?: boolean | undefined;
21
+ data?: string | JQuery.PlainObject<any> | undefined;
22
+ dataFilter?: ((data: string, type: string) => any) | undefined;
23
+ dataType?: string | undefined;
24
+ enctype?: "application/x-www-form-urlencoded" | "multipart/form-data" | "text/plain" | undefined;
25
+ error?: JQuery.TypeOrArray<JQuery.Ajax.ErrorCallback<any>> | undefined;
26
+ global?: boolean | undefined;
27
+ ifModified?: boolean | undefined;
28
+ isLocal?: boolean | undefined;
29
+ jsonp?: string | false | undefined;
30
+ jsonpCallback?: string | ((this: any) => string) | undefined;
31
+ method?: string | undefined;
32
+ mimeType?: string | undefined;
33
+ password?: string | undefined;
34
+ processData?: boolean | undefined;
35
+ scriptCharset?: string | undefined;
36
+ statusCode?: JQuery.Ajax.StatusCodeCallbacks<any> | undefined;
37
+ success?: JQuery.TypeOrArray<JQuery.Ajax.SuccessCallback<any>> | undefined;
38
+ timeout?: number | undefined;
39
+ traditional?: boolean | undefined;
40
+ type?: string | undefined;
41
+ username?: string | undefined;
42
+ xhr?: (() => XMLHttpRequest) | undefined;
43
+ xhrFields?: JQuery.Ajax.XHRFields | undefined;
44
+ };
@@ -0,0 +1,22 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.mergeAjaxConfig = exports.getDefaultConfig = void 0;
4
+ const tslib_1 = require("tslib");
5
+ const DEFAULT_CONFIG = {
6
+ // we never want caching
7
+ cache: false,
8
+ // we always want JSON
9
+ dataType: "json",
10
+ headers: { Accept: "application/json", "Content-Type": "application/json" },
11
+ };
12
+ function getDefaultConfig(config) {
13
+ return mergeAjaxConfig(DEFAULT_CONFIG, config);
14
+ }
15
+ exports.getDefaultConfig = getDefaultConfig;
16
+ function mergeAjaxConfig(config, toMerge) {
17
+ const _a = config || {}, { headers } = _a, passThrough = tslib_1.__rest(_a, ["headers"]);
18
+ const _b = toMerge || {}, { headers: headers2 } = _b, passThrough2 = tslib_1.__rest(_b, ["headers"]);
19
+ return Object.assign(Object.assign(Object.assign({}, passThrough), passThrough2), { headers: Object.assign(Object.assign({}, headers), headers2) });
20
+ }
21
+ exports.mergeAjaxConfig = mergeAjaxConfig;
22
+ //# sourceMappingURL=AjaxRequestConfig.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AjaxRequestConfig.js","sourceRoot":"","sources":["../src/AjaxRequestConfig.ts"],"names":[],"mappings":";;;;AAAA,MAAM,cAAc,GAAwB;IAC1C,wBAAwB;IACxB,KAAK,EAAE,KAAK;IACZ,sBAAsB;IACtB,QAAQ,EAAE,MAAM;IAChB,OAAO,EAAE,EAAE,MAAM,EAAE,kBAAkB,EAAE,cAAc,EAAE,kBAAkB,EAAE;CAC5E,CAAC;AAUF,SAAgB,gBAAgB,CAAC,MAA0B;IACzD,OAAO,eAAe,CAAC,cAAc,EAAE,MAAM,CAAC,CAAC;AACjD,CAAC;AAFD,4CAEC;AAED,SAAgB,eAAe,CAAC,MAA4B,EAAE,OAA6B;IACzF,MAAM,KAA8B,MAAM,IAAI,EAAE,EAA1C,EAAE,OAAO,OAAiC,EAA5B,WAAW,sBAAzB,WAA2B,CAAe,CAAC;IACjD,MAAM,KAAyC,OAAO,IAAI,EAAE,EAAtD,EAAE,OAAO,EAAE,QAAQ,OAAmC,EAA9B,YAAY,sBAApC,WAAsC,CAAgB,CAAC;IAC7D,qDACK,WAAW,GACX,YAAY,KACf,OAAO,kCACF,OAAO,GACP,QAAQ,KAEb;AACJ,CAAC;AAXD,0CAWC","sourcesContent":["const DEFAULT_CONFIG: JQuery.AjaxSettings = {\r\n // we never want caching\r\n cache: false,\r\n // we always want JSON\r\n dataType: \"json\",\r\n headers: { Accept: \"application/json\", \"Content-Type\": \"application/json\" },\r\n};\r\n\r\n/**\r\n * Available config options for end user when making a given request.\r\n */\r\nexport type AjaxRequestConfig = Pick<\r\n JQuery.AjaxSettings,\r\n \"complete\" | \"beforeSend\" | \"headers\" | \"statusCode\" | \"timeout\"\r\n>;\r\n\r\nexport function getDefaultConfig(config?: AjaxRequestConfig): JQuery.AjaxSettings {\r\n return mergeAjaxConfig(DEFAULT_CONFIG, config);\r\n}\r\n\r\nexport function mergeAjaxConfig(config?: JQuery.AjaxSettings, toMerge?: JQuery.AjaxSettings) {\r\n const { headers, ...passThrough } = config || {};\r\n const { headers: headers2, ...passThrough2 } = toMerge || {};\r\n return {\r\n ...passThrough,\r\n ...passThrough2,\r\n headers: {\r\n ...headers,\r\n ...headers2,\r\n },\r\n };\r\n}\r\n"]}
@@ -0,0 +1,29 @@
1
+ /// <reference types="jquery/misc" />
2
+ /// <reference types="jquery/jquerystatic" />
3
+ import { HttpResponseModel, ODataHttpClient } from "@odata2ts/http-client-api";
4
+ import { AjaxRequestConfig } from "./AjaxRequestConfig";
5
+ export type ErrorMessageRetriever = (errorResponse: any) => string | undefined;
6
+ export interface ClientOptions {
7
+ useCsrfProtection?: boolean;
8
+ csrfTokenFetchUrl?: string;
9
+ }
10
+ export declare const getV2OrV4ErrorMessage: ErrorMessageRetriever;
11
+ export declare class JQueryClient implements ODataHttpClient<AjaxRequestConfig> {
12
+ private clientOptions?;
13
+ private readonly client;
14
+ private readonly config;
15
+ private csrfToken;
16
+ private getErrorMessage;
17
+ 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>>;
29
+ }
@@ -0,0 +1,132 @@
1
+ "use strict";
2
+ /// <reference path="../../../node_modules/@types/jquery/misc.d.ts" />
3
+ /// <reference path="../../../node_modules/@types/jquery/JQueryStatic.d.ts" />
4
+ Object.defineProperty(exports, "__esModule", { value: true });
5
+ exports.JQueryClient = exports.getV2OrV4ErrorMessage = void 0;
6
+ const tslib_1 = require("tslib");
7
+ const AjaxRequestConfig_1 = require("./AjaxRequestConfig");
8
+ 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 {
16
+ constructor(jquery, config, clientOptions) {
17
+ this.clientOptions = clientOptions;
18
+ this.getErrorMessage = exports.getV2OrV4ErrorMessage;
19
+ this.client = jquery;
20
+ this.config = (0, AjaxRequestConfig_1.getDefaultConfig)(config);
21
+ }
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();
29
+ }
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
+ },
124
+ });
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
+ }
130
+ }
131
+ exports.JQueryClient = JQueryClient;
132
+ //# sourceMappingURL=JQueryClient.js.map
@@ -0,0 +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"]}
@@ -0,0 +1,6 @@
1
+ /// <reference types="jquery/misc" />
2
+ export declare class JQueryClientError extends Error {
3
+ readonly status: number | undefined;
4
+ readonly cause: Error | JQuery.jqXHR | undefined;
5
+ constructor(msg: string, status: number | undefined, cause: Error | JQuery.jqXHR | undefined);
6
+ }
@@ -0,0 +1,14 @@
1
+ "use strict";
2
+ /// <reference path="../../../node_modules/@types/jquery/misc.d.ts" />
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ exports.JQueryClientError = void 0;
5
+ class JQueryClientError extends Error {
6
+ constructor(msg, status, cause) {
7
+ super(msg, { cause });
8
+ this.status = status;
9
+ this.cause = cause;
10
+ this.name = this.constructor.name;
11
+ }
12
+ }
13
+ exports.JQueryClientError = JQueryClientError;
14
+ //# sourceMappingURL=JQueryClientError.js.map
@@ -0,0 +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"]}
package/lib/index.d.ts ADDED
@@ -0,0 +1,3 @@
1
+ export { AjaxRequestConfig } from "./AjaxRequestConfig";
2
+ export * from "./JQueryClient";
3
+ export type { JQueryClientError } from "./JQueryClientError";
package/lib/index.js ADDED
@@ -0,0 +1,5 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const tslib_1 = require("tslib");
4
+ tslib_1.__exportStar(require("./JQueryClient"), exports);
5
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AACA,yDAA+B","sourcesContent":["export { AjaxRequestConfig } from \"./AjaxRequestConfig\";\r\nexport * from \"./JQueryClient\";\r\nexport type { JQueryClientError } from \"./JQueryClientError\";\r\n"]}
package/package.json ADDED
@@ -0,0 +1,53 @@
1
+ {
2
+ "name": "@odata2ts/http-client-jquery",
3
+ "version": "0.4.0",
4
+ "publishConfig": {
5
+ "access": "public"
6
+ },
7
+ "description": "JQuery based http client usable by odata2ts",
8
+ "license": "MIT",
9
+ "repository": "git@github.com:odata2ts/http-client.git",
10
+ "author": "texttechne",
11
+ "main": "./lib/index.js",
12
+ "scripts": {
13
+ "build": "yarn clean && yarn compile",
14
+ "check-circular-deps": "madge ./src --extensions ts --circular",
15
+ "clean": "rimraf lib coverage",
16
+ "compile": "tsc",
17
+ "prepublish": "yarn build",
18
+ "test": "jest --passWithNoTests"
19
+ },
20
+ "files": [
21
+ "*.md",
22
+ "lib",
23
+ "LICENSE"
24
+ ],
25
+ "keywords": [
26
+ "http client",
27
+ "jquery",
28
+ "ui5",
29
+ "odata2ts",
30
+ "ts",
31
+ "typescript"
32
+ ],
33
+ "peerDependencies": {
34
+ "jquery": ">1.0"
35
+ },
36
+ "dependencies": {
37
+ "@odata2ts/http-client-api": "^0.1.0"
38
+ },
39
+ "devDependencies": {
40
+ "@types/jest": "^27.4.1",
41
+ "@types/jquery": "^3.5.16",
42
+ "@types/node": "^20.2.5",
43
+ "jest": "29.5.0",
44
+ "jest-environment-jsdom": "^29.5.0",
45
+ "jquery": "^3.6.3",
46
+ "rimraf": "^5.0.1",
47
+ "ts-jest": "^29.1.0",
48
+ "ts-node": "10.9.1",
49
+ "typescript": "5.0.4"
50
+ },
51
+ "types": "./lib/index.d.ts",
52
+ "gitHead": "a93b726286ef9a118fda63b0e7900d6b3e739dd2"
53
+ }