@scalemule/nextjs 0.0.37 → 0.0.39

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.
@@ -2743,7 +2743,6 @@ function createServerClient(config) {
2743
2743
  }
2744
2744
  var SESSION_COOKIE_NAME = "sm_session";
2745
2745
  var USER_ID_COOKIE_NAME = "sm_user_id";
2746
- var KNOWN_ACCOUNTS_COOKIE_NAME = "sm_known_accounts";
2747
2746
  ({
2748
2747
  secure: process.env.NODE_ENV === "production"});
2749
2748
  function createCookieHeader(name, value, options = {}) {
@@ -2844,163 +2843,6 @@ function getSessionFromRequest(request) {
2844
2843
  expiresAt: /* @__PURE__ */ new Date()
2845
2844
  };
2846
2845
  }
2847
- var MAX_KNOWN_ACCOUNTS = 10;
2848
- function maskEmail(email) {
2849
- const [local, domain] = email.split("@");
2850
- if (!domain) return "***@***.***";
2851
- const tldDot = domain.lastIndexOf(".");
2852
- const tld = tldDot > 0 ? domain.slice(tldDot) : "";
2853
- const domainBase = tldDot > 0 ? domain.slice(0, tldDot) : domain;
2854
- return `${local[0] || "*"}***@${domainBase[0] || "*"}***${tld}`;
2855
- }
2856
- function stableColorIndex(userId) {
2857
- let hash = 0;
2858
- for (let i = 0; i < userId.length; i++) {
2859
- hash = (hash << 5) - hash + userId.charCodeAt(i) | 0;
2860
- }
2861
- return Math.abs(hash) % 8;
2862
- }
2863
- function applyPrivacyToEntry(entry, privacy) {
2864
- switch (privacy) {
2865
- case "full":
2866
- return entry;
2867
- case "masked":
2868
- return {
2869
- userId: entry.userId,
2870
- email: entry.email ? maskEmail(entry.email) : void 0,
2871
- fullName: entry.fullName ? `${entry.fullName[0].toUpperCase()}.` : void 0,
2872
- provider: entry.provider,
2873
- lastActiveAt: entry.lastActiveAt,
2874
- colorIndex: stableColorIndex(entry.userId)
2875
- };
2876
- case "minimal":
2877
- return {
2878
- userId: entry.userId,
2879
- provider: entry.provider,
2880
- lastActiveAt: entry.lastActiveAt,
2881
- displayLabel: "Account",
2882
- colorIndex: stableColorIndex(entry.userId)
2883
- };
2884
- }
2885
- }
2886
- function appendKnownAccountCookie(headers2, account, existingCookie, options = {}, privacy) {
2887
- let accounts = {};
2888
- if (existingCookie) {
2889
- try {
2890
- accounts = JSON.parse(decodeURIComponent(existingCookie));
2891
- } catch {
2892
- }
2893
- }
2894
- const effectivePrivacy = privacy || "full";
2895
- for (const [userId, entry] of Object.entries(accounts)) {
2896
- accounts[userId] = applyPrivacyToEntry(entry, effectivePrivacy);
2897
- }
2898
- accounts[account.userId] = applyPrivacyToEntry(account, effectivePrivacy);
2899
- const entries = Object.entries(accounts);
2900
- if (entries.length > MAX_KNOWN_ACCOUNTS) {
2901
- entries.sort((a, b) => new Date(b[1].lastActiveAt).getTime() - new Date(a[1].lastActiveAt).getTime());
2902
- accounts = Object.fromEntries(entries.slice(0, MAX_KNOWN_ACCOUNTS));
2903
- }
2904
- const maxAge = 365 * 24 * 60 * 60;
2905
- const secure = options.secure ?? process.env.NODE_ENV === "production";
2906
- const sameSite = options.sameSite ?? "lax";
2907
- const path = options.path ?? "/";
2908
- let cookie = `${KNOWN_ACCOUNTS_COOKIE_NAME}=${encodeURIComponent(JSON.stringify(accounts))}; Path=${path}; Max-Age=${maxAge}; SameSite=${sameSite}`;
2909
- if (secure) {
2910
- cookie += "; Secure";
2911
- }
2912
- if (options.domain) {
2913
- cookie += `; Domain=${options.domain}`;
2914
- }
2915
- headers2.append("Set-Cookie", cookie);
2916
- }
2917
- function removeKnownAccountFromCookie(headers2, userId, existingCookie, options = {}) {
2918
- let accounts = {};
2919
- if (existingCookie) {
2920
- try {
2921
- accounts = JSON.parse(decodeURIComponent(existingCookie));
2922
- } catch {
2923
- }
2924
- }
2925
- delete accounts[userId];
2926
- const maxAge = 365 * 24 * 60 * 60;
2927
- const secure = options.secure ?? process.env.NODE_ENV === "production";
2928
- const sameSite = options.sameSite ?? "lax";
2929
- const path = options.path ?? "/";
2930
- let cookie = `${KNOWN_ACCOUNTS_COOKIE_NAME}=${encodeURIComponent(JSON.stringify(accounts))}; Path=${path}; Max-Age=${maxAge}; SameSite=${sameSite}`;
2931
- if (secure) {
2932
- cookie += "; Secure";
2933
- }
2934
- if (options.domain) {
2935
- cookie += `; Domain=${options.domain}`;
2936
- }
2937
- headers2.append("Set-Cookie", cookie);
2938
- }
2939
- function clearKnownAccountsCookie(headers2, options = {}) {
2940
- const path = options.path ?? "/";
2941
- let cookie = `${KNOWN_ACCOUNTS_COOKIE_NAME}=; Path=${path}; Max-Age=0`;
2942
- if (options.domain) {
2943
- cookie += `; Domain=${options.domain}`;
2944
- }
2945
- headers2.append("Set-Cookie", cookie);
2946
- }
2947
- function getKnownAccountsFromRequest(request) {
2948
- const cookieHeader = request.headers.get("cookie");
2949
- if (!cookieHeader) return [];
2950
- const cookies4 = Object.fromEntries(
2951
- cookieHeader.split(";").map((c) => {
2952
- const [key, ...rest] = c.trim().split("=");
2953
- return [key, decodeURIComponent(rest.join("="))];
2954
- })
2955
- );
2956
- const raw = cookies4[KNOWN_ACCOUNTS_COOKIE_NAME];
2957
- if (!raw) return [];
2958
- try {
2959
- const accounts = JSON.parse(raw);
2960
- return Object.values(accounts);
2961
- } catch {
2962
- return [];
2963
- }
2964
- }
2965
- function getKnownAccountsCookieRaw(request) {
2966
- const cookieHeader = request.headers.get("cookie");
2967
- if (!cookieHeader) return null;
2968
- const cookies4 = Object.fromEntries(
2969
- cookieHeader.split(";").map((c) => {
2970
- const [key, ...rest] = c.trim().split("=");
2971
- return [key, decodeURIComponent(rest.join("="))];
2972
- })
2973
- );
2974
- return cookies4[KNOWN_ACCOUNTS_COOKIE_NAME] || null;
2975
- }
2976
- function normalizeKnownAccountsCookie(request, privacy, options = {}) {
2977
- if (!privacy || privacy === "full") return null;
2978
- const raw = getKnownAccountsCookieRaw(request);
2979
- if (!raw) return null;
2980
- let accounts = {};
2981
- try {
2982
- accounts = JSON.parse(raw);
2983
- } catch {
2984
- return null;
2985
- }
2986
- let changed = false;
2987
- for (const [userId, entry] of Object.entries(accounts)) {
2988
- const normalized = applyPrivacyToEntry(entry, privacy);
2989
- if (JSON.stringify(normalized) !== JSON.stringify(entry)) {
2990
- accounts[userId] = normalized;
2991
- changed = true;
2992
- }
2993
- }
2994
- if (!changed) return null;
2995
- const maxAge = 365 * 24 * 60 * 60;
2996
- const secure = options.secure ?? process.env.NODE_ENV === "production";
2997
- const sameSite = options.sameSite ?? "lax";
2998
- const path = options.path ?? "/";
2999
- let cookie = `${KNOWN_ACCOUNTS_COOKIE_NAME}=${encodeURIComponent(JSON.stringify(accounts))}; Path=${path}; Max-Age=${maxAge}; SameSite=${sameSite}`;
3000
- if (secure) cookie += "; Secure";
3001
- if (options.domain) cookie += `; Domain=${options.domain}`;
3002
- return cookie;
3003
- }
3004
2846
  async function requireSession() {
3005
2847
  const session = await getSession();
3006
2848
  if (!session) {
@@ -3160,25 +3002,7 @@ function createAuthRoutes(config = {}) {
3160
3002
  } catch {
3161
3003
  return successResponse({ user: registeredUser, message: "Registration successful" }, 201);
3162
3004
  }
3163
- const registerResponse = withSession(loginData, { user: registeredUser, sessionToken: loginData.session_token, userId: registeredUser.id }, cookieOptions);
3164
- if (config.enableAccountSwitcher) {
3165
- const existingKnown = getKnownAccountsCookieRaw(request);
3166
- appendKnownAccountCookie(
3167
- registerResponse.headers,
3168
- {
3169
- userId: registeredUser.id,
3170
- email: registeredUser.email,
3171
- fullName: registeredUser.full_name ?? void 0,
3172
- avatarUrl: registeredUser.avatar_url ?? void 0,
3173
- provider: "email",
3174
- lastActiveAt: (/* @__PURE__ */ new Date()).toISOString()
3175
- },
3176
- existingKnown,
3177
- cookieOptions,
3178
- config.accountSwitcherPrivacy
3179
- );
3180
- }
3181
- return registerResponse;
3005
+ return withSession(loginData, { user: registeredUser, sessionToken: loginData.session_token, userId: registeredUser.id }, cookieOptions);
3182
3006
  }
3183
3007
  // ==================== Login ====================
3184
3008
  case "login": {
@@ -3209,25 +3033,7 @@ function createAuthRoutes(config = {}) {
3209
3033
  email: loginData.user.email
3210
3034
  });
3211
3035
  }
