@karpeleslab/klbfw 0.2.9 → 0.2.11

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/fw-wrapper.js CHANGED
@@ -111,6 +111,24 @@ const setContext = (key, value) => {
111
111
  */
112
112
  const getToken = () => getFWProperty('token', undefined);
113
113
 
114
+ /**
115
+ * Gets the current token expiration time
116
+ * @returns {number|undefined} Token expiration time in milliseconds
117
+ */
118
+ const getTokenExp = () => getFWProperty('token_exp', undefined);
119
+
120
+ /**
121
+ * Sets the authentication token and its expiration time
122
+ * @param {string} token - New token value
123
+ * @param {number|undefined} tokenExp - Token expiration time in milliseconds
124
+ */
125
+ const setToken = (token, tokenExp) => {
126
+ if (typeof FW !== 'undefined') {
127
+ FW.token = token;
128
+ FW.token_exp = tokenExp;
129
+ }
130
+ };
131
+
114
132
  /**
115
133
  * Gets the registry
116
134
  * @returns {Object|undefined} Registry object
@@ -251,6 +269,8 @@ module.exports.getCurrency = getCurrency;
251
269
  module.exports.getContext = getContext;
252
270
  module.exports.setContext = setContext;
253
271
  module.exports.getToken = getToken;
272
+ module.exports.getTokenExp = getTokenExp;
273
+ module.exports.setToken = setToken;
254
274
  module.exports.getRegistry = getRegistry;
255
275
  module.exports.getUrl = getUrl;
256
276
  module.exports.getSiteStatic = getSiteStatic;
package/internal.js CHANGED
@@ -104,7 +104,7 @@ const buildRestUrl = (path, withToken, context) => {
104
104
  */
105
105
  const checkSupport = () => {
106
106
  const missingFeatures = [];
107
-
107
+
108
108
  if (typeof fetch === "undefined") {
109
109
  missingFeatures.push("fetch API");
110
110
  }
@@ -112,15 +112,79 @@ const checkSupport = () => {
112
112
  if (!fwWrapper.supported()) {
113
113
  missingFeatures.push("Framework wrapper");
114
114
  }
115
-
115
+
116
116
  if (missingFeatures.length > 0) {
117
117
  console.error("Missing required features: " + missingFeatures.join(", "));
118
118
  return false;
119
119
  }
120
-
120
+
121
121
  return true;
122
122
  };
123
123
 
124
+ /**
125
+ * Checks if token needs refresh and refreshes if necessary
126
+ * @returns {Promise<void>} Resolves when check/refresh is complete
127
+ */
128
+ const checkAndRefreshToken = () => {
129
+ const tokenExp = fwWrapper.getTokenExp();
130
+
131
+ // If token_exp is not defined, no refresh needed
132
+ if (tokenExp === undefined) {
133
+ return Promise.resolve();
134
+ }
135
+
136
+ const now = Date.now();
137
+ const fiveMinutes = 5 * 60 * 1000; // 5 minutes in milliseconds
138
+
139
+ // Check if token expires within 5 minutes
140
+ if (tokenExp - now <= fiveMinutes) {
141
+ // Need to refresh token
142
+ const callUrl = buildRestUrl('_special/token.json', true);
143
+ const headers = {};
144
+
145
+ if (fwWrapper.getToken() !== '') {
146
+ headers['Authorization'] = 'Session ' + fwWrapper.getToken();
147
+ }
148
+
149
+ return fetch(callUrl, {
150
+ method: 'GET',
151
+ credentials: 'include',
152
+ headers: headers
153
+ })
154
+ .then(response => {
155
+ if (!response.ok) {
156
+ // API returned an error, give up by setting token_exp to undefined
157
+ fwWrapper.setToken(fwWrapper.getToken(), undefined);
158
+ return;
159
+ }
160
+
161
+ const contentType = response.headers.get('content-type');
162
+ if (!contentType || contentType.indexOf('application/json') === -1) {
163
+ // Not JSON response, give up
164
+ fwWrapper.setToken(fwWrapper.getToken(), undefined);
165
+ return;
166
+ }
167
+
168
+ return response.json();
169
+ })
170
+ .then(json => {
171
+ if (json && json.token && json.token_exp) {
172
+ // Update token and token_exp
173
+ fwWrapper.setToken(json.token, json.token_exp);
174
+ } else {
175
+ // Invalid response, give up
176
+ fwWrapper.setToken(fwWrapper.getToken(), undefined);
177
+ }
178
+ })
179
+ .catch(() => {
180
+ // Error occurred, give up by setting token_exp to undefined
181
+ fwWrapper.setToken(fwWrapper.getToken(), undefined);
182
+ });
183
+ }
184
+
185
+ return Promise.resolve();
186
+ };
187
+
124
188
  /**
125
189
  * Makes an internal REST API call
126
190
  * @param {string} name - API endpoint name
@@ -137,58 +201,61 @@ const internalRest = (name, verb, params, context) => {
137
201
  if (typeof window !== "undefined") {
138
202
  context['t'] = getTimezoneData();
139
203
  }
140
-
141
- const callUrl = buildRestUrl(name, true, context);
142
- const headers = {};
143
-
144
- if (fwWrapper.getToken() !== '') {
145
- headers['Authorization'] = 'Session ' + fwWrapper.getToken();
146
- }
147
204
 
148
- // Handle GET requests
149
- if (verb === "GET") {
150
- if (params) {
151
- // Check if params is a JSON string, or if it needs encoding
152
- if (typeof params === "string") {
153
- return fetch(callUrl + "&_=" + encodeURIComponent(params), {
154
- method: verb,
155
- credentials: 'include',
156
- headers: headers
157
- });
158
- } else {
159
- return fetch(callUrl + "&_=" + encodeURIComponent(JSON.stringify(params)), {
160
- method: verb,
161
- credentials: 'include',
162
- headers: headers
163
- });
205
+ // Check and refresh token if needed before making the request
206
+ return checkAndRefreshToken().then(() => {
207
+ const callUrl = buildRestUrl(name, true, context);
208
+ const headers = {};
209
+
210
+ if (fwWrapper.getToken() !== '') {
211
+ headers['Authorization'] = 'Session ' + fwWrapper.getToken();
212
+ }
213
+
214
+ // Handle GET requests
215
+ if (verb === "GET") {
216
+ if (params) {
217
+ // Check if params is a JSON string, or if it needs encoding
218
+ if (typeof params === "string") {
219
+ return fetch(callUrl + "&_=" + encodeURIComponent(params), {
220
+ method: verb,
221
+ credentials: 'include',
222
+ headers: headers
223
+ });
224
+ } else {
225
+ return fetch(callUrl + "&_=" + encodeURIComponent(JSON.stringify(params)), {
226
+ method: verb,
227
+ credentials: 'include',
228
+ headers: headers
229
+ });
230
+ }
164
231
  }
232
+
233
+ return fetch(callUrl, {
234
+ method: verb,
235
+ credentials: 'include',
236
+ headers: headers
237
+ });
165
238
  }
166
-
167
- return fetch(callUrl, {
168
- method: verb,
169
- credentials: 'include',
170
- headers: headers
171
- });
172
- }
173
239
 
174
- // Handle FormData
175
- if (typeof FormData !== "undefined" && (params instanceof FormData)) {
240
+ // Handle FormData
241
+ if (typeof FormData !== "undefined" && (params instanceof FormData)) {
242
+ return fetch(callUrl, {
243
+ method: verb,
244
+ credentials: 'include',
245
+ body: params,
246
+ headers: headers
247
+ });
248
+ }
249
+
250
+ // Handle JSON requests
251
+ headers['Content-Type'] = 'application/json; charset=utf-8';
252
+
176
253
  return fetch(callUrl, {
177
254
  method: verb,
178
255
  credentials: 'include',
179
- body: params,
256
+ body: JSON.stringify(params),
180
257
  headers: headers
181
258
  });
182
- }
183
-
184
- // Handle JSON requests
185
- headers['Content-Type'] = 'application/json; charset=utf-8';
186
-
187
- return fetch(callUrl, {
188
- method: verb,
189
- credentials: 'include',
190
- body: JSON.stringify(params),
191
- headers: headers
192
259
  });
193
260
  };
194
261
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@karpeleslab/klbfw",
3
- "version": "0.2.9",
3
+ "version": "0.2.11",
4
4
  "description": "Frontend Framework",
5
5
  "main": "index.js",
6
6
  "types": "index.d.ts",
package/upload.js CHANGED
@@ -694,7 +694,7 @@ module.exports.upload = (function () {
694
694
  up.done = completedParts;
695
695
 
696
696
  // Check if all parts are complete
697
- if (pendingParts === 0) {
697
+ if (pendingParts === 0 && completedParts === up.blocks) {
698
698
  // All parts complete, finalize the upload
699
699
  up.status = "validating";
700
700