@ttt-productions/query-core 0.14.24 → 0.14.26
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/react/callables/create-callables.d.ts +3 -4
- package/dist/react/callables/create-callables.d.ts.map +1 -1
- package/dist/react/callables/create-callables.js.map +1 -1
- package/dist/react/firestore/stable-inputs.d.ts +2 -0
- package/dist/react/firestore/stable-inputs.d.ts.map +1 -0
- package/dist/react/firestore/stable-inputs.js +11 -0
- package/dist/react/firestore/stable-inputs.js.map +1 -0
- package/dist/react/firestore/use-firestore-collection.d.ts.map +1 -1
- package/dist/react/firestore/use-firestore-collection.js +12 -8
- package/dist/react/firestore/use-firestore-collection.js.map +1 -1
- package/dist/react/firestore/use-firestore-doc.d.ts.map +1 -1
- package/dist/react/firestore/use-firestore-doc.js +10 -7
- package/dist/react/firestore/use-firestore-doc.js.map +1 -1
- package/dist/react/firestore/use-firestore-live-infinite.d.ts.map +1 -1
- package/dist/react/firestore/use-firestore-live-infinite.js +19 -5
- package/dist/react/firestore/use-firestore-live-infinite.js.map +1 -1
- package/dist/react/firestore/use-firestore-mutations.d.ts +6 -5
- package/dist/react/firestore/use-firestore-mutations.d.ts.map +1 -1
- package/dist/react/firestore/use-firestore-mutations.js.map +1 -1
- package/dist/react/firestore/use-firestore-paginated.d.ts.map +1 -1
- package/dist/react/firestore/use-firestore-paginated.js +8 -9
- package/dist/react/firestore/use-firestore-paginated.js.map +1 -1
- package/dist/react/firestore/useBatchFirestoreDocs.d.ts +2 -2
- package/dist/react/firestore/useBatchFirestoreDocs.d.ts.map +1 -1
- package/dist/react/firestore/useBatchFirestoreDocs.js +1 -0
- package/dist/react/firestore/useBatchFirestoreDocs.js.map +1 -1
- package/dist/react/index.d.ts +1 -1
- package/dist/react/index.d.ts.map +1 -1
- package/dist/react/index.js.map +1 -1
- package/dist/react/session-mutation.d.ts +17 -2
- package/dist/react/session-mutation.d.ts.map +1 -1
- package/dist/react/session-mutation.js +38 -13
- package/dist/react/session-mutation.js.map +1 -1
- package/package.json +2 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-firestore-mutations.js","sourceRoot":"","sources":["../../../src/react/firestore/use-firestore-mutations.ts"],"names":[],"mappings":"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","sourcesContent":["'use client';\n\nimport { useQueryClient, type QueryKey, type UseMutationResult } from '@tanstack/react-query';\nimport {\n doc,\n setDoc,\n updateDoc,\n deleteDoc,\n writeBatch,\n type DocumentData,\n} from 'firebase/firestore';\nimport { useFirestoreDb } from './context.js';\nimport { useSessionMutation } from '../session-mutation.js';\nimport type { FirestoreMutationOptions, FirestoreBatchOptions } from '../../firestore/types.js';\nimport type { MutationOperation } from './types.js';\n\nconst DEFAULT_BATCH_SIZE = 450;\n\ninterface SetResult<T> {\n id: string;\n data: T;\n}\n\nexport function useFirestoreSet<T extends DocumentData>({\n invalidateKeys = [],\n}: Pick<FirestoreMutationOptions<T>, 'invalidateKeys'> = {}): UseMutationResult<\n SetResult<T>,\n Error,\n { docPath: string; data: T; merge?: boolean }\n> {\n const db = useFirestoreDb();\n const queryClient = useQueryClient();\n\n return useSessionMutation({\n mutationFn: async ({\n docPath,\n data,\n merge = false,\n }: {\n docPath: string;\n data: T;\n merge?: boolean;\n }) => {\n const docRef = doc(db, docPath);\n await setDoc(docRef, data, { merge });\n return { id: docRef.id, data };\n },\n onSuccess: () => {\n invalidateKeys.forEach((key) => {\n queryClient.invalidateQueries({ queryKey: key });\n });\n },\n });\n}\n\nexport function useFirestoreUpdate<T extends DocumentData>({\n invalidateKeys = [],\n optimistic,\n}: FirestoreMutationOptions<T> = {}): UseMutationResult<\n Partial<T>,\n Error,\n { docPath: string; data: Partial<T> },\n { previousData: T | undefined } | undefined\n> {\n const db = useFirestoreDb();\n const queryClient = useQueryClient();\n\n return useSessionMutation({\n mutationFn: async ({ docPath, data }: { docPath: string; data: Partial<T> }) => {\n const docRef = doc(db, docPath);\n await updateDoc(docRef, data as DocumentData);\n return data;\n },\n onMutate: async ({ data }) => {\n if (!optimistic) return undefined;\n\n await queryClient.cancelQueries({ queryKey: optimistic.queryKey });\n const previousData = queryClient.getQueryData<T>(optimistic.queryKey);\n\n queryClient.setQueryData<T>(optimistic.queryKey, (old) =>\n optimistic.updater(old, data as Partial<T>),\n );\n\n return { previousData };\n },\n onError: (_error, _variables, context) => {\n if (optimistic && context?.previousData !== undefined) {\n queryClient.setQueryData(optimistic.queryKey, context.previousData);\n }\n },\n onSettled: () => {\n invalidateKeys.forEach((key) => {\n queryClient.invalidateQueries({ queryKey: key });\n });\n if (optimistic) {\n queryClient.invalidateQueries({ queryKey: optimistic.queryKey });\n }\n },\n });\n}\n\nexport function useFirestoreDelete<T = unknown>({\n invalidateKeys = [],\n optimistic,\n}: {\n invalidateKeys?: readonly QueryKey[];\n optimistic?: {\n queryKey: QueryKey;\n updater: (oldData: T | undefined, docPath: string) => T;\n };\n} = {}): UseMutationResult<\n string,\n Error,\n { docPath: string },\n { previousData: T | undefined } | undefined\n> {\n const db = useFirestoreDb();\n const queryClient = useQueryClient();\n\n return useSessionMutation({\n mutationFn: async ({ docPath }: { docPath: string }) => {\n const docRef = doc(db, docPath);\n await deleteDoc(docRef);\n return docPath;\n },\n onMutate: async ({ docPath }) => {\n if (!optimistic) return undefined;\n\n await queryClient.cancelQueries({ queryKey: optimistic.queryKey });\n const previousData = queryClient.getQueryData<T>(optimistic.queryKey);\n\n queryClient.setQueryData<T>(optimistic.queryKey, (old) => optimistic.updater(old, docPath));\n\n return { previousData };\n },\n onError: (_error, _variables, context) => {\n if (optimistic && context?.previousData !== undefined) {\n queryClient.setQueryData(optimistic.queryKey, context.previousData);\n }\n },\n onSettled: () => {\n invalidateKeys.forEach((key) => {\n queryClient.invalidateQueries({ queryKey: key });\n });\n if (optimistic) {\n queryClient.invalidateQueries({ queryKey: optimistic.queryKey });\n }\n },\n });\n}\n\ninterface BatchResult {\n committed: number;\n batches: number;\n}\n\nexport function useFirestoreBatch({\n invalidateKeys = [],\n batchSize = DEFAULT_BATCH_SIZE,\n}: FirestoreBatchOptions = {}): UseMutationResult<\n BatchResult,\n Error,\n { operations: MutationOperation[] }\n> {\n const db = useFirestoreDb();\n const queryClient = useQueryClient();\n\n return useSessionMutation({\n mutationFn: async ({ operations }: { operations: MutationOperation[] }) => {\n const chunks: MutationOperation[][] = [];\n for (let i = 0; i < operations.length; i += batchSize) {\n chunks.push(operations.slice(i, i + batchSize));\n }\n\n let totalCommitted = 0;\n\n for (const chunk of chunks) {\n const batch = writeBatch(db);\n\n for (const op of chunk) {\n const docRef = doc(db, op.docPath);\n\n switch (op.type) {\n case 'set':\n if (op.merge) {\n batch.set(docRef, op.data, { merge: true });\n } else {\n batch.set(docRef, op.data);\n }\n break;\n case 'update':\n batch.update(docRef, op.data);\n break;\n case 'delete':\n batch.delete(docRef);\n break;\n }\n }\n\n await batch.commit();\n totalCommitted += chunk.length;\n }\n\n return {\n committed: totalCommitted,\n batches: chunks.length,\n };\n },\n onSuccess: () => {\n invalidateKeys.forEach((key) => {\n queryClient.invalidateQueries({ queryKey: key });\n });\n },\n });\n}\n"]}
|
|
1
|
+
{"version":3,"file":"use-firestore-mutations.js","sourceRoot":"","sources":["../../../src/react/firestore/use-firestore-mutations.ts"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAEb,OAAO,EAAE,cAAc,EAAiB,MAAM,uBAAuB,CAAC;AACtE,OAAO,EACL,GAAG,EACH,MAAM,EACN,SAAS,EACT,SAAS,EACT,UAAU,GAEX,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,EAAE,kBAAkB,EAA8B,MAAM,wBAAwB,CAAC;AAIxF,MAAM,kBAAkB,GAAG,GAAG,CAAC;AAO/B,MAAM,UAAU,eAAe,CAAyB,EACtD,cAAc,GAAG,EAAE,MACoC,EAAE;IAKzD,MAAM,EAAE,GAAG,cAAc,EAAE,CAAC;IAC5B,MAAM,WAAW,GAAG,cAAc,EAAE,CAAC;IAErC,OAAO,kBAAkB,CAAC;QACxB,UAAU,EAAE,KAAK,EAAE,EACjB,OAAO,EACP,IAAI,EACJ,KAAK,GAAG,KAAK,GAKd,EAAE,EAAE;YACH,MAAM,MAAM,GAAG,GAAG,CAAC,EAAE,EAAE,OAAO,CAAC,CAAC;YAChC,MAAM,MAAM,CAAC,MAAM,EAAE,IAAI,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC;YACtC,OAAO,EAAE,EAAE,EAAE,MAAM,CAAC,EAAE,EAAE,IAAI,EAAE,CAAC;QACjC,CAAC;QACD,SAAS,EAAE,GAAG,EAAE;YACd,cAAc,CAAC,OAAO,CAAC,CAAC,GAAG,EAAE,EAAE;gBAC7B,WAAW,CAAC,iBAAiB,CAAC,EAAE,QAAQ,EAAE,GAAG,EAAE,CAAC,CAAC;YACnD,CAAC,CAAC,CAAC;QACL,CAAC;KACF,CAAC,CAAC;AACL,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAyB,EACzD,cAAc,GAAG,EAAE,EACnB,UAAU,MACqB,EAAE;IAMjC,MAAM,EAAE,GAAG,cAAc,EAAE,CAAC;IAC5B,MAAM,WAAW,GAAG,cAAc,EAAE,CAAC;IAErC,OAAO,kBAAkB,CAAC;QACxB,UAAU,EAAE,KAAK,EAAE,EAAE,OAAO,EAAE,IAAI,EAAyC,EAAE,EAAE;YAC7E,MAAM,MAAM,GAAG,GAAG,CAAC,EAAE,EAAE,OAAO,CAAC,CAAC;YAChC,MAAM,SAAS,CAAC,MAAM,EAAE,IAAoB,CAAC,CAAC;YAC9C,OAAO,IAAI,CAAC;QACd,CAAC;QACD,QAAQ,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE;YAC3B,IAAI,CAAC,UAAU;gBAAE,OAAO,SAAS,CAAC;YAElC,MAAM,WAAW,CAAC,aAAa,CAAC,EAAE,QAAQ,EAAE,UAAU,CAAC,QAAQ,EAAE,CAAC,CAAC;YACnE,MAAM,YAAY,GAAG,WAAW,CAAC,YAAY,CAAI,UAAU,CAAC,QAAQ,CAAC,CAAC;YAEtE,WAAW,CAAC,YAAY,CAAI,UAAU,CAAC,QAAQ,EAAE,CAAC,GAAG,EAAE,EAAE,CACvD,UAAU,CAAC,OAAO,CAAC,GAAG,EAAE,IAAkB,CAAC,CAC5C,CAAC;YAEF,OAAO,EAAE,YAAY,EAAE,CAAC;QAC1B,CAAC;QACD,OAAO,EAAE,CAAC,MAAM,EAAE,UAAU,EAAE,OAAO,EAAE,EAAE;YACvC,IAAI,UAAU,IAAI,OAAO,EAAE,YAAY,KAAK,SAAS,EAAE,CAAC;gBACtD,WAAW,CAAC,YAAY,CAAC,UAAU,CAAC,QAAQ,EAAE,OAAO,CAAC,YAAY,CAAC,CAAC;YACtE,CAAC;QACH,CAAC;QACD,SAAS,EAAE,GAAG,EAAE;YACd,cAAc,CAAC,OAAO,CAAC,CAAC,GAAG,EAAE,EAAE;gBAC7B,WAAW,CAAC,iBAAiB,CAAC,EAAE,QAAQ,EAAE,GAAG,EAAE,CAAC,CAAC;YACnD,CAAC,CAAC,CAAC;YACH,IAAI,UAAU,EAAE,CAAC;gBACf,WAAW,CAAC,iBAAiB,CAAC,EAAE,QAAQ,EAAE,UAAU,CAAC,QAAQ,EAAE,CAAC,CAAC;YACnE,CAAC;QACH,CAAC;KACF,CAAC,CAAC;AACL,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAc,EAC9C,cAAc,GAAG,EAAE,EACnB,UAAU,MAOR,EAAE;IAMJ,MAAM,EAAE,GAAG,cAAc,EAAE,CAAC;IAC5B,MAAM,WAAW,GAAG,cAAc,EAAE,CAAC;IAErC,OAAO,kBAAkB,CAAC;QACxB,UAAU,EAAE,KAAK,EAAE,EAAE,OAAO,EAAuB,EAAE,EAAE;YACrD,MAAM,MAAM,GAAG,GAAG,CAAC,EAAE,EAAE,OAAO,CAAC,CAAC;YAChC,MAAM,SAAS,CAAC,MAAM,CAAC,CAAC;YACxB,OAAO,OAAO,CAAC;QACjB,CAAC;QACD,QAAQ,EAAE,KAAK,EAAE,EAAE,OAAO,EAAE,EAAE,EAAE;YAC9B,IAAI,CAAC,UAAU;gBAAE,OAAO,SAAS,CAAC;YAElC,MAAM,WAAW,CAAC,aAAa,CAAC,EAAE,QAAQ,EAAE,UAAU,CAAC,QAAQ,EAAE,CAAC,CAAC;YACnE,MAAM,YAAY,GAAG,WAAW,CAAC,YAAY,CAAI,UAAU,CAAC,QAAQ,CAAC,CAAC;YAEtE,WAAW,CAAC,YAAY,CAAI,UAAU,CAAC,QAAQ,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC,CAAC;YAE5F,OAAO,EAAE,YAAY,EAAE,CAAC;QAC1B,CAAC;QACD,OAAO,EAAE,CAAC,MAAM,EAAE,UAAU,EAAE,OAAO,EAAE,EAAE;YACvC,IAAI,UAAU,IAAI,OAAO,EAAE,YAAY,KAAK,SAAS,EAAE,CAAC;gBACtD,WAAW,CAAC,YAAY,CAAC,UAAU,CAAC,QAAQ,EAAE,OAAO,CAAC,YAAY,CAAC,CAAC;YACtE,CAAC;QACH,CAAC;QACD,SAAS,EAAE,GAAG,EAAE;YACd,cAAc,CAAC,OAAO,CAAC,CAAC,GAAG,EAAE,EAAE;gBAC7B,WAAW,CAAC,iBAAiB,CAAC,EAAE,QAAQ,EAAE,GAAG,EAAE,CAAC,CAAC;YACnD,CAAC,CAAC,CAAC;YACH,IAAI,UAAU,EAAE,CAAC;gBACf,WAAW,CAAC,iBAAiB,CAAC,EAAE,QAAQ,EAAE,UAAU,CAAC,QAAQ,EAAE,CAAC,CAAC;YACnE,CAAC;QACH,CAAC;KACF,CAAC,CAAC;AACL,CAAC;AAOD,MAAM,UAAU,iBAAiB,CAAC,EAChC,cAAc,GAAG,EAAE,EACnB,SAAS,GAAG,kBAAkB,MACL,EAAE;IAK3B,MAAM,EAAE,GAAG,cAAc,EAAE,CAAC;IAC5B,MAAM,WAAW,GAAG,cAAc,EAAE,CAAC;IAErC,OAAO,kBAAkB,CAAC;QACxB,UAAU,EAAE,KAAK,EAAE,EAAE,UAAU,EAAuC,EAAE,EAAE;YACxE,MAAM,MAAM,GAA0B,EAAE,CAAC;YACzC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,UAAU,CAAC,MAAM,EAAE,CAAC,IAAI,SAAS,EAAE,CAAC;gBACtD,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,GAAG,SAAS,CAAC,CAAC,CAAC;YAClD,CAAC;YAED,IAAI,cAAc,GAAG,CAAC,CAAC;YAEvB,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;gBAC3B,MAAM,KAAK,GAAG,UAAU,CAAC,EAAE,CAAC,CAAC;gBAE7B,KAAK,MAAM,EAAE,IAAI,KAAK,EAAE,CAAC;oBACvB,MAAM,MAAM,GAAG,GAAG,CAAC,EAAE,EAAE,EAAE,CAAC,OAAO,CAAC,CAAC;oBAEnC,QAAQ,EAAE,CAAC,IAAI,EAAE,CAAC;wBAChB,KAAK,KAAK;4BACR,IAAI,EAAE,CAAC,KAAK,EAAE,CAAC;gCACb,KAAK,CAAC,GAAG,CAAC,MAAM,EAAE,EAAE,CAAC,IAAI,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;4BAC9C,CAAC;iCAAM,CAAC;gCACN,KAAK,CAAC,GAAG,CAAC,MAAM,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC;4BAC7B,CAAC;4BACD,MAAM;wBACR,KAAK,QAAQ;4BACX,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC;4BAC9B,MAAM;wBACR,KAAK,QAAQ;4BACX,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;4BACrB,MAAM;oBACV,CAAC;gBACH,CAAC;gBAED,MAAM,KAAK,CAAC,MAAM,EAAE,CAAC;gBACrB,cAAc,IAAI,KAAK,CAAC,MAAM,CAAC;YACjC,CAAC;YAED,OAAO;gBACL,SAAS,EAAE,cAAc;gBACzB,OAAO,EAAE,MAAM,CAAC,MAAM;aACvB,CAAC;QACJ,CAAC;QACD,SAAS,EAAE,GAAG,EAAE;YACd,cAAc,CAAC,OAAO,CAAC,CAAC,GAAG,EAAE,EAAE;gBAC7B,WAAW,CAAC,iBAAiB,CAAC,EAAE,QAAQ,EAAE,GAAG,EAAE,CAAC,CAAC;YACnD,CAAC,CAAC,CAAC;QACL,CAAC;KACF,CAAC,CAAC;AACL,CAAC","sourcesContent":["'use client';\n\nimport { useQueryClient, type QueryKey } from '@tanstack/react-query';\nimport {\n doc,\n setDoc,\n updateDoc,\n deleteDoc,\n writeBatch,\n type DocumentData,\n} from 'firebase/firestore';\nimport { useFirestoreDb } from './context.js';\nimport { useSessionMutation, type SessionMutationResult } from '../session-mutation.js';\nimport type { FirestoreMutationOptions, FirestoreBatchOptions } from '../../firestore/types.js';\nimport type { MutationOperation } from './types.js';\n\nconst DEFAULT_BATCH_SIZE = 450;\n\ninterface SetResult<T> {\n id: string;\n data: T;\n}\n\nexport function useFirestoreSet<T extends DocumentData>({\n invalidateKeys = [],\n}: Pick<FirestoreMutationOptions<T>, 'invalidateKeys'> = {}): SessionMutationResult<\n SetResult<T>,\n Error,\n { docPath: string; data: T; merge?: boolean }\n> {\n const db = useFirestoreDb();\n const queryClient = useQueryClient();\n\n return useSessionMutation({\n mutationFn: async ({\n docPath,\n data,\n merge = false,\n }: {\n docPath: string;\n data: T;\n merge?: boolean;\n }) => {\n const docRef = doc(db, docPath);\n await setDoc(docRef, data, { merge });\n return { id: docRef.id, data };\n },\n onSuccess: () => {\n invalidateKeys.forEach((key) => {\n queryClient.invalidateQueries({ queryKey: key });\n });\n },\n });\n}\n\nexport function useFirestoreUpdate<T extends DocumentData>({\n invalidateKeys = [],\n optimistic,\n}: FirestoreMutationOptions<T> = {}): SessionMutationResult<\n Partial<T>,\n Error,\n { docPath: string; data: Partial<T> },\n { previousData: T | undefined } | undefined\n> {\n const db = useFirestoreDb();\n const queryClient = useQueryClient();\n\n return useSessionMutation({\n mutationFn: async ({ docPath, data }: { docPath: string; data: Partial<T> }) => {\n const docRef = doc(db, docPath);\n await updateDoc(docRef, data as DocumentData);\n return data;\n },\n onMutate: async ({ data }) => {\n if (!optimistic) return undefined;\n\n await queryClient.cancelQueries({ queryKey: optimistic.queryKey });\n const previousData = queryClient.getQueryData<T>(optimistic.queryKey);\n\n queryClient.setQueryData<T>(optimistic.queryKey, (old) =>\n optimistic.updater(old, data as Partial<T>),\n );\n\n return { previousData };\n },\n onError: (_error, _variables, context) => {\n if (optimistic && context?.previousData !== undefined) {\n queryClient.setQueryData(optimistic.queryKey, context.previousData);\n }\n },\n onSettled: () => {\n invalidateKeys.forEach((key) => {\n queryClient.invalidateQueries({ queryKey: key });\n });\n if (optimistic) {\n queryClient.invalidateQueries({ queryKey: optimistic.queryKey });\n }\n },\n });\n}\n\nexport function useFirestoreDelete<T = unknown>({\n invalidateKeys = [],\n optimistic,\n}: {\n invalidateKeys?: readonly QueryKey[];\n optimistic?: {\n queryKey: QueryKey;\n updater: (oldData: T | undefined, docPath: string) => T;\n };\n} = {}): SessionMutationResult<\n string,\n Error,\n { docPath: string },\n { previousData: T | undefined } | undefined\n> {\n const db = useFirestoreDb();\n const queryClient = useQueryClient();\n\n return useSessionMutation({\n mutationFn: async ({ docPath }: { docPath: string }) => {\n const docRef = doc(db, docPath);\n await deleteDoc(docRef);\n return docPath;\n },\n onMutate: async ({ docPath }) => {\n if (!optimistic) return undefined;\n\n await queryClient.cancelQueries({ queryKey: optimistic.queryKey });\n const previousData = queryClient.getQueryData<T>(optimistic.queryKey);\n\n queryClient.setQueryData<T>(optimistic.queryKey, (old) => optimistic.updater(old, docPath));\n\n return { previousData };\n },\n onError: (_error, _variables, context) => {\n if (optimistic && context?.previousData !== undefined) {\n queryClient.setQueryData(optimistic.queryKey, context.previousData);\n }\n },\n onSettled: () => {\n invalidateKeys.forEach((key) => {\n queryClient.invalidateQueries({ queryKey: key });\n });\n if (optimistic) {\n queryClient.invalidateQueries({ queryKey: optimistic.queryKey });\n }\n },\n });\n}\n\ninterface BatchResult {\n committed: number;\n batches: number;\n}\n\nexport function useFirestoreBatch({\n invalidateKeys = [],\n batchSize = DEFAULT_BATCH_SIZE,\n}: FirestoreBatchOptions = {}): SessionMutationResult<\n BatchResult,\n Error,\n { operations: MutationOperation[] }\n> {\n const db = useFirestoreDb();\n const queryClient = useQueryClient();\n\n return useSessionMutation({\n mutationFn: async ({ operations }: { operations: MutationOperation[] }) => {\n const chunks: MutationOperation[][] = [];\n for (let i = 0; i < operations.length; i += batchSize) {\n chunks.push(operations.slice(i, i + batchSize));\n }\n\n let totalCommitted = 0;\n\n for (const chunk of chunks) {\n const batch = writeBatch(db);\n\n for (const op of chunk) {\n const docRef = doc(db, op.docPath);\n\n switch (op.type) {\n case 'set':\n if (op.merge) {\n batch.set(docRef, op.data, { merge: true });\n } else {\n batch.set(docRef, op.data);\n }\n break;\n case 'update':\n batch.update(docRef, op.data);\n break;\n case 'delete':\n batch.delete(docRef);\n break;\n }\n }\n\n await batch.commit();\n totalCommitted += chunk.length;\n }\n\n return {\n committed: totalCommitted,\n batches: chunks.length,\n };\n },\n onSuccess: () => {\n invalidateKeys.forEach((key) => {\n queryClient.invalidateQueries({ queryKey: key });\n });\n },\n });\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-firestore-paginated.d.ts","sourceRoot":"","sources":["../../../src/react/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;
|
|
1
|
+
{"version":3,"file":"use-firestore-paginated.d.ts","sourceRoot":"","sources":["../../../src/react/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;AAI5B,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,0BAA0B,CAAC;AACvD,OAAO,KAAK,EAAE,yBAAyB,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAI3E,MAAM,MAAM,2BAA2B,CAAC,CAAC,IAAI,IAAI,CAC/C,cAAc,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,EAC/C,MAAM,CACP,GAAG;IACF,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC,EAAE,GAAG,SAAS,CAAC;IAC9B,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;CACtB,CAAC;AAEF,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,eAAe,EACf,MAAM,GACP,EAAE,yBAAyB,CAAC,CAAC,CAAC,GAAG,2BAA2B,CAAC,CAAC,CAAC,CAiH/D"}
|
|
@@ -4,6 +4,7 @@ import { useQuery, useQueryClient } from '@tanstack/react-query';
|
|
|
4
4
|
import { collection, query, getDocs, limit, startAfter, } from 'firebase/firestore';
|
|
5
5
|
import { useFirestoreDb } from './context.js';
|
|
6
6
|
import { paginatedPageKey } from '../cache-helpers.js';
|
|
7
|
+
import { useSerializedIdentity } from './stable-inputs.js';
|
|
7
8
|
const DEFAULT_PAGE_SIZE = 10;
|
|
8
9
|
export function useFirestorePaginated({ collectionPath, queryKey, constraints = [], pageSize = DEFAULT_PAGE_SIZE, initialPage = 1, enabled = true, staleTime, gcTime, refetchInterval, select, }) {
|
|
9
10
|
const db = useFirestoreDb();
|
|
@@ -11,6 +12,8 @@ export function useFirestorePaginated({ collectionPath, queryKey, constraints =
|
|
|
11
12
|
const queryKeyMemo = JSON.stringify(queryKey);
|
|
12
13
|
const constraintsMemo = JSON.stringify(constraints);
|
|
13
14
|
const identity = JSON.stringify([collectionPath, queryKeyMemo, constraintsMemo, pageSize]);
|
|
15
|
+
const stableQueryKey = useSerializedIdentity(queryKey, queryKeyMemo);
|
|
16
|
+
const stableConstraints = useSerializedIdentity(constraints, constraintsMemo);
|
|
14
17
|
const firstPage = Math.max(1, Math.floor(initialPage));
|
|
15
18
|
const [pageState, setPageState] = useState(() => ({ identity, page: firstPage }));
|
|
16
19
|
const page = pageState.identity === identity ? pageState.page : firstPage;
|
|
@@ -20,7 +23,7 @@ export function useFirestorePaginated({ collectionPath, queryKey, constraints =
|
|
|
20
23
|
let cursor = null;
|
|
21
24
|
if (n > 1) {
|
|
22
25
|
const previous = await queryClient.ensureQueryData({
|
|
23
|
-
queryKey: paginatedPageKey(
|
|
26
|
+
queryKey: paginatedPageKey(stableQueryKey, n - 1),
|
|
24
27
|
queryFn: () => fetchPage(n - 1),
|
|
25
28
|
});
|
|
26
29
|
if (!previous.hasMore || !previous.cursor) {
|
|
@@ -28,7 +31,7 @@ export function useFirestorePaginated({ collectionPath, queryKey, constraints =
|
|
|
28
31
|
}
|
|
29
32
|
cursor = previous.cursor;
|
|
30
33
|
}
|
|
31
|
-
const q = query(collection(db, collectionPath), ...
|
|
34
|
+
const q = query(collection(db, collectionPath), ...stableConstraints, ...(cursor ? [startAfter(cursor)] : []), limit(pageSize + 1));
|
|
32
35
|
const snapshot = await getDocs(q);
|
|
33
36
|
const pageDocs = snapshot.docs.slice(0, pageSize);
|
|
34
37
|
return {
|
|
@@ -41,9 +44,7 @@ export function useFirestorePaginated({ collectionPath, queryKey, constraints =
|
|
|
41
44
|
hasMore: snapshot.docs.length > pageSize,
|
|
42
45
|
after: cursor?.id ?? null,
|
|
43
46
|
};
|
|
44
|
-
},
|
|
45
|
-
// eslint-disable-next-line react-hooks/exhaustive-deps -- queryKey and constraints are captured through their serialized identity
|
|
46
|
-
[db, queryClient, identity, selectRef]);
|
|
47
|
+
}, [db, queryClient, collectionPath, stableQueryKey, stableConstraints, pageSize]);
|
|
47
48
|
const queryResult = useQuery({
|
|
48
49
|
queryKey: paginatedPageKey(queryKey, page),
|
|
49
50
|
queryFn: () => fetchPage(page),
|
|
@@ -74,16 +75,14 @@ export function useFirestorePaginated({ collectionPath, queryKey, constraints =
|
|
|
74
75
|
if (next < 1 || next === page)
|
|
75
76
|
return;
|
|
76
77
|
if (next > page + 1) {
|
|
77
|
-
const before = queryClient.getQueryData(paginatedPageKey(
|
|
78
|
+
const before = queryClient.getQueryData(paginatedPageKey(stableQueryKey, next - 1));
|
|
78
79
|
if (!before?.hasMore)
|
|
79
80
|
return;
|
|
80
81
|
}
|
|
81
82
|
if (next === page + 1 && !hasNextPage)
|
|
82
83
|
return;
|
|
83
84
|
setPageState({ identity, page: next });
|
|
84
|
-
},
|
|
85
|
-
// eslint-disable-next-line react-hooks/exhaustive-deps -- queryKey is captured through its serialized identity
|
|
86
|
-
[page, hasNextPage, identity, queryClient]);
|
|
85
|
+
}, [page, hasNextPage, identity, queryClient, stableQueryKey]);
|
|
87
86
|
const nextPage = useCallback(() => setPage(page + 1), [page, setPage]);
|
|
88
87
|
const prevPage = useCallback(() => setPage(page - 1), [page, setPage]);
|
|
89
88
|
return {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-firestore-paginated.js","sourceRoot":"","sources":["../../../src/react/firestore/use-firestore-paginated.ts"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAEb,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,OAAO,CAAC;AACjE,OAAO,EAAE,QAAQ,EAAE,cAAc,EAAuB,MAAM,uBAAuB,CAAC;AACtF,OAAO,EACL,UAAU,EACV,KAAK,EACL,OAAO,EACP,KAAK,EACL,UAAU,GAGX,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAIvD,MAAM,iBAAiB,GAAG,EAAE,CAAC;AAgB7B,MAAM,UAAU,qBAAqB,CAAwC,EAC3E,cAAc,EACd,QAAQ,EACR,WAAW,GAAG,EAAE,EAChB,QAAQ,GAAG,iBAAiB,EAC5B,WAAW,GAAG,CAAC,EACf,OAAO,GAAG,IAAI,EACd,SAAS,EACT,MAAM,EACN,eAAe,EACf,MAAM,GACuB;IAC7B,MAAM,EAAE,GAAG,cAAc,EAAE,CAAC;IAC5B,MAAM,WAAW,GAAG,cAAc,EAAE,CAAC;IAErC,MAAM,YAAY,GAAG,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;IAC9C,MAAM,eAAe,GAAG,IAAI,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC;IACpD,MAAM,QAAQ,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC,cAAc,EAAE,YAAY,EAAE,eAAe,EAAE,QAAQ,CAAC,CAAC,CAAC;IAC3F,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC,CAAC;IAEvD,MAAM,CAAC,SAAS,EAAE,YAAY,CAAC,GAAG,QAAQ,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC,CAAC,CAAC;IAClF,MAAM,IAAI,GAAG,SAAS,CAAC,QAAQ,KAAK,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC;IAE1E,MAAM,SAAS,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC;IACjC,SAAS,CAAC,OAAO,GAAG,MAAM,CAAC;IAE3B,MAAM,SAAS,GAAG,WAAW,CAC3B,KAAK,EAAE,CAAS,EAAqC,EAAE;QACrD,IAAI,MAAM,GAA4B,IAAI,CAAC;QAC3C,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;YACV,MAAM,QAAQ,GAAG,MAAM,WAAW,CAAC,eAAe,CAA2B;gBAC3E,QAAQ,EAAE,gBAAgB,CAAC,QAAQ,EAAE,CAAC,GAAG,CAAC,CAAC;gBAC3C,OAAO,EAAE,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC,GAAG,CAAC,CAAC;aAChC,CAAC,CAAC;YACH,IAAI,CAAC,QAAQ,CAAC,OAAO,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC;gBAC1C,OAAO,EAAE,KAAK,EAAE,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,QAAQ,CAAC,MAAM,EAAE,EAAE,IAAI,IAAI,EAAE,CAAC;YACzF,CAAC;YACD,MAAM,GAAG,QAAQ,CAAC,MAAM,CAAC;QAC3B,CAAC;QACD,MAAM,CAAC,GAAG,KAAK,CACb,UAAU,CAAC,EAAE,EAAE,cAAc,CAAC,EAC9B,GAAG,WAAW,EACd,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,EACvC,KAAK,CAAC,QAAQ,GAAG,CAAC,CAAC,CACpB,CAAC;QACF,MAAM,QAAQ,GAAG,MAAM,OAAO,CAAC,CAAC,CAAC,CAAC;QAClC,MAAM,QAAQ,GAAG,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC;QAClD,OAAO;YACL,KAAK,EAAE,QAAQ,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE;gBAC9B,MAAM,UAAU,GAAG,EAAE,EAAE,EAAE,OAAO,CAAC,EAAE,EAAE,GAAG,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC;gBACzD,MAAM,MAAM,GAAG,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC;gBAC9E,OAAO,MAAmB,CAAC;YAC7B,CAAC,CAAC;YACF,MAAM,EAAE,QAAQ,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC,IAAI,IAAI;YAC7C,OAAO,EAAE,QAAQ,CAAC,IAAI,CAAC,MAAM,GAAG,QAAQ;YACxC,KAAK,EAAE,MAAM,EAAE,EAAE,IAAI,IAAI;SAC1B,CAAC;IACJ,CAAC;IACD,kIAAkI;IAClI,CAAC,EAAE,EAAE,WAAW,EAAE,QAAQ,EAAE,SAAS,CAAC,CACvC,CAAC;IAEF,MAAM,WAAW,GAAG,QAAQ,CAAC;QAC3B,QAAQ,EAAE,gBAAgB,CAAC,QAAQ,EAAE,IAAI,CAAC;QAC1C,OAAO,EAAE,GAAG,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC;QAC9B,OAAO;QACP,SAAS;QACT,MAAM;QACN,eAAe;KAChB,CAAC,CAAC;IAEH,MAAM,YAAY,GAAG,QAAQ,CAAC;QAC5B,QAAQ,EAAE,gBAAgB,CAAC,QAAQ,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,GAAG,CAAC,CAAC,CAAC;QAC3D,OAAO,EAAE,GAAG,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,GAAG,CAAC,CAAC,CAAC;QAC/C,OAAO,EAAE,KAAK;KACf,CAAC,CAAC;IACH,MAAM,WAAW,GAAG,WAAW,CAAC,IAAI,CAAC;IACrC,MAAM,UAAU,GACd,IAAI,GAAG,CAAC;QACR,WAAW,KAAK,SAAS;QACzB,CAAC,YAAY,CAAC,IAAI,KAAK,SAAS;YAC9B,WAAW,CAAC,KAAK,KAAK,CAAC,YAAY,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,IAAI,IAAI,CAAC,CAAC,CAAC;IAClE,MAAM,EAAE,OAAO,EAAE,UAAU,EAAE,GAAG,WAAW,CAAC;IAC5C,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,OAAO,IAAI,UAAU,IAAI,CAAC,UAAU;YAAE,KAAK,OAAO,EAAE,CAAC;IAC3D,CAAC,EAAE,CAAC,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,OAAO,CAAC,CAAC,CAAC;IAE/C,MAAM,KAAK,GAAG,UAAU,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,WAAW,CAAC;IACnD,MAAM,WAAW,GAAG,OAAO,CAAC,KAAK,EAAE,OAAO,IAAI,KAAK,CAAC,MAAM,CAAC,CAAC;IAE5D,MAAM,OAAO,GAAG,WAAW,CACzB,CAAC,MAAc,EAAE,EAAE;QACjB,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;QAChC,IAAI,IAAI,GAAG,CAAC,IAAI,IAAI,KAAK,IAAI;YAAE,OAAO;QACtC,IAAI,IAAI,GAAG,IAAI,GAAG,CAAC,EAAE,CAAC;YACpB,MAAM,MAAM,GAAG,WAAW,CAAC,YAAY,CACrC,gBAAgB,CAAC,QAAQ,EAAE,IAAI,GAAG,CAAC,CAAC,CACrC,CAAC;YACF,IAAI,CAAC,MAAM,EAAE,OAAO;gBAAE,OAAO;QAC/B,CAAC;QACD,IAAI,IAAI,KAAK,IAAI,GAAG,CAAC,IAAI,CAAC,WAAW;YAAE,OAAO;QAC9C,YAAY,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;IACzC,CAAC;IACD,+GAA+G;IAC/G,CAAC,IAAI,EAAE,WAAW,EAAE,QAAQ,EAAE,WAAW,CAAC,CAC3C,CAAC;IAEF,MAAM,QAAQ,GAAG,WAAW,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,IAAI,GAAG,CAAC,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC;IACvE,MAAM,QAAQ,GAAG,WAAW,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,IAAI,GAAG,CAAC,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC;IAEvE,OAAO;QACL,GAAG,WAAW;QACd,GAAG,CAAC,UAAU;YACZ,CAAC,CAAC,EAAE,SAAS,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,EAAE,SAAkB,EAAE;YACpF,CAAC,CAAC,EAAE,CAAC;QACP,IAAI,EAAE,KAAK,EAAE,KAAK;QAClB,IAAI;QACJ,QAAQ;QACR,WAAW;QACX,WAAW,EAAE,IAAI,GAAG,CAAC;QACrB,OAAO;QACP,QAAQ;QACR,QAAQ;KACyB,CAAC;AACtC,CAAC","sourcesContent":["'use client';\n\nimport { useState, useCallback, useEffect, useRef } from 'react';\nimport { useQuery, useQueryClient, type UseQueryResult } from '@tanstack/react-query';\nimport {\n collection,\n query,\n getDocs,\n limit,\n startAfter,\n type DocumentData,\n type DocumentSnapshot,\n} from 'firebase/firestore';\nimport { useFirestoreDb } from './context.js';\nimport { paginatedPageKey } from '../cache-helpers.js';\nimport type { WithId } from '../../firestore/types.js';\nimport type { FirestorePaginatedOptions, PaginatedPage } from './types.js';\n\nconst DEFAULT_PAGE_SIZE = 10;\n\nexport type UseFirestorePaginatedResult<T> = Omit<\n UseQueryResult<PaginatedPage<WithId<T>>, Error>,\n 'data'\n> & {\n data: WithId<T>[] | undefined;\n page: number;\n pageSize: number;\n hasNextPage: boolean;\n hasPrevPage: boolean;\n setPage: (page: number) => void;\n nextPage: () => void;\n prevPage: () => void;\n};\n\nexport function useFirestorePaginated<T extends DocumentData = DocumentData>({\n collectionPath,\n queryKey,\n constraints = [],\n pageSize = DEFAULT_PAGE_SIZE,\n initialPage = 1,\n enabled = true,\n staleTime,\n gcTime,\n refetchInterval,\n select,\n}: FirestorePaginatedOptions<T>): UseFirestorePaginatedResult<T> {\n const db = useFirestoreDb();\n const queryClient = useQueryClient();\n\n const queryKeyMemo = JSON.stringify(queryKey);\n const constraintsMemo = JSON.stringify(constraints);\n const identity = JSON.stringify([collectionPath, queryKeyMemo, constraintsMemo, pageSize]);\n const firstPage = Math.max(1, Math.floor(initialPage));\n\n const [pageState, setPageState] = useState(() => ({ identity, page: firstPage }));\n const page = pageState.identity === identity ? pageState.page : firstPage;\n\n const selectRef = useRef(select);\n selectRef.current = select;\n\n const fetchPage = useCallback(\n async (n: number): Promise<PaginatedPage<WithId<T>>> => {\n let cursor: DocumentSnapshot | null = null;\n if (n > 1) {\n const previous = await queryClient.ensureQueryData<PaginatedPage<WithId<T>>>({\n queryKey: paginatedPageKey(queryKey, n - 1),\n queryFn: () => fetchPage(n - 1),\n });\n if (!previous.hasMore || !previous.cursor) {\n return { items: [], cursor: null, hasMore: false, after: previous.cursor?.id ?? null };\n }\n cursor = previous.cursor;\n }\n const q = query(\n collection(db, collectionPath),\n ...constraints,\n ...(cursor ? [startAfter(cursor)] : []),\n limit(pageSize + 1),\n );\n const snapshot = await getDocs(q);\n const pageDocs = snapshot.docs.slice(0, pageSize);\n return {\n items: pageDocs.map((docSnap) => {\n const dataWithId = { id: docSnap.id, ...docSnap.data() };\n const mapped = selectRef.current ? selectRef.current(dataWithId) : dataWithId;\n return mapped as WithId<T>;\n }),\n cursor: pageDocs[pageDocs.length - 1] ?? null,\n hasMore: snapshot.docs.length > pageSize,\n after: cursor?.id ?? null,\n };\n },\n // eslint-disable-next-line react-hooks/exhaustive-deps -- queryKey and constraints are captured through their serialized identity\n [db, queryClient, identity, selectRef],\n );\n\n const queryResult = useQuery({\n queryKey: paginatedPageKey(queryKey, page),\n queryFn: () => fetchPage(page),\n enabled,\n staleTime,\n gcTime,\n refetchInterval,\n });\n\n const previousPage = useQuery({\n queryKey: paginatedPageKey(queryKey, Math.max(1, page - 1)),\n queryFn: () => fetchPage(Math.max(1, page - 1)),\n enabled: false,\n });\n const cachedEntry = queryResult.data;\n const outOfChain =\n page > 1 &&\n cachedEntry !== undefined &&\n (previousPage.data === undefined ||\n cachedEntry.after !== (previousPage.data.cursor?.id ?? null));\n const { refetch, isFetching } = queryResult;\n useEffect(() => {\n if (enabled && outOfChain && !isFetching) void refetch();\n }, [enabled, outOfChain, isFetching, refetch]);\n\n const entry = outOfChain ? undefined : cachedEntry;\n const hasNextPage = Boolean(entry?.hasMore && entry.cursor);\n\n const setPage = useCallback(\n (target: number) => {\n const next = Math.floor(target);\n if (next < 1 || next === page) return;\n if (next > page + 1) {\n const before = queryClient.getQueryData<PaginatedPage<unknown>>(\n paginatedPageKey(queryKey, next - 1),\n );\n if (!before?.hasMore) return;\n }\n if (next === page + 1 && !hasNextPage) return;\n setPageState({ identity, page: next });\n },\n // eslint-disable-next-line react-hooks/exhaustive-deps -- queryKey is captured through its serialized identity\n [page, hasNextPage, identity, queryClient],\n );\n\n const nextPage = useCallback(() => setPage(page + 1), [page, setPage]);\n const prevPage = useCallback(() => setPage(page - 1), [page, setPage]);\n\n return {\n ...queryResult,\n ...(outOfChain\n ? { isLoading: true, isPending: true, isSuccess: false, status: 'pending' as const }\n : {}),\n data: entry?.items,\n page,\n pageSize,\n hasNextPage,\n hasPrevPage: page > 1,\n setPage,\n nextPage,\n prevPage,\n } as UseFirestorePaginatedResult<T>;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"use-firestore-paginated.js","sourceRoot":"","sources":["../../../src/react/firestore/use-firestore-paginated.ts"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAEb,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,OAAO,CAAC;AACjE,OAAO,EAAE,QAAQ,EAAE,cAAc,EAAuB,MAAM,uBAAuB,CAAC;AACtF,OAAO,EACL,UAAU,EACV,KAAK,EACL,OAAO,EACP,KAAK,EACL,UAAU,GAGX,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AACvD,OAAO,EAAE,qBAAqB,EAAE,MAAM,oBAAoB,CAAC;AAI3D,MAAM,iBAAiB,GAAG,EAAE,CAAC;AAgB7B,MAAM,UAAU,qBAAqB,CAAwC,EAC3E,cAAc,EACd,QAAQ,EACR,WAAW,GAAG,EAAE,EAChB,QAAQ,GAAG,iBAAiB,EAC5B,WAAW,GAAG,CAAC,EACf,OAAO,GAAG,IAAI,EACd,SAAS,EACT,MAAM,EACN,eAAe,EACf,MAAM,GACuB;IAC7B,MAAM,EAAE,GAAG,cAAc,EAAE,CAAC;IAC5B,MAAM,WAAW,GAAG,cAAc,EAAE,CAAC;IAErC,MAAM,YAAY,GAAG,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;IAC9C,MAAM,eAAe,GAAG,IAAI,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC;IACpD,MAAM,QAAQ,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC,cAAc,EAAE,YAAY,EAAE,eAAe,EAAE,QAAQ,CAAC,CAAC,CAAC;IAC3F,MAAM,cAAc,GAAG,qBAAqB,CAAC,QAAQ,EAAE,YAAY,CAAC,CAAC;IACrE,MAAM,iBAAiB,GAAG,qBAAqB,CAAC,WAAW,EAAE,eAAe,CAAC,CAAC;IAC9E,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC,CAAC;IAEvD,MAAM,CAAC,SAAS,EAAE,YAAY,CAAC,GAAG,QAAQ,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC,CAAC,CAAC;IAClF,MAAM,IAAI,GAAG,SAAS,CAAC,QAAQ,KAAK,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC;IAE1E,MAAM,SAAS,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC;IACjC,SAAS,CAAC,OAAO,GAAG,MAAM,CAAC;IAE3B,MAAM,SAAS,GAAG,WAAW,CAC3B,KAAK,EAAE,CAAS,EAAqC,EAAE;QACrD,IAAI,MAAM,GAA4B,IAAI,CAAC;QAC3C,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;YACV,MAAM,QAAQ,GAAG,MAAM,WAAW,CAAC,eAAe,CAA2B;gBAC3E,QAAQ,EAAE,gBAAgB,CAAC,cAAc,EAAE,CAAC,GAAG,CAAC,CAAC;gBACjD,OAAO,EAAE,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC,GAAG,CAAC,CAAC;aAChC,CAAC,CAAC;YACH,IAAI,CAAC,QAAQ,CAAC,OAAO,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC;gBAC1C,OAAO,EAAE,KAAK,EAAE,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,QAAQ,CAAC,MAAM,EAAE,EAAE,IAAI,IAAI,EAAE,CAAC;YACzF,CAAC;YACD,MAAM,GAAG,QAAQ,CAAC,MAAM,CAAC;QAC3B,CAAC;QACD,MAAM,CAAC,GAAG,KAAK,CACb,UAAU,CAAC,EAAE,EAAE,cAAc,CAAC,EAC9B,GAAG,iBAAiB,EACpB,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,EACvC,KAAK,CAAC,QAAQ,GAAG,CAAC,CAAC,CACpB,CAAC;QACF,MAAM,QAAQ,GAAG,MAAM,OAAO,CAAC,CAAC,CAAC,CAAC;QAClC,MAAM,QAAQ,GAAG,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC;QAClD,OAAO;YACL,KAAK,EAAE,QAAQ,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE;gBAC9B,MAAM,UAAU,GAAG,EAAE,EAAE,EAAE,OAAO,CAAC,EAAE,EAAE,GAAG,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC;gBACzD,MAAM,MAAM,GAAG,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC;gBAC9E,OAAO,MAAmB,CAAC;YAC7B,CAAC,CAAC;YACF,MAAM,EAAE,QAAQ,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC,IAAI,IAAI;YAC7C,OAAO,EAAE,QAAQ,CAAC,IAAI,CAAC,MAAM,GAAG,QAAQ;YACxC,KAAK,EAAE,MAAM,EAAE,EAAE,IAAI,IAAI;SAC1B,CAAC;IACJ,CAAC,EACD,CAAC,EAAE,EAAE,WAAW,EAAE,cAAc,EAAE,cAAc,EAAE,iBAAiB,EAAE,QAAQ,CAAC,CAC/E,CAAC;IAEF,MAAM,WAAW,GAAG,QAAQ,CAAC;QAC3B,QAAQ,EAAE,gBAAgB,CAAC,QAAQ,EAAE,IAAI,CAAC;QAC1C,OAAO,EAAE,GAAG,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC;QAC9B,OAAO;QACP,SAAS;QACT,MAAM;QACN,eAAe;KAChB,CAAC,CAAC;IAEH,MAAM,YAAY,GAAG,QAAQ,CAAC;QAC5B,QAAQ,EAAE,gBAAgB,CAAC,QAAQ,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,GAAG,CAAC,CAAC,CAAC;QAC3D,OAAO,EAAE,GAAG,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,GAAG,CAAC,CAAC,CAAC;QAC/C,OAAO,EAAE,KAAK;KACf,CAAC,CAAC;IACH,MAAM,WAAW,GAAG,WAAW,CAAC,IAAI,CAAC;IACrC,MAAM,UAAU,GACd,IAAI,GAAG,CAAC;QACR,WAAW,KAAK,SAAS;QACzB,CAAC,YAAY,CAAC,IAAI,KAAK,SAAS;YAC9B,WAAW,CAAC,KAAK,KAAK,CAAC,YAAY,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,IAAI,IAAI,CAAC,CAAC,CAAC;IAClE,MAAM,EAAE,OAAO,EAAE,UAAU,EAAE,GAAG,WAAW,CAAC;IAC5C,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,OAAO,IAAI,UAAU,IAAI,CAAC,UAAU;YAAE,KAAK,OAAO,EAAE,CAAC;IAC3D,CAAC,EAAE,CAAC,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,OAAO,CAAC,CAAC,CAAC;IAE/C,MAAM,KAAK,GAAG,UAAU,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,WAAW,CAAC;IACnD,MAAM,WAAW,GAAG,OAAO,CAAC,KAAK,EAAE,OAAO,IAAI,KAAK,CAAC,MAAM,CAAC,CAAC;IAE5D,MAAM,OAAO,GAAG,WAAW,CACzB,CAAC,MAAc,EAAE,EAAE;QACjB,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;QAChC,IAAI,IAAI,GAAG,CAAC,IAAI,IAAI,KAAK,IAAI;YAAE,OAAO;QACtC,IAAI,IAAI,GAAG,IAAI,GAAG,CAAC,EAAE,CAAC;YACpB,MAAM,MAAM,GAAG,WAAW,CAAC,YAAY,CACrC,gBAAgB,CAAC,cAAc,EAAE,IAAI,GAAG,CAAC,CAAC,CAC3C,CAAC;YACF,IAAI,CAAC,MAAM,EAAE,OAAO;gBAAE,OAAO;QAC/B,CAAC;QACD,IAAI,IAAI,KAAK,IAAI,GAAG,CAAC,IAAI,CAAC,WAAW;YAAE,OAAO;QAC9C,YAAY,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;IACzC,CAAC,EACD,CAAC,IAAI,EAAE,WAAW,EAAE,QAAQ,EAAE,WAAW,EAAE,cAAc,CAAC,CAC3D,CAAC;IAEF,MAAM,QAAQ,GAAG,WAAW,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,IAAI,GAAG,CAAC,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC;IACvE,MAAM,QAAQ,GAAG,WAAW,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,IAAI,GAAG,CAAC,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC;IAEvE,OAAO;QACL,GAAG,WAAW;QACd,GAAG,CAAC,UAAU;YACZ,CAAC,CAAC,EAAE,SAAS,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,EAAE,SAAkB,EAAE;YACpF,CAAC,CAAC,EAAE,CAAC;QACP,IAAI,EAAE,KAAK,EAAE,KAAK;QAClB,IAAI;QACJ,QAAQ;QACR,WAAW;QACX,WAAW,EAAE,IAAI,GAAG,CAAC;QACrB,OAAO;QACP,QAAQ;QACR,QAAQ;KACyB,CAAC;AACtC,CAAC","sourcesContent":["'use client';\n\nimport { useState, useCallback, useEffect, useRef } from 'react';\nimport { useQuery, useQueryClient, type UseQueryResult } from '@tanstack/react-query';\nimport {\n collection,\n query,\n getDocs,\n limit,\n startAfter,\n type DocumentData,\n type DocumentSnapshot,\n} from 'firebase/firestore';\nimport { useFirestoreDb } from './context.js';\nimport { paginatedPageKey } from '../cache-helpers.js';\nimport { useSerializedIdentity } from './stable-inputs.js';\nimport type { WithId } from '../../firestore/types.js';\nimport type { FirestorePaginatedOptions, PaginatedPage } from './types.js';\n\nconst DEFAULT_PAGE_SIZE = 10;\n\nexport type UseFirestorePaginatedResult<T> = Omit<\n UseQueryResult<PaginatedPage<WithId<T>>, Error>,\n 'data'\n> & {\n data: WithId<T>[] | undefined;\n page: number;\n pageSize: number;\n hasNextPage: boolean;\n hasPrevPage: boolean;\n setPage: (page: number) => void;\n nextPage: () => void;\n prevPage: () => void;\n};\n\nexport function useFirestorePaginated<T extends DocumentData = DocumentData>({\n collectionPath,\n queryKey,\n constraints = [],\n pageSize = DEFAULT_PAGE_SIZE,\n initialPage = 1,\n enabled = true,\n staleTime,\n gcTime,\n refetchInterval,\n select,\n}: FirestorePaginatedOptions<T>): UseFirestorePaginatedResult<T> {\n const db = useFirestoreDb();\n const queryClient = useQueryClient();\n\n const queryKeyMemo = JSON.stringify(queryKey);\n const constraintsMemo = JSON.stringify(constraints);\n const identity = JSON.stringify([collectionPath, queryKeyMemo, constraintsMemo, pageSize]);\n const stableQueryKey = useSerializedIdentity(queryKey, queryKeyMemo);\n const stableConstraints = useSerializedIdentity(constraints, constraintsMemo);\n const firstPage = Math.max(1, Math.floor(initialPage));\n\n const [pageState, setPageState] = useState(() => ({ identity, page: firstPage }));\n const page = pageState.identity === identity ? pageState.page : firstPage;\n\n const selectRef = useRef(select);\n selectRef.current = select;\n\n const fetchPage = useCallback(\n async (n: number): Promise<PaginatedPage<WithId<T>>> => {\n let cursor: DocumentSnapshot | null = null;\n if (n > 1) {\n const previous = await queryClient.ensureQueryData<PaginatedPage<WithId<T>>>({\n queryKey: paginatedPageKey(stableQueryKey, n - 1),\n queryFn: () => fetchPage(n - 1),\n });\n if (!previous.hasMore || !previous.cursor) {\n return { items: [], cursor: null, hasMore: false, after: previous.cursor?.id ?? null };\n }\n cursor = previous.cursor;\n }\n const q = query(\n collection(db, collectionPath),\n ...stableConstraints,\n ...(cursor ? [startAfter(cursor)] : []),\n limit(pageSize + 1),\n );\n const snapshot = await getDocs(q);\n const pageDocs = snapshot.docs.slice(0, pageSize);\n return {\n items: pageDocs.map((docSnap) => {\n const dataWithId = { id: docSnap.id, ...docSnap.data() };\n const mapped = selectRef.current ? selectRef.current(dataWithId) : dataWithId;\n return mapped as WithId<T>;\n }),\n cursor: pageDocs[pageDocs.length - 1] ?? null,\n hasMore: snapshot.docs.length > pageSize,\n after: cursor?.id ?? null,\n };\n },\n [db, queryClient, collectionPath, stableQueryKey, stableConstraints, pageSize],\n );\n\n const queryResult = useQuery({\n queryKey: paginatedPageKey(queryKey, page),\n queryFn: () => fetchPage(page),\n enabled,\n staleTime,\n gcTime,\n refetchInterval,\n });\n\n const previousPage = useQuery({\n queryKey: paginatedPageKey(queryKey, Math.max(1, page - 1)),\n queryFn: () => fetchPage(Math.max(1, page - 1)),\n enabled: false,\n });\n const cachedEntry = queryResult.data;\n const outOfChain =\n page > 1 &&\n cachedEntry !== undefined &&\n (previousPage.data === undefined ||\n cachedEntry.after !== (previousPage.data.cursor?.id ?? null));\n const { refetch, isFetching } = queryResult;\n useEffect(() => {\n if (enabled && outOfChain && !isFetching) void refetch();\n }, [enabled, outOfChain, isFetching, refetch]);\n\n const entry = outOfChain ? undefined : cachedEntry;\n const hasNextPage = Boolean(entry?.hasMore && entry.cursor);\n\n const setPage = useCallback(\n (target: number) => {\n const next = Math.floor(target);\n if (next < 1 || next === page) return;\n if (next > page + 1) {\n const before = queryClient.getQueryData<PaginatedPage<unknown>>(\n paginatedPageKey(stableQueryKey, next - 1),\n );\n if (!before?.hasMore) return;\n }\n if (next === page + 1 && !hasNextPage) return;\n setPageState({ identity, page: next });\n },\n [page, hasNextPage, identity, queryClient, stableQueryKey],\n );\n\n const nextPage = useCallback(() => setPage(page + 1), [page, setPage]);\n const prevPage = useCallback(() => setPage(page - 1), [page, setPage]);\n\n return {\n ...queryResult,\n ...(outOfChain\n ? { isLoading: true, isPending: true, isSuccess: false, status: 'pending' as const }\n : {}),\n data: entry?.items,\n page,\n pageSize,\n hasNextPage,\n hasPrevPage: page > 1,\n setPage,\n nextPage,\n prevPage,\n } as UseFirestorePaginatedResult<T>;\n}\n"]}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { Firestore } from 'firebase/firestore';
|
|
1
|
+
import type { DocumentData, Firestore } from 'firebase/firestore';
|
|
2
2
|
import type { BatchFirestoreDocOutcome } from '../../firestore/types.js';
|
|
3
3
|
export type BatchFirestoreDocsTransport = 'batch' | 'get';
|
|
4
4
|
export type BatchFirestoreDocsOptions = {
|
|
@@ -24,5 +24,5 @@ export type BatchFirestoreDocsResult<T> = {
|
|
|
24
24
|
failedReadsRunning: boolean;
|
|
25
25
|
refetch: () => Promise<void>;
|
|
26
26
|
};
|
|
27
|
-
export declare function useBatchFirestoreDocs<T extends
|
|
27
|
+
export declare function useBatchFirestoreDocs<T extends DocumentData>({ db, collectionPath, ids, queryKeyPrefix, staleTime, gcTime, enabled, subscribe, transport, absentStaleTime, absentRetryDelaysMs, }: BatchFirestoreDocsOptions): BatchFirestoreDocsResult<T>;
|
|
28
28
|
//# 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,KAAK,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"useBatchFirestoreDocs.d.ts","sourceRoot":"","sources":["../../../src/react/firestore/useBatchFirestoreDocs.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAIlE,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,0BAA0B,CAAC;AAIzE,MAAM,MAAM,2BAA2B,GAAG,OAAO,GAAG,KAAK,CAAC;AAE1D,MAAM,MAAM,yBAAyB,GAAG;IACtC,EAAE,EAAE,SAAS,CAAC;IAEd,cAAc,EAAE,MAAM,CAAC;IAEvB,GAAG,EAAE,MAAM,EAAE,CAAC;IAEd,cAAc,EAAE,MAAM,CAAC;IAEvB,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB,MAAM,CAAC,EAAE,MAAM,CAAC;IAEhB,OAAO,CAAC,EAAE,OAAO,CAAC;IAElB,SAAS,CAAC,EAAE,OAAO,CAAC;IAEpB,iHAAiH;IACjH,SAAS,CAAC,EAAE,2BAA2B,CAAC;IAExC,eAAe,CAAC,EAAE,MAAM,CAAC;IAEzB,mBAAmB,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CACzC,CAAC;AAEF,MAAM,MAAM,wBAAwB,CAAC,CAAC,IAAI;IACxC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;IAExB,SAAS,EAAE,OAAO,CAAC;IAEnB,OAAO,EAAE,OAAO,CAAC;IAEjB,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;IAEpB,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,wBAAwB,CAAC,CAAC,CAAC,CAAC,CAAC;IAEtD,kBAAkB,EAAE,OAAO,CAAC;IAE5B,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAC9B,CAAC;AA2CF,wBAAgB,qBAAqB,CAAC,CAAC,SAAS,YAAY,EAAE,EAC5D,EAAE,EACF,cAAc,EACd,GAAG,EACH,cAAc,EACd,SAA0B,EAC1B,MAAuB,EACvB,OAAc,EACd,SAAiB,EACjB,SAAmB,EACnB,eAA2B,EAC3B,mBAA4C,GAC7C,EAAE,yBAAyB,GAAG,wBAAwB,CAAC,CAAC,CAAC,CAkLzD"}
|
|
@@ -44,6 +44,7 @@ export function useBatchFirestoreDocs({ db, collectionPath, ids, queryKeyPrefix,
|
|
|
44
44
|
const queryClient = useQueryClient();
|
|
45
45
|
const idsKey = JSON.stringify(ids);
|
|
46
46
|
const uniqueIds = useMemo(() => {
|
|
47
|
+
// idsKey is this hook's own serialization of the ids list.
|
|
47
48
|
const parsed = JSON.parse(idsKey);
|
|
48
49
|
return Array.from(new Set(parsed.filter(Boolean)));
|
|
49
50
|
}, [idsKey]);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useBatchFirestoreDocs.js","sourceRoot":"","sources":["../../../src/react/firestore/useBatchFirestoreDocs.ts"],"names":[],"mappings":"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","sourcesContent":["'use client';\n\nimport { useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport { useQueries, useQueryClient } from '@tanstack/react-query';\nimport type { Firestore } from 'firebase/firestore';\nimport { isListenerOwned, listenerErrorOf, subscribeDoc } from './doc-subscription-registry.js';\nimport { getDocLoader } from './batch-doc-loader.js';\nimport { ABSENT_RETRY_DELAYS_MS, trackAbsentDoc } from './absence-scheduler.js';\nimport type { BatchFirestoreDocOutcome } from '../../firestore/types.js';\nimport { useReadRetryStates, type ReadRetrySource } from '../use-read-retry-state.js';\nimport { isPermissionDeniedError } from './resubscribe.js';\n\nexport type BatchFirestoreDocsTransport = 'batch' | 'get';\n\nexport type BatchFirestoreDocsOptions = {\n db: Firestore;\n\n collectionPath: string;\n\n ids: string[];\n\n queryKeyPrefix: string;\n\n staleTime?: number;\n\n gcTime?: number;\n\n enabled?: boolean;\n\n subscribe?: boolean;\n\n /** `'get'` is required where rules gate reads on `resource.data`: there an id-list query is denied wholesale. */\n transport?: BatchFirestoreDocsTransport;\n\n absentStaleTime?: number;\n\n absentRetryDelaysMs?: readonly number[];\n};\n\nexport type BatchFirestoreDocsResult<T> = {\n data: Record<string, T>;\n\n isLoading: boolean;\n\n isError: boolean;\n\n error: Error | null;\n\n outcomes: Record<string, BatchFirestoreDocOutcome<T>>;\n\n failedReadsRunning: boolean;\n\n refetch: () => Promise<void>;\n};\n\nconst LOADING_OUTCOME = { status: 'loading' } as const;\nconst IDLE_SOURCE: ReadRetrySource<Error> = { error: null, isFetching: false, isLoading: false };\nconst ABSENT_OUTCOME = { status: 'absent' } as const;\n\nfunction sameOutcome<T>(a: BatchFirestoreDocOutcome<T>, b: BatchFirestoreDocOutcome<T>): boolean {\n if (a.status !== b.status) return false;\n if (a.status === 'present') {\n const other = b as { data: T; failure?: { error: Error; retrying: boolean } };\n return (\n a.data === other.data &&\n a.failure?.error === other.failure?.error &&\n a.failure?.retrying === other.failure?.retrying\n );\n }\n if (a.status === 'failed') {\n const other = b as { error: Error; retrying: boolean };\n return a.error === other.error && a.retrying === other.retrying;\n }\n return true;\n}\n\nfunction failedOrHeld<T>(\n value: T | null | undefined,\n error: Error,\n retrying: boolean,\n): BatchFirestoreDocOutcome<T> {\n if (value === null || value === undefined || isPermissionDeniedError(error)) {\n return { status: 'failed', error, retrying };\n }\n return { status: 'present', data: value, failure: { error, retrying } };\n}\n\nfunction shallowRecordEqual<T>(a: Record<string, T>, b: Record<string, T>): boolean {\n const aKeys = Object.keys(a);\n if (aKeys.length !== Object.keys(b).length) return false;\n for (const key of aKeys) {\n if (!Object.prototype.hasOwnProperty.call(b, key) || a[key] !== b[key]) return false;\n }\n return true;\n}\n\nexport function useBatchFirestoreDocs<T extends Record<string, any>>({\n db,\n collectionPath,\n ids,\n queryKeyPrefix,\n staleTime = 30 * 60 * 1000,\n gcTime = 60 * 60 * 1000,\n enabled = true,\n subscribe = false,\n transport = 'batch',\n absentStaleTime = 30 * 1000,\n absentRetryDelaysMs = ABSENT_RETRY_DELAYS_MS,\n}: BatchFirestoreDocsOptions): BatchFirestoreDocsResult<T> {\n const queryClient = useQueryClient();\n\n const idsKey = JSON.stringify(ids);\n\n const uniqueIds = useMemo(() => {\n const parsed: string[] = JSON.parse(idsKey);\n return Array.from(new Set(parsed.filter(Boolean)));\n }, [idsKey]);\n\n const [subscribeErrors, setSubscribeErrors] = useState<Record<string, Error>>({});\n // Query observers notify on React Query's batched microtask; bumping state here shows a snapshot in the tick it lands.\n const [, setSnapshotVersion] = useState(0);\n\n const results = useQueries({\n queries: uniqueIds.map((id) => ({\n queryKey: [queryKeyPrefix, id],\n queryFn: async ({ signal }: { signal: AbortSignal }): Promise<T | null> => {\n const loader = getDocLoader(queryClient, db, collectionPath);\n const loaded =\n transport === 'get'\n ? await loader.loadOne(id, signal)\n : await loader.loadBatched(id, signal);\n // `onSnapshot` does not re-emit until the document changes, so a read that lands after a listener took the key yields to it.\n if (isListenerOwned(queryClient, queryKeyPrefix, id)) {\n const listenerError = listenerErrorOf(queryClient, queryKeyPrefix, id);\n if (listenerError) throw listenerError;\n const owned = queryClient.getQueryData([queryKeyPrefix, id]);\n if (owned !== undefined) return owned as T | null;\n }\n return loaded as T | null;\n },\n enabled: enabled && !subscribe,\n // Opts back into refetch-on-mount (the package default is off) so a remount re-reads a stale id.\n refetchOnMount: !subscribe,\n staleTime: subscribe\n ? Infinity\n : (query: { state: { data: unknown } }) =>\n query.state.data === null ? absentStaleTime : staleTime,\n gcTime,\n })),\n });\n\n useEffect(() => {\n if (!subscribe || !enabled || uniqueIds.length === 0) return;\n setSubscribeErrors({});\n const unsubscribers = uniqueIds.map((id) =>\n subscribeDoc({\n queryClient,\n db,\n collectionPath,\n queryKeyPrefix,\n id,\n onUpdate: () => {\n setSubscribeErrors((errors) => {\n if (!(id in errors)) return errors;\n const { [id]: _cleared, ...rest } = errors;\n return rest;\n });\n setSnapshotVersion((version) => version + 1);\n },\n onError: (error) =>\n setSubscribeErrors((errors) =>\n errors[id] === error ? errors : { ...errors, [id]: error },\n ),\n }),\n );\n return () => {\n for (const unsubscribe of unsubscribers) unsubscribe();\n };\n }, [uniqueIds, subscribe, enabled, collectionPath, queryKeyPrefix, queryClient, db]);\n\n const absentDelaysKey = absentRetryDelaysMs.join(',');\n const absentDelays = useMemo(\n () => absentDelaysKey.split(',').filter(Boolean).map(Number),\n [absentDelaysKey],\n );\n\n useEffect(() => {\n if (uniqueIds.length === 0) return;\n const releases = uniqueIds.map((id) =>\n trackAbsentDoc({ queryClient, queryKey: [queryKeyPrefix, id], delays: absentDelays }),\n );\n return () => {\n for (const release of releases) release();\n };\n }, [uniqueIds, queryKeyPrefix, queryClient, absentDelays]);\n\n // Only the effect writes these refs, so a concurrent render React discards never leaves them on an uncommitted map.\n const committedDataRef = useRef<Record<string, T>>({});\n const committedOutcomesRef = useRef<Record<string, BatchFirestoreDocOutcome<T>>>({});\n\n // TanStack clears a never-answered read's error as its refetch starts, so the failure is held through the retry.\n const retryStates = useReadRetryStates(\n uniqueIds.map((id, index) => ({\n source: (results[index] ?? IDLE_SOURCE) as ReadRetrySource<Error>,\n queryKey: [queryKeyPrefix, id],\n })),\n );\n\n const nextData: Record<string, T> = {};\n const nextOutcomes: Record<string, BatchFirestoreDocOutcome<T>> = {};\n let anyError: Error | null = null;\n let anyListenerError: Error | null = null;\n let oneShotLoading = false;\n let anyUnresolved = false;\n let failedReadsRunning = false;\n\n for (let index = 0; index < uniqueIds.length; index += 1) {\n const id = uniqueIds[index];\n const result = results[index];\n let outcome: BatchFirestoreDocOutcome<T> = LOADING_OUTCOME;\n const listenerError =\n (subscribe ? subscribeErrors[id] : undefined) ??\n listenerErrorOf(queryClient, queryKeyPrefix, id) ??\n undefined;\n if (\n result &&\n (result.isFetching || result.isPaused) &&\n result.errorUpdatedAt > result.dataUpdatedAt\n ) {\n failedReadsRunning = true;\n }\n const retryState = retryStates[index];\n if (result?.isError) anyError ??= result.error as Error;\n const value = result?.data as T | null | undefined;\n if (retryState && retryState.error !== null) {\n outcome = failedOrHeld(value, retryState.error, retryState.isRetrying);\n } else if (result) {\n if (result.isLoading) oneShotLoading = true;\n if (value === undefined) anyUnresolved = true;\n if (listenerError) {\n anyListenerError ??= listenerError;\n outcome = failedOrHeld(value, listenerError, false);\n } else if (value === null) {\n outcome = ABSENT_OUTCOME;\n } else if (value !== undefined) {\n outcome = { status: 'present', data: value };\n }\n }\n if (outcome.status === 'present') nextData[id] = outcome.data;\n const committed = committedOutcomesRef.current[id];\n nextOutcomes[id] = committed && sameOutcome(committed, outcome) ? committed : outcome;\n }\n\n const data = shallowRecordEqual(committedDataRef.current, nextData)\n ? committedDataRef.current\n : nextData;\n const outcomes = shallowRecordEqual(committedOutcomesRef.current, nextOutcomes)\n ? committedOutcomesRef.current\n : nextOutcomes;\n\n useEffect(() => {\n committedDataRef.current = data;\n committedOutcomesRef.current = outcomes;\n }, [data, outcomes]);\n\n const refetch = useCallback(async () => {\n if (subscribe || !enabled) return;\n await Promise.all(\n uniqueIds.map((id) =>\n queryClient.refetchQueries({ queryKey: [queryKeyPrefix, id], exact: true }),\n ),\n );\n }, [uniqueIds, subscribe, enabled, queryClient, queryKeyPrefix]);\n\n const isLoading = subscribe ? enabled && anyUnresolved : oneShotLoading;\n\n return {\n data,\n isLoading,\n isError: anyError !== null || anyListenerError !== null,\n error: anyError ?? anyListenerError,\n outcomes,\n failedReadsRunning,\n refetch,\n };\n}\n"]}
|
|
1
|
+
{"version":3,"file":"useBatchFirestoreDocs.js","sourceRoot":"","sources":["../../../src/react/firestore/useBatchFirestoreDocs.ts"],"names":[],"mappings":"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","sourcesContent":["'use client';\n\nimport { useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport { useQueries, useQueryClient } from '@tanstack/react-query';\nimport type { DocumentData, Firestore } from 'firebase/firestore';\nimport { isListenerOwned, listenerErrorOf, subscribeDoc } from './doc-subscription-registry.js';\nimport { getDocLoader } from './batch-doc-loader.js';\nimport { ABSENT_RETRY_DELAYS_MS, trackAbsentDoc } from './absence-scheduler.js';\nimport type { BatchFirestoreDocOutcome } from '../../firestore/types.js';\nimport { useReadRetryStates, type ReadRetrySource } from '../use-read-retry-state.js';\nimport { isPermissionDeniedError } from './resubscribe.js';\n\nexport type BatchFirestoreDocsTransport = 'batch' | 'get';\n\nexport type BatchFirestoreDocsOptions = {\n db: Firestore;\n\n collectionPath: string;\n\n ids: string[];\n\n queryKeyPrefix: string;\n\n staleTime?: number;\n\n gcTime?: number;\n\n enabled?: boolean;\n\n subscribe?: boolean;\n\n /** `'get'` is required where rules gate reads on `resource.data`: there an id-list query is denied wholesale. */\n transport?: BatchFirestoreDocsTransport;\n\n absentStaleTime?: number;\n\n absentRetryDelaysMs?: readonly number[];\n};\n\nexport type BatchFirestoreDocsResult<T> = {\n data: Record<string, T>;\n\n isLoading: boolean;\n\n isError: boolean;\n\n error: Error | null;\n\n outcomes: Record<string, BatchFirestoreDocOutcome<T>>;\n\n failedReadsRunning: boolean;\n\n refetch: () => Promise<void>;\n};\n\nconst LOADING_OUTCOME = { status: 'loading' } as const;\nconst IDLE_SOURCE: ReadRetrySource<Error> = { error: null, isFetching: false, isLoading: false };\nconst ABSENT_OUTCOME = { status: 'absent' } as const;\n\nfunction sameOutcome<T>(a: BatchFirestoreDocOutcome<T>, b: BatchFirestoreDocOutcome<T>): boolean {\n if (a.status !== b.status) return false;\n if (a.status === 'present') {\n const other = b as { data: T; failure?: { error: Error; retrying: boolean } };\n return (\n a.data === other.data &&\n a.failure?.error === other.failure?.error &&\n a.failure?.retrying === other.failure?.retrying\n );\n }\n if (a.status === 'failed') {\n const other = b as { error: Error; retrying: boolean };\n return a.error === other.error && a.retrying === other.retrying;\n }\n return true;\n}\n\nfunction failedOrHeld<T>(\n value: T | null | undefined,\n error: Error,\n retrying: boolean,\n): BatchFirestoreDocOutcome<T> {\n if (value === null || value === undefined || isPermissionDeniedError(error)) {\n return { status: 'failed', error, retrying };\n }\n return { status: 'present', data: value, failure: { error, retrying } };\n}\n\nfunction shallowRecordEqual<T>(a: Record<string, T>, b: Record<string, T>): boolean {\n const aKeys = Object.keys(a);\n if (aKeys.length !== Object.keys(b).length) return false;\n for (const key of aKeys) {\n if (!Object.prototype.hasOwnProperty.call(b, key) || a[key] !== b[key]) return false;\n }\n return true;\n}\n\nexport function useBatchFirestoreDocs<T extends DocumentData>({\n db,\n collectionPath,\n ids,\n queryKeyPrefix,\n staleTime = 30 * 60 * 1000,\n gcTime = 60 * 60 * 1000,\n enabled = true,\n subscribe = false,\n transport = 'batch',\n absentStaleTime = 30 * 1000,\n absentRetryDelaysMs = ABSENT_RETRY_DELAYS_MS,\n}: BatchFirestoreDocsOptions): BatchFirestoreDocsResult<T> {\n const queryClient = useQueryClient();\n\n const idsKey = JSON.stringify(ids);\n\n const uniqueIds = useMemo(() => {\n // idsKey is this hook's own serialization of the ids list.\n const parsed = JSON.parse(idsKey) as string[];\n return Array.from(new Set(parsed.filter(Boolean)));\n }, [idsKey]);\n\n const [subscribeErrors, setSubscribeErrors] = useState<Record<string, Error>>({});\n // Query observers notify on React Query's batched microtask; bumping state here shows a snapshot in the tick it lands.\n const [, setSnapshotVersion] = useState(0);\n\n const results = useQueries({\n queries: uniqueIds.map((id) => ({\n queryKey: [queryKeyPrefix, id],\n queryFn: async ({ signal }: { signal: AbortSignal }): Promise<T | null> => {\n const loader = getDocLoader(queryClient, db, collectionPath);\n const loaded =\n transport === 'get'\n ? await loader.loadOne(id, signal)\n : await loader.loadBatched(id, signal);\n // `onSnapshot` does not re-emit until the document changes, so a read that lands after a listener took the key yields to it.\n if (isListenerOwned(queryClient, queryKeyPrefix, id)) {\n const listenerError = listenerErrorOf(queryClient, queryKeyPrefix, id);\n if (listenerError) throw listenerError;\n const owned = queryClient.getQueryData([queryKeyPrefix, id]);\n if (owned !== undefined) return owned as T | null;\n }\n return loaded as T | null;\n },\n enabled: enabled && !subscribe,\n // Opts back into refetch-on-mount (the package default is off) so a remount re-reads a stale id.\n refetchOnMount: !subscribe,\n staleTime: subscribe\n ? Infinity\n : (query: { state: { data: unknown } }) =>\n query.state.data === null ? absentStaleTime : staleTime,\n gcTime,\n })),\n });\n\n useEffect(() => {\n if (!subscribe || !enabled || uniqueIds.length === 0) return;\n setSubscribeErrors({});\n const unsubscribers = uniqueIds.map((id) =>\n subscribeDoc({\n queryClient,\n db,\n collectionPath,\n queryKeyPrefix,\n id,\n onUpdate: () => {\n setSubscribeErrors((errors) => {\n if (!(id in errors)) return errors;\n const { [id]: _cleared, ...rest } = errors;\n return rest;\n });\n setSnapshotVersion((version) => version + 1);\n },\n onError: (error) =>\n setSubscribeErrors((errors) =>\n errors[id] === error ? errors : { ...errors, [id]: error },\n ),\n }),\n );\n return () => {\n for (const unsubscribe of unsubscribers) unsubscribe();\n };\n }, [uniqueIds, subscribe, enabled, collectionPath, queryKeyPrefix, queryClient, db]);\n\n const absentDelaysKey = absentRetryDelaysMs.join(',');\n const absentDelays = useMemo(\n () => absentDelaysKey.split(',').filter(Boolean).map(Number),\n [absentDelaysKey],\n );\n\n useEffect(() => {\n if (uniqueIds.length === 0) return;\n const releases = uniqueIds.map((id) =>\n trackAbsentDoc({ queryClient, queryKey: [queryKeyPrefix, id], delays: absentDelays }),\n );\n return () => {\n for (const release of releases) release();\n };\n }, [uniqueIds, queryKeyPrefix, queryClient, absentDelays]);\n\n // Only the effect writes these refs, so a concurrent render React discards never leaves them on an uncommitted map.\n const committedDataRef = useRef<Record<string, T>>({});\n const committedOutcomesRef = useRef<Record<string, BatchFirestoreDocOutcome<T>>>({});\n\n // TanStack clears a never-answered read's error as its refetch starts, so the failure is held through the retry.\n const retryStates = useReadRetryStates(\n uniqueIds.map((id, index) => ({\n source: (results[index] ?? IDLE_SOURCE) as ReadRetrySource<Error>,\n queryKey: [queryKeyPrefix, id],\n })),\n );\n\n const nextData: Record<string, T> = {};\n const nextOutcomes: Record<string, BatchFirestoreDocOutcome<T>> = {};\n let anyError: Error | null = null;\n let anyListenerError: Error | null = null;\n let oneShotLoading = false;\n let anyUnresolved = false;\n let failedReadsRunning = false;\n\n for (let index = 0; index < uniqueIds.length; index += 1) {\n const id = uniqueIds[index];\n const result = results[index];\n let outcome: BatchFirestoreDocOutcome<T> = LOADING_OUTCOME;\n const listenerError =\n (subscribe ? subscribeErrors[id] : undefined) ??\n listenerErrorOf(queryClient, queryKeyPrefix, id) ??\n undefined;\n if (\n result &&\n (result.isFetching || result.isPaused) &&\n result.errorUpdatedAt > result.dataUpdatedAt\n ) {\n failedReadsRunning = true;\n }\n const retryState = retryStates[index];\n if (result?.isError) anyError ??= result.error as Error;\n const value = result?.data as T | null | undefined;\n if (retryState && retryState.error !== null) {\n outcome = failedOrHeld(value, retryState.error, retryState.isRetrying);\n } else if (result) {\n if (result.isLoading) oneShotLoading = true;\n if (value === undefined) anyUnresolved = true;\n if (listenerError) {\n anyListenerError ??= listenerError;\n outcome = failedOrHeld(value, listenerError, false);\n } else if (value === null) {\n outcome = ABSENT_OUTCOME;\n } else if (value !== undefined) {\n outcome = { status: 'present', data: value };\n }\n }\n if (outcome.status === 'present') nextData[id] = outcome.data;\n const committed = committedOutcomesRef.current[id];\n nextOutcomes[id] = committed && sameOutcome(committed, outcome) ? committed : outcome;\n }\n\n const data = shallowRecordEqual(committedDataRef.current, nextData)\n ? committedDataRef.current\n : nextData;\n const outcomes = shallowRecordEqual(committedOutcomesRef.current, nextOutcomes)\n ? committedOutcomesRef.current\n : nextOutcomes;\n\n useEffect(() => {\n committedDataRef.current = data;\n committedOutcomesRef.current = outcomes;\n }, [data, outcomes]);\n\n const refetch = useCallback(async () => {\n if (subscribe || !enabled) return;\n await Promise.all(\n uniqueIds.map((id) =>\n queryClient.refetchQueries({ queryKey: [queryKeyPrefix, id], exact: true }),\n ),\n );\n }, [uniqueIds, subscribe, enabled, queryClient, queryKeyPrefix]);\n\n const isLoading = subscribe ? enabled && anyUnresolved : oneShotLoading;\n\n return {\n data,\n isLoading,\n isError: anyError !== null || anyListenerError !== null,\n error: anyError ?? anyListenerError,\n outcomes,\n failedReadsRunning,\n refetch,\n };\n}\n"]}
|
package/dist/react/index.d.ts
CHANGED
|
@@ -30,7 +30,7 @@ export type { FirestoreSearchOptions } from './search/types.js';
|
|
|
30
30
|
export { useReadRetryState, useReadRetryStates } from './use-read-retry-state.js';
|
|
31
31
|
export type { ReadRetryEntry, ReadRetrySource, ReadRetryState } from './use-read-retry-state.js';
|
|
32
32
|
export { MutationSessionProvider, MutationSessionEndedError, useSessionMutation, } from './session-mutation.js';
|
|
33
|
-
export type { MutationSession, MutationSessionProviderProps, SessionMutationFunctionContext, SessionMutationOptions, } from './session-mutation.js';
|
|
33
|
+
export type { MutationSession, MutationSessionProviderProps, SessionMutateOptions, SessionMutationFunctionContext, SessionMutationOptions, SessionMutationResult, } from './session-mutation.js';
|
|
34
34
|
export { createCallables, MAX_RESUMABLE_CALLS } from './callables/create-callables.js';
|
|
35
35
|
export type { CallableCaptureContext, CallableDeclaration, CallableErrorRouting, CallableMutationOptions, CallablePolicy, Callables, ResumableOutcome, } from './callables/create-callables.js';
|
|
36
36
|
export { usePendingMutationVariables, pendingMutationVariables, usePendingMutationTargets, hasPendingMutation, duplicateSubmissionError, useDuplicateGuardedMutation, } from './pending-mutations.js';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/react/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AACtD,YAAY,EAAE,wBAAwB,EAAE,MAAM,mBAAmB,CAAC;AAElE,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAC9C,YAAY,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AAExD,OAAO,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAC3E,YAAY,EAAE,sBAAsB,EAAE,MAAM,wBAAwB,CAAC;AAErE,OAAO,EAAE,eAAe,EAAE,MAAM,kCAAkC,CAAC;AACnE,OAAO,EAAE,sBAAsB,EAAE,MAAM,yCAAyC,CAAC;AACjF,OAAO,EAAE,oBAAoB,EAAE,MAAM,uCAAuC,CAAC;AAC7E,OAAO,EAAE,qBAAqB,EAAE,MAAM,wCAAwC,CAAC;AAC/E,YAAY,EAAE,2BAA2B,EAAE,MAAM,wCAAwC,CAAC;AAC1F,OAAO,EAAE,iBAAiB,EAAE,MAAM,oCAAoC,CAAC;AACvE,OAAO,EAAE,wBAAwB,EAAE,MAAM,4CAA4C,CAAC;AACtF,YAAY,EAAE,2BAA2B,EAAE,MAAM,4CAA4C,CAAC;AAE9F,OAAO,EACL,eAAe,EACf,kBAAkB,EAClB,kBAAkB,EAClB,iBAAiB,GAClB,MAAM,wCAAwC,CAAC;AAEhD,OAAO,EAAE,qBAAqB,EAAE,MAAM,sCAAsC,CAAC;AAC7E,YAAY,EACV,yBAAyB,EACzB,wBAAwB,EACxB,2BAA2B,GAC5B,MAAM,sCAAsC,CAAC;AAC9C,OAAO,EAAE,sBAAsB,EAAE,MAAM,kCAAkC,CAAC;AAE1E,OAAO,EAAE,kBAAkB,EAAE,MAAM,kCAAkC,CAAC;AAEtE,OAAO,EACL,kBAAkB,EAClB,cAAc,EACd,eAAe,EACf,gBAAgB,EAChB,iBAAiB,EACjB,2BAA2B,EAC3B,eAAe,GAChB,MAAM,oBAAoB,CAAC;AAC5B,YAAY,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAEpD,OAAO,EAAE,4BAA4B,EAAE,MAAM,oDAAoD,CAAC;AAClG,OAAO,EACL,KAAK,EACL,MAAM,EACN,SAAS,EACT,qBAAqB,EACrB,kBAAkB,GACnB,MAAM,uCAAuC,CAAC;AAC/C,YAAY,EACV,sBAAsB,EACtB,+BAA+B,GAChC,MAAM,oDAAoD,CAAC;AAC5D,YAAY,EACV,WAAW,EACX,iBAAiB,EACjB,WAAW,GACZ,MAAM,uCAAuC,CAAC;AAE/C,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AACjD,YAAY,EACV,mBAAmB,EACnB,0BAA0B,EAC1B,wBAAwB,EACxB,yBAAyB,EACzB,qBAAqB,EACrB,4BAA4B,EAC5B,YAAY,EACZ,aAAa,EACb,iBAAiB,GAClB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,mBAAmB,EAAE,oBAAoB,EAAE,MAAM,iCAAiC,CAAC;AAC5F,YAAY,EAAE,sBAAsB,EAAE,MAAM,mBAAmB,CAAC;AAEhE,OAAO,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAClF,YAAY,EAAE,cAAc,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAEjG,OAAO,EACL,uBAAuB,EACvB,yBAAyB,EACzB,kBAAkB,GACnB,MAAM,uBAAuB,CAAC;AAC/B,YAAY,EACV,eAAe,EACf,4BAA4B,EAC5B,8BAA8B,EAC9B,sBAAsB,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/react/index.ts"],"names":[],"mappings":"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"}
|
package/dist/react/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/react/index.ts"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAEb,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAGtD,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAG9C,OAAO,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAG3E,OAAO,EAAE,eAAe,EAAE,MAAM,kCAAkC,CAAC;AACnE,OAAO,EAAE,sBAAsB,EAAE,MAAM,yCAAyC,CAAC;AACjF,OAAO,EAAE,oBAAoB,EAAE,MAAM,uCAAuC,CAAC;AAC7E,OAAO,EAAE,qBAAqB,EAAE,MAAM,wCAAwC,CAAC;AAE/E,OAAO,EAAE,iBAAiB,EAAE,MAAM,oCAAoC,CAAC;AACvE,OAAO,EAAE,wBAAwB,EAAE,MAAM,4CAA4C,CAAC;AAGtF,OAAO,EACL,eAAe,EACf,kBAAkB,EAClB,kBAAkB,EAClB,iBAAiB,GAClB,MAAM,wCAAwC,CAAC;AAEhD,OAAO,EAAE,qBAAqB,EAAE,MAAM,sCAAsC,CAAC;AAM7E,OAAO,EAAE,sBAAsB,EAAE,MAAM,kCAAkC,CAAC;AAE1E,OAAO,EAAE,kBAAkB,EAAE,MAAM,kCAAkC,CAAC;AAEtE,OAAO,EACL,kBAAkB,EAClB,cAAc,EACd,eAAe,EACf,gBAAgB,EAChB,iBAAiB,EACjB,2BAA2B,EAC3B,eAAe,GAChB,MAAM,oBAAoB,CAAC;AAG5B,OAAO,EAAE,4BAA4B,EAAE,MAAM,oDAAoD,CAAC;AAClG,OAAO,EACL,KAAK,EACL,MAAM,EACN,SAAS,EACT,qBAAqB,EACrB,kBAAkB,GACnB,MAAM,uCAAuC,CAAC;AAW/C,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAYjD,OAAO,EAAE,mBAAmB,EAAE,oBAAoB,EAAE,MAAM,iCAAiC,CAAC;AAG5F,OAAO,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAGlF,OAAO,EACL,uBAAuB,EACvB,yBAAyB,EACzB,kBAAkB,GACnB,MAAM,uBAAuB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/react/index.ts"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAEb,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAGtD,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAG9C,OAAO,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAG3E,OAAO,EAAE,eAAe,EAAE,MAAM,kCAAkC,CAAC;AACnE,OAAO,EAAE,sBAAsB,EAAE,MAAM,yCAAyC,CAAC;AACjF,OAAO,EAAE,oBAAoB,EAAE,MAAM,uCAAuC,CAAC;AAC7E,OAAO,EAAE,qBAAqB,EAAE,MAAM,wCAAwC,CAAC;AAE/E,OAAO,EAAE,iBAAiB,EAAE,MAAM,oCAAoC,CAAC;AACvE,OAAO,EAAE,wBAAwB,EAAE,MAAM,4CAA4C,CAAC;AAGtF,OAAO,EACL,eAAe,EACf,kBAAkB,EAClB,kBAAkB,EAClB,iBAAiB,GAClB,MAAM,wCAAwC,CAAC;AAEhD,OAAO,EAAE,qBAAqB,EAAE,MAAM,sCAAsC,CAAC;AAM7E,OAAO,EAAE,sBAAsB,EAAE,MAAM,kCAAkC,CAAC;AAE1E,OAAO,EAAE,kBAAkB,EAAE,MAAM,kCAAkC,CAAC;AAEtE,OAAO,EACL,kBAAkB,EAClB,cAAc,EACd,eAAe,EACf,gBAAgB,EAChB,iBAAiB,EACjB,2BAA2B,EAC3B,eAAe,GAChB,MAAM,oBAAoB,CAAC;AAG5B,OAAO,EAAE,4BAA4B,EAAE,MAAM,oDAAoD,CAAC;AAClG,OAAO,EACL,KAAK,EACL,MAAM,EACN,SAAS,EACT,qBAAqB,EACrB,kBAAkB,GACnB,MAAM,uCAAuC,CAAC;AAW/C,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAYjD,OAAO,EAAE,mBAAmB,EAAE,oBAAoB,EAAE,MAAM,iCAAiC,CAAC;AAG5F,OAAO,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAGlF,OAAO,EACL,uBAAuB,EACvB,yBAAyB,EACzB,kBAAkB,GACnB,MAAM,uBAAuB,CAAC;AAU/B,OAAO,EAAE,eAAe,EAAE,mBAAmB,EAAE,MAAM,iCAAiC,CAAC;AAWvF,OAAO,EACL,2BAA2B,EAC3B,wBAAwB,EACxB,yBAAyB,EACzB,kBAAkB,EAClB,wBAAwB,EACxB,2BAA2B,GAC5B,MAAM,wBAAwB,CAAC","sourcesContent":["'use client';\n\nexport { createQueryClient } from './query-client.js';\nexport type { CreateQueryClientOptions } from './query-client.js';\n\nexport { QueryProvider } from './provider.js';\nexport type { QueryProviderProps } from './provider.js';\n\nexport { FirestoreProvider, useFirestoreDb } from './firestore/context.js';\nexport type { FirestoreProviderProps } from './firestore/context.js';\n\nexport { useFirestoreDoc } from './firestore/use-firestore-doc.js';\nexport { useFirestoreCollection } from './firestore/use-firestore-collection.js';\nexport { useFirestoreInfinite } from './firestore/use-firestore-infinite.js';\nexport { useFirestorePaginated } from './firestore/use-firestore-paginated.js';\nexport type { UseFirestorePaginatedResult } from './firestore/use-firestore-paginated.js';\nexport { useFirestoreCount } from './firestore/use-firestore-count.js';\nexport { useFirestoreLiveInfinite } from './firestore/use-firestore-live-infinite.js';\nexport type { FirestoreLiveInfiniteResult } from './firestore/use-firestore-live-infinite.js';\n\nexport {\n useFirestoreSet,\n useFirestoreUpdate,\n useFirestoreDelete,\n useFirestoreBatch,\n} from './firestore/use-firestore-mutations.js';\n\nexport { useBatchFirestoreDocs } from './firestore/useBatchFirestoreDocs.js';\nexport type {\n BatchFirestoreDocsOptions,\n BatchFirestoreDocsResult,\n BatchFirestoreDocsTransport,\n} from './firestore/useBatchFirestoreDocs.js';\nexport { ABSENT_RETRY_DELAYS_MS } from './firestore/absence-scheduler.js';\n\nexport { useFirestoreSearch } from './search/use-firestore-search.js';\n\nexport {\n invalidateByPrefix,\n removeByPrefix,\n updateQueryData,\n paginatedPageKey,\n mapPaginatedItems,\n prependToFirstPaginatedPage,\n placeRowInPages,\n} from './cache-helpers.js';\nexport type { PagedRows } from './cache-helpers.js';\n\nexport { createDomainEventInvalidator } from './domain-events/create-domain-event-invalidator.js';\nexport {\n exact,\n prefix,\n predicate,\n serializeInvalidation,\n applyInvalidations,\n} from './domain-events/cache-invalidation.js';\nexport type {\n DomainEventInvalidator,\n DomainEventInvalidationRegistry,\n} from './domain-events/create-domain-event-invalidator.js';\nexport type {\n CacheAction,\n CacheInvalidation,\n RefetchType,\n} from './domain-events/cache-invalidation.js';\n\nexport { docWithId } from './firestore/types.js';\nexport type {\n FirestoreDocOptions,\n FirestoreCollectionOptions,\n FirestoreInfiniteOptions,\n FirestorePaginatedOptions,\n FirestoreCountOptions,\n FirestoreLiveInfiniteOptions,\n InfinitePage,\n PaginatedPage,\n MutationOperation,\n} from './firestore/types.js';\nexport { flattenInfiniteData, getInfiniteDataCount } from './firestore/infinite-helpers.js';\nexport type { FirestoreSearchOptions } from './search/types.js';\n\nexport { useReadRetryState, useReadRetryStates } from './use-read-retry-state.js';\nexport type { ReadRetryEntry, ReadRetrySource, ReadRetryState } from './use-read-retry-state.js';\n\nexport {\n MutationSessionProvider,\n MutationSessionEndedError,\n useSessionMutation,\n} from './session-mutation.js';\nexport type {\n MutationSession,\n MutationSessionProviderProps,\n SessionMutateOptions,\n SessionMutationFunctionContext,\n SessionMutationOptions,\n SessionMutationResult,\n} from './session-mutation.js';\n\nexport { createCallables, MAX_RESUMABLE_CALLS } from './callables/create-callables.js';\nexport type {\n CallableCaptureContext,\n CallableDeclaration,\n CallableErrorRouting,\n CallableMutationOptions,\n CallablePolicy,\n Callables,\n ResumableOutcome,\n} from './callables/create-callables.js';\n\nexport {\n usePendingMutationVariables,\n pendingMutationVariables,\n usePendingMutationTargets,\n hasPendingMutation,\n duplicateSubmissionError,\n useDuplicateGuardedMutation,\n} from './pending-mutations.js';\n"]}
|
|
@@ -8,8 +8,22 @@ export interface MutationSession {
|
|
|
8
8
|
export type SessionMutationFunctionContext = MutationFunctionContext & {
|
|
9
9
|
session: MutationSession;
|
|
10
10
|
};
|
|
11
|
-
export type SessionMutationOptions<TData = unknown, TError = DefaultError, TVariables = void, TOnMutateResult = unknown> = Omit<UseMutationOptions<TData, TError, TVariables, TOnMutateResult>, 'mutationFn'> & {
|
|
11
|
+
export type SessionMutationOptions<TData = unknown, TError = DefaultError, TVariables = void, TOnMutateResult = unknown> = Omit<UseMutationOptions<TData, TError, TVariables, TOnMutateResult>, 'mutationFn' | 'onMutate' | 'onSuccess' | 'onError' | 'onSettled'> & {
|
|
12
12
|
mutationFn: (variables: TVariables, context: SessionMutationFunctionContext) => Promise<TData>;
|
|
13
|
+
onMutate?: (variables: TVariables, context: SessionMutationFunctionContext) => Promise<TOnMutateResult> | TOnMutateResult;
|
|
14
|
+
onSuccess?: (data: TData, variables: TVariables, onMutateResult: TOnMutateResult, context: SessionMutationFunctionContext) => Promise<unknown> | unknown;
|
|
15
|
+
onError?: (error: TError, variables: TVariables, onMutateResult: TOnMutateResult | undefined, context: SessionMutationFunctionContext) => Promise<unknown> | unknown;
|
|
16
|
+
onSettled?: (data: TData | undefined, error: TError | null, variables: TVariables, onMutateResult: TOnMutateResult | undefined, context: SessionMutationFunctionContext) => Promise<unknown> | unknown;
|
|
17
|
+
};
|
|
18
|
+
export interface SessionMutateOptions<TData, TError, TVariables, TOnMutateResult> {
|
|
19
|
+
onSuccess?: (data: TData, variables: TVariables, onMutateResult: TOnMutateResult | undefined, context: SessionMutationFunctionContext) => void;
|
|
20
|
+
onError?: (error: TError, variables: TVariables, onMutateResult: TOnMutateResult | undefined, context: SessionMutationFunctionContext) => void;
|
|
21
|
+
onSettled?: (data: TData | undefined, error: TError | null, variables: TVariables, onMutateResult: TOnMutateResult | undefined, context: SessionMutationFunctionContext) => void;
|
|
22
|
+
}
|
|
23
|
+
type DistributiveOmit<T, K extends PropertyKey> = T extends unknown ? Omit<T, K> : never;
|
|
24
|
+
export type SessionMutationResult<TData = unknown, TError = DefaultError, TVariables = void, TOnMutateResult = unknown> = DistributiveOmit<UseMutationResult<TData, TError, TVariables, TOnMutateResult>, 'mutate' | 'mutateAsync'> & {
|
|
25
|
+
mutate: (variables: TVariables, options?: SessionMutateOptions<TData, TError, TVariables, TOnMutateResult>) => void;
|
|
26
|
+
mutateAsync: (variables: TVariables, options?: SessionMutateOptions<TData, TError, TVariables, TOnMutateResult>) => Promise<TData>;
|
|
13
27
|
};
|
|
14
28
|
export declare class MutationSessionEndedError extends Error {
|
|
15
29
|
name: string;
|
|
@@ -23,5 +37,6 @@ export interface MutationSessionProviderProps {
|
|
|
23
37
|
}
|
|
24
38
|
export declare function MutationSessionProvider({ currentUid, children }: MutationSessionProviderProps): import("react").JSX.Element;
|
|
25
39
|
export declare function useMutationSessionCapture(): () => MutationSession;
|
|
26
|
-
export declare function useSessionMutation<TData = unknown, TError = DefaultError, TVariables = void, TOnMutateResult = unknown>(options: SessionMutationOptions<TData, TError, TVariables, TOnMutateResult>):
|
|
40
|
+
export declare function useSessionMutation<TData = unknown, TError = DefaultError, TVariables = void, TOnMutateResult = unknown>(options: SessionMutationOptions<TData, TError, TVariables, TOnMutateResult>): SessionMutationResult<TData, TError, TVariables, TOnMutateResult>;
|
|
41
|
+
export {};
|
|
27
42
|
//# sourceMappingURL=session-mutation.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"session-mutation.d.ts","sourceRoot":"","sources":["../../src/react/session-mutation.tsx"],"names":[],"mappings":"AAEA,OAAO,EAML,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AACf,OAAO,EAGL,KAAK,YAAY,EAEjB,KAAK,uBAAuB,EAC5B,KAAK,kBAAkB,EACvB,KAAK,iBAAiB,EACvB,MAAM,uBAAuB,CAAC;AAE/B,MAAM,WAAW,eAAe;IAC9B,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IACnB,SAAS,IAAI,OAAO,CAAC;IACrB,aAAa,IAAI,IAAI,CAAC;CACvB;AAED,MAAM,MAAM,8BAA8B,GAAG,uBAAuB,GAAG;IACrE,OAAO,EAAE,eAAe,CAAC;CAC1B,CAAC;AAEF,MAAM,MAAM,sBAAsB,CAChC,KAAK,GAAG,OAAO,EACf,MAAM,GAAG,YAAY,EACrB,UAAU,GAAG,IAAI,EACjB,eAAe,GAAG,OAAO,IACvB,IAAI,
|
|
1
|
+
{"version":3,"file":"session-mutation.d.ts","sourceRoot":"","sources":["../../src/react/session-mutation.tsx"],"names":[],"mappings":"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"}
|
|
@@ -67,33 +67,51 @@ function throwsToBoundary(throwOnError, error) {
|
|
|
67
67
|
return throwOnError(error);
|
|
68
68
|
return throwOnError === true;
|
|
69
69
|
}
|
|
70
|
+
function withSession(context, session) {
|
|
71
|
+
return { ...context, session };
|
|
72
|
+
}
|
|
70
73
|
function fenceCallOptions(session, options) {
|
|
71
74
|
if (!options)
|
|
72
75
|
return undefined;
|
|
73
76
|
const { onSuccess, onError, onSettled } = options;
|
|
74
77
|
return {
|
|
75
78
|
onSuccess: onSuccess
|
|
76
|
-
? (
|
|
77
|
-
if (session.isCurrent())
|
|
78
|
-
onSuccess(
|
|
79
|
+
? (data, variables, onMutateResult, context) => {
|
|
80
|
+
if (session.isCurrent()) {
|
|
81
|
+
onSuccess(data, variables, onMutateResult, withSession(context, session));
|
|
82
|
+
}
|
|
79
83
|
}
|
|
80
84
|
: undefined,
|
|
81
85
|
onError: onError
|
|
82
|
-
? (error,
|
|
86
|
+
? (error, variables, onMutateResult, context) => {
|
|
83
87
|
if (!(error instanceof MutationSessionEndedError) && session.isCurrent()) {
|
|
84
|
-
onError(error,
|
|
88
|
+
onError(error, variables, onMutateResult, withSession(context, session));
|
|
85
89
|
}
|
|
86
90
|
}
|
|
87
91
|
: undefined,
|
|
88
92
|
onSettled: onSettled
|
|
89
|
-
? (data, error,
|
|
93
|
+
? (data, error, variables, onMutateResult, context) => {
|
|
90
94
|
if (!(error instanceof MutationSessionEndedError) && session.isCurrent()) {
|
|
91
|
-
onSettled(data, error,
|
|
95
|
+
onSettled(data, error, variables, onMutateResult, withSession(context, session));
|
|
92
96
|
}
|
|
93
97
|
}
|
|
94
98
|
: undefined,
|
|
95
99
|
};
|
|
96
100
|
}
|
|
101
|
+
async function settleInSession(session, settled) {
|
|
102
|
+
let data;
|
|
103
|
+
try {
|
|
104
|
+
data = await settled;
|
|
105
|
+
}
|
|
106
|
+
catch (error) {
|
|
107
|
+
if (!(error instanceof MutationSessionEndedError) && !session.isCurrent()) {
|
|
108
|
+
throw new MutationSessionEndedError({ cause: error });
|
|
109
|
+
}
|
|
110
|
+
throw error;
|
|
111
|
+
}
|
|
112
|
+
session.assertCurrent();
|
|
113
|
+
return data;
|
|
114
|
+
}
|
|
97
115
|
export function useSessionMutation(options) {
|
|
98
116
|
const store = useContext(MutationSessionContext);
|
|
99
117
|
const queryClient = useQueryClient();
|
|
@@ -106,9 +124,10 @@ export function useSessionMutation(options) {
|
|
|
106
124
|
retry: (failureCount, error) => retriesAfter(baseRetry, failureCount, error),
|
|
107
125
|
throwOnError: (error) => throwsToBoundary(baseThrowOnError, error),
|
|
108
126
|
onMutate: (variables, context) => {
|
|
127
|
+
const session = store ? captureSession(store) : ALWAYS_CURRENT;
|
|
109
128
|
if (store)
|
|
110
|
-
runSessions.set(context,
|
|
111
|
-
return onMutate?.(variables, context);
|
|
129
|
+
runSessions.set(context, session);
|
|
130
|
+
return onMutate?.(variables, withSession(context, session));
|
|
112
131
|
},
|
|
113
132
|
mutationFn: async (variables, context) => {
|
|
114
133
|
const session = store ? runSessions.get(context) : ALWAYS_CURRENT;
|
|
@@ -129,22 +148,28 @@ export function useSessionMutation(options) {
|
|
|
129
148
|
onSuccess: (data, variables, onMutateResult, context) => {
|
|
130
149
|
if (runHasEnded(store, context))
|
|
131
150
|
return;
|
|
132
|
-
return onSuccess?.(data, variables, onMutateResult, context);
|
|
151
|
+
return onSuccess?.(data, variables, onMutateResult, withSession(context, runSession(context)));
|
|
133
152
|
},
|
|
134
153
|
onError: (error, variables, onMutateResult, context) => {
|
|
135
154
|
if (error instanceof MutationSessionEndedError || runHasEnded(store, context))
|
|
136
155
|
return;
|
|
137
|
-
return onError?.(error, variables, onMutateResult, context);
|
|
156
|
+
return onError?.(error, variables, onMutateResult, withSession(context, runSession(context)));
|
|
138
157
|
},
|
|
139
158
|
onSettled: (data, error, variables, onMutateResult, context) => {
|
|
140
159
|
if (error instanceof MutationSessionEndedError || runHasEnded(store, context))
|
|
141
160
|
return;
|
|
142
|
-
return onSettled?.(data, error, variables, onMutateResult, context);
|
|
161
|
+
return onSettled?.(data, error, variables, onMutateResult, withSession(context, runSession(context)));
|
|
143
162
|
},
|
|
144
163
|
});
|
|
164
|
+
function runSession(context) {
|
|
165
|
+
return (store && runSessions.get(context)) || ALWAYS_CURRENT;
|
|
166
|
+
}
|
|
145
167
|
const { mutate: rawMutate, mutateAsync: rawMutateAsync } = mutation;
|
|
146
168
|
const mutate = useCallback((variables, callOptions) => rawMutate(variables, fenceCallOptions(captureSession(store), callOptions)), [rawMutate, store]);
|
|
147
|
-
const mutateAsync = useCallback((variables, callOptions) =>
|
|
169
|
+
const mutateAsync = useCallback((variables, callOptions) => {
|
|
170
|
+
const session = captureSession(store);
|
|
171
|
+
return settleInSession(session, rawMutateAsync(variables, fenceCallOptions(session, callOptions)));
|
|
172
|
+
}, [rawMutateAsync, store]);
|
|
148
173
|
return { ...mutation, mutate, mutateAsync };
|
|
149
174
|
}
|
|
150
175
|
//# sourceMappingURL=session-mutation.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"session-mutation.js","sourceRoot":"","sources":["../../src/react/session-mutation.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAC;;AAEb,OAAO,EACL,aAAa,EACb,WAAW,EACX,UAAU,EACV,kBAAkB,EAClB,QAAQ,GAET,MAAM,OAAO,CAAC;AACf,OAAO,EACL,WAAW,EACX,cAAc,GAMf,MAAM,uBAAuB,CAAC;AAqB/B,MAAM,OAAO,yBAA0B,SAAQ,KAAK;IACzC,IAAI,GAAG,YAAY,CAAC;IAE7B,YAAY,OAA6B;QACvC,KAAK,CAAC,mDAAmD,EAAE,OAAO,CAAC,CAAC;IACtE,CAAC;CACF;AAMD,MAAM,sBAAsB,GAAG,aAAa,CAAsB,IAAI,CAAC,CAAC;AAOxE,MAAM,UAAU,uBAAuB,CAAC,EAAE,UAAU,EAAE,QAAQ,EAAgC;IAC5F,MAAM,CAAC,KAAK,CAAC,GAAG,QAAQ,CAAe,GAAG,EAAE,CAAC,CAAC;QAC5C,OAAO,EAAE,EAAE,GAAG,EAAE,UAAU,EAAE,UAAU,EAAE,CAAC,EAAE;KAC5C,CAAC,CAAC,CAAC;IACJ,2FAA2F;IAC3F,0DAA0D;IAC1D,kBAAkB,CAAC,GAAG,EAAE;QACtB,IAAI,KAAK,CAAC,OAAO,CAAC,GAAG,KAAK,UAAU,EAAE,CAAC;YACrC,KAAK,CAAC,OAAO,GAAG,EAAE,GAAG,EAAE,UAAU,EAAE,UAAU,EAAE,KAAK,CAAC,OAAO,CAAC,UAAU,GAAG,CAAC,EAAE,CAAC;QAChF,CAAC;IACH,CAAC,EAAE,CAAC,KAAK,EAAE,UAAU,CAAC,CAAC,CAAC;IACxB,OAAO,CACL,KAAC,sBAAsB,CAAC,QAAQ,IAAC,KAAK,EAAE,KAAK,YAAG,QAAQ,GAAmC,CAC5F,CAAC;AACJ,CAAC;AAED,MAAM,cAAc,GAAoB;IACtC,GAAG,EAAE,IAAI;IACT,SAAS,EAAE,GAAG,EAAE,CAAC,IAAI;IACrB,aAAa,EAAE,GAAG,EAAE,GAAE,CAAC;CACxB,CAAC;AAEF,SAAS,cAAc,CAAC,KAA0B;IAChD,IAAI,CAAC,KAAK;QAAE,OAAO,cAAc,CAAC;IAClC,MAAM,EAAE,GAAG,EAAE,UAAU,EAAE,GAAG,KAAK,CAAC,OAAO,CAAC;IAC1C,MAAM,SAAS,GAAG,GAAG,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,UAAU,KAAK,UAAU,CAAC;IAChE,OAAO;QACL,GAAG;QACH,SAAS;QACT,aAAa,EAAE,GAAG,EAAE;YAClB,IAAI,CAAC,SAAS,EAAE;gBAAE,MAAM,IAAI,yBAAyB,EAAE,CAAC;QAC1D,CAAC;KACF,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,yBAAyB;IACvC,MAAM,KAAK,GAAG,UAAU,CAAC,sBAAsB,CAAC,CAAC;IACjD,OAAO,WAAW,CAAC,GAAG,EAAE,CAAC,cAAc,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC;AAC3D,CAAC;AAED,MAAM,WAAW,GAAG,IAAI,OAAO,EAA4C,CAAC;AAE5E,SAAS,WAAW,CAAC,KAA0B,EAAE,OAAgC;IAC/E,IAAI,CAAC,KAAK;QAAE,OAAO,KAAK,CAAC;IACzB,OAAO,CAAC,CAAC,WAAW,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,SAAS,EAAE,IAAI,KAAK,CAAC,CAAC;AAC3D,CAAC;AAKD,SAAS,YAAY,CAAS,KAAoB,EAAE,YAAoB,EAAE,KAAa;IACrF,IAAI,KAAK,YAAY,yBAAyB;QAAE,OAAO,KAAK,CAAC;IAC7D,IAAI,OAAO,KAAK,KAAK,UAAU;QAAE,OAAO,KAAK,CAAC,YAAY,EAAE,KAAK,CAAC,CAAC;IACnE,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,YAAY,GAAG,KAAK,CAAC;IAC3D,OAAO,KAAK,KAAK,IAAI,CAAC;AACxB,CAAC;AAED,SAAS,gBAAgB,CAAS,YAAkC,EAAE,KAAa;IACjF,IAAI,KAAK,YAAY,yBAAyB;QAAE,OAAO,KAAK,CAAC;IAC7D,IAAI,OAAO,YAAY,KAAK,UAAU;QAAE,OAAO,YAAY,CAAC,KAAK,CAAC,CAAC;IACnE,OAAO,YAAY,KAAK,IAAI,CAAC;AAC/B,CAAC;AAED,SAAS,gBAAgB,CACvB,OAAwB,EACxB,OAA8E;IAE9E,IAAI,CAAC,OAAO;QAAE,OAAO,SAAS,CAAC;IAC/B,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE,SAAS,EAAE,GAAG,OAAO,CAAC;IAClD,OAAO;QACL,SAAS,EAAE,SAAS;YAClB,CAAC,CAAC,CAAC,GAAG,IAAI,EAAE,EAAE;gBACV,IAAI,OAAO,CAAC,SAAS,EAAE;oBAAE,SAAS,CAAC,GAAG,IAAI,CAAC,CAAC;YAC9C,CAAC;YACH,CAAC,CAAC,SAAS;QACb,OAAO,EAAE,OAAO;YACd,CAAC,CAAC,CAAC,KAAK,EAAE,GAAG,IAAI,EAAE,EAAE;gBACjB,IAAI,CAAC,CAAC,KAAK,YAAY,yBAAyB,CAAC,IAAI,OAAO,CAAC,SAAS,EAAE,EAAE,CAAC;oBACzE,OAAO,CAAC,KAAK,EAAE,GAAG,IAAI,CAAC,CAAC;gBAC1B,CAAC;YACH,CAAC;YACH,CAAC,CAAC,SAAS;QACb,SAAS,EAAE,SAAS;YAClB,CAAC,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,GAAG,IAAI,EAAE,EAAE;gBACvB,IAAI,CAAC,CAAC,KAAK,YAAY,yBAAyB,CAAC,IAAI,OAAO,CAAC,SAAS,EAAE,EAAE,CAAC;oBACzE,SAAS,CAAC,IAAI,EAAE,KAAK,EAAE,GAAG,IAAI,CAAC,CAAC;gBAClC,CAAC;YACH,CAAC;YACH,CAAC,CAAC,SAAS;KACd,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,kBAAkB,CAMhC,OAA2E;IAE3E,MAAM,KAAK,GAAG,UAAU,CAAC,sBAAsB,CAAC,CAAC;IACjD,MAAM,WAAW,GAAG,cAAc,EAAE,CAAC;IACrC,MAAM,EAAE,UAAU,EAAE,QAAQ,EAAE,SAAS,EAAE,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,YAAY,EAAE,GAAG,IAAI,EAAE,GACzF,OAAO,CAAC;IACV,MAAM,QAAQ,GAAG,WAAW,CAAC,sBAAsB,CAEjD,EAAE,WAAW,EAAE,OAAO,CAAC,WAAW,EAAE,CAAC,CAAC;IACxC,MAAM,SAAS,GAAG,CAAC,KAAK,IAAI,QAAQ,CAAC,KAAK,CAAkB,CAAC;IAC7D,MAAM,gBAAgB,GAAG,CAAC,YAAY,IAAI,QAAQ,CAAC,YAAY,CAAyB,CAAC;IAEzF,MAAM,QAAQ,GAAG,WAAW,CAA6C;QACvE,GAAG,IAAI;QACP,KAAK,EAAE,CAAC,YAAY,EAAE,KAAK,EAAE,EAAE,CAAC,YAAY,CAAC,SAAS,EAAE,YAAY,EAAE,KAAK,CAAC;QAC5E,YAAY,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,gBAAgB,CAAC,gBAAgB,EAAE,KAAK,CAAC;QAClE,QAAQ,EAAE,CAAC,SAAS,EAAE,OAAO,EAAE,EAAE;YAC/B,IAAI,KAAK;gBAAE,WAAW,CAAC,GAAG,CAAC,OAAO,EAAE,cAAc,CAAC,KAAK,CAAC,CAAC,CAAC;YAC3D,OAAO,QAAQ,EAAE,CAAC,SAAS,EAAE,OAAO,CAA+C,CAAC;QACtF,CAAC;QACD,UAAU,EAAE,KAAK,EAAE,SAAS,EAAE,OAAO,EAAE,EAAE;YACvC,MAAM,OAAO,GAAG,KAAK,CAAC,CAAC,CAAC,WAAW,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,cAAc,CAAC;YAClE,IAAI,CAAC,OAAO,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE;gBAAE,MAAM,IAAI,yBAAyB,EAAE,CAAC;YAC5E,IAAI,IAAW,CAAC;YAChB,IAAI,CAAC;gBACH,IAAI,GAAG,MAAM,UAAU,CAAC,SAAS,EAAE,EAAE,GAAG,OAAO,EAAE,OAAO,EAAE,CAAC,CAAC;YAC9D,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE;oBAAE,MAAM,IAAI,yBAAyB,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC;gBAChF,MAAM,KAAK,CAAC;YACd,CAAC;YACD,OAAO,CAAC,aAAa,EAAE,CAAC;YACxB,OAAO,IAAI,CAAC;QACd,CAAC;QACD,SAAS,EAAE,CAAC,IAAI,EAAE,SAAS,EAAE,cAAc,EAAE,OAAO,EAAE,EAAE;YACtD,IAAI,WAAW,CAAC,KAAK,EAAE,OAAO,CAAC;gBAAE,OAAO;YACxC,OAAO,SAAS,EAAE,CAAC,IAAI,EAAE,SAAS,EAAE,cAAc,EAAE,OAAO,CAAC,CAAC;QAC/D,CAAC;QACD,OAAO,EAAE,CAAC,KAAK,EAAE,SAAS,EAAE,cAAc,EAAE,OAAO,EAAE,EAAE;YACrD,IAAI,KAAK,YAAY,yBAAyB,IAAI,WAAW,CAAC,KAAK,EAAE,OAAO,CAAC;gBAAE,OAAO;YACtF,OAAO,OAAO,EAAE,CAAC,KAAK,EAAE,SAAS,EAAE,cAAc,EAAE,OAAO,CAAC,CAAC;QAC9D,CAAC;QACD,SAAS,EAAE,CAAC,IAAI,EAAE,KAAK,EAAE,SAAS,EAAE,cAAc,EAAE,OAAO,EAAE,EAAE;YAC7D,IAAI,KAAK,YAAY,yBAAyB,IAAI,WAAW,CAAC,KAAK,EAAE,OAAO,CAAC;gBAAE,OAAO;YACtF,OAAO,SAAS,EAAE,CAAC,IAAI,EAAE,KAAK,EAAE,SAAS,EAAE,cAAc,EAAE,OAAO,CAAC,CAAC;QACtE,CAAC;KACF,CAAC,CAAC;IAEH,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,WAAW,EAAE,cAAc,EAAE,GAAG,QAAQ,CAAC;IACpE,MAAM,MAAM,GAAG,WAAW,CACxB,CACE,SAAqB,EACrB,WAAuE,EACvE,EAAE,CAAC,SAAS,CAAC,SAAS,EAAE,gBAAgB,CAAC,cAAc,CAAC,KAAK,CAAC,EAAE,WAAW,CAAC,CAAC,EAC/E,CAAC,SAAS,EAAE,KAAK,CAAC,CACnB,CAAC;IACF,MAAM,WAAW,GAAG,WAAW,CAC7B,CACE,SAAqB,EACrB,WAAuE,EACvE,EAAE,CAAC,cAAc,CAAC,SAAS,EAAE,gBAAgB,CAAC,cAAc,CAAC,KAAK,CAAC,EAAE,WAAW,CAAC,CAAC,EACpF,CAAC,cAAc,EAAE,KAAK,CAAC,CACxB,CAAC;IACF,OAAO,EAAE,GAAG,QAAQ,EAAE,MAAM,EAAE,WAAW,EAKxC,CAAC;AACJ,CAAC","sourcesContent":["'use client';\n\nimport {\n createContext,\n useCallback,\n useContext,\n useInsertionEffect,\n useState,\n type ReactNode,\n} from 'react';\nimport {\n useMutation,\n useQueryClient,\n type DefaultError,\n type MutateOptions,\n type MutationFunctionContext,\n type UseMutationOptions,\n type UseMutationResult,\n} from '@tanstack/react-query';\n\nexport interface MutationSession {\n uid: string | null;\n isCurrent(): boolean;\n assertCurrent(): void;\n}\n\nexport type SessionMutationFunctionContext = MutationFunctionContext & {\n session: MutationSession;\n};\n\nexport type SessionMutationOptions<\n TData = unknown,\n TError = DefaultError,\n TVariables = void,\n TOnMutateResult = unknown,\n> = Omit<UseMutationOptions<TData, TError, TVariables, TOnMutateResult>, 'mutationFn'> & {\n mutationFn: (variables: TVariables, context: SessionMutationFunctionContext) => Promise<TData>;\n};\n\nexport class MutationSessionEndedError extends Error {\n override name = 'AbortError';\n\n constructor(options?: { cause?: unknown }) {\n super('The session that started this mutation has ended.', options);\n }\n}\n\ninterface SessionStore {\n current: { uid: string | null; generation: number };\n}\n\nconst MutationSessionContext = createContext<SessionStore | null>(null);\n\nexport interface MutationSessionProviderProps {\n currentUid: string | null;\n children?: ReactNode;\n}\n\nexport function MutationSessionProvider({ currentUid, children }: MutationSessionProviderProps) {\n const [store] = useState<SessionStore>(() => ({\n current: { uid: currentUid, generation: 0 },\n }));\n // Insertion effects run before any layout effect of the commit, so a child's layout effect\n // never starts a mutation under the uid this commit ends.\n useInsertionEffect(() => {\n if (store.current.uid !== currentUid) {\n store.current = { uid: currentUid, generation: store.current.generation + 1 };\n }\n }, [store, currentUid]);\n return (\n <MutationSessionContext.Provider value={store}>{children}</MutationSessionContext.Provider>\n );\n}\n\nconst ALWAYS_CURRENT: MutationSession = {\n uid: null,\n isCurrent: () => true,\n assertCurrent: () => {},\n};\n\nfunction captureSession(store: SessionStore | null): MutationSession {\n if (!store) return ALWAYS_CURRENT;\n const { uid, generation } = store.current;\n const isCurrent = () => store.current.generation === generation;\n return {\n uid,\n isCurrent,\n assertCurrent: () => {\n if (!isCurrent()) throw new MutationSessionEndedError();\n },\n };\n}\n\nexport function useMutationSessionCapture(): () => MutationSession {\n const store = useContext(MutationSessionContext);\n return useCallback(() => captureSession(store), [store]);\n}\n\nconst runSessions = new WeakMap<MutationFunctionContext, MutationSession>();\n\nfunction runHasEnded(store: SessionStore | null, context: MutationFunctionContext): boolean {\n if (!store) return false;\n return !(runSessions.get(context)?.isCurrent() ?? false);\n}\n\ntype Retry<TError> = UseMutationOptions<unknown, TError, unknown, unknown>['retry'];\ntype ThrowOnError<TError> = UseMutationOptions<unknown, TError, unknown, unknown>['throwOnError'];\n\nfunction retriesAfter<TError>(retry: Retry<TError>, failureCount: number, error: TError): boolean {\n if (error instanceof MutationSessionEndedError) return false;\n if (typeof retry === 'function') return retry(failureCount, error);\n if (typeof retry === 'number') return failureCount < retry;\n return retry === true;\n}\n\nfunction throwsToBoundary<TError>(throwOnError: ThrowOnError<TError>, error: TError): boolean {\n if (error instanceof MutationSessionEndedError) return false;\n if (typeof throwOnError === 'function') return throwOnError(error);\n return throwOnError === true;\n}\n\nfunction fenceCallOptions<TData, TError, TVariables, TOnMutateResult>(\n session: MutationSession,\n options: MutateOptions<TData, TError, TVariables, TOnMutateResult> | undefined,\n): MutateOptions<TData, TError, TVariables, TOnMutateResult> | undefined {\n if (!options) return undefined;\n const { onSuccess, onError, onSettled } = options;\n return {\n onSuccess: onSuccess\n ? (...args) => {\n if (session.isCurrent()) onSuccess(...args);\n }\n : undefined,\n onError: onError\n ? (error, ...rest) => {\n if (!(error instanceof MutationSessionEndedError) && session.isCurrent()) {\n onError(error, ...rest);\n }\n }\n : undefined,\n onSettled: onSettled\n ? (data, error, ...rest) => {\n if (!(error instanceof MutationSessionEndedError) && session.isCurrent()) {\n onSettled(data, error, ...rest);\n }\n }\n : undefined,\n };\n}\n\nexport function useSessionMutation<\n TData = unknown,\n TError = DefaultError,\n TVariables = void,\n TOnMutateResult = unknown,\n>(\n options: SessionMutationOptions<TData, TError, TVariables, TOnMutateResult>,\n): UseMutationResult<TData, TError, TVariables, TOnMutateResult> {\n const store = useContext(MutationSessionContext);\n const queryClient = useQueryClient();\n const { mutationFn, onMutate, onSuccess, onError, onSettled, retry, throwOnError, ...rest } =\n options;\n const defaults = queryClient.defaultMutationOptions<\n UseMutationOptions<unknown, TError, unknown, unknown>\n >({ mutationKey: options.mutationKey });\n const baseRetry = (retry ?? defaults.retry) as Retry<TError>;\n const baseThrowOnError = (throwOnError ?? defaults.throwOnError) as ThrowOnError<TError>;\n\n const mutation = useMutation<TData, TError, TVariables, TOnMutateResult>({\n ...rest,\n retry: (failureCount, error) => retriesAfter(baseRetry, failureCount, error),\n throwOnError: (error) => throwsToBoundary(baseThrowOnError, error),\n onMutate: (variables, context) => {\n if (store) runSessions.set(context, captureSession(store));\n return onMutate?.(variables, context) as TOnMutateResult | Promise<TOnMutateResult>;\n },\n mutationFn: async (variables, context) => {\n const session = store ? runSessions.get(context) : ALWAYS_CURRENT;\n if (!session || !session.isCurrent()) throw new MutationSessionEndedError();\n let data: TData;\n try {\n data = await mutationFn(variables, { ...context, session });\n } catch (error) {\n if (!session.isCurrent()) throw new MutationSessionEndedError({ cause: error });\n throw error;\n }\n session.assertCurrent();\n return data;\n },\n onSuccess: (data, variables, onMutateResult, context) => {\n if (runHasEnded(store, context)) return;\n return onSuccess?.(data, variables, onMutateResult, context);\n },\n onError: (error, variables, onMutateResult, context) => {\n if (error instanceof MutationSessionEndedError || runHasEnded(store, context)) return;\n return onError?.(error, variables, onMutateResult, context);\n },\n onSettled: (data, error, variables, onMutateResult, context) => {\n if (error instanceof MutationSessionEndedError || runHasEnded(store, context)) return;\n return onSettled?.(data, error, variables, onMutateResult, context);\n },\n });\n\n const { mutate: rawMutate, mutateAsync: rawMutateAsync } = mutation;\n const mutate = useCallback(\n (\n variables: TVariables,\n callOptions?: MutateOptions<TData, TError, TVariables, TOnMutateResult>,\n ) => rawMutate(variables, fenceCallOptions(captureSession(store), callOptions)),\n [rawMutate, store],\n );\n const mutateAsync = useCallback(\n (\n variables: TVariables,\n callOptions?: MutateOptions<TData, TError, TVariables, TOnMutateResult>,\n ) => rawMutateAsync(variables, fenceCallOptions(captureSession(store), callOptions)),\n [rawMutateAsync, store],\n );\n return { ...mutation, mutate, mutateAsync } as UseMutationResult<\n TData,\n TError,\n TVariables,\n TOnMutateResult\n >;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"session-mutation.js","sourceRoot":"","sources":["../../src/react/session-mutation.tsx"],"names":[],"mappings":"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","sourcesContent":["'use client';\n\nimport {\n createContext,\n useCallback,\n useContext,\n useInsertionEffect,\n useState,\n type ReactNode,\n} from 'react';\nimport {\n useMutation,\n useQueryClient,\n type DefaultError,\n type MutateOptions,\n type MutationFunctionContext,\n type UseMutationOptions,\n type UseMutationResult,\n} from '@tanstack/react-query';\n\nexport interface MutationSession {\n uid: string | null;\n isCurrent(): boolean;\n assertCurrent(): void;\n}\n\nexport type SessionMutationFunctionContext = MutationFunctionContext & {\n session: MutationSession;\n};\n\nexport type SessionMutationOptions<\n TData = unknown,\n TError = DefaultError,\n TVariables = void,\n TOnMutateResult = unknown,\n> = Omit<\n UseMutationOptions<TData, TError, TVariables, TOnMutateResult>,\n 'mutationFn' | 'onMutate' | 'onSuccess' | 'onError' | 'onSettled'\n> & {\n mutationFn: (variables: TVariables, context: SessionMutationFunctionContext) => Promise<TData>;\n onMutate?: (\n variables: TVariables,\n context: SessionMutationFunctionContext,\n ) => Promise<TOnMutateResult> | TOnMutateResult;\n onSuccess?: (\n data: TData,\n variables: TVariables,\n onMutateResult: TOnMutateResult,\n context: SessionMutationFunctionContext,\n ) => Promise<unknown> | unknown;\n onError?: (\n error: TError,\n variables: TVariables,\n onMutateResult: TOnMutateResult | undefined,\n context: SessionMutationFunctionContext,\n ) => Promise<unknown> | unknown;\n onSettled?: (\n data: TData | undefined,\n error: TError | null,\n variables: TVariables,\n onMutateResult: TOnMutateResult | undefined,\n context: SessionMutationFunctionContext,\n ) => Promise<unknown> | unknown;\n};\n\nexport interface SessionMutateOptions<TData, TError, TVariables, TOnMutateResult> {\n onSuccess?: (\n data: TData,\n variables: TVariables,\n onMutateResult: TOnMutateResult | undefined,\n context: SessionMutationFunctionContext,\n ) => void;\n onError?: (\n error: TError,\n variables: TVariables,\n onMutateResult: TOnMutateResult | undefined,\n context: SessionMutationFunctionContext,\n ) => void;\n onSettled?: (\n data: TData | undefined,\n error: TError | null,\n variables: TVariables,\n onMutateResult: TOnMutateResult | undefined,\n context: SessionMutationFunctionContext,\n ) => void;\n}\n\ntype DistributiveOmit<T, K extends PropertyKey> = T extends unknown ? Omit<T, K> : never;\n\nexport type SessionMutationResult<\n TData = unknown,\n TError = DefaultError,\n TVariables = void,\n TOnMutateResult = unknown,\n> = DistributiveOmit<\n UseMutationResult<TData, TError, TVariables, TOnMutateResult>,\n 'mutate' | 'mutateAsync'\n> & {\n mutate: (\n variables: TVariables,\n options?: SessionMutateOptions<TData, TError, TVariables, TOnMutateResult>,\n ) => void;\n mutateAsync: (\n variables: TVariables,\n options?: SessionMutateOptions<TData, TError, TVariables, TOnMutateResult>,\n ) => Promise<TData>;\n};\n\nexport class MutationSessionEndedError extends Error {\n override name = 'AbortError';\n\n constructor(options?: { cause?: unknown }) {\n super('The session that started this mutation has ended.', options);\n }\n}\n\ninterface SessionStore {\n current: { uid: string | null; generation: number };\n}\n\nconst MutationSessionContext = createContext<SessionStore | null>(null);\n\nexport interface MutationSessionProviderProps {\n currentUid: string | null;\n children?: ReactNode;\n}\n\nexport function MutationSessionProvider({ currentUid, children }: MutationSessionProviderProps) {\n const [store] = useState<SessionStore>(() => ({\n current: { uid: currentUid, generation: 0 },\n }));\n // Insertion effects run before any layout effect of the commit, so a child's layout effect\n // never starts a mutation under the uid this commit ends.\n useInsertionEffect(() => {\n if (store.current.uid !== currentUid) {\n store.current = { uid: currentUid, generation: store.current.generation + 1 };\n }\n }, [store, currentUid]);\n return (\n <MutationSessionContext.Provider value={store}>{children}</MutationSessionContext.Provider>\n );\n}\n\nconst ALWAYS_CURRENT: MutationSession = {\n uid: null,\n isCurrent: () => true,\n assertCurrent: () => {},\n};\n\nfunction captureSession(store: SessionStore | null): MutationSession {\n if (!store) return ALWAYS_CURRENT;\n const { uid, generation } = store.current;\n const isCurrent = () => store.current.generation === generation;\n return {\n uid,\n isCurrent,\n assertCurrent: () => {\n if (!isCurrent()) throw new MutationSessionEndedError();\n },\n };\n}\n\nexport function useMutationSessionCapture(): () => MutationSession {\n const store = useContext(MutationSessionContext);\n return useCallback(() => captureSession(store), [store]);\n}\n\nconst runSessions = new WeakMap<MutationFunctionContext, MutationSession>();\n\nfunction runHasEnded(store: SessionStore | null, context: MutationFunctionContext): boolean {\n if (!store) return false;\n return !(runSessions.get(context)?.isCurrent() ?? false);\n}\n\ntype Retry<TError> = UseMutationOptions<unknown, TError, unknown, unknown>['retry'];\ntype ThrowOnError<TError> = UseMutationOptions<unknown, TError, unknown, unknown>['throwOnError'];\n\nfunction retriesAfter<TError>(retry: Retry<TError>, failureCount: number, error: TError): boolean {\n if (error instanceof MutationSessionEndedError) return false;\n if (typeof retry === 'function') return retry(failureCount, error);\n if (typeof retry === 'number') return failureCount < retry;\n return retry === true;\n}\n\nfunction throwsToBoundary<TError>(throwOnError: ThrowOnError<TError>, error: TError): boolean {\n if (error instanceof MutationSessionEndedError) return false;\n if (typeof throwOnError === 'function') return throwOnError(error);\n return throwOnError === true;\n}\n\nfunction withSession(\n context: MutationFunctionContext,\n session: MutationSession,\n): SessionMutationFunctionContext {\n return { ...context, session };\n}\n\nfunction fenceCallOptions<TData, TError, TVariables, TOnMutateResult>(\n session: MutationSession,\n options: SessionMutateOptions<TData, TError, TVariables, TOnMutateResult> | undefined,\n): MutateOptions<TData, TError, TVariables, TOnMutateResult> | undefined {\n if (!options) return undefined;\n const { onSuccess, onError, onSettled } = options;\n return {\n onSuccess: onSuccess\n ? (data, variables, onMutateResult, context) => {\n if (session.isCurrent()) {\n onSuccess(data, variables, onMutateResult, withSession(context, session));\n }\n }\n : undefined,\n onError: onError\n ? (error, variables, onMutateResult, context) => {\n if (!(error instanceof MutationSessionEndedError) && session.isCurrent()) {\n onError(error, variables, onMutateResult, withSession(context, session));\n }\n }\n : undefined,\n onSettled: onSettled\n ? (data, error, variables, onMutateResult, context) => {\n if (!(error instanceof MutationSessionEndedError) && session.isCurrent()) {\n onSettled(data, error, variables, onMutateResult, withSession(context, session));\n }\n }\n : undefined,\n };\n}\n\nasync function settleInSession<TData>(\n session: MutationSession,\n settled: Promise<TData>,\n): Promise<TData> {\n let data: TData;\n try {\n data = await settled;\n } catch (error) {\n if (!(error instanceof MutationSessionEndedError) && !session.isCurrent()) {\n throw new MutationSessionEndedError({ cause: error });\n }\n throw error;\n }\n session.assertCurrent();\n return data;\n}\n\nexport function useSessionMutation<\n TData = unknown,\n TError = DefaultError,\n TVariables = void,\n TOnMutateResult = unknown,\n>(\n options: SessionMutationOptions<TData, TError, TVariables, TOnMutateResult>,\n): SessionMutationResult<TData, TError, TVariables, TOnMutateResult> {\n const store = useContext(MutationSessionContext);\n const queryClient = useQueryClient();\n const { mutationFn, onMutate, onSuccess, onError, onSettled, retry, throwOnError, ...rest } =\n options;\n const defaults = queryClient.defaultMutationOptions<\n UseMutationOptions<unknown, TError, unknown, unknown>\n >({ mutationKey: options.mutationKey });\n const baseRetry = (retry ?? defaults.retry) as Retry<TError>;\n const baseThrowOnError = (throwOnError ?? defaults.throwOnError) as ThrowOnError<TError>;\n\n const mutation = useMutation<TData, TError, TVariables, TOnMutateResult>({\n ...rest,\n retry: (failureCount, error) => retriesAfter(baseRetry, failureCount, error),\n throwOnError: (error) => throwsToBoundary(baseThrowOnError, error),\n onMutate: (variables, context) => {\n const session = store ? captureSession(store) : ALWAYS_CURRENT;\n if (store) runSessions.set(context, session);\n return onMutate?.(variables, withSession(context, session)) as\n TOnMutateResult | Promise<TOnMutateResult>;\n },\n mutationFn: async (variables, context) => {\n const session = store ? runSessions.get(context) : ALWAYS_CURRENT;\n if (!session || !session.isCurrent()) throw new MutationSessionEndedError();\n let data: TData;\n try {\n data = await mutationFn(variables, { ...context, session });\n } catch (error) {\n if (!session.isCurrent()) throw new MutationSessionEndedError({ cause: error });\n throw error;\n }\n session.assertCurrent();\n return data;\n },\n onSuccess: (data, variables, onMutateResult, context) => {\n if (runHasEnded(store, context)) return;\n return onSuccess?.(\n data,\n variables,\n onMutateResult,\n withSession(context, runSession(context)),\n );\n },\n onError: (error, variables, onMutateResult, context) => {\n if (error instanceof MutationSessionEndedError || runHasEnded(store, context)) return;\n return onError?.(error, variables, onMutateResult, withSession(context, runSession(context)));\n },\n onSettled: (data, error, variables, onMutateResult, context) => {\n if (error instanceof MutationSessionEndedError || runHasEnded(store, context)) return;\n return onSettled?.(\n data,\n error,\n variables,\n onMutateResult,\n withSession(context, runSession(context)),\n );\n },\n });\n\n function runSession(context: MutationFunctionContext): MutationSession {\n return (store && runSessions.get(context)) || ALWAYS_CURRENT;\n }\n\n const { mutate: rawMutate, mutateAsync: rawMutateAsync } = mutation;\n const mutate = useCallback(\n (\n variables: TVariables,\n callOptions?: SessionMutateOptions<TData, TError, TVariables, TOnMutateResult>,\n ) => rawMutate(variables, fenceCallOptions(captureSession(store), callOptions)),\n [rawMutate, store],\n );\n const mutateAsync = useCallback(\n (\n variables: TVariables,\n callOptions?: SessionMutateOptions<TData, TError, TVariables, TOnMutateResult>,\n ) => {\n const session = captureSession(store);\n return settleInSession(\n session,\n rawMutateAsync(variables, fenceCallOptions(session, callOptions)),\n );\n },\n [rawMutateAsync, store],\n );\n return { ...mutation, mutate, mutateAsync } as SessionMutationResult<\n TData,\n TError,\n TVariables,\n TOnMutateResult\n >;\n}\n"]}
|