shelving 1.89.6 → 1.91.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.
Files changed (117) hide show
  1. package/api/Resource.d.ts +1 -1
  2. package/api/Resource.js +1 -1
  3. package/constraint/Constraints.js +3 -5
  4. package/constraint/{FilterConstraint.d.ts → Filter.d.ts} +1 -6
  5. package/constraint/{FilterConstraint.js → Filter.js} +2 -18
  6. package/constraint/Filters.d.ts +26 -0
  7. package/constraint/Filters.js +41 -0
  8. package/constraint/{SortConstraint.d.ts → Sort.d.ts} +1 -9
  9. package/constraint/{SortConstraint.js → Sort.js} +1 -15
  10. package/constraint/Sorts.d.ts +25 -0
  11. package/constraint/Sorts.js +47 -0
  12. package/constraint/{QueryConstraints.d.ts → Statement.d.ts} +13 -16
  13. package/constraint/Statement.js +79 -0
  14. package/constraint/index.d.ts +5 -5
  15. package/constraint/index.js +5 -5
  16. package/db/Change.js +3 -3
  17. package/db/Collection.d.ts +5 -5
  18. package/db/Database.d.ts +5 -5
  19. package/db/Item.d.ts +6 -6
  20. package/db/Item.js +5 -5
  21. package/db/ItemState.d.ts +1 -1
  22. package/db/Query.d.ts +6 -6
  23. package/db/Query.js +2 -2
  24. package/error/ConditionError.d.ts +2 -2
  25. package/error/ConditionError.js +2 -4
  26. package/error/PermissionError.d.ts +0 -1
  27. package/error/PermissionError.js +0 -3
  28. package/error/RequiredError.d.ts +2 -2
  29. package/error/RequiredError.js +2 -4
  30. package/error/UnsupportedError.d.ts +2 -2
  31. package/error/UnsupportedError.js +2 -4
  32. package/error/ValidationError.d.ts +2 -4
  33. package/error/ValidationError.js +2 -6
  34. package/feedback/Feedback.d.ts +8 -15
  35. package/feedback/Feedback.js +7 -28
  36. package/feedback/Feedbacks.d.ts +12 -0
  37. package/feedback/Feedbacks.js +13 -0
  38. package/feedback/hydrations.js +2 -8
  39. package/feedback/index.d.ts +1 -4
  40. package/feedback/index.js +1 -4
  41. package/firestore/client/FirestoreClientProvider.d.ts +6 -6
  42. package/firestore/client/FirestoreClientProvider.js +2 -2
  43. package/firestore/lite/FirestoreLiteProvider.d.ts +5 -5
  44. package/firestore/lite/FirestoreLiteProvider.js +2 -2
  45. package/firestore/server/FirestoreServerProvider.d.ts +6 -6
  46. package/package.json +1 -1
  47. package/provider/CacheProvider.d.ts +6 -6
  48. package/provider/DebugProvider.d.ts +10 -10
  49. package/provider/DebugProvider.js +2 -2
  50. package/provider/MemoryProvider.d.ts +17 -17
  51. package/provider/MemoryProvider.js +20 -14
  52. package/provider/Provider.d.ts +14 -14
  53. package/provider/ThroughProvider.d.ts +11 -11
  54. package/provider/ValidationProvider.d.ts +10 -10
  55. package/provider/ValidationProvider.js +25 -19
  56. package/schema/AllowSchema.d.ts +2 -2
  57. package/schema/AllowSchema.js +7 -7
  58. package/schema/ArraySchema.js +10 -10
  59. package/schema/ColorSchema.d.ts +1 -1
  60. package/schema/ColorSchema.js +3 -3
  61. package/schema/DataSchema.js +2 -2
  62. package/schema/DateSchema.js +9 -9
  63. package/schema/DictionarySchema.js +10 -10
  64. package/schema/EmailSchema.js +2 -2
  65. package/schema/LinkSchema.js +10 -10
  66. package/schema/NumberSchema.js +10 -10
  67. package/schema/PhoneSchema.d.ts +1 -1
  68. package/schema/PhoneSchema.js +3 -3
  69. package/schema/RequiredSchema.d.ts +1 -1
  70. package/schema/RequiredSchema.js +3 -3
  71. package/schema/Schema.d.ts +0 -2
  72. package/schema/Schema.js +0 -2
  73. package/schema/SlugSchema.d.ts +1 -1
  74. package/schema/SlugSchema.js +2 -2
  75. package/schema/StringSchema.d.ts +1 -1
  76. package/schema/StringSchema.js +14 -14
  77. package/schema/TimeSchema.js +10 -10
  78. package/state/DataState.d.ts +17 -5
  79. package/state/DataState.js +28 -1
  80. package/state/DictionaryState.d.ts +8 -2
  81. package/state/DictionaryState.js +16 -2
  82. package/update/ArrayUpdate.d.ts +0 -3
  83. package/update/ArrayUpdate.js +3 -24
  84. package/update/DataUpdate.d.ts +13 -12
  85. package/update/DataUpdate.js +23 -55
  86. package/update/Delete.d.ts +0 -1
  87. package/update/Delete.js +0 -3
  88. package/update/DictionaryUpdate.d.ts +26 -19
  89. package/update/DictionaryUpdate.js +43 -66
  90. package/update/Increment.js +0 -1
  91. package/update/Update.d.ts +1 -3
  92. package/update/Update.js +0 -6
  93. package/util/array.d.ts +3 -1
  94. package/util/array.js +4 -2
  95. package/util/index.d.ts +0 -1
  96. package/util/index.js +0 -1
  97. package/util/object.d.ts +8 -1
  98. package/util/object.js +7 -0
  99. package/util/transform.d.ts +13 -8
  100. package/util/transform.js +17 -10
  101. package/util/validate.d.ts +16 -29
  102. package/util/validate.js +83 -47
  103. package/constraint/FilterConstraints.d.ts +0 -22
  104. package/constraint/FilterConstraints.js +0 -27
  105. package/constraint/QueryConstraints.js +0 -110
  106. package/constraint/SortConstraints.d.ts +0 -20
  107. package/constraint/SortConstraints.js +0 -29
  108. package/feedback/ErrorFeedback.d.ts +0 -5
  109. package/feedback/ErrorFeedback.js +0 -14
  110. package/feedback/InvalidFeedback.d.ts +0 -5
  111. package/feedback/InvalidFeedback.js +0 -14
  112. package/feedback/SuccessFeedback.d.ts +0 -5
  113. package/feedback/SuccessFeedback.js +0 -14
  114. package/feedback/WarningFeedback.d.ts +0 -5
  115. package/feedback/WarningFeedback.js +0 -14
  116. package/util/clone.d.ts +0 -16
  117. package/util/clone.js +0 -34
