@isograph/react 0.4.3 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (137) hide show
  1. package/.turbo/turbo-compile-libs.log +2 -2
  2. package/dist/core/FragmentReference.d.ts +4 -2
  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 +19 -11
  6. package/dist/core/IsographEnvironment.d.ts.map +1 -1
  7. package/dist/core/IsographEnvironment.js +27 -2
  8. package/dist/core/PromiseWrapper.d.ts +13 -7
  9. package/dist/core/PromiseWrapper.d.ts.map +1 -1
  10. package/dist/core/brand.d.ts +17 -0
  11. package/dist/core/brand.d.ts.map +1 -1
  12. package/dist/core/cache.d.ts +10 -7
  13. package/dist/core/cache.d.ts.map +1 -1
  14. package/dist/core/cache.js +102 -74
  15. package/dist/core/check.d.ts +8 -4
  16. package/dist/core/check.d.ts.map +1 -1
  17. package/dist/core/check.js +10 -7
  18. package/dist/core/componentCache.d.ts +1 -1
  19. package/dist/core/componentCache.d.ts.map +1 -1
  20. package/dist/core/componentCache.js +6 -4
  21. package/dist/core/entrypoint.d.ts +17 -7
  22. package/dist/core/entrypoint.d.ts.map +1 -1
  23. package/dist/core/garbageCollection.d.ts +8 -2
  24. package/dist/core/garbageCollection.d.ts.map +1 -1
  25. package/dist/core/garbageCollection.js +36 -14
  26. package/dist/core/logging.d.ts +16 -3
  27. package/dist/core/logging.d.ts.map +1 -1
  28. package/dist/core/makeNetworkRequest.d.ts +4 -2
  29. package/dist/core/makeNetworkRequest.d.ts.map +1 -1
  30. package/dist/core/makeNetworkRequest.js +115 -38
  31. package/dist/core/optimisticProxy.d.ts +59 -0
  32. package/dist/core/optimisticProxy.d.ts.map +1 -0
  33. package/dist/core/optimisticProxy.js +399 -0
  34. package/dist/core/read.d.ts +3 -2
  35. package/dist/core/read.d.ts.map +1 -1
  36. package/dist/core/read.js +158 -123
  37. package/dist/core/reader.d.ts +7 -4
  38. package/dist/core/reader.d.ts.map +1 -1
  39. package/dist/core/startUpdate.d.ts +3 -2
  40. package/dist/core/startUpdate.d.ts.map +1 -1
  41. package/dist/core/startUpdate.js +33 -34
  42. package/dist/index.d.ts +2 -2
  43. package/dist/index.d.ts.map +1 -1
  44. package/dist/index.js +2 -1
  45. package/dist/loadable-hooks/useClientSideDefer.d.ts +9 -4
  46. package/dist/loadable-hooks/useClientSideDefer.d.ts.map +1 -1
  47. package/dist/loadable-hooks/useClientSideDefer.js +34 -1
  48. package/dist/loadable-hooks/useConnectionSpecPagination.d.ts +5 -3
  49. package/dist/loadable-hooks/useConnectionSpecPagination.d.ts.map +1 -1
  50. package/dist/loadable-hooks/useConnectionSpecPagination.js +27 -13
  51. package/dist/loadable-hooks/useImperativeLoadableField.d.ts +1 -1
  52. package/dist/loadable-hooks/useImperativeLoadableField.d.ts.map +1 -1
  53. package/dist/loadable-hooks/useSkipLimitPagination.d.ts +1 -1
  54. package/dist/loadable-hooks/useSkipLimitPagination.d.ts.map +1 -1
  55. package/dist/loadable-hooks/useSkipLimitPagination.js +1 -1
  56. package/dist/react/FragmentReader.d.ts +2 -1
  57. package/dist/react/FragmentReader.d.ts.map +1 -1
  58. package/dist/react/FragmentRenderer.d.ts +2 -1
  59. package/dist/react/FragmentRenderer.d.ts.map +1 -1
  60. package/dist/react/LoadableFieldReader.d.ts +9 -3
  61. package/dist/react/LoadableFieldReader.d.ts.map +1 -1
  62. package/dist/react/LoadableFieldReader.js +40 -1
  63. package/dist/react/LoadableFieldRenderer.d.ts +9 -3
  64. package/dist/react/LoadableFieldRenderer.d.ts.map +1 -1
  65. package/dist/react/LoadableFieldRenderer.js +36 -1
  66. package/dist/react/useImperativeReference.d.ts +4 -3
  67. package/dist/react/useImperativeReference.d.ts.map +1 -1
  68. package/dist/react/useImperativeReference.js +3 -5
  69. package/dist/react/useLazyReference.d.ts +2 -1
  70. package/dist/react/useLazyReference.d.ts.map +1 -1
  71. package/dist/react/useReadAndSubscribe.d.ts.map +1 -1
  72. package/dist/react/useReadAndSubscribe.js +1 -3
  73. package/dist/react/useResult.d.ts.map +1 -1
  74. package/dist/react/useResult.js +6 -5
  75. package/package.json +16 -17
  76. package/src/core/FragmentReference.ts +10 -4
  77. package/src/core/IsographEnvironment.ts +59 -13
  78. package/src/core/PromiseWrapper.ts +14 -7
  79. package/src/core/brand.ts +18 -0
  80. package/src/core/cache.ts +186 -91
  81. package/src/core/check.ts +21 -10
  82. package/src/core/componentCache.ts +8 -4
  83. package/src/core/entrypoint.ts +35 -6
  84. package/src/core/garbageCollection.ts +61 -19
  85. package/src/core/logging.ts +15 -3
  86. package/src/core/makeNetworkRequest.ts +307 -74
  87. package/src/core/optimisticProxy.ts +563 -0
  88. package/src/core/read.ts +233 -163
  89. package/src/core/reader.ts +10 -6
  90. package/src/core/startUpdate.ts +45 -30
  91. package/src/index.ts +2 -1
  92. package/src/loadable-hooks/useClientSideDefer.ts +76 -26
  93. package/src/loadable-hooks/useConnectionSpecPagination.ts +34 -17
  94. package/src/loadable-hooks/useImperativeLoadableField.ts +2 -2
  95. package/src/loadable-hooks/useSkipLimitPagination.ts +2 -3
  96. package/src/react/FragmentReader.tsx +3 -1
  97. package/src/react/FragmentRenderer.tsx +8 -1
  98. package/src/react/LoadableFieldReader.tsx +123 -12
  99. package/src/react/LoadableFieldRenderer.tsx +122 -12
  100. package/src/react/useImperativeReference.ts +20 -11
  101. package/src/react/useLazyReference.ts +17 -6
  102. package/src/react/useReadAndSubscribe.ts +1 -8
  103. package/src/react/useResult.ts +9 -11
  104. package/src/tests/__isograph/Node/asEconomist/resolver_reader.ts +1 -1
  105. package/src/tests/__isograph/Query/linkedUpdate/entrypoint.ts +3 -1
  106. package/src/tests/__isograph/Query/linkedUpdate/raw_response_type.ts +13 -0
  107. package/src/tests/__isograph/Query/linkedUpdate/resolver_reader.ts +1 -1
  108. package/src/tests/__isograph/Query/meName/entrypoint.ts +3 -1
  109. package/src/tests/__isograph/Query/meName/raw_response_type.ts +7 -0
  110. package/src/tests/__isograph/Query/meName/resolver_reader.ts +1 -1
  111. package/src/tests/__isograph/Query/meNameSuccessor/entrypoint.ts +3 -1
  112. package/src/tests/__isograph/Query/meNameSuccessor/raw_response_type.ts +14 -0
  113. package/src/tests/__isograph/Query/meNameSuccessor/resolver_reader.ts +1 -1
  114. package/src/tests/__isograph/Query/nodeField/entrypoint.ts +3 -1
  115. package/src/tests/__isograph/Query/nodeField/raw_response_type.ts +7 -0
  116. package/src/tests/__isograph/Query/nodeField/resolver_reader.ts +1 -1
  117. package/src/tests/__isograph/Query/normalizeUndefinedField/entrypoint.ts +33 -0
  118. package/src/tests/__isograph/Query/normalizeUndefinedField/normalization_ast.ts +25 -0
  119. package/src/tests/__isograph/Query/normalizeUndefinedField/output_type.ts +3 -0
  120. package/src/tests/__isograph/Query/normalizeUndefinedField/param_type.ts +9 -0
  121. package/src/tests/__isograph/Query/normalizeUndefinedField/query_text.ts +6 -0
  122. package/src/tests/__isograph/Query/normalizeUndefinedField/raw_response_type.ts +7 -0
  123. package/src/tests/__isograph/Query/normalizeUndefinedField/resolver_reader.ts +38 -0
  124. package/src/tests/__isograph/Query/startUpdate/entrypoint.ts +3 -1
  125. package/src/tests/__isograph/Query/startUpdate/raw_response_type.ts +8 -0
  126. package/src/tests/__isograph/Query/startUpdate/resolver_reader.ts +1 -1
  127. package/src/tests/__isograph/Query/subquery/entrypoint.ts +3 -1
  128. package/src/tests/__isograph/Query/subquery/raw_response_type.ts +9 -0
  129. package/src/tests/__isograph/Query/subquery/resolver_reader.ts +1 -1
  130. package/src/tests/__isograph/iso.ts +11 -1
  131. package/src/tests/garbageCollection.test.ts +8 -5
  132. package/src/tests/meNameSuccessor.ts +6 -3
  133. package/src/tests/nodeQuery.ts +4 -2
  134. package/src/tests/normalizeData.test.ts +89 -15
  135. package/src/tests/optimisticProxy.test.ts +860 -0
  136. package/src/tests/startUpdate.test.ts +7 -5
  137. package/src/tests/__isograph/Economist/__link/output_type.ts +0 -2
