@isograph/react 0.0.0-main-4adb5045 → 0.0.0-main-82400fb8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (98) hide show
  1. package/.turbo/turbo-compile-libs.log +1 -1
  2. package/dist/core/FragmentReference.d.ts +1 -1
  3. package/dist/core/FragmentReference.d.ts.map +1 -1
  4. package/dist/core/FragmentReference.js +2 -2
  5. package/dist/core/IsographEnvironment.d.ts +7 -5
  6. package/dist/core/IsographEnvironment.d.ts.map +1 -1
  7. package/dist/core/IsographEnvironment.js +5 -4
  8. package/dist/core/cache.d.ts +5 -18
  9. package/dist/core/cache.d.ts.map +1 -1
  10. package/dist/core/cache.js +6 -218
  11. package/dist/core/componentCache.d.ts +2 -2
  12. package/dist/core/componentCache.d.ts.map +1 -1
  13. package/dist/core/componentCache.js +1 -26
  14. package/dist/core/entrypoint.d.ts +2 -2
  15. package/dist/core/entrypoint.d.ts.map +1 -1
  16. package/dist/core/garbageCollection.d.ts +2 -2
  17. package/dist/core/garbageCollection.d.ts.map +1 -1
  18. package/dist/core/getOrCreateCacheForArtifact.d.ts +8 -0
  19. package/dist/core/getOrCreateCacheForArtifact.d.ts.map +1 -0
  20. package/dist/core/getOrCreateCacheForArtifact.js +40 -0
  21. package/dist/core/logging.d.ts +8 -8
  22. package/dist/core/logging.d.ts.map +1 -1
  23. package/dist/core/makeNetworkRequest.d.ts +3 -3
  24. package/dist/core/makeNetworkRequest.d.ts.map +1 -1
  25. package/dist/core/makeNetworkRequest.js +3 -2
  26. package/dist/core/optimisticProxy.d.ts.map +1 -1
  27. package/dist/core/optimisticProxy.js +2 -1
  28. package/dist/core/read.d.ts +3 -3
  29. package/dist/core/read.d.ts.map +1 -1
  30. package/dist/core/startUpdate.d.ts.map +1 -1
  31. package/dist/core/startUpdate.js +2 -1
  32. package/dist/core/subscribe.d.ts +8 -0
  33. package/dist/core/subscribe.d.ts.map +1 -0
  34. package/dist/core/subscribe.js +127 -0
  35. package/dist/core/util.d.ts +7 -0
  36. package/dist/core/util.d.ts.map +1 -1
  37. package/dist/core/util.js +26 -0
  38. package/dist/core/writeData.d.ts +7 -0
  39. package/dist/core/writeData.d.ts.map +1 -0
  40. package/dist/core/writeData.js +36 -0
  41. package/dist/index.d.ts +5 -2
  42. package/dist/index.d.ts.map +1 -1
  43. package/dist/index.js +8 -5
  44. package/dist/loadable-hooks/useConnectionSpecPagination.d.ts +3 -3
  45. package/dist/loadable-hooks/useConnectionSpecPagination.d.ts.map +1 -1
  46. package/dist/loadable-hooks/useConnectionSpecPagination.js +2 -2
  47. package/dist/loadable-hooks/useSkipLimitPagination.d.ts +3 -3
  48. package/dist/loadable-hooks/useSkipLimitPagination.d.ts.map +1 -1
  49. package/dist/loadable-hooks/useSkipLimitPagination.js +2 -2
  50. package/dist/react/createIsographEnvironment.d.ts +4 -0
  51. package/dist/react/createIsographEnvironment.d.ts.map +1 -0
  52. package/dist/react/createIsographEnvironment.js +8 -0
  53. package/dist/react/maybeUnwrapNetworkRequest.d.ts +4 -0
  54. package/dist/react/maybeUnwrapNetworkRequest.d.ts.map +1 -0
  55. package/dist/react/maybeUnwrapNetworkRequest.js +14 -0
  56. package/dist/react/useLazyReference.d.ts.map +1 -1
  57. package/dist/react/useLazyReference.js +2 -2
  58. package/dist/react/useReadAndSubscribe.d.ts +4 -2
  59. package/dist/react/useReadAndSubscribe.d.ts.map +1 -1
  60. package/dist/react/useReadAndSubscribe.js +31 -2
  61. package/dist/react/useRerenderOnChange.d.ts +2 -2
  62. package/dist/react/useRerenderOnChange.d.ts.map +1 -1
  63. package/dist/react/useRerenderOnChange.js +2 -2
  64. package/dist/react/useResult.d.ts +2 -4
  65. package/dist/react/useResult.d.ts.map +1 -1
  66. package/dist/react/useResult.js +3 -13
  67. package/package.json +4 -4
  68. package/src/core/FragmentReference.ts +2 -2
  69. package/src/core/IsographEnvironment.ts +26 -10
  70. package/src/core/cache.ts +14 -360
  71. package/src/core/componentCache.ts +8 -43
  72. package/src/core/entrypoint.ts +2 -2
  73. package/src/core/garbageCollection.ts +5 -5
  74. package/src/core/getOrCreateCacheForArtifact.ts +86 -0
  75. package/src/core/logging.ts +10 -10
  76. package/src/core/makeNetworkRequest.ts +8 -8
  77. package/src/core/optimisticProxy.ts +2 -5
  78. package/src/core/read.ts +13 -13
  79. package/src/core/startUpdate.ts +1 -1
  80. package/src/core/subscribe.ts +195 -0
  81. package/src/core/util.ts +26 -0
  82. package/src/core/writeData.ts +79 -0
  83. package/src/index.ts +3 -4
  84. package/src/loadable-hooks/useConnectionSpecPagination.ts +5 -5
  85. package/src/loadable-hooks/useSkipLimitPagination.ts +5 -5
  86. package/src/react/createIsographEnvironment.ts +23 -0
  87. package/src/react/maybeUnwrapNetworkRequest.ts +17 -0
  88. package/src/react/useLazyReference.ts +2 -4
  89. package/src/react/useReadAndSubscribe.ts +53 -5
  90. package/src/react/useRerenderOnChange.ts +3 -3
  91. package/src/react/useResult.ts +6 -24
  92. package/src/tests/garbageCollection.test.ts +3 -6
  93. package/src/tests/meNameSuccessor.ts +1 -1
  94. package/src/tests/nodeQuery.ts +1 -1
  95. package/src/tests/normalizeData.test.ts +5 -3
  96. package/src/tests/optimisticProxy.test.ts +5 -3
  97. package/src/tests/startUpdate.test.ts +5 -7
  98. package/vitest.config.ts +5 -0
