@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,118 @@
1
+ import { CleanupFn } from '@isograph/disposable-types';
2
+ import { NetworkResponseObject, type EncounteredIds } from './cache';
3
+ import { CheckResult } from './check';
4
+ import {
5
+ IsographEntrypoint,
6
+ RefetchQueryNormalizationArtifact,
7
+ type NormalizationAstNodes,
8
+ } from './entrypoint';
9
+ import { FragmentReference, Variables } from './FragmentReference';
10
+ import {
11
+ IsographEnvironment,
12
+ IsographStore,
13
+ StoreRecord,
14
+ type Link,
15
+ } from './IsographEnvironment';
16
+ import { ReadDataResult } from './read';
17
+ import { Arguments } from './util';
18
+
19
+ export type LogMessage =
20
+ | {
21
+ kind: 'AboutToNormalize';
22
+ normalizationAst: NormalizationAstNodes;
23
+ networkResponse: NetworkResponseObject;
24
+ variables: Variables;
25
+ }
26
+ | {
27
+ kind: 'AfterNormalization';
28
+ store: IsographStore;
29
+ encounteredIds: EncounteredIds;
30
+ }
31
+ | {
32
+ kind: 'DeepEqualityCheck';
33
+ fragmentReference: FragmentReference<any, any>;
34
+ old: object;
35
+ new: object;
36
+ deeplyEqual: boolean;
37
+ }
38
+ | {
39
+ kind: 'ComponentRerendered';
40
+ componentName: string;
41
+ rootLink: Link;
42
+ }
43
+ | {
44
+ kind: 'MakeNetworkRequest';
45
+ artifact:
46
+ | RefetchQueryNormalizationArtifact
47
+ | IsographEntrypoint<any, any, any>;
48
+ variables: Variables;
49
+ networkRequestId: string;
50
+ }
51
+ | {
52
+ kind: 'ReceivedNetworkResponse';
53
+ // TODO should be object
54
+ networkResponse: any;
55
+ networkRequestId: string;
56
+ }
57
+ | {
58
+ kind: 'ReceivedNetworkError';
59
+ error: any;
60
+ networkRequestId: string;
61
+ }
62
+ | {
63
+ kind: 'MissingFieldHandlerCalled';
64
+ root: Link;
65
+ storeRecord: StoreRecord;
66
+ fieldName: string;
67
+ arguments: Arguments | null;
68
+ variables: Variables;
69
+ }
70
+ | {
71
+ kind: 'DoneReading';
72
+ response: ReadDataResult<any>;
73
+ fieldName: string;
74
+ root: Link;
75
+ }
76
+ | {
77
+ kind: 'NonEntrypointReceived';
78
+ entrypoint: any;
79
+ }
80
+ | {
81
+ kind: 'EnvironmentCheck';
82
+ result: CheckResult;
83
+ }
84
+ | {
85
+ kind: 'EnvironmentCreated';
86
+ };
87
+
88
+ export type LogFunction = (logMessage: LogMessage) => void;
89
+
90
+ // wrapped so that items in the loggers set are unique.
91
+ export type WrappedLogFunction = {
92
+ log: LogFunction;
93
+ };
94
+
95
+ export function logMessage(
96
+ environment: IsographEnvironment,
97
+ getMessage: () => LogMessage,
98
+ ) {
99
+ if (environment.loggers.size > 0) {
100
+ const message = getMessage();
101
+ for (const logger of environment.loggers) {
102
+ try {
103
+ logger.log(message);
104
+ } catch {}
105
+ }
106
+ }
107
+ }
108
+
109
+ export function registerLogger(
110
+ environment: IsographEnvironment,
111
+ log: LogFunction,
112
+ ): CleanupFn {
113
+ const wrapped = { log };
114
+ environment.loggers.add(wrapped);
115
+ return () => {
116
+ environment.loggers.delete(wrapped);
117
+ };
118
+ }
@@ -1,60 +1,168 @@
1
1
  import { ItemCleanupPair } from '@isograph/disposable-types';
2
+ import { normalizeData } from './cache';
3
+ import { check, DEFAULT_SHOULD_FETCH_VALUE, FetchOptions } from './check';
4
+ import { getOrCreateCachedComponent } from './componentCache';
2
5
  import {
3
6
  IsographEntrypoint,
4
7
  RefetchQueryNormalizationArtifact,
8
+ type NormalizationAst,
9
+ type NormalizationAstLoader,
5
10
  } from './entrypoint';
