@gandalan/weblibs 1.1.49 → 1.1.52

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/.eslintrc.cjs CHANGED
@@ -29,20 +29,20 @@ module.exports = {
29
29
  quotes: ["warn", "double"],
30
30
  semi: ["off", "never"],
31
31
  "no-multi-spaces": ["warn", { ignoreEOLComments: true }],
32
- "curly": "warn",
32
+ "curly": "off",
33
33
  "comma-spacing": "warn",
34
- "brace-style": ["warn"],
34
+ "brace-style": ["off"],
35
35
  "no-var": "warn",
36
36
  "key-spacing": "warn",
37
37
  "keyword-spacing": "warn",
38
38
  "space-infix-ops": "warn",
39
39
  "arrow-spacing": "warn",
40
- "no-trailing-spaces": "warn",
40
+ "no-trailing-spaces": "off",
41
41
  "space-before-blocks": "warn",
42
42
  "no-unused-vars": ["warn", {
43
43
  "args": "none",
44
44
  }],
45
- "no-console": "warn",
45
+ "no-console": "off",
46
46
  "no-extra-boolean-cast": "off",
47
47
  "no-multiple-empty-lines": ["warn", { "max": 1, "maxBOF": 0 }],
48
48
  "lines-between-class-members": ["warn", "always", { exceptAfterSingleLine: true }],
@@ -52,6 +52,6 @@ module.exports = {
52
52
  "eol-last": ["warn", "always"],
53
53
  "prefer-template": "warn",
54
54
  "template-curly-spacing": ["warn", "never"],
55
- "comma-dangle": ["warn", "always-multiline"],
56
- },
55
+ "comma-dangle": ["off"],
56
+ }
57
57
  };
package/api/fluentApi.js CHANGED
@@ -2,9 +2,12 @@ import { jwtDecode } from "jwt-decode";
2
2
 
3
3
  const envs = {};
4
4
 
