@isograph/react 0.0.0-main-55364d41 → 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
  };
@@ -139,48 +125,37 @@ export type RefetchQueryArtifactWrapper = {
139
125
  };
140
126
 
141
127
  export type Arguments = Argument[];
142
- export type Argument = {
143
- argumentName: string;
144
- variableName: string;
145
- };
128
+ export type Argument = [ArgumentName, ArgumentValue];
129
+ export type ArgumentName = string;
130
+ export type ArgumentValue =
131
+ | {
132
+ kind: 'Variable';
133
+ name: string;
134
+ }
135
+ | {
136
+ kind: 'Literal';
137
+ value: any;
138
+ };
146
139
 
147
- export type FragmentReference<
148
- TReadFromStore extends Object,
149
- TResolverProps,
150
- TResolverResult
151
- > = {
152
- kind: "FragmentReference";
153
- readerArtifact: ReaderArtifact<
154
- TReadFromStore,
155
- TResolverProps,
156
- TResolverResult
157
- >;
140
+ export type FragmentReference<TReadFromStore extends Object, TResolverProps, TResolverResult> = {
141
+ kind: 'FragmentReference';
142
+ readerArtifact: ReaderArtifact<TReadFromStore, TResolverProps, TResolverResult>;
158
143
  root: DataId;
159
144
  variables: { [index: string]: string } | null;
160
145
  // TODO: We should instead have ReaderAst<TResolverProps>
161
146
  nestedRefetchQueries: RefetchQueryArtifactWrapper[];
162
147
  };
163
148
 
164
- function assertIsEntrypoint<
165
- TReadFromStore extends Object,
166
- TResolverProps,
167
- TResolverResult
168
- >(
169
- value:
170
- | IsographEntrypoint<TReadFromStore, TResolverProps, TResolverResult>
171
- | typeof iso
172
- ): asserts value is IsographEntrypoint<
173
- TReadFromStore,
174
- TResolverProps,
175
- TResolverResult
176
- > {
177
- 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');
178
153
  }
179
154
 
180
- export function iso<TResolverParameter, TResolverReturn = TResolverParameter>(
181
- _queryText: TemplateStringsArray
182
- ): (
183
- x: (param: TResolverParameter) => TResolverReturn
155
+ export function iso<TResolverParameter>(
156
+ _queryText: TemplateStringsArray,
157
+ ): <TResolverReturn>(
158
+ x: (param: TResolverParameter) => TResolverReturn,
184
159
  ) => (param: TResolverParameter) => TResolverReturn {
185
160
  // The name `identity` here is a bit of a double entendre.
186
161
  // First, it is the identity function, constrained to operate
@@ -190,44 +165,49 @@ export function iso<TResolverParameter, TResolverReturn = TResolverParameter>(
190
165
  // is the identity function. At that point, the types
191
166
  // TResolverParameter and TResolverReturn must be identical.
192
167
 
193
- return function identity(
194
- x: (param: TResolverParameter) => TResolverReturn
168
+ return function identity<TResolverReturn>(
169
+ x: (param: TResolverParameter) => TResolverReturn,
195
170
  ): (param: TResolverParameter) => TResolverReturn {
196
171
  return x;
197
172
  };
198
173
  }
199
174
 
200
- export function useLazyReference<
201
- TReadFromStore extends Object,
202
- TResolverProps,
203
- TResolverResult
204
- >(
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>(
205
183
  entrypoint:
206
- | IsographEntrypoint<TReadFromStore, TResolverProps, TResolverResult>
207
- | typeof iso,
208
- 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,
209
190
  ): {
210
191
  queryReference: FragmentReference<
211
- TReadFromStore,
212
- TResolverProps,
213
- TResolverResult
192
+ ExtractTReadFromStore<TEntrypoint>,
193
+ ExtractResolverProps<TEntrypoint>,
194
+ ExtractResolverResult<TEntrypoint>
214
195
  >;
215
196
  } {
216
197
  assertIsEntrypoint(entrypoint);
217
198
  // Typechecking fails here... TODO investigate
218
- const cache = getOrCreateCacheForArtifact<TResolverResult>(
199
+ const cache = getOrCreateCacheForArtifact<ExtractResolverResult<TEntrypoint>>(
219
200
  entrypoint,
220
- variables
201
+ variables,
221
202
  );
222
203
 
223
204
  // TODO add comment explaining why we never use this value
224
205
  // @ts-ignore
225
- const data =
226
- useLazyDisposableState<PromiseWrapper<TResolverResult>>(cache).state;
206
+ const data = useLazyDisposableState<PromiseWrapper<TResolverResult>>(cache).state;
227
207
 
228
208
  return {
229
209
  queryReference: {
230
- kind: "FragmentReference",
210
+ kind: 'FragmentReference',
231
211
  readerArtifact: entrypoint.readerArtifact,
232
212
  root: ROOT_ID,
233
213
  variables,
@@ -236,57 +216,49 @@ export function useLazyReference<
236
216
  };
237
217
  }
238
218
 
239
- export function read<
240
- TReadFromStore extends Object,
241
- TResolverProps,
242
- TResolverResult
243
- >(
244
- fragmentReference: FragmentReference<
245
- TReadFromStore,
246
- TResolverProps,
247
- TResolverResult
248
- >
219
+ export function read<TReadFromStore extends Object, TResolverProps, TResolverResult>(
220
+ fragmentReference: FragmentReference<TReadFromStore, TResolverProps, TResolverResult>,
249
221
  ): TResolverResult {
250
222
  const variant = fragmentReference.readerArtifact.variant;
251
- if (variant.kind === "Eager") {
223
+ if (variant.kind === 'Eager') {
252
224
  const data = readData(
253
225
  fragmentReference.readerArtifact.readerAst,
254
226
  fragmentReference.root,
255
227
  fragmentReference.variables ?? {},
256
- fragmentReference.nestedRefetchQueries
228
+ fragmentReference.nestedRefetchQueries,
257
229
  );
258
- if (data.kind === "MissingData") {
230
+ if (data.kind === 'MissingData') {
259
231
  throw onNextChange();
260
232
  } else {
261
233
  return fragmentReference.readerArtifact.resolver(data.data);
262
234
  }
263
- } else if (variant.kind === "Component") {
235
+ } else if (variant.kind === 'Component') {
264
236
  // @ts-ignore
265
237
  return getOrCreateCachedComponent(
266
238
  fragmentReference.root,
267
239
  variant.componentName,
268
240
  fragmentReference.readerArtifact,
269
241
  fragmentReference.variables ?? {},
270
- fragmentReference.nestedRefetchQueries
242
+ fragmentReference.nestedRefetchQueries,
271
243
  );
272
244
  }
273
245
  // Why can't Typescript realize that this is unreachable??
274
- throw new Error("This is unreachable");
246
+ throw new Error('This is unreachable');
275
247
  }
276
248
 
277
249
  export function readButDoNotEvaluate<TReadFromStore extends Object>(
278
- reference: FragmentReference<TReadFromStore, unknown, unknown>
250
+ reference: FragmentReference<TReadFromStore, unknown, unknown>,
279
251
  ): TReadFromStore {
280
252
  const response = readData(
281
253
  reference.readerArtifact.readerAst,
282
254
  reference.root,
283
255
  reference.variables ?? {},
284
- reference.nestedRefetchQueries
256
+ reference.nestedRefetchQueries,
285
257
  );
286
- if (typeof window !== "undefined" && window.__LOG) {
287
- console.log("done reading", { response });
258
+ if (typeof window !== 'undefined' && window.__LOG) {
259
+ console.log('done reading', { response });
288
260
  }
289
- if (response.kind === "MissingData") {
261
+ if (response.kind === 'MissingData') {
290
262
  throw onNextChange();
291
263
  } else {
292
264
  return response.data;
@@ -295,11 +267,11 @@ export function readButDoNotEvaluate<TReadFromStore extends Object>(
295
267
 
296
268
  type ReadDataResult<TReadFromStore> =
297
269
  | {
298
- kind: "Success";
270
+ kind: 'Success';
299
271
  data: TReadFromStore;
300
272
  }
301
273
  | {
302
- kind: "MissingData";
274
+ kind: 'MissingData';
303
275
  reason: string;
304
276
  nestedReason?: ReadDataResult<unknown>;
305
277
  };
@@ -308,36 +280,36 @@ function readData<TReadFromStore>(
308
280
  ast: ReaderAst<TReadFromStore>,
309
281
  root: DataId,
310
282
  variables: { [index: string]: string },
311
- nestedRefetchQueries: RefetchQueryArtifactWrapper[]
283
+ nestedRefetchQueries: RefetchQueryArtifactWrapper[],
312
284
  ): ReadDataResult<TReadFromStore> {
313
285
  let storeRecord = getStore()[root];
314
286
  if (storeRecord === undefined) {
315
- return { kind: "MissingData", reason: "No record for root " + root };
287
+ return { kind: 'MissingData', reason: 'No record for root ' + root };
316
288
  }
317
289
 
318
290
  if (storeRecord === null) {
319
- return { kind: "Success", data: null as any };
291
+ return { kind: 'Success', data: null as any };
320
292
  }
321
293
 
322
294
  let target: { [index: string]: any } = {};
323
295
 
324
296
  for (const field of ast) {
325
297
  switch (field.kind) {
326
- case "Scalar": {
298
+ case 'Scalar': {
327
299
  const storeRecordName = getParentRecordKey(field, variables);
328
300
  const value = storeRecord[storeRecordName];
329
301
  // TODO consider making scalars into discriminated unions. This probably has
330
302
  // to happen for when we handle errors.
331
303
  if (value === undefined) {
332
304
  return {
333
- kind: "MissingData",
334
- reason: "No value for " + storeRecordName + " on root " + root,
305
+ kind: 'MissingData',
306
+ reason: 'No value for ' + storeRecordName + ' on root ' + root,
335
307
  };
336
308
  }
337
309
  target[field.alias ?? field.fieldName] = value;
338
310
  break;
339
311
  }
340
- case "Linked": {
312
+ case 'Linked': {
341
313
  const storeRecordName = getParentRecordKey(field, variables);
342
314
  const value = storeRecord[storeRecordName];
343
315
  if (Array.isArray(value)) {
@@ -346,34 +318,29 @@ function readData<TReadFromStore>(
346
318
  const link = assertLink(item);
347
319
  if (link === undefined) {
348
320
  return {
349
- kind: "MissingData",
321
+ kind: 'MissingData',
350
322
  reason:
351
- "No link for " +
323
+ 'No link for ' +
352
324
  storeRecordName +
353
- " on root " +
325
+ ' on root ' +
354
326
  root +
355
- ". Link is " +
327
+ '. Link is ' +
356
328
  JSON.stringify(item),
357
329
  };
358
330
  } else if (link === null) {
359
331
  results.push(null);
360
332
  continue;
361
333
  }
362
- const result = readData(
363
- field.selections,
364
- link.__link,
365
- variables,
366
- nestedRefetchQueries
367
- );
368
- if (result.kind === "MissingData") {
334
+ const result = readData(field.selections, link.__link, variables, nestedRefetchQueries);
335
+ if (result.kind === 'MissingData') {
369
336
  return {
370
- kind: "MissingData",
337
+ kind: 'MissingData',
371
338
  reason:
372
- "Missing data for " +
339
+ 'Missing data for ' +
373
340
  storeRecordName +
374
- " on root " +
341
+ ' on root ' +
375
342
  root +
376
- ". Link is " +
343
+ '. Link is ' +
377
344
  JSON.stringify(item),
378
345
  nestedReason: result,
379
346
  };
@@ -391,17 +358,17 @@ function readData<TReadFromStore>(
391
358
  root,
392
359
  field.fieldName,
393
360
  field.arguments,
394
- variables
361
+ variables,
395
362
  );
396
363
  if (altLink === undefined) {
397
364
  return {
398
- kind: "MissingData",
365
+ kind: 'MissingData',
399
366
  reason:
400
- "No link for " +
367
+ 'No link for ' +
401
368
  storeRecordName +
402
- " on root " +
369
+ ' on root ' +
403
370
  root +
404
- ". Link is " +
371
+ '. Link is ' +
405
372
  JSON.stringify(value),
406
373
  };
407
374
  } else {
@@ -412,81 +379,73 @@ function readData<TReadFromStore>(
412
379
  break;
413
380
  }
414
381
  const targetId = link.__link;
415
- const data = readData(
416
- field.selections,
417
- targetId,
418
- variables,
419
- nestedRefetchQueries
420
- );
421
- if (data.kind === "MissingData") {
382
+ const data = readData(field.selections, targetId, variables, nestedRefetchQueries);
383
+ if (data.kind === 'MissingData') {
422
384
  return {
423
- kind: "MissingData",
424
- reason: "Missing data for " + storeRecordName + " on root " + root,
385
+ kind: 'MissingData',
386
+ reason: 'Missing data for ' + storeRecordName + ' on root ' + root,
425
387
  nestedReason: data,
426
388
  };
427
389
  }
428
390
  target[field.alias ?? field.fieldName] = data.data;
429
391
  break;
430
392
  }
431
- case "RefetchField": {
393
+ case 'RefetchField': {
432
394
  const data = readData(
433
395
  field.readerArtifact.readerAst,
434
396
  root,
435
397
  variables,
436
398
  // Refetch fields just read the id, and don't need refetch query artifacts
437
- []
399
+ [],
438
400
  );
439
- if (typeof window !== "undefined" && window.__LOG) {
440
- console.log("refetch field data", data, field);
401
+ if (typeof window !== 'undefined' && window.__LOG) {
402
+ console.log('refetch field data', data, field);
441
403
  }
442
- if (data.kind === "MissingData") {
404
+ if (data.kind === 'MissingData') {
443
405
  return {
444
- kind: "MissingData",
445
- reason: "Missing data for " + field.alias + " on root " + root,
406
+ kind: 'MissingData',
407
+ reason: 'Missing data for ' + field.alias + ' on root ' + root,
446
408
  nestedReason: data,
447
409
  };
448
410
  } else {
449
411
  const refetchQueryIndex = field.refetchQuery;
450
412
  if (refetchQueryIndex == null) {
451
- throw new Error("refetchQuery is null in RefetchField");
413
+ throw new Error('refetchQuery is null in RefetchField');
452
414
  }
453
415
  const refetchQuery = nestedRefetchQueries[refetchQueryIndex];
454
416
  const refetchQueryArtifact = refetchQuery.artifact;
455
417
  const allowedVariables = refetchQuery.allowedVariables;
456
418
 
457
- target[field.alias] = field.readerArtifact.resolver(
458
- refetchQueryArtifact,
459
- {
460
- ...data.data,
461
- // TODO continue from here
462
- // variables need to be filtered for what we need just for the refetch query
463
- ...filterVariables(variables, allowedVariables),
464
- }
465
- );
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
+ });
466
425
  }
467
426
  break;
468
427
  }
469
- case "MutationField": {
428
+ case 'MutationField': {
470
429
  const data = readData(
471
430
  field.readerArtifact.readerAst,
472
431
  root,
473
432
  variables,
474
433
  // Refetch fields just read the id, and don't need refetch query artifacts
475
- []
434
+ [],
476
435
  );
477
- if (typeof window !== "undefined" && window.__LOG) {
478
- console.log("refetch field data", data, field);
436
+ if (typeof window !== 'undefined' && window.__LOG) {
437
+ console.log('refetch field data', data, field);
479
438
  }
480
- if (data.kind === "MissingData") {
439
+ if (data.kind === 'MissingData') {
481
440
  return {
482
- kind: "MissingData",
483
- reason: "Missing data for " + field.alias + " on root " + root,
441
+ kind: 'MissingData',
442
+ reason: 'Missing data for ' + field.alias + ' on root ' + root,
484
443
  nestedReason: data,
485
444
  };
486
445
  } else {
487
446
  const refetchQueryIndex = field.refetchQuery;
488
447
  if (refetchQueryIndex == null) {
489
- throw new Error("refetchQuery is null in MutationField");
448
+ throw new Error('refetchQuery is null in MutationField');
490
449
  }
491
450
  const refetchQuery = nestedRefetchQueries[refetchQueryIndex];
492
451
  const refetchQueryArtifact = refetchQuery.artifact;
@@ -495,48 +454,48 @@ function readData<TReadFromStore>(
495
454
  target[field.alias] = field.readerArtifact.resolver(
496
455
  refetchQueryArtifact,
497
456
  data.data,
498
- filterVariables(variables, allowedVariables)
457
+ filterVariables(variables, allowedVariables),
499
458
  );
500
459
  }
501
460
  break;
502
461
  }
503
- case "Resolver": {
462
+ case 'Resolver': {
504
463
  const usedRefetchQueries = field.usedRefetchQueries;
505
464
  const resolverRefetchQueries = usedRefetchQueries.map(
506
- (index) => nestedRefetchQueries[index]
465
+ (index) => nestedRefetchQueries[index],
507
466
  );
508
467
 
509
468
  const variant = field.readerArtifact.variant;
510
- if (variant.kind === "Eager") {
469
+ if (variant.kind === 'Eager') {
511
470
  const data = readData(
512
471
  field.readerArtifact.readerAst,
513
472
  root,
514
473
  variables,
515
- resolverRefetchQueries
474
+ resolverRefetchQueries,
516
475
  );
517
- if (data.kind === "MissingData") {
476
+ if (data.kind === 'MissingData') {
518
477
  return {
519
- kind: "MissingData",
520
- reason: "Missing data for " + field.alias + " on root " + root,
478
+ kind: 'MissingData',
479
+ reason: 'Missing data for ' + field.alias + ' on root ' + root,
521
480
  nestedReason: data,
522
481
  };
523
482
  } else {
524
483
  target[field.alias] = field.readerArtifact.resolver(data.data);
525
484
  }
526
- } else if (variant.kind === "Component") {
485
+ } else if (variant.kind === 'Component') {
527
486
  target[field.alias] = getOrCreateCachedComponent(
528
487
  root,
529
488
  variant.componentName,
530
489
  field.readerArtifact,
531
490
  variables,
532
- resolverRefetchQueries
491
+ resolverRefetchQueries,
533
492
  );
534
493
  }
535
494
  break;
536
495
  }
537
496
  }
538
497
  }
539
- return { kind: "Success", data: target as any };
498
+ return { kind: 'Success', data: target as any };
540
499
  }
541
500
 
542
501
  let customMissingFieldHandler: typeof defaultMissingFieldHandler | null = null;
@@ -546,24 +505,12 @@ function missingFieldHandler(
546
505
  root: DataId,
547
506
  fieldName: string,
548
507
  arguments_: { [index: string]: any } | null,
549
- variables: { [index: string]: any } | null
508
+ variables: { [index: string]: any } | null,
550
509
  ): Link | undefined {
551
510
  if (customMissingFieldHandler != null) {
552
- return customMissingFieldHandler(
553
- storeRecord,
554
- root,
555
- fieldName,
556
- arguments_,
557
- variables
558
- );
511
+ return customMissingFieldHandler(storeRecord, root, fieldName, arguments_, variables);
559
512
  } else {
560
- return defaultMissingFieldHandler(
561
- storeRecord,
562
- root,
563
- fieldName,
564
- arguments_,
565
- variables
566
- );
513
+ return defaultMissingFieldHandler(storeRecord, root, fieldName, arguments_, variables);
567
514
  }
568
515
  }
569
516
 
@@ -572,10 +519,10 @@ export function defaultMissingFieldHandler(
572
519
  root: DataId,
573
520
  fieldName: string,
574
521
  arguments_: { [index: string]: any } | null,
575
- variables: { [index: string]: any } | null
522
+ variables: { [index: string]: any } | null,
576
523
  ): Link | undefined {
577
- if (fieldName === "node" || fieldName === "user") {
578
- const variable = arguments_?.["id"];
524
+ if (fieldName === 'node' || fieldName === 'user') {
525
+ const variable = arguments_?.['id'];
579
526
  const value = variables?.[variable];
580
527
 
581
528
  // TODO can we handle explicit nulls here too? Probably, after wrapping in objects
@@ -585,23 +532,21 @@ export function defaultMissingFieldHandler(
585
532
  }
586
533
  }
587
534
 
588
- export function setMissingFieldHandler(
589
- handler: typeof defaultMissingFieldHandler
590
- ) {
535
+ export function setMissingFieldHandler(handler: typeof defaultMissingFieldHandler) {
591
536
  customMissingFieldHandler = handler;
592
537
  }
593
538
 
594
539
  function assertLink(link: DataTypeValue): Link | undefined | null {
595
540
  if (Array.isArray(link)) {
596
- throw new Error("Unexpected array");
541
+ throw new Error('Unexpected array');
597
542
  }
598
- if (typeof link === "object") {
543
+ if (typeof link === 'object') {
599
544
  return link;
600
545
  }
601
546
  if (link === undefined) {
602
547
  return undefined;
603
548
  }
604
- throw new Error("Invalid link");
549
+ throw new Error('Invalid link');
605
550
  }
606
551
 
607
552
  export type IsographComponentProps<TDataType, TOtherProps = Object> = {
@@ -610,7 +555,7 @@ export type IsographComponentProps<TDataType, TOtherProps = Object> = {
610
555
 
611
556
  function filterVariables(
612
557
  variables: { [index: string]: string },
613
- allowedVariables: string[]
558
+ allowedVariables: string[],
614
559
  ): { [index: string]: string } {
615
560
  const result: { [index: string]: string } = {};
616
561
  for (const key of allowedVariables) {