@isograph/react 0.2.0 → 0.3.1

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.
Files changed (151) hide show
  1. package/.turbo/turbo-compile-typescript.log +4 -0
  2. package/dist/core/FragmentReference.d.ts +25 -6
  3. package/dist/core/FragmentReference.d.ts.map +1 -0
  4. package/dist/core/FragmentReference.js +3 -13
  5. package/dist/core/IsographEnvironment.d.ts +34 -26
  6. package/dist/core/IsographEnvironment.d.ts.map +1 -0
  7. package/dist/core/IsographEnvironment.js +19 -22
  8. package/dist/core/PromiseWrapper.d.ts +4 -4
  9. package/dist/core/PromiseWrapper.d.ts.map +1 -0
  10. package/dist/core/PromiseWrapper.js +9 -9
  11. package/dist/core/areEqualWithDeepComparison.d.ts +5 -3
  12. package/dist/core/areEqualWithDeepComparison.d.ts.map +1 -0
  13. package/dist/core/areEqualWithDeepComparison.js +89 -39
  14. package/dist/core/cache.d.ts +20 -13
  15. package/dist/core/cache.d.ts.map +1 -0
  16. package/dist/core/cache.js +205 -128
  17. package/dist/core/check.d.ts +22 -0
  18. package/dist/core/check.d.ts.map +1 -0
  19. package/dist/core/check.js +127 -0
  20. package/dist/core/componentCache.d.ts +2 -2
  21. package/dist/core/componentCache.d.ts.map +1 -0
  22. package/dist/core/componentCache.js +28 -32
  23. package/dist/core/entrypoint.d.ts +31 -15
  24. package/dist/core/entrypoint.d.ts.map +1 -0
  25. package/dist/core/entrypoint.js +1 -2
  26. package/dist/core/garbageCollection.d.ts +6 -5
  27. package/dist/core/garbageCollection.d.ts.map +1 -0
  28. package/dist/core/garbageCollection.js +49 -16
  29. package/dist/core/logging.d.ts +68 -0
  30. package/dist/core/logging.d.ts.map +1 -0
  31. package/dist/core/logging.js +22 -0
  32. package/dist/core/makeNetworkRequest.d.ts +6 -3
  33. package/dist/core/makeNetworkRequest.d.ts.map +1 -0
  34. package/dist/core/makeNetworkRequest.js +160 -19
  35. package/dist/core/read.d.ts +25 -5
  36. package/dist/core/read.d.ts.map +1 -0
  37. package/dist/core/read.js +416 -259
  38. package/dist/core/reader.d.ts +31 -15
  39. package/dist/core/reader.d.ts.map +1 -0
  40. package/dist/core/startUpdate.d.ts +5 -0
  41. package/dist/core/startUpdate.d.ts.map +1 -0
  42. package/dist/core/startUpdate.js +15 -0
  43. package/dist/core/util.d.ts +5 -0
  44. package/dist/core/util.d.ts.map +1 -0
  45. package/dist/index.d.ts +19 -14
  46. package/dist/index.d.ts.map +1 -0
  47. package/dist/index.js +11 -2
  48. package/dist/loadable-hooks/useClientSideDefer.d.ts +9 -3
  49. package/dist/loadable-hooks/useClientSideDefer.d.ts.map +1 -0
  50. package/dist/loadable-hooks/useClientSideDefer.js +6 -8
  51. package/dist/loadable-hooks/useConnectionSpecPagination.d.ts +27 -0
  52. package/dist/loadable-hooks/useConnectionSpecPagination.d.ts.map +1 -0
  53. package/dist/loadable-hooks/useConnectionSpecPagination.js +162 -0
  54. package/dist/loadable-hooks/useImperativeExposedMutationField.d.ts +2 -2
  55. package/dist/loadable-hooks/useImperativeExposedMutationField.d.ts.map +1 -0
  56. package/dist/loadable-hooks/useImperativeExposedMutationField.js +1 -2
  57. package/dist/loadable-hooks/useImperativeLoadableField.d.ts +13 -7
  58. package/dist/loadable-hooks/useImperativeLoadableField.d.ts.map +1 -0
  59. package/dist/loadable-hooks/useImperativeLoadableField.js +4 -5
  60. package/dist/loadable-hooks/useSkipLimitPagination.d.ts +13 -26
  61. package/dist/loadable-hooks/useSkipLimitPagination.d.ts.map +1 -0
  62. package/dist/loadable-hooks/useSkipLimitPagination.js +93 -47
  63. package/dist/react/FragmentReader.d.ts +6 -4
  64. package/dist/react/FragmentReader.d.ts.map +1 -0
  65. package/dist/react/FragmentReader.js +4 -2
  66. package/dist/react/IsographEnvironmentProvider.d.ts +1 -0
  67. package/dist/react/IsographEnvironmentProvider.d.ts.map +1 -0
  68. package/dist/react/IsographEnvironmentProvider.js +3 -3
  69. package/dist/react/RenderAfterCommit__DO_NOT_USE.d.ts +10 -0
  70. package/dist/react/RenderAfterCommit__DO_NOT_USE.d.ts.map +1 -0
  71. package/dist/react/RenderAfterCommit__DO_NOT_USE.js +15 -0
  72. package/dist/react/useImperativeReference.d.ts +8 -6
  73. package/dist/react/useImperativeReference.d.ts.map +1 -0
  74. package/dist/react/useImperativeReference.js +6 -8
  75. package/dist/react/useLazyReference.d.ts +5 -3
  76. package/dist/react/useLazyReference.d.ts.map +1 -0
  77. package/dist/react/useLazyReference.js +34 -6
  78. package/dist/react/useReadAndSubscribe.d.ts +6 -3
  79. package/dist/react/useReadAndSubscribe.d.ts.map +1 -0
  80. package/dist/react/useReadAndSubscribe.js +13 -10
  81. package/dist/react/useRerenderOnChange.d.ts +7 -2
  82. package/dist/react/useRerenderOnChange.d.ts.map +1 -0
  83. package/dist/react/useRerenderOnChange.js +3 -4
  84. package/dist/react/useResult.d.ts +4 -3
  85. package/dist/react/useResult.d.ts.map +1 -0
  86. package/dist/react/useResult.js +14 -9
  87. package/isograph.config.json +8 -0
  88. package/package.json +14 -9
  89. package/{src/tests/schema.graphql → schema.graphql} +1 -0
  90. package/src/core/FragmentReference.ts +44 -17
  91. package/src/core/IsographEnvironment.ts +67 -50
  92. package/src/core/PromiseWrapper.ts +3 -3
  93. package/src/core/areEqualWithDeepComparison.ts +95 -41
  94. package/src/core/cache.ts +316 -169
  95. package/src/core/check.ts +212 -0
  96. package/src/core/componentCache.ts +40 -46
  97. package/src/core/entrypoint.ts +41 -16
  98. package/src/core/garbageCollection.ts +77 -26
  99. package/src/core/logging.ts +118 -0
  100. package/src/core/makeNetworkRequest.ts +249 -20
  101. package/src/core/read.ts +658 -368
  102. package/src/core/reader.ts +61 -21
  103. package/src/core/startUpdate.ts +28 -0
  104. package/src/core/util.ts +8 -0
  105. package/src/index.ts +94 -8
  106. package/src/loadable-hooks/useClientSideDefer.ts +48 -17
  107. package/src/loadable-hooks/useConnectionSpecPagination.ts +344 -0
  108. package/src/loadable-hooks/useImperativeExposedMutationField.ts +1 -1
  109. package/src/loadable-hooks/useImperativeLoadableField.ts +36 -12
  110. package/src/loadable-hooks/useSkipLimitPagination.ts +253 -94
  111. package/src/react/FragmentReader.tsx +15 -6
  112. package/src/react/IsographEnvironmentProvider.tsx +1 -1
  113. package/src/react/RenderAfterCommit__DO_NOT_USE.tsx +17 -0
  114. package/src/react/useImperativeReference.ts +50 -18
  115. package/src/react/useLazyReference.ts +79 -11
  116. package/src/react/useReadAndSubscribe.ts +33 -10
  117. package/src/react/useRerenderOnChange.ts +7 -2
  118. package/src/react/useResult.ts +30 -9
  119. package/src/tests/__isograph/Query/meName/entrypoint.ts +10 -29
  120. package/src/tests/__isograph/Query/meName/normalization_ast.ts +25 -0
  121. package/src/tests/__isograph/Query/meName/param_type.ts +5 -2
  122. package/src/tests/__isograph/Query/meName/query_text.ts +6 -0
  123. package/src/tests/__isograph/Query/meName/resolver_reader.ts +5 -0
  124. package/src/tests/__isograph/Query/meNameSuccessor/entrypoint.ts +10 -65
  125. package/src/tests/__isograph/Query/meNameSuccessor/normalization_ast.ts +56 -0
  126. package/src/tests/__isograph/Query/meNameSuccessor/param_type.ts +9 -6
  127. package/src/tests/__isograph/Query/meNameSuccessor/query_text.ts +13 -0
  128. package/src/tests/__isograph/Query/meNameSuccessor/resolver_reader.ts +10 -0
  129. package/src/tests/__isograph/Query/nodeField/entrypoint.ts +10 -28
  130. package/src/tests/__isograph/Query/nodeField/normalization_ast.ts +30 -0
  131. package/src/tests/__isograph/Query/nodeField/param_type.ts +7 -3
  132. package/src/tests/__isograph/Query/nodeField/parameters_type.ts +3 -0
  133. package/src/tests/__isograph/Query/nodeField/query_text.ts +6 -0
  134. package/src/tests/__isograph/Query/nodeField/resolver_reader.ts +5 -0
  135. package/src/tests/__isograph/Query/subquery/entrypoint.ts +28 -0
  136. package/src/tests/__isograph/Query/subquery/normalization_ast.ts +38 -0
  137. package/src/tests/__isograph/Query/subquery/output_type.ts +3 -0
  138. package/src/tests/__isograph/Query/subquery/param_type.ts +12 -0
  139. package/src/tests/__isograph/Query/subquery/parameters_type.ts +3 -0
  140. package/src/tests/__isograph/Query/subquery/query_text.ts +8 -0
  141. package/src/tests/__isograph/Query/subquery/resolver_reader.ts +52 -0
  142. package/src/tests/__isograph/iso.ts +24 -12
  143. package/src/tests/garbageCollection.test.ts +53 -45
  144. package/src/tests/meNameSuccessor.ts +8 -3
  145. package/src/tests/nodeQuery.ts +7 -4
  146. package/src/tests/normalizeData.test.ts +120 -0
  147. package/src/tests/tsconfig.json +3 -3
  148. package/tsconfig.json +2 -2
  149. package/tsconfig.pkg.json +7 -3
  150. package/vitest.config.ts +20 -0
  151. package/src/tests/isograph.config.json +0 -7
