Skip to content

Commit

Permalink
Add method to force a refresh from a cached function (#33)
Browse files Browse the repository at this point in the history
  • Loading branch information
cheap-glitch authored Aug 6, 2022
1 parent d49454a commit 126304e
Show file tree
Hide file tree
Showing 4 changed files with 36 additions and 15 deletions.
18 changes: 7 additions & 11 deletions index.test-d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,10 @@ expectAssignable<Promise<Record<string, any[]>>>(cache.set('key', {wow: [true, '
expectAssignable<Promise<number>>(cache.set('key', 1, {days: 1}));

const cachedPower = cache.function(async (n: number) => n ** 1000);
expectType<(n: number) => Promise<number>>(cachedPower);
expectType<((n: number) => Promise<number>) & {fresh: (n: number) => Promise<number>}>(cachedPower);
expectType<number>(await cachedPower(1));

expectType<(n: string) => Promise<number>>(
cache.function(async (n: string) => Number(n)),
);

expectType<(n: string) => Promise<number>>(
expectType<((n: string) => Promise<number>) & {fresh: (n: string) => Promise<number>}>(
cache.function(async (n: string) => Number(n)),
);

Expand All @@ -40,32 +36,32 @@ expectType<Promise<string>>(cache.function(identity)('1'));
expectNotAssignable<Promise<string>>(cache.function(identity)(1));
expectNotAssignable<Promise<number>>(cache.function(identity)('1'));

expectType<(n: string) => Promise<number>>(
expectType<((n: string) => Promise<number>) & {fresh: (n: string) => Promise<number>}>(
cache.function(async (n: string) => Number(n), {
maxAge: {days: 20},
}),
);

expectType<(n: string) => Promise<number>>(
expectType<((n: string) => Promise<number>) & {fresh: (n: string) => Promise<number>}>(
cache.function(async (n: string) => Number(n), {
maxAge: {days: 20},
staleWhileRevalidate: {days: 5},
}),
);

expectType<(date: Date) => Promise<string>>(
expectType<((date: Date) => Promise<string>) & {fresh: (date: Date) => Promise<string>}>(
cache.function(async (date: Date) => String(date.getHours()), {
cacheKey: ([date]) => date.toLocaleString(),
}),
);

expectType<(date: Date) => Promise<string>>(
expectType<((date: Date) => Promise<string>) & {fresh: (date: Date) => Promise<string>}>(
cache.function(async (date: Date) => String(date.getHours()), {
shouldRevalidate: date => typeof date === 'string',
}),
);

// This function won't be cached
expectType<(n: undefined[]) => Promise<undefined>>(
expectType<((n: undefined[]) => Promise<undefined>) & {fresh: (n: undefined[]) => Promise<undefined>}>(
cache.function(async (n: undefined[]) => n[1]),
);
14 changes: 10 additions & 4 deletions index.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import chromeP from 'webext-polyfill-kinda';
import microMemoize from 'micro-memoize';
import {isBackgroundPage, isExtensionContext} from 'webext-detect-page';
import toMilliseconds, {TimeDescriptor} from '@sindresorhus/to-milliseconds';
import chromeP from 'webext-polyfill-kinda';

const cacheDefault = {days: 30};

Expand Down Expand Up @@ -128,7 +128,7 @@ function function_<
staleWhileRevalidate = {days: 0},
shouldRevalidate,
}: MemoizedFunctionOptions<Arguments, ScopedValue> = {},
): Getter {
): Getter & {fresh: Getter} {
const getSet = async (
key: string,
args: Arguments,
Expand All @@ -144,7 +144,7 @@ function function_<
return set<ScopedValue>(key, freshValue, {milliseconds});
};

return microMemoize((async (...args: Arguments) => {
return Object.assign(microMemoize((async (...args: Arguments) => {
const userKey = cacheKey ? cacheKey(args) : (args[0] as string);
const cachedItem = await _get<ScopedValue>(userKey, false);
if (cachedItem === undefined || shouldRevalidate?.(cachedItem.data)) {
Expand All @@ -157,7 +157,13 @@ function function_<
}

return cachedItem.data;
}) as Getter);
}) as Getter), {
fresh: (async (...args: Arguments) => {
const userKey = cacheKey ? cacheKey(args) : (args[0] as string);

return getSet(userKey, args);
}) as Getter,
});
}

const cache = {
Expand Down
3 changes: 3 additions & 0 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,9 @@ const cachedGetHTML = cache.function(getHTML);

const html = await cachedGetHTML('https://google.com', {});
// The HTML of google.com will be saved with the key 'https://google.com'

const freshHtml = await cachedGetHTML.fresh('https://google.com', {});
// Escape hatch to ignore memoization and force a refresh of the cache
```

#### getter
Expand Down
16 changes: 16 additions & 0 deletions test/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -279,3 +279,19 @@ test.serial('function() avoids duplicate nearby function calls', async t => {
await call('@anne', cacheMePlease);
t.is(spy.callCount, 1);
});

test.serial('function.fresh() ignores cached value', async t => {
createCache(10, {
'cache:@anne': 'OVERWRITE_ME',
});

const spy = sinon.spy(getUsernameDemo);
const call = cache.function(spy);

t.is(await call.fresh('@anne'), 'ANNE');

t.true(spy.withArgs('@anne').calledOnce);
t.is(spy.callCount, 1);
t.is(chrome.storage.local.get.callCount, 0);
t.is(chrome.storage.local.set.lastCall.args[0]['cache:@anne'].data, 'ANNE');
});

0 comments on commit 126304e

Please sign in to comment.