@trainly/react 1.1.2 → 1.1.3

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.
@@ -67,9 +67,67 @@ export function TrainlyProvider(_a) {
67
67
  var _d = React.useState(false), isConnected = _d[0], setIsConnected = _d[1];
68
68
  var _e = React.useState(null), error = _e[0], setError = _e[1];
69
69
  var _f = React.useState([]), messages = _f[0], setMessages = _f[1];
70
- // Auto-connect on mount
70
+ var _g = React.useState(null), currentToken = _g[0], setCurrentToken = _g[1];
71
+ var refreshIntervalRef = React.useRef(null);
72
+ // Auto-connect on mount (only for non-OAuth modes)
71
73
  React.useEffect(function () {
72
- connect();
74
+ if (!appId && !getToken) {
75
+ connect();
76
+ }
77
+ }, []);
78
+ // NEW: Automatic OAuth state management
79
+ React.useEffect(function () {
80
+ if (!getToken || !appId)
81
+ return;
82
+ var manageOAuthConnection = function () { return __awaiter(_this, void 0, void 0, function () {
83
+ var token, error_1;
84
+ return __generator(this, function (_a) {
85
+ switch (_a.label) {
86
+ case 0:
87
+ _a.trys.push([0, 6, , 7]);
88
+ return [4 /*yield*/, getToken()];
89
+ case 1:
90
+ token = _a.sent();
91
+ if (!(token && token !== currentToken)) return [3 /*break*/, 4];
92
+ if (!(!isConnected || token !== currentToken)) return [3 /*break*/, 3];
93
+ console.log("🔐 New OAuth session detected, connecting to Trainly...");
94
+ return [4 /*yield*/, connectWithOAuthToken(token)];
95
+ case 2:
96
+ _a.sent();
97
+ _a.label = 3;
98
+ case 3: return [3 /*break*/, 5];
99
+ case 4:
100
+ if (!token && isConnected) {
101
+ // User signed out, disconnect from Trainly
102
+ console.log("🚪 User signed out, disconnecting from Trainly...");
103
+ clearRefreshInterval();
104
+ setIsConnected(false);
105
+ setCurrentToken(null);
106
+ setError(null);
107
+ }
108
+ _a.label = 5;
109
+ case 5: return [3 /*break*/, 7];
110
+ case 6:
111
+ error_1 = _a.sent();
112
+ console.error("OAuth state management error:", error_1);
113
+ return [3 /*break*/, 7];
114
+ case 7: return [2 /*return*/];
115
+ }
116
+ });
117
+ }); };
118
+ // Check OAuth state immediately
119
+ manageOAuthConnection();
120
+ // Set up periodic OAuth state checking (every 10 seconds)
121
+ var stateCheckInterval = setInterval(manageOAuthConnection, 10000);
122
+ return function () {
123
+ clearInterval(stateCheckInterval);
124
+ };
125
+ }, [getToken, appId, currentToken, isConnected]);
126
+ // Cleanup on unmount
127
+ React.useEffect(function () {
128
+ return function () {
129
+ clearRefreshInterval();
130
+ };
73
131
  }, []);
74
132
  var connect = function () { return __awaiter(_this, void 0, void 0, function () {
75
133
  var err_1;
@@ -100,7 +158,62 @@ export function TrainlyProvider(_a) {
100
158
  }
101
159
  });
102
160
  }); };
