shelving 1.74.0 → 1.75.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/Change.d.ts ADDED
@@ -0,0 +1,49 @@
1
+ import type { Data, Datas, Key } from "../util/data.js";
2
+ import type { ImmutableArray } from "../util/array.js";
3
+ import type { Provider, AsyncProvider } from "../provider/Provider.js";
4
+ import { DataUpdate } from "../update/DataUpdate.js";
5
+ import { Nullish } from "../util/null.js";
6
+ import type { ItemConstraints, ItemData } from "./Item.js";
7
+ export interface Change<T extends Datas, K extends Key<T>> {
8
+ readonly action: string;
9
+ readonly collection: K;
10
+ }
11
+ /** Add on an item. */
12
+ export interface AddChange<T extends Datas, K extends Key<T>> extends Change<T, K> {
13
+ readonly action: "ADD";
14
+ readonly collection: K;
15
+ readonly data: T[K];
16
+ }
17
+ /** Set on an item. */
18
+ export interface SetChange<T extends Datas, K extends Key<T>> extends Change<T, K> {
19
+ readonly action: "SET";
20
+ readonly collection: K;
21
+ readonly id: string;
22
+ readonly data: T[K];
23
+ }
24
+ /** Update change on an item. */
25
+ export interface UpdateChange<T extends Datas, K extends Key<T>> extends Change<T, K> {
26
+ readonly action: "UPDATE";
27
+ readonly collection: K;
28
+ readonly id: string;
29
+ readonly update: DataUpdate<T[K]>;
30
+ }
31
+ /** Delete change on an item. */
32
+ export interface DeleteChange<T extends Datas, K extends Key<T>> extends Change<T, K> {
33
+ readonly action: "DELETE";
34
+ readonly collection: K;
35
+ readonly id: string;
36
+ }
37
+ /** Set, update, or delete change on an item. */
38
+ export declare type ItemChange<T extends Datas, K extends Key<T> = Key<T>> = SetChange<T, K> | UpdateChange<T, K> | DeleteChange<T, K>;
39
+ /** Array of item changes. */
40
+ export declare type ItemChanges<T extends Datas, K extends Key<T> = Key<T>> = ImmutableArray<ItemChange<T, K>>;
41
+ /** Write change on an item. */
42
+ export declare type WriteChange<T extends Datas, K extends Key<T> = Key<T>> = ItemChange<T, K> | AddChange<T, K>;
43
+ /** Array of write changes. */
44
+ export declare type WriteChanges<T extends Datas, K extends Key<T> = Key<T>> = ImmutableArray<WriteChange<T, K>>;
45
+ /** 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
+ /** 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 _getItemConstraint<T extends Data>(id: string): ItemConstraints<ItemData<T>>;
package/db/Change.js ADDED
@@ -0,0 +1,38 @@
1
+ import { QueryConstraints } from "../constraint/QueryConstraints.js";
2
+ import { FilterConstraint } from "../constraint/FilterConstraint.js";
3
+ import { notNullish } from "../util/null.js";
4
+ /** Apply a set of changes to a synchronous provider. */
5
+ export function changeProvider(provider, changes) {
6
+ return changes.filter(notNullish).map(_changeItem, provider);
7
+ }
8
+ function _changeItem(change) {
9
+ const { action, collection } = change;
10
+ if (action === "ADD")
11
+ return { action: "SET", collection, id: this.addItem(collection, change.data), data: change.data };
12
+ else if (action === "SET")
13
+ this.setItem(collection, change.id, change.data);
14
+ else if (action === "UPDATE")
15
+ this.updateQuery(collection, _getItemConstraint(change.id), change.update);
16
+ else if (action === "DELETE")
17
+ this.deleteItem(collection, change.id);
18
+ return change;
19
+ }
20
+ /** 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));
23
+ }
24
+ async function _changeAsyncItem(change) {
25
+ const { collection, action } = change;
26
+ if (action === "ADD")
27
+ return { action: "SET", collection, id: await this.addItem(collection, change.data), data: change.data };
28
+ else if (action === "SET")
29
+ await this.setItem(collection, change.id, change.data);
30
+ else if (action === "UPDATE")
31
+ await this.updateQuery(collection, _getItemConstraint(change.id), change.update);
32
+ else if (action === "DELETE")
33
+ await this.deleteItem(collection, change.id);
34
+ return change;
35
+ }
36
+ export function _getItemConstraint(id) {
37
+ return new QueryConstraints(new FilterConstraint("id", id), undefined, 1);
38
+ }
@@ -1,9 +1,11 @@
1
1
  import type { Datas, Key } from "../util/data.js";
2
+ import type { Nullish } from "../util/null.js";
2
3
  import type { FilterList } from "../constraint/FilterConstraint.js";
3
4
  import type { SortList } from "../constraint/SortConstraint.js";
4
5
  import type { ItemData, AsyncItem, Item } from "./Item.js";
5
6
  import type { AsyncDatabase, Database } from "./Database.js";
6
7
  import type { AsyncQuery, Query } from "./Query.js";
8
+ import type { ItemChanges, WriteChange } from "./Change.js";
7
9
  /** Reference to a collection in a synchronous or asynchronous provider. */
