@canmingir/link 1.2.52 → 1.2.54

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@canmingir/link",
3
- "version": "1.2.52",
3
+ "version": "1.2.54",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "link-server": "./server/server.ts"
@@ -41,7 +41,6 @@
41
41
  "autosuggest-highlight": "^3.3.4",
42
42
  "aws-amplify": "^6.16.0",
43
43
  "axios": "^1.10.0",
44
- "axios-auth-refresh": "^3.3.6",
45
44
  "axios-retry": "^4.4.1",
46
45
  "cypress": "^15.3.0",
47
46
  "date-fns": "^3.6.0",
@@ -60,10 +59,10 @@
60
59
  "react-apexcharts": "^1.4.1",
61
60
  "react-chartjs-2": "^5.2.0",
62
61
  "react-dom": "^18.2.0",
63
- "react-is": "^18.3.1",
64
62
  "react-dropzone": "^14.2.3",
65
63
  "react-helmet-async": "^2.0.5",
66
64
  "react-hook-form": "^7.52.1",
65
+ "react-is": "^18.3.1",
67
66
  "react-lazy-load-image-component": "^1.6.2",
68
67
  "react-map-gl": "^7.1.7",
69
68
  "react-markdown": "^9.0.1",
package/src/http/index.js CHANGED
@@ -1,7 +1,5 @@
1
1
  import axios from "axios";
2
2
  import config from "../config/config";
3
- import createAuthRefreshInterceptor from "axios-auth-refresh";
4
- import { jwtDecode } from "jwt-decode";
5
3
  import oauth from "./oauth";
6
4
  import { publish } from "@nucleoidai/react-event";
7
5
  import { storage } from "@nucleoidjs/webstorage";
@@ -29,6 +27,40 @@ instance.interceptors.request.use((request) => {
29
27
  return request;
30
28
  });
31
29
 
