@octanejs/apollo-client 0.1.0
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/LICENSE +49 -0
- package/README.md +97 -0
- package/package.json +77 -0
- package/src/index.d.ts +1 -0
- package/src/index.js +3 -0
- package/src/react/context/ApolloContext.d.ts +8 -0
- package/src/react/context/ApolloContext.js +21 -0
- package/src/react/context/ApolloProvider.d.ts +9 -0
- package/src/react/context/ApolloProvider.js +15 -0
- package/src/react/hooks/constants.d.ts +2 -0
- package/src/react/hooks/constants.js +1 -0
- package/src/react/hooks/internal/__use.d.ts +3 -0
- package/src/react/hooks/internal/__use.js +9 -0
- package/src/react/hooks/internal/index.d.ts +5 -0
- package/src/react/hooks/internal/index.js +6 -0
- package/src/react/hooks/internal/site.d.ts +2 -0
- package/src/react/hooks/internal/site.js +20 -0
- package/src/react/hooks/internal/useDeepMemo.d.ts +5 -0
- package/src/react/hooks/internal/useDeepMemo.js +11 -0
- package/src/react/hooks/internal/useIsomorphicLayoutEffect.d.ts +2 -0
- package/src/react/hooks/internal/useIsomorphicLayoutEffect.js +8 -0
- package/src/react/hooks/internal/useRenderGuard.d.ts +1 -0
- package/src/react/hooks/internal/useRenderGuard.js +14 -0
- package/src/react/hooks/internal/useSuspenseHookCacheKey.d.ts +13 -0
- package/src/react/hooks/internal/useSuspenseHookCacheKey.js +19 -0
- package/src/react/hooks/internal/validateSuspenseHookOptions.d.ts +4 -0
- package/src/react/hooks/internal/validateSuspenseHookOptions.js +16 -0
- package/src/react/hooks/internal/wrapHook.d.ts +77 -0
- package/src/react/hooks/internal/wrapHook.js +64 -0
- package/src/react/hooks/useApolloClient.d.ts +17 -0
- package/src/react/hooks/useApolloClient.js +27 -0
- package/src/react/hooks/useBackgroundQuery.d.ts +3061 -0
- package/src/react/hooks/useBackgroundQuery.js +88 -0
- package/src/react/hooks/useFragment.d.ts +205 -0
- package/src/react/hooks/useFragment.js +75 -0
- package/src/react/hooks/useLazyQuery.d.ts +947 -0
- package/src/react/hooks/useLazyQuery.js +156 -0
- package/src/react/hooks/useLoadableQuery.d.ts +955 -0
- package/src/react/hooks/useLoadableQuery.js +98 -0
- package/src/react/hooks/useMutation.d.ts +585 -0
- package/src/react/hooks/useMutation.js +121 -0
- package/src/react/hooks/useQuery.d.ts +1401 -0
- package/src/react/hooks/useQuery.js +234 -0
- package/src/react/hooks/useQueryRefHandlers.d.ts +85 -0
- package/src/react/hooks/useQueryRefHandlers.js +79 -0
- package/src/react/hooks/useReactiveVar.d.ts +21 -0
- package/src/react/hooks/useReactiveVar.js +41 -0
- package/src/react/hooks/useReadQuery.d.ts +104 -0
- package/src/react/hooks/useReadQuery.js +83 -0
- package/src/react/hooks/useSubscription.d.ts +289 -0
- package/src/react/hooks/useSubscription.js +258 -0
- package/src/react/hooks/useSuspenseFragment.d.ts +154 -0
- package/src/react/hooks/useSuspenseFragment.js +50 -0
- package/src/react/hooks/useSuspenseQuery.d.ts +1629 -0
- package/src/react/hooks/useSuspenseQuery.js +130 -0
- package/src/react/hooks/useSyncExternalStore.d.ts +2 -0
- package/src/react/hooks/useSyncExternalStore.js +125 -0
- package/src/react/index.d.ts +68 -0
- package/src/react/index.js +18 -0
- package/src/react/internal/cache/FragmentReference.d.ts +41 -0
- package/src/react/internal/cache/FragmentReference.js +117 -0
- package/src/react/internal/cache/QueryReference.d.ts +180 -0
- package/src/react/internal/cache/QueryReference.js +310 -0
- package/src/react/internal/cache/SuspenseCache.d.ts +38 -0
- package/src/react/internal/cache/SuspenseCache.js +39 -0
- package/src/react/internal/cache/getSuspenseCache.d.ts +26 -0
- package/src/react/internal/cache/getSuspenseCache.js +8 -0
- package/src/react/internal/cache/types.d.ts +13 -0
- package/src/react/internal/cache/types.js +1 -0
- package/src/react/internal/index.d.ts +16 -0
- package/src/react/internal/index.js +10 -0
- package/src/react/internal/types.d.ts +15 -0
- package/src/react/internal/types.js +1 -0
- package/src/react/query-preloader/createQueryPreloader.d.ts +630 -0
- package/src/react/query-preloader/createQueryPreloader.js +89 -0
- package/src/react/types/deprecated.d.ts +140 -0
- package/src/react/types/deprecated.js +1 -0
- package/src/react/types/types.documentation.d.ts +551 -0
- package/src/react/types/types.documentation.js +1 -0
- package/src/testing/index.d.ts +1 -0
- package/src/testing/index.js +1 -0
- package/src/testing/react/MockedProvider.d.ts +21 -0
- package/src/testing/react/MockedProvider.js +53 -0
- package/src/testing/react/index.d.ts +2 -0
- package/src/testing/react/index.js +1 -0
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
import { equal } from '@wry/equality';
|
|
2
|
+
import * as React from 'octane';
|
|
3
|
+
import { NetworkStatus } from '@apollo/client';
|
|
4
|
+
import { maybeDeepFreeze, variablesUnknownSymbol } from '@apollo/client/utilities/internal';
|
|
5
|
+
import { invariant } from '@apollo/client/utilities/invariant';
|
|
6
|
+
import { useRenderGuard } from './internal/index.js';
|
|
7
|
+
import { isCompilerSite } from './internal/site.js';
|
|
8
|
+
import { useDeepMemo } from './internal/useDeepMemo.js';
|
|
9
|
+
import { useIsomorphicLayoutEffect } from './internal/useIsomorphicLayoutEffect.js';
|
|
10
|
+
import { useApolloClient } from './useApolloClient.js';
|
|
11
|
+
import { useSyncExternalStore } from './useSyncExternalStore.js';
|
|
12
|
+
// The following methods, when called will execute the query, regardless of
|
|
13
|
+
// whether the useLazyQuery execute function was called before.
|
|
14
|
+
const EAGER_METHODS = [
|
|
15
|
+
'refetch',
|
|
16
|
+
'fetchMore',
|
|
17
|
+
'updateQuery',
|
|
18
|
+
'startPolling',
|
|
19
|
+
'stopPolling',
|
|
20
|
+
'subscribeToMore',
|
|
21
|
+
];
|
|
22
|
+
export const useLazyQuery = function useLazyQuery(query, options) {
|
|
23
|
+
if (isCompilerSite(options)) options = undefined;
|
|
24
|
+
const client = useApolloClient(options?.client);
|
|
25
|
+
const previousDataRef = React.useRef(undefined);
|
|
26
|
+
const resultRef = React.useRef(undefined);
|
|
27
|
+
const stableOptions = useDeepMemo(() => options, [options]);
|
|
28
|
+
const calledDuringRender = useRenderGuard();
|
|
29
|
+
function createObservable() {
|
|
30
|
+
return client.watchQuery({
|
|
31
|
+
...options,
|
|
32
|
+
query,
|
|
33
|
+
initialFetchPolicy: options?.fetchPolicy,
|
|
34
|
+
fetchPolicy: 'standby',
|
|
35
|
+
[variablesUnknownSymbol]: true,
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
const [currentClient, setCurrentClient] = React.useState(client);
|
|
39
|
+
const [observable, setObservable] = React.useState(createObservable);
|
|
40
|
+
if (currentClient !== client) {
|
|
41
|
+
setCurrentClient(client);
|
|
42
|
+
setObservable(createObservable());
|
|
43
|
+
}
|
|
44
|
+
// TODO: Revisit after we have RxJS in place. We should be able to use
|
|
45
|
+
// observable.getCurrentResult() (or equivalent) to get these values which
|
|
46
|
+
// will hopefully alleviate the need for us to use refs to track these values.
|
|
47
|
+
const updateResult = React.useCallback((result, forceUpdate) => {
|
|
48
|
+
const previousData = resultRef.current?.data;
|
|
49
|
+
if (previousData && !equal(previousData, result.data)) {
|
|
50
|
+
previousDataRef.current = previousData;
|
|
51
|
+
}
|
|
52
|
+
resultRef.current = result;
|
|
53
|
+
forceUpdate();
|
|
54
|
+
}, []);
|
|
55
|
+
const observableResult = useSyncExternalStore(
|
|
56
|
+
React.useCallback(
|
|
57
|
+
(forceUpdate) => {
|
|
58
|
+
const subscription = observable.subscribe((result) => {
|
|
59
|
+
if (!equal(resultRef.current, result)) {
|
|
60
|
+
updateResult(result, forceUpdate);
|
|
61
|
+
}
|
|
62
|
+
});
|
|
63
|
+
return () => {
|
|
64
|
+
subscription.unsubscribe();
|
|
65
|
+
};
|
|
66
|
+
},
|
|
67
|
+
[observable, updateResult],
|
|
68
|
+
),
|
|
69
|
+
() => resultRef.current || initialResult,
|
|
70
|
+
() => initialResult,
|
|
71
|
+
);
|
|
72
|
+
// We use useMemo here to make sure the eager methods have a stable identity.
|
|
73
|
+
const eagerMethods = React.useMemo(() => {
|
|
74
|
+
const eagerMethods = {};
|
|
75
|
+
for (const key of EAGER_METHODS) {
|
|
76
|
+
eagerMethods[key] = function (...args) {
|
|
77
|
+
invariant(resultRef.current, 29, key);
|
|
78
|
+
// @ts-expect-error this is just to generic to type
|
|
79
|
+
return observable[key](...args);
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
return eagerMethods;
|
|
83
|
+
}, [observable]);
|
|
84
|
+
React.useEffect(() => {
|
|
85
|
+
const updatedOptions = {
|
|
86
|
+
query,
|
|
87
|
+
errorPolicy: stableOptions?.errorPolicy,
|
|
88
|
+
refetchOn: stableOptions?.refetchOn,
|
|
89
|
+
refetchWritePolicy: stableOptions?.refetchWritePolicy,
|
|
90
|
+
returnPartialData: stableOptions?.returnPartialData,
|
|
91
|
+
notifyOnNetworkStatusChange: stableOptions?.notifyOnNetworkStatusChange,
|
|
92
|
+
pollInterval: stableOptions?.pollInterval,
|
|
93
|
+
nextFetchPolicy: options?.nextFetchPolicy,
|
|
94
|
+
skipPollAttempt: options?.skipPollAttempt,
|
|
95
|
+
};
|
|
96
|
+
// Wait to apply the changed fetch policy until after the execute
|
|
97
|
+
// function has been called. The execute function will handle setting the
|
|
98
|
+
// the fetch policy away from standby for us when called for the first time.
|
|
99
|
+
if (observable.options.fetchPolicy !== 'standby' && stableOptions?.fetchPolicy) {
|
|
100
|
+
updatedOptions.fetchPolicy = stableOptions.fetchPolicy;
|
|
101
|
+
}
|
|
102
|
+
observable.applyOptions(updatedOptions);
|
|
103
|
+
}, [
|
|
104
|
+
query,
|
|
105
|
+
observable,
|
|
106
|
+
stableOptions,
|
|
107
|
+
// Ensure inline functions don't suffer from stale closures by checking for
|
|
108
|
+
// these deps separately. @wry/equality doesn't compare function identity
|
|
109
|
+
// so `stableOptions` isn't updated when using inline functions.
|
|
110
|
+
options?.nextFetchPolicy,
|
|
111
|
+
options?.skipPollAttempt,
|
|
112
|
+
]);
|
|
113
|
+
const execute = React.useCallback(
|
|
114
|
+
(...args) => {
|
|
115
|
+
invariant(!calledDuringRender(), 30);
|
|
116
|
+
const [executeOptions] = args;
|
|
117
|
+
let fetchPolicy = observable.options.fetchPolicy;
|
|
118
|
+
if (fetchPolicy === 'standby') {
|
|
119
|
+
fetchPolicy = observable.options.initialFetchPolicy;
|
|
120
|
+
}
|
|
121
|
+
return observable.reobserve({
|
|
122
|
+
fetchPolicy,
|
|
123
|
+
// If `variables` is not given, reset back to empty variables by
|
|
124
|
+
// ensuring the key exists in options
|
|
125
|
+
variables: executeOptions?.variables,
|
|
126
|
+
context: executeOptions?.context ?? {},
|
|
127
|
+
});
|
|
128
|
+
},
|
|
129
|
+
[observable, calledDuringRender],
|
|
130
|
+
);
|
|
131
|
+
const executeRef = React.useRef(execute);
|
|
132
|
+
useIsomorphicLayoutEffect(() => {
|
|
133
|
+
executeRef.current = execute;
|
|
134
|
+
}, null);
|
|
135
|
+
const stableExecute = React.useCallback((...args) => executeRef.current(...args), []);
|
|
136
|
+
const result = React.useMemo(() => {
|
|
137
|
+
const { partial, ...result } = observableResult;
|
|
138
|
+
return {
|
|
139
|
+
...eagerMethods,
|
|
140
|
+
...result,
|
|
141
|
+
client,
|
|
142
|
+
previousData: previousDataRef.current,
|
|
143
|
+
variables: observable.variables,
|
|
144
|
+
observable,
|
|
145
|
+
called: !!resultRef.current,
|
|
146
|
+
};
|
|
147
|
+
}, [client, observableResult, eagerMethods, observable]);
|
|
148
|
+
return [stableExecute, result];
|
|
149
|
+
};
|
|
150
|
+
const initialResult = maybeDeepFreeze({
|
|
151
|
+
data: undefined,
|
|
152
|
+
dataState: 'empty',
|
|
153
|
+
loading: false,
|
|
154
|
+
networkStatus: NetworkStatus.ready,
|
|
155
|
+
partial: true,
|
|
156
|
+
});
|