@ttt-productions/query-core 0.2.1 → 0.3.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.
Files changed (37) hide show
  1. package/dist/firestore/context.d.ts +28 -0
  2. package/dist/firestore/context.d.ts.map +1 -0
  3. package/dist/firestore/context.js +35 -0
  4. package/dist/firestore/context.js.map +1 -0
  5. package/dist/firestore/index.d.ts +11 -0
  6. package/dist/firestore/index.d.ts.map +1 -0
  7. package/dist/firestore/index.js +11 -0
  8. package/dist/firestore/index.js.map +1 -0
  9. package/dist/firestore/types.d.ts +142 -0
  10. package/dist/firestore/types.d.ts.map +1 -0
  11. package/dist/firestore/types.js +7 -0
  12. package/dist/firestore/types.js.map +1 -0
  13. package/dist/firestore/use-firestore-collection.d.ts +27 -0
  14. package/dist/firestore/use-firestore-collection.d.ts.map +1 -0
  15. package/dist/firestore/use-firestore-collection.js +74 -0
  16. package/dist/firestore/use-firestore-collection.js.map +1 -0
  17. package/dist/firestore/use-firestore-doc.d.ts +31 -0
  18. package/dist/firestore/use-firestore-doc.d.ts.map +1 -0
  19. package/dist/firestore/use-firestore-doc.js +75 -0
  20. package/dist/firestore/use-firestore-doc.js.map +1 -0
  21. package/dist/firestore/use-firestore-infinite.d.ts +55 -0
  22. package/dist/firestore/use-firestore-infinite.d.ts.map +1 -0
  23. package/dist/firestore/use-firestore-infinite.js +96 -0
  24. package/dist/firestore/use-firestore-infinite.js.map +1 -0
  25. package/dist/firestore/use-firestore-mutations.d.ts +38 -0
  26. package/dist/firestore/use-firestore-mutations.d.ts.map +1 -0
  27. package/dist/firestore/use-firestore-mutations.js +132 -0
  28. package/dist/firestore/use-firestore-mutations.js.map +1 -0
  29. package/dist/firestore/use-firestore-paginated.d.ts +44 -0
  30. package/dist/firestore/use-firestore-paginated.d.ts.map +1 -0
  31. package/dist/firestore/use-firestore-paginated.js +117 -0
  32. package/dist/firestore/use-firestore-paginated.js.map +1 -0
  33. package/dist/index.d.ts +2 -0
  34. package/dist/index.d.ts.map +1 -1
  35. package/dist/index.js +14 -0
  36. package/dist/index.js.map +1 -1
  37. package/package.json +11 -4
