integrate-sdk 0.5.5 → 0.5.6

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/dist/react.js CHANGED
@@ -11,18 +11,15 @@ var __export = (target, all) => {
11
11
  var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
12
12
 
13
13
  // src/react/hooks.ts
14
- import { useState, useEffect, useMemo, useCallback } from "react";
14
+ import { useState, useEffect } from "react";
15
15
  function getSafeFallback() {
16
16
  return {
17
17
  tokens: {},
18
- headers: {},
19
- isLoading: false,
20
- fetch: globalThis.fetch?.bind(globalThis) || (async () => new Response),
21
- mergeHeaders: (existingHeaders) => new Headers(existingHeaders)
18
+ isLoading: false
22
19
  };
23
20
  }
24
21
  function isReactHooksAvailable() {
25
- if (!useState || !useEffect || !useMemo || !useCallback) {
22
+ if (!useState || !useEffect) {
26
23
  return false;
27
24
  }
28
25
  if (typeof window === "undefined") {
@@ -82,39 +79,83 @@ function useIntegrateTokens(client) {
82
79
  return;
83
80
  }
84
81
  }, [client]);
85
- const headers = useMemo(() => {
86
- if (Object.keys(tokens).length === 0) {
87
- return {};
88
- }
89
- return {
90
- "x-integrate-tokens": JSON.stringify(tokens)
91
- };
92
- }, [tokens]);
93
- const fetchWithHeaders = useCallback(async (input, init) => {
94
- const mergedHeaders = new Headers(init?.headers);
95
- if (headers["x-integrate-tokens"]) {
96
- mergedHeaders.set("x-integrate-tokens", headers["x-integrate-tokens"]);
97
- }
98
- return fetch(input, {
99
- ...init,
100
- headers: mergedHeaders
101
- });
102
- }, [headers]);
103
- const mergeHeaders = useCallback((existingHeaders) => {
104
- const merged = new Headers(existingHeaders);
105
- if (headers["x-integrate-tokens"]) {
106
- merged.set("x-integrate-tokens", headers["x-integrate-tokens"]);
107
- }
108
- return merged;
109
- }, [headers]);
110
82
  return {
111
83
  tokens,
112
- headers,
113
- isLoading,
114
- fetch: fetchWithHeaders,
115
- mergeHeaders
84
+ isLoading
116
85
  };
117
86
  }
87
+ function useIntegrateAI(client, options = {}) {
88
+ const { apiPattern = /\/api\/chat/, debug = false } = options;
89
+ useEffect(() => {
90
+ if (!client || typeof window === "undefined") {
91
+ if (debug && !client) {
92
+ console.warn("[useIntegrateAI] No client provided, skipping interceptor setup");
93
+ }
94
+ return;
95
+ }
96
+ const originalFetch = window.fetch;
97
+ let currentTokens = {};
98
+ try {
99
+ currentTokens = client.getAllProviderTokens();
100
+ if (debug) {
101
+ console.log("[useIntegrateAI] Initial tokens loaded:", Object.keys(currentTokens));
102
+ }
103
+ } catch (error) {
104
+ console.error("[useIntegrateAI] Failed to get initial tokens:", error);
105
+ }
106
+ const updateTokens = () => {
107
+ try {
108
+ currentTokens = client.getAllProviderTokens();
109
+ if (debug) {
110
+ console.log("[useIntegrateAI] Tokens updated:", Object.keys(currentTokens));
111
+ }
112
+ } catch (error) {
113
+ console.error("[useIntegrateAI] Failed to update tokens:", error);
114
+ }
115
+ };
116
+ const handleLogout = () => {
117
+ currentTokens = {};
118
+ if (debug) {
119
+ console.log("[useIntegrateAI] Tokens cleared (logout)");
120
+ }
121
+ };
122
+ client.on("auth:complete", updateTokens);
123
+ client.on("auth:disconnect", updateTokens);
124
+ client.on("auth:logout", handleLogout);
125
+ const interceptedFetch = async (input, init) => {
126
+ const url = typeof input === "string" ? input : input instanceof URL ? input.href : input.url;
127
+ const shouldIntercept = typeof apiPattern === "string" ? url.includes(apiPattern) : apiPattern.test(url);
128
+ if (shouldIntercept && Object.keys(currentTokens).length > 0) {
129
+ if (debug) {
130
+ console.log("[useIntegrateAI] Intercepting request to:", url);
131
+ console.log("[useIntegrateAI] Injecting tokens:", Object.keys(currentTokens));
132
+ }
133
+ const headers = new Headers(init?.headers);
134
+ headers.set("x-integrate-tokens", JSON.stringify(currentTokens));
135
+ return originalFetch(input, {
136
+ ...init,
137
+ headers
138
+ });
139
+ }
140
+ return originalFetch(input, init);
141
+ };
142
+ window.fetch = interceptedFetch;
143
+ if (debug) {
144
+ console.log("[useIntegrateAI] Global fetch interceptor installed");
145
+ console.log("[useIntegrateAI] Pattern:", apiPattern);
146
+ }
147
+ return () => {
148
+ window.fetch = originalFetch;
149
+ client.off("auth:complete", updateTokens);
150
+ client.off("auth:disconnect", updateTokens);
151
+ client.off("auth:logout", handleLogout);
152
+ if (debug) {
153
+ console.log("[useIntegrateAI] Global fetch interceptor removed");
154
+ }
155
+ };
156
+ }, [client, apiPattern, debug]);
157
+ }
118
158
  export {
119
- useIntegrateTokens
159
+ useIntegrateTokens,
160
+ useIntegrateAI
120
161
  };
@@ -1,8 +1,7 @@
1
1
  /**
2
2
  * React hooks for integrate-sdk
3
3
  *
4
- * Provides React hooks for managing provider tokens and headers
5
- * in client-side applications.
4
+ * Provides React hooks for managing provider tokens in client-side applications.
6
5
  */
7
6
  import type { MCPClient } from "../client.js";
8
7
  /**
@@ -13,82 +12,117 @@ export interface UseIntegrateTokensResult {
13
12
  * Current provider tokens (e.g., { github: 'token123', gmail: 'token456' })
14
13
  */
15
14
  tokens: Record<string, string>;
16
- /**
17
- * Headers object ready to spread into fetch/useChat options
18
- * Includes 'x-integrate-tokens' header with JSON-stringified tokens
19
- */
20
- headers: Record<string, string>;
21
15
  /**
22
16
  * Whether tokens are currently being loaded
23
17
  */
24
18
  isLoading: boolean;
25
- /**
26
- * Custom fetch function with integrate tokens automatically included
27
- * Use this with libraries that accept a custom fetch function (like Vercel AI SDK's useChat)
28
- */
29
- fetch: (input: RequestInfo | URL, init?: RequestInit) => Promise<Response>;
30
- /**
31
- * Helper function to merge integrate headers with existing headers
32
- * Useful for manual fetch calls where you need to combine headers
33
- */
34
- mergeHeaders: (existingHeaders?: HeadersInit) => Headers;
35
19
  }
