@ttt-productions/query-core 0.14.14 → 0.14.16
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.
|
@@ -2,8 +2,10 @@ import type { UseQueryResult } from '@tanstack/react-query';
|
|
|
2
2
|
import type { FirestoreSourceState, WithSourceState } from '../../firestore/types.js';
|
|
3
3
|
/** A restart a subscribed result's `refetch()` asked for, open until the listener's first snapshot or its next error. */
|
|
4
4
|
interface PendingRestart {
|
|
5
|
-
/** The listener had failed
|
|
5
|
+
/** The listener had failed when the restart was asked for. */
|
|
6
6
|
fromError: boolean;
|
|
7
|
+
/** That failure, kept beside the held data while the restart is open, as a one-shot refetch keeps it. */
|
|
8
|
+
failure: Error | null;
|
|
7
9
|
}
|
|
8
10
|
interface SubscriptionStatus {
|
|
9
11
|
identity: string;
|
|
@@ -37,8 +39,13 @@ type SubscriptionStatusApi = ReturnType<typeof useSubscriptionStatus>;
|
|
|
37
39
|
* The subscribed hooks' result: the query's own result, with the listener's error and source
|
|
38
40
|
* state merged in. In subscribe mode `refetch()` re-opens the listener (clearing its error, with a
|
|
39
41
|
* fresh resubscribe ladder) and resolves once the re-opened listener delivers its first snapshot or
|
|
40
|
-
* surfaces its next error; until then the result reports fetching.
|
|
41
|
-
*
|
|
42
|
+
* surfaces its next error; until then the result reports fetching.
|
|
43
|
+
*
|
|
44
|
+
* A listener that fails after it answered keeps its last snapshot as `data` beside the failure, the
|
|
45
|
+
* way a one-shot read that fails a refetch keeps its data: `status: 'error'` and `isRefetchError`
|
|
46
|
+
* say the rows are not current, and a consumer can keep what it showed instead of tearing it down.
|
|
47
|
+
* A restart from that failure keeps both — the held data and the failure — until the re-opened
|
|
48
|
+
* listener answers. A listener that failed before it ever answered has no data to hold.
|
|
42
49
|
*/
|
|
43
50
|
export declare function useSubscribedResult<TData>(query: UseQueryResult<TData, Error>, subscribe: boolean, enabled: boolean, status: SubscriptionStatusApi): WithSourceState<UseQueryResult<TData, Error>>;
|
|
44
51
|
export {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"subscription-status.d.ts","sourceRoot":"","sources":["../../../src/react/firestore/subscription-status.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAuC,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACjG,OAAO,KAAK,EAAE,oBAAoB,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAC;AAEtF,yHAAyH;AACzH,UAAU,cAAc;IACtB,
|
|
1
|
+
{"version":3,"file":"subscription-status.d.ts","sourceRoot":"","sources":["../../../src/react/firestore/subscription-status.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAuC,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACjG,OAAO,KAAK,EAAE,oBAAoB,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAC;AAEtF,yHAAyH;AACzH,UAAU,cAAc;IACtB,8DAA8D;IAC9D,SAAS,EAAE,OAAO,CAAC;IACnB,yGAAyG;IACzG,OAAO,EAAE,KAAK,GAAG,IAAI,CAAC;CACvB;AAED,UAAU,kBAAkB;IAC1B,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;IACpB,WAAW,EAAE,oBAAoB,CAAC;IAClC,OAAO,EAAE,cAAc,GAAG,IAAI,CAAC;IAC/B,mGAAmG;IACnG,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,KAAK,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,kBAAkB,EAAE,UAAU,GAAG,UAAU,CAAC,CAAC,CAAC;AAM9E;;;;;;;;GAQG;AACH,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,MAAM;;;;;;oBAc1C,WAAW,GAAG,CAAC,CAAC,IAAI,EAAE,kBAAkB,KAAK,WAAW,CAAC;mBAkBnC,OAAO;EA2BxC;AAED,KAAK,qBAAqB,GAAG,UAAU,CAAC,OAAO,qBAAqB,CAAC,CAAC;AAQtE;;;;;;;;;;;GAWG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EACvC,KAAK,EAAE,cAAc,CAAC,KAAK,EAAE,KAAK,CAAC,EACnC,SAAS,EAAE,OAAO,EAClB,OAAO,EAAE,OAAO,EAChB,MAAM,EAAE,qBAAqB,GAC5B,eAAe,CAAC,cAAc,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC,CA0H/C"}
|
|
@@ -44,7 +44,10 @@ export function useSubscriptionStatus(identity) {
|
|
|
44
44
|
...base,
|
|
45
45
|
error: null,
|
|
46
46
|
sourceState: 'connecting',
|
|
47
|
-
restart: {
|
|
47
|
+
restart: {
|
|
48
|
+
fromError: base.error !== null || base.restart?.fromError === true,
|
|
49
|
+
failure: base.error ?? base.restart?.failure ?? null,
|
|
50
|
+
},
|
|
48
51
|
restarts: base.restarts + 1,
|
|
49
52
|
};
|
|
50
53
|
});
|
|
@@ -64,8 +67,13 @@ export function useSubscriptionStatus(identity) {
|
|
|
64
67
|
* The subscribed hooks' result: the query's own result, with the listener's error and source
|
|
65
68
|
* state merged in. In subscribe mode `refetch()` re-opens the listener (clearing its error, with a
|
|
66
69
|
* fresh resubscribe ladder) and resolves once the re-opened listener delivers its first snapshot or
|
|
67
|
-
* surfaces its next error; until then the result reports fetching.
|
|
68
|
-
*
|
|
70
|
+
* surfaces its next error; until then the result reports fetching.
|
|
71
|
+
*
|
|
72
|
+
* A listener that fails after it answered keeps its last snapshot as `data` beside the failure, the
|
|
73
|
+
* way a one-shot read that fails a refetch keeps its data: `status: 'error'` and `isRefetchError`
|
|
74
|
+
* say the rows are not current, and a consumer can keep what it showed instead of tearing it down.
|
|
75
|
+
* A restart from that failure keeps both — the held data and the failure — until the re-opened
|
|
76
|
+
* listener answers. A listener that failed before it ever answered has no data to hold.
|
|
69
77
|
*/
|
|
70
78
|
export function useSubscribedResult(query, subscribe, enabled, status) {
|
|
71
79
|
const { error, sourceState, pendingRestart, restart } = status;
|
|
@@ -91,12 +99,14 @@ export function useSubscribedResult(query, subscribe, enabled, status) {
|
|
|
91
99
|
result = query;
|
|
92
100
|
}
|
|
93
101
|
else if (error) {
|
|
102
|
+
const held = query.data !== undefined;
|
|
94
103
|
result = {
|
|
95
104
|
...query,
|
|
96
|
-
data:
|
|
105
|
+
data: query.data,
|
|
97
106
|
error,
|
|
98
107
|
isError: true,
|
|
99
|
-
isLoadingError:
|
|
108
|
+
isLoadingError: !held,
|
|
109
|
+
isRefetchError: held,
|
|
100
110
|
isSuccess: false,
|
|
101
111
|
isPending: false,
|
|
102
112
|
isLoading: false,
|
|
@@ -104,6 +114,23 @@ export function useSubscribedResult(query, subscribe, enabled, status) {
|
|
|
104
114
|
refetch,
|
|
105
115
|
};
|
|
106
116
|
}
|
|
117
|
+
else if (pendingRestart?.fromError && query.data !== undefined) {
|
|
118
|
+
result = {
|
|
119
|
+
...query,
|
|
120
|
+
error: pendingRestart.failure,
|
|
121
|
+
isError: pendingRestart.failure !== null,
|
|
122
|
+
isLoadingError: false,
|
|
123
|
+
isRefetchError: pendingRestart.failure !== null,
|
|
124
|
+
isSuccess: false,
|
|
125
|
+
isPending: false,
|
|
126
|
+
isLoading: false,
|
|
127
|
+
isFetching: true,
|
|
128
|
+
isRefetching: true,
|
|
129
|
+
status: pendingRestart.failure !== null ? 'error' : query.status,
|
|
130
|
+
fetchStatus: 'fetching',
|
|
131
|
+
refetch,
|
|
132
|
+
};
|
|
133
|
+
}
|
|
107
134
|
else if (pendingRestart?.fromError) {
|
|
108
135
|
result = {
|
|
109
136
|
...query,
|
|
@@ -132,6 +159,18 @@ export function useSubscribedResult(query, subscribe, enabled, status) {
|
|
|
132
159
|
refetch,
|
|
133
160
|
};
|
|
134
161
|
}
|
|
162
|
+
else if (active && query.isPending) {
|
|
163
|
+
// The listener has not delivered its first snapshot. The query underneath is disabled in
|
|
164
|
+
// subscribe mode, so it reports pending but not loading; the read IS loading, exactly like a
|
|
165
|
+
// one-shot read's first fetch — never an answered absence.
|
|
166
|
+
result = {
|
|
167
|
+
...query,
|
|
168
|
+
isLoading: true,
|
|
169
|
+
isFetching: true,
|
|
170
|
+
fetchStatus: 'fetching',
|
|
171
|
+
refetch,
|
|
172
|
+
};
|
|
173
|
+
}
|
|
135
174
|
else {
|
|
136
175
|
result = { ...query, refetch };
|
|
137
176
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"subscription-status.js","sourceRoot":"","sources":["../../../src/react/firestore/subscription-status.ts"],"names":[],"mappings":"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","sourcesContent":["'use client';\n\nimport { useCallback, useEffect, useRef, useState } from 'react';\nimport type { QueryObserverResult, RefetchOptions, UseQueryResult } from '@tanstack/react-query';\nimport type { FirestoreSourceState, WithSourceState } from '../../firestore/types.js';\n\n/** A restart a subscribed result's `refetch()` asked for, open until the listener's first snapshot or its next error. */\ninterface PendingRestart {\n /** The listener had failed: its last data is not shown as current while the restart is open. */\n fromError: boolean;\n}\n\ninterface SubscriptionStatus {\n identity: string;\n error: Error | null;\n sourceState: FirestoreSourceState;\n restart: PendingRestart | null;\n /** Bumped by every restart; the listener effect depends on it, so a bump re-opens the listener. */\n restarts: number;\n}\n\ntype StatusPatch = Partial<Omit<SubscriptionStatus, 'identity' | 'restarts'>>;\n\nfunction freshStatus(identity: string): SubscriptionStatus {\n return { identity, error: null, sourceState: 'connecting', restart: null, restarts: 0 };\n}\n\n/**\n * A realtime listener's source state and error, tagged to the subscription identity that\n * produced them. A new identity reads `connecting` with no error from its first render;\n * writes made for a retired identity are dropped once the new identity's listener has\n * started (it calls `reset`).\n *\n * `restart()` clears the error and bumps `restarts`; the listener effect re-opens on the bump,\n * and its first snapshot or next surfaced error ends the restart (`settled` in the patch).\n */\nexport function useSubscriptionStatus(identity: string) {\n const [status, setStatus] = useState<SubscriptionStatus>(() => freshStatus(identity));\n\n const current: SubscriptionStatus = status.identity === identity ? status : freshStatus(identity);\n\n const reset = useCallback(() => {\n setStatus((prev) =>\n prev.identity === identity\n ? { ...prev, error: null, sourceState: 'connecting' }\n : freshStatus(identity),\n );\n }, [identity]);\n\n const update = useCallback(\n (patch: StatusPatch | ((prev: SubscriptionStatus) => StatusPatch)) => {\n setStatus((prev) => {\n if (prev.identity !== identity) return prev;\n const next = typeof patch === 'function' ? patch(prev) : patch;\n return { ...prev, ...next };\n });\n },\n [identity],\n );\n\n // The identity the hook renders now. A `restart` captured under an earlier identity must not\n // touch the current one's status, or every write the current listener makes would be dropped.\n const renderedIdentity = useRef(identity);\n useEffect(() => {\n renderedIdentity.current = identity;\n }, [identity]);\n\n /** Re-opens the listener; false (and nothing changes) when this identity is no longer rendered. */\n const restart = useCallback((): boolean => {\n if (renderedIdentity.current !== identity) return false;\n setStatus((prev) => {\n const base = prev.identity === identity ? prev : freshStatus(identity);\n return {\n ...base,\n error: null,\n sourceState: 'connecting',\n restart: { fromError: base.error !== null || base.restart?.fromError === true },\n restarts: base.restarts + 1,\n };\n });\n return true;\n }, [identity]);\n\n return {\n error: current.error,\n sourceState: current.sourceState,\n pendingRestart: current.restart,\n restarts: current.restarts,\n reset,\n update,\n restart,\n };\n}\n\ntype SubscriptionStatusApi = ReturnType<typeof useSubscriptionStatus>;\n\ninterface RefetchWaiter<TData> {\n resolve: (result: QueryObserverResult<TData, Error>) => void;\n reject: (error: Error) => void;\n throwOnError: boolean;\n}\n\n/**\n * The subscribed hooks' result: the query's own result, with the listener's error and source\n * state merged in. In subscribe mode `refetch()` re-opens the listener (clearing its error, with a\n * fresh resubscribe ladder) and resolves once the re-opened listener delivers its first snapshot or\n * surfaces its next error; until then the result reports fetching. A restart after a failure shows\n * no data until that snapshot: the failed listener's last rows are not presented as current.\n */\nexport function useSubscribedResult<TData>(\n query: UseQueryResult<TData, Error>,\n subscribe: boolean,\n enabled: boolean,\n status: SubscriptionStatusApi,\n): WithSourceState<UseQueryResult<TData, Error>> {\n const { error, sourceState, pendingRestart, restart } = status;\n const waiters = useRef<RefetchWaiter<TData>[]>([]);\n const latest = useRef(query as QueryObserverResult<TData, Error>);\n const mounted = useRef(true);\n const active = subscribe && enabled;\n\n const refetch = useCallback(\n (options?: RefetchOptions): Promise<QueryObserverResult<TData, Error>> => {\n // An unmounted hook, or a refetch captured under an identity the hook has left, re-opens\n // nothing: it settles at once rather than waiting on a listener that will never report.\n if (!active || !mounted.current) return Promise.resolve(latest.current);\n return new Promise((resolve, reject) => {\n if (!restart()) {\n resolve(latest.current);\n return;\n }\n waiters.current.push({ resolve, reject, throwOnError: options?.throwOnError === true });\n });\n },\n [active, restart],\n );\n\n let result: UseQueryResult<TData, Error>;\n if (!subscribe) {\n result = query;\n } else if (error) {\n result = {\n ...query,\n data: undefined,\n error,\n isError: true,\n isLoadingError: true,\n isSuccess: false,\n isPending: false,\n isLoading: false,\n status: 'error',\n refetch,\n } as UseQueryResult<TData, Error>;\n } else if (pendingRestart?.fromError) {\n result = {\n ...query,\n data: undefined,\n error: null,\n isError: false,\n isLoadingError: false,\n isRefetchError: false,\n isSuccess: false,\n isPending: true,\n isLoading: true,\n isFetching: true,\n isRefetching: false,\n status: 'pending',\n fetchStatus: 'fetching',\n refetch,\n } as UseQueryResult<TData, Error>;\n } else if (pendingRestart) {\n result = {\n ...query,\n isFetching: true,\n isLoading: query.isPending,\n isRefetching: !query.isPending,\n fetchStatus: 'fetching',\n refetch,\n } as UseQueryResult<TData, Error>;\n } else {\n result = { ...query, refetch } as UseQueryResult<TData, Error>;\n }\n\n const restartOpen = pendingRestart !== null;\n useEffect(() => {\n latest.current = result as QueryObserverResult<TData, Error>;\n if (restartOpen || waiters.current.length === 0) return;\n const settled = waiters.current;\n waiters.current = [];\n for (const waiter of settled) {\n if (waiter.throwOnError && result.error) waiter.reject(result.error);\n else waiter.resolve(result as QueryObserverResult<TData, Error>);\n }\n });\n\n // A refetch still open when the hook unmounts resolves with the last result instead of hanging.\n useEffect(() => {\n mounted.current = true;\n return () => {\n mounted.current = false;\n const settled = waiters.current;\n waiters.current = [];\n for (const waiter of settled) waiter.resolve(latest.current);\n };\n }, []);\n\n return { ...result, sourceState } as WithSourceState<UseQueryResult<TData, Error>>;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"subscription-status.js","sourceRoot":"","sources":["../../../src/react/firestore/subscription-status.ts"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAEb,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAuBjE,SAAS,WAAW,CAAC,QAAgB;IACnC,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,IAAI,EAAE,WAAW,EAAE,YAAY,EAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC,EAAE,CAAC;AAC1F,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,qBAAqB,CAAC,QAAgB;IACpD,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,GAAG,QAAQ,CAAqB,GAAG,EAAE,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC,CAAC;IAEtF,MAAM,OAAO,GAAuB,MAAM,CAAC,QAAQ,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC;IAElG,MAAM,KAAK,GAAG,WAAW,CAAC,GAAG,EAAE;QAC7B,SAAS,CAAC,CAAC,IAAI,EAAE,EAAE,CACjB,IAAI,CAAC,QAAQ,KAAK,QAAQ;YACxB,CAAC,CAAC,EAAE,GAAG,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,WAAW,EAAE,YAAY,EAAE;YACrD,CAAC,CAAC,WAAW,CAAC,QAAQ,CAAC,CAC1B,CAAC;IACJ,CAAC,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC;IAEf,MAAM,MAAM,GAAG,WAAW,CACxB,CAAC,KAAgE,EAAE,EAAE;QACnE,SAAS,CAAC,CAAC,IAAI,EAAE,EAAE;YACjB,IAAI,IAAI,CAAC,QAAQ,KAAK,QAAQ;gBAAE,OAAO,IAAI,CAAC;YAC5C,MAAM,IAAI,GAAG,OAAO,KAAK,KAAK,UAAU,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;YAC/D,OAAO,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,EAAE,CAAC;QAC9B,CAAC,CAAC,CAAC;IACL,CAAC,EACD,CAAC,QAAQ,CAAC,CACX,CAAC;IAEF,6FAA6F;IAC7F,8FAA8F;IAC9F,MAAM,gBAAgB,GAAG,MAAM,CAAC,QAAQ,CAAC,CAAC;IAC1C,SAAS,CAAC,GAAG,EAAE;QACb,gBAAgB,CAAC,OAAO,GAAG,QAAQ,CAAC;IACtC,CAAC,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC;IAEf,mGAAmG;IACnG,MAAM,OAAO,GAAG,WAAW,CAAC,GAAY,EAAE;QACxC,IAAI,gBAAgB,CAAC,OAAO,KAAK,QAAQ;YAAE,OAAO,KAAK,CAAC;QACxD,SAAS,CAAC,CAAC,IAAI,EAAE,EAAE;YACjB,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC;YACvE,OAAO;gBACL,GAAG,IAAI;gBACP,KAAK,EAAE,IAAI;gBACX,WAAW,EAAE,YAAY;gBACzB,OAAO,EAAE;oBACP,SAAS,EAAE,IAAI,CAAC,KAAK,KAAK,IAAI,IAAI,IAAI,CAAC,OAAO,EAAE,SAAS,KAAK,IAAI;oBAClE,OAAO,EAAE,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,OAAO,EAAE,OAAO,IAAI,IAAI;iBACrD;gBACD,QAAQ,EAAE,IAAI,CAAC,QAAQ,GAAG,CAAC;aAC5B,CAAC;QACJ,CAAC,CAAC,CAAC;QACH,OAAO,IAAI,CAAC;IACd,CAAC,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC;IAEf,OAAO;QACL,KAAK,EAAE,OAAO,CAAC,KAAK;QACpB,WAAW,EAAE,OAAO,CAAC,WAAW;QAChC,cAAc,EAAE,OAAO,CAAC,OAAO;QAC/B,QAAQ,EAAE,OAAO,CAAC,QAAQ;QAC1B,KAAK;QACL,MAAM;QACN,OAAO;KACR,CAAC;AACJ,CAAC;AAUD;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,mBAAmB,CACjC,KAAmC,EACnC,SAAkB,EAClB,OAAgB,EAChB,MAA6B;IAE7B,MAAM,EAAE,KAAK,EAAE,WAAW,EAAE,cAAc,EAAE,OAAO,EAAE,GAAG,MAAM,CAAC;IAC/D,MAAM,OAAO,GAAG,MAAM,CAAyB,EAAE,CAAC,CAAC;IACnD,MAAM,MAAM,GAAG,MAAM,CAAC,KAA0C,CAAC,CAAC;IAClE,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC;IAC7B,MAAM,MAAM,GAAG,SAAS,IAAI,OAAO,CAAC;IAEpC,MAAM,OAAO,GAAG,WAAW,CACzB,CAAC,OAAwB,EAA8C,EAAE;QACvE,yFAAyF;QACzF,wFAAwF;QACxF,IAAI,CAAC,MAAM,IAAI,CAAC,OAAO,CAAC,OAAO;YAAE,OAAO,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;QACxE,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;YACrC,IAAI,CAAC,OAAO,EAAE,EAAE,CAAC;gBACf,OAAO,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;gBACxB,OAAO;YACT,CAAC;YACD,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,YAAY,EAAE,OAAO,EAAE,YAAY,KAAK,IAAI,EAAE,CAAC,CAAC;QAC1F,CAAC,CAAC,CAAC;IACL,CAAC,EACD,CAAC,MAAM,EAAE,OAAO,CAAC,CAClB,CAAC;IAEF,IAAI,MAAoC,CAAC;IACzC,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,MAAM,GAAG,KAAK,CAAC;IACjB,CAAC;SAAM,IAAI,KAAK,EAAE,CAAC;QACjB,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,KAAK,SAAS,CAAC;QACtC,MAAM,GAAG;YACP,GAAG,KAAK;YACR,IAAI,EAAE,KAAK,CAAC,IAAI;YAChB,KAAK;YACL,OAAO,EAAE,IAAI;YACb,cAAc,EAAE,CAAC,IAAI;YACrB,cAAc,EAAE,IAAI;YACpB,SAAS,EAAE,KAAK;YAChB,SAAS,EAAE,KAAK;YAChB,SAAS,EAAE,KAAK;YAChB,MAAM,EAAE,OAAO;YACf,OAAO;SACwB,CAAC;IACpC,CAAC;SAAM,IAAI,cAAc,EAAE,SAAS,IAAI,KAAK,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;QACjE,MAAM,GAAG;YACP,GAAG,KAAK;YACR,KAAK,EAAE,cAAc,CAAC,OAAO;YAC7B,OAAO,EAAE,cAAc,CAAC,OAAO,KAAK,IAAI;YACxC,cAAc,EAAE,KAAK;YACrB,cAAc,EAAE,cAAc,CAAC,OAAO,KAAK,IAAI;YAC/C,SAAS,EAAE,KAAK;YAChB,SAAS,EAAE,KAAK;YAChB,SAAS,EAAE,KAAK;YAChB,UAAU,EAAE,IAAI;YAChB,YAAY,EAAE,IAAI;YAClB,MAAM,EAAE,cAAc,CAAC,OAAO,KAAK,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM;YAChE,WAAW,EAAE,UAAU;YACvB,OAAO;SACwB,CAAC;IACpC,CAAC;SAAM,IAAI,cAAc,EAAE,SAAS,EAAE,CAAC;QACrC,MAAM,GAAG;YACP,GAAG,KAAK;YACR,IAAI,EAAE,SAAS;YACf,KAAK,EAAE,IAAI;YACX,OAAO,EAAE,KAAK;YACd,cAAc,EAAE,KAAK;YACrB,cAAc,EAAE,KAAK;YACrB,SAAS,EAAE,KAAK;YAChB,SAAS,EAAE,IAAI;YACf,SAAS,EAAE,IAAI;YACf,UAAU,EAAE,IAAI;YAChB,YAAY,EAAE,KAAK;YACnB,MAAM,EAAE,SAAS;YACjB,WAAW,EAAE,UAAU;YACvB,OAAO;SACwB,CAAC;IACpC,CAAC;SAAM,IAAI,cAAc,EAAE,CAAC;QAC1B,MAAM,GAAG;YACP,GAAG,KAAK;YACR,UAAU,EAAE,IAAI;YAChB,SAAS,EAAE,KAAK,CAAC,SAAS;YAC1B,YAAY,EAAE,CAAC,KAAK,CAAC,SAAS;YAC9B,WAAW,EAAE,UAAU;YACvB,OAAO;SACwB,CAAC;IACpC,CAAC;SAAM,IAAI,MAAM,IAAI,KAAK,CAAC,SAAS,EAAE,CAAC;QACrC,yFAAyF;QACzF,6FAA6F;QAC7F,2DAA2D;QAC3D,MAAM,GAAG;YACP,GAAG,KAAK;YACR,SAAS,EAAE,IAAI;YACf,UAAU,EAAE,IAAI;YAChB,WAAW,EAAE,UAAU;YACvB,OAAO;SACwB,CAAC;IACpC,CAAC;SAAM,CAAC;QACN,MAAM,GAAG,EAAE,GAAG,KAAK,EAAE,OAAO,EAAkC,CAAC;IACjE,CAAC;IAED,MAAM,WAAW,GAAG,cAAc,KAAK,IAAI,CAAC;IAC5C,SAAS,CAAC,GAAG,EAAE;QACb,MAAM,CAAC,OAAO,GAAG,MAA2C,CAAC;QAC7D,IAAI,WAAW,IAAI,OAAO,CAAC,OAAO,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO;QACxD,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC;QAChC,OAAO,CAAC,OAAO,GAAG,EAAE,CAAC;QACrB,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;YAC7B,IAAI,MAAM,CAAC,YAAY,IAAI,MAAM,CAAC,KAAK;gBAAE,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;;gBAChE,MAAM,CAAC,OAAO,CAAC,MAA2C,CAAC,CAAC;QACnE,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,gGAAgG;IAChG,SAAS,CAAC,GAAG,EAAE;QACb,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC;QACvB,OAAO,GAAG,EAAE;YACV,OAAO,CAAC,OAAO,GAAG,KAAK,CAAC;YACxB,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC;YAChC,OAAO,CAAC,OAAO,GAAG,EAAE,CAAC;YACrB,KAAK,MAAM,MAAM,IAAI,OAAO;gBAAE,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;QAC/D,CAAC,CAAC;IACJ,CAAC,EAAE,EAAE,CAAC,CAAC;IAEP,OAAO,EAAE,GAAG,MAAM,EAAE,WAAW,EAAmD,CAAC;AACrF,CAAC","sourcesContent":["'use client';\n\nimport { useCallback, useEffect, useRef, useState } from 'react';\nimport type { QueryObserverResult, RefetchOptions, UseQueryResult } from '@tanstack/react-query';\nimport type { FirestoreSourceState, WithSourceState } from '../../firestore/types.js';\n\n/** A restart a subscribed result's `refetch()` asked for, open until the listener's first snapshot or its next error. */\ninterface PendingRestart {\n /** The listener had failed when the restart was asked for. */\n fromError: boolean;\n /** That failure, kept beside the held data while the restart is open, as a one-shot refetch keeps it. */\n failure: Error | null;\n}\n\ninterface SubscriptionStatus {\n identity: string;\n error: Error | null;\n sourceState: FirestoreSourceState;\n restart: PendingRestart | null;\n /** Bumped by every restart; the listener effect depends on it, so a bump re-opens the listener. */\n restarts: number;\n}\n\ntype StatusPatch = Partial<Omit<SubscriptionStatus, 'identity' | 'restarts'>>;\n\nfunction freshStatus(identity: string): SubscriptionStatus {\n return { identity, error: null, sourceState: 'connecting', restart: null, restarts: 0 };\n}\n\n/**\n * A realtime listener's source state and error, tagged to the subscription identity that\n * produced them. A new identity reads `connecting` with no error from its first render;\n * writes made for a retired identity are dropped once the new identity's listener has\n * started (it calls `reset`).\n *\n * `restart()` clears the error and bumps `restarts`; the listener effect re-opens on the bump,\n * and its first snapshot or next surfaced error ends the restart (`settled` in the patch).\n */\nexport function useSubscriptionStatus(identity: string) {\n const [status, setStatus] = useState<SubscriptionStatus>(() => freshStatus(identity));\n\n const current: SubscriptionStatus = status.identity === identity ? status : freshStatus(identity);\n\n const reset = useCallback(() => {\n setStatus((prev) =>\n prev.identity === identity\n ? { ...prev, error: null, sourceState: 'connecting' }\n : freshStatus(identity),\n );\n }, [identity]);\n\n const update = useCallback(\n (patch: StatusPatch | ((prev: SubscriptionStatus) => StatusPatch)) => {\n setStatus((prev) => {\n if (prev.identity !== identity) return prev;\n const next = typeof patch === 'function' ? patch(prev) : patch;\n return { ...prev, ...next };\n });\n },\n [identity],\n );\n\n // The identity the hook renders now. A `restart` captured under an earlier identity must not\n // touch the current one's status, or every write the current listener makes would be dropped.\n const renderedIdentity = useRef(identity);\n useEffect(() => {\n renderedIdentity.current = identity;\n }, [identity]);\n\n /** Re-opens the listener; false (and nothing changes) when this identity is no longer rendered. */\n const restart = useCallback((): boolean => {\n if (renderedIdentity.current !== identity) return false;\n setStatus((prev) => {\n const base = prev.identity === identity ? prev : freshStatus(identity);\n return {\n ...base,\n error: null,\n sourceState: 'connecting',\n restart: {\n fromError: base.error !== null || base.restart?.fromError === true,\n failure: base.error ?? base.restart?.failure ?? null,\n },\n restarts: base.restarts + 1,\n };\n });\n return true;\n }, [identity]);\n\n return {\n error: current.error,\n sourceState: current.sourceState,\n pendingRestart: current.restart,\n restarts: current.restarts,\n reset,\n update,\n restart,\n };\n}\n\ntype SubscriptionStatusApi = ReturnType<typeof useSubscriptionStatus>;\n\ninterface RefetchWaiter<TData> {\n resolve: (result: QueryObserverResult<TData, Error>) => void;\n reject: (error: Error) => void;\n throwOnError: boolean;\n}\n\n/**\n * The subscribed hooks' result: the query's own result, with the listener's error and source\n * state merged in. In subscribe mode `refetch()` re-opens the listener (clearing its error, with a\n * fresh resubscribe ladder) and resolves once the re-opened listener delivers its first snapshot or\n * surfaces its next error; until then the result reports fetching.\n *\n * A listener that fails after it answered keeps its last snapshot as `data` beside the failure, the\n * way a one-shot read that fails a refetch keeps its data: `status: 'error'` and `isRefetchError`\n * say the rows are not current, and a consumer can keep what it showed instead of tearing it down.\n * A restart from that failure keeps both — the held data and the failure — until the re-opened\n * listener answers. A listener that failed before it ever answered has no data to hold.\n */\nexport function useSubscribedResult<TData>(\n query: UseQueryResult<TData, Error>,\n subscribe: boolean,\n enabled: boolean,\n status: SubscriptionStatusApi,\n): WithSourceState<UseQueryResult<TData, Error>> {\n const { error, sourceState, pendingRestart, restart } = status;\n const waiters = useRef<RefetchWaiter<TData>[]>([]);\n const latest = useRef(query as QueryObserverResult<TData, Error>);\n const mounted = useRef(true);\n const active = subscribe && enabled;\n\n const refetch = useCallback(\n (options?: RefetchOptions): Promise<QueryObserverResult<TData, Error>> => {\n // An unmounted hook, or a refetch captured under an identity the hook has left, re-opens\n // nothing: it settles at once rather than waiting on a listener that will never report.\n if (!active || !mounted.current) return Promise.resolve(latest.current);\n return new Promise((resolve, reject) => {\n if (!restart()) {\n resolve(latest.current);\n return;\n }\n waiters.current.push({ resolve, reject, throwOnError: options?.throwOnError === true });\n });\n },\n [active, restart],\n );\n\n let result: UseQueryResult<TData, Error>;\n if (!subscribe) {\n result = query;\n } else if (error) {\n const held = query.data !== undefined;\n result = {\n ...query,\n data: query.data,\n error,\n isError: true,\n isLoadingError: !held,\n isRefetchError: held,\n isSuccess: false,\n isPending: false,\n isLoading: false,\n status: 'error',\n refetch,\n } as UseQueryResult<TData, Error>;\n } else if (pendingRestart?.fromError && query.data !== undefined) {\n result = {\n ...query,\n error: pendingRestart.failure,\n isError: pendingRestart.failure !== null,\n isLoadingError: false,\n isRefetchError: pendingRestart.failure !== null,\n isSuccess: false,\n isPending: false,\n isLoading: false,\n isFetching: true,\n isRefetching: true,\n status: pendingRestart.failure !== null ? 'error' : query.status,\n fetchStatus: 'fetching',\n refetch,\n } as UseQueryResult<TData, Error>;\n } else if (pendingRestart?.fromError) {\n result = {\n ...query,\n data: undefined,\n error: null,\n isError: false,\n isLoadingError: false,\n isRefetchError: false,\n isSuccess: false,\n isPending: true,\n isLoading: true,\n isFetching: true,\n isRefetching: false,\n status: 'pending',\n fetchStatus: 'fetching',\n refetch,\n } as UseQueryResult<TData, Error>;\n } else if (pendingRestart) {\n result = {\n ...query,\n isFetching: true,\n isLoading: query.isPending,\n isRefetching: !query.isPending,\n fetchStatus: 'fetching',\n refetch,\n } as UseQueryResult<TData, Error>;\n } else if (active && query.isPending) {\n // The listener has not delivered its first snapshot. The query underneath is disabled in\n // subscribe mode, so it reports pending but not loading; the read IS loading, exactly like a\n // one-shot read's first fetch — never an answered absence.\n result = {\n ...query,\n isLoading: true,\n isFetching: true,\n fetchStatus: 'fetching',\n refetch,\n } as UseQueryResult<TData, Error>;\n } else {\n result = { ...query, refetch } as UseQueryResult<TData, Error>;\n }\n\n const restartOpen = pendingRestart !== null;\n useEffect(() => {\n latest.current = result as QueryObserverResult<TData, Error>;\n if (restartOpen || waiters.current.length === 0) return;\n const settled = waiters.current;\n waiters.current = [];\n for (const waiter of settled) {\n if (waiter.throwOnError && result.error) waiter.reject(result.error);\n else waiter.resolve(result as QueryObserverResult<TData, Error>);\n }\n });\n\n // A refetch still open when the hook unmounts resolves with the last result instead of hanging.\n useEffect(() => {\n mounted.current = true;\n return () => {\n mounted.current = false;\n const settled = waiters.current;\n waiters.current = [];\n for (const waiter of settled) waiter.resolve(latest.current);\n };\n }, []);\n\n return { ...result, sourceState } as WithSourceState<UseQueryResult<TData, Error>>;\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ttt-productions/query-core",
|
|
3
|
-
"version": "0.14.
|
|
3
|
+
"version": "0.14.16",
|
|
4
4
|
"description": "Shared TanStack Query (React Query) client defaults, query key helpers, and Firestore integration hooks for TTT Productions apps",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|