WIP
Showing
6 changed files
with
169 additions
and
0 deletions
package.json
0 → 100644
src/Provider.astro
0 → 100644
1 | --- | ||
2 | |||
3 | const { locals: { store, session } } = Astro | ||
4 | |||
5 | const getPreloadedState = async () => { | ||
6 | //await getAllAsync(store.dispatch) | ||
7 | return new Promise((resolve, reject) => { | ||
8 | setTimeout(() => { | ||
9 | resolve(store.getState()) | ||
10 | }, 0) | ||
11 | }) | ||
12 | } | ||
13 | |||
14 | --- | ||
15 | <script define:vars={{preloadedState: await getPreloadedState()}}> | ||
16 | window.__PRELOADED_STATE__ = preloadedState | ||
17 | console.log('window', window) | ||
18 | </script> |
src/client.mjs
0 → 100644
1 | import { configureStore } from '@reduxjs/toolkit' | ||
2 | import { setupListeners } from '@reduxjs/toolkit/query' | ||
3 | |||
4 | export function getBrowserStore() { | ||
5 | const { | ||
6 | astroStore: store | ||
7 | } = window | ||
8 | |||
9 | return store | ||
10 | } | ||
11 | |||
12 | export async function configureAstroStore(userStoreConfig) { | ||
13 | const { | ||
14 | __PRELOADED_STATE__: preloadedState, | ||
15 | } = window | ||
16 | console.log('preloadedState', preloadedState) | ||
17 | if (preloadedState) { | ||
18 | const store = configureStore({ | ||
19 | ...userStoreConfig, | ||
20 | preloadedState, | ||
21 | }) | ||
22 | await setupListeners(store.dispatch) | ||
23 | //await resetApiState(store.dispatch) | ||
24 | console.log('store', store) | ||
25 | |||
26 | window.astroStore = store | ||
27 | } | ||
28 | } |
src/index.mjs
0 → 100644
1 | import NodeCache from 'node-cache' | ||
2 | import { configureStore } from '@reduxjs/toolkit' | ||
3 | |||
4 | export const makeLeadingCase = (s) => s.substring(0, 1).toUpperCase() + s.substring(1) | ||
5 | |||
6 | export const fixUnsubscribe = async (store, action) => { | ||
7 | const promise = store.dispatch(action) | ||
8 | try { | ||
9 | return await promise | ||
10 | } finally { | ||
11 | if (promise.unsubscribe) promise.unsubscribe() | ||
12 | } | ||
13 | } | ||
14 | |||
15 | export const DefaultEndpointOptions = Symbol.for('DefaultEndpointOptions') | ||
16 | |||
17 | export const createApiWrappers = (apiSlice, options = {}) => { | ||
18 | const { util: { upsertQueryData } } = apiSlice | ||
19 | const { prefix, endpoints: endpointOptions = {} } = options | ||
20 | const { [ DefaultEndpointOptions ]: defaultEndpointOptions = {} } = endpointOptions | ||
21 | return Object.entries(apiSlice.endpoints).reduce((result, [ endpointName, endpoint ]) => { | ||
22 | const { initiate } = endpoint | ||
23 | const methodName = prefix ? `${prefix}${makeLeadingCase(endpointName)}` : endpointName | ||
24 | const { [ endpointName ]: { forceRefetch = false } = defaultEndpointOptions } = endpointOptions | ||
25 | result.endpoints[ methodName ] = (store, arg) => { | ||
26 | return fixUnsubscribe(store, initiate(arg, { forceRefetch, subscribe: true })) | ||
27 | } | ||
28 | result.upserts[ methodName ] = (store, arg, data) => { | ||
29 | return fixUnsubscribe(store, upsertQueryData(endpointName, arg, data)) | ||
30 | } | ||
31 | |||
32 | return result | ||
33 | }, { endpoints: {}, upserts: {} }) | ||
34 | } | ||
35 | |||
36 | export const createAstroApiWrappers = (apiWrappers) => Object.entries(apiWrappers).reduce((result, [ apiType, methods ]) => { | ||
37 | result[ apiType ] = Object.entries(methods).reduce((methods, [ methodName, method ]) => { | ||
38 | methods[ methodName ] = (Astro, ...args) => method(Astro.locals.store, ...args) | ||
39 | return methods | ||
40 | }, {}) | ||
41 | return result | ||
42 | }, {}) | ||
43 | |||
44 | export const sessionStoreCache = new NodeCache({ | ||
45 | stdTTL: 600, // in seconds | ||
46 | useClones: false, | ||
47 | }) | ||
48 | |||
49 | export const createGetSessionStore = (storeConfig) => (session) => { | ||
50 | const getStore = (sessionId) => { | ||
51 | const currentStore = sessionStoreCache.get(sessionId) | ||
52 | if (currentStore) return currentStore | ||
53 | const newStore = configureStore(storeConfig) | ||
54 | sessionStoreCache.set(sessionId, newStore) | ||
55 | return newStore | ||
56 | } | ||
57 | const { id: sessionId } = session | ||
58 | return getStore(sessionId) | ||
59 | } | ||
60 | |||
61 | export { default as AstroReduxProvider } from './Provider.astro' |
src/react.jsx
0 → 100644
1 | import React from 'react' | ||
2 | import { Provider } from 'react-redux' | ||
3 | import { getBrowserStore } from './client.mjs' | ||
4 | |||
5 | export const ReduxAstroProvider = (Component) => (props) => { | ||
6 | const { | ||
7 | ASTRO_STORE: possibleStore = {}, | ||
8 | ...rest | ||
9 | } = props | ||
10 | const store = possibleStore.dispatch ? possibleStore : getBrowserStore() | ||
11 | |||
12 | return ( | ||
13 | <Provider store={store}><Component {...rest}/></Provider> | ||
14 | ) | ||
15 | } |
src/slices.mjs
0 → 100644
1 | import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react' | ||
2 | |||
3 | export const loginPrepareHeaders = (headers, context) => { | ||
4 | const { getState } = context | ||
5 | const state = getState() | ||
6 | const { data: { access_token } = {} } = loginApiSlice.endpoints.getToken.select()(state) | ||
7 | if (access_token) { | ||
8 | headers.set('authorization', `Bearer ${access_token}`) | ||
9 | } | ||
10 | return headers | ||
11 | } | ||
12 | |||
13 | export const loginApiSlice = createApi({ | ||
14 | reducerPath: 'login', | ||
15 | tagTypes: ['Token'], | ||
16 | keepUnusedDataFor: 60, | ||
17 | baseQuery: fetchBaseQuery({ | ||
18 | baseUrl: '/login', | ||
19 | }), | ||
20 | refetchOnReconnect: true, | ||
21 | endpoints: builder => ({ | ||
22 | getToken: builder.query({ | ||
23 | query: () => ({ | ||
24 | url: '/token?refresh', | ||
25 | method: 'GET', | ||
26 | }), | ||
27 | providesTags(result, error, arg) { | ||
28 | const { expires_at, access_token } = result | ||
29 | return ['Token'] | ||
30 | }, | ||
31 | }), | ||
32 | }), | ||
33 | }) | ||
34 | |||
35 | export const { useGetTokenQuery } = loginApiSlice | ||
36 | export const invalidateToken = (dispatch) => dispatch(loginApiSlice.util.invalidateTags(['Token'])) | ||
37 |
-
Please register or sign in to post a comment