36
20
  /**
37
- * React hook to access integrate-sdk provider tokens and headers
21
+ * React hook to access integrate-sdk provider token status
38
22
  *
39
23
  * Automatically listens for authentication events and updates when tokens change.
40
- * Returns tokens and formatted headers ready to pass to API requests.
24
+ * Use this hook to display connection status in your UI.
25
+ *
26
+ * **For automatic token injection**, use `useIntegrateAI()` instead.
41
27
  *
42
28
  * **Note:** This hook must be called inside a React component. It will return safe
43
29
  * fallback values during SSR or if the client is not ready.
44
30
  *
45
31
  * @param client - MCP client instance created with createMCPClient() (optional)
46
- * @returns Object with tokens, headers, loading state, fetch function, and mergeHeaders helper
32
+ * @returns Object with tokens and loading state
47
33
  *
48
34
  * @example
49
35
  * ```tsx
50
36
  * import { createMCPClient, githubPlugin } from 'integrate-sdk';
51
37
  * import { useIntegrateTokens } from 'integrate-sdk/react';
52
- * import { useChat } from 'ai/react';
53
38
  *
54
39
  * const client = createMCPClient({
55
40
  * plugins: [githubPlugin({ clientId: '...' })],
56
41
  * });
57
42
  *
58
- * function ChatComponent() {
59
- * const { fetch: fetchWithTokens, isLoading } = useIntegrateTokens(client);
43
+ * function ConnectionStatus() {
44
+ * const { tokens, isLoading } = useIntegrateTokens(client);
60
45
  *
61
- * const chat = useChat({
62
- * api: '/api/chat',
63
- * fetch: fetchWithTokens, // Tokens automatically included
64
- * });
46
+ * if (isLoading) return <div>Loading...</div>;
65
47
  *
66
- * return <div>Chat UI here</div>;
48
+ * return (
49
+ * <div>
50
+ * {Object.keys(tokens).length > 0 ? (
51
+ * <span>Connected: {Object.keys(tokens).join(', ')}</span>
52
+ * ) : (
53
+ * <span>Not connected</span>
54
+ * )}
55
+ * </div>
56
+ * );
67
57
  * }
68
58
  * ```
59
+ */
60
+ export declare function useIntegrateTokens(client?: MCPClient<any> | null): UseIntegrateTokensResult;
61
+ /**
62
+ * Options for useIntegrateAI hook
63
+ */
64
+ export interface UseIntegrateAIOptions {
65
+ /**
66
+ * URL pattern to intercept for token injection
67
+ * Default: /\/api\/chat/
68
+ * Can be a string (uses .includes()) or RegExp
69
+ */
70
+ apiPattern?: string | RegExp;
71
+ /**
72
+ * Enable debug logging
73
+ * Default: false
74
+ */
75
+ debug?: boolean;
76
+ }
77
+ /**
78
+ * Global fetch interceptor for Vercel AI SDK
79
+ *
80
+ * Automatically injects integrate provider tokens into all AI SDK requests.
81
+ * Call this once at your app root (layout/provider) to enable automatic token
82
+ * injection for all `useChat` calls in your application.
83
+ *
84
+ * **Note:** This installs a global `window.fetch` interceptor that only affects
85
+ * requests matching the `apiPattern`. All other requests pass through unchanged.
86
+ *
87
+ * @param client - MCP client instance created with createMCPClient() (optional)
88
+ * @param options - Configuration options for the interceptor
69
89
  *
70
90
  * @example
71
91
  * ```tsx
72
- * // With mergeHeaders helper
73
- * import { createMCPClient } from 'integrate-sdk';
92
+ * // app/layout.tsx or app/providers.tsx
93
+ * 'use client';
94
+ *
95
+ * import { createMCPClient, githubPlugin } from 'integrate-sdk';
96
+ * import { useIntegrateAI } from 'integrate-sdk/react';
74
97
  *
75
- * const client = createMCPClient({ plugins: [...] });
98
+ * const client = createMCPClient({
99
+ * plugins: [
100
+ * githubPlugin({ clientId: process.env.NEXT_PUBLIC_GITHUB_CLIENT_ID }),
101
+ * ],
102
+ * });
76
103
  *
77
- * function MyComponent() {
78
- * const { mergeHeaders } = useIntegrateTokens(client);
104
+ * export function Providers({ children }) {
105
+ * // Install global interceptor once
106
+ * useIntegrateAI(client);
79
107
  *
80
- * const fetchData = async () => {
81
- * const response = await fetch('/api/data', {
82
- * method: 'POST',
83
- * headers: mergeHeaders({ 'Content-Type': 'application/json' }),
84
- * body: JSON.stringify({ query: 'example' }),
85
- * });
86
- * return response.json();
87
- * };
108
+ * return <>{children}</>;
109
+ * }
88
110
  *
89
- * return <button onClick={fetchData}>Fetch</button>;
111
+ * // Now any component can use useChat without manual token management
112
+ * function ChatPage() {
113
+ * const chat = useChat(); // ✅ Tokens automatically included!
114
+ * return <div>...</div>;
90
115
  * }
91
116
  * ```
117
+ *
118
+ * @example
119
+ * ```tsx
120
+ * // With custom API pattern and debug logging
121
+ * useIntegrateAI(client, {
122
+ * apiPattern: /\/(api|chat)\//, // Match /api/ or /chat/
123
+ * debug: true, // Log intercepted requests
124
+ * });
125
+ * ```
92
126
  */
