@isograph/react 0.0.0-main-ae8aa2fe → 0.0.0-main-d3ef6e33
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/dist/core/FragmentReference.d.ts +2 -0
- package/dist/core/PromiseWrapper.d.ts +17 -4
- package/dist/core/PromiseWrapper.js +35 -10
- package/dist/core/cache.d.ts +2 -2
- package/dist/core/cache.js +31 -4
- package/dist/core/componentCache.d.ts +2 -1
- package/dist/core/componentCache.js +2 -2
- package/dist/core/entrypoint.d.ts +2 -0
- package/dist/core/makeNetworkRequest.d.ts +2 -2
- package/dist/core/makeNetworkRequest.js +6 -2
- package/dist/core/read.d.ts +5 -1
- package/dist/core/read.js +75 -33
- package/dist/index.d.ts +6 -6
- package/dist/index.js +6 -3
- package/dist/loadable-hooks/useClientSideDefer.js +0 -1
- package/dist/react/{FragmentReferenceReader.d.ts → FragmentReader.d.ts} +4 -1
- package/dist/react/{FragmentReferenceReader.js → FragmentReader.js} +5 -4
- package/dist/react/useImperativeReference.d.ts +1 -1
- package/dist/react/useImperativeReference.js +3 -2
- package/dist/react/useLazyReference.js +2 -3
- package/dist/react/useReadAndSubscribe.d.ts +2 -2
- package/dist/react/useReadAndSubscribe.js +5 -3
- package/dist/react/useRerenderOnChange.d.ts +1 -2
- package/dist/react/useRerenderOnChange.js +3 -1
- package/dist/react/useResult.d.ts +4 -1
- package/dist/react/useResult.js +17 -4
- package/package.json +3 -3
- package/src/core/FragmentReference.ts +2 -0
- package/src/core/PromiseWrapper.ts +58 -12
- package/src/core/cache.ts +80 -57
- package/src/core/componentCache.ts +6 -1
- package/src/core/entrypoint.ts +1 -0
- package/src/core/makeNetworkRequest.ts +11 -6
- package/src/core/read.ts +108 -41
- package/src/index.ts +35 -25
- package/src/loadable-hooks/useClientSideDefer.ts +1 -1
- package/src/react/{FragmentReferenceReader.tsx → FragmentReader.tsx} +8 -2
- package/src/react/useImperativeReference.ts +4 -3
- package/src/react/useLazyReference.ts +2 -3
- package/src/react/useReadAndSubscribe.ts +8 -5
- package/src/react/useRerenderOnChange.ts +2 -2
- package/src/react/useResult.ts +28 -1
package/src/core/read.ts
CHANGED
@@ -9,6 +9,7 @@ import {
|
|
9
9
|
IsographEnvironment,
|
10
10
|
} from './IsographEnvironment';
|
11
11
|
import { makeNetworkRequest } from './makeNetworkRequest';
|
12
|
+
import { PromiseWrapper } from './PromiseWrapper';
|
12
13
|
import { ReaderAst } from './reader';
|
13
14
|
import { Arguments } from './util';
|
14
15
|
|
@@ -19,21 +20,43 @@ export type WithEncounteredRecords<T> = {
|
|
19
20
|
|
20
21
|
export function readButDoNotEvaluate<TReadFromStore extends Object>(
|
21
22
|
environment: IsographEnvironment,
|
22
|
-
|
23
|
+
fragmentReference: FragmentReference<TReadFromStore, unknown>,
|
24
|
+
networkRequestOptions: NetworkRequestReaderOptions,
|
23
25
|
): WithEncounteredRecords<TReadFromStore> {
|
24
26
|
const mutableEncounteredRecords = new Set<DataId>();
|
25
27
|
const response = readData(
|
26
28
|
environment,
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
29
|
+
fragmentReference.readerArtifact.readerAst,
|
30
|
+
fragmentReference.root,
|
31
|
+
fragmentReference.variables ?? {},
|
32
|
+
fragmentReference.nestedRefetchQueries,
|
33
|
+
fragmentReference.networkRequest,
|
34
|
+
networkRequestOptions,
|
31
35
|
mutableEncounteredRecords,
|
32
36
|
);
|
33
37
|
if (typeof window !== 'undefined' && window.__LOG) {
|
34
38
|
console.log('done reading', { response });
|
35
39
|
}
|
36
40
|
if (response.kind === 'MissingData') {
|
41
|
+
// There are two cases here that we care about:
|
42
|
+
// 1. the network request is in flight, we haven't suspend on it, and we want
|
43
|
+
// to throw if it errors out. So, networkRequestOptions.suspendIfInFlight === false
|
44
|
+
// and networkRequestOptions.throwOnNetworkError === true.
|
45
|
+
// 2. everything else
|
46
|
+
//
|
47
|
+
// In the first case, we cannot simply throw onNextChange, because if the network
|
48
|
+
// response errors out, we will not update the store, so the onNextChange promise
|
49
|
+
// will not resolve.
|
50
|
+
if (
|
51
|
+
!networkRequestOptions.suspendIfInFlight &&
|
52
|
+
networkRequestOptions.throwOnNetworkError
|
53
|
+
) {
|
54
|
+
// TODO assert that the network request state is not Err
|
55
|
+
throw new Promise((resolve, reject) => {
|
56
|
+
onNextChange(environment).then(resolve);
|
57
|
+
fragmentReference.networkRequest.promise.catch(reject);
|
58
|
+
});
|
59
|
+
}
|
37
60
|
throw onNextChange(environment);
|
38
61
|
} else {
|
39
62
|
return {
|
@@ -61,6 +84,8 @@ function readData<TReadFromStore>(
|
|
61
84
|
root: DataId,
|
62
85
|
variables: Variables,
|
63
86
|
nestedRefetchQueries: RefetchQueryNormalizationArtifactWrapper[],
|
87
|
+
networkRequest: PromiseWrapper<void, any>,
|
88
|
+
networkRequestOptions: NetworkRequestReaderOptions,
|
64
89
|
mutableEncounteredRecords: Set<DataId>,
|
65
90
|
): ReadDataResult<TReadFromStore> {
|
66
91
|
mutableEncounteredRecords.add(root);
|
@@ -126,6 +151,8 @@ function readData<TReadFromStore>(
|
|
126
151
|
link.__link,
|
127
152
|
variables,
|
128
153
|
nestedRefetchQueries,
|
154
|
+
networkRequest,
|
155
|
+
networkRequestOptions,
|
129
156
|
mutableEncounteredRecords,
|
130
157
|
);
|
131
158
|
if (result.kind === 'MissingData') {
|
@@ -183,6 +210,8 @@ function readData<TReadFromStore>(
|
|
183
210
|
targetId,
|
184
211
|
variables,
|
185
212
|
nestedRefetchQueries,
|
213
|
+
networkRequest,
|
214
|
+
networkRequestOptions,
|
186
215
|
mutableEncounteredRecords,
|
187
216
|
);
|
188
217
|
if (data.kind === 'MissingData') {
|
@@ -205,6 +234,10 @@ function readData<TReadFromStore>(
|
|
205
234
|
variables,
|
206
235
|
// Refetch fields just read the id, and don't need refetch query artifacts
|
207
236
|
[],
|
237
|
+
// This is probably indicative of the fact that we are doing redundant checks
|
238
|
+
// on the status of this network request...
|
239
|
+
networkRequest,
|
240
|
+
networkRequestOptions,
|
208
241
|
mutableEncounteredRecords,
|
209
242
|
);
|
210
243
|
if (data.kind === 'MissingData') {
|
@@ -256,6 +289,8 @@ function readData<TReadFromStore>(
|
|
256
289
|
root,
|
257
290
|
variables,
|
258
291
|
resolverRefetchQueries,
|
292
|
+
networkRequest,
|
293
|
+
networkRequestOptions,
|
259
294
|
mutableEncounteredRecords,
|
260
295
|
);
|
261
296
|
if (data.kind === 'MissingData') {
|
@@ -276,8 +311,10 @@ function readData<TReadFromStore>(
|
|
276
311
|
readerArtifact: field.readerArtifact,
|
277
312
|
root,
|
278
313
|
variables: generateChildVariableMap(variables, field.arguments),
|
314
|
+
networkRequest,
|
279
315
|
nestedRefetchQueries: resolverRefetchQueries,
|
280
316
|
} as const,
|
317
|
+
networkRequestOptions,
|
281
318
|
);
|
282
319
|
}
|
283
320
|
break;
|
@@ -290,6 +327,8 @@ function readData<TReadFromStore>(
|
|
290
327
|
variables,
|
291
328
|
// Refetch fields just read the id, and don't need refetch query artifacts
|
292
329
|
[],
|
330
|
+
networkRequest,
|
331
|
+
networkRequestOptions,
|
293
332
|
mutableEncounteredRecords,
|
294
333
|
);
|
295
334
|
if (refetchReaderParams.kind === 'MissingData') {
|
@@ -299,42 +338,50 @@ function readData<TReadFromStore>(
|
|
299
338
|
nestedReason: refetchReaderParams,
|
300
339
|
};
|
301
340
|
} else {
|
302
|
-
target[field.alias] = (args: any) =>
|
303
|
-
//
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
|
323
|
-
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
|
334
|
-
|
335
|
-
|
336
|
-
|
337
|
-
|
341
|
+
target[field.alias] = (args: any) => {
|
342
|
+
// TODO we should use the reader AST for this
|
343
|
+
const includeReadOutData = (variables: any, readOutData: any) => {
|
344
|
+
variables.id = readOutData.id;
|
345
|
+
return variables;
|
346
|
+
};
|
347
|
+
const localVariables = includeReadOutData(
|
348
|
+
args ?? {},
|
349
|
+
refetchReaderParams.data,
|
350
|
+
);
|
351
|
+
writeQueryArgsToVariables(
|
352
|
+
localVariables,
|
353
|
+
field.queryArguments,
|
354
|
+
variables,
|
355
|
+
);
|
356
|
+
|
357
|
+
return [
|
358
|
+
// Stable id
|
359
|
+
root +
|
360
|
+
'/' +
|
361
|
+
field.name +
|
362
|
+
'/' +
|
363
|
+
stableStringifyArgs(localVariables),
|
364
|
+
// Fetcher
|
365
|
+
() => {
|
366
|
+
const [networkRequest, disposeNetworkRequest] =
|
367
|
+
makeNetworkRequest(
|
368
|
+
environment,
|
369
|
+
field.entrypoint,
|
370
|
+
localVariables,
|
371
|
+
);
|
372
|
+
const fragmentReference = {
|
373
|
+
kind: 'FragmentReference',
|
374
|
+
readerArtifact: field.entrypoint.readerArtifact,
|
375
|
+
// TODO localVariables is not guaranteed to have an id field
|
376
|
+
root: localVariables.id,
|
377
|
+
variables: localVariables,
|
378
|
+
nestedRefetchQueries: field.entrypoint.nestedRefetchQueries,
|
379
|
+
networkRequest,
|
380
|
+
} as FragmentReference<any, any>;
|
381
|
+
return [fragmentReference, disposeNetworkRequest];
|
382
|
+
},
|
383
|
+
];
|
384
|
+
};
|
338
385
|
}
|
339
386
|
break;
|
340
387
|
}
|
@@ -419,3 +466,23 @@ function writeQueryArgsToVariables(
|
|
419
466
|
}
|
420
467
|
}
|
421
468
|
}
|
469
|
+
|
470
|
+
export type NetworkRequestReaderOptions = {
|
471
|
+
suspendIfInFlight?: boolean;
|
472
|
+
throwOnNetworkError?: boolean;
|
473
|
+
};
|
474
|
+
|
475
|
+
// TODO use a description of the params for this?
|
476
|
+
// TODO call stableStringifyArgs on the variable values, as well.
|
477
|
+
// This doesn't matter for now, since we are just using primitive values
|
478
|
+
// in the demo.
|
479
|
+
function stableStringifyArgs(args: Object) {
|
480
|
+
const keys = Object.keys(args);
|
481
|
+
keys.sort();
|
482
|
+
let s = '';
|
483
|
+
for (const key of keys) {
|
484
|
+
// @ts-expect-error
|
485
|
+
s += `${key}=${JSON.stringify(args[key])};`;
|
486
|
+
}
|
487
|
+
return s;
|
488
|
+
}
|
package/src/index.ts
CHANGED
@@ -4,7 +4,11 @@ export {
|
|
4
4
|
type RetainedQuery,
|
5
5
|
garbageCollectEnvironment,
|
6
6
|
} from './core/garbageCollection';
|
7
|
-
export {
|
7
|
+
export {
|
8
|
+
type PromiseWrapper,
|
9
|
+
readPromise,
|
10
|
+
getPromiseState,
|
11
|
+
} from './core/PromiseWrapper';
|
8
12
|
export { subscribe, normalizeData } from './core/cache';
|
9
13
|
export { makeNetworkRequest } from './core/makeNetworkRequest';
|
10
14
|
export {
|
@@ -21,36 +25,42 @@ export {
|
|
21
25
|
defaultMissingFieldHandler,
|
22
26
|
} from './core/IsographEnvironment';
|
23
27
|
export {
|
24
|
-
EagerReaderArtifact,
|
25
|
-
ComponentReaderArtifact,
|
26
|
-
RefetchReaderArtifact,
|
27
|
-
ReaderAst,
|
28
|
-
ReaderAstNode,
|
29
|
-
ReaderLinkedField,
|
30
|
-
ReaderNonLoadableResolverField,
|
31
|
-
ReaderScalarField,
|
32
|
-
TopLevelReaderArtifact,
|
33
|
-
LoadableField,
|
28
|
+
type EagerReaderArtifact,
|
29
|
+
type ComponentReaderArtifact,
|
30
|
+
type RefetchReaderArtifact,
|
31
|
+
type ReaderAst,
|
32
|
+
type ReaderAstNode,
|
33
|
+
type ReaderLinkedField,
|
34
|
+
type ReaderNonLoadableResolverField,
|
35
|
+
type ReaderScalarField,
|
36
|
+
type TopLevelReaderArtifact,
|
37
|
+
type LoadableField,
|
34
38
|
} from './core/reader';
|
35
39
|
export {
|
36
|
-
NormalizationAst,
|
37
|
-
NormalizationAstNode,
|
38
|
-
NormalizationLinkedField,
|
39
|
-
NormalizationScalarField,
|
40
|
-
IsographEntrypoint,
|
40
|
+
type NormalizationAst,
|
41
|
+
type NormalizationAstNode,
|
42
|
+
type NormalizationLinkedField,
|
43
|
+
type NormalizationScalarField,
|
44
|
+
type IsographEntrypoint,
|
41
45
|
assertIsEntrypoint,
|
42
|
-
RefetchQueryNormalizationArtifact,
|
43
|
-
RefetchQueryNormalizationArtifactWrapper,
|
46
|
+
type RefetchQueryNormalizationArtifact,
|
47
|
+
type RefetchQueryNormalizationArtifactWrapper,
|
48
|
+
type ExtractProps,
|
49
|
+
type ExtractReadFromStore,
|
50
|
+
type ExtractResolverResult,
|
44
51
|
} from './core/entrypoint';
|
45
52
|
export { readButDoNotEvaluate } from './core/read';
|
46
53
|
export {
|
47
|
-
ExtractSecondParam,
|
48
|
-
Argument,
|
49
|
-
ArgumentName,
|
50
|
-
ArgumentValue,
|
51
|
-
Arguments,
|
54
|
+
type ExtractSecondParam,
|
55
|
+
type Argument,
|
56
|
+
type ArgumentName,
|
57
|
+
type ArgumentValue,
|
58
|
+
type Arguments,
|
52
59
|
} from './core/util';
|
53
|
-
export {
|
60
|
+
export {
|
61
|
+
type FragmentReference,
|
62
|
+
type Variables,
|
63
|
+
} from './core/FragmentReference';
|
54
64
|
|
55
65
|
export {
|
56
66
|
IsographEnvironmentProvider,
|
@@ -58,7 +68,7 @@ export {
|
|
58
68
|
type IsographEnvironmentProviderProps,
|
59
69
|
} from './react/IsographEnvironmentProvider';
|
60
70
|
export { useImperativeReference } from './react/useImperativeReference';
|
61
|
-
export {
|
71
|
+
export { FragmentReader } from './react/FragmentReader';
|
62
72
|
export { useResult } from './react/useResult';
|
63
73
|
export { useLazyReference } from './react/useLazyReference';
|
64
74
|
export { useRerenderOnChange } from './react/useRerenderOnChange';
|
@@ -13,10 +13,10 @@ export function useClientSideDefer<TArgs, TResult>(
|
|
13
13
|
args: TArgs,
|
14
14
|
): FragmentReference<any, TResult>;
|
15
15
|
|
16
|
-
// TODO allow the user to pass props somehow
|
17
16
|
export function useClientSideDefer<TArgs, TResult>(
|
18
17
|
loadableField: LoadableField<TArgs, TResult>,
|
19
18
|
args?: TArgs,
|
19
|
+
// TODO this should return { fragmentReference, networkRequestReference }
|
20
20
|
): FragmentReference<any, TResult> {
|
21
21
|
// @ts-expect-error args is missing iff it has the type void
|
22
22
|
const [id, loader] = loadableField(args);
|
@@ -2,8 +2,9 @@ import * as React from 'react';
|
|
2
2
|
import { ExtractReadFromStore, IsographEntrypoint } from '../core/entrypoint';
|
3
3
|
import { FragmentReference } from '../core/FragmentReference';
|
4
4
|
import { useResult } from './useResult';
|
5
|
+
import { NetworkRequestReaderOptions } from '../core/read';
|
5
6
|
|
6
|
-
export function
|
7
|
+
export function FragmentReader<
|
7
8
|
TProps extends Record<any, any>,
|
8
9
|
TEntrypoint extends IsographEntrypoint<any, React.FC<TProps>>,
|
9
10
|
>(
|
@@ -14,6 +15,7 @@ export function FragmentReferenceReader<
|
|
14
15
|
React.FC<{}>
|
15
16
|
>;
|
16
17
|
additionalProps?: TProps;
|
18
|
+
networkRequestOptions?: NetworkRequestReaderOptions;
|
17
19
|
}
|
18
20
|
: {
|
19
21
|
fragmentReference: FragmentReference<
|
@@ -21,8 +23,12 @@ export function FragmentReferenceReader<
|
|
21
23
|
React.FC<TProps>
|
22
24
|
>;
|
23
25
|
additionalProps: TProps;
|
26
|
+
networkRequestOptions?: NetworkRequestReaderOptions;
|
24
27
|
},
|
25
28
|
): React.ReactNode {
|
26
|
-
const Component = useResult(
|
29
|
+
const Component = useResult(
|
30
|
+
props.fragmentReference,
|
31
|
+
props.networkRequestOptions ?? {},
|
32
|
+
);
|
27
33
|
return <Component {...props.additionalProps} />;
|
28
34
|
}
|
@@ -17,7 +17,7 @@ export function useImperativeReference<
|
|
17
17
|
fragmentReference:
|
18
18
|
| FragmentReference<TReadFromStore, TClientFieldValue>
|
19
19
|
| UnassignedState;
|
20
|
-
|
20
|
+
loadFragmentReference: (variables: Variables) => void;
|
21
21
|
} {
|
22
22
|
const { state, setState } =
|
23
23
|
useUpdatableDisposableState<
|
@@ -26,8 +26,8 @@ export function useImperativeReference<
|
|
26
26
|
const environment = useIsographEnvironment();
|
27
27
|
return {
|
28
28
|
fragmentReference: state,
|
29
|
-
|
30
|
-
const [
|
29
|
+
loadFragmentReference: (variables: Variables) => {
|
30
|
+
const [networkRequest, disposeNetworkRequest] = makeNetworkRequest(
|
31
31
|
environment,
|
32
32
|
entrypoint,
|
33
33
|
variables,
|
@@ -39,6 +39,7 @@ export function useImperativeReference<
|
|
39
39
|
root: ROOT_ID,
|
40
40
|
variables,
|
41
41
|
nestedRefetchQueries: entrypoint.nestedRefetchQueries,
|
42
|
+
networkRequest,
|
42
43
|
},
|
43
44
|
() => {
|
44
45
|
disposeNetworkRequest();
|
@@ -17,9 +17,7 @@ export function useLazyReference<
|
|
17
17
|
const environment = useIsographEnvironment();
|
18
18
|
const cache = getOrCreateCacheForArtifact(environment, entrypoint, variables);
|
19
19
|
|
20
|
-
|
21
|
-
// @ts-ignore(6133)
|
22
|
-
const _data = useLazyDisposableState(cache).state;
|
20
|
+
const networkRequest = useLazyDisposableState(cache).state;
|
23
21
|
|
24
22
|
return {
|
25
23
|
fragmentReference: {
|
@@ -28,6 +26,7 @@ export function useLazyReference<
|
|
28
26
|
root: ROOT_ID,
|
29
27
|
variables,
|
30
28
|
nestedRefetchQueries: entrypoint.nestedRefetchQueries,
|
29
|
+
networkRequest,
|
31
30
|
},
|
32
31
|
};
|
33
32
|
}
|
@@ -1,22 +1,25 @@
|
|
1
1
|
import { useState } from 'react';
|
2
2
|
import { FragmentReference } from '../core/FragmentReference';
|
3
|
-
import {
|
4
|
-
|
3
|
+
import {
|
4
|
+
NetworkRequestReaderOptions,
|
5
|
+
readButDoNotEvaluate,
|
6
|
+
} from '../core/read';
|
5
7
|
import { useRerenderOnChange } from './useRerenderOnChange';
|
8
|
+
import { useIsographEnvironment } from './IsographEnvironmentProvider';
|
6
9
|
|
7
10
|
/**
|
8
11
|
* Read the data from a fragment reference and subscribe to updates.
|
9
12
|
* Does not pass the data to the fragment reference's resolver function.
|
10
13
|
*/
|
11
14
|
export function useReadAndSubscribe<TReadFromStore extends Object>(
|
12
|
-
environment: IsographEnvironment,
|
13
15
|
fragmentReference: FragmentReference<TReadFromStore, any>,
|
16
|
+
networkRequestOptions: NetworkRequestReaderOptions,
|
14
17
|
): TReadFromStore {
|
18
|
+
const environment = useIsographEnvironment();
|
15
19
|
const [readOutDataAndRecords, setReadOutDataAndRecords] = useState(() =>
|
16
|
-
readButDoNotEvaluate(environment, fragmentReference),
|
20
|
+
readButDoNotEvaluate(environment, fragmentReference, networkRequestOptions),
|
17
21
|
);
|
18
22
|
useRerenderOnChange(
|
19
|
-
environment,
|
20
23
|
readOutDataAndRecords,
|
21
24
|
fragmentReference,
|
22
25
|
setReadOutDataAndRecords,
|
@@ -1,19 +1,19 @@
|
|
1
1
|
import { useEffect } from 'react';
|
2
|
-
import { IsographEnvironment } from '../core/IsographEnvironment';
|
3
2
|
import { subscribe } from '../core/cache';
|
4
3
|
import { WithEncounteredRecords } from '../core/read';
|
5
4
|
import { FragmentReference } from '../core/FragmentReference';
|
5
|
+
import { useIsographEnvironment } from './IsographEnvironmentProvider';
|
6
6
|
|
7
7
|
// TODO add unit tests for this. Add integration tests that test
|
8
8
|
// behavior when the encounteredRecords underneath a fragment change.
|
9
9
|
export function useRerenderOnChange<TReadFromStore extends Object>(
|
10
|
-
environment: IsographEnvironment,
|
11
10
|
encounteredDataAndRecords: WithEncounteredRecords<TReadFromStore>,
|
12
11
|
fragmentReference: FragmentReference<any, any>,
|
13
12
|
setEncounteredDataAndRecords: (
|
14
13
|
data: WithEncounteredRecords<TReadFromStore>,
|
15
14
|
) => void,
|
16
15
|
) {
|
16
|
+
const environment = useIsographEnvironment();
|
17
17
|
useEffect(() => {
|
18
18
|
return subscribe(
|
19
19
|
environment,
|
package/src/react/useResult.ts
CHANGED
@@ -2,12 +2,20 @@ import { useIsographEnvironment } from '../react/IsographEnvironmentProvider';
|
|
2
2
|
import { FragmentReference } from '../core/FragmentReference';
|
3
3
|
import { getOrCreateCachedComponent } from '../core/componentCache';
|
4
4
|
import { useReadAndSubscribe } from './useReadAndSubscribe';
|
5
|
+
import { NetworkRequestReaderOptions } from '../core/read';
|
6
|
+
import { getPromiseState, PromiseWrapper } from '../core/PromiseWrapper';
|
5
7
|
|
6
8
|
export function useResult<TReadFromStore extends Object, TClientFieldValue>(
|
7
9
|
fragmentReference: FragmentReference<TReadFromStore, TClientFieldValue>,
|
10
|
+
networkRequestOptions: NetworkRequestReaderOptions,
|
8
11
|
): TClientFieldValue {
|
9
12
|
const environment = useIsographEnvironment();
|
10
13
|
|
14
|
+
maybeUnwrapNetworkRequest(
|
15
|
+
fragmentReference.networkRequest,
|
16
|
+
networkRequestOptions,
|
17
|
+
);
|
18
|
+
|
11
19
|
switch (fragmentReference.readerArtifact.kind) {
|
12
20
|
case 'ComponentReaderArtifact': {
|
13
21
|
// @ts-expect-error
|
@@ -15,11 +23,30 @@ export function useResult<TReadFromStore extends Object, TClientFieldValue>(
|
|
15
23
|
environment,
|
16
24
|
fragmentReference.readerArtifact.componentName,
|
17
25
|
fragmentReference,
|
26
|
+
networkRequestOptions,
|
18
27
|
);
|
19
28
|
}
|
20
29
|
case 'EagerReaderArtifact': {
|
21
|
-
const data = useReadAndSubscribe(
|
30
|
+
const data = useReadAndSubscribe(
|
31
|
+
fragmentReference,
|
32
|
+
networkRequestOptions,
|
33
|
+
);
|
22
34
|
return fragmentReference.readerArtifact.resolver(data);
|
23
35
|
}
|
24
36
|
}
|
25
37
|
}
|
38
|
+
|
39
|
+
export function maybeUnwrapNetworkRequest(
|
40
|
+
networkRequest: PromiseWrapper<void, any>,
|
41
|
+
networkRequestOptions: NetworkRequestReaderOptions,
|
42
|
+
) {
|
43
|
+
const state = getPromiseState(networkRequest);
|
44
|
+
if (state.kind === 'Err' && networkRequestOptions.throwOnNetworkError) {
|
45
|
+
throw state.error;
|
46
|
+
} else if (
|
47
|
+
state.kind === 'Pending' &&
|
48
|
+
networkRequestOptions.suspendIfInFlight
|
49
|
+
) {
|
50
|
+
throw state.promise;
|
51
|
+
}
|
52
|
+
}
|