@isograph/react 0.3.0 → 0.4.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 (164) hide show
  1. package/.turbo/turbo-compile-libs.log +5 -0
  2. package/dist/core/FragmentReference.d.ts +17 -8
  3. package/dist/core/FragmentReference.d.ts.map +1 -1
  4. package/dist/core/FragmentReference.js +3 -12
  5. package/dist/core/IsographEnvironment.d.ts +30 -35
  6. package/dist/core/IsographEnvironment.d.ts.map +1 -1
  7. package/dist/core/IsographEnvironment.js +4 -0
  8. package/dist/core/PromiseWrapper.d.ts +6 -7
  9. package/dist/core/PromiseWrapper.d.ts.map +1 -1
  10. package/dist/core/PromiseWrapper.js +6 -12
  11. package/dist/core/areEqualWithDeepComparison.d.ts +1 -3
  12. package/dist/core/areEqualWithDeepComparison.d.ts.map +1 -1
  13. package/dist/core/areEqualWithDeepComparison.js +16 -2
  14. package/dist/core/brand.d.ts +2 -0
  15. package/dist/core/brand.d.ts.map +1 -0
  16. package/dist/core/brand.js +2 -0
  17. package/dist/core/cache.d.ts +16 -24
  18. package/dist/core/cache.d.ts.map +1 -1
  19. package/dist/core/cache.js +105 -72
  20. package/dist/core/check.d.ts +11 -7
  21. package/dist/core/check.d.ts.map +1 -1
  22. package/dist/core/check.js +2 -2
  23. package/dist/core/componentCache.d.ts +1 -1
  24. package/dist/core/componentCache.d.ts.map +1 -1
  25. package/dist/core/componentCache.js +27 -31
  26. package/dist/core/entrypoint.d.ts +43 -28
  27. package/dist/core/entrypoint.d.ts.map +1 -1
  28. package/dist/core/garbageCollection.d.ts +5 -6
  29. package/dist/core/garbageCollection.d.ts.map +1 -1
  30. package/dist/core/garbageCollection.js +1 -1
  31. package/dist/core/logging.d.ts +23 -15
  32. package/dist/core/logging.d.ts.map +1 -1
  33. package/dist/core/logging.js +8 -5
  34. package/dist/core/makeNetworkRequest.d.ts +5 -5
  35. package/dist/core/makeNetworkRequest.d.ts.map +1 -1
  36. package/dist/core/makeNetworkRequest.js +113 -28
  37. package/dist/core/read.d.ts +16 -11
  38. package/dist/core/read.d.ts.map +1 -1
  39. package/dist/core/read.js +468 -305
  40. package/dist/core/reader.d.ts +33 -37
  41. package/dist/core/reader.d.ts.map +1 -1
  42. package/dist/core/startUpdate.d.ts +8 -0
  43. package/dist/core/startUpdate.d.ts.map +1 -0
  44. package/dist/core/startUpdate.js +163 -0
  45. package/dist/core/util.d.ts +3 -0
  46. package/dist/core/util.d.ts.map +1 -1
  47. package/dist/index.d.ts +18 -15
  48. package/dist/index.d.ts.map +1 -1
  49. package/dist/index.js +9 -1
  50. package/dist/loadable-hooks/useClientSideDefer.d.ts +4 -10
  51. package/dist/loadable-hooks/useClientSideDefer.d.ts.map +1 -1
  52. package/dist/loadable-hooks/useClientSideDefer.js +2 -2
  53. package/dist/loadable-hooks/useConnectionSpecPagination.d.ts +8 -15
  54. package/dist/loadable-hooks/useConnectionSpecPagination.d.ts.map +1 -1
  55. package/dist/loadable-hooks/useConnectionSpecPagination.js +6 -4
  56. package/dist/loadable-hooks/useImperativeExposedMutationField.d.ts +1 -2
  57. package/dist/loadable-hooks/useImperativeExposedMutationField.d.ts.map +1 -1
  58. package/dist/loadable-hooks/useImperativeLoadableField.d.ts +4 -6
  59. package/dist/loadable-hooks/useImperativeLoadableField.d.ts.map +1 -1
  60. package/dist/loadable-hooks/useImperativeLoadableField.js +1 -1
  61. package/dist/loadable-hooks/useSkipLimitPagination.d.ts +6 -13
  62. package/dist/loadable-hooks/useSkipLimitPagination.d.ts.map +1 -1
  63. package/dist/loadable-hooks/useSkipLimitPagination.js +11 -9
  64. package/dist/react/FragmentReader.d.ts +7 -14
  65. package/dist/react/FragmentReader.d.ts.map +1 -1
  66. package/dist/react/FragmentReader.js +3 -30
  67. package/dist/react/FragmentRenderer.d.ts +15 -0
  68. package/dist/react/FragmentRenderer.d.ts.map +1 -0
  69. package/dist/react/FragmentRenderer.js +35 -0
  70. package/dist/react/IsographEnvironmentProvider.d.ts.map +1 -1
  71. package/dist/react/LoadableFieldReader.d.ts +12 -0
  72. package/dist/react/LoadableFieldReader.d.ts.map +1 -0
  73. package/dist/react/LoadableFieldReader.js +10 -0
  74. package/dist/react/LoadableFieldRenderer.d.ts +13 -0
  75. package/dist/react/LoadableFieldRenderer.d.ts.map +1 -0
  76. package/dist/react/LoadableFieldRenderer.js +37 -0
  77. package/dist/react/useImperativeReference.d.ts +7 -10
  78. package/dist/react/useImperativeReference.d.ts.map +1 -1
  79. package/dist/react/useImperativeReference.js +8 -9
  80. package/dist/react/useLazyReference.d.ts +4 -7
  81. package/dist/react/useLazyReference.d.ts.map +1 -1
  82. package/dist/react/useLazyReference.js +26 -5
  83. package/dist/react/useReadAndSubscribe.d.ts +3 -9
  84. package/dist/react/useReadAndSubscribe.d.ts.map +1 -1
  85. package/dist/react/useReadAndSubscribe.js +7 -3
  86. package/dist/react/useRerenderOnChange.d.ts +1 -1
  87. package/dist/react/useRerenderOnChange.d.ts.map +1 -1
  88. package/dist/react/useResult.d.ts +3 -6
  89. package/dist/react/useResult.d.ts.map +1 -1
  90. package/dist/react/useResult.js +10 -8
  91. package/isograph.config.json +1 -0
  92. package/package.json +6 -6
  93. package/src/core/FragmentReference.ts +40 -16
  94. package/src/core/IsographEnvironment.ts +57 -39
  95. package/src/core/PromiseWrapper.ts +15 -18
  96. package/src/core/areEqualWithDeepComparison.ts +22 -2
  97. package/src/core/brand.ts +18 -0
  98. package/src/core/cache.ts +153 -113
  99. package/src/core/check.ts +17 -12
  100. package/src/core/componentCache.ts +47 -50
  101. package/src/core/entrypoint.ts +66 -21
  102. package/src/core/garbageCollection.ts +9 -9
  103. package/src/core/logging.ts +39 -25
  104. package/src/core/makeNetworkRequest.ts +212 -34
  105. package/src/core/read.ts +728 -440
  106. package/src/core/reader.ts +46 -29
  107. package/src/core/startUpdate.ts +334 -0
  108. package/src/core/util.ts +4 -0
  109. package/src/index.ts +89 -8
  110. package/src/loadable-hooks/useClientSideDefer.ts +11 -10
  111. package/src/loadable-hooks/useConnectionSpecPagination.ts +27 -13
  112. package/src/loadable-hooks/useImperativeExposedMutationField.ts +1 -1
  113. package/src/loadable-hooks/useImperativeLoadableField.ts +10 -12
  114. package/src/loadable-hooks/useSkipLimitPagination.ts +38 -19
  115. package/src/react/FragmentReader.tsx +23 -39
  116. package/src/react/FragmentRenderer.tsx +46 -0
  117. package/src/react/IsographEnvironmentProvider.tsx +1 -1
  118. package/src/react/LoadableFieldReader.tsx +40 -0
  119. package/src/react/LoadableFieldRenderer.tsx +41 -0
  120. package/src/react/useImperativeReference.ts +49 -27
  121. package/src/react/useLazyReference.ts +62 -14
  122. package/src/react/useReadAndSubscribe.ts +17 -9
  123. package/src/react/useRerenderOnChange.ts +2 -2
  124. package/src/react/useResult.ts +22 -8
  125. package/src/tests/__isograph/Economist/link/output_type.ts +2 -0
  126. package/src/tests/__isograph/Node/asEconomist/resolver_reader.ts +28 -0
  127. package/src/tests/__isograph/Node/link/output_type.ts +3 -0
  128. package/src/tests/__isograph/Query/linkedUpdate/entrypoint.ts +31 -0
  129. package/src/tests/__isograph/Query/linkedUpdate/normalization_ast.ts +95 -0
  130. package/src/tests/__isograph/Query/linkedUpdate/output_type.ts +3 -0
  131. package/src/tests/__isograph/Query/linkedUpdate/param_type.ts +51 -0
  132. package/src/tests/__isograph/Query/linkedUpdate/query_text.ts +20 -0
  133. package/src/tests/__isograph/Query/linkedUpdate/resolver_reader.ts +93 -0
  134. package/src/tests/__isograph/Query/meName/entrypoint.ts +8 -29
  135. package/src/tests/__isograph/Query/meName/normalization_ast.ts +25 -0
  136. package/src/tests/__isograph/Query/meName/query_text.ts +6 -0
  137. package/src/tests/__isograph/Query/meName/resolver_reader.ts +5 -0
  138. package/src/tests/__isograph/Query/meNameSuccessor/entrypoint.ts +8 -67
  139. package/src/tests/__isograph/Query/meNameSuccessor/normalization_ast.ts +56 -0
  140. package/src/tests/__isograph/Query/meNameSuccessor/query_text.ts +13 -0
  141. package/src/tests/__isograph/Query/meNameSuccessor/resolver_reader.ts +10 -0
  142. package/src/tests/__isograph/Query/nodeField/entrypoint.ts +8 -34
  143. package/src/tests/__isograph/Query/nodeField/normalization_ast.ts +30 -0
  144. package/src/tests/__isograph/Query/nodeField/query_text.ts +6 -0
  145. package/src/tests/__isograph/Query/nodeField/resolver_reader.ts +5 -0
  146. package/src/tests/__isograph/Query/startUpdate/entrypoint.ts +31 -0
  147. package/src/tests/__isograph/Query/startUpdate/normalization_ast.ts +51 -0
  148. package/src/tests/__isograph/Query/startUpdate/output_type.ts +3 -0
  149. package/src/tests/__isograph/Query/startUpdate/param_type.ts +26 -0
  150. package/src/tests/__isograph/Query/startUpdate/parameters_type.ts +3 -0
  151. package/src/tests/__isograph/Query/startUpdate/query_text.ts +11 -0
  152. package/src/tests/__isograph/Query/startUpdate/resolver_reader.ts +55 -0
  153. package/src/tests/__isograph/Query/subquery/entrypoint.ts +8 -44
  154. package/src/tests/__isograph/Query/subquery/normalization_ast.ts +38 -0
  155. package/src/tests/__isograph/Query/subquery/query_text.ts +8 -0
  156. package/src/tests/__isograph/Query/subquery/resolver_reader.ts +7 -0
  157. package/src/tests/__isograph/iso.ts +24 -3
  158. package/src/tests/__isograph/tsconfig.json +8 -0
  159. package/src/tests/garbageCollection.test.ts +10 -8
  160. package/src/tests/meNameSuccessor.ts +1 -1
  161. package/src/tests/nodeQuery.ts +2 -1
  162. package/src/tests/normalizeData.test.ts +1 -2
  163. package/src/tests/startUpdate.test.ts +205 -0
  164. package/tsconfig.pkg.json +1 -2