93
- export declare function useIntegrateTokens(client?: MCPClient<any> | null): UseIntegrateTokensResult;
127
+ export declare function useIntegrateAI(client?: MCPClient<any> | null, options?: UseIntegrateAIOptions): void;
94
128
  //# sourceMappingURL=hooks.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"hooks.d.ts","sourceRoot":"","sources":["../../../src/react/hooks.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAE9C;;GAEG;AACH,MAAM,WAAW,wBAAwB;IACvC;;OAEG;IACH,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAE/B;;;OAGG;IACH,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAEhC;;OAEG;IACH,SAAS,EAAE,OAAO,CAAC;IAEnB;;;OAGG;IACH,KAAK,EAAE,CAAC,KAAK,EAAE,WAAW,GAAG,GAAG,EAAE,IAAI,CAAC,EAAE,WAAW,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAC;IAE3E;;;OAGG;IACH,YAAY,EAAE,CAAC,eAAe,CAAC,EAAE,WAAW,KAAK,OAAO,CAAC;CAC1D;AAuCD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwDG;AACH,wBAAgB,kBAAkB,CAChC,MAAM,CAAC,EAAE,SAAS,CAAC,GAAG,CAAC,GAAG,IAAI,GAC7B,wBAAwB,CA0H1B"}
1
+ {"version":3,"file":"hooks.d.ts","sourceRoot":"","sources":["../../../src/react/hooks.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAE9C;;GAEG;AACH,MAAM,WAAW,wBAAwB;IACvC;;OAEG;IACH,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAE/B;;OAEG;IACH,SAAS,EAAE,OAAO,CAAC;CACpB;AAoCD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuCG;AACH,wBAAgB,kBAAkB,CAChC,MAAM,CAAC,EAAE,SAAS,CAAC,GAAG,CAAC,GAAG,IAAI,GAC7B,wBAAwB,CA4E1B;AAED;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACpC;;;;OAIG;IACH,UAAU,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAE7B;;;OAGG;IACH,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiDG;AACH,wBAAgB,cAAc,CAC5B,MAAM,CAAC,EAAE,SAAS,CAAC,GAAG,CAAC,GAAG,IAAI,EAC9B,OAAO,GAAE,qBAA0B,GAClC,IAAI,CA6GN"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "integrate-sdk",
3
- "version": "0.5.5",
3
+ "version": "0.5.6",
4
4
  "description": "Type-safe TypeScript SDK for MCP Client with plugin-based OAuth provider configuration",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
package/react.ts CHANGED
@@ -4,6 +4,6 @@
4
4
  * @packageDocumentation
5
5
  */
6
6
 
7
- export { useIntegrateTokens } from "./src/react/hooks.js";
8
- export type { UseIntegrateTokensResult } from "./src/react/hooks.js";
7
+ export { useIntegrateTokens, useIntegrateAI } from "./src/react/hooks.js";
8
+ export type { UseIntegrateTokensResult, UseIntegrateAIOptions } from "./src/react/hooks.js";
9
9