@isograph/react 0.3.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 +16 -7
- package/dist/core/FragmentReference.d.ts.map +1 -1
- package/dist/core/FragmentReference.js +3 -12
- package/dist/core/IsographEnvironment.d.ts +17 -27
- package/dist/core/IsographEnvironment.d.ts.map +1 -1
- package/dist/core/IsographEnvironment.js +4 -0
- package/dist/core/PromiseWrapper.d.ts +3 -4
- package/dist/core/PromiseWrapper.d.ts.map +1 -1
- package/dist/core/PromiseWrapper.js +5 -4
- package/dist/core/areEqualWithDeepComparison.d.ts.map +1 -1
- package/dist/core/areEqualWithDeepComparison.js +16 -0
- package/dist/core/cache.d.ts +11 -20
- package/dist/core/cache.d.ts.map +1 -1
- package/dist/core/cache.js +60 -45
- package/dist/core/check.d.ts +9 -5
- package/dist/core/check.d.ts.map +1 -1
- package/dist/core/check.js +2 -2
- package/dist/core/componentCache.d.ts +1 -1
- package/dist/core/componentCache.d.ts.map +1 -1
- package/dist/core/componentCache.js +27 -31
- package/dist/core/entrypoint.d.ts +23 -26
- package/dist/core/entrypoint.d.ts.map +1 -1
- package/dist/core/garbageCollection.d.ts +3 -4
- package/dist/core/garbageCollection.d.ts.map +1 -1
- package/dist/core/garbageCollection.js +1 -1
- package/dist/core/logging.d.ts +12 -13
- package/dist/core/logging.d.ts.map +1 -1
- package/dist/core/logging.js +8 -5
- package/dist/core/makeNetworkRequest.d.ts +5 -5
- package/dist/core/makeNetworkRequest.d.ts.map +1 -1
- package/dist/core/makeNetworkRequest.js +107 -22
- package/dist/core/read.d.ts +15 -10
- package/dist/core/read.d.ts.map +1 -1
- package/dist/core/read.js +398 -304
- package/dist/core/reader.d.ts +24 -32
- package/dist/core/reader.d.ts.map +1 -1
- 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 +3 -0
- package/dist/core/util.d.ts.map +1 -1
- package/dist/index.d.ts +16 -16
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -1
- package/dist/loadable-hooks/useClientSideDefer.d.ts +4 -10
- package/dist/loadable-hooks/useClientSideDefer.d.ts.map +1 -1
- package/dist/loadable-hooks/useClientSideDefer.js +2 -2
- package/dist/loadable-hooks/useConnectionSpecPagination.d.ts +8 -15
- package/dist/loadable-hooks/useConnectionSpecPagination.d.ts.map +1 -1
- package/dist/loadable-hooks/useConnectionSpecPagination.js +6 -4
- package/dist/loadable-hooks/useImperativeExposedMutationField.d.ts +1 -2
- package/dist/loadable-hooks/useImperativeExposedMutationField.d.ts.map +1 -1
- package/dist/loadable-hooks/useImperativeLoadableField.d.ts +4 -6
- package/dist/loadable-hooks/useImperativeLoadableField.d.ts.map +1 -1
- package/dist/loadable-hooks/useImperativeLoadableField.js +1 -1
- package/dist/loadable-hooks/useSkipLimitPagination.d.ts +6 -13
- package/dist/loadable-hooks/useSkipLimitPagination.d.ts.map +1 -1
- package/dist/loadable-hooks/useSkipLimitPagination.js +11 -9
- package/dist/react/FragmentReader.d.ts +2 -3
- package/dist/react/FragmentReader.d.ts.map +1 -1
- package/dist/react/IsographEnvironmentProvider.d.ts.map +1 -1
- package/dist/react/useImperativeReference.d.ts +7 -10
- package/dist/react/useImperativeReference.d.ts.map +1 -1
- package/dist/react/useImperativeReference.js +2 -3
- package/dist/react/useLazyReference.d.ts +4 -7
- package/dist/react/useLazyReference.d.ts.map +1 -1
- package/dist/react/useLazyReference.js +26 -5
- package/dist/react/useReadAndSubscribe.d.ts +3 -9
- package/dist/react/useReadAndSubscribe.d.ts.map +1 -1
- package/dist/react/useReadAndSubscribe.js +7 -3
- package/dist/react/useRerenderOnChange.d.ts +1 -1
- package/dist/react/useRerenderOnChange.d.ts.map +1 -1
- package/dist/react/useResult.d.ts +3 -6
- package/dist/react/useResult.d.ts.map +1 -1
- package/dist/react/useResult.js +10 -8
- package/isograph.config.json +1 -0
- package/package.json +7 -6
- package/src/core/FragmentReference.ts +30 -15
- package/src/core/IsographEnvironment.ts +39 -31
- package/src/core/PromiseWrapper.ts +3 -3
- package/src/core/areEqualWithDeepComparison.ts +20 -0
- package/src/core/cache.ts +105 -72
- package/src/core/check.ts +13 -8
- package/src/core/componentCache.ts +45 -52
- package/src/core/entrypoint.ts +34 -16
- package/src/core/garbageCollection.ts +6 -6
- package/src/core/logging.ts +24 -22
- package/src/core/makeNetworkRequest.ts +183 -30
- package/src/core/read.ts +618 -435
- package/src/core/reader.ts +37 -24
- package/src/core/startUpdate.ts +28 -0
- package/src/core/util.ts +4 -0
- package/src/index.ts +82 -9
- package/src/loadable-hooks/useClientSideDefer.ts +11 -10
- package/src/loadable-hooks/useConnectionSpecPagination.ts +26 -13
- package/src/loadable-hooks/useImperativeExposedMutationField.ts +1 -1
- package/src/loadable-hooks/useImperativeLoadableField.ts +10 -12
- package/src/loadable-hooks/useSkipLimitPagination.ts +37 -19
- package/src/react/FragmentReader.tsx +3 -3
- package/src/react/IsographEnvironmentProvider.tsx +1 -1
- package/src/react/useImperativeReference.ts +40 -19
- package/src/react/useLazyReference.ts +62 -14
- package/src/react/useReadAndSubscribe.ts +17 -9
- package/src/react/useRerenderOnChange.ts +2 -2
- package/src/react/useResult.ts +21 -8
- package/src/tests/__isograph/Query/meName/entrypoint.ts +4 -28
- package/src/tests/__isograph/Query/meName/normalization_ast.ts +25 -0
- package/src/tests/__isograph/Query/meName/query_text.ts +6 -0
- package/src/tests/__isograph/Query/meName/resolver_reader.ts +4 -0
- package/src/tests/__isograph/Query/meNameSuccessor/entrypoint.ts +4 -66
- package/src/tests/__isograph/Query/meNameSuccessor/normalization_ast.ts +56 -0
- package/src/tests/__isograph/Query/meNameSuccessor/query_text.ts +13 -0
- package/src/tests/__isograph/Query/meNameSuccessor/resolver_reader.ts +7 -0
- package/src/tests/__isograph/Query/nodeField/entrypoint.ts +4 -33
- package/src/tests/__isograph/Query/nodeField/normalization_ast.ts +30 -0
- package/src/tests/__isograph/Query/nodeField/query_text.ts +6 -0
- package/src/tests/__isograph/Query/nodeField/resolver_reader.ts +4 -0
- package/src/tests/__isograph/Query/subquery/entrypoint.ts +4 -43
- package/src/tests/__isograph/Query/subquery/normalization_ast.ts +38 -0
- package/src/tests/__isograph/Query/subquery/query_text.ts +8 -0
- package/src/tests/__isograph/Query/subquery/resolver_reader.ts +5 -0
- package/src/tests/__isograph/iso.ts +3 -2
- package/src/tests/garbageCollection.test.ts +10 -8
- package/src/tests/meNameSuccessor.ts +1 -1
- package/src/tests/nodeQuery.ts +2 -1
- package/src/tests/normalizeData.test.ts +1 -1
- package/tsconfig.pkg.json +1 -2
package/src/core/cache.ts
CHANGED
@@ -3,56 +3,53 @@ import {
|
|
3
3
|
ItemCleanupPair,
|
4
4
|
ParentCache,
|
5
5
|
} from '@isograph/react-disposable-state';
|
6
|
-
import {
|
7
|
-
DataId,
|
8
|
-
Link,
|
9
|
-
ROOT_ID,
|
10
|
-
StoreRecord,
|
11
|
-
type IsographEnvironment,
|
12
|
-
DataTypeValue,
|
13
|
-
getLink,
|
14
|
-
FragmentSubscription,
|
15
|
-
type TypeName,
|
16
|
-
} from './IsographEnvironment';
|
17
6
|
import {
|
18
7
|
IsographEntrypoint,
|
19
|
-
NormalizationAst,
|
20
8
|
NormalizationInlineFragment,
|
21
9
|
NormalizationLinkedField,
|
22
10
|
NormalizationScalarField,
|
23
11
|
RefetchQueryNormalizationArtifactWrapper,
|
12
|
+
type NormalizationAst,
|
13
|
+
type NormalizationAstLoader,
|
14
|
+
type NormalizationAstNodes,
|
24
15
|
} from '../core/entrypoint';
|
25
|
-
import {
|
26
|
-
import {
|
27
|
-
import { WithEncounteredRecords, readButDoNotEvaluate } from './read';
|
16
|
+
import { mergeObjectsUsingReaderAst } from './areEqualWithDeepComparison';
|
17
|
+
import { FetchOptions } from './check';
|
28
18
|
import {
|
19
|
+
ExtractParameters,
|
29
20
|
FragmentReference,
|
30
21
|
Variables,
|
31
|
-
|
22
|
+
type UnknownTReadFromStore,
|
23
|
+
type VariableValue,
|
32
24
|
} from './FragmentReference';
|
33
|
-
import {
|
25
|
+
import {
|
26
|
+
DataId,
|
27
|
+
DataTypeValue,
|
28
|
+
FragmentSubscription,
|
29
|
+
getLink,
|
30
|
+
Link,
|
31
|
+
ROOT_ID,
|
32
|
+
StoreRecord,
|
33
|
+
type IsographEnvironment,
|
34
|
+
type TypeName,
|
35
|
+
} from './IsographEnvironment';
|
36
|
+
import { logMessage } from './logging';
|
34
37
|
import { maybeMakeNetworkRequest } from './makeNetworkRequest';
|
35
38
|
import { wrapResolvedValue } from './PromiseWrapper';
|
36
|
-
import {
|
37
|
-
import {
|
39
|
+
import { readButDoNotEvaluate, WithEncounteredRecords } from './read';
|
40
|
+
import { ReaderLinkedField, ReaderScalarField, type ReaderAst } from './reader';
|
41
|
+
import { Argument, ArgumentValue } from './util';
|
38
42
|
|
39
43
|
export const TYPENAME_FIELD_NAME = '__typename';
|
40
44
|
|
41
45
|
export function getOrCreateItemInSuspenseCache<
|
42
|
-
TReadFromStore extends
|
46
|
+
TReadFromStore extends UnknownTReadFromStore,
|
43
47
|
TClientFieldValue,
|
44
48
|
>(
|
45
49
|
environment: IsographEnvironment,
|
46
50
|
index: string,
|
47
51
|
factory: Factory<FragmentReference<TReadFromStore, TClientFieldValue>>,
|
48
52
|
): ParentCache<FragmentReference<TReadFromStore, TClientFieldValue>> {
|
49
|
-
// TODO this is probably a useless message, we should remove it
|
50
|
-
logMessage(environment, {
|
51
|
-
kind: 'GettingSuspenseCacheItem',
|
52
|
-
index,
|
53
|
-
availableCacheItems: Object.keys(environment.fragmentCache),
|
54
|
-
found: !!environment.fragmentCache[index],
|
55
|
-
});
|
56
53
|
if (environment.fragmentCache[index] == null) {
|
57
54
|
environment.fragmentCache[index] = new ParentCache(factory);
|
58
55
|
}
|
@@ -83,13 +80,18 @@ export function stableCopy<T>(value: T): T {
|
|
83
80
|
}
|
84
81
|
|
85
82
|
export function getOrCreateCacheForArtifact<
|
86
|
-
TReadFromStore extends
|
83
|
+
TReadFromStore extends UnknownTReadFromStore,
|
87
84
|
TClientFieldValue,
|
85
|
+
TNormalizationAst extends NormalizationAst | NormalizationAstLoader,
|
88
86
|
>(
|
89
87
|
environment: IsographEnvironment,
|
90
|
-
entrypoint: IsographEntrypoint<
|
88
|
+
entrypoint: IsographEntrypoint<
|
89
|
+
TReadFromStore,
|
90
|
+
TClientFieldValue,
|
91
|
+
TNormalizationAst
|
92
|
+
>,
|
91
93
|
variables: ExtractParameters<TReadFromStore>,
|
92
|
-
fetchOptions?: FetchOptions
|
94
|
+
fetchOptions?: FetchOptions<TClientFieldValue>,
|
93
95
|
): ParentCache<FragmentReference<TReadFromStore, TClientFieldValue>> {
|
94
96
|
const cacheKey =
|
95
97
|
entrypoint.networkRequestInfo.queryText +
|
@@ -124,8 +126,8 @@ export function getOrCreateCacheForArtifact<
|
|
124
126
|
return getOrCreateItemInSuspenseCache(environment, cacheKey, factory);
|
125
127
|
}
|
126
128
|
|
127
|
-
type NetworkResponseScalarValue = string | number | boolean;
|
128
|
-
type NetworkResponseValue =
|
129
|
+
export type NetworkResponseScalarValue = string | number | boolean;
|
130
|
+
export type NetworkResponseValue =
|
129
131
|
| NetworkResponseScalarValue
|
130
132
|
| null
|
131
133
|
| NetworkResponseObject
|
@@ -142,7 +144,7 @@ export type NetworkResponseObject = {
|
|
142
144
|
|
143
145
|
export function normalizeData(
|
144
146
|
environment: IsographEnvironment,
|
145
|
-
normalizationAst:
|
147
|
+
normalizationAst: NormalizationAstNodes,
|
146
148
|
networkResponse: NetworkResponseObject,
|
147
149
|
variables: Variables,
|
148
150
|
nestedRefetchQueries: RefetchQueryNormalizationArtifactWrapper[],
|
@@ -150,12 +152,12 @@ export function normalizeData(
|
|
150
152
|
): EncounteredIds {
|
151
153
|
const encounteredIds: EncounteredIds = new Map();
|
152
154
|
|
153
|
-
logMessage(environment, {
|
155
|
+
logMessage(environment, () => ({
|
154
156
|
kind: 'AboutToNormalize',
|
155
157
|
normalizationAst,
|
156
158
|
networkResponse,
|
157
159
|
variables,
|
158
|
-
});
|
160
|
+
}));
|
159
161
|
|
160
162
|
const recordsById = (environment.store[root.__typename] ??= {});
|
161
163
|
const newStoreRecord = (recordsById[root.__link] ??= {});
|
@@ -171,11 +173,11 @@ export function normalizeData(
|
|
171
173
|
encounteredIds,
|
172
174
|
);
|
173
175
|
|
174
|
-
logMessage(environment, {
|
176
|
+
logMessage(environment, () => ({
|
175
177
|
kind: 'AfterNormalization',
|
176
178
|
store: environment.store,
|
177
179
|
encounteredIds,
|
178
|
-
});
|
180
|
+
}));
|
179
181
|
|
180
182
|
callSubscriptions(environment, encounteredIds);
|
181
183
|
return encounteredIds;
|
@@ -208,9 +210,7 @@ export function subscribeToAnyChangesToRecord(
|
|
208
210
|
}
|
209
211
|
|
210
212
|
// TODO we should re-read and call callback if the value has changed
|
211
|
-
export function subscribe<
|
212
|
-
TReadFromStore extends { parameters: object; data: object },
|
213
|
-
>(
|
213
|
+
export function subscribe<TReadFromStore extends UnknownTReadFromStore>(
|
214
214
|
environment: IsographEnvironment,
|
215
215
|
encounteredDataAndRecords: WithEncounteredRecords<TReadFromStore>,
|
216
216
|
fragmentReference: FragmentReference<TReadFromStore, any>,
|
@@ -303,14 +303,14 @@ function callSubscriptions(
|
|
303
303
|
newEncounteredDataAndRecords.item,
|
304
304
|
);
|
305
305
|
|
306
|
-
logMessage(environment, {
|
306
|
+
logMessage(environment, () => ({
|
307
307
|
kind: 'DeepEqualityCheck',
|
308
308
|
fragmentReference: subscription.fragmentReference,
|
309
309
|
old: subscription.encounteredDataAndRecords.item,
|
310
310
|
new: newEncounteredDataAndRecords.item,
|
311
311
|
deeplyEqual:
|
312
312
|
mergedItem === subscription.encounteredDataAndRecords.item,
|
313
|
-
});
|
313
|
+
}));
|
314
314
|
|
315
315
|
if (mergedItem !== subscription.encounteredDataAndRecords.item) {
|
316
316
|
subscription.callback(newEncounteredDataAndRecords);
|
@@ -376,7 +376,7 @@ export type EncounteredIds = Map<TypeName, Set<DataId>>;
|
|
376
376
|
*/
|
377
377
|
function normalizeDataIntoRecord(
|
378
378
|
environment: IsographEnvironment,
|
379
|
-
normalizationAst:
|
379
|
+
normalizationAst: NormalizationAstNodes,
|
380
380
|
networkResponseParentRecord: NetworkResponseObject,
|
381
381
|
targetParentRecord: StoreRecord,
|
382
382
|
targetParentRecordLink: Link,
|
@@ -724,8 +724,19 @@ export function getParentRecordKey(
|
|
724
724
|
function getStoreKeyChunkForArgumentValue(
|
725
725
|
argumentValue: ArgumentValue,
|
726
726
|
variables: Variables,
|
727
|
-
) {
|
727
|
+
): VariableValue {
|
728
728
|
switch (argumentValue.kind) {
|
729
|
+
case 'Object': {
|
730
|
+
return Object.fromEntries(
|
731
|
+
argumentValue.value.map(([argumentName, argumentValue]) => {
|
732
|
+
return [
|
733
|
+
argumentName,
|
734
|
+
// substitute variables
|
735
|
+
getStoreKeyChunkForArgumentValue(argumentValue, variables),
|
736
|
+
];
|
737
|
+
}),
|
738
|
+
);
|
739
|
+
}
|
729
740
|
case 'Literal': {
|
730
741
|
return argumentValue.value;
|
731
742
|
}
|
@@ -749,7 +760,12 @@ function getStoreKeyChunkForArgumentValue(
|
|
749
760
|
}
|
750
761
|
|
751
762
|
function getStoreKeyChunkForArgument(argument: Argument, variables: Variables) {
|
752
|
-
|
763
|
+
let chunk = getStoreKeyChunkForArgumentValue(argument[1], variables);
|
764
|
+
|
765
|
+
if (typeof chunk === 'object') {
|
766
|
+
chunk = JSON.stringify(stableCopy(chunk));
|
767
|
+
}
|
768
|
+
|
753
769
|
return `${FIRST_SPLIT_KEY}${argument[0]}${SECOND_SPLIT_KEY}${chunk}`;
|
754
770
|
}
|
755
771
|
|
@@ -758,43 +774,60 @@ function getNetworkResponseKey(
|
|
758
774
|
): string {
|
759
775
|
let networkResponseKey = astNode.fieldName;
|
760
776
|
const fieldParameters = astNode.arguments;
|
777
|
+
|
761
778
|
if (fieldParameters != null) {
|
762
|
-
for (const
|
763
|
-
|
764
|
-
let argumentValueChunk;
|
765
|
-
switch (argumentValue.kind) {
|
766
|
-
case 'Literal': {
|
767
|
-
argumentValueChunk = 'l_' + argumentValue.value;
|
768
|
-
break;
|
769
|
-
}
|
770
|
-
case 'Variable': {
|
771
|
-
argumentValueChunk = 'v_' + argumentValue.name;
|
772
|
-
break;
|
773
|
-
}
|
774
|
-
case 'String': {
|
775
|
-
argumentValueChunk = 's_' + argumentValue.value;
|
776
|
-
break;
|
777
|
-
}
|
778
|
-
case 'Enum': {
|
779
|
-
argumentValueChunk = 'e_' + argumentValue.value;
|
780
|
-
break;
|
781
|
-
}
|
782
|
-
default: {
|
783
|
-
// Ensure we have covered all variants
|
784
|
-
let _: never = argumentValue;
|
785
|
-
_;
|
786
|
-
throw new Error('Unexpected case');
|
787
|
-
}
|
788
|
-
}
|
779
|
+
for (const [argumentName, argumentValue] of fieldParameters) {
|
780
|
+
let argumentValueChunk = getArgumentValueChunk(argumentValue);
|
789
781
|
networkResponseKey += `${FIRST_SPLIT_KEY}${argumentName}${SECOND_SPLIT_KEY}${argumentValueChunk}`;
|
790
782
|
}
|
791
783
|
}
|
784
|
+
|
792
785
|
return networkResponseKey;
|
793
786
|
}
|
794
787
|
|
788
|
+
function getArgumentValueChunk(argumentValue: ArgumentValue): string {
|
789
|
+
switch (argumentValue.kind) {
|
790
|
+
case 'Object': {
|
791
|
+
return (
|
792
|
+
'o_' +
|
793
|
+
argumentValue.value
|
794
|
+
.map(([argumentName, argumentValue]) => {
|
795
|
+
return (
|
796
|
+
argumentName +
|
797
|
+
THIRD_SPLIT_KEY +
|
798
|
+
getArgumentValueChunk(argumentValue)
|
799
|
+
);
|
800
|
+
})
|
801
|
+
.join('_') +
|
802
|
+
'_c'
|
803
|
+
);
|
804
|
+
}
|
805
|
+
case 'Literal': {
|
806
|
+
return 'l_' + argumentValue.value;
|
807
|
+
}
|
808
|
+
case 'Variable': {
|
809
|
+
return 'v_' + argumentValue.name;
|
810
|
+
}
|
811
|
+
case 'String': {
|
812
|
+
// replace all non-word characters (alphanumeric & underscore) with underscores
|
813
|
+
return 's_' + argumentValue.value.replaceAll(/\W/g, '_');
|
814
|
+
}
|
815
|
+
case 'Enum': {
|
816
|
+
return 'e_' + argumentValue.value;
|
817
|
+
}
|
818
|
+
default: {
|
819
|
+
// Ensure we have covered all variants
|
820
|
+
let _: never = argumentValue;
|
821
|
+
_;
|
822
|
+
throw new Error('Unexpected case');
|
823
|
+
}
|
824
|
+
}
|
825
|
+
}
|
826
|
+
|
795
827
|
// an alias might be pullRequests____first___first____after___cursor
|
796
828
|
export const FIRST_SPLIT_KEY = '____';
|
797
829
|
export const SECOND_SPLIT_KEY = '___';
|
830
|
+
export const THIRD_SPLIT_KEY = '__';
|
798
831
|
|
799
832
|
// Returns a key to look up an item in the store
|
800
833
|
function getDataIdOfNetworkResponse(
|
package/src/core/check.ts
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
import { getParentRecordKey } from './cache';
|
2
|
-
import {
|
2
|
+
import { NormalizationAstNodes } from './entrypoint';
|
3
3
|
import { Variables } from './FragmentReference';
|
4
4
|
import {
|
5
5
|
getLink,
|
@@ -9,16 +9,21 @@ import {
|
|
9
9
|
} from './IsographEnvironment';
|
10
10
|
import { logMessage } from './logging';
|
11
11
|
|
12
|
-
export type ShouldFetch =
|
12
|
+
export type ShouldFetch = RequiredShouldFetch | 'IfNecessary';
|
13
|
+
export type RequiredShouldFetch = 'Yes' | 'No';
|
13
14
|
|
14
15
|
export const DEFAULT_SHOULD_FETCH_VALUE: ShouldFetch = 'IfNecessary';
|
15
16
|
|
16
|
-
export type FetchOptions = {
|
17
|
+
export type FetchOptions<TReadOutData> = {
|
17
18
|
shouldFetch?: ShouldFetch;
|
18
|
-
onComplete?: () => void;
|
19
|
+
onComplete?: (data: TReadOutData) => void;
|
19
20
|
onError?: () => void;
|
20
21
|
};
|
21
22
|
|
23
|
+
export type RequiredFetchOptions<TReadOutData> = {
|
24
|
+
shouldFetch: RequiredShouldFetch;
|
25
|
+
} & FetchOptions<TReadOutData>;
|
26
|
+
|
22
27
|
export type CheckResult =
|
23
28
|
| {
|
24
29
|
kind: 'EnoughData';
|
@@ -30,7 +35,7 @@ export type CheckResult =
|
|
30
35
|
|
31
36
|
export function check(
|
32
37
|
environment: IsographEnvironment,
|
33
|
-
normalizationAst:
|
38
|
+
normalizationAst: NormalizationAstNodes,
|
34
39
|
variables: Variables,
|
35
40
|
root: Link,
|
36
41
|
): CheckResult {
|
@@ -44,16 +49,16 @@ export function check(
|
|
44
49
|
newStoreRecord,
|
45
50
|
root,
|
46
51
|
);
|
47
|
-
logMessage(environment, {
|
52
|
+
logMessage(environment, () => ({
|
48
53
|
kind: 'EnvironmentCheck',
|
49
54
|
result: checkResult,
|
50
|
-
});
|
55
|
+
}));
|
51
56
|
return checkResult;
|
52
57
|
}
|
53
58
|
|
54
59
|
function checkFromRecord(
|
55
60
|
environment: IsographEnvironment,
|
56
|
-
normalizationAst:
|
61
|
+
normalizationAst: NormalizationAstNodes,
|
57
62
|
variables: Variables,
|
58
63
|
record: StoreRecord,
|
59
64
|
recordLink: Link,
|
@@ -1,10 +1,13 @@
|
|
1
|
-
import { stableCopy } from './cache';
|
2
|
-
import { IsographEnvironment } from './IsographEnvironment';
|
3
|
-
import { FragmentReference } from './FragmentReference';
|
4
1
|
import { useReadAndSubscribe } from '../react/useReadAndSubscribe';
|
5
|
-
import {
|
6
|
-
|
2
|
+
import {
|
3
|
+
FragmentReference,
|
4
|
+
stableIdForFragmentReference,
|
5
|
+
} from './FragmentReference';
|
6
|
+
import { IsographEnvironment } from './IsographEnvironment';
|
7
7
|
import { logMessage } from './logging';
|
8
|
+
import { readPromise } from './PromiseWrapper';
|
9
|
+
import { NetworkRequestReaderOptions } from './read';
|
10
|
+
import { createStartUpdate } from './startUpdate';
|
8
11
|
|
9
12
|
export function getOrCreateCachedComponent(
|
10
13
|
environment: IsographEnvironment,
|
@@ -12,51 +15,41 @@ export function getOrCreateCachedComponent(
|
|
12
15
|
fragmentReference: FragmentReference<any, any>,
|
13
16
|
networkRequestOptions: NetworkRequestReaderOptions,
|
14
17
|
): React.FC<any> {
|
15
|
-
//
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
data,
|
53
|
-
parameters: fragmentReference.variables,
|
54
|
-
},
|
55
|
-
additionalRuntimeProps,
|
56
|
-
);
|
57
|
-
}
|
58
|
-
Component.displayName = `${componentName} (id: ${fragmentReference.root}) @component`;
|
59
|
-
return Component;
|
60
|
-
})();
|
61
|
-
return byArgs[stringifiedArgs];
|
18
|
+
// We create startUpdate outside of component to make it stable
|
19
|
+
const startUpdate = createStartUpdate(environment, fragmentReference);
|
20
|
+
|
21
|
+
return (environment.componentCache[
|
22
|
+
stableIdForFragmentReference(fragmentReference, componentName)
|
23
|
+
] ??= (() => {
|
24
|
+
function Component(additionalRuntimeProps: { [key: string]: any }) {
|
25
|
+
const readerWithRefetchQueries = readPromise(
|
26
|
+
fragmentReference.readerWithRefetchQueries,
|
27
|
+
);
|
28
|
+
|
29
|
+
const data = useReadAndSubscribe(
|
30
|
+
fragmentReference,
|
31
|
+
networkRequestOptions,
|
32
|
+
readerWithRefetchQueries.readerArtifact.readerAst,
|
33
|
+
);
|
34
|
+
|
35
|
+
logMessage(environment, () => ({
|
36
|
+
kind: 'ComponentRerendered',
|
37
|
+
componentName,
|
38
|
+
rootLink: fragmentReference.root,
|
39
|
+
}));
|
40
|
+
|
41
|
+
return readerWithRefetchQueries.readerArtifact.resolver(
|
42
|
+
{
|
43
|
+
data,
|
44
|
+
parameters: fragmentReference.variables,
|
45
|
+
startUpdate: readerWithRefetchQueries.readerArtifact.hasUpdatable
|
46
|
+
? startUpdate
|
47
|
+
: undefined,
|
48
|
+
},
|
49
|
+
additionalRuntimeProps,
|
50
|
+
);
|
51
|
+
}
|
52
|
+
Component.displayName = `${componentName} (id: ${fragmentReference.root}) @component`;
|
53
|
+
return Component;
|
54
|
+
})());
|
62
55
|
}
|
package/src/core/entrypoint.ts
CHANGED
@@ -1,9 +1,10 @@
|
|
1
|
+
import type { UnknownTReadFromStore } from './FragmentReference';
|
1
2
|
import type { TypeName } from './IsographEnvironment';
|
2
3
|
import { TopLevelReaderArtifact } from './reader';
|
3
4
|
import { Arguments } from './util';
|
4
5
|
|
5
6
|
export type ReaderWithRefetchQueries<
|
6
|
-
TReadFromStore extends
|
7
|
+
TReadFromStore extends UnknownTReadFromStore,
|
7
8
|
TClientFieldValue,
|
8
9
|
> = {
|
9
10
|
readonly kind: 'ReaderWithRefetchQueries';
|
@@ -16,18 +17,19 @@ export type ReaderWithRefetchQueries<
|
|
16
17
|
readonly nestedRefetchQueries: RefetchQueryNormalizationArtifactWrapper[];
|
17
18
|
};
|
18
19
|
|
19
|
-
export type NetworkRequestInfo = {
|
20
|
+
export type NetworkRequestInfo<TNormalizationAst> = {
|
20
21
|
readonly kind: 'NetworkRequestInfo';
|
21
22
|
readonly queryText: string;
|
22
|
-
readonly normalizationAst:
|
23
|
+
readonly normalizationAst: TNormalizationAst;
|
23
24
|
};
|
24
25
|
// This type should be treated as an opaque type.
|
25
26
|
export type IsographEntrypoint<
|
26
|
-
TReadFromStore extends
|
27
|
+
TReadFromStore extends UnknownTReadFromStore,
|
27
28
|
TClientFieldValue,
|
29
|
+
TNormalizationAst extends NormalizationAst | NormalizationAstLoader,
|
28
30
|
> = {
|
29
31
|
readonly kind: 'Entrypoint';
|
30
|
-
readonly networkRequestInfo: NetworkRequestInfo
|
32
|
+
readonly networkRequestInfo: NetworkRequestInfo<TNormalizationAst>;
|
31
33
|
readonly readerWithRefetchQueries: ReaderWithRefetchQueries<
|
32
34
|
TReadFromStore,
|
33
35
|
TClientFieldValue
|
@@ -36,13 +38,13 @@ export type IsographEntrypoint<
|
|
36
38
|
};
|
37
39
|
|
38
40
|
export type IsographEntrypointLoader<
|
39
|
-
TReadFromStore extends
|
41
|
+
TReadFromStore extends UnknownTReadFromStore,
|
40
42
|
TClientFieldValue,
|
41
43
|
> = {
|
42
44
|
readonly kind: 'EntrypointLoader';
|
43
45
|
readonly typeAndField: string;
|
44
46
|
readonly loader: () => Promise<
|
45
|
-
IsographEntrypoint<TReadFromStore, TClientFieldValue>
|
47
|
+
IsographEntrypoint<TReadFromStore, TClientFieldValue, NormalizationAst>
|
46
48
|
>;
|
47
49
|
};
|
48
50
|
|
@@ -50,7 +52,18 @@ export type NormalizationAstNode =
|
|
50
52
|
| NormalizationScalarField
|
51
53
|
| NormalizationLinkedField
|
52
54
|
| NormalizationInlineFragment;
|
53
|
-
|
55
|
+
|
56
|
+
export type NormalizationAstNodes = ReadonlyArray<NormalizationAstNode>;
|
57
|
+
|
58
|
+
export type NormalizationAst = {
|
59
|
+
readonly kind: 'NormalizationAst';
|
60
|
+
readonly selections: NormalizationAstNodes;
|
61
|
+
};
|
62
|
+
|
63
|
+
export type NormalizationAstLoader = {
|
64
|
+
readonly kind: 'NormalizationAstLoader';
|
65
|
+
readonly loader: () => Promise<NormalizationAst>;
|
66
|
+
};
|
54
67
|
|
55
68
|
export type NormalizationScalarField = {
|
56
69
|
readonly kind: 'Scalar';
|
@@ -62,20 +75,20 @@ export type NormalizationLinkedField = {
|
|
62
75
|
readonly kind: 'Linked';
|
63
76
|
readonly fieldName: string;
|
64
77
|
readonly arguments: Arguments | null;
|
65
|
-
readonly selections:
|
78
|
+
readonly selections: NormalizationAstNodes;
|
66
79
|
readonly concreteType: TypeName | null;
|
67
80
|
};
|
68
81
|
|
69
82
|
export type NormalizationInlineFragment = {
|
70
83
|
readonly kind: 'InlineFragment';
|
71
84
|
readonly type: string;
|
72
|
-
readonly selections:
|
85
|
+
readonly selections: NormalizationAstNodes;
|
73
86
|
};
|
74
87
|
|
75
88
|
// This is more like an entrypoint, but one specifically for a refetch query/mutation
|
76
89
|
export type RefetchQueryNormalizationArtifact = {
|
77
90
|
readonly kind: 'RefetchQuery';
|
78
|
-
readonly networkRequestInfo: NetworkRequestInfo
|
91
|
+
readonly networkRequestInfo: NetworkRequestInfo<NormalizationAst>;
|
79
92
|
readonly concreteType: TypeName;
|
80
93
|
};
|
81
94
|
|
@@ -86,21 +99,26 @@ export type RefetchQueryNormalizationArtifactWrapper = {
|
|
86
99
|
};
|
87
100
|
|
88
101
|
export function assertIsEntrypoint<
|
89
|
-
TReadFromStore extends
|
102
|
+
TReadFromStore extends UnknownTReadFromStore,
|
90
103
|
TClientFieldValue,
|
104
|
+
TNormalizationAst extends NormalizationAst | NormalizationAstLoader,
|
91
105
|
>(
|
92
106
|
value:
|
93
|
-
| IsographEntrypoint<TReadFromStore, TClientFieldValue>
|
107
|
+
| IsographEntrypoint<TReadFromStore, TClientFieldValue, TNormalizationAst>
|
94
108
|
| ((_: any) => any)
|
95
109
|
// Temporarily, allow any here. Once we automatically provide
|
96
110
|
// types to entrypoints, we probably don't need this.
|
97
111
|
| any,
|
98
|
-
): asserts value is IsographEntrypoint<
|
112
|
+
): asserts value is IsographEntrypoint<
|
113
|
+
TReadFromStore,
|
114
|
+
TClientFieldValue,
|
115
|
+
TNormalizationAst
|
116
|
+
> {
|
99
117
|
if (typeof value === 'function') throw new Error('Not a string');
|
100
118
|
}
|
101
119
|
|
102
120
|
export type ExtractReadFromStore<Type> =
|
103
|
-
Type extends IsographEntrypoint<infer X, any> ? X : never;
|
121
|
+
Type extends IsographEntrypoint<infer X, any, any> ? X : never;
|
104
122
|
export type ExtractResolverResult<Type> =
|
105
|
-
Type extends IsographEntrypoint<any, infer X> ? X : never;
|
123
|
+
Type extends IsographEntrypoint<any, infer X, any> ? X : never;
|
106
124
|
export type ExtractProps<Type> = Type extends React.FC<infer X> ? X : never;
|
@@ -1,23 +1,23 @@
|
|
1
|
+
import { getParentRecordKey } from './cache';
|
2
|
+
import { NormalizationAstNodes } from './entrypoint';
|
1
3
|
import { Variables } from './FragmentReference';
|
2
4
|
import {
|
5
|
+
assertLink,
|
3
6
|
DataId,
|
4
7
|
IsographEnvironment,
|
5
8
|
IsographStore,
|
6
9
|
StoreRecord,
|
7
|
-
assertLink,
|
8
10
|
type Link,
|
9
11
|
type TypeName,
|
10
12
|
} from './IsographEnvironment';
|
11
|
-
import { getParentRecordKey } from './cache';
|
12
|
-
import { NormalizationAst } from './entrypoint';
|
13
13
|
|
14
14
|
export type RetainedQuery = {
|
15
|
-
readonly normalizationAst:
|
15
|
+
readonly normalizationAst: NormalizationAstNodes;
|
16
16
|
readonly variables: {};
|
17
17
|
readonly root: Link;
|
18
18
|
};
|
19
19
|
|
20
|
-
type DidUnretainSomeQuery = boolean;
|
20
|
+
export type DidUnretainSomeQuery = boolean;
|
21
21
|
export function unretainQuery(
|
22
22
|
environment: IsographEnvironment,
|
23
23
|
retainedQuery: RetainedQuery,
|
@@ -108,7 +108,7 @@ function recordReachableIdsFromRecord(
|
|
108
108
|
store: IsographStore,
|
109
109
|
currentRecord: StoreRecord,
|
110
110
|
mutableRetainedIds: RetainedIds,
|
111
|
-
selections:
|
111
|
+
selections: NormalizationAstNodes,
|
112
112
|
variables: Variables | null,
|
113
113
|
) {
|
114
114
|
for (const selection of selections) {
|