30
+ let isRefreshing = false;
31
+ let failedQueue = [];
32
+
33
+ function processQueue(error, token = null) {
34
+ failedQueue.forEach(({ resolve, reject }) => {
35
+ if (error) reject(error);
36
+ else resolve(token);
37
+ });
38
+ failedQueue = [];
39
+ }
40
+
41
+ async function doRefresh() {
42
+ const { appId } = config();
43
+ const projectId = storage.get("projectId");
44
+ const identityProvider = storage.get("link", "identityProvider");
45
+
46
+ const { data } = await oauth.post("/oauth", {
47
+ refreshToken: storage.get("link", "refreshToken"),
48
+ appId,
49
+ projectId,
50
+ identityProvider,
51
+ ...(identityProvider === "DEMO" && {
52
+ username: "admin",
53
+ password: "admin",
54
+ }),
55
+ });
56
+
57
+ storage.set("link", "accessToken", data.accessToken);
58
+ if (data.refreshToken) {
59
+ storage.set("link", "refreshToken", data.refreshToken);
60
+ }
61
+ return data.accessToken;
62
+ }
63
+
32
64
  instance.interceptors.response.use(
33
65
  (response) => {
34
66
  if (response.headers["content-type"] === "application/json") {
@@ -39,18 +71,48 @@ instance.interceptors.response.use(
39
71
  },
40
72
  async (error) => {
41
73
  publish("LOADED", { loading: false });
74
+ const originalRequest = error.config;
42
75
  const statusCode = error.response?.status;
43
- const identityProvider = storage.get("link", "identityProvider");
44
76
 
45
- if (statusCode === 500 && identityProvider === "DEMO") {
46
- const token = storage.get("link", "accessToken");
77
+ if (statusCode === 401 && !originalRequest._retried) {
78
+ originalRequest._retried = true;
79
+
80
+ const usedToken = originalRequest.headers["Authorization"]?.replace(
81
+ "Bearer ",
82
+ ""
83
+ );
84
+ const storedToken = storage.get("link", "accessToken");
85
+
86
+ if (storedToken && storedToken !== usedToken) {
87
+ originalRequest.headers["Authorization"] = `Bearer ${storedToken}`;
88
+ return instance(originalRequest);
89
+ }
90
+
91
+ if (isRefreshing) {
92
+ return new Promise((resolve, reject) => {
93
+ failedQueue.push({ resolve, reject });
94
+ }).then((token) => {
95
+ originalRequest.headers["Authorization"] = `Bearer ${token}`;
96
+ return instance(originalRequest);
97
+ });
98
+ }
99
+
100
+ isRefreshing = true;
101
+
47
102
  try {
48
- const decodedToken = jwtDecode(token);
49
- if (decodedToken.exp * 1000 < Date.now()) {
50
- return Promise.reject(error);
51
- }
52
- } catch (_) {
53
- return Promise.reject(error);
103
+ const token = await doRefresh();
104
+ processQueue(null, token);
105
+ originalRequest.headers["Authorization"] = `Bearer ${token}`;
106
+ return instance(originalRequest);
107
+ } catch (refreshError) {
108
+ processQueue(refreshError, null);
109
+ const { base } = config();
110
+ storage.remove("link", "accessToken");
111
+ storage.remove("link", "refreshToken");
112
+ window.location.href = `${window.location.origin}${base}/login`;
113
+ return Promise.reject(refreshError);
114
+ } finally {
115
+ isRefreshing = false;
54
116
  }
55
117
  }
56
118
 
@@ -92,99 +154,9 @@ instance.interceptors.response.use(
92
154
  break;
93
155
  }
94
156
  return Promise.reject(error);
95
- },
157
+ }
96
158
  );
97
159
 
98
160
  export const fetcher = (url) => instance.get(url).then((res) => res.data);
99
161
 
100
- const refreshAuthLogic = async (failedRequest) => {
101
- try {
102
- const { appId } = config();
103
- const projectId = storage.get("projectId");
104
- const identityProvider = storage.get("link", "identityProvider");
105
-
106
- const { data } = await oauth.post("/oauth", {
107
- refreshToken: storage.get("link", "refreshToken"),
108
- appId,
109
- projectId,
110
- identityProvider,
111
- ...(identityProvider === "DEMO" && {
112
- username: "admin",
113
- password: "admin",
114
- }),
115
- });
116
-
117
- const { accessToken, refreshToken } = data;
118
-
119
- failedRequest.response.config.headers["Authorization"] =
120
- "Bearer " + accessToken;
121
-
122
- storage.set("link", "accessToken", accessToken);
123
- if (refreshToken) {
124
- storage.set("link", "refreshToken", refreshToken);
125
- }
126
-
127
- return Promise.resolve();
128
- } catch (error) {
129
- const { base } = config();
130
-
131
- storage.remove("link", "accessToken");
132
- storage.remove("link", "refreshToken");
133
-
134
- window.location.href = `${window.location.origin}${base}/login`;
135
- return Promise.reject(error);
136
- }
137
- };
138
-
139
- const refreshInterceptor =
140
- typeof createAuthRefreshInterceptor === "function"
141
- ? createAuthRefreshInterceptor
142
- : createAuthRefreshInterceptor.default;
143
-
144
- refreshInterceptor(instance, refreshAuthLogic, {
145
- statusCodes: [401, 403, 500],
146
- pauseInstanceWhileRefreshing: true,
147
- shouldRefresh: (error) => {
148
- const { base } = config();
149
- const token = storage.get("link", "accessToken");
150
- const identityProvider = storage.get("link", "identityProvider");
151
- const statusCode = error.response?.status;
152
-
153
- if (!token) {
154
- window.location.href = `${window.location.origin}${base}/login`;
155
- return false;
156
- }
157
-
158
- if (identityProvider === "DEMO") {
159
- if (statusCode !== 500) {
160
- return true;
161
- }
162
-
163
- try {
164
- const decodedToken = jwtDecode(token);
165
- return decodedToken.exp * 1000 < Date.now();
166
- } catch (_) {
167
- // If we can't decode, attempt refresh once.
168
- return true;
169
- }
170
- }
171
-
172
- if (statusCode === 500) {
173
- return false;
174
- }
175
-
176
- try {
177
- const decodedToken = jwtDecode(token);
178
- if (decodedToken.exp * 1000 < Date.now()) {
179
- return true;
180
- }
181
- } catch (err) {
182
- window.location.href = `${window.location.origin}${base}/login`;
183
- return false;
184
- }
185
-
186
- return false;
187
- },
188
- });
189
-
190
162
  export default instance;
package/src/http/oauth.js CHANGED
@@ -1,7 +1,6 @@
1
1
  import axios from "axios";
2
2
  import axiosRetry from "axios-retry";
3
3
  import config from "../config/config.js";
4
- import qs from "qs";
5
4
 
6
5
  const instance = axios.create({
7
6
  baseURL: config().api,
@@ -12,16 +11,6 @@ const instance = axios.create({
12
11
  },
13
12
  });
14
13
 
15
- axiosRetry(instance, { retries: 3 });
16
-
17
- instance.interceptors.response.use(
18
- (response) => {
19
- response.data = qs.parse(response.data);
20
- return response;
21
- },
22
- (error) => {
23
- return Promise.reject(error);
24
- }
25
- );
14
+ axiosRetry(instance, { retries: 2 });
26
15
 
27
16
  export default instance;
package/src/http/user.js CHANGED
@@ -2,7 +2,6 @@ import axios from "axios";
2
2
  import config from "../config/config.js";
3
3
  import http from "./index";
4
4
  import { jwtDecode } from "jwt-decode";
5
- import oauth from "./oauth";
6
5
  import { storage } from "@nucleoidjs/webstorage";
7
6
 
8
7
  const instance = axios.create({
@@ -23,51 +22,9 @@ instance.interceptors.request.use(async (request) => {
23
22
 
24
23
  instance.getUserDetails = async () => {
25
24
  try {
26
- const refreshToken = await storage.get("link", "refreshToken");
25
+ const refreshToken = storage.get("link", "refreshToken");
27
26
 
28
27
  if (!refreshToken) {
29
- console.log("No refresh token found");
30
- return null;
31
- }
32
-
33
- let accessToken = await storage.get("link", "accessToken");
34
-
35
- if (!accessToken) {
36
- console.log("No access token found");
37
- return null;
38
- }
39
-
40
- try {
41
- const decodedToken = jwtDecode(accessToken);
42
- const isExpired = decodedToken.exp * 1000 < Date.now();
43
-
44
- if (isExpired) {
45
- console.log(
46
- "Access token expired, refreshing before fetching user details...",
47
- );
48
- const { appId } = config();
49
- const projectId = storage.get("projectId");
50
- const identityProvider = storage.get("link", "identityProvider");
51
-
52
- const { data } = await oauth.post("/oauth", {
53
- refreshToken,
54
- appId,
55
- projectId,
56
- identityProvider,
57
- ...(identityProvider === "DEMO" && {
58
- username: "admin",
59
- password: "admin",
60
- }),
61
- });
62
-
63
- accessToken = data.accessToken;
64
- storage.set("link", "accessToken", accessToken);
65
- console.log(
66
- "Access token refreshed successfully, now fetching user details",
67
- );
68
- }
69
- } catch (error) {
70
- console.error("Error checking or refreshing token:", error);
71
28
  return null;
72
29
  }
73
30
 
@@ -81,7 +38,6 @@ instance.getUserDetails = async () => {
81
38
  return response.data.user;
82
39
  }
83
40
 
84
- console.log("No user data received from server");
85
41
  return null;
86
42
  } catch (error) {
87
43
  console.error("Error fetching user details from server:", error);
@@ -100,7 +56,7 @@ instance.getPermittedUsers = async () => {
100
56
  ...new Set(
101
57
  response.data
102
58
  .filter((p) => p.appId === appId && p.projectId === projectId)
103
- .map((p) => p.userId),
59
+ .map((p) => p.userId)
104
60
  ),
105
61
  ];
106
62
 
@@ -122,7 +78,7 @@ instance.getPermittedUsers = async () => {
122
78
  }
123
79
  const { data } = await axios.get(
124
80
  `https://api.github.com/user/${userId}`,
125
- { headers: { Accept: "application/vnd.github+json" } },
81
+ { headers: { Accept: "application/vnd.github+json" } }
126
82
  );
127
83
  return {
128
84
  id: String(data.id),
@@ -132,7 +88,7 @@ instance.getPermittedUsers = async () => {
132
88
  avatarUrl: data.avatar_url || null,
133
89
  email: data.email || null,
134
90
  };
135
- }),
91
+ })
136
92
  );
137
93
 
138
94
  return results
package/vite/vite.js CHANGED
@@ -51,7 +51,6 @@ async function vite() {
51
51
  include: [
52
52
  "@mui/material",
53
53
  "@nucleoidai/platform",
54
- "axios-auth-refresh",
55
54
  "@emotion/react",
56
55
  "@emotion/styled",
57
56
  "@emotion/css",
@@ -67,7 +66,7 @@ async function vite() {
67
66
  find: /^src(.+)/,
68
67
  replacement: path.join(
69
68
  process.cwd(),
70
- "/node_modules/@nucleoidai/platform/minimal/src/$1",
69
+ "/node_modules/@nucleoidai/platform/minimal/src/$1"
71
70
  ),
72
71
  },
73
72
  ],