3212
- const loginResponse = withSession(loginData, { user: loginData.user, sessionToken: loginData.session_token, userId: loginData.user.id }, cookieOptions);
3213
- if (config.enableAccountSwitcher) {
3214
- const existingKnown = getKnownAccountsCookieRaw(request);
3215
- appendKnownAccountCookie(
3216
- loginResponse.headers,
3217
- {
3218
- userId: loginData.user.id,
3219
- email: loginData.user.email,
3220
- fullName: loginData.user.full_name ?? void 0,
3221
- avatarUrl: loginData.user.avatar_url ?? void 0,
3222
- provider: "email",
3223
- lastActiveAt: (/* @__PURE__ */ new Date()).toISOString()
3224
- },
3225
- existingKnown,
3226
- cookieOptions,
3227
- config.accountSwitcherPrivacy
3228
- );
3229
- }
3230
- return loginResponse;
3036
+ return withSession(loginData, { user: loginData.user, sessionToken: loginData.session_token, userId: loginData.user.id }, cookieOptions);
3231
3037
  }
3232
3038
  // ==================== Logout ====================
3233
3039
  case "logout": {
@@ -3374,59 +3180,6 @@ function createAuthRoutes(config = {}) {
3374
3180
  }
3375
3181
  return successResponse({ message: "Password changed successfully" });
3376
3182
  }
