integrate-sdk 0.3.7 → 0.3.9

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.
Files changed (46) hide show
  1. package/dist/index.js +207 -11
  2. package/dist/server.js +182 -11
  3. package/dist/src/adapters/nextjs-oauth-redirect.d.ts +34 -0
  4. package/dist/src/adapters/nextjs-oauth-redirect.d.ts.map +1 -0
  5. package/dist/src/client.d.ts +43 -5
  6. package/dist/src/client.d.ts.map +1 -1
  7. package/dist/src/config/types.d.ts +15 -0
  8. package/dist/src/config/types.d.ts.map +1 -1
  9. package/dist/src/index.d.ts +3 -1
  10. package/dist/src/index.d.ts.map +1 -1
  11. package/dist/src/oauth/manager.d.ts +4 -0
  12. package/dist/src/oauth/manager.d.ts.map +1 -1
  13. package/dist/src/oauth/types.d.ts +30 -6
  14. package/dist/src/oauth/types.d.ts.map +1 -1
  15. package/dist/src/oauth/window-manager.d.ts +1 -1
  16. package/dist/src/oauth/window-manager.d.ts.map +1 -1
  17. package/package.json +3 -15
  18. package/dist/src/adapters/nextjs-callback.d.ts +0 -44
  19. package/dist/src/adapters/nextjs-callback.d.ts.map +0 -1
  20. package/src/adapters/auto-routes.ts +0 -217
  21. package/src/adapters/base-handler.ts +0 -212
  22. package/src/adapters/nextjs-callback.tsx +0 -160
  23. package/src/adapters/nextjs.ts +0 -318
  24. package/src/adapters/tanstack-start.ts +0 -264
  25. package/src/client.ts +0 -952
  26. package/src/config/types.ts +0 -180
  27. package/src/errors.ts +0 -207
  28. package/src/index.ts +0 -110
  29. package/src/integrations/vercel-ai.ts +0 -104
  30. package/src/oauth/manager.ts +0 -307
  31. package/src/oauth/pkce.ts +0 -127
  32. package/src/oauth/types.ts +0 -101
  33. package/src/oauth/window-manager.ts +0 -322
  34. package/src/plugins/generic.ts +0 -119
  35. package/src/plugins/github-client.ts +0 -345
  36. package/src/plugins/github.ts +0 -122
  37. package/src/plugins/gmail-client.ts +0 -114
  38. package/src/plugins/gmail.ts +0 -108
  39. package/src/plugins/server-client.ts +0 -20
  40. package/src/plugins/types.ts +0 -89
  41. package/src/protocol/jsonrpc.ts +0 -88
  42. package/src/protocol/messages.ts +0 -145
  43. package/src/server.ts +0 -117
  44. package/src/transport/http-session.ts +0 -322
  45. package/src/transport/http-stream.ts +0 -331
  46. package/src/utils/naming.ts +0 -52
package/dist/index.js CHANGED
@@ -591,6 +591,7 @@ function base64UrlEncode(array) {
591
591
  }
592
592
 
593
593
  // src/oauth/window-manager.ts
594
+ "use client";
594
595
  function isBrowser() {
595
596
  return typeof window !== "undefined" && typeof window.document !== "undefined";
596
597
  }
