Files
kycnotme/web/src/lib/redis/redisActionsSessions.ts
2025-06-09 10:00:55 +00:00

71 lines
1.8 KiB
TypeScript

import { randomUUID } from 'node:crypto'
import { deserializeActionResult } from 'astro:actions'
import { z } from 'astro:content'
import { RedisGenericManager } from './redisGenericManager'
const dataSchema = z.object({
actionName: z.string(),
actionResult: z.union([
z.object({
type: z.literal('data'),
contentType: z.literal('application/json+devalue'),
status: z.literal(200),
body: z.string(),
}),
z.object({
type: z.literal('error'),
contentType: z.literal('application/json'),
status: z.number(),
body: z.string(),
}),
z.object({
type: z.literal('empty'),
status: z.literal(204),
}),
]),
})
class RedisActionsSessions extends RedisGenericManager {
private readonly prefix = 'actions_session:'
async store(data: z.input<typeof dataSchema>) {
const sessionId = randomUUID()
const parsedData = dataSchema.parse(data)
await this.redisClient.set(`${this.prefix}${sessionId}`, JSON.stringify(parsedData), {
EX: this.expirationTime,
})
return sessionId
}
async get(sessionId: string | null | undefined) {
if (!sessionId) return null
const key = `${this.prefix}${sessionId}`
const rawData = await this.redisClient.get(key)
if (!rawData) return null
const data = dataSchema.parse(JSON.parse(rawData))
const deserializedActionResult = deserializeActionResult(data.actionResult)
return {
deserializedActionResult,
...data,
}
}
async delete(sessionId: string | null | undefined) {
if (!sessionId) return
await this.redisClient.del(`${this.prefix}${sessionId}`)
}
}
export const redisActionsSessions = await RedisActionsSessions.createAndConnect({
expirationTime: 60 * 5, // 5 minutes in seconds
})