3377
- // ==================== Switch Account ====================
3378
- // Clears the active session so the user can re-authenticate as a different account.
3379
- // The known accounts cookie is preserved — only the session cookie is cleared.
3380
- case "switch-account": {
3381
- if (!config.enableAccountSwitcher) {
3382
- return errorResponse("NOT_FOUND", "Account switcher not enabled", 404);
3383
- }
3384
- const session = await getSession();
3385
- if (session) {
3386
- try {
3387
- await sm.auth.logout(session.sessionToken);
3388
- } catch {
3389
- }
3390
- }
3391
- const switchResponse = clearSession({ message: "Session cleared for account switch" }, cookieOptions);
3392
- const knownAccounts = getKnownAccountsFromRequest(request);
3393
- return new Response(
3394
- JSON.stringify({ success: true, data: { message: "Session cleared for account switch", knownAccounts } }),
3395
- { status: 200, headers: switchResponse.headers }
3396
- );
3397
- }
3398
- // ==================== Forget Account ====================
3399
- // Remove a specific account from the known accounts cookie.
3400
- case "forget-account": {
3401
- if (!config.enableAccountSwitcher) {
3402
- return errorResponse("NOT_FOUND", "Account switcher not enabled", 404);
3403
- }
3404
- const { user_id } = body;
3405
- if (!user_id) {
3406
- return errorResponse("VALIDATION_ERROR", "user_id required", 400);
3407
- }
3408
- const headers2 = new Headers();
3409
- headers2.set("Content-Type", "application/json");
3410
- const existingKnown = getKnownAccountsCookieRaw(request);
3411
- removeKnownAccountFromCookie(headers2, user_id, existingKnown, cookieOptions);
3412
- return new Response(
3413
- JSON.stringify({ success: true, data: { message: "Account forgotten" } }),
3414
- { status: 200, headers: headers2 }
3415
- );
3416
- }
3417
- // ==================== Forget All Accounts ====================
3418
- case "forget-all-accounts": {
3419
- if (!config.enableAccountSwitcher) {
3420
- return errorResponse("NOT_FOUND", "Account switcher not enabled", 404);
3421
- }
3422
- const headers2 = new Headers();
3423
- headers2.set("Content-Type", "application/json");
3424
- clearKnownAccountsCookie(headers2, cookieOptions);
3425
- return new Response(
3426
- JSON.stringify({ success: true, data: { message: "All accounts forgotten" } }),
3427
- { status: 200, headers: headers2 }
3428
- );
3429
- }
3430
3183
  default:
