integrate-sdk 0.7.48 → 0.7.50

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 (38) hide show
  1. package/dist/adapters/auto-routes.d.ts.map +1 -1
  2. package/dist/adapters/auto-routes.js +380 -24
  3. package/dist/adapters/base-handler.d.ts +50 -6
  4. package/dist/adapters/base-handler.d.ts.map +1 -1
  5. package/dist/adapters/base-handler.js +368 -18
  6. package/dist/adapters/context-cookie.d.ts +85 -0
  7. package/dist/adapters/context-cookie.d.ts.map +1 -0
  8. package/dist/adapters/context-cookie.js +152 -0
  9. package/dist/adapters/index.js +399 -37
  10. package/dist/adapters/nextjs.d.ts.map +1 -1
  11. package/dist/adapters/nextjs.js +387 -31
  12. package/dist/adapters/node.d.ts.map +1 -1
  13. package/dist/adapters/node.js +380 -24
  14. package/dist/adapters/session-detector.d.ts +37 -0
  15. package/dist/adapters/session-detector.d.ts.map +1 -0
  16. package/dist/adapters/session-detector.js +157 -0
  17. package/dist/adapters/solid-start.js +387 -31
  18. package/dist/adapters/svelte-kit.js +387 -31
  19. package/dist/ai/google.d.ts.map +1 -1
  20. package/dist/ai/google.js +6 -4
  21. package/dist/ai/index.js +6 -4
  22. package/dist/index.js +392 -30
  23. package/dist/oauth.js +380 -24
  24. package/dist/server.js +407 -37
  25. package/dist/src/adapters/auto-routes.d.ts.map +1 -1
  26. package/dist/src/adapters/base-handler.d.ts +50 -6
  27. package/dist/src/adapters/base-handler.d.ts.map +1 -1
  28. package/dist/src/adapters/context-cookie.d.ts +85 -0
  29. package/dist/src/adapters/context-cookie.d.ts.map +1 -0
  30. package/dist/src/adapters/nextjs.d.ts.map +1 -1
  31. package/dist/src/adapters/node.d.ts.map +1 -1
  32. package/dist/src/adapters/session-detector.d.ts +37 -0
  33. package/dist/src/adapters/session-detector.d.ts.map +1 -0
  34. package/dist/src/ai/google.d.ts.map +1 -1
  35. package/dist/src/config/types.d.ts +24 -0
  36. package/dist/src/config/types.d.ts.map +1 -1
  37. package/dist/src/server.d.ts.map +1 -1
  38. package/package.json +1 -1
