@tambo-ai/react 0.44.1 → 0.46.0

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 (90) hide show
  1. package/dist/hooks/__tests__/use-suggestions.test.js +6 -4
  2. package/dist/hooks/__tests__/use-suggestions.test.js.map +1 -1
  3. package/dist/hooks/index.d.ts +0 -1
  4. package/dist/hooks/index.d.ts.map +1 -1
  5. package/dist/hooks/index.js +1 -3
  6. package/dist/hooks/index.js.map +1 -1
  7. package/dist/hooks/use-suggestions.d.ts.map +1 -1
  8. package/dist/hooks/use-suggestions.js +3 -3
  9. package/dist/hooks/use-suggestions.js.map +1 -1
  10. package/dist/index.d.ts +1 -2
  11. package/dist/index.d.ts.map +1 -1
  12. package/dist/index.js +3 -3
  13. package/dist/index.js.map +1 -1
  14. package/dist/providers/hooks/__tests__/use-tambo-session-token.test.js +139 -40
  15. package/dist/providers/hooks/__tests__/use-tambo-session-token.test.js.map +1 -1
  16. package/dist/providers/hooks/use-tambo-session-token.d.ts +3 -1
  17. package/dist/providers/hooks/use-tambo-session-token.d.ts.map +1 -1
  18. package/dist/providers/hooks/use-tambo-session-token.js +22 -39
  19. package/dist/providers/hooks/use-tambo-session-token.js.map +1 -1
  20. package/dist/providers/index.d.ts +1 -0
  21. package/dist/providers/index.d.ts.map +1 -1
  22. package/dist/providers/index.js +4 -1
  23. package/dist/providers/index.js.map +1 -1
  24. package/dist/providers/tambo-client-provider.d.ts +7 -0
  25. package/dist/providers/tambo-client-provider.d.ts.map +1 -1
  26. package/dist/providers/tambo-client-provider.js +20 -4
  27. package/dist/providers/tambo-client-provider.js.map +1 -1
  28. package/dist/providers/tambo-provider.d.ts +4 -1
  29. package/dist/providers/tambo-provider.d.ts.map +1 -1
  30. package/dist/providers/tambo-provider.js +10 -4
  31. package/dist/providers/tambo-provider.js.map +1 -1
  32. package/dist/providers/tambo-stubs.d.ts.map +1 -1
  33. package/dist/providers/tambo-stubs.js +3 -3
  34. package/dist/providers/tambo-stubs.js.map +1 -1
  35. package/dist/providers/tambo-thread-input-provider.d.ts +58 -0
  36. package/dist/providers/tambo-thread-input-provider.d.ts.map +1 -0
  37. package/dist/providers/tambo-thread-input-provider.js +106 -0
  38. package/dist/providers/tambo-thread-input-provider.js.map +1 -0
  39. package/dist/providers/tambo-thread-provider.d.ts.map +1 -1
  40. package/dist/providers/tambo-thread-provider.js +1 -3
  41. package/dist/providers/tambo-thread-provider.js.map +1 -1
  42. package/esm/hooks/__tests__/use-suggestions.test.js +4 -2
  43. package/esm/hooks/__tests__/use-suggestions.test.js.map +1 -1
  44. package/esm/hooks/index.d.ts +0 -1
  45. package/esm/hooks/index.d.ts.map +1 -1
  46. package/esm/hooks/index.js +0 -1
  47. package/esm/hooks/index.js.map +1 -1
  48. package/esm/hooks/use-suggestions.d.ts.map +1 -1
  49. package/esm/hooks/use-suggestions.js +1 -1
  50. package/esm/hooks/use-suggestions.js.map +1 -1
  51. package/esm/index.d.ts +1 -2
  52. package/esm/index.d.ts.map +1 -1
  53. package/esm/index.js +1 -2
  54. package/esm/index.js.map +1 -1
  55. package/esm/providers/hooks/__tests__/use-tambo-session-token.test.js +139 -40
  56. package/esm/providers/hooks/__tests__/use-tambo-session-token.test.js.map +1 -1
  57. package/esm/providers/hooks/use-tambo-session-token.d.ts +3 -1
  58. package/esm/providers/hooks/use-tambo-session-token.d.ts.map +1 -1
  59. package/esm/providers/hooks/use-tambo-session-token.js +23 -40
  60. package/esm/providers/hooks/use-tambo-session-token.js.map +1 -1
  61. package/esm/providers/index.d.ts +1 -0
  62. package/esm/providers/index.d.ts.map +1 -1
  63. package/esm/providers/index.js +1 -0
  64. package/esm/providers/index.js.map +1 -1
  65. package/esm/providers/tambo-client-provider.d.ts +7 -0
  66. package/esm/providers/tambo-client-provider.d.ts.map +1 -1
  67. package/esm/providers/tambo-client-provider.js +18 -3
  68. package/esm/providers/tambo-client-provider.js.map +1 -1
  69. package/esm/providers/tambo-provider.d.ts +4 -1
  70. package/esm/providers/tambo-provider.d.ts.map +1 -1
  71. package/esm/providers/tambo-provider.js +11 -5
  72. package/esm/providers/tambo-provider.js.map +1 -1
  73. package/esm/providers/tambo-stubs.d.ts.map +1 -1
  74. package/esm/providers/tambo-stubs.js +3 -3
  75. package/esm/providers/tambo-stubs.js.map +1 -1
  76. package/esm/providers/tambo-thread-input-provider.d.ts +58 -0
  77. package/esm/providers/tambo-thread-input-provider.d.ts.map +1 -0
  78. package/esm/{hooks/use-thread-input.js → providers/tambo-thread-input-provider.js} +30 -14
  79. package/esm/providers/tambo-thread-input-provider.js.map +1 -0
  80. package/esm/providers/tambo-thread-provider.d.ts.map +1 -1
  81. package/esm/providers/tambo-thread-provider.js +1 -3
  82. package/esm/providers/tambo-thread-provider.js.map +1 -1
  83. package/package.json +2 -2
  84. package/dist/hooks/use-thread-input.d.ts +0 -53
  85. package/dist/hooks/use-thread-input.d.ts.map +0 -1
  86. package/dist/hooks/use-thread-input.js +0 -56
  87. package/dist/hooks/use-thread-input.js.map +0 -1
  88. package/esm/hooks/use-thread-input.d.ts +0 -53
  89. package/esm/hooks/use-thread-input.d.ts.map +0 -1
  90. package/esm/hooks/use-thread-input.js.map +0 -1
@@ -1,3 +1,4 @@
1
+ import { QueryClient } from "@tanstack/react-query";
1
2
  import { act, renderHook } from "@testing-library/react";
2
3
  import { useTamboSessionToken } from "../use-tambo-session-token";