@@ -0,0 +1,28 @@
1
+ import { type ReactNode } from 'react';
2
+ import type { Firestore } from 'firebase/firestore';
3
+ export interface FirestoreProviderProps {
4
+ db: Firestore;
5
+ children: ReactNode;
6
+ }
7
+ /**
8
+ * Provides Firestore instance to all useFirestore* hooks.
9
+ * Wrap your app with this provider alongside TTTQueryProvider.
10
+ *
11
+ * @example
12
+ * ```tsx
13
+ * import { db } from '@/lib/firebase';
14
+ *
15
+ * <TTTQueryProvider>
16
+ * <FirestoreProvider db={db}>
17
+ * {children}
18
+ * </FirestoreProvider>
19
+ * </TTTQueryProvider>
20
+ * ```
21
+ */
22
+ export declare function FirestoreProvider({ db, children }: FirestoreProviderProps): import("react/jsx-runtime").JSX.Element;
23
+ /**
24
+ * Access the Firestore instance from context.
25
+ * Throws if used outside of FirestoreProvider.
26
+ */
27
+ export declare function useFirestoreDb(): Firestore;
28
+ //# sourceMappingURL=context.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../src/firestore/context.tsx"],"names":[],"mappings":"AAEA,OAAO,EAA6B,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAClE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAQpD,MAAM,WAAW,sBAAsB;IACrC,EAAE,EAAE,SAAS,CAAC;IACd,QAAQ,EAAE,SAAS,CAAC;CACrB;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,iBAAiB,CAAC,EAAE,EAAE,EAAE,QAAQ,EAAE,EAAE,sBAAsB,2CAMzE;AAED;;;GAGG;AACH,wBAAgB,cAAc,IAAI,SAAS,CAS1C"}
@@ -0,0 +1,35 @@
1
+ 'use client';
2
+ import { jsx as _jsx } from "react/jsx-runtime";
3
+ import { createContext, useContext } from 'react';
4
+ const FirestoreContext = createContext(null);
5
+ /**
6
+ * Provides Firestore instance to all useFirestore* hooks.
7
+ * Wrap your app with this provider alongside TTTQueryProvider.
8
+ *
9
+ * @example
10
+ * ```tsx
11
+ * import { db } from '@/lib/firebase';
12
+ *
13
+ * <TTTQueryProvider>
14
+ * <FirestoreProvider db={db}>
15
+ * {children}
16
+ * </FirestoreProvider>
17
+ * </TTTQueryProvider>
18
+ * ```
19
+ */
20
+ export function FirestoreProvider({ db, children }) {
21
+ return (_jsx(FirestoreContext.Provider, { value: { db }, children: children }));
22
+ }
23
+ /**
24
+ * Access the Firestore instance from context.
25
+ * Throws if used outside of FirestoreProvider.
26
+ */
27
+ export function useFirestoreDb() {
28
+ const context = useContext(FirestoreContext);
29
+ if (!context) {
30
+ throw new Error('useFirestoreDb must be used within a FirestoreProvider. ' +
31
+ 'Wrap your app with <FirestoreProvider db={db}>.');
32
+ }
33
+ return context.db;
34
+ }
35
+ //# sourceMappingURL=context.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context.js","sourceRoot":"","sources":["../../src/firestore/context.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAC;;AAEb,OAAO,EAAE,aAAa,EAAE,UAAU,EAAkB,MAAM,OAAO,CAAC;AAOlE,MAAM,gBAAgB,GAAG,aAAa,CAA+B,IAAI,CAAC,CAAC;AAO3E;;;;;;;;;;;;;;GAcG;AACH,MAAM,UAAU,iBAAiB,CAAC,EAAE,EAAE,EAAE,QAAQ,EAA0B;IACxE,OAAO,CACL,KAAC,gBAAgB,CAAC,QAAQ,IAAC,KAAK,EAAE,EAAE,EAAE,EAAE,YACrC,QAAQ,GACiB,CAC7B,CAAC;AACJ,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,cAAc;IAC5B,MAAM,OAAO,GAAG,UAAU,CAAC,gBAAgB,CAAC,CAAC;IAC7C,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,MAAM,IAAI,KAAK,CACb,0DAA0D;YAC1D,iDAAiD,CAClD,CAAC;IACJ,CAAC;IACD,OAAO,OAAO,CAAC,EAAE,CAAC;AACpB,CAAC"}
@@ -0,0 +1,11 @@
1
+ export { FirestoreProvider, useFirestoreDb } from './context';
2
+ export type { FirestoreProviderProps } from './context';
3
+ export type { WithId, FirestoreBaseOptions, FirestoreDocOptions, FirestoreCollectionOptions, FirestoreInfiniteOptions, FirestorePaginatedOptions, InfinitePage, PaginatedResult, MutationOperation, FirestoreMutationOptions, FirestoreBatchOptions, } from './types';
4
+ export { docWithId } from './types';
5
+ export { useFirestoreDoc } from './use-firestore-doc';
6
+ export { useFirestoreCollection } from './use-firestore-collection';
7
+ export { useFirestoreInfinite, flattenInfiniteData, getInfiniteDataCount } from './use-firestore-infinite';
8
+ export { useFirestorePaginated } from './use-firestore-paginated';
9
+ export type { UseFirestorePaginatedResult } from './use-firestore-paginated';
10
+ export { useFirestoreSet, useFirestoreUpdate, useFirestoreDelete, useFirestoreBatch, } from './use-firestore-mutations';
11
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/firestore/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAC9D,YAAY,EAAE,sBAAsB,EAAE,MAAM,WAAW,CAAC;AAGxD,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,SAAS,CAAC;AACjB,OAAO,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAGpC,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AACtD,OAAO,EAAE,sBAAsB,EAAE,MAAM,4BAA4B,CAAC;AACpE,OAAO,EACL,oBAAoB,EACpB,mBAAmB,EACnB,oBAAoB,EACrB,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;AAClE,YAAY,EAAE,2BAA2B,EAAE,MAAM,2BAA2B,CAAC;AAG7E,OAAO,EACL,eAAe,EACf,kBAAkB,EAClB,kBAAkB,EAClB,iBAAiB,GAClB,MAAM,2BAA2B,CAAC"}
@@ -0,0 +1,11 @@
1
+ // Context & Provider
2
+ export { FirestoreProvider, useFirestoreDb } from './context';
3
+ export { docWithId } from './types';
4
+ // Query Hooks
5
+ export { useFirestoreDoc } from './use-firestore-doc';
6
+ export { useFirestoreCollection } from './use-firestore-collection';
7
+ export { useFirestoreInfinite, flattenInfiniteData, getInfiniteDataCount } from './use-firestore-infinite';
8
+ export { useFirestorePaginated } from './use-firestore-paginated';
9
+ // Mutation Hooks
10
+ export { useFirestoreSet, useFirestoreUpdate, useFirestoreDelete, useFirestoreBatch, } from './use-firestore-mutations';
11
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/firestore/index.ts"],"names":[],"mappings":"AAAA,qBAAqB;AACrB,OAAO,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAiB9D,OAAO,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAEpC,cAAc;AACd,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AACtD,OAAO,EAAE,sBAAsB,EAAE,MAAM,4BAA4B,CAAC;AACpE,OAAO,EACL,oBAAoB,EACpB,mBAAmB,EACnB,oBAAoB,EACrB,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;AAGlE,iBAAiB;AACjB,OAAO,EACL,eAAe,EACf,kBAAkB,EAClB,kBAAkB,EAClB,iBAAiB,GAClB,MAAM,2BAA2B,CAAC"}
@@ -0,0 +1,142 @@
1
+ import type { DocumentData, DocumentSnapshot, QueryDocumentSnapshot, QueryConstraint } from 'firebase/firestore';
2
+ /**
3
+ * Document with ID included in the data object.
4
+ */
5
+ export type WithId<T> = T & {
6
+ id: string;
7
+ };
8
+ /**
9
+ * Extract document data with ID from a QueryDocumentSnapshot.
10
+ */
11
+ export declare function docWithId<T extends DocumentData>(snap: QueryDocumentSnapshot<T>): WithId<T>;
12
+ /**
13
+ * Base options shared across all Firestore hooks.
14
+ */
15
+ export interface FirestoreBaseOptions {
16
+ /** React Query cache key */
17
+ queryKey: readonly unknown[];
18
+ /** Enable/disable the query */
19
+ enabled?: boolean;
20
+ /** Stale time override (ms) */
21
+ staleTime?: number;
22
+ /** Garbage collection time override (ms) */
23
+ gcTime?: number;
24
+ }
25
+ /**
26
+ * Options for single document queries.
27
+ */
28
+ export interface FirestoreDocOptions<T> extends FirestoreBaseOptions {
29
+ /** Full document path (e.g., 'users/abc123') */
30
+ docPath: string;
31
+ /** Enable realtime updates via onSnapshot (default: false) */
32
+ subscribe?: boolean;
33
+ /** Transform function applied to document data. Receives data WITH id included. */
34
+ select?: (data: DocumentData & {
35
+ id: string;
36
+ }) => T;
37
+ }
38
+ /**
39
+ * Options for collection queries.
40
+ */
41
+ export interface FirestoreCollectionOptions<T> extends FirestoreBaseOptions {
42
+ /** Collection path (e.g., 'users' or 'projects/abc/members') */
43
+ collectionPath: string;
44
+ /** Firestore query constraints (where, orderBy, etc.) */
45
+ constraints?: QueryConstraint[];
46
+ /** Enable realtime updates via onSnapshot (default: false) */
47
+ subscribe?: boolean;
48
+ /** Transform function applied to each document. Receives data WITH id included. */
49
+ select?: (data: DocumentData & {
50
+ id: string;
51
+ }) => T;
52
+ }
53
+ /**
54
+ * Options for infinite scroll queries.
55
+ */
56
+ export interface FirestoreInfiniteOptions<T> extends FirestoreBaseOptions {
57
+ /** Collection path */
58
+ collectionPath: string;
59
+ /** Firestore query constraints (where, orderBy - required for pagination) */
60
+ constraints?: QueryConstraint[];
61
+ /** Number of items per page (default: 20) */
62
+ pageSize?: number;
63
+ /** Transform function applied to each document. Receives data WITH id included. */
64
+ select?: (data: DocumentData & {
65
+ id: string;
66
+ }) => T;
67
+ }
68
+ /**
69
+ * Options for paginated queries with page numbers.
70
+ */
71
+ export interface FirestorePaginatedOptions<T> extends FirestoreBaseOptions {
72
+ /** Collection path */
73
+ collectionPath: string;
74
+ /** Firestore query constraints */
75
+ constraints?: QueryConstraint[];
76
+ /** Number of items per page (default: 10) */
77
+ pageSize?: number;
78
+ /** Initial page number (default: 1) */
79
+ initialPage?: number;
80
+ /** Transform function applied to each document. Receives data WITH id included. */
81
+ select?: (data: DocumentData & {
82
+ id: string;
83
+ }) => T;
84
+ }
85
+ /**
86
+ * Result page for infinite queries.
87
+ */
88
+ export interface InfinitePage<T> {
89
+ items: WithId<T>[];
90
+ lastDoc: DocumentSnapshot | null;
91
+ size: number;
92
+ }
93
+ /**
94
+ * Result for paginated queries.
95
+ */
96
+ export interface PaginatedResult<T> {
97
+ items: WithId<T>[];
98
+ cursors: DocumentSnapshot[];
99
+ hasMore: boolean;
100
+ }
101
+ /**
102
+ * Mutation operation types for batch mutations.
103
+ */
104
+ export type MutationOperation = {
105
+ type: 'set';
106
+ docPath: string;
107
+ data: DocumentData;
108
+ merge?: boolean;
109
+ } | {
110
+ type: 'update';
111
+ docPath: string;
112
+ data: DocumentData;
113
+ } | {
114
+ type: 'delete';
115
+ docPath: string;
116
+ };
117
+ /**
118
+ * Options for document mutations.
119
+ */
120
+ export interface FirestoreMutationOptions<T> {
121
+ /** Document path for single-doc mutations */
122
+ docPath?: string;
123
+ /** Query keys to invalidate on success */
124
+ invalidateKeys?: readonly unknown[][];
125
+ /** Enable optimistic updates */
126
+ optimistic?: {
127
+ /** Query key of the cache to update */
128
+ queryKey: readonly unknown[];
129
+ /** How to update the cached data */
130
+ updater: (oldData: T | undefined, newData: Partial<T>) => T;
131
+ };
132
+ }
133
+ /**
134
+ * Options for batch mutations.
135
+ */
136
+ export interface FirestoreBatchOptions {
137
+ /** Query keys to invalidate on success */
138
+ invalidateKeys?: readonly unknown[][];
139
+ /** Max operations per batch (default: 450) */
140
+ batchSize?: number;
141
+ }
142
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/firestore/types.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Extract document data with ID from a QueryDocumentSnapshot.
3
+ */
4
+ export function docWithId(snap) {
5
+ return { id: snap.id, ...snap.data() };
6
+ }
7
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/firestore/types.ts"],"names":[],"mappings":"AAYA;;GAEG;AACH,MAAM,UAAU,SAAS,CACvB,IAA8B;IAE9B,OAAO,EAAE,EAAE,EAAE,IAAI,CAAC,EAAE,EAAE,GAAG,IAAI,CAAC,IAAI,EAAE,EAAE,CAAC;AACzC,CAAC"}
@@ -0,0 +1,27 @@
1
+ import { type UseQueryResult } from '@tanstack/react-query';
2
+ import { type DocumentData } from 'firebase/firestore';
3
+ import type { FirestoreCollectionOptions, WithId } from './types';
4
+ /**
5
+ * Fetch all documents from a Firestore collection with optional realtime updates.
6
+ * Use this for small collections where you need all documents at once.
7
+ * For large collections, use useFirestoreInfinite or useFirestorePaginated.
8
+ *
9
+ * @example
10
+ * ```tsx
11
+ * // Fetch all channels in a project
12
+ * const { data: channels } = useFirestoreCollection<Channel>({
13
+ * collectionPath: `projects/${projectId}/channels`,
14
+ * queryKey: ['channels', projectId],
15
+ * constraints: [orderBy('createdAt', 'asc')],
16
+ * });
17
+ *
18
+ * // With realtime updates
19
+ * const { data: members } = useFirestoreCollection<Member>({
20
+ * collectionPath: `projects/${projectId}/members`,
21
+ * queryKey: ['members', projectId],
22
+ * subscribe: true,
23
+ * });
24
+ * ```
25
+ */
26
+ export declare function useFirestoreCollection<T extends DocumentData = DocumentData>({ collectionPath, queryKey, constraints, enabled, subscribe, staleTime, gcTime, select, }: FirestoreCollectionOptions<T>): UseQueryResult<WithId<T>[], Error>;
27
+ //# sourceMappingURL=use-firestore-collection.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-firestore-collection.d.ts","sourceRoot":"","sources":["../../src/firestore/use-firestore-collection.ts"],"names":[],"mappings":"AAGA,OAAO,EAA4B,KAAK,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACtF,OAAO,EAKL,KAAK,YAAY,EAClB,MAAM,oBAAoB,CAAC;AAE5B,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AAElE;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,sBAAsB,CAAC,CAAC,SAAS,YAAY,GAAG,YAAY,EAAE,EAC5E,cAAc,EACd,QAAQ,EACR,WAAgB,EAChB,OAAc,EACd,SAAiB,EACjB,SAAS,EACT,MAAM,EACN,MAAM,GACP,EAAE,0BAA0B,CAAC,CAAC,CAAC,GAAG,cAAc,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,KAAK,CAAC,CAsDpE"}
@@ -0,0 +1,74 @@
1
+ 'use client';
2
+ import { useEffect } from 'react';
3
+ import { useQuery, useQueryClient } from '@tanstack/react-query';
4
+ import { collection, query, getDocs, onSnapshot, } from 'firebase/firestore';
5
+ import { useFirestoreDb } from './context';
6
+ /**
7
+ * Fetch all documents from a Firestore collection with optional realtime updates.
8
+ * Use this for small collections where you need all documents at once.
9
+ * For large collections, use useFirestoreInfinite or useFirestorePaginated.
10
+ *
11
+ * @example
12
+ * ```tsx
13
+ * // Fetch all channels in a project
14
+ * const { data: channels } = useFirestoreCollection<Channel>({
15
+ * collectionPath: `projects/${projectId}/channels`,
16
+ * queryKey: ['channels', projectId],
17
+ * constraints: [orderBy('createdAt', 'asc')],
18
+ * });
19
+ *
20
+ * // With realtime updates
21
+ * const { data: members } = useFirestoreCollection<Member>({
22
+ * collectionPath: `projects/${projectId}/members`,
23
+ * queryKey: ['members', projectId],
24
+ * subscribe: true,
25
+ * });
26
+ * ```
27
+ */
28
+ export function useFirestoreCollection({ collectionPath, queryKey, constraints = [], enabled = true, subscribe = false, staleTime, gcTime, select, }) {
29
+ const db = useFirestoreDb();
30
+ const queryClient = useQueryClient();
31
+ // Set up realtime subscription
32
+ useEffect(() => {
33
+ if (!subscribe || !enabled)
34
+ return;
35
+ const collectionRef = collection(db, collectionPath);
36
+ const q = constraints.length > 0
37
+ ? query(collectionRef, ...constraints)
38
+ : collectionRef;
39
+ const unsubscribe = onSnapshot(q, (snapshot) => {
40
+ const items = snapshot.docs.map((docSnap) => {
41
+ const rawData = docSnap.data();
42
+ // Include id in data passed to select, so it can be renamed/transformed
43
+ const dataWithId = { id: docSnap.id, ...rawData };
44
+ const data = select ? select(dataWithId) : dataWithId;
45
+ return data;
46
+ });
47
+ queryClient.setQueryData(queryKey, items);
48
+ }, (error) => {
49
+ console.error('[useFirestoreCollection] Subscription error:', error);
50
+ });
51
+ return () => unsubscribe();
52
+ }, [db, collectionPath, queryKey, constraints, enabled, subscribe, select, queryClient]);
53
+ return useQuery({
54
+ queryKey,
55
+ queryFn: async () => {
56
+ const collectionRef = collection(db, collectionPath);
57
+ const q = constraints.length > 0
58
+ ? query(collectionRef, ...constraints)
59
+ : collectionRef;
60
+ const snapshot = await getDocs(q);
61
+ return snapshot.docs.map((docSnap) => {
62
+ const rawData = docSnap.data();
63
+ // Include id in data passed to select, so it can be renamed/transformed
64
+ const dataWithId = { id: docSnap.id, ...rawData };
65
+ const data = select ? select(dataWithId) : dataWithId;
66
+ return data;
67
+ });
68
+ },
69
+ enabled: enabled && !subscribe,
70
+ staleTime: subscribe ? Infinity : staleTime,
71
+ gcTime,
72
+ });
73
+ }
74
+ //# sourceMappingURL=use-firestore-collection.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-firestore-collection.js","sourceRoot":"","sources":["../../src/firestore/use-firestore-collection.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,31 @@
1
+ import { type UseQueryResult } from '@tanstack/react-query';
2
+ import { type DocumentData } from 'firebase/firestore';
3
+ import type { FirestoreDocOptions, WithId } from './types';
4
+ /**
5
+ * Fetch a single Firestore document with optional realtime updates.
6
+ *
7
+ * @example
8
+ * ```tsx
9
+ * // Simple fetch
10
+ * const { data: user } = useFirestoreDoc<User>({
11
+ * docPath: `users/${userId}`,
12
+ * queryKey: ['user', userId],
13
+ * });
14
+ *
15
+ * // With realtime updates
16
+ * const { data: project } = useFirestoreDoc<Project>({
17
+ * docPath: `projects/${projectId}`,
18
+ * queryKey: ['project', projectId],
19
+ * subscribe: true,
20
+ * });
21
+ *
22
+ * // Conditional fetch
23
+ * const { data: profile } = useFirestoreDoc<Profile>({
24
+ * docPath: `profiles/${userId}`,
25
+ * queryKey: ['profile', userId],
26
+ * enabled: !!userId,
27
+ * });
28
+ * ```
29
+ */
30
+ export declare function useFirestoreDoc<T extends DocumentData = DocumentData>({ docPath, queryKey, enabled, subscribe, staleTime, gcTime, select, }: FirestoreDocOptions<T>): UseQueryResult<WithId<T> | null, Error>;
31
+ //# sourceMappingURL=use-firestore-doc.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-firestore-doc.d.ts","sourceRoot":"","sources":["../../src/firestore/use-firestore-doc.ts"],"names":[],"mappings":"AAGA,OAAO,EAA4B,KAAK,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACtF,OAAO,EAA2B,KAAK,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAEhF,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AAE3D;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAgB,eAAe,CAAC,CAAC,SAAS,YAAY,GAAG,YAAY,EAAE,EACrE,OAAO,EACP,QAAQ,EACR,OAAc,EACd,SAAiB,EACjB,SAAS,EACT,MAAM,EACN,MAAM,GACP,EAAE,mBAAmB,CAAC,CAAC,CAAC,GAAG,cAAc,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,IAAI,EAAE,KAAK,CAAC,CAkDlE"}
@@ -0,0 +1,75 @@
1
+ 'use client';
2
+ import { useEffect } from 'react';
3
+ import { useQuery, useQueryClient } from '@tanstack/react-query';
4
+ import { doc, getDoc, onSnapshot } from 'firebase/firestore';
5
+ import { useFirestoreDb } from './context';
6
+ /**
7
+ * Fetch a single Firestore document with optional realtime updates.
8
+ *
9
+ * @example
10
+ * ```tsx
11
+ * // Simple fetch
12
+ * const { data: user } = useFirestoreDoc<User>({
13
+ * docPath: `users/${userId}`,
14
+ * queryKey: ['user', userId],
15
+ * });
16
+ *
17
+ * // With realtime updates
18
+ * const { data: project } = useFirestoreDoc<Project>({
19
+ * docPath: `projects/${projectId}`,
20
+ * queryKey: ['project', projectId],
21
+ * subscribe: true,
22
+ * });
23
+ *
24
+ * // Conditional fetch
25
+ * const { data: profile } = useFirestoreDoc<Profile>({
26
+ * docPath: `profiles/${userId}`,
27
+ * queryKey: ['profile', userId],
28
+ * enabled: !!userId,
29
+ * });
30
+ * ```
31
+ */
32
+ export function useFirestoreDoc({ docPath, queryKey, enabled = true, subscribe = false, staleTime, gcTime, select, }) {
33
+ const db = useFirestoreDb();
34
+ const queryClient = useQueryClient();
35
+ // Set up realtime subscription
36
+ useEffect(() => {
37
+ if (!subscribe || !enabled)
38
+ return;
39
+ const docRef = doc(db, docPath);
40
+ const unsubscribe = onSnapshot(docRef, (snapshot) => {
41
+ if (snapshot.exists()) {
42
+ const rawData = snapshot.data();
43
+ // Include id in data passed to select, so it can be renamed/transformed
44
+ const dataWithId = { id: snapshot.id, ...rawData };
45
+ const data = select ? select(dataWithId) : dataWithId;
46
+ queryClient.setQueryData(queryKey, data);
47
+ }
48
+ else {
49
+ queryClient.setQueryData(queryKey, null);
50
+ }
51
+ }, (error) => {
52
+ console.error('[useFirestoreDoc] Subscription error:', error);
53
+ });
54
+ return () => unsubscribe();
55
+ }, [db, docPath, queryKey, enabled, subscribe, select, queryClient]);
56
+ return useQuery({
57
+ queryKey,
58
+ queryFn: async () => {
59
+ const docRef = doc(db, docPath);
60
+ const snapshot = await getDoc(docRef);
61
+ if (!snapshot.exists()) {
62
+ return null;
63
+ }
64
+ const rawData = snapshot.data();
65
+ // Include id in data passed to select, so it can be renamed/transformed
66
+ const dataWithId = { id: snapshot.id, ...rawData };
67
+ const data = select ? select(dataWithId) : dataWithId;
68
+ return data;
69
+ },
70
+ enabled: enabled && !subscribe, // Don't fetch if subscribing (snapshot handles it)
71
+ staleTime: subscribe ? Infinity : staleTime, // Realtime data is always fresh
72
+ gcTime,
73
+ });
74
+ }
75
+ //# sourceMappingURL=use-firestore-doc.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-firestore-doc.js","sourceRoot":"","sources":["../../src/firestore/use-firestore-doc.ts"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAEb,OAAO,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAClC,OAAO,EAAE,QAAQ,EAAE,cAAc,EAAuB,MAAM,uBAAuB,CAAC;AACtF,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,UAAU,EAAqB,MAAM,oBAAoB,CAAC;AAChF,OAAO,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAG3C;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,MAAM,UAAU,eAAe,CAAwC,EACrE,OAAO,EACP,QAAQ,EACR,OAAO,GAAG,IAAI,EACd,SAAS,GAAG,KAAK,EACjB,SAAS,EACT,MAAM,EACN,MAAM,GACiB;IACvB,MAAM,EAAE,GAAG,cAAc,EAAE,CAAC;IAC5B,MAAM,WAAW,GAAG,cAAc,EAAE,CAAC;IAErC,+BAA+B;IAC/B,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,CAAC,SAAS,IAAI,CAAC,OAAO;YAAE,OAAO;QAEnC,MAAM,MAAM,GAAG,GAAG,CAAC,EAAE,EAAE,OAAO,CAAC,CAAC;QAChC,MAAM,WAAW,GAAG,UAAU,CAC5B,MAAM,EACN,CAAC,QAAQ,EAAE,EAAE;YACX,IAAI,QAAQ,CAAC,MAAM,EAAE,EAAE,CAAC;gBACtB,MAAM,OAAO,GAAG,QAAQ,CAAC,IAAI,EAAE,CAAC;gBAChC,wEAAwE;gBACxE,MAAM,UAAU,GAAG,EAAE,EAAE,EAAE,QAAQ,CAAC,EAAE,EAAE,GAAG,OAAO,EAAE,CAAC;gBACnD,MAAM,IAAI,GAAG,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC;gBACtD,WAAW,CAAC,YAAY,CAAC,QAAQ,EAAE,IAAiB,CAAC,CAAC;YACxD,CAAC;iBAAM,CAAC;gBACN,WAAW,CAAC,YAAY,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;YAC3C,CAAC;QACH,CAAC,EACD,CAAC,KAAK,EAAE,EAAE;YACR,OAAO,CAAC,KAAK,CAAC,uCAAuC,EAAE,KAAK,CAAC,CAAC;QAChE,CAAC,CACF,CAAC;QAEF,OAAO,GAAG,EAAE,CAAC,WAAW,EAAE,CAAC;IAC7B,CAAC,EAAE,CAAC,EAAE,EAAE,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC;IAErE,OAAO,QAAQ,CAAC;QACd,QAAQ;QACR,OAAO,EAAE,KAAK,IAA+B,EAAE;YAC7C,MAAM,MAAM,GAAG,GAAG,CAAC,EAAE,EAAE,OAAO,CAAC,CAAC;YAChC,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,CAAC;YAEtC,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,EAAE,CAAC;gBACvB,OAAO,IAAI,CAAC;YACd,CAAC;YAED,MAAM,OAAO,GAAG,QAAQ,CAAC,IAAI,EAAE,CAAC;YAChC,wEAAwE;YACxE,MAAM,UAAU,GAAG,EAAE,EAAE,EAAE,QAAQ,CAAC,EAAE,EAAE,GAAG,OAAO,EAAE,CAAC;YACnD,MAAM,IAAI,GAAG,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC;YACtD,OAAO,IAAiB,CAAC;QAC3B,CAAC;QACD,OAAO,EAAE,OAAO,IAAI,CAAC,SAAS,EAAE,mDAAmD;QACnF,SAAS,EAAE,SAAS,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,SAAS,EAAE,gCAAgC;QAC7E,MAAM;KACP,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,55 @@
1
+ import { type UseInfiniteQueryResult } from '@tanstack/react-query';
2
+ import { type DocumentData, type DocumentSnapshot } from 'firebase/firestore';
3
+ import type { FirestoreInfiniteOptions, InfinitePage, WithId } from './types';
4
+ /**
5
+ * Infinite scroll pagination for Firestore collections.
6
+ * Automatically handles cursor-based pagination with React Query.
7
+ *
8
+ * @example
9
+ * ```tsx
10
+ * const {
11
+ * data,
12
+ * fetchNextPage,
13
+ * hasNextPage,
14
+ * isFetchingNextPage,
15
+ * isLoading,
16
+ * } = useFirestoreInfinite<Post>({
17
+ * collectionPath: 'posts',
18
+ * queryKey: ['posts', 'feed'],
19
+ * constraints: [
20
+ * where('status', '==', 'published'),
21
+ * orderBy('createdAt', 'desc'),
22
+ * ],
23
+ * pageSize: 20,
24
+ * });
25
+ *
26
+ * // Flatten pages for rendering
27
+ * const posts = data?.pages.flatMap(page => page.items) ?? [];
28
+ *
29
+ * // Load more on scroll
30
+ * <InfiniteScroll onLoadMore={fetchNextPage} hasMore={hasNextPage} />
31
+ * ```
32
+ */
33
+ export declare function useFirestoreInfinite<T extends DocumentData = DocumentData>({ collectionPath, queryKey, constraints, pageSize, enabled, staleTime, gcTime, select, }: FirestoreInfiniteOptions<T>): UseInfiniteQueryResult<{
34
+ pages: InfinitePage<T>[];
35
+ pageParams: (DocumentSnapshot | null)[];
36
+ }, Error>;
37
+ /**
38
+ * Helper to flatten infinite query pages into a single array.
39
+ *
40
+ * @example
41
+ * ```tsx
42
+ * const { data } = useFirestoreInfinite<Post>({ ... });
43
+ * const posts = flattenInfiniteData(data);
44
+ * ```
45
+ */
46
+ export declare function flattenInfiniteData<T>(data: {
47
+ pages: InfinitePage<T>[];
48
+ } | undefined): WithId<T>[];
49
+ /**
50
+ * Get total count of items across all loaded pages.
51
+ */
52
+ export declare function getInfiniteDataCount<T>(data: {
53
+ pages: InfinitePage<T>[];
54
+ } | undefined): number;
55
+ //# sourceMappingURL=use-firestore-infinite.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-firestore-infinite.d.ts","sourceRoot":"","sources":["../../src/firestore/use-firestore-infinite.ts"],"names":[],"mappings":"AAEA,OAAO,EAAoB,KAAK,sBAAsB,EAAE,MAAM,uBAAuB,CAAC;AACtF,OAAO,EAML,KAAK,YAAY,EACjB,KAAK,gBAAgB,EACtB,MAAM,oBAAoB,CAAC;AAE5B,OAAO,KAAK,EAAE,wBAAwB,EAAE,YAAY,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AAI9E;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,wBAAgB,oBAAoB,CAAC,CAAC,SAAS,YAAY,GAAG,YAAY,EAAE,EAC1E,cAAc,EACd,QAAQ,EACR,WAAgB,EAChB,QAA4B,EAC5B,OAAc,EACd,SAAS,EACT,MAAM,EACN,MAAM,GACP,EAAE,wBAAwB,CAAC,CAAC,CAAC,GAAG,sBAAsB,CAAC;IAAE,KAAK,EAAE,YAAY,CAAC,CAAC,CAAC,EAAE,CAAC;IAAC,UAAU,EAAE,CAAC,gBAAgB,GAAG,IAAI,CAAC,EAAE,CAAA;CAAE,EAAE,KAAK,CAAC,CA0CpI;AAED;;;;;;;;GAQG;AACH,wBAAgB,mBAAmB,CAAC,CAAC,EACnC,IAAI,EAAE;IAAE,KAAK,EAAE,YAAY,CAAC,CAAC,CAAC,EAAE,CAAA;CAAE,GAAG,SAAS,GAC7C,MAAM,CAAC,CAAC,CAAC,EAAE,CAGb;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,CAAC,EACpC,IAAI,EAAE;IAAE,KAAK,EAAE,YAAY,CAAC,CAAC,CAAC,EAAE,CAAA;CAAE,GAAG,SAAS,GAC7C,MAAM,CAGR"}
@@ -0,0 +1,96 @@
1
+ 'use client';
2
+ import { useInfiniteQuery } from '@tanstack/react-query';
3
+ import { collection, query, getDocs, limit, startAfter, } from 'firebase/firestore';
4
+ import { useFirestoreDb } from './context';
5
+ const DEFAULT_PAGE_SIZE = 20;
6
+ /**
7
+ * Infinite scroll pagination for Firestore collections.
8
+ * Automatically handles cursor-based pagination with React Query.
9
+ *
10
+ * @example
11
+ * ```tsx
12
+ * const {
13
+ * data,
14
+ * fetchNextPage,
15
+ * hasNextPage,
16
+ * isFetchingNextPage,
17
+ * isLoading,
18
+ * } = useFirestoreInfinite<Post>({
19
+ * collectionPath: 'posts',
20
+ * queryKey: ['posts', 'feed'],
21
+ * constraints: [
22
+ * where('status', '==', 'published'),
23
+ * orderBy('createdAt', 'desc'),
24
+ * ],
25
+ * pageSize: 20,
26
+ * });
27
+ *
28
+ * // Flatten pages for rendering
29
+ * const posts = data?.pages.flatMap(page => page.items) ?? [];
30
+ *
31
+ * // Load more on scroll
32
+ * <InfiniteScroll onLoadMore={fetchNextPage} hasMore={hasNextPage} />
33
+ * ```
34
+ */
35
+ export function useFirestoreInfinite({ collectionPath, queryKey, constraints = [], pageSize = DEFAULT_PAGE_SIZE, enabled = true, staleTime, gcTime, select, }) {
36
+ const db = useFirestoreDb();
37
+ return useInfiniteQuery({
38
+ queryKey,
39
+ queryFn: async ({ pageParam }) => {
40
+ const collectionRef = collection(db, collectionPath);
41
+ // Build query with constraints
42
+ const queryConstraints = [
43
+ ...constraints,
44
+ ...(pageParam ? [startAfter(pageParam)] : []),
45
+ limit(pageSize),
46
+ ];
47
+ const q = query(collectionRef, ...queryConstraints);
48
+ const snapshot = await getDocs(q);
49
+ const items = snapshot.docs.map((docSnap) => {
50
+ const rawData = docSnap.data();
51
+ // Include id in data passed to select, so it can be renamed/transformed
52
+ const dataWithId = { id: docSnap.id, ...rawData };
53
+ const data = select ? select(dataWithId) : dataWithId;
54
+ return data;
55
+ });
56
+ return {
57
+ items,
58
+ lastDoc: snapshot.docs[snapshot.docs.length - 1] ?? null,
59
+ size: snapshot.docs.length,
60
+ };
61
+ },
62
+ initialPageParam: null,
63
+ getNextPageParam: (lastPage) => {
64
+ // If we got fewer items than requested, there are no more pages
65
+ if (lastPage.size < pageSize)
66
+ return undefined;
67
+ return lastPage.lastDoc;
68
+ },
69
+ enabled,
70
+ staleTime,
71
+ gcTime,
72
+ });
73
+ }
74
+ /**
75
+ * Helper to flatten infinite query pages into a single array.
76
+ *
77
+ * @example
78
+ * ```tsx
79
+ * const { data } = useFirestoreInfinite<Post>({ ... });
80
+ * const posts = flattenInfiniteData(data);
81
+ * ```
82
+ */
83
+ export function flattenInfiniteData(data) {
84
+ if (!data)
85
+ return [];
86
+ return data.pages.flatMap((page) => page.items);
87
+ }
88
+ /**
89
+ * Get total count of items across all loaded pages.
90
+ */
91
+ export function getInfiniteDataCount(data) {
92
+ if (!data)
93
+ return 0;
94
+ return data.pages.reduce((sum, page) => sum + page.items.length, 0);
95
+ }
96
+ //# sourceMappingURL=use-firestore-infinite.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-firestore-infinite.js","sourceRoot":"","sources":["../../src/firestore/use-firestore-infinite.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,38 @@
1
+ import { type QueryKey, type UseMutationResult } from '@tanstack/react-query';
2
+ import { type DocumentData } from 'firebase/firestore';
3
+ import type { FirestoreMutationOptions, FirestoreBatchOptions, MutationOperation } from './types';
4
+ interface SetResult<T> {
5
+ id: string;
6
+ data: T;
7
+ }
8
+ export declare function useFirestoreSet<T extends DocumentData>({ invalidateKeys, }?: Pick<FirestoreMutationOptions<T>, 'invalidateKeys'>): UseMutationResult<SetResult<T>, Error, {
9
+ docPath: string;
10
+ data: T;
11
+ merge?: boolean;
12
+ }>;
13
+ export declare function useFirestoreUpdate<T extends DocumentData>({ invalidateKeys, optimistic, }?: FirestoreMutationOptions<T>): UseMutationResult<Partial<T>, Error, {
14
+ docPath: string;
15
+ data: Partial<T>;
16
+ }, {
17
+ previousData: T | undefined;
18
+ } | undefined>;
19
+ export declare function useFirestoreDelete<T = unknown>({ invalidateKeys, optimistic, }?: {
20
+ invalidateKeys?: readonly QueryKey[];
21
+ optimistic?: {
22
+ queryKey: QueryKey;
23
+ updater: (oldData: T | undefined, docPath: string) => T;
24
+ };
25
+ }): UseMutationResult<string, Error, {
26
+ docPath: string;
27
+ }, {
28
+ previousData: T | undefined;
29
+ } | undefined>;
30
+ interface BatchResult {
31
+ committed: number;
32
+ batches: number;
33
+ }
34
+ export declare function useFirestoreBatch({ invalidateKeys, batchSize, }?: FirestoreBatchOptions): UseMutationResult<BatchResult, Error, {
35
+ operations: MutationOperation[];
36
+ }>;
37
+ export {};
38
+ //# sourceMappingURL=use-firestore-mutations.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-firestore-mutations.d.ts","sourceRoot":"","sources":["../../src/firestore/use-firestore-mutations.ts"],"names":[],"mappings":"AAEA,OAAO,EAA+B,KAAK,QAAQ,EAAE,KAAK,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAC3G,OAAO,EAML,KAAK,YAAY,EAClB,MAAM,oBAAoB,CAAC;AAE5B,OAAO,KAAK,EAAE,wBAAwB,EAAE,qBAAqB,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAC;AAIlG,UAAU,SAAS,CAAC,CAAC;IACnB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,CAAC,CAAC;CACT;AAED,wBAAgB,eAAe,CAAC,CAAC,SAAS,YAAY,EAAE,EACtD,cAAmB,GACpB,GAAE,IAAI,CAAC,wBAAwB,CAAC,CAAC,CAAC,EAAE,gBAAgB,CAAM,GAAG,iBAAiB,CAC7E,SAAS,CAAC,CAAC,CAAC,EACZ,KAAK,EACL;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,CAAC,CAAC;IAAC,KAAK,CAAC,EAAE,OAAO,CAAA;CAAE,CAC9C,CAwBA;AAED,wBAAgB,kBAAkB,CAAC,CAAC,SAAS,YAAY,EAAE,EACzD,cAAmB,EACnB,UAAU,GACX,GAAE,wBAAwB,CAAC,CAAC,CAAM,GAAG,iBAAiB,CACrD,OAAO,CAAC,CAAC,CAAC,EACV,KAAK,EACL;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC,CAAA;CAAE,EACrC;IAAE,YAAY,EAAE,CAAC,GAAG,SAAS,CAAA;CAAE,GAAG,SAAS,CAC5C,CA0CA;AAED,wBAAgB,kBAAkB,CAAC,CAAC,GAAG,OAAO,EAAE,EAC9C,cAAmB,EACnB,UAAU,GACX,GAAE;IACD,cAAc,CAAC,EAAE,SAAS,QAAQ,EAAE,CAAC;IACrC,UAAU,CAAC,EAAE;QACX,QAAQ,EAAE,QAAQ,CAAC;QACnB,OAAO,EAAE,CAAC,OAAO,EAAE,CAAC,GAAG,SAAS,EAAE,OAAO,EAAE,MAAM,KAAK,CAAC,CAAC;KACzD,CAAC;CACE,GAAG,iBAAiB,CACxB,MAAM,EACN,KAAK,EACL;IAAE,OAAO,EAAE,MAAM,CAAA;CAAE,EACnB;IAAE,YAAY,EAAE,CAAC,GAAG,SAAS,CAAA;CAAE,GAAG,SAAS,CAC5C,CAoCA;AAED,UAAU,WAAW;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,wBAAgB,iBAAiB,CAAC,EAChC,cAAmB,EACnB,SAA8B,GAC/B,GAAE,qBAA0B,GAAG,iBAAiB,CAC/C,WAAW,EACX,KAAK,EACL;IAAE,UAAU,EAAE,iBAAiB,EAAE,CAAA;CAAE,CACpC,CAuDA"}
@@ -0,0 +1,132 @@
1
+ 'use client';
2
+ import { useMutation, useQueryClient } from '@tanstack/react-query';
3
+ import { doc, setDoc, updateDoc, deleteDoc, writeBatch, } from 'firebase/firestore';
4
+ import { useFirestoreDb } from './context';
5
+ const DEFAULT_BATCH_SIZE = 450;
6
+ export function useFirestoreSet({ invalidateKeys = [], } = {}) {
7
+ const db = useFirestoreDb();
8
+ const queryClient = useQueryClient();
9
+ return useMutation({
10
+ mutationFn: async ({ docPath, data, merge = false, }) => {
11
+ const docRef = doc(db, docPath);
12
+ await setDoc(docRef, data, { merge });
13
+ return { id: docRef.id, data };
14
+ },
15
+ onSuccess: () => {
16
+ invalidateKeys.forEach((key) => {
17
+ queryClient.invalidateQueries({ queryKey: key });
18
+ });
19
+ },
20
+ });
21
+ }
22
+ export function useFirestoreUpdate({ invalidateKeys = [], optimistic, } = {}) {
23
+ const db = useFirestoreDb();
24
+ const queryClient = useQueryClient();
25
+ return useMutation({
26
+ mutationFn: async ({ docPath, data, }) => {
27
+ const docRef = doc(db, docPath);
28
+ await updateDoc(docRef, data);
29
+ return data;
30
+ },
31
+ onMutate: async ({ data }) => {
32
+ if (!optimistic)
33
+ return undefined;
34
+ await queryClient.cancelQueries({ queryKey: optimistic.queryKey });
35
+ const previousData = queryClient.getQueryData(optimistic.queryKey);
36
+ queryClient.setQueryData(optimistic.queryKey, (old) => optimistic.updater(old, data));
37
+ return { previousData };
38
+ },
39
+ onError: (_error, _variables, context) => {
40
+ if (optimistic && context?.previousData !== undefined) {
41
+ queryClient.setQueryData(optimistic.queryKey, context.previousData);
42
+ }
43
+ },
44
+ onSettled: () => {
45
+ invalidateKeys.forEach((key) => {
46
+ queryClient.invalidateQueries({ queryKey: key });
47
+ });
48
+ if (optimistic) {
49
+ queryClient.invalidateQueries({ queryKey: optimistic.queryKey });
50
+ }
51
+ },
52
+ });
53
+ }
54
+ export function useFirestoreDelete({ invalidateKeys = [], optimistic, } = {}) {
55
+ const db = useFirestoreDb();
56
+ const queryClient = useQueryClient();
57
+ return useMutation({
58
+ mutationFn: async ({ docPath }) => {
59
+ const docRef = doc(db, docPath);
60
+ await deleteDoc(docRef);
61
+ return docPath;
62
+ },
63
+ onMutate: async ({ docPath }) => {
64
+ if (!optimistic)
65
+ return undefined;
66
+ await queryClient.cancelQueries({ queryKey: optimistic.queryKey });
67
+ const previousData = queryClient.getQueryData(optimistic.queryKey);
68
+ queryClient.setQueryData(optimistic.queryKey, (old) => optimistic.updater(old, docPath));
69
+ return { previousData };
70
+ },
71
+ onError: (_error, _variables, context) => {
72
+ if (optimistic && context?.previousData !== undefined) {
73
+ queryClient.setQueryData(optimistic.queryKey, context.previousData);
74
+ }
75
+ },
76
+ onSettled: () => {
77
+ invalidateKeys.forEach((key) => {
78
+ queryClient.invalidateQueries({ queryKey: key });
79
+ });
80
+ if (optimistic) {
81
+ queryClient.invalidateQueries({ queryKey: optimistic.queryKey });
82
+ }
83
+ },
84
+ });
85
+ }
86
+ export function useFirestoreBatch({ invalidateKeys = [], batchSize = DEFAULT_BATCH_SIZE, } = {}) {
87
+ const db = useFirestoreDb();
88
+ const queryClient = useQueryClient();
89
+ return useMutation({
90
+ mutationFn: async ({ operations, }) => {
91
+ const chunks = [];
92
+ for (let i = 0; i < operations.length; i += batchSize) {
93
+ chunks.push(operations.slice(i, i + batchSize));
94
+ }
95
+ let totalCommitted = 0;
96
+ for (const chunk of chunks) {
97
+ const batch = writeBatch(db);
98
+ for (const op of chunk) {
99
+ const docRef = doc(db, op.docPath);
100
+ switch (op.type) {
101
+ case 'set':
102
+ if (op.merge) {
103
+ batch.set(docRef, op.data, { merge: true });
104
+ }
105
+ else {
106
+ batch.set(docRef, op.data);
107
+ }
108
+ break;
109
+ case 'update':
110
+ batch.update(docRef, op.data);
111
+ break;
112
+ case 'delete':
113
+ batch.delete(docRef);
114
+ break;
115
+ }
116
+ }
117
+ await batch.commit();
118
+ totalCommitted += chunk.length;
119
+ }
120
+ return {
121
+ committed: totalCommitted,
122
+ batches: chunks.length,
123
+ };
124
+ },
125
+ onSuccess: () => {
126
+ invalidateKeys.forEach((key) => {
127
+ queryClient.invalidateQueries({ queryKey: key });
128
+ });
129
+ },
130
+ });
131
+ }
132
+ //# sourceMappingURL=use-firestore-mutations.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-firestore-mutations.js","sourceRoot":"","sources":["../../src/firestore/use-firestore-mutations.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,44 @@
1
+ import { type UseQueryResult } from '@tanstack/react-query';
2
+ import { type DocumentData } from 'firebase/firestore';
3
+ import type { FirestorePaginatedOptions, WithId } from './types';
4
+ /**
5
+ * Return type for useFirestorePaginated hook
6
+ */
7
+ export type UseFirestorePaginatedResult<T> = UseQueryResult<WithId<T>[], Error> & {
8
+ page: number;
9
+ pageSize: number;
10
+ hasNextPage: boolean;
11
+ hasPrevPage: boolean;
12
+ setPage: (page: number) => void;
13
+ nextPage: () => void;
14
+ prevPage: () => void;
15
+ resetToFirstPage: () => void;
16
+ };
17
+ /**
18
+ * Page-based pagination for Firestore collections.
19
+ * Supports navigating to specific pages (1, 2, 3...) rather than infinite scroll.
20
+ *
21
+ * @example
22
+ * ```tsx
23
+ * const {
24
+ * data,
25
+ * page,
26
+ * setPage,
27
+ * hasNextPage,
28
+ * hasPrevPage,
29
+ * isLoading,
30
+ * } = useFirestorePaginated<Task>({
31
+ * collectionPath: 'tasks',
32
+ * queryKey: ['tasks', 'list'],
33
+ * constraints: [where('status', '==', 'active'), orderBy('createdAt', 'desc')],
34
+ * pageSize: 10,
35
+ * });
36
+ *
37
+ * // Render pagination controls
38
+ * <button onClick={() => setPage(page - 1)} disabled={!hasPrevPage}>Previous</button>
39
+ * <span>Page {page}</span>
40
+ * <button onClick={() => setPage(page + 1)} disabled={!hasNextPage}>Next</button>
41
+ * ```
42
+ */
43
+ export declare function useFirestorePaginated<T extends DocumentData = DocumentData>({ collectionPath, queryKey, constraints, pageSize, initialPage, enabled, staleTime, gcTime, select, }: FirestorePaginatedOptions<T>): UseFirestorePaginatedResult<T>;
44
+ //# sourceMappingURL=use-firestore-paginated.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-firestore-paginated.d.ts","sourceRoot":"","sources":["../../src/firestore/use-firestore-paginated.ts"],"names":[],"mappings":"AAGA,OAAO,EAA4B,KAAK,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACtF,OAAO,EAML,KAAK,YAAY,EAElB,MAAM,oBAAoB,CAAC;AAE5B,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AAIjE;;GAEG;AACH,MAAM,MAAM,2BAA2B,CAAC,CAAC,IAAI,cAAc,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,KAAK,CAAC,GAAG;IAChF,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,OAAO,CAAC;IACrB,WAAW,EAAE,OAAO,CAAC;IACrB,OAAO,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAChC,QAAQ,EAAE,MAAM,IAAI,CAAC;IACrB,QAAQ,EAAE,MAAM,IAAI,CAAC;IACrB,gBAAgB,EAAE,MAAM,IAAI,CAAC;CAC9B,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAgB,qBAAqB,CAAC,CAAC,SAAS,YAAY,GAAG,YAAY,EAAE,EAC3E,cAAc,EACd,QAAQ,EACR,WAAgB,EAChB,QAA4B,EAC5B,WAAe,EACf,OAAc,EACd,SAAS,EACT,MAAM,EACN,MAAM,GACP,EAAE,yBAAyB,CAAC,CAAC,CAAC,GAAG,2BAA2B,CAAC,CAAC,CAAC,CAmG/D"}
@@ -0,0 +1,117 @@
1
+ 'use client';
2
+ import { useState, useCallback, useMemo } from 'react';
3
+ import { useQuery, useQueryClient } from '@tanstack/react-query';
4
+ import { collection, query, getDocs, limit, startAfter, } from 'firebase/firestore';
5
+ import { useFirestoreDb } from './context';
6
+ const DEFAULT_PAGE_SIZE = 10;
7
+ /**
8
+ * Page-based pagination for Firestore collections.
9
+ * Supports navigating to specific pages (1, 2, 3...) rather than infinite scroll.
10
+ *
11
+ * @example
12
+ * ```tsx
13
+ * const {
14
+ * data,
15
+ * page,
16
+ * setPage,
17
+ * hasNextPage,
18
+ * hasPrevPage,
19
+ * isLoading,
20
+ * } = useFirestorePaginated<Task>({
21
+ * collectionPath: 'tasks',
22
+ * queryKey: ['tasks', 'list'],
23
+ * constraints: [where('status', '==', 'active'), orderBy('createdAt', 'desc')],
24
+ * pageSize: 10,
25
+ * });
26
+ *
27
+ * // Render pagination controls
28
+ * <button onClick={() => setPage(page - 1)} disabled={!hasPrevPage}>Previous</button>
29
+ * <span>Page {page}</span>
30
+ * <button onClick={() => setPage(page + 1)} disabled={!hasNextPage}>Next</button>
31
+ * ```
32
+ */
33
+ export function useFirestorePaginated({ collectionPath, queryKey, constraints = [], pageSize = DEFAULT_PAGE_SIZE, initialPage = 1, enabled = true, staleTime, gcTime, select, }) {
34
+ const db = useFirestoreDb();
35
+ const queryClient = useQueryClient();
36
+ const [page, setPageInternal] = useState(initialPage);
37
+ const [cursors, setCursors] = useState(new Map());
38
+ const [hasMore, setHasMore] = useState(true);
39
+ // Create a stable query key that includes the page
40
+ const pageQueryKey = useMemo(() => [...queryKey, 'page', page], [queryKey, page]);
41
+ const queryResult = useQuery({
42
+ queryKey: pageQueryKey,
43
+ queryFn: async () => {
44
+ const collectionRef = collection(db, collectionPath);
45
+ // Get cursor for current page (if not page 1)
46
+ const cursor = page > 1 ? cursors.get(page - 1) : undefined;
47
+ // Build query
48
+ const queryConstraints = [
49
+ ...constraints,
50
+ ...(cursor ? [startAfter(cursor)] : []),
51
+ limit(pageSize),
52
+ ];
53
+ const q = query(collectionRef, ...queryConstraints);
54
+ const snapshot = await getDocs(q);
55
+ // Store the last doc as cursor for next page
56
+ if (snapshot.docs.length > 0) {
57
+ const lastDoc = snapshot.docs[snapshot.docs.length - 1];
58
+ setCursors((prev) => {
59
+ const next = new Map(prev);
60
+ next.set(page, lastDoc);
61
+ return next;
62
+ });
63
+ }
64
+ // Determine if there are more pages
65
+ setHasMore(snapshot.docs.length === pageSize);
66
+ return snapshot.docs.map((docSnap) => {
67
+ const rawData = docSnap.data();
68
+ // Include id in data passed to select, so it can be renamed/transformed
69
+ const dataWithId = { id: docSnap.id, ...rawData };
70
+ const data = select ? select(dataWithId) : dataWithId;
71
+ return data;
72
+ });
73
+ },
74
+ enabled,
75
+ staleTime,
76
+ gcTime,
77
+ });
78
+ const setPage = useCallback((newPage) => {
79
+ if (newPage < 1)
80
+ return;
81
+ // Can only go forward one page at a time if cursor doesn't exist
82
+ if (newPage > page + 1 && !cursors.has(newPage - 1)) {
83
+ console.warn('[useFirestorePaginated] Cannot skip pages. Navigate sequentially.');
84
+ return;
85
+ }
86
+ setPageInternal(newPage);
87
+ }, [page, cursors]);
88
+ const nextPage = useCallback(() => {
89
+ if (hasMore)
90
+ setPage(page + 1);
91
+ }, [page, hasMore, setPage]);
92
+ const prevPage = useCallback(() => {
93
+ if (page > 1)
94
+ setPage(page - 1);
95
+ }, [page, setPage]);
96
+ const resetToFirstPage = useCallback(() => {
97
+ setCursors(new Map());
98
+ setPageInternal(1);
99
+ setHasMore(true);
100
+ // Invalidate all cached pages
101
+ queryClient.invalidateQueries({ queryKey, exact: false });
102
+ }, [queryClient, queryKey]);
103
+ return {
104
+ ...queryResult,
105
+ // Pagination state
106
+ page,
107
+ pageSize,
108
+ hasNextPage: hasMore,
109
+ hasPrevPage: page > 1,
110
+ // Navigation functions
111
+ setPage,
112
+ nextPage,
113
+ prevPage,
114
+ resetToFirstPage,
115
+ };
116
+ }
117
+ //# sourceMappingURL=use-firestore-paginated.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-firestore-paginated.js","sourceRoot":"","sources":["../../src/firestore/use-firestore-paginated.ts"],"names":[],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -5,4 +5,6 @@ export type { QueryKey } from './keys';
5
5
  export { invalidateByPrefix, removeByPrefix, updateQueryData } from './cache-helpers';