8
10
  declare abstract class BaseCollection<T extends Datas = Datas, K extends Key<T> = Key<T>> {
9
11
  abstract readonly db: Database<T> | AsyncDatabase<T>;
@@ -14,6 +16,8 @@ declare abstract class BaseCollection<T extends Datas = Datas, K extends Key<T>
14
16
  abstract item(id: string): Item<T, K> | AsyncItem<T, K>;
15
17
  /** Add an item to this collection. */
16
18
  abstract add(data: T[K]): string | Promise<string>;
19
+ /** Run a set of changes on this database. */
20
+ abstract change(...changes: Nullish<WriteChange<T, K>>[]): ItemChanges<T, K> | Promise<ItemChanges<T, K>>;
17
21
  toString(): K;
18
22
  }
19
23
  /** Reference to a collection in a synchronous provider. */
@@ -24,6 +28,7 @@ export declare class Collection<T extends Datas = Datas, K extends Key<T> = Key<
24
28
  query(filters?: FilterList<ItemData<T[K]>>, sorts?: SortList<ItemData<T[K]>>, limit?: number | null): Query<T, K>;
25
29
  item(id: string): Item<T, K>;
26
30
  add(data: T[K]): string;
31
+ change(...changes: Nullish<WriteChange<T, K>>[]): ItemChanges<T, K>;
27
32
  }
28
33
  /** Reference to a collection in an asynchronous provider. */
29
34
  export declare class AsyncCollection<T extends Datas = Datas, K extends Key<T> = Key<T>> extends BaseCollection<T, K> {
@@ -33,5 +38,6 @@ export declare class AsyncCollection<T extends Datas = Datas, K extends Key<T> =
33
38
  query(filters?: FilterList<ItemData<T[K]>>, sorts?: SortList<ItemData<T[K]>>, limit?: number | null): AsyncQuery<T, K>;
34
39
  item(id: string): AsyncItem<T, K>;
35
40
  add(data: T[K]): Promise<string>;
41
+ change(...changes: Nullish<WriteChange<T, K>>[]): Promise<ItemChanges<T, K>>;
36
42
  }
37
43
  export {};
package/db/Collection.js CHANGED
@@ -21,6 +21,9 @@ export class Collection extends BaseCollection {
21
21
  add(data) {
22
22
  return this.db.provider.addItem(this.collection, data);
23
23
  }
24
+ change(...changes) {
25
+ return this.db.change(...changes);
26
+ }
24
27
  }
25
28
  /** Reference to a collection in an asynchronous provider. */
