@ttt-productions/query-core 0.14.22 → 0.14.24
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/README.md +6 -6
- package/dist/defaults.d.ts +0 -15
- package/dist/defaults.d.ts.map +1 -1
- package/dist/defaults.js +0 -15
- package/dist/defaults.js.map +1 -1
- package/dist/firestore/types.d.ts +5 -49
- package/dist/firestore/types.d.ts.map +1 -1
- package/dist/firestore/types.js.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +0 -1
- package/dist/index.js.map +1 -1
- package/dist/keys.d.ts +0 -22
- package/dist/keys.d.ts.map +1 -1
- package/dist/keys.js +0 -4
- package/dist/keys.js.map +1 -1
- package/dist/react/cache-helpers.d.ts +0 -32
- package/dist/react/cache-helpers.d.ts.map +1 -1
- package/dist/react/cache-helpers.js +0 -28
- package/dist/react/cache-helpers.js.map +1 -1
- package/dist/react/callables/create-callables.d.ts +40 -0
- package/dist/react/callables/create-callables.d.ts.map +1 -0
- package/dist/react/callables/create-callables.js +101 -0
- package/dist/react/callables/create-callables.js.map +1 -0
- package/dist/react/defaults.d.ts +0 -4
- package/dist/react/defaults.d.ts.map +1 -1
- package/dist/react/defaults.js +2 -6
- package/dist/react/defaults.js.map +1 -1
- package/dist/react/domain-events/cache-invalidation.d.ts +0 -37
- package/dist/react/domain-events/cache-invalidation.d.ts.map +1 -1
- package/dist/react/domain-events/cache-invalidation.js +4 -53
- package/dist/react/domain-events/cache-invalidation.js.map +1 -1
- package/dist/react/domain-events/create-domain-event-invalidator.d.ts +0 -18
- package/dist/react/domain-events/create-domain-event-invalidator.d.ts.map +1 -1
- package/dist/react/domain-events/create-domain-event-invalidator.js +0 -5
- package/dist/react/domain-events/create-domain-event-invalidator.js.map +1 -1
- package/dist/react/firestore/absence-scheduler.d.ts +0 -28
- package/dist/react/firestore/absence-scheduler.d.ts.map +1 -1
- package/dist/react/firestore/absence-scheduler.js +1 -39
- package/dist/react/firestore/absence-scheduler.js.map +1 -1
- package/dist/react/firestore/batch-doc-loader.d.ts +0 -30
- package/dist/react/firestore/batch-doc-loader.d.ts.map +1 -1
- package/dist/react/firestore/batch-doc-loader.js +0 -34
- package/dist/react/firestore/batch-doc-loader.js.map +1 -1
- package/dist/react/firestore/context.d.ts +0 -19
- package/dist/react/firestore/context.d.ts.map +1 -1
- package/dist/react/firestore/context.js +0 -19
- package/dist/react/firestore/context.js.map +1 -1
- package/dist/react/firestore/doc-subscription-registry.d.ts +0 -23
- package/dist/react/firestore/doc-subscription-registry.d.ts.map +1 -1
- package/dist/react/firestore/doc-subscription-registry.js +5 -26
- package/dist/react/firestore/doc-subscription-registry.js.map +1 -1
- package/dist/react/firestore/infinite-helpers.d.ts +0 -12
- package/dist/react/firestore/infinite-helpers.d.ts.map +1 -1
- package/dist/react/firestore/infinite-helpers.js +0 -12
- package/dist/react/firestore/infinite-helpers.js.map +1 -1
- package/dist/react/firestore/resubscribe.d.ts +0 -20
- package/dist/react/firestore/resubscribe.d.ts.map +1 -1
- package/dist/react/firestore/resubscribe.js +0 -20
- package/dist/react/firestore/resubscribe.js.map +1 -1
- package/dist/react/firestore/subscription-status.d.ts +0 -29
- package/dist/react/firestore/subscription-status.d.ts.map +1 -1
- package/dist/react/firestore/subscription-status.js +1 -34
- package/dist/react/firestore/subscription-status.js.map +1 -1
- package/dist/react/firestore/types.d.ts +0 -64
- package/dist/react/firestore/types.d.ts.map +1 -1
- package/dist/react/firestore/types.js +0 -3
- package/dist/react/firestore/types.js.map +1 -1
- package/dist/react/firestore/use-firestore-collection.d.ts +0 -20
- package/dist/react/firestore/use-firestore-collection.d.ts.map +1 -1
- package/dist/react/firestore/use-firestore-collection.js +1 -35
- package/dist/react/firestore/use-firestore-collection.js.map +1 -1
- package/dist/react/firestore/use-firestore-count.d.ts +0 -15
- package/dist/react/firestore/use-firestore-count.d.ts.map +1 -1
- package/dist/react/firestore/use-firestore-count.js +0 -15
- package/dist/react/firestore/use-firestore-count.js.map +1 -1
- package/dist/react/firestore/use-firestore-doc.d.ts +0 -23
- package/dist/react/firestore/use-firestore-doc.d.ts.map +1 -1
- package/dist/react/firestore/use-firestore-doc.js +3 -40
- package/dist/react/firestore/use-firestore-doc.js.map +1 -1
- package/dist/react/firestore/use-firestore-infinite.d.ts +0 -29
- package/dist/react/firestore/use-firestore-infinite.d.ts.map +1 -1
- package/dist/react/firestore/use-firestore-infinite.js +0 -32
- package/dist/react/firestore/use-firestore-infinite.js.map +1 -1
- package/dist/react/firestore/use-firestore-live-infinite.d.ts +0 -34
- package/dist/react/firestore/use-firestore-live-infinite.d.ts.map +1 -1
- package/dist/react/firestore/use-firestore-live-infinite.js +1 -35
- package/dist/react/firestore/use-firestore-live-infinite.js.map +1 -1
- package/dist/react/firestore/use-firestore-mutations.d.ts.map +1 -1
- package/dist/react/firestore/use-firestore-mutations.js +6 -5
- package/dist/react/firestore/use-firestore-mutations.js.map +1 -1
- package/dist/react/firestore/use-firestore-paginated.d.ts +0 -30
- package/dist/react/firestore/use-firestore-paginated.d.ts.map +1 -1
- package/dist/react/firestore/use-firestore-paginated.js +2 -33
- package/dist/react/firestore/use-firestore-paginated.js.map +1 -1
- package/dist/react/firestore/useBatchFirestoreDocs.d.ts +1 -123
- package/dist/react/firestore/useBatchFirestoreDocs.d.ts.map +1 -1
- package/dist/react/firestore/useBatchFirestoreDocs.js +23 -64
- package/dist/react/firestore/useBatchFirestoreDocs.js.map +1 -1
- package/dist/react/index.d.ts +4 -0
- package/dist/react/index.d.ts.map +1 -1
- package/dist/react/index.js +2 -13
- package/dist/react/index.js.map +1 -1
- package/dist/react/pending-mutations.d.ts +1 -21
- package/dist/react/pending-mutations.d.ts.map +1 -1
- package/dist/react/pending-mutations.js +1 -32
- package/dist/react/pending-mutations.js.map +1 -1
- package/dist/react/provider.d.ts +0 -5
- package/dist/react/provider.d.ts.map +1 -1
- package/dist/react/provider.js +0 -4
- package/dist/react/provider.js.map +1 -1
- package/dist/react/query-client.d.ts +0 -4
- package/dist/react/query-client.d.ts.map +1 -1
- package/dist/react/query-client.js +0 -4
- package/dist/react/query-client.js.map +1 -1
- package/dist/react/search/types.d.ts +0 -12
- package/dist/react/search/types.d.ts.map +1 -1
- package/dist/react/search/types.js.map +1 -1
- package/dist/react/search/use-firestore-search.d.ts +0 -29
- package/dist/react/search/use-firestore-search.d.ts.map +1 -1
- package/dist/react/search/use-firestore-search.js +3 -41
- package/dist/react/search/use-firestore-search.js.map +1 -1
- package/dist/react/session-mutation.d.ts +27 -0
- package/dist/react/session-mutation.d.ts.map +1 -0
- package/dist/react/session-mutation.js +150 -0
- package/dist/react/session-mutation.js.map +1 -0
- package/dist/react/use-read-retry-state.d.ts +1 -21
- package/dist/react/use-read-retry-state.d.ts.map +1 -1
- package/dist/react/use-read-retry-state.js +2 -21
- package/dist/react/use-read-retry-state.js.map +1 -1
- package/dist/search/rule.d.ts +0 -6
- package/dist/search/rule.d.ts.map +1 -1
- package/dist/search/rule.js +0 -6
- package/dist/search/rule.js.map +1 -1
- package/dist/search/types.d.ts +1 -13
- package/dist/search/types.d.ts.map +1 -1
- package/dist/search/types.js.map +1 -1
- package/package.json +4 -4
package/dist/react/index.d.ts
CHANGED
|
@@ -29,5 +29,9 @@ export { flattenInfiniteData, getInfiniteDataCount } from './firestore/infinite-
|
|
|
29
29
|
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
|
+
export { MutationSessionProvider, MutationSessionEndedError, useSessionMutation, } from './session-mutation.js';
|
|
33
|
+
export type { MutationSession, MutationSessionProviderProps, SessionMutationFunctionContext, SessionMutationOptions, } from './session-mutation.js';
|
|
34
|
+
export { createCallables, MAX_RESUMABLE_CALLS } from './callables/create-callables.js';
|
|
35
|
+
export type { CallableCaptureContext, CallableDeclaration, CallableErrorRouting, CallableMutationOptions, CallablePolicy, Callables, ResumableOutcome, } from './callables/create-callables.js';
|
|
32
36
|
export { usePendingMutationVariables, pendingMutationVariables, usePendingMutationTargets, hasPendingMutation, duplicateSubmissionError, useDuplicateGuardedMutation, } from './pending-mutations.js';
|
|
33
37
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/react/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/react/index.ts"],"names":[],"mappings":"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"}
|
package/dist/react/index.js
CHANGED
|
@@ -1,35 +1,24 @@
|
|
|
1
1
|
'use client';
|
|
2
|
-
// Query Client factory (client-only; requires @tanstack/react-query)
|
|
3
2
|
export { createQueryClient } from './query-client.js';
|
|
4
|
-
// Provider
|
|
5
3
|
export { QueryProvider } from './provider.js';
|
|
6
|
-
// Firestore Provider
|
|
7
4
|
export { FirestoreProvider, useFirestoreDb } from './firestore/context.js';
|
|
8
|
-
// Firestore Query Hooks
|
|
9
5
|
export { useFirestoreDoc } from './firestore/use-firestore-doc.js';
|
|
10
6
|
export { useFirestoreCollection } from './firestore/use-firestore-collection.js';
|
|
11
7
|
export { useFirestoreInfinite } from './firestore/use-firestore-infinite.js';
|
|
12
8
|
export { useFirestorePaginated } from './firestore/use-firestore-paginated.js';
|
|
13
9
|
export { useFirestoreCount } from './firestore/use-firestore-count.js';
|
|
14
10
|
export { useFirestoreLiveInfinite } from './firestore/use-firestore-live-infinite.js';
|
|
15
|
-
// Firestore Mutation Hooks
|
|
16
11
|
export { useFirestoreSet, useFirestoreUpdate, useFirestoreDelete, useFirestoreBatch, } from './firestore/use-firestore-mutations.js';
|
|
17
|
-
// Batch Firestore Docs
|
|
18
12
|
export { useBatchFirestoreDocs } from './firestore/useBatchFirestoreDocs.js';
|
|
19
13
|
export { ABSENT_RETRY_DELAYS_MS } from './firestore/absence-scheduler.js';
|
|
20
|
-
// Search Hook
|
|
21
14
|
export { useFirestoreSearch } from './search/use-firestore-search.js';
|
|
22
|
-
// Cache Helpers
|
|
23
15
|
export { invalidateByPrefix, removeByPrefix, updateQueryData, paginatedPageKey, mapPaginatedItems, prependToFirstPaginatedPage, placeRowInPages, } from './cache-helpers.js';
|
|
24
|
-
// Domain-event invalidator (mechanism — consumers register their event registry)
|
|
25
16
|
export { createDomainEventInvalidator } from './domain-events/create-domain-event-invalidator.js';
|
|
26
17
|
export { exact, prefix, predicate, serializeInvalidation, applyInvalidations, } from './domain-events/cache-invalidation.js';
|
|
27
|
-
// Firestore hook option and page types, and the snapshot helpers
|
|
28
18
|
export { docWithId } from './firestore/types.js';
|
|
29
19
|
export { flattenInfiniteData, getInfiniteDataCount } from './firestore/infinite-helpers.js';
|
|
30
|
-
// Read retry state
|
|
31
20
|
export { useReadRetryState, useReadRetryStates } from './use-read-retry-state.js';
|
|
32
|
-
|
|
33
|
-
|
|
21
|
+
export { MutationSessionProvider, MutationSessionEndedError, useSessionMutation, } from './session-mutation.js';
|
|
22
|
+
export { createCallables, MAX_RESUMABLE_CALLS } from './callables/create-callables.js';
|
|
34
23
|
export { usePendingMutationVariables, pendingMutationVariables, usePendingMutationTargets, hasPendingMutation, duplicateSubmissionError, useDuplicateGuardedMutation, } from './pending-mutations.js';
|
|
35
24
|
//# sourceMappingURL=index.js.map
|
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,
|
|
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;AAQ/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 SessionMutationFunctionContext,\n SessionMutationOptions,\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"]}
|
|
@@ -1,29 +1,9 @@
|
|
|
1
1
|
import { type MutationKey, type QueryClient, type UseMutationResult } from '@tanstack/react-query';
|
|
2
|
-
/** The variables of every pending mutation under `mutationKey` (prefix-matched), live. */
|
|
3
2
|
export declare function usePendingMutationVariables<V>(mutationKey: MutationKey): ReadonlyArray<V | undefined>;
|
|
4
|
-
/** The variables of every pending mutation under `mutationKey`, read once — for a duplicate guard. */
|
|
5
3
|
export declare function pendingMutationVariables<V>(queryClient: QueryClient, mutationKey: MutationKey): Array<V | undefined>;
|
|
6
|
-
/**
|
|
7
|
-
* The targets of every pending mutation under `mutationKey`, live — for a list whose rows each
|
|
8
|
-
* ask "is mine pending?" through one hook call. `targetOf` names a variables' target, or returns
|
|
9
|
-
* nothing for variables without one.
|
|
10
|
-
*/
|
|
11
4
|
export declare function usePendingMutationTargets<V>(mutationKey: MutationKey, targetOf: (variables: V) => string | null | undefined): ReadonlySet<string>;
|
|
12
|
-
/**
|
|
13
|
-
* True when a mutation under `mutationKey` is pending — any one, or with `matches`, one whose
|
|
14
|
-
* variables are for the same target.
|
|
15
|
-
*/
|
|
16
5
|
export declare function hasPendingMutation<V>(queryClient: QueryClient, mutationKey: MutationKey, matches?: (variables: V) => boolean): boolean;
|
|
17
|
-
/**
|
|
18
|
-
* The rejection a guarded `mutateAsync` throws for a duplicate submission: an `AbortError`, the
|
|
19
|
-
* shape a caller already treats as "nothing happened" rather than a failure to report.
|
|
20
|
-
*/
|
|
21
6
|
export declare function duplicateSubmissionError(what: string): Error;
|
|
22
|
-
/**
|
|
23
|
-
* Wrap a keyed mutation's `mutate` / `mutateAsync` in the cache-consulting duplicate guard:
|
|
24
|
-
* `mutate` drops a duplicate silently, and `mutateAsync` rejects it with
|
|
25
|
-
* {@link duplicateSubmissionError}. `isDuplicate` must have a stable identity (declare it at module
|
|
26
|
-
* level) so the guarded callbacks keep theirs.
|
|
27
|
-
*/
|
|
7
|
+
/** `isDuplicate` must have a stable identity (declare it at module level) so the guarded callbacks keep theirs. */
|
|
28
8
|
export declare function useDuplicateGuardedMutation<TData, TError, TVariables, TContext>(mutation: UseMutationResult<TData, TError, TVariables, TContext>, isDuplicate: (queryClient: QueryClient, variables: TVariables) => boolean, what: string): UseMutationResult<TData, TError, TVariables, TContext>;
|
|
29
9
|
//# sourceMappingURL=pending-mutations.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pending-mutations.d.ts","sourceRoot":"","sources":["../../src/react/pending-mutations.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"pending-mutations.d.ts","sourceRoot":"","sources":["../../src/react/pending-mutations.ts"],"names":[],"mappings":"AAGA,OAAO,EAIL,KAAK,WAAW,EAChB,KAAK,WAAW,EAChB,KAAK,iBAAiB,EACvB,MAAM,uBAAuB,CAAC;AAE/B,wBAAgB,2BAA2B,CAAC,CAAC,EAC3C,WAAW,EAAE,WAAW,GACvB,aAAa,CAAC,CAAC,GAAG,SAAS,CAAC,CAK9B;AAED,wBAAgB,wBAAwB,CAAC,CAAC,EACxC,WAAW,EAAE,WAAW,EACxB,WAAW,EAAE,WAAW,GACvB,KAAK,CAAC,CAAC,GAAG,SAAS,CAAC,CAKtB;AAED,wBAAgB,yBAAyB,CAAC,CAAC,EACzC,WAAW,EAAE,WAAW,EACxB,QAAQ,EAAE,CAAC,SAAS,EAAE,CAAC,KAAK,MAAM,GAAG,IAAI,GAAG,SAAS,GACpD,WAAW,CAAC,MAAM,CAAC,CAQrB;AAED,wBAAgB,kBAAkB,CAAC,CAAC,EAClC,WAAW,EAAE,WAAW,EACxB,WAAW,EAAE,WAAW,EACxB,OAAO,CAAC,EAAE,CAAC,SAAS,EAAE,CAAC,KAAK,OAAO,GAClC,OAAO,CAIT;AAED,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,MAAM,GAAG,KAAK,CAI5D;AAED,mHAAmH;AACnH,wBAAgB,2BAA2B,CAAC,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,QAAQ,EAC7E,QAAQ,EAAE,iBAAiB,CAAC,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,QAAQ,CAAC,EAChE,WAAW,EAAE,CAAC,WAAW,EAAE,WAAW,EAAE,SAAS,EAAE,UAAU,KAAK,OAAO,EACzE,IAAI,EAAE,MAAM,GACX,iBAAiB,CAAC,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,QAAQ,CAAC,CAuBxD"}
|
|
@@ -1,36 +1,18 @@
|
|
|
1
1
|
'use client';
|
|
2
|
-
// Authoritative pending for interactive mutations. A mutation registers in React Query's shared
|
|
3
|
-
// MutationCache under a stable `mutationKey` the app declares (one key per action), and its target
|
|
4
|
-
// travels in the mutation's variables. Pending is read from that cache, never from one mounted
|
|
5
|
-
// control's `isPending`, which gives three guarantees:
|
|
6
|
-
//
|
|
7
|
-
// 1. an in-flight request survives its originating control unmounting;
|
|
8
|
-
// 2. a remounted control still renders pending for that target;
|
|
9
|
-
// 3. a second submission for the same target is refused while the first is pending.
|
|
10
|
-
//
|
|
11
|
-
// The app owns its keys, its variable shapes and what counts as the same target; this module owns
|
|
12
|
-
// only the mechanics.
|
|
13
2
|
import { useCallback } from 'react';
|
|
14
3
|
import { useMutationState, useQueryClient, } from '@tanstack/react-query';
|
|
15
|
-
/** The variables of every pending mutation under `mutationKey` (prefix-matched), live. */
|
|
16
4
|
export function usePendingMutationVariables(mutationKey) {
|
|
17
5
|
return useMutationState({
|
|
18
6
|
filters: { mutationKey, status: 'pending' },
|
|
19
7
|
select: (mutation) => mutation.state.variables,
|
|
20
8
|
});
|
|
21
9
|
}
|
|
22
|
-
/** The variables of every pending mutation under `mutationKey`, read once — for a duplicate guard. */
|
|
23
10
|
export function pendingMutationVariables(queryClient, mutationKey) {
|
|
24
11
|
return queryClient
|
|
25
12
|
.getMutationCache()
|
|
26
13
|
.findAll({ mutationKey, status: 'pending' })
|
|
27
14
|
.map((mutation) => mutation.state.variables);
|
|
28
15
|
}
|
|
29
|
-
/**
|
|
30
|
-
* The targets of every pending mutation under `mutationKey`, live — for a list whose rows each
|
|
31
|
-
* ask "is mine pending?" through one hook call. `targetOf` names a variables' target, or returns
|
|
32
|
-
* nothing for variables without one.
|
|
33
|
-
*/
|
|
34
16
|
export function usePendingMutationTargets(mutationKey, targetOf) {
|
|
35
17
|
const targets = new Set();
|
|
36
18
|
for (const variables of usePendingMutationVariables(mutationKey)) {
|
|
@@ -42,31 +24,18 @@ export function usePendingMutationTargets(mutationKey, targetOf) {
|
|
|
42
24
|
}
|
|
43
25
|
return targets;
|
|
44
26
|
}
|
|
45
|
-
/**
|
|
46
|
-
* True when a mutation under `mutationKey` is pending — any one, or with `matches`, one whose
|
|
47
|
-
* variables are for the same target.
|
|
48
|
-
*/
|
|
49
27
|
export function hasPendingMutation(queryClient, mutationKey, matches) {
|
|
50
28
|
const pending = pendingMutationVariables(queryClient, mutationKey);
|
|
51
29
|
if (!matches)
|
|
52
30
|
return pending.length > 0;
|
|
53
31
|
return pending.some((variables) => variables !== undefined && matches(variables));
|
|
54
32
|
}
|
|
55
|
-
/**
|
|
56
|
-
* The rejection a guarded `mutateAsync` throws for a duplicate submission: an `AbortError`, the
|
|
57
|
-
* shape a caller already treats as "nothing happened" rather than a failure to report.
|
|
58
|
-
*/
|
|
59
33
|
export function duplicateSubmissionError(what) {
|
|
60
34
|
const duplicate = new Error(`${what} is already in flight.`);
|
|
61
35
|
duplicate.name = 'AbortError';
|
|
62
36
|
return duplicate;
|
|
63
37
|
}
|
|
64
|
-
/**
|
|
65
|
-
* Wrap a keyed mutation's `mutate` / `mutateAsync` in the cache-consulting duplicate guard:
|
|
66
|
-
* `mutate` drops a duplicate silently, and `mutateAsync` rejects it with
|
|
67
|
-
* {@link duplicateSubmissionError}. `isDuplicate` must have a stable identity (declare it at module
|
|
68
|
-
* level) so the guarded callbacks keep theirs.
|
|
69
|
-
*/
|
|
38
|
+
/** `isDuplicate` must have a stable identity (declare it at module level) so the guarded callbacks keep theirs. */
|
|
70
39
|
export function useDuplicateGuardedMutation(mutation, isDuplicate, what) {
|
|
71
40
|
const queryClient = useQueryClient();
|
|
72
41
|
const { mutate: rawMutate, mutateAsync: rawMutateAsync } = mutation;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pending-mutations.js","sourceRoot":"","sources":["../../src/react/pending-mutations.ts"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAEb,
|
|
1
|
+
{"version":3,"file":"pending-mutations.js","sourceRoot":"","sources":["../../src/react/pending-mutations.ts"],"names":[],"mappings":"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","sourcesContent":["'use client';\n\nimport { useCallback } from 'react';\nimport {\n useMutationState,\n useQueryClient,\n type MutateOptions,\n type MutationKey,\n type QueryClient,\n type UseMutationResult,\n} from '@tanstack/react-query';\n\nexport function usePendingMutationVariables<V>(\n mutationKey: MutationKey,\n): ReadonlyArray<V | undefined> {\n return useMutationState({\n filters: { mutationKey, status: 'pending' },\n select: (mutation) => mutation.state.variables as V | undefined,\n });\n}\n\nexport function pendingMutationVariables<V>(\n queryClient: QueryClient,\n mutationKey: MutationKey,\n): Array<V | undefined> {\n return queryClient\n .getMutationCache()\n .findAll({ mutationKey, status: 'pending' })\n .map((mutation) => mutation.state.variables as V | undefined);\n}\n\nexport function usePendingMutationTargets<V>(\n mutationKey: MutationKey,\n targetOf: (variables: V) => string | null | undefined,\n): ReadonlySet<string> {\n const targets = new Set<string>();\n for (const variables of usePendingMutationVariables<V>(mutationKey)) {\n if (variables === undefined) continue;\n const target = targetOf(variables);\n if (target) targets.add(target);\n }\n return targets;\n}\n\nexport function hasPendingMutation<V>(\n queryClient: QueryClient,\n mutationKey: MutationKey,\n matches?: (variables: V) => boolean,\n): boolean {\n const pending = pendingMutationVariables<V>(queryClient, mutationKey);\n if (!matches) return pending.length > 0;\n return pending.some((variables) => variables !== undefined && matches(variables));\n}\n\nexport function duplicateSubmissionError(what: string): Error {\n const duplicate = new Error(`${what} is already in flight.`);\n duplicate.name = 'AbortError';\n return duplicate;\n}\n\n/** `isDuplicate` must have a stable identity (declare it at module level) so the guarded callbacks keep theirs. */\nexport function useDuplicateGuardedMutation<TData, TError, TVariables, TContext>(\n mutation: UseMutationResult<TData, TError, TVariables, TContext>,\n isDuplicate: (queryClient: QueryClient, variables: TVariables) => boolean,\n what: string,\n): UseMutationResult<TData, TError, TVariables, TContext> {\n const queryClient = useQueryClient();\n const { mutate: rawMutate, mutateAsync: rawMutateAsync } = mutation;\n const mutate = useCallback(\n (variables: TVariables, options?: MutateOptions<TData, TError, TVariables, TContext>) => {\n if (isDuplicate(queryClient, variables)) return;\n rawMutate(variables, options);\n },\n [queryClient, rawMutate, isDuplicate],\n );\n const mutateAsync = useCallback(\n async (variables: TVariables, options?: MutateOptions<TData, TError, TVariables, TContext>) => {\n if (isDuplicate(queryClient, variables)) throw duplicateSubmissionError(what);\n return rawMutateAsync(variables, options);\n },\n [queryClient, rawMutateAsync, isDuplicate, what],\n );\n return { ...mutation, mutate, mutateAsync } as UseMutationResult<\n TData,\n TError,\n TVariables,\n TContext\n >;\n}\n"]}
|
package/dist/react/provider.d.ts
CHANGED
|
@@ -1,12 +1,7 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { type CreateQueryClientOptions } from './query-client.js';
|
|
3
3
|
export type QueryProviderProps = React.PropsWithChildren<{
|
|
4
|
-
/** Optional overrides applied when the client is first created. */
|
|
5
4
|
clientOptions?: CreateQueryClientOptions;
|
|
6
5
|
}>;
|
|
7
|
-
/**
|
|
8
|
-
* Client component wrapper for Next.js / React apps.
|
|
9
|
-
* Creates a single QueryClient per browser session.
|
|
10
|
-
*/
|
|
11
6
|
export declare function QueryProvider({ children, clientOptions }: QueryProviderProps): React.JSX.Element;
|
|
12
7
|
//# sourceMappingURL=provider.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"provider.d.ts","sourceRoot":"","sources":["../../src/react/provider.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,OAAO,EAAqB,KAAK,wBAAwB,EAAE,MAAM,mBAAmB,CAAC;AAErF,MAAM,MAAM,kBAAkB,GAAG,KAAK,CAAC,iBAAiB,CAAC;IACvD,
|
|
1
|
+
{"version":3,"file":"provider.d.ts","sourceRoot":"","sources":["../../src/react/provider.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,OAAO,EAAqB,KAAK,wBAAwB,EAAE,MAAM,mBAAmB,CAAC;AAErF,MAAM,MAAM,kBAAkB,GAAG,KAAK,CAAC,iBAAiB,CAAC;IACvD,aAAa,CAAC,EAAE,wBAAwB,CAAC;CAC1C,CAAC,CAAC;AAEH,wBAAgB,aAAa,CAAC,EAAE,QAAQ,EAAE,aAAa,EAAE,EAAE,kBAAkB,qBAG5E"}
|
package/dist/react/provider.js
CHANGED
|
@@ -3,10 +3,6 @@ import { jsx as _jsx } from "react/jsx-runtime";
|
|
|
3
3
|
import React from 'react';
|
|
4
4
|
import { QueryClientProvider } from '@tanstack/react-query';
|
|
5
5
|
import { createQueryClient } from './query-client.js';
|
|
6
|
-
/**
|
|
7
|
-
* Client component wrapper for Next.js / React apps.
|
|
8
|
-
* Creates a single QueryClient per browser session.
|
|
9
|
-
*/
|
|
10
6
|
export function QueryProvider({ children, clientOptions }) {
|
|
11
7
|
const [client] = React.useState(() => createQueryClient(clientOptions));
|
|
12
8
|
return _jsx(QueryClientProvider, { client: client, children: children });
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"provider.js","sourceRoot":"","sources":["../../src/react/provider.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAC;;AAEb,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAC5D,OAAO,EAAE,iBAAiB,EAAiC,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"provider.js","sourceRoot":"","sources":["../../src/react/provider.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAC;;AAEb,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAC5D,OAAO,EAAE,iBAAiB,EAAiC,MAAM,mBAAmB,CAAC;AAMrF,MAAM,UAAU,aAAa,CAAC,EAAE,QAAQ,EAAE,aAAa,EAAsB;IAC3E,MAAM,CAAC,MAAM,CAAC,GAAG,KAAK,CAAC,QAAQ,CAAC,GAAG,EAAE,CAAC,iBAAiB,CAAC,aAAa,CAAC,CAAC,CAAC;IACxE,OAAO,KAAC,mBAAmB,IAAC,MAAM,EAAE,MAAM,YAAG,QAAQ,GAAuB,CAAC;AAC/E,CAAC","sourcesContent":["'use client';\n\nimport React from 'react';\nimport { QueryClientProvider } from '@tanstack/react-query';\nimport { createQueryClient, type CreateQueryClientOptions } from './query-client.js';\n\nexport type QueryProviderProps = React.PropsWithChildren<{\n clientOptions?: CreateQueryClientOptions;\n}>;\n\nexport function QueryProvider({ children, clientOptions }: QueryProviderProps) {\n const [client] = React.useState(() => createQueryClient(clientOptions));\n return <QueryClientProvider client={client}>{children}</QueryClientProvider>;\n}\n"]}
|
|
@@ -1,8 +1,4 @@
|
|
|
1
1
|
import { QueryClient, type QueryClientConfig } from '@tanstack/react-query';
|
|
2
2
|
export type CreateQueryClientOptions = QueryClientConfig;
|
|
3
|
-
/**
|
|
4
|
-
* Factory so every app uses the same baseline behavior.
|
|
5
|
-
* Pass overrides to adjust defaults without forking.
|
|
6
|
-
*/
|
|
7
3
|
export declare function createQueryClient(overrides?: CreateQueryClientOptions): QueryClient;
|
|
8
4
|
//# sourceMappingURL=query-client.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"query-client.d.ts","sourceRoot":"","sources":["../../src/react/query-client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,KAAK,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAG5E,MAAM,MAAM,wBAAwB,GAAG,iBAAiB,CAAC;AAEzD
|
|
1
|
+
{"version":3,"file":"query-client.d.ts","sourceRoot":"","sources":["../../src/react/query-client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,KAAK,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAG5E,MAAM,MAAM,wBAAwB,GAAG,iBAAiB,CAAC;AAEzD,wBAAgB,iBAAiB,CAAC,SAAS,GAAE,wBAA6B,eAiBzE"}
|
|
@@ -1,9 +1,5 @@
|
|
|
1
1
|
import { QueryClient } from '@tanstack/react-query';
|
|
2
2
|
import { defaultQueryClientConfig } from './defaults.js';
|
|
3
|
-
/**
|
|
4
|
-
* Factory so every app uses the same baseline behavior.
|
|
5
|
-
* Pass overrides to adjust defaults without forking.
|
|
6
|
-
*/
|
|
7
3
|
export function createQueryClient(overrides = {}) {
|
|
8
4
|
return new QueryClient({
|
|
9
5
|
...defaultQueryClientConfig,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"query-client.js","sourceRoot":"","sources":["../../src/react/query-client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAA0B,MAAM,uBAAuB,CAAC;AAC5E,OAAO,EAAE,wBAAwB,EAAE,MAAM,eAAe,CAAC;AAIzD
|
|
1
|
+
{"version":3,"file":"query-client.js","sourceRoot":"","sources":["../../src/react/query-client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAA0B,MAAM,uBAAuB,CAAC;AAC5E,OAAO,EAAE,wBAAwB,EAAE,MAAM,eAAe,CAAC;AAIzD,MAAM,UAAU,iBAAiB,CAAC,YAAsC,EAAE;IACxE,OAAO,IAAI,WAAW,CAAC;QACrB,GAAG,wBAAwB;QAC3B,GAAG,SAAS;QACZ,cAAc,EAAE;YACd,GAAG,wBAAwB,CAAC,cAAc;YAC1C,GAAG,SAAS,CAAC,cAAc;YAC3B,OAAO,EAAE;gBACP,GAAG,wBAAwB,CAAC,cAAc,EAAE,OAAO;gBACnD,GAAG,SAAS,CAAC,cAAc,EAAE,OAAO;aACrC;YACD,SAAS,EAAE;gBACT,GAAG,wBAAwB,CAAC,cAAc,EAAE,SAAS;gBACrD,GAAG,SAAS,CAAC,cAAc,EAAE,SAAS;aACvC;SACF;KACF,CAAC,CAAC;AACL,CAAC","sourcesContent":["import { QueryClient, type QueryClientConfig } from '@tanstack/react-query';\nimport { defaultQueryClientConfig } from './defaults.js';\n\nexport type CreateQueryClientOptions = QueryClientConfig;\n\nexport function createQueryClient(overrides: CreateQueryClientOptions = {}) {\n return new QueryClient({\n ...defaultQueryClientConfig,\n ...overrides,\n defaultOptions: {\n ...defaultQueryClientConfig.defaultOptions,\n ...overrides.defaultOptions,\n queries: {\n ...defaultQueryClientConfig.defaultOptions?.queries,\n ...overrides.defaultOptions?.queries,\n },\n mutations: {\n ...defaultQueryClientConfig.defaultOptions?.mutations,\n ...overrides.defaultOptions?.mutations,\n },\n },\n });\n}\n"]}
|
|
@@ -1,28 +1,16 @@
|
|
|
1
1
|
import type { DocumentData } from 'firebase/firestore';
|
|
2
2
|
import type { SearchEqualityFilter } from '../../search/types.js';
|
|
3
|
-
/**
|
|
4
|
-
* Options for useFirestoreSearch hook
|
|
5
|
-
*/
|
|
6
3
|
export interface FirestoreSearchOptions<T extends DocumentData = DocumentData> {
|
|
7
|
-
/** Firestore collection path to search */
|
|
8
4
|
collectionPath: string;
|
|
9
|
-
/** Field name to search on (must be indexed and lowercase) */
|
|
10
5
|
searchField: string;
|
|
11
|
-
/** Search query text */
|
|
12
6
|
queryText: string;
|
|
13
|
-
/** Maximum number of results (default: 5) */
|
|
14
7
|
limit?: number;
|
|
15
|
-
/** Enable/disable the search (default: true) */
|
|
16
8
|
enabled?: boolean;
|
|
17
|
-
/** Transform function to convert raw Firestore data to typed result */
|
|
18
9
|
select?: (data: DocumentData & {
|
|
19
10
|
id: string;
|
|
20
11
|
}) => T;
|
|
21
|
-
/** Debounce delay in milliseconds (default: 300) */
|
|
22
12
|
debounceMs?: number;
|
|
23
|
-
/** React Query stale time (default: 60000ms) */
|
|
24
13
|
staleTime?: number;
|
|
25
|
-
/** Optional equality filters applied before the prefix range. */
|
|
26
14
|
equalityFilters?: SearchEqualityFilter[];
|
|
27
15
|
}
|
|
28
16
|
//# sourceMappingURL=types.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/react/search/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AACvD,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAC;AAElE
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/react/search/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AACvD,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAC;AAElE,MAAM,WAAW,sBAAsB,CAAC,CAAC,SAAS,YAAY,GAAG,YAAY;IAC3E,cAAc,EAAE,MAAM,CAAC;IACvB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE,YAAY,GAAG;QAAE,EAAE,EAAE,MAAM,CAAA;KAAE,KAAK,CAAC,CAAC;IACpD,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,eAAe,CAAC,EAAE,oBAAoB,EAAE,CAAC;CAC1C"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/react/search/types.ts"],"names":[],"mappings":"","sourcesContent":["import type { DocumentData } from 'firebase/firestore';\nimport type { SearchEqualityFilter } from '../../search/types.js';\n\
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/react/search/types.ts"],"names":[],"mappings":"","sourcesContent":["import type { DocumentData } from 'firebase/firestore';\nimport type { SearchEqualityFilter } from '../../search/types.js';\n\nexport interface FirestoreSearchOptions<T extends DocumentData = DocumentData> {\n collectionPath: string;\n searchField: string;\n queryText: string;\n limit?: number;\n enabled?: boolean;\n select?: (data: DocumentData & { id: string }) => T;\n debounceMs?: number;\n staleTime?: number;\n equalityFilters?: SearchEqualityFilter[];\n}\n"]}
|
|
@@ -2,34 +2,5 @@ import { type UseQueryResult } from '@tanstack/react-query';
|
|
|
2
2
|
import { type DocumentData } from 'firebase/firestore';
|
|
3
3
|
import type { FirestoreSearchOptions } from './types.js';
|
|
4
4
|
import type { WithId } from '../../firestore/types.js';
|
|
5
|
-
/**
|
|
6
|
-
* Generic Firestore search hook with debouncing and case-insensitive prefix matching.
|
|
7
|
-
* Automatically normalizes search text to lowercase and uses Firestore range queries.
|
|
8
|
-
*
|
|
9
|
-
* Features:
|
|
10
|
-
* - Debounced input (default 300ms)
|
|
11
|
-
* - Case-insensitive search
|
|
12
|
-
* - Searches only a text `isSearchableText` accepts (`FIRESTORE_SEARCH_MIN_LENGTH`, trimmed)
|
|
13
|
-
* - No answer while the debounce lags the typed text: `data` is undefined and `isLoading` is true
|
|
14
|
-
* (idle instead when the typed text is too short or the search is disabled)
|
|
15
|
-
* - Prefix matching with '\uf8ff' suffix
|
|
16
|
-
* - Configurable result limit
|
|
17
|
-
*
|
|
18
|
-
* @example
|
|
19
|
-
* ```typescript
|
|
20
|
-
* const { data, isLoading } = useFirestoreSearch<UserProfile>({
|
|
21
|
-
* collectionPath: 'userProfiles',
|
|
22
|
-
* searchField: 'username',
|
|
23
|
-
* queryText: searchValue,
|
|
24
|
-
* });
|
|
25
|
-
*
|
|
26
|
-
* const { data } = useFirestoreSearch<Team>({
|
|
27
|
-
* collectionPath: 'teams',
|
|
28
|
-
* searchField: 'name_lowercase',
|
|
29
|
-
* queryText: searchValue,
|
|
30
|
-
* limit: 10,
|
|
31
|
-
* });
|
|
32
|
-
* ```
|
|
33
|
-
*/
|
|
34
5
|
export declare function useFirestoreSearch<T extends DocumentData = DocumentData>({ collectionPath, searchField, queryText, limit, enabled, select, debounceMs, staleTime, equalityFilters, }: FirestoreSearchOptions<T>): UseQueryResult<WithId<T>[], Error>;
|
|
35
6
|
//# sourceMappingURL=use-firestore-search.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-firestore-search.d.ts","sourceRoot":"","sources":["../../../src/react/search/use-firestore-search.ts"],"names":[],"mappings":"AAGA,OAAO,EAAY,KAAK,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACtE,OAAO,EAOL,KAAK,YAAY,EAElB,MAAM,oBAAoB,CAAC;AAG5B,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,YAAY,CAAC;AACzD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,0BAA0B,CAAC;AAOvD
|
|
1
|
+
{"version":3,"file":"use-firestore-search.d.ts","sourceRoot":"","sources":["../../../src/react/search/use-firestore-search.ts"],"names":[],"mappings":"AAGA,OAAO,EAAY,KAAK,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACtE,OAAO,EAOL,KAAK,YAAY,EAElB,MAAM,oBAAoB,CAAC;AAG5B,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,YAAY,CAAC;AACzD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,0BAA0B,CAAC;AAOvD,wBAAgB,kBAAkB,CAAC,CAAC,SAAS,YAAY,GAAG,YAAY,EAAE,EACxE,cAAc,EACd,WAAW,EACX,SAAS,EACT,KAAqB,EACrB,OAAc,EACd,MAAM,EACN,UAAgC,EAChC,SAA8B,EAC9B,eAAoB,GACrB,EAAE,sBAAsB,CAAC,CAAC,CAAC,GAAG,cAAc,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,KAAK,CAAC,CAyDhE"}
|
|
@@ -7,40 +7,10 @@ import { keys } from '../../keys.js';
|
|
|
7
7
|
import { isSearchableText, normalizeSearchText } from '../../search/rule.js';
|
|
8
8
|
const DEFAULT_LIMIT = 5;
|
|
9
9
|
const DEFAULT_DEBOUNCE_MS = 300;
|
|
10
|
-
const DEFAULT_STALE_TIME = 60 * 1000;
|
|
11
|
-
/**
|
|
12
|
-
* Generic Firestore search hook with debouncing and case-insensitive prefix matching.
|
|
13
|
-
* Automatically normalizes search text to lowercase and uses Firestore range queries.
|
|
14
|
-
*
|
|
15
|
-
* Features:
|
|
16
|
-
* - Debounced input (default 300ms)
|
|
17
|
-
* - Case-insensitive search
|
|
18
|
-
* - Searches only a text `isSearchableText` accepts (`FIRESTORE_SEARCH_MIN_LENGTH`, trimmed)
|
|
19
|
-
* - No answer while the debounce lags the typed text: `data` is undefined and `isLoading` is true
|
|
20
|
-
* (idle instead when the typed text is too short or the search is disabled)
|
|
21
|
-
* - Prefix matching with '\uf8ff' suffix
|
|
22
|
-
* - Configurable result limit
|
|
23
|
-
*
|
|
24
|
-
* @example
|
|
25
|
-
* ```typescript
|
|
26
|
-
* const { data, isLoading } = useFirestoreSearch<UserProfile>({
|
|
27
|
-
* collectionPath: 'userProfiles',
|
|
28
|
-
* searchField: 'username',
|
|
29
|
-
* queryText: searchValue,
|
|
30
|
-
* });
|
|
31
|
-
*
|
|
32
|
-
* const { data } = useFirestoreSearch<Team>({
|
|
33
|
-
* collectionPath: 'teams',
|
|
34
|
-
* searchField: 'name_lowercase',
|
|
35
|
-
* queryText: searchValue,
|
|
36
|
-
* limit: 10,
|
|
37
|
-
* });
|
|
38
|
-
* ```
|
|
39
|
-
*/
|
|
10
|
+
const DEFAULT_STALE_TIME = 60 * 1000;
|
|
40
11
|
export function useFirestoreSearch({ collectionPath, searchField, queryText, limit = DEFAULT_LIMIT, enabled = true, select, debounceMs = DEFAULT_DEBOUNCE_MS, staleTime = DEFAULT_STALE_TIME, equalityFilters = [], }) {
|
|
41
12
|
const db = useFirestoreDb();
|
|
42
13
|
const [debouncedQuery, setDebouncedQuery] = useState(queryText);
|
|
43
|
-
// Debounce the search query
|
|
44
14
|
useEffect(() => {
|
|
45
15
|
const timer = setTimeout(() => {
|
|
46
16
|
setDebouncedQuery(queryText);
|
|
@@ -56,8 +26,7 @@ export function useFirestoreSearch({ collectionPath, searchField, queryText, lim
|
|
|
56
26
|
return [];
|
|
57
27
|
}
|
|
58
28
|
const collectionRef = collection(db, collectionPath);
|
|
59
|
-
//
|
|
60
|
-
// Using '\uf8ff' as upper bound creates a range that matches all strings starting with the query
|
|
29
|
+
// '\uf8ff' is the highest code point Firestore orders, so the range covers every string with the prefix.
|
|
61
30
|
const constraints = [
|
|
62
31
|
...equalityFilters.map((f) => where(f.field, '==', f.value)),
|
|
63
32
|
where(searchField, '>=', normalizedQuery),
|
|
@@ -77,20 +46,13 @@ export function useFirestoreSearch({ collectionPath, searchField, queryText, lim
|
|
|
77
46
|
enabled: shouldSearch,
|
|
78
47
|
staleTime,
|
|
79
48
|
});
|
|
80
|
-
// Until the debounce catches up, the query's key holds an earlier text, so its result (or its
|
|
81
|
-
// absence) is not an answer for the text typed now (FRONTEND-206): report no answer instead —
|
|
82
|
-
// still searching when the typed text will be searched, idle when it will not.
|
|
83
49
|
const typedQuery = normalizeSearchText(queryText);
|
|
84
50
|
if (typedQuery === normalizedQuery)
|
|
85
51
|
return searchQuery;
|
|
86
52
|
const willSearch = enabled && isSearchableText(queryText);
|
|
87
53
|
return withoutAnswer(searchQuery, willSearch);
|
|
88
54
|
}
|
|
89
|
-
/**
|
|
90
|
-
* The query result with every answer field replaced. The other fields stay getters onto the
|
|
91
|
-
* original result: TanStack tracks which fields a component reads to decide when it re-renders,
|
|
92
|
-
* and reading them all here (a spread) would opt every consumer out of that.
|
|
93
|
-
*/
|
|
55
|
+
/** Other fields stay getters onto the original result: TanStack re-renders on the fields a component reads, and a spread reads them all. */
|
|
94
56
|
function withoutAnswer(result, searching) {
|
|
95
57
|
const answerFields = {
|
|
96
58
|
data: undefined,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-firestore-search.js","sourceRoot":"","sources":["../../../src/react/search/use-firestore-search.ts"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAEb,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAC5C,OAAO,EAAE,QAAQ,EAAuB,MAAM,uBAAuB,CAAC;AACtE,OAAO,EACL,UAAU,EACV,OAAO,EACP,KAAK,EACL,KAAK,EACL,OAAO,EACP,KAAK,IAAI,cAAc,GAGxB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AACzD,OAAO,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AAGrC,OAAO,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AAE7E,MAAM,aAAa,GAAG,CAAC,CAAC;AACxB,MAAM,mBAAmB,GAAG,GAAG,CAAC;AAChC,MAAM,kBAAkB,GAAG,EAAE,GAAG,IAAI,CAAC
|
|
1
|
+
{"version":3,"file":"use-firestore-search.js","sourceRoot":"","sources":["../../../src/react/search/use-firestore-search.ts"],"names":[],"mappings":"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","sourcesContent":["'use client';\n\nimport { useState, useEffect } from 'react';\nimport { useQuery, type UseQueryResult } from '@tanstack/react-query';\nimport {\n collection,\n getDocs,\n query,\n where,\n orderBy,\n limit as firestoreLimit,\n type DocumentData,\n type QueryConstraint,\n} from 'firebase/firestore';\nimport { useFirestoreDb } from '../firestore/context.js';\nimport { keys } from '../../keys.js';\nimport type { FirestoreSearchOptions } from './types.js';\nimport type { WithId } from '../../firestore/types.js';\nimport { isSearchableText, normalizeSearchText } from '../../search/rule.js';\n\nconst DEFAULT_LIMIT = 5;\nconst DEFAULT_DEBOUNCE_MS = 300;\nconst DEFAULT_STALE_TIME = 60 * 1000;\n\nexport function useFirestoreSearch<T extends DocumentData = DocumentData>({\n collectionPath,\n searchField,\n queryText,\n limit = DEFAULT_LIMIT,\n enabled = true,\n select,\n debounceMs = DEFAULT_DEBOUNCE_MS,\n staleTime = DEFAULT_STALE_TIME,\n equalityFilters = [],\n}: FirestoreSearchOptions<T>): UseQueryResult<WithId<T>[], Error> {\n const db = useFirestoreDb();\n const [debouncedQuery, setDebouncedQuery] = useState(queryText);\n\n useEffect(() => {\n const timer = setTimeout(() => {\n setDebouncedQuery(queryText);\n }, debounceMs);\n\n return () => clearTimeout(timer);\n }, [queryText, debounceMs]);\n\n const normalizedQuery = normalizeSearchText(debouncedQuery);\n const shouldSearch = enabled && isSearchableText(debouncedQuery);\n\n const searchQuery = useQuery({\n queryKey: keys.custom(\n 'search',\n collectionPath,\n searchField,\n normalizedQuery,\n JSON.stringify(equalityFilters),\n ),\n queryFn: async (): Promise<WithId<T>[]> => {\n if (!shouldSearch) {\n return [];\n }\n\n const collectionRef = collection(db, collectionPath);\n\n // '\\uf8ff' is the highest code point Firestore orders, so the range covers every string with the prefix.\n const constraints: QueryConstraint[] = [\n ...equalityFilters.map((f) => where(f.field, '==', f.value)),\n where(searchField, '>=', normalizedQuery),\n where(searchField, '<=', normalizedQuery + '\\uf8ff'),\n orderBy(searchField, 'asc'),\n firestoreLimit(limit),\n ];\n\n const q = query(collectionRef, ...constraints);\n const snapshot = await getDocs(q);\n\n return snapshot.docs.map((docSnap) => {\n const rawData = docSnap.data();\n const dataWithId = { id: docSnap.id, ...rawData };\n const data = select ? select(dataWithId) : dataWithId;\n return data as WithId<T>;\n });\n },\n enabled: shouldSearch,\n staleTime,\n });\n\n const typedQuery = normalizeSearchText(queryText);\n if (typedQuery === normalizedQuery) return searchQuery;\n const willSearch = enabled && isSearchableText(queryText);\n return withoutAnswer(searchQuery, willSearch);\n}\n\n/** Other fields stay getters onto the original result: TanStack re-renders on the fields a component reads, and a spread reads them all. */\nfunction withoutAnswer<R extends UseQueryResult<unknown, Error>>(result: R, searching: boolean): R {\n const answerFields: Record<string, unknown> = {\n data: undefined,\n error: null,\n isError: false,\n isLoadingError: false,\n isRefetchError: false,\n isSuccess: false,\n isPending: true,\n isPlaceholderData: false,\n isFetched: false,\n isFetchedAfterMount: false,\n isRefetching: false,\n isLoading: searching,\n isFetching: searching,\n status: 'pending',\n fetchStatus: searching ? 'fetching' : 'idle',\n dataUpdatedAt: 0,\n errorUpdatedAt: 0,\n };\n const view = {} as R;\n for (const key of Object.keys(result)) {\n Object.defineProperty(view, key, {\n enumerable: true,\n configurable: true,\n get: key in answerFields ? () => answerFields[key] : () => result[key as keyof R],\n });\n }\n return view;\n}\n"]}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { type ReactNode } from 'react';
|
|
2
|
+
import { type DefaultError, type MutationFunctionContext, type UseMutationOptions, type UseMutationResult } from '@tanstack/react-query';
|
|
3
|
+
export interface MutationSession {
|
|
4
|
+
uid: string | null;
|
|
5
|
+
isCurrent(): boolean;
|
|
6
|
+
assertCurrent(): void;
|
|
7
|
+
}
|
|
8
|
+
export type SessionMutationFunctionContext = MutationFunctionContext & {
|
|
9
|
+
session: MutationSession;
|
|
10
|
+
};
|
|
11
|
+
export type SessionMutationOptions<TData = unknown, TError = DefaultError, TVariables = void, TOnMutateResult = unknown> = Omit<UseMutationOptions<TData, TError, TVariables, TOnMutateResult>, 'mutationFn'> & {
|
|
12
|
+
mutationFn: (variables: TVariables, context: SessionMutationFunctionContext) => Promise<TData>;
|
|
13
|
+
};
|
|
14
|
+
export declare class MutationSessionEndedError extends Error {
|
|
15
|
+
name: string;
|
|
16
|
+
constructor(options?: {
|
|
17
|
+
cause?: unknown;
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
export interface MutationSessionProviderProps {
|
|
21
|
+
currentUid: string | null;
|
|
22
|
+
children?: ReactNode;
|
|
23
|
+
}
|
|
24
|
+
export declare function MutationSessionProvider({ currentUid, children }: MutationSessionProviderProps): import("react").JSX.Element;
|
|
25
|
+
export declare function useMutationSessionCapture(): () => MutationSession;
|
|
26
|
+
export declare function useSessionMutation<TData = unknown, TError = DefaultError, TVariables = void, TOnMutateResult = unknown>(options: SessionMutationOptions<TData, TError, TVariables, TOnMutateResult>): UseMutationResult<TData, TError, TVariables, TOnMutateResult>;
|
|
27
|
+
//# sourceMappingURL=session-mutation.d.ts.map
|
|
@@ -0,0 +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,CAAC,kBAAkB,CAAC,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,eAAe,CAAC,EAAE,YAAY,CAAC,GAAG;IACvF,UAAU,EAAE,CAAC,SAAS,EAAE,UAAU,EAAE,OAAO,EAAE,8BAA8B,KAAK,OAAO,CAAC,KAAK,CAAC,CAAC;CAChG,CAAC;AAEF,qBAAa,yBAA0B,SAAQ,KAAK;IACzC,IAAI,SAAgB;gBAEjB,OAAO,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,OAAO,CAAA;KAAE;CAG1C;AAQD,MAAM,WAAW,4BAA4B;IAC3C,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,QAAQ,CAAC,EAAE,SAAS,CAAC;CACtB;AAED,wBAAgB,uBAAuB,CAAC,EAAE,UAAU,EAAE,QAAQ,EAAE,EAAE,4BAA4B,+BAc7F;AAqBD,wBAAgB,yBAAyB,IAAI,MAAM,eAAe,CAGjE;AAsDD,wBAAgB,kBAAkB,CAChC,KAAK,GAAG,OAAO,EACf,MAAM,GAAG,YAAY,EACrB,UAAU,GAAG,IAAI,EACjB,eAAe,GAAG,OAAO,EAEzB,OAAO,EAAE,sBAAsB,CAAC,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,eAAe,CAAC,GAC1E,iBAAiB,CAAC,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,eAAe,CAAC,CAmE/D"}
|