@isograph/react 0.4.3 → 0.5.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.
Files changed (137) hide show
  1. package/.turbo/turbo-compile-libs.log +2 -2
  2. package/dist/core/FragmentReference.d.ts +4 -2
  3. package/dist/core/FragmentReference.d.ts.map +1 -1
  4. package/dist/core/FragmentReference.js +2 -2
  5. package/dist/core/IsographEnvironment.d.ts +19 -11
  6. package/dist/core/IsographEnvironment.d.ts.map +1 -1
  7. package/dist/core/IsographEnvironment.js +27 -2
  8. package/dist/core/PromiseWrapper.d.ts +13 -7
  9. package/dist/core/PromiseWrapper.d.ts.map +1 -1
  10. package/dist/core/brand.d.ts +17 -0
  11. package/dist/core/brand.d.ts.map +1 -1
  12. package/dist/core/cache.d.ts +10 -7
  13. package/dist/core/cache.d.ts.map +1 -1
  14. package/dist/core/cache.js +102 -74
  15. package/dist/core/check.d.ts +8 -4
  16. package/dist/core/check.d.ts.map +1 -1
  17. package/dist/core/check.js +10 -7
  18. package/dist/core/componentCache.d.ts +1 -1
  19. package/dist/core/componentCache.d.ts.map +1 -1
  20. package/dist/core/componentCache.js +6 -4
  21. package/dist/core/entrypoint.d.ts +17 -7
  22. package/dist/core/entrypoint.d.ts.map +1 -1
  23. package/dist/core/garbageCollection.d.ts +8 -2
  24. package/dist/core/garbageCollection.d.ts.map +1 -1
  25. package/dist/core/garbageCollection.js +36 -14
  26. package/dist/core/logging.d.ts +16 -3
  27. package/dist/core/logging.d.ts.map +1 -1
  28. package/dist/core/makeNetworkRequest.d.ts +4 -2
  29. package/dist/core/makeNetworkRequest.d.ts.map +1 -1
  30. package/dist/core/makeNetworkRequest.js +115 -38
  31. package/dist/core/optimisticProxy.d.ts +59 -0
  32. package/dist/core/optimisticProxy.d.ts.map +1 -0
  33. package/dist/core/optimisticProxy.js +399 -0
  34. package/dist/core/read.d.ts +3 -2
  35. package/dist/core/read.d.ts.map +1 -1
  36. package/dist/core/read.js +158 -123
  37. package/dist/core/reader.d.ts +7 -4
  38. package/dist/core/reader.d.ts.map +1 -1
  39. package/dist/core/startUpdate.d.ts +3 -2
  40. package/dist/core/startUpdate.d.ts.map +1 -1
  41. package/dist/core/startUpdate.js +33 -34
  42. package/dist/index.d.ts +2 -2
  43. package/dist/index.d.ts.map +1 -1
  44. package/dist/index.js +2 -1
  45. package/dist/loadable-hooks/useClientSideDefer.d.ts +9 -4
  46. package/dist/loadable-hooks/useClientSideDefer.d.ts.map +1 -1
  47. package/dist/loadable-hooks/useClientSideDefer.js +34 -1
  48. package/dist/loadable-hooks/useConnectionSpecPagination.d.ts +5 -3
  49. package/dist/loadable-hooks/useConnectionSpecPagination.d.ts.map +1 -1
  50. package/dist/loadable-hooks/useConnectionSpecPagination.js +27 -13
  51. package/dist/loadable-hooks/useImperativeLoadableField.d.ts +1 -1
  52. package/dist/loadable-hooks/useImperativeLoadableField.d.ts.map +1 -1
  53. package/dist/loadable-hooks/useSkipLimitPagination.d.ts +1 -1
  54. package/dist/loadable-hooks/useSkipLimitPagination.d.ts.map +1 -1
  55. package/dist/loadable-hooks/useSkipLimitPagination.js +1 -1
  56. package/dist/react/FragmentReader.d.ts +2 -1
  57. package/dist/react/FragmentReader.d.ts.map +1 -1
  58. package/dist/react/FragmentRenderer.d.ts +2 -1
  59. package/dist/react/FragmentRenderer.d.ts.map +1 -1
  60. package/dist/react/LoadableFieldReader.d.ts +9 -3
  61. package/dist/react/LoadableFieldReader.d.ts.map +1 -1
  62. package/dist/react/LoadableFieldReader.js +40 -1
  63. package/dist/react/LoadableFieldRenderer.d.ts +9 -3
  64. package/dist/react/LoadableFieldRenderer.d.ts.map +1 -1
  65. package/dist/react/LoadableFieldRenderer.js +36 -1
  66. package/dist/react/useImperativeReference.d.ts +4 -3
  67. package/dist/react/useImperativeReference.d.ts.map +1 -1
  68. package/dist/react/useImperativeReference.js +3 -5
  69. package/dist/react/useLazyReference.d.ts +2 -1
  70. package/dist/react/useLazyReference.d.ts.map +1 -1
  71. package/dist/react/useReadAndSubscribe.d.ts.map +1 -1
  72. package/dist/react/useReadAndSubscribe.js +1 -3
  73. package/dist/react/useResult.d.ts.map +1 -1
  74. package/dist/react/useResult.js +6 -5
  75. package/package.json +16 -17
  76. package/src/core/FragmentReference.ts +10 -4
  77. package/src/core/IsographEnvironment.ts +59 -13
  78. package/src/core/PromiseWrapper.ts +14 -7
  79. package/src/core/brand.ts +18 -0
  80. package/src/core/cache.ts +186 -91
  81. package/src/core/check.ts +21 -10
  82. package/src/core/componentCache.ts +8 -4
  83. package/src/core/entrypoint.ts +35 -6
  84. package/src/core/garbageCollection.ts +61 -19
  85. package/src/core/logging.ts +15 -3
  86. package/src/core/makeNetworkRequest.ts +307 -74
  87. package/src/core/optimisticProxy.ts +563 -0
  88. package/src/core/read.ts +233 -163
  89. package/src/core/reader.ts +10 -6
  90. package/src/core/startUpdate.ts +45 -30
  91. package/src/index.ts +2 -1
  92. package/src/loadable-hooks/useClientSideDefer.ts +76 -26
  93. package/src/loadable-hooks/useConnectionSpecPagination.ts +34 -17
  94. package/src/loadable-hooks/useImperativeLoadableField.ts +2 -2
  95. package/src/loadable-hooks/useSkipLimitPagination.ts +2 -3
  96. package/src/react/FragmentReader.tsx +3 -1
  97. package/src/react/FragmentRenderer.tsx +8 -1
  98. package/src/react/LoadableFieldReader.tsx +123 -12
  99. package/src/react/LoadableFieldRenderer.tsx +122 -12
  100. package/src/react/useImperativeReference.ts +20 -11
  101. package/src/react/useLazyReference.ts +17 -6
  102. package/src/react/useReadAndSubscribe.ts +1 -8
  103. package/src/react/useResult.ts +9 -11
  104. package/src/tests/__isograph/Node/asEconomist/resolver_reader.ts +1 -1
  105. package/src/tests/__isograph/Query/linkedUpdate/entrypoint.ts +3 -1
  106. package/src/tests/__isograph/Query/linkedUpdate/raw_response_type.ts +13 -0
  107. package/src/tests/__isograph/Query/linkedUpdate/resolver_reader.ts +1 -1
  108. package/src/tests/__isograph/Query/meName/entrypoint.ts +3 -1
  109. package/src/tests/__isograph/Query/meName/raw_response_type.ts +7 -0
  110. package/src/tests/__isograph/Query/meName/resolver_reader.ts +1 -1
  111. package/src/tests/__isograph/Query/meNameSuccessor/entrypoint.ts +3 -1
  112. package/src/tests/__isograph/Query/meNameSuccessor/raw_response_type.ts +14 -0
  113. package/src/tests/__isograph/Query/meNameSuccessor/resolver_reader.ts +1 -1
  114. package/src/tests/__isograph/Query/nodeField/entrypoint.ts +3 -1
  115. package/src/tests/__isograph/Query/nodeField/raw_response_type.ts +7 -0
  116. package/src/tests/__isograph/Query/nodeField/resolver_reader.ts +1 -1
  117. package/src/tests/__isograph/Query/normalizeUndefinedField/entrypoint.ts +33 -0
  118. package/src/tests/__isograph/Query/normalizeUndefinedField/normalization_ast.ts +25 -0
  119. package/src/tests/__isograph/Query/normalizeUndefinedField/output_type.ts +3 -0
  120. package/src/tests/__isograph/Query/normalizeUndefinedField/param_type.ts +9 -0
  121. package/src/tests/__isograph/Query/normalizeUndefinedField/query_text.ts +6 -0
  122. package/src/tests/__isograph/Query/normalizeUndefinedField/raw_response_type.ts +7 -0
  123. package/src/tests/__isograph/Query/normalizeUndefinedField/resolver_reader.ts +38 -0
  124. package/src/tests/__isograph/Query/startUpdate/entrypoint.ts +3 -1
  125. package/src/tests/__isograph/Query/startUpdate/raw_response_type.ts +8 -0
  126. package/src/tests/__isograph/Query/startUpdate/resolver_reader.ts +1 -1
  127. package/src/tests/__isograph/Query/subquery/entrypoint.ts +3 -1
  128. package/src/tests/__isograph/Query/subquery/raw_response_type.ts +9 -0
  129. package/src/tests/__isograph/Query/subquery/resolver_reader.ts +1 -1
  130. package/src/tests/__isograph/iso.ts +11 -1
  131. package/src/tests/garbageCollection.test.ts +8 -5
  132. package/src/tests/meNameSuccessor.ts +6 -3
  133. package/src/tests/nodeQuery.ts +4 -2
  134. package/src/tests/normalizeData.test.ts +89 -15
  135. package/src/tests/optimisticProxy.test.ts +860 -0
  136. package/src/tests/startUpdate.test.ts +7 -5
  137. package/src/tests/__isograph/Economist/__link/output_type.ts +0 -2
