@isograph/react 0.0.0-main-d319cfe5 → 0.0.0-main-ad899464
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/FragmentReference.d.ts +4 -3
- package/dist/IsographEnvironment.d.ts +18 -12
- package/dist/IsographEnvironment.js +1 -1
- package/dist/areEqualWithDeepComparison.d.ts +3 -0
- package/dist/areEqualWithDeepComparison.js +61 -0
- package/dist/cache.d.ts +5 -2
- package/dist/cache.js +60 -13
- package/dist/componentCache.d.ts +3 -6
- package/dist/componentCache.js +19 -23
- package/dist/index.d.ts +2 -2
- package/dist/index.js +3 -4
- package/dist/read.d.ts +2 -3
- package/dist/read.js +10 -58
- package/dist/useReadAndSubscribe.d.ts +7 -0
- package/dist/useReadAndSubscribe.js +16 -0
- package/dist/useRerenderOnChange.d.ts +4 -0
- package/dist/useRerenderOnChange.js +21 -0
- package/dist/useResult.js +13 -5
- package/package.json +3 -3
- package/src/FragmentReference.ts +3 -1
- package/src/IsographEnvironment.tsx +22 -19
- package/src/areEqualWithDeepComparison.ts +78 -0
- package/src/cache.ts +81 -13
- package/src/componentCache.ts +32 -43
- package/src/index.ts +2 -2
- package/src/read.ts +8 -84
- package/src/reader.ts +1 -2
- package/src/useReadAndSubscribe.ts +25 -0
- package/src/useRerenderOnChange.ts +33 -0
- package/src/useResult.ts +17 -10
- package/dist/useRerenderWhenEncounteredRecordChanges.d.ts +0 -2
- package/dist/useRerenderWhenEncounteredRecordChanges.js +0 -16
- package/src/useRerenderWhenEncounteredRecordChanges.ts +0 -17
@@ -2,12 +2,13 @@ import { DataId } from './IsographEnvironment';
|
|
2
2
|
import { RefetchQueryArtifactWrapper } from './entrypoint';
|
3
3
|
import { ReaderArtifact } from './reader';
|
4
4
|
export type Variable = any;
|
5
|
+
export type Variables = {
|
6
|
+
readonly [index: string]: Variable;
|
7
|
+
};
|
5
8
|
export type FragmentReference<TReadFromStore extends Object, TClientFieldValue> = {
|
6
9
|
kind: 'FragmentReference';
|
7
10
|
readerArtifact: ReaderArtifact<TReadFromStore, TClientFieldValue>;
|
8
11
|
root: DataId;
|
9
|
-
variables:
|
10
|
-
[index: string]: Variable;
|
11
|
-
} | null;
|
12
|
+
variables: Variables | null;
|
12
13
|
nestedRefetchQueries: RefetchQueryArtifactWrapper[];
|
13
14
|
};
|
@@ -1,24 +1,30 @@
|
|
1
1
|
/// <reference types="react" />
|
2
2
|
import { ParentCache } from '@isograph/react-disposable-state';
|
3
3
|
import { RetainedQuery } from './garbageCollection';
|
4
|
+
import { WithEncounteredRecords } from './read';
|
5
|
+
import { FragmentReference } from './FragmentReference';
|
4
6
|
export type ComponentOrFieldName = string;
|
5
|
-
type StringifiedArgs = string;
|
6
|
-
type
|
7
|
+
export type StringifiedArgs = string;
|
8
|
+
type ComponentCache = {
|
7
9
|
[key: DataId]: {
|
8
10
|
[key: ComponentOrFieldName]: {
|
9
|
-
[key: StringifiedArgs]:
|
11
|
+
[key: StringifiedArgs]: React.FC<any>;
|
10
12
|
};
|
11
13
|
};
|
12
14
|
};
|
13
|
-
|
14
|
-
|
15
|
-
|
15
|
+
type FragmentSubscription<TReadFromStore extends Object> = {
|
16
|
+
readonly kind: 'FragmentSubscription';
|
17
|
+
readonly callback: (newEncounteredDataAndRecords: WithEncounteredRecords<TReadFromStore>) => void;
|
18
|
+
/** The value read out from the previous call to readButDoNotEvaluate */
|
19
|
+
readonly encounteredDataAndRecords: WithEncounteredRecords<TReadFromStore>;
|
20
|
+
readonly fragmentReference: FragmentReference<TReadFromStore, any>;
|
16
21
|
};
|
17
|
-
type
|
18
|
-
|
19
|
-
|
22
|
+
type AnyRecordSubscription = {
|
23
|
+
readonly kind: 'AnyRecords';
|
24
|
+
readonly callback: () => void;
|
20
25
|
};
|
21
|
-
type
|
26
|
+
type Subscription = FragmentSubscription<Object> | AnyRecordSubscription;
|
27
|
+
type Subscriptions = Set<Subscription>;
|
22
28
|
type SuspenseCache = {
|
23
29
|
[index: string]: ParentCache<any>;
|
24
30
|
};
|
@@ -26,12 +32,12 @@ export type IsographEnvironment = {
|
|
26
32
|
store: IsographStore;
|
27
33
|
networkFunction: IsographNetworkFunction;
|
28
34
|
missingFieldHandler: MissingFieldHandler | null;
|
35
|
+
componentCache: ComponentCache;
|
29
36
|
subscriptions: Subscriptions;
|
37
|
+
suspenseCache: SuspenseCache;
|
30
38
|
retainedQueries: Set<RetainedQuery>;
|
31
39
|
gcBuffer: Array<RetainedQuery>;
|
32
40
|
gcBufferSize: number;
|
33
|
-
componentAndEncounteredRecordsCache: ComponentAndEncounteredRecordsCache;
|
34
|
-
suspenseCache: SuspenseCache;
|
35
41
|
};
|
36
42
|
export type MissingFieldHandler = (storeRecord: StoreRecord, root: DataId, fieldName: string, arguments_: {
|
37
43
|
[index: string]: any;
|
@@ -8,7 +8,7 @@ function createIsographEnvironment(store, networkFunction, missingFieldHandler)
|
|
8
8
|
store,
|
9
9
|
networkFunction,
|
10
10
|
missingFieldHandler: missingFieldHandler !== null && missingFieldHandler !== void 0 ? missingFieldHandler : null,
|
11
|
-
|
11
|
+
componentCache: {},
|
12
12
|
subscriptions: new Set(),
|
13
13
|
suspenseCache: {},
|
14
14
|
retainedQueries: new Set(),
|
@@ -0,0 +1,3 @@
|
|
1
|
+
export declare function areEqualWithDeepComparison(oldItem: unknown, newItem: unknown): boolean;
|
2
|
+
export declare function areEqualArraysWithDeepComparison(oldItems: ReadonlyArray<unknown>, newItems: ReadonlyArray<unknown>): boolean;
|
3
|
+
export declare function areEqualObjectsWithDeepComparison(oldItemObject: object, newItemObject: object): boolean;
|
@@ -0,0 +1,61 @@
|
|
1
|
+
"use strict";
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
+
exports.areEqualObjectsWithDeepComparison = exports.areEqualArraysWithDeepComparison = exports.areEqualWithDeepComparison = void 0;
|
4
|
+
function areEqualWithDeepComparison(oldItem, newItem) {
|
5
|
+
if (newItem === null) {
|
6
|
+
return oldItem === null;
|
7
|
+
}
|
8
|
+
if (newItem === undefined) {
|
9
|
+
return oldItem === undefined;
|
10
|
+
}
|
11
|
+
if (Array.isArray(newItem)) {
|
12
|
+
if (!Array.isArray(oldItem)) {
|
13
|
+
return false;
|
14
|
+
}
|
15
|
+
return areEqualArraysWithDeepComparison(oldItem, newItem);
|
16
|
+
}
|
17
|
+
if (typeof newItem === 'object') {
|
18
|
+
if (typeof oldItem !== 'object') {
|
19
|
+
return false;
|
20
|
+
}
|
21
|
+
if (oldItem === null) {
|
22
|
+
return false;
|
23
|
+
}
|
24
|
+
return areEqualObjectsWithDeepComparison(oldItem, newItem);
|
25
|
+
}
|
26
|
+
return newItem === oldItem;
|
27
|
+
}
|
28
|
+
exports.areEqualWithDeepComparison = areEqualWithDeepComparison;
|
29
|
+
function areEqualArraysWithDeepComparison(oldItems, newItems) {
|
30
|
+
if (newItems.length !== oldItems.length) {
|
31
|
+
return false;
|
32
|
+
}
|
33
|
+
for (let i = 0; i < newItems.length; i++) {
|
34
|
+
if (!areEqualWithDeepComparison(oldItems[i], newItems[i])) {
|
35
|
+
return false;
|
36
|
+
}
|
37
|
+
}
|
38
|
+
return true;
|
39
|
+
}
|
40
|
+
exports.areEqualArraysWithDeepComparison = areEqualArraysWithDeepComparison;
|
41
|
+
function areEqualObjectsWithDeepComparison(oldItemObject, newItemObject) {
|
42
|
+
const oldKeys = Object.keys(oldItemObject);
|
43
|
+
const newKeys = Object.keys(newItemObject);
|
44
|
+
if (oldKeys.length !== newKeys.length) {
|
45
|
+
return false;
|
46
|
+
}
|
47
|
+
for (const oldKey of oldKeys) {
|
48
|
+
if (!(oldKey in newItemObject)) {
|
49
|
+
return false;
|
50
|
+
}
|
51
|
+
// @ts-expect-error
|
52
|
+
const oldValue = oldItemObject[oldKey];
|
53
|
+
// @ts-expect-error
|
54
|
+
const newValue = newItemObject[oldKey];
|
55
|
+
if (!areEqualWithDeepComparison(oldValue, newValue)) {
|
56
|
+
return false;
|
57
|
+
}
|
58
|
+
}
|
59
|
+
return true;
|
60
|
+
}
|
61
|
+
exports.areEqualObjectsWithDeepComparison = areEqualObjectsWithDeepComparison;
|
package/dist/cache.d.ts
CHANGED
@@ -1,8 +1,10 @@
|
|
1
1
|
import { ItemCleanupPair, ParentCache } from '@isograph/react-disposable-state';
|
2
2
|
import { PromiseWrapper } from './PromiseWrapper';
|
3
|
-
import {
|
3
|
+
import { type IsographEnvironment } from './IsographEnvironment';
|
4
4
|
import { IsographEntrypoint, NormalizationLinkedField, NormalizationScalarField } from './entrypoint';
|
5
5
|
import { ReaderLinkedField, ReaderScalarField } from './reader';
|
6
|
+
import { WithEncounteredRecords } from './read';
|
7
|
+
import { FragmentReference } from './FragmentReference';
|
6
8
|
declare global {
|
7
9
|
interface Window {
|
8
10
|
__LOG: boolean;
|
@@ -17,7 +19,8 @@ export declare function stableCopy<T>(value: T): T;
|
|
17
19
|
type IsoResolver = IsographEntrypoint<any, any>;
|
18
20
|
export declare function getOrCreateCacheForArtifact<TReadFromStore extends Object, TClientFieldValue>(environment: IsographEnvironment, artifact: IsographEntrypoint<TReadFromStore, TClientFieldValue>, variables: object): ParentCache<PromiseWrapper<TClientFieldValue>>;
|
19
21
|
export declare function makeNetworkRequest<T>(environment: IsographEnvironment, artifact: IsoResolver, variables: object): ItemCleanupPair<PromiseWrapper<T>>;
|
20
|
-
export declare function
|
22
|
+
export declare function subscribeToAnyChange(environment: IsographEnvironment, callback: () => void): () => void;
|
23
|
+
export declare function subscribe<TReadFromStore extends Object>(environment: IsographEnvironment, encounteredDataAndRecords: WithEncounteredRecords<TReadFromStore>, fragmentReference: FragmentReference<TReadFromStore, any>, callback: (newEncounteredDataAndRecords: WithEncounteredRecords<TReadFromStore>) => void): () => void;
|
21
24
|
export declare function onNextChange(environment: IsographEnvironment): Promise<void>;
|
22
25
|
export declare function getParentRecordKey(astNode: NormalizationLinkedField | NormalizationScalarField | ReaderLinkedField | ReaderScalarField, variables: {
|
23
26
|
[index: string]: string;
|
package/dist/cache.js
CHANGED
@@ -1,10 +1,12 @@
|
|
1
1
|
"use strict";
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
-
exports.SECOND_SPLIT_KEY = exports.FIRST_SPLIT_KEY = exports.getParentRecordKey = exports.onNextChange = exports.subscribe = exports.makeNetworkRequest = exports.getOrCreateCacheForArtifact = exports.stableCopy = void 0;
|
3
|
+
exports.SECOND_SPLIT_KEY = exports.FIRST_SPLIT_KEY = exports.getParentRecordKey = exports.onNextChange = exports.subscribe = exports.subscribeToAnyChange = exports.makeNetworkRequest = exports.getOrCreateCacheForArtifact = exports.stableCopy = void 0;
|
4
4
|
const react_disposable_state_1 = require("@isograph/react-disposable-state");
|
5
5
|
const PromiseWrapper_1 = require("./PromiseWrapper");
|
6
6
|
const IsographEnvironment_1 = require("./IsographEnvironment");
|
7
7
|
const garbageCollection_1 = require("./garbageCollection");
|
8
|
+
const read_1 = require("./read");
|
9
|
+
const areEqualWithDeepComparison_1 = require("./areEqualWithDeepComparison");
|
8
10
|
function getOrCreateCache(environment, index, factory) {
|
9
11
|
if (typeof window !== 'undefined' && window.__LOG) {
|
10
12
|
console.log('getting cache for', {
|
@@ -108,18 +110,31 @@ function normalizeData(environment, normalizationAst, networkResponse, variables
|
|
108
110
|
callSubscriptions(environment, encounteredIds);
|
109
111
|
return encounteredIds;
|
110
112
|
}
|
111
|
-
function
|
112
|
-
const
|
113
|
+
function subscribeToAnyChange(environment, callback) {
|
114
|
+
const subscription = {
|
115
|
+
kind: 'AnyRecords',
|
113
116
|
callback,
|
114
|
-
records: encounteredRecords,
|
115
117
|
};
|
116
|
-
environment.subscriptions.add(
|
117
|
-
return () => environment.subscriptions.delete(
|
118
|
+
environment.subscriptions.add(subscription);
|
119
|
+
return () => environment.subscriptions.delete(subscription);
|
120
|
+
}
|
121
|
+
exports.subscribeToAnyChange = subscribeToAnyChange;
|
122
|
+
function subscribe(environment, encounteredDataAndRecords, fragmentReference, callback) {
|
123
|
+
const fragmentSubscription = {
|
124
|
+
kind: 'FragmentSubscription',
|
125
|
+
callback,
|
126
|
+
encounteredDataAndRecords,
|
127
|
+
fragmentReference,
|
128
|
+
};
|
129
|
+
// @ts-expect-error
|
130
|
+
environment.subscriptions.add(fragmentSubscription);
|
131
|
+
// @ts-expect-error
|
132
|
+
return () => environment.subscriptions.delete(fragmentSubscription);
|
118
133
|
}
|
119
134
|
exports.subscribe = subscribe;
|
120
135
|
function onNextChange(environment) {
|
121
136
|
return new Promise((resolve) => {
|
122
|
-
const unsubscribe =
|
137
|
+
const unsubscribe = subscribeToAnyChange(environment, () => {
|
123
138
|
unsubscribe();
|
124
139
|
resolve();
|
125
140
|
});
|
@@ -127,12 +142,44 @@ function onNextChange(environment) {
|
|
127
142
|
}
|
128
143
|
exports.onNextChange = onNextChange;
|
129
144
|
function callSubscriptions(environment, recordsEncounteredWhenNormalizing) {
|
130
|
-
environment.subscriptions.forEach((
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
145
|
+
environment.subscriptions.forEach((subscription) => {
|
146
|
+
switch (subscription.kind) {
|
147
|
+
case 'FragmentSubscription': {
|
148
|
+
// TODO if there are multiple components subscribed to the same
|
149
|
+
// fragment, we will call readButNotEvaluate multiple times. We
|
150
|
+
// should fix that.
|
151
|
+
if (hasOverlappingIds(recordsEncounteredWhenNormalizing, subscription.encounteredDataAndRecords.encounteredRecords)) {
|
152
|
+
const newEncounteredDataAndRecords = (0, read_1.readButDoNotEvaluate)(environment, subscription.fragmentReference);
|
153
|
+
if (!(0, areEqualWithDeepComparison_1.areEqualObjectsWithDeepComparison)(subscription.encounteredDataAndRecords.item, newEncounteredDataAndRecords.item)) {
|
154
|
+
if (typeof window !== 'undefined' && window.__LOG) {
|
155
|
+
console.log('Deep equality - No', {
|
156
|
+
fragmentReference: subscription.fragmentReference,
|
157
|
+
old: subscription.encounteredDataAndRecords.item,
|
158
|
+
new: newEncounteredDataAndRecords.item,
|
159
|
+
});
|
160
|
+
}
|
161
|
+
// TODO deep compare values
|
162
|
+
subscription.callback(newEncounteredDataAndRecords);
|
163
|
+
}
|
164
|
+
else {
|
165
|
+
if (typeof window !== 'undefined' && window.__LOG) {
|
166
|
+
console.log('Deep equality - Yes', {
|
167
|
+
fragmentReference: subscription.fragmentReference,
|
168
|
+
old: subscription.encounteredDataAndRecords.item,
|
169
|
+
});
|
170
|
+
}
|
171
|
+
}
|
172
|
+
}
|
173
|
+
return;
|
174
|
+
}
|
175
|
+
case 'AnyRecords': {
|
176
|
+
return subscription.callback();
|
177
|
+
}
|
178
|
+
default: {
|
179
|
+
// @ts-expect-error(6133)
|
180
|
+
const _ = subscription;
|
181
|
+
throw new Error('Unexpected case');
|
182
|
+
}
|
136
183
|
}
|
137
184
|
});
|
138
185
|
}
|
package/dist/componentCache.d.ts
CHANGED
@@ -1,7 +1,4 @@
|
|
1
1
|
/// <reference types="react" />
|
2
|
-
import {
|
3
|
-
import {
|
4
|
-
|
5
|
-
export declare function getOrCreateCachedComponent(environment: IsographEnvironment, rootId: DataId, componentName: string, readerArtifact: ReaderArtifact<any, any>, variables: {
|
6
|
-
[key: string]: string;
|
7
|
-
}, resolverRefetchQueries: RefetchQueryArtifactWrapper[]): React.FC<any>;
|
2
|
+
import { IsographEnvironment } from './IsographEnvironment';
|
3
|
+
import { FragmentReference } from './FragmentReference';
|
4
|
+
export declare function getOrCreateCachedComponent(environment: IsographEnvironment, componentName: string, fragmentReference: FragmentReference<any, any>): React.FC<any>;
|
package/dist/componentCache.js
CHANGED
@@ -2,38 +2,34 @@
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
3
3
|
exports.getOrCreateCachedComponent = void 0;
|
4
4
|
const cache_1 = require("./cache");
|
5
|
-
const
|
6
|
-
|
7
|
-
function getOrCreateCachedComponent(environment, rootId, componentName, readerArtifact, variables, resolverRefetchQueries) {
|
5
|
+
const useReadAndSubscribe_1 = require("./useReadAndSubscribe");
|
6
|
+
function getOrCreateCachedComponent(environment, componentName, fragmentReference) {
|
8
7
|
var _a, _b, _c;
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
const
|
8
|
+
// cachedComponentsById is a three layer cache: id, then component name, then
|
9
|
+
// stringified args. These three, together, uniquely identify a read at a given
|
10
|
+
// time.
|
11
|
+
const cachedComponentsById = environment.componentCache;
|
12
|
+
cachedComponentsById[fragmentReference.root] =
|
13
|
+
(_a = cachedComponentsById[fragmentReference.root]) !== null && _a !== void 0 ? _a : {};
|
14
|
+
const componentsByName = cachedComponentsById[fragmentReference.root];
|
13
15
|
componentsByName[componentName] = (_b = componentsByName[componentName]) !== null && _b !== void 0 ? _b : {};
|
14
16
|
const byArgs = componentsByName[componentName];
|
17
|
+
const stringifiedArgs = JSON.stringify((0, cache_1.stableCopy)(fragmentReference.variables));
|
15
18
|
byArgs[stringifiedArgs] =
|
16
19
|
(_c = byArgs[stringifiedArgs]) !== null && _c !== void 0 ? _c : (() => {
|
17
20
|
function Component(additionalRuntimeProps) {
|
18
|
-
const
|
19
|
-
kind: 'FragmentReference',
|
20
|
-
readerArtifact: readerArtifact,
|
21
|
-
root: rootId,
|
22
|
-
variables,
|
23
|
-
nestedRefetchQueries: resolverRefetchQueries,
|
24
|
-
}, byArgs[stringifiedArgs]);
|
25
|
-
(0, useRerenderWhenEncounteredRecordChanges_1.useRerenderWhenEncounteredRecordChanges)(environment, encounteredRecords);
|
21
|
+
const data = (0, useReadAndSubscribe_1.useReadAndSubscribe)(environment, fragmentReference);
|
26
22
|
if (typeof window !== 'undefined' && window.__LOG) {
|
27
|
-
console.log('Component re-rendered: ' +
|
23
|
+
console.log('Component re-rendered: ' +
|
24
|
+
componentName +
|
25
|
+
' ' +
|
26
|
+
fragmentReference.root);
|
28
27
|
}
|
29
|
-
return readerArtifact.resolver(data, additionalRuntimeProps);
|
28
|
+
return fragmentReference.readerArtifact.resolver(data, additionalRuntimeProps);
|
30
29
|
}
|
31
|
-
Component.displayName = `${componentName} (id: ${
|
32
|
-
return
|
33
|
-
component: Component,
|
34
|
-
encounteredRecordsDuringLastRead: null,
|
35
|
-
};
|
30
|
+
Component.displayName = `${componentName} (id: ${fragmentReference.root}) @component`;
|
31
|
+
return Component;
|
36
32
|
})();
|
37
|
-
return byArgs[stringifiedArgs]
|
33
|
+
return byArgs[stringifiedArgs];
|
38
34
|
}
|
39
35
|
exports.getOrCreateCachedComponent = getOrCreateCachedComponent;
|
package/dist/index.d.ts
CHANGED
@@ -7,9 +7,9 @@ export { useImperativeReference } from './useImperativeReference';
|
|
7
7
|
export { EntrypointReader } from './EntrypointReader';
|
8
8
|
export { type ReaderArtifact, ReaderAst, ReaderAstNode, ReaderLinkedField, ReaderMutationField, ReaderRefetchField, ReaderResolverField, ReaderResolverVariant, ReaderScalarField, } from './reader';
|
9
9
|
export { NormalizationAst, NormalizationAstNode, NormalizationLinkedField, NormalizationScalarField, IsographEntrypoint, assertIsEntrypoint, RefetchQueryArtifact, RefetchQueryArtifactWrapper, } from './entrypoint';
|
10
|
-
export {
|
10
|
+
export { readButDoNotEvaluate } from './read';
|
11
11
|
export { useResult } from './useResult';
|
12
12
|
export { type FragmentReference } from './FragmentReference';
|
13
13
|
export { useLazyReference } from './useLazyReference';
|
14
14
|
export { ExtractSecondParam, Argument, ArgumentName, ArgumentValue, Arguments, } from './util';
|
15
|
-
export {
|
15
|
+
export { useRerenderOnChange } from './useRerenderOnChange';
|
package/dist/index.js
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
"use strict";
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
-
exports.
|
3
|
+
exports.useRerenderOnChange = exports.useLazyReference = exports.useResult = exports.readButDoNotEvaluate = exports.assertIsEntrypoint = exports.EntrypointReader = exports.useImperativeReference = exports.useIsographEnvironment = exports.IsographEnvironmentProvider = exports.defaultMissingFieldHandler = exports.createIsographStore = exports.createIsographEnvironment = exports.ROOT_ID = exports.subscribe = exports.makeNetworkRequest = exports.garbageCollectEnvironment = exports.unretainQuery = exports.retainQuery = void 0;
|
4
4
|
var garbageCollection_1 = require("./garbageCollection");
|
5
5
|
Object.defineProperty(exports, "retainQuery", { enumerable: true, get: function () { return garbageCollection_1.retainQuery; } });
|
6
6
|
Object.defineProperty(exports, "unretainQuery", { enumerable: true, get: function () { return garbageCollection_1.unretainQuery; } });
|
@@ -23,11 +23,10 @@ Object.defineProperty(exports, "EntrypointReader", { enumerable: true, get: func
|
|
23
23
|
var entrypoint_1 = require("./entrypoint");
|
24
24
|
Object.defineProperty(exports, "assertIsEntrypoint", { enumerable: true, get: function () { return entrypoint_1.assertIsEntrypoint; } });
|
25
25
|
var read_1 = require("./read");
|
26
|
-
Object.defineProperty(exports, "read", { enumerable: true, get: function () { return read_1.read; } });
|
27
26
|
Object.defineProperty(exports, "readButDoNotEvaluate", { enumerable: true, get: function () { return read_1.readButDoNotEvaluate; } });
|
28
27
|
var useResult_1 = require("./useResult");
|
29
28
|
Object.defineProperty(exports, "useResult", { enumerable: true, get: function () { return useResult_1.useResult; } });
|
30
29
|
var useLazyReference_1 = require("./useLazyReference");
|
31
30
|
Object.defineProperty(exports, "useLazyReference", { enumerable: true, get: function () { return useLazyReference_1.useLazyReference; } });
|
32
|
-
var
|
33
|
-
Object.defineProperty(exports, "
|
31
|
+
var useRerenderOnChange_1 = require("./useRerenderOnChange");
|
32
|
+
Object.defineProperty(exports, "useRerenderOnChange", { enumerable: true, get: function () { return useRerenderOnChange_1.useRerenderOnChange; } });
|
package/dist/read.d.ts
CHANGED
@@ -1,8 +1,7 @@
|
|
1
1
|
import { FragmentReference } from './FragmentReference';
|
2
|
-
import {
|
2
|
+
import { DataId, IsographEnvironment } from './IsographEnvironment';
|
3
3
|
export type WithEncounteredRecords<T> = {
|
4
4
|
encounteredRecords: Set<DataId>;
|
5
5
|
item: T;
|
6
6
|
};
|
7
|
-
export declare function
|
8
|
-
export declare function readButDoNotEvaluate<TReadFromStore extends Object>(environment: IsographEnvironment, reference: FragmentReference<TReadFromStore, unknown>, encounteredRecordCache: ComponentAndEncounteredRecords): WithEncounteredRecords<TReadFromStore>;
|
7
|
+
export declare function readButDoNotEvaluate<TReadFromStore extends Object>(environment: IsographEnvironment, reference: FragmentReference<TReadFromStore, unknown>): WithEncounteredRecords<TReadFromStore>;
|
package/dist/read.js
CHANGED
@@ -1,38 +1,10 @@
|
|
1
1
|
"use strict";
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
-
exports.readButDoNotEvaluate =
|
3
|
+
exports.readButDoNotEvaluate = void 0;
|
4
4
|
const cache_1 = require("./cache");
|
5
5
|
const componentCache_1 = require("./componentCache");
|
6
6
|
const IsographEnvironment_1 = require("./IsographEnvironment");
|
7
|
-
function
|
8
|
-
var _a, _b;
|
9
|
-
const variant = fragmentReference.readerArtifact.variant;
|
10
|
-
if (variant.kind === 'Eager') {
|
11
|
-
const mutableEncounteredRecords = new Set();
|
12
|
-
const data = readData(environment, fragmentReference.readerArtifact.readerAst, fragmentReference.root, (_a = fragmentReference.variables) !== null && _a !== void 0 ? _a : {}, fragmentReference.nestedRefetchQueries, mutableEncounteredRecords);
|
13
|
-
if (data.kind === 'MissingData') {
|
14
|
-
throw (0, cache_1.onNextChange)(environment);
|
15
|
-
}
|
16
|
-
else {
|
17
|
-
return {
|
18
|
-
encounteredRecords: mutableEncounteredRecords,
|
19
|
-
// @ts-expect-error This not properly typed yet
|
20
|
-
item: fragmentReference.readerArtifact.resolver(data.data),
|
21
|
-
};
|
22
|
-
}
|
23
|
-
}
|
24
|
-
else if (variant.kind === 'Component') {
|
25
|
-
return {
|
26
|
-
// @ts-ignore
|
27
|
-
item: (0, componentCache_1.getOrCreateCachedComponent)(environment, fragmentReference.root, variant.componentName, fragmentReference.readerArtifact, (_b = fragmentReference.variables) !== null && _b !== void 0 ? _b : {}, fragmentReference.nestedRefetchQueries),
|
28
|
-
encounteredRecords: new Set(),
|
29
|
-
};
|
30
|
-
}
|
31
|
-
// Why can't Typescript realize that this is unreachable??
|
32
|
-
throw new Error('This is unreachable');
|
33
|
-
}
|
34
|
-
exports.read = read;
|
35
|
-
function readButDoNotEvaluate(environment, reference, encounteredRecordCache) {
|
7
|
+
function readButDoNotEvaluate(environment, reference) {
|
36
8
|
var _a;
|
37
9
|
const mutableEncounteredRecords = new Set();
|
38
10
|
const response = readData(environment, reference.readerArtifact.readerAst, reference.root, (_a = reference.variables) !== null && _a !== void 0 ? _a : {}, reference.nestedRefetchQueries, mutableEncounteredRecords);
|
@@ -43,33 +15,13 @@ function readButDoNotEvaluate(environment, reference, encounteredRecordCache) {
|
|
43
15
|
throw (0, cache_1.onNextChange)(environment);
|
44
16
|
}
|
45
17
|
else {
|
46
|
-
const encounteredRecords = compareAndUpdateEncounteredRecords(encounteredRecordCache, mutableEncounteredRecords);
|
47
18
|
return {
|
48
|
-
encounteredRecords,
|
19
|
+
encounteredRecords: mutableEncounteredRecords,
|
49
20
|
item: response.data,
|
50
21
|
};
|
51
22
|
}
|
52
23
|
}
|
53
24
|
exports.readButDoNotEvaluate = readButDoNotEvaluate;
|
54
|
-
function compareAndUpdateEncounteredRecords(encounteredRecordCache, newEncounteredRecords) {
|
55
|
-
const { encounteredRecordsDuringLastRead } = encounteredRecordCache;
|
56
|
-
if (encounteredRecordsDuringLastRead == null ||
|
57
|
-
encounteredRecordsDuringLastRead.size != newEncounteredRecords.size) {
|
58
|
-
encounteredRecordCache.encounteredRecordsDuringLastRead =
|
59
|
-
newEncounteredRecords;
|
60
|
-
return newEncounteredRecords;
|
61
|
-
}
|
62
|
-
else {
|
63
|
-
for (const item of newEncounteredRecords) {
|
64
|
-
if (!encounteredRecordsDuringLastRead.has(item)) {
|
65
|
-
encounteredRecordCache.encounteredRecordsDuringLastRead =
|
66
|
-
newEncounteredRecords;
|
67
|
-
return newEncounteredRecords;
|
68
|
-
}
|
69
|
-
}
|
70
|
-
return encounteredRecordsDuringLastRead;
|
71
|
-
}
|
72
|
-
}
|
73
25
|
function readData(environment, ast, root, variables, nestedRefetchQueries, mutableEncounteredRecords) {
|
74
26
|
var _a, _b, _c, _d, _e;
|
75
27
|
mutableEncounteredRecords.add(root);
|
@@ -184,9 +136,6 @@ function readData(environment, ast, root, variables, nestedRefetchQueries, mutab
|
|
184
136
|
const data = readData(environment, field.readerArtifact.readerAst, root, variables,
|
185
137
|
// Refetch fields just read the id, and don't need refetch query artifacts
|
186
138
|
[], mutableEncounteredRecords);
|
187
|
-
if (typeof window !== 'undefined' && window.__LOG) {
|
188
|
-
console.log('refetch field data', data, field);
|
189
|
-
}
|
190
139
|
if (data.kind === 'MissingData') {
|
191
140
|
return {
|
192
141
|
kind: 'MissingData',
|
@@ -212,9 +161,6 @@ function readData(environment, ast, root, variables, nestedRefetchQueries, mutab
|
|
212
161
|
const data = readData(environment, field.readerArtifact.readerAst, root, variables,
|
213
162
|
// Mutation don't need refetch query artifacts
|
214
163
|
[], mutableEncounteredRecords);
|
215
|
-
if (typeof window !== 'undefined' && window.__LOG) {
|
216
|
-
console.log('refetch field data', data, field);
|
217
|
-
}
|
218
164
|
if (data.kind === 'MissingData') {
|
219
165
|
return {
|
220
166
|
kind: 'MissingData',
|
@@ -255,7 +201,13 @@ function readData(environment, ast, root, variables, nestedRefetchQueries, mutab
|
|
255
201
|
}
|
256
202
|
}
|
257
203
|
else if (variant.kind === 'Component') {
|
258
|
-
target[field.alias] = (0, componentCache_1.getOrCreateCachedComponent)(environment,
|
204
|
+
target[field.alias] = (0, componentCache_1.getOrCreateCachedComponent)(environment, variant.componentName, {
|
205
|
+
kind: 'FragmentReference',
|
206
|
+
readerArtifact: field.readerArtifact,
|
207
|
+
root,
|
208
|
+
variables,
|
209
|
+
nestedRefetchQueries: resolverRefetchQueries,
|
210
|
+
});
|
259
211
|
}
|
260
212
|
break;
|
261
213
|
}
|
@@ -0,0 +1,7 @@
|
|
1
|
+
import { FragmentReference } from './FragmentReference';
|
2
|
+
import { IsographEnvironment } from './IsographEnvironment';
|
3
|
+
/**
|
4
|
+
* Read the data from a fragment reference and subscribe to updates.
|
5
|
+
* Does not pass the data to the fragment reference's resolver function.
|
6
|
+
*/
|
7
|
+
export declare function useReadAndSubscribe<TReadFromStore extends Object>(environment: IsographEnvironment, fragmentReference: FragmentReference<TReadFromStore, any>): TReadFromStore;
|
@@ -0,0 +1,16 @@
|
|
1
|
+
"use strict";
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
+
exports.useReadAndSubscribe = void 0;
|
4
|
+
const react_1 = require("react");
|
5
|
+
const read_1 = require("./read");
|
6
|
+
const useRerenderOnChange_1 = require("./useRerenderOnChange");
|
7
|
+
/**
|
8
|
+
* Read the data from a fragment reference and subscribe to updates.
|
9
|
+
* Does not pass the data to the fragment reference's resolver function.
|
10
|
+
*/
|
11
|
+
function useReadAndSubscribe(environment, fragmentReference) {
|
12
|
+
const [readOutDataAndRecords, setReadOutDataAndRecords] = (0, react_1.useState)(() => (0, read_1.readButDoNotEvaluate)(environment, fragmentReference));
|
13
|
+
(0, useRerenderOnChange_1.useRerenderOnChange)(environment, readOutDataAndRecords, fragmentReference, setReadOutDataAndRecords);
|
14
|
+
return readOutDataAndRecords.item;
|
15
|
+
}
|
16
|
+
exports.useReadAndSubscribe = useReadAndSubscribe;
|
@@ -0,0 +1,4 @@
|
|
1
|
+
import { IsographEnvironment } from './IsographEnvironment';
|
2
|
+
import { WithEncounteredRecords } from './read';
|
3
|
+
import { FragmentReference } from './FragmentReference';
|
4
|
+
export declare function useRerenderOnChange<TReadFromStore extends Object>(environment: IsographEnvironment, encounteredDataAndRecords: WithEncounteredRecords<TReadFromStore>, fragmentReference: FragmentReference<any, any>, setEncounteredDataAndRecords: (data: WithEncounteredRecords<TReadFromStore>) => void): void;
|
@@ -0,0 +1,21 @@
|
|
1
|
+
"use strict";
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
+
exports.useRerenderOnChange = void 0;
|
4
|
+
const react_1 = require("react");
|
5
|
+
const cache_1 = require("./cache");
|
6
|
+
// TODO add unit tests for this. Add integration tests that test
|
7
|
+
// behavior when the encounteredRecords underneath a fragment change.
|
8
|
+
function useRerenderOnChange(environment, encounteredDataAndRecords, fragmentReference, setEncounteredDataAndRecords) {
|
9
|
+
(0, react_1.useEffect)(() => {
|
10
|
+
return (0, cache_1.subscribe)(environment, encounteredDataAndRecords, fragmentReference, (newEncounteredDataAndRecords) => {
|
11
|
+
setEncounteredDataAndRecords(newEncounteredDataAndRecords);
|
12
|
+
});
|
13
|
+
// Note: this is an empty array on purpose:
|
14
|
+
// - the fragment reference is stable for the life of the component
|
15
|
+
// - ownership of encounteredDataAndRecords is transferred into the
|
16
|
+
// environment
|
17
|
+
// - though maybe we need to include setEncounteredDataAndRecords in
|
18
|
+
// the dependency array
|
19
|
+
}, []);
|
20
|
+
}
|
21
|
+
exports.useRerenderOnChange = useRerenderOnChange;
|
package/dist/useResult.js
CHANGED
@@ -2,12 +2,20 @@
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
3
3
|
exports.useResult = void 0;
|
4
4
|
const IsographEnvironmentProvider_1 = require("./IsographEnvironmentProvider");
|
5
|
-
const
|
6
|
-
const
|
5
|
+
const componentCache_1 = require("./componentCache");
|
6
|
+
const useReadAndSubscribe_1 = require("./useReadAndSubscribe");
|
7
7
|
function useResult(fragmentReference) {
|
8
8
|
const environment = (0, IsographEnvironmentProvider_1.useIsographEnvironment)();
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
switch (fragmentReference.readerArtifact.variant.kind) {
|
10
|
+
case 'Component': {
|
11
|
+
// @ts-expect-error
|
12
|
+
return (0, componentCache_1.getOrCreateCachedComponent)(environment, fragmentReference.readerArtifact.variant.componentName, fragmentReference);
|
13
|
+
}
|
14
|
+
case 'Eager': {
|
15
|
+
const data = (0, useReadAndSubscribe_1.useReadAndSubscribe)(environment, fragmentReference);
|
16
|
+
// @ts-expect-error resolver is incorrectly typed in ReaderArtifact
|
17
|
+
return fragmentReference.readerArtifact.resolver(data);
|
18
|
+
}
|
19
|
+
}
|
12
20
|
}
|
13
21
|
exports.useResult = useResult;
|
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-ad899464",
|
4
4
|
"description": "Use Isograph with React",
|
5
5
|
"homepage": "https://isograph.dev",
|
6
6
|
"main": "dist/index.js",
|
@@ -16,8 +16,8 @@
|
|
16
16
|
"prepack": "yarn run test && yarn run compile"
|
17
17
|
},
|
18
18
|
"dependencies": {
|
19
|
-
"@isograph/disposable-types": "0.0.0-main-
|
20
|
-
"@isograph/react-disposable-state": "0.0.0-main-
|
19
|
+
"@isograph/disposable-types": "0.0.0-main-ad899464",
|
20
|
+
"@isograph/react-disposable-state": "0.0.0-main-ad899464",
|
21
21
|
"react": "^18.2.0"
|
22
22
|
},
|
23
23
|
"devDependencies": {
|
package/src/FragmentReference.ts
CHANGED
@@ -5,6 +5,8 @@ import { ReaderArtifact } from './reader';
|
|
5
5
|
// TODO type this better
|
6
6
|
export type Variable = any;
|
7
7
|
|
8
|
+
export type Variables = { readonly [index: string]: Variable };
|
9
|
+
|
8
10
|
export type FragmentReference<
|
9
11
|
TReadFromStore extends Object,
|
10
12
|
TClientFieldValue,
|
@@ -12,7 +14,7 @@ export type FragmentReference<
|
|
12
14
|
kind: 'FragmentReference';
|
13
15
|
readerArtifact: ReaderArtifact<TReadFromStore, TClientFieldValue>;
|
14
16
|
root: DataId;
|
15
|
-
variables:
|
17
|
+
variables: Variables | null;
|
16
18
|
// TODO: We should instead have ReaderAst<TClientFieldProps>
|
17
19
|
nestedRefetchQueries: RefetchQueryArtifactWrapper[];
|
18
20
|
};
|