@ttt-productions/query-core 0.8.0 → 0.8.2

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/dist/index.d.ts CHANGED
@@ -2,7 +2,7 @@ export { invalidateByPrefix, removeByPrefix, updateQueryData } from './cache-hel
2
2
  export type { WithId, FirestoreBaseOptions, FirestoreDocOptions, FirestoreCollectionOptions, FirestoreInfiniteOptions, FirestorePaginatedOptions, InfinitePage, PaginatedResult, MutationOperation, FirestoreMutationOptions, FirestoreBatchOptions, } from './firestore/types.js';
3
3
  export { docWithId } from './firestore/types.js';
4
4
  export { flattenInfiniteData, getInfiniteDataCount, } from './firestore/infinite-helpers.js';
5
- export type { FirestoreSearchConfig, FirestoreSearchOptions, } from './search/types.js';
5
+ export type { FirestoreSearchConfig, FirestoreSearchOptions, SearchEqualityFilter, } from './search/types.js';
6
6
  export { createDomainEventInvalidator, exact, prefix, predicate, serializeInvalidation, applyInvalidations, } from "./domain-events/index.js";
7
7
  export type { DomainEventInvalidator, DomainEventInvalidationRegistry, CacheInvalidation, RefetchType, } from "./domain-events/index.js";