package/api/Resource.d.ts CHANGED
@@ -15,7 +15,7 @@ export declare class Resource<P = unknown, R = void> implements Validatable<R> {
15
15
  * Validate a payload for this resource.
16
16
  *
17
17
  * @returns The validated payload for this resource.
18
- * @throws InvalidFeedback if the payload could not be validated.
18
+ * @throws Feedback if the payload could not be validated.
19
19
  */
20
20
  prepare(unsafePayload: unknown): P;
21
21
  /**
package/api/Resource.js CHANGED
@@ -17,7 +17,7 @@ export class Resource {
17
17
  * Validate a payload for this resource.
18
18
  *
19
19
  * @returns The validated payload for this resource.
20
- * @throws InvalidFeedback if the payload could not be validated.
20
+ * @throws Feedback if the payload could not be validated.
21
21
  */
22
22
  prepare(unsafePayload) {
23
23
  return validate(unsafePayload, this.payload);
@@ -1,4 +1,4 @@
1
- import { getPrototype } from "../util/object.js";
1
+ import { cloneObjectWith } from "../util/object.js";
2
2
  import { withArrayItems, omitArrayItems } from "../util/array.js";
3
3
  import { Constraint } from "./Constraint.js";
4
4
  /** Type of Rule that is powered by several sub-constraints (e.g. `Filters` and `Sorts` and `Query` itself extend this). */
@@ -21,13 +21,11 @@ export class Constraints extends Constraint {
21
21
  }
22
22
  /** Clone this set of constraints but add additional constraints. */
23
23
  with(...constraints) {
24
- const _constraints = withArrayItems(this._constraints, ...constraints);
25
- return _constraints !== this._constraints ? { __proto__: getPrototype(this), ...this, _constraints: _constraints } : this;
24
+ return cloneObjectWith(this, "_constraints", withArrayItems(this._constraints, ...constraints));
26
25
  }
27
26
  /** Clone this set of constraints but remove specific constraints. */
28
27
  omit(...constraints) {
29
- const _constraints = omitArrayItems(this._constraints, ...constraints);
30
- return _constraints !== this._constraints ? { __proto__: getPrototype(this), ...this, _constraints: _constraints } : this;
28
+ return cloneObjectWith(this, "_constraints", omitArrayItems(this._constraints, ...constraints));
31
29
  }
32
30
  /** Iterate over the constraints. */
33
31
  [Symbol.iterator]() {
@@ -1,5 +1,4 @@
1
1
  import { Data, FlatDataKey } from "../util/data.js";
2
- import type { Nullish } from "../util/null.js";
3
2
  import { ImmutableArray } from "../util/array.js";
4
3
  import type { Matchable } from "../util/match.js";
5
4
  import type { Constraint } from "./Constraint.js";
@@ -15,8 +14,6 @@ export type FilterProps<T extends Data> = {
15
14
  };
16
15
  /** Format that allows filters to be specified as a string, e.g. `!name` means `name is not` and `age>` means `age is more than` and `tags[]` means `tags array contains` */
17
16
  export type FilterKey<T extends Data> = keyof FilterProps<T>;
18
- /** List of filters in a flexible format. */
19
- export type FilterList<T extends Data> = FilterProps<T> | FilterConstraint<T> | Iterable<Nullish<FilterProps<T> | FilterConstraint<T>>>;
20
17
  /**
21
18
  * Filter: filters a list of data.
22
19
  *
@@ -24,7 +21,7 @@ export type FilterList<T extends Data> = FilterProps<T> | FilterConstraint<T> |
24
21
  * @param operator FilterOperator, e.g. `IS` or `CONTAINS`
25
22
  * @param value Value the specified property should be matched against.
26
23
  */
27
- export declare class FilterConstraint<T extends Data = Data> implements Constraint<T>, Matchable<[T]> {
24
+ export declare class Filter<T extends Data = Data> implements Constraint<T>, Matchable<[T]> {
28
25
  readonly keys: readonly [string, ...string[]];
29
26
  readonly operator: FilterOperator;
30
27
  readonly value: unknown;
@@ -35,5 +32,3 @@ export declare class FilterConstraint<T extends Data = Data> implements Constrai
35
32
  transform(items: Iterable<T>): Iterable<T>;
36
33
  toString(): string;
37
34
  }
38
- /** Turn `FilterList` into a list of `FilterConstraint` instances. */
39
- export declare function getFilters<T extends Data>(list: FilterList<T> | FilterList<T>[]): Iterable<FilterConstraint<T>>;
@@ -1,7 +1,6 @@
1
- import { getDataProps } from "../util/data.js";
2
1
  import { isArray } from "../util/array.js";
3
2
  import { isArrayWith, isEqualGreater, isEqualLess, isGreater, isInArray, isLess, notInArray, isEqual, notEqual } from "../util/equal.js";
4
- import { filterItems, isIterable } from "../util/iterate.js";
3
+ import { filterItems } from "../util/iterate.js";
5
4
  import { getProp } from "../util/object.js";
6
5
  import { splitString } from "../util/string.js";
7
6
  /** Map `FilterOperator` to its corresponding `Match` function. */
@@ -23,7 +22,7 @@ const MATCHERS = {
23
22
  * @param operator FilterOperator, e.g. `IS` or `CONTAINS`
24
23
  * @param value Value the specified property should be matched against.
25
24
  */
26
- export class FilterConstraint {
25
+ export class Filter {
27
26
  get key() {
28
27
  return this.keys.join(".");
29
28
  }
@@ -86,18 +85,3 @@ export class FilterConstraint {
86
85
  return `"${this.filterKey}":${JSON.stringify(this.value)}`;
87
86
  }
88
87
  }
89
- /** Turn `FilterList` into a list of `FilterConstraint` instances. */
90
- export function* getFilters(list) {
91
- if (list instanceof FilterConstraint) {
92
- yield list;
93
- }
94
- else if (isIterable(list)) {
95
- for (const filter of list)
96
- if (filter)
97
- yield* getFilters(filter);
98
- }
99
- else {
100
- for (const [key, value] of getDataProps(list))
101
- yield new FilterConstraint(key, value);
102
- }
103
- }
@@ -0,0 +1,26 @@
1
+ import type { Matchable } from "../util/match.js";
2
+ import { Data } from "../util/data.js";
3
+ import { Filter, FilterProps } from "./Filter.js";
4
+ import { Constraints } from "./Constraints.js";
5
+ /** A possible set of filters. */
6
+ export type PossibleFilters<T extends Data> = Filters<T> | FilterProps<T>;
7
+ /** Turn `FilterProps` into a list of `Filter` instances. */
8
+ export declare function getFilters<T extends Data>(filters: PossibleFilters<T>): Iterable<Filter<T>>;
9
+ /** An object that is filterable. */
10
+ export interface Filterable<T extends Data> extends Matchable<[T]> {
11
+ /** Add a filter to this filterable. */
12
+ filter(filters: PossibleFilters<T>): this;
13
+ /** Return a new instance of this class with no filters specified. */
14
+ unfiltered: this;
15
+ /** Match an item against the filters specified for this object. */
16
+ match(item: T): boolean;
17
+ }
18
+ /** A set of filters. */
19
+ export declare class Filters<T extends Data = Data> extends Constraints<T, Filter<T>> implements Filterable<T> {
20
+ static from<X extends Data = Data>(filters: PossibleFilters<X>): Filters<X>;
21
+ filter(filters: PossibleFilters<T>): this;
22
+ get unfiltered(): this;
23
+ match(item: T): boolean;
24
+ transform(items: Iterable<T>): Iterable<T>;
25
+ toString(): string;
26
+ }
@@ -0,0 +1,41 @@
1
+ import { getDataProps } from "../util/data.js";
2
+ import { filterItems } from "../util/iterate.js";
3
+ import { cloneObjectWith } from "../util/object.js";
4
+ import { clearArray } from "../util/array.js";
5
+ import { Filter } from "./Filter.js";
6
+ import { Constraints } from "./Constraints.js";
7
+ /** Turn `FilterProps` into a list of `Filter` instances. */
8
+ export function* getFilters(filters) {
9
+ if (filters instanceof Filters)
10
+ yield* filters;
11
+ else
12
+ for (const [key, value] of getDataProps(filters))
13
+ yield new Filter(key, value);
14
+ }
15
+ /** A set of filters. */
16
+ export class Filters extends Constraints {
17
+ static from(filters) {
18
+ return filters instanceof Filters ? filters : new Filters(...getFilters(filters));
19
+ }
20
+ // Implement `Filterable`
21
+ filter(filters) {
22
+ return this.with(...getFilters(filters));
23
+ }
24
+ get unfiltered() {
25
+ return cloneObjectWith(this, "_constraints", clearArray(this._constraints));
26
+ }
27
+ match(item) {
28
+ for (const rule of this._constraints)
29
+ if (!rule.match(item))
30
+ return false;
31
+ return true;
32
+ }
33
+ // Implement `Rule`
34
+ transform(items) {
35
+ return this._constraints.length ? filterItems(items, this) : items;
36
+ }
37
+ // Stringify as object syntax.
38
+ toString() {
39
+ return this._constraints.length ? `"filters":{${this._constraints.map(String).join(",")}}` : "";
40
+ }
41
+ }
@@ -1,18 +1,12 @@
1
- import type { ImmutableArray } from "../util/array.js";
2
1
  import type { Data, FlatDataKey } from "../util/data.js";
3
- import type { Nullish } from "../util/null.js";
4
2
  import { Rankable } from "../util/sort.js";
5
3
  import type { Constraint } from "./Constraint.js";
6
4
  /** Format that allows sorts to be set as a plain string, e.g. `name` sorts by name in ascending order and `!date` sorts by date in descending order. */
7
5
  export type SortKey<T extends Data> = FlatDataKey<T> | `${FlatDataKey<T>}` | `!${FlatDataKey<T>}`;
8
- /** One or more sort keys. */
9
- export type SortKeys<T extends Data> = SortKey<T> | ImmutableArray<SortKey<T>>;
10
6
  /** Possible operator references. */
11
7
  export type SortDirection = "ASC" | "DESC";
12
- /** List of sorts in a flexible format. */
13
- export type SortList<T extends Data> = SortKey<T> | SortConstraint<T> | Iterable<Nullish<SortKey<T> | SortConstraint<T>>>;
14
8
  /** Sort a list of values. */
15
- export declare class SortConstraint<T extends Data = Data> implements Constraint<T>, Rankable<T> {
9
+ export declare class Sort<T extends Data = Data> implements Constraint<T>, Rankable<T> {
16
10
  readonly keys: readonly [string, ...string[]];
17
11
  readonly direction: SortDirection;
18
12
  get key(): string;
@@ -22,5 +16,3 @@ export declare class SortConstraint<T extends Data = Data> implements Constraint
22
16
  transform(items: Iterable<T>): Iterable<T>;
23
17
  toString(): string;
24
18
  }
25
- /** Turn `SortList` into array of list of `SortConstraint` instances. */
26
- export declare function getSorts<T extends Data>(list: SortList<T> | SortList<T>[]): Iterable<SortConstraint<T>>;
@@ -2,7 +2,7 @@ import { getProp } from "../util/object.js";
2
2
  import { rank, rankAsc, rankDesc, sortItems } from "../util/sort.js";
3
3
  import { splitString } from "../util/string.js";
4
4
  /** Sort a list of values. */
5
- export class SortConstraint {
5
+ export class Sort {
6
6
  get key() {
7
7
  return this.keys.join(".");
8
8
  }
@@ -29,17 +29,3 @@ export class SortConstraint {
29
29
  return this.sortKey;
30
30
  }
31
31
  }
32
- /** Turn `SortList` into array of list of `SortConstraint` instances. */
33
- export function* getSorts(list) {
34
- if (typeof list === "string") {
35
- yield new SortConstraint(list);
36
- }
37
- else if (list instanceof SortConstraint) {
38
- yield list;
39
- }
40
- else {
41
- for (const sort of list)
42
- if (sort)
43
- yield* getSorts(sort);
44
- }
45
- }
@@ -0,0 +1,25 @@
1
+ import type { Data } from "../util/data.js";
2
+ import { ImmutableArray } from "../util/array.js";
3
+ import { Rankable } from "../util/sort.js";
4
+ import { Constraints } from "./Constraints.js";
5
+ import { Sort, SortKey } from "./Sort.js";
6
+ /** A possible set of sorts. */
7
+ export type PossibleSorts<T extends Data> = Sorts<T> | SortKey<T> | Iterable<SortKey<T>> | ImmutableArray<SortKey<T>>;
8
+ /** Turn `SortList` into array of list of `Sort` instances. */
9
+ export declare function getSorts<T extends Data>(sorts: PossibleSorts<T>): Iterable<Sort<T>>;
10
+ /** An object that is sortable. */
11
+ export interface Sortable<T extends Data> extends Rankable<T> {
12
+ /** Add one or more sorts to this sortable. */
13
+ sort(sorts: PossibleSorts<T>): this;
14
+ /** Return a new instance of this class with no sorts specified. */
15
+ unsorted: this;
16
+ }
17
+ /** A set of sorts. */
18
+ export declare class Sorts<T extends Data = Data> extends Constraints<T, Sort<T>> implements Sortable<T> {
19
+ static from<X extends Data>(sorts: PossibleSorts<X>): Sorts<X>;
20
+ sort(sorts: PossibleSorts<T>): this;
21
+ get unsorted(): this;
22
+ rank(left: T, right: T): number;
23
+ transform(items: Iterable<T>): Iterable<T>;
24
+ toString(): string;
25
+ }
@@ -0,0 +1,47 @@
1
+ import { clearArray } from "../util/array.js";
2
+ import { cloneObjectWith } from "../util/object.js";
3
+ import { sortItems } from "../util/sort.js";
4
+ import { Constraints } from "./Constraints.js";
5
+ import { Sort } from "./Sort.js";
6
+ /** Turn `SortList` into array of list of `Sort` instances. */
7
+ export function* getSorts(sorts) {
8
+ if (sorts instanceof Sorts) {
9
+ yield* sorts;
10
+ }
11
+ else if (typeof sorts === "string") {
12
+ yield new Sort(sorts);
13
+ }
14
+ else {
15
+ for (const sort of sorts)
16
+ yield new Sort(sort);
17
+ }
18
+ }
19
+ /** A set of sorts. */
20
+ export class Sorts extends Constraints {
21
+ static from(sorts) {
22
+ return sorts instanceof Sorts ? sorts : new Sorts(...getSorts(sorts));
23
+ }
24
+ // Implement `Sortable`
25
+ sort(sorts) {
26
+ return this.with(...getSorts(sorts));
27
+ }
28
+ get unsorted() {
29
+ return cloneObjectWith(this, "_constraints", clearArray(this._constraints));
30
+ }
31
+ rank(left, right) {
32
+ for (const rule of this._constraints) {
33
+ const l = rule.rank(left, right);
34
+ if (l !== 0)
35
+ return l;
36
+ }
37
+ return 0;
38
+ }
39
+ // Implement `Rule`
40
+ transform(items) {
41
+ return this._constraints.length ? sortItems(items, this) : items;
42
+ }
43
+ // Stringify as array syntax.
44
+ toString() {
45
+ return this._constraints.length ? `"sorts":[${this._constraints.map(String).join(",")}]` : "";
46
+ }
47
+ }
@@ -1,9 +1,7 @@
1
1
  import type { Data } from "../util/data.js";
2
- import { Filterable, FilterConstraints } from "./FilterConstraints.js";
3
- import { Sortable, SortConstraints } from "./SortConstraints.js";
2
+ import { Filterable, Filters, PossibleFilters } from "./Filters.js";
3
+ import { PossibleSorts, Sortable, Sorts } from "./Sorts.js";
4
4
  import { Constraint } from "./Constraint.js";
5
- import { FilterList } from "./FilterConstraint.js";
6
- import { SortList } from "./SortConstraint.js";
7
5
  /** Interface that combines Filterable, Sortable, Sliceable. */
8
6
  export interface Queryable<T extends Data> extends Filterable<T>, Sortable<T> {
9
7
  /**
@@ -17,29 +15,28 @@ export interface Queryable<T extends Data> extends Filterable<T>, Sortable<T> {
17
15
  after(item: T): this;
18
16
  /** Return a new instance of this class with a before offset defined. */
19
17
  before(item: T): this;
20
- /** Return a new instance of this class with no filters specified. */
21
- readonly unfilter: this;
22
- /** Return a new instance of this class with no sorts specified. */
23
- readonly unsort: this;
24
18
  /** The maximum number of items allowed by the limit. */
25
19
  readonly limit: number | null;
20
+ /** Return a new instance of this class with no limit specified. */
21
+ readonly unlimited: this;
26
22
  /** Return a new instance of this class with a limit set. */
27
23
  max(max: number | null): this;
28
24
  }
29
25
  /** Allows filtering, sorting, and limiting on a set of results. */
30
- export declare class QueryConstraints<T extends Data = Data> extends Constraint<T> implements Queryable<T> {
31
- readonly filters: FilterConstraints<T>;
32
- readonly sorts: SortConstraints<T>;
26
+ export declare class Statement<T extends Data = Data> extends Constraint<T> implements Queryable<T> {
27
+ readonly filters: Filters<T>;
28
+ readonly sorts: Sorts<T>;
33
29
  readonly limit: number | null;
34
- constructor(filters?: FilterList<T> | FilterConstraints<T>, sorts?: SortList<T> | SortConstraints<T>, limit?: number | null);
35
- filter(...filters: FilterList<T>[]): this;
36
- get unfilter(): this;
30
+ constructor(filters?: PossibleFilters<T>, sorts?: PossibleSorts<T>, limit?: number | null);
31
+ filter(filters: PossibleFilters<T>): this;
32
+ get unfiltered(): this;
37
33
  match(item: T): boolean;
38
- sort(...sorts: SortList<T>[]): this;
39
- get unsort(): this;
34
+ sort(sorts: PossibleSorts<T>): this;
35
+ get unsorted(): this;
40
36
  rank(left: T, right: T): number;
41
37
  after(item: T): this;
42
38
  before(item: T): this;
39
+ get unlimited(): this;
43
40
  max(limit: number | null): this;
44
41
  transform(items: Iterable<T>): Iterable<T>;
45
42
  toString(): string;
@@ -0,0 +1,79 @@
1
+ import { cloneObjectWith, getProp } from "../util/object.js";
2
+ import { assert } from "../util/assert.js";
3
+ import { limitArray } from "../util/array.js";
4
+ import { Filters } from "./Filters.js";
5
+ import { Sorts } from "./Sorts.js";
6
+ import { Constraint } from "./Constraint.js";
7
+ import { Filter } from "./Filter.js";
8
+ // Instances to save resources for the default case (empty query).
9
+ const EMPTY_FILTERS = new Filters(); // eslint-disable-line @typescript-eslint/no-explicit-any
10
+ const EMPTY_SORTS = new Sorts(); // eslint-disable-line @typescript-eslint/no-explicit-any
11
+ /** Allows filtering, sorting, and limiting on a set of results. */
12
+ export class Statement extends Constraint {
13
+ constructor(filters = EMPTY_FILTERS, sorts = EMPTY_SORTS, limit = null) {
14
+ super();
15
+ this.filters = Filters.from(filters);
16
+ this.sorts = Sorts.from(sorts);
17
+ this.limit = limit;
18
+ }
19
+ // Implement `Filterable`
20
+ filter(filters) {
21
+ return cloneObjectWith(this, "filters", this.filters.filter(filters));
22
+ }
23
+ get unfiltered() {
24
+ return cloneObjectWith(this, "filters", this.filters.unfiltered);
25
+ }
26
+ match(item) {
27
+ return this.filters.match(item);
28
+ }
29
+ // Implement `Sortable`
30
+ sort(sorts) {
31
+ return cloneObjectWith(this, "sorts", this.sorts.sort(sorts));
32
+ }
33
+ get unsorted() {
34
+ return cloneObjectWith(this, "sorts", this.sorts.unsorted);
35
+ }
36
+ rank(left, right) {
37
+ return this.sorts.rank(left, right);
38
+ }
39
+ // Implement `Queryable`
40
+ after(item) {
41
+ return cloneObjectWith(this, "filters", this.filters.with(..._getAfterFilters(this.sorts, item)));
42
+ }
43
+ before(item) {
44
+ return cloneObjectWith(this, "filters", this.filters.with(..._getBeforeFilters(this.sorts, item)));
45
+ }
46
+ get unlimited() {
47
+ return this.max(null);
48
+ }
49
+ max(limit) {
50
+ return cloneObjectWith(this, "limit", limit);
51
+ }
52
+ // Implement `Rule`
53
+ transform(items) {
54
+ const sorted = this.sorts.transform(this.filters.transform(items));
55
+ return typeof this.limit === "number" ? limitArray(sorted, this.limit) : sorted;
56
+ }
57
+ // Implement toString()
58
+ toString() {
59
+ return [this.filters.toString(), this.sorts.toString(), typeof this.limit === "number" ? `"limit":${this.limit}` : null].filter(Boolean).join(",");
60
+ }
61
+ }
62
+ function* _getAfterFilters(sorts, item) {
63
+ const lastSort = sorts.last;
64
+ assert(lastSort);
65
+ for (const sort of sorts) {
66
+ const { key, keys, direction } = sort;
67
+ const filterKey = (direction === "ASC" ? (sort === lastSort ? `${key}>` : `${key}>=`) : sort === lastSort ? `${key}<` : `${key}<=`);
68
+ yield new Filter(filterKey, getProp(item, ...keys));
69
+ }
70
+ }
71
+ function* _getBeforeFilters(sorts, item) {
72
+ const lastSort = sorts.last;
73
+ assert(lastSort);
74
+ for (const sort of sorts) {
75
+ const { key, keys, direction } = sort;
76
+ const filterKey = (direction === "ASC" ? (sort === lastSort ? `${key}<` : `${key}<=`) : sort === lastSort ? `${key}>` : `${key}>=`);
77
+ yield new Filter(filterKey, getProp(item, ...keys));
78
+ }
79
+ }
@@ -1,7 +1,7 @@
1
1
  export * from "./Constraint.js";
2
2
  export * from "./Constraints.js";
3
- export * from "./FilterConstraint.js";
4
- export * from "./FilterConstraints.js";
5
- export * from "./SortConstraint.js";
6
- export * from "./SortConstraints.js";
7
- export * from "./QueryConstraints.js";
3
+ export * from "./Filter.js";
4
+ export * from "./Filters.js";
5
+ export * from "./Sort.js";
6
+ export * from "./Sorts.js";
7
+ export * from "./Statement.js";
@@ -1,7 +1,7 @@
1
1
  export * from "./Constraint.js";
2
2
  export * from "./Constraints.js";
3
- export * from "./FilterConstraint.js";
4
- export * from "./FilterConstraints.js";
5
- export * from "./SortConstraint.js";
6
- export * from "./SortConstraints.js";
7
- export * from "./QueryConstraints.js";
3
+ export * from "./Filter.js";
4
+ export * from "./Filters.js";
5
+ export * from "./Sort.js";
6
+ export * from "./Sorts.js";
7
+ export * from "./Statement.js";
package/db/Change.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { notNullish } from "../util/null.js";
2
- import { getItemConstraints } from "./Item.js";
2
+ import { getItemStatement } from "./Item.js";
3
3
  /** Apply a set of changes to a synchronous provider. */
4
4
  export function changeProvider(provider, ...changes) {
5
5
  return changes.filter(notNullish).map(_changeItem, provider);
@@ -11,7 +11,7 @@ function _changeItem(change) {
11
11
  else if (action === "SET")
12
12
  this.setItem(collection, change.id, change.data);
13
13
  else if (action === "UPDATE")
14
- this.updateQuery(collection, getItemConstraints(change.id), change.updates);
14
+ this.updateQuery(collection, getItemStatement(change.id), change.updates);
15
15
  else if (action === "DELETE")
16
16
  this.deleteItem(collection, change.id);
17
17
  return change;
@@ -27,7 +27,7 @@ async function _changeAsyncItem(change) {
27
27
  else if (action === "SET")
28
28
  await this.setItem(collection, change.id, change.data);
29
29
  else if (action === "UPDATE")
30
- await this.updateQuery(collection, getItemConstraints(change.id), change.updates);
30
+ await this.updateQuery(collection, getItemStatement(change.id), change.updates);
31
31
  else if (action === "DELETE")
32
32
  await this.deleteItem(collection, change.id);
33
33
  return change;
@@ -1,6 +1,6 @@
1
1
  import type { Data } from "../util/data.js";
2
- import type { FilterList } from "../constraint/FilterConstraint.js";
3
- import type { SortList } from "../constraint/SortConstraint.js";
2
+ import type { PossibleFilters } from "../constraint/Filters.js";
3
+ import type { PossibleSorts } from "../constraint/Sorts.js";
4
4
  import type { Updates } from "../update/DataUpdate.js";
5
5
  import type { Provider, AsyncProvider } from "../provider/Provider.js";
6
6
  import { ItemData, AsyncItem, Item, ItemValue } from "./Item.js";
@@ -11,7 +11,7 @@ declare abstract class BaseCollection<T extends Data = Data> {
11
11
  abstract readonly provider: Provider | AsyncProvider;
12
12
  abstract readonly collection: string;
13
13
  /** Create a query on this item's collection. */
14
- abstract query(filters?: FilterList<Partial<ItemData<T>>>, sorts?: SortList<Partial<ItemData<T>>>, limit?: number | null): Query<T> | AsyncQuery<T>;
14
+ abstract query(filters?: PossibleFilters<ItemData<T>>, sorts?: PossibleSorts<ItemData<T>>, limit?: number | null): Query<T> | AsyncQuery<T>;
15
15
  /** Create a query on this item's collection. */
16
16
  abstract item(id: string): Item<T> | AsyncItem<T>;
17
17
  /** Get an item from this collection. */
@@ -39,7 +39,7 @@ export declare class Collection<T extends Data = Data> extends BaseCollection<T>
39
39
  readonly provider: Provider;
40
40
  readonly collection: string;
41
41
  constructor(provider: Provider, collection: string);
42
- query(filters?: FilterList<ItemData<T>>, sorts?: SortList<ItemData<T>>, limit?: number | null): Query<T>;
42
+ query(filters?: PossibleFilters<ItemData<T>>, sorts?: PossibleSorts<ItemData<T>>, limit?: number | null): Query<T>;
43
43
  item(id: string): Item<T>;
44
44
  get(id: string): ItemValue<T>;
45
45
  add(data: T): string;
@@ -52,7 +52,7 @@ export declare class AsyncCollection<T extends Data = Data> extends BaseCollecti
52
52
  readonly provider: AsyncProvider;
53
53
  readonly collection: string;
54
54
  constructor(provider: AsyncProvider, collection: string);
55
- query(filters?: FilterList<ItemData<T>>, sorts?: SortList<ItemData<T>>, limit?: number | null): AsyncQuery<T>;
55
+ query(filters?: PossibleFilters<ItemData<T>>, sorts?: PossibleSorts<ItemData<T>>, limit?: number | null): AsyncQuery<T>;
56
56
  item(id: string): AsyncItem<T>;
57
57
  get(id: string): Promise<ItemValue<T>>;
58
58
  add(data: T): Promise<string>;
package/db/Database.d.ts CHANGED
@@ -1,8 +1,8 @@
1
1
  import type { DataKey, Datas } from "../util/data.js";
2
2
  import type { Nullish } from "../util/null.js";
3
3
  import type { AsyncProvider, Provider } from "../provider/Provider.js";
4
- import type { FilterList } from "../constraint/FilterConstraint.js";
5
- import type { SortList } from "../constraint/SortConstraint.js";
4
+ import type { PossibleFilters } from "../constraint/Filters.js";
5
+ import type { PossibleSorts } from "../constraint/Sorts.js";
6
6
  import type { ItemData, ItemValue } from "../db/Item.js";
7
7
  import type { Updates } from "../update/DataUpdate.js";
8
8
  import { Item, AsyncItem } from "./Item.js";
@@ -15,7 +15,7 @@ declare abstract class BaseDatabase<T extends Datas> {
15
15
  /** Create a query on a collection in this database. */
16
16
  abstract collection<K extends DataKey<T>>(collection: K): Collection<T[K]> | AsyncCollection<T[K]>;
17
17
  /** Create a query on a collection in this database. */
18
- abstract query<K extends DataKey<T>>(collection: K, filters?: FilterList<Partial<ItemData<T[K]>>>, sorts?: SortList<Partial<ItemData<T[K]>>>, limit?: number | null): Query<T[K]> | AsyncQuery<T[K]>;
18
+ abstract query<K extends DataKey<T>>(collection: K, filters?: PossibleFilters<Partial<ItemData<T[K]>>>, sorts?: PossibleSorts<Partial<ItemData<T[K]>>>, limit?: number | null): Query<T[K]> | AsyncQuery<T[K]>;
19
19
  /** Reference an item in a collection in this database. */
20
20
  abstract item<K extends DataKey<T>>(collection: K, id: string): Item<T[K]> | AsyncItem<T[K]>;
21
21
  /** Run a set of changes in this database. */
@@ -44,7 +44,7 @@ export declare class Database<T extends Datas = Datas> extends BaseDatabase<T> {
44
44
  readonly provider: Provider;
45
45
  constructor(provider: Provider);
46
46
  collection<K extends DataKey<T>>(collection: K): Collection<T[K]>;
47
- query<K extends DataKey<T>>(collection: K, filters?: FilterList<ItemData<T[K]>>, sorts?: SortList<ItemData<T[K]>>, limit?: number | null): Query<T[K]>;
47
+ query<K extends DataKey<T>>(collection: K, filters?: PossibleFilters<ItemData<T[K]>>, sorts?: PossibleSorts<ItemData<T[K]>>, limit?: number | null): Query<T[K]>;
48
48
  item<K extends DataKey<T>>(collection: K, id: string): Item<T[K]>;
49
49
  change(...changes: Nullish<WriteChange>[]): ItemChanges;
50
50
  get<K extends DataKey<T>>(collection: K, id: string): ItemValue<T[K]>;
@@ -58,7 +58,7 @@ export declare class AsyncDatabase<T extends Datas = Datas> extends BaseDatabase
58
58
  readonly provider: AsyncProvider;
59
59
  constructor(provider: AsyncProvider);
60
60
  collection<K extends DataKey<T>>(collection: K): AsyncCollection<T[K]>;
61
- query<K extends DataKey<T>>(collection: K, filters?: FilterList<ItemData<T[K]>>, sorts?: SortList<ItemData<T[K]>>, limit?: number | null): AsyncQuery<T[K]>;
61
+ query<K extends DataKey<T>>(collection: K, filters?: PossibleFilters<ItemData<T[K]>>, sorts?: PossibleSorts<ItemData<T[K]>>, limit?: number | null): AsyncQuery<T[K]>;
62
62
  item<K extends DataKey<T>>(collection: K, id: string): AsyncItem<T[K]>;
63
63
  change(...changes: Nullish<WriteChange>[]): Promise<ItemChanges>;
64
64
  get<K extends DataKey<T>>(collection: K, id: string): Promise<ItemValue<T[K]>>;
package/db/Item.d.ts CHANGED
@@ -1,9 +1,9 @@
1
1
  import type { ImmutableArray } from "../util/array.js";
2
2
  import type { Stop, Handler, Dispatch } from "../util/function.js";
3
3
  import type { Provider, AsyncProvider } from "../provider/Provider.js";
4
- import { QueryConstraints } from "../constraint/QueryConstraints.js";
4
+ import type { Updates } from "../update/DataUpdate.js";
5
+ import { Statement } from "../constraint/Statement.js";
5
6
  import { Data } from "../util/data.js";
6
- import { DataUpdate, Updates } from "../update/DataUpdate.js";
7
7
  import type { DeleteChange, SetChange, UpdateChange } from "./Change.js";
8
8
  /** Item data with a string ID that uniquely identifies it. */
9
9
  export type ItemData<T extends Data = Data> = T & {
@@ -18,9 +18,9 @@ export declare function getIDs<T extends Data>(entities: Iterable<ItemData<T>>):
18
18
  /** An array of item data. */
19
19
  export type ItemArray<T extends Data = Data> = ImmutableArray<ItemData<T>>;
20
20
  /** A set of query constraints for item data. */
21
- export type ItemConstraints<T extends Data = Data> = QueryConstraints<ItemData<T>>;
22
- /** Get a `FilterConstraints` instance that targets a single item by its ID. */
23
- export declare const getItemConstraints: <T extends Data>(id: string) => QueryConstraints<ItemData<T>>;
21
+ export type ItemStatement<T extends Data = Data> = Statement<ItemData<T>>;
22
+ /** Get a `Filter` instance that targets a single item by its ID. */
23
+ export declare const getItemStatement: <T extends Data>(id: string) => Statement<ItemData<T>>;
24
24
  /** Reference to an item in a synchronous or asynchronous database. */
25
25
  declare abstract class BaseItem<T extends Data = Data> implements AsyncIterable<ItemValue<T>> {
26
26
  abstract readonly provider: Provider | AsyncProvider;
@@ -47,7 +47,7 @@ declare abstract class BaseItem<T extends Data = Data> implements AsyncIterable<
47
47
  /** Set the complete data of this item. */
48
48
  abstract set(data: T): void | PromiseLike<void>;
49
49
  /** Update this item. */
50
- abstract update(updates: DataUpdate<T> | Updates<T>): void | PromiseLike<void>;
50
+ abstract update(updates: Updates<T>): void | PromiseLike<void>;
51
51
  /** Delete this item. */
52
52
  abstract delete(): void | PromiseLike<void>;
53
53
  /** Get a set change for this item. */
package/db/Item.js CHANGED
@@ -1,6 +1,6 @@
1
- import { QueryConstraints } from "../constraint/QueryConstraints.js";
2
- import { FilterConstraint } from "../constraint/FilterConstraint.js";
3
- import { FilterConstraints } from "../constraint/FilterConstraints.js";
1
+ import { Statement } from "../constraint/Statement.js";
2
+ import { Filter } from "../constraint/Filter.js";
3
+ import { Filters } from "../constraint/Filters.js";
4
4
  import { getData } from "../util/data.js";
5
5
  import { runSequence } from "../util/sequence.js";
6
6
  /** Get the ID from item data. */
@@ -10,8 +10,8 @@ export function* getIDs(entities) {
10
10
  for (const { id } of entities)
11
11
  yield id;
12
12
  }
13
- /** Get a `FilterConstraints` instance that targets a single item by its ID. */
14
- export const getItemConstraints = (id) => new QueryConstraints(new FilterConstraints(new FilterConstraint("id", id)), undefined, 1);
13
+ /** Get a `Filter` instance that targets a single item by its ID. */
14
+ export const getItemStatement = (id) => new Statement(new Filters(new Filter("id", id)), undefined, 1);
15
15
  /** Reference to an item in a synchronous or asynchronous database. */
16
16
  class BaseItem {
17
17
  /** Get a set change for this item. */
package/db/ItemState.d.ts CHANGED
@@ -1,5 +1,5 @@
1
+ import type { Dispatch } from "../util/function.js";
1
2
  import { Data } from "../util/data.js";
2
- import { Dispatch } from "../util/function.js";
3
3
  import { State } from "../state/State.js";
4
4
  import { BooleanState } from "../state/BooleanState.js";
5
5
  import { ItemValue, Item, AsyncItem, ItemData } from "./Item.js";