session icon indicating copy to clipboard operation
session copied to clipboard

Support Promise API to SessionStore

Open rktyt opened this issue 1 year ago • 1 comments

Prerequisites

  • [X] I have written a descriptive issue title
  • [X] I have searched existing issues to ensure the feature has not already been requested

🚀 Feature Proposal

Related: https://github.com/fastify/session/issues/24

Currently, the request.session supports the promote api, but this alone is unwieldy. I would like to see the following code be allowed.

import fp from 'fastify-plugin'
import type { FastifyInstance } from 'fastify'
import fastifySession from '@fastify/session'

declare module 'fastify' {
  interface Session {
    data?: unknown
  }
}

const sleep = (msec: number) => new Promise((resolve) => setTimeout(resolve, msec))

const store: fastifySession.SessionStore = {
  async set(sessionId, session) {
    await sleep(1000)
  },
  async get(sessionId) {
    await sleep(1000)
    const session = {...}
    return session
  },
  async destroy(sessionId) {
    await sleep(1000)
  }
}

const mySessionPlugin = async (server: FastifyInstance) => {
  await server.register(fastifySession, {
    secret: process.env.SESSION_SECRET,
    store,
  })
}

export default fp(mySessionPlugin, {
  fastify: '4.x',
  name: 'my-session',
  dependencies: [],
})

Motivation

No response

Example

No response

rktyt avatar Sep 02 '22 02:09 rktyt

Imho it is not possible to change the method heads of the store class, or else all those existing Stores could be incompatible.

But this does not mean, that you cant implement a Store, where you support callbacks and promises. If the callbck parameter is not set, than return a Promise

Uzlopak avatar Sep 02 '22 16:09 Uzlopak

Imho it is not possible to change the method heads of the store class, or else all those existing Stores could be incompatible.

Can't the method caller handle both?

For example, the following Target file: lib/session.js

  save(callback) {
    if (callback) {
      const res = this[requestKey].sessionStore.set(
        this.sessionId,
        this,
        (error) => {
          callback(error)
        },
      )
      if (res instanceof Promise) {
        res.then(() => callback()).catch((error) => callback(error))
      }
    } else {
      return new Promise((resolve, reject) => {
        const res = this[requestKey].sessionStore.set(
          this.sessionId,
          this,
          (error) => {
            if (error) {
              reject(error)
            } else {
              resolve()
            }
          },
        )
        if (res instanceof Promise) {
          res.then(() => resolve()).catch((error) => reject(error))
        }
      })
    }
  }

or

  save(callback) {
    const setMethod = this[requestKey].sessionStore.set
    const isPromise = setMethod.length === 2
    if (callback) {
      isPromise
        ? setMethod(this.sessionId, this)
            .then(() => callback())
            .catch((error) => callback(error))
        : setMethod(this.sessionId, this, (error) => {
            callback(error)
          })
    } else {
      if (isPromise) {
        return setMethod(this.sessionId, this)
      }
      return new Promise((resolve, reject) => {
        setMethod(this.sessionId, this, (error) => {
          if (error) {
            reject(error)
          } else {
            resolve()
          }
        })
      })
    }
  }

rktyt avatar Sep 05 '22 02:09 rktyt

What do you currently use for Redis storage compatible with this library?

punkpeye avatar Sep 24 '22 17:09 punkpeye