@isograph/react 0.0.0-main-7fb13e90 → 0.0.0-main-9b984d79
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/IsographEnvironment.d.ts +4 -0
- package/dist/core/IsographEnvironment.js +13 -1
- package/dist/core/entrypoint.d.ts +5 -0
- package/dist/core/read.js +90 -38
- package/dist/core/reader.d.ts +2 -2
- package/package.json +4 -4
- package/src/core/IsographEnvironment.ts +23 -0
- package/src/core/entrypoint.ts +11 -0
- package/src/core/read.ts +154 -57
- package/src/core/reader.ts +5 -1
- package/src/tests/__isograph/Query/meName/entrypoint.ts +1 -1
- package/src/tests/__isograph/Query/meNameSuccessor/entrypoint.ts +1 -1
- package/src/tests/__isograph/Query/nodeField/entrypoint.ts +1 -1
@@ -3,6 +3,8 @@ import { ParentCache } from '@isograph/react-disposable-state';
|
|
3
3
|
import { RetainedQuery } from './garbageCollection';
|
4
4
|
import { WithEncounteredRecords } from './read';
|
5
5
|
import { FragmentReference, Variables } from './FragmentReference';
|
6
|
+
import { PromiseWrapper } from './PromiseWrapper';
|
7
|
+
import { IsographEntrypoint } from './entrypoint';
|
6
8
|
export type ComponentOrFieldName = string;
|
7
9
|
export type StringifiedArgs = string;
|
8
10
|
type ComponentCache = {
|
@@ -35,6 +37,7 @@ export type IsographEnvironment = {
|
|
35
37
|
readonly componentCache: ComponentCache;
|
36
38
|
readonly subscriptions: Subscriptions;
|
37
39
|
readonly fragmentCache: CacheMap<FragmentReference<any, any>>;
|
40
|
+
readonly entrypointArtifactCache: Map<string, PromiseWrapper<IsographEntrypoint<any, any>>>;
|
38
41
|
readonly retainedQueries: Set<RetainedQuery>;
|
39
42
|
readonly gcBuffer: Array<RetainedQuery>;
|
40
43
|
readonly gcBufferSize: number;
|
@@ -64,4 +67,5 @@ export declare function defaultMissingFieldHandler(_storeRecord: StoreRecord, _r
|
|
64
67
|
} | null, variables: Variables | null): Link | undefined;
|
65
68
|
export declare function assertLink(link: DataTypeValue): Link | null | undefined;
|
66
69
|
export declare function getLink(maybeLink: DataTypeValue): Link | null;
|
70
|
+
export declare function getOrLoadIsographArtifact(environment: IsographEnvironment, key: string, loader: () => Promise<IsographEntrypoint<any, any>>): PromiseWrapper<IsographEntrypoint<any, any>>;
|
67
71
|
export {};
|
@@ -1,6 +1,7 @@
|
|
1
1
|
"use strict";
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
-
exports.getLink = exports.assertLink = exports.defaultMissingFieldHandler = exports.createIsographStore = exports.createIsographEnvironment = exports.ROOT_ID = void 0;
|
3
|
+
exports.getOrLoadIsographArtifact = exports.getLink = exports.assertLink = exports.defaultMissingFieldHandler = exports.createIsographStore = exports.createIsographEnvironment = exports.ROOT_ID = void 0;
|
4
|
+
const PromiseWrapper_1 = require("./PromiseWrapper");
|
4
5
|
exports.ROOT_ID = '__ROOT';
|
5
6
|
const DEFAULT_GC_BUFFER_SIZE = 10;
|
6
7
|
function createIsographEnvironment(store, networkFunction, missingFieldHandler) {
|
@@ -11,6 +12,7 @@ function createIsographEnvironment(store, networkFunction, missingFieldHandler)
|
|
11
12
|
componentCache: {},
|
12
13
|
subscriptions: new Set(),
|
13
14
|
fragmentCache: {},
|
15
|
+
entrypointArtifactCache: new Map(),
|
14
16
|
retainedQueries: new Set(),
|
15
17
|
gcBuffer: [],
|
16
18
|
gcBufferSize: DEFAULT_GC_BUFFER_SIZE,
|
@@ -58,3 +60,13 @@ function getLink(maybeLink) {
|
|
58
60
|
return null;
|
59
61
|
}
|
60
62
|
exports.getLink = getLink;
|
63
|
+
function getOrLoadIsographArtifact(environment, key, loader) {
|
64
|
+
const value = environment.entrypointArtifactCache.get(key);
|
65
|
+
if (value != null) {
|
66
|
+
return value;
|
67
|
+
}
|
68
|
+
const wrapped = (0, PromiseWrapper_1.wrapPromise)(loader());
|
69
|
+
environment.entrypointArtifactCache.set(key, wrapped);
|
70
|
+
return wrapped;
|
71
|
+
}
|
72
|
+
exports.getOrLoadIsographArtifact = getOrLoadIsographArtifact;
|
@@ -12,6 +12,11 @@ export type IsographEntrypoint<TReadFromStore extends Object, TClientFieldValue>
|
|
12
12
|
readonly normalizationAst: NormalizationAst;
|
13
13
|
readonly readerWithRefetchQueries: ReaderWithRefetchQueries<TReadFromStore, TClientFieldValue>;
|
14
14
|
};
|
15
|
+
export type IsographEntrypointLoader<TReadFromStore extends Object, TClientFieldValue> = {
|
16
|
+
readonly kind: 'EntrypointLoader';
|
17
|
+
readonly typeAndField: string;
|
18
|
+
readonly loader: () => Promise<IsographEntrypoint<TReadFromStore, TClientFieldValue>>;
|
19
|
+
};
|
15
20
|
export type NormalizationAstNode = NormalizationScalarField | NormalizationLinkedField | NormalizationInlineFragment;
|
16
21
|
export type NormalizationAst = ReadonlyArray<NormalizationAstNode>;
|
17
22
|
export type NormalizationScalarField = {
|
package/dist/core/read.js
CHANGED
@@ -193,32 +193,40 @@ function readData(environment, ast, root, variables, nestedRefetchQueries, netwo
|
|
193
193
|
case 'Resolver': {
|
194
194
|
const usedRefetchQueries = field.usedRefetchQueries;
|
195
195
|
const resolverRefetchQueries = usedRefetchQueries.map((index) => nestedRefetchQueries[index]);
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
196
|
+
switch (field.readerArtifact.kind) {
|
197
|
+
case 'EagerReaderArtifact': {
|
198
|
+
const data = readData(environment, field.readerArtifact.readerAst, root, variables, resolverRefetchQueries, networkRequest, networkRequestOptions, mutableEncounteredRecords);
|
199
|
+
if (data.kind === 'MissingData') {
|
200
|
+
return {
|
201
|
+
kind: 'MissingData',
|
202
|
+
reason: 'Missing data for ' + field.alias + ' on root ' + root,
|
203
|
+
nestedReason: data,
|
204
|
+
};
|
205
|
+
}
|
206
|
+
else {
|
207
|
+
target[field.alias] = field.readerArtifact.resolver(data.data);
|
208
|
+
}
|
209
|
+
break;
|
205
210
|
}
|
206
|
-
|
207
|
-
target[field.alias] = field.readerArtifact.
|
211
|
+
case 'ComponentReaderArtifact': {
|
212
|
+
target[field.alias] = (0, componentCache_1.getOrCreateCachedComponent)(environment, field.readerArtifact.componentName, {
|
213
|
+
kind: 'FragmentReference',
|
214
|
+
readerWithRefetchQueries: (0, PromiseWrapper_1.wrapResolvedValue)({
|
215
|
+
kind: 'ReaderWithRefetchQueries',
|
216
|
+
readerArtifact: field.readerArtifact,
|
217
|
+
nestedRefetchQueries: resolverRefetchQueries,
|
218
|
+
}),
|
219
|
+
root,
|
220
|
+
variables: generateChildVariableMap(variables, field.arguments),
|
221
|
+
networkRequest,
|
222
|
+
}, networkRequestOptions);
|
223
|
+
break;
|
224
|
+
}
|
225
|
+
default: {
|
226
|
+
let _ = field.readerArtifact;
|
227
|
+
_;
|
228
|
+
throw new Error('Unexpected kind');
|
208
229
|
}
|
209
|
-
}
|
210
|
-
else if (kind === 'ComponentReaderArtifact') {
|
211
|
-
target[field.alias] = (0, componentCache_1.getOrCreateCachedComponent)(environment, field.readerArtifact.componentName, {
|
212
|
-
kind: 'FragmentReference',
|
213
|
-
readerWithRefetchQueries: (0, PromiseWrapper_1.wrapResolvedValue)({
|
214
|
-
kind: 'ReaderWithRefetchQueries',
|
215
|
-
readerArtifact: field.readerArtifact,
|
216
|
-
nestedRefetchQueries: resolverRefetchQueries,
|
217
|
-
}),
|
218
|
-
root,
|
219
|
-
variables: generateChildVariableMap(variables, field.arguments),
|
220
|
-
networkRequest,
|
221
|
-
}, networkRequestOptions);
|
222
230
|
}
|
223
231
|
break;
|
224
232
|
}
|
@@ -251,21 +259,65 @@ function readData(environment, ast, root, variables, nestedRefetchQueries, netwo
|
|
251
259
|
stableStringifyArgs(localVariables),
|
252
260
|
// Fetcher
|
253
261
|
() => {
|
254
|
-
const
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
.
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
262
|
+
const fragmentReferenceAndDisposeFromEntrypoint = (entrypoint) => {
|
263
|
+
const [networkRequest, disposeNetworkRequest] = (0, makeNetworkRequest_1.makeNetworkRequest)(environment, entrypoint, localVariables);
|
264
|
+
const fragmentReference = {
|
265
|
+
kind: 'FragmentReference',
|
266
|
+
readerWithRefetchQueries: (0, PromiseWrapper_1.wrapResolvedValue)({
|
267
|
+
kind: 'ReaderWithRefetchQueries',
|
268
|
+
readerArtifact: entrypoint.readerWithRefetchQueries.readerArtifact,
|
269
|
+
nestedRefetchQueries: entrypoint.readerWithRefetchQueries
|
270
|
+
.nestedRefetchQueries,
|
271
|
+
}),
|
272
|
+
// TODO localVariables is not guaranteed to have an id field
|
273
|
+
root: localVariables.id,
|
274
|
+
variables: localVariables,
|
275
|
+
networkRequest,
|
276
|
+
};
|
277
|
+
return [fragmentReference, disposeNetworkRequest];
|
267
278
|
};
|
268
|
-
|
279
|
+
if (field.entrypoint.kind === 'Entrypoint') {
|
280
|
+
return fragmentReferenceAndDisposeFromEntrypoint(field.entrypoint);
|
281
|
+
}
|
282
|
+
else {
|
283
|
+
const isographArtifactPromiseWrapper = (0, IsographEnvironment_1.getOrLoadIsographArtifact)(environment, field.entrypoint.typeAndField, field.entrypoint.loader);
|
284
|
+
const state = (0, PromiseWrapper_1.getPromiseState)(isographArtifactPromiseWrapper);
|
285
|
+
if (state.kind === 'Ok') {
|
286
|
+
return fragmentReferenceAndDisposeFromEntrypoint(state.value);
|
287
|
+
}
|
288
|
+
else {
|
289
|
+
// Promise is pending or thrown
|
290
|
+
let entrypointLoaderState = { kind: 'EntrypointNotLoaded' };
|
291
|
+
const networkRequest = (0, PromiseWrapper_1.wrapPromise)(isographArtifactPromiseWrapper.promise.then((entrypoint) => {
|
292
|
+
if (entrypointLoaderState.kind === 'EntrypointNotLoaded') {
|
293
|
+
const [networkRequest, disposeNetworkRequest] = (0, makeNetworkRequest_1.makeNetworkRequest)(environment, entrypoint, localVariables);
|
294
|
+
entrypointLoaderState = {
|
295
|
+
kind: 'NetworkRequestStarted',
|
296
|
+
disposeNetworkRequest,
|
297
|
+
};
|
298
|
+
return networkRequest.promise;
|
299
|
+
}
|
300
|
+
}));
|
301
|
+
const readerWithRefetchPromise = isographArtifactPromiseWrapper.promise.then((entrypoint) => entrypoint.readerWithRefetchQueries);
|
302
|
+
const fragmentReference = {
|
303
|
+
kind: 'FragmentReference',
|
304
|
+
readerWithRefetchQueries: (0, PromiseWrapper_1.wrapPromise)(readerWithRefetchPromise),
|
305
|
+
// TODO localVariables is not guaranteed to have an id field
|
306
|
+
root: localVariables.id,
|
307
|
+
variables: localVariables,
|
308
|
+
networkRequest,
|
309
|
+
};
|
310
|
+
return [
|
311
|
+
fragmentReference,
|
312
|
+
() => {
|
313
|
+
if (entrypointLoaderState.kind === 'NetworkRequestStarted') {
|
314
|
+
entrypointLoaderState.disposeNetworkRequest();
|
315
|
+
}
|
316
|
+
entrypointLoaderState = { kind: 'Disposed' };
|
317
|
+
},
|
318
|
+
];
|
319
|
+
}
|
320
|
+
}
|
269
321
|
},
|
270
322
|
];
|
271
323
|
};
|
package/dist/core/reader.d.ts
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
import { Factory } from '@isograph/disposable-types';
|
3
3
|
import { FragmentReference } from './FragmentReference';
|
4
4
|
import { ComponentOrFieldName, DataId, IsographEnvironment } from './IsographEnvironment';
|
5
|
-
import { IsographEntrypoint, RefetchQueryNormalizationArtifact, RefetchQueryNormalizationArtifactWrapper } from './entrypoint';
|
5
|
+
import { IsographEntrypoint, IsographEntrypointLoader, RefetchQueryNormalizationArtifact, RefetchQueryNormalizationArtifactWrapper } from './entrypoint';
|
6
6
|
import { Arguments } from './util';
|
7
7
|
export type TopLevelReaderArtifact<TReadFromStore extends Object, TClientFieldValue, TComponentProps extends Record<string, never>> = EagerReaderArtifact<TReadFromStore, TClientFieldValue> | ComponentReaderArtifact<TReadFromStore, TComponentProps>;
|
8
8
|
export type EagerReaderArtifact<TReadFromStore extends Object, TClientFieldValue> = {
|
@@ -56,7 +56,7 @@ export type ReaderLoadableField = {
|
|
56
56
|
readonly name: string;
|
57
57
|
readonly queryArguments: Arguments | null;
|
58
58
|
readonly refetchReaderAst: ReaderAst<any>;
|
59
|
-
readonly entrypoint: IsographEntrypoint<any, any>;
|
59
|
+
readonly entrypoint: IsographEntrypoint<any, any> | IsographEntrypointLoader<any, any>;
|
60
60
|
};
|
61
61
|
type StableId = string;
|
62
62
|
export type LoadableField<TArgs, TResult> = (args: TArgs) => [StableId, Factory<FragmentReference<any, TResult>>];
|
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-9b984d79",
|
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-
|
21
|
-
"@isograph/react-disposable-state": "0.0.0-main-
|
22
|
-
"@isograph/reference-counted-pointer": "0.0.0-main-
|
20
|
+
"@isograph/disposable-types": "0.0.0-main-9b984d79",
|
21
|
+
"@isograph/react-disposable-state": "0.0.0-main-9b984d79",
|
22
|
+
"@isograph/reference-counted-pointer": "0.0.0-main-9b984d79"
|
23
23
|
},
|
24
24
|
"peerDependencies": {
|
25
25
|
"react": "18.2.0"
|
@@ -2,6 +2,8 @@ import { ParentCache } from '@isograph/react-disposable-state';
|
|
2
2
|
import { RetainedQuery } from './garbageCollection';
|
3
3
|
import { WithEncounteredRecords } from './read';
|
4
4
|
import { FragmentReference, Variables } from './FragmentReference';
|
5
|
+
import { PromiseWrapper, wrapPromise } from './PromiseWrapper';
|
6
|
+
import { IsographEntrypoint } from './entrypoint';
|
5
7
|
|
6
8
|
export type ComponentOrFieldName = string;
|
7
9
|
export type StringifiedArgs = string;
|
@@ -27,6 +29,7 @@ type AnyRecordSubscription = {
|
|
27
29
|
|
28
30
|
type Subscription = FragmentSubscription<Object> | AnyRecordSubscription;
|
29
31
|
type Subscriptions = Set<Subscription>;
|
32
|
+
// Should this be a map?
|
30
33
|
type CacheMap<T> = { [index: string]: ParentCache<T> };
|
31
34
|
|
32
35
|
export type IsographEnvironment = {
|
@@ -38,6 +41,11 @@ export type IsographEnvironment = {
|
|
38
41
|
// N.B. this must be <any, any>, but all *usages* of this should go through
|
39
42
|
// a function that adds type parameters.
|
40
43
|
readonly fragmentCache: CacheMap<FragmentReference<any, any>>;
|
44
|
+
// TODO make this a CacheMap and add GC
|
45
|
+
readonly entrypointArtifactCache: Map<
|
46
|
+
string,
|
47
|
+
PromiseWrapper<IsographEntrypoint<any, any>>
|
48
|
+
>;
|
41
49
|
readonly retainedQueries: Set<RetainedQuery>;
|
42
50
|
readonly gcBuffer: Array<RetainedQuery>;
|
43
51
|
readonly gcBufferSize: number;
|
@@ -103,6 +111,7 @@ export function createIsographEnvironment(
|
|
103
111
|
componentCache: {},
|
104
112
|
subscriptions: new Set(),
|
105
113
|
fragmentCache: {},
|
114
|
+
entrypointArtifactCache: new Map(),
|
106
115
|
retainedQueries: new Set(),
|
107
116
|
gcBuffer: [],
|
108
117
|
gcBufferSize: DEFAULT_GC_BUFFER_SIZE,
|
@@ -158,3 +167,17 @@ export function getLink(maybeLink: DataTypeValue): Link | null {
|
|
158
167
|
}
|
159
168
|
return null;
|
160
169
|
}
|
170
|
+
|
171
|
+
export function getOrLoadIsographArtifact(
|
172
|
+
environment: IsographEnvironment,
|
173
|
+
key: string,
|
174
|
+
loader: () => Promise<IsographEntrypoint<any, any>>,
|
175
|
+
): PromiseWrapper<IsographEntrypoint<any, any>> {
|
176
|
+
const value = environment.entrypointArtifactCache.get(key);
|
177
|
+
if (value != null) {
|
178
|
+
return value;
|
179
|
+
}
|
180
|
+
const wrapped = wrapPromise(loader());
|
181
|
+
environment.entrypointArtifactCache.set(key, wrapped);
|
182
|
+
return wrapped;
|
183
|
+
}
|
package/src/core/entrypoint.ts
CHANGED
@@ -29,6 +29,17 @@ export type IsographEntrypoint<
|
|
29
29
|
>;
|
30
30
|
};
|
31
31
|
|
32
|
+
export type IsographEntrypointLoader<
|
33
|
+
TReadFromStore extends Object,
|
34
|
+
TClientFieldValue,
|
35
|
+
> = {
|
36
|
+
readonly kind: 'EntrypointLoader';
|
37
|
+
readonly typeAndField: string;
|
38
|
+
readonly loader: () => Promise<
|
39
|
+
IsographEntrypoint<TReadFromStore, TClientFieldValue>
|
40
|
+
>;
|
41
|
+
};
|
42
|
+
|
32
43
|
export type NormalizationAstNode =
|
33
44
|
| NormalizationScalarField
|
34
45
|
| NormalizationLinkedField
|
package/src/core/read.ts
CHANGED
@@ -1,17 +1,24 @@
|
|
1
|
+
import { CleanupFn } from '@isograph/isograph-disposable-types/dist';
|
1
2
|
import { getParentRecordKey, onNextChange } from './cache';
|
2
3
|
import { getOrCreateCachedComponent } from './componentCache';
|
3
|
-
import {
|
4
|
+
import {
|
5
|
+
IsographEntrypoint,
|
6
|
+
RefetchQueryNormalizationArtifactWrapper,
|
7
|
+
} from './entrypoint';
|
4
8
|
import { FragmentReference, Variables } from './FragmentReference';
|
5
9
|
import {
|
6
10
|
assertLink,
|
7
11
|
DataId,
|
8
12
|
defaultMissingFieldHandler,
|
13
|
+
getOrLoadIsographArtifact,
|
9
14
|
IsographEnvironment,
|
10
15
|
} from './IsographEnvironment';
|
11
16
|
import { makeNetworkRequest } from './makeNetworkRequest';
|
12
17
|
import {
|
18
|
+
getPromiseState,
|
13
19
|
PromiseWrapper,
|
14
20
|
readPromise,
|
21
|
+
wrapPromise,
|
15
22
|
wrapResolvedValue,
|
16
23
|
} from './PromiseWrapper';
|
17
24
|
import { ReaderAst } from './reader';
|
@@ -291,44 +298,53 @@ function readData<TReadFromStore>(
|
|
291
298
|
(index) => nestedRefetchQueries[index],
|
292
299
|
);
|
293
300
|
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
root,
|
300
|
-
variables,
|
301
|
-
resolverRefetchQueries,
|
302
|
-
networkRequest,
|
303
|
-
networkRequestOptions,
|
304
|
-
mutableEncounteredRecords,
|
305
|
-
);
|
306
|
-
if (data.kind === 'MissingData') {
|
307
|
-
return {
|
308
|
-
kind: 'MissingData',
|
309
|
-
reason: 'Missing data for ' + field.alias + ' on root ' + root,
|
310
|
-
nestedReason: data,
|
311
|
-
};
|
312
|
-
} else {
|
313
|
-
target[field.alias] = field.readerArtifact.resolver(data.data);
|
314
|
-
}
|
315
|
-
} else if (kind === 'ComponentReaderArtifact') {
|
316
|
-
target[field.alias] = getOrCreateCachedComponent(
|
317
|
-
environment,
|
318
|
-
field.readerArtifact.componentName,
|
319
|
-
{
|
320
|
-
kind: 'FragmentReference',
|
321
|
-
readerWithRefetchQueries: wrapResolvedValue({
|
322
|
-
kind: 'ReaderWithRefetchQueries',
|
323
|
-
readerArtifact: field.readerArtifact,
|
324
|
-
nestedRefetchQueries: resolverRefetchQueries,
|
325
|
-
}),
|
301
|
+
switch (field.readerArtifact.kind) {
|
302
|
+
case 'EagerReaderArtifact': {
|
303
|
+
const data = readData(
|
304
|
+
environment,
|
305
|
+
field.readerArtifact.readerAst,
|
326
306
|
root,
|
327
|
-
variables
|
307
|
+
variables,
|
308
|
+
resolverRefetchQueries,
|
328
309
|
networkRequest,
|
329
|
-
|
330
|
-
|
331
|
-
|
310
|
+
networkRequestOptions,
|
311
|
+
mutableEncounteredRecords,
|
312
|
+
);
|
313
|
+
if (data.kind === 'MissingData') {
|
314
|
+
return {
|
315
|
+
kind: 'MissingData',
|
316
|
+
reason: 'Missing data for ' + field.alias + ' on root ' + root,
|
317
|
+
nestedReason: data,
|
318
|
+
};
|
319
|
+
} else {
|
320
|
+
target[field.alias] = field.readerArtifact.resolver(data.data);
|
321
|
+
}
|
322
|
+
break;
|
323
|
+
}
|
324
|
+
case 'ComponentReaderArtifact': {
|
325
|
+
target[field.alias] = getOrCreateCachedComponent(
|
326
|
+
environment,
|
327
|
+
field.readerArtifact.componentName,
|
328
|
+
{
|
329
|
+
kind: 'FragmentReference',
|
330
|
+
readerWithRefetchQueries: wrapResolvedValue({
|
331
|
+
kind: 'ReaderWithRefetchQueries',
|
332
|
+
readerArtifact: field.readerArtifact,
|
333
|
+
nestedRefetchQueries: resolverRefetchQueries,
|
334
|
+
}),
|
335
|
+
root,
|
336
|
+
variables: generateChildVariableMap(variables, field.arguments),
|
337
|
+
networkRequest,
|
338
|
+
} as const,
|
339
|
+
networkRequestOptions,
|
340
|
+
);
|
341
|
+
break;
|
342
|
+
}
|
343
|
+
default: {
|
344
|
+
let _: never = field.readerArtifact;
|
345
|
+
_;
|
346
|
+
throw new Error('Unexpected kind');
|
347
|
+
}
|
332
348
|
}
|
333
349
|
break;
|
334
350
|
}
|
@@ -376,30 +392,111 @@ function readData<TReadFromStore>(
|
|
376
392
|
stableStringifyArgs(localVariables),
|
377
393
|
// Fetcher
|
378
394
|
() => {
|
379
|
-
const
|
380
|
-
|
381
|
-
|
395
|
+
const fragmentReferenceAndDisposeFromEntrypoint = (
|
396
|
+
entrypoint: IsographEntrypoint<any, any>,
|
397
|
+
): [FragmentReference<any, any>, CleanupFn] => {
|
398
|
+
const [networkRequest, disposeNetworkRequest] =
|
399
|
+
makeNetworkRequest(environment, entrypoint, localVariables);
|
400
|
+
|
401
|
+
const fragmentReference: FragmentReference<any, any> = {
|
402
|
+
kind: 'FragmentReference',
|
403
|
+
readerWithRefetchQueries: wrapResolvedValue({
|
404
|
+
kind: 'ReaderWithRefetchQueries',
|
405
|
+
readerArtifact:
|
406
|
+
entrypoint.readerWithRefetchQueries.readerArtifact,
|
407
|
+
nestedRefetchQueries:
|
408
|
+
entrypoint.readerWithRefetchQueries
|
409
|
+
.nestedRefetchQueries,
|
410
|
+
} as const),
|
411
|
+
|
412
|
+
// TODO localVariables is not guaranteed to have an id field
|
413
|
+
root: localVariables.id,
|
414
|
+
variables: localVariables,
|
415
|
+
networkRequest,
|
416
|
+
};
|
417
|
+
return [fragmentReference, disposeNetworkRequest];
|
418
|
+
};
|
419
|
+
|
420
|
+
if (field.entrypoint.kind === 'Entrypoint') {
|
421
|
+
return fragmentReferenceAndDisposeFromEntrypoint(
|
382
422
|
field.entrypoint,
|
383
|
-
localVariables,
|
384
423
|
);
|
424
|
+
} else {
|
425
|
+
const isographArtifactPromiseWrapper =
|
426
|
+
getOrLoadIsographArtifact(
|
427
|
+
environment,
|
428
|
+
field.entrypoint.typeAndField,
|
429
|
+
field.entrypoint.loader,
|
430
|
+
);
|
431
|
+
const state = getPromiseState(isographArtifactPromiseWrapper);
|
432
|
+
if (state.kind === 'Ok') {
|
433
|
+
return fragmentReferenceAndDisposeFromEntrypoint(
|
434
|
+
state.value,
|
435
|
+
);
|
436
|
+
} else {
|
437
|
+
// Promise is pending or thrown
|
385
438
|
|
386
|
-
|
387
|
-
|
388
|
-
|
389
|
-
|
390
|
-
|
391
|
-
|
392
|
-
|
393
|
-
|
394
|
-
|
395
|
-
} as const),
|
439
|
+
let entrypointLoaderState:
|
440
|
+
| {
|
441
|
+
kind: 'EntrypointNotLoaded';
|
442
|
+
}
|
443
|
+
| {
|
444
|
+
kind: 'NetworkRequestStarted';
|
445
|
+
disposeNetworkRequest: CleanupFn;
|
446
|
+
}
|
447
|
+
| { kind: 'Disposed' } = { kind: 'EntrypointNotLoaded' };
|
396
448
|
|
397
|
-
|
398
|
-
|
399
|
-
|
400
|
-
|
401
|
-
|
402
|
-
|
449
|
+
const networkRequest = wrapPromise(
|
450
|
+
isographArtifactPromiseWrapper.promise.then(
|
451
|
+
(entrypoint) => {
|
452
|
+
if (
|
453
|
+
entrypointLoaderState.kind === 'EntrypointNotLoaded'
|
454
|
+
) {
|
455
|
+
const [networkRequest, disposeNetworkRequest] =
|
456
|
+
makeNetworkRequest(
|
457
|
+
environment,
|
458
|
+
entrypoint,
|
459
|
+
localVariables,
|
460
|
+
);
|
461
|
+
entrypointLoaderState = {
|
462
|
+
kind: 'NetworkRequestStarted',
|
463
|
+
disposeNetworkRequest,
|
464
|
+
};
|
465
|
+
return networkRequest.promise;
|
466
|
+
}
|
467
|
+
},
|
468
|
+
),
|
469
|
+
);
|
470
|
+
const readerWithRefetchPromise =
|
471
|
+
isographArtifactPromiseWrapper.promise.then(
|
472
|
+
(entrypoint) => entrypoint.readerWithRefetchQueries,
|
473
|
+
);
|
474
|
+
|
475
|
+
const fragmentReference: FragmentReference<any, any> = {
|
476
|
+
kind: 'FragmentReference',
|
477
|
+
readerWithRefetchQueries: wrapPromise(
|
478
|
+
readerWithRefetchPromise,
|
479
|
+
),
|
480
|
+
|
481
|
+
// TODO localVariables is not guaranteed to have an id field
|
482
|
+
root: localVariables.id,
|
483
|
+
variables: localVariables,
|
484
|
+
networkRequest,
|
485
|
+
};
|
486
|
+
|
487
|
+
return [
|
488
|
+
fragmentReference,
|
489
|
+
() => {
|
490
|
+
if (
|
491
|
+
entrypointLoaderState.kind === 'NetworkRequestStarted'
|
492
|
+
) {
|
493
|
+
entrypointLoaderState.disposeNetworkRequest();
|
494
|
+
}
|
495
|
+
entrypointLoaderState = { kind: 'Disposed' };
|
496
|
+
},
|
497
|
+
];
|
498
|
+
}
|
499
|
+
}
|
403
500
|
},
|
404
501
|
];
|
405
502
|
};
|
package/src/core/reader.ts
CHANGED
@@ -7,6 +7,7 @@ import {
|
|
7
7
|
} from './IsographEnvironment';
|
8
8
|
import {
|
9
9
|
IsographEntrypoint,
|
10
|
+
IsographEntrypointLoader,
|
10
11
|
RefetchQueryNormalizationArtifact,
|
11
12
|
RefetchQueryNormalizationArtifactWrapper,
|
12
13
|
} from './entrypoint';
|
@@ -111,7 +112,10 @@ export type ReaderLoadableField = {
|
|
111
112
|
readonly queryArguments: Arguments | null;
|
112
113
|
readonly refetchReaderAst: ReaderAst<any>;
|
113
114
|
|
114
|
-
|
115
|
+
// TODO we should not type these as any
|
116
|
+
readonly entrypoint:
|
117
|
+
| IsographEntrypoint<any, any>
|
118
|
+
| IsographEntrypointLoader<any, any>;
|
115
119
|
};
|
116
120
|
|
117
121
|
type StableId = string;
|