shelving 1.68.4 → 1.69.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/observe/Observable.d.ts +4 -0
- package/observe/Observable.js +0 -3
- package/observe/Observer.d.ts +4 -4
- package/observe/Subject.d.ts +5 -5
- package/observe/Subject.js +23 -17
- package/package.json +1 -1
- package/react/useSubscribe.js +8 -1
- package/state/SelfClosingState.js +5 -5
- package/util/async.js +3 -3
- package/util/timeout.d.ts +5 -2
- package/util/timeout.js +21 -9
package/observe/Observable.d.ts
CHANGED
|
@@ -6,6 +6,8 @@ export declare type Unsubscribe = () => void;
|
|
|
6
6
|
export interface Observable<T> {
|
|
7
7
|
/** Subscribe an observer to this observable. */
|
|
8
8
|
subscribe(observer: PartialObserver<T> | Dispatch<[T]>): Unsubscribe;
|
|
9
|
+
/** Is this observable closed? */
|
|
10
|
+
readonly closed?: boolean;
|
|
9
11
|
}
|
|
10
12
|
/** Subscribe function is a function that initiates a subscription to an observer. */
|
|
11
13
|
export declare type Subscribe<T> = (observer: PartialObserver<T>) => Unsubscribe;
|
|
@@ -17,4 +19,6 @@ export declare function subscribe<T>(source: Subscribable<T>, target: PartialObs
|
|
|
17
19
|
export interface Connectable<T> {
|
|
18
20
|
/** Subscribe this entity to a subscribable. */
|
|
19
21
|
connect(subscribable: Subscribable<T>): Unsubscribe;
|
|
22
|
+
/** Is this observable closed? */
|
|
23
|
+
readonly closed?: boolean;
|
|
20
24
|
}
|
package/observe/Observable.js
CHANGED
|
@@ -1,7 +1,4 @@
|
|
|
1
|
-
import { ConditionError } from "../error/ConditionError.js";
|
|
2
1
|
/** Start a subscription to a `Subscribable` and return the `Unsubscriber` function. */
|
|
3
2
|
export function subscribe(source, target) {
|
|
4
|
-
if (target.closed)
|
|
5
|
-
throw new ConditionError("Target is closed");
|
|
6
3
|
return typeof source === "function" ? source(target) : source.subscribe(target);
|
|
7
4
|
}
|
package/observe/Observer.d.ts
CHANGED
|
@@ -8,13 +8,13 @@ import type { Connectable } from "./Observable.js";
|
|
|
8
8
|
* - Compatible with https://github.com/tc39/proposal-observable/
|
|
9
9
|
*/
|
|
10
10
|
export interface Observer<T> {
|
|
11
|
-
/** Send the next value to this
|
|
11
|
+
/** Send the next value to this observer. */
|
|
12
12
|
readonly next: Dispatch<[T]>;
|
|
13
|
-
/** End this
|
|
13
|
+
/** End this observer with an error. */
|
|
14
14
|
readonly error: Handler;
|
|
15
|
-
/** End this
|
|
15
|
+
/** End this observer with success. */
|
|
16
16
|
readonly complete: Dispatch;
|
|
17
|
-
/** Is this
|
|
17
|
+
/** Is this observer closed? */
|
|
18
18
|
readonly closed?: boolean;
|
|
19
19
|
}
|
|
20
20
|
/** Partial observer is an observer missing one or more of its callbacks. */
|
package/observe/Subject.d.ts
CHANGED
|
@@ -9,7 +9,7 @@ import { Observable, Subscribable, Unsubscribe } from "./Observable.js";
|
|
|
9
9
|
*/
|
|
10
10
|
export declare class Subject<T> implements Observable<T>, ConnectableObserver<T> {
|
|
11
11
|
/** List of sources this subject is subscribed to. */
|
|
12
|
-
protected readonly
|
|
12
|
+
protected readonly _connections: Set<Unsubscribe>;
|
|
13
13
|
/** List of subscribed observers that values are forwarded to. */
|
|
14
14
|
protected readonly _subscribers: Set<Partial<import("./Observer.js").Observer<T>>>;
|
|
15
15
|
/** Get the number of current subscribers. */
|
|
@@ -24,17 +24,17 @@ export declare class Subject<T> implements Observable<T>, ConnectableObserver<T>
|
|
|
24
24
|
error(reason: Error | unknown): void;
|
|
25
25
|
complete(): void;
|
|
26
26
|
/** Close this subject (called by `error()` and `complete()`). */
|
|
27
|
-
|
|
28
|
-
/** Connect this
|
|
27
|
+
protected _close(): void;
|
|
28
|
+
/** Connect this subject to a source. */
|
|
29
29
|
connect(source: Subscribable<T>): Unsubscribe;
|
|
30
30
|
/** Disconnect this subject from all sources. */
|
|
31
31
|
disconnect(): void;
|
|
32
32
|
/**
|
|
33
33
|
* Subscribe to this subject and return an unsubscriber function.
|
|
34
|
-
* - Allows either an `Observer` object or separate `next()
|
|
34
|
+
* - Allows either an `Observer` object or separate `next()", `error()` and `complete()` functions.
|
|
35
35
|
* - Implements `Observable`
|
|
36
36
|
*/
|
|
37
|
-
subscribe(
|
|
37
|
+
subscribe(target: PartialObserver<T> | Dispatch<[T]>): Unsubscribe;
|
|
38
38
|
/** Add an observer (called by `subscribe()`). */
|
|
39
39
|
protected _addObserver(observer: PartialObserver<T>): void;
|
|
40
40
|
/** Called after adding the first observer. */
|
package/observe/Subject.js
CHANGED
|
@@ -11,7 +11,7 @@ import { subscribe } from "./Observable.js";
|
|
|
11
11
|
export class Subject {
|
|
12
12
|
constructor() {
|
|
13
13
|
/** List of sources this subject is subscribed to. */
|
|
14
|
-
this.
|
|
14
|
+
this._connections = new Set();
|
|
15
15
|
/** List of subscribed observers that values are forwarded to. */
|
|
16
16
|
this._subscribers = new Set();
|
|
17
17
|
/** Is this subject open or closed (i.e. `error()` or `complete()` have been called. */
|
|
@@ -19,7 +19,7 @@ export class Subject {
|
|
|
19
19
|
}
|
|
20
20
|
/** Get the number of current subscribers. */
|
|
21
21
|
get connections() {
|
|
22
|
-
return this.
|
|
22
|
+
return this._connections.size;
|
|
23
23
|
}
|
|
24
24
|
/** Get the number of current subscribers. */
|
|
25
25
|
get subscribers() {
|
|
@@ -27,7 +27,7 @@ export class Subject {
|
|
|
27
27
|
}
|
|
28
28
|
next(value) {
|
|
29
29
|
if (this.closed)
|
|
30
|
-
throw new ConditionError(
|
|
30
|
+
throw new ConditionError(`Observer is closed`);
|
|
31
31
|
this._dispatch(value);
|
|
32
32
|
}
|
|
33
33
|
/** Call `next()` on the subscribers. */
|
|
@@ -37,7 +37,7 @@ export class Subject {
|
|
|
37
37
|
}
|
|
38
38
|
error(reason) {
|
|
39
39
|
if (this.closed)
|
|
40
|
-
throw new ConditionError(
|
|
40
|
+
throw new ConditionError(`Observer is closed`);
|
|
41
41
|
this._close();
|
|
42
42
|
for (const subscriber of this._subscribers) {
|
|
43
43
|
this._subscribers.delete(subscriber);
|
|
@@ -46,7 +46,7 @@ export class Subject {
|
|
|
46
46
|
}
|
|
47
47
|
complete() {
|
|
48
48
|
if (this.closed)
|
|
49
|
-
throw new ConditionError(
|
|
49
|
+
throw new ConditionError(`Observer is closed`);
|
|
50
50
|
this._close();
|
|
51
51
|
for (const subscriber of this._subscribers) {
|
|
52
52
|
this._subscribers.delete(subscriber);
|
|
@@ -58,38 +58,43 @@ export class Subject {
|
|
|
58
58
|
this.closed = true;
|
|
59
59
|
this.disconnect();
|
|
60
60
|
}
|
|
61
|
-
/** Connect this
|
|
61
|
+
/** Connect this subject to a source. */
|
|
62
62
|
connect(source) {
|
|
63
63
|
if (this.closed)
|
|
64
|
-
throw new ConditionError(
|
|
64
|
+
throw new ConditionError(`Connectable is closed`);
|
|
65
65
|
const unsubscribe = subscribe(source, this);
|
|
66
66
|
const cleanup = () => {
|
|
67
|
-
this.
|
|
67
|
+
this._connections.delete(cleanup);
|
|
68
68
|
dispatch(unsubscribe);
|
|
69
69
|
};
|
|
70
|
-
this.
|
|
70
|
+
this._connections.add(cleanup);
|
|
71
71
|
return cleanup;
|
|
72
72
|
}
|
|
73
73
|
/** Disconnect this subject from all sources. */
|
|
74
74
|
disconnect() {
|
|
75
|
-
for (const cleanup of this.
|
|
75
|
+
for (const cleanup of this._connections)
|
|
76
76
|
dispatch(cleanup); // Cleanups are self-cleaning.
|
|
77
77
|
}
|
|
78
78
|
/**
|
|
79
79
|
* Subscribe to this subject and return an unsubscriber function.
|
|
80
|
-
* - Allows either an `Observer` object or separate `next()
|
|
80
|
+
* - Allows either an `Observer` object or separate `next()", `error()` and `complete()` functions.
|
|
81
81
|
* - Implements `Observable`
|
|
82
82
|
*/
|
|
83
|
-
subscribe(
|
|
84
|
-
|
|
83
|
+
subscribe(target) {
|
|
84
|
+
if (this.closed)
|
|
85
|
+
throw new ConditionError(`Observable is closed`);
|
|
86
|
+
const observer = typeof target === `function` ? { next: target } : target;
|
|
87
|
+
if (observer.closed)
|
|
88
|
+
throw new ConditionError("Target is closed");
|
|
85
89
|
this._addObserver(observer);
|
|
86
90
|
return this._removeObserver.bind(this, observer);
|
|
87
91
|
}
|
|
88
92
|
/** Add an observer (called by `subscribe()`). */
|
|
89
93
|
_addObserver(observer) {
|
|
90
|
-
const
|
|
94
|
+
const sizeBefore = this._subscribers.size;
|
|
91
95
|
this._subscribers.add(observer);
|
|
92
|
-
|
|
96
|
+
const sizeAfter = this._subscribers.size;
|
|
97
|
+
if (!sizeBefore && sizeAfter)
|
|
93
98
|
this._addFirstObserver();
|
|
94
99
|
}
|
|
95
100
|
/** Called after adding the first observer. */
|
|
@@ -98,9 +103,10 @@ export class Subject {
|
|
|
98
103
|
}
|
|
99
104
|
/** Remove an observer. */
|
|
100
105
|
_removeObserver(observer) {
|
|
101
|
-
const
|
|
106
|
+
const sizeBefore = this._subscribers.size;
|
|
102
107
|
this._subscribers.delete(observer);
|
|
103
|
-
|
|
108
|
+
const sizeAfter = this._subscribers.size;
|
|
109
|
+
if (sizeBefore && !sizeAfter)
|
|
104
110
|
this._removeLastObserver();
|
|
105
111
|
}
|
|
106
112
|
/** Called after adding the first observer. */
|
package/package.json
CHANGED
package/react/useSubscribe.js
CHANGED
|
@@ -12,5 +12,12 @@ import { BLACKHOLE } from "../util/function.js";
|
|
|
12
12
|
*/
|
|
13
13
|
export function useSubscribe(subscribable) {
|
|
14
14
|
const setState = useState(subscribable instanceof State && !subscribable.loading ? subscribable.value : NOVALUE)[1];
|
|
15
|
-
useEffect(subscribable
|
|
15
|
+
useEffect(subscribable
|
|
16
|
+
? () => {
|
|
17
|
+
// If the subscribable is an observer, only subscribe if the subscribable isn't closed.
|
|
18
|
+
// Otherwise `subscribe()` is likely to throw a `Observer is closed` error.
|
|
19
|
+
if (typeof subscribable === "function" || !subscribable.closed)
|
|
20
|
+
return subscribe(subscribable, { next: setState, error: setState });
|
|
21
|
+
}
|
|
22
|
+
: BLACKHOLE, [subscribable]);
|
|
16
23
|
}
|
|
@@ -18,7 +18,10 @@ export class SelfClosingState extends State {
|
|
|
18
18
|
export class DelayedSelfClosingState extends State {
|
|
19
19
|
constructor(delay, ...args) {
|
|
20
20
|
super(...args);
|
|
21
|
-
this._timeout = new Timeout(
|
|
21
|
+
this._timeout = new Timeout(() => {
|
|
22
|
+
if (!this.closed)
|
|
23
|
+
this.complete();
|
|
24
|
+
}, delay);
|
|
22
25
|
}
|
|
23
26
|
// Override to clear the timeout when an observer is added.
|
|
24
27
|
_addFirstObserver() {
|
|
@@ -26,9 +29,6 @@ export class DelayedSelfClosingState extends State {
|
|
|
26
29
|
}
|
|
27
30
|
// Override to close this state when the last observer is removed.
|
|
28
31
|
_removeLastObserver() {
|
|
29
|
-
this._timeout.set(
|
|
30
|
-
if (!this.closed)
|
|
31
|
-
this.complete();
|
|
32
|
-
});
|
|
32
|
+
this._timeout.set();
|
|
33
33
|
}
|
|
34
34
|
}
|
package/util/async.js
CHANGED
|
@@ -69,7 +69,7 @@ export async function callAsyncParallel(callback, items, ...args) {
|
|
|
69
69
|
// Internal way for us to save `resolve()` and `reject()` from a new Promise used by `Deferred` and `ExtendablePromise`
|
|
70
70
|
let resolve; // eslint-disable-line @typescript-eslint/no-explicit-any
|
|
71
71
|
let reject;
|
|
72
|
-
function
|
|
72
|
+
function _saveResolveReject(x, // eslint-disable-line @typescript-eslint/no-explicit-any
|
|
73
73
|
y) {
|
|
74
74
|
resolve = x;
|
|
75
75
|
reject = y;
|
|
@@ -77,7 +77,7 @@ y) {
|
|
|
77
77
|
/** Type of `Promise` with its `resolve()` and `reject()` methods exposed publicly. */
|
|
78
78
|
export class Deferred extends Promise {
|
|
79
79
|
constructor() {
|
|
80
|
-
super(
|
|
80
|
+
super(_saveResolveReject);
|
|
81
81
|
this.resolve = resolve;
|
|
82
82
|
this.reject = reject;
|
|
83
83
|
}
|
|
@@ -90,7 +90,7 @@ export class Deferred extends Promise {
|
|
|
90
90
|
/** Type of `Promise` with `._resolve()` and `._reject()` methods available. */
|
|
91
91
|
export class AbstractPromise extends Promise {
|
|
92
92
|
constructor() {
|
|
93
|
-
super(
|
|
93
|
+
super(_saveResolveReject);
|
|
94
94
|
this._resolve = resolve;
|
|
95
95
|
this._reject = reject;
|
|
96
96
|
}
|
package/util/timeout.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { Dispatch } from "./function.js";
|
|
1
2
|
/**
|
|
2
3
|
* Create a new Timeout.
|
|
3
4
|
*
|
|
@@ -9,9 +10,10 @@
|
|
|
9
10
|
* @param ms The default delay for any created timeouts (in ms).
|
|
10
11
|
*/
|
|
11
12
|
export declare class Timeout {
|
|
13
|
+
private _callback;
|
|
12
14
|
private _ms;
|
|
13
15
|
private _timeout;
|
|
14
|
-
constructor(ms?: number);
|
|
16
|
+
constructor(callback?: Dispatch | null, ms?: number);
|
|
15
17
|
/** Is a timeout currently set? */
|
|
16
18
|
get exists(): boolean;
|
|
17
19
|
/**
|
|
@@ -19,7 +21,8 @@ export declare class Timeout {
|
|
|
19
21
|
* @param callback
|
|
20
22
|
* @param ms The delay for this timeout (in ms).
|
|
21
23
|
*/
|
|
22
|
-
set(callback
|
|
24
|
+
set(callback?: Dispatch | null, ms?: number): void;
|
|
25
|
+
private _run;
|
|
23
26
|
/** Cancel any existing timeout.. */
|
|
24
27
|
clear(): void;
|
|
25
28
|
}
|
package/util/timeout.js
CHANGED
|
@@ -9,8 +9,14 @@
|
|
|
9
9
|
* @param ms The default delay for any created timeouts (in ms).
|
|
10
10
|
*/
|
|
11
11
|
export class Timeout {
|
|
12
|
-
constructor(ms = 0) {
|
|
13
|
-
this._timeout =
|
|
12
|
+
constructor(callback = null, ms = 0) {
|
|
13
|
+
this._timeout = null;
|
|
14
|
+
this._run = () => {
|
|
15
|
+
this._timeout = null;
|
|
16
|
+
if (this._callback)
|
|
17
|
+
this._callback();
|
|
18
|
+
};
|
|
19
|
+
this._callback = callback;
|
|
14
20
|
this._ms = ms;
|
|
15
21
|
}
|
|
16
22
|
/** Is a timeout currently set? */
|
|
@@ -22,16 +28,22 @@ export class Timeout {
|
|
|
22
28
|
* @param callback
|
|
23
29
|
* @param ms The delay for this timeout (in ms).
|
|
24
30
|
*/
|
|
25
|
-
set(callback, ms = this._ms) {
|
|
31
|
+
set(callback = this._callback, ms = this._ms) {
|
|
26
32
|
this.clear();
|
|
27
|
-
this._timeout = setTimeout(
|
|
28
|
-
this._timeout = undefined;
|
|
29
|
-
callback();
|
|
30
|
-
}, ms);
|
|
33
|
+
this._timeout = setTimeout(_executeTimeout, ms, this, callback);
|
|
31
34
|
}
|
|
32
35
|
/** Cancel any existing timeout.. */
|
|
33
36
|
clear() {
|
|
34
|
-
|
|
35
|
-
|
|
37
|
+
const timeout = this._timeout;
|
|
38
|
+
if (timeout) {
|
|
39
|
+
this._timeout = null;
|
|
40
|
+
clearTimeout(timeout);
|
|
41
|
+
}
|
|
36
42
|
}
|
|
37
43
|
}
|
|
44
|
+
/** Actually execute the timeout. */
|
|
45
|
+
function _executeTimeout(timeout, callback) {
|
|
46
|
+
timeout.clear();
|
|
47
|
+
if (callback)
|
|
48
|
+
callback();
|
|
49
|
+
}
|