shelving 1.51.4 → 1.52.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/Database.js CHANGED
@@ -168,9 +168,9 @@ export class DatabaseQuery extends Query {
168
168
  }
169
169
  /** Get the data for a document from a result for that document. */
170
170
  export function getQueryData(entries, ref) {
171
- const first = getFirstItem(entries);
172
- if (first)
173
- return getDocumentData(first[1], ref.doc(first[0]));
171
+ const data = getQueryResult(entries, ref);
172
+ if (data)
173
+ return data;
174
174
  throw new QueryRequiredError(ref);
175
175
  }
176
176
  /** Get the data for a document from a result for that document. */
@@ -178,7 +178,7 @@ export function getQueryResult(entries, ref) {
178
178
  const first = getFirstItem(entries);
179
179
  if (first)
180
180
  return getDocumentData(first[1], ref.doc(first[0]));
181
- throw new QueryRequiredError(ref);
181
+ return null;
182
182
  }
183
183
  /** A document reference within a specific database. */
184
184
  export class DatabaseDocument {
package/db/errors.d.ts CHANGED
@@ -7,16 +7,40 @@ export declare class DocumentRequiredError<T extends Data> extends RequiredError
7
7
  ref: DatabaseDocument<T>;
8
8
  constructor(ref: DatabaseDocument<T>);
9
9
  }
