@merit-systems/echo-next-sdk 0.0.3 → 0.0.5

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/client.d.ts CHANGED
@@ -1,3 +1,5 @@
1
+ import { EchoConfig, EchoClient } from '@merit-systems/echo-typescript-sdk';
2
+
1
3
  interface EchoClientConfig {
2
4
  basePath?: string;
3
5
  }
@@ -5,6 +7,20 @@ interface EchoClientConfig {
5
7
  * Sign in to Echo (client-side only)
6
8
  */
7
9
  declare function signIn(config?: EchoClientConfig): void;
8
- declare function refreshToken(config?: EchoClientConfig): void;
10
+ /**
11
+ * Create an Echo client for client-side usage (React components, hooks)
12
+ * Uses relative URLs that work in the browser
13
+ */
14
+ declare function createEchoClient(config?: EchoConfig): EchoClient;
15
+ /**
16
+ * Pre-configured Echo client for client-side usage
17
+ * Ready to use in React components
18
+ */
19
+ declare const echoClient: EchoClient;
20
+ /**
21
+ * React hook to get the Echo client
22
+ * Provides a consistent way to access the client in components
23
+ */
24
+ declare function useEcho(config?: EchoConfig): EchoClient;
9
25
 
10
- export { type EchoClientConfig, refreshToken, signIn };
26
+ export { type EchoClientConfig, createEchoClient, echoClient, signIn, useEcho };
package/dist/client.js CHANGED
@@ -1,4 +1,5 @@
1
1
  // src/client.ts
2
+ import { EchoClient } from "@merit-systems/echo-typescript-sdk";
2
3
  function signIn(config) {
3
4
  if (typeof window === "undefined") {
4
5
  console.warn("signIn() can only be called in client components");
@@ -7,16 +8,25 @@ function signIn(config) {
7
8
  const basePath = config?.basePath || "/api/echo";
8
9
  window.location.href = `${window.location.origin}${basePath}/signin`;
9
10
  }
10
- function refreshToken(config) {
11
- if (typeof window === "undefined") {
12
- console.warn("refreshToken() can only be called in client components");
13
- return;
11
+ function createEchoClient(config) {
12
+ const proxyPath = config?.basePath ? `${config.basePath}/proxy` : "/api/echo/proxy";
13
+ return new EchoClient({
14
+ baseUrl: proxyPath,
15
+ // No apiKey needed - proxy handles authentication automatically
16
+ apiKey: "next-sdk-proxy"
17
+ });
18
+ }
19
+ var echoClient = createEchoClient();
20
+ function useEcho(config) {
21
+ if (config) {
22
+ return createEchoClient(config);
14
23
  }
15
- const basePath = config?.basePath || "/api/echo";
16
- window.location.href = `${window.location.origin}${basePath}/refresh`;
24
+ return echoClient;
17
25
  }
18
26
  export {
19
- refreshToken,
20
- signIn
27
+ createEchoClient,
28
+ echoClient,
29
+ signIn,
30
+ useEcho
21
31
  };
22
32
  //# sourceMappingURL=client.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/client.ts"],"sourcesContent":["export interface EchoClientConfig {\n basePath?: string;\n}\n\n/**\n * Sign in to Echo (client-side only)\n */\nexport function signIn(config?: EchoClientConfig) {\n if (typeof window === 'undefined') {\n console.warn('signIn() can only be called in client components');\n return;\n }\n\n const basePath = config?.basePath || '/api/echo';\n window.location.href = `${window.location.origin}${basePath}/signin`;\n}\n\nexport function refreshToken(config?: EchoClientConfig) {\n if (typeof window === 'undefined') {\n console.warn('refreshToken() can only be called in client components');\n return;\n }\n\n const basePath = config?.basePath || '/api/echo';\n window.location.href = `${window.location.origin}${basePath}/refresh`;\n}\n"],"mappings":";AAOO,SAAS,OAAO,QAA2B;AAChD,MAAI,OAAO,WAAW,aAAa;AACjC,YAAQ,KAAK,kDAAkD;AAC/D;AAAA,EACF;AAEA,QAAM,WAAW,QAAQ,YAAY;AACrC,SAAO,SAAS,OAAO,GAAG,OAAO,SAAS,MAAM,GAAG,QAAQ;AAC7D;AAEO,SAAS,aAAa,QAA2B;AACtD,MAAI,OAAO,WAAW,aAAa;AACjC,YAAQ,KAAK,wDAAwD;AACrE;AAAA,EACF;AAEA,QAAM,WAAW,QAAQ,YAAY;AACrC,SAAO,SAAS,OAAO,GAAG,OAAO,SAAS,MAAM,GAAG,QAAQ;AAC7D;","names":[]}
1
+ {"version":3,"sources":["../src/client.ts"],"sourcesContent":["import { EchoClient, EchoConfig } from '@merit-systems/echo-typescript-sdk';\n\nexport interface EchoClientConfig {\n basePath?: string;\n}\n\n/**\n * Sign in to Echo (client-side only)\n */\nexport function signIn(config?: EchoClientConfig) {\n if (typeof window === 'undefined') {\n console.warn('signIn() can only be called in client components');\n return;\n }\n\n const basePath = config?.basePath || '/api/echo';\n window.location.href = `${window.location.origin}${basePath}/signin`;\n}\n\n/**\n * Create an Echo client for client-side usage (React components, hooks)\n * Uses relative URLs that work in the browser\n */\nexport function createEchoClient(config?: EchoConfig): EchoClient {\n const proxyPath = config?.basePath\n ? `${config.basePath}/proxy`\n : '/api/echo/proxy';\n\n return new EchoClient({\n baseUrl: proxyPath,\n // No apiKey needed - proxy handles authentication automatically\n apiKey: 'next-sdk-proxy',\n });\n}\n\n/**\n * Pre-configured Echo client for client-side usage\n * Ready to use in React components\n */\nexport const echoClient = createEchoClient();\n\n/**\n * React hook to get the Echo client\n * Provides a consistent way to access the client in components\n */\nexport function useEcho(config?: EchoConfig): EchoClient {\n if (config) {\n return createEchoClient(config);\n }\n return echoClient;\n}\n"],"mappings":";AAAA,SAAS,kBAA8B;AAShC,SAAS,OAAO,QAA2B;AAChD,MAAI,OAAO,WAAW,aAAa;AACjC,YAAQ,KAAK,kDAAkD;AAC/D;AAAA,EACF;AAEA,QAAM,WAAW,QAAQ,YAAY;AACrC,SAAO,SAAS,OAAO,GAAG,OAAO,SAAS,MAAM,GAAG,QAAQ;AAC7D;AAMO,SAAS,iBAAiB,QAAiC;AAChE,QAAM,YAAY,QAAQ,WACtB,GAAG,OAAO,QAAQ,WAClB;AAEJ,SAAO,IAAI,WAAW;AAAA,IACpB,SAAS;AAAA;AAAA,IAET,QAAQ;AAAA,EACV,CAAC;AACH;AAMO,IAAM,aAAa,iBAAiB;AAMpC,SAAS,QAAQ,QAAiC;AACvD,MAAI,QAAQ;AACV,WAAO,iBAAiB,MAAM;AAAA,EAChC;AACA,SAAO;AACT;","names":[]}
package/dist/index.d.ts CHANGED
@@ -1,10 +1,20 @@
1
- import { User, EchoOpenAIProvider, EchoAnthropicProvider } from '@merit-systems/echo-typescript-sdk';
1
+ import { User, EchoOpenAIProvider, EchoAnthropicProvider, EchoGoogleProvider } from '@merit-systems/echo-typescript-sdk';
2
2
  import { NextRequest } from 'next/server';
3
3
 
4
4
  interface EchoConfig {
5
+ /**
6
+ * Echo App ID.
7
+ */
5
8
  appId: string;
9
+ /**
10
+ * Base path of API URL.
11
+ * @default /api/echo
12
+ */
6
13
  basePath?: string;
14
+ /** @internal */
7
15
  baseRouterUrl?: string;
16
+ /** @internal */
17
+ baseEchoUrl?: string;
8
18
  }
9
19
  type AppRouteHandlers = Record<'GET' | 'POST', (req: NextRequest) => Promise<Response>>;
10
20
  type EchoResult = {
@@ -13,6 +23,7 @@ type EchoResult = {
13
23
  isSignedIn: () => Promise<boolean>;
14
24
  openai: EchoOpenAIProvider;
15
25
  anthropic: EchoAnthropicProvider;
26
+ google: EchoGoogleProvider;
16
27
  };
17
28
 
18
29
  /**
package/dist/index.js CHANGED
@@ -1,13 +1,20 @@
1
1
  // src/index.ts
2
- import { NextResponse as NextResponse2 } from "next/server";
2
+ import { cookies } from "next/headers";
3
+ import { NextResponse as NextResponse3 } from "next/server";
4
+ import { EchoClient as EchoClient2 } from "@merit-systems/echo-typescript-sdk";
3
5
 
4
6
  // src/auth/token-manager.ts
5
7
  import {
6
- EchoClient,
7
- ECHO_BASE_URL
8
+ EchoClient
8
9
  } from "@merit-systems/echo-typescript-sdk";
9
10
  import { cookies as getCookies } from "next/headers";
10
11
 
12
+ // src/config.ts
13
+ import { ECHO_BASE_URL } from "@merit-systems/echo-typescript-sdk";
14
+ function resolveEchoBaseUrl(config) {
15
+ return config.baseEchoUrl || ECHO_BASE_URL;
16
+ }
17
+
11
18
  // src/auth/jwt-utils.ts
12
19
  import { jwtDecode } from "jwt-decode";
13
20
  function shouldRefreshToken(token) {
@@ -23,14 +30,14 @@ function shouldRefreshToken(token) {
23
30
  }
24
31
 
25
32
  // src/auth/token-manager.ts
26
- async function performTokenRefresh(refreshToken, appId) {
27
- return fetch(`${ECHO_BASE_URL}/api/oauth/token`, {
33
+ async function performTokenRefresh(refreshToken, config) {
34
+ return fetch(`${resolveEchoBaseUrl(config)}/api/oauth/token`, {
28
35
  method: "POST",
29
36
  headers: { "Content-Type": "application/json" },
30
37
  body: JSON.stringify({
31
38
  grant_type: "refresh_token",
32
39
  refresh_token: refreshToken,
33
- client_id: appId
40
+ client_id: config.appId
34
41
  })
35
42
  }).then(async (r) => {
36
43
  if (r.ok) {
@@ -40,7 +47,7 @@ async function performTokenRefresh(refreshToken, appId) {
40
47
  return Promise.reject(new Error(await r.text()));
41
48
  });
42
49
  }
43
- async function getEchoToken(appId) {
50
+ async function getEchoToken(config) {
44
51
  const cookies2 = await getCookies();
45
52
  const accessToken = cookies2.get("echo_access_token")?.value;
46
53
  if (!accessToken || shouldRefreshToken(accessToken)) {
@@ -50,7 +57,7 @@ async function getEchoToken(appId) {
50
57
  return null;
51
58
  }
52
59
  try {
53
- const refreshResult = await performTokenRefresh(refreshToken, appId);
60
+ const refreshResult = await performTokenRefresh(refreshToken, config);
54
61
  cookies2.set("echo_access_token", refreshResult.access_token, {
55
62
  httpOnly: true,
56
63
  secure: process.env.NODE_ENV === "production",
@@ -89,22 +96,66 @@ async function getEchoToken(appId) {
89
96
 
90
97
  // src/providers/anthropic.ts
91
98
  import {
92
- createEchoAnthropic as createEchoAnthropicBase,
93
- ROUTER_BASE_URL
99
+ createEchoAnthropic as createEchoAnthropicBase
94
100
  } from "@merit-systems/echo-typescript-sdk";
95
- function createEchoAnthropic({
96
- appId,
97
- baseRouterUrl = ROUTER_BASE_URL
98
- }) {
99
- return createEchoAnthropicBase(
100
- { appId, baseRouterUrl },
101
- async () => getEchoToken(appId)
102
- );
101
+ function createEchoAnthropic(config) {
102
+ return createEchoAnthropicBase(config, async () => getEchoToken(config));
103
103
  }
104
104
 
105
- // src/auth/oauth-handlers.ts
105
+ // src/providers/google.ts
106
+ import {
107
+ createEchoGoogle as createEchoGoogleBase
108
+ } from "@merit-systems/echo-typescript-sdk";
109
+ function createEchoGoogle(config) {
110
+ return createEchoGoogleBase(config, async () => getEchoToken(config));
111
+ }
112
+
113
+ // src/providers/openai.ts
114
+ import {
115
+ createEchoOpenAI as createEchoOpenAIBase
116
+ } from "@merit-systems/echo-typescript-sdk";
117
+ function createEchoOpenAI(config) {
118
+ return createEchoOpenAIBase(config, async () => getEchoToken(config));
119
+ }
120
+
121
+ // src/proxy/index.ts
106
122
  import { NextResponse } from "next/server";
107
- import { ECHO_BASE_URL as ECHO_BASE_URL2 } from "@merit-systems/echo-typescript-sdk";
123
+ async function handleEchoClientProxy(req, config) {
124
+ const proxyPath = req.nextUrl.pathname.replace(/^.*\/proxy/, "");
125
+ const baseUrl = config.baseEchoUrl || "https://echo.merit.systems";
126
+ const targetUrl = `${baseUrl}${proxyPath}`;
127
+ const headers = new Headers(req.headers);
128
+ headers.delete("host");
129
+ headers.delete("accept-encoding");
130
+ headers.set("accept-encoding", "identity");
131
+ headers.delete("if-none-match");
132
+ headers.delete("if-modified-since");
133
+ const accessToken = await getEchoToken(config);
134
+ if (!accessToken) {
135
+ return NextResponse.json(
136
+ { error: "Authentication required" },
137
+ { status: 401 }
138
+ );
139
+ }
140
+ headers.set("Authorization", `Bearer ${accessToken}`);
141
+ try {
142
+ const response = await fetch(targetUrl, {
143
+ method: req.method,
144
+ headers,
145
+ ...req.method !== "GET" && req.method !== "HEAD" && { body: req.body }
146
+ });
147
+ return response;
148
+ } catch (error) {
149
+ console.error("Proxy request failed:", error);
150
+ return NextResponse.json(
151
+ { error: "Proxy request failed" },
152
+ { status: 500 }
153
+ );
154
+ }
155
+ }
156
+
157
+ // src/auth/oauth-handlers.ts
158
+ import { NextResponse as NextResponse2 } from "next/server";
108
159
  async function generateCodeChallenge() {
109
160
  const codeVerifier = Array.from(crypto.getRandomValues(new Uint8Array(32))).map((b) => b.toString(16).padStart(2, "0")).join("");
110
161
  const encoder = new TextEncoder();
@@ -120,14 +171,15 @@ async function generateCodeChallenge() {
120
171
  async function handleSignIn(req, config) {
121
172
  const { origin } = req.nextUrl;
122
173
  const basePath = config.basePath || "/api/echo";
123
- const redirectUrl = new URL(`${ECHO_BASE_URL2}/api/oauth/authorize`);
174
+ const baseUrl = resolveEchoBaseUrl(config);
175
+ const redirectUrl = new URL(`${baseUrl}/api/oauth/authorize`);
124
176
  redirectUrl.searchParams.set("client_id", config.appId);
125
177
  redirectUrl.searchParams.set("redirect_uri", `${origin}${basePath}/callback`);
126
178
  redirectUrl.searchParams.set("response_type", "code");
127
179
  const { codeVerifier, codeChallenge } = await generateCodeChallenge();
128
180
  redirectUrl.searchParams.set("code_challenge", codeChallenge);
129
181
  redirectUrl.searchParams.set("code_challenge_method", "S256");
130
- const response = NextResponse.redirect(redirectUrl.toString());
182
+ const response = NextResponse2.redirect(redirectUrl.toString());
131
183
  response.cookies.set("echo_code_verifier", codeVerifier, {
132
184
  httpOnly: true,
133
185
  secure: process.env.NODE_ENV === "production",
@@ -144,16 +196,16 @@ async function handleCallback(req, config) {
144
196
  const code = req.nextUrl.searchParams.get("code");
145
197
  const state = req.nextUrl.searchParams.get("state");
146
198
  if (!code || !state) {
147
- return NextResponse.json({ error: "Invalid request" }, { status: 400 });
199
+ return NextResponse2.json({ error: "Invalid request" }, { status: 400 });
148
200
  }
149
201
  const codeVerifier = req.cookies.get("echo_code_verifier")?.value;
150
202
  if (!codeVerifier) {
151
- return NextResponse.json(
203
+ return NextResponse2.json(
152
204
  { error: "Code verifier not found. Please try signing in again." },
153
205
  { status: 400 }
154
206
  );
155
207
  }
156
- const tokenEndpoint = `${ECHO_BASE_URL2}/api/oauth/token`;
208
+ const tokenEndpoint = `${resolveEchoBaseUrl(config)}/api/oauth/token`;
157
209
  const params = new URLSearchParams();
158
210
  params.set("grant_type", "authorization_code");
159
211
  params.set("code", code);
@@ -163,18 +215,20 @@ async function handleCallback(req, config) {
163
215
  const tokenResponse = await fetch(tokenEndpoint, {
164
216
  method: "POST",
165
217
  headers: {
166
- "Content-Type": "application/x-www-form-urlencoded"
218
+ "Content-Type": "application/x-www-form-urlencoded",
219
+ "x-client-user-agent": req.headers.get("user-agent") || "",
220
+ "x-client-ip": req.headers.get("x-forwarded-for")?.split(",")[0]?.trim() || ""
167
221
  },
168
222
  body: params.toString()
169
223
  });
170
224
  if (!tokenResponse.ok) {
171
- return NextResponse.json(
225
+ return NextResponse2.json(
172
226
  { error: "Token exchange failed" },
173
227
  { status: 500 }
174
228
  );
175
229
  }
176
230
  const tokenData = await tokenResponse.json();
177
- const response = NextResponse.redirect(`${origin}`);
231
+ const response = NextResponse2.redirect(`${origin}`);
178
232
  response.cookies.set("echo_code_verifier", "", {
179
233
  httpOnly: true,
180
234
  secure: process.env.NODE_ENV === "production",
@@ -214,44 +268,31 @@ async function handleCallback(req, config) {
214
268
  }
215
269
  async function handleRefresh(req, config) {
216
270
  try {
217
- const token = await getEchoToken(config.appId);
271
+ const token = await getEchoToken(config);
218
272
  if (!token) {
219
- return NextResponse.json({ error: "No token found" }, { status: 401 });
273
+ return NextResponse2.json({ error: "No token found" }, { status: 401 });
220
274
  }
221
- return NextResponse.json({ success: true });
275
+ return NextResponse2.json({ success: true });
222
276
  } catch (error) {
223
277
  console.error("Error refreshing token:", error);
224
- return NextResponse.json(
278
+ return NextResponse2.json(
225
279
  { error: "Error refreshing token" },
226
280
  { status: 500 }
227
281
  );
228
282
  }
229
283
  }
230
284
 
231
- // src/providers/openai.ts
232
- import {
233
- createEchoOpenAI as createEchoOpenAIBase,
234
- ROUTER_BASE_URL as ROUTER_BASE_URL2
235
- } from "@merit-systems/echo-typescript-sdk";
236
- function createEchoOpenAI({
237
- appId,
238
- baseRouterUrl = ROUTER_BASE_URL2
239
- }) {
240
- return createEchoOpenAIBase(
241
- { appId, baseRouterUrl },
242
- async () => getEchoToken(appId)
243
- );
244
- }
245
-
246
285
  // src/index.ts
247
- import { EchoClient as EchoClient2, ECHO_BASE_URL as ECHO_BASE_URL3 } from "@merit-systems/echo-typescript-sdk";
248
- import { cookies } from "next/headers";
249
286
  function Echo(config) {
250
287
  const httpHandler = async (req) => {
251
288
  const { pathname } = req.nextUrl;
252
289
  const basePath = config.basePath || "/api/echo";
253
290
  const path = pathname.replace(basePath, "");
291
+ if (path.startsWith("/proxy")) {
292
+ return handleEchoClientProxy(req, config);
293
+ }
254
294
  switch (path) {
295
+ // all the auth stuff
255
296
  case "/signin":
256
297
  return handleSignIn(req, config);
257
298
  case "/callback":
@@ -259,7 +300,8 @@ function Echo(config) {
259
300
  case "/refresh":
260
301
  return handleRefresh(req, config);
261
302
  default:
262
- return NextResponse2.error();
303
+ console.error("Unknown path", path);
304
+ return NextResponse3.error();
263
305
  }
264
306
  };
265
307
  const getUser = async () => {
@@ -268,10 +310,8 @@ function Echo(config) {
268
310
  if (!accessToken) {
269
311
  return null;
270
312
  }
271
- const echo = new EchoClient2({
272
- apiKey: accessToken,
273
- baseUrl: ECHO_BASE_URL3
274
- });
313
+ const baseUrl = resolveEchoBaseUrl(config);
314
+ const echo = new EchoClient2({ apiKey: accessToken, baseUrl });
275
315
  const user = await echo.users.getUserInfo();
276
316
  return user;
277
317
  };
@@ -288,16 +328,18 @@ function Echo(config) {
288
328
  return expiryTime > now;
289
329
  };
290
330
  return {
331
+ // HTTP handlers for Next.js API routes
291
332
  handlers: {
292
333
  GET: httpHandler,
293
334
  POST: httpHandler
294
335
  },
295
- // echo auth
336
+ // Authentication utilities (server-side only)
296
337
  getUser,
297
338
  isSignedIn,
298
- // providers
339
+ // AI provider clients
299
340
  openai: createEchoOpenAI(config),
300
- anthropic: createEchoAnthropic(config)
341
+ anthropic: createEchoAnthropic(config),
342
+ google: createEchoGoogle(config)
301
343
  };
302
344
  }
303
345
  export {
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/auth/token-manager.ts","../src/auth/jwt-utils.ts","../src/providers/anthropic.ts","../src/auth/oauth-handlers.ts","../src/providers/openai.ts"],"sourcesContent":["import { NextRequest, NextResponse } from 'next/server';\nimport { createEchoAnthropic } from 'providers/anthropic';\nimport {\n handleCallback,\n handleRefresh,\n handleSignIn,\n} from './auth/oauth-handlers';\nimport { createEchoOpenAI } from './providers/openai';\nimport { EchoConfig, EchoResult } from './types';\nimport { EchoClient, ECHO_BASE_URL } from '@merit-systems/echo-typescript-sdk';\nimport { cookies } from 'next/headers';\n\n/**\n * Echo SDK for Next.js\n * Provides OAuth authentication and token management for Echo API integration\n */\nexport default function Echo(config: EchoConfig): EchoResult {\n /**\n * HTTP handler for OAuth routes (signin and callback)\n */\n const httpHandler = async (req: NextRequest): Promise<Response> => {\n const { pathname } = req.nextUrl;\n const basePath = config.basePath || '/api/echo';\n const path = pathname.replace(basePath, '');\n\n switch (path) {\n case '/signin':\n return handleSignIn(req, config);\n\n case '/callback':\n return handleCallback(req, config);\n\n case '/refresh':\n return handleRefresh(req, config);\n\n default:\n return NextResponse.error();\n }\n };\n\n /**\n * Get current user info with automatic token refresh\n */\n const getUser = async () => {\n // read only access token, if expired we are fucked\n const cookieStore = await cookies();\n const accessToken = cookieStore.get('echo_access_token')?.value;\n if (!accessToken) {\n return null;\n }\n const echo = new EchoClient({\n apiKey: accessToken,\n baseUrl: ECHO_BASE_URL,\n });\n const user = await echo.users.getUserInfo();\n return user;\n };\n\n const isSignedIn = async () => {\n const cookieStore = await cookies();\n const refreshTokenExpiry = cookieStore.get(\n 'echo_refresh_token_expires'\n )?.value;\n\n if (!refreshTokenExpiry) {\n return false; // No expiry stored\n }\n\n const expiryTime = parseInt(refreshTokenExpiry);\n const now = Math.floor(Date.now() / 1000);\n\n return expiryTime > now; // True if not expired\n };\n\n return {\n handlers: {\n GET: httpHandler,\n POST: httpHandler,\n },\n // echo auth\n getUser,\n isSignedIn,\n // providers\n openai: createEchoOpenAI(config),\n anthropic: createEchoAnthropic(config),\n };\n}\n","import {\n EchoClient,\n ECHO_BASE_URL,\n User,\n} from '@merit-systems/echo-typescript-sdk';\nimport { cookies as getCookies } from 'next/headers';\nimport { shouldRefreshToken } from './jwt-utils';\n\nexport interface RefreshTokenResponse {\n access_token: string;\n token_type: string;\n expires_in: number;\n refresh_token: string;\n refresh_token_expires_in: number;\n scope: string;\n user: {\n id: string;\n email: string;\n name: string;\n };\n echo_app: {\n id: string;\n name: string;\n description: string;\n };\n}\n\n/**\n * Refresh an access token using a refresh token\n * @param refreshToken - The refresh token to use\n * @param appId - The Echo app ID\n * @returns Promise resolving to the new token data\n */\nexport async function performTokenRefresh(\n refreshToken: string,\n appId: string\n): Promise<RefreshTokenResponse> {\n return fetch(`${ECHO_BASE_URL}/api/oauth/token`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n grant_type: 'refresh_token',\n refresh_token: refreshToken,\n client_id: appId,\n }),\n }).then(async r => {\n if (r.ok) {\n const tokenData = (await r.json()) as RefreshTokenResponse;\n return tokenData;\n }\n return Promise.reject(new Error(await r.text()));\n });\n}\n\n/**\n * Get a valid Echo token, refreshing if necessary\n * @param appId - The Echo app ID for token refresh\n * @returns Promise resolving to a valid access token or null if authentication failed\n */\nexport async function getEchoToken(appId: string): Promise<string | null> {\n const cookies = await getCookies();\n const accessToken = cookies.get('echo_access_token')?.value;\n\n // Check if token needs refresh\n if (!accessToken || shouldRefreshToken(accessToken)) {\n const refreshToken = cookies.get('echo_refresh_token')?.value;\n\n if (!refreshToken) {\n console.log('No refresh token found');\n return null;\n }\n\n try {\n const refreshResult = await performTokenRefresh(refreshToken, appId);\n\n // Set new tokens in cookies\n cookies.set('echo_access_token', refreshResult.access_token, {\n httpOnly: true,\n secure: process.env.NODE_ENV === 'production',\n sameSite: 'lax',\n maxAge: refreshResult.expires_in,\n path: '/',\n });\n\n cookies.set('echo_refresh_token', refreshResult.refresh_token, {\n httpOnly: true,\n secure: process.env.NODE_ENV === 'production',\n sameSite: 'lax',\n maxAge: refreshResult.refresh_token_expires_in,\n path: '/',\n });\n\n // Store refresh token expiry time for checking\n cookies.set(\n 'echo_refresh_token_expires',\n String(\n Math.floor(Date.now() / 1000) + refreshResult.refresh_token_expires_in\n ),\n {\n httpOnly: true,\n secure: process.env.NODE_ENV === 'production',\n sameSite: 'lax',\n maxAge: refreshResult.refresh_token_expires_in,\n path: '/',\n }\n );\n\n return refreshResult.access_token;\n } catch (error) {\n console.error('Token refresh failed:', refreshToken, error);\n return null;\n }\n }\n\n return accessToken;\n}\n\nexport async function getUser(appId: string): Promise<User> {\n const echo = await getEchoClient(appId);\n if (!echo) {\n throw new Error('User not signed in');\n }\n return echo.users.getUserInfo();\n}\n\nexport async function getEchoClient(appId: string): Promise<EchoClient | null> {\n const token = await getEchoToken(appId);\n if (!token) {\n return null;\n }\n return new EchoClient({\n baseUrl: ECHO_BASE_URL,\n apiKey: token,\n });\n}\n","import { jwtDecode } from 'jwt-decode';\n\ninterface JwtPayload {\n exp?: number;\n}\n\n/**\n * Check if a JWT token needs to be refreshed\n * @param token - The JWT access token to check\n * @returns true if token should be refreshed, false otherwise\n */\nexport function shouldRefreshToken(token: string): boolean {\n try {\n const decoded = jwtDecode<JwtPayload>(token);\n if (!decoded.exp) return true;\n\n const now = Math.floor(Date.now() / 1000);\n // Refresh if token expires within 30 seconds\n const bufferTime = 30;\n return decoded.exp <= now + bufferTime;\n } catch {\n return true; // If we can't decode, assume it needs refresh\n }\n}\n","import { getEchoToken } from '../auth/token-manager';\nimport {\n createEchoAnthropic as createEchoAnthropicBase,\n EchoAnthropicProvider,\n EchoConfig,\n ROUTER_BASE_URL,\n} from '@merit-systems/echo-typescript-sdk';\n\nexport function createEchoAnthropic({\n appId,\n baseRouterUrl = ROUTER_BASE_URL,\n}: EchoConfig): EchoAnthropicProvider {\n return createEchoAnthropicBase({ appId, baseRouterUrl }, async () =>\n getEchoToken(appId)\n );\n}\n","import { NextRequest, NextResponse } from 'next/server';\nimport { getEchoToken, RefreshTokenResponse } from './token-manager';\nimport { EchoConfig, ECHO_BASE_URL } from '@merit-systems/echo-typescript-sdk';\n\n/**\n * Generate PKCE code challenge and verifier\n * @returns Object containing code verifier and challenge\n */\nasync function generateCodeChallenge(): Promise<{\n codeVerifier: string;\n codeChallenge: string;\n}> {\n const codeVerifier = Array.from(crypto.getRandomValues(new Uint8Array(32)))\n .map(b => b.toString(16).padStart(2, '0'))\n .join('');\n\n const encoder = new TextEncoder();\n const codeChallengeBuffer = await crypto.subtle.digest(\n 'SHA-256',\n encoder.encode(codeVerifier)\n );\n\n const codeChallenge = btoa(\n String.fromCharCode(...new Uint8Array(codeChallengeBuffer))\n )\n .replace(/\\+/g, '-')\n .replace(/\\//g, '_')\n .replace(/=+$/, '');\n\n return { codeVerifier, codeChallenge };\n}\n\n/**\n * Handle OAuth signin request - redirect to Echo authorization server\n * @param req - The incoming Next.js request\n * @param config - Echo configuration\n * @returns NextResponse with redirect to authorization server\n */\nexport async function handleSignIn(\n req: NextRequest,\n config: EchoConfig\n): Promise<NextResponse> {\n const { origin } = req.nextUrl;\n const basePath = config.basePath || '/api/echo';\n\n const redirectUrl = new URL(`${ECHO_BASE_URL}/api/oauth/authorize`);\n redirectUrl.searchParams.set('client_id', config.appId);\n redirectUrl.searchParams.set('redirect_uri', `${origin}${basePath}/callback`);\n redirectUrl.searchParams.set('response_type', 'code');\n\n const { codeVerifier, codeChallenge } = await generateCodeChallenge();\n\n redirectUrl.searchParams.set('code_challenge', codeChallenge);\n redirectUrl.searchParams.set('code_challenge_method', 'S256');\n\n // Create response with redirect and set cookie for code verifier\n const response = NextResponse.redirect(redirectUrl.toString());\n\n // Set the code verifier in a secure cookie that will be available during callback\n response.cookies.set('echo_code_verifier', codeVerifier, {\n httpOnly: true,\n secure: process.env.NODE_ENV === 'production',\n sameSite: 'lax',\n maxAge: 300, // 5 minutes - same as auth code TTL\n path: '/',\n });\n\n return response;\n}\n\n/**\n * Handle OAuth callback - exchange authorization code for tokens\n * @param req - The incoming Next.js request\n * @param config - Echo configuration\n * @returns NextResponse with redirect to home page and tokens set as cookies\n */\nexport async function handleCallback(\n req: NextRequest,\n config: EchoConfig\n): Promise<NextResponse> {\n const { origin } = req.nextUrl;\n const basePath = config.basePath || '/api/echo';\n\n const code = req.nextUrl.searchParams.get('code');\n const state = req.nextUrl.searchParams.get('state');\n\n if (!code || !state) {\n return NextResponse.json({ error: 'Invalid request' }, { status: 400 });\n }\n\n // Retrieve the code verifier from the cookie\n const codeVerifier = req.cookies.get('echo_code_verifier')?.value;\n\n if (!codeVerifier) {\n return NextResponse.json(\n { error: 'Code verifier not found. Please try signing in again.' },\n { status: 400 }\n );\n }\n\n // Exchange the code for a token from the token endpoint\n const tokenEndpoint = `${ECHO_BASE_URL}/api/oauth/token`;\n\n const params = new URLSearchParams();\n params.set('grant_type', 'authorization_code');\n params.set('code', code);\n params.set('redirect_uri', `${origin}${basePath}/callback`);\n params.set('client_id', config.appId);\n params.set('code_verifier', codeVerifier);\n\n const tokenResponse = await fetch(tokenEndpoint, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/x-www-form-urlencoded',\n },\n body: params.toString(),\n });\n\n if (!tokenResponse.ok) {\n return NextResponse.json(\n { error: 'Token exchange failed' },\n { status: 500 }\n );\n }\n\n const tokenData = (await tokenResponse.json()) as RefreshTokenResponse;\n\n const response = NextResponse.redirect(`${origin}`);\n\n // Clear the code verifier cookie after successful token exchange\n response.cookies.set('echo_code_verifier', '', {\n httpOnly: true,\n secure: process.env.NODE_ENV === 'production',\n sameSite: 'lax',\n maxAge: 0, // Expire immediately\n path: '/',\n });\n\n // Set the access token as a cookie\n response.cookies.set('echo_access_token', tokenData.access_token, {\n httpOnly: true,\n secure: process.env.NODE_ENV === 'production',\n sameSite: 'lax',\n maxAge: tokenData.expires_in, // expires_in is typically in seconds\n path: '/',\n });\n\n tokenData.refresh_token_expires_in;\n\n response.cookies.set('echo_refresh_token', tokenData.refresh_token, {\n httpOnly: true,\n secure: process.env.NODE_ENV === 'production',\n sameSite: 'lax',\n maxAge: tokenData.refresh_token_expires_in,\n path: '/',\n });\n\n // Store refresh token expiry time for checking\n response.cookies.set(\n 'echo_refresh_token_expires',\n String(Math.floor(Date.now() / 1000) + tokenData.refresh_token_expires_in),\n {\n httpOnly: true,\n secure: process.env.NODE_ENV === 'production',\n sameSite: 'lax',\n maxAge: tokenData.refresh_token_expires_in,\n path: '/',\n }\n );\n\n return response;\n}\n\nexport async function handleRefresh(\n req: NextRequest,\n config: EchoConfig\n): Promise<NextResponse> {\n try {\n const token = await getEchoToken(config.appId);\n if (!token) {\n return NextResponse.json({ error: 'No token found' }, { status: 401 });\n }\n\n return NextResponse.json({ success: true });\n } catch (error) {\n console.error('Error refreshing token:', error);\n return NextResponse.json(\n { error: 'Error refreshing token' },\n { status: 500 }\n );\n }\n}\n","import { getEchoToken } from '../auth/token-manager';\nimport {\n createEchoOpenAI as createEchoOpenAIBase,\n EchoConfig,\n EchoOpenAIProvider,\n ROUTER_BASE_URL,\n} from '@merit-systems/echo-typescript-sdk';\n\nexport function createEchoOpenAI({\n appId,\n baseRouterUrl = ROUTER_BASE_URL,\n}: EchoConfig): EchoOpenAIProvider {\n return createEchoOpenAIBase({ appId, baseRouterUrl }, async () =>\n getEchoToken(appId)\n );\n}\n"],"mappings":"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","names":["NextResponse","cookies","ECHO_BASE_URL","ROUTER_BASE_URL","EchoClient","ECHO_BASE_URL","NextResponse"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/auth/token-manager.ts","../src/config.ts","../src/auth/jwt-utils.ts","../src/providers/anthropic.ts","../src/providers/google.ts","../src/providers/openai.ts","../src/proxy/index.ts","../src/auth/oauth-handlers.ts"],"sourcesContent":["import { cookies } from 'next/headers';\nimport { NextRequest, NextResponse } from 'next/server';\n\nimport { EchoClient } from '@merit-systems/echo-typescript-sdk';\nimport { EchoConfig, EchoResult } from './types';\n\nimport { createEchoAnthropic } from 'providers/anthropic';\nimport { createEchoGoogle } from 'providers/google';\nimport { createEchoOpenAI } from 'providers/openai';\n\nimport { resolveEchoBaseUrl } from 'config';\nimport { handleEchoClientProxy } from 'proxy';\nimport {\n handleCallback,\n handleRefresh,\n handleSignIn,\n} from './auth/oauth-handlers';\n\n/**\n * Echo SDK for Next.js\n * Provides OAuth authentication and token management for Echo API integration\n */\nexport default function Echo(config: EchoConfig): EchoResult {\n /**\n * HTTP handler for OAuth routes (signin and callback)\n */\n const httpHandler = async (req: NextRequest): Promise<Response> => {\n const { pathname } = req.nextUrl;\n const basePath = config.basePath || '/api/echo';\n const path = pathname.replace(basePath, '');\n\n if (path.startsWith('/proxy')) {\n return handleEchoClientProxy(req, config);\n }\n\n switch (path) {\n // all the auth stuff\n case '/signin':\n return handleSignIn(req, config);\n\n case '/callback':\n return handleCallback(req, config);\n\n case '/refresh':\n return handleRefresh(req, config);\n\n default:\n console.error('Unknown path', path);\n return NextResponse.error();\n }\n };\n\n /**\n * Get current user info with automatic token refresh\n */\n const getUser = async () => {\n // read only access token, if expired we are fucked\n const cookieStore = await cookies();\n const accessToken = cookieStore.get('echo_access_token')?.value;\n if (!accessToken) {\n return null;\n }\n const baseUrl = resolveEchoBaseUrl(config);\n const echo = new EchoClient({ apiKey: accessToken, baseUrl });\n const user = await echo.users.getUserInfo();\n return user;\n };\n\n const isSignedIn = async () => {\n const cookieStore = await cookies();\n const refreshTokenExpiry = cookieStore.get(\n 'echo_refresh_token_expires'\n )?.value;\n\n if (!refreshTokenExpiry) {\n return false; // No expiry stored\n }\n\n const expiryTime = parseInt(refreshTokenExpiry);\n const now = Math.floor(Date.now() / 1000);\n\n return expiryTime > now; // True if not expired\n };\n\n return {\n // HTTP handlers for Next.js API routes\n handlers: {\n GET: httpHandler,\n POST: httpHandler,\n },\n\n // Authentication utilities (server-side only)\n getUser,\n isSignedIn,\n\n // AI provider clients\n openai: createEchoOpenAI(config),\n anthropic: createEchoAnthropic(config),\n google: createEchoGoogle(config),\n };\n}\n","import {\n EchoClient,\n EchoConfig,\n User,\n} from '@merit-systems/echo-typescript-sdk';\nimport { cookies as getCookies } from 'next/headers';\nimport { resolveEchoBaseUrl } from '../config';\nimport { shouldRefreshToken } from './jwt-utils';\n\nexport interface RefreshTokenResponse {\n access_token: string;\n token_type: string;\n expires_in: number;\n refresh_token: string;\n refresh_token_expires_in: number;\n scope: string;\n user: {\n id: string;\n email: string;\n name: string;\n };\n echo_app: {\n id: string;\n name: string;\n description: string;\n };\n}\n\n/**\n * Refresh an access token using a refresh token\n * @param refreshToken - The refresh token to use\n * @param appId - The Echo app ID\n * @returns Promise resolving to the new token data\n */\nexport async function performTokenRefresh(\n refreshToken: string,\n config: EchoConfig\n): Promise<RefreshTokenResponse> {\n return fetch(`${resolveEchoBaseUrl(config)}/api/oauth/token`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n grant_type: 'refresh_token',\n refresh_token: refreshToken,\n client_id: config.appId,\n }),\n }).then(async r => {\n if (r.ok) {\n const tokenData = (await r.json()) as RefreshTokenResponse;\n return tokenData;\n }\n return Promise.reject(new Error(await r.text()));\n });\n}\n\n/**\n * Get a valid Echo token, refreshing if necessary\n * @param appId - The Echo app ID for token refresh\n * @returns Promise resolving to a valid access token or null if authentication failed\n */\nexport async function getEchoToken(config: EchoConfig): Promise<string | null> {\n const cookies = await getCookies();\n const accessToken = cookies.get('echo_access_token')?.value;\n\n // Check if token needs refresh\n if (!accessToken || shouldRefreshToken(accessToken)) {\n const refreshToken = cookies.get('echo_refresh_token')?.value;\n\n if (!refreshToken) {\n console.log('No refresh token found');\n return null;\n }\n\n try {\n const refreshResult = await performTokenRefresh(refreshToken, config);\n\n // Set new tokens in cookies\n cookies.set('echo_access_token', refreshResult.access_token, {\n httpOnly: true,\n secure: process.env.NODE_ENV === 'production',\n sameSite: 'lax',\n maxAge: refreshResult.expires_in,\n path: '/',\n });\n\n cookies.set('echo_refresh_token', refreshResult.refresh_token, {\n httpOnly: true,\n secure: process.env.NODE_ENV === 'production',\n sameSite: 'lax',\n maxAge: refreshResult.refresh_token_expires_in,\n path: '/',\n });\n\n // Store refresh token expiry time for checking\n cookies.set(\n 'echo_refresh_token_expires',\n String(\n Math.floor(Date.now() / 1000) + refreshResult.refresh_token_expires_in\n ),\n {\n httpOnly: true,\n secure: process.env.NODE_ENV === 'production',\n sameSite: 'lax',\n maxAge: refreshResult.refresh_token_expires_in,\n path: '/',\n }\n );\n\n return refreshResult.access_token;\n } catch (error) {\n console.error('Token refresh failed:', refreshToken, error);\n return null;\n }\n }\n\n return accessToken;\n}\n\nexport async function getUser(config: EchoConfig): Promise<User> {\n const echo = await getEchoClient(config);\n if (!echo) {\n throw new Error('User not signed in');\n }\n return echo.users.getUserInfo();\n}\n\nexport async function getEchoClient(\n config: EchoConfig\n): Promise<EchoClient | null> {\n const token = await getEchoToken(config);\n if (!token) {\n return null;\n }\n return new EchoClient({\n baseUrl: resolveEchoBaseUrl(config),\n apiKey: token,\n });\n}\n","import { ECHO_BASE_URL } from '@merit-systems/echo-typescript-sdk';\nimport type { EchoConfig } from './types';\n\nexport function resolveEchoBaseUrl(config: EchoConfig): string {\n return config.baseEchoUrl || ECHO_BASE_URL;\n}\n","import { jwtDecode } from 'jwt-decode';\n\ninterface JwtPayload {\n exp?: number;\n}\n\n/**\n * Check if a JWT token needs to be refreshed\n * @param token - The JWT access token to check\n * @returns true if token should be refreshed, false otherwise\n */\nexport function shouldRefreshToken(token: string): boolean {\n try {\n const decoded = jwtDecode<JwtPayload>(token);\n if (!decoded.exp) return true;\n\n const now = Math.floor(Date.now() / 1000);\n // Refresh if token expires within 30 seconds\n const bufferTime = 30;\n return decoded.exp <= now + bufferTime;\n } catch {\n return true; // If we can't decode, assume it needs refresh\n }\n}\n","import { getEchoToken } from '../auth/token-manager';\nimport {\n createEchoAnthropic as createEchoAnthropicBase,\n EchoAnthropicProvider,\n EchoConfig,\n} from '@merit-systems/echo-typescript-sdk';\n\nexport function createEchoAnthropic(config: EchoConfig): EchoAnthropicProvider {\n return createEchoAnthropicBase(config, async () => getEchoToken(config));\n}\n","import {\n createEchoGoogle as createEchoGoogleBase,\n EchoConfig,\n EchoGoogleProvider,\n} from '@merit-systems/echo-typescript-sdk';\nimport { getEchoToken } from '../auth/token-manager';\n\nexport function createEchoGoogle(config: EchoConfig): EchoGoogleProvider {\n return createEchoGoogleBase(config, async () => getEchoToken(config));\n}\n","import { getEchoToken } from '../auth/token-manager';\nimport {\n createEchoOpenAI as createEchoOpenAIBase,\n EchoConfig,\n EchoOpenAIProvider,\n} from '@merit-systems/echo-typescript-sdk';\n\nexport function createEchoOpenAI(config: EchoConfig): EchoOpenAIProvider {\n return createEchoOpenAIBase(config, async () => getEchoToken(config));\n}\n","import { NextRequest, NextResponse } from 'next/server';\nimport { getEchoToken } from '../auth/token-manager';\nimport { EchoConfig } from '../types';\n\n/**\n * Proxy requests to Echo service with automatic authentication\n */\nexport async function handleEchoClientProxy(\n req: NextRequest,\n config: EchoConfig\n): Promise<Response> {\n const proxyPath = req.nextUrl.pathname.replace(/^.*\\/proxy/, '');\n const baseUrl = config.baseEchoUrl || 'https://echo.merit.systems';\n const targetUrl = `${baseUrl}${proxyPath}`;\n\n const headers = new Headers(req.headers);\n headers.delete('host');\n // Don't ask upstream to compress\n headers.delete('accept-encoding');\n headers.set('accept-encoding', 'identity');\n\n // Optional: also drop conditional headers to avoid weirdness\n headers.delete('if-none-match');\n headers.delete('if-modified-since');\n\n // Get valid token using existing function (handles refresh automatically)\n const accessToken = await getEchoToken(config);\n\n if (!accessToken) {\n return NextResponse.json(\n { error: 'Authentication required' },\n { status: 401 }\n );\n }\n // Inject the valid token\n headers.set('Authorization', `Bearer ${accessToken}`);\n try {\n const response = await fetch(targetUrl, {\n method: req.method,\n headers,\n ...(req.method !== 'GET' && req.method !== 'HEAD' && { body: req.body }),\n });\n\n return response;\n } catch (error) {\n console.error('Proxy request failed:', error);\n return NextResponse.json(\n { error: 'Proxy request failed' },\n { status: 500 }\n );\n }\n}\n","import { EchoConfig } from '@merit-systems/echo-typescript-sdk';\nimport { NextRequest, NextResponse } from 'next/server';\nimport { resolveEchoBaseUrl } from '../config';\nimport { getEchoToken, RefreshTokenResponse } from './token-manager';\n\n/**\n * Generate PKCE code challenge and verifier\n * @returns Object containing code verifier and challenge\n */\nasync function generateCodeChallenge(): Promise<{\n codeVerifier: string;\n codeChallenge: string;\n}> {\n const codeVerifier = Array.from(crypto.getRandomValues(new Uint8Array(32)))\n .map(b => b.toString(16).padStart(2, '0'))\n .join('');\n\n const encoder = new TextEncoder();\n const codeChallengeBuffer = await crypto.subtle.digest(\n 'SHA-256',\n encoder.encode(codeVerifier)\n );\n\n const codeChallenge = btoa(\n String.fromCharCode(...new Uint8Array(codeChallengeBuffer))\n )\n .replace(/\\+/g, '-')\n .replace(/\\//g, '_')\n .replace(/=+$/, '');\n\n return { codeVerifier, codeChallenge };\n}\n\n/**\n * Handle OAuth signin request - redirect to Echo authorization server\n * @param req - The incoming Next.js request\n * @param config - Echo configuration\n * @returns NextResponse with redirect to authorization server\n */\nexport async function handleSignIn(\n req: NextRequest,\n config: EchoConfig\n): Promise<NextResponse> {\n const { origin } = req.nextUrl;\n const basePath = config.basePath || '/api/echo';\n\n const baseUrl = resolveEchoBaseUrl(config);\n\n const redirectUrl = new URL(`${baseUrl}/api/oauth/authorize`);\n redirectUrl.searchParams.set('client_id', config.appId);\n redirectUrl.searchParams.set('redirect_uri', `${origin}${basePath}/callback`);\n redirectUrl.searchParams.set('response_type', 'code');\n\n const { codeVerifier, codeChallenge } = await generateCodeChallenge();\n\n redirectUrl.searchParams.set('code_challenge', codeChallenge);\n redirectUrl.searchParams.set('code_challenge_method', 'S256');\n\n // Create response with redirect and set cookie for code verifier\n const response = NextResponse.redirect(redirectUrl.toString());\n\n // Set the code verifier in a secure cookie that will be available during callback\n response.cookies.set('echo_code_verifier', codeVerifier, {\n httpOnly: true,\n secure: process.env.NODE_ENV === 'production',\n sameSite: 'lax',\n maxAge: 300, // 5 minutes - same as auth code TTL\n path: '/',\n });\n\n return response;\n}\n\n/**\n * Handle OAuth callback - exchange authorization code for tokens\n * @param req - The incoming Next.js request\n * @param config - Echo configuration\n * @returns NextResponse with redirect to home page and tokens set as cookies\n */\nexport async function handleCallback(\n req: NextRequest,\n config: EchoConfig\n): Promise<NextResponse> {\n const { origin } = req.nextUrl;\n const basePath = config.basePath || '/api/echo';\n\n const code = req.nextUrl.searchParams.get('code');\n const state = req.nextUrl.searchParams.get('state');\n\n if (!code || !state) {\n return NextResponse.json({ error: 'Invalid request' }, { status: 400 });\n }\n\n // Retrieve the code verifier from the cookie\n const codeVerifier = req.cookies.get('echo_code_verifier')?.value;\n\n if (!codeVerifier) {\n return NextResponse.json(\n { error: 'Code verifier not found. Please try signing in again.' },\n { status: 400 }\n );\n }\n\n // Exchange the code for a token from the token endpoint\n const tokenEndpoint = `${resolveEchoBaseUrl(config)}/api/oauth/token`;\n\n const params = new URLSearchParams();\n params.set('grant_type', 'authorization_code');\n params.set('code', code);\n params.set('redirect_uri', `${origin}${basePath}/callback`);\n params.set('client_id', config.appId);\n params.set('code_verifier', codeVerifier);\n\n const tokenResponse = await fetch(tokenEndpoint, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/x-www-form-urlencoded',\n 'x-client-user-agent': req.headers.get('user-agent') || '',\n 'x-client-ip':\n req.headers.get('x-forwarded-for')?.split(',')[0]?.trim() || '',\n },\n body: params.toString(),\n });\n\n if (!tokenResponse.ok) {\n return NextResponse.json(\n { error: 'Token exchange failed' },\n { status: 500 }\n );\n }\n\n const tokenData = (await tokenResponse.json()) as RefreshTokenResponse;\n\n const response = NextResponse.redirect(`${origin}`);\n\n // Clear the code verifier cookie after successful token exchange\n response.cookies.set('echo_code_verifier', '', {\n httpOnly: true,\n secure: process.env.NODE_ENV === 'production',\n sameSite: 'lax',\n maxAge: 0, // Expire immediately\n path: '/',\n });\n\n // Set the access token as a cookie\n response.cookies.set('echo_access_token', tokenData.access_token, {\n httpOnly: true,\n secure: process.env.NODE_ENV === 'production',\n sameSite: 'lax',\n maxAge: tokenData.expires_in, // expires_in is typically in seconds\n path: '/',\n });\n\n tokenData.refresh_token_expires_in;\n\n response.cookies.set('echo_refresh_token', tokenData.refresh_token, {\n httpOnly: true,\n secure: process.env.NODE_ENV === 'production',\n sameSite: 'lax',\n maxAge: tokenData.refresh_token_expires_in,\n path: '/',\n });\n\n // Store refresh token expiry time for checking\n response.cookies.set(\n 'echo_refresh_token_expires',\n String(Math.floor(Date.now() / 1000) + tokenData.refresh_token_expires_in),\n {\n httpOnly: true,\n secure: process.env.NODE_ENV === 'production',\n sameSite: 'lax',\n maxAge: tokenData.refresh_token_expires_in,\n path: '/',\n }\n );\n\n return response;\n}\n\nexport async function handleRefresh(\n req: NextRequest,\n config: EchoConfig\n): Promise<NextResponse> {\n try {\n const token = await getEchoToken(config);\n if (!token) {\n return NextResponse.json({ error: 'No token found' }, { status: 401 });\n }\n\n return NextResponse.json({ success: true });\n } catch (error) {\n console.error('Error refreshing token:', error);\n return NextResponse.json(\n { error: 'Error refreshing token' },\n { status: 500 }\n );\n }\n}\n"],"mappings":"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","names":["NextResponse","EchoClient","cookies","NextResponse","NextResponse","NextResponse","EchoClient"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@merit-systems/echo-next-sdk",
3
- "version": "0.0.3",
3
+ "version": "0.0.5",
4
4
  "description": "Next.js SDK for Echo",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -25,7 +25,8 @@
25
25
  "test": "echo 'no tests'",
26
26
  "test:unit": "echo 'no tests'",
27
27
  "test:watch": "echo 'no tests'",
28
- "prepublishOnly": "pnpm run build"
28
+ "prepublishOnly": "pnpm run build",
29
+ "prepare": "tsup src/index.ts src/client.ts --dts --format esm --out-dir dist"
29
30
  },
30
31
  "keywords": [
31
32
  "echo",
@@ -36,7 +37,7 @@
36
37
  "author": "Merit Systems",
37
38
  "license": "MIT",
38
39
  "dependencies": {
39
- "@merit-systems/echo-typescript-sdk": "1.0.4",
40
+ "@merit-systems/echo-typescript-sdk": "1.0.7",
40
41
  "ai": "^5.0.17",
41
42
  "jwt-decode": "^4.0.0"
42
43
  },