diff --git a/packages/adapter-node-redis/.env.test b/packages/adapter-node-redis/.env.test
new file mode 100644
index 0000000000..b715203c98
--- /dev/null
+++ b/packages/adapter-node-redis/.env.test
@@ -0,0 +1,2 @@
+NODE_REDIS_URL=redis://localhost:6379
+NODE_REDIS_PASSWORD=
\ No newline at end of file
diff --git a/packages/adapter-node-redis/README.md b/packages/adapter-node-redis/README.md
new file mode 100644
index 0000000000..bc47758ce8
--- /dev/null
+++ b/packages/adapter-node-redis/README.md
@@ -0,0 +1,28 @@
+
+
+
+
+
+
+
+
+
Node Redis Adapter - NextAuth.js / Auth.js
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+---
+
+Check out the documentation at [authjs.dev](https://authjs.dev/reference/adapter/node-redis).
diff --git a/packages/adapter-node-redis/docker-compose.yml b/packages/adapter-node-redis/docker-compose.yml
new file mode 100644
index 0000000000..e738f9144d
--- /dev/null
+++ b/packages/adapter-node-redis/docker-compose.yml
@@ -0,0 +1,5 @@
+services:
+ redis:
+ image: redis
+ ports:
+ - "6379:6379"
diff --git a/packages/adapter-node-redis/package.json b/packages/adapter-node-redis/package.json
new file mode 100644
index 0000000000..f86439c77a
--- /dev/null
+++ b/packages/adapter-node-redis/package.json
@@ -0,0 +1,53 @@
+{
+ "name": "@auth/node-redis-adapter",
+ "version": "1.0.0",
+ "description": "Node Redis adapter for Auth.js.",
+ "homepage": "https://authjs.dev",
+ "repository": "https://github.com/nextauthjs/next-auth",
+ "bugs": {
+ "url": "https://github.com/nextauthjs/next-auth/issues"
+ },
+ "author": "github.com/lengerrong",
+ "type": "module",
+ "types": "./index.d.ts",
+ "files": [
+ "*.js",
+ "*.d.ts*",
+ "src"
+ ],
+ "exports": {
+ ".": {
+ "types": "./index.d.ts",
+ "import": "./index.js"
+ }
+ },
+ "license": "ISC",
+ "keywords": [
+ "next-auth",
+ "next.js",
+ "oauth",
+ "node",
+ "redis"
+ ],
+ "private": false,
+ "publishConfig": {
+ "access": "public"
+ },
+ "scripts": {
+ "test": "./test/test.sh",
+ "build": "tsc",
+ "clean": "rm -rf *.js *.d.ts*"
+ },
+ "dependencies": {
+ "@auth/core": "workspace:*"
+ },
+ "peerDependencies": {
+ "redis": "^5.7.0",
+ "uuid": "^11.1.0"
+ },
+ "devDependencies": {
+ "@types/uuid": "^8.3.3",
+ "redis": "^5.7.0",
+ "dotenv": "^10.0.0"
+ }
+}
diff --git a/packages/adapter-node-redis/src/index.ts b/packages/adapter-node-redis/src/index.ts
new file mode 100644
index 0000000000..10ebe96477
--- /dev/null
+++ b/packages/adapter-node-redis/src/index.ts
@@ -0,0 +1,394 @@
+/**
+ *
+ *
+ * ## Installation
+ *
+ * ```bash npm2yarn
+ * npm install redis @auth/node-redis-adapter
+ * ```
+ *
+ * @module @auth/node-redis-adapter
+ */
+import { Account } from "@auth/core"
+
+import type {
+ Adapter,
+ AdapterUser,
+ AdapterSession,
+ VerificationToken,
+} from "@auth/core/adapters"
+
+import { RedisClientType } from "redis"
+
+import { v4 as uuid } from "uuid"
+
+import { withRedisClient } from "./utils"
+
+export interface RedisAdapterOptions {
+ baseKeyPrefix?: string
+ accountKeyPrefix?: string
+ accountByUserIdPrefix?: string
+ emailKeyPrefix?: string
+ sessionKeyPrefix?: string
+ sessionByUserIdKeyPrefix?: string
+ userKeyPrefix?: string
+ verificationTokenKeyPrefix?: string
+}
+
+export const defaultOptions: RedisAdapterOptions = {
+ baseKeyPrefix: "",
+ accountKeyPrefix: "user:account:",
+ accountByUserIdPrefix: "user:account:by-user-id:",
+ emailKeyPrefix: "user:email:",
+ sessionKeyPrefix: "user:session:",
+ sessionByUserIdKeyPrefix: "user:session:by-user-id:",
+ userKeyPrefix: "user:",
+ verificationTokenKeyPrefix: "user:token:",
+}
+
+const isoDateRE =
+ /(\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d:[0-5]\d\.\d+([+-][0-2]\d:[0-5]\d|Z))|(\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d:[0-5]\d([+-][0-2]\d:[0-5]\d|Z))|(\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d([+-][0-2]\d:[0-5]\d|Z))/
+function isDate(value: any) {
+ return value && isoDateRE.test(value) && !isNaN(Date.parse(value))
+}
+
+export const hydrateDates = (json: object) => {
+ return Object.entries(json).reduce((acc, [key, val]) => {
+ acc[key] = isDate(val) ? new Date(val as string) : val
+ return acc
+ }, {} as any)
+}
+
+export function NodeRedisAdapter(options: RedisAdapterOptions = {}): Adapter {
+ const mergedOptions = Object.entries({
+ ...defaultOptions,
+ ...options,
+ }).reduce(
+ (acc, [key, val]) => {
+ if (key !== "baseKeyPrefix") {
+ acc[key as keyof RedisAdapterOptions] = acc["baseKeyPrefix"] + val
+ }
+ return acc
+ },
+ {
+ baseKeyPrefix: options.baseKeyPrefix || defaultOptions.baseKeyPrefix,
+ } as RedisAdapterOptions
+ )
+
+ const {
+ accountKeyPrefix,
+ accountByUserIdPrefix,
+ emailKeyPrefix,
+ sessionKeyPrefix,
+ sessionByUserIdKeyPrefix,
+ userKeyPrefix,
+ verificationTokenKeyPrefix,
+ } = mergedOptions
+
+ const getObjectFromRedis = (
+ client: RedisClientType,
+ key: string
+ ) => {
+ return client.get(key).then((value) => {
+ if (!value) return null
+ try {
+ const t = JSON.parse(value) as T
+ return hydrateDates(t) as T
+ } catch (error: unknown) {
+ console.error("RedisAdapter.getObjectFromRedis", error)
+ return null
+ }
+ })
+ }
+
+ const saveObject = async (
+ client: RedisClientType,
+ key: string,
+ obj: T
+ ) => {
+ await client.set(key, JSON.stringify(obj))
+ return obj
+ }
+
+ const getObject = async (
+ client: RedisClientType,
+ key: string
+ ) => {
+ return getObjectFromRedis(client, key)
+ }
+
+ const getUser = (client: RedisClientType, id: string) => {
+ return getObject(client, userKeyPrefix + id)
+ }
+
+ const setUser = async (
+ client: RedisClientType,
+ user: Omit
+ ) => {
+ const id = uuid()
+ if (user["email"]) {
+ await client.set(`${emailKeyPrefix}${user["email"]}`, id)
+ }
+ const savedUser = {
+ ...user,
+ id,
+ } as AdapterUser
+ await saveObject(client, userKeyPrefix + id, savedUser)
+ return savedUser
+ }
+
+ const deleteUser = async (client: RedisClientType, user: AdapterUser) => {
+ if (user["email"]) {
+ await client.del(`${emailKeyPrefix}${user["email"]}`)
+ }
+ await client.del(`${userKeyPrefix}${user.id}`)
+ const sessionByUserIdKey = `${sessionByUserIdKeyPrefix}${user.id}`
+ const sessionKey = await client.get(sessionByUserIdKey)
+ await client.del(sessionByUserIdKey)
+ if (sessionKey) {
+ await client.del(sessionKey)
+ }
+ const accountByUserIdKey = accountByUserIdPrefix + user.id
+ const accountKey = await client.get(accountByUserIdKey)
+ await client.del(accountByUserIdKey)
+ if (accountKey) {
+ await client.del(accountKey)
+ }
+ return user
+ }
+
+ const updateUser = (client: RedisClientType, user: AdapterUser) => {
+ return getObject(client, userKeyPrefix + user.id).then(
+ async (olduser) => {
+ // delete olduser email to prevent email duplication
+ if (olduser && user["email"] !== olduser["email"]) {
+ await client.del(`${emailKeyPrefix}${olduser["email"]}`)
+ await client.set(`${emailKeyPrefix}${user["email"]}`, user.id)
+ }
+ await saveObject(client, userKeyPrefix + user.id, {
+ ...olduser,
+ ...user,
+ } as AdapterUser)
+ return user
+ }
+ )
+ }
+
+ return {
+ createUser: async (user: Omit) => {
+ return withRedisClient(async (client: RedisClientType) => {
+ return setUser(client, user)
+ })
+ },
+ getUser: async (id: string) => {
+ return withRedisClient(async (client: RedisClientType) => {
+ return getUser(client, id)
+ })
+ },
+ getUserByEmail: async (email: string) => {
+ return withRedisClient(async (client: RedisClientType) => {
+ const id = await client.get(emailKeyPrefix + email)
+ if (!id) return null
+ return getObject(client, userKeyPrefix + id)
+ })
+ },
+ updateUser: async (user: Partial) => {
+ return withRedisClient(async (client: RedisClientType) => {
+ if (!user.id) {
+ return setUser(client, {
+ ...user,
+ email: user.email || "",
+ emailVerified: user.emailVerified || null,
+ })
+ }
+ return updateUser(client, user as AdapterUser)
+ })
+ },
+ deleteUser: (userId: string) => {
+ return withRedisClient(async (client: RedisClientType) => {
+ return getObject(client, userKeyPrefix + userId)
+ .then((user) => {
+ if (user) {
+ return deleteUser(client, user)
+ }
+ return Promise.resolve(null)
+ })
+ .catch(() => Promise.resolve(null))
+ })
+ },
+ /** Using the provider id and the id of the user for a specific account, get the user. */
+ getUserByAccount: (
+ providerAccountId: Pick
+ ) => {
+ const id = `${accountKeyPrefix}${providerAccountId.provider}:${providerAccountId.providerAccountId}`
+ return withRedisClient(async (client: RedisClientType) => {
+ return getObject(client, id).then((account) => {
+ if (account) {
+ return getObject(
+ client,
+ `${userKeyPrefix}${account.userId}`
+ )
+ }
+ return Promise.resolve(null)
+ })
+ })
+ },
+ linkAccount: (account: Account) => {
+ const id = `${accountKeyPrefix}${account.provider}:${account.providerAccountId}`
+ return withRedisClient(async (client: RedisClientType) => {
+ return saveObject(client, id, account)
+ .then((account) => {
+ client
+ .set(accountByUserIdPrefix + account.userId, id)
+ .catch(console.error)
+ return account
+ })
+ .catch(() => Promise.resolve(undefined))
+ })
+ },
+ unlinkAccount: (
+ providerAccountId: Pick
+ ) => {
+ const id = `${accountKeyPrefix}${providerAccountId.provider}:${providerAccountId.providerAccountId}`
+ return withRedisClient(async (client: RedisClientType) => {
+ return getObject(client, id)
+ .then((account) => {
+ if (account) {
+ client
+ .del(accountByUserIdPrefix + account.userId)
+ .catch(console.error)
+ return client.del(id).then(() => account)
+ }
+ return Promise.resolve(undefined)
+ })
+ .catch(() => Promise.resolve(undefined))
+ })
+ },
+ /** Creates a session for the user and returns it. */
+ createSession: (session: {
+ sessionToken: string
+ userId: string
+ expires: Date
+ }) => {
+ const key = `${sessionKeyPrefix}${session.sessionToken}`
+ return withRedisClient(async (client: RedisClientType) => {
+ return saveObject(client, key, session).then(() => {
+ client
+ .expireAt(key, Math.floor(session.expires.getTime() / 1000))
+ .catch(console.error)
+ client
+ .set(`${sessionByUserIdKeyPrefix}${session.userId}`, key)
+ .catch(console.error)
+ return session as AdapterSession
+ })
+ })
+ },
+ getSessionAndUser: (sessionToken: string) => {
+ return withRedisClient(async (client: RedisClientType) => {
+ return getObject(
+ client,
+ `${sessionKeyPrefix}${sessionToken}`
+ )
+ .then((session) => {
+ if (session) {
+ return getObject(
+ client,
+ userKeyPrefix + session.userId
+ ).then((user) => {
+ if (user) {
+ return {
+ session,
+ user,
+ }
+ }
+ return {
+ session,
+ user: {} as AdapterUser,
+ }
+ })
+ }
+ return Promise.resolve(null)
+ })
+ .catch(() => Promise.resolve(null))
+ })
+ },
+ updateSession: (
+ session: Partial & Pick
+ ) => {
+ return withRedisClient(async (client: RedisClientType) => {
+ return getObject(
+ client,
+ `${sessionKeyPrefix}${session.sessionToken}`
+ )
+ .then((oldsession) =>
+ saveObject(client, `${sessionKeyPrefix}${session?.sessionToken}`, {
+ ...oldsession,
+ ...session,
+ } as AdapterSession)
+ )
+ .catch(() => Promise.resolve(session as AdapterSession))
+ })
+ },
+ /**
+ * Deletes a session from the database.
+ * It is preferred that this method also returns the session
+ * that is being deleted for logging purposes.
+ */
+ deleteSession: (sessionToken: string) => {
+ return withRedisClient(async (client: RedisClientType) => {
+ return getObject(
+ client,
+ `${sessionKeyPrefix}${sessionToken}`
+ )
+ .then((session) => {
+ if (session) {
+ client
+ .del(`${sessionByUserIdKeyPrefix}${session.userId}`)
+ .catch(console.error)
+ return client
+ .del(`${sessionKeyPrefix}${sessionToken}`)
+ .then(() => session)
+ }
+ return Promise.resolve(null)
+ })
+ .catch(() => Promise.resolve(null))
+ })
+ },
+ createVerificationToken: (verificationToken: VerificationToken) => {
+ return withRedisClient(async (client: RedisClientType) => {
+ return saveObject(
+ client,
+ `${verificationTokenKeyPrefix}${verificationToken.identifier}:${verificationToken.token}`,
+ verificationToken
+ )
+ })
+ },
+ /**
+ * Return verification token from the database
+ * and delete it so it cannot be used again.
+ */
+ useVerificationToken: ({
+ identifier,
+ token,
+ }: {
+ identifier: string
+ token: string
+ }) => {
+ return withRedisClient(async (client: RedisClientType) => {
+ return getObject(
+ client,
+ `${verificationTokenKeyPrefix}${identifier}:${token}`
+ ).then((verificationToken) =>
+ client
+ .del(`${verificationTokenKeyPrefix}${identifier}:${token}`)
+ .then(() => verificationToken)
+ )
+ })
+ },
+ }
+}
diff --git a/packages/adapter-node-redis/src/utils.ts b/packages/adapter-node-redis/src/utils.ts
new file mode 100644
index 0000000000..e464643464
--- /dev/null
+++ b/packages/adapter-node-redis/src/utils.ts
@@ -0,0 +1,60 @@
+import { createClient, RedisClientType } from "redis"
+
+// Singleton Redis client
+let redisClient: RedisClientType | null = null
+let initializing = false
+let initializedPromise: Promise | null = null
+
+export const getRedisClient = async (): Promise => {
+ if (redisClient && redisClient.isOpen) {
+ return redisClient
+ }
+
+ // Prevent duplicate initializations
+ if (initializing && initializedPromise) {
+ return initializedPromise
+ }
+
+ initializing = true
+
+ initializedPromise = (async () => {
+ redisClient = createClient({
+ url: process.env.NODE_REDIS_URL,
+ password: process.env.NODE_REDIS_PASSWORD,
+ })
+
+ redisClient.on("error", (err) => {
+ console.error("Redis error:", err)
+ })
+
+ await redisClient.connect()
+ console.log("Connected to Redis")
+
+ return redisClient
+ })()
+
+ try {
+ return await initializedPromise
+ } finally {
+ initializing = false
+ }
+}
+
+/**
+ * Helper function to perform operations with Redis client
+ * Automatically handles getting the client and proper error handling
+ * @param operation Function that receives Redis client and performs operations
+ * @returns Result of the operation
+ */
+
+export const withRedisClient = async (
+ operation: (client: RedisClientType) => Promise
+): Promise => {
+ const client = await getRedisClient()
+ try {
+ return await operation(client)
+ } catch (error) {
+ console.error("Redis operation failed:", error)
+ throw error
+ }
+}
diff --git a/packages/adapter-node-redis/test/index.test.ts b/packages/adapter-node-redis/test/index.test.ts
new file mode 100644
index 0000000000..e5c34589af
--- /dev/null
+++ b/packages/adapter-node-redis/test/index.test.ts
@@ -0,0 +1,42 @@
+import { runBasicTests } from "utils/adapter"
+import { hydrateDates, NodeRedisAdapter } from "../src"
+import { getRedisClient } from "../src/utils"
+
+import "dotenv/config"
+
+const client = await getRedisClient()
+
+runBasicTests({
+ adapter: NodeRedisAdapter({ baseKeyPrefix: "testNodeRedis:" }),
+ db: {
+ disconnect: async () => {
+ await client.quit()
+ },
+ async user(id: string) {
+ const data = await client.get(`testNodeRedis:user:${id}`)
+ if (!data) return null
+ return hydrateDates(JSON.parse(data))
+ },
+ async account({ provider, providerAccountId }) {
+ const data = await client.get(
+ `testNodeRedis:user:account:${provider}:${providerAccountId}`
+ )
+ if (!data) return null
+ return hydrateDates(JSON.parse(data))
+ },
+ async session(sessionToken) {
+ const data = await client.get(
+ `testNodeRedis:user:session:${sessionToken}`
+ )
+ if (!data) return null
+ return hydrateDates(JSON.parse(data))
+ },
+ async verificationToken(where) {
+ const data = await client.get(
+ `testNodeRedis:user:token:${where.identifier}:${where.token}`
+ )
+ if (!data) return null
+ return hydrateDates(JSON.parse(data))
+ },
+ },
+})
diff --git a/packages/adapter-node-redis/test/test.sh b/packages/adapter-node-redis/test/test.sh
new file mode 100755
index 0000000000..de7ca8c009
--- /dev/null
+++ b/packages/adapter-node-redis/test/test.sh
@@ -0,0 +1,16 @@
+#!/usr/bin/env bash
+
+echo "Initializing container for Node-Redis tests"
+
+# Init Redis containers
+docker compose up -d
+
+echo "Waiting 5s for db to start..."
+sleep 5
+
+# Always stop container, but exit with 1 when tests are failing
+if vitest run -c ../utils/vitest.config.ts; then
+ docker compose down -v
+else
+ docker compose down -v && exit 1
+fi
diff --git a/packages/adapter-node-redis/tsconfig.json b/packages/adapter-node-redis/tsconfig.json
new file mode 100644
index 0000000000..6f3b51d36f
--- /dev/null
+++ b/packages/adapter-node-redis/tsconfig.json
@@ -0,0 +1,9 @@
+{
+ "extends": "../utils/tsconfig.json",
+ "compilerOptions": {
+ "outDir": ".",
+ "rootDir": "src"
+ },
+ "exclude": ["*.js", "*.d.ts"],
+ "include": ["src/**/*"]
+}
diff --git a/packages/adapter-node-redis/typedoc.config.cjs b/packages/adapter-node-redis/typedoc.config.cjs
new file mode 100644
index 0000000000..2edb8a5046
--- /dev/null
+++ b/packages/adapter-node-redis/typedoc.config.cjs
@@ -0,0 +1,14 @@
+// @ts-check
+
+/**
+ * @type {import('typedoc').TypeDocOptions & import('typedoc-plugin-markdown').MarkdownTheme}
+ */
+module.exports = {
+ entryPoints: ["src/index.ts"],
+ entryPointStrategy: "expand",
+ tsconfig: "./tsconfig.json",
+ entryModule: "@auth/node-redis-adapter",
+ entryFileName: "../node-redis-adapter.mdx",
+ includeVersion: true,
+ readme: 'none',
+}
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index f6fe6e4264..78b306b82d 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -249,7 +249,7 @@ importers:
version: 3.8.3(@algolia/client-search@5.20.0)(@types/react@18.2.78)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(search-insights@2.17.2)
'@inkeep/widgets':
specifier: ^0.2.289
- version: 0.2.289(@internationalized/date@3.5.2)(@types/react@18.2.78)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.6.3)
+ version: 0.2.289(@internationalized/date@3.5.6)(@types/react@18.2.78)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.6.3)
'@next/third-parties':
specifier: ^14.2.15
version: 14.2.15(next@14.2.21(@opentelemetry/api@1.7.0)(@playwright/test@1.41.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.70.0))(react@18.3.1)
@@ -527,6 +527,25 @@ importers:
specifier: ^8.18.0
version: 8.18.0
+ packages/adapter-node-redis:
+ dependencies:
+ '@auth/core':
+ specifier: workspace:*
+ version: link:../core
+ uuid:
+ specifier: ^11.1.0
+ version: 11.1.0
+ devDependencies:
+ '@types/uuid':
+ specifier: ^8.3.3
+ version: 8.3.4
+ dotenv:
+ specifier: ^10.0.0
+ version: 10.0.0
+ redis:
+ specifier: ^5.7.0
+ version: 5.8.0
+
packages/adapter-pg:
dependencies:
'@auth/core':
@@ -4495,10 +4514,20 @@ packages:
peerDependencies:
'@redis/client': ^1.0.0
+ '@redis/bloom@5.8.0':
+ resolution: {integrity: sha512-kpKZzAAjGiGYn88Bqq6+ozxPg6kGYWRZH9vnOwGcoSCbrW14SZpZVMYMFSio8FH9ZJUdUcmT/RLGlA1W1t0UWQ==}
+ engines: {node: '>= 18'}
+ peerDependencies:
+ '@redis/client': ^5.8.0
+
'@redis/client@1.5.13':
resolution: {integrity: sha512-epkUM9D0Sdmt93/8Ozk43PNjLi36RZzG+d/T1Gdu5AI8jvghonTeLYV69WVWdilvFo+PYxbP0TZ0saMvr6nscQ==}
engines: {node: '>=14'}
+ '@redis/client@5.8.0':
+ resolution: {integrity: sha512-ywZjKGoSSAECGYOd9bJpws6d4867SN686obUWT/sRmo1c/Q8V+jWyInvlqwKa0BOvTHHwYeB2WFUEvd6PADeOQ==}
+ engines: {node: '>= 18'}
+
'@redis/graph@1.1.1':
resolution: {integrity: sha512-FEMTcTHZozZciLRl6GiiIB4zGm5z5F3F6a6FZCyrfxdKOhFlGkiAqlexWMBzCi4DcRoyiOsuLfW+cjlGWyExOw==}
peerDependencies:
@@ -4509,16 +4538,34 @@ packages:
peerDependencies:
'@redis/client': ^1.0.0
+ '@redis/json@5.8.0':
+ resolution: {integrity: sha512-xPBpwY6aKoRzMSu67MpwrBiSliON9bfHo9Y/pSPBjW8/KoOm1MzGqwJUO20qdjXpFoKJsDWwxIE1LHdBNzcImw==}
+ engines: {node: '>= 18'}
+ peerDependencies:
+ '@redis/client': ^5.8.0
+
'@redis/search@1.1.6':
resolution: {integrity: sha512-mZXCxbTYKBQ3M2lZnEddwEAks0Kc7nauire8q20oA0oA/LoA+E/b5Y5KZn232ztPb1FkIGqo12vh3Lf+Vw5iTw==}
peerDependencies:
'@redis/client': ^1.0.0
+ '@redis/search@5.8.0':
+ resolution: {integrity: sha512-lF9pNv9vySmirm1EzCH6YeRjhvH6lLT7tvebYHEM7WTkEQ/7kZWb4athliKESHpxzTQ36U9UbzuedSywHV6OhQ==}
+ engines: {node: '>= 18'}
+ peerDependencies:
+ '@redis/client': ^5.8.0
+
'@redis/time-series@1.0.5':
resolution: {integrity: sha512-IFjIgTusQym2B5IZJG3XKr5llka7ey84fw/NOYqESP5WUfQs9zz1ww/9+qoz4ka/S6KcGBodzlCeZ5UImKbscg==}
peerDependencies:
'@redis/client': ^1.0.0
+ '@redis/time-series@5.8.0':
+ resolution: {integrity: sha512-kPTlW2ACXokjQNXjCD8Pw9mHDoB94AHUlHFahyjxz9lUJUVwiva2Dgfrd2k3JxHhSBqyY2PREIj9YwIUSTSSqQ==}
+ engines: {node: '>= 18'}
+ peerDependencies:
+ '@redis/client': ^5.8.0
+
'@repeaterjs/repeater@3.0.5':
resolution: {integrity: sha512-l3YHBLAol6d/IKnB9LhpD0cEZWAoe3eFKUyTYWmFmCO2Q/WOckxLQAUyMZWwZV2M/m3+4vgRoaolFqaII82/TA==}
@@ -11656,6 +11703,10 @@ packages:
redis@4.6.12:
resolution: {integrity: sha512-41Xuuko6P4uH4VPe5nE3BqXHB7a9lkFL0J29AlxKaIfD6eWO8VO/5PDF9ad2oS+mswMsfFxaM5DlE3tnXT+P8Q==}
+ redis@5.8.0:
+ resolution: {integrity: sha512-re0MHm1KHbiVIUPDGoUM3jldvjH5EM/wGZ3A33gyUYoC/UnVNKNnZHM5hcJVry7L2O2eJU3nflSXTliv10BTKg==}
+ engines: {node: '>= 18'}
+
reflect-metadata@0.1.13:
resolution: {integrity: sha512-Ts1Y/anZELhSsjMcU605fU9RE4Oi3p5ORujwbIKXfWa+0Zxs510Qrmrce5/Jowq3cHSZSJqBjypxmHarc+vEWg==}
@@ -13427,6 +13478,10 @@ packages:
resolution: {integrity: sha512-8XkAphELsDnEGrDxUOHB3RGvXz6TeuYSGEZBOjtTtPm2lwhGBjLgOzLHB63IUWfBpNucQjND6d3AOudO+H3RWQ==}
hasBin: true
+ uuid@11.1.0:
+ resolution: {integrity: sha512-0/A9rDy9P7cJ+8w1c9WD9V//9Wj15Ce2MPz8Ri6032usz+NfePxx5AcN3bN+r6ZL6jEo066/yNYB3tn4pQEx+A==}
+ hasBin: true
+
uuid@3.4.0:
resolution: {integrity: sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==}
deprecated: Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.
@@ -14213,7 +14268,7 @@ snapshots:
react: 18.3.1
react-dom: 18.3.1(react@18.3.1)
- '@ark-ui/anatomy@0.1.0(@internationalized/date@3.5.2)':
+ '@ark-ui/anatomy@0.1.0(@internationalized/date@3.5.6)':
dependencies:
'@zag-js/accordion': 0.20.0
'@zag-js/anatomy': 0.20.0
@@ -14224,7 +14279,7 @@ snapshots:
'@zag-js/color-utils': 0.20.0
'@zag-js/combobox': 0.20.0
'@zag-js/date-picker': 0.20.0
- '@zag-js/date-utils': 0.20.0(@internationalized/date@3.5.2)
+ '@zag-js/date-utils': 0.20.0(@internationalized/date@3.5.6)
'@zag-js/dialog': 0.20.0
'@zag-js/editable': 0.20.0
'@zag-js/hover-card': 0.20.0
@@ -14250,7 +14305,7 @@ snapshots:
transitivePeerDependencies:
- '@internationalized/date'
- '@ark-ui/react@0.15.0(@internationalized/date@3.5.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
+ '@ark-ui/react@0.15.0(@internationalized/date@3.5.6)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
dependencies:
'@zag-js/accordion': 0.19.1
'@zag-js/anatomy': 0.19.1
@@ -14262,7 +14317,7 @@ snapshots:
'@zag-js/combobox': 0.19.1
'@zag-js/core': 0.19.1
'@zag-js/date-picker': 0.19.1
- '@zag-js/date-utils': 0.19.1(@internationalized/date@3.5.2)
+ '@zag-js/date-utils': 0.19.1(@internationalized/date@3.5.6)
'@zag-js/dialog': 0.19.1
'@zag-js/editable': 0.19.1
'@zag-js/hover-card': 0.19.1
@@ -17141,11 +17196,11 @@ snapshots:
react: 18.3.1
react-dom: 18.3.1(react@18.3.1)
- '@inkeep/components@0.0.24(@ark-ui/react@0.15.0(@internationalized/date@3.5.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@internationalized/date@3.5.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.6.3)':
+ '@inkeep/components@0.0.24(@ark-ui/react@0.15.0(@internationalized/date@3.5.6)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@internationalized/date@3.5.6)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.6.3)':
dependencies:
- '@ark-ui/react': 0.15.0(@internationalized/date@3.5.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
- '@inkeep/preset': 0.0.24(@internationalized/date@3.5.2)(typescript@5.6.3)
- '@inkeep/preset-chakra': 0.0.24(@internationalized/date@3.5.2)(typescript@5.6.3)
+ '@ark-ui/react': 0.15.0(@internationalized/date@3.5.6)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ '@inkeep/preset': 0.0.24(@internationalized/date@3.5.6)(typescript@5.6.3)
+ '@inkeep/preset-chakra': 0.0.24(@internationalized/date@3.5.6)(typescript@5.6.3)
'@inkeep/shared': 0.0.25
'@inkeep/styled-system': 0.0.44
'@pandacss/dev': 0.22.1(typescript@5.6.3)
@@ -17157,9 +17212,9 @@ snapshots:
- jsdom
- typescript
- '@inkeep/preset-chakra@0.0.24(@internationalized/date@3.5.2)(typescript@5.6.3)':
+ '@inkeep/preset-chakra@0.0.24(@internationalized/date@3.5.6)(typescript@5.6.3)':
dependencies:
- '@ark-ui/anatomy': 0.1.0(@internationalized/date@3.5.2)
+ '@ark-ui/anatomy': 0.1.0(@internationalized/date@3.5.6)
'@inkeep/shared': 0.0.25
'@pandacss/dev': 0.22.1(typescript@5.6.3)
transitivePeerDependencies:
@@ -17167,10 +17222,10 @@ snapshots:
- jsdom
- typescript
- '@inkeep/preset@0.0.24(@internationalized/date@3.5.2)(typescript@5.6.3)':
+ '@inkeep/preset@0.0.24(@internationalized/date@3.5.6)(typescript@5.6.3)':
dependencies:
- '@ark-ui/anatomy': 0.1.0(@internationalized/date@3.5.2)
- '@inkeep/preset-chakra': 0.0.24(@internationalized/date@3.5.2)(typescript@5.6.3)
+ '@ark-ui/anatomy': 0.1.0(@internationalized/date@3.5.6)
+ '@inkeep/preset-chakra': 0.0.24(@internationalized/date@3.5.6)(typescript@5.6.3)
'@inkeep/shared': 0.0.25
'@pandacss/dev': 0.22.1(typescript@5.6.3)
colorjs.io: 0.4.5
@@ -17185,14 +17240,14 @@ snapshots:
'@inkeep/styled-system@0.0.46': {}
- '@inkeep/widgets@0.2.289(@internationalized/date@3.5.2)(@types/react@18.2.78)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.6.3)':
+ '@inkeep/widgets@0.2.289(@internationalized/date@3.5.6)(@types/react@18.2.78)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.6.3)':
dependencies:
'@apollo/client': 3.9.5(@types/react@18.2.78)(graphql-ws@5.14.3(graphql@16.8.1))(graphql@16.8.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
- '@ark-ui/react': 0.15.0(@internationalized/date@3.5.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ '@ark-ui/react': 0.15.0(@internationalized/date@3.5.6)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
'@inkeep/color-mode': 0.0.24(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
- '@inkeep/components': 0.0.24(@ark-ui/react@0.15.0(@internationalized/date@3.5.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@internationalized/date@3.5.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.6.3)
- '@inkeep/preset': 0.0.24(@internationalized/date@3.5.2)(typescript@5.6.3)
- '@inkeep/preset-chakra': 0.0.24(@internationalized/date@3.5.2)(typescript@5.6.3)
+ '@inkeep/components': 0.0.24(@ark-ui/react@0.15.0(@internationalized/date@3.5.6)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@internationalized/date@3.5.6)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.6.3)
+ '@inkeep/preset': 0.0.24(@internationalized/date@3.5.6)(typescript@5.6.3)
+ '@inkeep/preset-chakra': 0.0.24(@internationalized/date@3.5.6)(typescript@5.6.3)
'@inkeep/shared': 0.0.25
'@inkeep/styled-system': 0.0.46
'@types/lodash.isequal': 4.5.8
@@ -18485,12 +18540,20 @@ snapshots:
dependencies:
'@redis/client': 1.5.13
+ '@redis/bloom@5.8.0(@redis/client@5.8.0)':
+ dependencies:
+ '@redis/client': 5.8.0
+
'@redis/client@1.5.13':
dependencies:
cluster-key-slot: 1.1.2
generic-pool: 3.9.0
yallist: 4.0.0
+ '@redis/client@5.8.0':
+ dependencies:
+ cluster-key-slot: 1.1.2
+
'@redis/graph@1.1.1(@redis/client@1.5.13)':
dependencies:
'@redis/client': 1.5.13
@@ -18499,14 +18562,26 @@ snapshots:
dependencies:
'@redis/client': 1.5.13
+ '@redis/json@5.8.0(@redis/client@5.8.0)':
+ dependencies:
+ '@redis/client': 5.8.0
+
'@redis/search@1.1.6(@redis/client@1.5.13)':
dependencies:
'@redis/client': 1.5.13
+ '@redis/search@5.8.0(@redis/client@5.8.0)':
+ dependencies:
+ '@redis/client': 5.8.0
+
'@redis/time-series@1.0.5(@redis/client@1.5.13)':
dependencies:
'@redis/client': 1.5.13
+ '@redis/time-series@5.8.0(@redis/client@5.8.0)':
+ dependencies:
+ '@redis/client': 5.8.0
+
'@repeaterjs/repeater@3.0.5': {}
'@rollup/pluginutils@4.2.1':
@@ -20539,9 +20614,9 @@ snapshots:
dependencies:
'@internationalized/date': 3.5.2
- '@zag-js/date-utils@0.20.0(@internationalized/date@3.5.2)':
+ '@zag-js/date-utils@0.19.1(@internationalized/date@3.5.6)':
dependencies:
- '@internationalized/date': 3.5.2
+ '@internationalized/date': 3.5.6
'@zag-js/date-utils@0.20.0(@internationalized/date@3.5.6)':
dependencies:
@@ -27997,6 +28072,14 @@ snapshots:
'@redis/search': 1.1.6(@redis/client@1.5.13)
'@redis/time-series': 1.0.5(@redis/client@1.5.13)
+ redis@5.8.0:
+ dependencies:
+ '@redis/bloom': 5.8.0(@redis/client@5.8.0)
+ '@redis/client': 5.8.0
+ '@redis/json': 5.8.0(@redis/client@5.8.0)
+ '@redis/search': 5.8.0(@redis/client@5.8.0)
+ '@redis/time-series': 5.8.0(@redis/client@5.8.0)
+
reflect-metadata@0.1.13: {}
reflect-metadata@0.1.14: {}
@@ -30013,6 +30096,8 @@ snapshots:
uuid@10.0.0:
optional: true
+ uuid@11.1.0: {}
+
uuid@3.4.0: {}
uuid@8.3.2: {}