@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
@@ -4,13 +4,15 @@ exports.useReadAndSubscribe = void 0;
|
|
4
4
|
const react_1 = require("react");
|
5
5
|
const read_1 = require("../core/read");
|
6
6
|
const useRerenderOnChange_1 = require("./useRerenderOnChange");
|
7
|
+
const IsographEnvironmentProvider_1 = require("./IsographEnvironmentProvider");
|
7
8
|
/**
|
8
9
|
* Read the data from a fragment reference and subscribe to updates.
|
9
10
|
* Does not pass the data to the fragment reference's resolver function.
|
10
11
|
*/
|
11
|
-
function useReadAndSubscribe(
|
12
|
-
const
|
13
|
-
(0,
|
12
|
+
function useReadAndSubscribe(fragmentReference, networkRequestOptions) {
|
13
|
+
const environment = (0, IsographEnvironmentProvider_1.useIsographEnvironment)();
|
14
|
+
const [readOutDataAndRecords, setReadOutDataAndRecords] = (0, react_1.useState)(() => (0, read_1.readButDoNotEvaluate)(environment, fragmentReference, networkRequestOptions));
|
15
|
+
(0, useRerenderOnChange_1.useRerenderOnChange)(readOutDataAndRecords, fragmentReference, setReadOutDataAndRecords);
|
14
16
|
return readOutDataAndRecords.item;
|
15
17
|
}
|
16
18
|
exports.useReadAndSubscribe = useReadAndSubscribe;
|
@@ -1,4 +1,3 @@
|
|
1
|
-
import { IsographEnvironment } from '../core/IsographEnvironment';
|
2
1
|
import { WithEncounteredRecords } from '../core/read';
|
3
2
|
import { FragmentReference } from '../core/FragmentReference';
|
4
|
-
export declare function useRerenderOnChange<TReadFromStore extends Object>(
|
3
|
+
export declare function useRerenderOnChange<TReadFromStore extends Object>(encounteredDataAndRecords: WithEncounteredRecords<TReadFromStore>, fragmentReference: FragmentReference<any, any>, setEncounteredDataAndRecords: (data: WithEncounteredRecords<TReadFromStore>) => void): void;
|
@@ -3,9 +3,11 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.useRerenderOnChange = void 0;
|
4
4
|
const react_1 = require("react");
|
5
5
|
const cache_1 = require("../core/cache");
|
6
|
+
const IsographEnvironmentProvider_1 = require("./IsographEnvironmentProvider");
|
6
7
|
// TODO add unit tests for this. Add integration tests that test
|
7
8
|
// behavior when the encounteredRecords underneath a fragment change.
|
8
|
-
function useRerenderOnChange(
|
9
|
+
function useRerenderOnChange(encounteredDataAndRecords, fragmentReference, setEncounteredDataAndRecords) {
|
10
|
+
const environment = (0, IsographEnvironmentProvider_1.useIsographEnvironment)();
|
9
11
|
(0, react_1.useEffect)(() => {
|
10
12
|
return (0, cache_1.subscribe)(environment, encounteredDataAndRecords, fragmentReference, (newEncounteredDataAndRecords) => {
|
11
13
|
setEncounteredDataAndRecords(newEncounteredDataAndRecords);
|
@@ -1,2 +1,5 @@
|
|
1
1
|
import { FragmentReference } from '../core/FragmentReference';
|
2
|
-
|
2
|
+
import { NetworkRequestReaderOptions } from '../core/read';
|
3
|
+
import { PromiseWrapper } from '../core/PromiseWrapper';
|
4
|
+
export declare function useResult<TReadFromStore extends Object, TClientFieldValue>(fragmentReference: FragmentReference<TReadFromStore, TClientFieldValue>, networkRequestOptions: NetworkRequestReaderOptions): TClientFieldValue;
|
5
|
+
export declare function maybeUnwrapNetworkRequest(networkRequest: PromiseWrapper<void, any>, networkRequestOptions: NetworkRequestReaderOptions): void;
|
package/dist/react/useResult.js
CHANGED
@@ -1,20 +1,33 @@
|
|
1
1
|
"use strict";
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
-
exports.useResult = void 0;
|
3
|
+
exports.maybeUnwrapNetworkRequest = exports.useResult = void 0;
|
4
4
|
const IsographEnvironmentProvider_1 = require("../react/IsographEnvironmentProvider");
|
5
5
|
const componentCache_1 = require("../core/componentCache");
|
6
6
|
const useReadAndSubscribe_1 = require("./useReadAndSubscribe");
|
7
|
-
|
7
|
+
const PromiseWrapper_1 = require("../core/PromiseWrapper");
|
8
|
+
function useResult(fragmentReference, networkRequestOptions) {
|
8
9
|
const environment = (0, IsographEnvironmentProvider_1.useIsographEnvironment)();
|
10
|
+
maybeUnwrapNetworkRequest(fragmentReference.networkRequest, networkRequestOptions);
|
9
11
|
switch (fragmentReference.readerArtifact.kind) {
|
10
12
|
case 'ComponentReaderArtifact': {
|
11
13
|
// @ts-expect-error
|
12
|
-
return (0, componentCache_1.getOrCreateCachedComponent)(environment, fragmentReference.readerArtifact.componentName, fragmentReference);
|
14
|
+
return (0, componentCache_1.getOrCreateCachedComponent)(environment, fragmentReference.readerArtifact.componentName, fragmentReference, networkRequestOptions);
|
13
15
|
}
|
14
16
|
case 'EagerReaderArtifact': {
|
15
|
-
const data = (0, useReadAndSubscribe_1.useReadAndSubscribe)(
|
17
|
+
const data = (0, useReadAndSubscribe_1.useReadAndSubscribe)(fragmentReference, networkRequestOptions);
|
16
18
|
return fragmentReference.readerArtifact.resolver(data);
|
17
19
|
}
|
18
20
|
}
|
19
21
|
}
|
20
22
|
exports.useResult = useResult;
|
23
|
+
function maybeUnwrapNetworkRequest(networkRequest, networkRequestOptions) {
|
24
|
+
const state = (0, PromiseWrapper_1.getPromiseState)(networkRequest);
|
25
|
+
if (state.kind === 'Err' && networkRequestOptions.throwOnNetworkError) {
|
26
|
+
throw state.error;
|
27
|
+
}
|
28
|
+
else if (state.kind === 'Pending' &&
|
29
|
+
networkRequestOptions.suspendIfInFlight) {
|
30
|
+
throw state.promise;
|
31
|
+
}
|
32
|
+
}
|
33
|
+
exports.maybeUnwrapNetworkRequest = maybeUnwrapNetworkRequest;
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@isograph/react",
|
3
|
-
"version": "0.0.0-main-
|
3
|
+
"version": "0.0.0-main-d3ef6e33",
|
4
4
|
"description": "Use Isograph with React",
|
5
5
|
"homepage": "https://isograph.dev",
|
6
6
|
"main": "dist/index.js",
|
@@ -17,8 +17,8 @@
|
|
17
17
|
"tsc": "tsc"
|
18
18
|
},
|
19
19
|
"dependencies": {
|
20
|
-
"@isograph/disposable-types": "0.0.0-main-
|
21
|
-
"@isograph/react-disposable-state": "0.0.0-main-
|
20
|
+
"@isograph/disposable-types": "0.0.0-main-d3ef6e33",
|
21
|
+
"@isograph/react-disposable-state": "0.0.0-main-d3ef6e33",
|
22
22
|
"react": "^18.2.0"
|
23
23
|
},
|
24
24
|
"devDependencies": {
|
@@ -1,6 +1,7 @@
|
|
1
1
|
import { DataId } from './IsographEnvironment';
|
2
2
|
import { RefetchQueryNormalizationArtifactWrapper } from '../core/entrypoint';
|
3
3
|
import { TopLevelReaderArtifact } from './reader';
|
4
|
+
import { PromiseWrapper } from './PromiseWrapper';
|
4
5
|
|
5
6
|
// TODO type this better
|
6
7
|
export type VariableValue = string | number | boolean | null | object;
|
@@ -21,4 +22,5 @@ export type FragmentReference<
|
|
21
22
|
readonly variables: Variables | null;
|
22
23
|
// TODO: We should instead have ReaderAst<TClientFieldProps>
|
23
24
|
readonly nestedRefetchQueries: RefetchQueryNormalizationArtifactWrapper[];
|
25
|
+
readonly networkRequest: PromiseWrapper<void, any>;
|
24
26
|
};
|
@@ -1,29 +1,75 @@
|
|
1
|
+
export type AnyError = any;
|
2
|
+
|
1
3
|
const NOT_SET: Symbol = Symbol('NOT_SET');
|
2
4
|
type NotSet = typeof NOT_SET;
|
3
5
|
|
6
|
+
type Result<T, E> =
|
7
|
+
| {
|
8
|
+
kind: 'Ok';
|
9
|
+
value: T;
|
10
|
+
}
|
11
|
+
| {
|
12
|
+
kind: 'Err';
|
13
|
+
error: E;
|
14
|
+
};
|
15
|
+
|
4
16
|
/**
|
5
17
|
* Invariant:
|
6
18
|
* Before the promise is resolved, value becomes non-null.
|
7
19
|
*/
|
8
|
-
export type PromiseWrapper<T> = {
|
20
|
+
export type PromiseWrapper<T, E> = {
|
9
21
|
readonly promise: Promise<T>;
|
10
|
-
|
22
|
+
result: Result<Exclude<T, NotSet>, E> | NotSet;
|
11
23
|
};
|
12
24
|
|
13
|
-
export function wrapPromise<T>(promise: Promise<T>): PromiseWrapper<T> {
|
25
|
+
export function wrapPromise<T>(promise: Promise<T>): PromiseWrapper<T, any> {
|
14
26
|
// TODO confirm suspense works if the promise is already resolved.
|
15
|
-
const wrapper: PromiseWrapper<T> = { promise,
|
16
|
-
promise
|
17
|
-
|
18
|
-
|
19
|
-
|
27
|
+
const wrapper: PromiseWrapper<T, any> = { promise, result: NOT_SET };
|
28
|
+
promise
|
29
|
+
.then((v) => {
|
30
|
+
// v is assignable to Exclude<T, Symbol> | Symbol
|
31
|
+
wrapper.result = { kind: 'Ok', value: v as any };
|
32
|
+
})
|
33
|
+
.catch((e) => {
|
34
|
+
// e is assignable to Exclude<T, Symbol> | Symbol
|
35
|
+
wrapper.result = { kind: 'Err', error: e as any };
|
36
|
+
});
|
20
37
|
return wrapper;
|
21
38
|
}
|
22
39
|
|
23
|
-
export function
|
24
|
-
|
25
|
-
|
26
|
-
|
40
|
+
export function readPromise<T, E>(p: PromiseWrapper<T, E>): T {
|
41
|
+
const { result } = p;
|
42
|
+
if (result !== NOT_SET) {
|
43
|
+
// Safety: p.result is either NOT_SET or an actual value.
|
44
|
+
const resultKind = result as Result<T, any>;
|
45
|
+
if (resultKind.kind === 'Ok') {
|
46
|
+
return resultKind.value;
|
47
|
+
} else {
|
48
|
+
throw resultKind.error;
|
49
|
+
}
|
27
50
|
}
|
51
|
+
|
28
52
|
throw p.promise;
|
29
53
|
}
|
54
|
+
|
55
|
+
export type PromiseState<T, E> =
|
56
|
+
| {
|
57
|
+
kind: 'Pending';
|
58
|
+
promise: Promise<T>;
|
59
|
+
}
|
60
|
+
| Result<T, E>;
|
61
|
+
|
62
|
+
export function getPromiseState<T, E>(
|
63
|
+
p: PromiseWrapper<T, E>,
|
64
|
+
): PromiseState<T, E> {
|
65
|
+
const { result } = p;
|
66
|
+
if (result !== NOT_SET) {
|
67
|
+
// Safety: p.result is either NOT_SET or an actual value.
|
68
|
+
const resultKind = result as Result<T, any>;
|
69
|
+
return resultKind;
|
70
|
+
}
|
71
|
+
return {
|
72
|
+
kind: 'Pending',
|
73
|
+
promise: p.promise,
|
74
|
+
};
|
75
|
+
}
|
package/src/core/cache.ts
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
import { Factory, ParentCache } from '@isograph/react-disposable-state';
|
2
|
-
import { PromiseWrapper } from './PromiseWrapper';
|
2
|
+
import { AnyError, PromiseWrapper } from './PromiseWrapper';
|
3
3
|
import {
|
4
4
|
DataId,
|
5
5
|
ROOT_ID,
|
@@ -80,15 +80,10 @@ export function getOrCreateCacheForArtifact<
|
|
80
80
|
environment: IsographEnvironment,
|
81
81
|
artifact: IsographEntrypoint<TReadFromStore, TClientFieldValue>,
|
82
82
|
variables: Variables,
|
83
|
-
): ParentCache<PromiseWrapper<
|
83
|
+
): ParentCache<PromiseWrapper<void, AnyError>> {
|
84
84
|
const cacheKey = artifact.queryText + JSON.stringify(stableCopy(variables));
|
85
|
-
const factory
|
86
|
-
|
87
|
-
return getOrCreateCache<PromiseWrapper<TClientFieldValue>>(
|
88
|
-
environment,
|
89
|
-
cacheKey,
|
90
|
-
factory,
|
91
|
-
);
|
85
|
+
const factory = () => makeNetworkRequest(environment, artifact, variables);
|
86
|
+
return getOrCreateCache(environment, cacheKey, factory);
|
92
87
|
}
|
93
88
|
|
94
89
|
type NetworkResponseScalarValue = string | number | boolean;
|
@@ -183,64 +178,92 @@ export function onNextChange(environment: IsographEnvironment): Promise<void> {
|
|
183
178
|
});
|
184
179
|
}
|
185
180
|
|
181
|
+
// Calls to readButDoNotEvaluate can suspend (i.e. throw a promise).
|
182
|
+
// Maybe in the future, they will be able to throw errors.
|
183
|
+
//
|
184
|
+
// That's probably okay to ignore. We don't, however, want to prevent
|
185
|
+
// updating other subscriptions if one subscription had missing data.
|
186
|
+
function withErrorHandling<T>(f: (t: T) => void): (t: T) => void {
|
187
|
+
return (t) => {
|
188
|
+
try {
|
189
|
+
return f(t);
|
190
|
+
} catch {}
|
191
|
+
};
|
192
|
+
}
|
193
|
+
|
186
194
|
function callSubscriptions(
|
187
195
|
environment: IsographEnvironment,
|
188
196
|
recordsEncounteredWhenNormalizing: Set<DataId>,
|
189
197
|
) {
|
190
|
-
environment.subscriptions.forEach(
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
hasOverlappingIds(
|
198
|
-
recordsEncounteredWhenNormalizing,
|
199
|
-
subscription.encounteredDataAndRecords.encounteredRecords,
|
200
|
-
)
|
201
|
-
) {
|
202
|
-
const newEncounteredDataAndRecords = readButDoNotEvaluate(
|
203
|
-
environment,
|
204
|
-
subscription.fragmentReference,
|
205
|
-
);
|
206
|
-
|
198
|
+
environment.subscriptions.forEach(
|
199
|
+
withErrorHandling((subscription) => {
|
200
|
+
switch (subscription.kind) {
|
201
|
+
case 'FragmentSubscription': {
|
202
|
+
// TODO if there are multiple components subscribed to the same
|
203
|
+
// fragment, we will call readButNotEvaluate multiple times. We
|
204
|
+
// should fix that.
|
207
205
|
if (
|
208
|
-
|
209
|
-
|
210
|
-
|
206
|
+
hasOverlappingIds(
|
207
|
+
recordsEncounteredWhenNormalizing,
|
208
|
+
subscription.encounteredDataAndRecords.encounteredRecords,
|
211
209
|
)
|
212
210
|
) {
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
211
|
+
const newEncounteredDataAndRecords = readButDoNotEvaluate(
|
212
|
+
environment,
|
213
|
+
subscription.fragmentReference,
|
214
|
+
// Is this wrong?
|
215
|
+
// Reasons to think no:
|
216
|
+
// - we are only updating the read-out value, and the network
|
217
|
+
// options only affect whether we throw.
|
218
|
+
// - the component will re-render, and re-throw on its own, anyway.
|
219
|
+
//
|
220
|
+
// Reasons to think not:
|
221
|
+
// - it seems more efficient to suspend here and not update state,
|
222
|
+
// if we expect that the component will just throw anyway
|
223
|
+
// - consistency
|
224
|
+
// - it's also weird, this is called from makeNetworkRequest, where
|
225
|
+
// we don't currently pass network request options
|
226
|
+
{},
|
227
|
+
);
|
228
|
+
|
229
|
+
if (
|
230
|
+
!areEqualObjectsWithDeepComparison(
|
231
|
+
subscription.encounteredDataAndRecords.item,
|
232
|
+
newEncounteredDataAndRecords.item,
|
233
|
+
)
|
234
|
+
) {
|
235
|
+
if (typeof window !== 'undefined' && window.__LOG) {
|
236
|
+
console.log('Deep equality - No', {
|
237
|
+
fragmentReference: subscription.fragmentReference,
|
238
|
+
old: subscription.encounteredDataAndRecords.item,
|
239
|
+
new: newEncounteredDataAndRecords.item,
|
240
|
+
});
|
241
|
+
}
|
242
|
+
// TODO deep compare values
|
243
|
+
subscription.callback(newEncounteredDataAndRecords);
|
244
|
+
} else {
|
245
|
+
if (typeof window !== 'undefined' && window.__LOG) {
|
246
|
+
console.log('Deep equality - Yes', {
|
247
|
+
fragmentReference: subscription.fragmentReference,
|
248
|
+
old: subscription.encounteredDataAndRecords.item,
|
249
|
+
});
|
250
|
+
}
|
228
251
|
}
|
229
252
|
}
|
253
|
+
return;
|
254
|
+
}
|
255
|
+
case 'AnyRecords': {
|
256
|
+
return subscription.callback();
|
257
|
+
}
|
258
|
+
default: {
|
259
|
+
// Ensure we have covered all variants
|
260
|
+
const _: never = subscription;
|
261
|
+
_;
|
262
|
+
throw new Error('Unexpected case');
|
230
263
|
}
|
231
|
-
return;
|
232
|
-
}
|
233
|
-
case 'AnyRecords': {
|
234
|
-
return subscription.callback();
|
235
|
-
}
|
236
|
-
default: {
|
237
|
-
// Ensure we have covered all variants
|
238
|
-
const _: never = subscription;
|
239
|
-
_;
|
240
|
-
throw new Error('Unexpected case');
|
241
264
|
}
|
242
|
-
}
|
243
|
-
|
265
|
+
}),
|
266
|
+
);
|
244
267
|
}
|
245
268
|
|
246
269
|
function hasOverlappingIds(set1: Set<DataId>, set2: Set<DataId>): boolean {
|
@@ -563,7 +586,7 @@ function getStoreKeyChunkForArgumentValue(
|
|
563
586
|
return argumentValue.value;
|
564
587
|
}
|
565
588
|
case 'Variable': {
|
566
|
-
return variables[argumentValue.name];
|
589
|
+
return variables[argumentValue.name] ?? 'null';
|
567
590
|
}
|
568
591
|
case 'String': {
|
569
592
|
return argumentValue.value;
|
@@ -2,11 +2,13 @@ import { stableCopy } from './cache';
|
|
2
2
|
import { IsographEnvironment } from './IsographEnvironment';
|
3
3
|
import { FragmentReference } from './FragmentReference';
|
4
4
|
import { useReadAndSubscribe } from '../react/useReadAndSubscribe';
|
5
|
+
import { NetworkRequestReaderOptions } from './read';
|
5
6
|
|
6
7
|
export function getOrCreateCachedComponent(
|
7
8
|
environment: IsographEnvironment,
|
8
9
|
componentName: string,
|
9
10
|
fragmentReference: FragmentReference<any, any>,
|
11
|
+
networkRequestOptions: NetworkRequestReaderOptions,
|
10
12
|
): React.FC<any> {
|
11
13
|
// cachedComponentsById is a three layer cache: id, then component name, then
|
12
14
|
// stringified args. These three, together, uniquely identify a read at a given
|
@@ -27,7 +29,10 @@ export function getOrCreateCachedComponent(
|
|
27
29
|
byArgs[stringifiedArgs] ??
|
28
30
|
(() => {
|
29
31
|
function Component(additionalRuntimeProps: { [key: string]: any }) {
|
30
|
-
const data = useReadAndSubscribe(
|
32
|
+
const data = useReadAndSubscribe(
|
33
|
+
fragmentReference,
|
34
|
+
networkRequestOptions,
|
35
|
+
);
|
31
36
|
|
32
37
|
if (typeof window !== 'undefined' && window.__LOG) {
|
33
38
|
console.log(
|
package/src/core/entrypoint.ts
CHANGED
@@ -74,3 +74,4 @@ export type ExtractReadFromStore<Type> =
|
|
74
74
|
Type extends IsographEntrypoint<infer X, any> ? X : never;
|
75
75
|
export type ExtractResolverResult<Type> =
|
76
76
|
Type extends IsographEntrypoint<any, infer X> ? X : never;
|
77
|
+
export type ExtractProps<Type> = Type extends React.FC<infer X> ? X : never;
|
@@ -11,14 +11,14 @@ import {
|
|
11
11
|
unretainQuery,
|
12
12
|
} from './garbageCollection';
|
13
13
|
import { IsographEnvironment } from './IsographEnvironment';
|
14
|
-
import { PromiseWrapper, wrapPromise } from './PromiseWrapper';
|
14
|
+
import { AnyError, PromiseWrapper, wrapPromise } from './PromiseWrapper';
|
15
15
|
import { normalizeData } from './cache';
|
16
16
|
|
17
|
-
export function makeNetworkRequest
|
17
|
+
export function makeNetworkRequest(
|
18
18
|
environment: IsographEnvironment,
|
19
19
|
artifact: RefetchQueryNormalizationArtifact | IsographEntrypoint<any, any>,
|
20
20
|
variables: Variables,
|
21
|
-
): ItemCleanupPair<PromiseWrapper<
|
21
|
+
): ItemCleanupPair<PromiseWrapper<void, AnyError>> {
|
22
22
|
if (typeof window !== 'undefined' && window.__LOG) {
|
23
23
|
console.log('make network request', artifact, variables);
|
24
24
|
}
|
@@ -33,6 +33,13 @@ export function makeNetworkRequest<T>(
|
|
33
33
|
console.log('network response', artifact, networkResponse);
|
34
34
|
}
|
35
35
|
|
36
|
+
if (networkResponse.errors != null) {
|
37
|
+
// @ts-expect-error Why are we getting the wrong constructor here?
|
38
|
+
throw new Error('GraphQL network response had errors', {
|
39
|
+
cause: networkResponse,
|
40
|
+
});
|
41
|
+
}
|
42
|
+
|
36
43
|
if (status.kind === 'UndisposedIncomplete') {
|
37
44
|
normalizeData(
|
38
45
|
environment,
|
@@ -51,13 +58,11 @@ export function makeNetworkRequest<T>(
|
|
51
58
|
};
|
52
59
|
retainQuery(environment, retainedQuery);
|
53
60
|
}
|
54
|
-
// TODO return null
|
55
|
-
return networkResponse;
|
56
61
|
});
|
57
62
|
|
58
63
|
const wrapper = wrapPromise(promise);
|
59
64
|
|
60
|
-
const response: ItemCleanupPair<PromiseWrapper<
|
65
|
+
const response: ItemCleanupPair<PromiseWrapper<void, AnyError>> = [
|
61
66
|
wrapper,
|
62
67
|
() => {
|
63
68
|
if (status.kind === 'UndisposedComplete') {
|