@mittwald/api-client-commons 4.13.1 → 4.15.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -56,3 +56,34 @@ if (!response.data) {
56
56
  console.log("Project not found");
57
57
  }
58
58
  ```
59
+
60
+ ### Common interceptors
61
+
62
+ To make it easy to opt in to some API mechanisms, a few
63
+ [interceptors](https://axios-http.com/docs/interceptors) can be easily
64
+ configured.
65
+
66
+ #### withAccessToken
67
+
68
+ In most cases you want to add the users access token to every API-Request as a
69
+ request header. This can be tedious if you need to do this on your own. To
70
+ automatically set the request header use `withAccessToken` for your `APIClient`
71
+ instance.
72
+
73
+ ```ts
74
+ const client = new APIClient({ baseURL });
75
+ const authenticatedClient = withToken(client, token);
76
+ ```
77
+
78
+ #### withEventConsistencyHandling
79
+
80
+ To opt in into the
81
+ [event consistency handling](https://developer.mittwald.de/docs/v2/api/intro/#eventual-consistency)
82
+ you might use `withEventConsistencyHandling`. This will set automatically handle
83
+ the `etag` response header and set its value as `if-event-reached` request
84
+ header for GET requests:
85
+
86
+ ```ts
87
+ const client = new APIClient({ baseURL });
88
+ const authenticatedClient = withEventConsistencyHandling(client);
89
+ ```
package/dist/esm/index.js CHANGED
@@ -1,3 +1,4 @@
1
1
  export * from "./core/index.js";
2
2
  export * from "./types/index.js";
3
3
  export * from "./axios.js";
4
+ export * from "./interceptors/index.js";
@@ -0,0 +1,19 @@
1
+ import ApiClientBase from "../core/ApiClientBase.js";
2
+ function configureAccessTokenInterceptor(axios, token, headerName = "x-access-token") {
3
+ axios.interceptors.request.use((conf) => {
4
+ if (!conf.headers.has(headerName)) {
5
+ conf.headers.set(headerName, token);
6
+ }
7
+ return conf;
8
+ });
9
+ }
10
+ export function withAccessToken(clientOrAxiosInstance, token, headerName = "x-access-token") {
11
+ if (token) {
12
+ const axiosInstance = clientOrAxiosInstance instanceof ApiClientBase
13
+ ? clientOrAxiosInstance.axios
14
+ : clientOrAxiosInstance;
15
+ configureAccessTokenInterceptor(axiosInstance, token, headerName);
16
+ }
17
+ return clientOrAxiosInstance;
18
+ }
19
+ export default withAccessToken;
@@ -0,0 +1,27 @@
1
+ import ApiClientBase from "../core/ApiClientBase.js";
2
+ function isMutatingRequest(request) {
3
+ return ["post", "put", "delete", "patch"].includes(request.method?.toLowerCase() ?? "");
4
+ }
5
+ function configureConsistencyHandlingInterceptor(axios) {
6
+ let lastEventId = undefined;
7
+ axios.interceptors.request.use((config) => {
8
+ if (lastEventId !== undefined && !isMutatingRequest(config)) {
9
+ config.headers["if-event-reached"] = lastEventId;
10
+ }
11
+ return config;
12
+ });
13
+ axios.interceptors.response.use((response) => {
14
+ const headers = response.headers;
15
+ if (headers.has("etag") && isMutatingRequest(response.config)) {
16
+ lastEventId = headers.get("etag");
17
+ }
18
+ return response;
19
+ });
20
+ }
21
+ export function withEventConsistencyHandling(clientOrAxiosInstance) {
22
+ const axiosInstance = clientOrAxiosInstance instanceof ApiClientBase
23
+ ? clientOrAxiosInstance.axios
24
+ : clientOrAxiosInstance;
25
+ configureConsistencyHandlingInterceptor(axiosInstance);
26
+ return clientOrAxiosInstance;
27
+ }
@@ -0,0 +1,2 @@
1
+ export * from "./accessToken.js";
2
+ export * from "./consistencyHandling.js";
@@ -1,3 +1,4 @@
1
1
  export * from "./core/index.js";
2
2
  export * from "./types/index.js";
3
3
  export * from "./axios.js";
4
+ export * from "./interceptors/index.js";
@@ -0,0 +1,4 @@
1
+ import { AxiosInstance } from "axios";
2
+ import ApiClientBase from "../core/ApiClientBase.js";
3
+ export declare function withAccessToken<T extends ApiClientBase | AxiosInstance>(clientOrAxiosInstance: T, token: string | undefined, headerName?: string): T;
4
+ export default withAccessToken;
@@ -0,0 +1,3 @@
1
+ import { AxiosInstance } from "axios";
2
+ import ApiClientBase from "../core/ApiClientBase.js";
3
+ export declare function withEventConsistencyHandling<T extends ApiClientBase | AxiosInstance>(clientOrAxiosInstance: T): T;
@@ -0,0 +1,2 @@
1
+ export * from "./accessToken.js";
2
+ export * from "./consistencyHandling.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mittwald/api-client-commons",
3
- "version": "4.13.1",
3
+ "version": "4.15.0",
4
4
  "author": "Mittwald CM Service GmbH & Co. KG <opensource@mittwald.de>",
5
5
  "type": "module",
6
6
  "description": "Common types and utilities for mittwald API clients",
@@ -44,15 +44,15 @@
44
44
  "axios": "^1.6.7",
45
45
  "parse-path": "^7.0.0",
46
46
  "path-to-regexp": "^6.2.1",
47
- "type-fest": "^4.10.3"
47
+ "type-fest": "^4.12.0"
48
48
  },
49
49
  "devDependencies": {
50
50
  "@jest/globals": "^29.7.0",
51
51
  "@mittwald/react-use-promise": "^2.3.12",
52
52
  "@types/jest": "^29.5.12",
53
- "@typescript-eslint/eslint-plugin": "^7.0.2",
54
- "@typescript-eslint/parser": "^7.0.2",
55
- "eslint": "^8.56.0",
53
+ "@typescript-eslint/eslint-plugin": "^7.1.1",
54
+ "@typescript-eslint/parser": "^7.1.1",
55
+ "eslint": "^8.57.0",
56
56
  "eslint-config-prettier": "^9.1.0",
57
57
  "eslint-plugin-json": "^3.1.0",
58
58
  "eslint-plugin-prettier": "^5.1.3",
@@ -64,8 +64,8 @@
64
64
  "react": "^18.2.0",
65
65
  "rimraf": "^5.0.5",
66
66
  "ts-jest": "^29.1.2",
67
- "tsd": "^0.30.6",
68
- "typescript": "^5.3.3"
67
+ "tsd": "^0.30.7",
68
+ "typescript": "^5.4.2"
69
69
  },
70
70
  "peerDependencies": {
71
71
  "@mittwald/react-use-promise": "^2.1.0"
@@ -78,5 +78,5 @@
78
78
  "optional": true
79
79
  }
80
80
  },
81
- "gitHead": "27ede7b99b15b423749de87ecf08d74701721734"
81
+ "gitHead": "b04612b188ae649a5d1fb7788da3a6149d6a7ebd"
82
82
  }