|
@@ -1,4 +1,5 @@
|
|
|
import createPub from '../';
|
|
|
+import {usePub} from '../';
|
|
|
|
|
|
type QueryFuncType = (...args: Array<any>) => Promise;
|
|
|
|
|
@@ -25,6 +26,7 @@ const defaultOptions:CreateQueryPubOptions = {
|
|
|
cacheTimeout: 2 * 60 * 1000,
|
|
|
hidePendingOnRefresh: true,
|
|
|
avoidRepeatInProgress: true,
|
|
|
+ forceRefreshAfterTimeout: true,
|
|
|
}
|
|
|
|
|
|
export default (options:CreateQueryPubOptions) => {
|
|
@@ -33,33 +35,109 @@ export default (options:CreateQueryPubOptions) => {
|
|
|
|
|
|
options = {...defaultOptions, ...options}
|
|
|
|
|
|
- const createQuery = (queryFunc: QueryFuncType):Function => {
|
|
|
- return (promiseName:string, isMutation:boolean) => {
|
|
|
+ const withQueryFunc = (queryFunc?: QueryFuncType):Function => {
|
|
|
+ return ({promiseName, isMutation, cacheTagFunc}) => {
|
|
|
const qF = queryFunc || options.queryFunc
|
|
|
|
|
|
- const forceQuery = (...args) => {
|
|
|
+ const makeQuery = (...args:any[]) => {
|
|
|
return qF(...args)
|
|
|
}
|
|
|
|
|
|
- const query = (...args) => {
|
|
|
+ const query = (...args:any[]) => {
|
|
|
if (isMutation){
|
|
|
- if (options.avoidRepeatInProgress && queryPub.mutations?.[promiseName]?.status === 'PENDING'){
|
|
|
+ if (options.avoidRepeatInProgress && queryPub.mutations[promiseName]?.refreshing){
|
|
|
return currentPromises.mutations[promiseName]
|
|
|
}
|
|
|
else {
|
|
|
- queryPub.mutations[promiseName] = {status: 'PENDING'}
|
|
|
- return currentPromises.mutations[promiseName] = forceQuery(...args).then(payload => queryPub.mutations[promiseName] = {status: 'FULFILLED', payload},
|
|
|
- error => queryPub.mutations[promiseName] = {status: 'REJECTED', error})
|
|
|
+ if (!options.hidePendingOnRefresh || !queryPub.mutations[promiseName]){
|
|
|
+ queryPub.mutations[promiseName] = {status: 'PENDING', refreshing: true}
|
|
|
+ }
|
|
|
+ if (!queryPub.mutations[promiseName].refreshing){
|
|
|
+ queryPub.mutations[promiseName].refreshing = true
|
|
|
+ }
|
|
|
+ return currentPromises.mutations[promiseName] = makeQuery(...args).then(payload => queryPub.mutations[promiseName] = {status: 'FULFILLED', payload},
|
|
|
+ error => queryPub.mutations[promiseName] = {status: 'REJECTED', error})
|
|
|
}
|
|
|
}
|
|
|
if (!isMutation){
|
|
|
const stringifiedArgs = JSON.stringify(args)
|
|
|
- queryPub.queries[promiseName][stringifiedArgs]
|
|
|
+ if ((!options.cacheTimeout && queryPub.queries[promiseName]?.[stringifiedArgs].status === 'FULFILLED') ||
|
|
|
+ (queryPub.queries[promiseName]?.[stringifiedArgs] && (Date.now() - queryPub.queries[promiseName][stringifiedArgs].timeStamp) < options.cacheTimeout)){
|
|
|
+
|
|
|
+ return currentPromises.queries[promiseName][stringifiedArgs]
|
|
|
+ }
|
|
|
+ return forceQuery(...args)
|
|
|
}
|
|
|
}
|
|
|
- return {forceQuery, query}
|
|
|
+
|
|
|
+ const forceQuery = (...args:any[]) => {
|
|
|
+ if (isMutation) return query(...args)
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ const stringifiedArgs = JSON.stringify(args)
|
|
|
+ if (!queryPub.queries[promiseName]) {
|
|
|
+ queryPub.queries[promiseName] = {}
|
|
|
+ }
|
|
|
+ if (!currentPromises.queries[promiseName]){
|
|
|
+ currentPromises.queries[promiseName] = {}
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ if (options.avoidRepeatInProgress && queryPub.queries[promiseName]?.[stringifiedArgs]?.refreshing){
|
|
|
+ return currentPromises.queries[promiseName][stringifiedArgs]
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!options.hidePendingOnRefresh || !queryPub.queries[promiseName]?.[stringifiedArgs]){
|
|
|
+ queryPub.queries[promiseName][stringifiedArgs] = {status: 'PENDING', timeStamp: Date.now(), refreshing: true}
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!queryPub.queries[promiseName][stringifiedArgs].refreshing){
|
|
|
+ queryPub.queries[promiseName][stringifiedArgs].refreshing = true
|
|
|
+ }
|
|
|
+
|
|
|
+ if (queryPub.queries[promiseName][stringifiedArgs].timeoutId){
|
|
|
+ clearTimeout(queryPub.queries[promiseName][stringifiedArgs].timeoutId)
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ return currentPromises.queries[promiseName][stringifiedArgs] = makeQuery(...args).then(payload => queryPub.queries[promiseName][stringifiedArgs] = {
|
|
|
+ status: 'FULFILLED',
|
|
|
+ payload,
|
|
|
+ timeStamp: Date.now(),
|
|
|
+ cacheTags: cacheTagFunc(payload),
|
|
|
+ timeoutId: options.cacheTimeout ? setTimeout(() =>forceQuery(...args), options.cacheTimeout) : null
|
|
|
+ },
|
|
|
+ error => queryPub.queries[promiseName][stringifiedArgs] = {
|
|
|
+ status: 'REJECTED',
|
|
|
+ error,
|
|
|
+ timeStamp: Date.now(),
|
|
|
+ timeoutId: options.cacheTimeout ? setTimeout(() =>forceQuery(...args), options.cacheTimeout) : null
|
|
|
+ })
|
|
|
+ }
|
|
|
+
|
|
|
+ const hookName = `use${promiseName[0].toUpperCase() + promiseName.slice(1) + (isMutation ? 'Mutation' : 'Query')}`
|
|
|
+
|
|
|
+ const useMutation = () => {
|
|
|
+ usePub(queryPub.mutations)
|
|
|
+
|
|
|
+ return [query, queryPub.mutations[promiseName] || {status: 'INIT'}]
|
|
|
+ }
|
|
|
+
|
|
|
+ const useQuery = (...args) => {
|
|
|
+ query(...args)
|
|
|
+
|
|
|
+ usePub(queryPub.queries[promiseName])
|
|
|
+
|
|
|
+ const stringifiedArgs = JSON.stringify(args)
|
|
|
+ return queryPub.queries[promiseName][stringifiedArgs]
|
|
|
+ }
|
|
|
+
|
|
|
+ return {makeQuery, query, forceQuery, [hookName]: isMutation ? useMutation : useQuery}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- return {queryPub, createQuery}
|
|
|
+ return {queryPub, withQueryFunc, ...(options.queryFunc ? {createQuery: withQueryFunc(options.queryFunc)}: {})}
|
|
|
}
|