26
29
  export class AsyncCollection extends BaseCollection {
@@ -38,4 +41,7 @@ export class AsyncCollection extends BaseCollection {
38
41
  add(data) {
39
42
  return this.db.provider.addItem(this.collection, data);
40
43
  }
44
+ change(...changes) {
45
+ return this.db.change(...changes);
46
+ }
41
47
  }
package/db/Database.d.ts CHANGED
@@ -3,33 +3,39 @@ import type { AsyncProvider, Provider } from "../provider/Provider.js";
3
3
  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
+ import type { Nullish } from "../util/null.js";
6
7
  import { Item, AsyncItem } from "./Item.js";
7
8
  import { Query, AsyncQuery } from "./Query.js";
8
9
  import { Collection, AsyncCollection } from "./Collection.js";
10
+ import { ItemChanges, WriteChange } from "./Change.js";
9
11
  /** Database with a synchronous or asynchronous provider. */
10
- interface AbstractDatabase<T extends Datas> {
11
- readonly provider: Provider<T> | AsyncProvider<T>;
12
+ declare abstract class BaseDatabase<T extends Datas> {
13
+ abstract readonly provider: Provider<T> | AsyncProvider<T>;
12
14
  /** Create a query on a collection in this database. */
13
- collection<K extends Key<T>>(collection: K): Collection<T, K> | AsyncCollection<T, K>;
15
+ abstract collection<K extends Key<T>>(collection: K): Collection<T, K> | AsyncCollection<T, K>;
14
16
  /** Create a query on a collection in this database. */
15
- 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>;
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>;
16
18
  /** Reference an item in a collection in this database. */
17
- item<K extends Key<T>>(collection: K, id: string): Item<T, K> | AsyncItem<T, K>;
19
+ abstract item<K extends Key<T>>(collection: K, id: string): Item<T, K> | AsyncItem<T, K>;
20
+ /** 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>>;
18
22
  }
19
23
  /** Database with a synchronous provider. */
20
- export declare class Database<T extends Datas = Datas> implements AbstractDatabase<T> {
24
+ export declare class Database<T extends Datas = Datas> implements BaseDatabase<T> {
21
25
  readonly provider: Provider<T>;
22
26
  constructor(provider: Provider<T>);
23
27
  collection<K extends Key<T>>(collection: K): Collection<T, K>;
24
28
  query<K extends Key<T>>(collection: K, filters?: FilterList<ItemData<T[K]>>, sorts?: SortList<ItemData<T[K]>>, limit?: number | null): Query<T, K>;
25
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>;
26
31
  }
27
32
  /** Database with a synchronous provider. */
28
- export declare class AsyncDatabase<T extends Datas = Datas> implements AbstractDatabase<T> {
33
+ export declare class AsyncDatabase<T extends Datas = Datas> implements BaseDatabase<T> {
29
34
  readonly provider: AsyncProvider<T>;
30
35
  constructor(provider: AsyncProvider<T>);
31
36
  collection<K extends Key<T>>(collection: K): AsyncCollection<T, K>;
32
37
  query<K extends Key<T>>(collection: K, filters?: FilterList<ItemData<T[K]>>, sorts?: SortList<ItemData<T[K]>>, limit?: number | null): AsyncQuery<T, K>;
33
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>>;
34
40
  }
35
41
  export {};
package/db/Database.js CHANGED
@@ -1,6 +1,10 @@
1
1
  import { Item, AsyncItem } from "./Item.js";
2
2
  import { Query, AsyncQuery } from "./Query.js";
3
3
  import { Collection, AsyncCollection } from "./Collection.js";
4
+ import { changeAsyncProvider, changeProvider } from "./Change.js";
5
+ /** Database with a synchronous or asynchronous provider. */
6
+ class BaseDatabase {
7
+ }
4
8
  /** Database with a synchronous provider. */
5
9
  export class Database {
6
10
  constructor(provider) {
@@ -15,6 +19,9 @@ export class Database {
15
19
  item(collection, id) {
16
20
  return new Item(this, collection, id);
17
21
  }
22
+ change(...changes) {
23
+ return changeProvider(this.provider, changes);
24
+ }
18
25
  }
19
26
  /** Database with a synchronous provider. */
20
27
  export class AsyncDatabase {
@@ -30,4 +37,7 @@ export class AsyncDatabase {
30
37
  item(collection, id) {
31
38
  return new AsyncItem(this, collection, id);
32
39
  }
40
+ change(...changes) {
41
+ return changeAsyncProvider(this.provider, changes);
42
+ }
33
43
  }
package/db/Item.d.ts CHANGED
@@ -7,7 +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
+ import type { DeleteChange, SetChange, UpdateChange } from "./Change.js";
11
11
  /** Item data with a string ID that uniquely identifies it. */
12
12
  export declare type ItemData<T extends Data = Data> = T & {
13
13
  id: string;
@@ -53,16 +53,16 @@ declare abstract class BaseItem<T extends Datas = Datas, K extends Key<T> = Key<
53
53
  subscribe(next: PartialObserver<ItemValue<T[K]>> | Dispatch<[ItemValue<T[K]>]>): Unsubscribe;
54
54
  /** Set the complete data of this item. */
55
55
  abstract set(data: T[K]): void | PromiseLike<void>;
56
- /** Get a set change for this item. */
57
- getSet(data: T[K]): Changes<T>;
58
56
  /** Update this item. */
59
57
  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>;
62
58
  /** Delete this item. */
63
59
  abstract delete(): void | PromiseLike<void>;
60
+ /** Get a set change for this item. */
61
+ getSet(data: T[K]): SetChange<T, K>;
62
+ /** Get an update change for this item. */
63
+ getUpdate(updates: DataUpdate<T[K]> | PropUpdates<T[K]>): UpdateChange<T, K>;
64
64
  /** Get a delete change for this item. */
65
- getDelete(): Changes<T>;
65
+ getDelete(): DeleteChange<T, K>;
66
66
  toString(): `${K}/${string}`;
67
67
  }
68
68
  /** Reference to an item in a synchronous provider. */
package/db/Item.js CHANGED
@@ -16,15 +16,15 @@ class BaseItem {
16
16
  }
17
17
  /** Get a set change for this item. */
18
18
  getSet(data) {
19
- return { [this.toString()]: data };
19
+ return { action: "SET", collection: this.collection, id: this.id, data };
20
20
  }
21
21
  /** Get an update change for this item. */
22
22
  getUpdate(updates) {
23
- return { [this.toString()]: updates instanceof DataUpdate ? updates : new DataUpdate(updates) };
23
+ return { action: "UPDATE", collection: this.collection, id: this.id, update: updates instanceof DataUpdate ? updates : new DataUpdate(updates) };
24
24
  }
25
25
  /** Get a delete change for this item. */
26
26
  getDelete() {
27
- return { [this.toString()]: null };
27
+ return { action: "DELETE", collection: this.collection, id: this.id };
28
28
  }
29
29
  // Implement toString()
30
30
  toString() {
package/db/index.d.ts CHANGED
@@ -2,4 +2,4 @@ export * from "./Database.js";
2
2
  export * from "./Collection.js";
3
3
  export * from "./Item.js";
4
4
  export * from "./Query.js";
5
- export * from "./Changes.js";
5
+ export * from "./Change.js";
package/db/index.js CHANGED
@@ -2,4 +2,4 @@ export * from "./Database.js";
2
2
  export * from "./Collection.js";
3
3
  export * from "./Item.js";
4
4
  export * from "./Query.js";
5
- export * from "./Changes.js";
5
+ export * from "./Change.js";
package/package.json CHANGED
@@ -11,7 +11,7 @@
11
11
  "state-management",
12
12
  "query-builder"
13
13
  ],
14
- "version": "1.74.0",
14
+ "version": "1.75.0",
15
15
  "repository": "https://github.com/dhoulb/shelving",
16
16
  "author": "Dave Houlbrooke <dave@shax.com>",
17
17
  "license": "0BSD",
package/db/Changes.d.ts DELETED
@@ -1,24 +0,0 @@
1
- import type { Data, Datas, Key } from "../util/data.js";
2
- import { DataUpdate } from "../update/DataUpdate.js";
3
- import type { Provider, AsyncProvider } from "../provider/Provider.js";
4
- import type { Database, AsyncDatabase } from "./Database.js";
5
- import { ItemConstraints, ItemData } from "./Item.js";
6
- /**
7
- * Change set of operations to run against a database in `{ "collection/id": data | DataUpdate | null }` format.
8
- * - If data is an object, sets the item.
9
- * - If data is a `DataUpdate` instance, updates the item.
10
- * - If data is null, deletes the item.
11
- * - If data is undefined, skip the item.
12
- */
13
- export declare type Changes<T extends Datas> = {
14
- [K in Key<T> as `${K}/${string}`]: T[K] | DataUpdate<T[K]> | null | undefined;
15
- };
16
- /** Apply a set of changes to a synchronous database. */
17
- export declare function changeDatabase<T extends Datas>({ provider }: Database<T>, changes: Changes<T>): Changes<T>;
18
- /** Apply a set of changes to an asynchronous database. */
19
- export declare function changeAsyncDatabase<T extends Datas>({ provider }: AsyncDatabase<T>, changes: Changes<T>): Promise<Changes<T>>;
20
- /** Apply a set of changes to a synchronous provider. */
21
- export declare function changeProvider<T extends Datas>(provider: Provider<T>, changes: Changes<T>): Changes<T>;
22
- /** Apply a set of changes to an asynchronous provider. */
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 DELETED
@@ -1,45 +0,0 @@
1
- import { splitString } from "../util/string.js";
2
- import { DataUpdate } from "../update/DataUpdate.js";
3
- import { QueryConstraints } from "../constraint/QueryConstraints.js";
4
- import { FilterConstraint } from "../constraint/FilterConstraint.js";
5
- /** Apply a set of changes to a synchronous database. */
6
- export function changeDatabase({ provider }, changes) {
7
- return changeProvider(provider, changes);
8
- }
9
- /** Apply a set of changes to an asynchronous database. */
10
- export function changeAsyncDatabase({ provider }, changes) {
11
- return changeAsyncProvider(provider, changes);
12
- }
13
- /** Apply a set of changes to a synchronous provider. */
14
- export function changeProvider(provider, changes) {
15
- for (const [key, change] of Object.entries(changes)) {
16
- const [collection, id] = splitString(key, "/", 2);
17
- if (change === undefined)
18
- continue;
19
- else if (change === null)
20
- provider.deleteItem(collection, id);
21
- else if (change instanceof DataUpdate)
22
- provider.updateQuery(collection, _getItemConstraint(id), change);
23
- else
24
- provider.setItem(collection, id, change);
25
- }
26
- return changes;
27
- }
28
- /** Apply a set of changes to an asynchronous provider. */
29
- export async function changeAsyncProvider(provider, changes) {
30
- for (const [key, change] of Object.entries(changes)) {
31
- const [collection, id] = splitString(key, "/", 2);
32
- if (change === undefined)
33
- continue;
34
- else if (change === null)
35
- await provider.deleteItem(collection, id);
36
- else if (change instanceof DataUpdate)
37
- await provider.updateQuery(collection, _getItemConstraint(id), change);
38
- else
39
- await provider.setItem(collection, id, change);
40
- }
41
- return changes;
42
- }
43
- export function _getItemConstraint(id) {
44
- return new QueryConstraints(new FilterConstraint("id", id), undefined, 1);
45
- }
@@ -1 +0,0 @@
1
- export {};
@@ -1,35 +0,0 @@
1
- import { AsyncDatabase, DataUpdate } from "../index.js";
2
- test("Typescript", () => {
3
- const operations1 = {
4
- "collection1/a1": { one: 1, bool: false },
5
- "collection1/b2": null,
6
- "collection1/b3": new DataUpdate({ bool: true }),
7
- "collection2/a1": { two: 1, bool: false },
8
- "collection2/b2": null,
9
- "collection2/c3": new DataUpdate({ bool: true }),
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 };
35
- });