6
- import { Variables } from './FragmentReference';
11
+ import {
12
+ ExtractParameters,
13
+ type FragmentReference,
14
+ type UnknownTReadFromStore,
15
+ } from './FragmentReference';
7
16
  import {
8
17
  garbageCollectEnvironment,
9
18
  RetainedQuery,
10
19
  retainQuery,
11
20
  unretainQuery,
12
21
  } from './garbageCollection';
13
- import { IsographEnvironment } from './IsographEnvironment';
14
- import { AnyError, PromiseWrapper, wrapPromise } from './PromiseWrapper';
15
- import { normalizeData } from './cache';
22
+ import { IsographEnvironment, Link, ROOT_ID } from './IsographEnvironment';
23
+ import { logMessage } from './logging';
24
+ import {
25
+ AnyError,
26
+ PromiseWrapper,
27
+ wrapPromise,
28
+ wrapResolvedValue,
29
+ } from './PromiseWrapper';
30
+ import { readButDoNotEvaluate } from './read';
31
+ import { getOrCreateCachedStartUpdate } from './startUpdate';
32
+
33
+ let networkRequestId = 0;
16
34
 
17
- export function makeNetworkRequest(
35
+ export function maybeMakeNetworkRequest<
36
+ TReadFromStore extends UnknownTReadFromStore,
37
+ TClientFieldValue,
38
+ TNormalizationAst extends NormalizationAst | NormalizationAstLoader,
39
+ >(
18
40
  environment: IsographEnvironment,
19
- artifact: RefetchQueryNormalizationArtifact | IsographEntrypoint<any, any>,
20
- variables: Variables,
41
+ artifact:
42
+ | RefetchQueryNormalizationArtifact
43
+ | IsographEntrypoint<TReadFromStore, TClientFieldValue, TNormalizationAst>,
44
+ variables: ExtractParameters<TReadFromStore>,
45
+ fetchOptions?: FetchOptions<TClientFieldValue>,
21
46
  ): ItemCleanupPair<PromiseWrapper<void, AnyError>> {
22
- // @ts-expect-error
23
- if (typeof window !== 'undefined' && window.__LOG) {
24
- console.log('make network request', artifact, variables);
47
+ switch (fetchOptions?.shouldFetch ?? DEFAULT_SHOULD_FETCH_VALUE) {
48
+ case 'Yes': {
49
+ return makeNetworkRequest(environment, artifact, variables, fetchOptions);
50
+ }
51
+ case 'No': {
52
+ return [wrapResolvedValue(undefined), () => {}];
53
+ }
54
+ case 'IfNecessary': {
55
+ if (
56
+ artifact.networkRequestInfo.normalizationAst.kind ===
57
+ 'NormalizationAstLoader'
58
+ ) {
59
+ throw new Error(
60
+ 'Using lazy loaded normalizationAst with shouldFetch: "IfNecessary" is not supported as it will lead to slower initial load time.',
61
+ );
62
+ }
63
+ const result = check(
64
+ environment,
65
+ artifact.networkRequestInfo.normalizationAst.selections,
66
+ variables,
67
+ {
68
+ __link: ROOT_ID,
69
+ __typename: artifact.concreteType,
70
+ },
71
+ );
72
+
73
+ if (result.kind === 'EnoughData') {
74
+ return [wrapResolvedValue(undefined), () => {}];
75
+ } else {
76
+ return makeNetworkRequest(
77
+ environment,
78
+ artifact,
79
+ variables,
80
+ fetchOptions,
81
+ );
82
+ }
83
+ }
84
+ }
85
+ }
86
+
87
+ function loadNormalizationAst(
88
+ normalizationAst: NormalizationAstLoader | NormalizationAst,
89
+ ) {
90
+ switch (normalizationAst.kind) {
91
+ case 'NormalizationAst': {
92
+ return normalizationAst;
93
+ }
94
+ case 'NormalizationAstLoader': {
95
+ return normalizationAst.loader();
96
+ }
25
97
  }
98
+ }
99
+
100
+ export function makeNetworkRequest<
101
+ TReadFromStore extends UnknownTReadFromStore,
102
+ TClientFieldValue,
103
+ TNormalizationAst extends NormalizationAst | NormalizationAstLoader,
104
+ >(
105
+ environment: IsographEnvironment,
106
+ artifact:
107
+ | RefetchQueryNormalizationArtifact
108
+ | IsographEntrypoint<TReadFromStore, TClientFieldValue, TNormalizationAst>,
109
+ variables: ExtractParameters<TReadFromStore>,
110
+ fetchOptions?: FetchOptions<TClientFieldValue>,
111
+ ): ItemCleanupPair<PromiseWrapper<void, AnyError>> {
112
+ // TODO this should be a DataId and stored in the store
113
+ const myNetworkRequestId = networkRequestId + '';
114
+ networkRequestId++;
115
+
116
+ logMessage(environment, () => ({
117
+ kind: 'MakeNetworkRequest',
118
+ artifact,
119
+ variables,
120
+ networkRequestId: myNetworkRequestId,
121
+ }));
122
+
26
123
  let status: NetworkRequestStatus = {
27
124
  kind: 'UndisposedIncomplete',
28
125
  };
29
126
  // This should be an observable, not a promise
30
- const promise = environment
31
- .networkFunction(artifact.queryText, variables)
32
- .then((networkResponse) => {
33
- // @ts-expect-error
34
- if (typeof window !== 'undefined' && window.__LOG) {
35
- console.log('network response', artifact, networkResponse);
36
- }
127
+ const promise = Promise.all([
128
+ environment.networkFunction(
129
+ artifact.networkRequestInfo.queryText,
130
+ variables,
131
+ ),
132
+ loadNormalizationAst(artifact.networkRequestInfo.normalizationAst),
133
+ ])
134
+ .then(([networkResponse, normalizationAst]) => {
135
+ logMessage(environment, () => ({
136
+ kind: 'ReceivedNetworkResponse',
137
+ networkResponse,
138
+ networkRequestId: myNetworkRequestId,
139
+ }));
37
140
 
38
141
  if (networkResponse.errors != null) {
39
- // @ts-expect-error Why are we getting the wrong constructor here?
142
+ try {
143
+ fetchOptions?.onError?.();
144
+ } catch {}
40
145
  throw new Error('GraphQL network response had errors', {
41
146
  cause: networkResponse,
42
147
  });
43
148
  }
44
149
 
150
+ const root = { __link: ROOT_ID, __typename: artifact.concreteType };
45
151
  if (status.kind === 'UndisposedIncomplete') {
46
152
  normalizeData(
47
153
  environment,
48
- artifact.normalizationAst,
154
+ normalizationAst.selections,
49
155
  networkResponse.data ?? {},
50
156
  variables,
51
157
  artifact.kind === 'Entrypoint'
52
158
  ? artifact.readerWithRefetchQueries.nestedRefetchQueries
53
159
  : [],
160
+ root,
54
161
  );
55
162
  const retainedQuery = {
56
- normalizationAst: artifact.normalizationAst,
163
+ normalizationAst: normalizationAst.selections,
57
164
  variables,
165
+ root,
58
166
  };
59
167
  status = {
60
168
  kind: 'UndisposedComplete',
@@ -62,6 +170,35 @@ export function makeNetworkRequest(
62
170
  };
63
171
  retainQuery(environment, retainedQuery);
64
172
  }
173
+
174
+ const onComplete = fetchOptions?.onComplete;
175
+ if (onComplete != null) {
176
+ let data = readDataForOnComplete(
177
+ artifact,
178
+ environment,
179
+ root,
180
+ variables,
181
+ );
182
+
183
+ try {
184
+ // @ts-expect-error this problem will be fixed when we remove RefetchQueryNormalizationArtifact
185
+ // (or we can fix this by having a single param of type { kind: 'Entrypoint', entrypoint,
186
+ // fetchOptions: FetchOptions<TReadFromStore> } | { kind: 'RefetchQuery', refetchQuery,
187
+ // fetchOptions: FetchOptions<void> }).
188
+ onComplete(data);
189
+ } catch {}
190
+ }
191
+ })
192
+ .catch((e) => {
193
+ logMessage(environment, () => ({
194
+ kind: 'ReceivedNetworkError',
195
+ networkRequestId: myNetworkRequestId,
196
+ error: e,
197
+ }));
198
+ try {
199
+ fetchOptions?.onError?.();
200
+ } catch {}
201
+ throw e;
65
202
  });
66
203
 
67
204
  const wrapper = wrapPromise(promise);
@@ -97,3 +234,95 @@ type NetworkRequestStatus =
97
234
  readonly kind: 'UndisposedComplete';
98
235
  readonly retainedQuery: RetainedQuery;
99
236
  };
237
+
238
+ function readDataForOnComplete<
239
+ TReadFromStore extends UnknownTReadFromStore,
240
+ TClientFieldValue,
241
+ TNormalizationAst extends NormalizationAst | NormalizationAstLoader,
242
+ >(
243
+ artifact:
244
+ | RefetchQueryNormalizationArtifact
245
+ | IsographEntrypoint<TReadFromStore, TClientFieldValue, TNormalizationAst>,
246
+ environment: IsographEnvironment,
247
+ root: Link,
248
+ variables: ExtractParameters<TReadFromStore>,
249
+ ): TClientFieldValue | null {
250
+ // An entrypoint, but not a RefetchQueryNormalizationArtifact, has a reader ASTs.
251
+ // So, we can only pass data to onComplete if makeNetworkRequest was passed an entrypoint.
252
+ // This is awkward, since we don't express that in the types of the parameters
253
+ // (i.e. FetchOptions could be passed, along with a RefetchQueryNormalizationArtifact).
254
+ //
255
+ // However, this isn't a big deal: RefetchQueryNormalizationArtifact is going away.
256
+ if (artifact.kind === 'Entrypoint') {
257
+ // TODO this is a smell!
258
+ const fakeNetworkRequest = wrapResolvedValue(undefined);
259
+ // TODO this is a smell — we know the network response is not in flight,
260
+ // so we don't really care!
261
+ const fakeNetworkRequestOptions = {
262
+ suspendIfInFlight: false,
263
+ throwOnNetworkError: false,
264
+ };
265
+
266
+ const fragment: FragmentReference<TReadFromStore, TClientFieldValue> = {
267
+ kind: 'FragmentReference',
268
+ // TODO this smells.
269
+ readerWithRefetchQueries: wrapResolvedValue(
270
+ artifact.readerWithRefetchQueries,
271
+ ),
272
+ root,
273
+ variables,
274
+ networkRequest: fakeNetworkRequest,
275
+ };
276
+ const fragmentResult = readButDoNotEvaluate(
277
+ environment,
278
+ fragment,
279
+ fakeNetworkRequestOptions,
280
+ ).item;
281
+ const readerArtifact = artifact.readerWithRefetchQueries.readerArtifact;
282
+ switch (readerArtifact.kind) {
283
+ case 'ComponentReaderArtifact': {
284
+ // @ts-expect-error We should find a way to encode this in the type system:
285
+ // if we have a ComponentReaderArtifact, we will necessarily have a
286
+ // TClientFieldValue which is a React.FC<...>
287
+ return getOrCreateCachedComponent(
288
+ environment,
289
+ readerArtifact.fieldName,
290
+ {
291
+ kind: 'FragmentReference',
292
+ readerWithRefetchQueries: wrapResolvedValue({
293
+ kind: 'ReaderWithRefetchQueries',
294
+ readerArtifact: readerArtifact,
295
+ nestedRefetchQueries:
296
+ artifact.readerWithRefetchQueries.nestedRefetchQueries,
297
+ }),
298
+ root,
299
+ variables,
300
+ networkRequest: fakeNetworkRequest,
301
+ } as const,
302
+ fakeNetworkRequestOptions,
303
+ );
304
+ }
305
+ case 'EagerReaderArtifact': {
306
+ return readerArtifact.resolver({
307
+ data: fragmentResult,
308
+ parameters: variables,
309
+ ...(readerArtifact.hasUpdatable
310
+ ? {
311
+ startUpdate: getOrCreateCachedStartUpdate(
312
+ environment,
313
+ fragment,
314
+ artifact.readerWithRefetchQueries.readerArtifact.fieldName,
315
+ ),
316
+ }
317
+ : undefined),
318
+ });
319
+ }
320
+ default: {
321
+ const _: never = readerArtifact;
322
+ _;
323
+ throw new Error('Expected case');
324
+ }
325
+ }
326
+ }
327
+ return null;
328
+ }