@isograph/react 0.2.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 +25 -6
- package/dist/core/FragmentReference.d.ts.map +1 -0
- package/dist/core/FragmentReference.js +3 -13
- package/dist/core/IsographEnvironment.d.ts +34 -26
- package/dist/core/IsographEnvironment.d.ts.map +1 -0
- package/dist/core/IsographEnvironment.js +19 -22
- package/dist/core/PromiseWrapper.d.ts +4 -4
- package/dist/core/PromiseWrapper.d.ts.map +1 -0
- package/dist/core/PromiseWrapper.js +9 -9
- package/dist/core/areEqualWithDeepComparison.d.ts +5 -3
- package/dist/core/areEqualWithDeepComparison.d.ts.map +1 -0
- package/dist/core/areEqualWithDeepComparison.js +89 -39
- package/dist/core/cache.d.ts +20 -13
- package/dist/core/cache.d.ts.map +1 -0
- package/dist/core/cache.js +205 -128
- package/dist/core/check.d.ts +22 -0
- package/dist/core/check.d.ts.map +1 -0
- package/dist/core/check.js +127 -0
- package/dist/core/componentCache.d.ts +2 -2
- package/dist/core/componentCache.d.ts.map +1 -0
- package/dist/core/componentCache.js +28 -32
- package/dist/core/entrypoint.d.ts +31 -15
- package/dist/core/entrypoint.d.ts.map +1 -0
- package/dist/core/entrypoint.js +1 -2
- package/dist/core/garbageCollection.d.ts +6 -5
- package/dist/core/garbageCollection.d.ts.map +1 -0
- package/dist/core/garbageCollection.js +49 -16
- package/dist/core/logging.d.ts +68 -0
- package/dist/core/logging.d.ts.map +1 -0
- package/dist/core/logging.js +22 -0
- package/dist/core/makeNetworkRequest.d.ts +6 -3
- package/dist/core/makeNetworkRequest.d.ts.map +1 -0
- package/dist/core/makeNetworkRequest.js +160 -19
- package/dist/core/read.d.ts +25 -5
- package/dist/core/read.d.ts.map +1 -0
- package/dist/core/read.js +416 -259
- package/dist/core/reader.d.ts +31 -15
- package/dist/core/reader.d.ts.map +1 -0
- 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 +5 -0
- package/dist/core/util.d.ts.map +1 -0
- package/dist/index.d.ts +19 -14
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +11 -2
- package/dist/loadable-hooks/useClientSideDefer.d.ts +9 -3
- package/dist/loadable-hooks/useClientSideDefer.d.ts.map +1 -0
- package/dist/loadable-hooks/useClientSideDefer.js +6 -8
- package/dist/loadable-hooks/useConnectionSpecPagination.d.ts +27 -0
- package/dist/loadable-hooks/useConnectionSpecPagination.d.ts.map +1 -0
- package/dist/loadable-hooks/useConnectionSpecPagination.js +162 -0
- package/dist/loadable-hooks/useImperativeExposedMutationField.d.ts +2 -2
- package/dist/loadable-hooks/useImperativeExposedMutationField.d.ts.map +1 -0
- package/dist/loadable-hooks/useImperativeExposedMutationField.js +1 -2
- package/dist/loadable-hooks/useImperativeLoadableField.d.ts +13 -7
- package/dist/loadable-hooks/useImperativeLoadableField.d.ts.map +1 -0
- package/dist/loadable-hooks/useImperativeLoadableField.js +4 -5
- package/dist/loadable-hooks/useSkipLimitPagination.d.ts +13 -26
- package/dist/loadable-hooks/useSkipLimitPagination.d.ts.map +1 -0
- package/dist/loadable-hooks/useSkipLimitPagination.js +93 -47
- package/dist/react/FragmentReader.d.ts +6 -4
- package/dist/react/FragmentReader.d.ts.map +1 -0
- package/dist/react/FragmentReader.js +4 -2
- package/dist/react/IsographEnvironmentProvider.d.ts +1 -0
- package/dist/react/IsographEnvironmentProvider.d.ts.map +1 -0
- package/dist/react/IsographEnvironmentProvider.js +3 -3
- package/dist/react/RenderAfterCommit__DO_NOT_USE.d.ts +10 -0
- package/dist/react/RenderAfterCommit__DO_NOT_USE.d.ts.map +1 -0
- package/dist/react/RenderAfterCommit__DO_NOT_USE.js +15 -0
- package/dist/react/useImperativeReference.d.ts +8 -6
- package/dist/react/useImperativeReference.d.ts.map +1 -0
- package/dist/react/useImperativeReference.js +6 -8
- package/dist/react/useLazyReference.d.ts +5 -3
- package/dist/react/useLazyReference.d.ts.map +1 -0
- package/dist/react/useLazyReference.js +34 -6
- package/dist/react/useReadAndSubscribe.d.ts +6 -3
- package/dist/react/useReadAndSubscribe.d.ts.map +1 -0
- package/dist/react/useReadAndSubscribe.js +13 -10
- package/dist/react/useRerenderOnChange.d.ts +7 -2
- package/dist/react/useRerenderOnChange.d.ts.map +1 -0
- package/dist/react/useRerenderOnChange.js +3 -4
- package/dist/react/useResult.d.ts +4 -3
- package/dist/react/useResult.d.ts.map +1 -0
- package/dist/react/useResult.js +14 -9
- package/isograph.config.json +8 -0
- package/package.json +14 -9
- package/{src/tests/schema.graphql → schema.graphql} +1 -0
- package/src/core/FragmentReference.ts +44 -17
- package/src/core/IsographEnvironment.ts +67 -50
- package/src/core/PromiseWrapper.ts +3 -3
- package/src/core/areEqualWithDeepComparison.ts +95 -41
- package/src/core/cache.ts +316 -169
- package/src/core/check.ts +212 -0
- package/src/core/componentCache.ts +40 -46
- package/src/core/entrypoint.ts +41 -16
- package/src/core/garbageCollection.ts +77 -26
- package/src/core/logging.ts +118 -0
- package/src/core/makeNetworkRequest.ts +249 -20
- package/src/core/read.ts +658 -368
- package/src/core/reader.ts +61 -21
- package/src/core/startUpdate.ts +28 -0
- package/src/core/util.ts +8 -0
- package/src/index.ts +94 -8
- package/src/loadable-hooks/useClientSideDefer.ts +48 -17
- package/src/loadable-hooks/useConnectionSpecPagination.ts +344 -0
- package/src/loadable-hooks/useImperativeExposedMutationField.ts +1 -1
- package/src/loadable-hooks/useImperativeLoadableField.ts +36 -12
- package/src/loadable-hooks/useSkipLimitPagination.ts +253 -94
- package/src/react/FragmentReader.tsx +15 -6
- package/src/react/IsographEnvironmentProvider.tsx +1 -1
- package/src/react/RenderAfterCommit__DO_NOT_USE.tsx +17 -0
- package/src/react/useImperativeReference.ts +50 -18
- package/src/react/useLazyReference.ts +79 -11
- package/src/react/useReadAndSubscribe.ts +33 -10
- package/src/react/useRerenderOnChange.ts +7 -2
- package/src/react/useResult.ts +30 -9
- package/src/tests/__isograph/Query/meName/entrypoint.ts +10 -29
- package/src/tests/__isograph/Query/meName/normalization_ast.ts +25 -0
- package/src/tests/__isograph/Query/meName/param_type.ts +5 -2
- package/src/tests/__isograph/Query/meName/query_text.ts +6 -0
- package/src/tests/__isograph/Query/meName/resolver_reader.ts +5 -0
- package/src/tests/__isograph/Query/meNameSuccessor/entrypoint.ts +10 -65
- package/src/tests/__isograph/Query/meNameSuccessor/normalization_ast.ts +56 -0
- package/src/tests/__isograph/Query/meNameSuccessor/param_type.ts +9 -6
- package/src/tests/__isograph/Query/meNameSuccessor/query_text.ts +13 -0
- package/src/tests/__isograph/Query/meNameSuccessor/resolver_reader.ts +10 -0
- package/src/tests/__isograph/Query/nodeField/entrypoint.ts +10 -28
- package/src/tests/__isograph/Query/nodeField/normalization_ast.ts +30 -0
- package/src/tests/__isograph/Query/nodeField/param_type.ts +7 -3
- package/src/tests/__isograph/Query/nodeField/parameters_type.ts +3 -0
- package/src/tests/__isograph/Query/nodeField/query_text.ts +6 -0
- package/src/tests/__isograph/Query/nodeField/resolver_reader.ts +5 -0
- package/src/tests/__isograph/Query/subquery/entrypoint.ts +28 -0
- package/src/tests/__isograph/Query/subquery/normalization_ast.ts +38 -0
- package/src/tests/__isograph/Query/subquery/output_type.ts +3 -0
- package/src/tests/__isograph/Query/subquery/param_type.ts +12 -0
- package/src/tests/__isograph/Query/subquery/parameters_type.ts +3 -0
- package/src/tests/__isograph/Query/subquery/query_text.ts +8 -0
- package/src/tests/__isograph/Query/subquery/resolver_reader.ts +52 -0
- package/src/tests/__isograph/iso.ts +24 -12
- package/src/tests/garbageCollection.test.ts +53 -45
- package/src/tests/meNameSuccessor.ts +8 -3
- package/src/tests/nodeQuery.ts +7 -4
- package/src/tests/normalizeData.test.ts +120 -0
- package/src/tests/tsconfig.json +3 -3
- package/tsconfig.json +2 -2
- package/tsconfig.pkg.json +7 -3
- package/vitest.config.ts +20 -0
- package/src/tests/isograph.config.json +0 -7
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"useResult.d.ts","sourceRoot":"","sources":["../../src/react/useResult.ts"],"names":[],"mappings":"AACA,OAAO,EACL,iBAAiB,EACjB,KAAK,qBAAqB,EAC3B,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAEL,cAAc,EAEf,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAEL,2BAA2B,EAC5B,MAAM,cAAc,CAAC;AAKtB,wBAAgB,SAAS,CACvB,cAAc,SAAS,qBAAqB,EAC5C,iBAAiB,EAEjB,iBAAiB,EAAE,iBAAiB,CAAC,cAAc,EAAE,iBAAiB,CAAC,EACvE,4BAA4B,CAAC,EAAE,OAAO,CAAC,2BAA2B,CAAC,GAAG,IAAI,GACzE,iBAAiB,CA8CnB;AAED,wBAAgB,yBAAyB,CACvC,cAAc,EAAE,cAAc,CAAC,IAAI,EAAE,GAAG,CAAC,EACzC,qBAAqB,EAAE,2BAA2B,QAWnD"}
|
package/dist/react/useResult.js
CHANGED
@@ -1,11 +1,13 @@
|
|
1
1
|
"use strict";
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
-
exports.
|
4
|
-
|
3
|
+
exports.useResult = useResult;
|
4
|
+
exports.maybeUnwrapNetworkRequest = maybeUnwrapNetworkRequest;
|
5
5
|
const componentCache_1 = require("../core/componentCache");
|
6
|
-
const useReadAndSubscribe_1 = require("./useReadAndSubscribe");
|
7
|
-
const read_1 = require("../core/read");
|
8
6
|
const PromiseWrapper_1 = require("../core/PromiseWrapper");
|
7
|
+
const read_1 = require("../core/read");
|
8
|
+
const startUpdate_1 = require("../core/startUpdate");
|
9
|
+
const IsographEnvironmentProvider_1 = require("../react/IsographEnvironmentProvider");
|
10
|
+
const useReadAndSubscribe_1 = require("./useReadAndSubscribe");
|
9
11
|
function useResult(fragmentReference, partialNetworkRequestOptions) {
|
10
12
|
const environment = (0, IsographEnvironmentProvider_1.useIsographEnvironment)();
|
11
13
|
const networkRequestOptions = (0, read_1.getNetworkRequestOptionsWithDefaults)(partialNetworkRequestOptions);
|
@@ -14,15 +16,19 @@ function useResult(fragmentReference, partialNetworkRequestOptions) {
|
|
14
16
|
switch (readerWithRefetchQueries.readerArtifact.kind) {
|
15
17
|
case 'ComponentReaderArtifact': {
|
16
18
|
// @ts-expect-error
|
17
|
-
return (0, componentCache_1.getOrCreateCachedComponent)(environment, readerWithRefetchQueries.readerArtifact.
|
19
|
+
return (0, componentCache_1.getOrCreateCachedComponent)(environment, readerWithRefetchQueries.readerArtifact.fieldName, fragmentReference, networkRequestOptions);
|
18
20
|
}
|
19
21
|
case 'EagerReaderArtifact': {
|
20
|
-
const data = (0, useReadAndSubscribe_1.useReadAndSubscribe)(fragmentReference, networkRequestOptions);
|
21
|
-
|
22
|
+
const data = (0, useReadAndSubscribe_1.useReadAndSubscribe)(fragmentReference, networkRequestOptions, readerWithRefetchQueries.readerArtifact.readerAst);
|
23
|
+
const param = Object.assign({ data: data, parameters: fragmentReference.variables }, (readerWithRefetchQueries.readerArtifact.hasUpdatable
|
24
|
+
? {
|
25
|
+
startUpdate: (0, startUpdate_1.getOrCreateCachedStartUpdate)(environment, fragmentReference, readerWithRefetchQueries.readerArtifact.fieldName),
|
26
|
+
}
|
27
|
+
: undefined));
|
28
|
+
return readerWithRefetchQueries.readerArtifact.resolver(param);
|
22
29
|
}
|
23
30
|
}
|
24
31
|
}
|
25
|
-
exports.useResult = useResult;
|
26
32
|
function maybeUnwrapNetworkRequest(networkRequest, networkRequestOptions) {
|
27
33
|
const state = (0, PromiseWrapper_1.getPromiseState)(networkRequest);
|
28
34
|
if (state.kind === 'Err' && networkRequestOptions.throwOnNetworkError) {
|
@@ -33,4 +39,3 @@ function maybeUnwrapNetworkRequest(networkRequest, networkRequestOptions) {
|
|
33
39
|
throw state.promise;
|
34
40
|
}
|
35
41
|
}
|
36
|
-
exports.maybeUnwrapNetworkRequest = maybeUnwrapNetworkRequest;
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@isograph/react",
|
3
|
-
"version": "0.
|
3
|
+
"version": "0.3.1",
|
4
4
|
"description": "Use Isograph with React",
|
5
5
|
"homepage": "https://isograph.dev",
|
6
6
|
"main": "dist/index.js",
|
@@ -8,27 +8,32 @@
|
|
8
8
|
"author": "Isograph Labs",
|
9
9
|
"license": "MIT",
|
10
10
|
"scripts": {
|
11
|
-
"compile": "rm -rf dist/* && tsc -p tsconfig.pkg.json",
|
11
|
+
"compile-typescript": "rm -rf dist/* && tsc -p tsconfig.pkg.json",
|
12
12
|
"compile-watch": "tsc -p tsconfig.pkg.json --watch",
|
13
13
|
"test": "vitest run",
|
14
14
|
"test-watch": "vitest watch",
|
15
15
|
"coverage": "vitest run --coverage",
|
16
|
-
"prepack": "
|
17
|
-
"tsc": "tsc"
|
16
|
+
"prepack": "pnpm run test && pnpm run compile-typescript",
|
17
|
+
"tsc": "tsc",
|
18
|
+
"tsc-force": "tsc --build --clean && tsc --build --force",
|
19
|
+
"iso": "cross-env ../../target/debug/isograph_cli --config ./isograph.config.json",
|
20
|
+
"iso-watch": "cross-env ../../target/debug/isograph_cli --config ./isograph.config.json --watch"
|
18
21
|
},
|
19
22
|
"dependencies": {
|
20
|
-
"@isograph/disposable-types": "
|
23
|
+
"@isograph/disposable-types": "*",
|
21
24
|
"@isograph/react-disposable-state": "*",
|
22
25
|
"@isograph/reference-counted-pointer": "*"
|
23
26
|
},
|
24
27
|
"peerDependencies": {
|
25
|
-
"react": "18.
|
28
|
+
"react": "^18.0.0 || ^19.0.0"
|
26
29
|
},
|
27
30
|
"devDependencies": {
|
28
|
-
"@
|
31
|
+
"@babel/preset-typescript": "^7.24.7",
|
32
|
+
"@types/react": "18.3.1",
|
29
33
|
"react-test-renderer": "^18.2.0",
|
30
|
-
"
|
31
|
-
"
|
34
|
+
"typescript": "5.6.3",
|
35
|
+
"vite-plugin-babel": "^1.2.0",
|
36
|
+
"vite-plugin-commonjs": "^0.10.1"
|
32
37
|
},
|
33
38
|
"repository": {
|
34
39
|
"type": "git",
|
@@ -1,37 +1,64 @@
|
|
1
|
-
import { DataId } from './IsographEnvironment';
|
2
1
|
import { ReaderWithRefetchQueries } from '../core/entrypoint';
|
2
|
+
import { stableCopy } from './cache';
|
3
|
+
import { type Link } from './IsographEnvironment';
|
3
4
|
import { PromiseWrapper } from './PromiseWrapper';
|
5
|
+
import type { StartUpdate } from './reader';
|
4
6
|
|
5
7
|
// TODO type this better
|
6
|
-
export type VariableValue =
|
8
|
+
export type VariableValue =
|
9
|
+
| string
|
10
|
+
| number
|
11
|
+
| boolean
|
12
|
+
| null
|
13
|
+
| {
|
14
|
+
readonly [index: string]: VariableValue;
|
15
|
+
}
|
16
|
+
| VariableValue[];
|
7
17
|
|
8
18
|
export type Variables = { readonly [index: string]: VariableValue };
|
9
19
|
|
20
|
+
export type UnknownTReadFromStore = {
|
21
|
+
parameters: object;
|
22
|
+
data: object;
|
23
|
+
startUpdate?: StartUpdate<object>;
|
24
|
+
};
|
25
|
+
|
26
|
+
export type ExtractData<T> = T extends {
|
27
|
+
data: infer D extends object;
|
28
|
+
}
|
29
|
+
? D
|
30
|
+
: never;
|
31
|
+
|
32
|
+
export type ExtractParameters<T> = T extends {
|
33
|
+
parameters: infer P extends Variables;
|
34
|
+
}
|
35
|
+
? P
|
36
|
+
: Variables;
|
37
|
+
|
38
|
+
export type ExtractStartUpdate<
|
39
|
+
T extends {
|
40
|
+
startUpdate?: StartUpdate<object>;
|
41
|
+
},
|
42
|
+
> = T['startUpdate'];
|
43
|
+
|
10
44
|
export type FragmentReference<
|
11
|
-
TReadFromStore extends
|
45
|
+
TReadFromStore extends UnknownTReadFromStore,
|
12
46
|
TClientFieldValue,
|
13
47
|
> = {
|
14
48
|
readonly kind: 'FragmentReference';
|
15
49
|
readonly readerWithRefetchQueries: PromiseWrapper<
|
16
50
|
ReaderWithRefetchQueries<TReadFromStore, TClientFieldValue>
|
17
51
|
>;
|
18
|
-
readonly root:
|
19
|
-
readonly variables:
|
52
|
+
readonly root: Link;
|
53
|
+
readonly variables: ExtractParameters<TReadFromStore>;
|
20
54
|
readonly networkRequest: PromiseWrapper<void, any>;
|
21
55
|
};
|
22
56
|
|
57
|
+
export type StableIdForFragmentReference = string;
|
58
|
+
|
23
59
|
export function stableIdForFragmentReference(
|
24
60
|
fragmentReference: FragmentReference<any, any>,
|
25
|
-
|
26
|
-
|
27
|
-
}
|
28
|
-
|
29
|
-
function serializeVariables(variables: Variables) {
|
30
|
-
let s = '';
|
31
|
-
const keys = Object.keys(variables);
|
32
|
-
keys.sort();
|
33
|
-
for (const key of keys) {
|
34
|
-
s += `${key}:${variables[key]},`;
|
35
|
-
}
|
36
|
-
return s;
|
61
|
+
fieldName: string,
|
62
|
+
): StableIdForFragmentReference {
|
63
|
+
return `${fragmentReference.root.__typename}/${fragmentReference.root.__link}/${fieldName}/${JSON.stringify(stableCopy(fragmentReference.variables))}`;
|
37
64
|
}
|
@@ -1,42 +1,61 @@
|
|
1
1
|
import { ParentCache } from '@isograph/react-disposable-state';
|
2
|
+
import { IsographEntrypoint } from './entrypoint';
|
3
|
+
import {
|
4
|
+
FragmentReference,
|
5
|
+
Variables,
|
6
|
+
type StableIdForFragmentReference,
|
7
|
+
type UnknownTReadFromStore,
|
8
|
+
} from './FragmentReference';
|
2
9
|
import { RetainedQuery } from './garbageCollection';
|
3
|
-
import {
|
4
|
-
import { FragmentReference, Variables } from './FragmentReference';
|
10
|
+
import { LogFunction, WrappedLogFunction } from './logging';
|
5
11
|
import { PromiseWrapper, wrapPromise } from './PromiseWrapper';
|
6
|
-
import {
|
12
|
+
import { WithEncounteredRecords } from './read';
|
13
|
+
import type { ReaderAst, StartUpdate } from './reader';
|
7
14
|
|
8
15
|
export type ComponentOrFieldName = string;
|
9
16
|
export type StringifiedArgs = string;
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
};
|
17
|
+
|
18
|
+
export type FieldCache<T> = {
|
19
|
+
[key: StableIdForFragmentReference]: T;
|
14
20
|
};
|
15
21
|
|
16
|
-
export type FragmentSubscription<TReadFromStore extends
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
22
|
+
export type FragmentSubscription<TReadFromStore extends UnknownTReadFromStore> =
|
23
|
+
{
|
24
|
+
readonly kind: 'FragmentSubscription';
|
25
|
+
readonly callback: (
|
26
|
+
newEncounteredDataAndRecords: WithEncounteredRecords<TReadFromStore>,
|
27
|
+
) => void;
|
28
|
+
/** The value read out from the previous call to readButDoNotEvaluate */
|
29
|
+
readonly encounteredDataAndRecords: WithEncounteredRecords<TReadFromStore>;
|
30
|
+
readonly fragmentReference: FragmentReference<TReadFromStore, any>;
|
31
|
+
readonly readerAst: ReaderAst<TReadFromStore>;
|
32
|
+
};
|
33
|
+
|
34
|
+
export type AnyChangesToRecordSubscription = {
|
35
|
+
readonly kind: 'AnyChangesToRecord';
|
36
|
+
readonly callback: () => void;
|
37
|
+
readonly recordLink: Link;
|
24
38
|
};
|
25
|
-
|
39
|
+
|
40
|
+
export type AnyRecordSubscription = {
|
26
41
|
readonly kind: 'AnyRecords';
|
27
42
|
readonly callback: () => void;
|
28
43
|
};
|
29
44
|
|
30
|
-
type Subscription =
|
31
|
-
|
45
|
+
export type Subscription =
|
46
|
+
| FragmentSubscription<any>
|
47
|
+
| AnyChangesToRecordSubscription
|
48
|
+
| AnyRecordSubscription;
|
49
|
+
export type Subscriptions = Set<Subscription>;
|
32
50
|
// Should this be a map?
|
33
|
-
type CacheMap<T> = { [index: string]: ParentCache<T> };
|
51
|
+
export type CacheMap<T> = { [index: string]: ParentCache<T> };
|
34
52
|
|
35
53
|
export type IsographEnvironment = {
|
36
54
|
readonly store: IsographStore;
|
37
55
|
readonly networkFunction: IsographNetworkFunction;
|
38
56
|
readonly missingFieldHandler: MissingFieldHandler | null;
|
39
|
-
readonly componentCache:
|
57
|
+
readonly componentCache: FieldCache<React.FC<any>>;
|
58
|
+
readonly eagerReaderCache: FieldCache<StartUpdate<any> | undefined>;
|
40
59
|
readonly subscriptions: Subscriptions;
|
41
60
|
// N.B. this must be <any, any>, but all *usages* of this should go through
|
42
61
|
// a function that adds type parameters.
|
@@ -44,16 +63,17 @@ export type IsographEnvironment = {
|
|
44
63
|
// TODO make this a CacheMap and add GC
|
45
64
|
readonly entrypointArtifactCache: Map<
|
46
65
|
string,
|
47
|
-
PromiseWrapper<IsographEntrypoint<any, any>>
|
66
|
+
PromiseWrapper<IsographEntrypoint<any, any, any>>
|
48
67
|
>;
|
49
68
|
readonly retainedQueries: Set<RetainedQuery>;
|
50
69
|
readonly gcBuffer: Array<RetainedQuery>;
|
51
70
|
readonly gcBufferSize: number;
|
71
|
+
readonly loggers: Set<WrappedLogFunction>;
|
52
72
|
};
|
53
73
|
|
54
74
|
export type MissingFieldHandler = (
|
55
75
|
storeRecord: StoreRecord,
|
56
|
-
root:
|
76
|
+
root: Link,
|
57
77
|
fieldName: string,
|
58
78
|
arguments_: { [index: string]: any } | null,
|
59
79
|
variables: Variables | null,
|
@@ -66,6 +86,7 @@ export type IsographNetworkFunction = (
|
|
66
86
|
|
67
87
|
export type Link = {
|
68
88
|
readonly __link: DataId;
|
89
|
+
readonly __typename: TypeName;
|
69
90
|
};
|
70
91
|
|
71
92
|
export type DataTypeValue =
|
@@ -89,60 +110,54 @@ export type StoreRecord = {
|
|
89
110
|
readonly id?: DataId;
|
90
111
|
};
|
91
112
|
|
113
|
+
export type TypeName = string;
|
92
114
|
export type DataId = string;
|
93
115
|
|
94
116
|
export const ROOT_ID: DataId & '__ROOT' = '__ROOT';
|
95
117
|
|
96
118
|
export type IsographStore = {
|
97
|
-
[index:
|
98
|
-
|
119
|
+
[index: TypeName]: {
|
120
|
+
[index: DataId]: StoreRecord | null;
|
121
|
+
} | null;
|
122
|
+
readonly Query: {
|
123
|
+
readonly __ROOT: StoreRecord;
|
124
|
+
};
|
99
125
|
};
|
100
126
|
|
101
127
|
const DEFAULT_GC_BUFFER_SIZE = 10;
|
102
128
|
export function createIsographEnvironment(
|
103
129
|
store: IsographStore,
|
104
130
|
networkFunction: IsographNetworkFunction,
|
105
|
-
missingFieldHandler?: MissingFieldHandler,
|
131
|
+
missingFieldHandler?: MissingFieldHandler | null,
|
132
|
+
logFunction?: LogFunction | null,
|
106
133
|
): IsographEnvironment {
|
134
|
+
logFunction?.({
|
135
|
+
kind: 'EnvironmentCreated',
|
136
|
+
});
|
107
137
|
return {
|
108
138
|
store,
|
109
139
|
networkFunction,
|
110
140
|
missingFieldHandler: missingFieldHandler ?? null,
|
111
141
|
componentCache: {},
|
142
|
+
eagerReaderCache: {},
|
112
143
|
subscriptions: new Set(),
|
113
144
|
fragmentCache: {},
|
114
145
|
entrypointArtifactCache: new Map(),
|
115
146
|
retainedQueries: new Set(),
|
116
147
|
gcBuffer: [],
|
117
148
|
gcBufferSize: DEFAULT_GC_BUFFER_SIZE,
|
149
|
+
loggers: logFunction != null ? new Set([{ log: logFunction }]) : new Set(),
|
118
150
|
};
|
119
151
|
}
|
120
152
|
|
121
153
|
export function createIsographStore(): IsographStore {
|
122
154
|
return {
|
123
|
-
|
155
|
+
Query: {
|
156
|
+
[ROOT_ID]: {},
|
157
|
+
},
|
124
158
|
};
|
125
159
|
}
|
126
160
|
|
127
|
-
export function defaultMissingFieldHandler(
|
128
|
-
_storeRecord: StoreRecord,
|
129
|
-
_root: DataId,
|
130
|
-
fieldName: string,
|
131
|
-
arguments_: { [index: string]: any } | null,
|
132
|
-
variables: Variables | null,
|
133
|
-
): Link | undefined {
|
134
|
-
if (fieldName === 'node' || fieldName === 'user') {
|
135
|
-
const variable = arguments_?.['id'];
|
136
|
-
const value = variables?.[variable];
|
137
|
-
|
138
|
-
// TODO can we handle explicit nulls here too? Probably, after wrapping in objects
|
139
|
-
if (value != null) {
|
140
|
-
// @ts-expect-error
|
141
|
-
return { __link: value };
|
142
|
-
}
|
143
|
-
}
|
144
|
-
}
|
145
|
-
|
146
161
|
export function assertLink(link: DataTypeValue): Link | null | undefined {
|
147
162
|
if (Array.isArray(link)) {
|
148
163
|
throw new Error('Unexpected array');
|
@@ -160,10 +175,12 @@ export function getLink(maybeLink: DataTypeValue): Link | null {
|
|
160
175
|
if (
|
161
176
|
maybeLink != null &&
|
162
177
|
typeof maybeLink === 'object' &&
|
163
|
-
|
164
|
-
maybeLink.__link != null
|
178
|
+
'__link' in maybeLink &&
|
179
|
+
maybeLink.__link != null &&
|
180
|
+
'__typename' in maybeLink &&
|
181
|
+
maybeLink.__typename != null
|
165
182
|
) {
|
166
|
-
return maybeLink
|
183
|
+
return maybeLink;
|
167
184
|
}
|
168
185
|
return null;
|
169
186
|
}
|
@@ -171,8 +188,8 @@ export function getLink(maybeLink: DataTypeValue): Link | null {
|
|
171
188
|
export function getOrLoadIsographArtifact(
|
172
189
|
environment: IsographEnvironment,
|
173
190
|
key: string,
|
174
|
-
loader: () => Promise<IsographEntrypoint<any, any>>,
|
175
|
-
): PromiseWrapper<IsographEntrypoint<any, any>> {
|
191
|
+
loader: () => Promise<IsographEntrypoint<any, any, any>>,
|
192
|
+
): PromiseWrapper<IsographEntrypoint<any, any, any>> {
|
176
193
|
const value = environment.entrypointArtifactCache.get(key);
|
177
194
|
if (value != null) {
|
178
195
|
return value;
|
@@ -1,9 +1,9 @@
|
|
1
1
|
export type AnyError = any;
|
2
2
|
|
3
|
-
const NOT_SET: Symbol = Symbol('NOT_SET');
|
4
|
-
type NotSet = typeof NOT_SET;
|
3
|
+
export const NOT_SET: Symbol = Symbol('NOT_SET');
|
4
|
+
export type NotSet = typeof NOT_SET;
|
5
5
|
|
6
|
-
type Result<T, E> =
|
6
|
+
export type Result<T, E> =
|
7
7
|
| {
|
8
8
|
kind: 'Ok';
|
9
9
|
value: T;
|
@@ -1,78 +1,132 @@
|
|
1
|
-
|
1
|
+
import type { Link } from './IsographEnvironment';
|
2
|
+
import type { ReaderAst, ReaderLinkedField, ReaderScalarField } from './reader';
|
3
|
+
|
4
|
+
export function mergeUsingReaderAst(
|
5
|
+
field: ReaderScalarField | ReaderLinkedField,
|
2
6
|
oldItem: unknown,
|
3
7
|
newItem: unknown,
|
4
|
-
):
|
8
|
+
): unknown {
|
5
9
|
if (newItem === null) {
|
6
|
-
return oldItem === null;
|
10
|
+
return oldItem === null ? oldItem : newItem;
|
7
11
|
}
|
8
12
|
|
9
13
|
if (newItem === undefined) {
|
10
|
-
return oldItem === undefined;
|
14
|
+
return oldItem === undefined ? oldItem : newItem;
|
11
15
|
}
|
12
16
|
|
13
17
|
if (Array.isArray(newItem)) {
|
14
18
|
if (!Array.isArray(oldItem)) {
|
15
|
-
return
|
19
|
+
return newItem;
|
16
20
|
}
|
17
21
|
|
18
|
-
return
|
22
|
+
return mergeArraysUsingReaderAst(field, oldItem, newItem);
|
19
23
|
}
|
20
24
|
|
21
|
-
|
22
|
-
|
23
|
-
return
|
24
|
-
|
25
|
+
switch (field.kind) {
|
26
|
+
case 'Scalar':
|
27
|
+
return oldItem === newItem ? oldItem : newItem;
|
28
|
+
case 'Linked':
|
29
|
+
if (oldItem == null) {
|
30
|
+
return newItem;
|
31
|
+
}
|
25
32
|
|
26
|
-
|
27
|
-
|
33
|
+
return mergeObjectsUsingReaderAst(field.selections, oldItem, newItem);
|
34
|
+
default: {
|
35
|
+
// Ensure we have covered all variants
|
36
|
+
let _: never = field;
|
37
|
+
_;
|
38
|
+
throw new Error('Unexpected case.');
|
28
39
|
}
|
29
|
-
|
30
|
-
return areEqualObjectsWithDeepComparison(oldItem, newItem);
|
31
40
|
}
|
32
|
-
|
33
|
-
return newItem === oldItem;
|
34
41
|
}
|
35
42
|
|
36
|
-
export function
|
43
|
+
export function mergeArraysUsingReaderAst(
|
44
|
+
field: ReaderScalarField | ReaderLinkedField,
|
37
45
|
oldItems: ReadonlyArray<unknown>,
|
38
|
-
newItems:
|
39
|
-
):
|
46
|
+
newItems: Array<unknown>,
|
47
|
+
): ReadonlyArray<unknown> {
|
40
48
|
if (newItems.length !== oldItems.length) {
|
41
|
-
return
|
49
|
+
return newItems;
|
42
50
|
}
|
43
51
|
|
52
|
+
let canRecycle = true;
|
44
53
|
for (let i = 0; i < newItems.length; i++) {
|
45
|
-
|
46
|
-
|
54
|
+
const mergedItem = mergeUsingReaderAst(field, oldItems[i], newItems[i]);
|
55
|
+
if (mergedItem !== oldItems[i]) {
|
56
|
+
canRecycle = false;
|
57
|
+
} else {
|
58
|
+
newItems[i] = mergedItem;
|
47
59
|
}
|
48
60
|
}
|
49
61
|
|
50
|
-
return
|
62
|
+
return canRecycle ? oldItems : newItems;
|
51
63
|
}
|
52
64
|
|
53
|
-
export function
|
65
|
+
export function mergeObjectsUsingReaderAst(
|
66
|
+
ast: ReaderAst<object>,
|
54
67
|
oldItemObject: object,
|
55
68
|
newItemObject: object,
|
56
|
-
):
|
57
|
-
|
58
|
-
const
|
69
|
+
): object {
|
70
|
+
let canRecycle = true;
|
71
|
+
for (const field of ast) {
|
72
|
+
switch (field.kind) {
|
73
|
+
case 'Scalar':
|
74
|
+
case 'Linked':
|
75
|
+
const key = field.alias ?? field.fieldName;
|
76
|
+
// @ts-expect-error
|
77
|
+
const oldValue = oldItemObject[key];
|
78
|
+
// @ts-expect-error
|
79
|
+
const newValue = newItemObject[key];
|
59
80
|
|
60
|
-
|
61
|
-
|
62
|
-
|
81
|
+
const mergedValue = mergeUsingReaderAst(field, oldValue, newValue);
|
82
|
+
if (mergedValue !== oldValue) {
|
83
|
+
canRecycle = false;
|
84
|
+
} else {
|
85
|
+
// @ts-expect-error
|
86
|
+
newItemObject[key] = mergedValue;
|
87
|
+
}
|
88
|
+
break;
|
89
|
+
case 'Resolver': {
|
90
|
+
const key = field.alias;
|
91
|
+
// @ts-expect-error
|
92
|
+
const oldValue = oldItemObject[key];
|
93
|
+
// @ts-expect-error
|
94
|
+
const newValue = newItemObject[key];
|
63
95
|
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
96
|
+
if (oldValue !== newValue) {
|
97
|
+
canRecycle = false;
|
98
|
+
}
|
99
|
+
break;
|
100
|
+
}
|
101
|
+
case 'Link': {
|
102
|
+
const key = field.alias;
|
103
|
+
// @ts-expect-error
|
104
|
+
const oldValue: Link = oldItemObject[key];
|
105
|
+
// @ts-expect-error
|
106
|
+
const newValue: Link = newItemObject[key];
|
72
107
|
|
73
|
-
|
74
|
-
|
108
|
+
if (
|
109
|
+
oldValue.__link !== newValue.__link ||
|
110
|
+
oldValue.__typename !== newValue.__typename
|
111
|
+
) {
|
112
|
+
canRecycle = false;
|
113
|
+
} else {
|
114
|
+
// @ts-expect-error
|
115
|
+
newItemObject[key] = oldValue;
|
116
|
+
}
|
117
|
+
break;
|
118
|
+
}
|
119
|
+
case 'ImperativelyLoadedField':
|
120
|
+
case 'LoadablySelectedField':
|
121
|
+
break;
|
122
|
+
default: {
|
123
|
+
// Ensure we have covered all variants
|
124
|
+
let _: never = field;
|
125
|
+
_;
|
126
|
+
throw new Error('Unexpected case.');
|
127
|
+
}
|
75
128
|
}
|
76
129
|
}
|
77
|
-
|
130
|
+
|
131
|
+
return canRecycle ? oldItemObject : newItemObject;
|
78
132
|
}
|