package/dist/oauth.js CHANGED
@@ -27,6 +27,280 @@ var __export = (target, all) => {
27
27
  var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
28
28
  var __require = /* @__PURE__ */ createRequire(import.meta.url);
29
29
 
30
+ // src/adapters/session-detector.ts
31
+ var exports_session_detector = {};
32
+ __export(exports_session_detector, {
33
+ tryDecodeJWT: () => tryDecodeJWT,
34
+ detectSessionContext: () => detectSessionContext
35
+ });
36
+ function tryDecodeJWT(token) {
37
+ try {
38
+ const parts = token.split(".");
39
+ if (parts.length !== 3) {
40
+ return;
41
+ }
42
+ const payloadPart = parts[1];
43
+ if (!payloadPart) {
44
+ return;
45
+ }
46
+ const base64 = payloadPart.replace(/-/g, "+").replace(/_/g, "/");
47
+ const jsonPayload = decodeURIComponent(atob(base64).split("").map((c) => "%" + ("00" + c.charCodeAt(0).toString(16)).slice(-2)).join(""));
48
+ return JSON.parse(jsonPayload);
49
+ } catch (error) {
50
+ return;
51
+ }
52
+ }
53
+ function getCookies(request) {
54
+ const cookies = new Map;
55
+ const cookieHeader = request.headers.get("cookie");
56
+ if (!cookieHeader) {
57
+ return cookies;
58
+ }
59
+ const pairs = cookieHeader.split(";");
60
+ for (const pair of pairs) {
61
+ const [name, ...valueParts] = pair.split("=");
62
+ if (name && valueParts.length > 0) {
63
+ const trimmedName = name.trim();
64
+ const value = valueParts.join("=").trim();
65
+ cookies.set(trimmedName, value);
66
+ }
67
+ }
68
+ return cookies;
69
+ }
70
+ function tryBetterAuth(cookies) {
71
+ const sessionToken = cookies.get("better-auth.session_token");
72
+ if (!sessionToken) {
73
+ return;
74
+ }
75
+ const payload = tryDecodeJWT(sessionToken);
76
+ if (!payload) {
77
+ return;
78
+ }
79
+ const userId = payload.sub || payload.userId || payload.user_id || payload.id;
80
+ if (!userId) {
81
+ return;
82
+ }
83
+ return {
84
+ userId,
85
+ sessionId: payload.jti || payload.sessionId
86
+ };
87
+ }
88
+ function tryNextAuth(cookies) {
89
+ const sessionToken = cookies.get("__Secure-next-auth.session-token") || cookies.get("next-auth.session-token");
90
+ if (!sessionToken) {
91
+ return;
92
+ }
93
+ if (sessionToken.includes(".")) {
94
+ const payload = tryDecodeJWT(sessionToken);
95
+ if (payload) {
96
+ return {
97
+ userId: payload.sub || payload.userId || payload.user_id || payload.id,
98
+ sessionId: payload.jti
99
+ };
100
+ }
101
+ }
102
+ return;
103
+ }
104
+ function tryClerk(cookies) {
105
+ const sessionToken = cookies.get("__session");
106
+ if (!sessionToken) {
107
+ return;
108
+ }
109
+ const payload = tryDecodeJWT(sessionToken);
110
+ if (!payload) {
111
+ return;
112
+ }
113
+ return {
114
+ userId: payload.sub || payload.userId,
115
+ organizationId: payload.org_id || payload.organizationId,
116
+ sessionId: payload.sid || payload.sessionId
117
+ };
118
+ }
119
+ function tryLucia(cookies) {
120
+ const sessionToken = cookies.get("lucia_session");
121
+ if (!sessionToken) {
122
+ return;
123
+ }
124
+ return {
125
+ sessionId: sessionToken
126
+ };
127
+ }
128
+ function tryGenericSession(cookies) {
129
+ const sessionToken = cookies.get("auth_session") || cookies.get("session");
130
+ if (!sessionToken) {
131
+ return;
132
+ }
133
+ if (sessionToken.includes(".")) {
134
+ const payload = tryDecodeJWT(sessionToken);
135
+ if (payload) {
136
+ return {
137
+ userId: payload.sub || payload.userId || payload.user_id || payload.id,
138
+ sessionId: payload.jti || payload.sessionId || payload.sid
139
+ };
140
+ }
141
+ }
142
+ return {
143
+ sessionId: sessionToken
144
+ };
145
+ }
146
+ async function detectSessionContext(request) {
147
+ const cookies = getCookies(request);
148
+ let context;
149
+ context = tryBetterAuth(cookies);
150
+ if (context?.userId) {
151
+ return context;
152
+ }
153
+ context = tryNextAuth(cookies);
154
+ if (context?.userId) {
155
+ return context;
156
+ }
157
+ context = tryClerk(cookies);
158
+ if (context?.userId) {
159
+ return context;
160
+ }
161
+ context = tryLucia(cookies);
162
+ if (context?.userId) {
163
+ return context;
164
+ }
165
+ context = tryGenericSession(cookies);
166
+ if (context?.userId) {
167
+ return context;
168
+ }
169
+ return;
170
+ }
171
+
172
+ // src/adapters/context-cookie.ts
173
+ var exports_context_cookie = {};
174
+ __export(exports_context_cookie, {
175
+ readContextCookie: () => readContextCookie,
176
+ getSetCookieHeader: () => getSetCookieHeader,
177
+ getContextCookieFromRequest: () => getContextCookieFromRequest,
178
+ getClearCookieHeader: () => getClearCookieHeader,
179
+ createContextCookie: () => createContextCookie,
180
+ CONTEXT_COOKIE_NAME: () => CONTEXT_COOKIE_NAME,
181
+ CONTEXT_COOKIE_MAX_AGE: () => CONTEXT_COOKIE_MAX_AGE
182
+ });
183
+ async function deriveKey(secret) {
184
+ const encoder = new TextEncoder;
185
+ const secretData = encoder.encode(secret);
186
+ const keyMaterial = await crypto.subtle.importKey("raw", secretData, { name: "PBKDF2" }, false, ["deriveBits", "deriveKey"]);
187
+ const salt = encoder.encode("integrate-oauth-context-v1");
188
+ return await crypto.subtle.deriveKey({
189
+ name: "PBKDF2",
190
+ salt,
191
+ iterations: 1e5,
192
+ hash: "SHA-256"
193
+ }, keyMaterial, { name: "AES-GCM", length: 256 }, false, ["encrypt", "decrypt"]);
194
+ }
195
+ async function encryptPayload(payload, secret) {
196
+ const key = await deriveKey(secret);
197
+ const iv = crypto.getRandomValues(new Uint8Array(12));
198
+ const encoder = new TextEncoder;
199
+ const data = encoder.encode(JSON.stringify(payload));
200
+ const encrypted = await crypto.subtle.encrypt({
201
+ name: "AES-GCM",
202
+ iv
203
+ }, key, data);
204
+ const combined = new Uint8Array(iv.length + encrypted.byteLength);
205
+ combined.set(iv, 0);
206
+ combined.set(new Uint8Array(encrypted), iv.length);
207
+ return base64UrlEncode(combined);
208
+ }
209
+ async function decryptPayload(cookieValue, secret) {
210
+ try {
211
+ const combined = base64UrlDecode(cookieValue);
212
+ const iv = combined.slice(0, 12);
213
+ const encrypted = combined.slice(12);
214
+ const key = await deriveKey(secret);
215
+ const decrypted = await crypto.subtle.decrypt({
216
+ name: "AES-GCM",
217
+ iv
218
+ }, key, encrypted);
219
+ const decoder = new TextDecoder;
220
+ const json = decoder.decode(decrypted);
221
+ const payload = JSON.parse(json);
222
+ const age = Date.now() - payload.timestamp;
223
+ if (age > CONTEXT_COOKIE_MAX_AGE * 1000) {
224
+ return;
225
+ }
226
+ return payload;
227
+ } catch (error) {
228
+ return;
229
+ }
230
+ }
231
+ function base64UrlEncode(data) {
232
+ const base64 = btoa(String.fromCharCode(...data));
233
+ return base64.replace(/\+/g, "-").replace(/\//g, "_").replace(/=/g, "");
234
+ }
235
+ function base64UrlDecode(str) {
236
+ let base64 = str.replace(/-/g, "+").replace(/_/g, "/");
237
+ const padding = base64.length % 4;
238
+ if (padding) {
239
+ base64 += "=".repeat(4 - padding);
240
+ }
241
+ const binary = atob(base64);
242
+ const bytes = new Uint8Array(binary.length);
243
+ for (let i = 0;i < binary.length; i++) {
244
+ bytes[i] = binary.charCodeAt(i);
245
+ }
246
+ return bytes;
247
+ }
248
+ async function createContextCookie(context, provider, secret) {
249
+ const payload = {
250
+ context,
251
+ provider,
252
+ timestamp: Date.now()
253
+ };
254
+ return await encryptPayload(payload, secret);
255
+ }
256
+ async function readContextCookie(cookieValue, secret) {
257
+ const payload = await decryptPayload(cookieValue, secret);
258
+ if (!payload) {
259
+ return;
260
+ }
261
+ return {
262
+ context: payload.context,
263
+ provider: payload.provider
264
+ };
265
+ }
266
+ function getSetCookieHeader(cookieValue, maxAge = CONTEXT_COOKIE_MAX_AGE) {
267
+ const attributes = [
268
+ `${CONTEXT_COOKIE_NAME}=${cookieValue}`,
269
+ `Max-Age=${maxAge}`,
270
+ "HttpOnly",
271
+ "Secure",
272
+ "SameSite=Lax",
273
+ "Path=/"
274
+ ];
275
+ return attributes.join("; ");
276
+ }
277
+ function getClearCookieHeader() {
278
+ const attributes = [
279
+ `${CONTEXT_COOKIE_NAME}=`,
280
+ "Max-Age=0",
281
+ "HttpOnly",
282
+ "Secure",
283
+ "SameSite=Lax",
284
+ "Path=/"
285
+ ];
286
+ return attributes.join("; ");
287
+ }
288
+ function getContextCookieFromRequest(request) {
289
+ const cookieHeader = request.headers.get("cookie");
290
+ if (!cookieHeader) {
291
+ return;
292
+ }
293
+ const cookies = cookieHeader.split(";");
294
+ for (const cookie of cookies) {
295
+ const [name, ...valueParts] = cookie.split("=");
296
+ if (name && name.trim() === CONTEXT_COOKIE_NAME) {
297
+ return valueParts.join("=").trim();
298
+ }
299
+ }
300
+ return;
301
+ }
302
+ var CONTEXT_COOKIE_NAME = "__integrate_oauth_ctx", CONTEXT_COOKIE_MAX_AGE = 300;
303
+
30
304
  // src/adapters/base-handler.ts
31
305
  var exports_base_handler = {};
32
306
  __export(exports_base_handler, {
@@ -55,25 +329,35 @@ class OAuthHandler {
55
329
  return headers;
56
330
  }
57
331
  async handleAuthorize(request) {
58
- const providerConfig = this.config.providers[request.provider];
332
+ let webRequest;
333
+ let authorizeRequest;
334
+ if (request instanceof Request) {
335
+ webRequest = request;
336
+ authorizeRequest = await request.json();
337
+ } else if (typeof request === "object" && "json" in request && typeof request.json === "function") {
338
+ authorizeRequest = await request.json();
339
+ } else {
340
+ authorizeRequest = request;
341
+ }
342
+ const providerConfig = this.config.providers[authorizeRequest.provider];
59
343
  if (!providerConfig) {
60
- throw new Error(`Provider ${request.provider} not configured. Add OAuth credentials to your API route configuration.`);
344
+ throw new Error(`Provider ${authorizeRequest.provider} not configured. Add OAuth credentials to your API route configuration.`);
61
345
  }
62
346
  if (!providerConfig.clientId || !providerConfig.clientSecret) {
63
- throw new Error(`Missing OAuth credentials for ${request.provider}. Check your environment variables.`);
347
+ throw new Error(`Missing OAuth credentials for ${authorizeRequest.provider}. Check your environment variables.`);
64
348
  }
65
349
  const url = new URL("/oauth/authorize", this.serverUrl);
66
- url.searchParams.set("provider", request.provider);
350
+ url.searchParams.set("provider", authorizeRequest.provider);
67
351
  url.searchParams.set("client_id", providerConfig.clientId);
68
352
  url.searchParams.set("client_secret", providerConfig.clientSecret);
69
- const scopes = request.scopes || providerConfig.scopes || [];
353
+ const scopes = authorizeRequest.scopes || providerConfig.scopes || [];
70
354
  if (scopes.length > 0) {
71
355
  url.searchParams.set("scope", scopes.join(","));
72
356
  }
73
- url.searchParams.set("state", request.state);
74
- url.searchParams.set("code_challenge", request.codeChallenge);
75
- url.searchParams.set("code_challenge_method", request.codeChallengeMethod);
76
- const redirectUri = request.redirectUri || providerConfig.redirectUri;
357
+ url.searchParams.set("state", authorizeRequest.state);
358
+ url.searchParams.set("code_challenge", authorizeRequest.codeChallenge);
359
+ url.searchParams.set("code_challenge_method", authorizeRequest.codeChallengeMethod);
360
+ const redirectUri = authorizeRequest.redirectUri || providerConfig.redirectUri;
77
361
  if (redirectUri) {
78
362
  url.searchParams.set("redirect_uri", redirectUri);
79
363
  }
@@ -86,15 +370,62 @@ class OAuthHandler {
86
370
  throw new Error(`MCP server failed to generate authorization URL: ${error}`);
87
371
  }
88
372
  const data = await response.json();
89
- return data;
373
+ const result = data;
374
+ if (webRequest) {
375
+ try {
376
+ const { detectSessionContext: detectSessionContext2 } = await Promise.resolve().then(() => exports_session_detector);
377
+ const { createContextCookie: createContextCookie2, getSetCookieHeader: getSetCookieHeader2 } = await Promise.resolve().then(() => exports_context_cookie);
378
+ let context;
379
+ if (this.config.getSessionContext) {
380
+ context = await this.config.getSessionContext(webRequest);
381
+ }
382
+ if (!context || !context.userId) {
383
+ context = await detectSessionContext2(webRequest);
384
+ }
385
+ if (context && context.userId) {
386
+ const secret = this.apiKey || providerConfig.clientSecret;
387
+ const cookieValue = await createContextCookie2(context, authorizeRequest.provider, secret);
388
+ result.setCookie = getSetCookieHeader2(cookieValue);
389
+ }
390
+ } catch (error) {
391
+ console.warn("[OAuth] Failed to capture user context:", error);
392
+ }
393
+ }
394
+ return result;
90
395
  }
91
396
  async handleCallback(request) {
92
- const providerConfig = this.config.providers[request.provider];
397
+ let webRequest;
398
+ let callbackRequest;
399
+ if (request instanceof Request) {
400
+ webRequest = request;
401
+ callbackRequest = await request.json();
402
+ } else if (typeof request === "object" && "json" in request && typeof request.json === "function") {
403
+ callbackRequest = await request.json();
404
+ } else {
405
+ callbackRequest = request;
406
+ }
407
+ const providerConfig = this.config.providers[callbackRequest.provider];
93
408
  if (!providerConfig) {
94
- throw new Error(`Provider ${request.provider} not configured. Add OAuth credentials to your API route configuration.`);
409
+ throw new Error(`Provider ${callbackRequest.provider} not configured. Add OAuth credentials to your API route configuration.`);
95
410
  }
96
411
  if (!providerConfig.clientId || !providerConfig.clientSecret) {
97
- throw new Error(`Missing OAuth credentials for ${request.provider}. Check your environment variables.`);
412
+ throw new Error(`Missing OAuth credentials for ${callbackRequest.provider}. Check your environment variables.`);
413
+ }
414
+ let context;
415
+ if (webRequest) {
416
+ try {
417
+ const { getContextCookieFromRequest: getContextCookieFromRequest2, readContextCookie: readContextCookie2 } = await Promise.resolve().then(() => exports_context_cookie);
418
+ const cookieValue = getContextCookieFromRequest2(webRequest);
419
+ if (cookieValue) {
420
+ const secret = this.apiKey || providerConfig.clientSecret;
421
+ const contextData = await readContextCookie2(cookieValue, secret);
422
+ if (contextData && contextData.provider === callbackRequest.provider) {
423
+ context = contextData.context;
424
+ }
425
+ }
426
+ } catch (error) {
427
+ console.warn("[OAuth] Failed to restore user context:", error);
428
+ }
98
429
  }
99
430
  const url = new URL("/oauth/callback", this.serverUrl);
100
431
  const response = await fetch(url.toString(), {
@@ -103,10 +434,10 @@ class OAuthHandler {
103
434
  "Content-Type": "application/json"
104
435
  }),
105
436
  body: JSON.stringify({
106
- provider: request.provider,
107
- code: request.code,
108
- code_verifier: request.codeVerifier,
109
- state: request.state,
437
+ provider: callbackRequest.provider,
438
+ code: callbackRequest.code,
439
+ code_verifier: callbackRequest.codeVerifier,
440
+ state: callbackRequest.state,
110
441
  client_id: providerConfig.clientId,
111
442
  client_secret: providerConfig.clientSecret,
112
443
  redirect_uri: providerConfig.redirectUri
@@ -117,7 +448,26 @@ class OAuthHandler {
117
448
  throw new Error(`MCP server failed to exchange authorization code: ${error}`);
118
449
  }
119
450
  const data = await response.json();
120
- return data;
451
+ const result = data;
452
+ if (this.config.setProviderToken && context) {
453
+ try {
454
+ const tokenData = {
455
+ accessToken: result.accessToken,
456
+ refreshToken: result.refreshToken,
457
+ tokenType: result.tokenType,
458
+ expiresIn: result.expiresIn,
459
+ expiresAt: result.expiresAt
460
+ };
461
+ await this.config.setProviderToken(callbackRequest.provider, tokenData, context);
462
+ } catch (error) {
463
+ console.error("[OAuth] Failed to save provider token:", error);
464
+ }
465
+ }
466
+ if (webRequest) {
467
+ const { getClearCookieHeader: getClearCookieHeader2 } = await Promise.resolve().then(() => exports_context_cookie);
468
+ result.clearCookie = getClearCookieHeader2();
469
+ }
470
+ return result;
121
471
  }
122
472
  async handleStatus(provider, accessToken) {
123
473
  const url = new URL("/oauth/status", this.serverUrl);
@@ -213,14 +563,20 @@ async function POST(req, context) {
213
563
  }
214
564
  try {
215
565
  if (action === "authorize") {
216
- const body = await parseRequestBody(req);
217
- const result = await handler.handleAuthorize(body);
218
- return createSuccessResponse(result);
566
+ const result = await handler.handleAuthorize(req);
567
+ const response = createSuccessResponse(result);
568
+ if (result.setCookie) {
569
+ response.headers?.set?.("Set-Cookie", result.setCookie);
570
+ }
571
+ return response;
219
572
  }
220
573
  if (action === "callback") {
221
- const body = await parseRequestBody(req);
222
- const result = await handler.handleCallback(body);
223
- return createSuccessResponse(result);
574
+ const result = await handler.handleCallback(req);
575
+ const response = createSuccessResponse(result);
576
+ if (result.clearCookie) {
577
+ response.headers?.set?.("Set-Cookie", result.clearCookie);
578
+ }
579
+ return response;
224
580
  }
225
581
  if (action === "disconnect") {
226
582
  const body = await parseRequestBody(req);