shelving 1.88.0 → 1.89.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/db/ItemState.d.ts +1 -1
- package/db/QueryState.d.ts +2 -2
- package/package.json +1 -1
- package/react/createCache.d.ts +15 -0
- package/react/createCache.js +21 -0
- package/react/index.d.ts +1 -1
- package/react/index.js +1 -1
- package/react/useData.d.ts +10 -7
- package/react/useData.js +7 -3
- package/util/data.d.ts +4 -1
- package/util/data.js +3 -0
- package/util/object.d.ts +4 -0
- package/util/object.js +3 -0
- package/react/useCache.d.ts +0 -46
- package/react/useCache.js +0 -56
package/db/ItemState.d.ts
CHANGED
|
@@ -14,7 +14,7 @@ export declare class ItemState<T extends Datas, K extends DataKey<T> = DataKey<T
|
|
|
14
14
|
constructor(ref: Item<T, K> | AsyncItem<T, K>);
|
|
15
15
|
/** Refresh this state from the source provider. */
|
|
16
16
|
readonly refresh: () => void;
|
|
17
|
-
_refresh
|
|
17
|
+
private _refresh;
|
|
18
18
|
/** Refresh this state if data in the cache is older than `maxAge` (in milliseconds). */
|
|
19
19
|
refreshStale(maxAge: number): void;
|
|
20
20
|
/** Subscribe this state to the source provider. */
|
package/db/QueryState.d.ts
CHANGED
|
@@ -27,7 +27,7 @@ export declare class QueryState<T extends Datas, K extends DataKey<T> = DataKey<
|
|
|
27
27
|
constructor(ref: Query<T, K> | AsyncQuery<T, K>);
|
|
28
28
|
/** Refresh this state from the source provider. */
|
|
29
29
|
readonly refresh: () => void;
|
|
30
|
-
_refresh
|
|
30
|
+
private _refresh;
|
|
31
31
|
/** Refresh this state if data in the cache is older than `maxAge` (in milliseconds). */
|
|
32
32
|
refreshStale(maxAge: number): void;
|
|
33
33
|
/** Subscribe this state to the source provider. */
|
|
@@ -37,7 +37,7 @@ export declare class QueryState<T extends Datas, K extends DataKey<T> = DataKey<
|
|
|
37
37
|
* - Promise that needs to be handled.
|
|
38
38
|
*/
|
|
39
39
|
readonly loadMore: () => void;
|
|
40
|
-
_loadMore
|
|
40
|
+
private _loadMore;
|
|
41
41
|
/** Iterate over the items. */
|
|
42
42
|
[Symbol.iterator](): Iterator<ItemData<T[K]>>;
|
|
43
43
|
}
|
package/package.json
CHANGED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/// <reference types="react" />
|
|
2
|
+
/**
|
|
3
|
+
* Interface for a cache controller.
|
|
4
|
+
* - Cache is a `Map` indexed by strings that can be used to store any value.
|
|
5
|
+
*/
|
|
6
|
+
export interface CacheController<T> {
|
|
7
|
+
/** Wrap around a set of elements to provide the cache to them. */
|
|
8
|
+
readonly Cache: ({ children }: {
|
|
9
|
+
children: React.ReactNode;
|
|
10
|
+
}) => React.ReactElement;
|
|
11
|
+
/** Use the current cache map in a component. */
|
|
12
|
+
readonly useCache: () => Map<string, T>;
|
|
13
|
+
}
|
|
14
|
+
/** Create a cache. */
|
|
15
|
+
export declare function createCache<T>(): CacheController<T>;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { useContext, createContext, createElement } from "react";
|
|
2
|
+
import { ConditionError } from "../error/ConditionError.js";
|
|
3
|
+
import { useReduce } from "./useReduce.js";
|
|
4
|
+
/** Reducer that gets an existing `Map` instance or creates a new one. */
|
|
5
|
+
const _reduceMap = (previous) => previous || new Map();
|
|
6
|
+
/** Create a cache. */
|
|
7
|
+
export function createCache() {
|
|
8
|
+
const context = createContext(undefined);
|
|
9
|
+
return {
|
|
10
|
+
useCache: () => {
|
|
11
|
+
const cache = useContext(context);
|
|
12
|
+
if (!cache)
|
|
13
|
+
throw new ConditionError("useCache() must be used inside <Cache>");
|
|
14
|
+
return cache;
|
|
15
|
+
},
|
|
16
|
+
Cache: ({ children }) => {
|
|
17
|
+
const cache = useReduce(_reduceMap);
|
|
18
|
+
return createElement(context.Provider, { children, value: cache });
|
|
19
|
+
},
|
|
20
|
+
};
|
|
21
|
+
}
|
package/react/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export * from "./useLazy.js";
|
|
2
2
|
export * from "./useReduce.js";
|
|
3
3
|
export * from "./useInstance.js";
|
|
4
|
-
export * from "./
|
|
4
|
+
export * from "./createCache.js";
|
|
5
5
|
export * from "./useSequence.js";
|
|
6
6
|
export * from "./useState.js";
|
|
7
7
|
export * from "./useData.js";
|
package/react/index.js
CHANGED
package/react/useData.d.ts
CHANGED
|
@@ -1,15 +1,18 @@
|
|
|
1
|
+
/// <reference types="react" />
|
|
1
2
|
import type { ImmutableArray } from "../util/array.js";
|
|
2
|
-
import { DataKey, Datas } from "../util/data.js";
|
|
3
3
|
import { AsyncItem } from "../db/Item.js";
|
|
4
4
|
import { ItemState } from "../db/ItemState.js";
|
|
5
5
|
import { AsyncQuery } from "../db/Query.js";
|
|
6
6
|
import { QueryState } from "../db/QueryState.js";
|
|
7
|
-
type
|
|
8
|
-
type
|
|
7
|
+
type AnyRef = AsyncItem<any, any> | AsyncQuery<any, any>;
|
|
8
|
+
type RefToState<T> = T extends undefined ? undefined : T extends AsyncItem<infer D, infer K> ? ItemState<D, K> : T extends AsyncQuery<infer D, infer K> ? QueryState<D, K> : never;
|
|
9
9
|
/** Use one or more data items or queries. */
|
|
10
|
-
export declare function useData<T extends
|
|
11
|
-
export declare function useData<T extends
|
|
12
|
-
|
|
13
|
-
[K in keyof T]: ReferenceReferenceState<T[K]>;
|
|
10
|
+
export declare function useData<T extends AnyRef | undefined>(ref: T): RefToState<T>;
|
|
11
|
+
export declare function useData<T extends ImmutableArray<AnyRef | undefined>>(...refs: T): {
|
|
12
|
+
[K in keyof T]: RefToState<T[K]>;
|
|
14
13
|
};
|
|
14
|
+
/** Wrap components with `<DataCache>` to allow the use of `useData()`. */
|
|
15
|
+
export declare const DataCache: ({ children }: {
|
|
16
|
+
children: import("react").ReactNode;
|
|
17
|
+
}) => import("react").ReactElement<any, string | import("react").JSXElementConstructor<any>>;
|
|
15
18
|
export {};
|
package/react/useData.js
CHANGED
|
@@ -4,14 +4,18 @@ import { AsyncItem } from "../db/Item.js";
|
|
|
4
4
|
import { ItemState } from "../db/ItemState.js";
|
|
5
5
|
import { QueryState } from "../db/QueryState.js";
|
|
6
6
|
import { useState } from "./useState.js";
|
|
7
|
-
import {
|
|
7
|
+
import { createCache } from "./createCache.js";
|
|
8
|
+
/** Create a cache. */
|
|
9
|
+
const { Cache, useCache } = createCache();
|
|
8
10
|
export function useData(...refs) {
|
|
9
11
|
const cache = useCache();
|
|
10
|
-
const states = mapArray(refs,
|
|
12
|
+
const states = mapArray(refs, _getRefState, cache);
|
|
11
13
|
return useState(...states);
|
|
12
14
|
}
|
|
13
15
|
/** Get the corresponding `ItemState` or `QueryState` instance from the cache for a given `Item` or `Query`. */
|
|
14
|
-
function
|
|
16
|
+
function _getRefState(ref, cache) {
|
|
15
17
|
const key = ref === null || ref === void 0 ? void 0 : ref.toString();
|
|
16
18
|
return ref && key ? cache.get(key) || setMapItem(cache, key, ref instanceof AsyncItem ? new ItemState(ref) : new QueryState(ref)) : undefined;
|
|
17
19
|
}
|
|
20
|
+
/** Wrap components with `<DataCache>` to allow the use of `useData()`. */
|
|
21
|
+
export const DataCache = Cache;
|
package/util/data.d.ts
CHANGED
|
@@ -36,9 +36,12 @@ export declare function assertData<T extends Data>(value: T | unknown): asserts
|
|
|
36
36
|
export declare const isDataProp: <T extends Data>(obj: T, key: unknown) => key is DataKey<T>;
|
|
37
37
|
/** Get the data of a result (returns data or throws `RequiredError` if value is `null` or `undefined`). */
|
|
38
38
|
export declare function getData<T extends Data>(result: OptionalData<T>): T;
|
|
39
|
-
/** Get the props of a data object. */
|
|
39
|
+
/** Get the props of a data object as a set of entries. */
|
|
40
40
|
export declare function getDataProps<T extends Data>(data: T): ImmutableArray<DataProp<T>>;
|
|
41
41
|
export declare function getDataProps<T extends Data>(data: T | Partial<T>): ImmutableArray<DataProp<T>>;
|
|
42
|
+
/** Get the props of a data object as a set of entries. */
|
|
43
|
+
export declare function getDataKeys<T extends Data>(data: T): ImmutableArray<DataKey<T>>;
|
|
44
|
+
export declare function getDataKeys<T extends Data>(data: T | Partial<T>): ImmutableArray<DataKey<T>>;
|
|
42
45
|
/** Type that represents an empty data object. */
|
|
43
46
|
export type EmptyData = {
|
|
44
47
|
readonly [K in never]: never;
|
package/util/data.js
CHANGED
|
@@ -19,6 +19,9 @@ export function getData(result) {
|
|
|
19
19
|
export function getDataProps(data) {
|
|
20
20
|
return Object.entries(data);
|
|
21
21
|
}
|
|
22
|
+
export function getDataKeys(data) {
|
|
23
|
+
return Object.keys(data);
|
|
24
|
+
}
|
|
22
25
|
/** An empty object. */
|
|
23
26
|
export const EMPTY_DATA = { __proto__: null };
|
|
24
27
|
/** Function that returns an an empty object. */
|
package/util/object.d.ts
CHANGED
|
@@ -67,6 +67,10 @@ export type OmitProps<T, TT> = Omit<T, {
|
|
|
67
67
|
export declare function getProps<T extends ImmutableObject>(obj: T): ImmutableArray<ObjectProp<T>>;
|
|
68
68
|
export declare function getProps<T extends ImmutableObject>(obj: T | Partial<T>): ImmutableArray<ObjectProp<T>>;
|
|
69
69
|
export declare function getProps<T extends ImmutableObject>(obj: T | Partial<T> | Iterable<ObjectProp<T>>): Iterable<ObjectProp<T>>;
|
|
70
|
+
/** Get the keys of an object as an array. */
|
|
71
|
+
export declare function getKeys<T extends ImmutableObject>(obj: T): ImmutableArray<ObjectKey<T>>;
|
|
72
|
+
export declare function getKeys<T extends ImmutableObject>(obj: T | Partial<T>): ImmutableArray<ObjectKey<T>>;
|
|
73
|
+
export declare function getKeys<T extends ImmutableObject>(obj: T | Partial<T> | Iterable<ObjectKey<T>>): Iterable<ObjectKey<T>>;
|
|
70
74
|
/**
|
|
71
75
|
* Extract the value of a named prop from an object.
|
|
72
76
|
* - Extraction is possibly deep if deeper keys are specified.
|
package/util/object.js
CHANGED
|
@@ -26,6 +26,9 @@ export const isProp = (obj, key) => Object.prototype.hasOwnProperty.call(obj, ke
|
|
|
26
26
|
export function getProps(obj) {
|
|
27
27
|
return isIterable(obj) ? obj : Object.entries(obj);
|
|
28
28
|
}
|
|
29
|
+
export function getKeys(obj) {
|
|
30
|
+
return isIterable(obj) ? obj : Object.keys(obj);
|
|
31
|
+
}
|
|
29
32
|
export function getProp(obj, key, ...keys) {
|
|
30
33
|
const value = obj[key];
|
|
31
34
|
return !isArrayLength(keys) ? value : isObject(value) ? getProp(value, ...keys) : undefined;
|
package/react/useCache.d.ts
DELETED
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
/// <reference types="react" />
|
|
2
|
-
/**
|
|
3
|
-
* Controller that creates an independent cache.
|
|
4
|
-
* - The cache is a `Map` instance that stores indexed items.
|
|
5
|
-
*/
|
|
6
|
-
export declare class CacheController<T> {
|
|
7
|
-
protected _context: import("react").Context<Map<string, T> | undefined>;
|
|
8
|
-
/** Use this cache in a component. */
|
|
9
|
-
readonly useCache: () => Map<string, T>;
|
|
10
|
-
/** Component that provides a cache of this type to its children. */
|
|
11
|
-
readonly Cache: ({ children }: {
|
|
12
|
-
children: React.ReactNode;
|
|
13
|
-
}) => React.ReactElement | null;
|
|
14
|
-
}
|
|
15
|
-
/**
|
|
16
|
-
* Default cache
|
|
17
|
-
* - This is a flexible generic cache intended to be the default.
|
|
18
|
-
* - Use this cache unless you want to cache a completely independent set of items without interference.
|
|
19
|
-
*/
|
|
20
|
-
export declare const CACHE: CacheController<any>;
|
|
21
|
-
/**
|
|
22
|
-
* Use a global cache in a component.
|
|
23
|
-
* - Throws an error if used outside of `<Cache>`
|
|
24
|
-
*/
|
|
25
|
-
export declare const useCache: <T>() => Map<string, T>;
|
|
26
|
-
/**
|
|
27
|
-
* Component that provides a global cache to its children.
|
|
28
|
-
*
|
|
29
|
-
* Note: If mounted globally this cache will bloat over time, so you need a strategy to clear or reset the cache occasionally.
|
|
30
|
-
*
|
|
31
|
-
* A good strategy is to wrap a separate `<Cache>` around each page of your app.
|
|
32
|
-
* This means the cache can only grow to the size of each page and the memory is released when the user navigates to a new page.
|
|
33
|
-
* You might need to use `<Cache key="something unique to the page">` to ensure the cache component is destroyed and remounted for each page.
|
|
34
|
-
*
|
|
35
|
-
* Put a `<Suspense>` boundary _inside_ `<Cache>`
|
|
36
|
-
* - This prevents promises being thrown up through the cache causing it to be destroyed.
|
|
37
|
-
* - When the promise resolves and the render is tried again the data would not exist (because the cache was destroyed).
|
|
38
|
-
* - This will cause an infinite loading loop.
|
|
39
|
-
*
|
|
40
|
-
* Put your error boundary _outside_ your `<Cache>`
|
|
41
|
-
* - The error being thrown up through the cache causes it to be destroyed.
|
|
42
|
-
* - This means when the uses tells the error boundary to try again (if supported) all data on the page will be retried.
|
|
43
|
-
*/
|
|
44
|
-
export declare const Cache: ({ children }: {
|
|
45
|
-
children: React.ReactNode;
|
|
46
|
-
}) => React.ReactElement | null;
|
package/react/useCache.js
DELETED
|
@@ -1,56 +0,0 @@
|
|
|
1
|
-
import { useContext, createContext, createElement } from "react";
|
|
2
|
-
import { ConditionError } from "../error/ConditionError.js";
|
|
3
|
-
import { useReduce } from "./useReduce.js";
|
|
4
|
-
/**
|
|
5
|
-
* Controller that creates an independent cache.
|
|
6
|
-
* - The cache is a `Map` instance that stores indexed items.
|
|
7
|
-
*/
|
|
8
|
-
export class CacheController {
|
|
9
|
-
constructor() {
|
|
10
|
-
this._context = createContext(undefined);
|
|
11
|
-
/** Use this cache in a component. */
|
|
12
|
-
this.useCache = () => {
|
|
13
|
-
const cache = useContext(this._context);
|
|
14
|
-
if (!cache)
|
|
15
|
-
throw new ConditionError("useCache() must be used inside <Cache>");
|
|
16
|
-
return cache;
|
|
17
|
-
};
|
|
18
|
-
/** Component that provides a cache of this type to its children. */
|
|
19
|
-
this.Cache = ({ children }) => {
|
|
20
|
-
const cache = useReduce(_reduceMap);
|
|
21
|
-
return createElement(this._context.Provider, { children, value: cache });
|
|
22
|
-
};
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
/** Reducer that gets an existing `Map` instance or creates a new one. */
|
|
26
|
-
const _reduceMap = (previous) => previous || new Map();
|
|
27
|
-
/**
|
|
28
|
-
* Default cache
|
|
29
|
-
* - This is a flexible generic cache intended to be the default.
|
|
30
|
-
* - Use this cache unless you want to cache a completely independent set of items without interference.
|
|
31
|
-
*/
|
|
32
|
-
export const CACHE = new CacheController(); // eslint-disable-line @typescript-eslint/no-explicit-any
|
|
33
|
-
/**
|
|
34
|
-
* Use a global cache in a component.
|
|
35
|
-
* - Throws an error if used outside of `<Cache>`
|
|
36
|
-
*/
|
|
37
|
-
export const useCache = CACHE.useCache;
|
|
38
|
-
/**
|
|
39
|
-
* Component that provides a global cache to its children.
|
|
40
|
-
*
|
|
41
|
-
* Note: If mounted globally this cache will bloat over time, so you need a strategy to clear or reset the cache occasionally.
|
|
42
|
-
*
|
|
43
|
-
* A good strategy is to wrap a separate `<Cache>` around each page of your app.
|
|
44
|
-
* This means the cache can only grow to the size of each page and the memory is released when the user navigates to a new page.
|
|
45
|
-
* You might need to use `<Cache key="something unique to the page">` to ensure the cache component is destroyed and remounted for each page.
|
|
46
|
-
*
|
|
47
|
-
* Put a `<Suspense>` boundary _inside_ `<Cache>`
|
|
48
|
-
* - This prevents promises being thrown up through the cache causing it to be destroyed.
|
|
49
|
-
* - When the promise resolves and the render is tried again the data would not exist (because the cache was destroyed).
|
|
50
|
-
* - This will cause an infinite loading loop.
|
|
51
|
-
*
|
|
52
|
-
* Put your error boundary _outside_ your `<Cache>`
|
|
53
|
-
* - The error being thrown up through the cache causes it to be destroyed.
|
|
54
|
-
* - This means when the uses tells the error boundary to try again (if supported) all data on the page will be retried.
|
|
55
|
-
*/
|
|
56
|
-
export const Cache = CACHE.Cache;
|