@isograph/react 0.2.0 → 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.turbo/turbo-compile-typescript.log +4 -0
- package/dist/core/FragmentReference.d.ts +25 -6
- package/dist/core/FragmentReference.d.ts.map +1 -0
- package/dist/core/FragmentReference.js +3 -13
- package/dist/core/IsographEnvironment.d.ts +34 -26
- package/dist/core/IsographEnvironment.d.ts.map +1 -0
- package/dist/core/IsographEnvironment.js +19 -22
- package/dist/core/PromiseWrapper.d.ts +4 -4
- package/dist/core/PromiseWrapper.d.ts.map +1 -0
- package/dist/core/PromiseWrapper.js +9 -9
- package/dist/core/areEqualWithDeepComparison.d.ts +5 -3
- package/dist/core/areEqualWithDeepComparison.d.ts.map +1 -0
- package/dist/core/areEqualWithDeepComparison.js +89 -39
- package/dist/core/cache.d.ts +20 -13
- package/dist/core/cache.d.ts.map +1 -0
- package/dist/core/cache.js +205 -128
- package/dist/core/check.d.ts +22 -0
- package/dist/core/check.d.ts.map +1 -0
- package/dist/core/check.js +127 -0
- package/dist/core/componentCache.d.ts +2 -2
- package/dist/core/componentCache.d.ts.map +1 -0
- package/dist/core/componentCache.js +28 -32
- package/dist/core/entrypoint.d.ts +31 -15
- package/dist/core/entrypoint.d.ts.map +1 -0
- package/dist/core/entrypoint.js +1 -2
- package/dist/core/garbageCollection.d.ts +6 -5
- package/dist/core/garbageCollection.d.ts.map +1 -0
- package/dist/core/garbageCollection.js +49 -16
- package/dist/core/logging.d.ts +68 -0
- package/dist/core/logging.d.ts.map +1 -0
- package/dist/core/logging.js +22 -0
- package/dist/core/makeNetworkRequest.d.ts +6 -3
- package/dist/core/makeNetworkRequest.d.ts.map +1 -0
- package/dist/core/makeNetworkRequest.js +160 -19
- package/dist/core/read.d.ts +25 -5
- package/dist/core/read.d.ts.map +1 -0
- package/dist/core/read.js +416 -259
- package/dist/core/reader.d.ts +31 -15
- package/dist/core/reader.d.ts.map +1 -0
- package/dist/core/startUpdate.d.ts +5 -0
- package/dist/core/startUpdate.d.ts.map +1 -0
- package/dist/core/startUpdate.js +15 -0
- package/dist/core/util.d.ts +5 -0
- package/dist/core/util.d.ts.map +1 -0
- package/dist/index.d.ts +19 -14
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +11 -2
- package/dist/loadable-hooks/useClientSideDefer.d.ts +9 -3
- package/dist/loadable-hooks/useClientSideDefer.d.ts.map +1 -0
- package/dist/loadable-hooks/useClientSideDefer.js +6 -8
- package/dist/loadable-hooks/useConnectionSpecPagination.d.ts +27 -0
- package/dist/loadable-hooks/useConnectionSpecPagination.d.ts.map +1 -0
- package/dist/loadable-hooks/useConnectionSpecPagination.js +162 -0
- package/dist/loadable-hooks/useImperativeExposedMutationField.d.ts +2 -2
- package/dist/loadable-hooks/useImperativeExposedMutationField.d.ts.map +1 -0
- package/dist/loadable-hooks/useImperativeExposedMutationField.js +1 -2
- package/dist/loadable-hooks/useImperativeLoadableField.d.ts +13 -7
- package/dist/loadable-hooks/useImperativeLoadableField.d.ts.map +1 -0
- package/dist/loadable-hooks/useImperativeLoadableField.js +4 -5
- package/dist/loadable-hooks/useSkipLimitPagination.d.ts +13 -26
- package/dist/loadable-hooks/useSkipLimitPagination.d.ts.map +1 -0
- package/dist/loadable-hooks/useSkipLimitPagination.js +93 -47
- package/dist/react/FragmentReader.d.ts +6 -4
- package/dist/react/FragmentReader.d.ts.map +1 -0
- package/dist/react/FragmentReader.js +4 -2
- package/dist/react/IsographEnvironmentProvider.d.ts +1 -0
- package/dist/react/IsographEnvironmentProvider.d.ts.map +1 -0
- package/dist/react/IsographEnvironmentProvider.js +3 -3
- package/dist/react/RenderAfterCommit__DO_NOT_USE.d.ts +10 -0
- package/dist/react/RenderAfterCommit__DO_NOT_USE.d.ts.map +1 -0
- package/dist/react/RenderAfterCommit__DO_NOT_USE.js +15 -0
- package/dist/react/useImperativeReference.d.ts +8 -6
- package/dist/react/useImperativeReference.d.ts.map +1 -0
- package/dist/react/useImperativeReference.js +6 -8
- package/dist/react/useLazyReference.d.ts +5 -3
- package/dist/react/useLazyReference.d.ts.map +1 -0
- package/dist/react/useLazyReference.js +34 -6
- package/dist/react/useReadAndSubscribe.d.ts +6 -3
- package/dist/react/useReadAndSubscribe.d.ts.map +1 -0
- package/dist/react/useReadAndSubscribe.js +13 -10
- package/dist/react/useRerenderOnChange.d.ts +7 -2
- package/dist/react/useRerenderOnChange.d.ts.map +1 -0
- package/dist/react/useRerenderOnChange.js +3 -4
- package/dist/react/useResult.d.ts +4 -3
- package/dist/react/useResult.d.ts.map +1 -0
- package/dist/react/useResult.js +14 -9
- package/isograph.config.json +8 -0
- package/package.json +14 -9
- package/{src/tests/schema.graphql → schema.graphql} +1 -0
- package/src/core/FragmentReference.ts +44 -17
- package/src/core/IsographEnvironment.ts +67 -50
- package/src/core/PromiseWrapper.ts +3 -3
- package/src/core/areEqualWithDeepComparison.ts +95 -41
- package/src/core/cache.ts +316 -169
- package/src/core/check.ts +212 -0
- package/src/core/componentCache.ts +40 -46
- package/src/core/entrypoint.ts +41 -16
- package/src/core/garbageCollection.ts +77 -26
- package/src/core/logging.ts +118 -0
- package/src/core/makeNetworkRequest.ts +249 -20
- package/src/core/read.ts +658 -368
- package/src/core/reader.ts +61 -21
- package/src/core/startUpdate.ts +28 -0
- package/src/core/util.ts +8 -0
- package/src/index.ts +94 -8
- package/src/loadable-hooks/useClientSideDefer.ts +48 -17
- package/src/loadable-hooks/useConnectionSpecPagination.ts +344 -0
- package/src/loadable-hooks/useImperativeExposedMutationField.ts +1 -1
- package/src/loadable-hooks/useImperativeLoadableField.ts +36 -12
- package/src/loadable-hooks/useSkipLimitPagination.ts +253 -94
- package/src/react/FragmentReader.tsx +15 -6
- package/src/react/IsographEnvironmentProvider.tsx +1 -1
- package/src/react/RenderAfterCommit__DO_NOT_USE.tsx +17 -0
- package/src/react/useImperativeReference.ts +50 -18
- package/src/react/useLazyReference.ts +79 -11
- package/src/react/useReadAndSubscribe.ts +33 -10
- package/src/react/useRerenderOnChange.ts +7 -2
- package/src/react/useResult.ts +30 -9
- package/src/tests/__isograph/Query/meName/entrypoint.ts +10 -29
- package/src/tests/__isograph/Query/meName/normalization_ast.ts +25 -0
- package/src/tests/__isograph/Query/meName/param_type.ts +5 -2
- package/src/tests/__isograph/Query/meName/query_text.ts +6 -0
- package/src/tests/__isograph/Query/meName/resolver_reader.ts +5 -0
- package/src/tests/__isograph/Query/meNameSuccessor/entrypoint.ts +10 -65
- package/src/tests/__isograph/Query/meNameSuccessor/normalization_ast.ts +56 -0
- package/src/tests/__isograph/Query/meNameSuccessor/param_type.ts +9 -6
- package/src/tests/__isograph/Query/meNameSuccessor/query_text.ts +13 -0
- package/src/tests/__isograph/Query/meNameSuccessor/resolver_reader.ts +10 -0
- package/src/tests/__isograph/Query/nodeField/entrypoint.ts +10 -28
- package/src/tests/__isograph/Query/nodeField/normalization_ast.ts +30 -0
- package/src/tests/__isograph/Query/nodeField/param_type.ts +7 -3
- package/src/tests/__isograph/Query/nodeField/parameters_type.ts +3 -0
- package/src/tests/__isograph/Query/nodeField/query_text.ts +6 -0
- package/src/tests/__isograph/Query/nodeField/resolver_reader.ts +5 -0
- package/src/tests/__isograph/Query/subquery/entrypoint.ts +28 -0
- package/src/tests/__isograph/Query/subquery/normalization_ast.ts +38 -0
- package/src/tests/__isograph/Query/subquery/output_type.ts +3 -0
- package/src/tests/__isograph/Query/subquery/param_type.ts +12 -0
- package/src/tests/__isograph/Query/subquery/parameters_type.ts +3 -0
- package/src/tests/__isograph/Query/subquery/query_text.ts +8 -0
- package/src/tests/__isograph/Query/subquery/resolver_reader.ts +52 -0
- package/src/tests/__isograph/iso.ts +24 -12
- package/src/tests/garbageCollection.test.ts +53 -45
- package/src/tests/meNameSuccessor.ts +8 -3
- package/src/tests/nodeQuery.ts +7 -4
- package/src/tests/normalizeData.test.ts +120 -0
- package/src/tests/tsconfig.json +3 -3
- package/tsconfig.json +2 -2
- package/tsconfig.pkg.json +7 -3
- package/vitest.config.ts +20 -0
- package/src/tests/isograph.config.json +0 -7
@@ -1,9 +1,4 @@
|
|
1
|
-
import { LoadableField } from '../core/reader';
|
2
|
-
import { useIsographEnvironment } from '../react/IsographEnvironmentProvider';
|
3
1
|
import { ItemCleanupPair } from '@isograph/disposable-types';
|
4
|
-
import { FragmentReference } from '../core/FragmentReference';
|
5
|
-
import { maybeUnwrapNetworkRequest } from '../react/useResult';
|
6
|
-
import { readButDoNotEvaluate } from '../core/read';
|
7
2
|
import {
|
8
3
|
UNASSIGNED_STATE,
|
9
4
|
useUpdatableDisposableState,
|
@@ -12,32 +7,60 @@ import {
|
|
12
7
|
createReferenceCountedPointer,
|
13
8
|
ReferenceCountedPointer,
|
14
9
|
} from '@isograph/reference-counted-pointer';
|
10
|
+
import { useState } from 'react';
|
11
|
+
import { subscribeToAnyChange } from '../core/cache';
|
12
|
+
import { FetchOptions } from '../core/check';
|
13
|
+
import {
|
14
|
+
FragmentReference,
|
15
|
+
type UnknownTReadFromStore,
|
16
|
+
} from '../core/FragmentReference';
|
15
17
|
import { getPromiseState, readPromise } from '../core/PromiseWrapper';
|
18
|
+
import {
|
19
|
+
readButDoNotEvaluate,
|
20
|
+
type WithEncounteredRecords,
|
21
|
+
} from '../core/read';
|
22
|
+
import { LoadableField, type ReaderAst } from '../core/reader';
|
23
|
+
import { getOrCreateCachedStartUpdate } from '../core/startUpdate';
|
24
|
+
import { useIsographEnvironment } from '../react/IsographEnvironmentProvider';
|
25
|
+
import { useSubscribeToMultiple } from '../react/useReadAndSubscribe';
|
26
|
+
import { maybeUnwrapNetworkRequest } from '../react/useResult';
|
16
27
|
|
17
|
-
type
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
type UseSkipLimitReturnValue<TArgs, TItem> =
|
28
|
+
export type UseSkipLimitReturnValue<
|
29
|
+
TReadFromStore extends UnknownTReadFromStore,
|
30
|
+
TItem,
|
31
|
+
> =
|
23
32
|
| {
|
24
33
|
readonly kind: 'Complete';
|
25
|
-
readonly fetchMore: (
|
34
|
+
readonly fetchMore: (
|
35
|
+
count: number,
|
36
|
+
fetchOptions?: FetchOptions<ReadonlyArray<TItem>>,
|
37
|
+
) => void;
|
26
38
|
readonly results: ReadonlyArray<TItem>;
|
27
39
|
}
|
28
40
|
| {
|
29
41
|
readonly kind: 'Pending';
|
30
42
|
readonly results: ReadonlyArray<TItem>;
|
31
|
-
readonly pendingFragment: FragmentReference<
|
43
|
+
readonly pendingFragment: FragmentReference<
|
44
|
+
TReadFromStore,
|
45
|
+
ReadonlyArray<TItem>
|
46
|
+
>;
|
32
47
|
};
|
33
48
|
|
34
|
-
type ArrayFragmentReference<
|
35
|
-
|
36
|
-
|
37
|
-
|
49
|
+
type ArrayFragmentReference<
|
50
|
+
TReadFromStore extends UnknownTReadFromStore,
|
51
|
+
TItem,
|
52
|
+
> = FragmentReference<TReadFromStore, ReadonlyArray<TItem>>;
|
53
|
+
|
54
|
+
type LoadedFragmentReferences<
|
55
|
+
TReadFromStore extends { parameters: object; data: object },
|
56
|
+
TItem,
|
57
|
+
> = ReadonlyArray<LoadedFragmentReference<TReadFromStore, TItem>>;
|
38
58
|
|
39
|
-
type
|
40
|
-
|
59
|
+
type LoadedFragmentReference<
|
60
|
+
TReadFromStore extends { parameters: object; data: object },
|
61
|
+
TItem,
|
62
|
+
> = ItemCleanupPair<
|
63
|
+
ReferenceCountedPointer<ArrayFragmentReference<TReadFromStore, TItem>>
|
41
64
|
>;
|
42
65
|
|
43
66
|
function flatten<T>(arr: ReadonlyArray<ReadonlyArray<T>>): ReadonlyArray<T> {
|
@@ -50,95 +73,145 @@ function flatten<T>(arr: ReadonlyArray<ReadonlyArray<T>>): ReadonlyArray<T> {
|
|
50
73
|
return outArray;
|
51
74
|
}
|
52
75
|
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
* - the data received so far.
|
59
|
-
*
|
60
|
-
* This hook will suspend if any network request is in flight.
|
61
|
-
*
|
62
|
-
* Calling fetchMore before the hook mounts is a no-op.
|
63
|
-
*
|
64
|
-
* NOTE: this hook does not subscribe to changes. This is a known
|
65
|
-
* issue. If you are running into this issue, reach out on GitHub/
|
66
|
-
* Twitter, and we'll fix the issue.
|
67
|
-
*/
|
76
|
+
export type UseSkipLimitPaginationArgs = {
|
77
|
+
skip: number;
|
78
|
+
limit: number;
|
79
|
+
};
|
80
|
+
|
68
81
|
export function useSkipLimitPagination<
|
69
|
-
TArgs extends {
|
70
|
-
skip: number | void | null;
|
71
|
-
limit: number | void | null;
|
72
|
-
},
|
73
82
|
TItem,
|
83
|
+
TReadFromStore extends UnknownTReadFromStore,
|
74
84
|
>(
|
75
|
-
loadableField: LoadableField<
|
76
|
-
|
85
|
+
loadableField: LoadableField<
|
86
|
+
TReadFromStore,
|
87
|
+
ReadonlyArray<TItem>,
|
88
|
+
UseSkipLimitPaginationArgs
|
89
|
+
>,
|
90
|
+
initialState?: {
|
91
|
+
skip?: number | void | null;
|
92
|
+
},
|
93
|
+
): UseSkipLimitReturnValue<TReadFromStore, TItem> {
|
77
94
|
const networkRequestOptions = {
|
78
95
|
suspendIfInFlight: true,
|
79
96
|
throwOnNetworkError: true,
|
80
97
|
};
|
81
98
|
const { state, setState } =
|
82
|
-
useUpdatableDisposableState<
|
99
|
+
useUpdatableDisposableState<
|
100
|
+
LoadedFragmentReferences<TReadFromStore, TItem>
|
101
|
+
>();
|
83
102
|
|
84
103
|
const environment = useIsographEnvironment();
|
85
104
|
|
105
|
+
// TODO move this out of useSkipLimitPagination, and pass environment and networkRequestOptions
|
106
|
+
// as parameters (or recreate networkRequestOptions)
|
86
107
|
function readCompletedFragmentReferences(
|
87
|
-
completedReferences:
|
88
|
-
ItemCleanupPair<ReferenceCountedPointer<ArrayFragmentReference<TItem>>>
|
89
|
-
>,
|
108
|
+
completedReferences: ArrayFragmentReference<TReadFromStore, TItem>[],
|
90
109
|
) {
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
110
|
+
const results = completedReferences.map((fragmentReference, i) => {
|
111
|
+
const readerWithRefetchQueries = readPromise(
|
112
|
+
fragmentReference.readerWithRefetchQueries,
|
113
|
+
);
|
114
|
+
|
115
|
+
// invariant: readOutDataAndRecords.length === completedReferences.length
|
116
|
+
const data = readOutDataAndRecords[i]?.item;
|
117
|
+
if (data == null) {
|
96
118
|
throw new Error(
|
97
|
-
'
|
98
|
-
This is indicative of a bug in Isograph.',
|
119
|
+
'Parameter data is unexpectedly null. This is indicative of a bug in Isograph.',
|
99
120
|
);
|
100
121
|
}
|
101
122
|
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
123
|
+
const firstParameter = {
|
124
|
+
data,
|
125
|
+
parameters: fragmentReference.variables,
|
126
|
+
...(readerWithRefetchQueries.readerArtifact.hasUpdatable
|
127
|
+
? {
|
128
|
+
startUpdate: getOrCreateCachedStartUpdate(
|
129
|
+
environment,
|
130
|
+
fragmentReference,
|
131
|
+
readerWithRefetchQueries.readerArtifact.kind,
|
132
|
+
),
|
133
|
+
}
|
134
|
+
: undefined),
|
135
|
+
};
|
111
136
|
|
112
|
-
|
113
|
-
|
114
|
-
)
|
137
|
+
if (
|
138
|
+
readerWithRefetchQueries.readerArtifact.kind !== 'EagerReaderArtifact'
|
139
|
+
) {
|
140
|
+
throw new Error(
|
141
|
+
`@loadable field of kind "${readerWithRefetchQueries.readerArtifact.kind}" is not supported by useSkipLimitPagination`,
|
142
|
+
);
|
143
|
+
}
|
115
144
|
|
116
|
-
return readerWithRefetchQueries.readerArtifact.resolver(
|
117
|
-
data.item,
|
118
|
-
undefined,
|
119
|
-
) as ReadonlyArray<any>;
|
145
|
+
return readerWithRefetchQueries.readerArtifact.resolver(firstParameter);
|
120
146
|
});
|
121
147
|
|
122
148
|
const items = flatten(results);
|
123
149
|
return items;
|
124
150
|
}
|
125
151
|
|
152
|
+
function subscribeCompletedFragmentReferences(
|
153
|
+
completedReferences: ArrayFragmentReference<TReadFromStore, TItem>[],
|
154
|
+
) {
|
155
|
+
return completedReferences.map(
|
156
|
+
(
|
157
|
+
fragmentReference,
|
158
|
+
i,
|
159
|
+
): {
|
160
|
+
records: WithEncounteredRecords<TReadFromStore>;
|
161
|
+
callback: (
|
162
|
+
updatedRecords: WithEncounteredRecords<TReadFromStore>,
|
163
|
+
) => void;
|
164
|
+
fragmentReference: ArrayFragmentReference<TReadFromStore, TItem>;
|
165
|
+
readerAst: ReaderAst<TItem>;
|
166
|
+
} => {
|
167
|
+
maybeUnwrapNetworkRequest(
|
168
|
+
fragmentReference.networkRequest,
|
169
|
+
networkRequestOptions,
|
170
|
+
);
|
171
|
+
|
172
|
+
const readerWithRefetchQueries = readPromise(
|
173
|
+
fragmentReference.readerWithRefetchQueries,
|
174
|
+
);
|
175
|
+
|
176
|
+
const records = readOutDataAndRecords[i];
|
177
|
+
if (records == null) {
|
178
|
+
throw new Error(
|
179
|
+
'subscribeCompletedFragmentReferences records is unexpectedly null',
|
180
|
+
);
|
181
|
+
}
|
182
|
+
|
183
|
+
return {
|
184
|
+
fragmentReference,
|
185
|
+
readerAst: readerWithRefetchQueries.readerArtifact.readerAst,
|
186
|
+
records,
|
187
|
+
callback(_data) {
|
188
|
+
rerender({});
|
189
|
+
},
|
190
|
+
};
|
191
|
+
},
|
192
|
+
);
|
193
|
+
}
|
194
|
+
|
126
195
|
const getFetchMore =
|
127
196
|
(loadedSoFar: number) =>
|
128
|
-
(
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
197
|
+
(
|
198
|
+
count: number,
|
199
|
+
fetchOptions?: FetchOptions<ReadonlyArray<TItem>>,
|
200
|
+
): void => {
|
201
|
+
const loadedField = loadableField(
|
202
|
+
{
|
203
|
+
skip: loadedSoFar,
|
204
|
+
limit: count,
|
205
|
+
},
|
206
|
+
fetchOptions ?? {},
|
207
|
+
)[1]();
|
135
208
|
const newPointer = createReferenceCountedPointer(loadedField);
|
136
209
|
const clonedPointers = loadedReferences.map(([refCountedPointer]) => {
|
137
210
|
const clonedRefCountedPointer = refCountedPointer.cloneIfNotDisposed();
|
138
211
|
if (clonedRefCountedPointer == null) {
|
139
212
|
throw new Error(
|
140
213
|
'This reference counted pointer has already been disposed. \
|
141
|
-
|
214
|
+
This is indicative of a bug in useSkipLimitPagination.',
|
142
215
|
);
|
143
216
|
}
|
144
217
|
return clonedRefCountedPointer;
|
@@ -148,7 +221,9 @@ export function useSkipLimitPagination<
|
|
148
221
|
const totalItemCleanupPair: ItemCleanupPair<
|
149
222
|
ReadonlyArray<
|
150
223
|
ItemCleanupPair<
|
151
|
-
ReferenceCountedPointer<
|
224
|
+
ReferenceCountedPointer<
|
225
|
+
ArrayFragmentReference<TReadFromStore, TItem>
|
226
|
+
>
|
152
227
|
>
|
153
228
|
>
|
154
229
|
> = [
|
@@ -163,33 +238,73 @@ export function useSkipLimitPagination<
|
|
163
238
|
setState(totalItemCleanupPair);
|
164
239
|
};
|
165
240
|
|
241
|
+
const [, rerender] = useState({});
|
242
|
+
|
166
243
|
const loadedReferences = state === UNASSIGNED_STATE ? [] : state;
|
167
|
-
if (loadedReferences.length === 0) {
|
168
|
-
return {
|
169
|
-
kind: 'Complete',
|
170
|
-
fetchMore: getFetchMore(0),
|
171
|
-
results: [],
|
172
|
-
};
|
173
|
-
}
|
174
244
|
|
175
|
-
const mostRecentItem
|
176
|
-
|
177
|
-
|
245
|
+
const mostRecentItem:
|
246
|
+
| LoadedFragmentReference<TReadFromStore, TItem>
|
247
|
+
| undefined = loadedReferences[loadedReferences.length - 1];
|
248
|
+
const mostRecentFragmentReference =
|
249
|
+
mostRecentItem?.[0].getItemIfNotDisposed();
|
250
|
+
|
251
|
+
if (mostRecentItem && mostRecentFragmentReference === null) {
|
178
252
|
throw new Error(
|
179
253
|
'FragmentReference is unexpectedly disposed. \
|
180
|
-
|
254
|
+
This is indicative of a bug in Isograph.',
|
181
255
|
);
|
182
256
|
}
|
183
257
|
|
184
|
-
const networkRequestStatus =
|
185
|
-
mostRecentFragmentReference
|
258
|
+
const networkRequestStatus =
|
259
|
+
mostRecentFragmentReference &&
|
260
|
+
getPromiseState(mostRecentFragmentReference.networkRequest);
|
261
|
+
|
262
|
+
const slicedFragmentReferences =
|
263
|
+
networkRequestStatus?.kind === 'Ok'
|
264
|
+
? loadedReferences
|
265
|
+
: loadedReferences.slice(0, loadedReferences.length - 1);
|
266
|
+
|
267
|
+
const completedFragmentReferences = slicedFragmentReferences.map(
|
268
|
+
([pointer]) => {
|
269
|
+
const fragmentReference = pointer.getItemIfNotDisposed();
|
270
|
+
if (fragmentReference == null) {
|
271
|
+
throw new Error(
|
272
|
+
'FragmentReference is unexpectedly disposed. \
|
273
|
+
This is indicative of a bug in Isograph.',
|
274
|
+
);
|
275
|
+
}
|
276
|
+
return fragmentReference;
|
277
|
+
},
|
186
278
|
);
|
279
|
+
|
280
|
+
const readOutDataAndRecords = completedFragmentReferences.map(
|
281
|
+
(fragmentReference) =>
|
282
|
+
readButDoNotEvaluate(
|
283
|
+
environment,
|
284
|
+
fragmentReference,
|
285
|
+
networkRequestOptions,
|
286
|
+
),
|
287
|
+
);
|
288
|
+
|
289
|
+
useSubscribeToMultiple<TReadFromStore>(
|
290
|
+
subscribeCompletedFragmentReferences(completedFragmentReferences),
|
291
|
+
);
|
292
|
+
|
293
|
+
if (!networkRequestStatus) {
|
294
|
+
return {
|
295
|
+
kind: 'Complete',
|
296
|
+
fetchMore: getFetchMore(initialState?.skip ?? 0),
|
297
|
+
results: [],
|
298
|
+
};
|
299
|
+
}
|
300
|
+
|
187
301
|
switch (networkRequestStatus.kind) {
|
188
302
|
case 'Pending': {
|
189
|
-
const
|
190
|
-
|
191
|
-
|
192
|
-
);
|
303
|
+
const unsubscribe = subscribeToAnyChange(environment, () => {
|
304
|
+
unsubscribe();
|
305
|
+
rerender({});
|
306
|
+
});
|
307
|
+
|
193
308
|
return {
|
194
309
|
kind: 'Pending',
|
195
310
|
pendingFragment: mostRecentFragmentReference,
|
@@ -200,7 +315,9 @@ export function useSkipLimitPagination<
|
|
200
315
|
throw networkRequestStatus.error;
|
201
316
|
}
|
202
317
|
case 'Ok': {
|
203
|
-
const results = readCompletedFragmentReferences(
|
318
|
+
const results = readCompletedFragmentReferences(
|
319
|
+
completedFragmentReferences,
|
320
|
+
);
|
204
321
|
return {
|
205
322
|
kind: 'Complete',
|
206
323
|
results,
|
@@ -209,3 +326,45 @@ export function useSkipLimitPagination<
|
|
209
326
|
}
|
210
327
|
}
|
211
328
|
}
|
329
|
+
|
330
|
+
// @ts-ignore
|
331
|
+
function tsTests() {
|
332
|
+
type Parameters = {
|
333
|
+
readonly search: string;
|
334
|
+
readonly skip: number;
|
335
|
+
readonly limit: number;
|
336
|
+
};
|
337
|
+
|
338
|
+
let basicLoadable!: LoadableField<
|
339
|
+
{
|
340
|
+
readonly data: object;
|
341
|
+
readonly parameters: Omit<Parameters, 'search'>;
|
342
|
+
},
|
343
|
+
object[]
|
344
|
+
>;
|
345
|
+
|
346
|
+
useSkipLimitPagination(basicLoadable);
|
347
|
+
useSkipLimitPagination(basicLoadable, {});
|
348
|
+
useSkipLimitPagination(basicLoadable, { skip: 10 });
|
349
|
+
|
350
|
+
let unprovidedSearchLoadable!: LoadableField<
|
351
|
+
{
|
352
|
+
readonly data: object;
|
353
|
+
readonly parameters: Parameters;
|
354
|
+
},
|
355
|
+
object[]
|
356
|
+
>;
|
357
|
+
// @ts-expect-error
|
358
|
+
useSkipLimitPagination(unprovidedSearchLoadable);
|
359
|
+
|
360
|
+
let providedSearchLoadable!: LoadableField<
|
361
|
+
{
|
362
|
+
readonly data: object;
|
363
|
+
readonly parameters: Parameters;
|
364
|
+
},
|
365
|
+
object[],
|
366
|
+
Omit<Parameters, 'search'>
|
367
|
+
>;
|
368
|
+
|
369
|
+
useSkipLimitPagination(providedSearchLoadable);
|
370
|
+
}
|
@@ -1,20 +1,26 @@
|
|
1
1
|
import * as React from 'react';
|
2
2
|
import { ExtractReadFromStore, IsographEntrypoint } from '../core/entrypoint';
|
3
3
|
import { FragmentReference } from '../core/FragmentReference';
|
4
|
-
import { useResult } from './useResult';
|
5
4
|
import { NetworkRequestReaderOptions } from '../core/read';
|
5
|
+
import { useResult } from './useResult';
|
6
|
+
|
7
|
+
export type IsExactlyIntrinsicAttributes<T> = T extends JSX.IntrinsicAttributes
|
8
|
+
? JSX.IntrinsicAttributes extends T
|
9
|
+
? true
|
10
|
+
: false
|
11
|
+
: false;
|
6
12
|
|
7
13
|
export function FragmentReader<
|
8
14
|
TProps extends Record<any, any>,
|
9
|
-
TEntrypoint extends IsographEntrypoint<any, React.FC<TProps
|
15
|
+
TEntrypoint extends IsographEntrypoint<any, React.FC<TProps>, any>,
|
10
16
|
>(
|
11
|
-
props: TProps extends
|
17
|
+
props: IsExactlyIntrinsicAttributes<TProps> extends true
|
12
18
|
? {
|
13
19
|
fragmentReference: FragmentReference<
|
14
20
|
ExtractReadFromStore<TEntrypoint>,
|
15
|
-
React.FC<
|
21
|
+
React.FC<TProps>
|
16
22
|
>;
|
17
|
-
additionalProps?:
|
23
|
+
additionalProps?: Record<PropertyKey, never>;
|
18
24
|
networkRequestOptions?: Partial<NetworkRequestReaderOptions>;
|
19
25
|
}
|
20
26
|
: {
|
@@ -22,7 +28,7 @@ export function FragmentReader<
|
|
22
28
|
ExtractReadFromStore<TEntrypoint>,
|
23
29
|
React.FC<TProps>
|
24
30
|
>;
|
25
|
-
additionalProps: TProps
|
31
|
+
additionalProps: Omit<TProps, keyof JSX.IntrinsicAttributes>;
|
26
32
|
networkRequestOptions?: Partial<NetworkRequestReaderOptions>;
|
27
33
|
},
|
28
34
|
): React.ReactNode {
|
@@ -30,5 +36,8 @@ export function FragmentReader<
|
|
30
36
|
props.fragmentReference,
|
31
37
|
props.networkRequestOptions,
|
32
38
|
);
|
39
|
+
// TypeScript is not understanding that if additionalProps is Record<PropertyKey, never>,
|
40
|
+
// it means that TProps === JSX.IntrinsicAttributes.
|
41
|
+
// @ts-expect-error
|
33
42
|
return <Component {...props.additionalProps} />;
|
34
43
|
}
|
@@ -1,5 +1,5 @@
|
|
1
1
|
import * as React from 'react';
|
2
|
-
import {
|
2
|
+
import { createContext, ReactNode, useContext } from 'react';
|
3
3
|
import { type IsographEnvironment } from '../core/IsographEnvironment';
|
4
4
|
|
5
5
|
export const IsographEnvironmentContext =
|
@@ -0,0 +1,17 @@
|
|
1
|
+
import { useEffect, useState } from 'react';
|
2
|
+
|
3
|
+
/**
|
4
|
+
* This is a function that will render a component only after it commits.
|
5
|
+
* It should not be used in production. It's useful as a way to debug issues
|
6
|
+
* with NextJS, where an indefinite suspense causes the server to hang
|
7
|
+
* forever and never complete the original request.
|
8
|
+
*/
|
9
|
+
export function RenderAfterCommit__DO_NOT_USE({
|
10
|
+
children,
|
11
|
+
}: {
|
12
|
+
children: React.ReactNode;
|
13
|
+
}) {
|
14
|
+
const [show, setShow] = useState(false);
|
15
|
+
useEffect(() => setShow(true), []);
|
16
|
+
return show ? children : null;
|
17
|
+
}
|
@@ -1,39 +1,71 @@
|
|
1
1
|
import {
|
2
|
-
|
2
|
+
UNASSIGNED_STATE,
|
3
3
|
useUpdatableDisposableState,
|
4
4
|
} from '@isograph/react-disposable-state';
|
5
|
-
import {
|
6
|
-
import {
|
7
|
-
|
5
|
+
import { FetchOptions, type RequiredFetchOptions } from '../core/check';
|
6
|
+
import {
|
7
|
+
IsographEntrypoint,
|
8
|
+
type NormalizationAst,
|
9
|
+
type NormalizationAstLoader,
|
10
|
+
} from '../core/entrypoint';
|
11
|
+
import {
|
12
|
+
ExtractParameters,
|
13
|
+
FragmentReference,
|
14
|
+
type UnknownTReadFromStore,
|
15
|
+
} from '../core/FragmentReference';
|
8
16
|
import { ROOT_ID } from '../core/IsographEnvironment';
|
9
|
-
import {
|
17
|
+
import { maybeMakeNetworkRequest } from '../core/makeNetworkRequest';
|
10
18
|
import { wrapResolvedValue } from '../core/PromiseWrapper';
|
19
|
+
import { useIsographEnvironment } from './IsographEnvironmentProvider';
|
11
20
|
|
12
|
-
|
21
|
+
export type UseImperativeReferenceResult<
|
22
|
+
TReadFromStore extends UnknownTReadFromStore,
|
23
|
+
TClientFieldValue,
|
24
|
+
TNormalizationAst extends NormalizationAst | NormalizationAstLoader,
|
25
|
+
> = {
|
26
|
+
fragmentReference: FragmentReference<
|
27
|
+
TReadFromStore,
|
28
|
+
TClientFieldValue
|
29
|
+
> | null;
|
30
|
+
loadFragmentReference: (
|
31
|
+
variables: ExtractParameters<TReadFromStore>,
|
32
|
+
...[fetchOptions]: NormalizationAstLoader extends TNormalizationAst
|
33
|
+
? [fetchOptions: RequiredFetchOptions<TClientFieldValue>]
|
34
|
+
: [fetchOptions?: FetchOptions<TClientFieldValue>]
|
35
|
+
) => void;
|
36
|
+
};
|
13
37
|
|
14
38
|
export function useImperativeReference<
|
15
|
-
TReadFromStore extends
|
39
|
+
TReadFromStore extends UnknownTReadFromStore,
|
16
40
|
TClientFieldValue,
|
41
|
+
TNormalizationAst extends NormalizationAst | NormalizationAstLoader,
|
17
42
|
>(
|
18
|
-
entrypoint: IsographEntrypoint<
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
43
|
+
entrypoint: IsographEntrypoint<
|
44
|
+
TReadFromStore,
|
45
|
+
TClientFieldValue,
|
46
|
+
TNormalizationAst
|
47
|
+
>,
|
48
|
+
): UseImperativeReferenceResult<
|
49
|
+
TReadFromStore,
|
50
|
+
TClientFieldValue,
|
51
|
+
TNormalizationAst
|
52
|
+
> {
|
25
53
|
const { state, setState } =
|
26
54
|
useUpdatableDisposableState<
|
27
55
|
FragmentReference<TReadFromStore, TClientFieldValue>
|
28
56
|
>();
|
29
57
|
const environment = useIsographEnvironment();
|
30
58
|
return {
|
31
|
-
fragmentReference: state,
|
32
|
-
loadFragmentReference: (
|
33
|
-
|
59
|
+
fragmentReference: state !== UNASSIGNED_STATE ? state : null,
|
60
|
+
loadFragmentReference: (
|
61
|
+
variables: ExtractParameters<TReadFromStore>,
|
62
|
+
fetchOptions?: FetchOptions<TClientFieldValue>,
|
63
|
+
) => {
|
64
|
+
const [networkRequest, disposeNetworkRequest] = maybeMakeNetworkRequest(
|
34
65
|
environment,
|
35
66
|
entrypoint,
|
36
67
|
variables,
|
68
|
+
fetchOptions,
|
37
69
|
);
|
38
70
|
setState([
|
39
71
|
{
|
@@ -44,7 +76,7 @@ export function useImperativeReference<
|
|
44
76
|
nestedRefetchQueries:
|
45
77
|
entrypoint.readerWithRefetchQueries.nestedRefetchQueries,
|
46
78
|
}),
|
47
|
-
root: ROOT_ID,
|
79
|
+
root: { __link: ROOT_ID, __typename: entrypoint.concreteType },
|
48
80
|
variables,
|
49
81
|
networkRequest,
|
50
82
|
},
|