8
8
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,kBAAkB,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAGzF,YAAY,EACV,MAAM,EACN,oBAAoB,EACpB,mBAAmB,EACnB,0BAA0B,EAC1B,wBAAwB,EACxB,yBAAyB,EACzB,YAAY,EACZ,eAAe,EACf,iBAAiB,EACjB,wBAAwB,EACxB,qBAAqB,GACtB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AACjD,OAAO,EACL,mBAAmB,EACnB,oBAAoB,GACrB,MAAM,iCAAiC,CAAC;AAGzC,YAAY,EACV,qBAAqB,EACrB,sBAAsB,GACvB,MAAM,mBAAmB,CAAC;AAG3B,OAAO,EACL,4BAA4B,EAC5B,KAAK,EACL,MAAM,EACN,SAAS,EACT,qBAAqB,EACrB,kBAAkB,GACnB,MAAM,0BAA0B,CAAC;AAClC,YAAY,EACV,sBAAsB,EACtB,+BAA+B,EAC/B,iBAAiB,EACjB,WAAW,GACZ,MAAM,0BAA0B,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,kBAAkB,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAGzF,YAAY,EACV,MAAM,EACN,oBAAoB,EACpB,mBAAmB,EACnB,0BAA0B,EAC1B,wBAAwB,EACxB,yBAAyB,EACzB,YAAY,EACZ,eAAe,EACf,iBAAiB,EACjB,wBAAwB,EACxB,qBAAqB,GACtB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AACjD,OAAO,EACL,mBAAmB,EACnB,oBAAoB,GACrB,MAAM,iCAAiC,CAAC;AAGzC,YAAY,EACV,qBAAqB,EACrB,sBAAsB,EACtB,oBAAoB,GACrB,MAAM,mBAAmB,CAAC;AAG3B,OAAO,EACL,4BAA4B,EAC5B,KAAK,EACL,MAAM,EACN,SAAS,EACT,qBAAqB,EACrB,kBAAkB,GACnB,MAAM,0BAA0B,CAAC;AAClC,YAAY,EACV,sBAAsB,EACtB,+BAA+B,EAC/B,iBAAiB,EACjB,WAAW,GACZ,MAAM,0BAA0B,CAAC"}
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,gBAAgB;AAChB,OAAO,EAAE,kBAAkB,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAgBzF,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AACjD,OAAO,EACL,mBAAmB,EACnB,oBAAoB,GACrB,MAAM,iCAAiC,CAAC;AAQzC,iFAAiF;AACjF,OAAO,EACL,4BAA4B,EAC5B,KAAK,EACL,MAAM,EACN,SAAS,EACT,qBAAqB,EACrB,kBAAkB,GACnB,MAAM,0BAA0B,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,gBAAgB;AAChB,OAAO,EAAE,kBAAkB,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAgBzF,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AACjD,OAAO,EACL,mBAAmB,EACnB,oBAAoB,GACrB,MAAM,iCAAiC,CAAC;AASzC,iFAAiF;AACjF,OAAO,EACL,4BAA4B,EAC5B,KAAK,EACL,MAAM,EACN,SAAS,EACT,qBAAqB,EACrB,kBAAkB,GACnB,MAAM,0BAA0B,CAAC"}
@@ -0,0 +1,24 @@
1
+ import { type Firestore } from 'firebase/firestore';
2
+ import type { QueryClient } from '@tanstack/react-query';
3
+ export interface SubscribeDocParams {
4
+ queryClient: QueryClient;
5
+ db: Firestore;
6
+ /** Top-level/full collection path the doc lives in (e.g. 'publicUsers'). */
7
+ collectionPath: string;
8
+ /** Cache key prefix; the doc is cached at `[queryKeyPrefix, id]`. */
9
+ queryKeyPrefix: string;
10
+ id: string;
11
+ /** Called whenever a snapshot (data or missing) lands, so the caller can re-render. */
12
+ onUpdate: () => void;
13
+ /** Called on listener error. */
14
+ onError?: (error: Error) => void;
15
+ }
16
+ /**
17
+ * Subscribe to a single document via a shared, reference-counted listener.
18
+ * Returns an idempotent unsubscribe function; the underlying Firestore listener is
19
+ * detached only when the last subscriber for that id unsubscribes.
20
+ */
21
+ export declare function subscribeDoc(params: SubscribeDocParams): () => void;
22
+ /** Test-only: number of active shared listeners for a QueryClient. */
23
+ export declare function __activeListenerCount(queryClient: QueryClient): number;
24
+ //# sourceMappingURL=doc-subscription-registry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"doc-subscription-registry.d.ts","sourceRoot":"","sources":["../../../src/react/firestore/doc-subscription-registry.ts"],"names":[],"mappings":"AAEA,OAAO,EAAmB,KAAK,SAAS,EAAE,MAAM,oBAAoB,CAAC;AACrE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AA0CzD,MAAM,WAAW,kBAAkB;IACjC,WAAW,EAAE,WAAW,CAAC;IACzB,EAAE,EAAE,SAAS,CAAC;IACd,4EAA4E;IAC5E,cAAc,EAAE,MAAM,CAAC;IACvB,qEAAqE;IACrE,cAAc,EAAE,MAAM,CAAC;IACvB,EAAE,EAAE,MAAM,CAAC;IACX,uFAAuF;IACvF,QAAQ,EAAE,MAAM,IAAI,CAAC;IACrB,gCAAgC;IAChC,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;CAClC;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,kBAAkB,GAAG,MAAM,IAAI,CA2CnE;AAED,sEAAsE;AACtE,wBAAgB,qBAAqB,CAAC,WAAW,EAAE,WAAW,GAAG,MAAM,CAEtE"}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"doc-subscription-registry.js","sourceRoot":"","sources":["../../../src/react/firestore/doc-subscription-registry.ts"],"names":[],"mappings":"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"}
@@ -30,6 +30,16 @@ export type BatchFirestoreDocsOptions = {
30
30
  * Whether queries should be enabled (default: true)
31
31
  */
32
32
  enabled?: boolean;
33
+ /**
34
+ * Real-time mode (default: false). When true, each id is resolved via a shared,
35
+ * reference-counted `onSnapshot` listener instead of a one-shot `getDocs` batch:
36
+ * - a missing doc caches `null` (negative caching) and resolves the instant it appears,
37
+ * - identity edits propagate live, and every browser tab stays consistent,
38
+ * - `staleTime` is irrelevant (listeners keep the cache fresh).
39
+ * Initial read cost matches the batch path; listeners then stay open while mounted.
40
+ * Use for small, frequently-rendered, change-sensitive identity docs (e.g. publicUsers).
41
+ */
42
+ subscribe?: boolean;
33
43
  };
