@insforge/sdk 1.4.1 → 1.4.2

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/README.md CHANGED
@@ -366,6 +366,11 @@ import { createBrowserClient } from "@insforge/sdk/ssr";
366
366
  export const insforge = createBrowserClient();
367
367
  ```
368
368
 
369
+ `createBrowserClient()` is for Client Components that consume an existing SSR
370
+ session. Its TypeScript surface does not include auth mutations such as
371
+ `signInWithPassword()`, `signUp()`, or `signOut()`. Run auth mutations on the
372
+ server so the app can write server-owned auth cookies.
373
+
369
374
  ```typescript
370
375
  // app/lib/insforge/server.ts
371
376
  import { cookies } from "next/headers";
@@ -383,18 +388,126 @@ import { createRefreshAuthRouter } from "@insforge/sdk/ssr";
383
388
  export const { POST } = createRefreshAuthRouter();
384
389
  ```
385
390
 
386
- For server-owned refresh cookies, run sign-in in a Route Handler or Server Action and use `setAuthCookies()` from `@insforge/sdk/ssr` with the framework cookie writer. In Next.js Route Handlers, pass `response.cookies`:
391
+ For sign-in, sign-up, and sign-out, use `createAuthActions()` in a Server
392
+ Action file. Server Actions are stable in Next.js 14+. Do not return raw auth
393
+ responses from Server Actions; return only the user or app-specific safe fields
394
+ so access and refresh tokens stay server-owned.
387
395
 
388
396
  ```typescript
389
- import { NextResponse } from "next/server";
390
- import { setAuthCookies } from "@insforge/sdk/ssr";
397
+ // app/actions.ts
398
+ "use server";
391
399
 