3431
3184
  return errorResponse("NOT_FOUND", `Unknown endpoint: ${path}`, 404);
3432
3185
  }
@@ -3442,25 +3195,20 @@ function createAuthRoutes(config = {}) {
3442
3195
  switch (path) {
3443
3196
  // ==================== Get Current User ====================
3444
3197
  case "me": {
3445
- const normCookie = config.enableAccountSwitcher ? normalizeKnownAccountsCookie(request, config.accountSwitcherPrivacy, cookieOptions) : null;
3446
- const withNorm = (resp) => {
3447
- if (normCookie) resp.headers.append("Set-Cookie", normCookie);
3448
- return resp;
3449
- };
3450
3198
  const session = await getSession();
3451
3199
  if (!session) {
3452
- return withNorm(errorResponse("UNAUTHORIZED", "Authentication required", 401));
3200
+ return errorResponse("UNAUTHORIZED", "Authentication required", 401);
3453
3201
  }
3454
3202
  let userData;
3455
3203
  try {
3456
3204
  userData = await sm.auth.me(session.sessionToken);
3457
3205
  } catch {
3458
- return withNorm(clearSession(
3206
+ return clearSession(
3459
3207
  { error: { code: "SESSION_EXPIRED", message: "Session expired" } },
3460
3208
  cookieOptions
3461
- ));
3209
+ );
3462
3210
  }
3463
- return withNorm(successResponse({ user: userData, sessionToken: session.sessionToken, userId: session.userId }));
3211
+ return successResponse({ user: userData, sessionToken: session.sessionToken, userId: session.userId });
3464
3212
  }
3465
3213
  // ==================== Get Session Status ====================
3466
3214
  case "session": {
@@ -3470,14 +3218,6 @@ function createAuthRoutes(config = {}) {
3470
3218
  userId: session?.userId || null
3471
3219
  });
3472
3220
  }
3473
- // ==================== Get Known Accounts ====================
3474
- case "known-accounts": {
3475
- if (!config.enableAccountSwitcher) {
3476
- return errorResponse("NOT_FOUND", "Account switcher not enabled", 404);
3477
- }
3478
- const knownAccounts = getKnownAccountsFromRequest(request);
3479
- return successResponse({ knownAccounts });
3480
- }
3481
3221
  default:
3482
3222
  return errorResponse("NOT_FOUND", `Unknown endpoint: ${path}`, 404);
3483
3223
  }
@@ -5085,4 +4825,4 @@ async function prefetchBundles(keys) {
5085
4825
  await Promise.all(keys.map((key) => getBundle(key)));
5086
4826
  }
5087
4827
 
