shelving 1.194.0 → 1.195.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/api/cache/APICache.d.ts +10 -2
- package/api/cache/APICache.js +13 -4
- package/api/cache/EndpointCache.d.ts +9 -2
- package/api/cache/EndpointCache.js +15 -4
- package/db/cache/CollectionCache.d.ts +5 -5
- package/db/cache/CollectionCache.js +10 -10
- package/db/cache/DBCache.d.ts +5 -5
- package/db/cache/DBCache.js +10 -10
- package/package.json +3 -3
- package/store/FetchStore.d.ts +4 -3
- package/store/FetchStore.js +12 -8
- package/store/Store.d.ts +9 -0
- package/store/Store.js +11 -0
package/api/cache/APICache.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { AnyCaller } from "../../util/function.js";
|
|
1
2
|
import type { Endpoint } from "../endpoint/Endpoint.js";
|
|
2
3
|
import type { APIProvider } from "../provider/APIProvider.js";
|
|
3
4
|
import { EndpointCache } from "./EndpointCache.js";
|
|
@@ -12,13 +13,20 @@ export declare class APICache<P, R> implements AsyncDisposable {
|
|
|
12
13
|
private _get;
|
|
13
14
|
/** Get (or create) the `EndpointCache` for the given endpoint. */
|
|
14
15
|
get<PP extends P, RR extends R>(endpoint: Endpoint<PP, RR>): EndpointCache<PP, RR>;
|
|
16
|
+
/**
|
|
17
|
+
* Fetch (or return a cached result) for the given endpoint and payload.
|
|
18
|
+
* - Returns the cached value immediately if one exists.
|
|
19
|
+
* - Waits for the in-flight fetch if the store is loading.
|
|
20
|
+
* - Throws if the fetch fails, matching `APIProvider.call` behaviour.
|
|
21
|
+
*/
|
|
22
|
+
call<PP extends P, RR extends R>(endpoint: Endpoint<PP, RR>, payload: PP, maxAge?: number, caller?: AnyCaller): Promise<RR>;
|
|
15
23
|
/** Invalidate a specific store for an endpoint. */
|
|
16
24
|
invalidate<PP extends P, RR extends R>(endpoint: Endpoint<PP, RR>, payload: PP): void;
|
|
17
25
|
/** Invalidate all stores for an endpoint. */
|
|
18
26
|
invalidateAll<PP extends P, RR extends R>(endpoint: Endpoint<PP, RR>): void;
|
|
19
27
|
/** Trigger a refetch on a specific store for an endpoint. */
|
|
20
|
-
refresh<PP extends P, RR extends R>(endpoint: Endpoint<PP, RR>, payload: PP): void;
|
|
28
|
+
refresh<PP extends P, RR extends R>(endpoint: Endpoint<PP, RR>, payload: PP, maxAge?: number): void;
|
|
21
29
|
/** Trigger a refetch on all stores for an endpoint. */
|
|
22
|
-
refreshAll<PP extends P, RR extends R>(endpoint: Endpoint<PP, RR
|
|
30
|
+
refreshAll<PP extends P, RR extends R>(endpoint: Endpoint<PP, RR>, maxAge?: number): void;
|
|
23
31
|
[Symbol.asyncDispose](): Promise<void>;
|
|
24
32
|
}
|
package/api/cache/APICache.js
CHANGED
|
@@ -17,6 +17,15 @@ export class APICache {
|
|
|
17
17
|
get(endpoint) {
|
|
18
18
|
return this._get(endpoint) || setMapItem(this._endpoints, endpoint, new EndpointCache(endpoint, this.provider));
|
|
19
19
|
}
|
|
20
|
+
/**
|
|
21
|
+
* Fetch (or return a cached result) for the given endpoint and payload.
|
|
22
|
+
* - Returns the cached value immediately if one exists.
|
|
23
|
+
* - Waits for the in-flight fetch if the store is loading.
|
|
24
|
+
* - Throws if the fetch fails, matching `APIProvider.call` behaviour.
|
|
25
|
+
*/
|
|
26
|
+
async call(endpoint, payload, maxAge, caller = this.call) {
|
|
27
|
+
return this.get(endpoint).call(payload, maxAge, caller);
|
|
28
|
+
}
|
|
20
29
|
/** Invalidate a specific store for an endpoint. */
|
|
21
30
|
invalidate(endpoint, payload) {
|
|
22
31
|
this._get(endpoint)?.invalidate(payload);
|
|
@@ -26,12 +35,12 @@ export class APICache {
|
|
|
26
35
|
this._get(endpoint)?.invalidateAll();
|
|
27
36
|
}
|
|
28
37
|
/** Trigger a refetch on a specific store for an endpoint. */
|
|
29
|
-
refresh(endpoint, payload) {
|
|
30
|
-
this._get(endpoint)?.refresh(payload);
|
|
38
|
+
refresh(endpoint, payload, maxAge) {
|
|
39
|
+
this._get(endpoint)?.refresh(payload, maxAge);
|
|
31
40
|
}
|
|
32
41
|
/** Trigger a refetch on all stores for an endpoint. */
|
|
33
|
-
refreshAll(endpoint) {
|
|
34
|
-
this._get(endpoint)?.refreshAll();
|
|
42
|
+
refreshAll(endpoint, maxAge) {
|
|
43
|
+
this._get(endpoint)?.refreshAll(maxAge);
|
|
35
44
|
}
|
|
36
45
|
// Implement `AsyncDisposable`
|
|
37
46
|
[Symbol.asyncDispose]() {
|
|
@@ -13,13 +13,20 @@ export declare class EndpointCache<P = unknown, R = unknown> implements AsyncDis
|
|
|
13
13
|
constructor(endpoint: Endpoint<P, R>, provider: APIProvider<P, R>);
|
|
14
14
|
/** Get (or create) the `EndpointStore` for the given payload. */
|
|
15
15
|
get(payload: P, caller?: AnyCaller): EndpointStore<P, R>;
|
|
16
|
+
/**
|
|
17
|
+
* Fetch (or return a cached result) for the given payload.
|
|
18
|
+
* - Returns the cached value immediately if one exists.
|
|
19
|
+
* - Waits for the in-flight fetch if the store is loading.
|
|
20
|
+
* - Throws if the fetch fails, matching `APIProvider.call` behaviour.
|
|
21
|
+
*/
|
|
22
|
+
call(payload: P, maxAge?: number, caller?: AnyCaller): Promise<R>;
|
|
16
23
|
/** Invalidate a specific store. */
|
|
17
24
|
invalidate(payload: P, caller?: AnyCaller): void;
|
|
18
25
|
/** Invalidate all stores. */
|
|
19
26
|
invalidateAll(): void;
|
|
20
27
|
/** Trigger a refetch on a specific store. */
|
|
21
|
-
refresh(payload: P, caller?: AnyCaller): Promise<void>;
|
|
28
|
+
refresh(payload: P, maxAge?: number, caller?: AnyCaller): Promise<void>;
|
|
22
29
|
/** Trigger a refetch on all stores. */
|
|
23
|
-
refreshAll(): Promise<void>;
|
|
30
|
+
refreshAll(maxAge?: number): Promise<void>;
|
|
24
31
|
[Symbol.asyncDispose](): Promise<void>;
|
|
25
32
|
}
|
|
@@ -19,6 +19,17 @@ export class EndpointCache {
|
|
|
19
19
|
const url = this.provider.renderURL(this.endpoint, payload, caller).href;
|
|
20
20
|
return this._endpoints.get(url) || setMapItem(this._endpoints, url, new EndpointStore(this.endpoint, payload, this.provider));
|
|
21
21
|
}
|
|
22
|
+
/**
|
|
23
|
+
* Fetch (or return a cached result) for the given payload.
|
|
24
|
+
* - Returns the cached value immediately if one exists.
|
|
25
|
+
* - Waits for the in-flight fetch if the store is loading.
|
|
26
|
+
* - Throws if the fetch fails, matching `APIProvider.call` behaviour.
|
|
27
|
+
*/
|
|
28
|
+
async call(payload, maxAge, caller = this.call) {
|
|
29
|
+
const store = this.get(payload, caller);
|
|
30
|
+
await store.refresh(maxAge);
|
|
31
|
+
return store.value;
|
|
32
|
+
}
|
|
22
33
|
/** Invalidate a specific store. */
|
|
23
34
|
invalidate(payload, caller = this.invalidate) {
|
|
24
35
|
this.get(payload, caller)?.invalidate();
|
|
@@ -29,12 +40,12 @@ export class EndpointCache {
|
|
|
29
40
|
store.invalidate();
|
|
30
41
|
}
|
|
31
42
|
/** Trigger a refetch on a specific store. */
|
|
32
|
-
async refresh(payload, caller = this.invalidate) {
|
|
33
|
-
await this.get(payload, caller)?.refresh();
|
|
43
|
+
async refresh(payload, maxAge, caller = this.invalidate) {
|
|
44
|
+
await this.get(payload, caller)?.refresh(maxAge);
|
|
34
45
|
}
|
|
35
46
|
/** Trigger a refetch on all stores. */
|
|
36
|
-
async refreshAll() {
|
|
37
|
-
await awaitValues(...this._endpoints.values().map(store => store.refresh()));
|
|
47
|
+
async refreshAll(maxAge) {
|
|
48
|
+
await awaitValues(...this._endpoints.values().map(store => store.refresh(maxAge)));
|
|
38
49
|
}
|
|
39
50
|
// Implement `AsyncDisposable`
|
|
40
51
|
[Symbol.asyncDispose]() {
|
|
@@ -23,15 +23,15 @@ export declare class CollectionCache<I extends Identifier, T extends Data> imple
|
|
|
23
23
|
/** Get (or create) the `QueryStore` for the given query. */
|
|
24
24
|
getQuery(query: Query<Item<I, T>>): QueryStore<I, T>;
|
|
25
25
|
/** Refresh a specific item store. */
|
|
26
|
-
refreshItem(id: I): Promise<void>;
|
|
26
|
+
refreshItem(id: I, maxAge?: number): Promise<void>;
|
|
27
27
|
/** Refresh every cached item store. */
|
|
28
|
-
refreshItems(): Promise<void>;
|
|
28
|
+
refreshItems(maxAge?: number): Promise<void>;
|
|
29
29
|
/** Refresh a specific query store. */
|
|
30
|
-
refreshQuery(query: Query<Item<I, T
|
|
30
|
+
refreshQuery(query: Query<Item<I, T>>, maxAge?: number): Promise<void>;
|
|
31
31
|
/** Refresh every cached query store. */
|
|
32
|
-
refreshQueries(): Promise<void>;
|
|
32
|
+
refreshQueries(maxAge?: number): Promise<void>;
|
|
33
33
|
/** Refresh every cached store (items and queries). */
|
|
34
|
-
refreshAll(): Promise<void>;
|
|
34
|
+
refreshAll(maxAge?: number): Promise<void>;
|
|
35
35
|
private _queryKey;
|
|
36
36
|
[Symbol.asyncDispose](): Promise<void>;
|
|
37
37
|
}
|
|
@@ -29,24 +29,24 @@ export class CollectionCache {
|
|
|
29
29
|
return this._queries.get(key) || setMapItem(this._queries, key, new QueryStore(this.collection, query, this.provider, this.memory));
|
|
30
30
|
}
|
|
31
31
|
/** Refresh a specific item store. */
|
|
32
|
-
async refreshItem(id) {
|
|
33
|
-
await this._items.get(id)?.refresh();
|
|
32
|
+
async refreshItem(id, maxAge) {
|
|
33
|
+
await this._items.get(id)?.refresh(maxAge);
|
|
34
34
|
}
|
|
35
35
|
/** Refresh every cached item store. */
|
|
36
|
-
async refreshItems() {
|
|
37
|
-
await awaitValues(...this._items.values().map(store => store.refresh()));
|
|
36
|
+
async refreshItems(maxAge) {
|
|
37
|
+
await awaitValues(...this._items.values().map(store => store.refresh(maxAge)));
|
|
38
38
|
}
|
|
39
39
|
/** Refresh a specific query store. */
|
|
40
|
-
async refreshQuery(query) {
|
|
41
|
-
await this._queries.get(this._queryKey(query))?.refresh();
|
|
40
|
+
async refreshQuery(query, maxAge) {
|
|
41
|
+
await this._queries.get(this._queryKey(query))?.refresh(maxAge);
|
|
42
42
|
}
|
|
43
43
|
/** Refresh every cached query store. */
|
|
44
|
-
async refreshQueries() {
|
|
45
|
-
await awaitValues(...this._queries.values().map(store => store.refresh()));
|
|
44
|
+
async refreshQueries(maxAge) {
|
|
45
|
+
await awaitValues(...this._queries.values().map(store => store.refresh(maxAge)));
|
|
46
46
|
}
|
|
47
47
|
/** Refresh every cached store (items and queries). */
|
|
48
|
-
async refreshAll() {
|
|
49
|
-
await awaitValues(this.refreshItems(), this.refreshQueries());
|
|
48
|
+
async refreshAll(maxAge) {
|
|
49
|
+
await awaitValues(this.refreshItems(maxAge), this.refreshQueries(maxAge));
|
|
50
50
|
}
|
|
51
51
|
_queryKey(query) {
|
|
52
52
|
return JSON.stringify(query);
|
package/db/cache/DBCache.d.ts
CHANGED
|
@@ -25,14 +25,14 @@ export declare class DBCache<I extends Identifier = Identifier, T extends Data =
|
|
|
25
25
|
/** Get (or create) a `QueryStore` for a collection/query in one hop. */
|
|
26
26
|
getQuery<II extends I, TT extends T>(collection: Collection<string, II, TT>, query: Query<Item<II, TT>>): QueryStore<II, TT>;
|
|
27
27
|
/** Refresh a specific item store for a collection. */
|
|
28
|
-
refreshItem<II extends I, TT extends T>(collection: Collection<string, II, TT>, id: II): Promise<void>;
|
|
28
|
+
refreshItem<II extends I, TT extends T>(collection: Collection<string, II, TT>, id: II, maxAge?: number): Promise<void>;
|
|
29
29
|
/** Refresh every cached item store for a collection. */
|
|
30
|
-
refreshItems<II extends I, TT extends T>(collection: Collection<string, II, TT
|
|
30
|
+
refreshItems<II extends I, TT extends T>(collection: Collection<string, II, TT>, maxAge?: number): Promise<void>;
|
|
31
31
|
/** Refresh a specific query store for a collection. */
|
|
32
|
-
refreshQuery<II extends I, TT extends T>(collection: Collection<string, II, TT>, query: Query<Item<II, TT
|
|
32
|
+
refreshQuery<II extends I, TT extends T>(collection: Collection<string, II, TT>, query: Query<Item<II, TT>>, maxAge?: number): Promise<void>;
|
|
33
33
|
/** Refresh every cached query store for a collection. */
|
|
34
|
-
refreshQueries<II extends I, TT extends T>(collection: Collection<string, II, TT
|
|
34
|
+
refreshQueries<II extends I, TT extends T>(collection: Collection<string, II, TT>, maxAge?: number): Promise<void>;
|
|
35
35
|
/** Refresh every cached store (items and queries) for a collection. */
|
|
36
|
-
refreshAll<II extends I, TT extends T>(collection: Collection<string, II, TT
|
|
36
|
+
refreshAll<II extends I, TT extends T>(collection: Collection<string, II, TT>, maxAge?: number): Promise<void>;
|
|
37
37
|
[Symbol.asyncDispose](): Promise<void>;
|
|
38
38
|
}
|
package/db/cache/DBCache.js
CHANGED
|
@@ -32,24 +32,24 @@ export class DBCache {
|
|
|
32
32
|
return this.get(collection).getQuery(query);
|
|
33
33
|
}
|
|
34
34
|
/** Refresh a specific item store for a collection. */
|
|
35
|
-
async refreshItem(collection, id) {
|
|
36
|
-
await this._get(collection)?.refreshItem(id);
|
|
35
|
+
async refreshItem(collection, id, maxAge) {
|
|
36
|
+
await this._get(collection)?.refreshItem(id, maxAge);
|
|
37
37
|
}
|
|
38
38
|
/** Refresh every cached item store for a collection. */
|
|
39
|
-
async refreshItems(collection) {
|
|
40
|
-
await this._get(collection)?.refreshItems();
|
|
39
|
+
async refreshItems(collection, maxAge) {
|
|
40
|
+
await this._get(collection)?.refreshItems(maxAge);
|
|
41
41
|
}
|
|
42
42
|
/** Refresh a specific query store for a collection. */
|
|
43
|
-
async refreshQuery(collection, query) {
|
|
44
|
-
await this._get(collection)?.refreshQuery(query);
|
|
43
|
+
async refreshQuery(collection, query, maxAge) {
|
|
44
|
+
await this._get(collection)?.refreshQuery(query, maxAge);
|
|
45
45
|
}
|
|
46
46
|
/** Refresh every cached query store for a collection. */
|
|
47
|
-
async refreshQueries(collection) {
|
|
48
|
-
await this._get(collection)?.refreshQueries();
|
|
47
|
+
async refreshQueries(collection, maxAge) {
|
|
48
|
+
await this._get(collection)?.refreshQueries(maxAge);
|
|
49
49
|
}
|
|
50
50
|
/** Refresh every cached store (items and queries) for a collection. */
|
|
51
|
-
async refreshAll(collection) {
|
|
52
|
-
await this._get(collection)?.refreshAll();
|
|
51
|
+
async refreshAll(collection, maxAge) {
|
|
52
|
+
await this._get(collection)?.refreshAll(maxAge);
|
|
53
53
|
}
|
|
54
54
|
// Implement `AsyncDisposable`
|
|
55
55
|
async [Symbol.asyncDispose]() {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "shelving",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.195.0",
|
|
4
4
|
"author": "Dave Houlbrooke <dave@shax.com>",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -9,12 +9,12 @@
|
|
|
9
9
|
"main": "./index.js",
|
|
10
10
|
"module": "./index.js",
|
|
11
11
|
"devDependencies": {
|
|
12
|
-
"@biomejs/biome": "^2.4.
|
|
12
|
+
"@biomejs/biome": "^2.4.14",
|
|
13
13
|
"@google-cloud/firestore": "^8.5.0",
|
|
14
14
|
"@types/bun": "^1.3.13",
|
|
15
15
|
"@types/react": "^19.2.14",
|
|
16
16
|
"@types/react-dom": "^19.2.3",
|
|
17
|
-
"@typescript/native-preview": "^7.0.0-dev.
|
|
17
|
+
"@typescript/native-preview": "^7.0.0-dev.20260502.1",
|
|
18
18
|
"firebase": "^12.12.1",
|
|
19
19
|
"react": "^19.2.5",
|
|
20
20
|
"react-dom": "^19.2.5"
|
package/store/FetchStore.d.ts
CHANGED
|
@@ -14,6 +14,7 @@ export declare class FetchStore<T, TT = T> extends BusyStore<T, TT> {
|
|
|
14
14
|
get loading(): boolean;
|
|
15
15
|
write(input: StoreInput<TT>): void;
|
|
16
16
|
read(): import("./Store.js").StoreInternal<T>;
|
|
17
|
+
get age(): number;
|
|
17
18
|
constructor(value: T | typeof NONE, callback?: FetchCallback<TT>);
|
|
18
19
|
/**
|
|
19
20
|
* Fetch the result for this store now.
|
|
@@ -21,7 +22,7 @@ export declare class FetchStore<T, TT = T> extends BusyStore<T, TT> {
|
|
|
21
22
|
* - Refreshes are de-duplicated. Concurrent calls while a fetch is in-flight return the same promise.
|
|
22
23
|
* - Never throws — errors are stored as `reason`.
|
|
23
24
|
*/
|
|
24
|
-
refresh(): Promise<boolean> | boolean;
|
|
25
|
+
refresh(maxAge?: number): Promise<boolean> | boolean;
|
|
25
26
|
private _pendingRefresh;
|
|
26
27
|
/**
|
|
27
28
|
* Current `AbortSignal` for this store's in-flight fetch.
|
|
@@ -36,13 +37,13 @@ export declare class FetchStore<T, TT = T> extends BusyStore<T, TT> {
|
|
|
36
37
|
*/
|
|
37
38
|
protected _fetch(signal: AbortSignal): TT | PromiseLike<TT>;
|
|
38
39
|
private _callback;
|
|
40
|
+
/** Whether this store is has currently been invalidated and needs a refresh. */
|
|
41
|
+
get invalidated(): boolean;
|
|
39
42
|
/**
|
|
40
43
|
* Invalidate this store so a new fetch is triggered on the next read of `loading` or `value`.
|
|
41
44
|
* - Triggers `abort()` so any current awaits are cancelled.
|
|
42
45
|
*/
|
|
43
46
|
invalidate(): void;
|
|
44
47
|
private _invalidation;
|
|
45
|
-
/** Re-fetch now if the current value is older than `maxAge` milliseconds or has been invalidated. */
|
|
46
|
-
refreshStale(maxAge: number): Promise<boolean> | boolean;
|
|
47
48
|
abort(): void;
|
|
48
49
|
}
|
package/store/FetchStore.js
CHANGED
|
@@ -15,7 +15,7 @@ export class FetchStore extends BusyStore {
|
|
|
15
15
|
// We optimistically refresh so the value is available the next time the user wants it.
|
|
16
16
|
get loading() {
|
|
17
17
|
const loading = super.loading;
|
|
18
|
-
if (this.
|
|
18
|
+
if (this.invalidated || loading)
|
|
19
19
|
void this.refresh();
|
|
20
20
|
return loading;
|
|
21
21
|
}
|
|
@@ -33,6 +33,10 @@ export class FetchStore extends BusyStore {
|
|
|
33
33
|
this.loading; // Ping loading to possibly trigger the intiial fetch.
|
|
34
34
|
return super.read();
|
|
35
35
|
}
|
|
36
|
+
// Override to consider invalid to be really old.
|
|
37
|
+
get age() {
|
|
38
|
+
return this.invalidated ? Infinity : super.age;
|
|
39
|
+
}
|
|
36
40
|
// Override to create to save `callback`
|
|
37
41
|
constructor(value, callback) {
|
|
38
42
|
super(value);
|
|
@@ -44,9 +48,11 @@ export class FetchStore extends BusyStore {
|
|
|
44
48
|
* - Refreshes are de-duplicated. Concurrent calls while a fetch is in-flight return the same promise.
|
|
45
49
|
* - Never throws — errors are stored as `reason`.
|
|
46
50
|
*/
|
|
47
|
-
refresh() {
|
|
51
|
+
refresh(maxAge) {
|
|
48
52
|
if (this._pendingRefresh)
|
|
49
53
|
return this._pendingRefresh;
|
|
54
|
+
if (!this.stale(maxAge))
|
|
55
|
+
return false;
|
|
50
56
|
try {
|
|
51
57
|
const value = this._fetch(this.signal); // Retrieving a new signal calls `abort()` which cancels the previous one.
|
|
52
58
|
if (isAsync(value))
|
|
@@ -81,6 +87,10 @@ export class FetchStore extends BusyStore {
|
|
|
81
87
|
return this._callback(signal);
|
|
82
88
|
}
|
|
83
89
|
_callback;
|
|
90
|
+
/** Whether this store is has currently been invalidated and needs a refresh. */
|
|
91
|
+
get invalidated() {
|
|
92
|
+
return !!this._invalidation;
|
|
93
|
+
}
|
|
84
94
|
/**
|
|
85
95
|
* Invalidate this store so a new fetch is triggered on the next read of `loading` or `value`.
|
|
86
96
|
* - Triggers `abort()` so any current awaits are cancelled.
|
|
@@ -90,12 +100,6 @@ export class FetchStore extends BusyStore {
|
|
|
90
100
|
this._invalidation++;
|
|
91
101
|
}
|
|
92
102
|
_invalidation = 0;
|
|
93
|
-
/** Re-fetch now if the current value is older than `maxAge` milliseconds or has been invalidated. */
|
|
94
|
-
refreshStale(maxAge) {
|
|
95
|
-
if (this._invalidation || this.age > maxAge)
|
|
96
|
-
return this.refresh();
|
|
97
|
-
return true;
|
|
98
|
-
}
|
|
99
103
|
// Override to abort any current in-flight fetch and pending async operation.
|
|
100
104
|
// - Sends `ABORT` to the current `AbortSignal` and clears the controller (a new signal will be created on the next read or fetch).
|
|
101
105
|
// - Any pending `await()` result will be silently discarded.
|
package/store/Store.d.ts
CHANGED
|
@@ -92,6 +92,15 @@ export declare class Store<T, TT = T> implements AsyncIterable<T, void, void>, A
|
|
|
92
92
|
* @example if (store.age > MINUTE) refreshStore(store);
|
|
93
93
|
*/
|
|
94
94
|
get age(): number;
|
|
95
|
+
/**
|
|
96
|
+
* Whether this store is stale based on a `maxAge` value in milliseconds.
|
|
97
|
+
*
|
|
98
|
+
* @param maxAge The maximum age for the stale check.
|
|
99
|
+
* - `0` zero means "always refresh" (this is the default).
|
|
100
|
+
* - `Infinity` means "refresh only if store is still in a loading state.
|
|
101
|
+
* - Any other value may or may not be stale based on `this.age`
|
|
102
|
+
*/
|
|
103
|
+
stale(maxAge?: number): boolean;
|
|
95
104
|
/** Current error of this store, or `undefined` if there is no error. */
|
|
96
105
|
get reason(): unknown;
|
|
97
106
|
set reason(reason: unknown);
|
package/store/Store.js
CHANGED
|
@@ -132,6 +132,17 @@ export class Store {
|
|
|
132
132
|
const time = this.time;
|
|
133
133
|
return typeof time === "number" ? Date.now() - time : Infinity;
|
|
134
134
|
}
|
|
135
|
+
/**
|
|
136
|
+
* Whether this store is stale based on a `maxAge` value in milliseconds.
|
|
137
|
+
*
|
|
138
|
+
* @param maxAge The maximum age for the stale check.
|
|
139
|
+
* - `0` zero means "always refresh" (this is the default).
|
|
140
|
+
* - `Infinity` means "refresh only if store is still in a loading state.
|
|
141
|
+
* - Any other value may or may not be stale based on `this.age`
|
|
142
|
+
*/
|
|
143
|
+
stale(maxAge = 0) {
|
|
144
|
+
return this.age >= maxAge;
|
|
145
|
+
}
|
|
135
146
|
/** Current error of this store, or `undefined` if there is no error. */
|
|
136
147
|
get reason() {
|
|
137
148
|
return this._reason;
|