103
- // NEW: V1 OAuth Token connection method
161
+ // Clear any existing refresh interval
162
+ var clearRefreshInterval = function () {
163
+ if (refreshIntervalRef.current) {
164
+ clearInterval(refreshIntervalRef.current);
165
+ refreshIntervalRef.current = null;
166
+ }
167
+ };
168
+ // Set up automatic token refresh
169
+ var setupTokenRefresh = function (token) {
170
+ if (!getToken || !appId)
171
+ return;
172
+ // Clear any existing interval
173
+ clearRefreshInterval();
174
+ // Decode token to get expiration (without verification)
175
+ try {
176
+ var payload = JSON.parse(atob(token.split(".")[1]));
177
+ var exp = payload.exp * 1000; // Convert to milliseconds
178
+ var now = Date.now();
179
+ var timeUntilExpiry = exp - now;
180
+ // Refresh 30 seconds before expiry (or immediately if already expired)
181
+ var refreshIn = Math.max(timeUntilExpiry - 30000, 1000);
182
+ console.log("\uD83D\uDD04 Token refresh scheduled in ".concat(Math.round(refreshIn / 1000), " seconds"));
183
+ refreshIntervalRef.current = setTimeout(function () { return __awaiter(_this, void 0, void 0, function () {
184
+ var newToken, error_2;
185
+ return __generator(this, function (_a) {
186
+ switch (_a.label) {
187
+ case 0:
188
+ _a.trys.push([0, 4, , 5]);
189
+ console.log("🔄 Auto-refreshing token...");
190
+ return [4 /*yield*/, getToken()];
191
+ case 1:
192
+ newToken = _a.sent();
193
+ if (!(newToken && newToken !== currentToken)) return [3 /*break*/, 3];
194
+ return [4 /*yield*/, client.connectWithOAuthToken(newToken)];
195
+ case 2:
196
+ _a.sent();
197
+ setCurrentToken(newToken);
198
+ setupTokenRefresh(newToken); // Schedule next refresh
199
+ console.log("✅ Token auto-refreshed successfully");
200
+ _a.label = 3;
201
+ case 3: return [3 /*break*/, 5];
202
+ case 4:
203
+ error_2 = _a.sent();
204
+ console.error("❌ Auto token refresh failed:", error_2);
205
+ setIsConnected(false);
206
+ return [3 /*break*/, 5];
207
+ case 5: return [2 /*return*/];
208
+ }
209
+ });
210
+ }); }, refreshIn);
211
+ }
212
+ catch (error) {
213
+ console.warn("Could not decode token for refresh scheduling:", error);
214
+ }
215
+ };
216
+ // NEW: V1 OAuth Token connection method with auto-refresh
104
217
  var connectWithOAuthToken = function (idToken) { return __awaiter(_this, void 0, void 0, function () {
105
218
  var err_2;
106
219
  return __generator(this, function (_a) {
@@ -112,7 +225,10 @@ export function TrainlyProvider(_a) {
112
225
  return [4 /*yield*/, client.connectWithOAuthToken(idToken)];
113
226
  case 1:
114
227
  _a.sent();
228
+ setCurrentToken(idToken);
115
229
  setIsConnected(true);
230
+ // Set up automatic token refresh
231
+ setupTokenRefresh(idToken);
116
232
  return [3 /*break*/, 4];
117
233
  case 2:
118
234
  err_2 = _a.sent();
@@ -131,7 +247,7 @@ export function TrainlyProvider(_a) {
131
247
  });
132
248
  }); };
133
249
  var ask = function (question) { return __awaiter(_this, void 0, void 0, function () {
134
- var response, err_3, errorMessage, newToken, response, refreshError_1, error_1;
250
+ var response, err_3, errorMessage, newToken, response, refreshError_1, error_3;
135
251
  return __generator(this, function (_a) {
136
252
  switch (_a.label) {
137
253
  case 0:
@@ -172,13 +288,13 @@ export function TrainlyProvider(_a) {
172
288
  console.error("❌ Token refresh failed:", refreshError_1);
173
289
  return [3 /*break*/, 9];
174
290
  case 9:
175
- error_1 = {
291
+ error_3 = {
176
292
  code: "QUERY_FAILED",
177
293
  message: "Failed to get answer",
178
294
  details: err_3,
179
295
  };
180
- setError(error_1);
181
- throw error_1;
296
+ setError(error_3);
297
+ throw error_3;
182
298
  case 10:
183
299
  setIsLoading(false);
184
300
  return [7 /*endfinally*/];
@@ -187,7 +303,7 @@ export function TrainlyProvider(_a) {
187
303
  });
188
304
  }); };
189
305
  var askWithCitations = function (question) { return __awaiter(_this, void 0, void 0, function () {
190
- var response, err_4, error_2;
306
+ var response, err_4, error_4;
191
307
  return __generator(this, function (_a) {
192
308
  switch (_a.label) {
193
309
  case 0:
@@ -203,13 +319,13 @@ export function TrainlyProvider(_a) {
203
319
  }];
204
320
  case 2:
205
321
  err_4 = _a.sent();
206
- error_2 = {
322
+ error_4 = {
207
323
  code: "QUERY_FAILED",
208
324
  message: "Failed to get answer with citations",
209
325
  details: err_4,
210
326
  };
211
- setError(error_2);
212
- throw error_2;
327
+ setError(error_4);
328
+ throw error_4;
213
329
  case 3:
214
330
  setIsLoading(false);
215
331
  return [7 /*endfinally*/];
@@ -218,7 +334,7 @@ export function TrainlyProvider(_a) {
218
334
  });
219
335
  }); };
220
336
  var upload = function (file) { return __awaiter(_this, void 0, void 0, function () {
221
- var result, err_5, errorMessage, newToken, result, refreshError_2, error_3;
337
+ var result, err_5, errorMessage, newToken, result, refreshError_2, error_5;
222
338
  return __generator(this, function (_a) {
223
339
  switch (_a.label) {
224
340
  case 0:
@@ -259,13 +375,13 @@ export function TrainlyProvider(_a) {
259
375
  console.error("❌ Token refresh failed:", refreshError_2);
260
376
  return [3 /*break*/, 9];
261
377
  case 9:
262
- error_3 = {
378
+ error_5 = {
263
379
  code: "UPLOAD_FAILED",
264
380
  message: "Failed to upload file",
265
381
  details: err_5,
266
382
  };
267
- setError(error_3);
268
- throw error_3;
383
+ setError(error_5);
384
+ throw error_5;
269
385
  case 10:
270
386
  setIsLoading(false);
271
387
  return [7 /*endfinally*/];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@trainly/react",
3
- "version": "1.1.2",
3
+ "version": "1.1.3",
4
4
  "description": "Dead simple RAG integration for React apps with OAuth authentication",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",