remote-content.ts 2.23 KB
import { configureStore } from '@reduxjs/toolkit'
import { createSlice } from '@reduxjs/toolkit'
import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query'

import { parseHtml } from './html.ts'

interface SiteConfig {
  name: string,
  baseUrl: string,
}

export const configSlice = createSlice({
  name: 'config',
  initialState: {
    sites: {},
  },
  reducers: {
    setSiteConfig(state, { payload: { name, baseUrl } }) {
      if (!state.sites[ name ]) state.sites[ name ] = {}
      Object.assign(state.sites[ name ], { baseUrl })
    }
  },
  selectors: {
    getSiteBaseUrl: (state, name) => state.sites?.[ name ]?.baseUrl,
  },
})


const baseQuery = fetchBaseQuery()

const siteBaseQuery = async (args, api, options) => {
  const { site, url } = args
  const baseUrl = getSiteBaseUrl(site)
  return baseQuery({ ...args, url: `${baseUrl ? `${baseUrl}/` : ''}${url}` }, api, options)
}

export const sitePageSlice = createApi({
  reducerPath: 'pages',
  tagTypes: ['Page'],
  keepUnusedDataFor: 60,
  refetchOnReconnect: true,
  refetchOnMountOrArgChange: true,
  baseQuery: siteBaseQuery,
  endpoints: builder => ({
    getPage: builder.query({
      query: (args) => {
        const { site, page } = args
        return {
          site,
          url: page,
          method: 'GET',
          responseHandler: 'text',
        }
      },
      providesTags: (result, err, args) => {
        const { site, page } = args
        return [ { type: 'Page', id: { site, page } } ]
      },
    }),
  }),
})

export const store = configureStore({
  reducer: {
    [ configSlice.reducerPath ]: configSlice.reducer,
    [ sitePageSlice.reducerPath ]: sitePageSlice.reducer,
  },
  middleware: getDefaultMiddleware => getDefaultMiddleware().concat([
    sitePageSlice.middleware,
  ]),
})

export const getSitePage = async (site: string, page: string) => {
  const result = await store.dispatch(sitePageSlice.endpoints.getPage.initiate({ site, page }))
  return result
}

export const setSiteConfig = (siteConfig: SiteConfig) => {
  return store.dispatch(configSlice.actions.setSiteConfig(siteConfig))
}

export const getSiteBaseUrl = (name: string): string => {
  return configSlice.selectors.getSiteBaseUrl(store.getState(), name)
}

setSiteConfig({ name: 'direct' })