@@ -699,6 +700,21 @@ class OAuthWindowManager {
699
700
  let state = params.get("state");
700
701
  let error = params.get("error");
701
702
  let errorDescription = params.get("error_description");
703
+ if (!code && !error && window.location.hash) {
704
+ try {
705
+ const hash = window.location.hash.substring(1);
706
+ const hashParams = new URLSearchParams(hash);
707
+ const oauthCallback = hashParams.get("oauth_callback");
708
+ if (oauthCallback) {
709
+ const parsed = JSON.parse(decodeURIComponent(oauthCallback));
710
+ code = parsed.code;
711
+ state = parsed.state;
712
+ window.history.replaceState(null, "", window.location.pathname + window.location.search);
713
+ }
714
+ } catch (e) {
715
+ console.error("Failed to parse OAuth callback params from hash:", e);
716
+ }
717
+ }
702
718
  if (!code && !error) {
703
719
  try {
704
720
  const stored = sessionStorage.getItem("oauth_callback_params");
@@ -761,6 +777,8 @@ function sendCallbackToOpener(params) {
761
777
  }
762
778
 
763
779
  // src/oauth/manager.ts
780
+ "use client";
781
+
764
782
  class OAuthManager {
765
783
  pendingAuths = new Map;
766
784
  sessionToken;
@@ -824,6 +842,7 @@ class OAuthManager {
824
842
  try {
825
843
  const response = await this.exchangeCodeForToken(pendingAuth.provider, code, pendingAuth.codeVerifier, state);
826
844
  this.sessionToken = response.sessionToken;
845
+ this.saveSessionToken(response.sessionToken);
827
846
  this.pendingAuths.delete(state);
828
847
  return response.sessionToken;
829
848
  } catch (error) {
@@ -867,9 +886,26 @@ class OAuthManager {
867
886
  }
868
887
  setSessionToken(token) {
869
888
  this.sessionToken = token;
889
+ this.saveSessionToken(token);
870
890
  }
871
891
  clearSessionToken() {
872
892
  this.sessionToken = undefined;
893
+ if (typeof window !== "undefined" && window.sessionStorage) {
894
+ try {
895
+ window.sessionStorage.removeItem("integrate_session_token");
896
+ } catch (error) {
897
+ console.error("Failed to clear session token from sessionStorage:", error);
898
+ }
899
+ }
900
+ }
901
+ saveSessionToken(token) {
902
+ if (typeof window !== "undefined" && window.sessionStorage) {
903
+ try {
904
+ window.sessionStorage.setItem("integrate_session_token", token);
905
+ } catch (error) {
906
+ console.error("Failed to save session token to sessionStorage:", error);
907
+ }
908
+ }
873
909
  }
874
910
  async getAuthorizationUrl(provider, scopes, state, codeChallenge, redirectUri) {
875
911
  const url = `${this.oauthApiBase}/authorize`;
@@ -921,6 +957,42 @@ class OAuthManager {
921
957
  }
922
958
 
923
959
  // src/client.ts
960
+ "use client";
961
+
962
+ class SimpleEventEmitter {
963
+ handlers = new Map;
964
+ on(event, handler) {
965
+ if (!this.handlers.has(event)) {
966
+ this.handlers.set(event, new Set);
967
+ }
968
+ this.handlers.get(event).add(handler);
969
+ }
970
+ off(event, handler) {
971
+ const handlers = this.handlers.get(event);
972
+ if (handlers) {
973
+ handlers.delete(handler);
974
+ }
975
+ }
976
+ emit(event, payload) {
977
+ const handlers = this.handlers.get(event);
978
+ if (handlers) {
979
+ handlers.forEach((handler) => {
980
+ try {
981
+ handler(payload);
982
+ } catch (error) {
983
+ console.error(`Error in event handler for ${event}:`, error);
984
+ }
985
+ });
986
+ }
987
+ }
988
+ removeAllListeners(event) {
989
+ if (event) {
990
+ this.handlers.delete(event);
991
+ } else {
992
+ this.handlers.clear();
993
+ }
994
+ }
995
+ }
924
996
  var MCP_SERVER_URL = "https://mcp.integrate.dev/api/v1/mcp";
925
997
  var clientCache = new Map;
926
998
  var cleanupClients = new Set;
@@ -939,6 +1011,7 @@ class MCPClient {
939
1011
  connectionMode;
940
1012
  connecting = null;
941
1013
  oauthManager;
1014
+ eventEmitter = new SimpleEventEmitter;
942
1015
  github;
943
1016
  gmail;
944
1017
  server;
@@ -957,9 +1030,16 @@ class MCPClient {
957
1030
  this.maxReauthRetries = config.maxReauthRetries ?? 1;
958
1031
  this.connectionMode = config.connectionMode ?? "lazy";
959
1032
  this.oauthManager = new OAuthManager(config.oauthApiBase || "/api/integrate/oauth", config.oauthFlow);
960
- if (config.sessionToken) {
961
- this.oauthManager.setSessionToken(config.sessionToken);
962
- this.transport.setHeader("X-Session-Token", config.sessionToken);
1033
+ let sessionToken = config.sessionToken;
1034
+ if (!sessionToken) {
1035
+ const storedToken = this.loadSessionToken();
1036
+ if (storedToken) {
1037
+ sessionToken = storedToken;
1038
+ }
1039
+ }
1040
+ if (sessionToken) {
1041
+ this.oauthManager.setSessionToken(sessionToken);
1042
+ this.transport.setHeader("X-Session-Token", sessionToken);
963
1043
  }
964
1044
  for (const plugin of this.plugins) {
965
1045
  for (const toolName of plugin.tools) {
@@ -1175,6 +1255,42 @@ class MCPClient {
1175
1255
  onMessage(handler) {
1176
1256
  return this.transport.onMessage(handler);
1177
1257
  }
1258
+ on(event, handler) {
1259
+ this.eventEmitter.on(event, handler);
1260
+ }
1261
+ off(event, handler) {
1262
+ this.eventEmitter.off(event, handler);
1263
+ }
1264
+ saveSessionToken(token) {
1265
+ if (typeof window !== "undefined" && window.sessionStorage) {
1266
+ try {
1267
+ window.sessionStorage.setItem("integrate_session_token", token);
1268
+ } catch (error) {
1269
+ console.error("Failed to save session token to sessionStorage:", error);
1270
+ }
1271
+ }
1272
+ }
1273
+ loadSessionToken() {
1274
+ if (typeof window !== "undefined" && window.sessionStorage) {
1275
+ try {
1276
+ return window.sessionStorage.getItem("integrate_session_token") || undefined;
1277
+ } catch (error) {
1278
+ console.error("Failed to load session token from sessionStorage:", error);
1279
+ return;
1280
+ }
1281
+ }
1282
+ return;
1283
+ }
1284
+ clearSessionToken() {
1285
+ if (typeof window !== "undefined" && window.sessionStorage) {
1286
+ try {
1287
+ window.sessionStorage.removeItem("integrate_session_token");
1288
+ } catch (error) {
1289
+ console.error("Failed to clear session token from sessionStorage:", error);
1290
+ }
1291
+ }
1292
+ this.oauthManager.clearSessionToken();
1293
+ }
1178
1294
  async disconnect() {
1179
1295
  for (const plugin of this.plugins) {
1180
1296
  if (plugin.onDisconnect) {
@@ -1218,18 +1334,44 @@ class MCPClient {
1218
1334
  async authorize(provider) {
1219
1335
  const plugin = this.plugins.find((p) => p.oauth?.provider === provider);
1220
1336
  if (!plugin?.oauth) {
1221
- throw new Error(`No OAuth configuration found for provider: ${provider}`);
1337
+ const error = new Error(`No OAuth configuration found for provider: ${provider}`);
1338
+ this.eventEmitter.emit("auth:error", { provider, error });
1339
+ throw error;
1340
+ }
1341
+ this.eventEmitter.emit("auth:started", { provider });
1342
+ try {
1343
+ await this.oauthManager.initiateFlow(provider, plugin.oauth);
1344
+ const sessionToken = this.oauthManager.getSessionToken();
1345
+ if (sessionToken) {
1346
+ this.saveSessionToken(sessionToken);
1347
+ this.eventEmitter.emit("auth:complete", { provider, sessionToken });
1348
+ }
1349
+ this.authState.set(provider, { authenticated: true });
1350
+ } catch (error) {
1351
+ this.eventEmitter.emit("auth:error", { provider, error });
1352
+ throw error;
1222
1353
  }
1223
- await this.oauthManager.initiateFlow(provider, plugin.oauth);
1224
- this.authState.set(provider, { authenticated: true });
1225
1354
  }
1226
1355
  async handleOAuthCallback(params) {
1227
- const sessionToken = await this.oauthManager.handleCallback(params.code, params.state);
1228
- this.transport.setHeader("X-Session-Token", sessionToken);
1229
- for (const plugin of this.plugins) {
1230
- if (plugin.oauth) {
1231
- this.authState.set(plugin.oauth.provider, { authenticated: true });
1356
+ try {
1357
+ const sessionToken = await this.oauthManager.handleCallback(params.code, params.state);
1358
+ this.saveSessionToken(sessionToken);
1359
+ this.transport.setHeader("X-Session-Token", sessionToken);
1360
+ for (const plugin of this.plugins) {
1361
+ if (plugin.oauth) {
1362
+ this.authState.set(plugin.oauth.provider, { authenticated: true });
1363
+ this.eventEmitter.emit("auth:complete", {
1364
+ provider: plugin.oauth.provider,
1365
+ sessionToken
1366
+ });
1367
+ }
1232
1368
  }
1369
+ } catch (error) {
1370
+ this.eventEmitter.emit("auth:error", {
1371
+ provider: "unknown",
1372
+ error
1373
+ });
1374
+ throw error;
1233
1375
  }
1234
1376
  }
1235
1377
  getSessionToken() {
@@ -1324,6 +1466,9 @@ function createMCPClient(config) {
1324
1466
  console.error("Failed to connect client:", error);
1325
1467
  });
1326
1468
  }
1469
+ if (config.autoHandleOAuthCallback !== false) {
1470
+ processOAuthCallbackFromHash(client);
1471
+ }
1327
1472
  return client;
1328
1473
  } else {
1329
1474
  const client = new MCPClient(config);
@@ -1336,9 +1481,35 @@ function createMCPClient(config) {
1336
1481
  console.error("Failed to connect client:", error);
1337
1482
  });
1338
1483
  }
1484
+ if (config.autoHandleOAuthCallback !== false) {
1485
+ processOAuthCallbackFromHash(client);
1486
+ }
1339
1487
  return client;
1340
1488
  }
1341
1489
  }
1490
+ function processOAuthCallbackFromHash(client) {
1491
+ if (typeof window === "undefined") {
1492
+ return;
1493
+ }
1494
+ try {
1495
+ const hash = window.location.hash;
1496
+ if (hash && hash.includes("oauth_callback=")) {
1497
+ const hashParams = new URLSearchParams(hash.substring(1));
1498
+ const oauthCallbackData = hashParams.get("oauth_callback");
1499
+ if (oauthCallbackData) {
1500
+ const callbackParams = JSON.parse(decodeURIComponent(oauthCallbackData));
1501
+ if (callbackParams.code && callbackParams.state) {
1502
+ client.handleOAuthCallback(callbackParams).catch((error) => {
1503
+ console.error("Failed to process OAuth callback:", error);
1504
+ });
1505
+ window.history.replaceState(null, "", window.location.pathname + window.location.search);
1506
+ }
1507
+ }
1508
+ }
1509
+ } catch (error) {
1510
+ console.error("Failed to process OAuth callback from hash:", error);
1511
+ }
1512
+ }
1342
1513
  async function clearClientCache() {
1343
1514
  const clients = Array.from(clientCache.values());
1344
1515
  clientCache.clear();
@@ -1356,6 +1527,30 @@ async function clearClientCache() {
1356
1527
  // src/index.ts
1357
1528
  init_nextjs();
1358
1529
 
1530
+ // src/adapters/nextjs-oauth-redirect.ts
1531
+ function createOAuthRedirectHandler(config) {
1532
+ const redirectUrl = config?.redirectUrl || "/";
1533
+ const errorRedirectUrl = config?.errorRedirectUrl || "/auth-error";
1534
+ return async function GET(req) {
1535
+ const { searchParams } = new URL(req.url);
1536
+ const code = searchParams.get("code");
1537
+ const state = searchParams.get("state");
1538
+ const error = searchParams.get("error");
1539
+ const errorDescription = searchParams.get("error_description");
1540
+ if (error) {
1541
+ const errorMsg = errorDescription || error;
1542
+ console.error("[OAuth Redirect] Error:", errorMsg);
1543
+ return Response.redirect(new URL(`${errorRedirectUrl}?error=${encodeURIComponent(errorMsg)}`, req.url));
1544
+ }
1545
+ if (!code || !state) {
1546
+ console.error("[OAuth Redirect] Missing code or state parameter");
1547
+ return Response.redirect(new URL(`${errorRedirectUrl}?error=${encodeURIComponent("Invalid OAuth callback")}`, req.url));
1548
+ }
1549
+ const targetUrl = new URL(redirectUrl, req.url);
1550
+ targetUrl.hash = `oauth_callback=${encodeURIComponent(JSON.stringify({ code, state }))}`;
1551
+ return Response.redirect(targetUrl);
1552
+ };
1553
+ }
1359
1554
  // src/adapters/tanstack-start.ts
1360
1555
  function createTanStackOAuthHandler(config) {
1361
1556
  const handler = new OAuthHandler(config);
@@ -1590,6 +1785,7 @@ export {
1590
1785
  generateCodeChallenge,
1591
1786
  createTanStackOAuthHandler,
1592
1787
  createSimplePlugin,
1788
+ createOAuthRedirectHandler,
1593
1789
  createNextOAuthHandler,
1594
1790
  createMCPClient,
1595
1791
  convertMCPToolsToVercelAI,
package/dist/server.js CHANGED
@@ -591,6 +591,7 @@ function base64UrlEncode(array) {
591
591
  }
592
592
 
593
593
  // src/oauth/window-manager.ts
594
+ "use client";
594
595
  function isBrowser() {
595
596
  return typeof window !== "undefined" && typeof window.document !== "undefined";
596
597
  }
@@ -699,6 +700,21 @@ class OAuthWindowManager {
699
700
  let state = params.get("state");
700
701
  let error = params.get("error");
701
702
  let errorDescription = params.get("error_description");
703
+ if (!code && !error && window.location.hash) {
704
+ try {
705
+ const hash = window.location.hash.substring(1);
706
+ const hashParams = new URLSearchParams(hash);
707
+ const oauthCallback = hashParams.get("oauth_callback");
708
+ if (oauthCallback) {
709
+ const parsed = JSON.parse(decodeURIComponent(oauthCallback));
710
+ code = parsed.code;
711
+ state = parsed.state;
712
+ window.history.replaceState(null, "", window.location.pathname + window.location.search);
713
+ }
714
+ } catch (e) {
715
+ console.error("Failed to parse OAuth callback params from hash:", e);
716
+ }
717
+ }
702
718
  if (!code && !error) {
703
719
  try {
704
720
  const stored = sessionStorage.getItem("oauth_callback_params");
@@ -761,6 +777,8 @@ function sendCallbackToOpener(params) {
761
777
  }
762
778
 
763
779
  // src/oauth/manager.ts
780
+ "use client";
781
+
764
782
  class OAuthManager {
765
783
  pendingAuths = new Map;
766
784
  sessionToken;
@@ -824,6 +842,7 @@ class OAuthManager {
824
842
  try {
825
843
  const response = await this.exchangeCodeForToken(pendingAuth.provider, code, pendingAuth.codeVerifier, state);
826
844
  this.sessionToken = response.sessionToken;
845
+ this.saveSessionToken(response.sessionToken);
827
846
  this.pendingAuths.delete(state);
828
847
  return response.sessionToken;
829
848
  } catch (error) {
@@ -867,9 +886,26 @@ class OAuthManager {
867
886
  }
868
887
  setSessionToken(token) {
869
888
  this.sessionToken = token;
889
+ this.saveSessionToken(token);
870
890
  }
871
891
  clearSessionToken() {
872
892
  this.sessionToken = undefined;
893
+ if (typeof window !== "undefined" && window.sessionStorage) {
894
+ try {
895
+ window.sessionStorage.removeItem("integrate_session_token");
896
+ } catch (error) {
897
+ console.error("Failed to clear session token from sessionStorage:", error);
898
+ }
899
+ }
900
+ }
901
+ saveSessionToken(token) {
902
+ if (typeof window !== "undefined" && window.sessionStorage) {
903
+ try {
904
+ window.sessionStorage.setItem("integrate_session_token", token);
905
+ } catch (error) {
906
+ console.error("Failed to save session token to sessionStorage:", error);
907
+ }
908
+ }
873
909
  }
874
910
  async getAuthorizationUrl(provider, scopes, state, codeChallenge, redirectUri) {
875
911
  const url = `${this.oauthApiBase}/authorize`;
@@ -921,6 +957,42 @@ class OAuthManager {
921
957
  }
922
958
 
923
959
  // src/client.ts
960
+ "use client";
961
+
962
+ class SimpleEventEmitter {
963
+ handlers = new Map;
964
+ on(event, handler) {
965
+ if (!this.handlers.has(event)) {
966
+ this.handlers.set(event, new Set);
967
+ }
968
+ this.handlers.get(event).add(handler);
969
+ }
970
+ off(event, handler) {
971
+ const handlers = this.handlers.get(event);
972
+ if (handlers) {
973
+ handlers.delete(handler);
974
+ }
975
+ }
976
+ emit(event, payload) {
977
+ const handlers = this.handlers.get(event);
978
+ if (handlers) {
979
+ handlers.forEach((handler) => {
980
+ try {
981
+ handler(payload);
982
+ } catch (error) {
983
+ console.error(`Error in event handler for ${event}:`, error);
984
+ }
985
+ });
986
+ }
987
+ }
988
+ removeAllListeners(event) {
989
+ if (event) {
990
+ this.handlers.delete(event);
991
+ } else {
992
+ this.handlers.clear();
993
+ }
994
+ }
995
+ }
924
996
  var MCP_SERVER_URL = "https://mcp.integrate.dev/api/v1/mcp";
925
997
  var clientCache = new Map;
926
998
  var cleanupClients = new Set;
@@ -939,6 +1011,7 @@ class MCPClient {
939
1011
  connectionMode;
940
1012
  connecting = null;
941
1013
  oauthManager;
1014
+ eventEmitter = new SimpleEventEmitter;
942
1015
  github;
943
1016
  gmail;
944
1017
  server;
@@ -957,9 +1030,16 @@ class MCPClient {
957
1030
  this.maxReauthRetries = config.maxReauthRetries ?? 1;
958
1031
  this.connectionMode = config.connectionMode ?? "lazy";
959
1032
  this.oauthManager = new OAuthManager(config.oauthApiBase || "/api/integrate/oauth", config.oauthFlow);
960
- if (config.sessionToken) {
961
- this.oauthManager.setSessionToken(config.sessionToken);
962
- this.transport.setHeader("X-Session-Token", config.sessionToken);
1033
+ let sessionToken = config.sessionToken;
1034
+ if (!sessionToken) {
1035
+ const storedToken = this.loadSessionToken();
1036
+ if (storedToken) {
1037
+ sessionToken = storedToken;
1038
+ }
1039
+ }
1040
+ if (sessionToken) {
1041
+ this.oauthManager.setSessionToken(sessionToken);
1042
+ this.transport.setHeader("X-Session-Token", sessionToken);
963
1043
  }
964
1044
  for (const plugin of this.plugins) {
965
1045
  for (const toolName of plugin.tools) {
@@ -1175,6 +1255,42 @@ class MCPClient {
1175
1255
  onMessage(handler) {
1176
1256
  return this.transport.onMessage(handler);
1177
1257
  }
1258
+ on(event, handler) {
1259
+ this.eventEmitter.on(event, handler);
1260
+ }
1261
+ off(event, handler) {
1262
+ this.eventEmitter.off(event, handler);
1263
+ }
1264
+ saveSessionToken(token) {
1265
+ if (typeof window !== "undefined" && window.sessionStorage) {
1266
+ try {
1267
+ window.sessionStorage.setItem("integrate_session_token", token);
1268
+ } catch (error) {
1269
+ console.error("Failed to save session token to sessionStorage:", error);
1270
+ }
1271
+ }
1272
+ }
1273
+ loadSessionToken() {
1274
+ if (typeof window !== "undefined" && window.sessionStorage) {
1275
+ try {
1276
+ return window.sessionStorage.getItem("integrate_session_token") || undefined;
1277
+ } catch (error) {
1278
+ console.error("Failed to load session token from sessionStorage:", error);
1279
+ return;
1280
+ }
1281
+ }
1282
+ return;
1283
+ }
1284
+ clearSessionToken() {
1285
+ if (typeof window !== "undefined" && window.sessionStorage) {
1286
+ try {
1287
+ window.sessionStorage.removeItem("integrate_session_token");
1288
+ } catch (error) {
1289
+ console.error("Failed to clear session token from sessionStorage:", error);
1290
+ }
1291
+ }
1292
+ this.oauthManager.clearSessionToken();
1293
+ }
1178
1294
  async disconnect() {
1179
1295
  for (const plugin of this.plugins) {
1180
1296
  if (plugin.onDisconnect) {
@@ -1218,18 +1334,44 @@ class MCPClient {
1218
1334
  async authorize(provider) {
1219
1335
  const plugin = this.plugins.find((p) => p.oauth?.provider === provider);
1220
1336
  if (!plugin?.oauth) {
1221
- throw new Error(`No OAuth configuration found for provider: ${provider}`);
1337
+ const error = new Error(`No OAuth configuration found for provider: ${provider}`);
1338
+ this.eventEmitter.emit("auth:error", { provider, error });
1339
+ throw error;
1340
+ }
1341
+ this.eventEmitter.emit("auth:started", { provider });
1342
+ try {
1343
+ await this.oauthManager.initiateFlow(provider, plugin.oauth);
1344
+ const sessionToken = this.oauthManager.getSessionToken();
1345
+ if (sessionToken) {
1346
+ this.saveSessionToken(sessionToken);
1347
+ this.eventEmitter.emit("auth:complete", { provider, sessionToken });
1348
+ }
1349
+ this.authState.set(provider, { authenticated: true });
1350
+ } catch (error) {
1351
+ this.eventEmitter.emit("auth:error", { provider, error });
1352
+ throw error;
1222
1353
  }
1223
- await this.oauthManager.initiateFlow(provider, plugin.oauth);
1224
- this.authState.set(provider, { authenticated: true });
1225
1354
  }
1226
1355
  async handleOAuthCallback(params) {
1227
- const sessionToken = await this.oauthManager.handleCallback(params.code, params.state);
1228
- this.transport.setHeader("X-Session-Token", sessionToken);
1229
- for (const plugin of this.plugins) {
1230
- if (plugin.oauth) {
1231
- this.authState.set(plugin.oauth.provider, { authenticated: true });
1356
+ try {
1357
+ const sessionToken = await this.oauthManager.handleCallback(params.code, params.state);
1358
+ this.saveSessionToken(sessionToken);
1359
+ this.transport.setHeader("X-Session-Token", sessionToken);
1360
+ for (const plugin of this.plugins) {
1361
+ if (plugin.oauth) {
1362
+ this.authState.set(plugin.oauth.provider, { authenticated: true });
1363
+ this.eventEmitter.emit("auth:complete", {
1364
+ provider: plugin.oauth.provider,
1365
+ sessionToken
1366
+ });
1367
+ }
1232
1368
  }
1369
+ } catch (error) {
1370
+ this.eventEmitter.emit("auth:error", {
1371
+ provider: "unknown",
1372
+ error
1373
+ });
1374
+ throw error;
1233
1375
  }
1234
1376
  }
1235
1377
  getSessionToken() {
@@ -1324,6 +1466,9 @@ function createMCPClient(config) {
1324
1466
  console.error("Failed to connect client:", error);
1325
1467
  });
1326
1468
  }
1469
+ if (config.autoHandleOAuthCallback !== false) {
1470
+ processOAuthCallbackFromHash(client);
1471
+ }
1327
1472
  return client;
1328
1473
  } else {
1329
1474
  const client = new MCPClient(config);
@@ -1336,9 +1481,35 @@ function createMCPClient(config) {
1336
1481
  console.error("Failed to connect client:", error);
1337
1482
  });
1338
1483
  }
1484
+ if (config.autoHandleOAuthCallback !== false) {
1485
+ processOAuthCallbackFromHash(client);
1486
+ }
1339
1487
  return client;
1340
1488
  }
1341
1489
  }
1490
+ function processOAuthCallbackFromHash(client) {
1491
+ if (typeof window === "undefined") {
1492
+ return;
1493
+ }
1494
+ try {
1495
+ const hash = window.location.hash;
1496
+ if (hash && hash.includes("oauth_callback=")) {
1497
+ const hashParams = new URLSearchParams(hash.substring(1));
1498
+ const oauthCallbackData = hashParams.get("oauth_callback");
1499
+ if (oauthCallbackData) {
1500
+ const callbackParams = JSON.parse(decodeURIComponent(oauthCallbackData));
1501
+ if (callbackParams.code && callbackParams.state) {
1502
+ client.handleOAuthCallback(callbackParams).catch((error) => {
1503
+ console.error("Failed to process OAuth callback:", error);
1504
+ });
1505
+ window.history.replaceState(null, "", window.location.pathname + window.location.search);
1506
+ }
1507
+ }
1508
+ }
1509
+ } catch (error) {
1510
+ console.error("Failed to process OAuth callback from hash:", error);
1511
+ }
1512
+ }
1342
1513
  async function clearClientCache() {
1343
1514
  const clients = Array.from(clientCache.values());
1344
1515
  clientCache.clear();
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Next.js OAuth Redirect Handler
3
+ * Handles OAuth callback redirects and forwards parameters to the client
4
+ */
5
+ type NextRequest = any;
6
+ type NextResponse = any;
7
+ export interface OAuthRedirectConfig {
8
+ /** URL to redirect to after OAuth callback (default: '/') */
9
+ redirectUrl?: string;
10
+ /** URL to redirect to on OAuth error (default: '/auth-error') */
11
+ errorRedirectUrl?: string;
12
+ }
13
+ /**
14
+ * Create OAuth redirect handler for Next.js
15
+ *
16
+ * This handler processes OAuth callbacks from providers and redirects
17
+ * to your application with the OAuth parameters encoded in the URL.
18
+ *
19
+ * @param config - Redirect configuration
20
+ * @returns Next.js route handler
21
+ *
22
+ * @example
23
+ * ```typescript
24
+ * // app/oauth/callback/route.ts
25
+ * import { createOAuthRedirectHandler } from 'integrate-sdk';
26
+ *
27
+ * export const GET = createOAuthRedirectHandler({
28
+ * redirectUrl: '/dashboard',
29
+ * });
30
+ * ```
31
+ */
32
+ export declare function createOAuthRedirectHandler(config?: OAuthRedirectConfig): (req: NextRequest) => Promise<NextResponse>;
33
+ export {};
34
+ //# sourceMappingURL=nextjs-oauth-redirect.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"nextjs-oauth-redirect.d.ts","sourceRoot":"","sources":["../../../src/adapters/nextjs-oauth-redirect.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,KAAK,WAAW,GAAG,GAAG,CAAC;AACvB,KAAK,YAAY,GAAG,GAAG,CAAC;AAExB,MAAM,WAAW,mBAAmB;IAClC,6DAA6D;IAC7D,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,iEAAiE;IACjE,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,0BAA0B,CAAC,MAAM,CAAC,EAAE,mBAAmB,IAI3C,KAAK,WAAW,KAAG,OAAO,CAAC,YAAY,CAAC,CAkCnE"}