package/src/core/cache.ts CHANGED
@@ -1,51 +1,33 @@
1
- import {
2
- Factory,
3
- ItemCleanupPair,
4
- ParentCache,
5
- } from '@isograph/react-disposable-state';
6
- import {
7
- IsographEntrypoint,
1
+ import { type Factory, ParentCache } from '@isograph/react-disposable-state';
2
+ import type {
3
+ NormalizationAstNodes,
8
4
  NormalizationInlineFragment,
9
5
  NormalizationLinkedField,
10
6
  NormalizationScalarField,
11
- type NormalizationAst,
12
- type NormalizationAstLoader,
13
- type NormalizationAstNodes,
14
- } from '../core/entrypoint';
15
- import { mergeObjectsUsingReaderAst } from './areEqualWithDeepComparison';
16
- import { FetchOptions } from './check';
17
- import {
18
- ExtractParameters,
7
+ } from './entrypoint';
8
+ import type {
19
9
  FragmentReference,
10
+ UnknownTReadFromStore,
20
11
  Variables,
21
- type UnknownTReadFromStore,
22
- type VariableValue,
12
+ VariableValue,
23
13
  } from './FragmentReference';
24
14
  import {
25
- DataId,
26
- DataTypeValue,
27
- FragmentSubscription,
15
+ type DataId,
16
+ type DataTypeValue,
28
17
  getLink,
29
- getOrLoadReaderWithRefetchQueries,
30
- ROOT_ID,
31
- StoreLink,
32
- StoreRecord,
33
18
  type IsographEnvironment,
19
+ ROOT_ID,
20
+ type StoreLink,
21
+ type StoreRecord,
34
22
  type TypeName,
35
23
  } from './IsographEnvironment';
36
24
  import { logMessage } from './logging';
37
25
  import {
38
- maybeMakeNetworkRequest,
39
- retainQueryWithoutMakingNetworkRequest,
40
- } from './makeNetworkRequest';
41
- import {
42
- addNetworkResponseStoreLayer,
43
26
  getMutableStoreRecordProxy,
44
27
  type StoreLayerWithData,
45
28
  } from './optimisticProxy';
46
- import { readButDoNotEvaluate, WithEncounteredRecords } from './read';
47
- import { ReaderLinkedField, ReaderScalarField, type ReaderAst } from './reader';
48
- import { Argument, ArgumentValue } from './util';
29
+ import type { ReaderLinkedField, ReaderScalarField } from './reader';
30
+ import { type Argument, type ArgumentValue, isArray, stableCopy } from './util';
49
31
 
50
32
  export const TYPENAME_FIELD_NAME = '__typename';
51
33
 
@@ -64,90 +46,6 @@ export function getOrCreateItemInSuspenseCache<
64
46
  return environment.fragmentCache[index];
65
47
  }
