Skip to content

Commit 6d46633

Browse files
committed
refactor: cleanup to reduce file size and add tests
1 parent cb2b425 commit 6d46633

20 files changed

+324
-206
lines changed

.babelrc

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,15 @@
1111
"@babel/preset-typescript",
1212
"@babel/react"
1313
],
14-
"plugins": ["babel-plugin-transform-async-to-promises"],
14+
"plugins": [
15+
[
16+
"const-enum",
17+
{
18+
"transform": "constObject"
19+
}
20+
],
21+
"babel-plugin-transform-async-to-promises"
22+
],
1523
"env": {
1624
"test": {
1725
"presets": [
@@ -24,7 +32,15 @@
2432
}
2533
]
2634
],
27-
"plugins": ["babel-plugin-transform-async-to-promises"]
35+
"plugins": [
36+
[
37+
"const-enum",
38+
{
39+
"transform": "constObject"
40+
}
41+
],
42+
"babel-plugin-transform-async-to-promises"
43+
]
2844
}
2945
}
3046
}

.eslintrc

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
{
2626
"ignoreParameters": true
2727
}
28-
]
28+
],
29+
"no-shadow": "error"
2930
}
3031
}

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@
6363
"@typescript-eslint/parser": "^3.6.1",
6464
"babel-eslint": "^10.1.0",
6565
"babel-jest": "^26.0.1",
66+
"babel-plugin-const-enum": "^1.0.1",
6667
"babel-plugin-transform-async-to-promises": "^0.8.15",
6768
"cross-env": "^7.0.2",
6869
"eslint": "7.x",

src/core/query.ts