34
44
  export type BatchFirestoreDocsResult<T> = {
35
45
  /**
@@ -75,5 +85,5 @@ export type BatchFirestoreDocsResult<T> = {
75
85
  * // users = { user1: {...}, user2: {...}, user3: {...} }
76
86
  * ```
77
87
  */
78
- export declare function useBatchFirestoreDocs<T extends Record<string, any>>({ db, collectionPath, ids, queryKeyPrefix, staleTime, gcTime, enabled, }: BatchFirestoreDocsOptions): BatchFirestoreDocsResult<T>;
88
+ export declare function useBatchFirestoreDocs<T extends Record<string, any>>({ db, collectionPath, ids, queryKeyPrefix, staleTime, gcTime, enabled, subscribe, }: BatchFirestoreDocsOptions): BatchFirestoreDocsResult<T>;
79
89
  //# sourceMappingURL=useBatchFirestoreDocs.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"useBatchFirestoreDocs.d.ts","sourceRoot":"","sources":["../../../src/react/firestore/useBatchFirestoreDocs.ts"],"names":[],"mappings":"AAIA,OAAO,EAAiD,KAAK,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAInG,MAAM,MAAM,yBAAyB,GAAG;IACtC;;OAEG;IACH,EAAE,EAAE,SAAS,CAAC;IAEd;;OAEG;IACH,cAAc,EAAE,MAAM,CAAC;IAEvB;;OAEG;IACH,GAAG,EAAE,MAAM,EAAE,CAAC;IAEd;;;;OAIG;IACH,cAAc,EAAE,MAAM,CAAC;IAEvB;;OAEG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB;;OAEG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAEhB;;OAEG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB,CAAC;AAEF,MAAM,MAAM,wBAAwB,CAAC,CAAC,IAAI;IACxC;;;OAGG;IACH,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;IAExB;;OAEG;IACH,SAAS,EAAE,OAAO,CAAC;IAEnB;;OAEG;IACH,OAAO,EAAE,OAAO,CAAC;IAEjB;;OAEG;IACH,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;IAEpB;;OAEG;IACH,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAC9B,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,qBAAqB,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,EACnE,EAAE,EACF,cAAc,EACd,GAAG,EACH,cAAc,EACd,SAA0B,EAC1B,MAAuB,EACvB,OAAc,GACf,EAAE,yBAAyB,GAAG,wBAAwB,CAAC,CAAC,CAAC,CAkHzD"}
1
+ {"version":3,"file":"useBatchFirestoreDocs.d.ts","sourceRoot":"","sources":["../../../src/react/firestore/useBatchFirestoreDocs.ts"],"names":[],"mappings":"AAIA,OAAO,EAAiD,KAAK,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAKnG,MAAM,MAAM,yBAAyB,GAAG;IACtC;;OAEG;IACH,EAAE,EAAE,SAAS,CAAC;IAEd;;OAEG;IACH,cAAc,EAAE,MAAM,CAAC;IAEvB;;OAEG;IACH,GAAG,EAAE,MAAM,EAAE,CAAC;IAEd;;;;OAIG;IACH,cAAc,EAAE,MAAM,CAAC;IAEvB;;OAEG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB;;OAEG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAEhB;;OAEG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;IAElB;;;;;;;;OAQG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB,CAAC;AAEF,MAAM,MAAM,wBAAwB,CAAC,CAAC,IAAI;IACxC;;;OAGG;IACH,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;IAExB;;OAEG;IACH,SAAS,EAAE,OAAO,CAAC;IAEnB;;OAEG;IACH,OAAO,EAAE,OAAO,CAAC;IAEjB;;OAEG;IACH,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;IAEpB;;OAEG;IACH,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAC9B,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,qBAAqB,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,EACnE,EAAE,EACF,cAAc,EACd,GAAG,EACH,cAAc,EACd,SAA0B,EAC1B,MAAuB,EACvB,OAAc,EACd,SAAiB,GAClB,EAAE,yBAAyB,GAAG,wBAAwB,CAAC,CAAC,CAAC,CAoJzD"}
@@ -1,7 +1,8 @@
1
1
  'use client';
2
- import { useMemo } from 'react';
2
+ import { useEffect, useMemo, useState } from 'react';
3
3
  import { useQueries, useQueryClient } from '@tanstack/react-query';
4
4
  import { collection, getDocs, query, where, documentId } from 'firebase/firestore';
5
+ import { subscribeDoc } from './doc-subscription-registry.js';
5
6
  const FIRESTORE_IN_LIMIT = 30;
6
7
  /**
7
8
  * Efficiently batch fetch Firestore documents with individual caching
@@ -24,7 +25,7 @@ const FIRESTORE_IN_LIMIT = 30;
24
25
  * // users = { user1: {...}, user2: {...}, user3: {...} }
25
26
  * ```
26
27
  */
27
- export function useBatchFirestoreDocs({ db, collectionPath, ids, queryKeyPrefix, staleTime = 30 * 60 * 1000, gcTime = 60 * 60 * 1000, enabled = true, }) {
28
+ export function useBatchFirestoreDocs({ db, collectionPath, ids, queryKeyPrefix, staleTime = 30 * 60 * 1000, gcTime = 60 * 60 * 1000, enabled = true, subscribe = false, }) {
28
29
  const queryClient = useQueryClient();
29
30
  // Stabilize ids reference to prevent cascading re-renders
30
31
  const idsKey = JSON.stringify(ids);
@@ -33,9 +34,32 @@ export function useBatchFirestoreDocs({ db, collectionPath, ids, queryKeyPrefix,
33
34
  const parsed = JSON.parse(idsKey);
34
35
  return Array.from(new Set(parsed.filter(Boolean)));
35
36
  }, [idsKey]);
36
- // Separate IDs into cached/fresh vs needs-fetch
37
+ // ── Real-time subscribe mode ──────────────────────────────────────────────
38
+ // Re-render trigger; bumped whenever a subscribed doc's snapshot lands.
39
+ const [snapshotVersion, setSnapshotVersion] = useState(0);
40
+ const [subscribeError, setSubscribeError] = useState(null);
41
+ useEffect(() => {
42
+ if (!subscribe || !enabled || uniqueIds.length === 0)
43
+ return;
44
+ setSubscribeError(null);
45
+ const unsubscribers = uniqueIds.map((id) => subscribeDoc({
46
+ queryClient,
47
+ db,
48
+ collectionPath,
49
+ queryKeyPrefix,
50
+ id,
51
+ onUpdate: () => setSnapshotVersion((v) => v + 1),
52
+ onError: (error) => setSubscribeError(error),
53
+ }));
54
+ return () => {
55
+ for (const unsubscribe of unsubscribers)
56
+ unsubscribe();
57
+ };
58
+ // eslint-disable-next-line react-hooks/exhaustive-deps -- idsKey stands in for uniqueIds
59
+ }, [idsKey, subscribe, enabled, collectionPath, queryKeyPrefix, queryClient, db]);
60
+ // Separate IDs into cached/fresh vs needs-fetch (one-shot path only)
37
61
  const { fetchIds } = useMemo(() => {
38
- if (!enabled) {
62
+ if (!enabled || subscribe) {
39
63
  return { fetchIds: [] };
40
64
  }
41
65
  const needsFetch = [];
@@ -48,7 +72,7 @@ export function useBatchFirestoreDocs({ db, collectionPath, ids, queryKeyPrefix,
48
72
  }
49
73
  }
50
74
  return { fetchIds: needsFetch };
51
- }, [uniqueIds, queryKeyPrefix, queryClient, staleTime, enabled]);
75
+ }, [uniqueIds, queryKeyPrefix, queryClient, staleTime, enabled, subscribe]);
52
76
  // Batch the fetchIds into groups of 30
53
77
  const batches = useMemo(() => {
54
78
  const result = [];
@@ -81,18 +105,19 @@ export function useBatchFirestoreDocs({ db, collectionPath, ids, queryKeyPrefix,
81
105
  enabled: enabled && batch.length > 0,
82
106
  })),
83
107
  });
84
- // Combine results
85
- const isLoading = batchQueries.some(q => q.isLoading);
86
- const isError = batchQueries.some(q => q.isError);
87
- const error = batchQueries.find(q => q.error)?.error || null;
108
+ // Combine results (one-shot batch path)
109
+ const batchIsLoading = batchQueries.some(q => q.isLoading);
110
+ const batchIsError = batchQueries.some(q => q.isError);
111
+ const batchError = batchQueries.find(q => q.error)?.error || null;
88
112
  // Trigger re-derivation when batch fetches complete
89
113
  const batchSettledCount = batchQueries.filter(q => q.isSuccess || q.isError).length;
90
114
  const batchUpdateTimestamp = batchQueries.reduce((sum, q) => sum + (q.dataUpdatedAt ?? 0), 0);
91
115
  const data = useMemo(() => {
92
116
  const combined = {};
93
- // Always read all IDs from individual cache entries.
94
- // Batch queries populate these entries via setQueryData; we never read
95
- // batch results directly, so IDs can't fall through the cached/fetched split.
117
+ // Always read all IDs from individual cache entries. Both paths populate these via
118
+ // setQueryData (batch queryFn, or the subscribe listener); we never read batch results
119
+ // directly, so IDs can't fall through the cached/fetched split. A `null` entry means a
120
+ // doc is known-absent (subscribe negative caching) and is correctly excluded here.
96
121
  for (const id of uniqueIds) {
97
122
  const cached = queryClient.getQueryData([queryKeyPrefix, id]);
98
123
  if (cached) {
@@ -100,15 +125,19 @@ export function useBatchFirestoreDocs({ db, collectionPath, ids, queryKeyPrefix,
100
125
  }
101
126
  }
102
127
  return combined;
103
- }, [uniqueIds, queryKeyPrefix, queryClient, batchSettledCount, batchUpdateTimestamp]);
128
+ // snapshotVersion: re-derive when a subscribed doc updates.
129
+ }, [uniqueIds, queryKeyPrefix, queryClient, batchSettledCount, batchUpdateTimestamp, snapshotVersion]);
130
+ // In subscribe mode the batch queries are inert; "loading" means a subscribed id has not
131
+ // received its first snapshot yet (no cache entry — `null` counts as resolved-missing).
132
+ const subscribeIsLoading = subscribe && enabled && uniqueIds.some((id) => queryClient.getQueryData([queryKeyPrefix, id]) === undefined);
104
133
  const refetch = async () => {
105
134
  await Promise.all(batchQueries.map(q => q.refetch()));
106
135
  };
107
136
  return {
108
137
  data,
109
- isLoading,
110
- isError,
111
- error: error,
138
+ isLoading: batchIsLoading || subscribeIsLoading,
139
+ isError: batchIsError || subscribeError !== null,
140
+ error: batchError ?? subscribeError,
112
141
  refetch,
113
142
  };
114
143
  }
