index.mjs 2.24 KB
import NodeCache from 'node-cache'
import { configureStore } from '@reduxjs/toolkit'

export const makeLeadingCase = (s) => s.substring(0, 1).toUpperCase() + s.substring(1)

export const fixUnsubscribe = async (store, action) => {
  const promise = store.dispatch(action)
  try {
    return await promise
  } finally {
    if (promise.unsubscribe) promise.unsubscribe()
  }
}

export const DefaultEndpointOptions = Symbol.for('DefaultEndpointOptions')

export const createApiWrappers = (apiSlice, options = {}) => {
  const { util: { upsertQueryData } } = apiSlice
  const { prefix, endpoints: endpointOptions = {} } = options
  const { [ DefaultEndpointOptions ]: defaultEndpointOptions = {} } = endpointOptions
  return Object.entries(apiSlice.endpoints).reduce((result, [ endpointName, endpoint ]) => {
    const { initiate } = endpoint
    const methodName = prefix ? `${prefix}${makeLeadingCase(endpointName)}` : endpointName
    const { [ endpointName ]: { forceRefetch = false } = defaultEndpointOptions } = endpointOptions
    result.endpoints[ methodName ] = (store, arg) => {
      return fixUnsubscribe(store, initiate(arg, { forceRefetch, subscribe: true }))
    }
    result.upserts[ methodName ] = (store, arg, data) => {
      return fixUnsubscribe(store, upsertQueryData(endpointName, arg, data))
    }

    return result
  }, { endpoints: {}, upserts: {} })
}

export const createAstroApiWrappers = (apiWrappers) => Object.entries(apiWrappers).reduce((result, [ apiType, methods ]) => {
  result[ apiType ] = Object.entries(methods).reduce((methods, [ methodName, method ]) => {
    methods[ methodName ] = (Astro, ...args) => method(Astro.locals.store, ...args)
    return methods
  }, {})
  return result
}, {})

export const sessionStoreCache = new NodeCache({
  stdTTL: 600,    // in seconds
  useClones: false,
})

export const createGetSessionStore = (storeConfig) => (session) => {
  const getStore = (sessionId) => {
    const currentStore = sessionStoreCache.get(sessionId)
    if (currentStore) return currentStore
    const newStore = configureStore(storeConfig)
    sessionStoreCache.set(sessionId, newStore)
    return newStore
  }
  const { id: sessionId } = session
  return getStore(sessionId)
}

export { default as AstroReduxProvider } from './Provider.astro'