66
48
 
67
- /**
68
- * Creates a copy of the provided value, ensuring any nested objects have their
69
- * keys sorted such that equivalent values would have identical JSON.stringify
70
- * results.
71
- */
72
- export function stableCopy<T>(value: T): T {
73
- if (value == null || typeof value !== 'object') {
74
- return value;
75
- }
76
- if (isArray(value)) {
77
- // @ts-ignore
78
- return value.map(stableCopy);
79
- }
80
- const keys = Object.keys(value).sort();
81
- const stable: { [index: string]: any } = {};
82
- for (let i = 0; i < keys.length; i++) {
83
- // @ts-ignore
84
- stable[keys[i]] = stableCopy(value[keys[i]]);
85
- }
86
- return stable as any;
87
- }
88
-
89
- export function getOrCreateCacheForArtifact<
90
- TReadFromStore extends UnknownTReadFromStore,
91
- TClientFieldValue,
92
- TNormalizationAst extends NormalizationAst | NormalizationAstLoader,
93
- TRawResponseType extends NetworkResponseObject,
94
- >(
95
- environment: IsographEnvironment,
96
- entrypoint: IsographEntrypoint<
97
- TReadFromStore,
98
- TClientFieldValue,
99
- TNormalizationAst,
100
- TRawResponseType
101
- >,
102
- variables: ExtractParameters<TReadFromStore>,
103
- fetchOptions?: FetchOptions<TClientFieldValue, TRawResponseType>,
104
- ): ParentCache<FragmentReference<TReadFromStore, TClientFieldValue>> {
105
- let cacheKey = '';
106
- switch (entrypoint.networkRequestInfo.operation.kind) {
107
- case 'Operation':
108
- cacheKey =
109
- entrypoint.networkRequestInfo.operation.text +
110
- JSON.stringify(stableCopy(variables));
111
- break;
112
- case 'PersistedOperation':
113
- cacheKey =
114
- entrypoint.networkRequestInfo.operation.operationId +
115
- JSON.stringify(stableCopy(variables));
116
- break;
117
- }
118
- const factory = () => {
119
- const { fieldName, readerArtifactKind, readerWithRefetchQueries } =
120
- getOrLoadReaderWithRefetchQueries(
121
- environment,
122
- entrypoint.readerWithRefetchQueries,
123
- );
124
- const [networkRequest, disposeNetworkRequest] = maybeMakeNetworkRequest(
125
- environment,
126
- entrypoint,
127
- variables,
128
- readerWithRefetchQueries,
129
- fetchOptions ?? null,
130
- );
131
-
132
- const itemCleanupPair: ItemCleanupPair<
133
- FragmentReference<TReadFromStore, TClientFieldValue>
134
- > = [
135
- {
136
- kind: 'FragmentReference',
137
- readerWithRefetchQueries,
138
- fieldName,
139
- readerArtifactKind,
140
- root: { __link: ROOT_ID, __typename: entrypoint.concreteType },
141
- variables,
142
- networkRequest: networkRequest,
143
- },
144
- disposeNetworkRequest,
145
- ];
146
- return itemCleanupPair;
147
- };
148
- return getOrCreateItemInSuspenseCache(environment, cacheKey, factory);
149
- }
150
-
151
49
  export type NetworkResponseScalarValue = string | number | boolean;
