@isograph/react 0.0.0-main-366b2007 → 0.0.0-main-df52a61c

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.
@@ -11,11 +11,6 @@ type UseSkipLimitReturnValue<TArgs, TItem> = {
11
11
  readonly results: ReadonlyArray<TItem>;
12
12
  readonly pendingFragment: FragmentReference<any, ReadonlyArray<TItem>>;
13
13
  };
14
- /**
15
- * NOTE: this hook does not subscribe to changes. This is a known
16
- * issue. If you are running into this issue, reach out on GitHub/
17
- * Twitter, and we'll fix the issue.
18
- */
19
14
  export declare function useSkipLimitPagination<TArgs extends {
20
15
  skip: number | void | null;
21
16
  limit: number | void | null;
@@ -9,6 +9,7 @@ const react_1 = require("react");
9
9
  const react_disposable_state_1 = require("@isograph/react-disposable-state");
10
10
  const reference_counted_pointer_1 = require("@isograph/reference-counted-pointer");
11
11
  const PromiseWrapper_1 = require("../core/PromiseWrapper");
12
+ const useReadAndSubscribe_1 = require("../react/useReadAndSubscribe");
12
13
  function flatten(arr) {
13
14
  let outArray = [];
14
15
  for (const subarr of arr) {
@@ -18,11 +19,6 @@ function flatten(arr) {
18
19
  }
19
20
  return outArray;
20
21
  }
21
- /**
22
- * NOTE: this hook does not subscribe to changes. This is a known
23
- * issue. If you are running into this issue, reach out on GitHub/
24
- * Twitter, and we'll fix the issue.
25
- */
26
22
  function useSkipLimitPagination(loadableField) {
27
23
  const networkRequestOptions = {
28
24
  suspendIfInFlight: true,
@@ -33,19 +29,10 @@ function useSkipLimitPagination(loadableField) {
33
29
  // TODO move this out of useSkipLimitPagination, and pass environment and networkRequestOptions
34
30
  // as parameters (or recreate networkRequestOptions)
35
31
  function readCompletedFragmentReferences(completedReferences) {
36
- // In general, this will not suspend. But it could, if there is missing data.
37
- // A better version of this hook would not do any reading here.
38
- const results = completedReferences.map(([pointer]) => {
39
- const fragmentReference = pointer.getItemIfNotDisposed();
40
- if (fragmentReference == null) {
41
- throw new Error('FragmentReference is unexpectedly disposed. \
42
- This is indicative of a bug in Isograph.');
43
- }
44
- (0, useResult_1.maybeUnwrapNetworkRequest)(fragmentReference.networkRequest, networkRequestOptions);
45
- const data = (0, read_1.readButDoNotEvaluate)(environment, fragmentReference, networkRequestOptions);
32
+ const results = completedReferences.map((fragmentReference, i) => {
46
33
  const readerWithRefetchQueries = (0, PromiseWrapper_1.readPromise)(fragmentReference.readerWithRefetchQueries);
47
34
  const firstParameter = {
48
- data: data.item,
35
+ data: readOutDataAndRecords[i].item,
49
36
  parameters: fragmentReference.variables,
50
37
  };
51
38
  if (readerWithRefetchQueries.readerArtifact.kind !== 'EagerReaderArtifact') {
@@ -56,6 +43,20 @@ function useSkipLimitPagination(loadableField) {
56
43
  const items = flatten(results);
57
44
  return items;
58
45
  }
46
+ function subscribeCompletedFragmentReferences(completedReferences) {
47
+ return completedReferences.map((fragmentReference, i) => {
48
+ (0, useResult_1.maybeUnwrapNetworkRequest)(fragmentReference.networkRequest, networkRequestOptions);
49
+ const readerWithRefetchQueries = (0, PromiseWrapper_1.readPromise)(fragmentReference.readerWithRefetchQueries);
50
+ return {
51
+ fragmentReference,
52
+ readerAst: readerWithRefetchQueries.readerArtifact.readerAst,
53
+ records: readOutDataAndRecords[i],
54
+ callback(_data) {
55
+ rerender({});
56
+ },
57
+ };
58
+ });
59
+ }
59
60
  const getFetchMore = (loadedSoFar) => (args, count) => {
60
61
  // @ts-expect-error
61
62
  const loadedField = loadableField(Object.assign(Object.assign({}, args), { skip: loadedSoFar, limit: count }))[1]();
@@ -81,23 +82,36 @@ function useSkipLimitPagination(loadableField) {
81
82
  };
82
83
  const [, rerender] = (0, react_1.useState)({});
83
84
  const loadedReferences = state === react_disposable_state_1.UNASSIGNED_STATE ? [] : state;
84
- if (loadedReferences.length === 0) {
85
+ const mostRecentItem = loadedReferences[loadedReferences.length - 1];
86
+ const mostRecentFragmentReference = mostRecentItem === null || mostRecentItem === void 0 ? void 0 : mostRecentItem[0].getItemIfNotDisposed();
87
+ if (mostRecentItem && mostRecentFragmentReference === null) {
88
+ throw new Error('FragmentReference is unexpectedly disposed. \
89
+ This is indicative of a bug in Isograph.');
90
+ }
91
+ const networkRequestStatus = mostRecentFragmentReference &&
92
+ (0, PromiseWrapper_1.getPromiseState)(mostRecentFragmentReference.networkRequest);
93
+ const slicedFragmentReferences = (networkRequestStatus === null || networkRequestStatus === void 0 ? void 0 : networkRequestStatus.kind) === 'Ok'
94
+ ? loadedReferences
95
+ : loadedReferences.slice(0, loadedReferences.length - 1);
96
+ const completedFragmentReferences = slicedFragmentReferences.map(([pointer]) => {
97
+ const fragmentReference = pointer.getItemIfNotDisposed();
98
+ if (fragmentReference == null) {
99
+ throw new Error('FragmentReference is unexpectedly disposed. \
100
+ This is indicative of a bug in Isograph.');
101
+ }
102
+ return fragmentReference;
103
+ });
104
+ const readOutDataAndRecords = completedFragmentReferences.map((fragmentReference) => (0, read_1.readButDoNotEvaluate)(environment, fragmentReference, networkRequestOptions));
105
+ (0, useReadAndSubscribe_1.useSubscribeToMultiple)(subscribeCompletedFragmentReferences(completedFragmentReferences));
106
+ if (!networkRequestStatus) {
85
107
  return {
86
108
  kind: 'Complete',
87
109
  fetchMore: getFetchMore(0),
88
110
  results: [],
89
111
  };
90
112
  }
91
- const mostRecentItem = loadedReferences[loadedReferences.length - 1];
92
- const mostRecentFragmentReference = mostRecentItem[0].getItemIfNotDisposed();
93
- if (mostRecentFragmentReference === null) {
94
- throw new Error('FragmentReference is unexpectedly disposed. \
95
- This is indicative of a bug in Isograph.');
96
- }
97
- const networkRequestStatus = (0, PromiseWrapper_1.getPromiseState)(mostRecentFragmentReference.networkRequest);
98
113
  switch (networkRequestStatus.kind) {
99
114
  case 'Pending': {
100
- const completedFragmentReferences = loadedReferences.slice(0, loadedReferences.length - 1);
101
115
  const unsubscribe = (0, cache_1.subscribeToAnyChange)(environment, () => {
102
116
  unsubscribe();
103
117
  rerender({});
@@ -112,7 +126,7 @@ function useSkipLimitPagination(loadableField) {
112
126
  throw networkRequestStatus.error;
113
127
  }
114
128
  case 'Ok': {
115
- const results = readCompletedFragmentReferences(loadedReferences);
129
+ const results = readCompletedFragmentReferences(completedFragmentReferences);
116
130
  return {
117
131
  kind: 'Complete',
118
132
  results,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@isograph/react",
3
- "version": "0.0.0-main-366b2007",
3
+ "version": "0.0.0-main-df52a61c",
4
4
  "description": "Use Isograph with React",
5
5
  "homepage": "https://isograph.dev",
6
6
  "main": "dist/index.js",
@@ -17,9 +17,9 @@
17
17
  "tsc": "tsc"
18
18
  },
19
19
  "dependencies": {
20
- "@isograph/disposable-types": "0.0.0-main-366b2007",
21
- "@isograph/react-disposable-state": "0.0.0-main-366b2007",
22
- "@isograph/reference-counted-pointer": "0.0.0-main-366b2007"
20
+ "@isograph/disposable-types": "0.0.0-main-df52a61c",
21
+ "@isograph/react-disposable-state": "0.0.0-main-df52a61c",
22
+ "@isograph/reference-counted-pointer": "0.0.0-main-df52a61c"
23
23
  },
24
24
  "peerDependencies": {
25
25
  "react": "18.2.0"
@@ -1,4 +1,4 @@
1
- import { LoadableField } from '../core/reader';
1
+ import { LoadableField, type ReaderAst } from '../core/reader';
2
2
  import { useIsographEnvironment } from '../react/IsographEnvironmentProvider';
3
3
  import { ItemCleanupPair } from '@isograph/disposable-types';
4
4
  import { FragmentReference } from '../core/FragmentReference';
@@ -15,6 +15,8 @@ import {
15
15
  ReferenceCountedPointer,
16
16
  } from '@isograph/reference-counted-pointer';
17
17
  import { getPromiseState, readPromise } from '../core/PromiseWrapper';
18
+ import { type WithEncounteredRecords } from '../core/read';
19
+ import { useSubscribeToMultiple } from '../react/useReadAndSubscribe';
18
20
 
19
21
  type SkipOrLimit = 'skip' | 'limit';
20
22
  type OmitSkipLimit<TArgs> = keyof Omit<TArgs, SkipOrLimit> extends never
@@ -41,10 +43,13 @@ type ArrayFragmentReference<
41
43
  type LoadedFragmentReferences<
42
44
  TReadFromStore extends Object,
43
45
  TItem,
44
- > = ReadonlyArray<
45
- ItemCleanupPair<
46
- ReferenceCountedPointer<ArrayFragmentReference<TReadFromStore, TItem>>
47
- >
46
+ > = ReadonlyArray<LoadedFragmentReference<TReadFromStore, TItem>>;
47
+
48
+ type LoadedFragmentReference<
49
+ TReadFromStore extends Object,
50
+ TItem,
51
+ > = ItemCleanupPair<
52
+ ReferenceCountedPointer<ArrayFragmentReference<TReadFromStore, TItem>>
48
53
  >;
49
54
 
50
55
  function flatten<T>(arr: ReadonlyArray<ReadonlyArray<T>>): ReadonlyArray<T> {
@@ -57,11 +62,6 @@ function flatten<T>(arr: ReadonlyArray<ReadonlyArray<T>>): ReadonlyArray<T> {
57
62
  return outArray;
58
63
  }
59
64
 
60
- /**
61
- * NOTE: this hook does not subscribe to changes. This is a known
62
- * issue. If you are running into this issue, reach out on GitHub/
63
- * Twitter, and we'll fix the issue.
64
- */
65
65
  export function useSkipLimitPagination<
66
66
  TArgs extends {
67
67
  skip: number | void | null;
@@ -86,39 +86,15 @@ export function useSkipLimitPagination<
86
86
  // TODO move this out of useSkipLimitPagination, and pass environment and networkRequestOptions
87
87
  // as parameters (or recreate networkRequestOptions)
88
88
  function readCompletedFragmentReferences(
89
- completedReferences: ReadonlyArray<
90
- ItemCleanupPair<
91
- ReferenceCountedPointer<ArrayFragmentReference<TReadFromStore, TItem>>
92
- >
93
- >,
89
+ completedReferences: ArrayFragmentReference<TReadFromStore, TItem>[],
94
90
  ) {
95
- // In general, this will not suspend. But it could, if there is missing data.
96
- // A better version of this hook would not do any reading here.
97
- const results = completedReferences.map(([pointer]) => {
98
- const fragmentReference = pointer.getItemIfNotDisposed();
99
- if (fragmentReference == null) {
100
- throw new Error(
101
- 'FragmentReference is unexpectedly disposed. \
102
- This is indicative of a bug in Isograph.',
103
- );
104
- }
105
-
106
- maybeUnwrapNetworkRequest(
107
- fragmentReference.networkRequest,
108
- networkRequestOptions,
109
- );
110
- const data = readButDoNotEvaluate(
111
- environment,
112
- fragmentReference,
113
- networkRequestOptions,
114
- );
115
-
91
+ const results = completedReferences.map((fragmentReference, i) => {
116
92
  const readerWithRefetchQueries = readPromise(
117
93
  fragmentReference.readerWithRefetchQueries,
118
94
  );
119
95
 
120
96
  const firstParameter = {
121
- data: data.item,
97
+ data: readOutDataAndRecords[i].item,
122
98
  parameters: fragmentReference.variables,
123
99
  };
124
100
 
@@ -137,6 +113,42 @@ export function useSkipLimitPagination<
137
113
  return items;
138
114
  }
139
115
 
116
+ function subscribeCompletedFragmentReferences(
117
+ completedReferences: ArrayFragmentReference<TReadFromStore, TItem>[],
118
+ ) {
119
+ return completedReferences.map(
120
+ (
121
+ fragmentReference,
122
+ i,
123
+ ): {
124
+ records: WithEncounteredRecords<TReadFromStore>;
125
+ callback: (
126
+ updatedRecords: WithEncounteredRecords<TReadFromStore>,
127
+ ) => void;
128
+ fragmentReference: ArrayFragmentReference<TReadFromStore, TItem>;
129
+ readerAst: ReaderAst<TItem>;
130
+ } => {
131
+ maybeUnwrapNetworkRequest(
132
+ fragmentReference.networkRequest,
133
+ networkRequestOptions,
134
+ );
135
+
136
+ const readerWithRefetchQueries = readPromise(
137
+ fragmentReference.readerWithRefetchQueries,
138
+ );
139
+
140
+ return {
141
+ fragmentReference,
142
+ readerAst: readerWithRefetchQueries.readerArtifact.readerAst,
143
+ records: readOutDataAndRecords[i],
144
+ callback(_data) {
145
+ rerender({});
146
+ },
147
+ };
148
+ },
149
+ );
150
+ }
151
+
140
152
  const getFetchMore =
141
153
  (loadedSoFar: number) =>
142
154
  (args: OmitSkipLimit<TArgs>, count: number): void => {
@@ -182,33 +194,64 @@ export function useSkipLimitPagination<
182
194
  const [, rerender] = useState({});
183
195
 
184
196
  const loadedReferences = state === UNASSIGNED_STATE ? [] : state;
185
- if (loadedReferences.length === 0) {
186
- return {
187
- kind: 'Complete',
188
- fetchMore: getFetchMore(0),
189
- results: [],
190
- };
191
- }
192
197
 
193
- const mostRecentItem = loadedReferences[loadedReferences.length - 1];
194
- const mostRecentFragmentReference = mostRecentItem[0].getItemIfNotDisposed();
195
- if (mostRecentFragmentReference === null) {
198
+ const mostRecentItem: LoadedFragmentReference<TReadFromStore, TItem> | null =
199
+ loadedReferences[loadedReferences.length - 1];
200
+ const mostRecentFragmentReference =
201
+ mostRecentItem?.[0].getItemIfNotDisposed();
202
+
203
+ if (mostRecentItem && mostRecentFragmentReference === null) {
196
204
  throw new Error(
197
205
  'FragmentReference is unexpectedly disposed. \
198
206
  This is indicative of a bug in Isograph.',
199
207
  );
200
208
  }
201
209
 
202
- const networkRequestStatus = getPromiseState(
203
- mostRecentFragmentReference.networkRequest,
210
+ const networkRequestStatus =
211
+ mostRecentFragmentReference &&
212
+ getPromiseState(mostRecentFragmentReference.networkRequest);
213
+
214
+ const slicedFragmentReferences =
215
+ networkRequestStatus?.kind === 'Ok'
216
+ ? loadedReferences
217
+ : loadedReferences.slice(0, loadedReferences.length - 1);
218
+
219
+ const completedFragmentReferences = slicedFragmentReferences.map(
220
+ ([pointer]) => {
221
+ const fragmentReference = pointer.getItemIfNotDisposed();
222
+ if (fragmentReference == null) {
223
+ throw new Error(
224
+ 'FragmentReference is unexpectedly disposed. \
225
+ This is indicative of a bug in Isograph.',
226
+ );
227
+ }
228
+ return fragmentReference;
229
+ },
204
230
  );
231
+
232
+ const readOutDataAndRecords = completedFragmentReferences.map(
233
+ (fragmentReference) =>
234
+ readButDoNotEvaluate(
235
+ environment,
236
+ fragmentReference,
237
+ networkRequestOptions,
238
+ ),
239
+ );
240
+
241
+ useSubscribeToMultiple<TReadFromStore>(
242
+ subscribeCompletedFragmentReferences(completedFragmentReferences),
243
+ );
244
+
245
+ if (!networkRequestStatus) {
246
+ return {
247
+ kind: 'Complete',
248
+ fetchMore: getFetchMore(0),
249
+ results: [],
250
+ };
251
+ }
252
+
205
253
  switch (networkRequestStatus.kind) {
206
254
  case 'Pending': {
207
- const completedFragmentReferences = loadedReferences.slice(
208
- 0,
209
- loadedReferences.length - 1,
210
- );
211
-
212
255
  const unsubscribe = subscribeToAnyChange(environment, () => {
213
256
  unsubscribe();
214
257
  rerender({});
@@ -224,7 +267,9 @@ export function useSkipLimitPagination<
224
267
  throw networkRequestStatus.error;
225
268
  }
226
269
  case 'Ok': {
227
- const results = readCompletedFragmentReferences(loadedReferences);
270
+ const results = readCompletedFragmentReferences(
271
+ completedFragmentReferences,
272
+ );
228
273
  return {
229
274
  kind: 'Complete',
230
275
  results,