5
+ const JWT_SAFE_RENEWAL = 30; // seconds before token expiry to renew
6
+
5
7
  export async function fetchEnv(env = "") {
6
8
  if (!(env in envs)) {
7
9
  const hubUrl = `https://connect.idas-cloudservices.net/api/Endpoints?env=${env}`;
10
+ console.log("fetching env", hubUrl);
8
11
  const r = await fetch(hubUrl);
9
12
  const data = await r.json();
10
13
  envs[env] = data;
@@ -17,6 +20,20 @@ export function getRefreshToken(token) {
17
20
  return decoded.refreshToken;
18
21
  }
19
22
 
23
+ export function isTokenValid(token)
24
+ {
25
+ try
26
+ {
27
+ const decoded = jwtDecode(token);
28
+ if (!decoded)
29
+ throw new Error("Invalid token");
30
+ return (decoded.exp - JWT_SAFE_RENEWAL > Date.now() / 1000);
31
+ }
32
+ catch {
33
+ return false;
34
+ }
35
+ }
36
+
20
37
  export function authBuilder() {
21
38
  return {
22
39
  authUrl: "",
@@ -27,38 +44,28 @@ export function authBuilder() {
27
44
  useAppToken(appToken = "") {
28
45
  this.appToken = appToken; return this;
29
46
  },
47
+
30
48
  useBaseUrl(authUrl = "") {
31
49
  this.authUrl = authUrl; return this;
32
50
  },
51
+
33
52
  useToken(jwtToken = "") {
34
53
  this.token = jwtToken; return this;
35
54
  },
55
+
36
56
  useRefreshToken(storedRefreshToken = "") {
37
57
  this.refreshToken = storedRefreshToken; return this;
38
58
  },
39
59
 
40
- async authenticate(username = "", password = "") {
60
+ async authenticate(username = "", password = "")
61
+ {
41
62
  console.log("authenticating:", this.token ? `token set, exp: ${jwtDecode(this.token).exp - (Date.now() / 1000)}` : "no token,", this.refreshToken);
42
63
 
43
- if (this.token) {
44
- try {
45
- const decoded = jwtDecode(this.token);
46
- if (!decoded) {
47
- throw new Error("Invalid token");
48
- }
49
-
50
- if (decoded.exp - 60 > Date.now() / 1000) {
51
- return this.token;
52
- }
64
+ if (this.token && isTokenValid(this.token))
65
+ return this.token;
53
66
 
54
- if (decoded.refreshToken && !this.refreshToken) {
55
- this.refreshToken = decoded.refreshToken;
56
- }
57
- } catch (e) {
58
- console.error("Error decoding token", e);
59
- return null;
60
- }
61
- }
67
+ if (this.token && !this.refreshToken)
68
+ this.refreshToken = getRefreshToken(this.token);
62
69
 
63
70
  if (this.refreshToken) {
64
71
  try {
@@ -72,7 +79,6 @@ export function authBuilder() {
72
79
  // - should still be valid for a while
73
80
  }
74
81
  return this.token;
75
-
76
82
  }
77
83
 
78
84
  if (username && password) {
@@ -90,7 +96,7 @@ export function authBuilder() {
90
96
  },
91
97
 
92
98
  async tryRefreshToken(refreshToken = "") {
93
- const payload = { "Token": refreshToken };
99
+ const payload = { "Token": refreshToken };
94
100
  const res = await fetch(`${this.authUrl}/LoginJwt/Refresh`,
95
101
  {
96
102
  method: "PUT",
@@ -102,6 +108,58 @@ export function authBuilder() {
102
108
  }
103
109
  }
104
110
 
111
+ export function restClient()
112
+ {
113
+ return {
114
+ baseUrl: "",
115
+ token: "",
116
+
117
+ useBaseUrl(url = "") {
118
+ this.baseUrl = url; return this;
119
+ },
120
+
121
+ useToken(jwtToken = "") {
122
+ this.token = jwtToken; return this;
123
+ },
124
+
125
+ async get(url = "", auth = true) {
126
+ const finalUrl = `${this.baseUrl}/${url}`;
127
+ const headers = this.token ? { "Authorization": `Bearer ${this.token}` } : {};
128
+ const res = await fetch(finalUrl, { method: "GET", headers });
129
+ if (res.ok)
130
+ return await res.json();
131
+ throw new Error(`GET ${finalUrl} failed: ${res.status} ${res.statusText}`);
132
+ },
133
+
134
+ async put(url = "", payload = {}) {
135
+ const finalUrl = `${this.baseUrl}/${url}`;
136
+ const headers = this.token ? { "Authorization": `Bearer ${this.token}`, "Content-Type": "application/json" } : {};
137
+ const res = await fetch(finalUrl, { method: "PUT", body: JSON.stringify(payload), headers });
138
+ if (res.ok)
139
+ return await res.json();
140
+ throw new Error(`PUT ${finalUrl} failed: ${res.status} ${res.statusText}`);
141
+ },
142
+
143
+ async post(url = "", payload = {}) {
144
+ const finalUrl = `${this.baseUrl}/${url}`;
145
+ const headers = this.token ? { "Authorization": `Bearer ${this.token}`, "Content-Type": "application/json" } : {};
146
+ const res = await fetch(finalUrl, { method: "POST", body: JSON.stringify(payload), headers });
147
+ if (res.ok)
148
+ return await res.json();
149
+ throw new Error(`POST ${finalUrl} failed: ${res.status} ${res.statusText}`);
150
+ },
151
+
152
+ async delete(url = "") {
153
+ const finalUrl = `${this.baseUrl}/${url}`;
154
+ const headers = this.token ? { "Authorization": `Bearer ${this.token}` } : {};
155
+ const res = await fetch(finalUrl, { method: "DELETE", headers });
156
+ if (res.ok)
157
+ return await res.json();
158
+ throw new Error(`DELETE ${finalUrl} failed: ${res.status} ${res.statusText}`);
159
+ }
160
+ }
161
+ }
162
+
105
163
  export function api() {
106
164
  return {
107
165
  baseUrl: "",
@@ -115,74 +173,68 @@ export function api() {
115
173
  useEnvironment(env = "") {
116
174
  this.env = env; return this;
117
175
  },
176
+
118
177
  useAppToken(newApptoken = "") {
119
178
  this.appToken = newApptoken; return this;
120
179
  },
180
+
121
181
  useBaseUrl(url = "") {
122
182
  this.baseUrl = url; return this;
123
183
  },
184
+
124
185
  useAuthUrl(url = "") {
125
186
  this.authUrl = url; return this;
126
187
  },
188
+
127
189
  useToken(jwtToken = "") {
128
190
  this.token = jwtToken; return this;
129
191
  },
192
+
130
193
  useRefreshToken(storedRefreshToken = "") {
131
194
  this.refreshToken = storedRefreshToken; return this;
132
195
  },
196
+
133
197
  useGlobalAuth() {
134
198
  // eslint-disable-next-line no-undef
135
- this.token = globalThis.idas.token; this.refreshToken = globalThis.idas.refreshToken; return this;
199
+ this.token = globalThis.idasTokens.token; this.refreshToken = globalThis.idasTokens.refreshToken; return this;
136
200
  },
137
201
 
138
- async get(url = "") {
139
- console.log("get", url);
140
- await this.ensureAuthenticated();
141
- const headers = this.token ? { "Authorization": `Bearer ${this.token}` } : {};
142
- const res = await fetch(`${this.baseUrl}/${url}`, { method: "GET", headers });
143
- return await res.json();
202
+ async get(url = "", auth = true) {
203
+ if (auth)
204
+ await this.ensureAuthenticated();
205
+ return restClient().useBaseUrl(this.baseUrl).useToken(this.token).get(url);
144
206
  },
145
207
 
146
- async put(url = "", payload = {}) {
147
- console.log("put", url, payload);
148
- await this.ensureAuthenticated();
149
-
150
- const headers = this.token ? { "Authorization": `Bearer ${this.token}`, "Content-Type": "application/json" } : {};
151
- const res = await fetch(`${this.baseUrl}/${url}`,
152
- { method: "PUT", body: JSON.stringify(payload), headers });
153
- return await res.json();
208
+ async put(url = "", payload = {}, auth = true) {
209
+ if (auth)
210
+ await this.ensureAuthenticated();
211
+ return restClient().useBaseUrl(this.baseUrl).useToken(this.token).put(url, payload);
154
212
  },
155
213
 
156
- async post(url = "", payload = {}) {
157
- console.log("post", url, payload);
158
- await this.ensureAuthenticated();
159
-
160
- const headers = this.token ? { "Authorization": `Bearer ${this.token}`, "Content-Type": "application/json" } : {};
161
- const res = await fetch(`${this.baseUrl}/${url}`,
162
- { method: "POST", body: JSON.stringify(payload), headers });
163
- return await res.json();
214
+ async post(url = "", payload = {}, auth = true) {
215
+ if (auth)
216
+ await this.ensureAuthenticated();
217
+ return restClient().useBaseUrl(this.baseUrl).useToken(this.token).post(url, payload);
164
218
  },
165
219
 
166
- async delete(url = "") {
167
- console.log("delete", url);
168
- await this.ensureAuthenticated();
169
-
170
- const headers = this.token ? { "Authorization": `Bearer ${this.token}` } : {};
171
- const res = await fetch(`${this.baseUrl}/${url}`, { method: "DELETE", headers });
172
- return await res.json();
220
+ async delete(url = "", auth = true) {
221
+ if (auth)
222
+ await this.ensureAuthenticated();
223
+ return restClient().useBaseUrl(this.baseUrl).useToken(this.token).delete(url);
173
224
  },
174
225
 
175
226
  async ensureAuthenticated() {
176
- await this.ensureBaseUrlIsSet();
177
- if (!this.token && !this.refreshToken) {
227
+ if (this.token && isTokenValid(this.token))
178
228
  return;
179
- }
229
+
230
+ await this.ensureBaseUrlIsSet();
231
+
180
232
  try {
181
233
  const temptoken = await authBuilder()
182
- .useToken(this.token)
183
- .useRefreshToken(this.refreshToken)
184
234
  .useAppToken(this.appToken)
185
235
  .useBaseUrl(this.authUrl)
236
+ .useToken(this.token)
237
+ .useRefreshToken(this.refreshToken)
186
238
  .authenticate() || "";
187
239
 
188
240
  if (!temptoken) {
@@ -202,15 +254,20 @@ export function api() {
202
254
  },
203
255
 
204
256
  async ensureBaseUrlIsSet() {
205
- if (this.env && !this.baseUrl) {
257
+ if (this.env && (!this.baseUrl || !this.authUrl)) {
206
258
  const envInfo = await fetchEnv(this.env);
207
- this.baseUrl = envInfo.idas;
208
- this.authUrl = envInfo.idas;
259
+ this.baseUrl = this.baseUrl || envInfo.idas;
260
+ this.authUrl = this.authUrl || envInfo.idas;
261
+ console.log("envInfo", envInfo);
209
262
  }
210
263
 
211
264
  if (!this.baseUrl) {
212
265
  throw new Error("apiBaseurl not set");
213
266
  }
267
+
268
+ if (!this.authUrl) {
269
+ throw new Error("authUrl not set");
270
+ }
214
271
  },
215
272
 
216
273
  redirectToLogin(authPath = "") {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gandalan/weblibs",
3
- "version": "1.1.49",
3
+ "version": "1.1.52",
4
4
  "description": "WebLibs for Gandalan JS/TS/Svelte projects",
5
5
  "keywords": [
6
6
  "gandalan"