Skip to content

Commit

Permalink
refactor(core): add reusable rxSwr operator
Browse files Browse the repository at this point in the history
  • Loading branch information
bjoerge committed Sep 30, 2024
1 parent 6859b0a commit 332168b
Show file tree
Hide file tree
Showing 2 changed files with 56 additions and 0 deletions.
1 change: 1 addition & 0 deletions packages/sanity/src/core/util/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ export * from './isString'
export * from './isTruthy'
export * from './PartialExcept'
export * from './resizeObserver'
export * from './rxSwr'
export * from './schemaUtils'
export * from './searchUtils'
export * from './supportsTouch'
Expand Down
55 changes: 55 additions & 0 deletions packages/sanity/src/core/util/rxSwr.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import QuickLRU from 'quick-lru'
import {concat, defer, EMPTY, map, type Observable, of, type OperatorFunction} from 'rxjs'
import {tap} from 'rxjs/operators'

interface SWRCache<T> {
/**
* Note: This will throw if key does not exist. Always check for existence with `has` before calling
*/
get(key: string): T
has(key: string): boolean
set(key: string, value: T): void
delete(key: string): void
}

const createSWRCache = createLRUCache

export function createSWR<T>(options: {maxSize: number}) {
const cache = createSWRCache<T>(options)
return function rxSwr(key: string): OperatorFunction<T, {fromCache: boolean; value: T}> {
return (input$: Observable<T>) => {
return concat(
defer(() => (cache.has(key) ? of({fromCache: true, value: cache.get(key)}) : EMPTY)),
input$.pipe(
tap((result) => cache.set(key, result)),
map((value) => ({
fromCache: false,
value: value,
})),
),
)
}
}
}

function createLRUCache<T>(options: {maxSize: number}): SWRCache<T> {
const lru = new QuickLRU<string, {value: T}>(options)
return {
get(key: string) {
const entry = lru.get(key)
if (!entry) {
throw new Error(`Key not found in LRU cache: ${key}`)
}
return entry.value
},
set(key: string, value: T) {
lru.set(key, {value})
},
delete(key: string) {
lru.delete(key)
},
has(key: string) {
return lru.has(key)
},
}
}

0 comments on commit 332168b

Please sign in to comment.