5088
- export { CSRF_COOKIE_NAME, CSRF_HEADER_NAME, KNOWN_ACCOUNTS_COOKIE_NAME, OAUTH_STATE_COOKIE_NAME, SESSION_COOKIE_NAME, ScaleMuleError, ScaleMuleServer, USER_ID_COOKIE_NAME, apiHandler, appendKnownAccountCookie, buildClientContextHeaders, buildFlagContext, clearKnownAccountsCookie, clearOAuthState, clearSession, configureBundles, configureSecrets, createAnalyticsRoutes, createAuthMiddleware, createAuthRoutes, createNotificationRoutes, createPushRoutes, createServerClient, createWebhookHandler, createWebhookRoutes, errorCodeToStatus, extractClientContext, extractClientContextFromReq, generateCSRFToken, getAppSecret, getAppSecretOrDefault, getBootstrapFlags, getBundle, getCSRFToken, getKnownAccountsCookieRaw, getKnownAccountsFromRequest, getMySqlBundle, getOAuthBundle, getPostgresBundle, getRedisBundle, getS3Bundle, getSession, getSessionFromRequest, getSmtpBundle, invalidateBundleCache, invalidateSecretCache, normalizeKnownAccountsCookie, parseWebhookEvent, prefetchBundles, prefetchSecrets, registerVideoWebhook, removeKnownAccountFromCookie, requireAppSecret, requireBundle, requireSession, resolveGatewayUrl, setOAuthState, unwrap, validateCSRFToken, validateCSRFTokenAsync, validateOAuthState, validateOAuthStateAsync, verifyWebhookSignature, withAuth, withCSRFProtection, withCSRFToken, withSession };
4828
+ export { CSRF_COOKIE_NAME, CSRF_HEADER_NAME, OAUTH_STATE_COOKIE_NAME, SESSION_COOKIE_NAME, ScaleMuleError, ScaleMuleServer, USER_ID_COOKIE_NAME, apiHandler, buildClientContextHeaders, buildFlagContext, clearOAuthState, clearSession, configureBundles, configureSecrets, createAnalyticsRoutes, createAuthMiddleware, createAuthRoutes, createNotificationRoutes, createPushRoutes, createServerClient, createWebhookHandler, createWebhookRoutes, errorCodeToStatus, extractClientContext, extractClientContextFromReq, generateCSRFToken, getAppSecret, getAppSecretOrDefault, getBootstrapFlags, getBundle, getCSRFToken, getMySqlBundle, getOAuthBundle, getPostgresBundle, getRedisBundle, getS3Bundle, getSession, getSessionFromRequest, getSmtpBundle, invalidateBundleCache, invalidateSecretCache, parseWebhookEvent, prefetchBundles, prefetchSecrets, registerVideoWebhook, requireAppSecret, requireBundle, requireSession, resolveGatewayUrl, setOAuthState, unwrap, validateCSRFToken, validateCSRFTokenAsync, validateOAuthState, validateOAuthStateAsync, verifyWebhookSignature, withAuth, withCSRFProtection, withCSRFToken, withSession };
@@ -1,2 +1,2 @@
1
- export { g as createWebhookHandler } from '../webhook-handler-CNKQ1k2a.mjs';
2
- import '../index-BIIUrnPr.mjs';
1
+ export { g as createWebhookHandler } from '../webhook-handler-Cz9jtet2.mjs';
2
+ import '../index-BoENfro3.mjs';
@@ -1,2 +1,2 @@
1
- export { g as createWebhookHandler } from '../webhook-handler-BobYTuNP.js';
2
- import '../index-BIIUrnPr.js';
1
+ export { g as createWebhookHandler } from '../webhook-handler-CjSSCdvI.js';
2
+ import '../index-BoENfro3.js';
@@ -1,6 +1,6 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
2
  import { ReactNode } from 'react';
3
- import { U as User, A as ApiError, a9 as StorageFile } from './index-BIIUrnPr.mjs';
3
+ import { U as User, A as ApiError, a8 as StorageFile } from './index-BoENfro3.mjs';
4
4
 
5
5
  interface MockUserOptions {
6
6
  id?: string;
package/dist/testing.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
2
  import { ReactNode } from 'react';
3
- import { U as User, A as ApiError, a9 as StorageFile } from './index-BIIUrnPr.js';
3
+ import { U as User, A as ApiError, a8 as StorageFile } from './index-BoENfro3.js';
4
4
 
5
5
  interface MockUserOptions {
6
6
  id?: string;
@@ -1,4 +1,4 @@
1
- import { $ as RegisterRequest, p as ClientContext, U as User, v as LoginRequest, L as LoginResponse, c as ListFilesParams, t as ListFilesResponse, a9 as StorageFile, af as UploadResponse } from './index-BIIUrnPr.js';
1
+ import { _ as RegisterRequest, p as ClientContext, U as User, v as LoginRequest, L as LoginResponse, c as ListFilesParams, t as ListFilesResponse, a8 as StorageFile, ae as UploadResponse } from './index-BoENfro3.js';
2
2
 
3
3
  /**
4
4
  * Server-Side ScaleMule Client
@@ -1,4 +1,4 @@
1
- import { $ as RegisterRequest, p as ClientContext, U as User, v as LoginRequest, L as LoginResponse, c as ListFilesParams, t as ListFilesResponse, a9 as StorageFile, af as UploadResponse } from './index-BIIUrnPr.mjs';
1
+ import { _ as RegisterRequest, p as ClientContext, U as User, v as LoginRequest, L as LoginResponse, c as ListFilesParams, t as ListFilesResponse, a8 as StorageFile, ae as UploadResponse } from './index-BoENfro3.mjs';
2
2
 
3
3
  /**
4
4
  * Server-Side ScaleMule Client
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@scalemule/nextjs",
3
- "version": "0.0.37",
3
+ "version": "0.0.39",
4
4
  "description": "ScaleMule SDK for Next.js applications - authentication, storage, and user management",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",
@@ -52,7 +52,7 @@
52
52
  "clean": "rm -rf dist"
53
53
  },
54
54
  "dependencies": {
55
- "@scalemule/sdk": "^0.0.29"
55
+ "@scalemule/sdk": "^0.0.31"
56
56
  },
57
57
  "peerDependencies": {
58
58
  "next": ">=14.0.0",