@@ -1 +1 @@
1
- {"version":3,"file":"useBatchFirestoreDocs.js","sourceRoot":"","sources":["../../../src/react/firestore/useBatchFirestoreDocs.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"useBatchFirestoreDocs.js","sourceRoot":"","sources":["../../../src/react/firestore/useBatchFirestoreDocs.ts"],"names":[],"mappings":"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"}
@@ -29,5 +29,5 @@ import type { WithId } from '../../firestore/types.js';
29
29
  * });
30
30
  * ```
31
31
  */
32
- export declare function useFirestoreSearch<T extends DocumentData = DocumentData>({ collectionPath, searchField, queryText, limit, enabled, select, debounceMs, staleTime, }: FirestoreSearchOptions<T>): UseQueryResult<WithId<T>[], Error>;
32
+ export declare function useFirestoreSearch<T extends DocumentData = DocumentData>({ collectionPath, searchField, queryText, limit, enabled, select, debounceMs, staleTime, equalityFilters, }: FirestoreSearchOptions<T>): UseQueryResult<WithId<T>[], Error>;
33
33
  //# sourceMappingURL=use-firestore-search.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"use-firestore-search.d.ts","sourceRoot":"","sources":["../../../src/react/search/use-firestore-search.ts"],"names":[],"mappings":"AAGA,OAAO,EAAY,KAAK,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACtE,OAAO,EAOL,KAAK,YAAY,EAElB,MAAM,oBAAoB,CAAC;AAG5B,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAC;AACpE,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,0BAA0B,CAAC;AAMvD;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,wBAAgB,kBAAkB,CAAC,CAAC,SAAS,YAAY,GAAG,YAAY,EAAE,EACxE,cAAc,EACd,WAAW,EACX,SAAS,EACT,KAAqB,EACrB,OAAc,EACd,MAAM,EACN,UAAgC,EAChC,SAA8B,GAC/B,EAAE,sBAAsB,CAAC,CAAC,CAAC,GAAG,cAAc,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,KAAK,CAAC,CAgDhE"}
1
+ {"version":3,"file":"use-firestore-search.d.ts","sourceRoot":"","sources":["../../../src/react/search/use-firestore-search.ts"],"names":[],"mappings":"AAGA,OAAO,EAAY,KAAK,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACtE,OAAO,EAOL,KAAK,YAAY,EAElB,MAAM,oBAAoB,CAAC;AAG5B,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAC;AACpE,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,0BAA0B,CAAC;AAMvD;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,wBAAgB,kBAAkB,CAAC,CAAC,SAAS,YAAY,GAAG,YAAY,EAAE,EACxE,cAAc,EACd,WAAW,EACX,SAAS,EACT,KAAqB,EACrB,OAAc,EACd,MAAM,EACN,UAAgC,EAChC,SAA8B,EAC9B,eAAoB,GACrB,EAAE,sBAAsB,CAAC,CAAC,CAAC,GAAG,cAAc,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,KAAK,CAAC,CAiDhE"}
@@ -34,7 +34,7 @@ const DEFAULT_STALE_TIME = 60 * 1000; // 1 minute
34
34
  * });
35
35
  * ```