392
- const response = NextResponse.json({ user: data.user });
393
- setAuthCookies(response.cookies, {
394
- accessToken: data.accessToken,
395
- refreshToken: data.refreshToken,
396
- });
397
- return response;
400
+ import { cookies } from "next/headers";
401
+ import { createAuthActions } from "@insforge/sdk/ssr";
402
+
403
+ export async function signIn(formData: FormData) {
404
+ const auth = createAuthActions({ cookies: await cookies() });
405
+
406
+ const { data, error } = await auth.signInWithPassword({
407
+ email: String(formData.get("email")),
408
+ password: String(formData.get("password")),
409
+ });
410
+
411
+ return { user: data?.user ?? null, error };
412
+ }
413
+ ```
414
+
415
+ For OAuth in SSR apps, start and finish the flow on the server. Store the PKCE
416
+ verifier in an httpOnly app cookie and exchange the callback code with
417
+ `createAuthActions()`:
418
+
419
+ ```typescript
420
+ // app/actions.ts
421
+ "use server";
422
+
423
+ import { cookies } from "next/headers";
424
+ import { redirect } from "next/navigation";
425
+ import { createAuthActions } from "@insforge/sdk/ssr";
426
+
427
+ export async function signInWithGoogle() {
428
+ const cookieStore = await cookies();
429
+ const auth = createAuthActions({ cookies: cookieStore });
430
+ const { data, error } = await auth.signInWithOAuth("google", {
431
+ redirectTo: new URL(
432
+ "/api/auth/callback",
433
+ process.env.NEXT_PUBLIC_APP_URL
434
+ ).toString(),
435
+ skipBrowserRedirect: true,
436
+ });
437
+
438
+ if (error || !data.url || !data.codeVerifier) {
439
+ throw new Error(error?.message ?? "OAuth init failed");
440
+ }
441
+
442
+ cookieStore.set("insforge_code_verifier", data.codeVerifier, {
443
+ httpOnly: true,
444
+ secure: process.env.NODE_ENV === "production",
445
+ sameSite: "lax",
446
+ path: "/",
447
+ maxAge: 600,
448
+ });
449
+
450
+ redirect(data.url);
451
+ }
452
+ ```
453
+
454
+ ```typescript
455
+ // app/api/auth/callback/route.ts
456
+ import { cookies } from "next/headers";
457
+ import { NextResponse, type NextRequest } from "next/server";
458
+ import { createAuthActions } from "@insforge/sdk/ssr";
459
+
460
+ export async function GET(request: NextRequest) {
461
+ const code = request.nextUrl.searchParams.get("insforge_code");
462
+ const verifier = (await cookies()).get("insforge_code_verifier")?.value;
463
+ if (!code || !verifier) {
464
+ return NextResponse.redirect(new URL("/login?error=oauth", request.url));
465
+ }
466
+
467
+ const response = NextResponse.redirect(new URL("/dashboard", request.url));
468
+ const auth = createAuthActions({
469
+ requestCookies: request.cookies,
470
+ responseCookies: response.cookies,
471
+ });
472
+ const { error } = await auth.exchangeOAuthCode(code, verifier);
473
+ if (error) {
474
+ return NextResponse.redirect(new URL("/login?error=oauth", request.url));
475
+ }
476
+
477
+ response.cookies.delete("insforge_code_verifier");
478
+ return response;
479
+ }
480
+ ```
481
+
482
+ SSR browser clients do not exchange OAuth callbacks automatically. OAuth
483
+ callbacks must be completed on the server so the refresh token lands in the
484
+ httpOnly app cookie.
485
+
486
+ For Route Handlers, pass request cookies for reading the current session and
487
+ response cookies for writing the next session:
488
+
489
+ ```typescript
490
+ // app/api/auth/sign-out/route.ts
491
+ import { NextResponse, type NextRequest } from "next/server";
492
+ import { createAuthActions } from "@insforge/sdk/ssr";
493
+
494
+ export async function POST(request: NextRequest) {
495
+ const response = NextResponse.json({ ok: true });
496
+ const auth = createAuthActions({
497
+ requestCookies: request.cookies,
498
+ responseCookies: response.cookies,
499
+ });
500
+
501
+ const { error } = await auth.signOut();
502
+ if (error) {
503
+ return NextResponse.json(
504
+ { error: error.error, message: error.message },
505
+ { status: error.statusCode }
506
+ );
507
+ }
508
+
509
+ return response;
510
+ }
398
511
  ```
399
512
 
400
513
  If your refresh route needs custom side effects:
package/SDK-REFERENCE.md CHANGED
@@ -59,6 +59,10 @@ const insforge = createBrowserClient({
59
59
 
60
60
  The browser client reads the access-token cookie, uses it for Database, Storage, Functions, and Realtime, and calls the refresh route when the access token is missing or near expiry.
61
61
 
62
+ The browser client consumes an existing SSR session. Its TypeScript surface does
63
+ not include auth mutations such as `signInWithPassword()`, `signUp()`, or
64
+ `signOut()`.
65
+
62
66
  ### `createServerClient()`
63
67
 
64
68
  ```typescript
@@ -81,34 +85,40 @@ import { createRefreshAuthRouter } from "@insforge/sdk/ssr";
81
85
  export const { POST } = createRefreshAuthRouter();
82
86
  ```
83
87
 
84
- For server-owned refresh cookies, sign-in should also run through a Route Handler or Server Action that can set cookies:
88
+ For server-owned refresh cookies, sign-in, sign-up, and sign-out should run
89
+ through a Server Action or Route Handler that can set cookies. Do not return
90
+ raw auth responses from Server Actions; return only the user or app-specific
91
+ safe fields.
85
92
 
86
93
  ```typescript
87
- import { NextResponse } from "next/server";
88
- import { createServerClient, setAuthCookies } from "@insforge/sdk/ssr";
94
+ // app/actions.ts
95
+ "use server";
89
96
 
