diff --git a/package-lock.json b/package-lock.json index 9e8d778..ad25fc2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,7 +13,7 @@ }, "devDependencies": { "@eslint/js": "^9.3.0", - "@supabase/supabase-js": "^2.43.4", + "@supabase/supabase-js": "^2.56.0", "@vitest/coverage-v8": "^1.6.0", "eslint": "^8.57.0", "prettier": "^3.2.5", @@ -897,9 +897,9 @@ "dev": true }, "node_modules/@supabase/auth-js": { - "version": "2.64.2", - "resolved": "https://registry.npmjs.org/@supabase/auth-js/-/auth-js-2.64.2.tgz", - "integrity": "sha512-s+lkHEdGiczDrzXJ1YWt2y3bxRi+qIUnXcgkpLSrId7yjBeaXBFygNjTaoZLG02KNcYwbuZ9qkEIqmj2hF7svw==", + "version": "2.71.1", + "resolved": "https://registry.npmjs.org/@supabase/auth-js/-/auth-js-2.71.1.tgz", + "integrity": "sha512-mMIQHBRc+SKpZFRB2qtupuzulaUhFYupNyxqDj5Jp/LyPvcWvjaJzZzObv6URtL/O6lPxkanASnotGtNpS3H2Q==", "dev": true, "license": "MIT", "dependencies": { @@ -907,9 +907,9 @@ } }, "node_modules/@supabase/functions-js": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/@supabase/functions-js/-/functions-js-2.3.1.tgz", - "integrity": "sha512-QyzNle/rVzlOi4BbVqxLSH828VdGY1RElqGFAj+XeVypj6+PVtMlD21G8SDnsPQDtlqqTtoGRgdMlQZih5hTuw==", + "version": "2.4.5", + "resolved": "https://registry.npmjs.org/@supabase/functions-js/-/functions-js-2.4.5.tgz", + "integrity": "sha512-v5GSqb9zbosquTo6gBwIiq7W9eQ7rE5QazsK/ezNiQXdCbY+bH8D9qEaBIkhVvX4ZRW5rP03gEfw5yw9tiq4EQ==", "dev": true, "license": "MIT", "dependencies": { @@ -930,9 +930,9 @@ } }, "node_modules/@supabase/postgrest-js": { - "version": "1.15.2", - "resolved": "https://registry.npmjs.org/@supabase/postgrest-js/-/postgrest-js-1.15.2.tgz", - "integrity": "sha512-9/7pUmXExvGuEK1yZhVYXPZnLEkDTwxgMQHXLrN5BwPZZm4iUCL1YEyep/Z2lIZah8d8M433mVAUEGsihUj5KQ==", + "version": "1.21.3", + "resolved": "https://registry.npmjs.org/@supabase/postgrest-js/-/postgrest-js-1.21.3.tgz", + "integrity": "sha512-rg3DmmZQKEVCreXq6Am29hMVe1CzemXyIWVYyyua69y6XubfP+DzGfLxME/1uvdgwqdoaPbtjBDpEBhqxq1ZwA==", "dev": true, "license": "MIT", "dependencies": { @@ -940,22 +940,22 @@ } }, "node_modules/@supabase/realtime-js": { - "version": "2.9.5", - "resolved": "https://registry.npmjs.org/@supabase/realtime-js/-/realtime-js-2.9.5.tgz", - "integrity": "sha512-TEHlGwNGGmKPdeMtca1lFTYCedrhTAv3nZVoSjrKQ+wkMmaERuCe57zkC5KSWFzLYkb5FVHW8Hrr+PX1DDwplQ==", + "version": "2.15.1", + "resolved": "https://registry.npmjs.org/@supabase/realtime-js/-/realtime-js-2.15.1.tgz", + "integrity": "sha512-edRFa2IrQw50kNntvUyS38hsL7t2d/psah6om6aNTLLcWem0R6bOUq7sk7DsGeSlNfuwEwWn57FdYSva6VddYw==", "dev": true, "license": "MIT", "dependencies": { - "@supabase/node-fetch": "^2.6.14", - "@types/phoenix": "^1.5.4", - "@types/ws": "^8.5.10", - "ws": "^8.14.2" + "@supabase/node-fetch": "^2.6.13", + "@types/phoenix": "^1.6.6", + "@types/ws": "^8.18.1", + "ws": "^8.18.2" } }, "node_modules/@supabase/storage-js": { - "version": "2.5.5", - "resolved": "https://registry.npmjs.org/@supabase/storage-js/-/storage-js-2.5.5.tgz", - "integrity": "sha512-OpLoDRjFwClwc2cjTJZG8XviTiQH4Ik8sCiMK5v7et0MDu2QlXjCAW3ljxJB5+z/KazdMOTnySi+hysxWUPu3w==", + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/@supabase/storage-js/-/storage-js-2.11.0.tgz", + "integrity": "sha512-Y+kx/wDgd4oasAgoAq0bsbQojwQ+ejIif8uczZ9qufRHWFLMU5cODT+ApHsSrDufqUcVKt+eyxtOXSkeh2v9ww==", "dev": true, "license": "MIT", "dependencies": { @@ -963,18 +963,18 @@ } }, "node_modules/@supabase/supabase-js": { - "version": "2.43.4", - "resolved": "https://registry.npmjs.org/@supabase/supabase-js/-/supabase-js-2.43.4.tgz", - "integrity": "sha512-/pLPaxiIsn5Vaz3s32HC6O/VNwfeddnzS0bZRpOW0AKcPuXroD8pT9G8mpiBlZfpKsMmq6k7tlhW7Sr1PAQ1lw==", + "version": "2.56.0", + "resolved": "https://registry.npmjs.org/@supabase/supabase-js/-/supabase-js-2.56.0.tgz", + "integrity": "sha512-XqwhHSyVnkjdliPN61CmXsmFGnFHTX2WDdwjG3Ukvdzuu3Trix+dXupYOQ3BueIyYp7B6t0yYpdQtJP2hIInyg==", "dev": true, "license": "MIT", "dependencies": { - "@supabase/auth-js": "2.64.2", - "@supabase/functions-js": "2.3.1", + "@supabase/auth-js": "2.71.1", + "@supabase/functions-js": "2.4.5", "@supabase/node-fetch": "2.6.15", - "@supabase/postgrest-js": "1.15.2", - "@supabase/realtime-js": "2.9.5", - "@supabase/storage-js": "2.5.5" + "@supabase/postgrest-js": "1.21.3", + "@supabase/realtime-js": "2.15.1", + "@supabase/storage-js": "^2.10.4" } }, "node_modules/@types/estree": { diff --git a/package.json b/package.json index c12897e..78f12e3 100644 --- a/package.json +++ b/package.json @@ -33,7 +33,7 @@ "homepage": "https://github.com/supabase/ssr#readme", "devDependencies": { "@eslint/js": "^9.3.0", - "@supabase/supabase-js": "^2.43.4", + "@supabase/supabase-js": "^2.56.0", "@vitest/coverage-v8": "^1.6.0", "eslint": "^8.57.0", "prettier": "^3.2.5", diff --git a/src/createBrowserClient.ts b/src/createBrowserClient.ts index 6f270ba..6608381 100644 --- a/src/createBrowserClient.ts +++ b/src/createBrowserClient.ts @@ -141,6 +141,13 @@ export function createBrowserClient< detectSessionInUrl: isBrowser(), persistSession: true, storage, + ...(options?.cookies && + "encode" in options.cookies && + options.cookies.encode === "tokens-only" + ? { + userStorage: options?.auth?.userStorage ?? window.localStorage, + } + : null), }, }); diff --git a/src/createServerClient.ts b/src/createServerClient.ts index ebaf027..9eae3b1 100644 --- a/src/createServerClient.ts +++ b/src/createServerClient.ts @@ -12,6 +12,7 @@ import type { CookieMethodsServer, CookieMethodsServerDeprecated, } from "./types"; +import { memoryLocalStorageAdapter } from "./utils/helpers"; /** * @deprecated Please specify `getAll` and `setAll` cookie methods instead of @@ -170,6 +171,14 @@ export function createServerClient< detectSessionInUrl: false, persistSession: true, storage, + ...(options?.cookies && + "encode" in options.cookies && + options.cookies.encode === "tokens-only" + ? { + userStorage: + options?.auth?.userStorage ?? memoryLocalStorageAdapter(), + } + : null), }, }); diff --git a/src/types.ts b/src/types.ts index 7a88e64..ed3f2dd 100644 --- a/src/types.ts +++ b/src/types.ts @@ -33,6 +33,15 @@ export type CookieMethodsBrowserDeprecated = { }; export type CookieMethodsBrowser = { + /** + * If set to true, only the user's session (access and refresh tokens) will be encoded in cookies. The user object will be encoded in local storage if the `userStorage` option is not provided when creating the client. + * + * You should keep this option the same between `createBrowserClient()` and `createServerClient()`. When set to `tokens-only` accessing the `user` property on the data returned from `getSession()` will only be possible if the user has already been stored in the separate storage. It's best to use `getClaims()` instead to avoid surprizes. + * + * @experimental + */ + encode?: "user-and-tokens" | "tokens-only"; + getAll: GetAllCookies; setAll: SetAllCookies; }; @@ -44,6 +53,15 @@ export type CookieMethodsServerDeprecated = { }; export type CookieMethodsServer = { + /** + * If set to `tokens-only`, only the user's access and refresh tokens will be encoded in cookies. The user object will be encoded in memory if the `userStorage` option is not provided when creating the client. Unset value defaults to `user-and-tokens`. + * + * You should keep this option the same between `createBrowserClient()` and `createServerClient()`. When set to `tokens-only` accessing the `user` property on the data returned from `getSession()` will not be possible. Use `getUser()` or preferably `getClaims()` instead. + * + * @experimental + */ + encode?: "user-and-tokens" | "tokens-only"; + getAll: GetAllCookies; setAll?: SetAllCookies; }; diff --git a/src/utils/helpers.ts b/src/utils/helpers.ts index 92ff993..70d9b66 100644 --- a/src/utils/helpers.ts +++ b/src/utils/helpers.ts @@ -51,3 +51,25 @@ export function isBrowser() { typeof window !== "undefined" && typeof window.document !== "undefined" ); } + +/** + * Returns a localStorage-like object that stores the key-value pairs in + * memory. + */ +export function memoryLocalStorageAdapter( + store: { [key: string]: string } = {}, +) { + return { + getItem: (key: string) => { + return store[key] || null; + }, + + setItem: (key: string, value: string) => { + store[key] = value; + }, + + removeItem: (key: string) => { + delete store[key]; + }, + }; +}