shelving 1.64.0 → 1.65.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.
Files changed (154) hide show
  1. package/api/Resource.js +2 -2
  2. package/db/Reference.d.ts +37 -23
  3. package/db/Reference.js +65 -33
  4. package/db/index.d.ts +0 -3
  5. package/db/index.js +0 -3
  6. package/error/ThroughError.d.ts +8 -0
  7. package/error/ThroughError.js +13 -0
  8. package/firestore/client/FirestoreClientProvider.d.ts +11 -10
  9. package/firestore/client/FirestoreClientProvider.js +18 -17
  10. package/firestore/lite/FirestoreLiteProvider.d.ts +10 -10
  11. package/firestore/lite/FirestoreLiteProvider.js +15 -14
  12. package/firestore/server/FirestoreServerProvider.d.ts +11 -10
  13. package/firestore/server/FirestoreServerProvider.js +18 -17
  14. package/index.d.ts +2 -1
  15. package/index.js +2 -1
  16. package/markup/rules.js +4 -4
  17. package/observe/AbstractObserver.d.ts +15 -0
  18. package/observe/AbstractObserver.js +42 -0
  19. package/observe/AsyncObserver.d.ts +5 -0
  20. package/observe/AsyncObserver.js +8 -0
  21. package/{stream/LastStream.d.ts → observe/LastSubject.d.ts} +2 -2
  22. package/observe/LastSubject.js +12 -0
  23. package/observe/MatchObserver.d.ts +9 -0
  24. package/observe/MatchObserver.js +12 -0
  25. package/observe/MatchableObserver.d.ts +7 -0
  26. package/observe/MatchableObserver.js +10 -0
  27. package/observe/Observable.d.ts +20 -0
  28. package/observe/Observable.js +7 -0
  29. package/observe/Observer.d.ts +31 -0
  30. package/observe/Observer.js +48 -0
  31. package/observe/OnceObserver.d.ts +5 -0
  32. package/observe/OnceObserver.js +8 -0
  33. package/observe/Subject.d.ts +46 -0
  34. package/observe/Subject.js +110 -0
  35. package/observe/ThroughObserver.d.ts +5 -0
  36. package/observe/ThroughObserver.js +8 -0
  37. package/observe/TransformObserver.d.ts +9 -0
  38. package/observe/TransformObserver.js +12 -0
  39. package/observe/TransformableObserver.d.ts +7 -0
  40. package/observe/TransformableObserver.js +8 -0
  41. package/observe/index.d.ts +13 -0
  42. package/observe/index.js +13 -0
  43. package/observe/util.d.ts +24 -0
  44. package/observe/util.js +34 -0
  45. package/package.json +1 -1
  46. package/provider/BatchProvider.d.ts +8 -8
  47. package/provider/BatchProvider.js +26 -31
  48. package/provider/CacheProvider.d.ts +12 -21
  49. package/provider/CacheProvider.js +40 -74
  50. package/provider/DebugProvider.d.ts +20 -0
  51. package/provider/DebugProvider.js +170 -0
  52. package/provider/MemoryProvider.d.ts +38 -24
  53. package/provider/MemoryProvider.js +141 -102
  54. package/provider/Provider.d.ts +23 -22
  55. package/provider/ThroughProvider.d.ts +20 -11
  56. package/provider/ThroughProvider.js +12 -12
  57. package/provider/ValidationProvider.d.ts +10 -9
  58. package/provider/ValidationProvider.js +31 -28
  59. package/provider/index.d.ts +1 -1
  60. package/provider/index.js +1 -1
  61. package/query/Filter.d.ts +1 -1
  62. package/query/Filter.js +4 -3
  63. package/query/Filters.d.ts +1 -1
  64. package/react/index.d.ts +0 -6
  65. package/react/index.js +3 -6
  66. package/react/useDocument.d.ts +31 -38
  67. package/react/useDocument.js +71 -76
  68. package/react/useInstance.d.ts +4 -7
  69. package/react/useInstance.js +6 -9
  70. package/react/useLazy.d.ts +5 -9
  71. package/react/useQuery.d.ts +48 -46
  72. package/react/useQuery.js +116 -87
  73. package/react/useReduce.d.ts +8 -1
  74. package/react/useReduce.js +1 -3
  75. package/react/useSubscribe.d.ts +5 -6
  76. package/react/useSubscribe.js +10 -11
  77. package/{stream → state}/ArrayState.d.ts +1 -1
  78. package/{stream → state}/ArrayState.js +8 -10
  79. package/{stream → state}/BooleanState.d.ts +1 -1
  80. package/{stream → state}/BooleanState.js +3 -5
  81. package/{stream → state}/DataState.d.ts +3 -3
  82. package/{stream → state}/DataState.js +6 -6
  83. package/{stream → state}/ObjectState.d.ts +1 -1
  84. package/{stream → state}/ObjectState.js +6 -8
  85. package/state/SelfClosingState.d.ts +18 -0
  86. package/state/SelfClosingState.js +34 -0
  87. package/state/State.d.ts +32 -0
  88. package/state/State.js +69 -0
  89. package/{stream → state}/index.d.ts +1 -4
  90. package/{stream → state}/index.js +1 -4
  91. package/util/array.d.ts +0 -8
  92. package/util/array.js +0 -4
  93. package/util/async.d.ts +4 -5
  94. package/util/async.js +3 -2
  95. package/util/clone.js +3 -2
  96. package/util/data.d.ts +7 -3
  97. package/util/data.js +1 -1
  98. package/util/entry.d.ts +1 -3
  99. package/util/equal.d.ts +4 -5
  100. package/util/filter.d.ts +1 -26
  101. package/util/filter.js +1 -25
  102. package/util/function.d.ts +5 -5
  103. package/util/function.js +3 -3
  104. package/util/hydrate.js +2 -2
  105. package/util/index.d.ts +1 -1
  106. package/util/index.js +1 -1
  107. package/util/iterate.d.ts +3 -9
  108. package/util/iterate.js +7 -11
  109. package/util/match.d.ts +20 -0
  110. package/util/match.js +14 -0
  111. package/util/object.d.ts +0 -19
  112. package/util/object.js +0 -8
  113. package/util/search.d.ts +1 -1
  114. package/util/sort.d.ts +4 -10
  115. package/util/sort.js +0 -11
  116. package/util/timeout.d.ts +2 -0
  117. package/util/timeout.js +8 -1
  118. package/util/transform.d.ts +41 -9
  119. package/util/transform.js +18 -4
  120. package/util/validate.d.ts +6 -10
  121. package/util/validate.js +1 -3
  122. package/api/errors.d.ts +0 -8
  123. package/api/errors.js +0 -9
  124. package/db/PaginationState.d.ts +0 -28
  125. package/db/PaginationState.js +0 -59
  126. package/db/errors.d.ts +0 -13
  127. package/db/errors.js +0 -17
  128. package/db/util.d.ts +0 -11
  129. package/db/util.js +0 -21
  130. package/provider/ErrorProvider.d.ts +0 -31
  131. package/provider/ErrorProvider.js +0 -175
  132. package/react/useCompare.d.ts +0 -3
  133. package/react/useCompare.js +0 -8
  134. package/react/useFetch.d.ts +0 -17
  135. package/react/useFetch.js +0 -41
  136. package/react/usePagination.d.ts +0 -8
  137. package/react/usePagination.js +0 -25
  138. package/react/usePureEffect.d.ts +0 -10
  139. package/react/usePureEffect.js +0 -17
  140. package/react/usePureState.d.ts +0 -11
  141. package/react/usePureState.js +0 -16
  142. package/react/useState.d.ts +0 -39
  143. package/react/useState.js +0 -65
  144. package/stream/LastStream.js +0 -12
  145. package/stream/LazyState.d.ts +0 -11
  146. package/stream/LazyState.js +0 -28
  147. package/stream/LazyStream.d.ts +0 -12
  148. package/stream/LazyStream.js +0 -28
  149. package/stream/State.d.ts +0 -46
  150. package/stream/State.js +0 -66
  151. package/stream/Stream.d.ts +0 -66
  152. package/stream/Stream.js +0 -122
  153. package/util/observe.d.ts +0 -103
  154. package/util/observe.js +0 -147