@@ -0,0 +1,344 @@
1
+ import { ItemCleanupPair } from '@isograph/disposable-types';
2
+ import {
3
+ UNASSIGNED_STATE,
4
+ useUpdatableDisposableState,
5
+ } from '@isograph/react-disposable-state';
6
+ import {
7
+ createReferenceCountedPointer,
8
+ ReferenceCountedPointer,
9
+ } from '@isograph/reference-counted-pointer';
10
+ import { useState } from 'react';
11
+ import { subscribeToAnyChange } from '../core/cache';
12
+ import { FetchOptions } from '../core/check';
13
+ import {
14
+ FragmentReference,
15
+ type UnknownTReadFromStore,
16
+ } from '../core/FragmentReference';
17
+ import { getPromiseState, readPromise } from '../core/PromiseWrapper';
18
+ import {
19
+ readButDoNotEvaluate,
20
+ type WithEncounteredRecords,
21
+ } from '../core/read';
22
+ import { LoadableField, type ReaderAst } from '../core/reader';
23
+ import { getOrCreateCachedStartUpdate } from '../core/startUpdate';
24
+ import { useIsographEnvironment } from '../react/IsographEnvironmentProvider';
25
+ import { useSubscribeToMultiple } from '../react/useReadAndSubscribe';
26
+ import { maybeUnwrapNetworkRequest } from '../react/useResult';
27
+
28
+ export type UsePaginationReturnValue<
29
+ TReadFromStore extends UnknownTReadFromStore,
30
+ TItem,
31
+ > =
32
+ | {
33
+ kind: 'Pending';
34
+ pendingFragment: FragmentReference<TReadFromStore, Connection<TItem>>;
35
+ results: ReadonlyArray<TItem>;
36
+ }
37
+ | {
38
+ kind: 'Complete';
39
+ fetchMore: (
40
+ count: number,
41
+ fetchOptions?: FetchOptions<Connection<TItem>>,
42
+ ) => void;
43
+ results: ReadonlyArray<TItem>;
44
+ hasNextPage: boolean;
45
+ };
46
+
47
+ type LoadedFragmentReferences<
48
+ TReadFromStore extends { parameters: object; data: object },
49
+ TItem,
50
+ > = ReadonlyArray<LoadedFragmentReference<TReadFromStore, TItem>>;
51
+
52
+ type LoadedFragmentReference<
53
+ TReadFromStore extends { parameters: object; data: object },
54
+ TItem,
55
+ > = ItemCleanupPair<
56
+ ReferenceCountedPointer<FragmentReference<TReadFromStore, TItem>>
57
+ >;
58
+
59
+ function flatten<T>(arr: ReadonlyArray<ReadonlyArray<T>>): ReadonlyArray<T> {
60
+ let outArray: Array<T> = [];
61
+ for (const subarr of arr) {
62
+ for (const item of subarr) {
63
+ outArray.push(item);
64
+ }
65
+ }
66
+ return outArray;
67
+ }
68
+
69
+ export type PageInfo = {
70
+ readonly hasNextPage: boolean;
71
+ readonly endCursor: string | null;
72
+ };
73
+
74
+ export type Connection<T> = {
75
+ readonly edges: ReadonlyArray<T> | null;
76
+ readonly pageInfo: PageInfo;
77
+ };
78
+
79
+ type NonNullConnection<T> = {
80
+ readonly edges: ReadonlyArray<T>;
81
+ readonly pageInfo: PageInfo;
82
+ };
83
+
84
+ export type UseConnectionSpecPaginationArgs = {
85
+ first: number;
86
+ after: string | null;
87
+ };
88
+
89
+ export function useConnectionSpecPagination<
90
+ TReadFromStore extends UnknownTReadFromStore,
91
+ TItem,
92
+ >(
93
+ loadableField: LoadableField<
94
+ TReadFromStore,
95
+ Connection<TItem>,
96
+ UseConnectionSpecPaginationArgs
97
+ >,
98
+ initialState?: PageInfo,
99
+ ): UsePaginationReturnValue<TReadFromStore, TItem> {
100
+ const networkRequestOptions = {
101
+ suspendIfInFlight: true,
102
+ throwOnNetworkError: true,
103
+ };
104
+ const { state, setState } =
105
+ useUpdatableDisposableState<
106
+ LoadedFragmentReferences<TReadFromStore, Connection<TItem>>
107
+ >();
108
+
109
+ const environment = useIsographEnvironment();
110
+
111
+ // TODO move this out of useSkipLimitPagination, and pass environment and networkRequestOptions
112
+ // as parameters (or recreate networkRequestOptions)
113
+ function readCompletedFragmentReferences(
114
+ completedReferences: FragmentReference<TReadFromStore, Connection<TItem>>[],
115
+ ): NonNullConnection<TItem> {
116
+ const results = completedReferences.map((fragmentReference, i) => {
117
+ const readerWithRefetchQueries = readPromise(
118
+ fragmentReference.readerWithRefetchQueries,
119
+ );
120
+
121
+ // invariant: readOutDataAndRecords.length === completedReferences.length
122
+ const data = readOutDataAndRecords[i]?.item;
123
+ if (data == null) {
124
+ throw new Error(
125
+ 'Parameter data is unexpectedly null. This is indicative of a bug in Isograph.',
126
+ );
127
+ }
128
+
129
+ const firstParameter = {
130
+ data,
131
+ parameters: fragmentReference.variables,
132
+ ...(readerWithRefetchQueries.readerArtifact.hasUpdatable
133
+ ? {
134
+ startUpdate: getOrCreateCachedStartUpdate(
135
+ environment,
136
+ fragmentReference,
137
+ readerWithRefetchQueries.readerArtifact.fieldName,
138
+ ),
139
+ }
140
+ : undefined),
141
+ };
142
+
143
+ if (
144
+ readerWithRefetchQueries.readerArtifact.kind !== 'EagerReaderArtifact'
145
+ ) {
146
+ throw new Error(
147
+ `@loadable field of kind "${readerWithRefetchQueries.readerArtifact.kind}" is not supported by useSkipLimitPagination`,
148
+ );
149
+ }
150
+
151
+ return readerWithRefetchQueries.readerArtifact.resolver(firstParameter);
152
+ });
153
+
154
+ const items = flatten(results.map((result) => result.edges ?? []));
155
+
156
+ return {
157
+ edges: items,
158
+ pageInfo: results[results.length - 1]?.pageInfo ?? {
159
+ endCursor: null,
160
+ hasNextPage: true,
161
+ },
162
+ };
163
+ }
164
+
165
+ function subscribeCompletedFragmentReferences(
166
+ completedReferences: FragmentReference<TReadFromStore, Connection<TItem>>[],
167
+ ) {
168
+ return completedReferences.map(
169
+ (
170
+ fragmentReference,
171
+ i,
172
+ ): {
173
+ records: WithEncounteredRecords<TReadFromStore>;
174
+ callback: (
175
+ updatedRecords: WithEncounteredRecords<TReadFromStore>,
176
+ ) => void;
177
+ fragmentReference: FragmentReference<TReadFromStore, Connection<TItem>>;
178
+ readerAst: ReaderAst<Connection<TItem>>;
179
+ } => {
180
+ maybeUnwrapNetworkRequest(
181
+ fragmentReference.networkRequest,
182
+ networkRequestOptions,
183
+ );
184
+
185
+ const readerWithRefetchQueries = readPromise(
186
+ fragmentReference.readerWithRefetchQueries,
187
+ );
188
+
189
+ const records = readOutDataAndRecords[i];
190
+ if (records == null) {
191
+ throw new Error(
192
+ 'subscribeCompletedFragmentReferences records is unexpectedly null',
193
+ );
194
+ }
195
+
196
+ return {
197
+ fragmentReference,
198
+ readerAst: readerWithRefetchQueries.readerArtifact.readerAst,
199
+ records,
200
+ callback(_data) {
201
+ rerender({});
202
+ },
203
+ };
204
+ },
205
+ );
206
+ }
207
+
208
+ const getFetchMore =
209
+ (after: string | null) =>
210
+ (count: number, fetchOptions?: FetchOptions<Connection<TItem>>): void => {
211
+ const loadedField = loadableField(
212
+ {
213
+ after: after,
214
+ first: count,
215
+ },
216
+ fetchOptions ?? {},
217
+ )[1]();
218
+ const newPointer = createReferenceCountedPointer(loadedField);
219
+ const clonedPointers = loadedReferences.map(([refCountedPointer]) => {
220
+ const clonedRefCountedPointer = refCountedPointer.cloneIfNotDisposed();
221
+ if (clonedRefCountedPointer == null) {
222
+ throw new Error(
223
+ 'This reference counted pointer has already been disposed. \
224
+ This is indicative of a bug in useSkipLimitPagination.',
225
+ );
226
+ }
227
+ return clonedRefCountedPointer;
228
+ });
229
+ clonedPointers.push(newPointer);
230
+
231
+ const totalItemCleanupPair: ItemCleanupPair<
232
+ ReadonlyArray<
233
+ ItemCleanupPair<
234
+ ReferenceCountedPointer<
235
+ FragmentReference<TReadFromStore, Connection<TItem>>
236
+ >
237
+ >
238
+ >
239
+ > = [
240
+ clonedPointers,
241
+ () => {
242
+ clonedPointers.forEach(([, dispose]) => {
243
+ dispose();
244
+ });
245
+ },
246
+ ];
247
+
248
+ setState(totalItemCleanupPair);
249
+ };
250
+
251
+ const [, rerender] = useState({});
252
+
253
+ const loadedReferences = state === UNASSIGNED_STATE ? [] : state;
254
+
255
+ const mostRecentItem:
256
+ | LoadedFragmentReference<TReadFromStore, Connection<TItem>>
257
+ | undefined = loadedReferences[loadedReferences.length - 1];
258
+ const mostRecentFragmentReference =
259
+ mostRecentItem?.[0].getItemIfNotDisposed();
260
+
261
+ if (mostRecentItem && mostRecentFragmentReference === null) {
262
+ throw new Error(
263
+ 'FragmentReference is unexpectedly disposed. \
264
+ This is indicative of a bug in Isograph.',
265
+ );
266
+ }
267
+
268
+ const networkRequestStatus =
269
+ mostRecentFragmentReference &&
270
+ getPromiseState(mostRecentFragmentReference.networkRequest);
271
+
272
+ const slicedFragmentReferences =
273
+ networkRequestStatus?.kind === 'Ok'
274
+ ? loadedReferences
275
+ : loadedReferences.slice(0, loadedReferences.length - 1);
276
+
277
+ const completedFragmentReferences = slicedFragmentReferences.map(
278
+ ([pointer]) => {
279
+ const fragmentReference = pointer.getItemIfNotDisposed();
280
+ if (fragmentReference == null) {
281
+ throw new Error(
282
+ 'FragmentReference is unexpectedly disposed. \
283
+ This is indicative of a bug in Isograph.',
284
+ );
285
+ }
286
+ return fragmentReference;
287
+ },
288
+ );
289
+
290
+ const readOutDataAndRecords = completedFragmentReferences.map(
291
+ (fragmentReference) =>
292
+ readButDoNotEvaluate(
293
+ environment,
294
+ fragmentReference,
295
+ networkRequestOptions,
296
+ ),
297
+ );
298
+
299
+ useSubscribeToMultiple<TReadFromStore>(
300
+ subscribeCompletedFragmentReferences(completedFragmentReferences),
301
+ );
302
+
303
+ if (!networkRequestStatus) {
304
+ return {
305
+ kind: 'Complete',
306
+ fetchMore: getFetchMore(initialState?.endCursor ?? null),
307
+ results: [],
308
+ hasNextPage: initialState?.hasNextPage ?? true,
309
+ };
310
+ }
311
+
312
+ switch (networkRequestStatus.kind) {
313
+ case 'Pending': {
314
+ const unsubscribe = subscribeToAnyChange(environment, () => {
315
+ unsubscribe();
316
+ rerender({});
317
+ });
318
+
319
+ const results = readCompletedFragmentReferences(
320
+ completedFragmentReferences,
321
+ );
322
+ return {
323
+ results: results.edges,
324
+ kind: 'Pending',
325
+ pendingFragment: mostRecentFragmentReference,
326
+ };
327
+ }
328
+ case 'Err': {
329
+ throw networkRequestStatus.error;
330
+ }
331
+ case 'Ok': {
332
+ const results = readCompletedFragmentReferences(
333
+ completedFragmentReferences,
334
+ );
335
+
336
+ return {
337
+ results: results.edges,
338
+ hasNextPage: results.pageInfo.hasNextPage,
339
+ kind: 'Complete',
340
+ fetchMore: getFetchMore(results.pageInfo.endCursor),
341
+ };
342
+ }
343
+ }
344
+ }
@@ -1,4 +1,4 @@
1
- type UseImperativeLoadableFieldReturn<TArgs> = {
1
+ export type UseImperativeLoadableFieldReturn<TArgs> = {
2
2
  loadField: (args: TArgs) => void;
3
3
  };
4
4
 
@@ -1,26 +1,50 @@
1
- import { FragmentReference } from '../core/FragmentReference';
2
1
  import {
3
- UnassignedState,
2
+ UNASSIGNED_STATE,
4
3
  useUpdatableDisposableState,
5
4
  } from '@isograph/react-disposable-state';
5
+ import { FetchOptions } from '../core/check';
6
+ import {
7
+ ExtractParameters,
8
+ FragmentReference,
9
+ } from '../core/FragmentReference';
6
10
  import { LoadableField } from '../core/reader';
7
11
 
8
- type UseImperativeLoadableFieldReturn<TArgs, TResult> = {
9
- fragmentReference: FragmentReference<any, TResult> | UnassignedState;
10
- loadField: (args: TArgs) => void;
12
+ export type UseImperativeLoadableFieldReturn<
13
+ TReadFromStore extends { data: object; parameters: object },
14
+ TResult,
15
+ TProvidedArgs extends object,
16
+ > = {
17
+ fragmentReference: FragmentReference<TReadFromStore, TResult> | null;
18
+ loadField: (
19
+ // TODO this should be void iff all args are provided by the query, like in
20
+ // useClientSideDefer.
21
+ args: Omit<ExtractParameters<TReadFromStore>, keyof TProvidedArgs> | void,
22
+ fetchOptions?: FetchOptions<TResult>,
23
+ ) => void;
11
24
  };
12
25
 
13
- export function useImperativeLoadableField<TArgs, TResult>(
14
- loadableField: LoadableField<TArgs, TResult>,
15
- ): UseImperativeLoadableFieldReturn<TArgs, TResult> {
26
+ export function useImperativeLoadableField<
27
+ TReadFromStore extends { data: object; parameters: object },
28
+ TResult,
29
+ TProvidedArgs extends object,
30
+ >(
31
+ loadableField: LoadableField<
32
+ TReadFromStore,
33
+ TResult,
34
+ Omit<ExtractParameters<TReadFromStore>, keyof TProvidedArgs>
35
+ >,
36
+ ): UseImperativeLoadableFieldReturn<TReadFromStore, TResult, TProvidedArgs> {
16
37
  const { state, setState } =
17
- useUpdatableDisposableState<FragmentReference<any, TResult>>();
38
+ useUpdatableDisposableState<FragmentReference<TReadFromStore, TResult>>();
18
39
 
19
40
  return {
20
- loadField: (args: TArgs) => {
21
- const [_id, loader] = loadableField(args);
41
+ loadField: (
42
+ args: Omit<ExtractParameters<TReadFromStore>, keyof TProvidedArgs> | void,
43
+ fetchOptions?: FetchOptions<TResult>,
44
+ ) => {
45
+ const [_id, loader] = loadableField(args, fetchOptions ?? {});
22
46
  setState(loader());
23
47
  },
24
- fragmentReference: state,
48
+ fragmentReference: state !== UNASSIGNED_STATE ? state : null,
25
49
  };
26
50
  }