6
6
  export { TTTQueryProvider } from './provider';
7
7
  export type { TTTQueryProviderProps } from './provider';
8
+ export { FirestoreProvider, useFirestoreDb, useFirestoreDoc, useFirestoreCollection, useFirestoreInfinite, useFirestorePaginated, useFirestoreSet, useFirestoreUpdate, useFirestoreDelete, useFirestoreBatch, flattenInfiniteData, getInfiniteDataCount, docWithId, } from './firestore';
9
+ export type { FirestoreProviderProps, WithId, FirestoreBaseOptions, FirestoreDocOptions, FirestoreCollectionOptions, FirestoreInfiniteOptions, FirestorePaginatedOptions, InfinitePage, PaginatedResult, MutationOperation, FirestoreMutationOptions, FirestoreBatchOptions, } from './firestore';
8
10
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AACtD,YAAY,EAAE,2BAA2B,EAAE,MAAM,gBAAgB,CAAC;AAElE,OAAO,EAAE,IAAI,EAAE,cAAc,EAAE,MAAM,QAAQ,CAAC;AAC9C,YAAY,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAC;AAEvC,OAAO,EAAE,kBAAkB,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAEtF,OAAO,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAC9C,YAAY,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AACtD,YAAY,EAAE,2BAA2B,EAAE,MAAM,gBAAgB,CAAC;AAGlE,OAAO,EAAE,IAAI,EAAE,cAAc,EAAE,MAAM,QAAQ,CAAC;AAC9C,YAAY,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAC;AAGvC,OAAO,EAAE,kBAAkB,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAGtF,OAAO,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAC9C,YAAY,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAC;AAGxD,OAAO,EAEL,iBAAiB,EACjB,cAAc,EAEd,eAAe,EACf,sBAAsB,EACtB,oBAAoB,EACpB,qBAAqB,EAErB,eAAe,EACf,kBAAkB,EAClB,kBAAkB,EAClB,iBAAiB,EAEjB,mBAAmB,EACnB,oBAAoB,EACpB,SAAS,GACV,MAAM,aAAa,CAAC;AAErB,YAAY,EAEV,sBAAsB,EAEtB,MAAM,EACN,oBAAoB,EACpB,mBAAmB,EACnB,0BAA0B,EAC1B,wBAAwB,EACxB,yBAAyB,EACzB,YAAY,EACZ,eAAe,EACf,iBAAiB,EACjB,wBAAwB,EACxB,qBAAqB,GACtB,MAAM,aAAa,CAAC"}
package/dist/index.js CHANGED
@@ -1,5 +1,19 @@
1
+ // Query Client
1
2
  export { createTTTQueryClient } from './query-client';