package/dist/core/read.js CHANGED
@@ -1,25 +1,34 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.readButDoNotEvaluate = readButDoNotEvaluate;
4
+ exports.readLoadablySelectedFieldData = readLoadablySelectedFieldData;
5
+ exports.readResolverFieldData = readResolverFieldData;
6
+ exports.readScalarFieldData = readScalarFieldData;
7
+ exports.readLinkedFieldData = readLinkedFieldData;
4
8
  exports.getNetworkRequestOptionsWithDefaults = getNetworkRequestOptionsWithDefaults;
9
+ exports.readImperativelyLoadedField = readImperativelyLoadedField;
5
10
  const cache_1 = require("./cache");
6
11
  const componentCache_1 = require("./componentCache");
7
12
  const IsographEnvironment_1 = require("./IsographEnvironment");
13
+ const logging_1 = require("./logging");
8
14
  const makeNetworkRequest_1 = require("./makeNetworkRequest");
9
15
  const PromiseWrapper_1 = require("./PromiseWrapper");
10
- const logging_1 = require("./logging");
16
+ const startUpdate_1 = require("./startUpdate");
11
17
  function readButDoNotEvaluate(environment, fragmentReference, networkRequestOptions) {
12
18
  var _a;
13
19
  const mutableEncounteredRecords = new Map();
20
+ // TODO consider moving this to the outside
14
21
  const readerWithRefetchQueries = (0, PromiseWrapper_1.readPromise)(fragmentReference.readerWithRefetchQueries);
15
22
  const response = readData(environment, readerWithRefetchQueries.readerArtifact.readerAst, fragmentReference.root, (_a = fragmentReference.variables) !== null && _a !== void 0 ? _a : {}, readerWithRefetchQueries.nestedRefetchQueries, fragmentReference.networkRequest, networkRequestOptions, mutableEncounteredRecords);
16
- (0, logging_1.logMessage)(environment, {
23
+ (0, logging_1.logMessage)(environment, () => ({
17
24
  kind: 'DoneReading',
18
25
  response,
19
- });
26
+ fieldName: readerWithRefetchQueries.readerArtifact.fieldName,
27
+ root: fragmentReference.root,
28
+ }));
20
29
  if (response.kind === 'MissingData') {
21
30
  // There are two cases here that we care about:
22
- // 1. the network request is in flight, we haven't suspend on it, and we want
31
+ // 1. the network request is in flight, we haven't suspended on it, and we want
23
32
  // to throw if it errors out. So, networkRequestOptions.suspendIfInFlight === false
24
33
  // and networkRequestOptions.throwOnNetworkError === true.
25
34
  // 2. everything else
@@ -29,7 +38,15 @@ function readButDoNotEvaluate(environment, fragmentReference, networkRequestOpti
29
38
  // will not resolve.
30
39
  if (!networkRequestOptions.suspendIfInFlight &&
31
40
  networkRequestOptions.throwOnNetworkError) {
32
- // TODO assert that the network request state is not Err
41
+ // What are we doing here? If the network response has errored out, we can do
42
+ // two things: throw a rejected promise, or throw an error. Both work identically
43
+ // in the browser. However, during initial SSR on NextJS, throwing a rejected
44
+ // promise results in an infinite loop (including re-issuing the query until the
45
+ // process OOM's or something.) Hence, we throw an error.
46
+ const result = fragmentReference.networkRequest.result;
47
+ if (result !== PromiseWrapper_1.NOT_SET && result.kind === 'Err') {
48
+ throw new Error('NetworkError', { cause: result.error });
49
+ }
33
50
  throw new Promise((resolve, reject) => {
34
51
  (0, cache_1.onNextChangeToRecord)(environment, response.recordLink).then(resolve);
35
52
  fragmentReference.networkRequest.promise.catch(reject);
@@ -45,8 +62,8 @@ function readButDoNotEvaluate(environment, fragmentReference, networkRequestOpti
45
62
  }
46
63
  }
47
64
  function readData(environment, ast, root, variables, nestedRefetchQueries, networkRequest, networkRequestOptions, mutableEncounteredRecords) {
48
- var _a, _b, _c, _d, _e;
49
- const encounteredIds = (0, cache_1.insertIfNotExists)(mutableEncounteredRecords, root.__typename);
65
+ var _a, _b, _c;
66
+ const encounteredIds = (0, cache_1.insertEmptySetIfMissing)(mutableEncounteredRecords, root.__typename);
50
67
  encounteredIds.add(root.__link);
51
68
  let storeRecord = (_a = environment.store[root.__typename]) === null || _a === void 0 ? void 0 : _a[root.__link];
52
69
  if (storeRecord === undefined) {
@@ -60,327 +77,53 @@ function readData(environment, ast, root, variables, nestedRefetchQueries, netwo
60
77
  return {
61
78
  kind: 'Success',
62
79
  data: null,
63
- encounteredRecords: mutableEncounteredRecords,
64
80
  };
65
81
  }
66
82
  let target = {};
67
83
  for (const field of ast) {
68
84
  switch (field.kind) {
69
85
  case 'Scalar': {
70
- const storeRecordName = (0, cache_1.getParentRecordKey)(field, variables);
71
- const value = storeRecord[storeRecordName];
72
- // TODO consider making scalars into discriminated unions. This probably has
73
- // to happen for when we handle errors.
74
- if (value === undefined) {
75
- return {
76
- kind: 'MissingData',
77
- reason: 'No value for ' + storeRecordName + ' on root ' + root.__link,
78
- recordLink: root,
79
- };
86
+ const data = readScalarFieldData(field, storeRecord, root, variables);
87
+ if (data.kind === 'MissingData') {
88
+ return data;
80
89
  }
81
- target[(_b = field.alias) !== null && _b !== void 0 ? _b : field.fieldName] = value;
90
+ target[(_b = field.alias) !== null && _b !== void 0 ? _b : field.fieldName] = data.data;
91
+ break;
92
+ }
93
+ case 'Link': {
94
+ target[field.alias] = root;
82
95
  break;
83
96
  }
84
97
  case 'Linked': {
85
- const storeRecordName = (0, cache_1.getParentRecordKey)(field, variables);
86
- const value = storeRecord[storeRecordName];
87
- if (Array.isArray(value)) {
88
- const results = [];
89
- for (const item of value) {
90
- const link = (0, IsographEnvironment_1.assertLink)(item);
91
- if (link === undefined) {
92
- return {
93
- kind: 'MissingData',
94
- reason: 'No link for ' +
95
- storeRecordName +
96
- ' on root ' +
97
- root.__link +
98
- '. Link is ' +
99
- JSON.stringify(item),
100
- recordLink: root,
101
- };
102
- }
103
- else if (link === null) {
104
- results.push(null);
105
- continue;
106
- }
107
- const result = readData(environment, field.selections, link, variables, nestedRefetchQueries, networkRequest, networkRequestOptions, mutableEncounteredRecords);
108
- if (result.kind === 'MissingData') {
109
- return {
110
- kind: 'MissingData',
111
- reason: 'Missing data for ' +
112
- storeRecordName +
113
- ' on root ' +
114
- root.__link +
115
- '. Link is ' +
116
- JSON.stringify(item),
117
- nestedReason: result,
118
- recordLink: result.recordLink,
119
- };
120
- }
121
- results.push(result.data);
122
- }
123
- target[(_c = field.alias) !== null && _c !== void 0 ? _c : field.fieldName] = results;
124
- break;
125
- }
126
- let link = (0, IsographEnvironment_1.assertLink)(value);
127
- if (field.condition) {
128
- const data = readData(environment, field.condition.readerAst, root, variables, nestedRefetchQueries, networkRequest, networkRequestOptions, mutableEncounteredRecords);
129
- if (data.kind === 'MissingData') {
130
- return {
131
- kind: 'MissingData',
132
- reason: 'Missing data for ' +
133
- storeRecordName +
134
- ' on root ' +
135
- root.__link,
136
- nestedReason: data,
137
- recordLink: data.recordLink,
138
- };
139
- }
140
- const condition = field.condition.resolver({
141
- data: data.data,
142
- parameters: {},
143
- });
144
- if (condition === true) {
145
- link = root;
146
- }
147
- else if (condition === false) {
148
- link = null;
149
- }
150
- else {
151
- link = condition;
152
- }
153
- }
154
- if (link === undefined) {
155
- // TODO make this configurable, and also generated and derived from the schema
156
- const missingFieldHandler = environment.missingFieldHandler;
157
- const altLink = missingFieldHandler === null || missingFieldHandler === void 0 ? void 0 : missingFieldHandler(storeRecord, root, field.fieldName, field.arguments, variables);
158
- (0, logging_1.logMessage)(environment, {
159
- kind: 'MissingFieldHandlerCalled',
160
- root,
161
- storeRecord,
162
- fieldName: field.fieldName,
163
- arguments: field.arguments,
164
- variables,
165
- });
166
- if (altLink === undefined) {
167
- return {
168
- kind: 'MissingData',
169
- reason: 'No link for ' +
170
- storeRecordName +
171
- ' on root ' +
172
- root.__link +
173
- '. Link is ' +
174
- JSON.stringify(value),
175
- recordLink: root,
176
- };
177
- }
178
- else {
179
- link = altLink;
180
- }
181
- }
182
- else if (link === null) {
183
- target[(_d = field.alias) !== null && _d !== void 0 ? _d : field.fieldName] = null;
184
- break;
185
- }
186
- const targetId = link;
187
- const data = readData(environment, field.selections, targetId, variables, nestedRefetchQueries, networkRequest, networkRequestOptions, mutableEncounteredRecords);
98
+ const data = readLinkedFieldData(environment, field, storeRecord, root, variables, nestedRefetchQueries, networkRequest, networkRequestOptions, (ast, root) => readData(environment, ast, root, variables, nestedRefetchQueries, networkRequest, networkRequestOptions, mutableEncounteredRecords));
188
99
  if (data.kind === 'MissingData') {
189
- return {
190
- kind: 'MissingData',
191
- reason: 'Missing data for ' + storeRecordName + ' on root ' + root.__link,
192
- nestedReason: data,
193
- recordLink: data.recordLink,
194
- };
100
+ return data;
195
101
  }
196
- target[(_e = field.alias) !== null && _e !== void 0 ? _e : field.fieldName] = data.data;
102
+ target[(_c = field.alias) !== null && _c !== void 0 ? _c : field.fieldName] = data.data;
197
103
  break;
198
104
  }
199
105
  case 'ImperativelyLoadedField': {
200
- // First, we read the data using the refetch reader AST (i.e. read out the
201
- // id field).
202
- const data = readData(environment, field.refetchReaderArtifact.readerAst, root, variables,
203
- // Refetch fields just read the id, and don't need refetch query artifacts
204
- [],
205
- // This is probably indicative of the fact that we are doing redundant checks
206
- // on the status of this network request...
207
- networkRequest, networkRequestOptions, mutableEncounteredRecords);
106
+ const data = readImperativelyLoadedField(environment, field, root, variables, nestedRefetchQueries, networkRequest, networkRequestOptions, mutableEncounteredRecords);
208
107
  if (data.kind === 'MissingData') {
209
- return {
210
- kind: 'MissingData',
211
- reason: 'Missing data for ' + field.alias + ' on root ' + root.__link,
212
- nestedReason: data,
213
- recordLink: data.recordLink,
214
- };
215
- }
216
- else {
217
- const refetchQueryIndex = field.refetchQuery;
218
- const refetchQuery = nestedRefetchQueries[refetchQueryIndex];
219
- if (refetchQuery == null) {
220
- throw new Error('refetchQuery is null in RefetchField. This is indicative of a bug in Isograph.');
221
- }
222
- const refetchQueryArtifact = refetchQuery.artifact;
223
- const allowedVariables = refetchQuery.allowedVariables;
224
- // Second, we allow the user to call the resolver, which will ultimately
225
- // use the resolver reader AST to get the resolver parameters.
226
- target[field.alias] = (args) => [
227
- // Stable id
228
- root.__link + '__' + field.name,
229
- // Fetcher
230
- field.refetchReaderArtifact.resolver(environment, refetchQueryArtifact, data.data, filterVariables(Object.assign(Object.assign({}, args), variables), allowedVariables), root,
231
- // TODO these params should be removed
232
- null, []),
233
- ];
108
+ return data;
234
109
  }
110
+ target[field.alias] = data.data;
235
111
  break;
236
112
  }
237
113
  case 'Resolver': {
238
- const usedRefetchQueries = field.usedRefetchQueries;
239
- const resolverRefetchQueries = usedRefetchQueries.map((index) => {
240
- const resolverRefetchQuery = nestedRefetchQueries[index];
241
- if (resolverRefetchQuery == null) {
242
- throw new Error('resolverRefetchQuery is null in Resolver. This is indicative of a bug in Isograph.');
243
- }
244
- return resolverRefetchQuery;
245
- });
246
- switch (field.readerArtifact.kind) {
247
- case 'EagerReaderArtifact': {
248
- const data = readData(environment, field.readerArtifact.readerAst, root, generateChildVariableMap(variables, field.arguments), resolverRefetchQueries, networkRequest, networkRequestOptions, mutableEncounteredRecords);
249
- if (data.kind === 'MissingData') {
250
- return {
251
- kind: 'MissingData',
252
- reason: 'Missing data for ' + field.alias + ' on root ' + root.__link,
253
- nestedReason: data,
254
- recordLink: data.recordLink,
255
- };
256
- }
257
- else {
258
- const firstParameter = {
259
- data: data.data,
260
- parameters: variables,
261
- };
262
- target[field.alias] =
263
- field.readerArtifact.resolver(firstParameter);
264
- }
265
- break;
266
- }
267
- case 'ComponentReaderArtifact': {
268
- target[field.alias] = (0, componentCache_1.getOrCreateCachedComponent)(environment, field.readerArtifact.componentName, {
269
- kind: 'FragmentReference',
270
- readerWithRefetchQueries: (0, PromiseWrapper_1.wrapResolvedValue)({
271
- kind: 'ReaderWithRefetchQueries',
272
- readerArtifact: field.readerArtifact,
273
- nestedRefetchQueries: resolverRefetchQueries,
274
- }),
275
- root,
276
- variables: generateChildVariableMap(variables, field.arguments),
277
- networkRequest,
278
- }, networkRequestOptions);
279
- break;
280
- }
281
- default: {
282
- let _ = field.readerArtifact;
283
- _;
284
- throw new Error('Unexpected kind');
285
- }
114
+ const data = readResolverFieldData(environment, field, root, variables, nestedRefetchQueries, networkRequest, networkRequestOptions, mutableEncounteredRecords);
115
+ if (data.kind === 'MissingData') {
116
+ return data;
286
117
  }
118
+ target[field.alias] = data.data;
287
119
  break;
288
120
  }
289
121
  case 'LoadablySelectedField': {
290
- const refetchReaderParams = readData(environment, field.refetchReaderAst, root, variables,
291
- // Refetch fields just read the id, and don't need refetch query artifacts
292
- [], networkRequest, networkRequestOptions, mutableEncounteredRecords);
293
- if (refetchReaderParams.kind === 'MissingData') {
294
- return {
295
- kind: 'MissingData',
296
- reason: 'Missing data for ' + field.alias + ' on root ' + root.__link,
297
- nestedReason: refetchReaderParams,
298
- recordLink: refetchReaderParams.recordLink,
299
- };
300
- }
301
- else {
302
- target[field.alias] = (args, fetchOptions) => {
303
- // TODO we should use the reader AST for this
304
- const includeReadOutData = (variables, readOutData) => {
305
- variables.id = readOutData.id;
306
- return variables;
307
- };
308
- const localVariables = includeReadOutData(args !== null && args !== void 0 ? args : {}, refetchReaderParams.data);
309
- writeQueryArgsToVariables(localVariables, field.queryArguments, variables);
310
- return [
311
- // Stable id
312
- root.__typename +
313
- ':' +
314
- root.__link +
315
- '/' +
316
- field.name +
317
- '/' +
318
- stableStringifyArgs(localVariables),
319
- // Fetcher
320
- () => {
321
- const fragmentReferenceAndDisposeFromEntrypoint = (entrypoint) => {
322
- const [networkRequest, disposeNetworkRequest] = (0, makeNetworkRequest_1.maybeMakeNetworkRequest)(environment, entrypoint, localVariables, fetchOptions);
323
- const fragmentReference = {
324
- kind: 'FragmentReference',
325
- readerWithRefetchQueries: (0, PromiseWrapper_1.wrapResolvedValue)({
326
- kind: 'ReaderWithRefetchQueries',
327
- readerArtifact: entrypoint.readerWithRefetchQueries.readerArtifact,
328
- nestedRefetchQueries: entrypoint.readerWithRefetchQueries
329
- .nestedRefetchQueries,
330
- }),
331
- // TODO localVariables is not guaranteed to have an id field
332
- root,
333
- variables: localVariables,
334
- networkRequest,
335
- };
336
- return [fragmentReference, disposeNetworkRequest];
337
- };
338
- if (field.entrypoint.kind === 'Entrypoint') {
339
- return fragmentReferenceAndDisposeFromEntrypoint(field.entrypoint);
340
- }
341
- else {
342
- const isographArtifactPromiseWrapper = (0, IsographEnvironment_1.getOrLoadIsographArtifact)(environment, field.entrypoint.typeAndField, field.entrypoint.loader);
343
- const state = (0, PromiseWrapper_1.getPromiseState)(isographArtifactPromiseWrapper);
344
- if (state.kind === 'Ok') {
345
- return fragmentReferenceAndDisposeFromEntrypoint(state.value);
346
- }
347
- else {
348
- // Promise is pending or thrown
349
- let entrypointLoaderState = { kind: 'EntrypointNotLoaded' };
350
- const networkRequest = (0, PromiseWrapper_1.wrapPromise)(isographArtifactPromiseWrapper.promise.then((entrypoint) => {
351
- if (entrypointLoaderState.kind === 'EntrypointNotLoaded') {
352
- const [networkRequest, disposeNetworkRequest] = (0, makeNetworkRequest_1.maybeMakeNetworkRequest)(environment, entrypoint, localVariables, fetchOptions);
353
- entrypointLoaderState = {
354
- kind: 'NetworkRequestStarted',
355
- disposeNetworkRequest,
356
- };
357
- return networkRequest.promise;
358
- }
359
- }));
360
- const readerWithRefetchPromise = isographArtifactPromiseWrapper.promise.then((entrypoint) => entrypoint.readerWithRefetchQueries);
361
- const fragmentReference = {
362
- kind: 'FragmentReference',
363
- readerWithRefetchQueries: (0, PromiseWrapper_1.wrapPromise)(readerWithRefetchPromise),
364
- // TODO localVariables is not guaranteed to have an id field
365
- root,
366
- variables: localVariables,
367
- networkRequest,
368
- };
369
- return [
370
- fragmentReference,
371
- () => {
372
- if (entrypointLoaderState.kind === 'NetworkRequestStarted') {
373
- entrypointLoaderState.disposeNetworkRequest();
374
- }
375
- entrypointLoaderState = { kind: 'Disposed' };
376
- },
377
- ];
378
- }
379
- }
380
- },
381
- ];
382
- };
122
+ const data = readLoadablySelectedFieldData(environment, field, root, variables, networkRequest, networkRequestOptions, mutableEncounteredRecords);
123
+ if (data.kind === 'MissingData') {
124
+ return data;
383
125
  }
126
+ target[field.alias] = data.data;
384
127
  break;
385
128
  }
386
129
  default: {
@@ -394,7 +137,107 @@ function readData(environment, ast, root, variables, nestedRefetchQueries, netwo
394
137
  return {
395
138
  kind: 'Success',
396
139
  data: target,
397
- encounteredRecords: mutableEncounteredRecords,
140
+ };
141
+ }
142
+ function readLoadablySelectedFieldData(environment, field, root, variables, networkRequest, networkRequestOptions, mutableEncounteredRecords) {
143
+ const refetchReaderParams = readData(environment, field.refetchReaderAst, root, variables,
144
+ // Refetch fields just read the id, and don't need refetch query artifacts
145
+ [], networkRequest, networkRequestOptions, mutableEncounteredRecords);
146
+ if (refetchReaderParams.kind === 'MissingData') {
147
+ return {
148
+ kind: 'MissingData',
149
+ reason: 'Missing data for ' + field.alias + ' on root ' + root.__link,
150
+ nestedReason: refetchReaderParams,
151
+ recordLink: refetchReaderParams.recordLink,
152
+ };
153
+ }
154
+ return {
155
+ kind: 'Success',
156
+ data: (args,
157
+ // TODO get the associated type for FetchOptions from the loadably selected field
158
+ fetchOptions) => {
159
+ // TODO we should use the reader AST for this
160
+ const includeReadOutData = (variables, readOutData) => {
161
+ variables.id = readOutData.id;
162
+ return variables;
163
+ };
164
+ const localVariables = includeReadOutData(args !== null && args !== void 0 ? args : {}, refetchReaderParams.data);
165
+ writeQueryArgsToVariables(localVariables, field.queryArguments, variables);
166
+ return [
167
+ // Stable id
168
+ root.__typename +
169
+ ':' +
170
+ root.__link +
171
+ '/' +
172
+ field.name +
173
+ '/' +
174
+ stableStringifyArgs(localVariables),
175
+ // Fetcher
176
+ () => {
177
+ const fragmentReferenceAndDisposeFromEntrypoint = (entrypoint) => {
178
+ const readerWithRefetchQueries = entrypoint.readerWithRefetchQueries.kind ===
179
+ 'ReaderWithRefetchQueriesLoader'
180
+ ? (0, PromiseWrapper_1.wrapPromise)(entrypoint.readerWithRefetchQueries.loader())
181
+ : (0, PromiseWrapper_1.wrapResolvedValue)(entrypoint.readerWithRefetchQueries);
182
+ const [networkRequest, disposeNetworkRequest] = (0, makeNetworkRequest_1.maybeMakeNetworkRequest)(environment, entrypoint, localVariables, readerWithRefetchQueries, fetchOptions !== null && fetchOptions !== void 0 ? fetchOptions : null);
183
+ const fragmentReference = {
184
+ kind: 'FragmentReference',
185
+ readerWithRefetchQueries,
186
+ // TODO localVariables is not guaranteed to have an id field
187
+ root,
188
+ variables: localVariables,
189
+ networkRequest,
190
+ };
191
+ return [fragmentReference, disposeNetworkRequest];
192
+ };
193
+ if (field.entrypoint.kind === 'Entrypoint') {
194
+ return fragmentReferenceAndDisposeFromEntrypoint(field.entrypoint);
195
+ }
196
+ else {
197
+ const isographArtifactPromiseWrapper = (0, IsographEnvironment_1.getOrLoadIsographArtifact)(environment, field.entrypoint.typeAndField, field.entrypoint.loader);
198
+ const state = (0, PromiseWrapper_1.getPromiseState)(isographArtifactPromiseWrapper);
199
+ if (state.kind === 'Ok') {
200
+ return fragmentReferenceAndDisposeFromEntrypoint(state.value);
201
+ }
202
+ else {
203
+ // Promise is pending or thrown
204
+ let entrypointLoaderState = { kind: 'EntrypointNotLoaded' };
205
+ const readerWithRefetchQueries = (0, PromiseWrapper_1.wrapPromise)(isographArtifactPromiseWrapper.promise.then((entrypoint) => entrypoint.readerWithRefetchQueries.kind ===
206
+ 'ReaderWithRefetchQueriesLoader'
207
+ ? entrypoint.readerWithRefetchQueries.loader()
208
+ : entrypoint.readerWithRefetchQueries));
209
+ const networkRequest = (0, PromiseWrapper_1.wrapPromise)(isographArtifactPromiseWrapper.promise.then((entrypoint) => {
210
+ if (entrypointLoaderState.kind === 'EntrypointNotLoaded') {
211
+ const [networkRequest, disposeNetworkRequest] = (0, makeNetworkRequest_1.maybeMakeNetworkRequest)(environment, entrypoint, localVariables, readerWithRefetchQueries, fetchOptions !== null && fetchOptions !== void 0 ? fetchOptions : null);
212
+ entrypointLoaderState = {
213
+ kind: 'NetworkRequestStarted',
214
+ disposeNetworkRequest,
215
+ };
216
+ return networkRequest.promise;
217
+ }
218
+ }));
219
+ const fragmentReference = {
220
+ kind: 'FragmentReference',
221
+ readerWithRefetchQueries,
222
+ // TODO localVariables is not guaranteed to have an id field
223
+ root,
224
+ variables: localVariables,
225
+ networkRequest,
226
+ };
227
+ return [
228
+ fragmentReference,
229
+ () => {
230
+ if (entrypointLoaderState.kind === 'NetworkRequestStarted') {
231
+ entrypointLoaderState.disposeNetworkRequest();
232
+ }
233
+ entrypointLoaderState = { kind: 'Disposed' };
234
+ },
235
+ ];
236
+ }
237
+ }
238
+ },
239
+ ];
240
+ },
398
241
  };
399
242
  }
400
243
  function filterVariables(variables, allowedVariables) {
@@ -411,7 +254,10 @@ function generateChildVariableMap(variables, fieldArguments) {
411
254
  }
412
255
  const childVars = {};
413
256
  for (const [name, value] of fieldArguments) {
414
- if (value.kind === 'Variable') {
257
+ if (value.kind === 'Object') {
258
+ childVars[name] = generateChildVariableMap(variables, value.value);
259
+ }
260
+ else if (value.kind === 'Variable') {
415
261
  const variable = variables[value.name];
416
262
  // Variable could be null if it was not provided but has a default case,
417
263
  // so we allow the loop to continue rather than throwing an error.
@@ -431,6 +277,10 @@ function writeQueryArgsToVariables(targetVariables, queryArgs, variables) {
431
277
  }
432
278
  for (const [name, argType] of queryArgs) {
433
279
  switch (argType.kind) {
280
+ case 'Object': {
281
+ writeQueryArgsToVariables((targetVariables[name] = {}), argType.value, variables);
282
+ break;
283
+ }
434
284
  case 'Variable': {
435
285
  targetVariables[name] = variables[argType.name];
436
286
  break;
@@ -455,6 +305,279 @@ function writeQueryArgsToVariables(targetVariables, queryArgs, variables) {
455
305
  }
456
306
  }
457
307
  }
308
+ function readResolverFieldData(environment, field, root, variables, nestedRefetchQueries, networkRequest, networkRequestOptions, mutableEncounteredRecords) {
309
+ const usedRefetchQueries = field.usedRefetchQueries;
310
+ const resolverRefetchQueries = usedRefetchQueries.map((index) => {
311
+ const resolverRefetchQuery = nestedRefetchQueries[index];
312
+ if (resolverRefetchQuery == null) {
313
+ throw new Error('resolverRefetchQuery is null in Resolver. This is indicative of a bug in Isograph.');
314
+ }
315
+ return resolverRefetchQuery;
316
+ });
317
+ const readerWithRefetchQueries = {
318
+ kind: 'ReaderWithRefetchQueries',
319
+ readerArtifact: field.readerArtifact,
320
+ nestedRefetchQueries: resolverRefetchQueries,
321
+ };
322
+ const fragment = {
323
+ kind: 'FragmentReference',
324
+ readerWithRefetchQueries: (0, PromiseWrapper_1.wrapResolvedValue)(readerWithRefetchQueries),
325
+ root,
326
+ variables: generateChildVariableMap(variables, field.arguments),
327
+ networkRequest,
328
+ };
329
+ switch (field.readerArtifact.kind) {
330
+ case 'EagerReaderArtifact': {
331
+ const data = readData(environment, field.readerArtifact.readerAst, root, generateChildVariableMap(variables, field.arguments), resolverRefetchQueries, networkRequest, networkRequestOptions, mutableEncounteredRecords);
332
+ if (data.kind === 'MissingData') {
333
+ return {
334
+ kind: 'MissingData',
335
+ reason: 'Missing data for ' + field.alias + ' on root ' + root.__link,
336
+ nestedReason: data,
337
+ recordLink: data.recordLink,
338
+ };
339
+ }
340
+ const firstParameter = {
341
+ data: data.data,
342
+ parameters: variables,
343
+ startUpdate: field.readerArtifact.hasUpdatable
344
+ ? (0, startUpdate_1.getOrCreateCachedStartUpdate)(environment, fragment, readerWithRefetchQueries.readerArtifact.fieldName, networkRequestOptions)
345
+ : undefined,
346
+ };
347
+ return {
348
+ kind: 'Success',
349
+ data: field.readerArtifact.resolver(firstParameter),
350
+ };
351
+ }
352
+ case 'ComponentReaderArtifact': {
353
+ return {
354
+ kind: 'Success',
355
+ data: (0, componentCache_1.getOrCreateCachedComponent)(environment, field.readerArtifact.fieldName, fragment, networkRequestOptions),
356
+ };
357
+ }
358
+ default: {
359
+ let _ = field.readerArtifact;
360
+ _;
361
+ throw new Error('Unexpected kind');
362
+ }
363
+ }
364
+ }
365
+ function readScalarFieldData(field, storeRecord, root, variables) {
366
+ const storeRecordName = (0, cache_1.getParentRecordKey)(field, variables);
367
+ const value = storeRecord[storeRecordName];
368
+ // TODO consider making scalars into discriminated unions. This probably has
369
+ // to happen for when we handle errors.
370
+ if (value === undefined) {
371
+ return {
372
+ kind: 'MissingData',
373
+ reason: 'No value for ' + storeRecordName + ' on root ' + root.__link,
374
+ recordLink: root,
375
+ };
376
+ }
377
+ return { kind: 'Success', data: value };
378
+ }
379
+ function readLinkedFieldData(environment, field, storeRecord, root, variables, nestedRefetchQueries, networkRequest, networkRequestOptions, readData) {
380
+ const storeRecordName = (0, cache_1.getParentRecordKey)(field, variables);
381
+ const value = storeRecord[storeRecordName];
382
+ if (Array.isArray(value)) {
383
+ const results = [];
384
+ for (const item of value) {
385
+ const link = (0, IsographEnvironment_1.assertLink)(item);
386
+ if (link === undefined) {
387
+ return {
388
+ kind: 'MissingData',
389
+ reason: 'No link for ' +
390
+ storeRecordName +
391
+ ' on root ' +
392
+ root.__link +
393
+ '. Link is ' +
394
+ JSON.stringify(item),
395
+ recordLink: root,
396
+ };
397
+ }
398
+ else if (link === null) {
399
+ results.push(null);
400
+ continue;
401
+ }
402
+ const result = readData(field.selections, link);
403
+ if (result.kind === 'MissingData') {
404
+ return {
405
+ kind: 'MissingData',
406
+ reason: 'Missing data for ' +
407
+ storeRecordName +
408
+ ' on root ' +
409
+ root.__link +
410
+ '. Link is ' +
411
+ JSON.stringify(item),
412
+ nestedReason: result,
413
+ recordLink: result.recordLink,
414
+ };
415
+ }
416
+ results.push(result.data);
417
+ }
418
+ return {
419
+ kind: 'Success',
420
+ data: results,
421
+ };
422
+ }
423
+ let link = (0, IsographEnvironment_1.assertLink)(value);
424
+ if (field.condition) {
425
+ const data = readData(field.condition.readerAst, root);
426
+ if (data.kind === 'MissingData') {
427
+ return {
428
+ kind: 'MissingData',
429
+ reason: 'Missing data for ' + storeRecordName + ' on root ' + root.__link,
430
+ nestedReason: data,
431
+ recordLink: data.recordLink,
432
+ };
433
+ }
434
+ const readerWithRefetchQueries = {
435
+ kind: 'ReaderWithRefetchQueries',
436
+ readerArtifact: field.condition,
437
+ // TODO this is wrong
438
+ // should map field.condition.usedRefetchQueries
439
+ // but it doesn't exist
440
+ nestedRefetchQueries: [],
441
+ };
442
+ const fragment = {
443
+ kind: 'FragmentReference',
444
+ readerWithRefetchQueries: (0, PromiseWrapper_1.wrapResolvedValue)(readerWithRefetchQueries),
445
+ root,
446
+ variables: generateChildVariableMap(variables,
447
+ // TODO this is wrong
448
+ // should use field.arguments
449
+ // but it doesn't exist
450
+ []),
451
+ networkRequest,
452
+ };
453
+ const condition = field.condition.resolver(Object.assign({ data: data.data, parameters: {} }, (field.condition.hasUpdatable
454
+ ? {
455
+ startUpdate: (0, startUpdate_1.getOrCreateCachedStartUpdate)(environment, fragment, readerWithRefetchQueries.readerArtifact.fieldName, networkRequestOptions),
456
+ }
457
+ : undefined)));
458
+ link = condition;
459
+ }
460
+ if (link === undefined) {
461
+ // TODO make this configurable, and also generated and derived from the schema
462
+ const missingFieldHandler = environment.missingFieldHandler;
463
+ const altLink = missingFieldHandler === null || missingFieldHandler === void 0 ? void 0 : missingFieldHandler(storeRecord, root, field.fieldName, field.arguments, variables);
464
+ (0, logging_1.logMessage)(environment, () => ({
465
+ kind: 'MissingFieldHandlerCalled',
466
+ root,
467
+ storeRecord,
468
+ fieldName: field.fieldName,
469
+ arguments: field.arguments,
470
+ variables,
471
+ }));
472
+ if (altLink === undefined) {
473
+ return {
474
+ kind: 'MissingData',
475
+ reason: 'No link for ' +
476
+ storeRecordName +
477
+ ' on root ' +
478
+ root.__link +
479
+ '. Link is ' +
480
+ JSON.stringify(value),
481
+ recordLink: root,
482
+ };
483
+ }
484
+ else {
485
+ link = altLink;
486
+ }
487
+ }
488
+ else if (link === null) {
489
+ return {
490
+ kind: 'Success',
491
+ data: null,
492
+ };
493
+ }
494
+ const targetId = link;
495
+ const { refetchQueryIndex } = field;
496
+ if (refetchQueryIndex != null) {
497
+ // if field.refetchQueryIndex is not null, then the field is a client pointer, i.e.
498
+ // it is like a loadable field that returns the selections.
499
+ const refetchReaderParams = readData([
500
+ {
501
+ kind: 'Scalar',
502
+ fieldName: 'id',
503
+ alias: null,
504
+ arguments: null,
505
+ isUpdatable: false,
506
+ },
507
+ ], targetId);
508
+ if (refetchReaderParams.kind === 'MissingData') {
509
+ return {
510
+ kind: 'MissingData',
511
+ reason: 'Missing data for ' + field.alias + ' on root ' + targetId.__link,
512
+ nestedReason: refetchReaderParams,
513
+ recordLink: refetchReaderParams.recordLink,
514
+ };
515
+ }
516
+ const refetchQuery = nestedRefetchQueries[refetchQueryIndex];
517
+ if (refetchQuery == null) {
518
+ throw new Error('refetchQuery is null in RefetchField. This is indicative of a bug in Isograph.');
519
+ }
520
+ const refetchQueryArtifact = refetchQuery.artifact;
521
+ const allowedVariables = refetchQuery.allowedVariables;
522
+ return {
523
+ kind: 'Success',
524
+ data: (args,
525
+ // TODO get the associated type for FetchOptions from the loadably selected field
526
+ fetchOptions) => {
527
+ const includeReadOutData = (variables, readOutData) => {
528
+ variables.id = readOutData.id;
529
+ return variables;
530
+ };
531
+ const localVariables = includeReadOutData(args !== null && args !== void 0 ? args : {}, refetchReaderParams.data);
532
+ writeQueryArgsToVariables(localVariables, field.arguments, variables);
533
+ return [
534
+ // Stable id
535
+ targetId.__typename +
536
+ ':' +
537
+ targetId.__link +
538
+ '/' +
539
+ field.fieldName +
540
+ '/' +
541
+ stableStringifyArgs(localVariables),
542
+ // Fetcher
543
+ () => {
544
+ const variables = includeReadOutData(filterVariables(Object.assign(Object.assign({}, args), localVariables), allowedVariables), refetchReaderParams.data);
545
+ const readerWithRefetchQueries = (0, PromiseWrapper_1.wrapResolvedValue)({
546
+ kind: 'ReaderWithRefetchQueries',
547
+ readerArtifact: {
548
+ kind: 'EagerReaderArtifact',
549
+ fieldName: field.fieldName,
550
+ readerAst: field.selections,
551
+ resolver: ({ data }) => data,
552
+ hasUpdatable: false,
553
+ },
554
+ nestedRefetchQueries,
555
+ });
556
+ const [networkRequest, disposeNetworkRequest] = (0, makeNetworkRequest_1.maybeMakeNetworkRequest)(environment, refetchQueryArtifact, variables, readerWithRefetchQueries, fetchOptions !== null && fetchOptions !== void 0 ? fetchOptions : null);
557
+ const fragmentReference = {
558
+ kind: 'FragmentReference',
559
+ readerWithRefetchQueries: readerWithRefetchQueries,
560
+ root: targetId,
561
+ variables,
562
+ networkRequest,
563
+ };
564
+ return [fragmentReference, disposeNetworkRequest];
565
+ },
566
+ ];
567
+ },
568
+ };
569
+ }
570
+ const data = readData(field.selections, targetId);
571
+ if (data.kind === 'MissingData') {
572
+ return {
573
+ kind: 'MissingData',
574
+ reason: 'Missing data for ' + storeRecordName + ' on root ' + root.__link,
575
+ nestedReason: data,
576
+ recordLink: data.recordLink,
577
+ };
578
+ }
579
+ return data;
580
+ }
458
581
  function getNetworkRequestOptionsWithDefaults(networkRequestOptions) {
459
582
  var _a, _b;
460
583
  return {
@@ -476,3 +599,43 @@ function stableStringifyArgs(args) {
476
599
  }
477
600
  return s;
478
601
  }
602
+ function readImperativelyLoadedField(environment, field, root, variables, nestedRefetchQueries, networkRequest, networkRequestOptions, mutableEncounteredRecords) {
603
+ // First, we read the data using the refetch reader AST (i.e. read out the
604
+ // id field).
605
+ const data = readData(environment, field.refetchReaderArtifact.readerAst, root, variables,
606
+ // Refetch fields just read the id, and don't need refetch query artifacts
607
+ [],
608
+ // This is probably indicative of the fact that we are doing redundant checks
609
+ // on the status of this network request...
610
+ networkRequest, networkRequestOptions, mutableEncounteredRecords);
611
+ if (data.kind === 'MissingData') {
612
+ return {
613
+ kind: 'MissingData',
614
+ reason: 'Missing data for ' + field.alias + ' on root ' + root.__link,
615
+ nestedReason: data,
616
+ recordLink: data.recordLink,
617
+ };
618
+ }
619
+ else {
620
+ const { refetchQueryIndex } = field;
621
+ const refetchQuery = nestedRefetchQueries[refetchQueryIndex];
622
+ if (refetchQuery == null) {
623
+ throw new Error('Refetch query not found. This is indicative of a bug in Isograph.');
624
+ }
625
+ const refetchQueryArtifact = refetchQuery.artifact;
626
+ const allowedVariables = refetchQuery.allowedVariables;
627
+ // Second, we allow the user to call the resolver, which will ultimately
628
+ // use the resolver reader AST to get the resolver parameters.
629
+ return {
630
+ kind: 'Success',
631
+ data: (args) => [
632
+ // Stable id
633
+ root.__typename + ':' + root.__link + '__' + field.name,
634
+ // Fetcher
635
+ field.refetchReaderArtifact.resolver(environment, refetchQueryArtifact, data.data, filterVariables(Object.assign(Object.assign({}, args), variables), allowedVariables), root,
636
+ // TODO these params should be removed
637
+ null, []),
638
+ ],
639
+ };
640
+ }
641
+ }