shelving 1.73.3 → 1.74.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/db/Changes.d.ts CHANGED
@@ -1,7 +1,8 @@
1
- import type { Datas, Key } from "../util/data.js";
1
+ import type { Data, Datas, Key } from "../util/data.js";
2
2
  import { DataUpdate } from "../update/DataUpdate.js";
3
3
  import type { Provider, AsyncProvider } from "../provider/Provider.js";
4
4
  import type { Database, AsyncDatabase } from "./Database.js";
5
+ import { ItemConstraints, ItemData } from "./Item.js";
5
6
  /**
6
7
  * Change set of operations to run against a database in `{ "collection/id": data | DataUpdate | null }` format.
7
8
  * - If data is an object, sets the item.
@@ -9,8 +10,8 @@ import type { Database, AsyncDatabase } from "./Database.js";
9
10
  * - If data is null, deletes the item.
10
11
  * - If data is undefined, skip the item.
11
12
  */
12
- export declare type Changes<DB extends Datas> = {
13
- [K in Key<DB> as `${K}/${string}`]: DB[K] | DataUpdate<DB[K]> | null | undefined;
13
+ export declare type Changes<T extends Datas> = {
14
+ [K in Key<T> as `${K}/${string}`]: T[K] | DataUpdate<T[K]> | null | undefined;
14
15
  };
15
16
  /** Apply a set of changes to a synchronous database. */
16
17
  export declare function changeDatabase<T extends Datas>({ provider }: Database<T>, changes: Changes<T>): Changes<T>;
@@ -20,3 +21,4 @@ export declare function changeAsyncDatabase<T extends Datas>({ provider }: Async
20
21
  export declare function changeProvider<T extends Datas>(provider: Provider<T>, changes: Changes<T>): Changes<T>;
21
22
  /** Apply a set of changes to an asynchronous provider. */
22
23
  export declare function changeAsyncProvider<T extends Datas>(provider: AsyncProvider<T>, changes: Changes<T>): Promise<Changes<T>>;
24
+ export declare function _getItemConstraint<T extends Data>(id: string): ItemConstraints<ItemData<T>>;
package/db/Changes.js CHANGED
@@ -1,5 +1,7 @@
1
1
  import { splitString } from "../util/string.js";
2
2
  import { DataUpdate } from "../update/DataUpdate.js";
3
+ import { QueryConstraints } from "../constraint/QueryConstraints.js";
4
+ import { FilterConstraint } from "../constraint/FilterConstraint.js";
3
5
  /** Apply a set of changes to a synchronous database. */
4
6
  export function changeDatabase({ provider }, changes) {
5
7
  return changeProvider(provider, changes);
@@ -17,7 +19,7 @@ export function changeProvider(provider, changes) {
17
19
  else if (change === null)
18
20
  provider.deleteItem(collection, id);
19
21
  else if (change instanceof DataUpdate)
20
- provider.updateItem(collection, id, change);
22
+ provider.updateQuery(collection, _getItemConstraint(id), change);
21
23
  else
22
24
  provider.setItem(collection, id, change);
23
25
  }
@@ -32,9 +34,12 @@ export async function changeAsyncProvider(provider, changes) {
32
34
  else if (change === null)
33
35
  await provider.deleteItem(collection, id);
34
36
  else if (change instanceof DataUpdate)
35
- await provider.updateItem(collection, id, change);
37
+ await provider.updateQuery(collection, _getItemConstraint(id), change);
36
38
  else
37
39
  await provider.setItem(collection, id, change);
38
40
  }
39
41
  return changes;
40
42
  }
43
+ export function _getItemConstraint(id) {
44
+ return new QueryConstraints(new FilterConstraint("id", id), undefined, 1);
45
+ }
@@ -1,11 +1,35 @@
1
- import { DataUpdate } from "../index.js";
1
+ import { AsyncDatabase, DataUpdate } from "../index.js";
2
2
  test("Typescript", () => {
3
- const operations = {
4
- "collection1/a1": { a: 1, one: false },
3
+ const operations1 = {
4
+ "collection1/a1": { one: 1, bool: false },
5
5
  "collection1/b2": null,
6
- "collection1/b3": new DataUpdate({ one: true }),
7
- "collection2/a1": { b: 1, one: false },
6
+ "collection1/b3": new DataUpdate({ bool: true }),
7
+ "collection2/a1": { two: 1, bool: false },
8
8
  "collection2/b2": null,
9
- "collection2/c3": new DataUpdate({ one: true }),
9
+ "collection2/c3": new DataUpdate({ bool: true }),
10
10
  };
11
+ // Check the keys.
12
+ const operations2 = {
13
+ // @ts-expect-error
14
+ "NOTCOLLECTION/a1": { a: 1, bool: false },
15
+ };
16
+ // Check the values.
17
+ const operations3 = {
18
+ "collection1/a1": {
19
+ one: 1,
20
+ // @ts-expect-error
21
+ bool: "NOTBOOL",
22
+ },
23
+ };
24
+ // Check some objects.
25
+ const db = new AsyncDatabase(undefined);
26
+ const changes = {
27
+ ...db.item("collection1", "a1").getUpdate({ bool: true }),
28
+ ...db.item("collection2", "b2").getSet({ two: 123, bool: false }),
29
+ ...db.item("collection2", "b2").getDelete(),
30
+ };
31
+ // Merging changes.
32
+ const changes1 = {};
33
+ const changes2 = {};
34
+ const changes3 = { ...changes1, ...changes2 };
11
35
  });
@@ -5,35 +5,33 @@ import type { ItemData, AsyncItem, Item } from "./Item.js";
5
5
  import type { AsyncDatabase, Database } from "./Database.js";
6
6
  import type { AsyncQuery, Query } from "./Query.js";
7
7
  /** Reference to a collection in a synchronous or asynchronous provider. */
8
- interface CollectionInterface<T extends Datas = Datas, K extends Key<T> = Key<T>> {
9
- readonly db: Database<T> | AsyncDatabase<T>;
10
- readonly collection: K;
8
+ declare abstract class BaseCollection<T extends Datas = Datas, K extends Key<T> = Key<T>> {
9
+ abstract readonly db: Database<T> | AsyncDatabase<T>;
10
+ abstract readonly collection: K;
11
11
  /** Create a query on this item's collection. */
12
- query(filters?: FilterList<ItemData<T[K]>>, sorts?: SortList<ItemData<T[K]>>, limit?: number | null): Query<T, K> | AsyncQuery<T, K>;
12
+ abstract query(filters?: FilterList<ItemData<T[K]>>, sorts?: SortList<ItemData<T[K]>>, limit?: number | null): Query<T, K> | AsyncQuery<T, K>;
13
13
  /** Create a query on this item's collection. */
14
- item(id: string): Item<T, K> | AsyncItem<T, K>;
14
+ abstract item(id: string): Item<T, K> | AsyncItem<T, K>;
15
15
  /** Add an item to this collection. */
16
- add(data: T[K]): string | Promise<string>;
16
+ abstract add(data: T[K]): string | Promise<string>;
17
17
  toString(): K;
18
18
  }
19
19
  /** Reference to a collection in a synchronous provider. */
20
- export declare class Collection<T extends Datas = Datas, K extends Key<T> = Key<T>> implements CollectionInterface<T, K> {
20
+ export declare class Collection<T extends Datas = Datas, K extends Key<T> = Key<T>> extends BaseCollection<T, K> {
21
21
  readonly db: Database<T>;
22
22
  readonly collection: K;
23
23
  constructor(db: Database<T>, collection: K);
24
24
  query(filters?: FilterList<ItemData<T[K]>>, sorts?: SortList<ItemData<T[K]>>, limit?: number | null): Query<T, K>;
25
25
  item(id: string): Item<T, K>;
26
26
  add(data: T[K]): string;
27
- toString(): K;
28
27
  }
29
28
  /** Reference to a collection in an asynchronous provider. */
30
- export declare class AsyncCollection<T extends Datas = Datas, K extends Key<T> = Key<T>> implements CollectionInterface<T, K> {
29
+ export declare class AsyncCollection<T extends Datas = Datas, K extends Key<T> = Key<T>> extends BaseCollection<T, K> {
31
30
  readonly db: AsyncDatabase<T>;
32
31
  readonly collection: K;
33
32
  constructor(db: AsyncDatabase<T>, collection: K);
34
33
  query(filters?: FilterList<ItemData<T[K]>>, sorts?: SortList<ItemData<T[K]>>, limit?: number | null): AsyncQuery<T, K>;
35
34
  item(id: string): AsyncItem<T, K>;
36
35
  add(data: T[K]): Promise<string>;
37
- toString(): K;
38
36
  }
39
37
  export {};
package/db/Collection.js CHANGED
@@ -1,6 +1,14 @@
1
+ /** Reference to a collection in a synchronous or asynchronous provider. */
2
+ class BaseCollection {
3
+ // Implement toString()
4
+ toString() {
5
+ return this.collection;
6
+ }
7
+ }
1
8
  /** Reference to a collection in a synchronous provider. */
2
- export class Collection {
9
+ export class Collection extends BaseCollection {
3
10
  constructor(db, collection) {
11
+ super();
4
12
  this.db = db;
5
13
  this.collection = collection;
6
14
  }
@@ -13,13 +21,11 @@ export class Collection {
13
21
  add(data) {
14
22
  return this.db.provider.addItem(this.collection, data);
15
23
  }
16
- toString() {
17
- return this.collection;
18
- }
19
24
  }
20
25
  /** Reference to a collection in an asynchronous provider. */
21
- export class AsyncCollection {
26
+ export class AsyncCollection extends BaseCollection {
22
27
  constructor(db, collection) {
28
+ super();
23
29
  this.db = db;
24
30
  this.collection = collection;
25
31
  }
@@ -32,7 +38,4 @@ export class AsyncCollection {
32
38
  add(data) {
33
39
  return this.db.provider.addItem(this.collection, data);
34
40
  }
35
- toString() {
36
- return this.collection;
37
- }
38
41
  }
package/db/Item.d.ts CHANGED
@@ -7,6 +7,7 @@ import { DataUpdate, PropUpdates } from "../update/DataUpdate.js";
7
7
  import type { QueryConstraints } from "../constraint/QueryConstraints.js";
8
8
  import type { AsyncDatabase, Database } from "./Database.js";
9
9
  import type { AsyncQuery, Query } from "./Query.js";
10
+ import type { Changes } from "./Changes.js";
10
11
  /** Item data with a string ID that uniquely identifies it. */
11
12
  export declare type ItemData<T extends Data = Data> = T & {
12
13
  id: string;
@@ -18,21 +19,22 @@ export declare type ItemArray<T extends Data = Data> = ImmutableArray<ItemData<T
18
19
  /** A set of query constraints for item data. */
19
20
  export declare type ItemConstraints<T extends Data = Data> = QueryConstraints<ItemData<T>>;
20
21
  /** Reference to an item in a synchronous or asynchronous provider. */
21
- interface ItemInterface<T extends Datas = Datas, K extends Key<T> = Key<T>> extends Observable<ItemValue<T[K]>> {
22
- readonly collection: K;
23
- readonly id: string;
22
+ declare abstract class BaseItem<T extends Datas = Datas, K extends Key<T> = Key<T>> implements Observable<ItemValue<T[K]>> {
23
+ abstract readonly db: Database<T> | AsyncDatabase<T>;
24
+ abstract readonly collection: K;
25
+ abstract readonly id: string;
24
26
  /** Get an 'optional' reference to this item (uses a `ModelQuery` with an `id` filter). */
25
- optional: Query<T, K> | AsyncQuery<T, K>;
27
+ abstract optional: Query<T, K> | AsyncQuery<T, K>;
26
28
  /**
27
29
  * Does this item exist?
28
30
  * @return `true` if an item exists or `false` otherwise (possibly promised).
29
31
  */
30
- exists: boolean | PromiseLike<boolean>;
32
+ abstract exists: boolean | PromiseLike<boolean>;
31
33
  /**
32
34
  * Get the optional data of this item.
33
35
  * @return Document's data, or `null` if the item doesn't exist (possibly promised).
34
36
  */
35
- value: ItemValue<T[K]> | PromiseLike<ItemValue<T[K]>>;
37
+ abstract value: ItemValue<T[K]> | PromiseLike<ItemValue<T[K]>>;
36
38
  /**
37
39
  * Get the data of this item.
38
40
  * - Useful for destructuring, e.g. `{ name, title } = await itemThatMustExist.asyncData`
@@ -40,7 +42,7 @@ interface ItemInterface<T extends Datas = Datas, K extends Key<T> = Key<T>> exte
40
42
  * @return Document's data (possibly promised).
41
43
  * @throws RequiredError if the item does not exist.
42
44
  */
43
- data: ItemData<T[K]> | PromiseLike<ItemData<T[K]>>;
45
+ abstract data: ItemData<T[K]> | PromiseLike<ItemData<T[K]>>;
44
46
  /**
45
47
  * Subscribe to the result of this item (indefinitely).
46
48
  * - `next()` is called once with the initial result, and again any time the result changes.
@@ -50,15 +52,21 @@ interface ItemInterface<T extends Datas = Datas, K extends Key<T> = Key<T>> exte
50
52
  */
51
53
  subscribe(next: PartialObserver<ItemValue<T[K]>> | Dispatch<[ItemValue<T[K]>]>): Unsubscribe;
52
54
  /** Set the complete data of this item. */
53
- set(data: T[K]): void | PromiseLike<void>;
55
+ abstract set(data: T[K]): void | PromiseLike<void>;
56
+ /** Get a set change for this item. */
57
+ getSet(data: T[K]): Changes<T>;
54
58
  /** Update this item. */
55
- update(updates: DataUpdate<T[K]> | PropUpdates<T[K]>): void | PromiseLike<void>;
59
+ abstract update(updates: DataUpdate<T[K]> | PropUpdates<T[K]>): void | PromiseLike<void>;
60
+ /** Get an update change for this item. */
61
+ getUpdate(updates: DataUpdate<T[K]> | PropUpdates<T[K]>): Changes<T>;
56
62
  /** Delete this item. */
57
- delete(): void | PromiseLike<void>;
63
+ abstract delete(): void | PromiseLike<void>;
64
+ /** Get a delete change for this item. */
65
+ getDelete(): Changes<T>;
58
66
  toString(): `${K}/${string}`;
59
67
  }
60
68
  /** Reference to an item in a synchronous provider. */
61
- export declare class Item<T extends Datas = Datas, K extends Key<T> = Key<T>> implements ItemInterface<T, K> {
69
+ export declare class Item<T extends Datas = Datas, K extends Key<T> = Key<T>> extends BaseItem<T, K> {
62
70
  readonly db: Database<T>;
63
71
  readonly collection: K;
64
72
  readonly id: string;
@@ -67,14 +75,12 @@ export declare class Item<T extends Datas = Datas, K extends Key<T> = Key<T>> im
67
75
  get exists(): boolean;
68
76
  get value(): ItemValue<T[K]>;
69
77
  get data(): ItemData<T[K]>;
70
- subscribe(next: PartialObserver<ItemValue<T[K]>> | Dispatch<[ItemValue<T[K]>]>): Unsubscribe;
71
78
  set(data: T[K]): void;
72
79
  update(updates: DataUpdate<T[K]> | PropUpdates<T[K]>): void;
73
80
  delete(): void;
74
- toString(): `${K}/${string}`;
75
81
  }
76
82
  /** Reference to an item in an asynchronous provider. */
77
- export declare class AsyncItem<T extends Datas = Datas, K extends Key<T> = Key<T>> implements ItemInterface<T, K> {
83
+ export declare class AsyncItem<T extends Datas = Datas, K extends Key<T> = Key<T>> extends BaseItem<T, K> {
78
84
  readonly db: AsyncDatabase<T>;
79
85
  readonly collection: K;
80
86
  readonly id: string;
@@ -83,11 +89,9 @@ export declare class AsyncItem<T extends Datas = Datas, K extends Key<T> = Key<T
83
89
  get exists(): Promise<boolean>;
84
90
  get value(): Promise<ItemValue<T[K]>>;
85
91
  get data(): Promise<ItemData<T[K]>>;
86
- subscribe(next: PartialObserver<ItemValue<T[K]>> | Dispatch<[ItemValue<T[K]>]>): Unsubscribe;
87
92
  set(data: T[K]): Promise<void>;
88
93
  update(updates: DataUpdate<T[K]> | PropUpdates<T[K]>): Promise<void>;
89
94
  delete(): Promise<void>;
90
- toString(): `${K}/${string}`;
91
95
  }
92
96
  /** Get the ID from item data. */
93
97
  export declare const getID: <T extends Data>({ id }: ItemData<T>) => string;
package/db/Item.js CHANGED
@@ -1,9 +1,40 @@
1
1
  import { getData } from "../util/data.js";
2
2
  import { FilterConstraint } from "../constraint/FilterConstraint.js";
3
3
  import { DataUpdate } from "../update/DataUpdate.js";
4
+ import { isTransformable } from "../util/transform.js";
5
+ /** Reference to an item in a synchronous or asynchronous provider. */
6
+ class BaseItem {
7
+ /**
8
+ * Subscribe to the result of this item (indefinitely).
9
+ * - `next()` is called once with the initial result, and again any time the result changes.
10
+ *
11
+ * @param next Observer with `next`, `error`, or `complete` methods or a `next()` dispatcher.
12
+ * @return Function that ends the subscription.
13
+ */
14
+ subscribe(next) {
15
+ return this.db.provider.subscribeItem(this.collection, this.id, typeof next === "function" ? { next } : next);
16
+ }
17
+ /** Get a set change for this item. */
18
+ getSet(data) {
19
+ return { [this.toString()]: data };
20
+ }
21
+ /** Get an update change for this item. */
22
+ getUpdate(updates) {
23
+ return { [this.toString()]: updates instanceof DataUpdate ? updates : new DataUpdate(updates) };
24
+ }
25
+ /** Get a delete change for this item. */
26
+ getDelete() {
27
+ return { [this.toString()]: null };
28
+ }
29
+ // Implement toString()
30
+ toString() {
31
+ return `${this.collection}/${this.id}`;
32
+ }
33
+ }
4
34
  /** Reference to an item in a synchronous provider. */
5
- export class Item {
35
+ export class Item extends BaseItem {
6
36
  constructor(db, collection, id) {
37
+ super();
7
38
  this.db = db;
8
39
  this.collection = collection;
9
40
  this.id = id;
@@ -20,25 +51,20 @@ export class Item {
20
51
  get data() {
21
52
  return getData(this.value);
22
53
  }
23
- subscribe(next) {
24
- return this.db.provider.subscribeItem(this.collection, this.id, typeof next === "function" ? { next } : next);
25
- }
26
54
  set(data) {
27
55
  return this.db.provider.setItem(this.collection, this.id, data);
28
56
  }
29
57
  update(updates) {
30
- return this.db.provider.updateItem(this.collection, this.id, updates instanceof DataUpdate ? updates : new DataUpdate(updates));
58
+ return this.db.provider.updateItem(this.collection, this.id, isTransformable(updates) ? updates : new DataUpdate(updates));
31
59
  }
32
60
  delete() {
33
61
  return this.db.provider.deleteItem(this.collection, this.id);
34
62
  }
35
- toString() {
36
- return `${this.collection}/${this.id}`;
37
- }
38
63
  }
39
64
  /** Reference to an item in an asynchronous provider. */
40
- export class AsyncItem {
65
+ export class AsyncItem extends BaseItem {
41
66
  constructor(provider, collection, id) {
67
+ super();
42
68
  this.db = provider;
43
69
  this.collection = collection;
44
70
  this.id = id;
@@ -55,21 +81,15 @@ export class AsyncItem {
55
81
  get data() {
56
82
  return this.value.then(getData);
57
83
  }
58
- subscribe(next) {
59
- return this.db.provider.subscribeItem(this.collection, this.id, typeof next === "function" ? { next } : next);
60
- }
61
84
  set(data) {
62
85
  return this.db.provider.setItem(this.collection, this.id, data);
63
86
  }
64
87
  update(updates) {
65
- return this.db.provider.updateItem(this.collection, this.id, updates instanceof DataUpdate ? updates : new DataUpdate(updates));
88
+ return this.db.provider.updateItem(this.collection, this.id, isTransformable(updates) ? updates : new DataUpdate(updates));
66
89
  }
67
90
  delete() {
68
91
  return this.db.provider.deleteItem(this.collection, this.id);
69
92
  }
70
- toString() {
71
- return `${this.collection}/${this.id}`;
72
- }
73
93
  }
74
94
  /** Get the ID from item data. */
75
95
  export const getID = ({ id }) => id;
package/db/Query.d.ts CHANGED
@@ -9,43 +9,44 @@ import { DataUpdate, PropUpdates } from "../update/DataUpdate.js";
9
9
  import type { ItemArray, ItemValue, ItemData } from "./Item.js";
10
10
  import type { AsyncDatabase, Database } from "./Database.js";
11
11
  /** Reference to a set of items in a sync or async provider. */
12
- interface QueryInterface<T extends Datas = Datas, K extends Key<T> = Key<T>> extends QueryConstraints<ItemData<T[K]>>, Observable<ItemArray<T[K]>> {
13
- readonly collection: K;
12
+ declare abstract class BaseQuery<T extends Datas = Datas, K extends Key<T> = Key<T>> extends QueryConstraints<ItemData<T[K]>> implements Observable<ItemArray<T[K]>> {
13
+ abstract readonly db: Database<T> | AsyncDatabase<T>;
14
+ abstract readonly collection: K;
14
15
  /**
15
16
  * Get array of entities for this query.
16
17
  * @return Array of entities.
17
18
  */
18
- value: ItemArray<T[K]> | PromiseLike<ItemArray<T[K]>>;
19
+ abstract value: ItemArray<T[K]> | PromiseLike<ItemArray<T[K]>>;
19
20
  /**
20
21
  * Count the number of results of this set of items.
21
22
  * @return Number of items matching the query (possibly promised).
22
23
  */
23
- count: number | PromiseLike<number>;
24
+ abstract count: number | PromiseLike<number>;
24
25
  /**
25
26
  * Does at least one item exist for this query?
26
27
  * @return `true` if a item exists or `false` otherwise (possibly promised).
27
28
  */
28
- exists: boolean | PromiseLike<boolean>;
29
+ abstract exists: boolean | PromiseLike<boolean>;
29
30
  /**
30
31
  * Get the first item matched by this query or `null` if this query has no results.
31
32
  * @throws RequiredError if there were no results for this query.
32
33
  */
33
- firstValue: ItemValue<T[K]> | PromiseLike<ItemValue<T[K]>>;
34
+ abstract firstValue: ItemValue<T[K]> | PromiseLike<ItemValue<T[K]>>;
34
35
  /**
35
36
  * Get the first item matched by this query.
36
37
  * @throws RequiredError if there were no results for this query.
37
38
  */
38
- firstData: ItemData<T[K]> | PromiseLike<ItemData<T[K]>>;
39
+ abstract firstData: ItemData<T[K]> | PromiseLike<ItemData<T[K]>>;
39
40
  /**
40
41
  * Get the last item matched by this query or `null` if this query has no results.
41
42
  * @throws RequiredError if there were no results for this query.
42
43
  */
43
- lastValue: ItemValue<T[K]> | PromiseLike<ItemValue<T[K]>>;
44
+ abstract lastValue: ItemValue<T[K]> | PromiseLike<ItemValue<T[K]>>;
44
45
  /**
45
46
  * Get the last item matched by this query.
46
47
  * @throws RequiredError if there were no results for this query.
47
48
  */
48
- lastData: ItemData<T[K]> | PromiseLike<ItemData<T[K]>>;
49
+ abstract lastData: ItemData<T[K]> | PromiseLike<ItemData<T[K]>>;
49
50
  /**
50
51
  * Subscribe to all matching items.
51
52
  * - `next()` is called once with the initial results, and again any time the results change.
@@ -60,22 +61,23 @@ interface QueryInterface<T extends Datas = Datas, K extends Key<T> = Key<T>> ext
60
61
  * @param data Complete data to set the item to.
61
62
  * @return Nothing (possibly promised).
62
63
  */
63
- set(data: T[K]): number | PromiseLike<number>;
64
+ abstract set(data: T[K]): number | PromiseLike<number>;
64
65
  /**
65
66
  * Update all matching items with the same partial value.
66
67
  *
67
68
  * @param updates `Update` instance or set of updates to apply to every matching item.
68
69
  * @return Nothing (possibly promised).
69
70
  */
70
- update(updates: DataUpdate<T[K]> | PropUpdates<T[K]>): number | PromiseLike<number>;
71
+ abstract update(updates: DataUpdate<T[K]> | PropUpdates<T[K]>): number | PromiseLike<number>;
71
72
  /**
72
73
  * Delete all matching items.
73
74
  * @return Nothing (possibly promised).
74
75
  */
75
- delete(): number | PromiseLike<number>;
76
+ abstract delete(): number | PromiseLike<number>;
77
+ toString(): string;
76
78
  }
77
79
  /** Reference to a set of items in a provider. */
78
- export declare class Query<T extends Datas = Datas, K extends Key<T> = Key<T>> extends QueryConstraints<ItemData<T[K]>> implements QueryInterface<T, K> {
80
+ export declare class Query<T extends Datas = Datas, K extends Key<T> = Key<T>> extends BaseQuery<T, K> implements BaseQuery<T, K> {
79
81
  readonly db: Database<T>;
80
82
  readonly collection: K;
81
83
  constructor(db: Database<T>, collection: K, filters?: FilterList<ItemData<T[K]>>, sorts?: SortList<ItemData<T[K]>>, limit?: number | null);
@@ -86,18 +88,15 @@ export declare class Query<T extends Datas = Datas, K extends Key<T> = Key<T>> e
86
88
  get firstData(): ItemData<T[K]>;
87
89
  get lastValue(): ItemValue<T[K]>;
88
90
  get lastData(): ItemData<T[K]>;
89
- subscribe(next: PartialObserver<ItemArray<T[K]>> | Dispatch<[ItemArray<T[K]>]>): Unsubscribe;
90
91
  set(data: T[K]): number;
91
92
  update(updates: DataUpdate<T[K]> | PropUpdates<T[K]>): number;
92
93
  delete(): number;
93
- toString(): string;
94
94
  }
95
95
  /** Reference to a set of items in a provider. */
96
- export declare class AsyncQuery<T extends Datas = Datas, K extends Key<T> = Key<T>> extends QueryConstraints<ItemData<T[K]>> implements QueryInterface<T, K> {
96
+ export declare class AsyncQuery<T extends Datas = Datas, K extends Key<T> = Key<T>> extends BaseQuery<T, K> implements BaseQuery<T, K> {
97
97
  readonly db: AsyncDatabase<T>;
98
98
  readonly collection: K;
99
99
  constructor(db: AsyncDatabase<T>, collection: K, filters?: FilterList<ItemData<T[K]>>, sorts?: SortList<ItemData<T[K]>>, limit?: number | null);
100
- closed?: boolean;
101
100
  get value(): Promise<ItemArray<T[K]>>;
102
101
  get count(): Promise<number>;
103
102
  get exists(): Promise<boolean>;
@@ -105,10 +104,8 @@ export declare class AsyncQuery<T extends Datas = Datas, K extends Key<T> = Key<
105
104
  get firstData(): Promise<ItemData<T[K]>>;
106
105
  get lastValue(): Promise<ItemValue<T[K]>>;
107
106
  get lastData(): Promise<ItemData<T[K]>>;
108
- subscribe(next: PartialObserver<ItemArray<T[K]>> | Dispatch<[ItemArray<T[K]>]>): Unsubscribe;
109
107
  set(data: T[K]): Promise<number>;
110
108
  update(updates: DataUpdate<T[K]> | PropUpdates<T[K]>): PromiseLike<number>;
111
109
  delete(): PromiseLike<number>;
112
- toString(): string;
113
110
  }
114
111
  export {};
package/db/Query.js CHANGED
@@ -2,8 +2,25 @@ import { getFirstItem, getLastItem, getOptionalFirstItem, getOptionalLastItem }
2
2
  import { QueryConstraints } from "../constraint/QueryConstraints.js";
3
3
  import { countItems, hasItems } from "../util/iterate.js";
4
4
  import { DataUpdate } from "../update/DataUpdate.js";
5
+ /** Reference to a set of items in a sync or async provider. */
6
+ class BaseQuery extends QueryConstraints {
7
+ /**
8
+ * Subscribe to all matching items.
9
+ * - `next()` is called once with the initial results, and again any time the results change.
10
+ *
11
+ * @param next Observer with `next`, `error`, or `complete` methods or a `next()` dispatcher.
12
+ * @return Function that ends the subscription.
13
+ */
14
+ subscribe(next) {
15
+ return this.db.provider.subscribeQuery(this.collection, this, typeof next === "function" ? { next } : next);
16
+ }
17
+ // Override to include the collection name.
18
+ toString() {
19
+ return `${this.collection}?${super.toString()}`;
20
+ }
21
+ }
5
22
  /** Reference to a set of items in a provider. */
6
- export class Query extends QueryConstraints {
23
+ export class Query extends BaseQuery {
7
24
  constructor(db, collection, filters, sorts, limit) {
8
25
  super(filters, sorts, limit);
9
26
  this.db = db;
@@ -30,9 +47,6 @@ export class Query extends QueryConstraints {
30
47
  get lastData() {
31
48
  return getLastItem(this.value);
32
49
  }
33
- subscribe(next) {
34
- return this.db.provider.subscribeQuery(this.collection, this, typeof next === "function" ? { next } : next);
35
- }
36
50
  set(data) {
37
51
  return this.db.provider.setQuery(this.collection, this, data);
38
52
  }
@@ -42,12 +56,9 @@ export class Query extends QueryConstraints {
42
56
  delete() {
43
57
  return this.db.provider.deleteQuery(this.collection, this);
44
58
  }
45
- toString() {
46
- return `${this.collection}?${super.toString()}`;
47
- }
48
59
  }
49
60
  /** Reference to a set of items in a provider. */
50
- export class AsyncQuery extends QueryConstraints {
61
+ export class AsyncQuery extends BaseQuery {
51
62
  constructor(db, collection, filters, sorts, limit) {
52
63
  super(filters, sorts, limit);
53
64
  this.db = db;
@@ -74,9 +85,6 @@ export class AsyncQuery extends QueryConstraints {
74
85
  get lastData() {
75
86
  return this.value.then(getLastItem);
76
87
  }
77
- subscribe(next) {
78
- return this.db.provider.subscribeQuery(this.collection, this, typeof next === "function" ? { next } : next);
79
- }
80
88
  set(data) {
81
89
  return this.db.provider.setQuery(this.collection, this, data);
82
90
  }
@@ -86,7 +94,4 @@ export class AsyncQuery extends QueryConstraints {
86
94
  delete() {
87
95
  return this.db.provider.deleteQuery(this.collection, this);
88
96
  }
89
- toString() {
90
- return `${this.collection}?${super.toString()}`;
91
- }
92
97
  }
package/package.json CHANGED
@@ -11,7 +11,7 @@
11
11
  "state-management",
12
12
  "query-builder"
13
13
  ],
14
- "version": "1.73.3",
14
+ "version": "1.74.0",
15
15
  "repository": "https://github.com/dhoulb/shelving",
16
16
  "author": "Dave Houlbrooke <dave@shax.com>",
17
17
  "license": "0BSD",
@@ -6,7 +6,7 @@ import type { ArrayType, ImmutableArray } from "./array.js";
6
6
  export interface Transformable<I, O> {
7
7
  transform(input: I): O;
8
8
  }
9
- /** Is an unknown value a derivable. */
9
+ /** Is an unknown value a transformable. */
10
10
  export declare const isTransformable: <T extends Transformable<unknown, unknown>>(v: unknown) => v is T;
11
11
  /** Function that can transform an input value into an output value. */
12
12
  export declare type Transform<I, O> = (input: I) => O;
package/util/transform.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import { isFunction } from "./function.js";
2
2
  import { getProps, isData } from "./data.js";
3
3
  import { getEntries } from "./entry.js";
4
- /** Is an unknown value a derivable. */
4
+ /** Is an unknown value a transformable. */
5
5
  export const isTransformable = (v) => isData(v) && typeof v.transform === "function";
6
6
  export function transform(input, transformer) {
7
7
  return isFunction(transformer) ? transformer(input) : isTransformable(transformer) ? transformer.transform(input) : transformer;