shelving 1.101.0 → 1.102.1
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 +13 -4
- package/db/ItemState.js +51 -18
- package/db/QueryState.d.ts +13 -5
- package/db/QueryState.js +59 -25
- package/firestore/client/FirestoreClientProvider.js +3 -3
- package/firestore/server/FirestoreServerProvider.js +3 -3
- package/firestore/util/error.d.ts +2 -0
- package/firestore/util/error.js +19 -0
- package/iterate/ThroughGenerator.d.ts +1 -1
- package/iterate/ThroughGenerator.js +4 -4
- package/package.json +1 -1
- package/provider/DebugProvider.js +10 -10
- package/provider/MemoryProvider.d.ts +3 -1
- package/provider/MemoryProvider.js +6 -0
- package/react/createCache.js +3 -5
- package/react/useData.d.ts +5 -9
- package/react/useData.js +3 -8
- package/react/useState.d.ts +1 -12
- package/react/useState.js +6 -14
- package/sequence/AbstractSequence.d.ts +2 -2
- package/sequence/DeferredSequence.d.ts +2 -2
- package/sequence/InspectSequence.d.ts +1 -1
- package/sequence/LazyDeferredSequence.d.ts +14 -0
- package/sequence/LazyDeferredSequence.js +34 -0
- package/sequence/ThroughSequence.d.ts +3 -3
- package/sequence/ThroughSequence.js +4 -6
- package/sequence/index.d.ts +1 -2
- package/sequence/index.js +1 -2
- package/state/ArrayState.d.ts +1 -2
- package/state/ArrayState.js +2 -2
- package/state/BooleanState.d.ts +2 -2
- package/state/BooleanState.js +2 -2
- package/state/DictionaryState.d.ts +1 -2
- package/state/DictionaryState.js +2 -2
- package/state/State.d.ts +8 -16
- package/state/State.js +14 -21
- package/util/dispose.d.ts +39 -0
- package/util/dispose.js +61 -0
- package/util/index.d.ts +1 -1
- package/util/index.js +1 -1
- package/util/sequence.d.ts +3 -1
- package/util/sequence.js +27 -8
- package/sequence/SwitchingDeferredSequence.d.ts +0 -8
- package/sequence/SwitchingDeferredSequence.js +0 -13
- package/sequence/SwitchingSequence.d.ts +0 -10
- package/sequence/SwitchingSequence.js +0 -52
- package/util/switch.d.ts +0 -33
- package/util/switch.js +0 -49
package/db/ItemState.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { AsyncItemReference, ItemData, ItemReference, ItemValue } from "./ItemReference.js";
|
|
2
|
+
import type { AsyncProvider, Provider } from "../provider/Provider.js";
|
|
2
3
|
import type { StopCallback } from "../util/callback.js";
|
|
3
4
|
import type { Data } from "../util/data.js";
|
|
4
5
|
import { BooleanState } from "../state/BooleanState.js";
|
|
@@ -15,10 +16,18 @@ export declare class ItemState<T extends Data = Data> extends State<ItemValue<T>
|
|
|
15
16
|
get exists(): boolean;
|
|
16
17
|
constructor(ref: ItemReference<T> | AsyncItemReference<T>);
|
|
17
18
|
/** Refresh this state from the source provider. */
|
|
18
|
-
|
|
19
|
+
refresh(provider?: Provider | AsyncProvider): void;
|
|
19
20
|
private _refresh;
|
|
20
21
|
/** Refresh this state if data in the cache is older than `maxAge` (in milliseconds). */
|
|
21
|
-
refreshStale(maxAge: number): void;
|
|
22
|
-
/** Subscribe this state to
|
|
23
|
-
|
|
22
|
+
refreshStale(maxAge: number, provider?: Provider | AsyncProvider): void;
|
|
23
|
+
/** Subscribe this state to a provider. */
|
|
24
|
+
connect(provider?: Provider | AsyncProvider): StopCallback;
|
|
25
|
+
[Symbol.asyncIterator](): AsyncGenerator<ItemValue<T>, void, void>;
|
|
26
|
+
private _iterating;
|
|
27
|
+
/** Start subscription to `MemoryProvider` if there is one. */
|
|
28
|
+
start(): void;
|
|
29
|
+
/** Stop subscription to `MemoryProvider` if there is one. */
|
|
30
|
+
stop(): void;
|
|
31
|
+
private _stop;
|
|
32
|
+
[Symbol.dispose](): void;
|
|
24
33
|
}
|
package/db/ItemState.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { CacheProvider } from "../provider/CacheProvider.js";
|
|
2
|
-
import { SwitchingDeferredSequence } from "../sequence/SwitchingDeferredSequence.js";
|
|
3
2
|
import { BooleanState } from "../state/BooleanState.js";
|
|
4
3
|
import { State } from "../state/State.js";
|
|
4
|
+
import { call } from "../util/callback.js";
|
|
5
5
|
import { getRequired } from "../util/null.js";
|
|
6
6
|
import { getOptionalSource } from "../util/source.js";
|
|
7
7
|
import { getItemData } from "./ItemReference.js";
|
|
@@ -17,31 +17,32 @@ export class ItemState extends State {
|
|
|
17
17
|
}
|
|
18
18
|
/** Does the item exist? */
|
|
19
19
|
get exists() {
|
|
20
|
-
return
|
|
20
|
+
return !!this.value;
|
|
21
21
|
}
|
|
22
22
|
constructor(ref) {
|
|
23
23
|
var _a;
|
|
24
24
|
const { provider, collection, id } = ref;
|
|
25
|
-
const
|
|
26
|
-
const time =
|
|
27
|
-
|
|
28
|
-
super(table && typeof time === "number" ? { value: table.getItem(id), time, next } : { next });
|
|
25
|
+
const memory = (_a = getOptionalSource(CacheProvider, provider)) === null || _a === void 0 ? void 0 : _a.memory;
|
|
26
|
+
const time = memory ? memory.getItemTime(collection, id) : undefined;
|
|
27
|
+
super(memory && typeof time === "number" ? memory.getItem(collection, id) : undefined, time);
|
|
29
28
|
this.busy = new BooleanState();
|
|
30
|
-
|
|
31
|
-
this.
|
|
32
|
-
if (!this.busy.value)
|
|
33
|
-
void this._refresh();
|
|
34
|
-
};
|
|
29
|
+
this._iterating = 0;
|
|
30
|
+
this._stop = undefined;
|
|
35
31
|
this.ref = ref;
|
|
36
32
|
// Queue a request to refresh the value if it doesn't exist.
|
|
37
33
|
if (this.loading)
|
|
38
34
|
this.refresh();
|
|
39
35
|
}
|
|
40
|
-
|
|
36
|
+
/** Refresh this state from the source provider. */
|
|
37
|
+
refresh(provider = this.ref.provider) {
|
|
38
|
+
if (!this.busy.value)
|
|
39
|
+
void this._refresh(provider);
|
|
40
|
+
}
|
|
41
|
+
async _refresh(provider) {
|
|
41
42
|
this.busy.value = true;
|
|
42
43
|
this.reason = undefined; // Optimistically clear the error.
|
|
43
44
|
try {
|
|
44
|
-
this.value = await this.ref.
|
|
45
|
+
this.value = (await provider.getItem(this.ref.collection, this.ref.id));
|
|
45
46
|
}
|
|
46
47
|
catch (thrown) {
|
|
47
48
|
this.reason = thrown;
|
|
@@ -51,12 +52,44 @@ export class ItemState extends State {
|
|
|
51
52
|
}
|
|
52
53
|
}
|
|
53
54
|
/** Refresh this state if data in the cache is older than `maxAge` (in milliseconds). */
|
|
54
|
-
refreshStale(maxAge) {
|
|
55
|
+
refreshStale(maxAge, provider) {
|
|
55
56
|
if (this.age > maxAge)
|
|
56
|
-
this.refresh();
|
|
57
|
+
this.refresh(provider);
|
|
58
|
+
}
|
|
59
|
+
/** Subscribe this state to a provider. */
|
|
60
|
+
connect(provider = this.ref.provider) {
|
|
61
|
+
return this.from(provider.getItemSequence(this.ref.collection, this.ref.id));
|
|
62
|
+
}
|
|
63
|
+
// Override to subscribe to `MemoryProvider` while things are iterating over this state.
|
|
64
|
+
async *[Symbol.asyncIterator]() {
|
|
65
|
+
this.start();
|
|
66
|
+
this._iterating++;
|
|
67
|
+
try {
|
|
68
|
+
yield* super[Symbol.asyncIterator]();
|
|
69
|
+
}
|
|
70
|
+
finally {
|
|
71
|
+
this._iterating--;
|
|
72
|
+
if (this._iterating < 1)
|
|
73
|
+
this.stop();
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
/** Start subscription to `MemoryProvider` if there is one. */
|
|
77
|
+
start() {
|
|
78
|
+
var _a;
|
|
79
|
+
if (!this._stop) {
|
|
80
|
+
const { collection, id, provider } = this.ref;
|
|
81
|
+
const memory = (_a = getOptionalSource(CacheProvider, provider)) === null || _a === void 0 ? void 0 : _a.memory;
|
|
82
|
+
if (memory)
|
|
83
|
+
this._stop = this.from(memory.getCachedItemSequence(collection, id));
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
/** Stop subscription to `MemoryProvider` if there is one. */
|
|
87
|
+
stop() {
|
|
88
|
+
if (this._stop)
|
|
89
|
+
this._stop = void call(this._stop);
|
|
57
90
|
}
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
91
|
+
// Implement `Disposable`
|
|
92
|
+
[Symbol.dispose]() {
|
|
93
|
+
this.stop();
|
|
61
94
|
}
|
|
62
95
|
}
|
package/db/QueryState.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { ItemArray, ItemData, ItemValue } from "./ItemReference.js";
|
|
2
2
|
import type { AsyncQueryReference, QueryReference } from "./QueryReference.js";
|
|
3
|
+
import type { AsyncProvider, Provider } from "../provider/Provider.js";
|
|
3
4
|
import type { StopCallback } from "../util/callback.js";
|
|
4
5
|
import type { Data } from "../util/data.js";
|
|
5
6
|
import { BooleanState } from "../state/BooleanState.js";
|
|
@@ -26,18 +27,25 @@ export declare class QueryState<T extends Data = Data> extends State<ItemArray<T
|
|
|
26
27
|
get count(): number;
|
|
27
28
|
constructor(ref: QueryReference<T> | AsyncQueryReference<T>);
|
|
28
29
|
/** Refresh this state from the source provider. */
|
|
29
|
-
|
|
30
|
+
refresh(provider?: Provider | AsyncProvider): void;
|
|
30
31
|
private _refresh;
|
|
31
32
|
/** Refresh this state if data in the cache is older than `maxAge` (in milliseconds). */
|
|
32
33
|
refreshStale(maxAge: number): void;
|
|
33
|
-
/** Subscribe this state to
|
|
34
|
-
|
|
34
|
+
/** Subscribe this state to a provider. */
|
|
35
|
+
connect(provider?: Provider | AsyncProvider): StopCallback;
|
|
35
36
|
/**
|
|
36
37
|
* Load more items after the last once.
|
|
37
38
|
* - Promise that needs to be handled.
|
|
38
39
|
*/
|
|
39
|
-
|
|
40
|
+
loadMore(): void;
|
|
40
41
|
private _loadMore;
|
|
41
|
-
|
|
42
|
+
[Symbol.asyncIterator](): AsyncGenerator<ItemArray<T>, void, void>;
|
|
43
|
+
private _iterating;
|
|
44
|
+
/** Start subscription to `MemoryProvider` if there is one. */
|
|
45
|
+
start(): void;
|
|
46
|
+
/** Stop subscription to `MemoryProvider` if there is one. */
|
|
47
|
+
stop(): void;
|
|
48
|
+
private _stop;
|
|
49
|
+
[Symbol.dispose](): void;
|
|
42
50
|
[Symbol.iterator](): Iterator<ItemData<T>>;
|
|
43
51
|
}
|
package/db/QueryState.js
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { CacheProvider } from "../provider/CacheProvider.js";
|
|
2
|
-
import { SwitchingDeferredSequence } from "../sequence/SwitchingDeferredSequence.js";
|
|
3
2
|
import { BooleanState } from "../state/BooleanState.js";
|
|
4
3
|
import { State } from "../state/State.js";
|
|
5
4
|
import { getOptionalFirstItem, getOptionalLastItem } from "../util/array.js";
|
|
5
|
+
import { call } from "../util/callback.js";
|
|
6
|
+
import { NONE } from "../util/constants.js";
|
|
6
7
|
import { getRequired } from "../util/null.js";
|
|
7
8
|
import { getAfterQuery, getLimit } from "../util/query.js";
|
|
8
9
|
import { getOptionalSource } from "../util/source.js";
|
|
@@ -30,7 +31,7 @@ export class QueryState extends State {
|
|
|
30
31
|
}
|
|
31
32
|
/** Does the document have at least one result. */
|
|
32
33
|
get exists() {
|
|
33
|
-
return
|
|
34
|
+
return !!this.value.length;
|
|
34
35
|
}
|
|
35
36
|
/** Get the number of items matching this query. */
|
|
36
37
|
get count() {
|
|
@@ -39,36 +40,29 @@ export class QueryState extends State {
|
|
|
39
40
|
constructor(ref) {
|
|
40
41
|
var _a, _b;
|
|
41
42
|
const { provider, collection, query } = ref;
|
|
42
|
-
const
|
|
43
|
-
const time =
|
|
44
|
-
|
|
45
|
-
super(table && typeof time === "number" ? { value: table.getQuery(ref), time, next } : { next });
|
|
43
|
+
const memory = (_a = getOptionalSource(CacheProvider, provider)) === null || _a === void 0 ? void 0 : _a.memory;
|
|
44
|
+
const time = memory ? memory.getQueryTime(collection, query) : undefined;
|
|
45
|
+
super(memory && typeof time === "number" ? memory.getQuery(collection, query) : NONE, time);
|
|
46
46
|
this.busy = new BooleanState();
|
|
47
47
|
this._hasMore = false;
|
|
48
|
-
|
|
49
|
-
this.
|
|
50
|
-
if (!this.busy.value)
|
|
51
|
-
void this._refresh();
|
|
52
|
-
};
|
|
53
|
-
/**
|
|
54
|
-
* Load more items after the last once.
|
|
55
|
-
* - Promise that needs to be handled.
|
|
56
|
-
*/
|
|
57
|
-
this.loadMore = () => {
|
|
58
|
-
if (!this.busy.value)
|
|
59
|
-
void this._loadMore();
|
|
60
|
-
};
|
|
48
|
+
this._iterating = 0;
|
|
49
|
+
this._stop = undefined;
|
|
61
50
|
this.ref = ref;
|
|
62
51
|
this.limit = (_b = getLimit(query)) !== null && _b !== void 0 ? _b : Infinity;
|
|
63
52
|
// Queue a request to refresh the value if it doesn't exist.
|
|
64
53
|
if (this.loading)
|
|
65
54
|
this.refresh();
|
|
66
55
|
}
|
|
67
|
-
|
|
56
|
+
/** Refresh this state from the source provider. */
|
|
57
|
+
refresh(provider = this.ref.provider) {
|
|
58
|
+
if (!this.busy.value)
|
|
59
|
+
void this._refresh(provider);
|
|
60
|
+
}
|
|
61
|
+
async _refresh(provider) {
|
|
68
62
|
this.busy.value = true;
|
|
69
63
|
this.reason = undefined; // Optimistically clear the error.
|
|
70
64
|
try {
|
|
71
|
-
const items = await this.ref.
|
|
65
|
+
const items = (await provider.getQuery(this.ref.collection, this.ref.query));
|
|
72
66
|
this._hasMore = items.length >= this.limit; // If the query returned {limit} or more items, we can assume there are more items waiting to be queried.
|
|
73
67
|
this.value = items;
|
|
74
68
|
}
|
|
@@ -84,9 +78,17 @@ export class QueryState extends State {
|
|
|
84
78
|
if (this.age > maxAge)
|
|
85
79
|
this.refresh();
|
|
86
80
|
}
|
|
87
|
-
/** Subscribe this state to
|
|
88
|
-
|
|
89
|
-
return this.from(this.ref);
|
|
81
|
+
/** Subscribe this state to a provider. */
|
|
82
|
+
connect(provider = this.ref.provider) {
|
|
83
|
+
return this.from(provider.getQuerySequence(this.ref.collection, this.ref.query));
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Load more items after the last once.
|
|
87
|
+
* - Promise that needs to be handled.
|
|
88
|
+
*/
|
|
89
|
+
loadMore() {
|
|
90
|
+
if (!this.busy.value)
|
|
91
|
+
void this._loadMore();
|
|
90
92
|
}
|
|
91
93
|
async _loadMore() {
|
|
92
94
|
this.busy.value = true;
|
|
@@ -105,7 +107,39 @@ export class QueryState extends State {
|
|
|
105
107
|
this.busy.value = false;
|
|
106
108
|
}
|
|
107
109
|
}
|
|
108
|
-
|
|
110
|
+
// Override to subscribe to `MemoryProvider` while things are iterating over this state.
|
|
111
|
+
async *[Symbol.asyncIterator]() {
|
|
112
|
+
this.start();
|
|
113
|
+
this._iterating++;
|
|
114
|
+
try {
|
|
115
|
+
yield* super[Symbol.asyncIterator]();
|
|
116
|
+
}
|
|
117
|
+
finally {
|
|
118
|
+
this._iterating--;
|
|
119
|
+
if (this._iterating < 1)
|
|
120
|
+
this.stop();
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
/** Start subscription to `MemoryProvider` if there is one. */
|
|
124
|
+
start() {
|
|
125
|
+
var _a;
|
|
126
|
+
if (!this._stop) {
|
|
127
|
+
const { collection, query, provider } = this.ref;
|
|
128
|
+
const memory = (_a = getOptionalSource(CacheProvider, provider)) === null || _a === void 0 ? void 0 : _a.memory;
|
|
129
|
+
if (memory)
|
|
130
|
+
this._stop = this.from(memory.getCachedQuerySequence(collection, query));
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
/** Stop subscription to `MemoryProvider` if there is one. */
|
|
134
|
+
stop() {
|
|
135
|
+
if (this._stop)
|
|
136
|
+
this._stop = void call(this._stop);
|
|
137
|
+
}
|
|
138
|
+
// Implement `Disposable`
|
|
139
|
+
[Symbol.dispose]() {
|
|
140
|
+
this.stop();
|
|
141
|
+
}
|
|
142
|
+
// Implement `Iteratable`
|
|
109
143
|
[Symbol.iterator]() {
|
|
110
144
|
return this.value.values();
|
|
111
145
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { addDoc, collection, deleteDoc, doc, documentId, getDoc, getDocs, increment, limit, onSnapshot, orderBy, query, setDoc, updateDoc, where } from "firebase/firestore";
|
|
2
2
|
import { getItemData } from "../../db/ItemReference.js";
|
|
3
|
-
import {
|
|
3
|
+
import { LazyDeferredSequence } from "../../sequence/LazyDeferredSequence.js";
|
|
4
4
|
import { getObject } from "../../util/object.js";
|
|
5
5
|
import { getFilters, getLimit, getOrders } from "../../util/query.js";
|
|
6
6
|
import { mapItems } from "../../util/transform.js";
|
|
@@ -61,7 +61,7 @@ export class FirestoreClientProvider {
|
|
|
61
61
|
return _getItemValue(await getDoc(doc(this._firestore, c, id)));
|
|
62
62
|
}
|
|
63
63
|
getItemSequence(c, id) {
|
|
64
|
-
return new
|
|
64
|
+
return new LazyDeferredSequence(sequence => onSnapshot(doc(this._firestore, c, id), //
|
|
65
65
|
//
|
|
66
66
|
snapshot => sequence.resolve(_getItemValue(snapshot)), reason => sequence.reject(reason)));
|
|
67
67
|
}
|
|
@@ -82,7 +82,7 @@ export class FirestoreClientProvider {
|
|
|
82
82
|
return _getItems(await getDocs(_getQuery(this._firestore, c, q)));
|
|
83
83
|
}
|
|
84
84
|
getQuerySequence(c, q) {
|
|
85
|
-
return new
|
|
85
|
+
return new LazyDeferredSequence(sequence => onSnapshot(_getQuery(this._firestore, c, q), //
|
|
86
86
|
//
|
|
87
87
|
snapshot => sequence.resolve(_getItems(snapshot)), reason => sequence.reject(reason)));
|
|
88
88
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { FieldPath, FieldValue, Firestore } from "@google-cloud/firestore";
|
|
2
2
|
import { getItemData } from "../../db/ItemReference.js";
|
|
3
|
-
import {
|
|
3
|
+
import { LazyDeferredSequence } from "../../sequence/LazyDeferredSequence.js";
|
|
4
4
|
import { getObject } from "../../util/object.js";
|
|
5
5
|
import { getFilters, getLimit, getOrders } from "../../util/query.js";
|
|
6
6
|
import { mapItems } from "../../util/transform.js";
|
|
@@ -59,7 +59,7 @@ export class FirestoreServerProvider {
|
|
|
59
59
|
}
|
|
60
60
|
getItemSequence(c, id) {
|
|
61
61
|
const ref = this._firestore.collection(c).doc(id);
|
|
62
|
-
return new
|
|
62
|
+
return new LazyDeferredSequence(sequence => ref.onSnapshot(snapshot => sequence.resolve(_getItemValue(snapshot)), //
|
|
63
63
|
sequence.reject));
|
|
64
64
|
}
|
|
65
65
|
async addItem(c, data) {
|
|
@@ -79,7 +79,7 @@ export class FirestoreServerProvider {
|
|
|
79
79
|
}
|
|
80
80
|
getQuerySequence(c, q) {
|
|
81
81
|
const ref = _getQuery(this._firestore, c, q);
|
|
82
|
-
return new
|
|
82
|
+
return new LazyDeferredSequence(sequence => ref.onSnapshot(snapshot => sequence.resolve(_getItemArray(snapshot)), //
|
|
83
83
|
sequence.reject));
|
|
84
84
|
}
|
|
85
85
|
async setQuery(c, q, data) {
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { ConnectionError } from "../../error/ConnectionError.js";
|
|
2
|
+
import { PermissionError } from "../../error/PermissionError.js";
|
|
3
|
+
import { RequiredError } from "../../error/RequiredError.js";
|
|
4
|
+
import { isObject } from "../../util/object.js";
|
|
5
|
+
/** Convert a Firestore error (which use gRPC error codes) into a corresponding Shelving error. */
|
|
6
|
+
export function convertFirestoreError(thrown) {
|
|
7
|
+
if (isObject(thrown)) {
|
|
8
|
+
const code = thrown.code;
|
|
9
|
+
if (typeof code === "string") {
|
|
10
|
+
if (code === "unavailable")
|
|
11
|
+
throw new ConnectionError();
|
|
12
|
+
if (code === "not-found")
|
|
13
|
+
throw new RequiredError();
|
|
14
|
+
if (code === "permission-denied")
|
|
15
|
+
throw new PermissionError();
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
throw thrown;
|
|
19
|
+
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { AbstractGenerator } from "./AbstractGenerator.js";
|
|
2
2
|
/** Iterable that pulls values from a source iterable. */
|
|
3
3
|
export declare class ThroughGenerator<T, R, N> extends AbstractGenerator<T, R, N> {
|
|
4
|
-
private readonly
|
|
4
|
+
private readonly _source;
|
|
5
5
|
constructor(iterator: Iterator<T, R, N>);
|
|
6
6
|
next(value: N): IteratorResult<T, R>;
|
|
7
7
|
throw(thrown: Error | unknown): IteratorResult<T, R>;
|
|
@@ -3,16 +3,16 @@ import { AbstractGenerator } from "./AbstractGenerator.js";
|
|
|
3
3
|
export class ThroughGenerator extends AbstractGenerator {
|
|
4
4
|
constructor(iterator) {
|
|
5
5
|
super();
|
|
6
|
-
this.
|
|
6
|
+
this._source = iterator;
|
|
7
7
|
}
|
|
8
8
|
// Implement `AbstractGenerator`
|
|
9
9
|
next(value) {
|
|
10
|
-
return this.
|
|
10
|
+
return this._source.next(value);
|
|
11
11
|
}
|
|
12
12
|
throw(thrown) {
|
|
13
|
-
return this.
|
|
13
|
+
return this._source.throw ? this._source.throw(thrown) : super.throw(thrown);
|
|
14
14
|
}
|
|
15
15
|
return(value) {
|
|
16
|
-
return this.
|
|
16
|
+
return this._source.return ? this._source.return(value) : super.return(value);
|
|
17
17
|
}
|
|
18
18
|
}
|
package/package.json
CHANGED
|
@@ -3,9 +3,9 @@
|
|
|
3
3
|
class AbstractDebugProvider {
|
|
4
4
|
async *getItemSequence(collection, id) {
|
|
5
5
|
try {
|
|
6
|
-
console.debug("
|
|
6
|
+
console.debug("⋯ ITERATE", collection, id);
|
|
7
7
|
for await (const item of this.source.getItemSequence(collection, id)) {
|
|
8
|
-
console.debug("
|
|
8
|
+
console.debug("↩ ITERATE", collection, id, item);
|
|
9
9
|
yield item;
|
|
10
10
|
}
|
|
11
11
|
console.debug("✔ ITERATE", collection, id);
|
|
@@ -16,9 +16,9 @@ class AbstractDebugProvider {
|
|
|
16
16
|
}
|
|
17
17
|
async *getQuerySequence(collection, query) {
|
|
18
18
|
try {
|
|
19
|
-
console.debug("
|
|
19
|
+
console.debug("⋯ ITERATE", collection, query);
|
|
20
20
|
for await (const items of this.source.getQuerySequence(collection, query)) {
|
|
21
|
-
console.debug("
|
|
21
|
+
console.debug("↩ ITERATE", collection, query, items);
|
|
22
22
|
yield items;
|
|
23
23
|
}
|
|
24
24
|
console.debug("✔ ITERATE", collection, query);
|
|
@@ -37,7 +37,7 @@ export class DebugProvider extends AbstractDebugProvider {
|
|
|
37
37
|
getItem(collection, id) {
|
|
38
38
|
try {
|
|
39
39
|
const item = this.source.getItem(collection, id);
|
|
40
|
-
console.debug("
|
|
40
|
+
console.debug("↩ GET", collection, id, item);
|
|
41
41
|
return item;
|
|
42
42
|
}
|
|
43
43
|
catch (reason) {
|
|
@@ -48,7 +48,7 @@ export class DebugProvider extends AbstractDebugProvider {
|
|
|
48
48
|
addItem(collection, data) {
|
|
49
49
|
try {
|
|
50
50
|
const id = this.source.addItem(collection, data);
|
|
51
|
-
console.debug("✔ ADD", collection, data,
|
|
51
|
+
console.debug("✔ ADD", collection, data, id);
|
|
52
52
|
return id;
|
|
53
53
|
}
|
|
54
54
|
catch (reason) {
|
|
@@ -68,8 +68,8 @@ export class DebugProvider extends AbstractDebugProvider {
|
|
|
68
68
|
}
|
|
69
69
|
updateItem(collection, id, updates) {
|
|
70
70
|
try {
|
|
71
|
+
this.source.updateItem(collection, id, updates);
|
|
71
72
|
console.debug("✔ UPDATE", collection, id, updates);
|
|
72
|
-
return this.source.updateItem(collection, id, updates);
|
|
73
73
|
}
|
|
74
74
|
catch (reason) {
|
|
75
75
|
console.error("✘ UPDATE", collection, id, updates, reason);
|
|
@@ -89,7 +89,7 @@ export class DebugProvider extends AbstractDebugProvider {
|
|
|
89
89
|
getQuery(collection, query) {
|
|
90
90
|
try {
|
|
91
91
|
const items = this.source.getQuery(collection, query);
|
|
92
|
-
console.debug("✔ GET", collection, query,
|
|
92
|
+
console.debug("✔ GET", collection, query, items);
|
|
93
93
|
return items;
|
|
94
94
|
}
|
|
95
95
|
catch (reason) {
|
|
@@ -141,7 +141,7 @@ export class AsyncDebugProvider extends AbstractDebugProvider {
|
|
|
141
141
|
try {
|
|
142
142
|
console.debug("⋯ GET", collection, id);
|
|
143
143
|
const item = await this.source.getItem(collection, id);
|
|
144
|
-
console.debug("
|
|
144
|
+
console.debug("↩ GET", collection, id, item);
|
|
145
145
|
return item;
|
|
146
146
|
}
|
|
147
147
|
catch (reason) {
|
|
@@ -198,7 +198,7 @@ export class AsyncDebugProvider extends AbstractDebugProvider {
|
|
|
198
198
|
try {
|
|
199
199
|
console.debug("⋯ GET", collection, query);
|
|
200
200
|
const items = await this.source.getQuery(collection, query);
|
|
201
|
-
console.debug("✔ GET", collection, query,
|
|
201
|
+
console.debug("✔ GET", collection, query, items);
|
|
202
202
|
return items;
|
|
203
203
|
}
|
|
204
204
|
catch (reason) {
|
|
@@ -16,6 +16,7 @@ export declare class MemoryProvider implements Provider {
|
|
|
16
16
|
getItemTime(collection: string, id: string): number | undefined;
|
|
17
17
|
getItem(collection: string, id: string): ItemValue;
|
|
18
18
|
getItemSequence(collection: string, id: string): AsyncIterable<ItemValue>;
|
|
19
|
+
getCachedItemSequence(collection: string, id: string): AsyncIterable<ItemValue>;
|
|
19
20
|
addItem(collection: string, data: Data): string;
|
|
20
21
|
setItem(collection: string, id: string, data: Data): boolean;
|
|
21
22
|
updateItem(collection: string, id: string, updates: Updates): boolean;
|
|
@@ -23,6 +24,7 @@ export declare class MemoryProvider implements Provider {
|
|
|
23
24
|
getQueryTime(collection: string, query: ItemQuery): number | undefined;
|
|
24
25
|
getQuery(collection: string, query: ItemQuery): ItemArray;
|
|
25
26
|
getQuerySequence(collection: string, query: ItemQuery): AsyncIterable<ItemArray>;
|
|
27
|
+
getCachedQuerySequence(collection: string, query: ItemQuery): AsyncIterable<ItemArray>;
|
|
26
28
|
setQuery(collection: string, query: ItemQuery, data: Data): number;
|
|
27
29
|
updateQuery(collection: string, query: ItemQuery, updates: Updates): number;
|
|
28
30
|
deleteQuery(collection: string, query: ItemQuery): number;
|
|
@@ -34,7 +36,7 @@ export declare class MemoryTable<T extends Data = Data> {
|
|
|
34
36
|
/** Times data was last updated. */
|
|
35
37
|
protected readonly _times: Map<string, number>;
|
|
36
38
|
/** Deferred sequence of next values. */
|
|
37
|
-
readonly _changed: DeferredSequence<void
|
|
39
|
+
readonly _changed: DeferredSequence<void>;
|
|
38
40
|
getItemTime(id: string): number | undefined;
|
|
39
41
|
getItem(id: string): ItemValue<T>;
|
|
40
42
|
getItemSequence(id: string): AsyncIterable<ItemValue<T>>;
|
|
@@ -30,6 +30,9 @@ export class MemoryProvider {
|
|
|
30
30
|
getItemSequence(collection, id) {
|
|
31
31
|
return this.getTable(collection).getItemSequence(id);
|
|
32
32
|
}
|
|
33
|
+
getCachedItemSequence(collection, id) {
|
|
34
|
+
return this.getTable(collection).getCachedItemSequence(id);
|
|
35
|
+
}
|
|
33
36
|
addItem(collection, data) {
|
|
34
37
|
return this.getTable(collection).addItem(data);
|
|
35
38
|
}
|
|
@@ -51,6 +54,9 @@ export class MemoryProvider {
|
|
|
51
54
|
getQuerySequence(collection, query) {
|
|
52
55
|
return this.getTable(collection).getQuerySequence(query);
|
|
53
56
|
}
|
|
57
|
+
getCachedQuerySequence(collection, query) {
|
|
58
|
+
return this.getTable(collection).getCachedQuerySequence(query);
|
|
59
|
+
}
|
|
54
60
|
setQuery(collection, query, data) {
|
|
55
61
|
return this.getTable(collection).setQuery(query, data);
|
|
56
62
|
}
|
package/react/createCache.js
CHANGED
|
@@ -1,8 +1,5 @@
|
|
|
1
|
-
import { createContext, createElement, useContext } from "react";
|
|
1
|
+
import { createContext, createElement, useContext, useRef } from "react";
|
|
2
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
3
|
/** Create a cache. */
|
|
7
4
|
export function createCache() {
|
|
8
5
|
const context = createContext(undefined);
|
|
@@ -14,7 +11,8 @@ export function createCache() {
|
|
|
14
11
|
return cache;
|
|
15
12
|
},
|
|
16
13
|
Cache: ({ children }) => {
|
|
17
|
-
|
|
14
|
+
var _a;
|
|
15
|
+
const cache = ((_a = useRef()).current || (_a.current = new Map()));
|
|
18
16
|
return createElement(context.Provider, { children, value: cache });
|
|
19
17
|
},
|
|
20
18
|
};
|
package/react/useData.d.ts
CHANGED
|
@@ -1,18 +1,14 @@
|
|
|
1
1
|
/// <reference types="react" />
|
|
2
2
|
import type { AsyncQueryReference } from "../db/QueryReference.js";
|
|
3
|
-
import type {
|
|
4
|
-
import type { Nullish } from "../util/null.js";
|
|
3
|
+
import type { Data } from "../util/data.js";
|
|
5
4
|
import { AsyncItemReference } from "../db/ItemReference.js";
|
|
6
5
|
import { ItemState } from "../db/ItemState.js";
|
|
7
6
|
import { QueryState } from "../db/QueryState.js";
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
export declare function useData<T extends
|
|
11
|
-
export declare function useData<T extends
|
|
12
|
-
[K in keyof T]: NullishReferenceState<T[K]>;
|
|
13
|
-
};
|
|
7
|
+
export declare function useData<T extends Data>(ref: AsyncItemReference<T>): ItemState<T>;
|
|
8
|
+
export declare function useData<T extends Data>(ref: AsyncItemReference<T> | undefined): ItemState<T> | undefined;
|
|
9
|
+
export declare function useData<T extends Data>(ref: AsyncQueryReference<T>): QueryState<T>;
|
|
10
|
+
export declare function useData<T extends Data>(ref: AsyncQueryReference<T> | undefined): QueryState<T> | undefined;
|
|
14
11
|
/** Wrap components with `<DataProvider>` to allow the use of `useData()`. */
|
|
15
12
|
export declare const DataProvider: ({ children }: {
|
|
16
13
|
children: import("react").ReactNode;
|
|
17
14
|
}) => import("react").ReactElement<any, string | import("react").JSXElementConstructor<any>>;
|
|
18
|
-
export {};
|
package/react/useData.js
CHANGED
|
@@ -2,20 +2,15 @@ import { AsyncItemReference } from "../db/ItemReference.js";
|
|
|
2
2
|
import { ItemState } from "../db/ItemState.js";
|
|
3
3
|
import { QueryState } from "../db/QueryState.js";
|
|
4
4
|
import { setMapItem } from "../util/map.js";
|
|
5
|
-
import { mapArray } from "../util/transform.js";
|
|
6
5
|
import { createCache } from "./createCache.js";
|
|
7
6
|
import { useState } from "./useState.js";
|
|
8
7
|
/** Create a cache. */
|
|
9
8
|
const { Cache, useCache } = createCache();
|
|
10
|
-
export function useData(
|
|
9
|
+
export function useData(ref) {
|
|
11
10
|
const cache = useCache();
|
|
12
|
-
const states = mapArray(refs, _getRefState, cache);
|
|
13
|
-
return useState(...states);
|
|
14
|
-
}
|
|
15
|
-
/** Get the corresponding `ItemState` or `QueryState` instance from the cache for a given `Item` or `Query`. */
|
|
16
|
-
function _getRefState(ref, cache) {
|
|
17
11
|
const key = ref === null || ref === void 0 ? void 0 : ref.toString();
|
|
18
|
-
|
|
12
|
+
const state = ref && key ? cache.get(key) || setMapItem(cache, key, ref instanceof AsyncItemReference ? new ItemState(ref) : new QueryState(ref)) : undefined;
|
|
13
|
+
return useState(state);
|
|
19
14
|
}
|
|
20
15
|
/** Wrap components with `<DataProvider>` to allow the use of `useData()`. */
|
|
21
16
|
export const DataProvider = Cache;
|
package/react/useState.d.ts
CHANGED
|
@@ -1,14 +1,3 @@
|
|
|
1
1
|
import type { AnyState } from "../state/State.js";
|
|
2
|
-
import type { ImmutableArray } from "../util/array.js";
|
|
3
|
-
import type { Nullish } from "../util/null.js";
|
|
4
|
-
/**
|
|
5
|
-
* Subscribe to one or more `State` instances.
|
|
6
|
-
*
|
|
7
|
-
* @param state `State` instance.
|
|
8
|
-
* - Subscription is recreated every time the state instance changes.
|
|
9
|
-
* - Memoise this value to persist the subscription for the lifetime of the component.
|
|
10
|
-
* - If the value is a `State` instance
|
|
11
|
-
*/
|
|
12
2
|
export declare function useState<T extends AnyState>(state: T): T;
|
|
13
|
-
export declare function useState<T extends AnyState>(state?:
|
|
14
|
-
export declare function useState<T extends ImmutableArray<Nullish<AnyState>>>(...states: T): T;
|
|
3
|
+
export declare function useState<T extends AnyState>(state?: T | undefined): T | undefined;
|