10
- /** Thrown if a query doesn't exist. */
11
- export declare class QueryRequiredError<T extends Data> extends RequiredError {
12
- ref: DatabaseQuery<T>;
13
- constructor(ref: DatabaseQuery<T>);
10
+ /** Thrown if an error occurs while reading a document. */
11
+ export declare class DocumentReadError<T extends Data> extends Error {
12
+ error: Error;
13
+ ref: DatabaseDocument<T>;
14
+ constructor(error: Error, ref: DatabaseDocument<T>);
15
+ }
16
+ /** Thrown if an error occurs while writing a document. */
17
+ export declare class DocumentWriteError<T extends Data> extends Error {
18
+ error: Error;
19
+ ref: DatabaseDocument<T>;
20
+ constructor(error: Error, ref: DatabaseDocument<T>);
14
21
  }
15
22
  /** Thrown if a document can't validate. */
16
23
  export declare class DocumentValidationError<T extends Data> extends ValidationError {
17
24
  ref: DatabaseDocument<T>;
18
25
  constructor(ref: DatabaseDocument<T>, feedback: Feedback);
19
26
  }
27
+ /** Thrown if a query doesn't exist. */
28
+ export declare class QueryRequiredError<T extends Data> extends RequiredError {
29
+ ref: DatabaseQuery<T>;
30
+ constructor(ref: DatabaseQuery<T>);
31
+ }
32
+ /** Thrown if an error occurs while reading a query. */
33
+ export declare class QueryReadError<T extends Data> extends Error {
34
+ error: Error;
35
+ ref: DatabaseQuery<T>;
36
+ constructor(error: Error, ref: DatabaseQuery<T>);
37
+ }
38
+ /** Thrown if an error occurs while writing a query. */
39
+ export declare class QueryWriteError<T extends Data> extends Error {
40
+ error: Error;
41
+ ref: DatabaseQuery<T>;
42
+ constructor(error: Error, ref: DatabaseQuery<T>);
43
+ }
20
44
  /** Thrown if a query can't validate a set of results. */
21
45
  export declare class QueryValidationError<T extends Data> extends ValidationError {
22
46
  ref: DatabaseQuery<T>;
package/db/errors.js CHANGED
@@ -2,27 +2,63 @@ import { RequiredError, ValidationError } from "../error/index.js";
2
2
  /** Thrown if a document doesn't exist. */
3
3
  export class DocumentRequiredError extends RequiredError {
4
4
  constructor(ref) {
5
- super(`Document "${ref.toString()}" does not exist`);
5
+ super(`Document ${ref.toString()} does not exist`);
6
6
  this.ref = ref;
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`);
10
+ /** Thrown if an error occurs while reading a document. */
11
+ export class DocumentReadError extends Error {
12
+ constructor(error, ref) {
13
+ super(`Error reading document ${ref.toString()}:\n${error.message}`);
14
+ this.error = error;
14
15
  this.ref = ref;
15
16
  }
16
17
  }
17
- QueryRequiredError.prototype.name = "QueryRequiredError";
18
+ DocumentReadError.prototype.name = "DocumentReadError";
19
+ /** Thrown if an error occurs while writing a document. */
20
+ export class DocumentWriteError extends Error {
21
+ constructor(error, ref) {
22
+ super(`Error writing document ${ref.toString()}:\n${error.message}`);
23
+ this.error = error;
24
+ this.ref = ref;
25
+ }
26
+ }
27
+ DocumentWriteError.prototype.name = "DocumentWriteError";
18
28
  /** Thrown if a document can't validate. */
19
29
  export class DocumentValidationError extends ValidationError {
20
30
  constructor(ref, feedback) {
21
- super(`Invalid data for "${ref.toString()}"`, feedback);
31
+ super(`Invalid data for ${ref.toString()}`, feedback);
22
32
  this.ref = ref;
23
33
  }
24
34
  }
25
35
  DocumentValidationError.prototype.name = "DocumentValidationError";
36
+ /** Thrown if a query doesn't exist. */
37
+ export class QueryRequiredError extends RequiredError {
38
+ constructor(ref) {
39
+ super(`Query ${ref.toString()} has no results`);
40
+ this.ref = ref;
41
+ }
42
+ }
43
+ QueryRequiredError.prototype.name = "QueryRequiredError";
44
+ /** Thrown if an error occurs while reading a query. */
45
+ export class QueryReadError extends Error {
46
+ constructor(error, ref) {
47
+ super(`Error reading query ${ref.toString()}:\n${error.message}`);
48
+ this.error = error;
49
+ this.ref = ref;
50
+ }
51
+ }
52
+ QueryReadError.prototype.name = "QueryReadError";
53
+ /** Thrown if an error occurs while writing a query. */
54
+ export class QueryWriteError extends Error {
55
+ constructor(error, ref) {
56
+ super(`Error writing query ${ref.toString()}:\n${error.message}`);
57
+ this.error = error;
58
+ this.ref = ref;
59
+ }
60
+ }
61
+ DocumentWriteError.prototype.name = "DocumentWriteError";
26
62
  /** Thrown if a query can't validate a set of results. */
27
63
  export class QueryValidationError extends ValidationError {
28
64
  constructor(ref, feedback) {
package/package.json CHANGED
@@ -11,7 +11,7 @@
11
11
  "state-management",
12
12
  "query-builder"
13
13
  ],
14
- "version": "1.51.4",
14
+ "version": "1.52.0",
15
15
  "repository": "https://github.com/dhoulb/shelving",
16
16
  "author": "Dave Houlbrooke <dave@shax.com>",
17
17
  "license": "0BSD",
@@ -63,13 +63,13 @@
63
63
  "@types/jest": "^27.4.0",
64
64
  "@types/react": "^17.0.39",
65
65
  "@types/react-dom": "^17.0.11",
66
- "@typescript-eslint/eslint-plugin": "^5.11.0",
67
- "@typescript-eslint/parser": "^5.11.0",
66
+ "@typescript-eslint/eslint-plugin": "^5.12.0",
67
+ "@typescript-eslint/parser": "^5.12.0",
68
68
  "eslint": "^8.9.0",
69
- "eslint-config-prettier": "^8.3.0",
69
+ "eslint-config-prettier": "^8.4.0",
70
70
  "eslint-plugin-import": "^2.25.4",
71
71
  "eslint-plugin-prettier": "^4.0.0",
72
- "firebase": "^9.6.6",
72
+ "firebase": "^9.6.7",
73
73
  "jest": "^27.5.1",
74
74
  "jest-ts-webcompat-resolver": "^1.0.0",
75
75
  "prettier": "^2.5.1",
package/query/Query.js CHANGED
@@ -70,6 +70,6 @@ export class Query extends Rule {
70
70
  }
71
71
  // Implement toString()
72
72
  toString() {
73
- return `${this.filters}&${this.sorts}${this.limit ? `&LIMIT=${this.limit}` : ""}`;
73
+ return `filters=${this.filters}&sorts=${this.sorts}&limit={this.limit || ""}`;
74
74
  }
75
75
  }
package/query/Rules.js CHANGED
@@ -19,7 +19,7 @@ export class Rules extends Rule {
19
19
  return this._rules.length;
20
20
  }
21
21
  toString() {
22
- return this._rules.map(toString).join("&");
22
+ return this._rules.map(toString).join(",");
23
23
  }
24
24
  /** Clone this set of rules but add additional rules. */
25
25
  with(...rules) {
@@ -1,5 +1,5 @@
1
1
  import { useState } from "react";
2
- import { CacheProvider, throwAsync, NOERROR, findSourceProvider, NOVALUE, callAsync, getDocumentData } from "../index.js";
2
+ import { CacheProvider, throwAsync, NOERROR, findSourceProvider, NOVALUE, callAsync, getDocumentData, isAsync } from "../index.js";
3
3
  import { usePureEffect } from "./usePureEffect.js";
4
4
  import { usePureMemo } from "./usePureMemo.js";
5
5
  import { usePureState } from "./usePureState.js";
@@ -9,13 +9,14 @@ export function useAsyncDocument(ref, maxAge = 1000) {
9
9
  // Create two states to hold the value and error.
10
10
  const [value, setNext] = usePureState(getCachedResult, memoRef);
11
11
  const [error, setError] = useState(NOERROR);
12
- if (error !== NOERROR)
13
- throw error; // If there's an error throw it.
14
12
  // Register effect.
15
13
  usePureEffect(subscribeEffect, memoRef, maxAge, setNext, setError);
16
14
  // Always return undefined if there's no ref.
17
15
  if (!ref)
18
16
  return undefined;
17
+ // If there's an error throw it.
18
+ if (error !== NOERROR)
19
+ throw error;
19
20
  // If document is cached return the cached value.
20
21
  if (value !== NOVALUE)
21
22
  return value;
@@ -24,7 +25,10 @@ export function useAsyncDocument(ref, maxAge = 1000) {
24
25
  if (maxAge === true)
25
26
  setTimeout(ref.subscribe({ next: setNext, error: setError }), 10000);
26
27
  // Return a promise for the result.
27
- return ref.result;
28
+ const result = ref.result;
29
+ if (isAsync(result))
30
+ result.then(setNext, setError);
31
+ return result;
28
32
  }
29
33
  /** Get the initial result for a reference from the cache. */
30
34
  function getCachedResult(ref) {
@@ -34,22 +38,30 @@ function getCachedResult(ref) {
34
38
  return provider.isCached(ref) ? provider.cache.get(ref) : NOVALUE;
35
39
  }
36
40
  /** Effect that subscribes a component to the cache for a reference. */
37
- function subscribeEffect(ref, maxAge, next, error) {
41
+ function subscribeEffect(ref, maxAge, setNext, setError) {
38
42
  if (ref) {
39
43
  const provider = findSourceProvider(ref.db.provider, CacheProvider);
40
- const stopCache = provider.cache.subscribe(ref, { next, error });
44
+ const stopCache = provider.cache.subscribe(ref, { next: setNext, error: setError });
41
45
  if (maxAge === true) {
42
46
  // If `maxAge` is true subscribe to the source for as long as this component is attached.
43
- const stopSource = ref.subscribe({ next, error });
47
+ const stopSource = ref.subscribe({ next: setNext, error: setError });
44
48
  return () => {
45
49
  stopCache();
46
50
  stopSource();
47
51
  };
48
52
  }
49
- else {
53
+ else if (provider.getCachedAge(ref) > maxAge) {
50
54
  // If cache provider's cached document is older than maxAge then force refresh the data.
51
- if (provider.getCachedAge(ref) > maxAge)
52
- Promise.resolve(ref.result).then(next, error);
55
+ try {
56
+ const result = ref.result;
57
+ if (isAsync(result))
58
+ result.then(setNext, setError);
59
+ else
60
+ setNext(result);
61
+ }
62
+ catch (e) {
63
+ setError(e);
64
+ }
53
65
  }
54
66
  return stopCache;
55
67
  }
package/react/useQuery.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { useState } from "react";
2
- import { CacheProvider, NOERROR, findSourceProvider, NOVALUE, getMap, callAsync, getQueryData, throwAsync, ResultsObserver, getQueryResult, } from "../index.js";
2
+ import { CacheProvider, NOERROR, findSourceProvider, NOVALUE, getMap, callAsync, getQueryData, throwAsync, ResultsObserver, getQueryResult, isAsync, } from "../index.js";
3
3
  import { usePureEffect } from "./usePureEffect.js";
4
4
  import { usePureMemo } from "./usePureMemo.js";
5
5
  import { usePureState } from "./usePureState.js";
@@ -24,7 +24,10 @@ export function useAsyncQuery(ref, maxAge = 1000) {
24
24
  if (maxAge === true)
25
25
  setTimeout(ref.subscribe({ next: setNext, error: setError }), 10000);
26
26
  // Return a promise for the result.
27
- return ref.results;
27
+ const results = ref.results;
28
+ if (isAsync(results))
29
+ results.then(setNext, setError);
30
+ return results;
28
31
  }
29
32
  /** Get the initial results for a reference from the cache. */
30
33
  function getCachedResults(ref) {
@@ -34,10 +37,10 @@ function getCachedResults(ref) {
34
37
  return provider.isCached(ref) ? getMap(provider.cache.getQuery(ref)) : NOVALUE;
35
38
  }
36
39
  /** Effect that subscribes a component to the cache for a reference. */
37
- function subscribeEffect(ref, maxAge, next, error) {
40
+ function subscribeEffect(ref, maxAge, setNext, setError) {
38
41
  if (ref) {
39
42
  const provider = findSourceProvider(ref.db.provider, CacheProvider);
40
- const observer = new ResultsObserver({ next, error });
43
+ const observer = new ResultsObserver({ next: setNext, error: setError });
41
44
  const stopCache = provider.cache.subscribeQuery(ref, observer);
42
45
  if (maxAge === true) {
43
46
  // If `maxAge` is true subscribe to the source for as long as this component is attached.
@@ -47,10 +50,19 @@ function subscribeEffect(ref, maxAge, next, error) {
47
50
  stopSource();
48
51
  };
49
52
  }
50
- else {
53
+ else if (provider.getCachedAge(ref) > maxAge) {
51
54
  // If cache provider's cached document is older than maxAge then force refresh the data.
52
- if (provider.getCachedAge(ref) > maxAge)
53
- Promise.resolve(ref.results).then(next, error);
55
+ Promise.resolve(ref.results).then(setNext, setError);
56
+ try {
57
+ const results = ref.results;
58
+ if (isAsync(results))
59
+ results.then(setNext, setError);
60
+ else
61
+ setNext(results);
62
+ }
63
+ catch (e) {
64
+ setError(e);
65
+ }
54
66
  }
55
67
  return stopCache;
56
68
  }
package/util/jsx.d.ts CHANGED
@@ -7,8 +7,8 @@ export declare type JSXProps = {
7
7
  readonly children?: JSXNode;
8
8
  };
9
9
  /** JSX element (similar to `React.ReactElement`) */
10
- export declare type JSXElement<P extends JSXProps = JSXProps, T extends string | JSXElementCreator<P> = string | JSXElementCreator<P>> = {
11
- type: T;
10
+ export declare type JSXElement<P extends JSXProps = JSXProps> = {
11
+ type: string | JSXElementCreator<P>;
12
12
  props: P;
13
13
  key: string | number | null;
14
14
  $$typeof?: symbol;