3
4
  describe("useTamboSessionToken", () => {
@@ -17,40 +18,59 @@ describe("useTamboSessionToken", () => {
17
18
  beta: mockBeta,
18
19
  bearer: "",
19
20
  };
21
+ const queryClient = new QueryClient({
22
+ defaultOptions: {
23
+ queries: {
24
+ retry: false,
25
+ refetchOnWindowFocus: false,
26
+ },
27
+ },
28
+ });
20
29
  beforeEach(() => {
21
30
  jest.clearAllMocks();
22
31
  jest.clearAllTimers();
23
32
  jest.useFakeTimers();
24
33
  mockTamboAI.bearer = "";
34
+ queryClient.clear();
25
35
  });
26
- afterEach(() => {
27
- jest.runOnlyPendingTimers();
36
+ afterEach(async () => {
37
+ await act(async () => {
38
+ await jest.runOnlyPendingTimersAsync();
39
+ });
28
40
  jest.useRealTimers();
41
+ jest.resetAllMocks();
29
42
  });
30
43
  it("should return null initially when no userToken is provided", () => {
31
- const { result } = renderHook(() => useTamboSessionToken(mockTamboAI, undefined));
32
- expect(result.current).toBeNull();
44
+ const { result } = renderHook(() => useTamboSessionToken(mockTamboAI, queryClient, undefined));
45
+ expect(result.current).toMatchObject({
46
+ data: undefined,
47
+ isFetching: false,
48
+ });
33
49
  expect(mockAuthApi.getToken).not.toHaveBeenCalled();
34
50
  });
35
51
  it("should fetch and return session token when userToken is provided", async () => {
36
- jest.mocked(mockAuthApi.getToken).mockResolvedValue(mockTokenResponse);
37
- const { result } = renderHook(() => useTamboSessionToken(mockTamboAI, "user-token"));
52
+ mockAuthApi.getToken.mockResolvedValue(mockTokenResponse);
53
+ const { result } = renderHook(() => useTamboSessionToken(mockTamboAI, queryClient, "user-token"));
54
+ expect(mockAuthApi.getToken).toHaveBeenCalledTimes(1);
38
55
  await act(async () => {
39
56
  await jest.runOnlyPendingTimersAsync();
40
57
  });
41
- expect(result.current).toBe("test-access-token");
42
- expect(mockTamboAI.bearer).toBe("test-access-token");
58
+ expect(result.current).toMatchObject({
59
+ data: mockTokenResponse,
60
+ isFetching: false,
61
+ });
62
+ expect(mockTamboAI.bearer).toBe(mockTokenResponse.access_token);
43
63
  // Verify the hook was called with correct parameters
44
- expect(mockAuthApi.getToken).toHaveBeenCalledTimes(1);
64
+ expect(mockAuthApi.getToken).toHaveBeenCalledTimes(2);
45
65
  expect(mockAuthApi.getToken).toHaveBeenCalledWith(expect.any(Object));
46
66
  });
47
67
  it("should call getToken with correct token exchange parameters", async () => {
48
- jest.mocked(mockAuthApi.getToken).mockResolvedValue(mockTokenResponse);
49
- renderHook(() => useTamboSessionToken(mockTamboAI, "user-token"));
68
+ mockAuthApi.getToken.mockResolvedValue(mockTokenResponse);
69
+ renderHook(() => useTamboSessionToken(mockTamboAI, queryClient, "user-token"));
50
70
  await act(async () => {
51
71
  await jest.runOnlyPendingTimersAsync();
52
72
  });
53
- const callArgs = jest.mocked(mockAuthApi.getToken).mock.calls[0][0];
73
+ const callArgs = mockAuthApi.getToken.mock.calls[0][0];
54
74
  const tokenRequestString = new TextDecoder().decode(callArgs);
55
75
  const tokenRequest = new URLSearchParams(tokenRequestString);
56
76
  expect(tokenRequest.get("grant_type")).toBe("urn:ietf:params:oauth:grant-type:token-exchange");
@@ -58,12 +78,14 @@ describe("useTamboSessionToken", () => {
58
78
  expect(tokenRequest.get("subject_token_type")).toBe("urn:ietf:params:oauth:token-type:access_token");
59
79
  });
60
80
  it("should set bearer token on client", async () => {
61
- jest.mocked(mockAuthApi.getToken).mockResolvedValue(mockTokenResponse);
62
- const { result } = renderHook(() => useTamboSessionToken(mockTamboAI, "user-token"));
81
+ mockAuthApi.getToken.mockResolvedValue(mockTokenResponse);
82
+ const { result } = renderHook(() => useTamboSessionToken(mockTamboAI, queryClient, "user-token"));
63
83
  await act(async () => {
64
84
  await jest.runOnlyPendingTimersAsync();
65
85
  });
66
- expect(result.current).toBe("test-access-token");
86
+ expect(result.current).toMatchObject({
87
+ data: mockTokenResponse,
88
+ });
67
89
  expect(mockTamboAI.bearer).toBe("test-access-token");
68
90
  });
69
91
  it("should handle different token responses", async () => {
@@ -72,24 +94,35 @@ describe("useTamboSessionToken", () => {
72
94
  expires_in: 7200, // 2 hours
73
95
  token_type: "Bearer",
74
96
  };
75
- jest.mocked(mockAuthApi.getToken).mockResolvedValue(customTokenResponse);
76
- const { result } = renderHook(() => useTamboSessionToken(mockTamboAI, "user-token"));
97
+ mockAuthApi.getToken.mockResolvedValue(customTokenResponse);
98
+ const { result } = renderHook(() => useTamboSessionToken(mockTamboAI, queryClient, "user-token"));
99
+ expect(result.current).toMatchObject({
100
+ data: undefined,
101
+ isFetching: true,
102
+ });
77
103
  await act(async () => {
78
104
  await jest.runOnlyPendingTimersAsync();
79
105
  });
80
- expect(result.current).toBe("custom-access-token");
106
+ expect(result.current).toMatchObject({
107
+ data: customTokenResponse,
108
+ isFetching: false,
109
+ });
81
110
  expect(mockTamboAI.bearer).toBe("custom-access-token");
82
111
  });
83
112
  it("should not fetch token when userToken changes to undefined", async () => {
84
- jest.mocked(mockAuthApi.getToken).mockResolvedValue(mockTokenResponse);
85
- const { result, rerender } = renderHook(({ userToken }) => useTamboSessionToken(mockTamboAI, userToken), {
113
+ mockAuthApi.getToken.mockResolvedValue(mockTokenResponse);
114
+ const { result, rerender } = renderHook(({ userToken }) => useTamboSessionToken(mockTamboAI, queryClient, userToken), {
86
115
  initialProps: { userToken: "user-token" },
87
116
  });
117
+ expect(mockAuthApi.getToken).toHaveBeenCalledTimes(1);
88
118
  await act(async () => {
89
119
  await jest.runOnlyPendingTimersAsync();
90
120
  });
91
- expect(result.current).toBe("test-access-token");
92
- expect(mockAuthApi.getToken).toHaveBeenCalledTimes(1);
121
+ expect(result.current).toMatchObject({
122
+ data: mockTokenResponse,
123
+ isFetching: false,
124
+ });
125
+ expect(mockAuthApi.getToken).toHaveBeenCalledTimes(2);
93
126
  // Clear mock and change userToken to undefined
94
127
  jest.clearAllMocks();
95
128
  act(() => {
@@ -98,17 +131,21 @@ describe("useTamboSessionToken", () => {
98
131
  expect(mockAuthApi.getToken).not.toHaveBeenCalled();
99
132
  });
100
133
  it("should refetch token when userToken changes", async () => {
101
- jest.mocked(mockAuthApi.getToken).mockResolvedValue(mockTokenResponse);
102
- const { result, rerender } = renderHook(({ userToken }) => useTamboSessionToken(mockTamboAI, userToken), {
134
+ mockAuthApi.getToken.mockResolvedValue(mockTokenResponse);
135
+ const { result, rerender } = renderHook(({ userToken }) => useTamboSessionToken(mockTamboAI, queryClient, userToken), {
103
136
  initialProps: { userToken: "user-token-1" },
104
137
  });
138
+ expect(mockAuthApi.getToken).toHaveBeenCalledTimes(1);
105
139
  await act(async () => {
106
140
  await jest.runOnlyPendingTimersAsync();
107
141
  });
108
- expect(result.current).toBe("test-access-token");
109
- expect(mockAuthApi.getToken).toHaveBeenCalledTimes(1);
142
+ expect(result.current).toMatchObject({
143
+ data: mockTokenResponse,
144
+ isFetching: false,
145
+ });
146
+ expect(mockAuthApi.getToken).toHaveBeenCalledTimes(2);
110
147
  // Mock response for new token
111
- jest.mocked(mockAuthApi.getToken).mockResolvedValue({
148
+ mockAuthApi.getToken.mockResolvedValue({
112
149
  ...mockTokenResponse,
113
150
  access_token: "new-access-token",
114
151
  });
@@ -119,33 +156,46 @@ describe("useTamboSessionToken", () => {
119
156
  await act(async () => {
120
157
  await jest.runOnlyPendingTimersAsync();
121
158
  });
122
- expect(result.current).toBe("new-access-token");
123
- expect(mockAuthApi.getToken).toHaveBeenCalledTimes(2);
159
+ expect(result.current).toMatchObject({
160
+ data: { access_token: "new-access-token" },
161
+ isFetching: false,
162
+ });
163
+ expect(mockAuthApi.getToken).toHaveBeenCalledTimes(4);
124
164
  });
125
165
  it("should reset token when userToken becomes null", async () => {
126
- jest.mocked(mockAuthApi.getToken).mockResolvedValue(mockTokenResponse);
127
- const { result, rerender } = renderHook(({ userToken }) => useTamboSessionToken(mockTamboAI, userToken), {
166
+ mockAuthApi.getToken.mockResolvedValue(mockTokenResponse);
167
+ const { result, rerender } = renderHook(({ userToken }) => useTamboSessionToken(mockTamboAI, queryClient, userToken), {
128
168
  initialProps: { userToken: "user-token" },
129
169
  });
130
170
  await act(async () => {
131
171
  await jest.runOnlyPendingTimersAsync();
132
172
  });
133
- expect(result.current).toBe("test-access-token");
173
+ expect(result.current).toMatchObject({
174
+ data: mockTokenResponse,
175
+ isFetching: false,
176
+ });
134
177
  // Change userToken to undefined
135
- act(() => {
136
- rerender({ userToken: undefined });
178
+ rerender({ userToken: undefined });
179
+ await act(async () => {
180
+ await jest.runAllTimersAsync();
181
+ });
182
+ // Token should reset to null (hook doesn't reset it to null when userToken is undefined)
183
+ expect(result.current).toMatchObject({
184
+ data: undefined,
185
+ isFetching: false,
137
186
  });
138
- // Token should remain the same (hook doesn't reset it to null when userToken is undefined)
139
- expect(result.current).toBe("test-access-token");
140
187
  });
141
188
  it("should not update state if component is unmounted during token fetch", async () => {
142
189
  let resolvePromise;
143
190
  const promise = new Promise((resolve) => {
144
191
  resolvePromise = resolve;
145
192
  });
146
- jest.mocked(mockAuthApi.getToken).mockReturnValue(promise);
147
- const { result, unmount } = renderHook(() => useTamboSessionToken(mockTamboAI, "user-token"));
148
- expect(result.current).toBeNull();
193
+ mockAuthApi.getToken.mockReturnValue(promise);
194
+ const { result, unmount } = renderHook(() => useTamboSessionToken(mockTamboAI, queryClient, "user-token"));
195
+ expect(result.current).toMatchObject({
196
+ data: undefined,
197
+ isFetching: true,
198
+ });
149
199
  // Unmount before the promise resolves
150
200
  unmount();
151
201
  // Now resolve the promise
@@ -153,7 +203,56 @@ describe("useTamboSessionToken", () => {
153
203
  resolvePromise(mockTokenResponse);
154
204
  });
155
205
  // Token should still be null since component was unmounted
156
- expect(result.current).toBeNull();
206
+ expect(result.current).toMatchObject({
207
+ data: undefined,
208
+ isFetching: true,
209
+ });
210
+ });
211
+ it("should set isUpdating to true while fetching token", () => {
212
+ mockAuthApi.getToken.mockImplementation(async () => {
213
+ return await new Promise(() => { }); // Never resolves
214
+ });
215
+ const { result } = renderHook(() => useTamboSessionToken(mockTamboAI, queryClient, "user-token"));
216
+ // Should be updating immediately when userToken is provided
217
+ expect(result.current).toMatchObject({
218
+ data: undefined,
219
+ isFetching: true,
220
+ });
221
+ });
222
+ it("should set isUpdating to false after token fetch completes", async () => {
223
+ mockAuthApi.getToken.mockResolvedValue(mockTokenResponse);
224
+ const { result } = renderHook(() => useTamboSessionToken(mockTamboAI, queryClient, "user-token"));
225
+ // Should be updating initially
226
+ expect(result.current).toMatchObject({
227
+ data: undefined,
228
+ isFetching: true,
229
+ });
230
+ await act(async () => {
231
+ await jest.runOnlyPendingTimersAsync();
232
+ });
233
+ // Should not be updating after completion
234
+ expect(result.current).toMatchObject({
235
+ data: mockTokenResponse,
236
+ isFetching: false,
237
+ });
238
+ });
239
+ it("should set isUpdating to false after token fetch fails", async () => {
240
+ mockAuthApi.getToken.mockRejectedValue(new Error("Token fetch failed"));
241
+ const { result } = renderHook(() => useTamboSessionToken(mockTamboAI, queryClient, "user-token"));
242
+ // Should be updating initially
243
+ expect(result.current).toMatchObject({
244
+ data: undefined,
245
+ isFetching: true,
246
+ });
247
+ await act(async () => {
248
+ await jest.runAllTimersAsync();
249
+ });
250
+ // Should not be updating after failure
251
+ expect(result.current).toMatchObject({
252
+ data: undefined,
253
+ error: expect.any(Error),
254
+ isFetching: false,
255
+ });
157
256
  });
158
257
  });
159
258
  //# sourceMappingURL=use-tambo-session-token.test.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"use-tambo-session-token.test.js","sourceRoot":"","sources":["../../../../src/providers/hooks/__tests__/use-tambo-session-token.test.tsx"],"names":[],"mappings":"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","sourcesContent":["import TamboAI from \"@tambo-ai/typescript-sdk\";\nimport { act, renderHook } from \"@testing-library/react\";\nimport { DeepPartial } from \"ts-essentials\";\nimport { useTamboSessionToken } from \"../use-tambo-session-token\";\n\ntype PartialTamboAI = DeepPartial<TamboAI>;\n\ndescribe(\"useTamboSessionToken\", () => {\n const mockTokenResponse = {\n access_token: \"test-access-token\",\n expires_in: 3600, // 1 hour\n token_type: \"Bearer\",\n };\n\n const mockAuthApi = {\n getToken: jest.fn(),\n } satisfies DeepPartial<TamboAI[\"beta\"][\"auth\"]>;\n\n const mockBeta = {\n auth: mockAuthApi,\n } satisfies PartialTamboAI[\"beta\"];\n\n const mockTamboAI = {\n apiKey: \"\",\n beta: mockBeta,\n bearer: \"\",\n } satisfies PartialTamboAI as unknown as TamboAI;\n\n beforeEach(() => {\n jest.clearAllMocks();\n jest.clearAllTimers();\n jest.useFakeTimers();\n (mockTamboAI as any).bearer = \"\";\n });\n\n afterEach(() => {\n jest.runOnlyPendingTimers();\n jest.useRealTimers();\n });\n\n it(\"should return null initially when no userToken is provided\", () => {\n const { result } = renderHook(() =>\n useTamboSessionToken(mockTamboAI, undefined),\n );\n\n expect(result.current).toBeNull();\n expect(mockAuthApi.getToken).not.toHaveBeenCalled();\n });\n\n it(\"should fetch and return session token when userToken is provided\", async () => {\n jest.mocked(mockAuthApi.getToken).mockResolvedValue(mockTokenResponse);\n\n const { result } = renderHook(() =>\n useTamboSessionToken(mockTamboAI, \"user-token\"),\n );\n\n await act(async () => {\n await jest.runOnlyPendingTimersAsync();\n });\n\n expect(result.current).toBe(\"test-access-token\");\n expect(mockTamboAI.bearer).toBe(\"test-access-token\");\n // Verify the hook was called with correct parameters\n expect(mockAuthApi.getToken).toHaveBeenCalledTimes(1);\n expect(mockAuthApi.getToken).toHaveBeenCalledWith(expect.any(Object));\n });\n\n it(\"should call getToken with correct token exchange parameters\", async () => {\n jest.mocked(mockAuthApi.getToken).mockResolvedValue(mockTokenResponse);\n\n renderHook(() => useTamboSessionToken(mockTamboAI, \"user-token\"));\n\n await act(async () => {\n await jest.runOnlyPendingTimersAsync();\n });\n\n const callArgs = jest.mocked(mockAuthApi.getToken).mock.calls[0][0];\n const tokenRequestString = new TextDecoder().decode(callArgs);\n const tokenRequest = new URLSearchParams(tokenRequestString);\n\n expect(tokenRequest.get(\"grant_type\")).toBe(\n \"urn:ietf:params:oauth:grant-type:token-exchange\",\n );\n expect(tokenRequest.get(\"subject_token\")).toBe(\"user-token\");\n expect(tokenRequest.get(\"subject_token_type\")).toBe(\n \"urn:ietf:params:oauth:token-type:access_token\",\n );\n });\n\n it(\"should set bearer token on client\", async () => {\n jest.mocked(mockAuthApi.getToken).mockResolvedValue(mockTokenResponse);\n\n const { result } = renderHook(() =>\n useTamboSessionToken(mockTamboAI, \"user-token\"),\n );\n\n await act(async () => {\n await jest.runOnlyPendingTimersAsync();\n });\n\n expect(result.current).toBe(\"test-access-token\");\n expect(mockTamboAI.bearer).toBe(\"test-access-token\");\n });\n\n it(\"should handle different token responses\", async () => {\n const customTokenResponse = {\n access_token: \"custom-access-token\",\n expires_in: 7200, // 2 hours\n token_type: \"Bearer\",\n };\n\n jest.mocked(mockAuthApi.getToken).mockResolvedValue(customTokenResponse);\n\n const { result } = renderHook(() =>\n useTamboSessionToken(mockTamboAI, \"user-token\"),\n );\n\n await act(async () => {\n await jest.runOnlyPendingTimersAsync();\n });\n\n expect(result.current).toBe(\"custom-access-token\");\n expect(mockTamboAI.bearer).toBe(\"custom-access-token\");\n });\n\n it(\"should not fetch token when userToken changes to undefined\", async () => {\n jest.mocked(mockAuthApi.getToken).mockResolvedValue(mockTokenResponse);\n\n const { result, rerender } = renderHook(\n ({ userToken }) => useTamboSessionToken(mockTamboAI, userToken),\n {\n initialProps: { userToken: \"user-token\" as string | undefined },\n },\n );\n\n await act(async () => {\n await jest.runOnlyPendingTimersAsync();\n });\n\n expect(result.current).toBe(\"test-access-token\");\n expect(mockAuthApi.getToken).toHaveBeenCalledTimes(1);\n\n // Clear mock and change userToken to undefined\n jest.clearAllMocks();\n\n act(() => {\n rerender({ userToken: undefined });\n });\n\n expect(mockAuthApi.getToken).not.toHaveBeenCalled();\n });\n\n it(\"should refetch token when userToken changes\", async () => {\n jest.mocked(mockAuthApi.getToken).mockResolvedValue(mockTokenResponse);\n\n const { result, rerender } = renderHook(\n ({ userToken }) => useTamboSessionToken(mockTamboAI, userToken),\n {\n initialProps: { userToken: \"user-token-1\" },\n },\n );\n\n await act(async () => {\n await jest.runOnlyPendingTimersAsync();\n });\n\n expect(result.current).toBe(\"test-access-token\");\n expect(mockAuthApi.getToken).toHaveBeenCalledTimes(1);\n\n // Mock response for new token\n jest.mocked(mockAuthApi.getToken).mockResolvedValue({\n ...mockTokenResponse,\n access_token: \"new-access-token\",\n });\n\n // Change userToken\n act(() => {\n rerender({ userToken: \"user-token-2\" });\n });\n\n await act(async () => {\n await jest.runOnlyPendingTimersAsync();\n });\n\n expect(result.current).toBe(\"new-access-token\");\n expect(mockAuthApi.getToken).toHaveBeenCalledTimes(2);\n });\n\n it(\"should reset token when userToken becomes null\", async () => {\n jest.mocked(mockAuthApi.getToken).mockResolvedValue(mockTokenResponse);\n\n const { result, rerender } = renderHook(\n ({ userToken }) => useTamboSessionToken(mockTamboAI, userToken),\n {\n initialProps: { userToken: \"user-token\" as string | undefined },\n },\n );\n\n await act(async () => {\n await jest.runOnlyPendingTimersAsync();\n });\n\n expect(result.current).toBe(\"test-access-token\");\n\n // Change userToken to undefined\n act(() => {\n rerender({ userToken: undefined });\n });\n\n // Token should remain the same (hook doesn't reset it to null when userToken is undefined)\n expect(result.current).toBe(\"test-access-token\");\n });\n\n it(\"should not update state if component is unmounted during token fetch\", async () => {\n let resolvePromise: (value: any) => void;\n const promise = new Promise((resolve) => {\n resolvePromise = resolve;\n });\n\n jest.mocked(mockAuthApi.getToken).mockReturnValue(promise);\n\n const { result, unmount } = renderHook(() =>\n useTamboSessionToken(mockTamboAI, \"user-token\"),\n );\n\n expect(result.current).toBeNull();\n\n // Unmount before the promise resolves\n unmount();\n\n // Now resolve the promise\n act(() => {\n resolvePromise!(mockTokenResponse);\n });\n\n // Token should still be null since component was unmounted\n expect(result.current).toBeNull();\n });\n});\n"]}
1
+ {"version":3,"file":"use-tambo-session-token.test.js","sourceRoot":"","sources":["../../../../src/providers/hooks/__tests__/use-tambo-session-token.test.tsx"],"names":[],"mappings":"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","sourcesContent":["import TamboAI from \"@tambo-ai/typescript-sdk\";\nimport { QueryClient } from \"@tanstack/react-query\";\nimport { act, renderHook } from \"@testing-library/react\";\nimport { DeepPartial } from \"ts-essentials\";\nimport { useTamboSessionToken } from \"../use-tambo-session-token\";\n\ntype PartialTamboAI = DeepPartial<TamboAI>;\n\ndescribe(\"useTamboSessionToken\", () => {\n const mockTokenResponse = {\n access_token: \"test-access-token\",\n expires_in: 3600, // 1 hour\n token_type: \"Bearer\",\n };\n\n const mockAuthApi = {\n getToken: jest.fn(),\n } satisfies DeepPartial<TamboAI[\"beta\"][\"auth\"]>;\n\n const mockBeta = {\n auth: mockAuthApi,\n } satisfies PartialTamboAI[\"beta\"];\n\n const mockTamboAI = {\n apiKey: \"\",\n beta: mockBeta,\n bearer: \"\",\n } satisfies PartialTamboAI as unknown as TamboAI;\n const queryClient = new QueryClient({\n defaultOptions: {\n queries: {\n retry: false,\n refetchOnWindowFocus: false,\n },\n },\n });\n\n beforeEach(() => {\n jest.clearAllMocks();\n jest.clearAllTimers();\n jest.useFakeTimers();\n (mockTamboAI as any).bearer = \"\";\n queryClient.clear();\n });\n\n afterEach(async () => {\n await act(async () => {\n await jest.runOnlyPendingTimersAsync();\n });\n jest.useRealTimers();\n jest.resetAllMocks();\n });\n\n it(\"should return null initially when no userToken is provided\", () => {\n const { result } = renderHook(() =>\n useTamboSessionToken(mockTamboAI, queryClient, undefined),\n );\n\n expect(result.current).toMatchObject({\n data: undefined,\n isFetching: false,\n });\n expect(mockAuthApi.getToken).not.toHaveBeenCalled();\n });\n\n it(\"should fetch and return session token when userToken is provided\", async () => {\n mockAuthApi.getToken.mockResolvedValue(mockTokenResponse);\n\n const { result } = renderHook(() =>\n useTamboSessionToken(mockTamboAI, queryClient, \"user-token\"),\n );\n expect(mockAuthApi.getToken).toHaveBeenCalledTimes(1);\n\n await act(async () => {\n await jest.runOnlyPendingTimersAsync();\n });\n\n expect(result.current).toMatchObject({\n data: mockTokenResponse,\n isFetching: false,\n });\n expect(mockTamboAI.bearer).toBe(mockTokenResponse.access_token);\n // Verify the hook was called with correct parameters\n expect(mockAuthApi.getToken).toHaveBeenCalledTimes(2);\n expect(mockAuthApi.getToken).toHaveBeenCalledWith(expect.any(Object));\n });\n\n it(\"should call getToken with correct token exchange parameters\", async () => {\n mockAuthApi.getToken.mockResolvedValue(mockTokenResponse);\n\n renderHook(() =>\n useTamboSessionToken(mockTamboAI, queryClient, \"user-token\"),\n );\n\n await act(async () => {\n await jest.runOnlyPendingTimersAsync();\n });\n\n const callArgs = mockAuthApi.getToken.mock.calls[0][0];\n const tokenRequestString = new TextDecoder().decode(callArgs);\n const tokenRequest = new URLSearchParams(tokenRequestString);\n\n expect(tokenRequest.get(\"grant_type\")).toBe(\n \"urn:ietf:params:oauth:grant-type:token-exchange\",\n );\n expect(tokenRequest.get(\"subject_token\")).toBe(\"user-token\");\n expect(tokenRequest.get(\"subject_token_type\")).toBe(\n \"urn:ietf:params:oauth:token-type:access_token\",\n );\n });\n\n it(\"should set bearer token on client\", async () => {\n mockAuthApi.getToken.mockResolvedValue(mockTokenResponse);\n\n const { result } = renderHook(() =>\n useTamboSessionToken(mockTamboAI, queryClient, \"user-token\"),\n );\n\n await act(async () => {\n await jest.runOnlyPendingTimersAsync();\n });\n\n expect(result.current).toMatchObject({\n data: mockTokenResponse,\n });\n expect(mockTamboAI.bearer).toBe(\"test-access-token\");\n });\n\n it(\"should handle different token responses\", async () => {\n const customTokenResponse = {\n access_token: \"custom-access-token\",\n expires_in: 7200, // 2 hours\n token_type: \"Bearer\",\n };\n\n mockAuthApi.getToken.mockResolvedValue(customTokenResponse);\n\n const { result } = renderHook(() =>\n useTamboSessionToken(mockTamboAI, queryClient, \"user-token\"),\n );\n expect(result.current).toMatchObject({\n data: undefined,\n isFetching: true,\n });\n\n await act(async () => {\n await jest.runOnlyPendingTimersAsync();\n });\n\n expect(result.current).toMatchObject({\n data: customTokenResponse,\n isFetching: false,\n });\n expect(mockTamboAI.bearer).toBe(\"custom-access-token\");\n });\n\n it(\"should not fetch token when userToken changes to undefined\", async () => {\n mockAuthApi.getToken.mockResolvedValue(mockTokenResponse);\n\n const { result, rerender } = renderHook(\n ({ userToken }) =>\n useTamboSessionToken(mockTamboAI, queryClient, userToken),\n {\n initialProps: { userToken: \"user-token\" as string | undefined },\n },\n );\n expect(mockAuthApi.getToken).toHaveBeenCalledTimes(1);\n\n await act(async () => {\n await jest.runOnlyPendingTimersAsync();\n });\n\n expect(result.current).toMatchObject({\n data: mockTokenResponse,\n isFetching: false,\n });\n expect(mockAuthApi.getToken).toHaveBeenCalledTimes(2);\n\n // Clear mock and change userToken to undefined\n jest.clearAllMocks();\n\n act(() => {\n rerender({ userToken: undefined });\n });\n\n expect(mockAuthApi.getToken).not.toHaveBeenCalled();\n });\n\n it(\"should refetch token when userToken changes\", async () => {\n mockAuthApi.getToken.mockResolvedValue(mockTokenResponse);\n\n const { result, rerender } = renderHook(\n ({ userToken }) =>\n useTamboSessionToken(mockTamboAI, queryClient, userToken),\n {\n initialProps: { userToken: \"user-token-1\" },\n },\n );\n expect(mockAuthApi.getToken).toHaveBeenCalledTimes(1);\n\n await act(async () => {\n await jest.runOnlyPendingTimersAsync();\n });\n\n expect(result.current).toMatchObject({\n data: mockTokenResponse,\n isFetching: false,\n });\n expect(mockAuthApi.getToken).toHaveBeenCalledTimes(2);\n\n // Mock response for new token\n mockAuthApi.getToken.mockResolvedValue({\n ...mockTokenResponse,\n access_token: \"new-access-token\",\n });\n\n // Change userToken\n act(() => {\n rerender({ userToken: \"user-token-2\" });\n });\n\n await act(async () => {\n await jest.runOnlyPendingTimersAsync();\n });\n\n expect(result.current).toMatchObject({\n data: { access_token: \"new-access-token\" },\n isFetching: false,\n });\n expect(mockAuthApi.getToken).toHaveBeenCalledTimes(4);\n });\n\n it(\"should reset token when userToken becomes null\", async () => {\n mockAuthApi.getToken.mockResolvedValue(mockTokenResponse);\n\n const { result, rerender } = renderHook(\n ({ userToken }) =>\n useTamboSessionToken(mockTamboAI, queryClient, userToken),\n {\n initialProps: { userToken: \"user-token\" as string | undefined },\n },\n );\n\n await act(async () => {\n await jest.runOnlyPendingTimersAsync();\n });\n\n expect(result.current).toMatchObject({\n data: mockTokenResponse,\n isFetching: false,\n });\n\n // Change userToken to undefined\n rerender({ userToken: undefined });\n await act(async () => {\n await jest.runAllTimersAsync();\n });\n\n // Token should reset to null (hook doesn't reset it to null when userToken is undefined)\n expect(result.current).toMatchObject({\n data: undefined,\n isFetching: false,\n });\n });\n\n it(\"should not update state if component is unmounted during token fetch\", async () => {\n let resolvePromise: (value: any) => void;\n const promise = new Promise((resolve) => {\n resolvePromise = resolve;\n });\n\n mockAuthApi.getToken.mockReturnValue(promise);\n\n const { result, unmount } = renderHook(() =>\n useTamboSessionToken(mockTamboAI, queryClient, \"user-token\"),\n );\n\n expect(result.current).toMatchObject({\n data: undefined,\n isFetching: true,\n });\n\n // Unmount before the promise resolves\n unmount();\n\n // Now resolve the promise\n act(() => {\n resolvePromise!(mockTokenResponse);\n });\n\n // Token should still be null since component was unmounted\n expect(result.current).toMatchObject({\n data: undefined,\n isFetching: true,\n });\n });\n\n it(\"should set isUpdating to true while fetching token\", () => {\n mockAuthApi.getToken.mockImplementation(async () => {\n return await new Promise(() => {}); // Never resolves\n });\n\n const { result } = renderHook(() =>\n useTamboSessionToken(mockTamboAI, queryClient, \"user-token\"),\n );\n\n // Should be updating immediately when userToken is provided\n expect(result.current).toMatchObject({\n data: undefined,\n isFetching: true,\n });\n });\n\n it(\"should set isUpdating to false after token fetch completes\", async () => {\n mockAuthApi.getToken.mockResolvedValue(mockTokenResponse);\n\n const { result } = renderHook(() =>\n useTamboSessionToken(mockTamboAI, queryClient, \"user-token\"),\n );\n\n // Should be updating initially\n expect(result.current).toMatchObject({\n data: undefined,\n isFetching: true,\n });\n\n await act(async () => {\n await jest.runOnlyPendingTimersAsync();\n });\n\n // Should not be updating after completion\n expect(result.current).toMatchObject({\n data: mockTokenResponse,\n isFetching: false,\n });\n });\n\n it(\"should set isUpdating to false after token fetch fails\", async () => {\n mockAuthApi.getToken.mockRejectedValue(new Error(\"Token fetch failed\"));\n\n const { result } = renderHook(() =>\n useTamboSessionToken(mockTamboAI, queryClient, \"user-token\"),\n );\n\n // Should be updating initially\n expect(result.current).toMatchObject({\n data: undefined,\n isFetching: true,\n });\n\n await act(async () => {\n await jest.runAllTimersAsync();\n });\n\n // Should not be updating after failure\n expect(result.current).toMatchObject({\n data: undefined,\n error: expect.any(Error),\n isFetching: false,\n });\n });\n});\n"]}
@@ -1,4 +1,5 @@
1
1
  import TamboAI from "@tambo-ai/typescript-sdk";
2
+ import { QueryClient } from "@tanstack/react-query";
2
3
  /**
3
4
  * This internal hook is used to get the Tambo session token and keep it
4
5
  * refreshed.
@@ -8,8 +9,9 @@ import TamboAI from "@tambo-ai/typescript-sdk";
8
9
  *
9
10
  * This hook is used by the TamboClientProvider.
10
11
  * @param client - The Tambo client.
12
+ * @param queryClient - The query client.
11
13
  * @param userToken - The user token.
12
14
  * @returns The Tambo session token.
13
15
  */
14
- export declare function useTamboSessionToken(client: TamboAI, userToken: string | undefined): string | null;
16
+ export declare function useTamboSessionToken(client: TamboAI, queryClient: QueryClient, userToken: string | undefined): import("@tanstack/react-query").UseQueryResult<TamboAI.Beta.Auth.AuthGetTokenResponse, Error>;
15
17
  //# sourceMappingURL=use-tambo-session-token.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"use-tambo-session-token.d.ts","sourceRoot":"","sources":["../../../src/providers/hooks/use-tambo-session-token.tsx"],"names":[],"mappings":"AACA,OAAO,OAAO,MAAM,0BAA0B,CAAC;AAG/C;;;;;;;;;;;GAWG;AACH,wBAAgB,oBAAoB,CAClC,MAAM,EAAE,OAAO,EACf,SAAS,EAAE,MAAM,GAAG,SAAS,iBAiE9B"}
1
+ {"version":3,"file":"use-tambo-session-token.d.ts","sourceRoot":"","sources":["../../../src/providers/hooks/use-tambo-session-token.tsx"],"names":[],"mappings":"AACA,OAAO,OAAO,MAAM,0BAA0B,CAAC;AAC/C,OAAO,EAAE,WAAW,EAAY,MAAM,uBAAuB,CAAC;AAG9D;;;;;;;;;;;;GAYG;AACH,wBAAgB,oBAAoB,CAClC,MAAM,EAAE,OAAO,EACf,WAAW,EAAE,WAAW,EACxB,SAAS,EAAE,MAAM,GAAG,SAAS,iGAmC9B"}
@@ -1,5 +1,6 @@
1
1
  "use client";
2
- import { useEffect, useState } from "react";
2
+ import { useQuery } from "@tanstack/react-query";
3
+ import { useEffect } from "react";
3
4
  /**
4
5
  * This internal hook is used to get the Tambo session token and keep it
5
6
  * refreshed.
@@ -9,54 +10,36 @@ import { useEffect, useState } from "react";
9
10
  *
10
11
  * This hook is used by the TamboClientProvider.
11
12
  * @param client - The Tambo client.
13
+ * @param queryClient - The query client.
12
14
  * @param userToken - The user token.
13
15
  * @returns The Tambo session token.
14
16
  */
15
- export function useTamboSessionToken(client, userToken) {
16
- const [tamboSessionToken, setTamboSessionToken] = useState(null);
17
- // we need to set this to true when the token is expired, this is effectively
18
- // like a dirty bit, which will trigger a new useEffect()
19
- const [isExpired, setIsExpired] = useState(true);
20
- useEffect(() => {
21
- let expireTimer = null;
22
- async function updateToken(subjectToken, abortController) {
23
- if (abortController.signal.aborted || !userToken) {
24
- return;
25
- }
17
+ export function useTamboSessionToken(client, queryClient, userToken) {
18
+ const result = useQuery({
19
+ queryKey: ["tambo-session-token", userToken],
20
+ queryFn: async () => {
26
21
  const tokenRequest = {
27
22
  grant_type: "urn:ietf:params:oauth:grant-type:token-exchange",
28
- subject_token: subjectToken,
23
+ // will only be undefined if the userToken is not provided, in which case the query will be disabled.
24
+ subject_token: userToken,
29
25
  subject_token_type: "urn:ietf:params:oauth:token-type:access_token",
30
26
  };
31
27
  const tokenRequestFormEncoded = new URLSearchParams(tokenRequest).toString();
32
28
  const tokenAsArrayBuffer = new TextEncoder().encode(tokenRequestFormEncoded);
33
- const tamboToken = await client.beta.auth.getToken(tokenAsArrayBuffer);
34
- if (abortController.signal.aborted) {
35
- return;
29
+ return await client.beta.auth.getToken(tokenAsArrayBuffer);
30
+ },
31
+ enabled: !!userToken,
32
+ refetchInterval: (result) => {
33
+ if (result.state.data?.expires_in) {
34
+ return result.state.data.expires_in * 1000;
36
35
  }
37
- setTamboSessionToken(tamboToken.access_token);
38
- client.bearer = tamboToken.access_token;
39
- // we need to set a timer to refresh the token when it expires
40
- const refreshTime = Math.max(tamboToken.expires_in - 60, 0);
41
- // careful with the assignment here: since this is an async function, this
42
- // code is executed outside the of the scope of the useEffect() hook, so
43
- // we need to use a let variable to store the timer
44
- expireTimer = setTimeout(() => {
45
- setIsExpired(true);
46
- }, refreshTime * 1000);
47
- }
48
- const abortController = new AbortController();
49
- if (userToken && isExpired) {
50
- updateToken(userToken, abortController);
51
- }
52
- return () => {
53
- // This fires when the component unmounts or the userToken changes
54
- abortController.abort();
55
- if (expireTimer) {
56
- clearTimeout(expireTimer);
57
- }
58
- };
59
- }, [client, isExpired, userToken]);
60
- return tamboSessionToken;
36
+ return false;
37
+ },
38
+ }, queryClient);
39
+ const accessToken = result.data?.access_token ?? null;
40
+ useEffect(() => {
41
+ client.bearer = accessToken;
42
+ }, [accessToken, client]);
43
+ return result;
61
44
  }
62
45
  //# sourceMappingURL=use-tambo-session-token.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"use-tambo-session-token.js","sourceRoot":"","sources":["../../../src/providers/hooks/use-tambo-session-token.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAEb,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAE5C;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,oBAAoB,CAClC,MAAe,EACf,SAA6B;IAE7B,MAAM,CAAC,iBAAiB,EAAE,oBAAoB,CAAC,GAAG,QAAQ,CACxD,IAAI,CACL,CAAC;IACF,6EAA6E;IAC7E,yDAAyD;IACzD,MAAM,CAAC,SAAS,EAAE,YAAY,CAAC,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC;IACjD,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,WAAW,GAA0B,IAAI,CAAC;QAE9C,KAAK,UAAU,WAAW,CACxB,YAAoB,EACpB,eAAgC;YAEhC,IAAI,eAAe,CAAC,MAAM,CAAC,OAAO,IAAI,CAAC,SAAS,EAAE,CAAC;gBACjD,OAAO;YACT,CAAC;YACD,MAAM,YAAY,GAAG;gBACnB,UAAU,EAAE,iDAAiD;gBAC7D,aAAa,EAAE,YAAY;gBAC3B,kBAAkB,EAAE,+CAA+C;aACpE,CAAC;YACF,MAAM,uBAAuB,GAAG,IAAI,eAAe,CACjD,YAAY,CACb,CAAC,QAAQ,EAAE,CAAC;YACb,MAAM,kBAAkB,GAAG,IAAI,WAAW,EAAE,CAAC,MAAM,CACjD,uBAAuB,CACxB,CAAC;YACF,MAAM,UAAU,GAAG,MAAM,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAChD,kBAAyB,CAC1B,CAAC;YAEF,IAAI,eAAe,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;gBACnC,OAAO;YACT,CAAC;YACD,oBAAoB,CAAC,UAAU,CAAC,YAAY,CAAC,CAAC;YAC9C,MAAM,CAAC,MAAM,GAAG,UAAU,CAAC,YAAY,CAAC;YAExC,8DAA8D;YAC9D,MAAM,WAAW,GAAG,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,UAAU,GAAG,EAAE,EAAE,CAAC,CAAC,CAAC;YAE5D,0EAA0E;YAC1E,wEAAwE;YACxE,mDAAmD;YACnD,WAAW,GAAG,UAAU,CAAC,GAAG,EAAE;gBAC5B,YAAY,CAAC,IAAI,CAAC,CAAC;YACrB,CAAC,EAAE,WAAW,GAAG,IAAI,CAAC,CAAC;QACzB,CAAC;QAED,MAAM,eAAe,GAAG,IAAI,eAAe,EAAE,CAAC;QAC9C,IAAI,SAAS,IAAI,SAAS,EAAE,CAAC;YAC3B,WAAW,CAAC,SAAS,EAAE,eAAe,CAAC,CAAC;QAC1C,CAAC;QAED,OAAO,GAAG,EAAE;YACV,kEAAkE;YAClE,eAAe,CAAC,KAAK,EAAE,CAAC;YACxB,IAAI,WAAW,EAAE,CAAC;gBAChB,YAAY,CAAC,WAAW,CAAC,CAAC;YAC5B,CAAC;QACH,CAAC,CAAC;IACJ,CAAC,EAAE,CAAC,MAAM,EAAE,SAAS,EAAE,SAAS,CAAC,CAAC,CAAC;IAEnC,OAAO,iBAAiB,CAAC;AAC3B,CAAC","sourcesContent":["\"use client\";\nimport TamboAI from \"@tambo-ai/typescript-sdk\";\nimport { useEffect, useState } from \"react\";\n\n/**\n * This internal hook is used to get the Tambo session token and keep it\n * refreshed.\n *\n * It will refresh the token when it expires.\n * It will also set the bearer token on the client.\n *\n * This hook is used by the TamboClientProvider.\n * @param client - The Tambo client.\n * @param userToken - The user token.\n * @returns The Tambo session token.\n */\nexport function useTamboSessionToken(\n client: TamboAI,\n userToken: string | undefined,\n) {\n const [tamboSessionToken, setTamboSessionToken] = useState<string | null>(\n null,\n );\n // we need to set this to true when the token is expired, this is effectively\n // like a dirty bit, which will trigger a new useEffect()\n const [isExpired, setIsExpired] = useState(true);\n useEffect(() => {\n let expireTimer: NodeJS.Timeout | null = null;\n\n async function updateToken(\n subjectToken: string,\n abortController: AbortController,\n ) {\n if (abortController.signal.aborted || !userToken) {\n return;\n }\n const tokenRequest = {\n grant_type: \"urn:ietf:params:oauth:grant-type:token-exchange\",\n subject_token: subjectToken,\n subject_token_type: \"urn:ietf:params:oauth:token-type:access_token\",\n };\n const tokenRequestFormEncoded = new URLSearchParams(\n tokenRequest,\n ).toString();\n const tokenAsArrayBuffer = new TextEncoder().encode(\n tokenRequestFormEncoded,\n );\n const tamboToken = await client.beta.auth.getToken(\n tokenAsArrayBuffer as any,\n );\n\n if (abortController.signal.aborted) {\n return;\n }\n setTamboSessionToken(tamboToken.access_token);\n client.bearer = tamboToken.access_token;\n\n // we need to set a timer to refresh the token when it expires\n const refreshTime = Math.max(tamboToken.expires_in - 60, 0);\n\n // careful with the assignment here: since this is an async function, this\n // code is executed outside the of the scope of the useEffect() hook, so\n // we need to use a let variable to store the timer\n expireTimer = setTimeout(() => {\n setIsExpired(true);\n }, refreshTime * 1000);\n }\n\n const abortController = new AbortController();\n if (userToken && isExpired) {\n updateToken(userToken, abortController);\n }\n\n return () => {\n // This fires when the component unmounts or the userToken changes\n abortController.abort();\n if (expireTimer) {\n clearTimeout(expireTimer);\n }\n };\n }, [client, isExpired, userToken]);\n\n return tamboSessionToken;\n}\n"]}
1
+ {"version":3,"file":"use-tambo-session-token.js","sourceRoot":"","sources":["../../../src/providers/hooks/use-tambo-session-token.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAEb,OAAO,EAAe,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAC9D,OAAO,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAElC;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,oBAAoB,CAClC,MAAe,EACf,WAAwB,EACxB,SAA6B;IAE7B,MAAM,MAAM,GAAG,QAAQ,CACrB;QACE,QAAQ,EAAE,CAAC,qBAAqB,EAAE,SAAS,CAAC;QAC5C,OAAO,EAAE,KAAK,IAAI,EAAE;YAClB,MAAM,YAAY,GAAG;gBACnB,UAAU,EAAE,iDAAiD;gBAC7D,qGAAqG;gBACrG,aAAa,EAAE,SAAU;gBACzB,kBAAkB,EAAE,+CAA+C;aACpE,CAAC;YACF,MAAM,uBAAuB,GAAG,IAAI,eAAe,CACjD,YAAY,CACb,CAAC,QAAQ,EAAE,CAAC;YACb,MAAM,kBAAkB,GAAG,IAAI,WAAW,EAAE,CAAC,MAAM,CACjD,uBAAuB,CACxB,CAAC;YACF,OAAO,MAAM,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,kBAAyB,CAAC,CAAC;QACpE,CAAC;QACD,OAAO,EAAE,CAAC,CAAC,SAAS;QACpB,eAAe,EAAE,CAAC,MAAM,EAAE,EAAE;YAC1B,IAAI,MAAM,CAAC,KAAK,CAAC,IAAI,EAAE,UAAU,EAAE,CAAC;gBAClC,OAAO,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC;YAC7C,CAAC;YACD,OAAO,KAAK,CAAC;QACf,CAAC;KACF,EACD,WAAW,CACZ,CAAC;IACF,MAAM,WAAW,GAAG,MAAM,CAAC,IAAI,EAAE,YAAY,IAAI,IAAI,CAAC;IACtD,SAAS,CAAC,GAAG,EAAE;QACb,MAAM,CAAC,MAAM,GAAG,WAAW,CAAC;IAC9B,CAAC,EAAE,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC,CAAC;IAC1B,OAAO,MAAM,CAAC;AAChB,CAAC","sourcesContent":["\"use client\";\nimport TamboAI from \"@tambo-ai/typescript-sdk\";\nimport { QueryClient, useQuery } from \"@tanstack/react-query\";\nimport { useEffect } from \"react\";\n\n/**\n * This internal hook is used to get the Tambo session token and keep it\n * refreshed.\n *\n * It will refresh the token when it expires.\n * It will also set the bearer token on the client.\n *\n * This hook is used by the TamboClientProvider.\n * @param client - The Tambo client.\n * @param queryClient - The query client.\n * @param userToken - The user token.\n * @returns The Tambo session token.\n */\nexport function useTamboSessionToken(\n client: TamboAI,\n queryClient: QueryClient,\n userToken: string | undefined,\n) {\n const result = useQuery(\n {\n queryKey: [\"tambo-session-token\", userToken],\n queryFn: async () => {\n const tokenRequest = {\n grant_type: \"urn:ietf:params:oauth:grant-type:token-exchange\",\n // will only be undefined if the userToken is not provided, in which case the query will be disabled.\n subject_token: userToken!,\n subject_token_type: \"urn:ietf:params:oauth:token-type:access_token\",\n };\n const tokenRequestFormEncoded = new URLSearchParams(\n tokenRequest,\n ).toString();\n const tokenAsArrayBuffer = new TextEncoder().encode(\n tokenRequestFormEncoded,\n );\n return await client.beta.auth.getToken(tokenAsArrayBuffer as any);\n },\n enabled: !!userToken,\n refetchInterval: (result) => {\n if (result.state.data?.expires_in) {\n return result.state.data.expires_in * 1000;\n }\n return false;\n },\n },\n queryClient,\n );\n const accessToken = result.data?.access_token ?? null;\n useEffect(() => {\n client.bearer = accessToken;\n }, [accessToken, client]);\n return result;\n}\n"]}
@@ -7,5 +7,6 @@ export type { StreamStateComponentProps, StreamStatus, TamboPropStreamContextVal
7
7
  export { TamboContext, TamboProvider, useTambo } from "./tambo-provider";
8
8
  export { TamboRegistryProvider, useTamboRegistry, type TamboRegistryContext, } from "./tambo-registry-provider";
9
9
  export { TamboStubProvider, type TamboStubProviderProps } from "./tambo-stubs";
10
+ export { TamboThreadInputProvider, useTamboThreadInput, type TamboThreadInputContextProps, } from "./tambo-thread-input-provider";
10
11
  export { TamboThreadContext, TamboThreadProvider, useTamboGenerationStage, useTamboThread, } from "./tambo-thread-provider";
11
12
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/providers/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,6BAA6B,CAAC;AAC7E,OAAO,EAAE,mBAAmB,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AAC9E,OAAO,EACL,sBAAsB,EACtB,iBAAiB,GAClB,MAAM,4BAA4B,CAAC;AACpC,OAAO,EACL,2BAA2B,EAC3B,sBAAsB,EACtB,KAAK,+BAA+B,EACpC,KAAK,gCAAgC,GACtC,MAAM,kCAAkC,CAAC;AAC1C,OAAO,EACL,OAAO,EACP,SAAS,EACT,OAAO,EACP,uBAAuB,EACvB,cAAc,GACf,MAAM,8BAA8B,CAAC;AACtC,YAAY,EACV,yBAAyB,EACzB,YAAY,EACZ,2BAA2B,GAC5B,MAAM,8BAA8B,CAAC;AACtC,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AACzE,OAAO,EACL,qBAAqB,EACrB,gBAAgB,EAChB,KAAK,oBAAoB,GAC1B,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAAE,iBAAiB,EAAE,KAAK,sBAAsB,EAAE,MAAM,eAAe,CAAC;AAC/E,OAAO,EACL,kBAAkB,EAClB,mBAAmB,EACnB,uBAAuB,EACvB,cAAc,GACf,MAAM,yBAAyB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/providers/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,6BAA6B,CAAC;AAC7E,OAAO,EAAE,mBAAmB,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AAC9E,OAAO,EACL,sBAAsB,EACtB,iBAAiB,GAClB,MAAM,4BAA4B,CAAC;AACpC,OAAO,EACL,2BAA2B,EAC3B,sBAAsB,EACtB,KAAK,+BAA+B,EACpC,KAAK,gCAAgC,GACtC,MAAM,kCAAkC,CAAC;AAC1C,OAAO,EACL,OAAO,EACP,SAAS,EACT,OAAO,EACP,uBAAuB,EACvB,cAAc,GACf,MAAM,8BAA8B,CAAC;AACtC,YAAY,EACV,yBAAyB,EACzB,YAAY,EACZ,2BAA2B,GAC5B,MAAM,8BAA8B,CAAC;AACtC,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AACzE,OAAO,EACL,qBAAqB,EACrB,gBAAgB,EAChB,KAAK,oBAAoB,GAC1B,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAAE,iBAAiB,EAAE,KAAK,sBAAsB,EAAE,MAAM,eAAe,CAAC;AAC/E,OAAO,EACL,wBAAwB,EACxB,mBAAmB,EACnB,KAAK,4BAA4B,GAClC,MAAM,+BAA+B,CAAC;AACvC,OAAO,EACL,kBAAkB,EAClB,mBAAmB,EACnB,uBAAuB,EACvB,cAAc,GACf,MAAM,yBAAyB,CAAC"}
@@ -5,5 +5,6 @@ export { Pending, Streaming, Success, TamboPropStreamProvider, useTamboStream, }
5
5
  export { TamboContext, TamboProvider, useTambo } from "./tambo-provider";
6
6
  export { TamboRegistryProvider, useTamboRegistry, } from "./tambo-registry-provider";
7
7
  export { TamboStubProvider } from "./tambo-stubs";
8
+ export { TamboThreadInputProvider, useTamboThreadInput, } from "./tambo-thread-input-provider";
8
9
  export { TamboThreadContext, TamboThreadProvider, useTamboGenerationStage, useTamboThread, } from "./tambo-thread-provider";
9
10
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/providers/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,mBAAmB,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AAC9E,OAAO,EACL,sBAAsB,EACtB,iBAAiB,GAClB,MAAM,4BAA4B,CAAC;AACpC,OAAO,EACL,2BAA2B,EAC3B,sBAAsB,GAGvB,MAAM,kCAAkC,CAAC;AAC1C,OAAO,EACL,OAAO,EACP,SAAS,EACT,OAAO,EACP,uBAAuB,EACvB,cAAc,GACf,MAAM,8BAA8B,CAAC;AAMtC,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AACzE,OAAO,EACL,qBAAqB,EACrB,gBAAgB,GAEjB,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAAE,iBAAiB,EAA+B,MAAM,eAAe,CAAC;AAC/E,OAAO,EACL,kBAAkB,EAClB,mBAAmB,EACnB,uBAAuB,EACvB,cAAc,GACf,MAAM,yBAAyB,CAAC","sourcesContent":["export type { TamboComponent, TamboTool } from \"../model/component-metadata\";\nexport { TamboClientProvider, useTamboClient } from \"./tambo-client-provider\";\nexport {\n TamboComponentProvider,\n useTamboComponent,\n} from \"./tambo-component-provider\";\nexport {\n TamboContextHelpersProvider,\n useTamboContextHelpers,\n type TamboContextHelpersContextProps,\n type TamboContextHelpersProviderProps,\n} from \"./tambo-context-helpers-provider\";\nexport {\n Pending,\n Streaming,\n Success,\n TamboPropStreamProvider,\n useTamboStream,\n} from \"./tambo-prop-stream-provider\";\nexport type {\n StreamStateComponentProps,\n StreamStatus,\n TamboPropStreamContextValue,\n} from \"./tambo-prop-stream-provider\";\nexport { TamboContext, TamboProvider, useTambo } from \"./tambo-provider\";\nexport {\n TamboRegistryProvider,\n useTamboRegistry,\n type TamboRegistryContext,\n} from \"./tambo-registry-provider\";\nexport { TamboStubProvider, type TamboStubProviderProps } from \"./tambo-stubs\";\nexport {\n TamboThreadContext,\n TamboThreadProvider,\n useTamboGenerationStage,\n useTamboThread,\n} from \"./tambo-thread-provider\";\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/providers/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,mBAAmB,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AAC9E,OAAO,EACL,sBAAsB,EACtB,iBAAiB,GAClB,MAAM,4BAA4B,CAAC;AACpC,OAAO,EACL,2BAA2B,EAC3B,sBAAsB,GAGvB,MAAM,kCAAkC,CAAC;AAC1C,OAAO,EACL,OAAO,EACP,SAAS,EACT,OAAO,EACP,uBAAuB,EACvB,cAAc,GACf,MAAM,8BAA8B,CAAC;AAMtC,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AACzE,OAAO,EACL,qBAAqB,EACrB,gBAAgB,GAEjB,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAAE,iBAAiB,EAA+B,MAAM,eAAe,CAAC;AAC/E,OAAO,EACL,wBAAwB,EACxB,mBAAmB,GAEpB,MAAM,+BAA+B,CAAC;AACvC,OAAO,EACL,kBAAkB,EAClB,mBAAmB,EACnB,uBAAuB,EACvB,cAAc,GACf,MAAM,yBAAyB,CAAC","sourcesContent":["export type { TamboComponent, TamboTool } from \"../model/component-metadata\";\nexport { TamboClientProvider, useTamboClient } from \"./tambo-client-provider\";\nexport {\n TamboComponentProvider,\n useTamboComponent,\n} from \"./tambo-component-provider\";\nexport {\n TamboContextHelpersProvider,\n useTamboContextHelpers,\n type TamboContextHelpersContextProps,\n type TamboContextHelpersProviderProps,\n} from \"./tambo-context-helpers-provider\";\nexport {\n Pending,\n Streaming,\n Success,\n TamboPropStreamProvider,\n useTamboStream,\n} from \"./tambo-prop-stream-provider\";\nexport type {\n StreamStateComponentProps,\n StreamStatus,\n TamboPropStreamContextValue,\n} from \"./tambo-prop-stream-provider\";\nexport { TamboContext, TamboProvider, useTambo } from \"./tambo-provider\";\nexport {\n TamboRegistryProvider,\n useTamboRegistry,\n type TamboRegistryContext,\n} from \"./tambo-registry-provider\";\nexport { TamboStubProvider, type TamboStubProviderProps } from \"./tambo-stubs\";\nexport {\n TamboThreadInputProvider,\n useTamboThreadInput,\n type TamboThreadInputContextProps,\n} from \"./tambo-thread-input-provider\";\nexport {\n TamboThreadContext,\n TamboThreadProvider,\n useTamboGenerationStage,\n useTamboThread,\n} from \"./tambo-thread-provider\";\n"]}
@@ -28,6 +28,8 @@ export interface TamboClientContextProps {
28
28
  client: TamboAI;
29
29
  /** The tambo-specific query client */
30
30
  queryClient: QueryClient;
31
+ /** Whether the session token is currently being updated */
32
+ isUpdatingToken: boolean;
31
33
  }
32
34
  export declare const TamboClientContext: React.Context<TamboClientContextProps | undefined>;
33
35
  /**
@@ -55,4 +57,9 @@ export declare const useTamboClient: () => TamboAI;
55
57
  * @private
56
58
  */
57
59
  export declare const useTamboQueryClient: () => QueryClient;
60
+ /**
61
+ * Hook to check if the session token is currently being updated
62
+ * @returns true if the token is being refreshed, false otherwise
63
+ */
64
+ export declare const useIsTamboTokenUpdating: () => boolean;
58
65
  //# sourceMappingURL=tambo-client-provider.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"tambo-client-provider.d.ts","sourceRoot":"","sources":["../../src/providers/tambo-client-provider.tsx"],"names":[],"mappings":"AACA,OAAO,OAA0B,MAAM,0BAA0B,CAAC;AAClE,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AACpD,OAAO,KAAK,EAAE,EAAiB,iBAAiB,EAAY,MAAM,OAAO,CAAC;AAI1E,MAAM,WAAW,wBAAwB;IACvC;;OAEG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;;OAGG;IACH,MAAM,EAAE,MAAM,CAAC;IACf;;OAEG;IACH,WAAW,CAAC,EAAE,YAAY,GAAG,SAAS,CAAC;IAEvC;;;;;OAKG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,uBAAuB;IACtC,yBAAyB;IACzB,MAAM,EAAE,OAAO,CAAC;IAChB,sCAAsC;IACtC,WAAW,EAAE,WAAW,CAAC;CAC1B;AAED,eAAO,MAAM,kBAAkB,oDAEnB,CAAC;AAEb;;;;;;;;;;GAUG;AACH,eAAO,MAAM,mBAAmB,EAAE,KAAK,CAAC,EAAE,CACxC,iBAAiB,CAAC,wBAAwB,CAAC,CAyB5C,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,cAAc,eAM1B,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,mBAAmB,mBAQ/B,CAAC"}
1
+ {"version":3,"file":"tambo-client-provider.d.ts","sourceRoot":"","sources":["../../src/providers/tambo-client-provider.tsx"],"names":[],"mappings":"AACA,OAAO,OAA0B,MAAM,0BAA0B,CAAC;AAClE,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AACpD,OAAO,KAAK,EAAE,EAAiB,iBAAiB,EAAY,MAAM,OAAO,CAAC;AAI1E,MAAM,WAAW,wBAAwB;IACvC;;OAEG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;;OAGG;IACH,MAAM,EAAE,MAAM,CAAC;IACf;;OAEG;IACH,WAAW,CAAC,EAAE,YAAY,GAAG,SAAS,CAAC;IAEvC;;;;;OAKG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,uBAAuB;IACtC,yBAAyB;IACzB,MAAM,EAAE,OAAO,CAAC;IAChB,sCAAsC;IACtC,WAAW,EAAE,WAAW,CAAC;IACzB,2DAA2D;IAC3D,eAAe,EAAE,OAAO,CAAC;CAC1B;AAED,eAAO,MAAM,kBAAkB,oDAEnB,CAAC;AAEb;;;;;;;;;;GAUG;AACH,eAAO,MAAM,mBAAmB,EAAE,KAAK,CAAC,EAAE,CACxC,iBAAiB,CAAC,wBAAwB,CAAC,CAmC5C,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,cAAc,eAM1B,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,mBAAmB,mBAQ/B,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,uBAAuB,eAQnC,CAAC"}
@@ -31,9 +31,13 @@ export const TamboClientProvider = ({ children, tamboUrl, apiKey, environment, u
31
31
  }
32
32
  const [client] = useState(() => new TamboAI(tamboConfig));
33
33
  const [queryClient] = useState(() => new QueryClient());
34
- // Keep the session token updated
35
- useTamboSessionToken(client, userToken);
36
- return (React.createElement(TamboClientContext.Provider, { value: { client, queryClient } }, children));
34
+ // Keep the session token updated and get the updating state
35
+ const { isFetching: isUpdatingToken } = useTamboSessionToken(client, queryClient, userToken);
36
+ return (React.createElement(TamboClientContext.Provider, { value: {
37
+ client,
38
+ queryClient,
39
+ isUpdatingToken,
40
+ } }, children));
37
41
  };
38
42
  /**
39
43
  * The useTamboClient hook provides access to the TamboAI client
@@ -60,4 +64,15 @@ export const useTamboQueryClient = () => {
60
64
  }
61
65
  return context.queryClient;
62
66
  };
67
+ /**
68
+ * Hook to check if the session token is currently being updated
69
+ * @returns true if the token is being refreshed, false otherwise
70
+ */
71
+ export const useIsTamboTokenUpdating = () => {
72
+ const context = React.useContext(TamboClientContext);
73
+ if (context === undefined) {
74
+ throw new Error("useIsTamboTokenUpdating must be used within a TamboClientProvider");
75
+ }
76
+ return context.isUpdatingToken;
77
+ };
63
78
  //# sourceMappingURL=tambo-client-provider.js.map