shelving 1.76.0 → 1.76.1

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/Change.d.ts CHANGED
@@ -1,35 +1,36 @@
1
- import type { Data, Datas, Key } from "../util/data.js";
1
+ import type { Data, Datas, Key, Value } from "../util/data.js";
2
2
  import type { ImmutableArray } from "../util/array.js";
3
3
  import type { Provider, AsyncProvider } from "../provider/Provider.js";
4
4
  import { DataUpdate } from "../update/DataUpdate.js";
5
5
  import { Nullish } from "../util/null.js";
6
+ import { DeepIterable } from "../util/iterate.js";
6
7
  import type { ItemConstraints, ItemData } from "./Item.js";
7
- export interface Change<T extends Datas, K extends Key<T>> {
8
+ export interface Change<T extends Datas> {
8
9
  readonly action: string;
9
- readonly collection: K;
10
+ readonly collection: Key<T>;
10
11
  }
11
12
  /** Add on an item. */
12
- export interface AddChange<T extends Datas, K extends Key<T>> extends Change<T, K> {
13
+ export interface AddChange<T extends Datas, K extends Key<T> = Key<T>> extends Change<T> {
13
14
  readonly action: "ADD";
14
15
  readonly collection: K;
15
16
  readonly data: T[K];
16
17
  }
17
18
  /** Set on an item. */
18
- export interface SetChange<T extends Datas, K extends Key<T>> extends Change<T, K> {
19
+ export interface SetChange<T extends Datas, K extends Key<T> = Key<T>> extends Change<T> {
19
20
  readonly action: "SET";
20
21
  readonly collection: K;
21
22
  readonly id: string;
22
23
  readonly data: T[K];
23
24
  }
24
25
  /** Update change on an item. */
25
- export interface UpdateChange<T extends Datas, K extends Key<T>> extends Change<T, K> {
26
+ export interface UpdateChange<T extends Datas, K extends Key<T> = Key<T>> extends Change<T> {
26
27
  readonly action: "UPDATE";
27
28
  readonly collection: K;
28
29
  readonly id: string;
29
- readonly update: DataUpdate<T[K]>;
30
+ readonly update: DataUpdate<Value<T>>;
30
31
  }
31
32
  /** Delete change on an item. */
32
- export interface DeleteChange<T extends Datas, K extends Key<T>> extends Change<T, K> {
33
+ export interface DeleteChange<T extends Datas, K extends Key<T> = Key<T>> extends Change<T> {
33
34
  readonly action: "DELETE";
34
35
  readonly collection: K;
35
36
  readonly id: string;
@@ -43,7 +44,7 @@ export declare type WriteChange<T extends Datas, K extends Key<T> = Key<T>> = It
43
44
  /** Array of write changes. */
44
45
  export declare type WriteChanges<T extends Datas, K extends Key<T> = Key<T>> = ImmutableArray<WriteChange<T, K>>;
45
46
  /** Apply a set of changes to a synchronous provider. */
46
- export declare function changeProvider<T extends Datas, K extends Key<T> = Key<T>>(provider: Provider<T>, changes: ImmutableArray<Nullish<WriteChange<T, K>>>): ItemChanges<T, K>;
47
+ export declare function changeProvider<T extends Datas, K extends Key<T>>(provider: Provider<T>, ...changes: DeepIterable<Nullish<WriteChange<T, K>>>[]): ItemChanges<T, K>;
47
48
  /** Apply a set of changes to an asynchronous provider. */
48
- export declare function changeAsyncProvider<T extends Datas, K extends Key<T>>(provider: AsyncProvider<T>, changes: ImmutableArray<Nullish<WriteChange<T, K>>>): Promise<ItemChanges<T, K>>;
49
+ export declare function changeAsyncProvider<T extends Datas, K extends Key<T>>(provider: AsyncProvider<T>, ...changes: DeepIterable<Nullish<WriteChange<T, K>>>[]): Promise<ItemChanges<T, K>>;
49
50
  export declare function _getItemConstraint<T extends Data>(id: string): ItemConstraints<ItemData<T>>;
package/db/Change.js CHANGED
@@ -1,9 +1,10 @@
1
1
  import { QueryConstraints } from "../constraint/QueryConstraints.js";
2
2
  import { FilterConstraint } from "../constraint/FilterConstraint.js";
3
3
  import { notNullish } from "../util/null.js";
4
+ import { flattenDeepIterable } from "../util/iterate.js";
4
5
  /** Apply a set of changes to a synchronous provider. */
5
- export function changeProvider(provider, changes) {
6
- return changes.filter(notNullish).map(_changeItem, provider);
6
+ export function changeProvider(provider, ...changes) {
7
+ return Array.from(flattenDeepIterable(changes)).filter(notNullish).map(_changeItem, provider);
7
8
  }
8
9
  function _changeItem(change) {
9
10
  const { action, collection } = change;
@@ -18,8 +19,8 @@ function _changeItem(change) {
18
19
  return change;
19
20
  }
20
21
  /** Apply a set of changes to an asynchronous provider. */
21
- export function changeAsyncProvider(provider, changes) {
22
- return Promise.all(changes.filter(notNullish).map(_changeAsyncItem, provider));
22
+ export function changeAsyncProvider(provider, ...changes) {
23
+ return Promise.all(Array.from(flattenDeepIterable(changes)).filter(notNullish).map(_changeAsyncItem, provider));
23
24
  }
24
25
  async function _changeAsyncItem(change) {
25
26
  const { collection, action } = change;
@@ -2,10 +2,11 @@ import type { Datas, Key } from "../util/data.js";
2
2
  import type { Nullish } from "../util/null.js";
3
3
  import type { FilterList } from "../constraint/FilterConstraint.js";
4
4
  import type { SortList } from "../constraint/SortConstraint.js";
5
- import type { ItemData, AsyncItem, Item } from "./Item.js";
5
+ import type { DeepIterable } from "../util/iterate.js";
6
6
  import type { AsyncDatabase, Database } from "./Database.js";
7
- import type { AsyncQuery, Query } from "./Query.js";
8
- import type { AddChange, ItemChanges, WriteChange } from "./Change.js";
7
+ import { ItemData, AsyncItem, Item } from "./Item.js";
8
+ import { AsyncQuery, Query } from "./Query.js";
9
+ import { AddChange, ItemChanges, WriteChange } from "./Change.js";
9
10
  /** Reference to a collection in a synchronous or asynchronous provider. */
10
11
  declare abstract class BaseCollection<T extends Datas = Datas, K extends Key<T> = Key<T>> {
11
12
  abstract readonly db: Database<T> | AsyncDatabase<T>;
@@ -17,7 +18,7 @@ declare abstract class BaseCollection<T extends Datas = Datas, K extends Key<T>
17
18
  /** Add an item to this collection. */
18
19
  abstract add(data: T[K]): string | Promise<string>;
19
20
  /** Run a set of changes on this database. */
20
- abstract change(...changes: Nullish<WriteChange<T, K>>[]): ItemChanges<T, K> | Promise<ItemChanges<T, K>>;
21
+ abstract change(...changes: DeepIterable<Nullish<WriteChange<T, K>>>[]): ItemChanges<T, K> | Promise<ItemChanges<T, K>>;
21
22
  /** Get an add change for this collection. */
22
23
  getAdd(data: T[K]): AddChange<T, K>;
23
24
  toString(): K;
@@ -30,7 +31,7 @@ export declare class Collection<T extends Datas = Datas, K extends Key<T> = Key<
30
31
  query(filters?: FilterList<ItemData<T[K]>>, sorts?: SortList<ItemData<T[K]>>, limit?: number | null): Query<T, K>;
31
32
  item(id: string): Item<T, K>;
32
33
  add(data: T[K]): string;
33
- change(...changes: Nullish<WriteChange<T, K>>[]): ItemChanges<T, K>;
34
+ change(...changes: DeepIterable<Nullish<WriteChange<T, K>>>[]): ItemChanges<T, K>;
34
35
  }
35
36
  /** Reference to a collection in an asynchronous provider. */
36
37
  export declare class AsyncCollection<T extends Datas = Datas, K extends Key<T> = Key<T>> extends BaseCollection<T, K> {
@@ -40,6 +41,6 @@ export declare class AsyncCollection<T extends Datas = Datas, K extends Key<T> =
40
41
  query(filters?: FilterList<ItemData<T[K]>>, sorts?: SortList<ItemData<T[K]>>, limit?: number | null): AsyncQuery<T, K>;
41
42
  item(id: string): AsyncItem<T, K>;
42
43
  add(data: T[K]): Promise<string>;
43
- change(...changes: Nullish<WriteChange<T, K>>[]): Promise<ItemChanges<T, K>>;
44
+ change(...changes: DeepIterable<Nullish<WriteChange<T, K>>>[]): Promise<ItemChanges<T, K>>;
44
45
  }
45
46
  export {};
package/db/Collection.js CHANGED
@@ -1,3 +1,6 @@
1
+ import { AsyncItem, Item } from "./Item.js";
2
+ import { AsyncQuery, Query } from "./Query.js";
3
+ import { changeAsyncProvider, changeProvider } from "./Change.js";
1
4
  /** Reference to a collection in a synchronous or asynchronous provider. */
2
5
  class BaseCollection {
3
6
  /** Get an add change for this collection. */
@@ -17,16 +20,16 @@ export class Collection extends BaseCollection {
17
20
  this.collection = collection;
18
21
  }
19
22
  query(filters, sorts, limit) {
20
- return this.db.query(this.collection, filters, sorts, limit);
23
+ return new Query(this.db, this.collection, filters, sorts, limit);
21
24
  }
22
25
  item(id) {
23
- return this.db.item(this.collection, id);
26
+ return new Item(this.db, this.collection, id);
24
27
  }
25
28
  add(data) {
26
29
  return this.db.provider.addItem(this.collection, data);
27
30
  }
28
31
  change(...changes) {
29
- return this.db.change(...changes);
32
+ return changeProvider(this.db.provider, changes);
30
33
  }
31
34
  }
32
35
  /** Reference to a collection in an asynchronous provider. */
@@ -37,15 +40,15 @@ export class AsyncCollection extends BaseCollection {
37
40
  this.collection = collection;
38
41
  }
39
42
  query(filters, sorts, limit) {
40
- return this.db.query(this.collection, filters, sorts, limit);
43
+ return new AsyncQuery(this.db, this.collection, filters, sorts, limit);
41
44
  }
42
45
  item(id) {
43
- return this.db.item(this.collection, id);
46
+ return new AsyncItem(this.db, this.collection, id);
44
47
  }
45
48
  add(data) {
46
49
  return this.db.provider.addItem(this.collection, data);
47
50
  }
48
51
  change(...changes) {
49
- return this.db.change(...changes);
52
+ return changeAsyncProvider(this.db.provider, changes);
50
53
  }
51
54
  }
package/db/Database.d.ts CHANGED
@@ -4,6 +4,7 @@ import type { FilterList } from "../constraint/FilterConstraint.js";
4
4
  import type { SortList } from "../constraint/SortConstraint.js";
5
5
  import type { ItemData } from "../db/Item.js";
6
6
  import type { Nullish } from "../util/null.js";
7
+ import { DeepIterable } from "../util/iterate.js";
7
8
  import { Item, AsyncItem } from "./Item.js";
8
9
  import { Query, AsyncQuery } from "./Query.js";
9
10
  import { Collection, AsyncCollection } from "./Collection.js";
@@ -12,30 +13,30 @@ import { ItemChanges, WriteChange } from "./Change.js";
12
13
  declare abstract class BaseDatabase<T extends Datas> {
13
14
  abstract readonly provider: Provider<T> | AsyncProvider<T>;
14
15
  /** Create a query on a collection in this database. */
15
- abstract collection<K extends Key<T>>(collection: K): Collection<T, K> | AsyncCollection<T, K>;
16
+ abstract collection<K extends Key<T>>(collection: K): Collection<Pick<T, K>, K> | AsyncCollection<Pick<T, K>, K>;
16
17
  /** Create a query on a collection in this database. */
17
- abstract query<K extends Key<T>>(collection: K, filters?: FilterList<ItemData<T[K]>>, sorts?: SortList<ItemData<T[K]>>, limit?: number | null): Query<T, K> | AsyncQuery<T, K>;
18
+ abstract query<K extends Key<T>>(collection: K, filters?: FilterList<ItemData<T[K]>>, sorts?: SortList<ItemData<T[K]>>, limit?: number | null): Query<Pick<T, K>, K> | AsyncQuery<Pick<T, K>, K>;
18
19
  /** Reference an item in a collection in this database. */
19
- abstract item<K extends Key<T>>(collection: K, id: string): Item<T, K> | AsyncItem<T, K>;
20
+ abstract item<K extends Key<T>>(collection: K, id: string): Item<Pick<T, K>, K> | AsyncItem<Pick<T, K>, K>;
20
21
  /** Run a set of changes on this database. */
21
- abstract change<K extends Key<T>>(...changes: Nullish<WriteChange<T, K>>[]): ItemChanges<T, K> | Promise<ItemChanges<T, K>>;
22
+ abstract change<K extends Key<T>>(...changes: DeepIterable<Nullish<WriteChange<Pick<T, K>, K>>>[]): ItemChanges<Pick<T, K>, K> | Promise<ItemChanges<Pick<T, K>, K>>;
22
23
  }
23
24
  /** Database with a synchronous provider. */
24
25
  export declare class Database<T extends Datas = Datas> implements BaseDatabase<T> {
25
26
  readonly provider: Provider<T>;
26
27
  constructor(provider: Provider<T>);
27
- collection<K extends Key<T>>(collection: K): Collection<T, K>;
28
- query<K extends Key<T>>(collection: K, filters?: FilterList<ItemData<T[K]>>, sorts?: SortList<ItemData<T[K]>>, limit?: number | null): Query<T, K>;
29
- item<K extends Key<T>>(collection: K, id: string): Item<T, K>;
30
- change<K extends Key<T>>(...changes: Nullish<WriteChange<T, K>>[]): ItemChanges<T, K>;
28
+ collection<K extends Key<T>>(collection: K): Collection<Pick<T, K>, K>;
29
+ query<K extends Key<T>>(collection: K, filters?: FilterList<ItemData<T[K]>>, sorts?: SortList<ItemData<T[K]>>, limit?: number | null): Query<Pick<T, K>, K>;
30
+ item<K extends Key<T>>(collection: K, id: string): Item<Pick<T, K>, K>;
31
+ change<K extends Key<T>>(...changes: DeepIterable<Nullish<WriteChange<Pick<T, K>, K>>>[]): ItemChanges<Pick<T, K>, K>;
31
32
  }
32
33
  /** Database with a synchronous provider. */
33
34
  export declare class AsyncDatabase<T extends Datas = Datas> implements BaseDatabase<T> {
34
35
  readonly provider: AsyncProvider<T>;
35
36
  constructor(provider: AsyncProvider<T>);
36
- collection<K extends Key<T>>(collection: K): AsyncCollection<T, K>;
37
- query<K extends Key<T>>(collection: K, filters?: FilterList<ItemData<T[K]>>, sorts?: SortList<ItemData<T[K]>>, limit?: number | null): AsyncQuery<T, K>;
38
- item<K extends Key<T>>(collection: K, id: string): AsyncItem<T, K>;
39
- change<K extends Key<T>>(...changes: Nullish<WriteChange<T, K>>[]): Promise<ItemChanges<T, K>>;
37
+ collection<K extends Key<T>>(collection: K): AsyncCollection<Pick<T, K>, K>;
38
+ query<K extends Key<T>>(collection: K, filters?: FilterList<ItemData<T[K]>>, sorts?: SortList<ItemData<T[K]>>, limit?: number | null): AsyncQuery<Pick<T, K>, K>;
39
+ item<K extends Key<T>>(collection: K, id: string): AsyncItem<Pick<T, K>, K>;
40
+ change<K extends Key<T>>(...changes: DeepIterable<Nullish<WriteChange<Pick<T, K>, K>>>[]): Promise<ItemChanges<Pick<T, K>, K>>;
40
41
  }
41
42
  export {};
package/package.json CHANGED
@@ -11,7 +11,7 @@
11
11
  "state-management",
12
12
  "query-builder"
13
13
  ],
14
- "version": "1.76.0",
14
+ "version": "1.76.1",
15
15
  "repository": "https://github.com/dhoulb/shelving",
16
16
  "author": "Dave Houlbrooke <dave@shax.com>",
17
17
  "license": "0BSD",
@@ -1,17 +1,17 @@
1
1
  import type { Unsubscribe } from "../observe/Observable.js";
2
- import { Key, Datas } from "../util/data.js";
2
+ import { Datas, Value } from "../util/data.js";
3
3
  import { ItemValue, ItemData, AsyncItem, Item } from "../db/Item.js";
4
4
  import { State } from "../state/State.js";
5
5
  import { BooleanState } from "../state/BooleanState.js";
6
6
  /** Hold the current state of a item. */
7
- export declare class ItemState<T extends Datas, K extends Key<T>> extends State<ItemValue<T[K]>> {
8
- readonly ref: Item<T, K> | AsyncItem<T, K>;
7
+ export declare class ItemState<T extends Datas> extends State<ItemValue<Value<T>>> {
8
+ readonly ref: Item<T> | AsyncItem<T>;
9
9
  readonly busy: BooleanState;
10
10
  /** Get the data of the item (throws `RequiredError` if item doesn't exist). */
11
- get data(): ItemData<T[K]>;
11
+ get data(): ItemData<Value<T>>;
12
12
  /** Does the item exist (i.e. its value isn't `null`)? */
13
13
  get exists(): boolean;
14
- constructor(ref: Item<T, K> | AsyncItem<T, K>);
14
+ constructor(ref: Item<T> | AsyncItem<T>);
15
15
  /** Refresh this state from the source provider. */
16
16
  readonly refresh: () => void;
17
17
  _refresh(): Promise<void>;
@@ -28,5 +28,5 @@ export declare class ItemState<T extends Datas, K extends Key<T>> extends State<
28
28
  * Use an item in a React component.
29
29
  * - Uses the default cache, so will error if not used inside `<Cache>`
30
30
  */
31
- export declare function useItem<T extends Datas, K extends Key<T>>(ref: Item<T, K> | AsyncItem<T, K>): ItemState<T, K>;
32
- export declare function useItem<T extends Datas, K extends Key<T>>(ref?: Item<T, K> | AsyncItem<T, K>): ItemState<T, K> | undefined;
31
+ export declare function useItem<T extends Datas>(ref: Item<T> | AsyncItem<T>): ItemState<T>;
32
+ export declare function useItem<T extends Datas>(ref?: Item<T> | AsyncItem<T>): ItemState<T> | undefined;
@@ -1,30 +1,30 @@
1
1
  import type { Unsubscribe } from "../observe/Observable.js";
2
- import type { Key, Datas } from "../util/data.js";
2
+ import type { Datas, Value } from "../util/data.js";
3
3
  import type { ItemArray, ItemValue, ItemData } from "../db/Item.js";
4
4
  import { AsyncQuery, Query } from "../db/Query.js";
5
5
  import { State } from "../state/State.js";
6
6
  import { BooleanState } from "../state/BooleanState.js";
7
7
  /** Hold the current state of a query. */
8
- export declare class QueryState<T extends Datas, K extends Key<T>> extends State<ItemArray<T[K]>> {
9
- readonly ref: Query<T, K> | AsyncQuery<T, K>;
8
+ export declare class QueryState<T extends Datas> extends State<ItemArray<Value<T>>> {
9
+ readonly ref: Query<T> | AsyncQuery<T>;
10
10
  readonly busy: BooleanState;
11
11
  readonly limit: number;
12
12
  /** Can more items be loaded after the current result. */
13
13
  get hasMore(): boolean;
14
14
  private _hasMore;
15
15
  /** Get the first document matched by this query or `null` if this query has no items. */
16
- get firstValue(): ItemValue<T[K]>;
16
+ get firstValue(): ItemValue<Value<T>>;
17
17
  /** Get the first document matched by this query. */
18
- get firstData(): ItemData<T[K]>;
18
+ get firstData(): ItemData<Value<T>>;
19
19
  /** Get the last document matched by this query or `null` if this query has no items. */
20
- get lastValue(): ItemValue<T[K]>;
20
+ get lastValue(): ItemValue<Value<T>>;
21
21
  /** Get the last document matched by this query. */
22
- get lastData(): ItemData<T[K]>;
22
+ get lastData(): ItemData<Value<T>>;
23
23
  /** Does the document have at least one result. */
24
24
  get exists(): boolean;
25
25
  /** Get the number of items matching this query. */
26
26
  get count(): number;
27
- constructor(ref: Query<T, K> | AsyncQuery<T, K>);
27
+ constructor(ref: Query<T> | AsyncQuery<T>);
28
28
  /** Refresh this state from the source provider. */
29
29
  readonly refresh: () => void;
30
30
  _refresh(): Promise<void>;
@@ -47,5 +47,5 @@ export declare class QueryState<T extends Datas, K extends Key<T>> extends State
47
47
  * Use a query in a React component.
48
48
  * - Uses the default cache, so will error if not used inside `<Cache>`
49
49
  */
50
- export declare function useQuery<T extends Datas, K extends Key<T>>(ref: Query<T, K> | AsyncQuery<T, K>): QueryState<T, K>;
51
- export declare function useQuery<T extends Datas, K extends Key<T>>(ref?: Query<T, K> | AsyncQuery<T, K>): QueryState<T, K> | undefined;
50
+ export declare function useQuery<T extends Datas>(ref: Query<T> | AsyncQuery<T>): QueryState<T>;
51
+ export declare function useQuery<T extends Datas>(ref?: Query<T> | AsyncQuery<T>): QueryState<T> | undefined;
package/util/iterate.d.ts CHANGED
@@ -20,6 +20,10 @@ export declare const isAsyncIterable: <T extends AsyncIterable<unknown>>(value:
20
20
  * - Checks `items.size` or `items.length` first, or consumes the iterable and counts its iterations.
21
21
  */
22
22
  export declare function countItems(items: Iterable<unknown>): number;
23
+ /** An iterable possibly containing multiple other iterables. */
24
+ export declare type DeepIterable<T> = T | Iterable<DeepIterable<T>>;
25
+ /** Flatten one or more iterables. */
26
+ export declare function flattenDeepIterable<T>(items: DeepIterable<T>): Iterable<T>;
23
27
  /**
24
28
  * Does an iterable have one or more items.
25
29
  * - Checks `items.size` or `items.length` first, or consumes the iterable and counts its iterations.
package/util/iterate.js CHANGED
@@ -31,6 +31,14 @@ function _countItems(items) {
31
31
  count++;
32
32
  return count;
33
33
  }
34
+ /** Flatten one or more iterables. */
35
+ export function* flattenDeepIterable(items) {
36
+ if (isIterable(items))
37
+ for (const item of items)
38
+ yield* flattenDeepIterable(item);
39
+ else
40
+ yield items;
41
+ }
34
42
  /**
35
43
  * Does an iterable have one or more items.
36
44
  * - Checks `items.size` or `items.length` first, or consumes the iterable and counts its iterations.