astro.mjs 3.02 KB
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 astroEnhanceSlice = (apiSlice, options = {}) => {
  const { util: { upsertQueryData } } = apiSlice
  const { prefix, endpoints: endpointOptions = {} } = options
  const { [ DefaultEndpointOptions ]: defaultEndpointOptions = {} } = endpointOptions

  const _astro = apiSlice._astro || (apiSlice._astro = { upserts: {} })
  const { upserts } = _astro
  const enhanceSingleEndpoint = (endpointName) => (endpoint) => {
    if (!_astro[ endpointName ]) {
      const { endpoints: { [ endpointName ]: endpoint } } = apiSlice
      const { initiate } = endpoint
      const { [ endpointName ]: { forceRefetch = false } = defaultEndpointOptions } = endpointOptions
      _astro[ endpointName ] = (Astro, arg) => {
        return fixUnsubscribe(Astro.locals.store, initiate(arg, { forceRefetch, subscribe: true }))
      }
    }
    if (!upserts[ endpointName ]) {
      upserts[ endpointName ] = (Astro, arg, data) => {
        return fixUnsubscribe(Astro.locals.store, upsertQueryData(endpointName, arg, data))
      }
    }
  }
  const endpoints = Object.keys(apiSlice.endpoints).reduce((result, endpointName) => (result[ endpointName ] = enhanceSingleEndpoint(endpointName), result), {})
  return apiSlice.enhanceEndpoints({ endpoints })
}

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 { default as AstroReduxProvider } from './Provider.astro'
export { default as RefreshToken } from './RefreshToken.astro'
export { default as RefreshTokenReact } from './RefreshToken.jsx'