@isograph/react 0.0.0-main-0e6e4170 → 0.0.0-main-7faadacd

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.
@@ -1,4 +1,4 @@
1
1
 
2
- > @isograph/react@0.0.0-main-0e6e4170 compile-typescript /Users/runner/work/isograph/isograph/libs/isograph-react
2
+ > @isograph/react@0.0.0-main-7faadacd compile-typescript /Users/runner/work/isograph/isograph/libs/isograph-react
3
3
  > rm -rf dist/* && tsc -p tsconfig.pkg.json
4
4
 
@@ -1,24 +1,30 @@
1
1
  import { type EncounteredIds } from './cache';
2
- import { ExtractData, FragmentReference, type UnknownTReadFromStore } from './FragmentReference';
3
- import { IsographEnvironment, type Link } from './IsographEnvironment';
2
+ import { RefetchQueryNormalizationArtifactWrapper } from './entrypoint';
3
+ import { ExtractData, FragmentReference, Variables, type UnknownTReadFromStore } from './FragmentReference';
4
+ import { IsographEnvironment, type DataTypeValue, type Link, type StoreRecord } from './IsographEnvironment';
5
+ import { PromiseWrapper } from './PromiseWrapper';
6
+ import { ReaderAst, type ReaderImperativelyLoadedField, type ReaderLinkedField, type ReaderScalarField } from './reader';
4
7
  export type WithEncounteredRecords<T> = {
5
8
  readonly encounteredRecords: EncounteredIds;
6
9
  readonly item: ExtractData<T>;
7
10
  };
8
11
  export declare function readButDoNotEvaluate<TReadFromStore extends UnknownTReadFromStore>(environment: IsographEnvironment, fragmentReference: FragmentReference<TReadFromStore, unknown>, networkRequestOptions: NetworkRequestReaderOptions): WithEncounteredRecords<TReadFromStore>;
9
- export type ReadDataResult<TReadFromStore> = {
12
+ export type ReadDataResultSuccess<Data> = {
10
13
  readonly kind: 'Success';
11
- readonly data: ExtractData<TReadFromStore>;
12
- readonly encounteredRecords: EncounteredIds;
13
- } | {
14
+ readonly data: Data;
15
+ };
16
+ export type ReadDataResult<Data> = ReadDataResultSuccess<Data> | {
14
17
  readonly kind: 'MissingData';
15
18
  readonly reason: string;
16
19
  readonly nestedReason?: ReadDataResult<unknown>;
17
20
  readonly recordLink: Link;
18
21
  };
22
+ export declare function readScalarFieldData(field: ReaderScalarField, storeRecord: StoreRecord, root: Link, variables: Variables): ReadDataResult<string | number | boolean | Link | DataTypeValue[] | null>;
23
+ export declare function readLinkedFieldData(environment: IsographEnvironment, field: ReaderLinkedField, storeRecord: StoreRecord, root: Link, variables: Variables, networkRequest: PromiseWrapper<void, any>, readData: <TReadFromStore>(ast: ReaderAst<TReadFromStore>, root: Link) => ReadDataResult<object>): ReadDataResult<unknown>;
19
24
  export type NetworkRequestReaderOptions = {
20
25
  suspendIfInFlight: boolean;
21
26
  throwOnNetworkError: boolean;
22
27
  };
23
28
  export declare function getNetworkRequestOptionsWithDefaults(networkRequestOptions?: Partial<NetworkRequestReaderOptions> | void): NetworkRequestReaderOptions;
29
+ export declare function readImperativelyLoadedField(environment: IsographEnvironment, field: ReaderImperativelyLoadedField, root: Link, variables: Variables, nestedRefetchQueries: RefetchQueryNormalizationArtifactWrapper[], networkRequest: PromiseWrapper<void, any>, networkRequestOptions: NetworkRequestReaderOptions, mutableEncounteredRecords: EncounteredIds): ReadDataResult<unknown>;
24
30
  //# sourceMappingURL=read.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"read.d.ts","sourceRoot":"","sources":["../../src/core/read.ts"],"names":[],"mappings":"AACA,OAAO,EAIL,KAAK,cAAc,EACpB,MAAM,SAAS,CAAC;AAQjB,OAAO,EACL,WAAW,EAEX,iBAAiB,EAEjB,KAAK,qBAAqB,EAC3B,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAGL,mBAAmB,EACnB,KAAK,IAAI,EACV,MAAM,uBAAuB,CAAC;AAe/B,MAAM,MAAM,sBAAsB,CAAC,CAAC,IAAI;IACtC,QAAQ,CAAC,kBAAkB,EAAE,cAAc,CAAC;IAC5C,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAC,CAAC,CAAC,CAAC;CAC/B,CAAC;AAEF,wBAAgB,oBAAoB,CAClC,cAAc,SAAS,qBAAqB,EAE5C,WAAW,EAAE,mBAAmB,EAChC,iBAAiB,EAAE,iBAAiB,CAAC,cAAc,EAAE,OAAO,CAAC,EAC7D,qBAAqB,EAAE,2BAA2B,GACjD,sBAAsB,CAAC,cAAc,CAAC,CAiExC;AAED,MAAM,MAAM,cAAc,CAAC,cAAc,IACrC;IACE,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC;IACzB,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAC,cAAc,CAAC,CAAC;IAC3C,QAAQ,CAAC,kBAAkB,EAAE,cAAc,CAAC;CAC7C,GACD;IACE,QAAQ,CAAC,IAAI,EAAE,aAAa,CAAC;IAC7B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,YAAY,CAAC,EAAE,cAAc,CAAC,OAAO,CAAC,CAAC;IAChD,QAAQ,CAAC,UAAU,EAAE,IAAI,CAAC;CAC3B,CAAC;AAwoBN,MAAM,MAAM,2BAA2B,GAAG;IACxC,iBAAiB,EAAE,OAAO,CAAC;IAC3B,mBAAmB,EAAE,OAAO,CAAC;CAC9B,CAAC;AAEF,wBAAgB,oCAAoC,CAClD,qBAAqB,CAAC,EAAE,OAAO,CAAC,2BAA2B,CAAC,GAAG,IAAI,GAClE,2BAA2B,CAK7B"}
1
+ {"version":3,"file":"read.d.ts","sourceRoot":"","sources":["../../src/core/read.ts"],"names":[],"mappings":"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"}
package/dist/core/read.js CHANGED
@@ -1,7 +1,10 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.readButDoNotEvaluate = readButDoNotEvaluate;
4
+ exports.readScalarFieldData = readScalarFieldData;
5
+ exports.readLinkedFieldData = readLinkedFieldData;
4
6
  exports.getNetworkRequestOptionsWithDefaults = getNetworkRequestOptionsWithDefaults;
7
+ exports.readImperativelyLoadedField = readImperativelyLoadedField;
5
8
  const cache_1 = require("./cache");
6
9
  const componentCache_1 = require("./componentCache");
7
10
  const IsographEnvironment_1 = require("./IsographEnvironment");
@@ -56,7 +59,7 @@ function readButDoNotEvaluate(environment, fragmentReference, networkRequestOpti
56
59
  }
57
60
  }
58
61
  function readData(environment, ast, root, variables, nestedRefetchQueries, networkRequest, networkRequestOptions, mutableEncounteredRecords) {
59
- var _a, _b, _c, _d, _e;
62
+ var _a, _b, _c;
60
63
  const encounteredIds = (0, cache_1.insertIfNotExists)(mutableEncounteredRecords, root.__typename);
61
64
  encounteredIds.add(root.__link);
62
65
  let storeRecord = (_a = environment.store[root.__typename]) === null || _a === void 0 ? void 0 : _a[root.__link];
@@ -71,25 +74,17 @@ function readData(environment, ast, root, variables, nestedRefetchQueries, netwo
71
74
  return {
72
75
  kind: 'Success',
73
76
  data: null,
74
- encounteredRecords: mutableEncounteredRecords,
75
77
  };
76
78
  }
77
79
  let target = {};
78
80
  for (const field of ast) {
79
81
  switch (field.kind) {
80
82
  case 'Scalar': {
81
- const storeRecordName = (0, cache_1.getParentRecordKey)(field, variables);
82
- const value = storeRecord[storeRecordName];
83
- // TODO consider making scalars into discriminated unions. This probably has
84
- // to happen for when we handle errors.
85
- if (value === undefined) {
86
- return {
87
- kind: 'MissingData',
88
- reason: 'No value for ' + storeRecordName + ' on root ' + root.__link,
89
- recordLink: root,
90
- };
83
+ const data = readScalarFieldData(field, storeRecord, root, variables);
84
+ if (data.kind === 'MissingData') {
85
+ return data;
91
86
  }
92
- target[(_b = field.alias) !== null && _b !== void 0 ? _b : field.fieldName] = value;
87
+ target[(_b = field.alias) !== null && _b !== void 0 ? _b : field.fieldName] = data.data;
93
88
  break;
94
89
  }
95
90
  case 'Link': {
@@ -97,176 +92,19 @@ function readData(environment, ast, root, variables, nestedRefetchQueries, netwo
97
92
  break;
98
93
  }
99
94
  case 'Linked': {
100
- const storeRecordName = (0, cache_1.getParentRecordKey)(field, variables);
101
- const value = storeRecord[storeRecordName];
102
- if (Array.isArray(value)) {
103
- const results = [];
104
- for (const item of value) {
105
- const link = (0, IsographEnvironment_1.assertLink)(item);
106
- if (link === undefined) {
107
- return {
108
- kind: 'MissingData',
109
- reason: 'No link for ' +
110
- storeRecordName +
111
- ' on root ' +
112
- root.__link +
113
- '. Link is ' +
114
- JSON.stringify(item),
115
- recordLink: root,
116
- };
117
- }
118
- else if (link === null) {
119
- results.push(null);
120
- continue;
121
- }
122
- const result = readData(environment, field.selections, link, variables, nestedRefetchQueries, networkRequest, networkRequestOptions, mutableEncounteredRecords);
123
- if (result.kind === 'MissingData') {
124
- return {
125
- kind: 'MissingData',
126
- reason: 'Missing data for ' +
127
- storeRecordName +
128
- ' on root ' +
129
- root.__link +
130
- '. Link is ' +
131
- JSON.stringify(item),
132
- nestedReason: result,
133
- recordLink: result.recordLink,
134
- };
135
- }
136
- results.push(result.data);
137
- }
138
- target[(_c = field.alias) !== null && _c !== void 0 ? _c : field.fieldName] = results;
139
- break;
140
- }
141
- let link = (0, IsographEnvironment_1.assertLink)(value);
142
- if (field.condition) {
143
- const data = readData(environment, field.condition.readerAst, root, variables, nestedRefetchQueries, networkRequest, networkRequestOptions, mutableEncounteredRecords);
144
- if (data.kind === 'MissingData') {
145
- return {
146
- kind: 'MissingData',
147
- reason: 'Missing data for ' +
148
- storeRecordName +
149
- ' on root ' +
150
- root.__link,
151
- nestedReason: data,
152
- recordLink: data.recordLink,
153
- };
154
- }
155
- const readerWithRefetchQueries = {
156
- kind: 'ReaderWithRefetchQueries',
157
- readerArtifact: field.condition,
158
- // TODO this is wrong
159
- // should map field.condition.usedRefetchQueries
160
- // but it doesn't exist
161
- nestedRefetchQueries: [],
162
- };
163
- const fragment = {
164
- kind: 'FragmentReference',
165
- readerWithRefetchQueries: (0, PromiseWrapper_1.wrapResolvedValue)(readerWithRefetchQueries),
166
- root,
167
- variables: generateChildVariableMap(variables,
168
- // TODO this is wrong
169
- // should use field.condition.variables
170
- // but it doesn't exist
171
- []),
172
- networkRequest,
173
- };
174
- const condition = field.condition.resolver(Object.assign({ data: data.data, parameters: {} }, (field.condition.hasUpdatable
175
- ? {
176
- startUpdate: (0, startUpdate_1.getOrCreateCachedStartUpdate)(environment, fragment, readerWithRefetchQueries.readerArtifact.fieldName),
177
- }
178
- : undefined)));
179
- if (condition === true) {
180
- link = root;
181
- }
182
- else if (condition === false) {
183
- link = null;
184
- }
185
- else {
186
- link = condition;
187
- }
188
- }
189
- if (link === undefined) {
190
- // TODO make this configurable, and also generated and derived from the schema
191
- const missingFieldHandler = environment.missingFieldHandler;
192
- const altLink = missingFieldHandler === null || missingFieldHandler === void 0 ? void 0 : missingFieldHandler(storeRecord, root, field.fieldName, field.arguments, variables);
193
- (0, logging_1.logMessage)(environment, {
194
- kind: 'MissingFieldHandlerCalled',
195
- root,
196
- storeRecord,
197
- fieldName: field.fieldName,
198
- arguments: field.arguments,
199
- variables,
200
- });
201
- if (altLink === undefined) {
202
- return {
203
- kind: 'MissingData',
204
- reason: 'No link for ' +
205
- storeRecordName +
206
- ' on root ' +
207
- root.__link +
208
- '. Link is ' +
209
- JSON.stringify(value),
210
- recordLink: root,
211
- };
212
- }
213
- else {
214
- link = altLink;
215
- }
216
- }
217
- else if (link === null) {
218
- target[(_d = field.alias) !== null && _d !== void 0 ? _d : field.fieldName] = null;
219
- break;
220
- }
221
- const targetId = link;
222
- const data = readData(environment, field.selections, targetId, variables, nestedRefetchQueries, networkRequest, networkRequestOptions, mutableEncounteredRecords);
95
+ const data = readLinkedFieldData(environment, field, storeRecord, root, variables, networkRequest, (ast, root) => readData(environment, ast, root, variables, nestedRefetchQueries, networkRequest, networkRequestOptions, mutableEncounteredRecords));
223
96
  if (data.kind === 'MissingData') {
224
- return {
225
- kind: 'MissingData',
226
- reason: 'Missing data for ' + storeRecordName + ' on root ' + root.__link,
227
- nestedReason: data,
228
- recordLink: data.recordLink,
229
- };
97
+ return data;
230
98
  }
231
- target[(_e = field.alias) !== null && _e !== void 0 ? _e : field.fieldName] = data.data;
99
+ target[(_c = field.alias) !== null && _c !== void 0 ? _c : field.fieldName] = data.data;
232
100
  break;
233
101
  }
234
102
  case 'ImperativelyLoadedField': {
235
- // First, we read the data using the refetch reader AST (i.e. read out the
236
- // id field).
237
- const data = readData(environment, field.refetchReaderArtifact.readerAst, root, variables,
238
- // Refetch fields just read the id, and don't need refetch query artifacts
239
- [],
240
- // This is probably indicative of the fact that we are doing redundant checks
241
- // on the status of this network request...
242
- networkRequest, networkRequestOptions, mutableEncounteredRecords);
103
+ const data = readImperativelyLoadedField(environment, field, root, variables, nestedRefetchQueries, networkRequest, networkRequestOptions, mutableEncounteredRecords);
243
104
  if (data.kind === 'MissingData') {
244
- return {
245
- kind: 'MissingData',
246
- reason: 'Missing data for ' + field.alias + ' on root ' + root.__link,
247
- nestedReason: data,
248
- recordLink: data.recordLink,
249
- };
250
- }
251
- else {
252
- const refetchQueryIndex = field.refetchQuery;
253
- const refetchQuery = nestedRefetchQueries[refetchQueryIndex];
254
- if (refetchQuery == null) {
255
- throw new Error('refetchQuery is null in RefetchField. This is indicative of a bug in Isograph.');
256
- }
257
- const refetchQueryArtifact = refetchQuery.artifact;
258
- const allowedVariables = refetchQuery.allowedVariables;
259
- // Second, we allow the user to call the resolver, which will ultimately
260
- // use the resolver reader AST to get the resolver parameters.
261
- target[field.alias] = (args) => [
262
- // Stable id
263
- root.__link + '__' + field.name,
264
- // Fetcher
265
- field.refetchReaderArtifact.resolver(environment, refetchQueryArtifact, data.data, filterVariables(Object.assign(Object.assign({}, args), variables), allowedVariables), root,
266
- // TODO these params should be removed
267
- null, []),
268
- ];
105
+ return data;
269
106
  }
107
+ target[field.alias] = data.data;
270
108
  break;
271
109
  }
272
110
  case 'Resolver': {
@@ -436,7 +274,6 @@ function readData(environment, ast, root, variables, nestedRefetchQueries, netwo
436
274
  return {
437
275
  kind: 'Success',
438
276
  data: target,
439
- encounteredRecords: mutableEncounteredRecords,
440
277
  };
441
278
  }
442
279
  function filterVariables(variables, allowedVariables) {
@@ -504,6 +341,155 @@ function writeQueryArgsToVariables(targetVariables, queryArgs, variables) {
504
341
  }
505
342
  }
506
343
  }
344
+ function readScalarFieldData(field, storeRecord, root, variables) {
345
+ const storeRecordName = (0, cache_1.getParentRecordKey)(field, variables);
346
+ const value = storeRecord[storeRecordName];
347
+ // TODO consider making scalars into discriminated unions. This probably has
348
+ // to happen for when we handle errors.
349
+ if (value === undefined) {
350
+ return {
351
+ kind: 'MissingData',
352
+ reason: 'No value for ' + storeRecordName + ' on root ' + root.__link,
353
+ recordLink: root,
354
+ };
355
+ }
356
+ return { kind: 'Success', data: value };
357
+ }
358
+ function readLinkedFieldData(environment, field, storeRecord, root, variables, networkRequest, readData) {
359
+ const storeRecordName = (0, cache_1.getParentRecordKey)(field, variables);
360
+ const value = storeRecord[storeRecordName];
361
+ if (Array.isArray(value)) {
362
+ const results = [];
363
+ for (const item of value) {
364
+ const link = (0, IsographEnvironment_1.assertLink)(item);
365
+ if (link === undefined) {
366
+ return {
367
+ kind: 'MissingData',
368
+ reason: 'No link for ' +
369
+ storeRecordName +
370
+ ' on root ' +
371
+ root.__link +
372
+ '. Link is ' +
373
+ JSON.stringify(item),
374
+ recordLink: root,
375
+ };
376
+ }
377
+ else if (link === null) {
378
+ results.push(null);
379
+ continue;
380
+ }
381
+ const result = readData(field.selections, link);
382
+ if (result.kind === 'MissingData') {
383
+ return {
384
+ kind: 'MissingData',
385
+ reason: 'Missing data for ' +
386
+ storeRecordName +
387
+ ' on root ' +
388
+ root.__link +
389
+ '. Link is ' +
390
+ JSON.stringify(item),
391
+ nestedReason: result,
392
+ recordLink: result.recordLink,
393
+ };
394
+ }
395
+ results.push(result.data);
396
+ }
397
+ return {
398
+ kind: 'Success',
399
+ data: results,
400
+ };
401
+ }
402
+ let link = (0, IsographEnvironment_1.assertLink)(value);
403
+ if (field.condition) {
404
+ const data = readData(field.condition.readerAst, root);
405
+ if (data.kind === 'MissingData') {
406
+ return {
407
+ kind: 'MissingData',
408
+ reason: 'Missing data for ' + storeRecordName + ' on root ' + root.__link,
409
+ nestedReason: data,
410
+ recordLink: data.recordLink,
411
+ };
412
+ }
413
+ const readerWithRefetchQueries = {
414
+ kind: 'ReaderWithRefetchQueries',
415
+ readerArtifact: field.condition,
416
+ // TODO this is wrong
417
+ // should map field.condition.usedRefetchQueries
418
+ // but it doesn't exist
419
+ nestedRefetchQueries: [],
420
+ };
421
+ const fragment = {
422
+ kind: 'FragmentReference',
423
+ readerWithRefetchQueries: (0, PromiseWrapper_1.wrapResolvedValue)(readerWithRefetchQueries),
424
+ root,
425
+ variables: generateChildVariableMap(variables,
426
+ // TODO this is wrong
427
+ // should use field.condition.variables
428
+ // but it doesn't exist
429
+ []),
430
+ networkRequest,
431
+ };
432
+ const condition = field.condition.resolver(Object.assign({ data: data.data, parameters: {} }, (field.condition.hasUpdatable
433
+ ? {
434
+ startUpdate: (0, startUpdate_1.getOrCreateCachedStartUpdate)(environment, fragment, readerWithRefetchQueries.readerArtifact.fieldName),
435
+ }
436
+ : undefined)));
437
+ if (condition === true) {
438
+ link = root;
439
+ }
440
+ else if (condition === false) {
441
+ link = null;
442
+ }
443
+ else {
444
+ link = condition;
445
+ }
446
+ }
447
+ if (link === undefined) {
448
+ // TODO make this configurable, and also generated and derived from the schema
449
+ const missingFieldHandler = environment.missingFieldHandler;
450
+ const altLink = missingFieldHandler === null || missingFieldHandler === void 0 ? void 0 : missingFieldHandler(storeRecord, root, field.fieldName, field.arguments, variables);
451
+ (0, logging_1.logMessage)(environment, {
452
+ kind: 'MissingFieldHandlerCalled',
453
+ root,
454
+ storeRecord,
455
+ fieldName: field.fieldName,
456
+ arguments: field.arguments,
457
+ variables,
458
+ });
459
+ if (altLink === undefined) {
460
+ return {
461
+ kind: 'MissingData',
462
+ reason: 'No link for ' +
463
+ storeRecordName +
464
+ ' on root ' +
465
+ root.__link +
466
+ '. Link is ' +
467
+ JSON.stringify(value),
468
+ recordLink: root,
469
+ };
470
+ }
471
+ else {
472
+ link = altLink;
473
+ }
474
+ }
475
+ else if (link === null) {
476
+ return {
477
+ kind: 'Success',
478
+ data: null,
479
+ };
480
+ }
481
+ const targetId = link;
482
+ const data = readData(field.selections, targetId);
483
+ if (data.kind === 'MissingData') {
484
+ return {
485
+ kind: 'MissingData',
486
+ reason: 'Missing data for ' + storeRecordName + ' on root ' + root.__link,
487
+ nestedReason: data,
488
+ recordLink: data.recordLink,
489
+ };
490
+ }
491
+ return data;
492
+ }
507
493
  function getNetworkRequestOptionsWithDefaults(networkRequestOptions) {
508
494
  var _a, _b;
509
495
  return {
@@ -525,3 +511,43 @@ function stableStringifyArgs(args) {
525
511
  }
526
512
  return s;
527
513
  }
514
+ function readImperativelyLoadedField(environment, field, root, variables, nestedRefetchQueries, networkRequest, networkRequestOptions, mutableEncounteredRecords) {
515
+ // First, we read the data using the refetch reader AST (i.e. read out the
516
+ // id field).
517
+ const data = readData(environment, field.refetchReaderArtifact.readerAst, root, variables,
518
+ // Refetch fields just read the id, and don't need refetch query artifacts
519
+ [],
520
+ // This is probably indicative of the fact that we are doing redundant checks
521
+ // on the status of this network request...
522
+ networkRequest, networkRequestOptions, mutableEncounteredRecords);
523
+ if (data.kind === 'MissingData') {
524
+ return {
525
+ kind: 'MissingData',
526
+ reason: 'Missing data for ' + field.alias + ' on root ' + root.__link,
527
+ nestedReason: data,
528
+ recordLink: data.recordLink,
529
+ };
530
+ }
531
+ else {
532
+ const refetchQueryIndex = field.refetchQuery;
533
+ const refetchQuery = nestedRefetchQueries[refetchQueryIndex];
534
+ if (refetchQuery == null) {
535
+ throw new Error('refetchQuery is null in RefetchField. This is indicative of a bug in Isograph.');
536
+ }
537
+ const refetchQueryArtifact = refetchQuery.artifact;
538
+ const allowedVariables = refetchQuery.allowedVariables;
539
+ // Second, we allow the user to call the resolver, which will ultimately
540
+ // use the resolver reader AST to get the resolver parameters.
541
+ return {
542
+ kind: 'Success',
543
+ data: (args) => [
544
+ // Stable id
545
+ root.__link + '__' + field.name,
546
+ // Fetcher
547
+ field.refetchReaderArtifact.resolver(environment, refetchQueryArtifact, data.data, filterVariables(Object.assign(Object.assign({}, args), variables), allowedVariables), root,
548
+ // TODO these params should be removed
549
+ null, []),
550
+ ],
551
+ };
552
+ }
553
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@isograph/react",
3
- "version": "0.0.0-main-0e6e4170",
3
+ "version": "0.0.0-main-7faadacd",
4
4
  "description": "Use Isograph with React",
5
5
  "homepage": "https://isograph.dev",
6
6
  "main": "dist/index.js",
@@ -20,9 +20,9 @@
20
20
  "iso-watch": "cross-env ../../target/debug/isograph_cli --config ./isograph.config.json --watch"
21
21
  },
22
22
  "dependencies": {
23
- "@isograph/disposable-types": "0.0.0-main-0e6e4170",
24
- "@isograph/react-disposable-state": "0.0.0-main-0e6e4170",
25
- "@isograph/reference-counted-pointer": "0.0.0-main-0e6e4170"
23
+ "@isograph/disposable-types": "0.0.0-main-7faadacd",
24
+ "@isograph/react-disposable-state": "0.0.0-main-7faadacd",
25
+ "@isograph/reference-counted-pointer": "0.0.0-main-7faadacd"
26
26
  },
27
27
  "peerDependencies": {
28
28
  "react": "^18.0.0 || ^19.0.0"
package/src/core/read.ts CHANGED
@@ -14,7 +14,6 @@ import {
14
14
  } from './entrypoint';
15
15
  import {
16
16
  ExtractData,
17
- ExtractParameters,
18
17
  FragmentReference,
19
18
  Variables,
20
19
  type UnknownTReadFromStore,
@@ -23,7 +22,9 @@ import {
23
22
  assertLink,
24
23
  getOrLoadIsographArtifact,
25
24
  IsographEnvironment,
25
+ type DataTypeValue,
26
26
  type Link,
27
+ type StoreRecord,
27
28
  } from './IsographEnvironment';
28
29
  import { logMessage } from './logging';
29
30
  import { maybeMakeNetworkRequest } from './makeNetworkRequest';
@@ -35,7 +36,12 @@ import {
35
36
  wrapPromise,
36
37
  wrapResolvedValue,
37
38
  } from './PromiseWrapper';
38
- import { ReaderAst } from './reader';
39
+ import {
40
+ ReaderAst,
41
+ type ReaderImperativelyLoadedField,
42
+ type ReaderLinkedField,
43
+ type ReaderScalarField,
44
+ } from './reader';
39
45
  import { getOrCreateCachedStartUpdate } from './startUpdate';
40
46
  import { Arguments } from './util';
41
47
 
@@ -117,12 +123,13 @@ export function readButDoNotEvaluate<
117
123
  }
118
124
  }
119
125
 
120
- export type ReadDataResult<TReadFromStore> =
121
- | {
122
- readonly kind: 'Success';
123
- readonly data: ExtractData<TReadFromStore>;
124
- readonly encounteredRecords: EncounteredIds;
125
- }
126
+ export type ReadDataResultSuccess<Data> = {
127
+ readonly kind: 'Success';
128
+ readonly data: Data;
129
+ };
130
+
131
+ export type ReadDataResult<Data> =
132
+ | ReadDataResultSuccess<Data>
126
133
  | {
127
134
  readonly kind: 'MissingData';
128
135
  readonly reason: string;
@@ -134,12 +141,12 @@ function readData<TReadFromStore>(
134
141
  environment: IsographEnvironment,
135
142
  ast: ReaderAst<TReadFromStore>,
136
143
  root: Link,
137
- variables: ExtractParameters<TReadFromStore>,
144
+ variables: Variables,
138
145
  nestedRefetchQueries: RefetchQueryNormalizationArtifactWrapper[],
139
146
  networkRequest: PromiseWrapper<void, any>,
140
147
  networkRequestOptions: NetworkRequestReaderOptions,
141
148
  mutableEncounteredRecords: EncounteredIds,
142
- ): ReadDataResult<TReadFromStore> {
149
+ ): ReadDataResult<ExtractData<TReadFromStore>> {
143
150
  const encounteredIds = insertIfNotExists(
144
151
  mutableEncounteredRecords,
145
152
  root.__typename,
@@ -158,7 +165,6 @@ function readData<TReadFromStore>(
158
165
  return {
159
166
  kind: 'Success',
160
167
  data: null as any,
161
- encounteredRecords: mutableEncounteredRecords,
162
168
  };
163
169
  }
164
170
 
@@ -167,19 +173,12 @@ function readData<TReadFromStore>(
167
173
  for (const field of ast) {
168
174
  switch (field.kind) {
169
175
  case 'Scalar': {
170
- const storeRecordName = getParentRecordKey(field, variables);
171
- const value = storeRecord[storeRecordName];
172
- // TODO consider making scalars into discriminated unions. This probably has
173
- // to happen for when we handle errors.
174
- if (value === undefined) {
175
- return {
176
- kind: 'MissingData',
177
- reason:
178
- 'No value for ' + storeRecordName + ' on root ' + root.__link,
179
- recordLink: root,
180
- };
176
+ const data = readScalarFieldData(field, storeRecord, root, variables);
177
+
178
+ if (data.kind === 'MissingData') {
179
+ return data;
181
180
  }
182
- target[field.alias ?? field.fieldName] = value;
181
+ target[field.alias ?? field.fieldName] = data.data;
183
182
  break;
184
183
  }
185
184
  case 'Link': {
@@ -187,246 +186,46 @@ function readData<TReadFromStore>(
187
186
  break;
188
187
  }
189
188
  case 'Linked': {
190
- const storeRecordName = getParentRecordKey(field, variables);
191
- const value = storeRecord[storeRecordName];
192
- if (Array.isArray(value)) {
193
- const results = [];
194
- for (const item of value) {
195
- const link = assertLink(item);
196
- if (link === undefined) {
197
- return {
198
- kind: 'MissingData',
199
- reason:
200
- 'No link for ' +
201
- storeRecordName +
202
- ' on root ' +
203
- root.__link +
204
- '. Link is ' +
205
- JSON.stringify(item),
206
- recordLink: root,
207
- };
208
- } else if (link === null) {
209
- results.push(null);
210
- continue;
211
- }
212
-
213
- const result = readData(
189
+ const data = readLinkedFieldData(
190
+ environment,
191
+ field,
192
+ storeRecord,
193
+ root,
194
+ variables,
195
+ networkRequest,
196
+ (ast, root) =>
197
+ readData(
214
198
  environment,
215
- field.selections,
216
- link,
199
+ ast,
200
+ root,
217
201
  variables,
218
202
  nestedRefetchQueries,
219
203
  networkRequest,
220
204
  networkRequestOptions,
221
205
  mutableEncounteredRecords,
222
- );
223
- if (result.kind === 'MissingData') {
224
- return {
225
- kind: 'MissingData',
226
- reason:
227
- 'Missing data for ' +
228
- storeRecordName +
229
- ' on root ' +
230
- root.__link +
231
- '. Link is ' +
232
- JSON.stringify(item),
233
- nestedReason: result,
234
- recordLink: result.recordLink,
235
- };
236
- }
237
- results.push(result.data);
238
- }
239
- target[field.alias ?? field.fieldName] = results;
240
- break;
241
- }
242
- let link = assertLink(value);
243
-
244
- if (field.condition) {
245
- const data = readData(
246
- environment,
247
- field.condition.readerAst,
248
- root,
249
- variables,
250
- nestedRefetchQueries,
251
- networkRequest,
252
- networkRequestOptions,
253
- mutableEncounteredRecords,
254
- );
255
- if (data.kind === 'MissingData') {
256
- return {
257
- kind: 'MissingData',
258
- reason:
259
- 'Missing data for ' +
260
- storeRecordName +
261
- ' on root ' +
262
- root.__link,
263
- nestedReason: data,
264
- recordLink: data.recordLink,
265
- };
266
- }
267
-
268
- const readerWithRefetchQueries = {
269
- kind: 'ReaderWithRefetchQueries',
270
- readerArtifact: field.condition,
271
- // TODO this is wrong
272
- // should map field.condition.usedRefetchQueries
273
- // but it doesn't exist
274
- nestedRefetchQueries: [],
275
- } satisfies ReaderWithRefetchQueries<any, any>;
276
-
277
- const fragment = {
278
- kind: 'FragmentReference',
279
- readerWithRefetchQueries: wrapResolvedValue(
280
- readerWithRefetchQueries,
281
206
  ),
282
- root,
283
- variables: generateChildVariableMap(
284
- variables,
285
- // TODO this is wrong
286
- // should use field.condition.variables
287
- // but it doesn't exist
288
- [],
289
- ),
290
- networkRequest,
291
- } satisfies FragmentReference<any, any>;
292
-
293
- const condition = field.condition.resolver({
294
- data: data.data,
295
- parameters: {},
296
- ...(field.condition.hasUpdatable
297
- ? {
298
- startUpdate: getOrCreateCachedStartUpdate(
299
- environment,
300
- fragment,
301
- readerWithRefetchQueries.readerArtifact.fieldName,
302
- ),
303
- }
304
- : undefined),
305
- });
306
- if (condition === true) {
307
- link = root;
308
- } else if (condition === false) {
309
- link = null;
310
- } else {
311
- link = condition;
312
- }
313
- }
314
-
315
- if (link === undefined) {
316
- // TODO make this configurable, and also generated and derived from the schema
317
- const missingFieldHandler = environment.missingFieldHandler;
318
-
319
- const altLink = missingFieldHandler?.(
320
- storeRecord,
321
- root,
322
- field.fieldName,
323
- field.arguments,
324
- variables,
325
- );
326
- logMessage(environment, {
327
- kind: 'MissingFieldHandlerCalled',
328
- root,
329
- storeRecord,
330
- fieldName: field.fieldName,
331
- arguments: field.arguments,
332
- variables,
333
- });
334
-
335
- if (altLink === undefined) {
336
- return {
337
- kind: 'MissingData',
338
- reason:
339
- 'No link for ' +
340
- storeRecordName +
341
- ' on root ' +
342
- root.__link +
343
- '. Link is ' +
344
- JSON.stringify(value),
345
- recordLink: root,
346
- };
347
- } else {
348
- link = altLink;
349
- }
350
- } else if (link === null) {
351
- target[field.alias ?? field.fieldName] = null;
352
- break;
353
- }
354
- const targetId = link;
355
- const data = readData(
356
- environment,
357
- field.selections,
358
- targetId,
359
- variables,
360
- nestedRefetchQueries,
361
- networkRequest,
362
- networkRequestOptions,
363
- mutableEncounteredRecords,
364
207
  );
365
208
  if (data.kind === 'MissingData') {
366
- return {
367
- kind: 'MissingData',
368
- reason:
369
- 'Missing data for ' + storeRecordName + ' on root ' + root.__link,
370
- nestedReason: data,
371
- recordLink: data.recordLink,
372
- };
209
+ return data;
373
210
  }
374
211
  target[field.alias ?? field.fieldName] = data.data;
375
212
  break;
376
213
  }
377
214
  case 'ImperativelyLoadedField': {
378
- // First, we read the data using the refetch reader AST (i.e. read out the
379
- // id field).
380
- const data = readData(
215
+ const data = readImperativelyLoadedField(
381
216
  environment,
382
- field.refetchReaderArtifact.readerAst,
217
+ field,
383
218
  root,
384
219
  variables,
385
- // Refetch fields just read the id, and don't need refetch query artifacts
386
- [],
387
- // This is probably indicative of the fact that we are doing redundant checks
388
- // on the status of this network request...
220
+ nestedRefetchQueries,
389
221
  networkRequest,
390
222
  networkRequestOptions,
391
223
  mutableEncounteredRecords,
392
224
  );
393
225
  if (data.kind === 'MissingData') {
394
- return {
395
- kind: 'MissingData',
396
- reason:
397
- 'Missing data for ' + field.alias + ' on root ' + root.__link,
398
- nestedReason: data,
399
- recordLink: data.recordLink,
400
- };
401
- } else {
402
- const refetchQueryIndex = field.refetchQuery;
403
- const refetchQuery = nestedRefetchQueries[refetchQueryIndex];
404
- if (refetchQuery == null) {
405
- throw new Error(
406
- 'refetchQuery is null in RefetchField. This is indicative of a bug in Isograph.',
407
- );
408
- }
409
- const refetchQueryArtifact = refetchQuery.artifact;
410
- const allowedVariables = refetchQuery.allowedVariables;
411
-
412
- // Second, we allow the user to call the resolver, which will ultimately
413
- // use the resolver reader AST to get the resolver parameters.
414
- target[field.alias] = (args: any) => [
415
- // Stable id
416
- root.__link + '__' + field.name,
417
- // Fetcher
418
- field.refetchReaderArtifact.resolver(
419
- environment,
420
- refetchQueryArtifact,
421
- data.data,
422
- filterVariables({ ...args, ...variables }, allowedVariables),
423
- root,
424
- // TODO these params should be removed
425
- null,
426
- [],
427
- ),
428
- ];
226
+ return data;
429
227
  }
228
+ target[field.alias] = data.data;
430
229
  break;
431
230
  }
432
231
  case 'Resolver': {
@@ -690,7 +489,6 @@ function readData<TReadFromStore>(
690
489
  return {
691
490
  kind: 'Success',
692
491
  data: target as any,
693
- encounteredRecords: mutableEncounteredRecords,
694
492
  };
695
493
  }
696
494
 
@@ -776,6 +574,197 @@ function writeQueryArgsToVariables(
776
574
  }
777
575
  }
778
576
 
577
+ export function readScalarFieldData(
578
+ field: ReaderScalarField,
579
+ storeRecord: StoreRecord,
580
+ root: Link,
581
+ variables: Variables,
582
+ ): ReadDataResult<string | number | boolean | Link | DataTypeValue[] | null> {
583
+ const storeRecordName = getParentRecordKey(field, variables);
584
+ const value = storeRecord[storeRecordName];
585
+ // TODO consider making scalars into discriminated unions. This probably has
586
+ // to happen for when we handle errors.
587
+ if (value === undefined) {
588
+ return {
589
+ kind: 'MissingData',
590
+ reason: 'No value for ' + storeRecordName + ' on root ' + root.__link,
591
+ recordLink: root,
592
+ };
593
+ }
594
+ return { kind: 'Success', data: value };
595
+ }
596
+
597
+ export function readLinkedFieldData(
598
+ environment: IsographEnvironment,
599
+ field: ReaderLinkedField,
600
+ storeRecord: StoreRecord,
601
+ root: Link,
602
+ variables: Variables,
603
+ networkRequest: PromiseWrapper<void, any>,
604
+
605
+ readData: <TReadFromStore>(
606
+ ast: ReaderAst<TReadFromStore>,
607
+ root: Link,
608
+ ) => ReadDataResult<object>,
609
+ ): ReadDataResult<unknown> {
610
+ const storeRecordName = getParentRecordKey(field, variables);
611
+ const value = storeRecord[storeRecordName];
612
+ if (Array.isArray(value)) {
613
+ const results = [];
614
+ for (const item of value) {
615
+ const link = assertLink(item);
616
+ if (link === undefined) {
617
+ return {
618
+ kind: 'MissingData',
619
+ reason:
620
+ 'No link for ' +
621
+ storeRecordName +
622
+ ' on root ' +
623
+ root.__link +
624
+ '. Link is ' +
625
+ JSON.stringify(item),
626
+ recordLink: root,
627
+ };
628
+ } else if (link === null) {
629
+ results.push(null);
630
+ continue;
631
+ }
632
+
633
+ const result = readData(field.selections, link);
634
+ if (result.kind === 'MissingData') {
635
+ return {
636
+ kind: 'MissingData',
637
+ reason:
638
+ 'Missing data for ' +
639
+ storeRecordName +
640
+ ' on root ' +
641
+ root.__link +
642
+ '. Link is ' +
643
+ JSON.stringify(item),
644
+ nestedReason: result,
645
+ recordLink: result.recordLink,
646
+ };
647
+ }
648
+ results.push(result.data);
649
+ }
650
+ return {
651
+ kind: 'Success',
652
+ data: results,
653
+ };
654
+ }
655
+ let link = assertLink(value);
656
+
657
+ if (field.condition) {
658
+ const data = readData(field.condition.readerAst, root);
659
+ if (data.kind === 'MissingData') {
660
+ return {
661
+ kind: 'MissingData',
662
+ reason:
663
+ 'Missing data for ' + storeRecordName + ' on root ' + root.__link,
664
+ nestedReason: data,
665
+ recordLink: data.recordLink,
666
+ };
667
+ }
668
+
669
+ const readerWithRefetchQueries = {
670
+ kind: 'ReaderWithRefetchQueries',
671
+ readerArtifact: field.condition,
672
+ // TODO this is wrong
673
+ // should map field.condition.usedRefetchQueries
674
+ // but it doesn't exist
675
+ nestedRefetchQueries: [],
676
+ } satisfies ReaderWithRefetchQueries<any, any>;
677
+
678
+ const fragment = {
679
+ kind: 'FragmentReference',
680
+ readerWithRefetchQueries: wrapResolvedValue(readerWithRefetchQueries),
681
+ root,
682
+ variables: generateChildVariableMap(
683
+ variables,
684
+ // TODO this is wrong
685
+ // should use field.condition.variables
686
+ // but it doesn't exist
687
+ [],
688
+ ),
689
+ networkRequest,
690
+ } satisfies FragmentReference<any, any>;
691
+
692
+ const condition = field.condition.resolver({
693
+ data: data.data,
694
+ parameters: {},
695
+ ...(field.condition.hasUpdatable
696
+ ? {
697
+ startUpdate: getOrCreateCachedStartUpdate(
698
+ environment,
699
+ fragment,
700
+ readerWithRefetchQueries.readerArtifact.fieldName,
701
+ ),
702
+ }
703
+ : undefined),
704
+ });
705
+ if (condition === true) {
706
+ link = root;
707
+ } else if (condition === false) {
708
+ link = null;
709
+ } else {
710
+ link = condition;
711
+ }
712
+ }
713
+
714
+ if (link === undefined) {
715
+ // TODO make this configurable, and also generated and derived from the schema
716
+ const missingFieldHandler = environment.missingFieldHandler;
717
+
718
+ const altLink = missingFieldHandler?.(
719
+ storeRecord,
720
+ root,
721
+ field.fieldName,
722
+ field.arguments,
723
+ variables,
724
+ );
725
+ logMessage(environment, {
726
+ kind: 'MissingFieldHandlerCalled',
727
+ root,
728
+ storeRecord,
729
+ fieldName: field.fieldName,
730
+ arguments: field.arguments,
731
+ variables,
732
+ });
733
+
734
+ if (altLink === undefined) {
735
+ return {
736
+ kind: 'MissingData',
737
+ reason:
738
+ 'No link for ' +
739
+ storeRecordName +
740
+ ' on root ' +
741
+ root.__link +
742
+ '. Link is ' +
743
+ JSON.stringify(value),
744
+ recordLink: root,
745
+ };
746
+ } else {
747
+ link = altLink;
748
+ }
749
+ } else if (link === null) {
750
+ return {
751
+ kind: 'Success',
752
+ data: null,
753
+ };
754
+ }
755
+ const targetId = link;
756
+ const data = readData(field.selections, targetId);
757
+ if (data.kind === 'MissingData') {
758
+ return {
759
+ kind: 'MissingData',
760
+ reason: 'Missing data for ' + storeRecordName + ' on root ' + root.__link,
761
+ nestedReason: data,
762
+ recordLink: data.recordLink,
763
+ };
764
+ }
765
+ return data;
766
+ }
767
+
779
768
  export type NetworkRequestReaderOptions = {
780
769
  suspendIfInFlight: boolean;
781
770
  throwOnNetworkError: boolean;
@@ -804,3 +793,69 @@ function stableStringifyArgs(args: object) {
804
793
  }
805
794
  return s;
806
795
  }
796
+
797
+ export function readImperativelyLoadedField(
798
+ environment: IsographEnvironment,
799
+ field: ReaderImperativelyLoadedField,
800
+ root: Link,
801
+ variables: Variables,
802
+ nestedRefetchQueries: RefetchQueryNormalizationArtifactWrapper[],
803
+ networkRequest: PromiseWrapper<void, any>,
804
+ networkRequestOptions: NetworkRequestReaderOptions,
805
+ mutableEncounteredRecords: EncounteredIds,
806
+ ): ReadDataResult<unknown> {
807
+ // First, we read the data using the refetch reader AST (i.e. read out the
808
+ // id field).
809
+ const data = readData(
810
+ environment,
811
+ field.refetchReaderArtifact.readerAst,
812
+ root,
813
+ variables,
814
+ // Refetch fields just read the id, and don't need refetch query artifacts
815
+ [],
816
+ // This is probably indicative of the fact that we are doing redundant checks
817
+ // on the status of this network request...
818
+ networkRequest,
819
+ networkRequestOptions,
820
+ mutableEncounteredRecords,
821
+ );
822
+ if (data.kind === 'MissingData') {
823
+ return {
824
+ kind: 'MissingData',
825
+ reason: 'Missing data for ' + field.alias + ' on root ' + root.__link,
826
+ nestedReason: data,
827
+ recordLink: data.recordLink,
828
+ };
829
+ } else {
830
+ const refetchQueryIndex = field.refetchQuery;
831
+ const refetchQuery = nestedRefetchQueries[refetchQueryIndex];
832
+ if (refetchQuery == null) {
833
+ throw new Error(
834
+ 'refetchQuery is null in RefetchField. This is indicative of a bug in Isograph.',
835
+ );
836
+ }
837
+ const refetchQueryArtifact = refetchQuery.artifact;
838
+ const allowedVariables = refetchQuery.allowedVariables;
839
+
840
+ // Second, we allow the user to call the resolver, which will ultimately
841
+ // use the resolver reader AST to get the resolver parameters.
842
+ return {
843
+ kind: 'Success',
844
+ data: (args: any) => [
845
+ // Stable id
846
+ root.__link + '__' + field.name,
847
+ // Fetcher
848
+ field.refetchReaderArtifact.resolver(
849
+ environment,
850
+ refetchQueryArtifact,
851
+ data.data,
852
+ filterVariables({ ...args, ...variables }, allowedVariables),
853
+ root,
854
+ // TODO these params should be removed
855
+ null,
856
+ [],
857
+ ),
858
+ ],
859
+ };
860
+ }
861
+ }