152
50
  export type NetworkResponseValue =
153
51
  | NetworkResponseScalarValue
@@ -222,33 +120,6 @@ export function subscribeToAnyChangesToRecord(
222
120
  return () => environment.subscriptions.delete(subscription);
223
121
  }
224
122
 
225
- export function subscribe<TReadFromStore extends UnknownTReadFromStore>(
226
- environment: IsographEnvironment,
227
- encounteredDataAndRecords: WithEncounteredRecords<TReadFromStore>,
228
- fragmentReference: FragmentReference<TReadFromStore, any>,
229
- callback: (
230
- newEncounteredDataAndRecords: WithEncounteredRecords<TReadFromStore>,
231
- ) => void,
232
- readerAst: ReaderAst<TReadFromStore>,
233
- ): () => void {
234
- const fragmentSubscription: FragmentSubscription<TReadFromStore> = {
235
- kind: 'FragmentSubscription',
236
- callback,
237
- encounteredDataAndRecords,
238
- fragmentReference,
239
- readerAst,
240
- };
241
-
242
- // subscribe is called in an effect. (We should actually subscribe during the
243
- // initial render.) Because it's called in an effect, we might have missed some
244
- // changes since the initial render! So, at this point, we re-read and call the
245
- // subscription (i.e. re-render) if the fragment data has changed.
246
- callSubscriptionIfDataChanged(environment, fragmentSubscription);
247
-
248
- environment.subscriptions.add(fragmentSubscription);
249
- return () => environment.subscriptions.delete(fragmentSubscription);
250
- }
251
-
252
123
  export function onNextChangeToRecord(
253
124
  environment: IsographEnvironment,
254
125
  recordLink: StoreLink,
@@ -265,161 +136,6 @@ export function onNextChangeToRecord(
265
136
  });
266
137
  }
267
138
 