90
- export async function POST(request: Request) {
91
- const client = createServerClient();
92
- const { data, error } = await client.auth.signInWithPassword(
93
- await request.json(),
94
- );
95
- if (error || !data?.accessToken) {
96
- return Response.json(error, { status: error?.statusCode ?? 400 });
97
- }
97
+ import { cookies } from "next/headers";
98
+ import { createAuthActions } from "@insforge/sdk/ssr";
98
99
 
99
- const response = NextResponse.json({
100
- accessToken: data.accessToken,
101
- user: data.user,
102
- });
103
- setAuthCookies(response.cookies, {
104
- accessToken: data.accessToken,
105
- refreshToken: data.refreshToken,
100
+ export async function signIn(formData: FormData) {
101
+ const auth = createAuthActions({ cookies: await cookies() });
102
+
103
+ const { data, error } = await auth.signInWithPassword({
104
+ email: String(formData.get("email")),
105
+ password: String(formData.get("password")),
106
106
  });
107
107
 
108
- return response;
108
+ return { user: data?.user ?? null, error };
109
109
  }
110
110
  ```
111
111
 
112
+ In Route Handlers, pass `requestCookies` and `responseCookies` to the same
113
+ helper when request and response cookie stores are separate.
114
+
115
+ For OAuth, initiate and exchange on the server. Use
116
+ `createAuthActions().signInWithOAuth(provider, { redirectTo, skipBrowserRedirect: true })`
117
+ in a Server Action, store the returned `codeVerifier` in an httpOnly app cookie,
118
+ redirect to `data.url`, then call `createAuthActions().exchangeOAuthCode(code,
119
+ codeVerifier)` from the callback Route Handler. SSR browser clients do not
120
+ auto-exchange OAuth callbacks.
121
+
112
122
  Use `refreshAuth()` directly when the route needs app-specific logic:
113
123
 
114
124
  ```typescript
@@ -1,4 +1,4 @@
1
- import { A as AuthSession, I as InsForgeConfig, e as AuthRefreshResponse, d as InsForgeError } from './types-NjykhyRq.js';
1
+ import { A as AuthSession, I as InsForgeConfig, e as AuthRefreshResponse, d as InsForgeError } from './types-Dk-44JJf.js';
2
2
  import { UserSchema, CreateUserRequest, CreateUserResponse, CreateSessionRequest, CreateSessionResponse, OAuthProvidersSchema, RefreshSessionResponse, GetProfileResponse, SendVerificationEmailRequest, VerifyEmailRequest, VerifyEmailResponse, SendResetPasswordEmailRequest, ExchangeResetPasswordTokenRequest, ExchangeResetPasswordTokenResponse, ResetPasswordResponse, GetPublicAuthConfigResponse, StorageFileSchema, ListObjectsResponseSchema, ChatCompletionRequest, ImageGenerationRequest, EmbeddingsRequest, SubscribeResponse, SocketMessage, SendRawEmailRequest, SendEmailResponse, StripeEnvironment, CreateCheckoutSessionBody, CreateCheckoutSessionResponse, CreateCustomerPortalSessionBody, CreateCustomerPortalSessionResponse, RazorpayEnvironment, CreateRazorpayOrderBody, CreateRazorpayOrderResponse, VerifyRazorpayOrderBody, VerifyRazorpayOrderResponse, CreateRazorpaySubscriptionBody, CreateRazorpaySubscriptionResponse, VerifyRazorpaySubscriptionBody, VerifyRazorpaySubscriptionResponse, CancelRazorpaySubscriptionBodyInput, CancelRazorpaySubscriptionResponse, PauseRazorpaySubscriptionResponse, ResumeRazorpaySubscriptionResponse } from '@insforge/shared-schemas';
3
3
  import * as _supabase_postgrest_js from '@supabase/postgrest-js';
4
4
 
@@ -204,6 +204,7 @@ declare class HttpClient {
204
204
 
205
205
  interface AuthOptions {
206
206
  isServerMode?: boolean;
207
+ detectOAuthCallback?: boolean;
207
208
  }
208
209
  type OAuthSignInOptions = {
209
210
  redirectTo: string;
@@ -1,4 +1,4 @@
1
- import { A as AuthSession, I as InsForgeConfig, e as AuthRefreshResponse, d as InsForgeError } from './types-NjykhyRq.mjs';
1
+ import { A as AuthSession, I as InsForgeConfig, e as AuthRefreshResponse, d as InsForgeError } from './types-Dk-44JJf.mjs';
2
2
  import { UserSchema, CreateUserRequest, CreateUserResponse, CreateSessionRequest, CreateSessionResponse, OAuthProvidersSchema, RefreshSessionResponse, GetProfileResponse, SendVerificationEmailRequest, VerifyEmailRequest, VerifyEmailResponse, SendResetPasswordEmailRequest, ExchangeResetPasswordTokenRequest, ExchangeResetPasswordTokenResponse, ResetPasswordResponse, GetPublicAuthConfigResponse, StorageFileSchema, ListObjectsResponseSchema, ChatCompletionRequest, ImageGenerationRequest, EmbeddingsRequest, SubscribeResponse, SocketMessage, SendRawEmailRequest, SendEmailResponse, StripeEnvironment, CreateCheckoutSessionBody, CreateCheckoutSessionResponse, CreateCustomerPortalSessionBody, CreateCustomerPortalSessionResponse, RazorpayEnvironment, CreateRazorpayOrderBody, CreateRazorpayOrderResponse, VerifyRazorpayOrderBody, VerifyRazorpayOrderResponse, CreateRazorpaySubscriptionBody, CreateRazorpaySubscriptionResponse, VerifyRazorpaySubscriptionBody, VerifyRazorpaySubscriptionResponse, CancelRazorpaySubscriptionBodyInput, CancelRazorpaySubscriptionResponse, PauseRazorpaySubscriptionResponse, ResumeRazorpaySubscriptionResponse } from '@insforge/shared-schemas';
3
3
  import * as _supabase_postgrest_js from '@supabase/postgrest-js';
4
4
 
@@ -204,6 +204,7 @@ declare class HttpClient {
204
204
 
205
205
  interface AuthOptions {
206
206
  isServerMode?: boolean;
207
+ detectOAuthCallback?: boolean;
207
208
  }
208
209
  type OAuthSignInOptions = {
209
210
  redirectTo: string;
package/dist/index.d.mts CHANGED
@@ -1,7 +1,7 @@
1
- import { I as InsForgeClient } from './client-hYdj36T6.mjs';
2
- export { c as AI, A as Auth, C as ConnectionState, D as Database, E as Emails, f as EventCallback, d as FunctionInvokeOptions, F as Functions, H as HttpClient, L as Logger, P as Payments, e as PaymentsResponse, R as Realtime, S as Storage, a as StorageBucket, b as StorageResponse, T as TokenManager } from './client-hYdj36T6.mjs';
3
- import { I as InsForgeConfig, a as InsForgeAdminConfig } from './types-NjykhyRq.mjs';
4
- export { b as ApiError, A as AuthSession, d as InsForgeError, c as InsForgeErrorCode } from './types-NjykhyRq.mjs';
1
+ import { I as InsForgeClient } from './client-C-qBRoea.mjs';
2
+ export { c as AI, A as Auth, C as ConnectionState, D as Database, E as Emails, f as EventCallback, d as FunctionInvokeOptions, F as Functions, H as HttpClient, L as Logger, P as Payments, e as PaymentsResponse, R as Realtime, S as Storage, a as StorageBucket, b as StorageResponse, T as TokenManager } from './client-C-qBRoea.mjs';
3
+ import { I as InsForgeConfig, a as InsForgeAdminConfig } from './types-Dk-44JJf.mjs';
4
+ export { b as ApiError, A as AuthSession, d as InsForgeError, c as InsForgeErrorCode } from './types-Dk-44JJf.mjs';
5
5
  export { AuthErrorResponse, CreateSessionRequest, CreateUserRequest, RealtimeErrorPayload, SendRawEmailRequest as SendEmailOptions, SendEmailResponse, SocketMessage, SubscribeResponse, UserSchema } from '@insforge/shared-schemas';
6
6
  import '@supabase/postgrest-js';
7
7
 
package/dist/index.d.ts CHANGED
@@ -1,7 +1,7 @@
1
- import { I as InsForgeClient } from './client-DoWwzWnh.js';
2
- export { c as AI, A as Auth, C as ConnectionState, D as Database, E as Emails, f as EventCallback, d as FunctionInvokeOptions, F as Functions, H as HttpClient, L as Logger, P as Payments, e as PaymentsResponse, R as Realtime, S as Storage, a as StorageBucket, b as StorageResponse, T as TokenManager } from './client-DoWwzWnh.js';
3
- import { I as InsForgeConfig, a as InsForgeAdminConfig } from './types-NjykhyRq.js';
4
- export { b as ApiError, A as AuthSession, d as InsForgeError, c as InsForgeErrorCode } from './types-NjykhyRq.js';
1
+ import { I as InsForgeClient } from './client-BR9o-WUm.js';
2
+ export { c as AI, A as Auth, C as ConnectionState, D as Database, E as Emails, f as EventCallback, d as FunctionInvokeOptions, F as Functions, H as HttpClient, L as Logger, P as Payments, e as PaymentsResponse, R as Realtime, S as Storage, a as StorageBucket, b as StorageResponse, T as TokenManager } from './client-BR9o-WUm.js';
3
+ import { I as InsForgeConfig, a as InsForgeAdminConfig } from './types-Dk-44JJf.js';
4
+ export { b as ApiError, A as AuthSession, d as InsForgeError, c as InsForgeErrorCode } from './types-Dk-44JJf.js';
5
5
  export { AuthErrorResponse, CreateSessionRequest, CreateUserRequest, RealtimeErrorPayload, SendRawEmailRequest as SendEmailOptions, SendEmailResponse, SocketMessage, SubscribeResponse, UserSchema } from '@insforge/shared-schemas';
6
6
  import '@supabase/postgrest-js';
7
7
 
package/dist/index.js CHANGED
@@ -885,19 +885,32 @@ var HttpClient = class {
885
885
 
886
886
  // src/modules/auth/helpers.ts
887
887
  var PKCE_VERIFIER_KEY = "insforge_pkce_verifier";
888
+ async function getWebCrypto() {
889
+ const webCrypto = globalThis.crypto;
890
+ if (typeof webCrypto?.getRandomValues === "function" && webCrypto.subtle) {
891
+ return webCrypto;
892
+ }
893
+ if (typeof process !== "undefined" && process.versions?.node) {
894
+ const { webcrypto } = await import("crypto");
895
+ return webcrypto;
896
+ }
897
+ throw new Error("Web Crypto API is not available in this environment");
898
+ }
888
899
  function base64UrlEncode(buffer) {
889
900
  const base64 = btoa(String.fromCharCode(...buffer));
890
901
  return base64.replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
891
902
  }
892
- function generateCodeVerifier() {
903
+ async function generateCodeVerifier() {
904
+ const webCrypto = await getWebCrypto();
893
905
  const array = new Uint8Array(32);
894
- crypto.getRandomValues(array);
906
+ webCrypto.getRandomValues(array);
895
907
  return base64UrlEncode(array);
896
908
  }
897
909
  async function generateCodeChallenge(verifier) {
910
+ const webCrypto = await getWebCrypto();
898
911
  const encoder = new TextEncoder();
899
912
  const data = encoder.encode(verifier);
900
- const hash = await crypto.subtle.digest("SHA-256", data);
913
+ const hash = await webCrypto.subtle.digest("SHA-256", data);
901
914
  return base64UrlEncode(new Uint8Array(hash));
902
915
  }
903
916
  function storePkceVerifier(verifier) {
@@ -944,7 +957,7 @@ var Auth = class {
944
957
  this.http = http;
945
958
  this.tokenManager = tokenManager;
946
959
  this.options = options;
947
- this.authCallbackHandled = this.detectAuthCallback();
960
+ this.authCallbackHandled = options.detectOAuthCallback === false ? Promise.resolve() : this.detectAuthCallback();
948
961
  }
949
962
  isServerMode() {
950
963
  return !!this.options.isServerMode;
@@ -1090,7 +1103,7 @@ var Auth = class {
1090
1103
  }
1091
1104
  const { provider } = signInOptions;
1092
1105
  const providerKey = encodeURIComponent(provider.toLowerCase());
1093
- const codeVerifier = generateCodeVerifier();
1106
+ const codeVerifier = await generateCodeVerifier();
1094
1107
  const codeChallenge = await generateCodeChallenge(codeVerifier);
1095
1108
  storePkceVerifier(codeVerifier);
1096
1109
  const params = {
@@ -2812,7 +2825,8 @@ var InsForgeClient = class {
2812
2825
  this.tokenManager.setAccessToken(accessToken);
2813
2826
  }
2814
2827
  this.auth = new Auth(this.http, this.tokenManager, {
2815
- isServerMode: config.isServerMode ?? !!accessToken
2828
+ isServerMode: config.isServerMode ?? !!accessToken,
2829
+ detectOAuthCallback: config.auth?.detectOAuthCallback
2816
2830
  });
2817
2831
  this.database = new Database(this.http);
2818
2832
  this.storage = new Storage(this.http);