shelving 1.188.6 → 1.189.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/endpoint/util.js +2 -2
- package/package.json +1 -1
- package/store/ArrayStore.d.ts +4 -2
- package/store/ArrayStore.js +5 -1
- package/store/BooleanStore.d.ts +2 -3
- package/store/BooleanStore.js +3 -2
- package/store/DataStore.d.ts +4 -2
- package/store/DataStore.js +8 -0
- package/store/DictionaryStore.d.ts +4 -3
- package/store/DictionaryStore.js +8 -3
- package/store/FetchStore.d.ts +2 -1
- package/store/FetchStore.js +7 -3
- package/store/LoadingStore.d.ts +10 -0
- package/store/LoadingStore.js +16 -0
- package/store/PathStore.d.ts +6 -5
- package/store/PathStore.js +8 -8
- package/store/PayloadFetchStore.d.ts +2 -2
- package/store/PayloadFetchStore.js +2 -2
- package/store/Store.d.ts +35 -17
- package/store/Store.js +36 -15
- package/store/URLStore.d.ts +3 -3
- package/store/URLStore.js +6 -7
- package/store/ValueStore.d.ts +5 -0
- package/store/ValueStore.js +8 -0
- package/store/index.d.ts +2 -0
- package/store/index.js +2 -0
- package/util/constants.d.ts +4 -2
- package/util/constants.js +4 -2
- package/util/data.d.ts +0 -3
- package/util/data.js +0 -4
- package/util/dictionary.d.ts +1 -1
- package/util/dictionary.js +1 -1
- package/util/path.d.ts +6 -4
- package/util/path.js +1 -1
- package/util/sequence.d.ts +2 -2
- package/util/sequence.js +5 -5
package/api/endpoint/util.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { MethodNotAllowedError, NotFoundError } from "../../error/RequestError.js";
|
|
2
2
|
import { ValueError } from "../../error/ValueError.js";
|
|
3
|
-
import {
|
|
3
|
+
import { requireDictionary } from "../../util/dictionary.js";
|
|
4
4
|
import { getResponse, isRequestMethod, parseRequestBody } from "../../util/http.js";
|
|
5
5
|
import { isPlainObject } from "../../util/object.js";
|
|
6
6
|
import { requireURL } from "../../util/url.js";
|
|
@@ -19,7 +19,7 @@ export function handleEndpoints(base, handlers, request, context, caller = handl
|
|
|
19
19
|
const pathParams = handler.endpoint.match(method, targetPath, caller);
|
|
20
20
|
if (!pathParams)
|
|
21
21
|
continue;
|
|
22
|
-
const params = searchParams.size ? { ...
|
|
22
|
+
const params = searchParams.size ? { ...requireDictionary(searchParams), ...pathParams } : pathParams;
|
|
23
23
|
return _handleEndpoint(handler, params, request, context, handleEndpoints);
|
|
24
24
|
}
|
|
25
25
|
throw new NotFoundError("No matching endpoint", { received: targetPath, caller });
|
package/package.json
CHANGED
package/store/ArrayStore.d.ts
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
|
-
import type { ImmutableArray } from "../util/array.js";
|
|
1
|
+
import type { ImmutableArray, PossibleArray } from "../util/array.js";
|
|
2
2
|
import type { NONE } from "../util/constants.js";
|
|
3
|
+
import type { AnyCaller } from "../util/function.js";
|
|
3
4
|
import { Store } from "./Store.js";
|
|
4
5
|
/** Store an array. */
|
|
5
|
-
export declare class ArrayStore<T> extends Store<ImmutableArray<T>> implements Iterable<T> {
|
|
6
|
+
export declare class ArrayStore<T> extends Store<PossibleArray<T>, ImmutableArray<T>> implements Iterable<T> {
|
|
6
7
|
constructor(value?: ImmutableArray<T> | typeof NONE);
|
|
8
|
+
convert(value: PossibleArray<T>, caller?: AnyCaller): ImmutableArray<T>;
|
|
7
9
|
/** Get the first item in this store or `null` if this query has no items. */
|
|
8
10
|
get optionalFirst(): T | undefined;
|
|
9
11
|
/** Get the last item in this store or `null` if this query has no items. */
|
package/store/ArrayStore.js
CHANGED
|
@@ -1,10 +1,14 @@
|
|
|
1
|
-
import { getFirst, getLast, omitArrayItems, requireFirst, requireLast, toggleArrayItems, withArrayItems } from "../util/array.js";
|
|
1
|
+
import { getFirst, getLast, omitArrayItems, requireArray, requireFirst, requireLast, toggleArrayItems, withArrayItems, } from "../util/array.js";
|
|
2
2
|
import { Store } from "./Store.js";
|
|
3
3
|
/** Store an array. */
|
|
4
4
|
export class ArrayStore extends Store {
|
|
5
5
|
constructor(value = []) {
|
|
6
6
|
super(value);
|
|
7
7
|
}
|
|
8
|
+
// Implement to automatically convert `PossibleArray`
|
|
9
|
+
convert(value, caller = this.convert) {
|
|
10
|
+
return requireArray(value, undefined, undefined, caller);
|
|
11
|
+
}
|
|
8
12
|
/** Get the first item in this store or `null` if this query has no items. */
|
|
9
13
|
get optionalFirst() {
|
|
10
14
|
return getFirst(this.value);
|
package/store/BooleanStore.d.ts
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
|
-
import type { NONE } from "../util/constants.js";
|
|
2
1
|
import { Store } from "./Store.js";
|
|
3
2
|
/** Store a boolean. */
|
|
4
|
-
export declare class BooleanStore extends Store<boolean> {
|
|
5
|
-
|
|
3
|
+
export declare class BooleanStore extends Store<unknown, boolean> {
|
|
4
|
+
convert(value: unknown): boolean;
|
|
6
5
|
/** Toggle the current boolean value. */
|
|
7
6
|
toggle(): void;
|
|
8
7
|
isEqual(a: boolean, b: boolean): boolean;
|
package/store/BooleanStore.js
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { Store } from "./Store.js";
|
|
2
2
|
/** Store a boolean. */
|
|
3
3
|
export class BooleanStore extends Store {
|
|
4
|
-
|
|
5
|
-
|
|
4
|
+
// Override to automatically convert to boolean.
|
|
5
|
+
convert(value) {
|
|
6
|
+
return !!value;
|
|
6
7
|
}
|
|
7
8
|
/** Toggle the current boolean value. */
|
|
8
9
|
toggle() {
|
package/store/DataStore.d.ts
CHANGED
|
@@ -3,7 +3,7 @@ import type { AnyCaller } from "../util/function.js";
|
|
|
3
3
|
import type { Updates } from "../util/update.js";
|
|
4
4
|
import { Store } from "./Store.js";
|
|
5
5
|
/** Store a data object. */
|
|
6
|
-
export declare class DataStore<T extends Data> extends Store<T> {
|
|
6
|
+
export declare class DataStore<T extends Data> extends Store<T, T> {
|
|
7
7
|
/** Get the data of this store. */
|
|
8
8
|
get data(): T;
|
|
9
9
|
/** Set the data of this store. */
|
|
@@ -14,9 +14,10 @@ export declare class DataStore<T extends Data> extends Store<T> {
|
|
|
14
14
|
get<K extends DataKey<T>>(name: K): T[K];
|
|
15
15
|
/** Update a single named prop in this data. */
|
|
16
16
|
set<K extends DataKey<T>>(name: K, value: T[K]): void;
|
|
17
|
+
convert(value: T): T;
|
|
17
18
|
}
|
|
18
19
|
/** Store an optional data object. */
|
|
19
|
-
export declare class OptionalDataStore<T extends Data> extends Store<T | undefined> {
|
|
20
|
+
export declare class OptionalDataStore<T extends Data> extends Store<T | undefined, T | undefined> {
|
|
20
21
|
/** Get current data value of this store (or throw `Promise` that resolves to the next required value). */
|
|
21
22
|
get data(): T;
|
|
22
23
|
/** Set the data of this store. */
|
|
@@ -33,4 +34,5 @@ export declare class OptionalDataStore<T extends Data> extends Store<T | undefin
|
|
|
33
34
|
set<K extends DataKey<T>>(name: K, value: T[K]): void;
|
|
34
35
|
/** Set the data to `undefined`. */
|
|
35
36
|
delete(): void;
|
|
37
|
+
convert(value: T): T;
|
|
36
38
|
}
|
package/store/DataStore.js
CHANGED
|
@@ -25,6 +25,10 @@ export class DataStore extends Store {
|
|
|
25
25
|
set(name, value) {
|
|
26
26
|
this.value = withProp(this.data, name, value);
|
|
27
27
|
}
|
|
28
|
+
// Implement to passthrough.
|
|
29
|
+
convert(value) {
|
|
30
|
+
return value;
|
|
31
|
+
}
|
|
28
32
|
}
|
|
29
33
|
/** Store an optional data object. */
|
|
30
34
|
export class OptionalDataStore extends Store {
|
|
@@ -63,4 +67,8 @@ export class OptionalDataStore extends Store {
|
|
|
63
67
|
delete() {
|
|
64
68
|
this.value = undefined;
|
|
65
69
|
}
|
|
70
|
+
// Implement to passthrough.
|
|
71
|
+
convert(value) {
|
|
72
|
+
return value;
|
|
73
|
+
}
|
|
66
74
|
}
|
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import type { DictionaryItem, ImmutableDictionary } from "../util/dictionary.js";
|
|
1
|
+
import type { DictionaryItem, ImmutableDictionary, PossibleDictionary } from "../util/dictionary.js";
|
|
2
2
|
import type { Updates } from "../util/update.js";
|
|
3
3
|
import { Store } from "./Store.js";
|
|
4
4
|
/** Store a dictionary object. */
|
|
5
|
-
export declare class DictionaryStore<T> extends Store<ImmutableDictionary<T>> implements Iterable<DictionaryItem<T>> {
|
|
6
|
-
constructor(value?:
|
|
5
|
+
export declare class DictionaryStore<T> extends Store<PossibleDictionary<T>, ImmutableDictionary<T>> implements Iterable<DictionaryItem<T>> {
|
|
6
|
+
constructor(value?: PossibleDictionary<T>);
|
|
7
|
+
convert(possible: PossibleDictionary<T>): ImmutableDictionary<T>;
|
|
7
8
|
/** Get the length of the current value of this store. */
|
|
8
9
|
get count(): number;
|
|
9
10
|
/** Set a named entry in this object with a different value. */
|
package/store/DictionaryStore.js
CHANGED
|
@@ -1,11 +1,16 @@
|
|
|
1
|
-
import { getDictionaryItems, omitDictionaryItems } from "../util/dictionary.js";
|
|
1
|
+
import { EMPTY_DICTIONARY, getDictionaryItems, omitDictionaryItems, requireDictionary } from "../util/dictionary.js";
|
|
2
2
|
import { omitProps, withProp } from "../util/object.js";
|
|
3
3
|
import { updateData } from "../util/update.js";
|
|
4
4
|
import { Store } from "./Store.js";
|
|
5
5
|
/** Store a dictionary object. */
|
|
6
6
|
export class DictionaryStore extends Store {
|
|
7
|
-
|
|
8
|
-
|
|
7
|
+
// Override to set default value to empty dictionary.
|
|
8
|
+
constructor(value = EMPTY_DICTIONARY) {
|
|
9
|
+
super(requireDictionary(value));
|
|
10
|
+
}
|
|
11
|
+
// Override to convert a possible dictionary to a dictionary on set.
|
|
12
|
+
convert(possible) {
|
|
13
|
+
return requireDictionary(possible);
|
|
9
14
|
}
|
|
10
15
|
/** Get the length of the current value of this store. */
|
|
11
16
|
get count() {
|
package/store/FetchStore.d.ts
CHANGED
|
@@ -9,7 +9,7 @@ export type FetchCallback<T> = (signal: AbortSignal) => T | PromiseLike<T>;
|
|
|
9
9
|
* @param value The initial value for the store, or `NONE` if it does not have one yet.
|
|
10
10
|
* @param callback An optional callback that, if set, will be called when the `refresh()` method is invoked to fetch the next value.
|
|
11
11
|
*/
|
|
12
|
-
export declare class FetchStore<T> extends Store<T> {
|
|
12
|
+
export declare class FetchStore<T> extends Store<T | typeof NONE, T> {
|
|
13
13
|
/**
|
|
14
14
|
* Store that indicates the busy state of this store.
|
|
15
15
|
* - `true` while a refresh is in-flight, `false` otherwise.
|
|
@@ -20,6 +20,7 @@ export declare class FetchStore<T> extends Store<T> {
|
|
|
20
20
|
get value(): T;
|
|
21
21
|
set value(value: T | typeof NONE | PromiseLike<T | typeof NONE>);
|
|
22
22
|
constructor(value: T | typeof NONE, callback?: FetchCallback<T>);
|
|
23
|
+
convert(value: T | typeof NONE): T | typeof NONE;
|
|
23
24
|
/**
|
|
24
25
|
* Fetch the result for this store now.
|
|
25
26
|
* - Triggered automatically when someone reads `value` or `loading`.
|
package/store/FetchStore.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { RequiredError } from "../error/RequiredError.js";
|
|
2
2
|
import { isAsync } from "../util/async.js";
|
|
3
|
-
import {
|
|
3
|
+
import { ABORT, NONE } from "../util/constants.js";
|
|
4
4
|
import { awaitDispose } from "../util/dispose.js";
|
|
5
5
|
import { BooleanStore } from "./BooleanStore.js";
|
|
6
6
|
import { Store } from "./Store.js";
|
|
@@ -42,6 +42,10 @@ export class FetchStore extends Store {
|
|
|
42
42
|
this.busy = new BooleanStore(value === NONE);
|
|
43
43
|
this._callback = callback;
|
|
44
44
|
}
|
|
45
|
+
// Implement to allow `NONE`
|
|
46
|
+
convert(value) {
|
|
47
|
+
return value;
|
|
48
|
+
}
|
|
45
49
|
/**
|
|
46
50
|
* Fetch the result for this store now.
|
|
47
51
|
* - Triggered automatically when someone reads `value` or `loading`.
|
|
@@ -55,7 +59,7 @@ export class FetchStore extends Store {
|
|
|
55
59
|
if (this._inflight)
|
|
56
60
|
return this._inflight;
|
|
57
61
|
// Cancel any existing controller and create a fresh one for this fetch.
|
|
58
|
-
this._controller?.abort(
|
|
62
|
+
this._controller?.abort(ABORT);
|
|
59
63
|
this._controller = new AbortController();
|
|
60
64
|
try {
|
|
61
65
|
const value = this._fetch(this._controller.signal);
|
|
@@ -122,7 +126,7 @@ export class FetchStore extends Store {
|
|
|
122
126
|
* - Any pending `await()` result will be silently discarded.
|
|
123
127
|
*/
|
|
124
128
|
abort() {
|
|
125
|
-
this._controller?.abort(
|
|
129
|
+
this._controller?.abort(ABORT);
|
|
126
130
|
this._controller = undefined;
|
|
127
131
|
this._inflight = undefined;
|
|
128
132
|
this.busy.value = false;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { NONE } from "../util/constants.js";
|
|
2
|
+
import { Store } from "./Store.js";
|
|
3
|
+
/**
|
|
4
|
+
* Store that is explicitly allows a "loading" state when it has no value (which is also the default value).
|
|
5
|
+
* - Note: All stores have know how to interpret `NONE` — this subclass simply _allows_ that through its types.
|
|
6
|
+
*/
|
|
7
|
+
export declare class LoadingStore<T> extends Store<T, T | typeof NONE> {
|
|
8
|
+
constructor(value?: T | typeof NONE);
|
|
9
|
+
convert(value: T | typeof NONE): T | typeof NONE;
|
|
10
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { NONE } from "../util/constants.js";
|
|
2
|
+
import { Store } from "./Store.js";
|
|
3
|
+
/**
|
|
4
|
+
* Store that is explicitly allows a "loading" state when it has no value (which is also the default value).
|
|
5
|
+
* - Note: All stores have know how to interpret `NONE` — this subclass simply _allows_ that through its types.
|
|
6
|
+
*/
|
|
7
|
+
export class LoadingStore extends Store {
|
|
8
|
+
// Override to default to `NONE`
|
|
9
|
+
constructor(value = NONE) {
|
|
10
|
+
super(value);
|
|
11
|
+
}
|
|
12
|
+
// Implement to allow `NONE`
|
|
13
|
+
convert(value) {
|
|
14
|
+
return value;
|
|
15
|
+
}
|
|
16
|
+
}
|
package/store/PathStore.d.ts
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { AnyCaller } from "../util/function.js";
|
|
2
|
+
import type { AbsolutePath, PossiblePath } from "../util/path.js";
|
|
2
3
|
import { Store } from "./Store.js";
|
|
3
4
|
/** Store an absolute path, e.g. `/a/b/c` */
|
|
4
|
-
export declare class PathStore extends Store<AbsolutePath> {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
5
|
+
export declare class PathStore extends Store<PossiblePath, AbsolutePath> {
|
|
6
|
+
readonly base: AbsolutePath;
|
|
7
|
+
constructor(path?: string, base?: AbsolutePath);
|
|
8
|
+
convert(possible: PossiblePath, caller: AnyCaller): AbsolutePath;
|
|
8
9
|
/** Based on the current store path, is a path active? */
|
|
9
10
|
isActive(path: AbsolutePath): boolean;
|
|
10
11
|
/** Based on the current store path, is a path proud (i.e. a child of the current store path)? */
|
package/store/PathStore.js
CHANGED
|
@@ -2,15 +2,15 @@ import { isPathActive, isPathProud, requirePath } from "../util/path.js";
|
|
|
2
2
|
import { Store } from "./Store.js";
|
|
3
3
|
/** Store an absolute path, e.g. `/a/b/c` */
|
|
4
4
|
export class PathStore extends Store {
|
|
5
|
-
|
|
6
|
-
|
|
5
|
+
base;
|
|
6
|
+
// Override to set default path to `.` and base to `/`
|
|
7
|
+
constructor(path = ".", base = "/") {
|
|
8
|
+
super(requirePath(path, base, PathStore));
|
|
9
|
+
this.base = base;
|
|
7
10
|
}
|
|
8
|
-
//
|
|
9
|
-
|
|
10
|
-
return
|
|
11
|
-
}
|
|
12
|
-
set value(path) {
|
|
13
|
-
super.value = requirePath(path, super.value);
|
|
11
|
+
// Implement to convert a possible path to an absolute path (relative to `this.base`).
|
|
12
|
+
convert(possible, caller) {
|
|
13
|
+
return requirePath(possible, this.base, caller);
|
|
14
14
|
}
|
|
15
15
|
/** Based on the current store path, is a path active? */
|
|
16
16
|
isActive(path) {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { NONE } from "../util/constants.js";
|
|
2
2
|
import { FetchStore } from "./FetchStore.js";
|
|
3
|
-
import {
|
|
3
|
+
import { ValueStore } from "./ValueStore.js";
|
|
4
4
|
export type PayloadFetchCallback<P, R> = (payload: P) => R | PromiseLike<R>;
|
|
5
5
|
/**
|
|
6
6
|
* Store that fetches its values from a remote source by sending a payload to them.
|
|
@@ -14,7 +14,7 @@ export declare class PayloadFetchStore<P, R> extends FetchStore<R> {
|
|
|
14
14
|
* Store keeping the current payload to send to the fetch on send.
|
|
15
15
|
* - New payloads can be set using `this.payload.value`
|
|
16
16
|
*/
|
|
17
|
-
readonly payload:
|
|
17
|
+
readonly payload: ValueStore<P>;
|
|
18
18
|
constructor(payload: P, value: R | typeof NONE, callback?: PayloadFetchCallback<P, R>);
|
|
19
19
|
[Symbol.asyncDispose](): Promise<void>;
|
|
20
20
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { awaitDispose } from "../util/dispose.js";
|
|
2
2
|
import { FetchStore } from "./FetchStore.js";
|
|
3
|
-
import {
|
|
3
|
+
import { ValueStore } from "./ValueStore.js";
|
|
4
4
|
/**
|
|
5
5
|
* Store that fetches its values from a remote source by sending a payload to them.
|
|
6
6
|
*
|
|
@@ -16,7 +16,7 @@ export class PayloadFetchStore extends FetchStore {
|
|
|
16
16
|
payload;
|
|
17
17
|
// Override to save initial payload and callback.
|
|
18
18
|
constructor(payload, value, callback) {
|
|
19
|
-
const payloadStore = new
|
|
19
|
+
const payloadStore = new ValueStore(payload);
|
|
20
20
|
super(value, callback && (() => callback(payloadStore.value)));
|
|
21
21
|
this.payload = payloadStore;
|
|
22
22
|
void _iterate(this);
|
package/store/Store.d.ts
CHANGED
|
@@ -1,9 +1,13 @@
|
|
|
1
1
|
import { DeferredSequence } from "../sequence/DeferredSequence.js";
|
|
2
|
-
import { NONE } from "../util/constants.js";
|
|
3
|
-
import type { Arguments } from "../util/function.js";
|
|
2
|
+
import { NONE, SKIP } from "../util/constants.js";
|
|
3
|
+
import type { AnyCaller, Arguments } from "../util/function.js";
|
|
4
4
|
import { type PossibleStarter } from "../util/start.js";
|
|
5
5
|
/** Any `Store` instance. */
|
|
6
|
-
export type AnyStore = Store<any>;
|
|
6
|
+
export type AnyStore = Store<any, any>;
|
|
7
|
+
/** Callback that sets a store's value (possibly asynchronously). */
|
|
8
|
+
export type StoreCallback<I, A extends Arguments = []> = (...args: A) => I | PromiseLike<I>;
|
|
9
|
+
/** Reducer that receives a store's current value and sets the stores next value (possibly asynchronously). */
|
|
10
|
+
export type StoreReducer<I, O, A extends Arguments = []> = (value: O, ...args: A) => I | PromiseLike<I>;
|
|
7
11
|
/**
|
|
8
12
|
* Store that retains its most recent value and is async-iterable to allow values to be observed.
|
|
9
13
|
* - Current value can be read at `store.value` and `store.data`
|
|
@@ -13,10 +17,18 @@ export type AnyStore = Store<any>;
|
|
|
13
17
|
* @param initial The initial value for this store, a `Promise` that resolves to the initial value, a source `Subscribable` to subscribe to, or another `Store` instance to take the initial value from and subscribe to.
|
|
14
18
|
* - To set this store to be loading, use the `NONE` constant or a `Promise` value.
|
|
15
19
|
* - To set this store to an explicit value, use that value or another `Store` instance with a value.
|
|
20
|
+
*
|
|
21
|
+
* @param I The "input type" for this store.
|
|
22
|
+
* - Indicates what values `this.value` can be set to.
|
|
23
|
+
* - Methods that set values like `this.call()` and `this.await()` can also accept these values.
|
|
24
|
+
* @param O The "output type" for this store.
|
|
25
|
+
* - Indicates what value `this.value` will return.
|
|
26
|
+
* - Must extend the input type `I`.
|
|
27
|
+
* - Defaults to I.
|
|
16
28
|
*/
|
|
17
|
-
export declare class Store<
|
|
29
|
+
export declare abstract class Store<I, O> implements AsyncIterable<O, void, void>, AsyncDisposable {
|
|
18
30
|
/** Deferred sequence this store uses to issue values as they change. */
|
|
19
|
-
readonly next: DeferredSequence<
|
|
31
|
+
readonly next: DeferredSequence<O, void, void>;
|
|
20
32
|
/**
|
|
21
33
|
* Store is considered to be "loading" if it has no value or error.
|
|
22
34
|
* - Calling `this.value` will throw `this.reason` if there's an error reason set, or a `Promise` if there's no value set.
|
|
@@ -29,14 +41,20 @@ export declare class Store<T> implements AsyncIterable<T, void, void>, AsyncDisp
|
|
|
29
41
|
* @throws {Promise} if this store currently has no value (resolves when this store receives its next value or error).
|
|
30
42
|
* @throws {unknown} if this store currently has an error.
|
|
31
43
|
*/
|
|
32
|
-
get value():
|
|
44
|
+
get value(): O;
|
|
33
45
|
/**
|
|
34
|
-
* Set the value of this store
|
|
35
|
-
* -
|
|
46
|
+
* Set the value of this store.
|
|
47
|
+
* - Sets any sync values.
|
|
36
48
|
* - Awaits any async values.
|
|
49
|
+
* - Setting value the `NONE` symbol indicates the store has no value so should be in a "loading" state.
|
|
50
|
+
* - Setting value to `SKIP` indicates the value should be silently ignored (sometimes it's helpful to have a way to skip setting entirely).
|
|
51
|
+
* - Setting value to the same as the existing value
|
|
52
|
+
* - If this store has any pending `await()` calls they are aborted and their results are silently discarded.
|
|
37
53
|
*/
|
|
38
|
-
set value(value:
|
|
54
|
+
set value(value: I | PromiseLike<I>);
|
|
39
55
|
private _value;
|
|
56
|
+
/** Convert a possible value for this store into an actual value of this store. */
|
|
57
|
+
abstract convert(possible: I, _caller?: AnyCaller): O | typeof NONE | typeof SKIP;
|
|
40
58
|
/**
|
|
41
59
|
* Time (in milliseconds) this store was last updated with a new value.
|
|
42
60
|
* - Will be `undefined` if the value is still loading.
|
|
@@ -62,16 +80,16 @@ export declare class Store<T> implements AsyncIterable<T, void, void>, AsyncDisp
|
|
|
62
80
|
protected set starter(start: PossibleStarter<[this]>);
|
|
63
81
|
private _starter;
|
|
64
82
|
/** Store is initiated with an initial store. */
|
|
65
|
-
constructor(value:
|
|
83
|
+
constructor(value: O | typeof NONE);
|
|
66
84
|
/** Set the value of this store as values are pulled from a sequence. */
|
|
67
|
-
through(sequence: AsyncIterable<
|
|
85
|
+
through(sequence: AsyncIterable<I>): AsyncIterable<I>;
|
|
68
86
|
/**
|
|
69
87
|
* Call a callback that returns a new value (possibly async) for this store.
|
|
70
88
|
* - Errors are stored as `reason`; never throws.
|
|
71
89
|
*
|
|
72
90
|
* @returns `true` if the value was applied, `false` if an error occurred or the result was superseded.
|
|
73
91
|
*/
|
|
74
|
-
call<A extends Arguments
|
|
92
|
+
call<A extends Arguments>(callback: StoreCallback<I, A>, ...args: A): Promise<boolean> | boolean;
|
|
75
93
|
/**
|
|
76
94
|
* Reduce the current value using a reducer callback that receives the current value.
|
|
77
95
|
*
|
|
@@ -84,7 +102,7 @@ export declare class Store<T> implements AsyncIterable<T, void, void>, AsyncDisp
|
|
|
84
102
|
* @throws {Promise} if this store currently has no value (resolves when this store receives its next value or error).
|
|
85
103
|
* @throws {unknown} if this store currently has an error reason set.
|
|
86
104
|
*/
|
|
87
|
-
reduce<A extends Arguments
|
|
105
|
+
reduce<A extends Arguments>(reducer: StoreReducer<I, O, A>, ...args: A): Promise<boolean> | boolean;
|
|
88
106
|
/**
|
|
89
107
|
* Await an async value and save it to this store.
|
|
90
108
|
* - Saves the resolved value.
|
|
@@ -96,16 +114,16 @@ export declare class Store<T> implements AsyncIterable<T, void, void>, AsyncDisp
|
|
|
96
114
|
* @returns `true` if the value was applied, `false` if superseded, aborted, or errored.
|
|
97
115
|
* @throws {never} Never throws — safe to call without handling the return value.
|
|
98
116
|
*/
|
|
99
|
-
await(
|
|
100
|
-
private
|
|
117
|
+
await(pending: PromiseLike<I>): Promise<boolean>;
|
|
118
|
+
private _pending;
|
|
101
119
|
/**
|
|
102
120
|
* Abort any current pending `await()` call.
|
|
103
121
|
* - The pending call's result will be silently discarded and its error will not be stored.
|
|
104
122
|
*/
|
|
105
123
|
abort(): void;
|
|
106
|
-
[Symbol.asyncIterator](): AsyncIterator<
|
|
124
|
+
[Symbol.asyncIterator](): AsyncIterator<O, void, void>;
|
|
107
125
|
private _iterating;
|
|
108
126
|
/** Compare two values for this store and return whether they are equal. */
|
|
109
|
-
isEqual(a:
|
|
127
|
+
isEqual(a: O, b: O): boolean;
|
|
110
128
|
[Symbol.asyncDispose](): Promise<void>;
|
|
111
129
|
}
|
package/store/Store.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { DeferredSequence } from "../sequence/DeferredSequence.js";
|
|
2
2
|
import { isAsync } from "../util/async.js";
|
|
3
|
-
import {
|
|
3
|
+
import { getSetter } from "../util/class.js";
|
|
4
|
+
import { NONE, SKIP } from "../util/constants.js";
|
|
4
5
|
import { awaitDispose } from "../util/dispose.js";
|
|
5
6
|
import { isDeepEqual } from "../util/equal.js";
|
|
6
7
|
import { getStarter } from "../util/start.js";
|
|
@@ -13,6 +14,14 @@ import { getStarter } from "../util/start.js";
|
|
|
13
14
|
* @param initial The initial value for this store, a `Promise` that resolves to the initial value, a source `Subscribable` to subscribe to, or another `Store` instance to take the initial value from and subscribe to.
|
|
14
15
|
* - To set this store to be loading, use the `NONE` constant or a `Promise` value.
|
|
15
16
|
* - To set this store to an explicit value, use that value or another `Store` instance with a value.
|
|
17
|
+
*
|
|
18
|
+
* @param I The "input type" for this store.
|
|
19
|
+
* - Indicates what values `this.value` can be set to.
|
|
20
|
+
* - Methods that set values like `this.call()` and `this.await()` can also accept these values.
|
|
21
|
+
* @param O The "output type" for this store.
|
|
22
|
+
* - Indicates what value `this.value` will return.
|
|
23
|
+
* - Must extend the input type `I`.
|
|
24
|
+
* - Defaults to I.
|
|
16
25
|
*/
|
|
17
26
|
export class Store {
|
|
18
27
|
/** Deferred sequence this store uses to issue values as they change. */
|
|
@@ -39,9 +48,13 @@ export class Store {
|
|
|
39
48
|
return this._value;
|
|
40
49
|
}
|
|
41
50
|
/**
|
|
42
|
-
* Set the value of this store
|
|
43
|
-
* -
|
|
51
|
+
* Set the value of this store.
|
|
52
|
+
* - Sets any sync values.
|
|
44
53
|
* - Awaits any async values.
|
|
54
|
+
* - Setting value the `NONE` symbol indicates the store has no value so should be in a "loading" state.
|
|
55
|
+
* - Setting value to `SKIP` indicates the value should be silently ignored (sometimes it's helpful to have a way to skip setting entirely).
|
|
56
|
+
* - Setting value to the same as the existing value
|
|
57
|
+
* - If this store has any pending `await()` calls they are aborted and their results are silently discarded.
|
|
45
58
|
*/
|
|
46
59
|
set value(value) {
|
|
47
60
|
if (isAsync(value)) {
|
|
@@ -50,15 +63,23 @@ export class Store {
|
|
|
50
63
|
else {
|
|
51
64
|
this.abort();
|
|
52
65
|
this._reason = undefined;
|
|
53
|
-
|
|
66
|
+
const v = value === NONE || value === SKIP
|
|
67
|
+
? value || typeof SKIP
|
|
68
|
+
: this.convert(value, getSetter(this, "value"));
|
|
69
|
+
if (v === NONE) {
|
|
70
|
+
// Put the store back into a loading state.
|
|
54
71
|
this._time = undefined;
|
|
55
|
-
this._value =
|
|
72
|
+
this._value = v;
|
|
56
73
|
this.next.cancel();
|
|
57
74
|
}
|
|
58
|
-
else if (
|
|
75
|
+
else if (v === SKIP) {
|
|
76
|
+
// Silently skip this set value call.
|
|
77
|
+
}
|
|
78
|
+
else if (this._value === NONE || !this.isEqual(v, this._value)) {
|
|
79
|
+
// Set this value.
|
|
59
80
|
this._time = Date.now();
|
|
60
|
-
this._value =
|
|
61
|
-
this.next.resolve(
|
|
81
|
+
this._value = v;
|
|
82
|
+
this.next.resolve(v);
|
|
62
83
|
}
|
|
63
84
|
}
|
|
64
85
|
}
|
|
@@ -162,33 +183,33 @@ export class Store {
|
|
|
162
183
|
* @returns `true` if the value was applied, `false` if superseded, aborted, or errored.
|
|
163
184
|
* @throws {never} Never throws — safe to call without handling the return value.
|
|
164
185
|
*/
|
|
165
|
-
async await(
|
|
186
|
+
async await(pending) {
|
|
166
187
|
// Keep track of the value that is being awaited.
|
|
167
188
|
// If `_pendingValue` changes while waiting for `asyncValue` to resolve, another call to `await()` has `set value`, `set reason`, or `abort()` has invalidated this one.
|
|
168
189
|
// If that happens we silently discard the resolved value/reason of this await call.
|
|
169
|
-
this.
|
|
190
|
+
this._pending = pending;
|
|
170
191
|
try {
|
|
171
|
-
const value = await
|
|
172
|
-
if (this.
|
|
192
|
+
const value = await pending;
|
|
193
|
+
if (this._pending === pending) {
|
|
173
194
|
this.value = value;
|
|
174
195
|
return true;
|
|
175
196
|
}
|
|
176
197
|
return false;
|
|
177
198
|
}
|
|
178
199
|
catch (reason) {
|
|
179
|
-
if (this.
|
|
200
|
+
if (this._pending === pending) {
|
|
180
201
|
this.reason = reason;
|
|
181
202
|
}
|
|
182
203
|
return false;
|
|
183
204
|
}
|
|
184
205
|
}
|
|
185
|
-
|
|
206
|
+
_pending = undefined;
|
|
186
207
|
/**
|
|
187
208
|
* Abort any current pending `await()` call.
|
|
188
209
|
* - The pending call's result will be silently discarded and its error will not be stored.
|
|
189
210
|
*/
|
|
190
211
|
abort() {
|
|
191
|
-
this.
|
|
212
|
+
this._pending = undefined;
|
|
192
213
|
}
|
|
193
214
|
// Implement `AsyncIterator`
|
|
194
215
|
// Issues the current value of this store first, then any subsequent values that are issued.
|
package/store/URLStore.d.ts
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
|
+
import type { AnyCaller } from "../util/function.js";
|
|
1
2
|
import { type PossibleURIParams, type URIParams, type URIScheme } from "../util/uri.js";
|
|
2
3
|
import { type PossibleURL, type URL, type URLString } from "../util/url.js";
|
|
3
4
|
import { Store } from "./Store.js";
|
|
4
5
|
/** Store a URL, e.g. `https://top.com/a/b/c` */
|
|
5
|
-
export declare class URLStore extends Store<URL> {
|
|
6
|
+
export declare class URLStore extends Store<PossibleURL, URL> {
|
|
6
7
|
readonly base: URL | undefined;
|
|
7
8
|
constructor(url: PossibleURL, base?: PossibleURL);
|
|
8
|
-
|
|
9
|
-
get value(): URL;
|
|
9
|
+
convert(value: PossibleURL, caller?: AnyCaller): URL;
|
|
10
10
|
get href(): URLString;
|
|
11
11
|
set href(href: URLString);
|
|
12
12
|
get origin(): URLString;
|
package/store/URLStore.js
CHANGED
|
@@ -5,22 +5,21 @@ import { Store } from "./Store.js";
|
|
|
5
5
|
/** Store a URL, e.g. `https://top.com/a/b/c` */
|
|
6
6
|
export class URLStore extends Store {
|
|
7
7
|
base;
|
|
8
|
+
// Override to convert possible URL to URL.
|
|
8
9
|
constructor(url, base) {
|
|
9
10
|
const baseURL = getURL(base);
|
|
10
|
-
super(requireURL(url, baseURL));
|
|
11
|
+
super(requireURL(url, baseURL, URLStore));
|
|
11
12
|
this.base = baseURL;
|
|
12
13
|
}
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
get value() {
|
|
17
|
-
return super.value;
|
|
14
|
+
// Override to convert possible URL to URL (relative to `this.base`).
|
|
15
|
+
convert(value, caller = this.convert) {
|
|
16
|
+
return requireURL(value, this.base, caller);
|
|
18
17
|
}
|
|
19
18
|
get href() {
|
|
20
19
|
return this.value.href;
|
|
21
20
|
}
|
|
22
21
|
set href(href) {
|
|
23
|
-
this.value =
|
|
22
|
+
this.value = href;
|
|
24
23
|
}
|
|
25
24
|
get origin() {
|
|
26
25
|
return this.value.origin;
|
package/store/index.d.ts
CHANGED
|
@@ -3,7 +3,9 @@ export * from "./BooleanStore.js";
|
|
|
3
3
|
export * from "./DataStore.js";
|
|
4
4
|
export * from "./DictionaryStore.js";
|
|
5
5
|
export * from "./FetchStore.js";
|
|
6
|
+
export * from "./LoadingStore.js";
|
|
6
7
|
export * from "./PathStore.js";
|
|
7
8
|
export * from "./PayloadFetchStore.js";
|
|
8
9
|
export * from "./Store.js";
|
|
9
10
|
export * from "./URLStore.js";
|
|
11
|
+
export * from "./ValueStore.js";
|
package/store/index.js
CHANGED
|
@@ -3,7 +3,9 @@ export * from "./BooleanStore.js";
|
|
|
3
3
|
export * from "./DataStore.js";
|
|
4
4
|
export * from "./DictionaryStore.js";
|
|
5
5
|
export * from "./FetchStore.js";
|
|
6
|
+
export * from "./LoadingStore.js";
|
|
6
7
|
export * from "./PathStore.js";
|
|
7
8
|
export * from "./PayloadFetchStore.js";
|
|
8
9
|
export * from "./Store.js";
|
|
9
10
|
export * from "./URLStore.js";
|
|
11
|
+
export * from "./ValueStore.js";
|
package/util/constants.d.ts
CHANGED
|
@@ -30,7 +30,9 @@ export declare const NBSP = "\u00A0";
|
|
|
30
30
|
export declare const THINSP = "\u2009";
|
|
31
31
|
/** Non-breaking narrow space (goes between numbers and their corresponding units). */
|
|
32
32
|
export declare const NNBSP = "\u202F";
|
|
33
|
-
/** The `
|
|
34
|
-
export declare const
|
|
33
|
+
/** The `ABORT` symbol indicates something was manually aborted. */
|
|
34
|
+
export declare const ABORT: unique symbol;
|
|
35
35
|
/** The `NONE` symbol indicates something is nothing. */
|
|
36
36
|
export declare const NONE: unique symbol;
|
|
37
|
+
/** The `SKIP` symbol indicates something should be silently skipped. */
|
|
38
|
+
export declare const SKIP: unique symbol;
|
package/util/constants.js
CHANGED
|
@@ -30,7 +30,9 @@ export const NBSP = "\xA0";
|
|
|
30
30
|
export const THINSP = "\u2009";
|
|
31
31
|
/** Non-breaking narrow space (goes between numbers and their corresponding units). */
|
|
32
32
|
export const NNBSP = "\u202F";
|
|
33
|
-
/** The `
|
|
34
|
-
export const
|
|
33
|
+
/** The `ABORT` symbol indicates something was manually aborted. */
|
|
34
|
+
export const ABORT = Symbol("shelving/ABORT");
|
|
35
35
|
/** The `NONE` symbol indicates something is nothing. */
|
|
36
36
|
export const NONE = Symbol("shelving/NONE");
|
|
37
|
+
/** The `SKIP` symbol indicates something should be silently skipped. */
|
|
38
|
+
export const SKIP = Symbol("shelving/SKIP");
|
package/util/data.d.ts
CHANGED
|
@@ -84,9 +84,6 @@ export type FlatData<T extends NestedData> = Resolve<UnionToIntersection<T[keyof
|
|
|
84
84
|
export declare function isData(value: unknown): value is Data;
|
|
85
85
|
/** Assert that an unknown value is a data object. */
|
|
86
86
|
export declare function assertData(value: unknown, caller?: AnyCaller): asserts value is Data;
|
|
87
|
-
/** Convert a data object or set of `DataProp` props for that object back into the full object. */
|
|
88
|
-
export declare function getData<T extends Data>(input: T): T;
|
|
89
|
-
export declare function getData<T extends Data>(input: T | Iterable<DataProp<T>>): Partial<T>;
|
|
90
87
|
/** Is an unknown value the key for an own prop of a data object. */
|
|
91
88
|
export declare const isDataProp: <T extends Data>(data: T, key: unknown) => key is DataKey<T>;
|
|
92
89
|
/** Assert that an unknown value is the key for an own prop of a data object. */
|
package/util/data.js
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { RequiredError } from "../error/RequiredError.js";
|
|
2
|
-
import { isIterable } from "./iterate.js";
|
|
3
2
|
import { isObject, isPlainObject } from "./object.js";
|
|
4
3
|
/** Is an unknown value a data object? */
|
|
5
4
|
export function isData(value) {
|
|
@@ -10,9 +9,6 @@ export function assertData(value, caller = assertData) {
|
|
|
10
9
|
if (!isPlainObject(value))
|
|
11
10
|
throw new RequiredError("Must be data object", { received: value, caller });
|
|
12
11
|
}
|
|
13
|
-
export function getData(input) {
|
|
14
|
-
return isIterable(input) ? Object.fromEntries(input) : input;
|
|
15
|
-
}
|
|
16
12
|
/** Is an unknown value the key for an own prop of a data object. */
|
|
17
13
|
export const isDataProp = (data, key) => typeof key === "string" && Object.hasOwn(data, key);
|
|
18
14
|
/** Assert that an unknown value is the key for an own prop of a data object. */
|
package/util/dictionary.d.ts
CHANGED
|
@@ -18,7 +18,7 @@ export declare function isDictionary(value: unknown): value is ImmutableDictiona
|
|
|
18
18
|
/** Assert that an unknown value is a dictionary object */
|
|
19
19
|
export declare function assertDictionary(value: unknown, caller?: AnyCaller): asserts value is ImmutableDictionary;
|
|
20
20
|
/** Convert a possible dictionary into a dictionary. */
|
|
21
|
-
export declare function
|
|
21
|
+
export declare function requireDictionary<T>(dict: PossibleDictionary<T>): ImmutableDictionary<T>;
|
|
22
22
|
/** Turn a dictionary object into a set of props. */
|
|
23
23
|
export declare function getDictionaryItems<T>(input: ImmutableDictionary<T>): readonly DictionaryItem<T>[];
|
|
24
24
|
export declare function getDictionaryItems<T>(input: PossibleDictionary<T>): Iterable<DictionaryItem<T>>;
|
package/util/dictionary.js
CHANGED
|
@@ -12,7 +12,7 @@ export function assertDictionary(value, caller = assertDictionary) {
|
|
|
12
12
|
throw new ValueError("Must be dictionary object", { received: value, caller });
|
|
13
13
|
}
|
|
14
14
|
/** Convert a possible dictionary into a dictionary. */
|
|
15
|
-
export function
|
|
15
|
+
export function requireDictionary(dict) {
|
|
16
16
|
return isDictionary(dict) ? dict : Object.fromEntries(dict);
|
|
17
17
|
}
|
|
18
18
|
export function getDictionaryItems(input) {
|
package/util/path.d.ts
CHANGED
|
@@ -6,10 +6,12 @@ export type AbsolutePath = `/` | `/${string}`;
|
|
|
6
6
|
export type RelativePath = `.` | `./${string}` | `..` | `../${string}`;
|
|
7
7
|
/** Either an absolute path string or a relative path string. */
|
|
8
8
|
export type Path = AbsolutePath | RelativePath;
|
|
9
|
+
/** Things that can be converted to a path. */
|
|
10
|
+
export type PossiblePath = string | URL;
|
|
9
11
|
/** Is a string path an absolute path? */
|
|
10
|
-
export declare function isAbsolutePath(path:
|
|
12
|
+
export declare function isAbsolutePath(path: Path): path is AbsolutePath;
|
|
11
13
|
/** Is a string path an absolute path? */
|
|
12
|
-
export declare function isRelativePath(path:
|
|
14
|
+
export declare function isRelativePath(path: Path): path is RelativePath;
|
|
13
15
|
/**
|
|
14
16
|
* Resolve a relative or absolute path and return the absolute path, or `undefined` if not a valid path.
|
|
15
17
|
* - Uses `new URL` to do path processing, so URL strings can also be resolved.
|
|
@@ -19,7 +21,7 @@ export declare function isRelativePath(path: string): path is RelativePath;
|
|
|
19
21
|
* @param base Absolute path used for resolving relative paths in `possible`
|
|
20
22
|
* @return Absolute path with a leading trailing slash, e.g. `/a/c/b`
|
|
21
23
|
*/
|
|
22
|
-
export declare function getPath(value: Nullish<
|
|
24
|
+
export declare function getPath(value: Nullish<PossiblePath>, base?: AbsolutePath): AbsolutePath | undefined;
|
|
23
25
|
/**
|
|
24
26
|
* Resolve a relative or absolute path and return the path, or throw `RequiredError` if not a valid path.
|
|
25
27
|
* - Internally uses `new URL` to do path processing but shouldn't ever reveal that fact.
|
|
@@ -29,7 +31,7 @@ export declare function getPath(value: Nullish<string | URL>, base?: AbsolutePat
|
|
|
29
31
|
* @param base Absolute path used for resolving relative paths in `possible`
|
|
30
32
|
* @return Absolute path with a leading trailing slash, e.g. `/a/c/b`
|
|
31
33
|
*/
|
|
32
|
-
export declare function requirePath(value:
|
|
34
|
+
export declare function requirePath(value: PossiblePath, base?: AbsolutePath, caller?: AnyCaller): AbsolutePath;
|
|
33
35
|
/** Is a target path active? */
|
|
34
36
|
export declare function isPathActive(target: AbsolutePath, current: AbsolutePath): boolean;
|
|
35
37
|
/** Is a target path proud (i.e. is the current path, or is a child of the current path)? */
|
package/util/path.js
CHANGED
|
@@ -42,7 +42,7 @@ export function getPath(value, base) {
|
|
|
42
42
|
export function requirePath(value, base, caller = requirePath) {
|
|
43
43
|
const path = getPath(value, base);
|
|
44
44
|
if (!path)
|
|
45
|
-
throw new RequiredError("Invalid
|
|
45
|
+
throw new RequiredError("Invalid path", { received: value, caller });
|
|
46
46
|
return path;
|
|
47
47
|
}
|
|
48
48
|
/** Is a target path active? */
|
package/util/sequence.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { ABORT } from "./constants.js";
|
|
2
2
|
import type { ErrorCallback, ValueCallback } from "./function.js";
|
|
3
3
|
export interface IteratorAbortResult<R> {
|
|
4
|
-
done: typeof
|
|
4
|
+
done: typeof ABORT;
|
|
5
5
|
value: R;
|
|
6
6
|
}
|
|
7
7
|
/** An extension of */
|
package/util/sequence.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { UnexpectedError } from "../error/UnexpectedError.js";
|
|
2
2
|
import { getDeferred, getDelay } from "./async.js";
|
|
3
|
-
import {
|
|
3
|
+
import { ABORT } from "./constants.js";
|
|
4
4
|
/** Turn a `Promise<R>` into an `IteratorAbortResult<R>` */
|
|
5
5
|
async function _awaitAbort(value) {
|
|
6
|
-
return { done:
|
|
6
|
+
return { done: ABORT, value: await value };
|
|
7
7
|
}
|
|
8
8
|
/** Call an iterator's `return()` method (if it exists) with an initial value, and return the `value` it returns. */
|
|
9
9
|
async function _iteratorReturn(iterator, initial, caller) {
|
|
@@ -35,7 +35,7 @@ export async function* repeatUntil(source, ...signals) {
|
|
|
35
35
|
]);
|
|
36
36
|
if (done) {
|
|
37
37
|
// For aborts, tell the iterator we're no longer using it.
|
|
38
|
-
if (done ===
|
|
38
|
+
if (done === ABORT)
|
|
39
39
|
return _iteratorReturn(iterator, value, repeatUntil);
|
|
40
40
|
// Don't need to do this for `done: true` results from the iterator, because we assume the iterator stopped itself.
|
|
41
41
|
return value;
|
|
@@ -81,7 +81,7 @@ export async function* callSequence(sequence, callback) {
|
|
|
81
81
|
export function runSequence(sequence, onNext, onError, onReturn) {
|
|
82
82
|
const { promise, resolve } = getDeferred();
|
|
83
83
|
void _runSequenceIterator(sequence[Symbol.asyncIterator](), promise, onNext, onError, onReturn);
|
|
84
|
-
return (value) => resolve({ done:
|
|
84
|
+
return (value) => resolve({ done: ABORT, value });
|
|
85
85
|
}
|
|
86
86
|
async function _runSequenceIterator(iterator, stopped, onNext, onError, onReturn) {
|
|
87
87
|
let n;
|
|
@@ -90,7 +90,7 @@ async function _runSequenceIterator(iterator, stopped, onNext, onError, onReturn
|
|
|
90
90
|
const { done, value } = await Promise.race([stopped, iterator.next(n)]);
|
|
91
91
|
if (done) {
|
|
92
92
|
// For manual aborts tell the iterator we're no longer using it.
|
|
93
|
-
if (done ===
|
|
93
|
+
if (done === ABORT) {
|
|
94
94
|
const v = await _iteratorReturn(iterator, value, runSequence);
|
|
95
95
|
return onReturn?.(v);
|
|
96
96
|
}
|