@ttt-productions/query-core 0.14.30 → 0.14.32
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/app-config/create-app-config.d.ts +38 -0
- package/dist/react/app-config/create-app-config.d.ts.map +1 -0
- package/dist/react/app-config/create-app-config.js +115 -0
- package/dist/react/app-config/create-app-config.js.map +1 -0
- package/dist/react/index.d.ts +3 -1
- package/dist/react/index.d.ts.map +1 -1
- package/dist/react/index.js +1 -0
- package/dist/react/index.js.map +1 -1
- package/dist/react/session-mutation.d.ts +15 -4
- package/dist/react/session-mutation.d.ts.map +1 -1
- package/dist/react/session-mutation.js +35 -7
- package/dist/react/session-mutation.js.map +1 -1
- package/package.json +2 -2
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { type ReactNode } from 'react';
|
|
2
|
+
export type AppConfigStatus = 'loading' | 'ready' | 'missing' | 'unavailable';
|
|
3
|
+
export type StoredAppConfig = Readonly<Record<string, unknown>>;
|
|
4
|
+
export type AppConfigLeverOf<TLevers extends object> = keyof TLevers & string;
|
|
5
|
+
export type AppConfigSnapshotState<TLevers extends object, TExtra extends object> = {
|
|
6
|
+
status: AppConfigStatus;
|
|
7
|
+
levers: TLevers;
|
|
8
|
+
refusedLevers: readonly AppConfigLeverOf<TLevers>[];
|
|
9
|
+
} & TExtra;
|
|
10
|
+
export type AppConfigState<TLevers extends object, TExtra extends object> = AppConfigSnapshotState<TLevers, TExtra> & {
|
|
11
|
+
retry: () => void;
|
|
12
|
+
retrying: boolean;
|
|
13
|
+
};
|
|
14
|
+
export interface AppConfigDefinition<TLevers extends object, TExtra extends object> {
|
|
15
|
+
path: string;
|
|
16
|
+
defaults: TLevers;
|
|
17
|
+
readLevers: (stored: StoredAppConfig) => TLevers;
|
|
18
|
+
isLeverRefused: (stored: StoredAppConfig, lever: AppConfigLeverOf<TLevers>) => boolean;
|
|
19
|
+
extra: {
|
|
20
|
+
read: (stored: StoredAppConfig | null) => TExtra;
|
|
21
|
+
whileUnknown: TExtra;
|
|
22
|
+
};
|
|
23
|
+
onLeverRefused?: (lever: AppConfigLeverOf<TLevers>, value: unknown) => void;
|
|
24
|
+
onUnavailable?: (error: unknown, attempts: number) => void;
|
|
25
|
+
}
|
|
26
|
+
export interface AppConfig<TLevers extends object, TExtra extends object> {
|
|
27
|
+
AppConfigProvider: (props: {
|
|
28
|
+
children: ReactNode;
|
|
29
|
+
}) => ReactNode;
|
|
30
|
+
useAppConfig: () => AppConfigState<TLevers, TExtra>;
|
|
31
|
+
readAppConfigSnapshot: (stored: StoredAppConfig | null) => AppConfigSnapshotState<TLevers, TExtra>;
|
|
32
|
+
LOADING_APP_CONFIG: AppConfigSnapshotState<TLevers, TExtra>;
|
|
33
|
+
UNAVAILABLE_APP_CONFIG: AppConfigSnapshotState<TLevers, TExtra>;
|
|
34
|
+
}
|
|
35
|
+
export declare const APP_CONFIG_MAX_QUICK_ATTEMPTS = 6;
|
|
36
|
+
export declare const APP_CONFIG_BACKGROUND_RETRY_MS = 60000;
|
|
37
|
+
export declare function createAppConfig<TLevers extends object, TExtra extends object>(definition: AppConfigDefinition<TLevers, TExtra>): AppConfig<TLevers, TExtra>;
|
|
38
|
+
//# sourceMappingURL=create-app-config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"create-app-config.d.ts","sourceRoot":"","sources":["../../../src/react/app-config/create-app-config.tsx"],"names":[],"mappings":"AAEA,OAAO,EAQL,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AAIf,MAAM,MAAM,eAAe,GAAG,SAAS,GAAG,OAAO,GAAG,SAAS,GAAG,aAAa,CAAC;AAE9E,MAAM,MAAM,eAAe,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;AAEhE,MAAM,MAAM,gBAAgB,CAAC,OAAO,SAAS,MAAM,IAAI,MAAM,OAAO,GAAG,MAAM,CAAC;AAE9E,MAAM,MAAM,sBAAsB,CAAC,OAAO,SAAS,MAAM,EAAE,MAAM,SAAS,MAAM,IAAI;IAClF,MAAM,EAAE,eAAe,CAAC;IACxB,MAAM,EAAE,OAAO,CAAC;IAChB,aAAa,EAAE,SAAS,gBAAgB,CAAC,OAAO,CAAC,EAAE,CAAC;CACrD,GAAG,MAAM,CAAC;AAEX,MAAM,MAAM,cAAc,CAAC,OAAO,SAAS,MAAM,EAAE,MAAM,SAAS,MAAM,IAAI,sBAAsB,CAChG,OAAO,EACP,MAAM,CACP,GAAG;IACF,KAAK,EAAE,MAAM,IAAI,CAAC;IAClB,QAAQ,EAAE,OAAO,CAAC;CACnB,CAAC;AAEF,MAAM,WAAW,mBAAmB,CAAC,OAAO,SAAS,MAAM,EAAE,MAAM,SAAS,MAAM;IAChF,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,OAAO,CAAC;IAClB,UAAU,EAAE,CAAC,MAAM,EAAE,eAAe,KAAK,OAAO,CAAC;IACjD,cAAc,EAAE,CAAC,MAAM,EAAE,eAAe,EAAE,KAAK,EAAE,gBAAgB,CAAC,OAAO,CAAC,KAAK,OAAO,CAAC;IACvF,KAAK,EAAE;QACL,IAAI,EAAE,CAAC,MAAM,EAAE,eAAe,GAAG,IAAI,KAAK,MAAM,CAAC;QACjD,YAAY,EAAE,MAAM,CAAC;KACtB,CAAC;IACF,cAAc,CAAC,EAAE,CAAC,KAAK,EAAE,gBAAgB,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC;IAC5E,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;CAC5D;AAED,MAAM,WAAW,SAAS,CAAC,OAAO,SAAS,MAAM,EAAE,MAAM,SAAS,MAAM;IACtE,iBAAiB,EAAE,CAAC,KAAK,EAAE;QAAE,QAAQ,EAAE,SAAS,CAAA;KAAE,KAAK,SAAS,CAAC;IACjE,YAAY,EAAE,MAAM,cAAc,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;IACpD,qBAAqB,EAAE,CACrB,MAAM,EAAE,eAAe,GAAG,IAAI,KAC3B,sBAAsB,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;IAC7C,kBAAkB,EAAE,sBAAsB,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;IAC5D,sBAAsB,EAAE,sBAAsB,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;CACjE;AAKD,eAAO,MAAM,6BAA6B,IAAI,CAAC;AAC/C,eAAO,MAAM,8BAA8B,QAAS,CAAC;AAMrD,wBAAgB,eAAe,CAAC,OAAO,SAAS,MAAM,EAAE,MAAM,SAAS,MAAM,EAC3E,UAAU,EAAE,mBAAmB,CAAC,OAAO,EAAE,MAAM,CAAC,GAC/C,SAAS,CAAC,OAAO,EAAE,MAAM,CAAC,CAyH5B"}
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
|
+
import { createContext, useCallback, useContext, useEffect, useMemo, useRef, useState, } from 'react';
|
|
4
|
+
import { doc, onSnapshot } from 'firebase/firestore';
|
|
5
|
+
import { useFirestoreDb } from '../firestore/context.js';
|
|
6
|
+
// A permission-denied error ends a Firestore listener for good, and the first listen can lose a race
|
|
7
|
+
// with the first App Check token, so the listener re-subscribes on its own: a short backoff, then
|
|
8
|
+
// about once a minute for as long as the page is open.
|
|
9
|
+
export const APP_CONFIG_MAX_QUICK_ATTEMPTS = 6;
|
|
10
|
+
export const APP_CONFIG_BACKGROUND_RETRY_MS = 60_000;
|
|
11
|
+
function quickRetryDelayMs(attempt) {
|
|
12
|
+
return Math.min(1000 * 2 ** (attempt - 1), 10_000);
|
|
13
|
+
}
|
|
14
|
+
export function createAppConfig(definition) {
|
|
15
|
+
const leverKeys = Object.keys(definition.defaults);
|
|
16
|
+
const LOADING_APP_CONFIG = {
|
|
17
|
+
...definition.extra.whileUnknown,
|
|
18
|
+
status: 'loading',
|
|
19
|
+
levers: definition.defaults,
|
|
20
|
+
refusedLevers: [],
|
|
21
|
+
};
|
|
22
|
+
const UNAVAILABLE_APP_CONFIG = {
|
|
23
|
+
...LOADING_APP_CONFIG,
|
|
24
|
+
status: 'unavailable',
|
|
25
|
+
};
|
|
26
|
+
function readAppConfigSnapshot(stored) {
|
|
27
|
+
const extra = definition.extra.read(stored);
|
|
28
|
+
if (stored === null) {
|
|
29
|
+
return { ...extra, status: 'missing', levers: definition.defaults, refusedLevers: [] };
|
|
30
|
+
}
|
|
31
|
+
return {
|
|
32
|
+
...extra,
|
|
33
|
+
status: 'ready',
|
|
34
|
+
levers: definition.readLevers(stored),
|
|
35
|
+
refusedLevers: leverKeys.filter((lever) => definition.isLeverRefused(stored, lever)),
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
const AppConfigContext = createContext({
|
|
39
|
+
...LOADING_APP_CONFIG,
|
|
40
|
+
retry: () => { },
|
|
41
|
+
retrying: false,
|
|
42
|
+
});
|
|
43
|
+
function AppConfigProvider({ children }) {
|
|
44
|
+
const db = useFirestoreDb();
|
|
45
|
+
const [snapshot, setSnapshot] = useState(LOADING_APP_CONFIG);
|
|
46
|
+
const [subscription, setSubscription] = useState(0);
|
|
47
|
+
const [retrying, setRetrying] = useState(false);
|
|
48
|
+
const reportedRefusals = useRef(new Set());
|
|
49
|
+
useEffect(() => {
|
|
50
|
+
const ref = doc(db, definition.path);
|
|
51
|
+
let attempt = 0;
|
|
52
|
+
let retryTimer;
|
|
53
|
+
let unsubscribe;
|
|
54
|
+
let disposed = false;
|
|
55
|
+
const subscribe = () => {
|
|
56
|
+
if (disposed)
|
|
57
|
+
return;
|
|
58
|
+
unsubscribe = onSnapshot(ref, (snap) => {
|
|
59
|
+
attempt = 0;
|
|
60
|
+
const stored = snap.exists() ? snap.data() : null;
|
|
61
|
+
const next = readAppConfigSnapshot(stored);
|
|
62
|
+
for (const lever of next.refusedLevers) {
|
|
63
|
+
const value = stored?.[lever];
|
|
64
|
+
const key = `${lever}:${typeof value}:${JSON.stringify(value)}`;
|
|
65
|
+
if (reportedRefusals.current.has(key))
|
|
66
|
+
continue;
|
|
67
|
+
reportedRefusals.current.add(key);
|
|
68
|
+
definition.onLeverRefused?.(lever, value);
|
|
69
|
+
}
|
|
70
|
+
setSnapshot(next);
|
|
71
|
+
setRetrying(false);
|
|
72
|
+
}, (error) => {
|
|
73
|
+
unsubscribe?.();
|
|
74
|
+
unsubscribe = undefined;
|
|
75
|
+
attempt += 1;
|
|
76
|
+
if (attempt < APP_CONFIG_MAX_QUICK_ATTEMPTS) {
|
|
77
|
+
retryTimer = setTimeout(subscribe, quickRetryDelayMs(attempt));
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
if (attempt === APP_CONFIG_MAX_QUICK_ATTEMPTS) {
|
|
81
|
+
definition.onUnavailable?.(error, attempt);
|
|
82
|
+
// A snapshot already read stays the best knowledge there is.
|
|
83
|
+
setSnapshot((current) => current.status === 'loading' ? UNAVAILABLE_APP_CONFIG : current);
|
|
84
|
+
setRetrying(false);
|
|
85
|
+
}
|
|
86
|
+
retryTimer = setTimeout(subscribe, APP_CONFIG_BACKGROUND_RETRY_MS);
|
|
87
|
+
});
|
|
88
|
+
};
|
|
89
|
+
subscribe();
|
|
90
|
+
return () => {
|
|
91
|
+
disposed = true;
|
|
92
|
+
if (retryTimer !== undefined)
|
|
93
|
+
clearTimeout(retryTimer);
|
|
94
|
+
unsubscribe?.();
|
|
95
|
+
};
|
|
96
|
+
}, [db, subscription]);
|
|
97
|
+
const retry = useCallback(() => {
|
|
98
|
+
setRetrying(true);
|
|
99
|
+
setSubscription((count) => count + 1);
|
|
100
|
+
}, []);
|
|
101
|
+
const value = useMemo(() => ({ ...snapshot, retry, retrying }), [snapshot, retry, retrying]);
|
|
102
|
+
return _jsx(AppConfigContext.Provider, { value: value, children: children });
|
|
103
|
+
}
|
|
104
|
+
function useAppConfig() {
|
|
105
|
+
return useContext(AppConfigContext);
|
|
106
|
+
}
|
|
107
|
+
return {
|
|
108
|
+
AppConfigProvider,
|
|
109
|
+
useAppConfig,
|
|
110
|
+
readAppConfigSnapshot,
|
|
111
|
+
LOADING_APP_CONFIG,
|
|
112
|
+
UNAVAILABLE_APP_CONFIG,
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
//# sourceMappingURL=create-app-config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"create-app-config.js","sourceRoot":"","sources":["../../../src/react/app-config/create-app-config.tsx"],"names":[],"mappings":"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","sourcesContent":["'use client';\n\nimport {\n createContext,\n useCallback,\n useContext,\n useEffect,\n useMemo,\n useRef,\n useState,\n type ReactNode,\n} from 'react';\nimport { doc, onSnapshot } from 'firebase/firestore';\nimport { useFirestoreDb } from '../firestore/context.js';\n\nexport type AppConfigStatus = 'loading' | 'ready' | 'missing' | 'unavailable';\n\nexport type StoredAppConfig = Readonly<Record<string, unknown>>;\n\nexport type AppConfigLeverOf<TLevers extends object> = keyof TLevers & string;\n\nexport type AppConfigSnapshotState<TLevers extends object, TExtra extends object> = {\n status: AppConfigStatus;\n levers: TLevers;\n refusedLevers: readonly AppConfigLeverOf<TLevers>[];\n} & TExtra;\n\nexport type AppConfigState<TLevers extends object, TExtra extends object> = AppConfigSnapshotState<\n TLevers,\n TExtra\n> & {\n retry: () => void;\n retrying: boolean;\n};\n\nexport interface AppConfigDefinition<TLevers extends object, TExtra extends object> {\n path: string;\n defaults: TLevers;\n readLevers: (stored: StoredAppConfig) => TLevers;\n isLeverRefused: (stored: StoredAppConfig, lever: AppConfigLeverOf<TLevers>) => boolean;\n extra: {\n read: (stored: StoredAppConfig | null) => TExtra;\n whileUnknown: TExtra;\n };\n onLeverRefused?: (lever: AppConfigLeverOf<TLevers>, value: unknown) => void;\n onUnavailable?: (error: unknown, attempts: number) => void;\n}\n\nexport interface AppConfig<TLevers extends object, TExtra extends object> {\n AppConfigProvider: (props: { children: ReactNode }) => ReactNode;\n useAppConfig: () => AppConfigState<TLevers, TExtra>;\n readAppConfigSnapshot: (\n stored: StoredAppConfig | null,\n ) => AppConfigSnapshotState<TLevers, TExtra>;\n LOADING_APP_CONFIG: AppConfigSnapshotState<TLevers, TExtra>;\n UNAVAILABLE_APP_CONFIG: AppConfigSnapshotState<TLevers, TExtra>;\n}\n\n// A permission-denied error ends a Firestore listener for good, and the first listen can lose a race\n// with the first App Check token, so the listener re-subscribes on its own: a short backoff, then\n// about once a minute for as long as the page is open.\nexport const APP_CONFIG_MAX_QUICK_ATTEMPTS = 6;\nexport const APP_CONFIG_BACKGROUND_RETRY_MS = 60_000;\n\nfunction quickRetryDelayMs(attempt: number): number {\n return Math.min(1000 * 2 ** (attempt - 1), 10_000);\n}\n\nexport function createAppConfig<TLevers extends object, TExtra extends object>(\n definition: AppConfigDefinition<TLevers, TExtra>,\n): AppConfig<TLevers, TExtra> {\n const leverKeys = Object.keys(definition.defaults) as AppConfigLeverOf<TLevers>[];\n\n const LOADING_APP_CONFIG: AppConfigSnapshotState<TLevers, TExtra> = {\n ...definition.extra.whileUnknown,\n status: 'loading',\n levers: definition.defaults,\n refusedLevers: [],\n };\n const UNAVAILABLE_APP_CONFIG: AppConfigSnapshotState<TLevers, TExtra> = {\n ...LOADING_APP_CONFIG,\n status: 'unavailable',\n };\n\n function readAppConfigSnapshot(\n stored: StoredAppConfig | null,\n ): AppConfigSnapshotState<TLevers, TExtra> {\n const extra = definition.extra.read(stored);\n if (stored === null) {\n return { ...extra, status: 'missing', levers: definition.defaults, refusedLevers: [] };\n }\n return {\n ...extra,\n status: 'ready',\n levers: definition.readLevers(stored),\n refusedLevers: leverKeys.filter((lever) => definition.isLeverRefused(stored, lever)),\n };\n }\n\n const AppConfigContext = createContext<AppConfigState<TLevers, TExtra>>({\n ...LOADING_APP_CONFIG,\n retry: () => {},\n retrying: false,\n });\n\n function AppConfigProvider({ children }: { children: ReactNode }) {\n const db = useFirestoreDb();\n const [snapshot, setSnapshot] =\n useState<AppConfigSnapshotState<TLevers, TExtra>>(LOADING_APP_CONFIG);\n const [subscription, setSubscription] = useState(0);\n const [retrying, setRetrying] = useState(false);\n const reportedRefusals = useRef(new Set<string>());\n\n useEffect(() => {\n const ref = doc(db, definition.path);\n let attempt = 0;\n let retryTimer: ReturnType<typeof setTimeout> | undefined;\n let unsubscribe: (() => void) | undefined;\n let disposed = false;\n\n const subscribe = () => {\n if (disposed) return;\n unsubscribe = onSnapshot(\n ref,\n (snap) => {\n attempt = 0;\n const stored: StoredAppConfig | null = snap.exists() ? snap.data() : null;\n const next = readAppConfigSnapshot(stored);\n for (const lever of next.refusedLevers) {\n const value: unknown = stored?.[lever];\n const key = `${lever}:${typeof value}:${JSON.stringify(value)}`;\n if (reportedRefusals.current.has(key)) continue;\n reportedRefusals.current.add(key);\n definition.onLeverRefused?.(lever, value);\n }\n setSnapshot(next);\n setRetrying(false);\n },\n (error) => {\n unsubscribe?.();\n unsubscribe = undefined;\n attempt += 1;\n if (attempt < APP_CONFIG_MAX_QUICK_ATTEMPTS) {\n retryTimer = setTimeout(subscribe, quickRetryDelayMs(attempt));\n return;\n }\n if (attempt === APP_CONFIG_MAX_QUICK_ATTEMPTS) {\n definition.onUnavailable?.(error, attempt);\n // A snapshot already read stays the best knowledge there is.\n setSnapshot((current) =>\n current.status === 'loading' ? UNAVAILABLE_APP_CONFIG : current,\n );\n setRetrying(false);\n }\n retryTimer = setTimeout(subscribe, APP_CONFIG_BACKGROUND_RETRY_MS);\n },\n );\n };\n\n subscribe();\n return () => {\n disposed = true;\n if (retryTimer !== undefined) clearTimeout(retryTimer);\n unsubscribe?.();\n };\n }, [db, subscription]);\n\n const retry = useCallback(() => {\n setRetrying(true);\n setSubscription((count) => count + 1);\n }, []);\n\n const value = useMemo<AppConfigState<TLevers, TExtra>>(\n () => ({ ...snapshot, retry, retrying }),\n [snapshot, retry, retrying],\n );\n\n return <AppConfigContext.Provider value={value}>{children}</AppConfigContext.Provider>;\n }\n\n function useAppConfig(): AppConfigState<TLevers, TExtra> {\n return useContext(AppConfigContext);\n }\n\n return {\n AppConfigProvider,\n useAppConfig,\n readAppConfigSnapshot,\n LOADING_APP_CONFIG,\n UNAVAILABLE_APP_CONFIG,\n };\n}\n"]}
|
package/dist/react/index.d.ts
CHANGED
|
@@ -31,8 +31,10 @@ export { useReadRetryState, useReadRetryStates } from './use-read-retry-state.js
|
|
|
31
31
|
export type { ReadRetryEntry } from './use-read-retry-state.js';
|
|
32
32
|
export type { ReadRetrySource, ReadRetryState } from './read-retry-derivation.js';
|
|
33
33
|
export { MutationSessionProvider, MutationSessionEndedError, useSessionMutation, } from './session-mutation.js';
|
|
34
|
-
export type { MutationSession, MutationSessionProviderProps, SessionMutateOptions, SessionMutationFunctionContext, SessionMutationOptions, SessionMutationResult, UnknownOutcomePolicy, } from './session-mutation.js';
|
|
34
|
+
export type { LiveSessionSource, MutationSession, MutationSessionProviderProps, SessionMutateOptions, SessionMutationFunctionContext, SessionMutationOptions, SessionMutationResult, UnknownOutcomePolicy, } from './session-mutation.js';
|
|
35
35
|
export { createCallables, MAX_RESUMABLE_CALLS } from './callables/create-callables.js';
|
|
36
36
|
export type { CallableCaptureContext, CallableDeclaration, CallableErrorRouting, CallableMutationOptions, CallablePolicy, Callables, ResumableOutcome, } from './callables/create-callables.js';
|
|
37
37
|
export { usePendingMutationVariables, pendingMutationVariables, usePendingMutationTargets, hasPendingMutation, duplicateSubmissionError, useDuplicateGuardedMutation, } from './pending-mutations.js';
|
|
38
|
+
export { APP_CONFIG_BACKGROUND_RETRY_MS, APP_CONFIG_MAX_QUICK_ATTEMPTS, createAppConfig, } from './app-config/create-app-config.js';
|
|
39
|
+
export type { AppConfig, AppConfigDefinition, AppConfigLeverOf, AppConfigSnapshotState, AppConfigState, AppConfigStatus, StoredAppConfig, } from './app-config/create-app-config.js';
|
|
38
40
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/react/index.ts"],"names":[],"mappings":"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"}
|
|
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
|
@@ -21,4 +21,5 @@ export { useReadRetryState, useReadRetryStates } from './use-read-retry-state.js
|
|
|
21
21
|
export { MutationSessionProvider, MutationSessionEndedError, useSessionMutation, } from './session-mutation.js';
|
|
22
22
|
export { createCallables, MAX_RESUMABLE_CALLS } from './callables/create-callables.js';
|
|
23
23
|
export { usePendingMutationVariables, pendingMutationVariables, usePendingMutationTargets, hasPendingMutation, duplicateSubmissionError, useDuplicateGuardedMutation, } from './pending-mutations.js';
|
|
24
|
+
export { APP_CONFIG_BACKGROUND_RETRY_MS, APP_CONFIG_MAX_QUICK_ATTEMPTS, createAppConfig, } from './app-config/create-app-config.js';
|
|
24
25
|
//# 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,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;AAIlF,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;AAIlF,OAAO,EACL,uBAAuB,EACvB,yBAAyB,EACzB,kBAAkB,GACnB,MAAM,uBAAuB,CAAC;AAY/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;AAEhC,OAAO,EACL,8BAA8B,EAC9B,6BAA6B,EAC7B,eAAe,GAChB,MAAM,mCAAmC,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 } from './use-read-retry-state.js';\nexport type { ReadRetrySource, ReadRetryState } from './read-retry-derivation.js';\n\nexport {\n MutationSessionProvider,\n MutationSessionEndedError,\n useSessionMutation,\n} from './session-mutation.js';\nexport type {\n LiveSessionSource,\n MutationSession,\n MutationSessionProviderProps,\n SessionMutateOptions,\n SessionMutationFunctionContext,\n SessionMutationOptions,\n SessionMutationResult,\n UnknownOutcomePolicy,\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\nexport {\n APP_CONFIG_BACKGROUND_RETRY_MS,\n APP_CONFIG_MAX_QUICK_ATTEMPTS,\n createAppConfig,\n} from './app-config/create-app-config.js';\nexport type {\n AppConfig,\n AppConfigDefinition,\n AppConfigLeverOf,\n AppConfigSnapshotState,\n AppConfigState,\n AppConfigStatus,\n StoredAppConfig,\n} from './app-config/create-app-config.js';\n"]}
|
|
@@ -37,12 +37,23 @@ export declare class MutationSessionEndedError extends Error {
|
|
|
37
37
|
cause?: unknown;
|
|
38
38
|
});
|
|
39
39
|
}
|
|
40
|
-
|
|
41
|
-
|
|
40
|
+
/** The signed-in uid as the auth layer holds it right now, and a subscription to its changes —
|
|
41
|
+
* the pair `useSyncExternalStore` takes. */
|
|
42
|
+
export interface LiveSessionSource {
|
|
43
|
+
read: () => string | null;
|
|
44
|
+
subscribe: (onChange: () => void) => () => void;
|
|
45
|
+
}
|
|
46
|
+
export type MutationSessionProviderProps = {
|
|
42
47
|
unknownOutcome?: UnknownOutcomePolicy;
|
|
43
48
|
children?: ReactNode;
|
|
44
|
-
}
|
|
45
|
-
|
|
49
|
+
} & ({
|
|
50
|
+
currentUid: string | null;
|
|
51
|
+
liveSession?: never;
|
|
52
|
+
} | {
|
|
53
|
+
liveSession: LiveSessionSource;
|
|
54
|
+
currentUid?: never;
|
|
55
|
+
});
|
|
56
|
+
export declare function MutationSessionProvider(props: MutationSessionProviderProps): import("react").JSX.Element;
|
|
46
57
|
export declare function useMutationSessionCapture(): () => MutationSession;
|
|
47
58
|
export declare function useSessionMutation<TData = unknown, TError = DefaultError, TVariables = void, TOnMutateResult = unknown>(options: SessionMutationOptions<TData, TError, TVariables, TOnMutateResult>): SessionMutationResult<TData, TError, TVariables, TOnMutateResult>;
|
|
48
59
|
export {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"session-mutation.d.ts","sourceRoot":"","sources":["../../src/react/session-mutation.tsx"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"session-mutation.d.ts","sourceRoot":"","sources":["../../src/react/session-mutation.tsx"],"names":[],"mappings":"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"}
|
|
@@ -9,19 +9,43 @@ export class MutationSessionEndedError extends Error {
|
|
|
9
9
|
}
|
|
10
10
|
}
|
|
11
11
|
const MutationSessionContext = createContext(null);
|
|
12
|
-
|
|
12
|
+
function observeUid(store, uid) {
|
|
13
|
+
if (store.current.uid !== uid) {
|
|
14
|
+
store.current = { uid, generation: store.current.generation + 1 };
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
// A live source is read at every capture and every check, so an action started in the same task
|
|
18
|
+
// as a sign-in belongs to the new uid even before any render has seen it.
|
|
19
|
+
function syncLive(store) {
|
|
20
|
+
if (store.live)
|
|
21
|
+
observeUid(store, store.live.read());
|
|
22
|
+
}
|
|
23
|
+
export function MutationSessionProvider(props) {
|
|
24
|
+
const { unknownOutcome, children } = props;
|
|
25
|
+
const live = props.liveSession ?? null;
|
|
26
|
+
const currentUid = props.liveSession ? null : (props.currentUid ?? null);
|
|
13
27
|
const [store] = useState(() => ({
|
|
14
|
-
current: { uid: currentUid, generation: 0 },
|
|
28
|
+
current: { uid: live ? live.read() : currentUid, generation: 0 },
|
|
29
|
+
live,
|
|
15
30
|
unknownOutcome: unknownOutcome ?? null,
|
|
16
31
|
}));
|
|
17
32
|
// Insertion effects run before any layout effect of the commit, so a child's layout effect
|
|
18
33
|
// never starts a mutation under the uid this commit ends.
|
|
19
34
|
useInsertionEffect(() => {
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
35
|
+
store.live = live;
|
|
36
|
+
if (live)
|
|
37
|
+
syncLive(store);
|
|
38
|
+
else
|
|
39
|
+
observeUid(store, currentUid);
|
|
23
40
|
store.unknownOutcome = unknownOutcome ?? null;
|
|
24
|
-
}, [store, currentUid, unknownOutcome]);
|
|
41
|
+
}, [store, live, currentUid, unknownOutcome]);
|
|
42
|
+
// Every change the source reports is observed as it happens, so a sign-out followed by the same
|
|
43
|
+
// uid signing back in ends the session even when no check ran in between.
|
|
44
|
+
useInsertionEffect(() => {
|
|
45
|
+
if (!live)
|
|
46
|
+
return;
|
|
47
|
+
return live.subscribe(() => syncLive(store));
|
|
48
|
+
}, [store, live]);
|
|
25
49
|
return (_jsx(MutationSessionContext.Provider, { value: store, children: children }));
|
|
26
50
|
}
|
|
27
51
|
const ALWAYS_CURRENT = {
|
|
@@ -32,8 +56,12 @@ const ALWAYS_CURRENT = {
|
|
|
32
56
|
function captureSession(store) {
|
|
33
57
|
if (!store)
|
|
34
58
|
return ALWAYS_CURRENT;
|
|
59
|
+
syncLive(store);
|
|
35
60
|
const { uid, generation } = store.current;
|
|
36
|
-
const isCurrent = () =>
|
|
61
|
+
const isCurrent = () => {
|
|
62
|
+
syncLive(store);
|
|
63
|
+
return store.current.generation === generation;
|
|
64
|
+
};
|
|
37
65
|
return {
|
|
38
66
|
uid,
|
|
39
67
|
isCurrent,
|
|
@@ -1 +1 @@
|
|
|
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 QueryClient,\n type QueryKey,\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 unknownOutcomeReads?: (variables: TVariables) => readonly QueryKey[];\n};\n\nexport interface UnknownOutcomePolicy {\n isUnknownOutcome: (error: unknown) => boolean;\n rereadAfterMs: readonly number[];\n reread: (queryClient: QueryClient, keys: readonly QueryKey[]) => 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 unknownOutcome: UnknownOutcomePolicy | null;\n}\n\nconst MutationSessionContext = createContext<SessionStore | null>(null);\n\nexport interface MutationSessionProviderProps {\n currentUid: string | null;\n unknownOutcome?: UnknownOutcomePolicy;\n children?: ReactNode;\n}\n\nexport function MutationSessionProvider({\n currentUid,\n unknownOutcome,\n children,\n}: MutationSessionProviderProps) {\n const [store] = useState<SessionStore>(() => ({\n current: { uid: currentUid, generation: 0 },\n unknownOutcome: unknownOutcome ?? null,\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.unknownOutcome = unknownOutcome ?? null;\n }, [store, currentUid, unknownOutcome]);\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\nfunction rereadOnUnknownOutcome<TVariables>(\n store: SessionStore | null,\n queryClient: QueryClient,\n reads: ((variables: TVariables) => readonly QueryKey[]) | undefined,\n error: unknown,\n variables: TVariables,\n session: MutationSession,\n): void {\n const policy = store?.unknownOutcome;\n if (!policy || !reads || !policy.isUnknownOutcome(error)) return;\n const keys = reads(variables);\n if (keys.length === 0) return;\n for (const delayMs of policy.rereadAfterMs) {\n setTimeout(() => {\n if (session.isCurrent()) void policy.reread(queryClient, keys);\n }, delayMs);\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 {\n mutationFn,\n onMutate,\n onSuccess,\n onError,\n onSettled,\n retry,\n throwOnError,\n unknownOutcomeReads,\n ...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 const session = runSession(context);\n rereadOnUnknownOutcome(store, queryClient, unknownOutcomeReads, error, variables, session);\n return onError?.(error, variables, onMutateResult, withSession(context, session));\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"]}
|
|
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 QueryClient,\n type QueryKey,\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 unknownOutcomeReads?: (variables: TVariables) => readonly QueryKey[];\n};\n\nexport interface UnknownOutcomePolicy {\n isUnknownOutcome: (error: unknown) => boolean;\n rereadAfterMs: readonly number[];\n reread: (queryClient: QueryClient, keys: readonly QueryKey[]) => 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\n/** The signed-in uid as the auth layer holds it right now, and a subscription to its changes —\n * the pair `useSyncExternalStore` takes. */\nexport interface LiveSessionSource {\n read: () => string | null;\n subscribe: (onChange: () => void) => () => void;\n}\n\ninterface SessionStore {\n current: { uid: string | null; generation: number };\n live: LiveSessionSource | null;\n unknownOutcome: UnknownOutcomePolicy | null;\n}\n\nconst MutationSessionContext = createContext<SessionStore | null>(null);\n\nexport type MutationSessionProviderProps = {\n unknownOutcome?: UnknownOutcomePolicy;\n children?: ReactNode;\n} & (\n | { currentUid: string | null; liveSession?: never }\n | { liveSession: LiveSessionSource; currentUid?: never }\n);\n\nfunction observeUid(store: SessionStore, uid: string | null): void {\n if (store.current.uid !== uid) {\n store.current = { uid, generation: store.current.generation + 1 };\n }\n}\n\n// A live source is read at every capture and every check, so an action started in the same task\n// as a sign-in belongs to the new uid even before any render has seen it.\nfunction syncLive(store: SessionStore): void {\n if (store.live) observeUid(store, store.live.read());\n}\n\nexport function MutationSessionProvider(props: MutationSessionProviderProps) {\n const { unknownOutcome, children } = props;\n const live = props.liveSession ?? null;\n const currentUid = props.liveSession ? null : (props.currentUid ?? null);\n const [store] = useState<SessionStore>(() => ({\n current: { uid: live ? live.read() : currentUid, generation: 0 },\n live,\n unknownOutcome: unknownOutcome ?? null,\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 store.live = live;\n if (live) syncLive(store);\n else observeUid(store, currentUid);\n store.unknownOutcome = unknownOutcome ?? null;\n }, [store, live, currentUid, unknownOutcome]);\n // Every change the source reports is observed as it happens, so a sign-out followed by the same\n // uid signing back in ends the session even when no check ran in between.\n useInsertionEffect(() => {\n if (!live) return;\n return live.subscribe(() => syncLive(store));\n }, [store, live]);\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 syncLive(store);\n const { uid, generation } = store.current;\n const isCurrent = () => {\n syncLive(store);\n return store.current.generation === generation;\n };\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\nfunction rereadOnUnknownOutcome<TVariables>(\n store: SessionStore | null,\n queryClient: QueryClient,\n reads: ((variables: TVariables) => readonly QueryKey[]) | undefined,\n error: unknown,\n variables: TVariables,\n session: MutationSession,\n): void {\n const policy = store?.unknownOutcome;\n if (!policy || !reads || !policy.isUnknownOutcome(error)) return;\n const keys = reads(variables);\n if (keys.length === 0) return;\n for (const delayMs of policy.rereadAfterMs) {\n setTimeout(() => {\n if (session.isCurrent()) void policy.reread(queryClient, keys);\n }, delayMs);\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 {\n mutationFn,\n onMutate,\n onSuccess,\n onError,\n onSettled,\n retry,\n throwOnError,\n unknownOutcomeReads,\n ...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 const session = runSession(context);\n rereadOnUnknownOutcome(store, queryClient, unknownOutcomeReads, error, variables, session);\n return onError?.(error, variables, onMutateResult, withSession(context, session));\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"]}
|
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.32",
|
|
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",
|
|
@@ -64,7 +64,7 @@
|
|
|
64
64
|
}
|
|
65
65
|
},
|
|
66
66
|
"dependencies": {
|
|
67
|
-
"@ttt-productions/firebase-helpers": "^0.12.
|
|
67
|
+
"@ttt-productions/firebase-helpers": "^0.12.23"
|
|
68
68
|
},
|
|
69
69
|
"devDependencies": {
|
|
70
70
|
"@tanstack/react-query": "^5.90.0",
|