shelving 1.30.2 → 1.30.3

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/Database.d.ts CHANGED
@@ -56,7 +56,9 @@ export declare class DataQuery<T extends Data = Data> extends Query<T> implement
56
56
  get count(): number | PromiseLike<number>;
57
57
  /**
58
58
  * Get an entry for the first document matching this query.
59
- * @return Entry in `[id, data]` format for the first document, or `undefined` if there are no matching documents (possibly promised).
59
+ *
60
+ * @return Entry in `[id, data]` format for the first document.
61
+ * @throws RequiredError if there were no results for this query.
60
62
  */
61
63
  get first(): Entry<T> | undefined | PromiseLike<Entry<T> | undefined>;
62
64
  /**
@@ -100,6 +102,8 @@ export declare class DataQuery<T extends Data = Data> extends Query<T> implement
100
102
  validate(unsafeEntries: Results): Results<T>;
101
103
  toString(): string;
102
104
  }
105
+ /** Get the data for a document from a result for that document. */
106
+ export declare function getQueryFirst<T extends Data>(results: Results<T>, ref: DataQuery<T>): Entry<T>;
103
107
  /** A document reference within a specific database. */
104
108
  export declare class DataDocument<T extends Data = Data> implements Observable<Result<T>>, Validatable<T> {
105
109
  readonly provider: Provider;
package/db/Database.js CHANGED
@@ -2,7 +2,7 @@ import { callAsync, getFirstItem, throwAsync, validate, toMap, countItems, Trans
2
2
  import { DataUpdate, Update } from "../update/index.js";
3
3
  import { Feedback, InvalidFeedback } from "../feedback/index.js";
4
4
  import { Filters, Query, EqualFilter } from "../query/index.js";
5
- import { DocumentRequiredError, DocumentValidationError, QueryValidationError } from "./errors.js";
5
+ import { DocumentRequiredError, DocumentValidationError, QueryRequiredError, QueryValidationError } from "./errors.js";
6
6
  import { DocumentDelete, DocumentSet, DocumentUpdate, Writes } from "./Write.js";
7
7
  /**
8
8
  * Combines a database model and a provider.
@@ -81,10 +81,12 @@ export class DataQuery extends Query {
81
81
  }
82
82
  /**
83
83
  * Get an entry for the first document matching this query.
84
- * @return Entry in `[id, data]` format for the first document, or `undefined` if there are no matching documents (possibly promised).
84
+ *
85
+ * @return Entry in `[id, data]` format for the first document.
86
+ * @throws RequiredError if there were no results for this query.
85
87
  */
86
88
  get first() {
87
- return callAsync(getFirstItem, this.max(1).results);
89
+ return callAsync(getQueryFirst, this.max(1).results, this);
88
90
  }
89
91
  /**
90
92
  * Subscribe to all matching documents.
@@ -158,6 +160,13 @@ export class DataQuery extends Query {
158
160
  return `${this.collection}?${super.toString()}`;
159
161
  }
160
162
  }
163
+ /** Get the data for a document from a result for that document. */
164
+ export function getQueryFirst(results, ref) {
165
+ const first = getFirstItem(results);
166
+ if (first)
167
+ return first;
168
+ throw new QueryRequiredError(ref);
169
+ }
161
170
  /** A document reference within a specific database. */
162
171
  export class DataDocument {
163
172
  constructor(provider, validator, collection, id) {
package/db/errors.d.ts CHANGED
@@ -7,6 +7,11 @@ export declare class DocumentRequiredError<T extends Data> extends RequiredError
7
7
  ref: DataDocument<T>;
8
8
  constructor(ref: DataDocument<T>);
9
9
  }
10
+ /** Thrown if a query doesn't exist. */
11
+ export declare class QueryRequiredError<T extends Data> extends RequiredError {
12
+ ref: DataQuery<T>;
13
+ constructor(ref: DataQuery<T>);
14
+ }
10
15
  /** Thrown if a document can't validate. */
11
16
  export declare class DocumentValidationError<T extends Data> extends ValidationError {
12
17
  ref: DataDocument<T>;
package/db/errors.js CHANGED
@@ -7,6 +7,14 @@ export class DocumentRequiredError extends RequiredError {
7
7
  }
8
8
  }
9
9
  DocumentRequiredError.prototype.name = "DocumentRequiredError";
10
+ /** Thrown if a query doesn't exist. */
11
+ export class QueryRequiredError extends RequiredError {
12
+ constructor(ref) {
13
+ super(`Query "${ref.toString()}" has no results`);
14
+ this.ref = ref;
15
+ }
16
+ }
17
+ QueryRequiredError.prototype.name = "QueryRequiredError";
10
18
  /** Thrown if a document can't validate. */
11
19
  export class DocumentValidationError extends ValidationError {
12
20
  constructor(ref, feedback) {
package/package.json CHANGED
@@ -11,7 +11,7 @@
11
11
  "state-management",
12
12
  "query-builder"
13
13
  ],
14
- "version": "1.30.2",
14
+ "version": "1.30.3",
15
15
  "repository": "https://github.com/dhoulb/shelving",
16
16
  "author": "Dave Houlbrooke <dave@shax.com>",
17
17
  "license": "0BSD",
package/react/index.d.ts CHANGED
@@ -7,4 +7,5 @@ export * from "./useFetch.js";
7
7
  export * from "./useDocument.js";
8
8
  export * from "./useDocumentData.js";
9
9
  export * from "./useQuery.js";
10
+ export * from "./useQueryFirst.js";
10
11
  export * from "./usePagination.js";
package/react/index.js CHANGED
@@ -7,4 +7,5 @@ export * from "./useFetch.js";
7
7
  export * from "./useDocument.js";
8
8
  export * from "./useDocumentData.js";
9
9
  export * from "./useQuery.js";
10
+ export * from "./useQueryFirst.js";
10
11
  export * from "./usePagination.js";
@@ -14,7 +14,7 @@ import { DataDocument, Data } from "../index.js";
14
14
  * @trhows `Error` if a `CacheProvider` is not part of the database's provider chain.
15
15
  * @throws `Error` if there was a problem retrieving the data.
16
16
  */
17
- export declare function useAsyncDocumentData<T extends Data>(ref: DataDocument<T>, maxAge?: number | true): T | Promise<T>;
17
+ export declare function useAsyncDocumentData<T extends Data>(ref: DataDocument<T>, maxAge?: number | true): T | PromiseLike<T>;
18
18
  export declare function useAsyncDocumentData<T extends Data>(ref: DataDocument<T> | undefined, maxAge?: number | true): T | PromiseLike<T> | undefined;
19
19
  /**
20
20
  * Use the cached data of a document in a React component.
@@ -0,0 +1,36 @@
1
+ import { DataQuery, Data, Entry } from "../index.js";
2
+ /**
3
+ * Use the cached data of a document in a React component (or a `Promise` to indicate the data is still loading).
4
+ * - Requires database to use `CacheProvider` and will error if this does not exist.
5
+ *
6
+ * @param ref Query reference or `undefined`.
7
+ * - If `undefined` is set this function will always return `undefined` (this simplifies scenarios where no document is needed, as hooks must always be called in the same order).
8
+ * @param maxAge How 'out of date' data is allowed to be before it'll be refetched.
9
+ * - If `maxAge` is true, a realtime subscription to the data will be created for the lifetime of the component.
10
+ *
11
+ * @returns The data of the document, or `Promise` that resolves when the data has loaded.
12
+ *
13
+ * @throws `RequiredError` if the query had no results.
14
+ * @trhows `Error` if a `CacheProvider` is not part of the database's provider chain.
15
+ * @throws `Error` if there was a problem retrieving the data.
16
+ */
17
+ export declare function useAsyncQueryFirst<T extends Data>(ref: DataQuery<T>, maxAge?: number | true): Entry<T> | PromiseLike<Entry<T>>;
18
+ export declare function useAsyncQueryFirst<T extends Data>(ref: DataQuery<T> | undefined, maxAge?: number | true): Entry<T> | PromiseLike<Entry<T>> | undefined;
19
+ /**
20
+ * Use the cached data of a document in a React component.
21
+ * - Requires database to use `CacheProvider` and will error if this does not exist.
22
+ *
23
+ * @param ref Query reference or `undefined`.
24
+ * - If `undefined` is set this function will always return `undefined` (this simplifies scenarios where no document is needed, as hooks must always be called in the same order).
25
+ * @param maxAge How 'out of date' data is allowed to be before it'll be refetched.
26
+ * - If `maxAge` is true, a realtime subscription to the data will be created for the lifetime of the component.
27
+ *
28
+ * @returns The data of the document.
29
+ *
30
+ * @throws `Promise` that resolves when the data has loaded.
31
+ * @throws `RequiredError` if the query had no results.
32
+ * @trhows `Error` if a `CacheProvider` is not part of the database's provider chain.
33
+ * @throws `Error` if there was a problem retrieving the data.
34
+ */
35
+ export declare function useQueryFirst<T extends Data>(ref: DataQuery<T>, maxAge?: number | true): Entry<T>;
36
+ export declare function useQueryFirst<T extends Data>(ref: DataQuery<T> | undefined, maxAge?: number | true): Entry<T> | undefined;
@@ -0,0 +1,9 @@
1
+ import { callAsync, getQueryFirst, throwAsync } from "../index.js";
2
+ import { useAsyncQuery } from "./useQuery.js";
3
+ export function useAsyncQueryFirst(ref, maxAge) {
4
+ const results = useAsyncQuery(ref, maxAge);
5
+ return ref && results ? callAsync(getQueryFirst, results, ref) : undefined;
6
+ }
7
+ export function useQueryFirst(ref, maxAge) {
8
+ return throwAsync(useAsyncQueryFirst(ref, maxAge));
9
+ }