3
+ // Query Keys
2
4
  export { keys, createKeyScope } from './keys';
5
+ // Cache Helpers
3
6
  export { invalidateByPrefix, removeByPrefix, updateQueryData } from './cache-helpers';
7
+ // Provider
4
8
  export { TTTQueryProvider } from './provider';
9
+ // Firestore Integration
10
+ export {
11
+ // Provider
12
+ FirestoreProvider, useFirestoreDb,
13
+ // Query Hooks
14
+ useFirestoreDoc, useFirestoreCollection, useFirestoreInfinite, useFirestorePaginated,
15
+ // Mutation Hooks
16
+ useFirestoreSet, useFirestoreUpdate, useFirestoreDelete, useFirestoreBatch,
17
+ // Helpers
18
+ flattenInfiniteData, getInfiniteDataCount, docWithId, } from './firestore';
5
19
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AAGtD,OAAO,EAAE,IAAI,EAAE,cAAc,EAAE,MAAM,QAAQ,CAAC;AAG9C,OAAO,EAAE,kBAAkB,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAEtF,OAAO,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,eAAe;AACf,OAAO,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AAGtD,aAAa;AACb,OAAO,EAAE,IAAI,EAAE,cAAc,EAAE,MAAM,QAAQ,CAAC;AAG9C,gBAAgB;AAChB,OAAO,EAAE,kBAAkB,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAEtF,WAAW;AACX,OAAO,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAG9C,wBAAwB;AACxB,OAAO;AACL,WAAW;AACX,iBAAiB,EACjB,cAAc;AACd,cAAc;AACd,eAAe,EACf,sBAAsB,EACtB,oBAAoB,EACpB,qBAAqB;AACrB,iBAAiB;AACjB,eAAe,EACf,kBAAkB,EAClB,kBAAkB,EAClB,iBAAiB;AACjB,UAAU;AACV,mBAAmB,EACnB,oBAAoB,EACpB,SAAS,GACV,MAAM,aAAa,CAAC"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@ttt-productions/query-core",
3
- "version": "0.2.1",
4
- "description": "Shared TanStack Query (React Query) client defaults + query key helpers for TTT Productions apps",
3
+ "version": "0.3.2",
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",
7
7
  "url": "git+https://github.com/ttt-productions/ttt-packages.git",
@@ -29,13 +29,20 @@
29
29
  },
30
30
  "peerDependencies": {
31
31
  "@tanstack/react-query": ">=5.0.0",
32
- "react": ">=19.0.0",
33
- "react-dom": ">=19.0.0"
32
+ "firebase": ">=10.0.0",
33
+ "react": ">=18.0.0",
34
+ "react-dom": ">=18.0.0"
35
+ },
36
+ "peerDependenciesMeta": {
37
+ "firebase": {
38
+ "optional": true
39
+ }
34
40
  },
35
41
  "devDependencies": {
36
42
  "@tanstack/react-query": "^5.0.0",
37
43
  "@types/react": "^19.0.0",
38
44
  "@types/react-dom": "^19.0.0",
45
+ "firebase": "^11.0.0",
39
46
  "react": "^19.2.0",
40
47
  "react-dom": "^19.2.0",
41
48
  "typescript": "^5.8.3"