@@ -5,7 +5,7 @@ import { ArrayUpdate } from "../../update/ArrayUpdate.js";
5
5
  import { DataUpdate } from "../../update/DataUpdate.js";
6
6
  import { Increment } from "../../update/Increment.js";
7
7
  import { ObjectUpdate } from "../../update/ObjectUpdate.js";
8
- import { dispatchError, dispatchNext } from "../../util/observe.js";
8
+ import { dispatchError, dispatchNext } from "../../observe/Observer.js";
9
9
  // Constants.
10
10
  // const ID = "__name__"; // DH: `__name__` is the entire path of the document. `__id__` is just ID.
11
11
  const ID = "__id__"; // Internal way Firestore Queries can reference the ID of the current document.
@@ -46,13 +46,14 @@ function getQuery(firestore, ref) {
46
46
  query = query.limit(limit);
47
47
  return query;
48
48
  }
49
- /** Create a set of results from a collection snapshot. */
50
- function* getResults(snapshot) {
51
- for (const s of snapshot.docs)
52
- yield { ...s.data(), id: s.id };
49
+ function getEntities(snapshot) {
50
+ return snapshot.docs.map(getEntity);
53
51
  }
54
- /** Get a result from a document snapshot. */
55
- function getResult(snapshot) {
52
+ function getEntity(snapshot) {
53
+ const data = snapshot.data();
54
+ return { ...data, id: snapshot.id };
55
+ }
56
+ function getOptionalEntity(snapshot) {
56
57
  const data = snapshot.data();
57
58
  return data ? { ...data, id: snapshot.id } : null;
58
59
  }
@@ -86,30 +87,30 @@ export class FirestoreServerProvider extends Provider {
86
87
  super();
87
88
  this.firestore = firestore;
88
89
  }
89
- async get(ref) {
90
- return getResult(await getDocument(this.firestore, ref).get());
90
+ async getDocument(ref) {
91
+ return getOptionalEntity(await getDocument(this.firestore, ref).get());
91
92
  }
92
- subscribe(ref, observer) {
93
- return getDocument(this.firestore, ref).onSnapshot(snapshot => dispatchNext(observer, getResult(snapshot)), thrown => dispatchError(observer, thrown));
93
+ subscribeDocument(ref, observer) {
94
+ return getDocument(this.firestore, ref).onSnapshot(snapshot => dispatchNext(observer, getOptionalEntity(snapshot)), thrown => dispatchError(observer, thrown));
94
95
  }
95
- async add(ref, data) {
96
+ async addDocument(ref, data) {
96
97
  return (await getCollection(this.firestore, ref).add(data)).id;
97
98
  }
98
- async set(ref, data) {
99
+ async setDocument(ref, data) {
99
100
  await getDocument(this.firestore, ref).set(data);
100
101
  }
101
- async update(ref, update) {
102
+ async updateDocument(ref, update) {
102
103
  const fieldValues = Object.fromEntries(yieldFieldValues(update));
103
104
  await getDocument(this.firestore, ref).update(fieldValues);
104
105
  }
105
- async delete(ref) {
106
+ async deleteDocument(ref) {
106
107
  await getDocument(this.firestore, ref).delete();
107
108
  }
108
109
  async getQuery(ref) {
109
- return getResults(await getQuery(this.firestore, ref).get());
110
+ return getEntities(await getQuery(this.firestore, ref).get());
110
111
  }
111
112
  subscribeQuery(ref, observer) {
112
- return getQuery(this.firestore, ref).onSnapshot(snapshot => dispatchNext(observer, getResults(snapshot)), thrown => dispatchError(observer, thrown));
113
+ return getQuery(this.firestore, ref).onSnapshot(snapshot => dispatchNext(observer, getEntities(snapshot)), thrown => dispatchError(observer, thrown));
113
114
  }
114
115
  async setQuery(ref, data) {
115
116
  return await bulkWrite(this.firestore, ref, (w, s) => void w.set(s.ref, data));
package/index.d.ts CHANGED
@@ -11,6 +11,7 @@ export * from "./api/index.js";
11
11
  export * from "./error/index.js";
12
12
  export * from "./feedback/index.js";
13
13
  export * from "./markup/index.js";
14
- export * from "./stream/index.js";
14
+ export * from "./observe/index.js";
15
+ export * from "./state/index.js";
15
16
  export * from "./update/index.js";
16
17
  export * from "./util/index.js";
package/index.js CHANGED
@@ -13,7 +13,8 @@ export * from "./api/index.js";
13
13
  export * from "./error/index.js";
14
14
  export * from "./feedback/index.js";
15
15
  export * from "./markup/index.js";
16
- export * from "./stream/index.js";
16
+ export * from "./observe/index.js";
17
+ export * from "./state/index.js";
17
18
  export * from "./update/index.js";
18
19
  export * from "./util/index.js";
19
20
  // Integrations.
package/markup/rules.js CHANGED
@@ -39,14 +39,14 @@ const UNORDERED = `[${BULLETS}] +`; // Anything that can be a bullet (used for u
39
39
  export const UNORDERED_LIST_RULE = {
40
40
  regexp: getBlockRegExp(`${UNORDERED}(${MATCH_BLOCK.source})`),
41
41
  render: ([, list = ""]) => {
42
- const children = list.split(SPLIT_UL_ITEMS).map(mapUnorderedItem);
42
+ const children = list.split(SPLIT_UL_ITEMS).map(_mapUnorderedItem);
43
43
  return { type: "ul", key: null, props: { children } };
44
44
  },
45
45
  contexts: ["block", "list"],
46
46
  childContext: "list",
47
47
  };
48
48
  const SPLIT_UL_ITEMS = new RegExp(`\\n+${UNORDERED}`, "g");
49
- const mapUnorderedItem = (item, key) => {
49
+ const _mapUnorderedItem = (item, key) => {
50
50
  const children = item.replace(MATCH_INDENT, "");
51
51
  return { type: "li", key, props: { children } };
52
52
  };
@@ -59,14 +59,14 @@ const ORDERED = "[0-9]+[.):] +"; // Number for a numbered list (e.g. `1.` or `2)
59
59
  export const ORDERED_LIST_RULE = {
60
60
  regexp: getBlockRegExp(`(${ORDERED}${MATCH_BLOCK.source})`),
61
61
  render: ([, list = ""]) => {
62
- const children = list.split(SPLIT_OL_ITEMS).map(mapOrderedItem);
62
+ const children = list.split(SPLIT_OL_ITEMS).map(_mapOrderedItem);
63
63
  return { type: "ol", key: null, props: { children } };
64
64
  },
65
65
  contexts: ["block", "list"],
66
66
  childContext: "list",
67
67
  };
68
68
  const SPLIT_OL_ITEMS = new RegExp(`\\n+(?=${ORDERED})`, "g");
69
- const mapOrderedItem = (item, key) => {
69
+ const _mapOrderedItem = (item, key) => {
70
70
  const firstSpace = item.indexOf(" ");
71
71
  const value = parseInt(item.slice(0, firstSpace), 10);
72
72
  const children = item
@@ -0,0 +1,15 @@
1
+ import { Subscribable, Unsubscribe } from "./Observable.js";
2
+ import { PartialObserver, ConnectableObserver } from "./Observer.js";
3
+ /** Abstract observer designed to pass values through to an observer. */
4
+ export declare abstract class AbstractObserver<I, O> implements ConnectableObserver<I> {
5
+ private _target;
6
+ private _cleanup;
7
+ get closed(): boolean;
8
+ get target(): PartialObserver<O>;
9
+ constructor(target: PartialObserver<O>);
10
+ connect(subscribable: Subscribable<I>): Unsubscribe;
11
+ disconnect(): void;
12
+ abstract next(value: I): void;
13
+ error(reason: Error | unknown): void;
14
+ complete(): void;
15
+ }
@@ -0,0 +1,42 @@
1
+ import { dispatch } from "../util/function.js";
2
+ import { ConditionError } from "../error/ConditionError.js";
3
+ import { subscribe } from "./Observable.js";
4
+ import { dispatchError, dispatchComplete } from "./Observer.js";
5
+ /** Abstract observer designed to pass values through to an observer. */
6
+ export class AbstractObserver {
7
+ constructor(target) {
8
+ this._target = target;
9
+ }
10
+ get closed() {
11
+ return !this._target;
12
+ }
13
+ get target() {
14
+ if (!this._target)
15
+ throw new ConditionError("Observer is closed");
16
+ return this._target;
17
+ }
18
+ connect(subscribable) {
19
+ if (!this._target)
20
+ throw new ConditionError("Observer is closed");
21
+ if (this._cleanup)
22
+ throw new ConditionError("Observer already connected");
23
+ this._cleanup = subscribe(subscribable, this);
24
+ return this.disconnect.bind(this);
25
+ }
26
+ disconnect() {
27
+ if (this._cleanup)
28
+ this._cleanup = void dispatch(this._cleanup);
29
+ }
30
+ error(reason) {
31
+ const target = this.target;
32
+ this._target = undefined; // Close this observer.
33
+ this.disconnect();
34
+ dispatchError(target, reason);
35
+ }
36
+ complete() {
37
+ const target = this.target;
38
+ this._target = undefined; // Close this observer.
39
+ this.disconnect();
40
+ dispatchComplete(target);
41
+ }
42
+ }
@@ -0,0 +1,5 @@
1
+ import { AbstractObserver } from "./AbstractObserver.js";
2
+ /** Observer that allows promised values to be passed to `next()`. */
3
+ export declare class AsyncObserver<T> extends AbstractObserver<PromiseLike<T>, T> {
4
+ next(value: PromiseLike<T>): void;
5
+ }
@@ -0,0 +1,8 @@
1
+ import { AbstractObserver } from "./AbstractObserver.js";
2
+ import { dispatchAsyncNext } from "./Observer.js";
3
+ /** Observer that allows promised values to be passed to `next()`. */
4
+ export class AsyncObserver extends AbstractObserver {
5
+ next(value) {
6
+ dispatchAsyncNext(this.target, value);
7
+ }
8
+ }
@@ -1,5 +1,5 @@
1
- import { Stream } from "./Stream.js";
1
+ import { Subject } from "./Subject.js";
2
2
  /** Stream that only calls its most recently added subscriber. */
3
- export declare class LastStream<T> extends Stream<T> {
3
+ export declare class LastSubject<T> extends Subject<T> {
4
4
  protected _dispatch(value: T): void;
5
5
  }
@@ -0,0 +1,12 @@
1
+ import { getLastItem } from "../util/array.js";
2
+ import { dispatchNext } from "./Observer.js";
3
+ import { Subject } from "./Subject.js";
4
+ /** Stream that only calls its most recently added subscriber. */
5
+ export class LastSubject extends Subject {
6
+ // Override to dispatch only to a slice of the subscribers.
7
+ _dispatch(value) {
8
+ const observer = getLastItem(this._subscribers);
9
+ if (observer)
10
+ dispatchNext(observer, value);
11
+ }
12
+ }
@@ -0,0 +1,9 @@
1
+ import { Matcher } from "../util/match.js";
2
+ import { MatchableObserver } from "./MatchableObserver.js";
3
+ import { PartialObserver } from "./Observer.js";
4
+ /** Observer that filters is next value with a matcher. */
5
+ export declare class MatchObserver<T> extends MatchableObserver<T> {
6
+ protected _matcher: Matcher<T, void>;
7
+ constructor(matcher: Matcher<T, void>, target: PartialObserver<T>);
8
+ match(value: T): boolean;
9
+ }
@@ -0,0 +1,12 @@
1
+ import { match } from "../util/match.js";
2
+ import { MatchableObserver } from "./MatchableObserver.js";
3
+ /** Observer that filters is next value with a matcher. */
4
+ export class MatchObserver extends MatchableObserver {
5
+ constructor(matcher, target) {
6
+ super(target);
7
+ this._matcher = matcher;
8
+ }
9
+ match(value) {
10
+ return match(value, this._matcher);
11
+ }
12
+ }
@@ -0,0 +1,7 @@
1
+ import { Matchable } from "../util/match.js";
2
+ import { AbstractObserver } from "./AbstractObserver.js";
3
+ /** Observer implementing `Matchable` that implements a `match()` property that is called filter the next value before dispatching it. */
4
+ export declare abstract class MatchableObserver<T> extends AbstractObserver<T, T> implements Matchable<T, void> {
5
+ next(value: T): void;
6
+ abstract match(value: T): boolean;
7
+ }
@@ -0,0 +1,10 @@
1
+ import { AbstractObserver } from "./AbstractObserver.js";
2
+ import { dispatchNext } from "./Observer.js";
3
+ /** Observer implementing `Matchable` that implements a `match()` property that is called filter the next value before dispatching it. */
4
+ export class MatchableObserver extends AbstractObserver {
5
+ next(value) {
6
+ const target = this.target;
7
+ if (this.match(value))
8
+ dispatchNext(target, value);
9
+ }
10
+ }
@@ -0,0 +1,20 @@
1
+ import type { Dispatch } from "../util/function.js";
2
+ import type { PartialObserver } from "./Observer.js";
3
+ /** Function that ends a subscription. */
4
+ export declare type Unsubscribe = () => void;
5
+ /** An object that can subscribed to. */
6
+ export interface Observable<T> {
7
+ /** Subscribe an observer to this observable. */
8
+ subscribe(observer: PartialObserver<T> | Dispatch<[T]>): Unsubscribe;
9
+ }
10
+ /** Subscribe function is a function that initiates a subscription to an observer. */
11
+ export declare type Subscribe<T> = (observer: PartialObserver<T>) => Unsubscribe;
12
+ /** Subscribable is either an observable object or a subscribe function. */
13
+ export declare type Subscribable<T> = Observable<T> | Subscribe<T>;
14
+ /** Start a subscription to a `Subscribable` and return the `Unsubscriber` function. */
15
+ export declare function subscribe<T>(source: Subscribable<T>, target: PartialObserver<T>): Unsubscribe;
16
+ /** An object that can be connected to a subscribable. */
17
+ export interface Connectable<T> {
18
+ /** Subscribe this entity to a subscribable. */
19
+ connect(subscribable: Subscribable<T>): Unsubscribe;
20
+ }
@@ -0,0 +1,7 @@
1
+ import { ConditionError } from "../error/ConditionError.js";
2
+ /** Start a subscription to a `Subscribable` and return the `Unsubscriber` function. */
3
+ export function subscribe(source, target) {
4
+ if (target.closed)
5
+ throw new ConditionError("Target is closed");
6
+ return typeof source === "function" ? source(target) : source.subscribe(target);
7
+ }
@@ -0,0 +1,31 @@
1
+ import type { Dispatch } from "../util/function.js";
2
+ import { Handler } from "../util/error.js";
3
+ import type { Connectable } from "./Observable.js";
4
+ /**
5
+ * Observer
6
+ * - An Observer is used to receive data from an Observable, and is supplied as an argument to subscribe.
7
+ * - All methods are optional.
8
+ * - Compatible with https://github.com/tc39/proposal-observable/
9
+ */
10
+ export interface Observer<T> {
11
+ /** Send the next value to this object. */
12
+ readonly next: Dispatch<[T]>;
13
+ /** End this object with an error. */
14
+ readonly error: Handler;
15
+ /** End this object with success. */
16
+ readonly complete: Dispatch;
17
+ /** Is this object closed? */
18
+ readonly closed?: boolean;
19
+ }
20
+ /** Partial observer is an observer missing one or more of its callbacks. */
21
+ export declare type PartialObserver<T> = Partial<Observer<T>>;
22
+ /** Connectable observer is an observer that can connect to a subscribable source. */
23
+ export declare type ConnectableObserver<T> = Observer<T> & Connectable<T>;
24
+ /** Dispatch the next value to an observer (and if the next value errors log the error). */
25
+ export declare function dispatchNext<T>(observer: PartialObserver<T>, value: T): void;
26
+ /** Dispatch the next value to an observer (and if the next value errors log the error). */
27
+ export declare function dispatchAsyncNext<T>(observer: PartialObserver<T>, value: PromiseLike<T>): void;
28
+ /** Dispatch a complete call an observer (and if the next value errors log the error). */
29
+ export declare function dispatchComplete<T>(observer: PartialObserver<T>): void;
30
+ /** Dispatch an error value to an observer. */
31
+ export declare function dispatchError<T>(observer: PartialObserver<T>, reason: Error | unknown): void;
@@ -0,0 +1,48 @@
1
+ import { logError } from "../util/error.js";
2
+ /** Dispatch the next value to an observer (and if the next value errors log the error). */
3
+ export function dispatchNext(observer, value) {
4
+ if (!observer.next)
5
+ return;
6
+ try {
7
+ observer.next(value);
8
+ }
9
+ catch (thrown) {
10
+ logError(thrown);
11
+ }
12
+ }
13
+ /** Dispatch the next value to an observer (and if the next value errors log the error). */
14
+ export function dispatchAsyncNext(observer, value) {
15
+ if (!observer.next)
16
+ return;
17
+ void _dispatchAsyncNext(observer, value);
18
+ }
19
+ async function _dispatchAsyncNext(observer, value) {
20
+ try {
21
+ dispatchNext(observer, await value);
22
+ }
23
+ catch (reason) {
24
+ dispatchError(observer, reason);
25
+ }
26
+ }
27
+ /** Dispatch a complete call an observer (and if the next value errors log the error). */
28
+ export function dispatchComplete(observer) {
29
+ if (!observer.complete)
30
+ return;
31
+ try {
32
+ observer.complete();
33
+ }
34
+ catch (thrown) {
35
+ logError(thrown);
36
+ }
37
+ }
38
+ /** Dispatch an error value to an observer. */
39
+ export function dispatchError(observer, reason) {
40
+ if (!observer.error)
41
+ return;
42
+ try {
43
+ observer.error(reason);
44
+ }
45
+ catch (thrown) {
46
+ logError(thrown);
47
+ }
48
+ }
@@ -0,0 +1,5 @@
1
+ import { ThroughObserver } from "./ThroughObserver.js";
2
+ /** Observer that fires once then ends itself. */
3
+ export declare class OnceObserver<T> extends ThroughObserver<T> {
4
+ next(value: T): void;
5
+ }
@@ -0,0 +1,8 @@
1
+ import { ThroughObserver } from "./ThroughObserver.js";
2
+ /** Observer that fires once then ends itself. */
3
+ export class OnceObserver extends ThroughObserver {
4
+ next(value) {
5
+ super.next(value);
6
+ this.complete();
7
+ }
8
+ }
@@ -0,0 +1,46 @@
1
+ import { Dispatch } from "../util/function.js";
2
+ import { ConnectableObserver, PartialObserver } from "./Observer.js";
3
+ import { Observable, Subscribable, Unsubscribe } from "./Observable.js";
4
+ /**
5
+ * Simple subject
6
+ * - Subject combines `Observer` and `Observable`.
7
+ * - Multiple observers can subscribe and values are multicase to all of them.
8
+ * - Does no deriving (input and output types are the same).
9
+ */
10
+ export declare class Subject<T> implements Observable<T>, ConnectableObserver<T> {
11
+ /** List of sources this subject is subscribed to. */
12
+ protected readonly _cleanups: Set<Unsubscribe>;
13
+ /** List of subscribed observers that values are forwarded to. */
14
+ protected readonly _subscribers: Set<Partial<import("./Observer.js").Observer<T>>>;
15
+ /** Get the number of current subscribers. */
16
+ get connections(): number;
17
+ /** Get the number of current subscribers. */
18
+ get subscribers(): number;
19
+ /** Is this subject open or closed (i.e. `error()` or `complete()` have been called. */
20
+ readonly closed: boolean;
21
+ next(value: T): void;
22
+ /** Call `next()` on the subscribers. */
23
+ protected _dispatch(value: T): void;
24
+ error(reason: Error | unknown): void;
25
+ complete(): void;
26
+ /** Close this subject (called by `error()` and `complete()`). */
27
+ private _close;
28
+ /** Connect this subjet to a source. */
29
+ connect(source: Subscribable<T>): Unsubscribe;
30
+ /** Disconnect this subject from all sources. */
31
+ disconnect(): void;
32
+ /**
33
+ * Subscribe to this subject and return an unsubscriber function.
34
+ * - Allows either an `Observer` object or separate `next()`, `error()` and `complete()` functions.
35
+ * - Implements `Observable`
36
+ */
37
+ subscribe(next: PartialObserver<T> | Dispatch<[T]>): Unsubscribe;
38
+ /** Add an observer (called by `subscribe()`). */
39
+ protected _addObserver(observer: PartialObserver<T>): void;
40
+ /** Called after adding the first observer. */
41
+ protected _addFirstObserver(): void;
42
+ /** Remove an observer. */
43
+ protected _removeObserver(observer: PartialObserver<T>): void;
44
+ /** Called after adding the first observer. */
45
+ protected _removeLastObserver(): void;
46
+ }
@@ -0,0 +1,110 @@
1
+ import { ConditionError } from "../error/ConditionError.js";
2
+ import { dispatch } from "../util/function.js";
3
+ import { dispatchComplete, dispatchError, dispatchNext } from "./Observer.js";
4
+ import { subscribe } from "./Observable.js";
5
+ /**
6
+ * Simple subject
7
+ * - Subject combines `Observer` and `Observable`.
8
+ * - Multiple observers can subscribe and values are multicase to all of them.
9
+ * - Does no deriving (input and output types are the same).
10
+ */
11
+ export class Subject {
12
+ constructor() {
13
+ /** List of sources this subject is subscribed to. */
14
+ this._cleanups = new Set();
15
+ /** List of subscribed observers that values are forwarded to. */
16
+ this._subscribers = new Set();
17
+ /** Is this subject open or closed (i.e. `error()` or `complete()` have been called. */
18
+ this.closed = false;
19
+ }
20
+ /** Get the number of current subscribers. */
21
+ get connections() {
22
+ return this._cleanups.size;
23
+ }
24
+ /** Get the number of current subscribers. */
25
+ get subscribers() {
26
+ return this._subscribers.size;
27
+ }
28
+ next(value) {
29
+ if (this.closed)
30
+ throw new ConditionError("Subject is closed");
31
+ this._dispatch(value);
32
+ }
33
+ /** Call `next()` on the subscribers. */
34
+ _dispatch(value) {
35
+ for (const observer of this._subscribers)
36
+ dispatchNext(observer, value);
37
+ }
38
+ error(reason) {
39
+ if (this.closed)
40
+ throw new ConditionError("Subject is closed");
41
+ this._close();
42
+ for (const subscriber of this._subscribers) {
43
+ this._subscribers.delete(subscriber);
44
+ dispatchError(subscriber, reason);
45
+ }
46
+ }
47
+ complete() {
48
+ if (this.closed)
49
+ throw new ConditionError("Subject is closed");
50
+ this._close();
51
+ for (const subscriber of this._subscribers) {
52
+ this._subscribers.delete(subscriber);
53
+ dispatchComplete(subscriber);
54
+ }
55
+ }
56
+ /** Close this subject (called by `error()` and `complete()`). */
57
+ _close() {
58
+ this.closed = true;
59
+ this.disconnect();
60
+ }
61
+ /** Connect this subjet to a source. */
62
+ connect(source) {
63
+ if (this.closed)
64
+ throw new ConditionError("Subject is closed");
65
+ const unsubscribe = subscribe(source, this);
66
+ const cleanup = () => {
67
+ this._cleanups.delete(cleanup);
68
+ dispatch(unsubscribe);
69
+ };
70
+ this._cleanups.add(cleanup);
71
+ return cleanup;
72
+ }
73
+ /** Disconnect this subject from all sources. */
74
+ disconnect() {
75
+ for (const cleanup of this._cleanups)
76
+ dispatch(cleanup); // Cleanups are self-cleaning.
77
+ }
78
+ /**
79
+ * Subscribe to this subject and return an unsubscriber function.
80
+ * - Allows either an `Observer` object or separate `next()`, `error()` and `complete()` functions.
81
+ * - Implements `Observable`
82
+ */
83
+ subscribe(next) {
84
+ const observer = typeof next === "function" ? { next } : next;
85
+ this._addObserver(observer);
86
+ return this._removeObserver.bind(this, observer);
87
+ }
88
+ /** Add an observer (called by `subscribe()`). */
89
+ _addObserver(observer) {
90
+ const size = this._subscribers.size;
91
+ this._subscribers.add(observer);
92
+ if (!size && this._subscribers.size)
93
+ this._addFirstObserver();
94
+ }
95
+ /** Called after adding the first observer. */
96
+ _addFirstObserver() {
97
+ //
98
+ }
99
+ /** Remove an observer. */
100
+ _removeObserver(observer) {
101
+ const size = this._subscribers.size;
102
+ this._subscribers.delete(observer);
103
+ if (size && !this._subscribers.size)
104
+ this._removeLastObserver();
105
+ }
106
+ /** Called after adding the first observer. */
107
+ _removeLastObserver() {
108
+ // Nothing.
109
+ }
110
+ }
@@ -0,0 +1,5 @@
1
+ import { AbstractObserver } from "./AbstractObserver.js";
2
+ /** Observer that unsubscribes.*/
3
+ export declare class ThroughObserver<T> extends AbstractObserver<T, T> {
4
+ next(value: T): void;
5
+ }
@@ -0,0 +1,8 @@
1
+ import { AbstractObserver } from "./AbstractObserver.js";
2
+ import { dispatchNext } from "./Observer.js";
3
+ /** Observer that unsubscribes.*/
4
+ export class ThroughObserver extends AbstractObserver {
5
+ next(value) {
6
+ dispatchNext(this.target, value);
7
+ }
8
+ }
@@ -0,0 +1,9 @@
1
+ import { Transformer } from "../util/transform.js";
2
+ import type { PartialObserver } from "./Observer.js";
3
+ import { TransformableObserver } from "./TransformableObserver.js";
4
+ /** Observer that transforms its next values with a transformer. */
5
+ export declare class TransformObserver<I, O> extends TransformableObserver<I, O> {
6
+ protected _transformer: Transformer<I, O>;
7
+ constructor(transformer: Transformer<I, O>, target: PartialObserver<O>);
8
+ transform(value: I): O;
9
+ }
@@ -0,0 +1,12 @@
1
+ import { transform } from "../util/transform.js";
2
+ import { TransformableObserver } from "./TransformableObserver.js";
3
+ /** Observer that transforms its next values with a transformer. */
4
+ export class TransformObserver extends TransformableObserver {
5
+ constructor(transformer, target) {
6
+ super(target);
7
+ this._transformer = transformer;
8
+ }
9
+ transform(value) {
10
+ return transform(value, this._transformer);
11
+ }
12
+ }
@@ -0,0 +1,7 @@
1
+ import type { Transformable } from "../util/transform.js";
2
+ import { AbstractObserver } from "./AbstractObserver.js";
3
+ /** Observer implementing `Transformable` that implements a `transform()` property that is called to transform the next value before dispatching it. */
4
+ export declare abstract class TransformableObserver<I, O> extends AbstractObserver<I, O> implements Transformable<I, O> {
5
+ next(value: I): void;
6
+ abstract transform(input: I): O;
7
+ }
@@ -0,0 +1,8 @@
1
+ import { AbstractObserver } from "./AbstractObserver.js";
2
+ import { dispatchNext } from "./Observer.js";
3
+ /** Observer implementing `Transformable` that implements a `transform()` property that is called to transform the next value before dispatching it. */
4
+ export class TransformableObserver extends AbstractObserver {
5
+ next(value) {
6
+ dispatchNext(this.target, this.transform(value));
7
+ }
8
+ }
@@ -0,0 +1,13 @@
1
+ export * from "./LastSubject.js";
2
+ export * from "./AsyncObserver.js";
3
+ export * from "./MatchableObserver.js";
4
+ export * from "./MatchObserver.js";
5
+ export * from "./Observable.js";
6
+ export * from "./Observer.js";
7
+ export * from "./OnceObserver.js";
8
+ export * from "./Subject.js";
9
+ export * from "./ThroughObserver.js";
10
+ export * from "./TransformableObserver.js";
11
+ export * from "./TransformObserver.js";
12
+ export * from "./AbstractObserver.js";
13
+ export * from "./util.js";
@@ -0,0 +1,13 @@
1
+ export * from "./LastSubject.js";
2
+ export * from "./AsyncObserver.js";
3
+ export * from "./MatchableObserver.js";
4
+ export * from "./MatchObserver.js";
5
+ export * from "./Observable.js";
6
+ export * from "./Observer.js";
7
+ export * from "./OnceObserver.js";
8
+ export * from "./Subject.js";
9
+ export * from "./ThroughObserver.js";
10
+ export * from "./TransformableObserver.js";
11
+ export * from "./TransformObserver.js";
12
+ export * from "./AbstractObserver.js";
13
+ export * from "./util.js";