268
- // Calls to readButDoNotEvaluate can suspend (i.e. throw a promise).
269
- // Maybe in the future, they will be able to throw errors.
270
- //
271
- // That's probably okay to ignore. We don't, however, want to prevent
272
- // updating other subscriptions if one subscription had missing data.
273
- function logAnyError(
274
- environment: IsographEnvironment,
275
- context: any,
276
- f: () => void,
277
- ) {
278
- try {
279
- f();
280
- } catch (e) {
281
- logMessage(environment, () => ({
282
- kind: 'ErrorEncounteredInWithErrorHandling',
283
- error: e,
284
- context,
285
- }));
286
- }
287
- }
288
-
289
- export function callSubscriptions(
290
- environment: IsographEnvironment,
291
- recordsEncounteredWhenNormalizing: EncounteredIds,
292
- ) {
293
- environment.subscriptions.forEach((subscription) =>
294
- logAnyError(environment, { situation: 'calling subscriptions' }, () => {
295
- switch (subscription.kind) {
296
- case 'FragmentSubscription': {
297
- // TODO if there are multiple components subscribed to the same
298
- // fragment, we will call readButNotEvaluate multiple times. We
299
- // should fix that.
300
- if (
301
- hasOverlappingIds(
302
- recordsEncounteredWhenNormalizing,
303
- subscription.encounteredDataAndRecords.encounteredRecords,
304
- )
305
- ) {
306
- callSubscriptionIfDataChanged(environment, subscription);
307
- }
308
- return;
309
- }
310
- case 'AnyRecords': {
311
- logAnyError(
312
- environment,
313
- { situation: 'calling AnyRecords callback' },
314
- () => subscription.callback(),
315
- );
316
- return;
317
- }
318
- case 'AnyChangesToRecord': {
319
- if (
320
- recordsEncounteredWhenNormalizing
321
- .get(subscription.recordLink.__typename)
322
- ?.has(subscription.recordLink.__link) != null
323
- ) {
324
- logAnyError(
325
- environment,
326
- { situation: 'calling AnyChangesToRecord callback' },
327
- () => subscription.callback(),
328
- );
329
- }
330
- return;
331
- }
332
- default: {
333
- // Ensure we have covered all variants
334
- const _: never = subscription;
335
- _;
336
- throw new Error('Unexpected case');
337
- }
338
- }
339
- }),
340
- );
341
- }
342
-
343
- function callSubscriptionIfDataChanged<
344
- TReadFromStore extends UnknownTReadFromStore,
345
- >(
346
- environment: IsographEnvironment,
347
- subscription: FragmentSubscription<TReadFromStore>,
348
- ) {
349
- const newEncounteredDataAndRecords = readButDoNotEvaluate(
350
- environment,
351
- subscription.fragmentReference,
352
- // Is this wrong?
353
- // Reasons to think no:
354
- // - we are only updating the read-out value, and the network
355
- // options only affect whether we throw.
356
- // - the component will re-render, and re-throw on its own, anyway.
357
- //
358
- // Reasons to think not:
359
- // - it seems more efficient to suspend here and not update state,
360
- // if we expect that the component will just throw anyway
361
- // - consistency
362
- // - it's also weird, this is called from makeNetworkRequest, where
363
- // we don't currently pass network request options
364
- {
365
- suspendIfInFlight: false,
366
- throwOnNetworkError: false,
367
- },
368
- );
369
-
370
- const mergedItem = mergeObjectsUsingReaderAst(
371
- subscription.readerAst,
372
- subscription.encounteredDataAndRecords.item,
373
- newEncounteredDataAndRecords.item,
374
- );
375
-
376
- logMessage(environment, () => ({
377
- kind: 'DeepEqualityCheck',
378
- fragmentReference: subscription.fragmentReference,
379
- old: subscription.encounteredDataAndRecords.item,
380
- new: newEncounteredDataAndRecords.item,
381
- deeplyEqual: mergedItem === subscription.encounteredDataAndRecords.item,
382
- }));
383
-
384
- if (mergedItem !== subscription.encounteredDataAndRecords.item) {
385
- logAnyError(
386
- environment,
387
- { situation: 'calling FragmentSubscription callback' },
388
- () => {
389
- subscription.callback(newEncounteredDataAndRecords);
390
- },
391
- );
392
- subscription.encounteredDataAndRecords = newEncounteredDataAndRecords;
393
- }
394
- }
395
-
396
- function hasOverlappingIds(
397
- ids1: EncounteredIds,
398
- ids2: EncounteredIds,
399
- ): boolean {
400
- for (const [typeName, set1] of ids1.entries()) {
401
- const set2 = ids2.get(typeName);
402
- if (set2 === undefined) {
403
- continue;
404
- }
405
-
406
- if (isNotDisjointFrom(set1, set2)) {
407
- return true;
408
- }
409
- }
410
- return false;
411
- }
412
-
413
- // TODO use a polyfill library
414
- function isNotDisjointFrom<T>(set1: Set<T>, set2: Set<T>): boolean {
415
- for (const id of set1) {
416
- if (set2.has(id)) {
417
- return true;
418
- }
419
- }
420
- return false;
421
- }
422
-
423
139
  export type EncounteredIds = Map<TypeName, Set<DataId>>;
424
140
  /**
425
141
  * Mutate targetParentRecord according to the normalizationAst and networkResponseParentRecord.
@@ -531,10 +247,6 @@ function normalizeScalarField(
531
247
  }
532
248
  }
533
249
 
534
- export function isArray(value: unknown): value is readonly unknown[] {
535
- return Array.isArray(value);
536
- }
537
-
538
250
  /**
539
251
  * Mutate targetParentRecord with a given linked field ast node.
540
252
  */
@@ -926,61 +638,3 @@ function getDataIdOfNetworkResponse(
926
638
  }
927
639
  return storeKey;
928
640
  }