Lines changed: 27 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import {
99
isDocumentVisible,
1010
isOnline,
1111
isServer,
12+
isValidTimeout,
1213
noop,
1314
replaceEqualDeep,
1415
sleep,
@@ -26,14 +27,6 @@ import { QueryObserver, UpdateListener } from './queryObserver'
2627

2728
// TYPES
2829

29-
interface QueryInitConfig<TResult, TError> {
30-
queryCache: QueryCache
31-
queryKey: ArrayQueryKey
32-
queryHash: string
33-
config: QueryConfig<TResult, TError>
34-
notifyGlobalListeners: (query: Query<TResult, TError>) => void
35-
}
36-
3730
export interface QueryState<TResult, TError> {
3831
canFetchMore?: boolean
3932
data?: TResult
@@ -65,11 +58,11 @@ export interface RefetchOptions {
6558
throwOnError?: boolean
6659
}
6760

68-
export enum ActionType {
69-
Failed = 'Failed',
70-
Fetch = 'Fetch',
71-
Success = 'Success',
72-
Error = 'Error',
61+
const enum ActionType {
62+
Failed,
63+
Fetch,
64+
Success,
65+
Error,
7366
}
7467

7568
interface FailedAction {
@@ -114,17 +107,19 @@ export class Query<TResult, TError> {
114107
private cancelFetch?: () => void
115108
private continueFetch?: () => void
116109
private isTransportCancelable?: boolean
117-
private notifyGlobalListeners: (query: Query<TResult, TError>) => void
118-
119-
constructor(init: QueryInitConfig<TResult, TError>) {
120-
this.config = init.config
121-
this.queryCache = init.queryCache
122-
this.queryKey = init.queryKey
123-
this.queryHash = init.queryHash
124-
this.notifyGlobalListeners = init.notifyGlobalListeners
110+
111+
constructor(
112+
queryKey: ArrayQueryKey,
113+
queryHash: string,
114+
config: QueryConfig<TResult, TError>
115+
) {
116+
this.config = config
117+
this.queryKey = queryKey
118+
this.queryHash = queryHash
119+
this.queryCache = config.queryCache!
125120
this.observers = []
126-
this.state = getDefaultState(init.config)
127-
this.cacheTime = init.config.cacheTime!
121+
this.state = getDefaultState(config)
122+
this.cacheTime = config.cacheTime!
128123
this.scheduleGc()
129124
}
130125

@@ -140,7 +135,7 @@ export class Query<TResult, TError> {
140135
observer.onQueryUpdate(action)
141136
})
142137

143-
this.notifyGlobalListeners(this)
138+
this.queryCache.notifyGlobalListeners(this)
144139
}
145140

146141
private scheduleGc(): void {
@@ -150,7 +145,7 @@ export class Query<TResult, TError> {
150145

151146
this.clearGcTimeout()
152147

153-
if (this.cacheTime === Infinity || this.observers.length > 0) {
148+
if (this.observers.length > 0 || !isValidTimeout(this.cacheTime)) {
154149
return
155150
}
156151

@@ -222,7 +217,7 @@ export class Query<TResult, TError> {
222217
}
223218

224219
isStale(): boolean {
225-
return this.observers.some(observer => observer.isStale())
220+
return this.observers.some(observer => observer.getCurrentResult().isStale)
226221
}
227222

228223
isStaleByTime(staleTime = 0): boolean {
@@ -234,16 +229,16 @@ export class Query<TResult, TError> {
234229
onInteraction(type: 'focus' | 'online'): void {
235230
// Execute the first observer which is enabled,
236231
// stale and wants to refetch on this interaction.
237-
const observer = this.observers.find(
232+
const staleObserver = this.observers.find(
238233
observer =>
239-
observer.isStale() &&
234+
observer.getCurrentResult().isStale &&
240235
observer.config.enabled &&
241236
((observer.config.refetchOnWindowFocus && type === 'focus') ||
242237
(observer.config.refetchOnReconnect && type === 'online'))
243238
)
244239

245-
if (observer) {
246-
observer.fetch().catch(noop)
240+
if (staleObserver) {
241+
staleObserver.fetch().catch(noop)
247242
}
248243

249244
// Continue any paused fetch
@@ -280,9 +275,9 @@ export class Query<TResult, TError> {
280275
if (this.isTransportCancelable) {
281276
this.cancel()
282277
}
283-
}
284278

285-
this.scheduleGc()
279+
this.scheduleGc()
280+
}
286281
}
287282

288283
async refetch(

src/core/queryCache.ts

Lines changed: 10 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import {
44
functionalUpdate,
55
getQueryArgs,
66
isDocumentVisible,
7-
isObject,
7+
isPlainObject,
88
isOnline,
99
isServer,
1010
} from './utils'
@@ -77,18 +77,15 @@ export class QueryCache {
7777

7878
constructor(config?: QueryCacheConfig) {
7979
this.config = config || {}
80-
81-
// A frozen cache does not add new queries to the cache
8280
this.globalListeners = []
83-
8481
this.queries = {}
8582
this.queriesArray = []
8683
this.isFetching = 0
8784
}
8885

89-
private notifyGlobalListeners(query?: Query<any, any>) {
86+
notifyGlobalListeners(query?: Query<any, any>) {
9087
this.isFetching = this.getQueries().reduce(
91-
(acc, query) => (query.state.isFetching ? acc + 1 : acc),
88+
(acc, q) => (q.state.isFetching ? acc + 1 : acc),
9289
0
9390
)
9491

@@ -228,16 +225,9 @@ export class QueryCache {
228225
return this.queries[queryHash] as Query<TResult, TError>
229226
}
230227

231-
const query = new Query<TResult, TError>({
232-
queryCache: this,
233-
queryKey,
234-
queryHash,
235-
config,
236-
notifyGlobalListeners: query => {
237-
this.notifyGlobalListeners(query)
238-
},
239-
})
228+
const query = new Query<TResult, TError>(queryKey, queryHash, config)
240229

230+
// A frozen cache does not add new queries to the cache
241231
if (!this.config.frozen) {
242232
this.queries[queryHash] = query
243233
this.queriesArray.push(query)
@@ -291,7 +281,7 @@ export class QueryCache {
291281
...args: any[]
292282
): Promise<TResult | undefined> {
293283
if (
294-
isObject(args[1]) &&
284+
isPlainObject(args[1]) &&
295285
(args[1].hasOwnProperty('throwOnError') ||
296286
args[1].hasOwnProperty('force'))
297287
) {
@@ -312,9 +302,11 @@ export class QueryCache {
312302
...config,
313303
})
314304

315-
let query
316305
try {
317-
query = this.buildQuery<TResult, TError>(queryKey, configWithoutRetry)
306+
const query = this.buildQuery<TResult, TError>(
307+
queryKey,
308+
configWithoutRetry
309+
)
318310
if (options?.force || query.isStaleByTime(config.staleTime)) {
319311
await query.fetch(undefined, configWithoutRetry)
320312
}

src/core/queryObserver.ts

Lines changed: 19 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,9 @@
1-
import { getStatusProps, isServer, isDocumentVisible } from './utils'
1+
import {
2+
getStatusProps,
3+
isServer,
4+
isDocumentVisible,
5+
isValidTimeout,
6+
} from './utils'
27
import type { QueryResult, QueryObserverConfig } from './types'
38
import type { Query, Action, FetchMoreOptions, RefetchOptions } from './query'
49
import type { QueryCache } from './queryCache'
@@ -90,18 +95,12 @@ export class QueryObserver<TResult, TError> {
9095
// Update refetch interval if needed
9196
if (
9297
config.enabled !== prevConfig.enabled ||
93-
config.refetchInterval !== prevConfig.refetchInterval ||
94-
config.refetchIntervalInBackground !==
95-
prevConfig.refetchIntervalInBackground
98+
config.refetchInterval !== prevConfig.refetchInterval
9699
) {
97100
this.updateRefetchInterval()
98101
}
99102
}
100103

101-
isStale(): boolean {
102-
return this.currentResult.isStale
103-
}
104-
105104
getCurrentQuery(): Query<TResult, TError> {
106105
return this.currentQuery
107106
}
@@ -144,14 +143,6 @@ export class QueryObserver<TResult, TError> {
144143
}
145144
}
146145

147-
private updateIsStale(): void {
148-
const isStale = this.currentQuery.isStaleByTime(this.config.staleTime)
149-
if (isStale !== this.currentResult.isStale) {
150-
this.updateResult()
151-
this.notify()
152-
}
153-
}
154-
155146
private notify(): void {
156147
this.updateListener?.(this.currentResult)
157148
}
@@ -163,19 +154,19 @@ export class QueryObserver<TResult, TError> {
163154

164155
this.clearStaleTimeout()
165156

166-
const staleTime = this.config.staleTime || 0
167-
const { isStale, updatedAt } = this.currentResult
168-
169-
if (isStale || staleTime === Infinity) {
157+
if (this.currentResult.isStale || !isValidTimeout(this.config.staleTime)) {
170158
return
171159
}
172160

173-
const timeElapsed = Date.now() - updatedAt
174-
const timeUntilStale = staleTime - timeElapsed + 1
161+
const timeElapsed = Date.now() - this.currentResult.updatedAt
162+
const timeUntilStale = this.config.staleTime - timeElapsed + 1
175163
const timeout = Math.max(timeUntilStale, 0)
176164

177165
this.staleTimeoutId = setTimeout(() => {
178-
this.updateIsStale()
166+
if (!this.currentResult.isStale) {
167+
this.currentResult = { ...this.currentResult, isStale: true }
168+
this.notify()
169+
}
179170
}, timeout)
180171
}
181172

@@ -186,12 +177,7 @@ export class QueryObserver<TResult, TError> {
186177

187178
this.clearRefetchInterval()
188179

189-
if (
190-
!this.config.enabled ||
191-
!this.config.refetchInterval ||
192-
this.config.refetchInterval < 0 ||
193-
this.config.refetchInterval === Infinity
194-
) {
180+
if (!this.config.enabled || !isValidTimeout(this.config.refetchInterval)) {
195181
return
196182
}
197183

@@ -309,6 +295,8 @@ export class QueryObserver<TResult, TError> {
309295
}
310296

311297
onQueryUpdate(action: Action<TResult, TError>): void {
298+
const { type } = action
299+
312300
// Store current result and get new result
313301
const prevResult = this.currentResult
314302
this.updateResult()
@@ -317,11 +305,11 @@ export class QueryObserver<TResult, TError> {
317305

318306
// We need to check the action because the state could have
319307
// transitioned from success to success in case of `setQueryData`.
320-
if (action.type === 'Success' && currentResult.isSuccess) {
308+
if (type === 2) {
321309
config.onSuccess?.(currentResult.data!)
322310
config.onSettled?.(currentResult.data!, null)
323311
this.updateTimers()
324-
} else if (action.type === 'Error' && currentResult.isError) {
312+
} else if (type === 3) {
325313
config.onError?.(currentResult.error!)
326314
config.onSettled?.(undefined, currentResult.error!)
327315
this.updateTimers()

0 commit comments

Comments
 (0)