@@ -19,6 +19,13 @@ import {
19
19
  type StoreLink,
20
20
  } from './IsographEnvironment';
21
21
  import { logMessage } from './logging';
22
+ import {
23
+ addStartUpdateStoreLayer,
24
+ getMutableStoreRecordProxy,
25
+ getOrInsertRecord,
26
+ type StartUpdateStoreLayer,
27
+ type StoreLayer,
28
+ } from './optimisticProxy';
22
29
  import { readPromise, type PromiseWrapper } from './PromiseWrapper';
23
30
  import {
24
31
  readImperativelyLoadedField,
@@ -36,11 +43,10 @@ export function getOrCreateCachedStartUpdate<
36
43
  >(
37
44
  environment: IsographEnvironment,
38
45
  fragmentReference: FragmentReference<TReadFromStore, unknown>,
39
- eagerResolverName: string,
40
46
  networkRequestOptions: NetworkRequestReaderOptions,
41
47
  ): ExtractStartUpdate<TReadFromStore> {
42
48
  return (environment.eagerReaderCache[
43
- stableIdForFragmentReference(fragmentReference, eagerResolverName)
49
+ stableIdForFragmentReference(fragmentReference)
44
50
  ] ??= createStartUpdate(
45
51
  environment,
46
52
  fragmentReference,
@@ -56,28 +62,38 @@ export function createStartUpdate<TReadFromStore extends UnknownTReadFromStore>(
56
62
  return (updater) => {
57
63
  let mutableUpdatedIds: EncounteredIds = new Map();
58
64
 
59
- let updatableData = createUpdatableProxy(
60
- environment,
61
- fragmentReference,
62
- networkRequestOptions,
63
- mutableUpdatedIds,
65
+ const startUpdate: StartUpdateStoreLayer['startUpdate'] = (storeLayer) => {
66
+ mutableUpdatedIds.clear();
67
+ let updatableData = createUpdatableProxy(
68
+ environment,
69
+ storeLayer,
70
+ fragmentReference,
71
+ networkRequestOptions,
72
+ mutableUpdatedIds,
73
+ );
74
+
75
+ try {
76
+ updater({ updatableData });
77
+ } catch (e) {
78
+ logMessage(environment, () => ({
79
+ kind: 'StartUpdateError',
80
+ error: e,
81
+ }));
82
+ throw e;
83
+ }
84
+ };
85
+
86
+ environment.store = addStartUpdateStoreLayer(
87
+ environment.store,
88
+ startUpdate,
64
89
  );
65
90
 
66
- try {
67
- updater({ updatableData });
68
- } catch (e) {
69
- logMessage(environment, () => ({
70
- kind: 'StartUpdateError',
71
- error: e,
72
- }));
73
- throw e;
74
- } finally {
75
- logMessage(environment, () => ({
76
- kind: 'StartUpdateComplete',
77
- updatedIds: mutableUpdatedIds,
78
- }));
79
- callSubscriptions(environment, mutableUpdatedIds);
80
- }
91
+ logMessage(environment, () => ({
92
+ kind: 'StartUpdateComplete',
93
+ updatedIds: mutableUpdatedIds,
94
+ }));
95
+
96
+ callSubscriptions(environment, mutableUpdatedIds);
81
97
  };
82
98
  }
83
99
 
@@ -85,6 +101,7 @@ export function createUpdatableProxy<
85
101
  TReadFromStore extends UnknownTReadFromStore,
86
102
  >(
87
103
  environment: IsographEnvironment,
104
+ storeLayer: StoreLayer,
88
105
  fragmentReference: FragmentReference<TReadFromStore, unknown>,
89
106
  networkRequestOptions: NetworkRequestReaderOptions,
90
107
  mutableUpdatedIds: EncounteredIds,
@@ -95,6 +112,7 @@ export function createUpdatableProxy<
95
112
 
96
113
  return readUpdatableData(
97
114
  environment,
115
+ storeLayer,
98
116
  readerWithRefetchQueries.readerArtifact.readerAst,
99
117
  fragmentReference.root,
100
118
  fragmentReference.variables ?? {},
@@ -154,6 +172,7 @@ function defineCachedProperty<T>(
154
172
 
155
173
  function readUpdatableData<TReadFromStore extends UnknownTReadFromStore>(
156
174
  environment: IsographEnvironment,
175
+ storeLayer: StoreLayer,
157
176
  ast: ReaderAst<TReadFromStore>,
158
177
  root: StoreLink,
159
178
  variables: ExtractParameters<TReadFromStore>,
@@ -163,14 +182,7 @@ function readUpdatableData<TReadFromStore extends UnknownTReadFromStore>(
163
182
  mutableState: MutableInvalidationState,
164
183
  mutableUpdatedIds: EncounteredIds,
165
184
  ): ReadDataResultSuccess<ExtractUpdatableData<TReadFromStore>> {
166
- let storeRecord = environment.store[root.__typename]?.[root.__link];
167
- if (storeRecord == null) {
168
- return {
169
- kind: 'Success',
170
- data: null as any,
171
- };
172
- }
173
-
185
+ const storeRecord = getMutableStoreRecordProxy(storeLayer, root);
174
186
  let target: { [index: string]: any } = {};
175
187
 
176
188
  for (const field of ast) {
@@ -196,6 +208,7 @@ function readUpdatableData<TReadFromStore extends UnknownTReadFromStore>(
196
208
  },
197
209
  field.isUpdatable
198
210
  ? (newValue) => {
211
+ const storeRecord = getOrInsertRecord(storeLayer.data, root);
199
212
  storeRecord[storeRecordName] = newValue;
200
213
  const updatedIds = insertEmptySetIfMissing(
201
214
  mutableUpdatedIds,
@@ -226,6 +239,7 @@ function readUpdatableData<TReadFromStore extends UnknownTReadFromStore>(
226
239
  (ast, root) =>
227
240
  readUpdatableData(
228
241
  environment,
242
+ storeLayer,
229
243
  ast,
230
244
  root,
231
245
  variables,
@@ -243,6 +257,7 @@ function readUpdatableData<TReadFromStore extends UnknownTReadFromStore>(
243
257
  },
244
258
  'isUpdatable' in field && field.isUpdatable
245
259
  ? (newValue) => {
260
+ const storeRecord = getOrInsertRecord(storeLayer.data, root);
246
261
  if (Array.isArray(newValue)) {
247
262
  storeRecord[storeRecordName] = newValue.map((node) =>
248
263
  assertLink(node?.__link),
package/src/index.ts CHANGED
@@ -21,6 +21,7 @@ export {
21
21
  callSubscriptions,
22
22
  subscribe,
23
23
  normalizeData,
24
+ writeData,
24
25
  type NetworkResponseObject,
25
26
  type NetworkResponseValue,
26
27
  type NetworkResponseScalarValue,
@@ -33,7 +34,7 @@ export {
33
34
  type DataTypeValue,
34
35
  type IsographEnvironment,
35
36
  type IsographNetworkFunction,
36
- type IsographStore,
37
+ type BaseStoreLayerData as IsographStore,
37
38
  type MissingFieldHandler,
38
39
  type StoreLink,
39
40
  type Link,
@@ -9,32 +9,10 @@ import {
9
9
  import { LoadableField } from '../core/reader';
10
10
  import { useIsographEnvironment } from '../react/IsographEnvironmentProvider';
11
11
 
12
- export function useClientSideDefer<
12
+ type ArgsWithoutProvidedArgs<
13
13
  TReadFromStore extends UnknownTReadFromStore,
14
- TResult,
15
- >(
16
- loadableField: LoadableField<
17
- TReadFromStore,
18
- TResult,
19
- ExtractParameters<TReadFromStore>
20
- >,
21
- args?: Record<PropertyKey, never>,
22
- fetchOptions?: FetchOptions<TResult>,
23
- ): { fragmentReference: FragmentReference<TReadFromStore, TResult> };
24
-
25
- export function useClientSideDefer<
26
- TReadFromStore extends UnknownTReadFromStore,
27
- TResult,
28
14
  TProvidedArgs extends object,
29
- >(
30
- loadableField: LoadableField<
31
- TReadFromStore,
32
- TResult,
33
- Omit<ExtractParameters<TReadFromStore>, keyof TProvidedArgs>
34
- >,
35
- args: Omit<ExtractParameters<TReadFromStore>, keyof TProvidedArgs>,
36
- fetchOptions?: FetchOptions<TResult>,
37
- ): { fragmentReference: FragmentReference<TReadFromStore, TResult> };
15
+ > = Omit<ExtractParameters<TReadFromStore>, keyof TProvidedArgs>;
38
16
 
39
17
  export function useClientSideDefer<
40
18
  TReadFromStore extends UnknownTReadFromStore,
@@ -46,9 +24,21 @@ export function useClientSideDefer<
46
24
  TResult,
47
25
  Omit<ExtractParameters<TReadFromStore>, keyof TProvidedArgs>
48
26
  >,
49
- args?: Omit<ExtractParameters<TReadFromStore>, keyof TProvidedArgs>,
50
- fetchOptions?: FetchOptions<TResult>,
27
+ ...maybeRequiredArgs: {} extends ArgsWithoutProvidedArgs<
28
+ TReadFromStore,
29
+ TProvidedArgs
30
+ >
31
+ ? [
32
+ args?: ArgsWithoutProvidedArgs<TReadFromStore, TProvidedArgs>,
33
+ fetchOptions?: FetchOptions<TResult, never>,
34
+ ]
35
+ : [
36
+ args: ArgsWithoutProvidedArgs<TReadFromStore, TProvidedArgs>,
37
+ fetchOptions?: FetchOptions<TResult, never>,
38
+ ]
51
39
  ): { fragmentReference: FragmentReference<TReadFromStore, TResult> } {
40
+ const [args, fetchOptions] = maybeRequiredArgs;
41
+
52
42
  const [id, loader] = loadableField(args, fetchOptions ?? {});
53
43
  const environment = useIsographEnvironment();
54
44
  const cache = getOrCreateItemInSuspenseCache(environment, id, loader);
@@ -57,3 +47,63 @@ export function useClientSideDefer<
57
47
 
58
48
  return { fragmentReference };
59
49
  }
50
+
51
+ // @ts-ignore
52
+ function tsTests() {
53
+ let neverArgs!: LoadableField<
54
+ {
55
+ parameters: Record<string, never>;
56
+ data: {};
57
+ },
58
+ unknown
59
+ >;
60
+
61
+ let optionalArgs!: LoadableField<
62
+ {
63
+ parameters: {
64
+ foo?: string;
65
+ };
66
+ data: {};
67
+ },
68
+ unknown
69
+ >;
70
+
71
+ let requiredArgs!: LoadableField<
72
+ {
73
+ parameters: {
74
+ foo: string;
75
+ };
76
+ data: {};
77
+ },
78
+ unknown
79
+ >;
80
+
81
+ useClientSideDefer(neverArgs);
82
+ useClientSideDefer(neverArgs, {});
83
+ useClientSideDefer(neverArgs, {
84
+ // @ts-expect-error
85
+ foo: 'bar',
86
+ });
87
+
88
+ useClientSideDefer(optionalArgs);
89
+ useClientSideDefer(optionalArgs, {});
90
+ useClientSideDefer(optionalArgs, {
91
+ foo: 'bar',
92
+ });
93
+ useClientSideDefer(optionalArgs, {
94
+ // @ts-expect-error
95
+ foo: 12,
96
+ });
97
+
98
+ // @ts-expect-error
99
+ useClientSideDefer(requiredArgs);
100
+ // @ts-expect-error
101
+ useClientSideDefer(requiredArgs, {});
102
+ useClientSideDefer(requiredArgs, {
103
+ foo: 'bar',
104
+ });
105
+ useClientSideDefer(requiredArgs, {
106
+ // @ts-expect-error
107
+ foo: 12,
108
+ });
109
+ }
@@ -35,13 +35,16 @@ export type UsePaginationReturnValue<
35
35
  results: ReadonlyArray<TItem>;
36
36
  }
37
37
  | {
38
- kind: 'Complete';
38
+ kind: 'HasMoreRecords';
39
39
  fetchMore: (
40
40
  count: number,
41
- fetchOptions?: FetchOptions<Connection<TItem>>,
41
+ fetchOptions?: FetchOptions<Connection<TItem>, never>,
42
42
  ) => void;
43
43
  results: ReadonlyArray<TItem>;
44
- hasNextPage: boolean;
44
+ }
45
+ | {
46
+ kind: 'NoMoreRecords';
47
+ results: ReadonlyArray<TItem>;
45
48
  };
46
49
 
47
50
  type LoadedFragmentReferences<
@@ -134,7 +137,6 @@ export function useConnectionSpecPagination<
134
137
  startUpdate: getOrCreateCachedStartUpdate(
135
138
  environment,
136
139
  fragmentReference,
137
- readerWithRefetchQueries.readerArtifact.fieldName,
138
140
  networkRequestOptions,
139
141
  ),
140
142
  }
@@ -208,7 +210,10 @@ export function useConnectionSpecPagination<
208
210
 
209
211
  const getFetchMore =
210
212
  (after: string | null) =>
211
- (count: number, fetchOptions?: FetchOptions<Connection<TItem>>): void => {
213
+ (
214
+ count: number,
215
+ fetchOptions?: FetchOptions<Connection<TItem>, never>,
216
+ ): void => {
212
217
  const loadedField = loadableField(
213
218
  {
214
219
  after: after,
@@ -302,12 +307,18 @@ export function useConnectionSpecPagination<
302
307
  );
303
308
 
304
309
  if (!networkRequestStatus) {
305
- return {
306
- kind: 'Complete',
307
- fetchMore: getFetchMore(initialState?.endCursor ?? null),
308
- results: [],
309
- hasNextPage: initialState?.hasNextPage ?? true,
310
- };
310
+ if (initialState?.hasNextPage ?? true) {
311
+ return {
312
+ kind: 'HasMoreRecords',
313
+ fetchMore: getFetchMore(initialState?.endCursor ?? null),
314
+ results: [],
315
+ };
316
+ } else {
317
+ return {
318
+ kind: 'NoMoreRecords',
319
+ results: [],
320
+ };
321
+ }
311
322
  }
312
323
 
313
324
  switch (networkRequestStatus.kind) {
@@ -334,12 +345,18 @@ export function useConnectionSpecPagination<
334
345
  completedFragmentReferences,
335
346
  );
336
347
 
337
- return {
338
- results: results.edges,
339
- hasNextPage: results.pageInfo.hasNextPage,
340
- kind: 'Complete',
341
- fetchMore: getFetchMore(results.pageInfo.endCursor),
342
- };
348
+ if (results.pageInfo.hasNextPage) {
349
+ return {
350
+ kind: 'HasMoreRecords',
351
+ fetchMore: getFetchMore(results.pageInfo.endCursor),
352
+ results: results.edges,
353
+ };
354
+ } else {
355
+ return {
356
+ kind: 'NoMoreRecords',
357
+ results: results.edges,
358
+ };
359
+ }
343
360
  }
344
361
  }
345
362
  }
@@ -19,7 +19,7 @@ export type UseImperativeLoadableFieldReturn<
19
19
  // TODO this should be void iff all args are provided by the query, like in
20
20
  // useClientSideDefer.
21
21
  args: Omit<ExtractParameters<TReadFromStore>, keyof TProvidedArgs> | void,
22
- fetchOptions?: FetchOptions<TResult>,
22
+ fetchOptions?: FetchOptions<TResult, never>,
23
23
  ) => void;
24
24
  };
25
25
 
@@ -40,7 +40,7 @@ export function useImperativeLoadableField<
40
40
  return {
41
41
  loadFragmentReference: (
42
42
  args: Omit<ExtractParameters<TReadFromStore>, keyof TProvidedArgs> | void,
43
- fetchOptions?: FetchOptions<TResult>,
43
+ fetchOptions?: FetchOptions<TResult, never>,
44
44
  ) => {
45
45
  const [_id, loader] = loadableField(args, fetchOptions ?? {});
46
46
  setState(loader());
@@ -33,7 +33,7 @@ export type UseSkipLimitReturnValue<
33
33
  readonly kind: 'Complete';
34
34
  readonly fetchMore: (
35
35
  count: number,
36
- fetchOptions?: FetchOptions<ReadonlyArray<TItem>>,
36
+ fetchOptions?: FetchOptions<ReadonlyArray<TItem>, never>,
37
37
  ) => void;
38
38
  readonly results: ReadonlyArray<TItem>;
39
39
  }
@@ -128,7 +128,6 @@ export function useSkipLimitPagination<
128
128
  startUpdate: getOrCreateCachedStartUpdate(
129
129
  environment,
130
130
  fragmentReference,
131
- readerWithRefetchQueries.readerArtifact.kind,
132
131
  networkRequestOptions,
133
132
  ),
134
133
  }
@@ -197,7 +196,7 @@ export function useSkipLimitPagination<
197
196
  (loadedSoFar: number) =>
198
197
  (
199
198
  count: number,
200
- fetchOptions?: FetchOptions<ReadonlyArray<TItem>>,
199
+ fetchOptions?: FetchOptions<ReadonlyArray<TItem>, never>,
201
200
  ): void => {
202
201
  const loadedField = loadableField(
203
202
  {
@@ -1,3 +1,4 @@
1
+ import type { NetworkResponseObject } from '../core/cache';
1
2
  import {
2
3
  type ExtractReadFromStore,
3
4
  type IsographEntrypoint,
@@ -8,7 +9,8 @@ import { useResult } from './useResult';
8
9
 
9
10
  export function FragmentReader<
10
11
  TResult,
11
- TEntrypoint extends IsographEntrypoint<any, TResult, any>,
12
+ TRawResponseType extends NetworkResponseObject,
13
+ TEntrypoint extends IsographEntrypoint<any, TResult, any, TRawResponseType>,
12
14
  TChildrenResult,
13
15
  >({
14
16
  fragmentReference,
@@ -6,6 +6,7 @@ import {
6
6
  import { type FragmentReference } from '../core/FragmentReference';
7
7
  import { type NetworkRequestReaderOptions } from '../core/read';
8
8
  import { useResult } from './useResult';
9
+ import type { NetworkResponseObject } from '../core/cache';
9
10
 
10
11
  export type IsExactlyIntrinsicAttributes<T> = T extends JSX.IntrinsicAttributes
11
12
  ? JSX.IntrinsicAttributes extends T
@@ -15,7 +16,13 @@ export type IsExactlyIntrinsicAttributes<T> = T extends JSX.IntrinsicAttributes
15
16
 
16
17
  export function FragmentRenderer<
17
18
  TProps extends Record<any, any>,
18
- TEntrypoint extends IsographEntrypoint<any, React.FC<TProps>, any>,
19
+ TRawResponseType extends NetworkResponseObject,
20
+ TEntrypoint extends IsographEntrypoint<
21
+ any,
22
+ React.FC<TProps>,
23
+ any,
24
+ TRawResponseType
25
+ >,
19
26
  >(
20
27
  props: IsExactlyIntrinsicAttributes<TProps> extends true
21
28
  ? {
@@ -1,3 +1,4 @@
1
+ import React from 'react';
1
2
  import { type FetchOptions } from '../core/check';
2
3
  import {
3
4
  ExtractParameters,
@@ -8,25 +9,43 @@ import { type LoadableField } from '../core/reader';
8
9
  import { useClientSideDefer } from '../loadable-hooks/useClientSideDefer';
9
10
  import { useResult } from './useResult';
10
11
 
12
+ type ArgsWithoutProvidedArgs<
13
+ TReadFromStore extends UnknownTReadFromStore,
14
+ TProvidedArgs extends object,
15
+ > = Omit<ExtractParameters<TReadFromStore>, keyof TProvidedArgs>;
16
+
17
+ type MaybeRequiredArgs<
18
+ TReadFromStore extends UnknownTReadFromStore,
19
+ TProvidedArgs extends object,
20
+ > =
21
+ {} extends ArgsWithoutProvidedArgs<TReadFromStore, TProvidedArgs>
22
+ ? {
23
+ args?: ArgsWithoutProvidedArgs<TReadFromStore, TProvidedArgs>;
24
+ }
25
+ : {
26
+ args: ArgsWithoutProvidedArgs<TReadFromStore, TProvidedArgs>;
27
+ };
28
+
11
29
  export function LoadableFieldReader<
12
30
  TReadFromStore extends UnknownTReadFromStore,
13
31
  TResult,
14
32
  TProvidedArgs extends object,
15
33
  TChildrenResult,
16
- >(props: {
17
- loadableField: LoadableField<
18
- TReadFromStore,
19
- TResult,
20
- Omit<ExtractParameters<TReadFromStore>, keyof TProvidedArgs>
21
- >;
22
- // TODO we can improve this to not require args if its an empty object
23
- args: Omit<ExtractParameters<TReadFromStore>, keyof TProvidedArgs>;
24
- fetchOptions?: FetchOptions<TResult>;
25
- networkRequestOptions?: Partial<NetworkRequestReaderOptions>;
26
- children: (arg: TResult) => TChildrenResult;
27
- }): TChildrenResult {
34
+ >(
35
+ props: {
36
+ loadableField: LoadableField<
37
+ TReadFromStore,
38
+ TResult,
39
+ Omit<ExtractParameters<TReadFromStore>, keyof TProvidedArgs>
40
+ >;
41
+ fetchOptions?: FetchOptions<TResult, never>;
42
+ networkRequestOptions?: Partial<NetworkRequestReaderOptions>;
43
+ children: (arg: TResult) => TChildrenResult;
44
+ } & MaybeRequiredArgs<TReadFromStore, TProvidedArgs>,
45
+ ): TChildrenResult {
28
46
  const { fragmentReference } = useClientSideDefer(
29
47
  props.loadableField,
48
+ // @ts-expect-error
30
49
  props.args,
31
50
  props.fetchOptions,
32
51
  );
@@ -38,3 +57,95 @@ export function LoadableFieldReader<
38
57
 
39
58
  return props.children(readOutFragmentData);
40
59
  }
60
+
61
+ // @ts-ignore
62
+ function tsTests() {
63
+ let neverArgs!: LoadableField<
64
+ {
65
+ parameters: Record<string, never>;
66
+ data: {};
67
+ },
68
+ unknown
69
+ >;
70
+
71
+ let optionalArgs!: LoadableField<
72
+ {
73
+ parameters: {
74
+ foo?: string;
75
+ };
76
+ data: {};
77
+ },
78
+ unknown
79
+ >;
80
+
81
+ let requiredArgs!: LoadableField<
82
+ {
83
+ parameters: {
84
+ foo: string;
85
+ };
86
+ data: {};
87
+ },
88
+ unknown
89
+ >;
90
+
91
+ <LoadableFieldReader loadableField={neverArgs} children={() => {}} />;
92
+ <LoadableFieldReader
93
+ loadableField={neverArgs}
94
+ children={() => {}}
95
+ args={{}}
96
+ />;
97
+ <LoadableFieldReader
98
+ loadableField={neverArgs}
99
+ children={() => {}}
100
+ args={{
101
+ // @ts-expect-error
102
+ foo: 'bar',
103
+ }}
104
+ />;
105
+
106
+ <LoadableFieldReader loadableField={optionalArgs} children={() => {}} />;
107
+ <LoadableFieldReader
108
+ loadableField={optionalArgs}
109
+ children={() => {}}
110
+ args={{}}
111
+ />;
112
+ <LoadableFieldReader
113
+ loadableField={optionalArgs}
114
+ children={() => {}}
115
+ args={{
116
+ foo: 'bar',
117
+ }}
118
+ />;
119
+ <LoadableFieldReader
120
+ loadableField={optionalArgs}
121
+ children={() => {}}
122
+ args={{
123
+ // @ts-expect-error
124
+ foo: 12,
125
+ }}
126
+ />;
127
+
128
+ // @ts-expect-error
129
+ <LoadableFieldReader loadableField={requiredArgs} children={() => {}} />;
130
+ <LoadableFieldReader
131
+ loadableField={requiredArgs}
132
+ children={() => {}}
133
+ // @ts-expect-error
134
+ args={{}}
135
+ />;
136
+ <LoadableFieldReader
137
+ loadableField={requiredArgs}
138
+ children={() => {}}
139
+ args={{
140
+ foo: 'bar',
141
+ }}
142
+ />;
143
+ <LoadableFieldReader
144
+ loadableField={requiredArgs}
145
+ children={() => {}}
146
+ args={{
147
+ // @ts-expect-error
148
+ foo: 12,
149
+ }}
150
+ />;
151
+ }