929
-
930
- export function writeData<
931
- TReadFromStore extends UnknownTReadFromStore,
932
- TRawResponseType extends NetworkResponseObject,
933
- TClientFieldValue,
934
- >(
935
- environment: IsographEnvironment,
936
- entrypoint: IsographEntrypoint<
937
- TReadFromStore,
938
- TClientFieldValue,
939
- NormalizationAst,
940
- TRawResponseType
941
- >,
942
- data: TRawResponseType,
943
- variables: ExtractParameters<TReadFromStore>,
944
- ): ItemCleanupPair<FragmentReference<TReadFromStore, TClientFieldValue>> {
945
- const encounteredIds: EncounteredIds = new Map();
946
- environment.store = addNetworkResponseStoreLayer(environment.store);
947
- normalizeData(
948
- environment,
949
- environment.store,
950
- entrypoint.networkRequestInfo.normalizationAst.selections,
951
- data,
952
- variables,
953
- { __link: ROOT_ID, __typename: entrypoint.concreteType },
954
- encounteredIds,
955
- );
956
- logMessage(environment, () => ({
957
- kind: 'AfterNormalization',
958
- store: environment.store,
959
- encounteredIds,
960
- }));
961
-
962
- callSubscriptions(environment, encounteredIds);
963
-
964
- const { fieldName, readerArtifactKind, readerWithRefetchQueries } =
965
- getOrLoadReaderWithRefetchQueries(
966
- environment,
967
- entrypoint.readerWithRefetchQueries,
968
- );
969
- const [networkRequest, disposeNetworkRequest] =
970
- retainQueryWithoutMakingNetworkRequest(environment, entrypoint, variables);
971
-
972
- return [
973
- {
974
- kind: 'FragmentReference',
975
- readerWithRefetchQueries,
976
- fieldName,
977
- readerArtifactKind,
978
- root: { __link: ROOT_ID, __typename: entrypoint.concreteType },
979
- variables,
980
- networkRequest,
981
- },
982
- () => {
983
- disposeNetworkRequest();
984
- },
985
- ];
986
- }
@@ -1,13 +1,9 @@
1
- import { useReadAndSubscribe } from '../react/useReadAndSubscribe';
2
- import { maybeUnwrapNetworkRequest } from '../react/useResult';
3
1
  import {
4
2
  FragmentReference,
5
3
  stableIdForFragmentReference,
6
4
  } from './FragmentReference';
7
- import { IsographEnvironment } from './IsographEnvironment';
8
- import { logMessage } from './logging';
9
- import { readPromise } from './PromiseWrapper';
10
- import { NetworkRequestReaderOptions } from './read';
5
+ import type { IsographEnvironment } from './IsographEnvironment';
6
+ import type { NetworkRequestReaderOptions } from './read';
11
7
  import { createStartUpdate } from './startUpdate';
12
8
 
13
9
  export function getOrCreateCachedComponent(
@@ -24,41 +20,10 @@ export function getOrCreateCachedComponent(
24
20
 
25
21
  return (environment.componentCache[
26
22
  stableIdForFragmentReference(fragmentReference)
27
- ] ??= (() => {
28
- function Component(additionalRuntimeProps: { [key: string]: any }) {
29
- maybeUnwrapNetworkRequest(
30
- fragmentReference.networkRequest,
31
- networkRequestOptions,
32
- );
33
- const readerWithRefetchQueries = readPromise(
34
- fragmentReference.readerWithRefetchQueries,
35
- );
36
-
37
- const data = useReadAndSubscribe(
38
- fragmentReference,
39
- networkRequestOptions,
40
- readerWithRefetchQueries.readerArtifact.readerAst,
41
- );
42
-
43
- logMessage(environment, () => ({
44
- kind: 'ComponentRerendered',
45
- componentName: fragmentReference.fieldName,
46
- rootLink: fragmentReference.root,
47
- }));
48
-
49
- return readerWithRefetchQueries.readerArtifact.resolver(
50
- {
51
- data,
52
- parameters: fragmentReference.variables,
53
- startUpdate: readerWithRefetchQueries.readerArtifact.hasUpdatable
54
- ? startUpdate
55
- : undefined,
56
- },
57
- additionalRuntimeProps,
58
- );
59
- }
60
- const idString = `(type: ${fragmentReference.root.__typename}, id: ${fragmentReference.root.__link})`;
61
- Component.displayName = `${fragmentReference.fieldName} ${idString} @component`;
62
- return Component;
63
- })());
23
+ ] ??= environment.componentFunction(
24
+ environment,
25
+ fragmentReference,
26
+ networkRequestOptions,
27
+ startUpdate,
28
+ ));
64
29
  }
