shelving 1.26.0 → 1.29.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/api/Resource.js +2 -2
- package/db/Database.d.ts +9 -9
- package/db/Database.js +7 -8
- package/db/Pagination.d.ts +2 -10
- package/db/Pagination.js +16 -39
- package/db/Write.d.ts +1 -1
- package/db/Write.js +2 -2
- package/firestore/client/FirestoreClientProvider.d.ts +3 -3
- package/firestore/client/FirestoreClientProvider.js +4 -8
- package/firestore/lite/FirestoreLiteProvider.d.ts +3 -3
- package/firestore/lite/FirestoreLiteProvider.js +3 -0
- package/firestore/server/FirestoreServerProvider.d.ts +3 -3
- package/firestore/server/FirestoreServerProvider.js +9 -6
- package/package.json +1 -1
- package/provider/CacheProvider.d.ts +3 -3
- package/provider/CacheProvider.js +6 -3
- package/provider/MemoryProvider.d.ts +3 -3
- package/provider/MemoryProvider.js +15 -3
- package/provider/Provider.d.ts +12 -9
- package/provider/ThroughProvider.d.ts +3 -3
- package/provider/ValidationProvider.d.ts +2 -2
- package/stream/DataState.d.ts +17 -2
- package/stream/DataState.js +35 -4
- package/stream/State.d.ts +0 -2
- package/stream/State.js +1 -9
- package/util/data.d.ts +0 -3
- package/util/data.js +0 -5
- package/util/null.d.ts +12 -1
- package/util/null.js +11 -1
- package/util/object.d.ts +8 -0
- package/util/object.js +4 -0
- package/util/undefined.d.ts +1 -3
- package/util/undefined.js +1 -3
- package/util/url.d.ts +8 -9
- package/util/url.js +16 -15
package/api/Resource.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { GET_UNDEFINED, validate } from "../util/index.js";
|
|
2
2
|
import { Feedback } from "../feedback/index.js";
|
|
3
3
|
import { ResourceValidationError } from "./errors.js";
|
|
4
4
|
/**
|
|
@@ -37,6 +37,6 @@ export class Resource {
|
|
|
37
37
|
}
|
|
38
38
|
}
|
|
39
39
|
}
|
|
40
|
-
export function RESOURCE(payload =
|
|
40
|
+
export function RESOURCE(payload = GET_UNDEFINED, result = GET_UNDEFINED) {
|
|
41
41
|
return new Resource(payload, result);
|
|
42
42
|
}
|
package/db/Database.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { Entry, Observable, Observer, Result, Unsubscriber, ResultsMap, Validatable, Validator, Key, Data, Results, Datas, Validators, ValidatorType, Dispatcher } from "../util/index.js";
|
|
1
|
+
import { Entry, Observable, Observer, Result, Unsubscriber, ResultsMap, Validatable, Validator, Key, Data, Results, Datas, Validators, ValidatorType, Dispatcher, Nullish } from "../util/index.js";
|
|
2
2
|
import { PropUpdates, Update } from "../update/index.js";
|
|
3
3
|
import type { Provider } from "../provider/Provider.js";
|
|
4
4
|
import { Filters, Sorts, Query } from "../query/index.js";
|
|
5
|
-
import { DocumentDelete, DocumentSet, DocumentUpdate, Write
|
|
5
|
+
import { DocumentDelete, DocumentSet, DocumentUpdate, Write } from "./Write.js";
|
|
6
6
|
/**
|
|
7
7
|
* Combines a database model and a provider.
|
|
8
8
|
*
|
|
@@ -18,10 +18,10 @@ export declare class Database<V extends Validators<Datas> = Validators<Datas>> {
|
|
|
18
18
|
query<K extends Key<V>>(collection: K, filters?: Filters<ValidatorType<V[K]>>, sorts?: Sorts<ValidatorType<V[K]>>, limit?: number | null): DataQuery<ValidatorType<V[K]>>;
|
|
19
19
|
/** Reference a document in a collection in this model. */
|
|
20
20
|
doc<K extends Key<V>>(collection: K, id: string): DataDocument<ValidatorType<V[K]>>;
|
|
21
|
-
/**
|
|
22
|
-
|
|
23
|
-
/** Perform
|
|
24
|
-
|
|
21
|
+
/** Create a writer for this database from a set of separate writes. */
|
|
22
|
+
writer(...writes: Nullish<Write>[]): Write;
|
|
23
|
+
/** Perform one or more writes on this database and return the `Writes` instance representing the combined changes. */
|
|
24
|
+
write(...writes: Nullish<Write>[]): Promise<Write>;
|
|
25
25
|
}
|
|
26
26
|
/** A documents reference within a specific database. */
|
|
27
27
|
export declare class DataQuery<T extends Data = Data> extends Query<T> implements Observable<Results<T>>, Validatable<Results<T>>, Iterable<Entry<T>> {
|
|
@@ -81,19 +81,19 @@ export declare class DataQuery<T extends Data = Data> extends Query<T> implement
|
|
|
81
81
|
* @param data Complete data to set the document to.
|
|
82
82
|
* @return Nothing (possibly promised).
|
|
83
83
|
*/
|
|
84
|
-
set(data: T):
|
|
84
|
+
set(data: T): number | PromiseLike<number>;
|
|
85
85
|
/**
|
|
86
86
|
* Update all matching documents with the same partial value.
|
|
87
87
|
*
|
|
88
88
|
* @param updates `Update` instance or set of updates to apply to every matching document.
|
|
89
89
|
* @return Nothing (possibly promised).
|
|
90
90
|
*/
|
|
91
|
-
update(updates: Update<T> | PropUpdates<T>):
|
|
91
|
+
update(updates: Update<T> | PropUpdates<T>): number | PromiseLike<number>;
|
|
92
92
|
/**
|
|
93
93
|
* Delete all matching documents.
|
|
94
94
|
* @return Nothing (possibly promised).
|
|
95
95
|
*/
|
|
96
|
-
delete():
|
|
96
|
+
delete(): number | PromiseLike<number>;
|
|
97
97
|
/** Iterate over the resuls (will throw `Promise` if the results are asynchronous). */
|
|
98
98
|
[Symbol.iterator](): Iterator<Entry<T>, void>;
|
|
99
99
|
/** Validate a set of results for this query reference. */
|
package/db/Database.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { callAsync, getFirstItem, throwAsync, validate, toMap, countItems, TransformObserver, } from "../util/index.js";
|
|
1
|
+
import { callAsync, getFirstItem, throwAsync, validate, toMap, countItems, TransformObserver, NOT_NULLISH, } from "../util/index.js";
|
|
2
2
|
import { DataUpdate, Update } from "../update/index.js";
|
|
3
3
|
import { Feedback, InvalidFeedback } from "../feedback/index.js";
|
|
4
4
|
import { Filters, Query, EqualFilter } from "../query/index.js";
|
|
@@ -25,14 +25,13 @@ export class Database {
|
|
|
25
25
|
doc(collection, id) {
|
|
26
26
|
return new DataDocument(this.provider, this.validators[collection], collection, id);
|
|
27
27
|
}
|
|
28
|
-
/**
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
return write;
|
|
28
|
+
/** Create a writer for this database from a set of separate writes. */
|
|
29
|
+
writer(...writes) {
|
|
30
|
+
return new Writes(...writes.filter(NOT_NULLISH));
|
|
32
31
|
}
|
|
33
|
-
/** Perform
|
|
34
|
-
async
|
|
35
|
-
const write = new Writes(...writes);
|
|
32
|
+
/** Perform one or more writes on this database and return the `Writes` instance representing the combined changes. */
|
|
33
|
+
async write(...writes) {
|
|
34
|
+
const write = new Writes(...writes.filter(NOT_NULLISH));
|
|
36
35
|
await write.transform(this);
|
|
37
36
|
return write;
|
|
38
37
|
}
|
package/db/Pagination.d.ts
CHANGED
|
@@ -7,23 +7,15 @@ import { DataQuery } from "./Database.js";
|
|
|
7
7
|
* - If you don't pass in initial values, it will autoload the first page.
|
|
8
8
|
*/
|
|
9
9
|
export declare class Pagination<T extends Data> extends State<ResultsMap<T>> implements Iterable<Entry<T>> {
|
|
10
|
+
protected _pending: boolean;
|
|
10
11
|
readonly ref: DataQuery<T>;
|
|
11
12
|
readonly limit: number;
|
|
12
|
-
readonly startLoading: boolean;
|
|
13
|
-
readonly startDone: boolean;
|
|
14
|
-
readonly endLoading: boolean;
|
|
15
|
-
readonly endDone: boolean;
|
|
16
13
|
constructor(ref: DataQuery<T>);
|
|
17
|
-
/**
|
|
18
|
-
* Load more results before the start.
|
|
19
|
-
* - Promise that needs to be handled.
|
|
20
|
-
*/
|
|
21
|
-
loadStart: () => Promise<void>;
|
|
22
14
|
/**
|
|
23
15
|
* Load more results after the end.
|
|
24
16
|
* - Promise that needs to be handled.
|
|
25
17
|
*/
|
|
26
|
-
|
|
18
|
+
more: () => Promise<void>;
|
|
27
19
|
/**
|
|
28
20
|
* Merge more results into this pagination.
|
|
29
21
|
* @return The change in the number of results.
|
package/db/Pagination.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { getLastItem, assertLength, assertNumber, yieldMerged, toMap, LOADING } from "../util/index.js";
|
|
2
2
|
import { State } from "../stream/index.js";
|
|
3
3
|
import { ConditionError } from "../index.js";
|
|
4
4
|
/**
|
|
@@ -9,56 +9,33 @@ import { ConditionError } from "../index.js";
|
|
|
9
9
|
export class Pagination extends State {
|
|
10
10
|
constructor(ref) {
|
|
11
11
|
super();
|
|
12
|
-
this.
|
|
13
|
-
this.startDone = false;
|
|
14
|
-
this.endLoading = false;
|
|
15
|
-
this.endDone = false;
|
|
16
|
-
/**
|
|
17
|
-
* Load more results before the start.
|
|
18
|
-
* - Promise that needs to be handled.
|
|
19
|
-
*/
|
|
20
|
-
this.loadStart = async () => {
|
|
21
|
-
if (this.closed)
|
|
22
|
-
throw new ConditionError();
|
|
23
|
-
if (!this.startLoading) {
|
|
24
|
-
this.startLoading = true;
|
|
25
|
-
if (!this.loading) {
|
|
26
|
-
const firstItem = getFirstItem(this.value);
|
|
27
|
-
if (firstItem) {
|
|
28
|
-
const next = await this.ref.after(firstItem[0], firstItem[1]).resultsMap;
|
|
29
|
-
this.startDone = next.size < this.limit;
|
|
30
|
-
this.startLoading = false;
|
|
31
|
-
return this.merge(next);
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
const next = await this.ref.resultsMap;
|
|
35
|
-
this.startDone = next.size < this.limit;
|
|
36
|
-
this.startLoading = false;
|
|
37
|
-
return this.next(next);
|
|
38
|
-
}
|
|
39
|
-
};
|
|
12
|
+
this._pending = false; // Prevents double-loading.
|
|
40
13
|
/**
|
|
41
14
|
* Load more results after the end.
|
|
42
15
|
* - Promise that needs to be handled.
|
|
43
16
|
*/
|
|
44
|
-
this.
|
|
17
|
+
this.more = async () => {
|
|
45
18
|
if (this.closed)
|
|
46
|
-
throw new ConditionError();
|
|
47
|
-
if (!this.
|
|
48
|
-
this.
|
|
19
|
+
throw new ConditionError("Pagination is closed");
|
|
20
|
+
if (!this._pending) {
|
|
21
|
+
this._pending = true;
|
|
49
22
|
if (!this.loading) {
|
|
50
23
|
const lastItem = getLastItem(this.value);
|
|
51
24
|
if (lastItem) {
|
|
52
25
|
const next = await this.ref.after(lastItem[0], lastItem[1]).resultsMap;
|
|
53
|
-
this.
|
|
54
|
-
|
|
55
|
-
|
|
26
|
+
this.merge(next);
|
|
27
|
+
if (next.size < this.limit)
|
|
28
|
+
this.complete();
|
|
29
|
+
this._pending = false;
|
|
30
|
+
return;
|
|
56
31
|
}
|
|
57
32
|
}
|
|
33
|
+
this._value === LOADING;
|
|
58
34
|
const next = await this.ref.resultsMap;
|
|
59
|
-
this.
|
|
60
|
-
|
|
61
|
-
|
|
35
|
+
this.next(next);
|
|
36
|
+
if (next.size < this.limit)
|
|
37
|
+
this.complete();
|
|
38
|
+
this._pending = false;
|
|
62
39
|
}
|
|
63
40
|
};
|
|
64
41
|
this.ref = ref;
|
package/db/Write.d.ts
CHANGED
|
@@ -12,7 +12,7 @@ export declare abstract class Write implements Transformable<Database, void | Pr
|
|
|
12
12
|
*/
|
|
13
13
|
export declare class Writes extends Write {
|
|
14
14
|
readonly writes: ImmutableArray<Write>;
|
|
15
|
-
constructor(...writes:
|
|
15
|
+
constructor(...writes: Write[]);
|
|
16
16
|
transform(db: Database): Promise<void>;
|
|
17
17
|
}
|
|
18
18
|
/** Represent a write made to a single document in a database. */
|
package/db/Write.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { DataUpdate, Update } from "../update/index.js";
|
|
2
|
-
import { transform
|
|
2
|
+
import { transform } from "../util/index.js";
|
|
3
3
|
/** Represent a write made to a database. */
|
|
4
4
|
export class Write {
|
|
5
5
|
}
|
|
@@ -11,7 +11,7 @@ export class Write {
|
|
|
11
11
|
export class Writes extends Write {
|
|
12
12
|
constructor(...writes) {
|
|
13
13
|
super();
|
|
14
|
-
this.writes = writes
|
|
14
|
+
this.writes = writes;
|
|
15
15
|
}
|
|
16
16
|
async transform(db) {
|
|
17
17
|
for (const writes of this.writes)
|
|
@@ -17,7 +17,7 @@ export declare class FirestoreClientProvider extends Provider implements Asynchr
|
|
|
17
17
|
delete<T extends Data>(ref: DataDocument<T>): Promise<void>;
|
|
18
18
|
getQuery<T extends Data>(ref: DataQuery<T>): Promise<Results<T>>;
|
|
19
19
|
subscribeQuery<T extends Data>(ref: DataQuery<T>, observer: Observer<Results<T>>): Unsubscriber;
|
|
20
|
-
setQuery<T extends Data>(ref: DataQuery<T>, data: T): Promise<
|
|
21
|
-
updateQuery<T extends Data>(ref: DataQuery<T>, updates: Update<T>): Promise<
|
|
22
|
-
deleteQuery<T extends Data>(ref: DataQuery<T>): Promise<
|
|
20
|
+
setQuery<T extends Data>(ref: DataQuery<T>, data: T): Promise<number>;
|
|
21
|
+
updateQuery<T extends Data>(ref: DataQuery<T>, updates: Update<T>): Promise<number>;
|
|
22
|
+
deleteQuery<T extends Data>(ref: DataQuery<T>): Promise<number>;
|
|
23
23
|
}
|
|
@@ -109,22 +109,18 @@ export class FirestoreClientProvider extends Provider {
|
|
|
109
109
|
}
|
|
110
110
|
async setQuery(ref, data) {
|
|
111
111
|
const snapshot = await getDocs(getQuery(this.firestore, ref));
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
await Promise.all(snapshot.docs.map(s => updateDoc(s.ref, updates)));
|
|
115
|
-
}
|
|
116
|
-
else if (data)
|
|
117
|
-
await Promise.all(snapshot.docs.map(s => setDoc(s.ref, data)));
|
|
118
|
-
else
|
|
119
|
-
await Promise.all(snapshot.docs.map(s => deleteDoc(s.ref)));
|
|
112
|
+
await Promise.all(snapshot.docs.map(s => setDoc(s.ref, data)));
|
|
113
|
+
return snapshot.size;
|
|
120
114
|
}
|
|
121
115
|
async updateQuery(ref, updates) {
|
|
122
116
|
const snapshot = await getDocs(getQuery(this.firestore, ref));
|
|
123
117
|
const fieldValues = getFieldValues(updates);
|
|
124
118
|
await Promise.all(snapshot.docs.map(s => updateDoc(s.ref, fieldValues)));
|
|
119
|
+
return snapshot.size;
|
|
125
120
|
}
|
|
126
121
|
async deleteQuery(ref) {
|
|
127
122
|
const snapshot = await getDocs(getQuery(this.firestore, ref));
|
|
128
123
|
await Promise.all(snapshot.docs.map(s => deleteDoc(s.ref)));
|
|
124
|
+
return snapshot.size;
|
|
129
125
|
}
|
|
130
126
|
}
|
|
@@ -17,7 +17,7 @@ export declare class FirestoreClientProvider extends Provider implements Asynchr
|
|
|
17
17
|
delete<T extends Data>(ref: DataDocument<T>): Promise<void>;
|
|
18
18
|
getQuery<T extends Data>(ref: DataQuery<T>): Promise<Results<T>>;
|
|
19
19
|
subscribeQuery(): Unsubscriber;
|
|
20
|
-
setQuery<T extends Data>(ref: DataQuery<T>, data: T | Update<T> | undefined): Promise<
|
|
21
|
-
updateQuery<T extends Data>(ref: DataQuery<T>, updates: Update<T>): Promise<
|
|
22
|
-
deleteQuery<T extends Data>(ref: DataQuery<T>): Promise<
|
|
20
|
+
setQuery<T extends Data>(ref: DataQuery<T>, data: T | Update<T> | undefined): Promise<number>;
|
|
21
|
+
updateQuery<T extends Data>(ref: DataQuery<T>, updates: Update<T>): Promise<number>;
|
|
22
|
+
deleteQuery<T extends Data>(ref: DataQuery<T>): Promise<number>;
|
|
23
23
|
}
|
|
@@ -110,14 +110,17 @@ export class FirestoreClientProvider extends Provider {
|
|
|
110
110
|
async setQuery(ref, data) {
|
|
111
111
|
const snapshot = await getDocs(getQuery(this.firestore, ref));
|
|
112
112
|
await Promise.all(snapshot.docs.map(s => setDoc(s.ref, data)));
|
|
113
|
+
return snapshot.size;
|
|
113
114
|
}
|
|
114
115
|
async updateQuery(ref, updates) {
|
|
115
116
|
const snapshot = await getDocs(getQuery(this.firestore, ref));
|
|
116
117
|
const fieldValues = getFieldValues(updates);
|
|
117
118
|
await Promise.all(snapshot.docs.map(s => updateDoc(s.ref, fieldValues)));
|
|
119
|
+
return snapshot.size;
|
|
118
120
|
}
|
|
119
121
|
async deleteQuery(ref) {
|
|
120
122
|
const snapshot = await getDocs(getQuery(this.firestore, ref));
|
|
121
123
|
await Promise.all(snapshot.docs.map(s => deleteDoc(s.ref)));
|
|
124
|
+
return snapshot.size;
|
|
122
125
|
}
|
|
123
126
|
}
|
|
@@ -15,7 +15,7 @@ export declare class FirestoreServerProvider extends Provider implements Asynchr
|
|
|
15
15
|
delete<T extends Data>(ref: DataDocument<T>): Promise<void>;
|
|
16
16
|
getQuery<T extends Data>(ref: DataQuery<T>): Promise<Iterable<Entry<T>>>;
|
|
17
17
|
subscribeQuery<T extends Data>(ref: DataQuery<T>, observer: Observer<Results<T>>): Unsubscriber;
|
|
18
|
-
setQuery<T extends Data>(ref: DataQuery<T>, data: T | Update<T> | undefined): Promise<
|
|
19
|
-
updateQuery<T extends Data>(ref: DataQuery<T>, updates: Update<T>): Promise<
|
|
20
|
-
deleteQuery<T extends Data>(ref: DataQuery<T>): Promise<
|
|
18
|
+
setQuery<T extends Data>(ref: DataQuery<T>, data: T | Update<T> | undefined): Promise<number>;
|
|
19
|
+
updateQuery<T extends Data>(ref: DataQuery<T>, updates: Update<T>): Promise<number>;
|
|
20
|
+
deleteQuery<T extends Data>(ref: DataQuery<T>): Promise<number>;
|
|
21
21
|
}
|
|
@@ -104,28 +104,31 @@ export class FirestoreServerProvider extends Provider {
|
|
|
104
104
|
return getQuery(this.firestore, ref).onSnapshot(snapshot => dispatchNext(observer, getResults(snapshot)), thrown => dispatchError(observer, thrown));
|
|
105
105
|
}
|
|
106
106
|
async setQuery(ref, data) {
|
|
107
|
-
await bulkWrite(this.firestore, ref, (w, s) => void w.set(s.ref, data));
|
|
107
|
+
return await bulkWrite(this.firestore, ref, (w, s) => void w.set(s.ref, data));
|
|
108
108
|
}
|
|
109
109
|
async updateQuery(ref, updates) {
|
|
110
110
|
const fieldValues = getFieldValues(updates);
|
|
111
|
-
await bulkWrite(this.firestore, ref, (w, s) => void w.update(s.ref, fieldValues));
|
|
111
|
+
return await bulkWrite(this.firestore, ref, (w, s) => void w.update(s.ref, fieldValues));
|
|
112
112
|
}
|
|
113
113
|
async deleteQuery(ref) {
|
|
114
|
-
await bulkWrite(this.firestore, ref, (w, s) => void w.delete(s.ref));
|
|
114
|
+
return await bulkWrite(this.firestore, ref, (w, s) => void w.delete(s.ref));
|
|
115
115
|
}
|
|
116
116
|
}
|
|
117
117
|
/** Perform a bulk update on a set of documents using a `BulkWriter` */
|
|
118
118
|
async function bulkWrite(firestore, ref, callback) {
|
|
119
|
+
let count = 0;
|
|
119
120
|
const writer = firestore.bulkWriter();
|
|
120
121
|
const query = getQuery(firestore, ref).limit(BATCH_SIZE).select(); // `select()` turs the query into a field mask query (with no field masks) which saves data transfer and memory.
|
|
121
122
|
let current = query;
|
|
122
123
|
while (current) {
|
|
123
|
-
const
|
|
124
|
-
|
|
124
|
+
const { docs, size } = await current.get();
|
|
125
|
+
count += size;
|
|
126
|
+
for (const s of docs)
|
|
125
127
|
callback(writer, s);
|
|
126
|
-
current =
|
|
128
|
+
current = size >= BATCH_SIZE && query.startAfter(docs.pop()).select();
|
|
127
129
|
void writer.flush();
|
|
128
130
|
}
|
|
129
131
|
await writer.close();
|
|
132
|
+
return count;
|
|
130
133
|
}
|
|
131
134
|
const BATCH_SIZE = 1000;
|
package/package.json
CHANGED
|
@@ -27,9 +27,9 @@ export declare class CacheProvider extends ThroughProvider implements Asynchrono
|
|
|
27
27
|
private _cacheResults;
|
|
28
28
|
getQuery<T extends Data>(ref: DataQuery<T>): Promise<Results<T>>;
|
|
29
29
|
subscribeQuery<T extends Data>(ref: DataQuery<T>, observer: Observer<Results<T>>): Unsubscriber;
|
|
30
|
-
setQuery<T extends Data>(ref: DataQuery<T>, data: T): Promise<
|
|
31
|
-
updateQuery<T extends Data>(ref: DataQuery<T>, updates: Update<T>): Promise<
|
|
32
|
-
deleteQuery<T extends Data>(ref: DataQuery<T>): Promise<
|
|
30
|
+
setQuery<T extends Data>(ref: DataQuery<T>, data: T): Promise<number>;
|
|
31
|
+
updateQuery<T extends Data>(ref: DataQuery<T>, updates: Update<T>): Promise<number>;
|
|
32
|
+
deleteQuery<T extends Data>(ref: DataQuery<T>): Promise<number>;
|
|
33
33
|
/** Reset this provider and clear all data. */
|
|
34
34
|
reset(): void;
|
|
35
35
|
}
|
|
@@ -79,16 +79,19 @@ export class CacheProvider extends ThroughProvider {
|
|
|
79
79
|
return super.subscribeQuery(ref, new TransformObserver(results => this._cacheResults(ref, results), observer));
|
|
80
80
|
}
|
|
81
81
|
async setQuery(ref, data) {
|
|
82
|
-
await super.setQuery(ref, data);
|
|
82
|
+
const count = await super.setQuery(ref, data);
|
|
83
83
|
this.cache.setQuery(ref, data);
|
|
84
|
+
return count;
|
|
84
85
|
}
|
|
85
86
|
async updateQuery(ref, updates) {
|
|
86
|
-
await super.updateQuery(ref, updates);
|
|
87
|
+
const count = await super.updateQuery(ref, updates);
|
|
87
88
|
this.cache.updateQuery(ref, updates);
|
|
89
|
+
return count;
|
|
88
90
|
}
|
|
89
91
|
async deleteQuery(ref) {
|
|
90
|
-
await super.deleteQuery(ref);
|
|
92
|
+
const count = await super.deleteQuery(ref);
|
|
91
93
|
this.cache.deleteQuery(ref);
|
|
94
|
+
return count;
|
|
92
95
|
}
|
|
93
96
|
/** Reset this provider and clear all data. */
|
|
94
97
|
reset() {
|
|
@@ -19,9 +19,9 @@ export declare class MemoryProvider extends Provider implements SynchronousProvi
|
|
|
19
19
|
delete<T extends Data>(ref: DataDocument<T>): void;
|
|
20
20
|
getQuery<T extends Data>(ref: DataQuery<T>): Results<T>;
|
|
21
21
|
subscribeQuery<T extends Data>(ref: DataQuery<T>, observer: Observer<Results<T>>): Unsubscriber;
|
|
22
|
-
setQuery<T extends Data>(ref: DataQuery<T>, data: T):
|
|
23
|
-
updateQuery<T extends Data>(ref: DataQuery<T>, updates: Update<T>):
|
|
24
|
-
deleteQuery<T extends Data>(ref: DataQuery<T>):
|
|
22
|
+
setQuery<T extends Data>(ref: DataQuery<T>, data: T): number;
|
|
23
|
+
updateQuery<T extends Data>(ref: DataQuery<T>, updates: Update<T>): number;
|
|
24
|
+
deleteQuery<T extends Data>(ref: DataQuery<T>): number;
|
|
25
25
|
/** Reset this provider and clear all data. */
|
|
26
26
|
reset(): void;
|
|
27
27
|
}
|
|
@@ -86,22 +86,34 @@ export class MemoryProvider extends Provider {
|
|
|
86
86
|
const table = this._table(ref);
|
|
87
87
|
// If there's a limit set: run the full query.
|
|
88
88
|
// If there's no limit set: only need to run the filtering (more efficient because sort order doesn't matter).
|
|
89
|
-
|
|
89
|
+
let count = 0;
|
|
90
|
+
for (const [id] of ref.limit ? ref.transform(table.data) : ref.filters.transform(table.data)) {
|
|
90
91
|
table.write(id, data);
|
|
92
|
+
count++;
|
|
93
|
+
}
|
|
94
|
+
return count;
|
|
91
95
|
}
|
|
92
96
|
updateQuery(ref, updates) {
|
|
93
97
|
const table = this._table(ref);
|
|
94
98
|
// If there's a limit set: run the full query.
|
|
95
99
|
// If there's no limit set: only need to run the filtering (more efficient because sort order doesn't matter).
|
|
96
|
-
|
|
100
|
+
let count = 0;
|
|
101
|
+
for (const [id, existing] of ref.limit ? ref.transform(table.data) : ref.filters.transform(table.data)) {
|
|
97
102
|
table.write(id, updates.transform(existing));
|
|
103
|
+
count++;
|
|
104
|
+
}
|
|
105
|
+
return count;
|
|
98
106
|
}
|
|
99
107
|
deleteQuery(ref) {
|
|
100
108
|
const table = this._table(ref);
|
|
101
109
|
// If there's a limit set: run the full query.
|
|
102
110
|
// If there's no limit set: only need to run the filtering (more efficient because sort order doesn't matter).
|
|
103
|
-
|
|
111
|
+
let count = 0;
|
|
112
|
+
for (const [id] of ref.limit ? ref.transform(table.data) : ref.filters.transform(table.data)) {
|
|
104
113
|
table.write(id, undefined);
|
|
114
|
+
count++;
|
|
115
|
+
}
|
|
116
|
+
return count;
|
|
105
117
|
}
|
|
106
118
|
/** Reset this provider and clear all data. */
|
|
107
119
|
reset() {
|
package/provider/Provider.d.ts
CHANGED
|
@@ -77,20 +77,23 @@ export declare abstract class Provider {
|
|
|
77
77
|
*
|
|
78
78
|
* @param ref Documents reference specifying which collection to set.
|
|
79
79
|
* @param value Value to set the document to.
|
|
80
|
+
* @return Number of documents that were set.
|
|
80
81
|
*/
|
|
81
|
-
abstract setQuery<T extends Data>(ref: DataQuery<T>, data: T):
|
|
82
|
+
abstract setQuery<T extends Data>(ref: DataQuery<T>, data: T): number | PromiseLike<number>;
|
|
82
83
|
/**
|
|
83
84
|
* Update the data of all matching documents.
|
|
84
85
|
*
|
|
85
86
|
* @param ref Documents reference specifying which collection to set.
|
|
86
87
|
* @param updates Update instance to set the document to.
|
|
88
|
+
* @return Number of documents that were updated.
|
|
87
89
|
*/
|
|
88
|
-
abstract updateQuery<T extends Data>(ref: DataQuery<T>, updates: Update<T>):
|
|
90
|
+
abstract updateQuery<T extends Data>(ref: DataQuery<T>, updates: Update<T>): number | PromiseLike<number>;
|
|
89
91
|
/**
|
|
90
92
|
* Delete all matching documents.
|
|
91
93
|
* @param ref Document reference specifying which document to delete.
|
|
94
|
+
* @return Number of documents that were deleted.
|
|
92
95
|
*/
|
|
93
|
-
abstract deleteQuery<T extends Data>(ref: DataQuery<T>):
|
|
96
|
+
abstract deleteQuery<T extends Data>(ref: DataQuery<T>): number | PromiseLike<number>;
|
|
94
97
|
}
|
|
95
98
|
/** Provider with a fully synchronous interface */
|
|
96
99
|
export interface SynchronousProvider extends Provider {
|
|
@@ -100,9 +103,9 @@ export interface SynchronousProvider extends Provider {
|
|
|
100
103
|
update<T extends Data>(ref: DataDocument<T>, value: Update<T>): void;
|
|
101
104
|
delete<T extends Data>(ref: DataDocument<T>): void;
|
|
102
105
|
getQuery<T extends Data>(ref: DataQuery<T>): Results<T>;
|
|
103
|
-
setQuery<T extends Data>(ref: DataQuery<T>, value: T):
|
|
104
|
-
updateQuery<T extends Data>(ref: DataQuery<T>, updates: Update<T>):
|
|
105
|
-
deleteQuery<T extends Data>(ref: DataQuery<T>):
|
|
106
|
+
setQuery<T extends Data>(ref: DataQuery<T>, value: T): number;
|
|
107
|
+
updateQuery<T extends Data>(ref: DataQuery<T>, updates: Update<T>): number;
|
|
108
|
+
deleteQuery<T extends Data>(ref: DataQuery<T>): number;
|
|
106
109
|
}
|
|
107
110
|
/** Provider with a fully asynchronous interface */
|
|
108
111
|
export interface AsynchronousProvider extends Provider {
|
|
@@ -112,7 +115,7 @@ export interface AsynchronousProvider extends Provider {
|
|
|
112
115
|
update<T extends Data>(ref: DataDocument<T>, updates: Update<T>): PromiseLike<void>;
|
|
113
116
|
delete<T extends Data>(ref: DataDocument<T>): PromiseLike<void>;
|
|
114
117
|
getQuery<T extends Data>(ref: DataQuery<T>): PromiseLike<Results<T>>;
|
|
115
|
-
setQuery<T extends Data>(ref: DataQuery<T>, value: T): PromiseLike<
|
|
116
|
-
updateQuery<T extends Data>(ref: DataQuery<T>, updates: Update<T>): PromiseLike<
|
|
117
|
-
deleteQuery<T extends Data>(ref: DataQuery<T>): PromiseLike<
|
|
118
|
+
setQuery<T extends Data>(ref: DataQuery<T>, value: T): PromiseLike<number>;
|
|
119
|
+
updateQuery<T extends Data>(ref: DataQuery<T>, updates: Update<T>): PromiseLike<number>;
|
|
120
|
+
deleteQuery<T extends Data>(ref: DataQuery<T>): PromiseLike<number>;
|
|
118
121
|
}
|
|
@@ -16,9 +16,9 @@ export declare class ThroughProvider extends Provider {
|
|
|
16
16
|
delete<T extends Data>(ref: DataDocument<T>): void | PromiseLike<void>;
|
|
17
17
|
getQuery<T extends Data>(ref: DataQuery<T>): Results<T> | PromiseLike<Results<T>>;
|
|
18
18
|
subscribeQuery<T extends Data>(ref: DataQuery<T>, observer: Observer<Results<T>>): Unsubscriber;
|
|
19
|
-
setQuery<T extends Data>(ref: DataQuery<T>, data: T):
|
|
20
|
-
updateQuery<T extends Data>(ref: DataQuery<T>, updates: Update<T>):
|
|
21
|
-
deleteQuery<T extends Data>(ref: DataQuery<T>):
|
|
19
|
+
setQuery<T extends Data>(ref: DataQuery<T>, data: T): number | PromiseLike<number>;
|
|
20
|
+
updateQuery<T extends Data>(ref: DataQuery<T>, updates: Update<T>): number | PromiseLike<number>;
|
|
21
|
+
deleteQuery<T extends Data>(ref: DataQuery<T>): number | PromiseLike<number>;
|
|
22
22
|
}
|
|
23
23
|
/** Find a specific source provider in a database's provider stack. */
|
|
24
24
|
export declare function findSourceProvider<P extends Provider>(provider: Provider, type: Class<P>): P;
|
|
@@ -11,6 +11,6 @@ export declare class ValidationProvider extends ThroughProvider {
|
|
|
11
11
|
update<T extends Data>(ref: DataDocument<T>, updates: Update<T>): void | PromiseLike<void>;
|
|
12
12
|
getQuery<T extends Data>(ref: DataQuery<T>): Results<T> | PromiseLike<Results<T>>;
|
|
13
13
|
subscribeQuery<T extends Data>(ref: DataQuery<T>, observer: Observer<Results<T>>): Unsubscriber;
|
|
14
|
-
setQuery<T extends Data>(ref: DataQuery<T>, value: T):
|
|
15
|
-
updateQuery<T extends Data>(ref: DataQuery<T>, updates: Update<T>):
|
|
14
|
+
setQuery<T extends Data>(ref: DataQuery<T>, value: T): number | PromiseLike<number>;
|
|
15
|
+
updateQuery<T extends Data>(ref: DataQuery<T>, updates: Update<T>): number | PromiseLike<number>;
|
|
16
16
|
}
|
package/stream/DataState.d.ts
CHANGED
|
@@ -1,9 +1,24 @@
|
|
|
1
|
-
import { Key, Data, PropTransformers } from "../util/index.js";
|
|
1
|
+
import { Key, Data, PropTransformers, Result } from "../util/index.js";
|
|
2
2
|
import { State } from "./State.js";
|
|
3
|
-
/** State that stores
|
|
3
|
+
/** State that stores a data object and has additional methods to help with that. */
|
|
4
4
|
export declare class DataState<T extends Data> extends State<T> {
|
|
5
|
+
/** Get the data value of this state. */
|
|
6
|
+
get data(): T;
|
|
5
7
|
/** Set a prop in this object to a new value. */
|
|
6
8
|
set<K extends Key<T>>(key: K, value: T[K]): void;
|
|
7
9
|
/** Update several props in this object. */
|
|
8
10
|
update(updates: PropTransformers<T>): void;
|
|
9
11
|
}
|
|
12
|
+
/** State that stores an optional data object and has additional methods to help with that. */
|
|
13
|
+
export declare class ResultState<T extends Data> extends State<Result<T>> {
|
|
14
|
+
/** Get the result value of this state. */
|
|
15
|
+
get result(): Result<T>;
|
|
16
|
+
/** Get current data value of this state (or throw `Promise` that resolves to the next required value). */
|
|
17
|
+
get data(): T;
|
|
18
|
+
/** Set a prop in this object to a new value. */
|
|
19
|
+
set<K extends Key<T>>(key: K, value: T[K]): void;
|
|
20
|
+
/** Update several props in this object. */
|
|
21
|
+
update(updates: PropTransformers<T>): void;
|
|
22
|
+
/** Delete this result. */
|
|
23
|
+
delete(): void;
|
|
24
|
+
}
|
package/stream/DataState.js
CHANGED
|
@@ -1,13 +1,44 @@
|
|
|
1
|
-
import { withProp, transformData } from "../util/index.js";
|
|
1
|
+
import { withProp, transformData, NOERROR, LOADING, awaitNext, getData } from "../util/index.js";
|
|
2
2
|
import { State } from "./State.js";
|
|
3
|
-
/** State that stores
|
|
3
|
+
/** State that stores a data object and has additional methods to help with that. */
|
|
4
4
|
export class DataState extends State {
|
|
5
|
+
/** Get the data value of this state. */
|
|
6
|
+
get data() {
|
|
7
|
+
return this.value;
|
|
8
|
+
}
|
|
5
9
|
/** Set a prop in this object to a new value. */
|
|
6
10
|
set(key, value) {
|
|
7
|
-
this.next(withProp(this.
|
|
11
|
+
this.next(withProp(this.data, key, value));
|
|
8
12
|
}
|
|
9
13
|
/** Update several props in this object. */
|
|
10
14
|
update(updates) {
|
|
11
|
-
this.next(transformData(this.
|
|
15
|
+
this.next(transformData(this.data, updates));
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
/** State that stores an optional data object and has additional methods to help with that. */
|
|
19
|
+
export class ResultState extends State {
|
|
20
|
+
/** Get the result value of this state. */
|
|
21
|
+
get result() {
|
|
22
|
+
return this.value;
|
|
23
|
+
}
|
|
24
|
+
/** Get current data value of this state (or throw `Promise` that resolves to the next required value). */
|
|
25
|
+
get data() {
|
|
26
|
+
if (this.reason !== NOERROR)
|
|
27
|
+
throw this.reason;
|
|
28
|
+
if (this._value === LOADING)
|
|
29
|
+
throw awaitNext(this).then(getData);
|
|
30
|
+
return getData(this._value);
|
|
31
|
+
}
|
|
32
|
+
/** Set a prop in this object to a new value. */
|
|
33
|
+
set(key, value) {
|
|
34
|
+
this.next(withProp(this.data, key, value));
|
|
35
|
+
}
|
|
36
|
+
/** Update several props in this object. */
|
|
37
|
+
update(updates) {
|
|
38
|
+
this.next(transformData(this.data, updates));
|
|
39
|
+
}
|
|
40
|
+
/** Delete this result. */
|
|
41
|
+
delete() {
|
|
42
|
+
this.next(undefined);
|
|
12
43
|
}
|
|
13
44
|
}
|
package/stream/State.d.ts
CHANGED
|
@@ -28,8 +28,6 @@ export declare class State<T> extends Stream<T> {
|
|
|
28
28
|
/** Most recently dispatched value (or throw `Promise` that resolves to the next value). */
|
|
29
29
|
get value(): T;
|
|
30
30
|
protected _value: T | typeof LOADING;
|
|
31
|
-
/** Get current required value (or throw `Promise` that resolves to the next required value). */
|
|
32
|
-
get data(): Exclude<T, null | undefined>;
|
|
33
31
|
/** Is there a current value, or is it still loading. */
|
|
34
32
|
get loading(): boolean;
|
|
35
33
|
/** Apply a transformer to this state. */
|
package/stream/State.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
var _a;
|
|
2
|
-
import { LOADING, NOERROR, dispatchNext, dispatchError, dispatchComplete, transform,
|
|
2
|
+
import { LOADING, NOERROR, dispatchNext, dispatchError, dispatchComplete, transform, awaitNext, } from "../util/index.js";
|
|
3
3
|
import { Stream } from "./Stream.js";
|
|
4
4
|
export class State extends Stream {
|
|
5
5
|
constructor() {
|
|
@@ -22,14 +22,6 @@ export class State extends Stream {
|
|
|
22
22
|
throw awaitNext(this);
|
|
23
23
|
return this._value;
|
|
24
24
|
}
|
|
25
|
-
/** Get current required value (or throw `Promise` that resolves to the next required value). */
|
|
26
|
-
get data() {
|
|
27
|
-
if (this.reason !== NOERROR)
|
|
28
|
-
throw this.reason;
|
|
29
|
-
if (this._value === LOADING)
|
|
30
|
-
throw awaitNext(this).then(getRequired);
|
|
31
|
-
return getRequired(this._value);
|
|
32
|
-
}
|
|
33
25
|
/** Is there a current value, or is it still loading. */
|
|
34
26
|
get loading() {
|
|
35
27
|
return this._value === LOADING;
|
package/util/data.d.ts
CHANGED
|
@@ -25,9 +25,6 @@ export declare const isData: <T extends Data>(value: unknown) => value is T;
|
|
|
25
25
|
/** Turn a data object into an array of entries (if it isn't one already). */
|
|
26
26
|
export declare function toProps<T extends Data>(input: T): ImmutableArray<Prop<T>>;
|
|
27
27
|
export declare function toProps<T extends Data>(input: Partial<T>): ImmutableArray<Prop<T>>;
|
|
28
|
-
/** Get a required value (returns value or throws `RequiredError` if value is `null` or `undefined`). */
|
|
29
|
-
export declare function getRequired<T>(v: T): Exclude<T, null | undefined>;
|
|
30
|
-
export declare function getRequired<T>(v: T | null | undefined): T;
|
|
31
28
|
/** Get the data of a result (returns data or throws `RequiredError` if value is `null` or `undefined`). */
|
|
32
29
|
export declare function getData<T extends Data>(result: Result<T>): T;
|
|
33
30
|
/**
|
package/util/data.js
CHANGED
|
@@ -4,11 +4,6 @@ export const isData = (value) => typeof value === "object" && value !== null;
|
|
|
4
4
|
export function toProps(input) {
|
|
5
5
|
return Object.entries(input);
|
|
6
6
|
}
|
|
7
|
-
export function getRequired(v) {
|
|
8
|
-
if (v === undefined || v === null)
|
|
9
|
-
throw new RequiredError(v === null ? "Required value is null" : "Required value is undefined");
|
|
10
|
-
return v;
|
|
11
|
-
}
|
|
12
7
|
/** Get the data of a result (returns data or throws `RequiredError` if value is `null` or `undefined`). */
|
|
13
8
|
export function getData(result) {
|
|
14
9
|
if (!result)
|
package/util/null.d.ts
CHANGED
|
@@ -3,4 +3,15 @@ export declare const IS_NULL: (v: unknown) => v is null;
|
|
|
3
3
|
/** Is a value not null? */
|
|
4
4
|
export declare const NOT_NULL: <T>(v: T | null) => v is T;
|
|
5
5
|
/** Function that always returns null. */
|
|
6
|
-
export declare const
|
|
6
|
+
export declare const GET_NULL: () => null;
|
|
7
|
+
/** Nullish is `null` or `undefined` */
|
|
8
|
+
export declare type Nullish<T> = T | null | undefined;
|
|
9
|
+
/** Nullish is `null` or `undefined` */
|
|
10
|
+
export declare type NotNullish<T> = Exclude<T, null | undefined>;
|
|
11
|
+
/** Is a value nullish? */
|
|
12
|
+
export declare const IS_NULLISH: <T>(v: Nullish<T>) => v is null | undefined;
|
|
13
|
+
/** Is a value nullish? */
|
|
14
|
+
export declare const NOT_NULLISH: <T>(v: Nullish<T>) => v is T;
|
|
15
|
+
/** Get a required value (returns value or throws `RequiredError` if value is `null` or `undefined`). */
|
|
16
|
+
export declare function getRequired<T>(v: T): NotNullish<T>;
|
|
17
|
+
export declare function getRequired<T>(v: Nullish<T>): T;
|
package/util/null.js
CHANGED
|
@@ -1,6 +1,16 @@
|
|
|
1
|
+
import { RequiredError } from "../error/index.js";
|
|
1
2
|
/** Is a value null? */
|
|
2
3
|
export const IS_NULL = (v) => v === null;
|
|
3
4
|
/** Is a value not null? */
|
|
4
5
|
export const NOT_NULL = (v) => v !== null;
|
|
5
6
|
/** Function that always returns null. */
|
|
6
|
-
export const
|
|
7
|
+
export const GET_NULL = () => null;
|
|
8
|
+
/** Is a value nullish? */
|
|
9
|
+
export const IS_NULLISH = (v) => v === null || v === undefined;
|
|
10
|
+
/** Is a value nullish? */
|
|
11
|
+
export const NOT_NULLISH = (v) => v !== null && v !== undefined;
|
|
12
|
+
export function getRequired(v) {
|
|
13
|
+
if (v === undefined || v === null)
|
|
14
|
+
throw new RequiredError("Required value is missing");
|
|
15
|
+
return v;
|
|
16
|
+
}
|
package/util/object.d.ts
CHANGED
|
@@ -87,3 +87,11 @@ export declare function deleteEntry<T>(obj: MutableObject<T>, key: string, value
|
|
|
87
87
|
* @param entries Set of keys or entries to remove.
|
|
88
88
|
*/
|
|
89
89
|
export declare function deleteEntries<T>(obj: MutableObject<T>, keys: ImmutableArray<string>): void;
|
|
90
|
+
/** Type that represents an empty object. */
|
|
91
|
+
export declare type EmptyObject = {
|
|
92
|
+
readonly [K in never]: never;
|
|
93
|
+
};
|
|
94
|
+
/** An empty object. */
|
|
95
|
+
export declare const EMPTY_OBJECT: EmptyObject;
|
|
96
|
+
/** Function that returns an an empty object. */
|
|
97
|
+
export declare const GET_EMPTY_OBJECT: () => EmptyObject;
|
package/util/object.js
CHANGED
|
@@ -98,3 +98,7 @@ export function deleteEntries(obj, keys) {
|
|
|
98
98
|
for (const key of keys)
|
|
99
99
|
delete obj[key];
|
|
100
100
|
}
|
|
101
|
+
/** An empty object. */
|
|
102
|
+
export const EMPTY_OBJECT = {};
|
|
103
|
+
/** Function that returns an an empty object. */
|
|
104
|
+
export const GET_EMPTY_OBJECT = () => EMPTY_OBJECT;
|
package/util/undefined.d.ts
CHANGED
|
@@ -4,6 +4,4 @@ export declare const IS_UNDEFINED: (v: unknown) => v is undefined;
|
|
|
4
4
|
export declare const IS_DEFINED: <T>(v: T | undefined) => v is T;
|
|
5
5
|
export declare const NOT_UNDEFINED: <T>(v: T | undefined) => v is T;
|
|
6
6
|
/** Function that always returns undefined. */
|
|
7
|
-
export declare const
|
|
8
|
-
/** Function that always returns void. */
|
|
9
|
-
export declare const VOID: () => void;
|
|
7
|
+
export declare const GET_UNDEFINED: () => undefined;
|
package/util/undefined.js
CHANGED
|
@@ -4,6 +4,4 @@ export const IS_UNDEFINED = (v) => v === undefined;
|
|
|
4
4
|
export const IS_DEFINED = (v) => v !== undefined;
|
|
5
5
|
export const NOT_UNDEFINED = IS_DEFINED;
|
|
6
6
|
/** Function that always returns undefined. */
|
|
7
|
-
export const
|
|
8
|
-
/** Function that always returns void. */
|
|
9
|
-
export const VOID = UNDEFINED;
|
|
7
|
+
export const GET_UNDEFINED = () => undefined;
|
package/util/url.d.ts
CHANGED
|
@@ -1,10 +1,9 @@
|
|
|
1
|
+
/** Things that can be converted to a URL instance. */
|
|
2
|
+
export declare type PossibleURL = string | URL;
|
|
3
|
+
export declare type PossibleOptionalURL = PossibleURL | null;
|
|
4
|
+
/** Convert a possible URL to a URL or return `null` if conversion fails. */
|
|
5
|
+
export declare function toURL(url: PossibleURL, base?: PossibleOptionalURL): URL | null;
|
|
6
|
+
/** Convert a possible URL to a URL but throw `AssertionError` if conversion fails. */
|
|
7
|
+
export declare function getURL(input: PossibleURL, base?: PossibleOptionalURL): URL;
|
|
1
8
|
/** Just get important part of a URL, e.g. `http://shax.com/test?uid=129483` → `shax.com/test` */
|
|
2
|
-
export declare const formatUrl: (url:
|
|
3
|
-
/**
|
|
4
|
-
* Convert a string to a URL instance or return `null` if we can't.
|
|
5
|
-
* - Automatically prepend `https://` if there's no `:` anywhere.
|
|
6
|
-
*
|
|
7
|
-
* @param url Base
|
|
8
|
-
* @param
|
|
9
|
-
*/
|
|
10
|
-
export declare function toURL(url: string | URL, base?: URL | string | undefined): URL | null;
|
|
9
|
+
export declare const formatUrl: (url: PossibleURL) => string;
|
package/util/url.js
CHANGED
|
@@ -1,25 +1,26 @@
|
|
|
1
|
-
import {
|
|
2
|
-
/**
|
|
3
|
-
export
|
|
4
|
-
const { host, pathname } = getRequired(toURL(url));
|
|
5
|
-
return `${host}${pathname.length > 1 ? pathname : ""}`;
|
|
6
|
-
};
|
|
7
|
-
/**
|
|
8
|
-
* Convert a string to a URL instance or return `null` if we can't.
|
|
9
|
-
* - Automatically prepend `https://` if there's no `:` anywhere.
|
|
10
|
-
*
|
|
11
|
-
* @param url Base
|
|
12
|
-
* @param
|
|
13
|
-
*/
|
|
14
|
-
export function toURL(url, base = typeof window === "object" ? window.location.href : undefined) {
|
|
1
|
+
import { AssertionError } from "../error/index.js";
|
|
2
|
+
/** Convert a possible URL to a URL or return `null` if conversion fails. */
|
|
3
|
+
export function toURL(url, base = typeof window === "object" ? window.location.href : null) {
|
|
15
4
|
if (url instanceof URL)
|
|
16
5
|
return url;
|
|
17
6
|
if (!url)
|
|
18
7
|
return null;
|
|
19
8
|
try {
|
|
20
|
-
return new URL(url, base);
|
|
9
|
+
return new URL(url, base || undefined);
|
|
21
10
|
}
|
|
22
11
|
catch (e) {
|
|
23
12
|
return null;
|
|
24
13
|
}
|
|
25
14
|
}
|
|
15
|
+
/** Convert a possible URL to a URL but throw `AssertionError` if conversion fails. */
|
|
16
|
+
export function getURL(input, base) {
|
|
17
|
+
const url = toURL(input, base);
|
|
18
|
+
if (!url)
|
|
19
|
+
throw new AssertionError("Invalid URL", input);
|
|
20
|
+
return url;
|
|
21
|
+
}
|
|
22
|
+
/** Just get important part of a URL, e.g. `http://shax.com/test?uid=129483` → `shax.com/test` */
|
|
23
|
+
export const formatUrl = (url) => {
|
|
24
|
+
const { host, pathname } = getURL(url);
|
|
25
|
+
return `${host}${pathname.length > 1 ? pathname : ""}`;
|
|
26
|
+
};
|