shelving 1.63.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 (188) hide show
  1. package/api/Resource.js +2 -2
  2. package/db/Database.d.ts +2 -1
  3. package/db/Reference.d.ts +46 -39
  4. package/db/Reference.js +70 -73
  5. package/db/index.d.ts +0 -3
  6. package/db/index.js +0 -3
  7. package/error/ThroughError.d.ts +8 -0
  8. package/error/ThroughError.js +13 -0
  9. package/firestore/client/FirestoreClientProvider.d.ts +11 -11
  10. package/firestore/client/FirestoreClientProvider.js +21 -15
  11. package/firestore/lite/FirestoreLiteProvider.d.ts +10 -11
  12. package/firestore/lite/FirestoreLiteProvider.js +21 -16
  13. package/firestore/server/FirestoreServerProvider.d.ts +11 -11
  14. package/firestore/server/FirestoreServerProvider.js +23 -17
  15. package/index.d.ts +2 -1
  16. package/index.js +2 -1
  17. package/markup/rules.js +4 -4
  18. package/observe/AbstractObserver.d.ts +15 -0
  19. package/observe/AbstractObserver.js +42 -0
  20. package/observe/AsyncObserver.d.ts +5 -0
  21. package/observe/AsyncObserver.js +8 -0
  22. package/{stream/LastStream.d.ts → observe/LastSubject.d.ts} +2 -2
  23. package/observe/LastSubject.js +12 -0
  24. package/observe/MatchObserver.d.ts +9 -0
  25. package/observe/MatchObserver.js +12 -0
  26. package/observe/MatchableObserver.d.ts +7 -0
  27. package/observe/MatchableObserver.js +10 -0
  28. package/observe/Observable.d.ts +20 -0
  29. package/observe/Observable.js +7 -0
  30. package/observe/Observer.d.ts +31 -0
  31. package/observe/Observer.js +48 -0
  32. package/observe/OnceObserver.d.ts +5 -0
  33. package/observe/OnceObserver.js +8 -0
  34. package/observe/Subject.d.ts +46 -0
  35. package/observe/Subject.js +110 -0
  36. package/observe/ThroughObserver.d.ts +5 -0
  37. package/observe/ThroughObserver.js +8 -0
  38. package/observe/TransformObserver.d.ts +9 -0
  39. package/observe/TransformObserver.js +12 -0
  40. package/observe/TransformableObserver.d.ts +7 -0
  41. package/observe/TransformableObserver.js +8 -0
  42. package/observe/index.d.ts +13 -0
  43. package/observe/index.js +13 -0
  44. package/observe/util.d.ts +24 -0
  45. package/observe/util.js +34 -0
  46. package/package.json +3 -3
  47. package/provider/BatchProvider.d.ts +8 -8
  48. package/provider/BatchProvider.js +26 -31
  49. package/provider/CacheProvider.d.ts +12 -24
  50. package/provider/CacheProvider.js +40 -67
  51. package/provider/DebugProvider.d.ts +20 -0
  52. package/provider/DebugProvider.js +170 -0
  53. package/provider/MemoryProvider.d.ts +43 -14
  54. package/provider/MemoryProvider.js +148 -115
  55. package/provider/Provider.d.ts +23 -23
  56. package/provider/ThroughProvider.d.ts +20 -12
  57. package/provider/ThroughProvider.js +12 -12
  58. package/provider/ValidationProvider.d.ts +10 -10
  59. package/provider/ValidationProvider.js +69 -14
  60. package/provider/index.d.ts +1 -1
  61. package/provider/index.js +1 -1
  62. package/query/Filter.d.ts +8 -16
  63. package/query/Filter.js +8 -7
  64. package/query/Filters.d.ts +6 -11
  65. package/query/Filters.js +5 -5
  66. package/query/Query.d.ts +10 -13
  67. package/query/Query.js +10 -10
  68. package/query/Rule.d.ts +2 -3
  69. package/query/Sort.d.ts +7 -8
  70. package/query/Sort.js +5 -5
  71. package/query/Sorts.d.ts +3 -4
  72. package/query/Sorts.js +2 -2
  73. package/query/index.d.ts +0 -1
  74. package/query/index.js +0 -1
  75. package/react/index.d.ts +0 -6
  76. package/react/index.js +3 -6
  77. package/react/useDocument.d.ts +32 -39
  78. package/react/useDocument.js +71 -75
  79. package/react/useInstance.d.ts +4 -7
  80. package/react/useInstance.js +6 -9
  81. package/react/useLazy.d.ts +5 -9
  82. package/react/useQuery.d.ts +48 -46
  83. package/react/useQuery.js +116 -87
  84. package/react/useReduce.d.ts +8 -1
  85. package/react/useReduce.js +1 -3
  86. package/react/useSubscribe.d.ts +5 -6
  87. package/react/useSubscribe.js +10 -11
  88. package/schema/AllowSchema.d.ts +3 -4
  89. package/schema/AllowSchema.js +1 -1
  90. package/schema/MapSchema.js +2 -2
  91. package/schema/ObjectSchema.js +2 -2
  92. package/{stream → state}/ArrayState.d.ts +1 -1
  93. package/{stream → state}/ArrayState.js +8 -10
  94. package/{stream → state}/BooleanState.d.ts +1 -1
  95. package/{stream → state}/BooleanState.js +3 -5
  96. package/{stream → state}/DataState.d.ts +3 -3
  97. package/{stream → state}/DataState.js +6 -6
  98. package/{stream → state}/ObjectState.d.ts +1 -1
  99. package/{stream → state}/ObjectState.js +6 -8
  100. package/state/SelfClosingState.d.ts +18 -0
  101. package/state/SelfClosingState.js +34 -0
  102. package/state/State.d.ts +32 -0
  103. package/state/State.js +69 -0
  104. package/{stream → state}/index.d.ts +1 -4
  105. package/{stream → state}/index.js +1 -4
  106. package/test/basics.d.ts +12 -15
  107. package/test/basics.js +10 -20
  108. package/test/people.d.ts +9 -14
  109. package/test/people.js +6 -12
  110. package/test/util.d.ts +3 -3
  111. package/test/util.js +7 -7
  112. package/update/ArrayUpdate.d.ts +2 -1
  113. package/update/ArrayUpdate.js +4 -4
  114. package/update/DataUpdate.d.ts +2 -1
  115. package/update/DataUpdate.js +3 -2
  116. package/update/ObjectUpdate.d.ts +2 -1
  117. package/update/ObjectUpdate.js +14 -5
  118. package/update/Update.d.ts +2 -2
  119. package/update/util.d.ts +1 -4
  120. package/update/util.js +3 -3
  121. package/util/async.d.ts +4 -5
  122. package/util/async.js +3 -2
  123. package/util/clone.js +3 -3
  124. package/util/data.d.ts +42 -44
  125. package/util/data.js +32 -33
  126. package/util/entry.d.ts +15 -28
  127. package/util/entry.js +19 -13
  128. package/util/equal.d.ts +4 -5
  129. package/util/filter.d.ts +5 -46
  130. package/util/filter.js +5 -47
  131. package/util/function.d.ts +5 -5
  132. package/util/function.js +3 -3
  133. package/util/hydrate.d.ts +1 -1
  134. package/util/hydrate.js +7 -7
  135. package/util/index.d.ts +1 -1
  136. package/util/index.js +1 -1
  137. package/util/iterate.d.ts +15 -19
  138. package/util/iterate.js +7 -17
  139. package/util/match.d.ts +20 -0
  140. package/util/match.js +14 -0
  141. package/util/random.js +2 -3
  142. package/util/search.d.ts +1 -1
  143. package/util/sort.d.ts +4 -30
  144. package/util/sort.js +0 -38
  145. package/util/string.d.ts +1 -1
  146. package/util/string.js +2 -7
  147. package/util/template.js +2 -2
  148. package/util/timeout.d.ts +2 -0
  149. package/util/timeout.js +8 -1
  150. package/util/transform.d.ts +39 -44
  151. package/util/transform.js +21 -34
  152. package/util/validate.d.ts +26 -20
  153. package/util/validate.js +20 -22
  154. package/api/errors.d.ts +0 -8
  155. package/api/errors.js +0 -9
  156. package/db/PaginationState.d.ts +0 -31
  157. package/db/PaginationState.js +0 -67
  158. package/db/errors.d.ts +0 -25
  159. package/db/errors.js +0 -34
  160. package/db/util.d.ts +0 -37
  161. package/db/util.js +0 -54
  162. package/provider/ErrorProvider.d.ts +0 -32
  163. package/provider/ErrorProvider.js +0 -175
  164. package/query/util.d.ts +0 -8
  165. package/query/util.js +0 -8
  166. package/react/useCompare.d.ts +0 -3
  167. package/react/useCompare.js +0 -8
  168. package/react/useFetch.d.ts +0 -17
  169. package/react/useFetch.js +0 -41
  170. package/react/usePagination.d.ts +0 -8
  171. package/react/usePagination.js +0 -22
  172. package/react/usePureEffect.d.ts +0 -10
  173. package/react/usePureEffect.js +0 -17
  174. package/react/usePureState.d.ts +0 -11
  175. package/react/usePureState.js +0 -16
  176. package/react/useState.d.ts +0 -39
  177. package/react/useState.js +0 -65
  178. package/stream/LastStream.js +0 -12
  179. package/stream/LazyState.d.ts +0 -11
  180. package/stream/LazyState.js +0 -28
  181. package/stream/LazyStream.d.ts +0 -12
  182. package/stream/LazyStream.js +0 -28
  183. package/stream/State.d.ts +0 -46
  184. package/stream/State.js +0 -66
  185. package/stream/Stream.d.ts +0 -66
  186. package/stream/Stream.js +0 -122
  187. package/util/observe.d.ts +0 -111
  188. package/util/observe.js +0 -159
