@isograph/react 0.0.0-main-1cd3db6d → 0.0.0-main-2c275831

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/src/index.tsx CHANGED
@@ -8,10 +8,10 @@ import {
8
8
  onNextChange,
9
9
  getStore,
10
10
  getParentRecordKey,
11
- } from "./cache";
12
- import { useLazyDisposableState } from "@isograph/react-disposable-state";
13
- import { type PromiseWrapper } from "./PromiseWrapper";
14
- import { getOrCreateCachedComponent } from "./componentCache";
11
+ } from './cache';
12
+ import { useLazyDisposableState } from '@isograph/react-disposable-state';
13
+ import { type PromiseWrapper } from './PromiseWrapper';
14
+ import { getOrCreateCachedComponent } from './componentCache';
15
15
 
16
16
  export {
17
17
  setNetwork,
@@ -21,31 +21,19 @@ export {
21
21
  Link,
22
22
  StoreRecord,
23
23
  clearStore,
24
- } from "./cache";
24
+ } from './cache';
25
25
 
26
26
  // This type should be treated as an opaque type.
27
- export type IsographEntrypoint<
28
- TReadFromStore extends Object,
29
- TResolverProps,
30
- TResolverResult
31
- > = {
32
- kind: "Entrypoint";
27
+ export type IsographEntrypoint<TReadFromStore extends Object, TResolverProps, TResolverResult> = {
28
+ kind: 'Entrypoint';
33
29
  queryText: string;
34
30
  normalizationAst: NormalizationAst;
35
- readerArtifact: ReaderArtifact<
36
- TReadFromStore,
37
- TResolverProps,
38
- TResolverResult
39
- >;
31
+ readerArtifact: ReaderArtifact<TReadFromStore, TResolverProps, TResolverResult>;
40
32
  nestedRefetchQueries: RefetchQueryArtifactWrapper[];
41
33
  };
42
34
 
43
- export type ReaderArtifact<
44
- TReadFromStore extends Object,
45
- TResolverProps,
46
- TResolverResult
47
- > = {
48
- kind: "ReaderArtifact";
35
+ export type ReaderArtifact<TReadFromStore extends Object, TResolverProps, TResolverResult> = {
36
+ kind: 'ReaderArtifact';
49
37
  readerAst: ReaderAst<TReadFromStore>;
50
38
  resolver: (data: TResolverProps) => TResolverResult;
51
39
  variant: ReaderResolverVariant;
@@ -62,13 +50,13 @@ export type ReaderAstNode =
62
50
  export type ReaderAst<TReadFromStore> = ReaderAstNode[];
63
51
 
64
52
  export type ReaderScalarField = {
65
- kind: "Scalar";
53
+ kind: 'Scalar';
66
54
  fieldName: string;
67
55
  alias: string | null;
68
56
  arguments: Arguments | null;
69
57
  };
70
58
  export type ReaderLinkedField = {
71
- kind: "Linked";
59
+ kind: 'Linked';
72
60
  fieldName: string;
73
61
  alias: string | null;
74
62
  selections: ReaderAst<unknown>;
@@ -76,13 +64,13 @@ export type ReaderLinkedField = {
76
64
  };
77
65
 
78
66
  export type ReaderResolverVariant =
79
- | { kind: "Eager" }
67
+ | { kind: 'Eager' }
80
68
  // componentName is the component's cacheKey for getRefReaderByName
81
69
  // and is the type + field concatenated
82
- | { kind: "Component"; componentName: string };
70
+ | { kind: 'Component'; componentName: string };
83
71
 
84
72
  export type ReaderResolverField = {
85
- kind: "Resolver";
73
+ kind: 'Resolver';
86
74
  alias: string;
87
75
  readerArtifact: ReaderArtifact<any, any, any>;
88
76
  arguments: Arguments | null;
@@ -90,7 +78,7 @@ export type ReaderResolverField = {
90
78
  };
91
79
 
92
80
  export type ReaderRefetchField = {
93
- kind: "RefetchField";
81
+ kind: 'RefetchField';
94
82
  alias: string;
95
83
  // TODO this bad modeling. A refetch field cannot have variant: "Component" (I think)
96
84
  readerArtifact: ReaderArtifact<any, any, any>;
@@ -98,7 +86,7 @@ export type ReaderRefetchField = {
98
86
  };
99
87
 
100
88
  export type ReaderMutationField = {
101
- kind: "MutationField";
89
+ kind: 'MutationField';
102
90
  alias: string;
103
91
  // TODO this bad modeling. A mutation field cannot have variant: "Component" (I think)
104
92
  readerArtifact: ReaderArtifact<any, any, any>;
@@ -106,20 +94,18 @@ export type ReaderMutationField = {
106
94
  allowedVariables: string[];
107
95
  };
108
96
 
109
- export type NormalizationAstNode =
110
- | NormalizationScalarField
111
- | NormalizationLinkedField;
97
+ export type NormalizationAstNode = NormalizationScalarField | NormalizationLinkedField;
112
98
  // @ts-ignore
113
99
  export type NormalizationAst = NormalizationAstNode[];
114
100
 
115
101
  export type NormalizationScalarField = {
116
- kind: "Scalar";
102
+ kind: 'Scalar';
117
103
  fieldName: string;
118
104
  arguments: Arguments | null;
119
105
  };
120
106
 
121
107
  export type NormalizationLinkedField = {
122
- kind: "Linked";
108
+ kind: 'Linked';
123
109
  fieldName: string;
124
110
  arguments: Arguments | null;
125
111
  selections: NormalizationAst;
@@ -127,7 +113,7 @@ export type NormalizationLinkedField = {
127
113
 
128
114
  // This is more like an entrypoint, but one specifically for a refetch query/mutation
129
115
  export type RefetchQueryArtifact = {
130
- kind: "RefetchQuery";
116
+ kind: 'RefetchQuery';
131
117
  queryText: string;
132
118
  normalizationAst: NormalizationAst;
133
119
  };
@@ -143,51 +129,33 @@ export type Argument = [ArgumentName, ArgumentValue];
143
129
  export type ArgumentName = string;
144
130
  export type ArgumentValue =
145
131
  | {
146
- kind: "Variable";
132
+ kind: 'Variable';
147
133
  name: string;
148
134
  }
149
135
  | {
150
- kind: "Literal";
136
+ kind: 'Literal';
151
137
  value: any;
152
138
  };
153
139
 
154
- export type FragmentReference<
155
- TReadFromStore extends Object,
156
- TResolverProps,
157
- TResolverResult
158
- > = {
159
- kind: "FragmentReference";
160
- readerArtifact: ReaderArtifact<
161
- TReadFromStore,
162
- TResolverProps,
163
- TResolverResult
164
- >;
140
+ export type FragmentReference<TReadFromStore extends Object, TResolverProps, TResolverResult> = {
141
+ kind: 'FragmentReference';
142
+ readerArtifact: ReaderArtifact<TReadFromStore, TResolverProps, TResolverResult>;
165
143
  root: DataId;
166
144
  variables: { [index: string]: string } | null;
167
145
  // TODO: We should instead have ReaderAst<TResolverProps>
168
146
  nestedRefetchQueries: RefetchQueryArtifactWrapper[];
169
147
  };
170
148
 
171
- function assertIsEntrypoint<
172
- TReadFromStore extends Object,
173
- TResolverProps,
174
- TResolverResult
175
- >(
176
- value:
177
- | IsographEntrypoint<TReadFromStore, TResolverProps, TResolverResult>
178
- | typeof iso
179
- ): asserts value is IsographEntrypoint<
180
- TReadFromStore,
181
- TResolverProps,
182
- TResolverResult
183
- > {
184
- if (typeof value === "function") throw new Error("Not a string");
149
+ function assertIsEntrypoint<TReadFromStore extends Object, TResolverProps, TResolverResult>(
150
+ value: IsographEntrypoint<TReadFromStore, TResolverProps, TResolverResult> | typeof iso,
151
+ ): asserts value is IsographEntrypoint<TReadFromStore, TResolverProps, TResolverResult> {
152
+ if (typeof value === 'function') throw new Error('Not a string');
185
153
  }
186
154
 
187
- export function iso<TResolverParameter, TResolverReturn = TResolverParameter>(
188
- _queryText: TemplateStringsArray
189
- ): (
190
- x: (param: TResolverParameter) => TResolverReturn
155
+ export function iso<TResolverParameter>(
156
+ _queryText: TemplateStringsArray,
157
+ ): <TResolverReturn>(
158
+ x: (param: TResolverParameter) => TResolverReturn,
191
159
  ) => (param: TResolverParameter) => TResolverReturn {
192
160
  // The name `identity` here is a bit of a double entendre.
193
161
  // First, it is the identity function, constrained to operate
@@ -197,44 +165,49 @@ export function iso<TResolverParameter, TResolverReturn = TResolverParameter>(
197
165
  // is the identity function. At that point, the types
198
166
  // TResolverParameter and TResolverReturn must be identical.
199
167
 
200
- return function identity(
201
- x: (param: TResolverParameter) => TResolverReturn
168
+ return function identity<TResolverReturn>(
169
+ x: (param: TResolverParameter) => TResolverReturn,
202
170
  ): (param: TResolverParameter) => TResolverReturn {
203
171
  return x;
204
172
  };
205
173
  }
206
174
 
207
- export function useLazyReference<
208
- TReadFromStore extends Object,
209
- TResolverProps,
210
- TResolverResult
211
- >(
175
+ type ExtractTReadFromStore<Type> = Type extends IsographEntrypoint<infer X, any, any> ? X : never;
176
+ type ExtractResolverProps<Type> = Type extends IsographEntrypoint<any, infer X, any> ? X : never;
177
+ type ExtractResolverResult<Type> = Type extends IsographEntrypoint<any, any, infer X> ? X : never;
178
+ // Note: we cannot write TEntrypoint extends IsographEntrypoint<any, any, any>, or else
179
+ // if we do not explicitly pass a type, the read out type will be any.
180
+ // We cannot write TEntrypoint extends IsographEntrypoint<never, never, never>, or else
181
+ // any actual Entrypoint we pass will not be valid.
182
+ export function useLazyReference<TEntrypoint>(
212
183
  entrypoint:
213
- | IsographEntrypoint<TReadFromStore, TResolverProps, TResolverResult>
214
- | typeof iso,
215
- variables: object
184
+ | TEntrypoint
185
+ // Temporarily, we need to allow useLazyReference to take the result of calling
186
+ // iso`...`. At runtime, we confirm that the passed-in `iso` literal is actually
187
+ // an entrypoint.
188
+ | ((_: any) => any),
189
+ variables: object,
216
190
  ): {
217
191
  queryReference: FragmentReference<
218
- TReadFromStore,
219
- TResolverProps,
220
- TResolverResult
192
+ ExtractTReadFromStore<TEntrypoint>,
193
+ ExtractResolverProps<TEntrypoint>,
194
+ ExtractResolverResult<TEntrypoint>
221
195
  >;
222
196
  } {
223
197
  assertIsEntrypoint(entrypoint);
224
198
  // Typechecking fails here... TODO investigate
225
- const cache = getOrCreateCacheForArtifact<TResolverResult>(
199
+ const cache = getOrCreateCacheForArtifact<ExtractResolverResult<TEntrypoint>>(
226
200
  entrypoint,
227
- variables
201
+ variables,
228
202
  );
229
203
 
230
204
  // TODO add comment explaining why we never use this value
231
205
  // @ts-ignore
232
- const data =
233
- useLazyDisposableState<PromiseWrapper<TResolverResult>>(cache).state;
206
+ const data = useLazyDisposableState<PromiseWrapper<TResolverResult>>(cache).state;
234
207
 
235
208
  return {
236
209
  queryReference: {
237
- kind: "FragmentReference",
210
+ kind: 'FragmentReference',
238
211
  readerArtifact: entrypoint.readerArtifact,
239
212
  root: ROOT_ID,
240
213
  variables,
@@ -243,57 +216,49 @@ export function useLazyReference<
243
216
  };
244
217
  }
245
218
 
246
- export function read<
247
- TReadFromStore extends Object,
248
- TResolverProps,
249
- TResolverResult
250
- >(
251
- fragmentReference: FragmentReference<
252
- TReadFromStore,
253
- TResolverProps,
254
- TResolverResult
255
- >
219
+ export function read<TReadFromStore extends Object, TResolverProps, TResolverResult>(
220
+ fragmentReference: FragmentReference<TReadFromStore, TResolverProps, TResolverResult>,
256
221
  ): TResolverResult {
257
222
  const variant = fragmentReference.readerArtifact.variant;
258
- if (variant.kind === "Eager") {
223
+ if (variant.kind === 'Eager') {
259
224
  const data = readData(
260
225
  fragmentReference.readerArtifact.readerAst,
261
226
  fragmentReference.root,
262
227
  fragmentReference.variables ?? {},
263
- fragmentReference.nestedRefetchQueries
228
+ fragmentReference.nestedRefetchQueries,
264
229
  );
265
- if (data.kind === "MissingData") {
230
+ if (data.kind === 'MissingData') {
266
231
  throw onNextChange();
267
232
  } else {
268
233
  return fragmentReference.readerArtifact.resolver(data.data);
269
234
  }
270
- } else if (variant.kind === "Component") {
235
+ } else if (variant.kind === 'Component') {
271
236
  // @ts-ignore
272
237
  return getOrCreateCachedComponent(
273
238
  fragmentReference.root,
274
239
  variant.componentName,
275
240
  fragmentReference.readerArtifact,
276
241
  fragmentReference.variables ?? {},
277
- fragmentReference.nestedRefetchQueries
242
+ fragmentReference.nestedRefetchQueries,
278
243
  );
279
244
  }
280
245
  // Why can't Typescript realize that this is unreachable??
281
- throw new Error("This is unreachable");
246
+ throw new Error('This is unreachable');
282
247
  }
283
248
 
284
249
  export function readButDoNotEvaluate<TReadFromStore extends Object>(
285
- reference: FragmentReference<TReadFromStore, unknown, unknown>
250
+ reference: FragmentReference<TReadFromStore, unknown, unknown>,
286
251
  ): TReadFromStore {
287
252
  const response = readData(
288
253
  reference.readerArtifact.readerAst,
289
254
  reference.root,
290
255
  reference.variables ?? {},
291
- reference.nestedRefetchQueries
256
+ reference.nestedRefetchQueries,
292
257
  );
293
- if (typeof window !== "undefined" && window.__LOG) {
294
- console.log("done reading", { response });
258
+ if (typeof window !== 'undefined' && window.__LOG) {
259
+ console.log('done reading', { response });
295
260
  }
296
- if (response.kind === "MissingData") {
261
+ if (response.kind === 'MissingData') {
297
262
  throw onNextChange();
298
263
  } else {
299
264
  return response.data;
@@ -302,11 +267,11 @@ export function readButDoNotEvaluate<TReadFromStore extends Object>(
302
267
 
303
268
  type ReadDataResult<TReadFromStore> =
304
269
  | {
305
- kind: "Success";
270
+ kind: 'Success';
306
271
  data: TReadFromStore;
307
272
  }
308
273
  | {
309
- kind: "MissingData";
274
+ kind: 'MissingData';
310
275
  reason: string;
311
276
  nestedReason?: ReadDataResult<unknown>;
312
277
  };
@@ -315,36 +280,36 @@ function readData<TReadFromStore>(
315
280
  ast: ReaderAst<TReadFromStore>,
316
281
  root: DataId,
317
282
  variables: { [index: string]: string },
318
- nestedRefetchQueries: RefetchQueryArtifactWrapper[]
283
+ nestedRefetchQueries: RefetchQueryArtifactWrapper[],
319
284
  ): ReadDataResult<TReadFromStore> {
320
285
  let storeRecord = getStore()[root];
321
286
  if (storeRecord === undefined) {
322
- return { kind: "MissingData", reason: "No record for root " + root };
287
+ return { kind: 'MissingData', reason: 'No record for root ' + root };
323
288
  }
324
289
 
325
290
  if (storeRecord === null) {
326
- return { kind: "Success", data: null as any };
291
+ return { kind: 'Success', data: null as any };
327
292
  }
328
293
 
329
294
  let target: { [index: string]: any } = {};
330
295
 
331
296
  for (const field of ast) {
332
297
  switch (field.kind) {
333
- case "Scalar": {
298
+ case 'Scalar': {
334
299
  const storeRecordName = getParentRecordKey(field, variables);
335
300
  const value = storeRecord[storeRecordName];
336
301
  // TODO consider making scalars into discriminated unions. This probably has
337
302
  // to happen for when we handle errors.
338
303
  if (value === undefined) {
339
304
  return {
340
- kind: "MissingData",
341
- reason: "No value for " + storeRecordName + " on root " + root,
305
+ kind: 'MissingData',
306
+ reason: 'No value for ' + storeRecordName + ' on root ' + root,
342
307
  };
343
308
  }
344
309
  target[field.alias ?? field.fieldName] = value;
345
310
  break;
346
311
  }
347
- case "Linked": {
312
+ case 'Linked': {
348
313
  const storeRecordName = getParentRecordKey(field, variables);
349
314
  const value = storeRecord[storeRecordName];
350
315
  if (Array.isArray(value)) {
@@ -353,34 +318,29 @@ function readData<TReadFromStore>(
353
318
  const link = assertLink(item);
354
319
  if (link === undefined) {
355
320
  return {
356
- kind: "MissingData",
321
+ kind: 'MissingData',
357
322
  reason:
358
- "No link for " +
323
+ 'No link for ' +
359
324
  storeRecordName +
360
- " on root " +
325
+ ' on root ' +
361
326
  root +
362
- ". Link is " +
327
+ '. Link is ' +
363
328
  JSON.stringify(item),
364
329
  };
365
330
  } else if (link === null) {
366
331
  results.push(null);
367
332
  continue;
368
333
  }
369
- const result = readData(
370
- field.selections,
371
- link.__link,
372
- variables,
373
- nestedRefetchQueries
374
- );
375
- if (result.kind === "MissingData") {
334
+ const result = readData(field.selections, link.__link, variables, nestedRefetchQueries);
335
+ if (result.kind === 'MissingData') {
376
336
  return {
377
- kind: "MissingData",
337
+ kind: 'MissingData',
378
338
  reason:
379
- "Missing data for " +
339
+ 'Missing data for ' +
380
340
  storeRecordName +
381
- " on root " +
341
+ ' on root ' +
382
342
  root +
383
- ". Link is " +
343
+ '. Link is ' +
384
344
  JSON.stringify(item),
385
345
  nestedReason: result,
386
346
  };
@@ -398,17 +358,17 @@ function readData<TReadFromStore>(
398
358
  root,
399
359
  field.fieldName,
400
360
  field.arguments,
401
- variables
361
+ variables,
402
362
  );
403
363
  if (altLink === undefined) {
404
364
  return {
405
- kind: "MissingData",
365
+ kind: 'MissingData',
406
366
  reason:
407
- "No link for " +
367
+ 'No link for ' +
408
368
  storeRecordName +
409
- " on root " +
369
+ ' on root ' +
410
370
  root +
411
- ". Link is " +
371
+ '. Link is ' +
412
372
  JSON.stringify(value),
413
373
  };
414
374
  } else {
@@ -419,81 +379,73 @@ function readData<TReadFromStore>(
419
379
  break;
420
380
  }
421
381
  const targetId = link.__link;
422
- const data = readData(
423
- field.selections,
424
- targetId,
425
- variables,
426
- nestedRefetchQueries
427
- );
428
- if (data.kind === "MissingData") {
382
+ const data = readData(field.selections, targetId, variables, nestedRefetchQueries);
383
+ if (data.kind === 'MissingData') {
429
384
  return {
430
- kind: "MissingData",
431
- reason: "Missing data for " + storeRecordName + " on root " + root,
385
+ kind: 'MissingData',
386
+ reason: 'Missing data for ' + storeRecordName + ' on root ' + root,
432
387
  nestedReason: data,
433
388
  };
434
389
  }
435
390
  target[field.alias ?? field.fieldName] = data.data;
436
391
  break;
437
392
  }
438
- case "RefetchField": {
393
+ case 'RefetchField': {
439
394
  const data = readData(
440
395
  field.readerArtifact.readerAst,
441
396
  root,
442
397
  variables,
443
398
  // Refetch fields just read the id, and don't need refetch query artifacts
444
- []
399
+ [],
445
400
  );
446
- if (typeof window !== "undefined" && window.__LOG) {
447
- console.log("refetch field data", data, field);
401
+ if (typeof window !== 'undefined' && window.__LOG) {
402
+ console.log('refetch field data', data, field);
448
403
  }
449
- if (data.kind === "MissingData") {
404
+ if (data.kind === 'MissingData') {
450
405
  return {
451
- kind: "MissingData",
452
- reason: "Missing data for " + field.alias + " on root " + root,
406
+ kind: 'MissingData',
407
+ reason: 'Missing data for ' + field.alias + ' on root ' + root,
453
408
  nestedReason: data,
454
409
  };
455
410
  } else {
456
411
  const refetchQueryIndex = field.refetchQuery;
457
412
  if (refetchQueryIndex == null) {
458
- throw new Error("refetchQuery is null in RefetchField");
413
+ throw new Error('refetchQuery is null in RefetchField');
459
414
  }
460
415
  const refetchQuery = nestedRefetchQueries[refetchQueryIndex];
461
416
  const refetchQueryArtifact = refetchQuery.artifact;
462
417
  const allowedVariables = refetchQuery.allowedVariables;
463
418
 
464
- target[field.alias] = field.readerArtifact.resolver(
465
- refetchQueryArtifact,
466
- {
467
- ...data.data,
468
- // TODO continue from here
469
- // variables need to be filtered for what we need just for the refetch query
470
- ...filterVariables(variables, allowedVariables),
471
- }
472
- );
419
+ target[field.alias] = field.readerArtifact.resolver(refetchQueryArtifact, {
420
+ ...data.data,
421
+ // TODO continue from here
422
+ // variables need to be filtered for what we need just for the refetch query
423
+ ...filterVariables(variables, allowedVariables),
424
+ });
473
425
  }
474
426
  break;
475
427
  }
476
- case "MutationField": {
428
+ case 'MutationField': {
477
429
  const data = readData(
478
430
  field.readerArtifact.readerAst,
479
431
  root,
480
432
  variables,
481
433
  // Refetch fields just read the id, and don't need refetch query artifacts
482
- []
434
+ [],
483
435
  );
484
- if (typeof window !== "undefined" && window.__LOG) {
485
- console.log("refetch field data", data, field);
436
+ if (typeof window !== 'undefined' && window.__LOG) {
437
+ console.log('refetch field data', data, field);
486
438
  }
487
- if (data.kind === "MissingData") {
439
+ if (data.kind === 'MissingData') {
488
440
  return {
489
- kind: "MissingData",
490
- reason: "Missing data for " + field.alias + " on root " + root,
441
+ kind: 'MissingData',
442
+ reason: 'Missing data for ' + field.alias + ' on root ' + root,
491
443
  nestedReason: data,
492
444
  };
493
445
  } else {
494
446
  const refetchQueryIndex = field.refetchQuery;
495
447
  if (refetchQueryIndex == null) {
496
- throw new Error("refetchQuery is null in MutationField");
448
+ throw new Error('refetchQuery is null in MutationField');
497
449
  }
498
450
  const refetchQuery = nestedRefetchQueries[refetchQueryIndex];
499
451
  const refetchQueryArtifact = refetchQuery.artifact;
@@ -502,48 +454,48 @@ function readData<TReadFromStore>(
502
454
  target[field.alias] = field.readerArtifact.resolver(
503
455
  refetchQueryArtifact,
504
456
  data.data,
505
- filterVariables(variables, allowedVariables)
457
+ filterVariables(variables, allowedVariables),
506
458
  );
507
459
  }
508
460
  break;
509
461
  }
510
- case "Resolver": {
462
+ case 'Resolver': {
511
463
  const usedRefetchQueries = field.usedRefetchQueries;
512
464
  const resolverRefetchQueries = usedRefetchQueries.map(
513
- (index) => nestedRefetchQueries[index]
465
+ (index) => nestedRefetchQueries[index],
514
466
  );
515
467
 
516
468
  const variant = field.readerArtifact.variant;
517
- if (variant.kind === "Eager") {
469
+ if (variant.kind === 'Eager') {
518
470
  const data = readData(
519
471
  field.readerArtifact.readerAst,
520
472
  root,
521
473
  variables,
522
- resolverRefetchQueries
474
+ resolverRefetchQueries,
523
475
  );
524
- if (data.kind === "MissingData") {
476
+ if (data.kind === 'MissingData') {
525
477
  return {
526
- kind: "MissingData",
527
- reason: "Missing data for " + field.alias + " on root " + root,
478
+ kind: 'MissingData',
479
+ reason: 'Missing data for ' + field.alias + ' on root ' + root,
528
480
  nestedReason: data,
529
481
  };
530
482
  } else {
531
483
  target[field.alias] = field.readerArtifact.resolver(data.data);
532
484
  }
533
- } else if (variant.kind === "Component") {
485
+ } else if (variant.kind === 'Component') {
534
486
  target[field.alias] = getOrCreateCachedComponent(
535
487
  root,
536
488
  variant.componentName,
537
489
  field.readerArtifact,
538
490
  variables,
539
- resolverRefetchQueries
491
+ resolverRefetchQueries,
540
492
  );
541
493
  }
542
494
  break;
543
495
  }
544
496
  }
545
497
  }
546
- return { kind: "Success", data: target as any };
498
+ return { kind: 'Success', data: target as any };
547
499
  }
548
500
 
549
501
  let customMissingFieldHandler: typeof defaultMissingFieldHandler | null = null;
@@ -553,24 +505,12 @@ function missingFieldHandler(
553
505
  root: DataId,
554
506
  fieldName: string,
555
507
  arguments_: { [index: string]: any } | null,
556
- variables: { [index: string]: any } | null
508
+ variables: { [index: string]: any } | null,
557
509
  ): Link | undefined {
558
510
  if (customMissingFieldHandler != null) {
559
- return customMissingFieldHandler(
560
- storeRecord,
561
- root,
562
- fieldName,
563
- arguments_,
564
- variables
565
- );
511
+ return customMissingFieldHandler(storeRecord, root, fieldName, arguments_, variables);
566
512
  } else {
567
- return defaultMissingFieldHandler(
568
- storeRecord,
569
- root,
570
- fieldName,
571
- arguments_,
572
- variables
573
- );
513
+ return defaultMissingFieldHandler(storeRecord, root, fieldName, arguments_, variables);
574
514
  }
575
515
  }
576
516
 
@@ -579,10 +519,10 @@ export function defaultMissingFieldHandler(
579
519
  root: DataId,
580
520
  fieldName: string,
581
521
  arguments_: { [index: string]: any } | null,
582
- variables: { [index: string]: any } | null
522
+ variables: { [index: string]: any } | null,
583
523
  ): Link | undefined {
584
- if (fieldName === "node" || fieldName === "user") {
585
- const variable = arguments_?.["id"];
524
+ if (fieldName === 'node' || fieldName === 'user') {
525
+ const variable = arguments_?.['id'];
586
526
  const value = variables?.[variable];
587
527
 
588
528
  // TODO can we handle explicit nulls here too? Probably, after wrapping in objects
@@ -592,23 +532,21 @@ export function defaultMissingFieldHandler(
592
532
  }
593
533
  }
594
534
 
595
- export function setMissingFieldHandler(
596
- handler: typeof defaultMissingFieldHandler
597
- ) {
535
+ export function setMissingFieldHandler(handler: typeof defaultMissingFieldHandler) {
598
536
  customMissingFieldHandler = handler;
599
537
  }
600
538
 
601
539
  function assertLink(link: DataTypeValue): Link | undefined | null {
602
540
  if (Array.isArray(link)) {
603
- throw new Error("Unexpected array");
541
+ throw new Error('Unexpected array');
604
542
  }
605
- if (typeof link === "object") {
543
+ if (typeof link === 'object') {
606
544
  return link;
607
545
  }
608
546
  if (link === undefined) {
609
547
  return undefined;
610
548
  }
611
- throw new Error("Invalid link");
549
+ throw new Error('Invalid link');
612
550
  }
613
551
 
614
552
  export type IsographComponentProps<TDataType, TOtherProps = Object> = {
@@ -617,7 +555,7 @@ export type IsographComponentProps<TDataType, TOtherProps = Object> = {
617
555
 
618
556
  function filterVariables(
619
557
  variables: { [index: string]: string },
620
- allowedVariables: string[]
558
+ allowedVariables: string[],
621
559
  ): { [index: string]: string } {
622
560
  const result: { [index: string]: string } = {};
623
561
  for (const key of allowedVariables) {