@@ -1,5 +1,7 @@
1
+ import type { Contravariant, PhantomData } from './brand';
2
+ import type { NetworkResponseObject } from './cache';
1
3
  import type { UnknownTReadFromStore } from './FragmentReference';
2
- import type { TypeName } from './IsographEnvironment';
4
+ import type { ComponentOrFieldName, TypeName } from './IsographEnvironment';
3
5
  import { TopLevelReaderArtifact } from './reader';
4
6
  import { Arguments } from './util';
5
7
 
@@ -22,6 +24,10 @@ export type ReaderWithRefetchQueriesLoader<
22
24
  TClientFieldValue,
23
25
  > = {
24
26
  readonly kind: 'ReaderWithRefetchQueriesLoader';
27
+ readonly fieldName: ComponentOrFieldName;
28
+ readonly readerArtifactKind:
29
+ | 'EagerReaderArtifact'
30
+ | 'ComponentReaderArtifact';
25
31
  readonly loader: () => Promise<
26
32
  ReaderWithRefetchQueries<TReadFromStore, TClientFieldValue>
27
33
  >;
@@ -55,6 +61,7 @@ export type IsographEntrypoint<
55
61
  TReadFromStore extends UnknownTReadFromStore,
56
62
  TClientFieldValue,
57
63
  TNormalizationAst extends NormalizationAst | NormalizationAstLoader,
64
+ TRawResponseType extends NetworkResponseObject,
58
65
  > = {
59
66
  readonly kind: 'Entrypoint';
60
67
  readonly networkRequestInfo: NetworkRequestInfo<TNormalizationAst>;
@@ -62,16 +69,29 @@ export type IsographEntrypoint<
62
69
  | ReaderWithRefetchQueries<TReadFromStore, TClientFieldValue>
63
70
  | ReaderWithRefetchQueriesLoader<TReadFromStore, TClientFieldValue>;
64
71
  readonly concreteType: TypeName;
72
+ /**
73
+ * This field exists solely for typechecking, and will not exist at runtime.
74
+ */
75
+ readonly '~TRawResponseType'?: PhantomData<Contravariant<TRawResponseType>>;
65
76
  };
66
77
 
67
78
  export type IsographEntrypointLoader<
68
79
  TReadFromStore extends UnknownTReadFromStore,
69
80
  TClientFieldValue,
81
+ TRawResponseType extends NetworkResponseObject,
70
82
  > = {
71
83
  readonly kind: 'EntrypointLoader';
72
84
  readonly typeAndField: string;
85
+ readonly readerArtifactKind:
86
+ | 'EagerReaderArtifact'
87
+ | 'ComponentReaderArtifact';
73
88
  readonly loader: () => Promise<
74
- IsographEntrypoint<TReadFromStore, TClientFieldValue, NormalizationAst>
89
+ IsographEntrypoint<
90
+ TReadFromStore,
91
+ TClientFieldValue,
92
+ NormalizationAst,
93
+ TRawResponseType
94
+ >
75
95
  >;
76
96
  };
77
97
 
@@ -129,9 +149,15 @@ export function assertIsEntrypoint<
129
149
  TReadFromStore extends UnknownTReadFromStore,
130
150
  TClientFieldValue,
131
151
  TNormalizationAst extends NormalizationAst | NormalizationAstLoader,
152
+ TRawResponseType extends NetworkResponseObject,
132
153
  >(
133
154
  value:
134
- | IsographEntrypoint<TReadFromStore, TClientFieldValue, TNormalizationAst>
155
+ | IsographEntrypoint<
156
+ TReadFromStore,
157
+ TClientFieldValue,
158
+ TNormalizationAst,
159
+ TRawResponseType
160
+ >
135
161
  | ((_: any) => any)
136
162
  // Temporarily, allow any here. Once we automatically provide
137
163
  // types to entrypoints, we probably don't need this.
@@ -139,13 +165,16 @@ export function assertIsEntrypoint<
139
165
  ): asserts value is IsographEntrypoint<
140
166
  TReadFromStore,
141
167
  TClientFieldValue,
142
- TNormalizationAst
168
+ TNormalizationAst,
169
+ TRawResponseType
143
170
  > {
144
171
  if (typeof value === 'function') throw new Error('Not a string');
145
172
  }
146
173
 
147
174
  export type ExtractReadFromStore<Type> =
148
- Type extends IsographEntrypoint<infer X, any, any> ? X : never;
175
+ Type extends IsographEntrypoint<infer X, any, any, any> ? X : never;
176
+ export type ExtractRawResponseType<Type> =
177
+ Type extends IsographEntrypoint<any, any, any, infer X> ? X : never;
149
178
  export type ExtractResolverResult<Type> =
150
- Type extends IsographEntrypoint<any, infer X, any> ? X : never;
179
+ Type extends IsographEntrypoint<any, infer X, any, any> ? X : never;
151
180
  export type ExtractProps<Type> = Type extends React.FC<infer X> ? X : never;
@@ -1,22 +1,41 @@
1
1
  import { getParentRecordKey } from './cache';
2
- import { NormalizationAstNodes } from './entrypoint';
2
+ import { NormalizationAstNodes, type NormalizationAst } from './entrypoint';
3
3
  import { Variables } from './FragmentReference';
4
4
  import {
5
5
  assertLink,
6
6
  DataId,
7
7
  IsographEnvironment,
8
- IsographStore,
9
8
  StoreRecord,
9
+ type StoreLayerData,
10
10
  type StoreLink,
11
11
  type TypeName,
12
12
  } from './IsographEnvironment';
13
+ import type { BaseStoreLayer } from './optimisticProxy';
14
+ import {
15
+ NOT_SET,
16
+ type PromiseWrapper,
17
+ type PromiseWrapperOk,
18
+ } from './PromiseWrapper';
13
19
 
14
20
  export type RetainedQuery = {
15
- readonly normalizationAst: NormalizationAstNodes;
21
+ readonly normalizationAst: PromiseWrapper<NormalizationAst>;
16
22
  readonly variables: {};
17
23
  readonly root: StoreLink;
18
24
  };
19
25
 
26
+ export interface RetainedQueryWithNormalizationAst extends RetainedQuery {
27
+ readonly normalizationAst: PromiseWrapperOk<NormalizationAst>;
28
+ }
29
+
30
+ function isRetainedQueryWithNormalizationAst(
31
+ query: RetainedQuery,
32
+ ): query is RetainedQueryWithNormalizationAst {
33
+ return (
34
+ query.normalizationAst.result !== NOT_SET &&
35
+ query.normalizationAst.result.kind === 'Ok'
36
+ );
37
+ }
38
+
20
39
  export type DidUnretainSomeQuery = boolean;
21
40
  export function unretainQuery(
22
41
  environment: IsographEnvironment,
@@ -44,23 +63,46 @@ export function retainQuery(
44
63
  }
45
64
 
46
65
  export function garbageCollectEnvironment(environment: IsographEnvironment) {
47
- const retainedIds: RetainedIds = {};
66
+ if (environment.store.kind !== 'BaseStoreLayer') {
67
+ return;
68
+ }
48
69
 
70
+ const retainedQueries: RetainedQueryWithNormalizationAst[] = [];
49
71
  for (const query of environment.retainedQueries) {
50
- recordReachableIds(environment.store, query, retainedIds);
72
+ if (!isRetainedQueryWithNormalizationAst(query)) {
73
+ return;
74
+ }
75
+ retainedQueries.push(query);
51
76
  }
77
+
52
78
  for (const query of environment.gcBuffer) {
53
- recordReachableIds(environment.store, query, retainedIds);
79
+ if (!isRetainedQueryWithNormalizationAst(query)) {
80
+ return;
81
+ }
82
+ retainedQueries.push(query);
54
83
  }
55
84
 
56
- for (const typeName in environment.store) {
57
- const dataById = environment.store[typeName];
85
+ garbageCollectBaseStoreLayer(retainedQueries, environment.store);
86
+ }
87
+
88
+ export function garbageCollectBaseStoreLayer(
89
+ retainedQueries: RetainedQueryWithNormalizationAst[],
90
+ baseStoreLayer: BaseStoreLayer,
91
+ ) {
92
+ const retainedIds: RetainedIds = {};
93
+
94
+ for (const query of retainedQueries) {
95
+ recordReachableIds(baseStoreLayer.data, query, retainedIds);
96
+ }
97
+
98
+ for (const typeName in baseStoreLayer.data) {
99
+ const dataById = baseStoreLayer.data[typeName];
58
100
  if (dataById == null) continue;
59
101
  const retainedTypeIds = retainedIds[typeName];
60
102
 
61
103
  // delete all objects
62
104
  if (retainedTypeIds == undefined || retainedTypeIds.size == 0) {
63
- delete environment.store[typeName];
105
+ delete baseStoreLayer.data[typeName];
64
106
  continue;
65
107
  }
66
108
 
@@ -71,7 +113,7 @@ export function garbageCollectEnvironment(environment: IsographEnvironment) {
71
113
  }
72
114
 
73
115
  if (Object.keys(dataById).length === 0) {
74
- delete environment.store[typeName];
116
+ delete baseStoreLayer.data[typeName];
75
117
  }
76
118
  }
77
119
  }
@@ -81,12 +123,12 @@ interface RetainedIds {
81
123
  }
82
124
 
83
125
  function recordReachableIds(
84
- store: IsographStore,
85
- retainedQuery: RetainedQuery,
126
+ dataLayer: StoreLayerData,
127
+ retainedQuery: RetainedQueryWithNormalizationAst,
86
128
  mutableRetainedIds: RetainedIds,
87
129
  ) {
88
130
  const record =
89
- store[retainedQuery.root.__typename]?.[retainedQuery.root.__link];
131
+ dataLayer[retainedQuery.root.__typename]?.[retainedQuery.root.__link];
90
132
 
91
133
  const retainedRecordsIds = (mutableRetainedIds[
92
134
  retainedQuery.root.__typename
@@ -95,17 +137,17 @@ function recordReachableIds(
95
137
 
96
138
  if (record) {
97
139
  recordReachableIdsFromRecord(
98
- store,
140
+ dataLayer,
99
141
  record,
100
142
  mutableRetainedIds,
101
- retainedQuery.normalizationAst,
143
+ retainedQuery.normalizationAst.result.value.selections,
102
144
  retainedQuery.variables,
103
145
  );
104
146
  }
105
147
  }
106
148
 
107
149
  function recordReachableIdsFromRecord(
108
- store: IsographStore,
150
+ dataLayer: StoreLayerData,
109
151
  currentRecord: StoreRecord,
110
152
  mutableRetainedIds: RetainedIds,
111
153
  selections: NormalizationAstNodes,
@@ -134,7 +176,7 @@ function recordReachableIdsFromRecord(
134
176
 
135
177
  let typeStore =
136
178
  selection.concreteType !== null
137
- ? store[selection.concreteType]
179
+ ? dataLayer[selection.concreteType]
138
180
  : null;
139
181
 
140
182
  if (typeStore == null && selection.concreteType !== null) {
@@ -144,7 +186,7 @@ function recordReachableIdsFromRecord(
144
186
  for (const nextRecordLink of links) {
145
187
  let __typename = nextRecordLink.__typename;
146
188
 
147
- const resolvedTypeStore = typeStore ?? store[__typename];
189
+ const resolvedTypeStore = typeStore ?? dataLayer[__typename];
148
190
 
149
191
  if (resolvedTypeStore == null) {
150
192
  continue;
@@ -156,7 +198,7 @@ function recordReachableIdsFromRecord(
156
198
  new Set());
157
199
  retainedRecordsIds.add(nextRecordLink.__link);
158
200
  recordReachableIdsFromRecord(
159
- store,
201
+ dataLayer,
160
202
  nextRecord,
161
203
  mutableRetainedIds,
162
204
  selection.selections,
@@ -9,13 +9,25 @@ import {
9
9
  import { FragmentReference, Variables } from './FragmentReference';
10
10
  import {
11
11
  IsographEnvironment,
12
- IsographStore,
13
12
  StoreRecord,
14
13
  type StoreLink,
15
14
  } from './IsographEnvironment';
16
15
  import { ReadDataResult } from './read';
17
16
  import { Arguments } from './util';
17
+ import type { StoreLayer } from './optimisticProxy';
18
18
 
19
+ /**
20
+ * Note: these types are unstable. We will add and remove items from this enum
21
+ * and add and remove fields. Please do not rely on the specifics here (for now).
22
+ *
23
+ * Goals include:
24
+ * - convenient debugging for Isograph developers
25
+ * - eventual support for the Isograph devtools
26
+ *
27
+ * In some cases (e.g. in `AfterNormalization`), we include large objects and thus
28
+ * prevent them from getting garbage collected (if the log message is printed).
29
+ * Especially in cases like that, we intend to remove those!
30
+ */
19
31
  export type LogMessage =
20
32
  | {
21
33
  kind: 'AboutToNormalize';
@@ -25,7 +37,7 @@ export type LogMessage =
25
37
  }
26
38
  | {
27
39
  kind: 'AfterNormalization';
28
- store: IsographStore;
40
+ store: StoreLayer;
29
41
  encounteredIds: EncounteredIds;
30
42
  }
31
43
  | {
@@ -44,7 +56,7 @@ export type LogMessage =
44
56
  kind: 'MakeNetworkRequest';
45
57
  artifact:
46
58
  | RefetchQueryNormalizationArtifact
47
- | IsographEntrypoint<any, any, any>;
59
+ | IsographEntrypoint<any, any, any, any>;
48
60
  variables: Variables;
49
61
  networkRequestId: string;
50
62
  }