36
36
  */
37
- export function useFirestoreSearch({ collectionPath, searchField, queryText, limit = DEFAULT_LIMIT, enabled = true, select, debounceMs = DEFAULT_DEBOUNCE_MS, staleTime = DEFAULT_STALE_TIME, }) {
37
+ export function useFirestoreSearch({ collectionPath, searchField, queryText, limit = DEFAULT_LIMIT, enabled = true, select, debounceMs = DEFAULT_DEBOUNCE_MS, staleTime = DEFAULT_STALE_TIME, equalityFilters = [], }) {
38
38
  const db = useFirestoreDb();
39
39
  const [debouncedQuery, setDebouncedQuery] = useState(queryText);
40
40
  // Debounce the search query
@@ -48,7 +48,7 @@ export function useFirestoreSearch({ collectionPath, searchField, queryText, lim
48
48
  const normalizedQuery = debouncedQuery.toLowerCase().trim();
49
49
  const shouldSearch = normalizedQuery.length >= 3 && enabled;
50
50
  return useQuery({
51
- queryKey: keys.custom('search', collectionPath, searchField, normalizedQuery),
51
+ queryKey: keys.custom('search', collectionPath, searchField, normalizedQuery, JSON.stringify(equalityFilters)),
52
52
  queryFn: async () => {
53
53
  if (!shouldSearch) {
54
54
  return [];
@@ -57,6 +57,7 @@ export function useFirestoreSearch({ collectionPath, searchField, queryText, lim
57
57
  // Build range query for prefix matching
58
58
  // Using '\uf8ff' as upper bound creates a range that matches all strings starting with the query
59
59
  const constraints = [
60
+ ...equalityFilters.map((f) => where(f.field, '==', f.value)),
60
61
  where(searchField, '>=', normalizedQuery),
61
62
  where(searchField, '<=', normalizedQuery + '\uf8ff'),
62
63
  orderBy(searchField, 'asc'),
@@ -1 +1 @@
1
- {"version":3,"file":"use-firestore-search.js","sourceRoot":"","sources":["../../../src/react/search/use-firestore-search.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"use-firestore-search.js","sourceRoot":"","sources":["../../../src/react/search/use-firestore-search.ts"],"names":[],"mappings":"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"}
@@ -1,4 +1,14 @@
1
1
  import type { DocumentData } from 'firebase/firestore';
2
+ /**
3
+ * Equality filter applied before the prefix range in a Firestore search.
4
+ * Each becomes a `where(field, '==', value)` constraint, ordered ahead of the
5
+ * search field. The composite index must list these equality fields (ASC)
6
+ * before the search field (ASC).
7
+ */
8
+ export interface SearchEqualityFilter {
9
+ field: string;
10
+ value: unknown;
11
+ }
2
12
  /**
3
13
  * Configuration for a Firestore search query
4
14
  */
@@ -9,6 +19,8 @@ export interface FirestoreSearchConfig {
9
19
  searchField: string;
10
20
  /** Maximum number of results to return */
11
21
  limit: number;
22
+ /** Optional equality filters applied before the prefix range. */
23
+ equalityFilters?: SearchEqualityFilter[];
12
24
  }
13
25
  /**
14
26
  * Options for useFirestoreSearch hook
@@ -32,5 +44,7 @@ export interface FirestoreSearchOptions<T extends DocumentData = DocumentData> {
32
44
  debounceMs?: number;
33
45
  /** React Query stale time (default: 60000ms) */
34
46
  staleTime?: number;
47
+ /** Optional equality filters applied before the prefix range. */
48
+ equalityFilters?: SearchEqualityFilter[];
35
49
  }
36
50
  //# sourceMappingURL=types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/search/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAEvD;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACpC,0CAA0C;IAC1C,cAAc,EAAE,MAAM,CAAC;IACvB,8DAA8D;IAC9D,WAAW,EAAE,MAAM,CAAC;IACpB,0CAA0C;IAC1C,KAAK,EAAE,MAAM,CAAC;CACf;AAED;;GAEG;AACH,MAAM,WAAW,sBAAsB,CAAC,CAAC,SAAS,YAAY,GAAG,YAAY;IAC3E,0CAA0C;IAC1C,cAAc,EAAE,MAAM,CAAC;IACvB,8DAA8D;IAC9D,WAAW,EAAE,MAAM,CAAC;IACpB,wBAAwB;IACxB,SAAS,EAAE,MAAM,CAAC;IAClB,6CAA6C;IAC7C,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,gDAAgD;IAChD,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,uEAAuE;IACvE,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE,YAAY,GAAG;QAAE,EAAE,EAAE,MAAM,CAAA;KAAE,KAAK,CAAC,CAAC;IACpD,oDAAoD;IACpD,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,gDAAgD;IAChD,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/search/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAEvD;;;;;GAKG;AACH,MAAM,WAAW,oBAAoB;IACnC,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,OAAO,CAAC;CAChB;AAED;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACpC,0CAA0C;IAC1C,cAAc,EAAE,MAAM,CAAC;IACvB,8DAA8D;IAC9D,WAAW,EAAE,MAAM,CAAC;IACpB,0CAA0C;IAC1C,KAAK,EAAE,MAAM,CAAC;IACd,iEAAiE;IACjE,eAAe,CAAC,EAAE,oBAAoB,EAAE,CAAC;CAC1C;AAED;;GAEG;AACH,MAAM,WAAW,sBAAsB,CAAC,CAAC,SAAS,YAAY,GAAG,YAAY;IAC3E,0CAA0C;IAC1C,cAAc,EAAE,MAAM,CAAC;IACvB,8DAA8D;IAC9D,WAAW,EAAE,MAAM,CAAC;IACpB,wBAAwB;IACxB,SAAS,EAAE,MAAM,CAAC;IAClB,6CAA6C;IAC7C,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,gDAAgD;IAChD,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,uEAAuE;IACvE,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE,YAAY,GAAG;QAAE,EAAE,EAAE,MAAM,CAAA;KAAE,KAAK,CAAC,CAAC;IACpD,oDAAoD;IACpD,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,gDAAgD;IAChD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,iEAAiE;IACjE,eAAe,CAAC,EAAE,oBAAoB,EAAE,CAAC;CAC1C"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ttt-productions/query-core",
3
- "version": "0.8.0",
3
+ "version": "0.8.2",
4
4
  "description": "Shared TanStack Query (React Query) client defaults, query key helpers, and Firestore integration hooks for TTT Productions apps",
5
5
  "repository": {
6
6
  "type": "git",