shelving 1.20.3 → 1.22.2
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/Resource.d.ts +13 -7
- package/api/Resource.js +9 -9
- package/db/Database.d.ts +7 -19
- package/db/Database.js +10 -22
- package/feedback/index.d.ts +0 -1
- package/feedback/index.js +0 -1
- package/firestore/client/FirestoreClientProvider.d.ts +3 -3
- package/firestore/client/FirestoreClientProvider.js +2 -2
- package/firestore/lite/FirestoreLiteProvider.d.ts +3 -3
- package/firestore/server/FirestoreServerProvider.d.ts +3 -3
- package/firestore/server/FirestoreServerProvider.js +2 -2
- package/package.json +1 -1
- package/provider/MemoryProvider.js +14 -14
- package/provider/ValidationProvider.js +2 -3
- package/react/useDocument.js +3 -3
- package/react/useFetch.js +2 -2
- package/react/usePureState.d.ts +4 -4
- package/react/useQuery.js +3 -3
- package/react/useSubscribe.js +1 -1
- package/schema/SlugSchema.d.ts +18 -0
- package/schema/SlugSchema.js +25 -0
- package/schema/index.d.ts +3 -2
- package/schema/index.js +3 -2
- package/stream/LastStream.js +1 -1
- package/stream/LazyState.d.ts +1 -1
- package/stream/LazyState.js +4 -4
- package/stream/LazyStream.d.ts +1 -1
- package/stream/LazyStream.js +5 -5
- package/stream/State.d.ts +1 -1
- package/stream/State.js +4 -4
- package/stream/Stream.d.ts +7 -7
- package/stream/Stream.js +21 -21
- package/util/async.d.ts +6 -6
- package/util/error.js +1 -1
- package/util/function.d.ts +8 -0
- package/util/function.js +19 -0
- package/util/index.d.ts +0 -1
- package/util/index.js +0 -1
- package/util/observable.d.ts +10 -14
- package/util/observable.js +17 -23
- package/feedback/util.d.ts +0 -3
- package/feedback/util.js +0 -7
- package/util/dispatch.d.ts +0 -29
- package/util/dispatch.js +0 -43
package/api/Resource.d.ts
CHANGED
|
@@ -6,24 +6,22 @@ import { Validator, Validatable } from "../util/index.js";
|
|
|
6
6
|
* @param returns The `Validator` the function's returned value must conform to (defaults to `undefined` if not specified).
|
|
7
7
|
*/
|
|
8
8
|
export declare class Resource<P = unknown, R = void> implements Validatable<R> {
|
|
9
|
-
static create<X, Y>(payload: Validator<X>, result: Validator<Y>): Resource<X, Y>;
|
|
10
|
-
static create<Y>(payload: undefined, result: Y): Resource<undefined, Y>;
|
|
11
|
-
static create<X>(payload: Validator<X>, result?: undefined): Resource<X, void>;
|
|
12
|
-
static create(payload?: undefined, result?: undefined): Resource<undefined, void>;
|
|
13
9
|
/** Payload validator. */
|
|
14
10
|
readonly payload: Validator<P>;
|
|
15
11
|
/** Result validator. */
|
|
16
12
|
readonly result: Validator<R>;
|
|
17
|
-
|
|
13
|
+
constructor(payload: Validator<P>, result: Validator<R>);
|
|
18
14
|
/**
|
|
19
15
|
* Validate a payload for this resource.
|
|
20
16
|
*
|
|
17
|
+
* @returns The validated payload for this resource.
|
|
18
|
+
* @throws InvalidFeedback if the payload could not be validated.
|
|
21
19
|
*/
|
|
22
|
-
|
|
20
|
+
prepare(unsafePayload: unknown): P;
|
|
23
21
|
/**
|
|
24
22
|
* Validate a result for this resource.
|
|
25
23
|
*
|
|
26
|
-
* @returns The validated
|
|
24
|
+
* @returns The validated result for this resource.
|
|
27
25
|
* @throws ValidationError if the result could not be validated.
|
|
28
26
|
*/
|
|
29
27
|
validate(unsafeResult: unknown): R;
|
|
@@ -32,3 +30,11 @@ export declare class Resource<P = unknown, R = void> implements Validatable<R> {
|
|
|
32
30
|
export declare type PayloadType<X extends Resource> = X extends Resource<infer Y, unknown> ? Y : never;
|
|
33
31
|
/** Extract the result type from a `Resource`. */
|
|
34
32
|
export declare type ResourceType<X extends Resource> = X extends Resource<unknown, infer Y> ? Y : never;
|
|
33
|
+
/**
|
|
34
|
+
* Shortcut to create a new `Resource` (consistent with `Schema` shortcuts.
|
|
35
|
+
* - Sets `undefined` as the default type for payload and result.
|
|
36
|
+
*/
|
|
37
|
+
export declare function RESOURCE<X, Y>(payload: Validator<X>, result: Validator<Y>): Resource<X, Y>;
|
|
38
|
+
export declare function RESOURCE<Y>(payload: undefined, result: Y): Resource<undefined, Y>;
|
|
39
|
+
export declare function RESOURCE<X>(payload: Validator<X>, result?: undefined): Resource<X, void>;
|
|
40
|
+
export declare function RESOURCE(payload?: undefined, result?: undefined): Resource<undefined, void>;
|
package/api/Resource.js
CHANGED
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
import { UNDEFINED, validate } from "../util/index.js";
|
|
2
|
-
import { Feedback
|
|
2
|
+
import { Feedback } from "../feedback/index.js";
|
|
3
3
|
import { ResourceValidationError } from "./errors.js";
|
|
4
|
-
/** Validator that always returns void/undefined. */
|
|
5
|
-
const UNDEFINED_VALIDATOR = UNDEFINED;
|
|
6
4
|
/**
|
|
7
5
|
* An abstract API resource definition, used to specify types for e.g. serverless functions..
|
|
8
6
|
*
|
|
@@ -15,20 +13,19 @@ export class Resource {
|
|
|
15
13
|
this.payload = payload;
|
|
16
14
|
this.result = result;
|
|
17
15
|
}
|
|
18
|
-
static create(payload = UNDEFINED_VALIDATOR, result = UNDEFINED_VALIDATOR) {
|
|
19
|
-
return new Resource(payload, result);
|
|
20
|
-
}
|
|
21
16
|
/**
|
|
22
17
|
* Validate a payload for this resource.
|
|
23
18
|
*
|
|
19
|
+
* @returns The validated payload for this resource.
|
|
20
|
+
* @throws InvalidFeedback if the payload could not be validated.
|
|
24
21
|
*/
|
|
25
|
-
|
|
26
|
-
return
|
|
22
|
+
prepare(unsafePayload) {
|
|
23
|
+
return validate(unsafePayload, this.payload);
|
|
27
24
|
}
|
|
28
25
|
/**
|
|
29
26
|
* Validate a result for this resource.
|
|
30
27
|
*
|
|
31
|
-
* @returns The validated
|
|
28
|
+
* @returns The validated result for this resource.
|
|
32
29
|
* @throws ValidationError if the result could not be validated.
|
|
33
30
|
*/
|
|
34
31
|
validate(unsafeResult) {
|
|
@@ -40,3 +37,6 @@ export class Resource {
|
|
|
40
37
|
}
|
|
41
38
|
}
|
|
42
39
|
}
|
|
40
|
+
export function RESOURCE(payload = UNDEFINED, result = UNDEFINED) {
|
|
41
|
+
return new Resource(payload, result);
|
|
42
|
+
}
|
package/db/Database.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Entry, Observable, Observer, Result, Unsubscriber, ResultsMap, Validatable, Validator, Key, Data, Results, Datas, Validators, ValidatorType, Dispatcher } from "../util/index.js";
|
|
2
2
|
import { Transform, Transforms } from "../transform/index.js";
|
|
3
3
|
import type { Provider } from "../provider/Provider.js";
|
|
4
4
|
import { Filters, Sorts, Query } from "../query/index.js";
|
|
@@ -58,26 +58,18 @@ export declare class DataQuery<T extends Data = Data> extends Query<T> implement
|
|
|
58
58
|
* Subscribe to all matching documents.
|
|
59
59
|
* - `next()` is called once with the initial results, and again any time the results change.
|
|
60
60
|
*
|
|
61
|
-
* @param
|
|
62
|
-
* @param next Callback that is called once initially and again whenever the results change.
|
|
63
|
-
* @param error Callback that is called if an error occurs.
|
|
64
|
-
* @param complete Callback that is called when the subscription is done.
|
|
65
|
-
*
|
|
61
|
+
* @param next Observer with `next`, `error`, or `complete` methods or a `next()` dispatcher.
|
|
66
62
|
* @return Function that ends the subscription.
|
|
67
63
|
*/
|
|
68
|
-
subscribe(next: Observer<Results<T>> | Dispatcher<Results<T
|
|
64
|
+
subscribe(next: Observer<Results<T>> | Dispatcher<[Results<T>]>): Unsubscriber;
|
|
69
65
|
/**
|
|
70
66
|
* Subscribe to all matching documents.
|
|
71
67
|
* - `next()` is called once with the initial results, and again any time the results change.
|
|
72
68
|
*
|
|
73
|
-
* @param
|
|
74
|
-
* @param next Callback that is called once initially and again whenever the results change.
|
|
75
|
-
* @param error Callback that is called if an error occurs.
|
|
76
|
-
* @param complete Callback that is called when the subscription is done.
|
|
77
|
-
*
|
|
69
|
+
* @param next Observer with `next`, `error`, or `complete` methods or a `next()` dispatcher.
|
|
78
70
|
* @return Function that ends the subscription.
|
|
79
71
|
*/
|
|
80
|
-
subscribeMap(next: Observer<ResultsMap<T>> | Dispatcher<ResultsMap<T
|
|
72
|
+
subscribeMap(next: Observer<ResultsMap<T>> | Dispatcher<[ResultsMap<T>]>): Unsubscriber;
|
|
81
73
|
/**
|
|
82
74
|
* Set all matching documents to the same exact value.
|
|
83
75
|
*
|
|
@@ -145,14 +137,10 @@ export declare class DataDocument<T extends Data = Data> implements Observable<R
|
|
|
145
137
|
* Subscribe to the result of this document (indefinitely).
|
|
146
138
|
* - `next()` is called once with the initial result, and again any time the result changes.
|
|
147
139
|
*
|
|
148
|
-
* @param
|
|
149
|
-
* @param next Callback that is called once initially and again whenever the result changes.
|
|
150
|
-
* @param error Callback that is called if an error occurs.
|
|
151
|
-
* @param complete Callback that is called when the subscription is done.
|
|
152
|
-
*
|
|
140
|
+
* @param next Observer with `next`, `error`, or `complete` methods or a `next()` dispatcher.
|
|
153
141
|
* @return Function that ends the subscription.
|
|
154
142
|
*/
|
|
155
|
-
subscribe(next: Observer<Result<T>> | Dispatcher<Result<T
|
|
143
|
+
subscribe(next: Observer<Result<T>> | Dispatcher<[Result<T>]>): Unsubscriber;
|
|
156
144
|
/**
|
|
157
145
|
* Set the complete data of this document.
|
|
158
146
|
*
|
package/db/Database.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { callAsync,
|
|
1
|
+
import { callAsync, getFirstItem, throwAsync, validate, toMap, countItems, DeriveObserver, } from "../util/index.js";
|
|
2
2
|
import { DataTransform, Transform } from "../transform/index.js";
|
|
3
3
|
import { Feedback, InvalidFeedback } from "../feedback/index.js";
|
|
4
4
|
import { Filters, Query, EqualFilter } from "../query/index.js";
|
|
@@ -79,29 +79,21 @@ export class DataQuery extends Query {
|
|
|
79
79
|
* Subscribe to all matching documents.
|
|
80
80
|
* - `next()` is called once with the initial results, and again any time the results change.
|
|
81
81
|
*
|
|
82
|
-
* @param
|
|
83
|
-
* @param next Callback that is called once initially and again whenever the results change.
|
|
84
|
-
* @param error Callback that is called if an error occurs.
|
|
85
|
-
* @param complete Callback that is called when the subscription is done.
|
|
86
|
-
*
|
|
82
|
+
* @param next Observer with `next`, `error`, or `complete` methods or a `next()` dispatcher.
|
|
87
83
|
* @return Function that ends the subscription.
|
|
88
84
|
*/
|
|
89
|
-
subscribe(next
|
|
90
|
-
return this.provider.subscribeQuery(this,
|
|
85
|
+
subscribe(next) {
|
|
86
|
+
return this.provider.subscribeQuery(this, typeof next === "function" ? { next } : next);
|
|
91
87
|
}
|
|
92
88
|
/**
|
|
93
89
|
* Subscribe to all matching documents.
|
|
94
90
|
* - `next()` is called once with the initial results, and again any time the results change.
|
|
95
91
|
*
|
|
96
|
-
* @param
|
|
97
|
-
* @param next Callback that is called once initially and again whenever the results change.
|
|
98
|
-
* @param error Callback that is called if an error occurs.
|
|
99
|
-
* @param complete Callback that is called when the subscription is done.
|
|
100
|
-
*
|
|
92
|
+
* @param next Observer with `next`, `error`, or `complete` methods or a `next()` dispatcher.
|
|
101
93
|
* @return Function that ends the subscription.
|
|
102
94
|
*/
|
|
103
|
-
subscribeMap(next
|
|
104
|
-
return this.provider.subscribeQuery(this, new DeriveObserver(toMap,
|
|
95
|
+
subscribeMap(next) {
|
|
96
|
+
return this.provider.subscribeQuery(this, new DeriveObserver(toMap, typeof next === "function" ? { next } : next));
|
|
105
97
|
}
|
|
106
98
|
/**
|
|
107
99
|
* Set all matching documents to the same exact value.
|
|
@@ -210,15 +202,11 @@ export class DataDocument {
|
|
|
210
202
|
* Subscribe to the result of this document (indefinitely).
|
|
211
203
|
* - `next()` is called once with the initial result, and again any time the result changes.
|
|
212
204
|
*
|
|
213
|
-
* @param
|
|
214
|
-
* @param next Callback that is called once initially and again whenever the result changes.
|
|
215
|
-
* @param error Callback that is called if an error occurs.
|
|
216
|
-
* @param complete Callback that is called when the subscription is done.
|
|
217
|
-
*
|
|
205
|
+
* @param next Observer with `next`, `error`, or `complete` methods or a `next()` dispatcher.
|
|
218
206
|
* @return Function that ends the subscription.
|
|
219
207
|
*/
|
|
220
|
-
subscribe(next
|
|
221
|
-
return this.provider.subscribe(this,
|
|
208
|
+
subscribe(next) {
|
|
209
|
+
return this.provider.subscribe(this, typeof next === "function" ? { next } : next);
|
|
222
210
|
}
|
|
223
211
|
/**
|
|
224
212
|
* Set the complete data of this document.
|
package/feedback/index.d.ts
CHANGED
package/feedback/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { Firestore } from "firebase/firestore";
|
|
2
|
-
import { Results, Provider, DataDocument, DataQuery, Result, Observer, Transform, AsynchronousProvider, Data } from "../../index.js";
|
|
2
|
+
import { Results, Provider, DataDocument, DataQuery, Result, Observer, Transform, AsynchronousProvider, Data, Unsubscriber } from "../../index.js";
|
|
3
3
|
/**
|
|
4
4
|
* Firestore client database provider.
|
|
5
5
|
* - Works with the Firebase JS SDK.
|
|
@@ -10,10 +10,10 @@ export declare class FirestoreClientProvider extends Provider implements Asynchr
|
|
|
10
10
|
readonly firestore: Firestore;
|
|
11
11
|
constructor(firestore: Firestore);
|
|
12
12
|
get<T extends Data>(ref: DataDocument<T>): Promise<Result<T>>;
|
|
13
|
-
subscribe<T extends Data>(ref: DataDocument<T>, observer: Observer<Result<T>>):
|
|
13
|
+
subscribe<T extends Data>(ref: DataDocument<T>, observer: Observer<Result<T>>): Unsubscriber;
|
|
14
14
|
add<T extends Data>(ref: DataQuery<T>, data: T): Promise<string>;
|
|
15
15
|
write<T extends Data>(ref: DataDocument<T>, value: T | Transform<T> | undefined): Promise<void>;
|
|
16
16
|
getQuery<T extends Data>(ref: DataQuery<T>): Promise<Results<T>>;
|
|
17
|
-
subscribeQuery<T extends Data>(ref: DataQuery<T>, observer: Observer<Results<T>>):
|
|
17
|
+
subscribeQuery<T extends Data>(ref: DataQuery<T>, observer: Observer<Results<T>>): Unsubscriber;
|
|
18
18
|
writeQuery<T extends Data>(ref: DataQuery<T>, value: T | Transform<T> | undefined): Promise<void>;
|
|
19
19
|
}
|
|
@@ -88,7 +88,7 @@ export class FirestoreClientProvider extends Provider {
|
|
|
88
88
|
return snapshot.data();
|
|
89
89
|
}
|
|
90
90
|
subscribe(ref, observer) {
|
|
91
|
-
return onSnapshot(getDocument(this.firestore, ref), snapshot => dispatchNext(snapshot.data()
|
|
91
|
+
return onSnapshot(getDocument(this.firestore, ref), snapshot => dispatchNext(observer, snapshot.data()), thrown => dispatchError(observer, thrown));
|
|
92
92
|
}
|
|
93
93
|
async add(ref, data) {
|
|
94
94
|
const reference = await addDoc(getCollection(this.firestore, ref), data); // eslint-disable-line @typescript-eslint/no-explicit-any
|
|
@@ -106,7 +106,7 @@ export class FirestoreClientProvider extends Provider {
|
|
|
106
106
|
return getResults(await getDocs(getQuery(this.firestore, ref)));
|
|
107
107
|
}
|
|
108
108
|
subscribeQuery(ref, observer) {
|
|
109
|
-
return onSnapshot(getQuery(this.firestore, ref), snapshot => dispatchNext(getResults(snapshot)
|
|
109
|
+
return onSnapshot(getQuery(this.firestore, ref), snapshot => dispatchNext(observer, getResults(snapshot)), thrown => dispatchError(observer, thrown));
|
|
110
110
|
}
|
|
111
111
|
async writeQuery(ref, value) {
|
|
112
112
|
const snapshot = await getDocs(getQuery(this.firestore, ref));
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { Firestore } from "firebase/firestore/lite";
|
|
2
|
-
import { Provider, DataDocument, DataQuery, Result, Transform, AsynchronousProvider, Data, Results } from "../../index.js";
|
|
2
|
+
import { Provider, DataDocument, DataQuery, Result, Transform, AsynchronousProvider, Data, Results, Unsubscriber } from "../../index.js";
|
|
3
3
|
/**
|
|
4
4
|
* Firestore Lite client database provider.
|
|
5
5
|
* - Works with the Firebase JS SDK.
|
|
@@ -10,10 +10,10 @@ export declare class FirestoreClientProvider extends Provider implements Asynchr
|
|
|
10
10
|
readonly firestore: Firestore;
|
|
11
11
|
constructor(firestore: Firestore);
|
|
12
12
|
get<T extends Data>(ref: DataDocument<T>): Promise<Result<T>>;
|
|
13
|
-
subscribe():
|
|
13
|
+
subscribe(): Unsubscriber;
|
|
14
14
|
add<T extends Data>(ref: DataQuery<T>, data: T): Promise<string>;
|
|
15
15
|
write<T extends Data>(ref: DataDocument<T>, value: T | Transform<T> | undefined): Promise<void>;
|
|
16
16
|
getQuery<T extends Data>(ref: DataQuery<T>): Promise<Results<T>>;
|
|
17
|
-
subscribeQuery():
|
|
17
|
+
subscribeQuery(): Unsubscriber;
|
|
18
18
|
writeQuery<T extends Data>(ref: DataQuery<T>, value: T | Transform<T> | undefined): Promise<void>;
|
|
19
19
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Firestore } from "@google-cloud/firestore";
|
|
2
|
-
import { Provider, DataDocument, DataQuery, Observer, Result, Transform, Data, AsynchronousProvider, Entry, Results } from "../../index.js";
|
|
2
|
+
import { Provider, DataDocument, DataQuery, Observer, Result, Transform, Data, AsynchronousProvider, Entry, Results, Unsubscriber } from "../../index.js";
|
|
3
3
|
/**
|
|
4
4
|
* Firestore server database provider.
|
|
5
5
|
* - Works with the Firebase Admin SDK for Node.JS
|
|
@@ -8,10 +8,10 @@ export declare class FirestoreServerProvider extends Provider implements Asynchr
|
|
|
8
8
|
readonly firestore: Firestore;
|
|
9
9
|
constructor(firestore?: Firestore);
|
|
10
10
|
get<T extends Data>(ref: DataDocument<T>): Promise<Result<T>>;
|
|
11
|
-
subscribe<T extends Data>(ref: DataDocument<T>, observer: Observer<Result<T>>):
|
|
11
|
+
subscribe<T extends Data>(ref: DataDocument<T>, observer: Observer<Result<T>>): Unsubscriber;
|
|
12
12
|
add<T extends Data>(ref: DataQuery<T>, data: T): Promise<string>;
|
|
13
13
|
write<T extends Data>(ref: DataDocument<T>, value: T | Transform<T> | undefined): Promise<void>;
|
|
14
14
|
getQuery<T extends Data>(ref: DataQuery<T>): Promise<Iterable<Entry<T>>>;
|
|
15
|
-
subscribeQuery<T extends Data>(ref: DataQuery<T>, observer: Observer<Results<T>>):
|
|
15
|
+
subscribeQuery<T extends Data>(ref: DataQuery<T>, observer: Observer<Results<T>>): Unsubscriber;
|
|
16
16
|
writeQuery<T extends Data>(ref: DataQuery<T>, value: T | Transform<T> | undefined): Promise<void>;
|
|
17
17
|
}
|
|
@@ -85,7 +85,7 @@ export class FirestoreServerProvider extends Provider {
|
|
|
85
85
|
return (await getDocument(this.firestore, ref).get()).data();
|
|
86
86
|
}
|
|
87
87
|
subscribe(ref, observer) {
|
|
88
|
-
return getDocument(this.firestore, ref).onSnapshot(snapshot => dispatchNext(snapshot.data()
|
|
88
|
+
return getDocument(this.firestore, ref).onSnapshot(snapshot => dispatchNext(observer, snapshot.data()), thrown => dispatchError(observer, thrown));
|
|
89
89
|
}
|
|
90
90
|
async add(ref, data) {
|
|
91
91
|
return (await getCollection(this.firestore, ref).add(data)).id;
|
|
@@ -102,7 +102,7 @@ export class FirestoreServerProvider extends Provider {
|
|
|
102
102
|
return getResults(await getQuery(this.firestore, ref).get());
|
|
103
103
|
}
|
|
104
104
|
subscribeQuery(ref, observer) {
|
|
105
|
-
return getQuery(this.firestore, ref).onSnapshot(snapshot => dispatchNext(getResults(snapshot)
|
|
105
|
+
return getQuery(this.firestore, ref).onSnapshot(snapshot => dispatchNext(observer, getResults(snapshot)), thrown => dispatchError(observer, thrown));
|
|
106
106
|
}
|
|
107
107
|
async writeQuery(ref, value) {
|
|
108
108
|
const writer = this.firestore.bulkWriter();
|
package/package.json
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { randomId,
|
|
1
|
+
import { randomId, dispatchNext, isMapEqual, } from "../util/index.js";
|
|
2
2
|
import { Transform } from "../transform/index.js";
|
|
3
3
|
import { DocumentRequiredError } from "../db/index.js";
|
|
4
4
|
import { Provider } from "./Provider.js";
|
|
@@ -25,10 +25,10 @@ export class MemoryProvider extends Provider {
|
|
|
25
25
|
const table = this._table(ref);
|
|
26
26
|
const id = ref.id;
|
|
27
27
|
// Call next() immediately with initial results.
|
|
28
|
-
dispatchNext(table.data.get(id)
|
|
28
|
+
dispatchNext(observer, table.data.get(id));
|
|
29
29
|
// Call next() every time the collection changes.
|
|
30
30
|
return table.on(changes => {
|
|
31
|
-
changes.has(id) && dispatchNext(changes.get(id)
|
|
31
|
+
changes.has(id) && dispatchNext(observer, changes.get(id));
|
|
32
32
|
});
|
|
33
33
|
}
|
|
34
34
|
add(ref, data) {
|
|
@@ -59,7 +59,7 @@ export class MemoryProvider extends Provider {
|
|
|
59
59
|
const table = this._table(ref);
|
|
60
60
|
// Call `next()` immediately with the initial results.
|
|
61
61
|
let lastResults = new Map(ref.derive(table.data));
|
|
62
|
-
dispatchNext(
|
|
62
|
+
dispatchNext(observer, lastResults);
|
|
63
63
|
// Possibly call `next()` when the collection changes if any changes affect the subscription.
|
|
64
64
|
return table.on(changes => {
|
|
65
65
|
for (const [id, next] of changes) {
|
|
@@ -71,7 +71,7 @@ export class MemoryProvider extends Provider {
|
|
|
71
71
|
const nextResults = new Map(ref.derive(table.data));
|
|
72
72
|
if (!isMapEqual(lastResults, nextResults)) {
|
|
73
73
|
lastResults = nextResults;
|
|
74
|
-
dispatchNext(
|
|
74
|
+
dispatchNext(observer, lastResults);
|
|
75
75
|
}
|
|
76
76
|
return;
|
|
77
77
|
}
|
|
@@ -99,11 +99,11 @@ class Table {
|
|
|
99
99
|
constructor() {
|
|
100
100
|
this.data = new Map();
|
|
101
101
|
this.changes = new Map();
|
|
102
|
-
this.
|
|
102
|
+
this.listeners = new Set();
|
|
103
103
|
this.fire = () => {
|
|
104
104
|
if (this.changes.size) {
|
|
105
|
-
for (const dispatcher of this.
|
|
106
|
-
|
|
105
|
+
for (const dispatcher of this.listeners)
|
|
106
|
+
dispatcher(this.changes);
|
|
107
107
|
this.changes.clear();
|
|
108
108
|
}
|
|
109
109
|
};
|
|
@@ -120,16 +120,16 @@ class Table {
|
|
|
120
120
|
this.changes.set(id, value);
|
|
121
121
|
}
|
|
122
122
|
}
|
|
123
|
-
on(
|
|
124
|
-
this.
|
|
125
|
-
return this.off.bind(this,
|
|
123
|
+
on(listener) {
|
|
124
|
+
this.listeners.add(listener);
|
|
125
|
+
return this.off.bind(this, listener);
|
|
126
126
|
}
|
|
127
|
-
off(
|
|
128
|
-
this.
|
|
127
|
+
off(listener) {
|
|
128
|
+
this.listeners.delete(listener);
|
|
129
129
|
}
|
|
130
130
|
reset() {
|
|
131
131
|
this.data.clear();
|
|
132
132
|
this.changes.clear();
|
|
133
|
-
this.
|
|
133
|
+
this.listeners.clear();
|
|
134
134
|
}
|
|
135
135
|
}
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { validate, ValidateObserver, callAsync } from "../util/index.js";
|
|
2
2
|
import { Transform, validateTransform } from "../transform/index.js";
|
|
3
|
-
import { throwFeedback } from "../feedback/index.js";
|
|
4
3
|
import { ThroughProvider } from "./ThroughProvider.js";
|
|
5
4
|
/** Validates any values that are read from or written to a source provider. */
|
|
6
5
|
export class ValidationProvider extends ThroughProvider {
|
|
@@ -11,7 +10,7 @@ export class ValidationProvider extends ThroughProvider {
|
|
|
11
10
|
return super.subscribe(ref, new ValidateObserver(ref, observer));
|
|
12
11
|
}
|
|
13
12
|
add(ref, data) {
|
|
14
|
-
return super.add(ref,
|
|
13
|
+
return super.add(ref, validate(data, ref.validator));
|
|
15
14
|
}
|
|
16
15
|
write(ref, value) {
|
|
17
16
|
return super.write(ref, value ? _validateWrite(value, ref.validator) : value);
|
|
@@ -28,5 +27,5 @@ export class ValidationProvider extends ThroughProvider {
|
|
|
28
27
|
}
|
|
29
28
|
/** Validate data or a transform for a path. */
|
|
30
29
|
function _validateWrite(value, validator) {
|
|
31
|
-
return
|
|
30
|
+
return value instanceof Transform ? validateTransform(value, validator) : validate(value, validator);
|
|
32
31
|
}
|
package/react/useDocument.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { useState } from "react";
|
|
2
|
-
import { CacheProvider, throwAsync, NOERROR, findSourceProvider, NOVALUE
|
|
2
|
+
import { CacheProvider, throwAsync, NOERROR, findSourceProvider, NOVALUE } from "../index.js";
|
|
3
3
|
import { usePureEffect } from "./usePureEffect.js";
|
|
4
4
|
import { usePureMemo } from "./usePureMemo.js";
|
|
5
5
|
import { usePureState } from "./usePureState.js";
|
|
@@ -22,7 +22,7 @@ export function useAsyncDocument(ref, maxAge = 1000) {
|
|
|
22
22
|
// If `maxAge` is `true` open a subscription for 10 seconds.
|
|
23
23
|
// Done before `ref.get()` because efficient providers (i.e. `BatchProvider`) will reuse the subscription's first result as its first get request.
|
|
24
24
|
if (maxAge === true)
|
|
25
|
-
setTimeout(ref.subscribe(setNext, setError), 10000);
|
|
25
|
+
setTimeout(ref.subscribe({ next: setNext, error: setError }), 10000);
|
|
26
26
|
// Return a promise for the result.
|
|
27
27
|
return ref.result;
|
|
28
28
|
}
|
|
@@ -49,7 +49,7 @@ function subscribeEffect(ref, maxAge, next, error) {
|
|
|
49
49
|
else {
|
|
50
50
|
// If cache provider's cached document is older than maxAge then force refresh the data.
|
|
51
51
|
if (provider.getCachedAge(ref) > maxAge)
|
|
52
|
-
|
|
52
|
+
Promise.resolve(ref.result).then(next, error);
|
|
53
53
|
}
|
|
54
54
|
return stopCache;
|
|
55
55
|
}
|
package/react/useFetch.js
CHANGED
|
@@ -23,7 +23,7 @@ export function useFetch(fetcher, deps, maxAge = 86400000) {
|
|
|
23
23
|
// Create a new state and start a fetch.
|
|
24
24
|
state = new State();
|
|
25
25
|
sources.set(key, state);
|
|
26
|
-
dispatchAsyncNext(fetcher(...deps)
|
|
26
|
+
dispatchAsyncNext(state, fetcher(...deps));
|
|
27
27
|
}
|
|
28
28
|
else if (state.closed) {
|
|
29
29
|
// Clean up source in a few seconds if it's closed.
|
|
@@ -32,7 +32,7 @@ export function useFetch(fetcher, deps, maxAge = 86400000) {
|
|
|
32
32
|
}
|
|
33
33
|
else if (state.age > maxAge) {
|
|
34
34
|
// Refetch if state has value and it's older than `maxAge`
|
|
35
|
-
dispatchAsyncNext(fetcher(...deps)
|
|
35
|
+
dispatchAsyncNext(state, fetcher(...deps));
|
|
36
36
|
}
|
|
37
37
|
useSubscribe(state);
|
|
38
38
|
return state;
|
package/react/usePureState.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Arguments
|
|
1
|
+
import { Arguments } from "../index.js";
|
|
2
2
|
/**
|
|
3
3
|
* Version of React's `useState()` that allows the use of a pure (side-effect free) function.
|
|
4
4
|
* - Unlike `useState()` the initialiser will be re-run and the state will be regenerated if `args` changes.
|
|
@@ -13,6 +13,6 @@ import { Arguments, Dispatcher } from "../index.js";
|
|
|
13
13
|
* - This means you can create the function once (outside the component) rather than creating it on every render.
|
|
14
14
|
* - This improves performance (though probably only noticeable on functions that render 1,000s of times).
|
|
15
15
|
*/
|
|
16
|
-
export declare function usePureState<T, A extends Arguments>(initial: (...args: A) => T, ...args: A): readonly [T,
|
|
17
|
-
export declare function usePureState<T, A extends Arguments>(initial: new (...args: A) => T, ...args: A): readonly [T,
|
|
18
|
-
export declare function usePureState<T>(initial: T, ...args: Arguments): readonly [T,
|
|
16
|
+
export declare function usePureState<T, A extends Arguments>(initial: (...args: A) => T, ...args: A): readonly [T, (next: T) => void];
|
|
17
|
+
export declare function usePureState<T, A extends Arguments>(initial: new (...args: A) => T, ...args: A): readonly [T, (next: T) => void];
|
|
18
|
+
export declare function usePureState<T>(initial: T, ...args: Arguments): readonly [T, (next: T) => void];
|
package/react/useQuery.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { useState } from "react";
|
|
2
|
-
import { CacheProvider, throwAsync, NOERROR, findSourceProvider, NOVALUE,
|
|
2
|
+
import { CacheProvider, throwAsync, NOERROR, findSourceProvider, NOVALUE, DeriveObserver, toMap, } from "../index.js";
|
|
3
3
|
import { usePureEffect } from "./usePureEffect.js";
|
|
4
4
|
import { usePureMemo } from "./usePureMemo.js";
|
|
5
5
|
import { usePureState } from "./usePureState.js";
|
|
@@ -22,7 +22,7 @@ export function useAsyncQuery(ref, maxAge = 1000) {
|
|
|
22
22
|
// If `maxAge` is `true` open a subscription for 10 seconds.
|
|
23
23
|
// Done before `ref.get()` because efficient providers (i.e. `BatchProvider`) will reuse the subscription's first result as its first get request.
|
|
24
24
|
if (maxAge === true)
|
|
25
|
-
setTimeout(ref.subscribeMap(setNext, setError), 10000);
|
|
25
|
+
setTimeout(ref.subscribeMap({ next: setNext, error: setError }), 10000);
|
|
26
26
|
// Return a promise for the result.
|
|
27
27
|
return ref.resultsMap;
|
|
28
28
|
}
|
|
@@ -50,7 +50,7 @@ function subscribeEffect(ref, maxAge, next, error) {
|
|
|
50
50
|
else {
|
|
51
51
|
// If cache provider's cached document is older than maxAge then force refresh the data.
|
|
52
52
|
if (provider.getCachedAge(ref) > maxAge)
|
|
53
|
-
|
|
53
|
+
Promise.resolve(ref.resultsMap).then(next, error);
|
|
54
54
|
}
|
|
55
55
|
return stopCache;
|
|
56
56
|
}
|
package/react/useSubscribe.js
CHANGED
|
@@ -14,4 +14,4 @@ export function useSubscribe(subscribable) {
|
|
|
14
14
|
usePureEffect(subscribeEffect, useState(LOADING)[1], subscribable);
|
|
15
15
|
}
|
|
16
16
|
/** Effect that subscribes the component to changes in the `State` instance for the lifetime of the component. */
|
|
17
|
-
const subscribeEffect = (
|
|
17
|
+
const subscribeEffect = (change, subscribable) => subscribable ? subscribe(subscribable, { next: change, error: change }) : undefined;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { StringSchema } from "./StringSchema.js";
|
|
2
|
+
/**
|
|
3
|
+
* Define a valid slug, e.g. `this-is-a-slug`
|
|
4
|
+
*
|
|
5
|
+
* - Useful for URL components, usernames, etc.
|
|
6
|
+
* - Minimum slug length is 2 characters.
|
|
7
|
+
* - Maximum slug length is 64 characters.
|
|
8
|
+
*/
|
|
9
|
+
export declare class SlugSchema extends StringSchema {
|
|
10
|
+
readonly multiline = false;
|
|
11
|
+
readonly min = 2;
|
|
12
|
+
readonly max = 32;
|
|
13
|
+
sanitize(unsafeString: string): string;
|
|
14
|
+
}
|
|
15
|
+
/** Valid slug, e.g. `this-is-a-slug` */
|
|
16
|
+
export declare const SLUG: SlugSchema;
|
|
17
|
+
/** Valid slug, e.g. `this-is-a-slug`, or `null` */
|
|
18
|
+
export declare const OPTIONAL_SLUG: import("./OptionalSchema.js").OptionalSchema<string>;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { toSlug } from "../util/index.js";
|
|
2
|
+
import { OPTIONAL } from "./OptionalSchema.js";
|
|
3
|
+
import { StringSchema } from "./StringSchema.js";
|
|
4
|
+
/**
|
|
5
|
+
* Define a valid slug, e.g. `this-is-a-slug`
|
|
6
|
+
*
|
|
7
|
+
* - Useful for URL components, usernames, etc.
|
|
8
|
+
* - Minimum slug length is 2 characters.
|
|
9
|
+
* - Maximum slug length is 64 characters.
|
|
10
|
+
*/
|
|
11
|
+
export class SlugSchema extends StringSchema {
|
|
12
|
+
constructor() {
|
|
13
|
+
super(...arguments);
|
|
14
|
+
this.multiline = false;
|
|
15
|
+
this.min = 2;
|
|
16
|
+
this.max = 32;
|
|
17
|
+
}
|
|
18
|
+
sanitize(unsafeString) {
|
|
19
|
+
return toSlug(unsafeString);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
/** Valid slug, e.g. `this-is-a-slug` */
|
|
23
|
+
export const SLUG = new SlugSchema({});
|
|
24
|
+
/** Valid slug, e.g. `this-is-a-slug`, or `null` */
|
|
25
|
+
export const OPTIONAL_SLUG = OPTIONAL(SLUG);
|
package/schema/index.d.ts
CHANGED
|
@@ -7,12 +7,13 @@ export * from "./DataSchema.js";
|
|
|
7
7
|
export * from "./DateSchema.js";
|
|
8
8
|
export * from "./EmailSchema.js";
|
|
9
9
|
export * from "./KeySchema.js";
|
|
10
|
+
export * from "./LinkSchema.js";
|
|
10
11
|
export * from "./MapSchema.js";
|
|
11
|
-
export * from "./OptionalSchema.js";
|
|
12
12
|
export * from "./NumberSchema.js";
|
|
13
13
|
export * from "./ObjectSchema.js";
|
|
14
|
+
export * from "./OptionalSchema.js";
|
|
14
15
|
export * from "./PhoneSchema.js";
|
|
15
16
|
export * from "./RequiredSchema.js";
|
|
17
|
+
export * from "./SlugSchema.js";
|
|
16
18
|
export * from "./StringSchema.js";
|
|
17
19
|
export * from "./ThroughSchema.js";
|
|
18
|
-
export * from "./LinkSchema.js";
|
package/schema/index.js
CHANGED
|
@@ -7,12 +7,13 @@ export * from "./DataSchema.js";
|
|
|
7
7
|
export * from "./DateSchema.js";
|
|
8
8
|
export * from "./EmailSchema.js";
|
|
9
9
|
export * from "./KeySchema.js";
|
|
10
|
+
export * from "./LinkSchema.js";
|
|
10
11
|
export * from "./MapSchema.js";
|
|
11
|
-
export * from "./OptionalSchema.js";
|
|
12
12
|
export * from "./NumberSchema.js";
|
|
13
13
|
export * from "./ObjectSchema.js";
|
|
14
|
+
export * from "./OptionalSchema.js";
|
|
14
15
|
export * from "./PhoneSchema.js";
|
|
15
16
|
export * from "./RequiredSchema.js";
|
|
17
|
+
export * from "./SlugSchema.js";
|
|
16
18
|
export * from "./StringSchema.js";
|
|
17
19
|
export * from "./ThroughSchema.js";
|
|
18
|
-
export * from "./LinkSchema.js";
|
package/stream/LastStream.js
CHANGED
|
@@ -4,7 +4,7 @@ import { Stream } from "./Stream.js";
|
|
|
4
4
|
export class LastStream extends Stream {
|
|
5
5
|
// Override to dispatch only to a slice of the subscribers.
|
|
6
6
|
_dispatch(value) {
|
|
7
|
-
const subscriber = getLastItem(this.
|
|
7
|
+
const subscriber = getLastItem(this._observers);
|
|
8
8
|
if (subscriber)
|
|
9
9
|
dispatchNext(subscriber, value);
|
|
10
10
|
}
|
package/stream/LazyState.d.ts
CHANGED
package/stream/LazyState.js
CHANGED
|
@@ -9,20 +9,20 @@ export class LazyState extends State {
|
|
|
9
9
|
this._delay = delay;
|
|
10
10
|
}
|
|
11
11
|
// Override to stop the source subscription when the last subscriber unsubscribes.
|
|
12
|
-
|
|
13
|
-
super.
|
|
12
|
+
_off(observer) {
|
|
13
|
+
super._off(observer);
|
|
14
14
|
if (this._delay) {
|
|
15
15
|
// Maybe stop in a bit (if there are still no subscribers).
|
|
16
16
|
if (this._timeout)
|
|
17
17
|
clearTimeout(this._timeout);
|
|
18
18
|
this._timeout = setTimeout(() => {
|
|
19
|
-
if (!this.
|
|
19
|
+
if (!this._observers.size && !this.closed)
|
|
20
20
|
this.complete();
|
|
21
21
|
}, this._delay);
|
|
22
22
|
}
|
|
23
23
|
else {
|
|
24
24
|
// Stop now.
|
|
25
|
-
if (!this.
|
|
25
|
+
if (!this._observers.size && !this.closed)
|
|
26
26
|
this.complete();
|
|
27
27
|
}
|
|
28
28
|
}
|
package/stream/LazyStream.d.ts
CHANGED
package/stream/LazyStream.js
CHANGED
|
@@ -9,19 +9,19 @@ export class LazyStream extends Stream {
|
|
|
9
9
|
this._delay = delay;
|
|
10
10
|
}
|
|
11
11
|
// Override to stop the source subscription when the last subscriber unsubscribes.
|
|
12
|
-
|
|
13
|
-
super.
|
|
12
|
+
_off(observer) {
|
|
13
|
+
super._off(observer);
|
|
14
14
|
if (this._delay) {
|
|
15
15
|
// Maybe stop in a bit (if there are still no subscribers).
|
|
16
|
-
if (!this.
|
|
16
|
+
if (!this._observers.size && !this.closed) {
|
|
17
17
|
if (this._timeout)
|
|
18
18
|
clearTimeout(this._timeout);
|
|
19
|
-
this._timeout = setTimeout(() => !this.
|
|
19
|
+
this._timeout = setTimeout(() => !this._observers.size && !this.closed && this.complete(), this._delay);
|
|
20
20
|
}
|
|
21
21
|
}
|
|
22
22
|
else {
|
|
23
23
|
// Stop now.
|
|
24
|
-
if (!this.
|
|
24
|
+
if (!this._observers.size && !this.closed)
|
|
25
25
|
this.complete();
|
|
26
26
|
}
|
|
27
27
|
}
|
package/stream/State.d.ts
CHANGED
|
@@ -35,7 +35,7 @@ export declare class State<T> extends Stream<T> {
|
|
|
35
35
|
/** Apply a deriver to this state. */
|
|
36
36
|
apply(deriver: Deriver<T, T>): void;
|
|
37
37
|
error(reason: Error | unknown): void;
|
|
38
|
-
|
|
38
|
+
_on(observer: Observer<T>): void;
|
|
39
39
|
protected _dispatch(value: T): void;
|
|
40
40
|
}
|
|
41
41
|
/** Create a state with an initial value. */
|
package/stream/State.js
CHANGED
|
@@ -45,14 +45,14 @@ export class State extends Stream {
|
|
|
45
45
|
super.error(reason);
|
|
46
46
|
}
|
|
47
47
|
// Override to send the current error or value to any new subscribers.
|
|
48
|
-
|
|
49
|
-
super.
|
|
48
|
+
_on(observer) {
|
|
49
|
+
super._on(observer);
|
|
50
50
|
if (this.reason !== NOERROR)
|
|
51
|
-
dispatchError(this.reason
|
|
51
|
+
dispatchError(observer, this.reason);
|
|
52
52
|
else if (this.closed)
|
|
53
53
|
dispatchComplete(observer);
|
|
54
54
|
else if (this._value !== LOADING)
|
|
55
|
-
dispatchNext(this.
|
|
55
|
+
dispatchNext(observer, this._value);
|
|
56
56
|
}
|
|
57
57
|
// Dispatcher saves any values that are dispatched.
|
|
58
58
|
_dispatch(value) {
|
package/stream/Stream.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Deriver, ObserverType, Subscribable,
|
|
1
|
+
import { Deriver, ObserverType, Subscribable, Unsubscriber, Observer, Observable, Constructor, Dispatcher } from "../util/index.js";
|
|
2
2
|
/** Any stream (useful for `extends AnyStream` clauses). */
|
|
3
3
|
export declare type AnyStream = Stream<any>;
|
|
4
4
|
/**
|
|
@@ -11,7 +11,7 @@ export declare class Stream<T> implements Observer<T>, Observable<T> {
|
|
|
11
11
|
/** List of sources this stream is subscribed to. */
|
|
12
12
|
protected readonly _cleanups: Set<Unsubscriber>;
|
|
13
13
|
/** List of subscribed observers that values are forwarded to. */
|
|
14
|
-
protected readonly
|
|
14
|
+
protected readonly _observers: Set<Observer<T>>;
|
|
15
15
|
/** Get the number of current subscribers. */
|
|
16
16
|
get subscribers(): number;
|
|
17
17
|
/** Is this stream open or closed (i.e. `error()` or `complete()` have been called. */
|
|
@@ -55,9 +55,9 @@ export declare class Stream<T> implements Observer<T>, Observable<T> {
|
|
|
55
55
|
* - Allows either an `Observer` object or separate `next()`, `error()` and `complete()` functions.
|
|
56
56
|
* - Implements `Observable`
|
|
57
57
|
*/
|
|
58
|
-
subscribe(next: Observer<T> | Dispatcher<T
|
|
59
|
-
/** Add an observer
|
|
60
|
-
|
|
61
|
-
/** Remove an observer
|
|
62
|
-
|
|
58
|
+
subscribe(next: Observer<T> | Dispatcher<[T]>): Unsubscriber;
|
|
59
|
+
/** Add an observer. */
|
|
60
|
+
_on(observer: Observer<T>): void;
|
|
61
|
+
/** Remove an observer. */
|
|
62
|
+
_off(observer: Observer<T>): void;
|
|
63
63
|
}
|
package/stream/Stream.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
var _a;
|
|
2
|
-
import { AsyncObserver, DeriveObserver, dispatchNext, dispatchError, dispatchComplete,
|
|
2
|
+
import { AsyncObserver, DeriveObserver, dispatchNext, dispatchError, dispatchComplete, subscribe, dispatch, } from "../util/index.js";
|
|
3
3
|
import { ConditionError } from "../error/index.js";
|
|
4
4
|
/**
|
|
5
5
|
* Simple stream.
|
|
@@ -10,13 +10,13 @@ export class Stream {
|
|
|
10
10
|
/** List of sources this stream is subscribed to. */
|
|
11
11
|
this._cleanups = new Set();
|
|
12
12
|
/** List of subscribed observers that values are forwarded to. */
|
|
13
|
-
this.
|
|
13
|
+
this._observers = new Set();
|
|
14
14
|
/** Is this stream open or closed (i.e. `error()` or `complete()` have been called. */
|
|
15
15
|
this.closed = false;
|
|
16
16
|
}
|
|
17
17
|
/** Get the number of current subscribers. */
|
|
18
18
|
get subscribers() {
|
|
19
|
-
return this.
|
|
19
|
+
return this._observers.size;
|
|
20
20
|
}
|
|
21
21
|
/**
|
|
22
22
|
* Send a next value.
|
|
@@ -29,8 +29,8 @@ export class Stream {
|
|
|
29
29
|
}
|
|
30
30
|
/** Call `next()` on the subscribers. */
|
|
31
31
|
_dispatch(value) {
|
|
32
|
-
for (const
|
|
33
|
-
dispatchNext(
|
|
32
|
+
for (const observer of this._observers)
|
|
33
|
+
dispatchNext(observer, value);
|
|
34
34
|
}
|
|
35
35
|
/**
|
|
36
36
|
* Complete this stream with an error.
|
|
@@ -41,9 +41,9 @@ export class Stream {
|
|
|
41
41
|
if (this.closed)
|
|
42
42
|
throw new ConditionError("Stream is closed");
|
|
43
43
|
this._close();
|
|
44
|
-
for (const subscriber of this.
|
|
45
|
-
|
|
46
|
-
|
|
44
|
+
for (const subscriber of this._observers) {
|
|
45
|
+
this._observers.delete(subscriber);
|
|
46
|
+
dispatchError(subscriber, reason);
|
|
47
47
|
}
|
|
48
48
|
}
|
|
49
49
|
/**
|
|
@@ -55,17 +55,17 @@ export class Stream {
|
|
|
55
55
|
if (this.closed)
|
|
56
56
|
throw new ConditionError("Stream is closed");
|
|
57
57
|
this._close();
|
|
58
|
-
for (const subscriber of this.
|
|
58
|
+
for (const subscriber of this._observers) {
|
|
59
|
+
this._observers.delete(subscriber);
|
|
59
60
|
dispatchComplete(subscriber);
|
|
60
|
-
this.off(subscriber);
|
|
61
61
|
}
|
|
62
62
|
}
|
|
63
63
|
/** Close this stream. */
|
|
64
64
|
_close() {
|
|
65
65
|
this.closed = true;
|
|
66
66
|
for (const cleanup of this._cleanups) {
|
|
67
|
-
dispatch(undefined, cleanup);
|
|
68
67
|
this._cleanups.delete(cleanup);
|
|
68
|
+
dispatch(cleanup);
|
|
69
69
|
}
|
|
70
70
|
}
|
|
71
71
|
/** Start a subscription that gets cleaned up when this subscriber ends. */
|
|
@@ -102,18 +102,18 @@ export class Stream {
|
|
|
102
102
|
* - Allows either an `Observer` object or separate `next()`, `error()` and `complete()` functions.
|
|
103
103
|
* - Implements `Observable`
|
|
104
104
|
*/
|
|
105
|
-
subscribe(next
|
|
106
|
-
const observer =
|
|
107
|
-
this.
|
|
108
|
-
return this.
|
|
105
|
+
subscribe(next) {
|
|
106
|
+
const observer = typeof next === "function" ? { next } : next;
|
|
107
|
+
this._on(observer);
|
|
108
|
+
return this._off.bind(this, observer);
|
|
109
109
|
}
|
|
110
|
-
/** Add an observer
|
|
111
|
-
|
|
112
|
-
this.
|
|
110
|
+
/** Add an observer. */
|
|
111
|
+
_on(observer) {
|
|
112
|
+
this._observers.add(observer);
|
|
113
113
|
}
|
|
114
|
-
/** Remove an observer
|
|
115
|
-
|
|
116
|
-
this.
|
|
114
|
+
/** Remove an observer. */
|
|
115
|
+
_off(observer) {
|
|
116
|
+
this._observers.delete(observer);
|
|
117
117
|
}
|
|
118
118
|
}
|
|
119
119
|
_a = Symbol.species;
|
package/util/async.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { DONE } from "./constants.js";
|
|
2
|
-
import
|
|
3
|
-
import type { Arguments } from "./function.js";
|
|
2
|
+
import { Handler } from "./error.js";
|
|
3
|
+
import type { Arguments, Dispatcher } from "./function.js";
|
|
4
4
|
/**
|
|
5
5
|
* Throw the value if it's an async (promised) value.
|
|
6
6
|
* @returns Synchronous (not promised) value.
|
|
@@ -15,15 +15,15 @@ export declare const _awaitCallAsync: <I, O, A extends Arguments>(callback: (v:
|
|
|
15
15
|
/** Type of `Promise` with its `resolve()` and `reject()` methods exposed publicly. */
|
|
16
16
|
export declare class Deferred<T> extends Promise<T> {
|
|
17
17
|
static get [Symbol.species](): PromiseConstructor;
|
|
18
|
-
readonly resolve: Dispatcher<T
|
|
19
|
-
readonly reject:
|
|
18
|
+
readonly resolve: Dispatcher<[T]>;
|
|
19
|
+
readonly reject: Handler;
|
|
20
20
|
constructor();
|
|
21
21
|
}
|
|
22
22
|
/** Type of `Promise` with `._resolve()` and `._reject()` methods available. */
|
|
23
23
|
export declare abstract class AbstractPromise<T> extends Promise<T> {
|
|
24
24
|
static get [Symbol.species](): PromiseConstructor;
|
|
25
|
-
protected readonly _resolve: Dispatcher<T
|
|
26
|
-
protected readonly _reject:
|
|
25
|
+
protected readonly _resolve: Dispatcher<[T]>;
|
|
26
|
+
protected readonly _reject: Handler;
|
|
27
27
|
constructor();
|
|
28
28
|
}
|
|
29
29
|
/** Promise that resolves after a specified delay in milliseconds. */
|
package/util/error.js
CHANGED
package/util/function.d.ts
CHANGED
|
@@ -8,3 +8,11 @@ export declare type Arguments = readonly unknown[];
|
|
|
8
8
|
export declare const PASSTHROUGH: <T>(value: T) => T;
|
|
9
9
|
/** Function that does nothing with its arguments and always returns void. */
|
|
10
10
|
export declare const BLACKHOLE: (...args: Arguments) => void | undefined;
|
|
11
|
+
/** Function that receives a dispatched value. */
|
|
12
|
+
export declare type Dispatcher<T extends Arguments = []> = (...value: T) => void;
|
|
13
|
+
/** Safely dispatch a value to a dispatcher function. */
|
|
14
|
+
export declare function dispatch<T extends Arguments>(dispatcher: Dispatcher<T>, ...value: T): void;
|
|
15
|
+
/** Safely dispatch a value to a dispatcher method on an object. */
|
|
16
|
+
export declare function dispatchMethod<T extends Arguments, M extends string | symbol>(obj: {
|
|
17
|
+
[K in M]: Dispatcher<T>;
|
|
18
|
+
}, key: M, ...value: T): void;
|
package/util/function.js
CHANGED
|
@@ -1,6 +1,25 @@
|
|
|
1
|
+
import { logError } from "./error.js";
|
|
1
2
|
/** Is a value a function? */
|
|
2
3
|
export const isFunction = (v) => typeof v === "function";
|
|
3
4
|
/** Function that just passes through the first argument. */
|
|
4
5
|
export const PASSTHROUGH = (value) => value;
|
|
5
6
|
/** Function that does nothing with its arguments and always returns void. */
|
|
6
7
|
export const BLACKHOLE = () => undefined;
|
|
8
|
+
/** Safely dispatch a value to a dispatcher function. */
|
|
9
|
+
export function dispatch(dispatcher, ...value) {
|
|
10
|
+
try {
|
|
11
|
+
dispatcher(...value);
|
|
12
|
+
}
|
|
13
|
+
catch (thrown) {
|
|
14
|
+
logError(thrown);
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
/** Safely dispatch a value to a dispatcher method on an object. */
|
|
18
|
+
export function dispatchMethod(obj, key, ...value) {
|
|
19
|
+
try {
|
|
20
|
+
obj[key](...value);
|
|
21
|
+
}
|
|
22
|
+
catch (thrown) {
|
|
23
|
+
logError(thrown);
|
|
24
|
+
}
|
|
25
|
+
}
|
package/util/index.d.ts
CHANGED
package/util/index.js
CHANGED
package/util/observable.d.ts
CHANGED
|
@@ -1,14 +1,12 @@
|
|
|
1
|
-
import { Dispatcher } from "./
|
|
1
|
+
import { Dispatcher } from "./function.js";
|
|
2
|
+
import { Handler } from "./error.js";
|
|
2
3
|
import { Deriver } from "./derive.js";
|
|
3
4
|
import { Validator } from "./validate.js";
|
|
4
5
|
/** Function that ends a subscription. */
|
|
5
6
|
export declare type Unsubscriber = () => void;
|
|
6
7
|
/** An object that can initiate a subscription with its `subscribe()`. */
|
|
7
8
|
export interface Observable<T> {
|
|
8
|
-
|
|
9
|
-
subscribe(observer: Observer<T>): Unsubscriber;
|
|
10
|
-
subscribe(next: Dispatcher<T>, error?: Dispatcher<unknown>, complete?: Dispatcher<void>): Unsubscriber;
|
|
11
|
-
subscribe(either: Observer<T> | Dispatcher<T>, error?: Dispatcher<unknown>, complete?: Dispatcher<void>): Unsubscriber;
|
|
9
|
+
subscribe(observer: Observer<T> | Dispatcher<[T]>): Unsubscriber;
|
|
12
10
|
}
|
|
13
11
|
/** Any observable (useful for `extends AnyObservable` clauses). */
|
|
14
12
|
export declare type AnyObservable = Observable<any>;
|
|
@@ -40,11 +38,11 @@ export interface Observer<T> {
|
|
|
40
38
|
*/
|
|
41
39
|
readonly from?: (source: Subscribable<T>) => this;
|
|
42
40
|
/** Receive the next value. */
|
|
43
|
-
readonly next
|
|
41
|
+
readonly next: Dispatcher<[T]>;
|
|
44
42
|
/** End the subscription with an error. */
|
|
45
|
-
readonly error?:
|
|
43
|
+
readonly error?: Handler;
|
|
46
44
|
/** End the subscription with success. */
|
|
47
|
-
readonly complete?: Dispatcher
|
|
45
|
+
readonly complete?: Dispatcher;
|
|
48
46
|
/** Whether the subscription has ended (either with success or failure). */
|
|
49
47
|
readonly closed?: boolean;
|
|
50
48
|
}
|
|
@@ -53,15 +51,13 @@ export declare type ObserverType<T extends AnyObserver> = T extends Observer<inf
|
|
|
53
51
|
/** Any observer (useful for `extends AnyObserver` clauses). */
|
|
54
52
|
export declare type AnyObserver = Observer<any>;
|
|
55
53
|
/** Dispatch the next value to an observer (and if the next value errors, calls a handler). */
|
|
56
|
-
export declare function dispatchNext<T>(
|
|
54
|
+
export declare function dispatchNext<T>(observer: Observer<T>, value: T): void;
|
|
57
55
|
/** Dispatch the next value to an observer (and if the next value errors, calls a handler). */
|
|
58
|
-
export declare function dispatchAsyncNext<T>(
|
|
56
|
+
export declare function dispatchAsyncNext<T>(observer: Observer<T>, value: PromiseLike<T>): void;
|
|
59
57
|
/** Dispatch a complete call an observer (and if the next value errors, calls a handler). */
|
|
60
|
-
export declare function dispatchComplete<T>(observer: Observer<T
|
|
58
|
+
export declare function dispatchComplete<T>(observer: Observer<T>): void;
|
|
61
59
|
/** Dispatch an error value to an observer. */
|
|
62
|
-
export declare function dispatchError<T>(
|
|
63
|
-
/** Create an `Observer` from a set `next()`, `error()` and `complete()` functions. */
|
|
64
|
-
export declare function createObserver<T>(next: Observer<T> | Dispatcher<T>, error?: Dispatcher<unknown>, complete?: Dispatcher<void>): Observer<T>;
|
|
60
|
+
export declare function dispatchError<T>(observer: Observer<T>, reason: Error | unknown): void;
|
|
65
61
|
/** Abstract observer designed to pass values through to an observer. */
|
|
66
62
|
export declare abstract class AbstractObserver<I, O> implements Observer<I> {
|
|
67
63
|
protected _cleanup: Unsubscriber | undefined;
|
package/util/observable.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ConditionError } from "../error/index.js";
|
|
2
|
-
import { dispatch } from "./
|
|
2
|
+
import { BLACKHOLE, dispatch } from "./function.js";
|
|
3
3
|
import { logError } from "./error.js";
|
|
4
4
|
import { isData } from "./data.js";
|
|
5
5
|
import { derive } from "./derive.js";
|
|
@@ -15,44 +15,38 @@ export function subscribe(source, target) {
|
|
|
15
15
|
return typeof source === "function" ? source(target) : source.subscribe(target);
|
|
16
16
|
}
|
|
17
17
|
/** Dispatch the next value to an observer (and if the next value errors, calls a handler). */
|
|
18
|
-
export function dispatchNext(
|
|
19
|
-
var _a;
|
|
18
|
+
export function dispatchNext(observer, value) {
|
|
20
19
|
try {
|
|
21
|
-
|
|
20
|
+
observer.next(value);
|
|
22
21
|
}
|
|
23
22
|
catch (thrown) {
|
|
24
|
-
|
|
23
|
+
logError(thrown);
|
|
25
24
|
}
|
|
26
25
|
}
|
|
27
26
|
/** Dispatch the next value to an observer (and if the next value errors, calls a handler). */
|
|
28
|
-
export function dispatchAsyncNext(
|
|
29
|
-
|
|
30
|
-
value.then(v => dispatchNext(v, observer, handler), handler);
|
|
27
|
+
export function dispatchAsyncNext(observer, value) {
|
|
28
|
+
value.then(v => dispatchNext(observer, v), logError);
|
|
31
29
|
}
|
|
32
30
|
/** Dispatch a complete call an observer (and if the next value errors, calls a handler). */
|
|
33
|
-
export function dispatchComplete(observer
|
|
31
|
+
export function dispatchComplete(observer) {
|
|
34
32
|
var _a;
|
|
35
33
|
try {
|
|
36
34
|
(_a = observer.complete) === null || _a === void 0 ? void 0 : _a.call(observer);
|
|
37
35
|
}
|
|
38
36
|
catch (thrown) {
|
|
39
|
-
|
|
37
|
+
logError(thrown);
|
|
40
38
|
}
|
|
41
39
|
}
|
|
42
40
|
/** Dispatch an error value to an observer. */
|
|
43
|
-
export function dispatchError(
|
|
41
|
+
export function dispatchError(observer, reason) {
|
|
44
42
|
var _a;
|
|
45
43
|
try {
|
|
46
44
|
(_a = observer.error) === null || _a === void 0 ? void 0 : _a.call(observer, reason);
|
|
47
45
|
}
|
|
48
46
|
catch (thrown) {
|
|
49
|
-
|
|
47
|
+
logError(thrown);
|
|
50
48
|
}
|
|
51
49
|
}
|
|
52
|
-
/** Create an `Observer` from a set `next()`, `error()` and `complete()` functions. */
|
|
53
|
-
export function createObserver(next, error, complete) {
|
|
54
|
-
return typeof next === "object" ? next : { next, error, complete };
|
|
55
|
-
}
|
|
56
50
|
/** Abstract observer designed to pass values through to an observer. */
|
|
57
51
|
export class AbstractObserver {
|
|
58
52
|
constructor(target) {
|
|
@@ -78,7 +72,7 @@ export class AbstractObserver {
|
|
|
78
72
|
if (!target)
|
|
79
73
|
throw new ConditionError("Observer is closed");
|
|
80
74
|
this._close();
|
|
81
|
-
dispatchError(
|
|
75
|
+
dispatchError(target, reason);
|
|
82
76
|
}
|
|
83
77
|
complete() {
|
|
84
78
|
const target = this._target;
|
|
@@ -91,7 +85,7 @@ export class AbstractObserver {
|
|
|
91
85
|
if (this._target)
|
|
92
86
|
this._target = undefined;
|
|
93
87
|
if (this._cleanup)
|
|
94
|
-
this._cleanup = void dispatch(
|
|
88
|
+
this._cleanup = void dispatch(this._cleanup);
|
|
95
89
|
}
|
|
96
90
|
}
|
|
97
91
|
/** Observer that unsubscribes.*/
|
|
@@ -99,7 +93,7 @@ export class ThroughObserver extends AbstractObserver {
|
|
|
99
93
|
next(value) {
|
|
100
94
|
if (!this._target)
|
|
101
95
|
throw new ConditionError("Observer is closed");
|
|
102
|
-
dispatchNext(
|
|
96
|
+
dispatchNext(this._target, value);
|
|
103
97
|
}
|
|
104
98
|
}
|
|
105
99
|
/** Observer that fires once then ends itself. */
|
|
@@ -119,7 +113,7 @@ export class DeriveObserver extends AbstractObserver {
|
|
|
119
113
|
const target = this._target;
|
|
120
114
|
if (!target)
|
|
121
115
|
throw new ConditionError("Observer is closed");
|
|
122
|
-
dispatchNext(derive(value, this._deriver)
|
|
116
|
+
dispatchNext(target, derive(value, this._deriver));
|
|
123
117
|
}
|
|
124
118
|
}
|
|
125
119
|
/** Observer that validates its next values with a validator. */
|
|
@@ -132,7 +126,7 @@ export class ValidateObserver extends AbstractObserver {
|
|
|
132
126
|
const target = this._target;
|
|
133
127
|
if (!target)
|
|
134
128
|
throw new ConditionError("Observer is closed");
|
|
135
|
-
dispatchNext(validate(value, this._validator)
|
|
129
|
+
dispatchNext(target, validate(value, this._validator));
|
|
136
130
|
}
|
|
137
131
|
}
|
|
138
132
|
/** Oserver that allows promised values to be passed to `next()`. */
|
|
@@ -141,7 +135,7 @@ export class AsyncObserver extends AbstractObserver {
|
|
|
141
135
|
const target = this._target;
|
|
142
136
|
if (!target)
|
|
143
137
|
throw new ConditionError("Observer is closed");
|
|
144
|
-
dispatchAsyncNext(
|
|
138
|
+
dispatchAsyncNext(target, value);
|
|
145
139
|
}
|
|
146
140
|
}
|
|
147
141
|
/** Get a promise that resolves to the next value of a source subscribable. */
|
|
@@ -150,5 +144,5 @@ export function awaitNext(source) {
|
|
|
150
144
|
}
|
|
151
145
|
/** Get a promise that resolves when a source subscribable is complete. */
|
|
152
146
|
export function awaitComplete(source) {
|
|
153
|
-
return new Promise((complete, error) => new ThroughObserver({ complete, error }).from(source));
|
|
147
|
+
return new Promise((complete, error) => new ThroughObserver({ next: BLACKHOLE, complete, error }).from(source));
|
|
154
148
|
}
|
package/feedback/util.d.ts
DELETED
package/feedback/util.js
DELETED
package/util/dispatch.d.ts
DELETED
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
/** Function that dispatches a value (we never care about the returned value). */
|
|
2
|
-
export declare type Dispatcher<T> = (value: T) => void;
|
|
3
|
-
/**
|
|
4
|
-
* Safely dispatch a value to a dispatcher function.
|
|
5
|
-
*
|
|
6
|
-
* @param value The value to dispatch into the dispatcher function.
|
|
7
|
-
* @param dispatcher Any dispatcher function.
|
|
8
|
-
* - Any errors thrown or rejected by the dispatcher are caught and routed to the catcher.
|
|
9
|
-
* @param handler Handler that handles any thrown errors.
|
|
10
|
-
*/
|
|
11
|
-
export declare function dispatch<T>(value: T, dispatcher: Dispatcher<T>, handler?: import("./error.js").Handler): void;
|
|
12
|
-
/** Safely dispatch an async value to a dispatcher function. */
|
|
13
|
-
export declare function dispatchAsync<T>(value: T | PromiseLike<T>, dispatcher: Dispatcher<T>, handler?: import("./error.js").Handler): void;
|
|
14
|
-
/**
|
|
15
|
-
* Safely dispatch a value to a dispatcher method on an object.
|
|
16
|
-
*
|
|
17
|
-
* @param value The value to dispatch into the dispatcher method.
|
|
18
|
-
* @param obj The object containing the method.
|
|
19
|
-
* @param key The key specifiying which method to call (if the method is not defined, nothing will be dispatched).
|
|
20
|
-
* - Any errors thrown or rejected by the dispatcher are caught and routed to the catcher.
|
|
21
|
-
* @param handler Handler that handles any thrown errors.
|
|
22
|
-
*/
|
|
23
|
-
export declare function thispatch<T, M extends string | symbol>(value: T, obj: {
|
|
24
|
-
[K in M]: Dispatcher<T>;
|
|
25
|
-
}, key: M, handler?: import("./error.js").Handler): void;
|
|
26
|
-
/** Safely dispatch an async value to a dispatcher method on an object. */
|
|
27
|
-
export declare function thispatchAsync<T, M extends string | symbol>(value: T | PromiseLike<T>, obj: {
|
|
28
|
-
[K in M]: Dispatcher<T>;
|
|
29
|
-
}, key: M, handler?: import("./error.js").Handler): void;
|
package/util/dispatch.js
DELETED
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
import { logError } from "./error.js";
|
|
2
|
-
import { callAsync } from "./async.js";
|
|
3
|
-
/**
|
|
4
|
-
* Safely dispatch a value to a dispatcher function.
|
|
5
|
-
*
|
|
6
|
-
* @param value The value to dispatch into the dispatcher function.
|
|
7
|
-
* @param dispatcher Any dispatcher function.
|
|
8
|
-
* - Any errors thrown or rejected by the dispatcher are caught and routed to the catcher.
|
|
9
|
-
* @param handler Handler that handles any thrown errors.
|
|
10
|
-
*/
|
|
11
|
-
export function dispatch(value, dispatcher, handler = logError) {
|
|
12
|
-
try {
|
|
13
|
-
dispatcher(value);
|
|
14
|
-
}
|
|
15
|
-
catch (thrown) {
|
|
16
|
-
handler(thrown);
|
|
17
|
-
}
|
|
18
|
-
}
|
|
19
|
-
/** Safely dispatch an async value to a dispatcher function. */
|
|
20
|
-
export function dispatchAsync(value, dispatcher, handler = logError) {
|
|
21
|
-
void callAsync(dispatch, value, dispatcher, handler);
|
|
22
|
-
}
|
|
23
|
-
/**
|
|
24
|
-
* Safely dispatch a value to a dispatcher method on an object.
|
|
25
|
-
*
|
|
26
|
-
* @param value The value to dispatch into the dispatcher method.
|
|
27
|
-
* @param obj The object containing the method.
|
|
28
|
-
* @param key The key specifiying which method to call (if the method is not defined, nothing will be dispatched).
|
|
29
|
-
* - Any errors thrown or rejected by the dispatcher are caught and routed to the catcher.
|
|
30
|
-
* @param handler Handler that handles any thrown errors.
|
|
31
|
-
*/
|
|
32
|
-
export function thispatch(value, obj, key, handler = logError) {
|
|
33
|
-
try {
|
|
34
|
-
obj[key](value);
|
|
35
|
-
}
|
|
36
|
-
catch (thrown) {
|
|
37
|
-
handler(thrown);
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
/** Safely dispatch an async value to a dispatcher method on an object. */
|
|
41
|
-
export function thispatchAsync(value, obj, key, handler = logError) {
|
|
42
|
-
void callAsync(thispatch, value, obj, key, handler);
|
|
43
|
-
}
|