@@ -45,10 +45,16 @@ function getQuery(firestore, ref) {
45
45
  constraints.push(firestoreLimit(limit));
46
46
  return firestoreQuery(getCollection(firestore, ref), ...constraints);
47
47
  }
48
- /** Create a set of results from a collection snapshot. */
49
- function* getResults(snapshot) {
50
- for (const s of snapshot.docs)
51
- yield [s.id, s.data()];
48
+ function getEntities(snapshot) {
49
+ return snapshot.docs.map(getEntity);
50
+ }
51
+ function getEntity(snapshot) {
52
+ const data = snapshot.data();
53
+ return { ...data, id: snapshot.id };
54
+ }
55
+ function getOptionalData(snapshot) {
56
+ const data = snapshot.data();
57
+ return data ? { ...data, id: snapshot.id } : null;
52
58
  }
53
59
  /** Convert `Update` instances into corresponding Firestore `FieldValue` instances. */
54
60
  function* yieldFieldValues(updates, prefix = "") {
@@ -82,32 +88,31 @@ export class FirestoreClientProvider extends Provider {
82
88
  super();
83
89
  this.firestore = firestore;
84
90
  }
85
- async get(ref) {
86
- const snapshot = await getDoc(getDocument(this.firestore, ref));
87
- return snapshot.data() || null;
91
+ async getDocument(ref) {
92
+ return getOptionalData(await getDoc(getDocument(this.firestore, ref)));
88
93
  }
89
- subscribe() {
90
- throw new Error("FirestoreLiteProvider does not support realtime subscriptions");
94
+ subscribeDocument() {
95
+ throw new UnsupportedError("FirestoreLiteProvider does not support realtime subscriptions");
91
96
  }
92
- async add(ref, data) {
93
- const reference = await addDoc(getCollection(this.firestore, ref), data); // eslint-disable-line @typescript-eslint/no-explicit-any
97
+ async addDocument(ref, data) {
98
+ const reference = await addDoc(getCollection(this.firestore, ref), data);
94
99
  return reference.id;
95
100
  }
96
- async set(ref, data) {
101
+ async setDocument(ref, data) {
97
102
  await setDoc(getDocument(this.firestore, ref), data);
98
103
  }
99
- async update(ref, update) {
104
+ async updateDocument(ref, update) {
100
105
  const fieldValues = Object.fromEntries(yieldFieldValues(update));
101
106
  await updateDoc(getDocument(this.firestore, ref), fieldValues);
102
107
  }
103
- async delete(ref) {
108
+ async deleteDocument(ref) {
104
109
  await deleteDoc(getDocument(this.firestore, ref));
105
110
  }
106
111
  async getQuery(ref) {
107
- return getResults(await getDocs(getQuery(this.firestore, ref)));
112
+ return getEntities(await getDocs(getQuery(this.firestore, ref)));
108
113
  }
109
114
  subscribeQuery() {
110
- throw new Error("FirestoreLiteProvider does not support realtime subscriptions");
115
+ throw new UnsupportedError("FirestoreLiteProvider does not support realtime subscriptions");
111
116
  }
112
117
  async setQuery(ref, data) {
113
118
  const snapshot = await getDocs(getQuery(this.firestore, ref));
@@ -1,10 +1,10 @@
1
1
  import { Firestore } from "@google-cloud/firestore";
2
2
  import type { DocumentReference, QueryReference } from "../../db/Reference.js";
3
- import type { Data, Result } from "../../util/data.js";
4
- import type { Entries, Entry } from "../../util/entry.js";
3
+ import type { Data, Entities, OptionalEntity } from "../../util/data.js";
4
+ import type { Unsubscribe } from "../../observe/Observable.js";
5
5
  import { AsynchronousProvider, Provider } from "../../provider/Provider.js";
6
6
  import { DataUpdate } from "../../update/DataUpdate.js";
7
- import { Observer, Unsubscriber } from "../../util/observe.js";
7
+ import { Observer } from "../../observe/Observer.js";
8
8
  /**
9
9
  * Firestore server database provider.
10
10
  * - Works with the Firebase Admin SDK for Node.JS
@@ -12,14 +12,14 @@ import { Observer, Unsubscriber } from "../../util/observe.js";
12
12
  export declare class FirestoreServerProvider extends Provider implements AsynchronousProvider {
13
13
  readonly firestore: Firestore;
14
14
  constructor(firestore?: Firestore);
15
- get<T extends Data>(ref: DocumentReference<T>): Promise<Result<T>>;
16
- subscribe<T extends Data>(ref: DocumentReference<T>, observer: Observer<Result<T>>): Unsubscriber;
17
- add<T extends Data>(ref: QueryReference<T>, data: T): Promise<string>;
18
- set<T extends Data>(ref: DocumentReference<T>, data: T): Promise<void>;
19
- update<T extends Data>(ref: DocumentReference<T>, update: DataUpdate<T>): Promise<void>;
20
- delete<T extends Data>(ref: DocumentReference<T>): Promise<void>;
21
- getQuery<T extends Data>(ref: QueryReference<T>): Promise<Iterable<Entry<T>>>;
22
- subscribeQuery<T extends Data>(ref: QueryReference<T>, observer: Observer<Entries<T>>): Unsubscriber;
15
+ getDocument<T extends Data>(ref: DocumentReference<T>): Promise<OptionalEntity<T>>;
16
+ subscribeDocument<T extends Data>(ref: DocumentReference<T>, observer: Observer<OptionalEntity<T>>): Unsubscribe;
17
+ addDocument<T extends Data>(ref: QueryReference<T>, data: T): Promise<string>;
18
+ setDocument<T extends Data>(ref: DocumentReference<T>, data: T): Promise<void>;
19
+ updateDocument<T extends Data>(ref: DocumentReference<T>, update: DataUpdate<T>): Promise<void>;
20
+ deleteDocument<T extends Data>(ref: DocumentReference<T>): Promise<void>;
21
+ getQuery<T extends Data>(ref: QueryReference<T>): Promise<Entities<T>>;
22
+ subscribeQuery<T extends Data>(ref: QueryReference<T>, observer: Observer<Entities<T>>): Unsubscribe;
23
23
  setQuery<T extends Data>(ref: QueryReference<T>, data: T): Promise<number>;
24
24
  updateQuery<T extends Data>(ref: QueryReference<T>, update: DataUpdate<T>): Promise<number>;
25
25
  deleteQuery<T extends Data>(ref: QueryReference<T>): Promise<number>;
@@ -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,10 +46,16 @@ 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.id, s.data()];
49
+ function getEntities(snapshot) {
50
+ return snapshot.docs.map(getEntity);
51
+ }
52
+ function getEntity(snapshot) {
53
+ const data = snapshot.data();
54
+ return { ...data, id: snapshot.id };
55
+ }
56
+ function getOptionalEntity(snapshot) {
57
+ const data = snapshot.data();
58
+ return data ? { ...data, id: snapshot.id } : null;
53
59
  }
54
60
  /** Convert `Update` instances into corresponding Firestore `FieldValue` instances. */
55
61
  function* yieldFieldValues(updates, prefix = "") {
@@ -81,36 +87,36 @@ export class FirestoreServerProvider extends Provider {
81
87
  super();
82
88
  this.firestore = firestore;
83
89
  }
84
- async get(ref) {
85
- return (await getDocument(this.firestore, ref).get()).data() || null;
90
+ async getDocument(ref) {
91
+ return getOptionalEntity(await getDocument(this.firestore, ref).get());
86
92
  }
87
- subscribe(ref, observer) {
88
- return getDocument(this.firestore, ref).onSnapshot(snapshot => dispatchNext(observer, snapshot.data() || null), thrown => dispatchError(observer, thrown));
93
+ subscribeDocument(ref, observer) {
94
+ return getDocument(this.firestore, ref).onSnapshot(snapshot => dispatchNext(observer, getOptionalEntity(snapshot)), thrown => dispatchError(observer, thrown));
89
95
  }
90
- async add(ref, data) {
96
+ async addDocument(ref, data) {
91
97
  return (await getCollection(this.firestore, ref).add(data)).id;
92
98
  }
93
- async set(ref, data) {
99
+ async setDocument(ref, data) {
94
100
  await getDocument(this.firestore, ref).set(data);
95
101
  }
96
- async update(ref, update) {
97
- const fieldValues = Object.fromEntries(yieldFieldValues(update)); // eslint-disable-line @typescript-eslint/no-explicit-any
102
+ async updateDocument(ref, update) {
103
+ const fieldValues = Object.fromEntries(yieldFieldValues(update));
98
104
  await getDocument(this.firestore, ref).update(fieldValues);
99
105
  }
100
- async delete(ref) {
106
+ async deleteDocument(ref) {
101
107
  await getDocument(this.firestore, ref).delete();
102
108
  }
103
109
  async getQuery(ref) {
104
- return getResults(await getQuery(this.firestore, ref).get());
110
+ return getEntities(await getQuery(this.firestore, ref).get());
105
111
  }
106
112
  subscribeQuery(ref, observer) {
107
- 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));
108
114
  }
109
115
  async setQuery(ref, data) {
110
116
  return await bulkWrite(this.firestore, ref, (w, s) => void w.set(s.ref, data));
111
117
  }
112
118
  async updateQuery(ref, update) {
113
- const fieldValues = Object.fromEntries(yieldFieldValues(update)); // eslint-disable-line @typescript-eslint/no-explicit-any
119
+ const fieldValues = Object.fromEntries(yieldFieldValues(update));
114
120
  return await bulkWrite(this.firestore, ref, (w, s) => void w.update(s.ref, fieldValues));
115
121
  }
116
122
  async deleteQuery(ref) {
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
+ }