@@ -5,8 +5,8 @@ import type {
5
5
  UnknownTReadFromStore,
6
6
  } from './FragmentReference';
7
7
  import type { ComponentOrFieldName, TypeName } from './IsographEnvironment';
8
- import { TopLevelReaderArtifact } from './reader';
9
- import { Arguments } from './util';
8
+ import type { TopLevelReaderArtifact } from './reader';
9
+ import type { Arguments } from './util';
10
10
 
11
11
  export type ReaderWithRefetchQueries<
12
12
  TReadFromStore extends UnknownTReadFromStore,
@@ -1,11 +1,11 @@
1
1
  import { getParentRecordKey } from './cache';
2
- import { NormalizationAstNodes, type NormalizationAst } from './entrypoint';
3
- import { Variables } from './FragmentReference';
2
+ import type { NormalizationAstNodes, NormalizationAst } from './entrypoint';
3
+ import type { Variables } from './FragmentReference';
4
4
  import {
5
5
  assertLink,
6
- DataId,
7
- IsographEnvironment,
8
- StoreRecord,
6
+ type DataId,
7
+ type IsographEnvironment,
8
+ type StoreRecord,
9
9
  type StoreLayerData,
10
10
  type StoreLink,
11
11
  type TypeName,
@@ -0,0 +1,86 @@
1
+ import type { ItemCleanupPair } from '@isograph/isograph-disposable-types/dist';
2
+ import type { ParentCache } from '@isograph/isograph-react-disposable-state/dist';
3
+ import {
4
+ type NetworkResponseObject,
5
+ getOrCreateItemInSuspenseCache,
6
+ } from './cache';
7
+ import type { FetchOptions } from './check';
8
+ import type {
9
+ IsographEntrypoint,
10
+ NormalizationAst,
11
+ NormalizationAstLoader,
12
+ } from './entrypoint';
13
+ import type {
14
+ ExtractParameters,
15
+ FragmentReference,
16
+ UnknownTReadFromStore,
17
+ } from './FragmentReference';
18
+ import {
19
+ type IsographEnvironment,
20
+ getOrLoadReaderWithRefetchQueries,
21
+ ROOT_ID,
22
+ } from './IsographEnvironment';
23
+ import { maybeMakeNetworkRequest } from './makeNetworkRequest';
24
+ import { stableCopy } from './util';
25
+
26
+ export function getOrCreateCacheForArtifact<
27
+ TReadFromStore extends UnknownTReadFromStore,
28
+ TClientFieldValue,
29
+ TNormalizationAst extends NormalizationAst | NormalizationAstLoader,
30
+ TRawResponseType extends NetworkResponseObject,
31
+ >(
32
+ environment: IsographEnvironment,
33
+ entrypoint: IsographEntrypoint<
34
+ TReadFromStore,
35
+ TClientFieldValue,
36
+ TNormalizationAst,
37
+ TRawResponseType
38
+ >,
39
+ variables: ExtractParameters<TReadFromStore>,
40
+ fetchOptions?: FetchOptions<TClientFieldValue, TRawResponseType>,
41
+ ): ParentCache<FragmentReference<TReadFromStore, TClientFieldValue>> {
42
+ let cacheKey = '';
43
+ switch (entrypoint.networkRequestInfo.operation.kind) {
44
+ case 'Operation':
45
+ cacheKey =
46
+ entrypoint.networkRequestInfo.operation.text +
47
+ JSON.stringify(stableCopy(variables));
48
+ break;
49
+ case 'PersistedOperation':
50
+ cacheKey =
51
+ entrypoint.networkRequestInfo.operation.operationId +
52
+ JSON.stringify(stableCopy(variables));
53
+ break;
54
+ }
55
+ const factory = () => {
56
+ const { fieldName, readerArtifactKind, readerWithRefetchQueries } =
57
+ getOrLoadReaderWithRefetchQueries(
58
+ environment,
59
+ entrypoint.readerWithRefetchQueries,
60
+ );
61
+ const [networkRequest, disposeNetworkRequest] = maybeMakeNetworkRequest(
62
+ environment,
63
+ entrypoint,
64
+ variables,
65
+ readerWithRefetchQueries,
66
+ fetchOptions ?? null,
67
+ );
68
+
69
+ const itemCleanupPair: ItemCleanupPair<
70
+ FragmentReference<TReadFromStore, TClientFieldValue>
71
+ > = [
72
+ {
73
+ kind: 'FragmentReference',
74
+ readerWithRefetchQueries,
75
+ fieldName,
76
+ readerArtifactKind,
77
+ root: { __link: ROOT_ID, __typename: entrypoint.concreteType },
78
+ variables,
79
+ networkRequest: networkRequest,
80
+ },
81
+ disposeNetworkRequest,
82
+ ];
83
+ return itemCleanupPair;
84
+ };
85
+ return getOrCreateItemInSuspenseCache(environment, cacheKey, factory);
86
+ }
@@ -1,19 +1,19 @@
1
- import { CleanupFn } from '@isograph/disposable-types';
2
- import { NetworkResponseObject, type EncounteredIds } from './cache';
3
- import { CheckResult } from './check';
4
- import {
1
+ import type { CleanupFn } from '@isograph/disposable-types';
2
+ import type { NetworkResponseObject, EncounteredIds } from './cache';
3
+ import type { CheckResult } from './check';
4
+ import type {
5
5
  IsographEntrypoint,
6
6
  RefetchQueryNormalizationArtifact,
7
- type NormalizationAstNodes,
7
+ NormalizationAstNodes,
8
8
  } from './entrypoint';
9
- import { FragmentReference, Variables } from './FragmentReference';
10
- import {
9
+ import type { FragmentReference, Variables } from './FragmentReference';
10
+ import type {
11
11
  IsographEnvironment,
12
12
  StoreRecord,
13
- type StoreLink,
13
+ StoreLink,
14
14
  } from './IsographEnvironment';
15
- import { ReadDataResult } from './read';
16
- import { Arguments } from './util';
15
+ import type { ReadDataResult } from './read';
16
+ import type { Arguments } from './util';
17
17
  import type { StoreLayer } from './optimisticProxy';
18
18
 
19
19
  /**
@@ -1,23 +1,22 @@
1
- import { ItemCleanupPair } from '@isograph/disposable-types';
1
+ import type { ItemCleanupPair } from '@isograph/disposable-types';
2
2
  import {
3
- callSubscriptions,
4
3
  normalizeData,
5
4
  type EncounteredIds,
6
5
  type NetworkResponseObject,
7
6
  } from './cache';
8
7
  import { check, DEFAULT_SHOULD_FETCH_VALUE, FetchOptions } from './check';
9
8
  import { getOrCreateCachedComponent } from './componentCache';
10
- import {
9
+ import type {
11
10
  IsographEntrypoint,
11
+ NormalizationAst,
12
+ NormalizationAstLoader,
12
13
  ReaderWithRefetchQueries,
13
14
  RefetchQueryNormalizationArtifact,
14
- type NormalizationAst,
15
- type NormalizationAstLoader,
16
15
  } from './entrypoint';
17
- import {
16
+ import type {
18
17
  ExtractParameters,
19
- type FragmentReference,
20
- type UnknownTReadFromStore,
18
+ FragmentReference,
19
+ UnknownTReadFromStore,
21
20
  } from './FragmentReference';
22
21
  import {
23
22
  garbageCollectEnvironment,
@@ -42,6 +41,7 @@ import {
42
41
  } from './PromiseWrapper';
43
42
  import { readButDoNotEvaluate } from './read';
44
43
  import { getOrCreateCachedStartUpdate } from './startUpdate';
44
+ import { callSubscriptions } from './subscribe';
45
45
 
46
46
  let networkRequestId = 0;
47
47
 
@@ -1,8 +1,5 @@
1
- import {
2
- callSubscriptions,
3
- insertEmptySetIfMissing,
4
- type EncounteredIds,
5
- } from './cache';
1
+ import { insertEmptySetIfMissing, type EncounteredIds } from './cache';
2
+ import { callSubscriptions } from './subscribe';
6
3
  import type {
7
4
  BaseStoreLayerData,
8
5
  IsographEnvironment,