@isograph/react 0.0.0-main-2f494978 → 0.0.0-main-6b81bb01
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/cache.d.ts +1 -1
- package/dist/useImperativeReference.d.ts +3 -3
- package/dist/useLazyReference.d.ts +3 -3
- package/dist/useLazyReference.js +2 -8
- package/package.json +4 -4
- package/src/cache.ts +13 -6
- package/src/tests/__isograph/Query/meName/entrypoint.ts +43 -0
- package/src/tests/__isograph/Query/meName/reader.ts +40 -0
- package/src/tests/__isograph/Query/meNameSuccessor/entrypoint.ts +79 -0
- package/src/tests/__isograph/Query/meNameSuccessor/reader.ts +67 -0
- package/src/tests/__isograph/Query/nodeField/entrypoint.ts +42 -0
- package/src/tests/__isograph/Query/nodeField/reader.ts +45 -0
- package/src/tests/__isograph/iso.ts +60 -0
- package/src/tests/garbageCollection.test.ts +130 -0
- package/src/tests/isograph.config.json +7 -0
- package/src/tests/meNameSuccessor.ts +20 -0
- package/src/tests/nodeQuery.ts +17 -0
- package/src/tests/schema.graphql +16 -0
- package/src/tests/tsconfig.json +21 -0
- package/src/useImperativeReference.ts +6 -15
- package/src/useLazyReference.ts +10 -35
- package/tsconfig.pkg.json +2 -1
package/dist/cache.d.ts
CHANGED
@@ -15,7 +15,7 @@ declare global {
|
|
15
15
|
*/
|
16
16
|
export declare function stableCopy<T>(value: T): T;
|
17
17
|
type IsoResolver = IsographEntrypoint<any, any>;
|
18
|
-
export declare function getOrCreateCacheForArtifact<
|
18
|
+
export declare function getOrCreateCacheForArtifact<TReadFromStore extends Object, TClientFieldValue>(environment: IsographEnvironment, artifact: IsographEntrypoint<TReadFromStore, TClientFieldValue>, variables: object): ParentCache<PromiseWrapper<TClientFieldValue>>;
|
19
19
|
export declare function makeNetworkRequest<T>(environment: IsographEnvironment, artifact: IsoResolver, variables: object): ItemCleanupPair<PromiseWrapper<T>>;
|
20
20
|
export declare function subscribe(environment: IsographEnvironment, callback: () => void): () => void;
|
21
21
|
export declare function onNextChange(environment: IsographEnvironment): Promise<void>;
|
@@ -1,8 +1,8 @@
|
|
1
1
|
import { UnassignedState } from '@isograph/react-disposable-state';
|
2
|
-
import {
|
2
|
+
import { IsographEntrypoint } from './entrypoint';
|
3
3
|
import { FragmentReference } from './FragmentReference';
|
4
|
-
export declare function useImperativeReference<
|
5
|
-
queryReference: FragmentReference<
|
4
|
+
export declare function useImperativeReference<TReadFromStore extends Object, TClientFieldValue>(entrypoint: IsographEntrypoint<TReadFromStore, TClientFieldValue>): {
|
5
|
+
queryReference: FragmentReference<TReadFromStore, TClientFieldValue> | UnassignedState;
|
6
6
|
loadQueryReference: (variables: {
|
7
7
|
[index: string]: string;
|
8
8
|
}) => void;
|
@@ -1,7 +1,7 @@
|
|
1
1
|
import { FragmentReference, Variable } from './FragmentReference';
|
2
|
-
import {
|
3
|
-
export declare function useLazyReference<
|
2
|
+
import { IsographEntrypoint } from './entrypoint';
|
3
|
+
export declare function useLazyReference<TReadFromStore extends Object, TClientFieldValue>(entrypoint: IsographEntrypoint<TReadFromStore, TClientFieldValue>, variables: {
|
4
4
|
[key: string]: Variable;
|
5
5
|
}): {
|
6
|
-
queryReference: FragmentReference<
|
6
|
+
queryReference: FragmentReference<TReadFromStore, TClientFieldValue>;
|
7
7
|
};
|
package/dist/useLazyReference.js
CHANGED
@@ -3,20 +3,14 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.useLazyReference = void 0;
|
4
4
|
const IsographEnvironmentProvider_1 = require("./IsographEnvironmentProvider");
|
5
5
|
const IsographEnvironment_1 = require("./IsographEnvironment");
|
6
|
-
const entrypoint_1 = require("./entrypoint");
|
7
6
|
const cache_1 = require("./cache");
|
8
7
|
const react_disposable_state_1 = require("@isograph/react-disposable-state");
|
9
|
-
// Note: we cannot write TEntrypoint extends IsographEntrypoint<any, any, any>, or else
|
10
|
-
// if we do not explicitly pass a type, the read out type will be any.
|
11
|
-
// We cannot write TEntrypoint extends IsographEntrypoint<never, never, never>, or else
|
12
|
-
// any actual Entrypoint we pass will not be valid.
|
13
8
|
function useLazyReference(entrypoint, variables) {
|
14
9
|
const environment = (0, IsographEnvironmentProvider_1.useIsographEnvironment)();
|
15
|
-
(0, entrypoint_1.assertIsEntrypoint)(entrypoint);
|
16
10
|
const cache = (0, cache_1.getOrCreateCacheForArtifact)(environment, entrypoint, variables);
|
17
11
|
// TODO add comment explaining why we never use this value
|
18
|
-
// @ts-ignore
|
19
|
-
const
|
12
|
+
// @ts-ignore(6133)
|
13
|
+
const _data = (0, react_disposable_state_1.useLazyDisposableState)(cache).state;
|
20
14
|
return {
|
21
15
|
queryReference: {
|
22
16
|
kind: 'FragmentReference',
|
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-6b81bb01",
|
4
4
|
"description": "Use Isograph with React",
|
5
5
|
"homepage": "https://isograph.dev",
|
6
6
|
"main": "dist/index.js",
|
@@ -10,14 +10,14 @@
|
|
10
10
|
"scripts": {
|
11
11
|
"compile": "rm -rf dist/* && tsc -p tsconfig.pkg.json",
|
12
12
|
"compile-watch": "tsc -p tsconfig.pkg.json --watch",
|
13
|
-
"test": "
|
13
|
+
"test": "vitest run",
|
14
14
|
"test-watch": "vitest watch",
|
15
15
|
"coverage": "vitest run --coverage",
|
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-6b81bb01",
|
20
|
+
"@isograph/react-disposable-state": "0.0.0-main-6b81bb01",
|
21
21
|
"react": "^18.2.0"
|
22
22
|
},
|
23
23
|
"devDependencies": {
|
package/src/cache.ts
CHANGED
@@ -76,15 +76,22 @@ export function stableCopy<T>(value: T): T {
|
|
76
76
|
|
77
77
|
type IsoResolver = IsographEntrypoint<any, any>;
|
78
78
|
|
79
|
-
export function getOrCreateCacheForArtifact<
|
79
|
+
export function getOrCreateCacheForArtifact<
|
80
|
+
TReadFromStore extends Object,
|
81
|
+
TClientFieldValue,
|
82
|
+
>(
|
80
83
|
environment: IsographEnvironment,
|
81
|
-
artifact: IsographEntrypoint<
|
84
|
+
artifact: IsographEntrypoint<TReadFromStore, TClientFieldValue>,
|
82
85
|
variables: object,
|
83
|
-
): ParentCache<PromiseWrapper<
|
86
|
+
): ParentCache<PromiseWrapper<TClientFieldValue>> {
|
84
87
|
const cacheKey = artifact.queryText + JSON.stringify(stableCopy(variables));
|
85
|
-
const factory: Factory<PromiseWrapper<
|
86
|
-
makeNetworkRequest<
|
87
|
-
return getOrCreateCache<PromiseWrapper<
|
88
|
+
const factory: Factory<PromiseWrapper<TClientFieldValue>> = () =>
|
89
|
+
makeNetworkRequest<TClientFieldValue>(environment, artifact, variables);
|
90
|
+
return getOrCreateCache<PromiseWrapper<TClientFieldValue>>(
|
91
|
+
environment,
|
92
|
+
cacheKey,
|
93
|
+
factory,
|
94
|
+
);
|
88
95
|
}
|
89
96
|
|
90
97
|
type NetworkRequestStatus =
|
@@ -0,0 +1,43 @@
|
|
1
|
+
import type {IsographEntrypoint, NormalizationAst, RefetchQueryArtifactWrapper} from '@isograph/react';
|
2
|
+
import type {Query__meName__param, Query__meName__outputType} from './reader';
|
3
|
+
import readerResolver from './reader';
|
4
|
+
const nestedRefetchQueries: RefetchQueryArtifactWrapper[] = [];
|
5
|
+
|
6
|
+
const queryText = 'query meName {\
|
7
|
+
me {\
|
8
|
+
id,\
|
9
|
+
name,\
|
10
|
+
},\
|
11
|
+
}';
|
12
|
+
|
13
|
+
const normalizationAst: NormalizationAst = [
|
14
|
+
{
|
15
|
+
kind: "Linked",
|
16
|
+
fieldName: "me",
|
17
|
+
arguments: null,
|
18
|
+
selections: [
|
19
|
+
{
|
20
|
+
kind: "Scalar",
|
21
|
+
fieldName: "id",
|
22
|
+
arguments: null,
|
23
|
+
},
|
24
|
+
{
|
25
|
+
kind: "Scalar",
|
26
|
+
fieldName: "name",
|
27
|
+
arguments: null,
|
28
|
+
},
|
29
|
+
],
|
30
|
+
},
|
31
|
+
];
|
32
|
+
const artifact: IsographEntrypoint<
|
33
|
+
Query__meName__param,
|
34
|
+
Query__meName__outputType
|
35
|
+
> = {
|
36
|
+
kind: "Entrypoint",
|
37
|
+
queryText,
|
38
|
+
normalizationAst,
|
39
|
+
nestedRefetchQueries,
|
40
|
+
readerArtifact: readerResolver,
|
41
|
+
};
|
42
|
+
|
43
|
+
export default artifact;
|
@@ -0,0 +1,40 @@
|
|
1
|
+
import type {ReaderArtifact, ReaderAst, ExtractSecondParam} from '@isograph/react';
|
2
|
+
import { meNameField as resolver } from '../../../garbageCollection.test.ts';
|
3
|
+
|
4
|
+
// the type, when read out (either via useLazyReference or via graph)
|
5
|
+
export type Query__meName__outputType = ReturnType<typeof resolver>;
|
6
|
+
|
7
|
+
const readerAst: ReaderAst<Query__meName__param> = [
|
8
|
+
{
|
9
|
+
kind: "Linked",
|
10
|
+
fieldName: "me",
|
11
|
+
alias: null,
|
12
|
+
arguments: null,
|
13
|
+
selections: [
|
14
|
+
{
|
15
|
+
kind: "Scalar",
|
16
|
+
fieldName: "name",
|
17
|
+
alias: null,
|
18
|
+
arguments: null,
|
19
|
+
},
|
20
|
+
],
|
21
|
+
},
|
22
|
+
];
|
23
|
+
|
24
|
+
export type Query__meName__param = {
|
25
|
+
me: {
|
26
|
+
name: string,
|
27
|
+
},
|
28
|
+
};
|
29
|
+
|
30
|
+
const artifact: ReaderArtifact<
|
31
|
+
Query__meName__param,
|
32
|
+
Query__meName__outputType
|
33
|
+
> = {
|
34
|
+
kind: "ReaderArtifact",
|
35
|
+
resolver: resolver as any,
|
36
|
+
readerAst,
|
37
|
+
variant: { kind: "Eager" },
|
38
|
+
};
|
39
|
+
|
40
|
+
export default artifact;
|
@@ -0,0 +1,79 @@
|
|
1
|
+
import type {IsographEntrypoint, NormalizationAst, RefetchQueryArtifactWrapper} from '@isograph/react';
|
2
|
+
import type {Query__meNameSuccessor__param, Query__meNameSuccessor__outputType} from './reader';
|
3
|
+
import readerResolver from './reader';
|
4
|
+
const nestedRefetchQueries: RefetchQueryArtifactWrapper[] = [];
|
5
|
+
|
6
|
+
const queryText = 'query meNameSuccessor {\
|
7
|
+
me {\
|
8
|
+
id,\
|
9
|
+
name,\
|
10
|
+
successor {\
|
11
|
+
id,\
|
12
|
+
successor {\
|
13
|
+
id,\
|
14
|
+
name,\
|
15
|
+
},\
|
16
|
+
},\
|
17
|
+
},\
|
18
|
+
}';
|
19
|
+
|
20
|
+
const normalizationAst: NormalizationAst = [
|
21
|
+
{
|
22
|
+
kind: "Linked",
|
23
|
+
fieldName: "me",
|
24
|
+
arguments: null,
|
25
|
+
selections: [
|
26
|
+
{
|
27
|
+
kind: "Scalar",
|
28
|
+
fieldName: "id",
|
29
|
+
arguments: null,
|
30
|
+
},
|
31
|
+
{
|
32
|
+
kind: "Scalar",
|
33
|
+
fieldName: "name",
|
34
|
+
arguments: null,
|
35
|
+
},
|
36
|
+
{
|
37
|
+
kind: "Linked",
|
38
|
+
fieldName: "successor",
|
39
|
+
arguments: null,
|
40
|
+
selections: [
|
41
|
+
{
|
42
|
+
kind: "Scalar",
|
43
|
+
fieldName: "id",
|
44
|
+
arguments: null,
|
45
|
+
},
|
46
|
+
{
|
47
|
+
kind: "Linked",
|
48
|
+
fieldName: "successor",
|
49
|
+
arguments: null,
|
50
|
+
selections: [
|
51
|
+
{
|
52
|
+
kind: "Scalar",
|
53
|
+
fieldName: "id",
|
54
|
+
arguments: null,
|
55
|
+
},
|
56
|
+
{
|
57
|
+
kind: "Scalar",
|
58
|
+
fieldName: "name",
|
59
|
+
arguments: null,
|
60
|
+
},
|
61
|
+
],
|
62
|
+
},
|
63
|
+
],
|
64
|
+
},
|
65
|
+
],
|
66
|
+
},
|
67
|
+
];
|
68
|
+
const artifact: IsographEntrypoint<
|
69
|
+
Query__meNameSuccessor__param,
|
70
|
+
Query__meNameSuccessor__outputType
|
71
|
+
> = {
|
72
|
+
kind: "Entrypoint",
|
73
|
+
queryText,
|
74
|
+
normalizationAst,
|
75
|
+
nestedRefetchQueries,
|
76
|
+
readerArtifact: readerResolver,
|
77
|
+
};
|
78
|
+
|
79
|
+
export default artifact;
|
@@ -0,0 +1,67 @@
|
|
1
|
+
import type {ReaderArtifact, ReaderAst, ExtractSecondParam} from '@isograph/react';
|
2
|
+
import { meNameField as resolver } from '../../../meNameSuccessor.ts';
|
3
|
+
|
4
|
+
// the type, when read out (either via useLazyReference or via graph)
|
5
|
+
export type Query__meNameSuccessor__outputType = ReturnType<typeof resolver>;
|
6
|
+
|
7
|
+
const readerAst: ReaderAst<Query__meNameSuccessor__param> = [
|
8
|
+
{
|
9
|
+
kind: "Linked",
|
10
|
+
fieldName: "me",
|
11
|
+
alias: null,
|
12
|
+
arguments: null,
|
13
|
+
selections: [
|
14
|
+
{
|
15
|
+
kind: "Scalar",
|
16
|
+
fieldName: "name",
|
17
|
+
alias: null,
|
18
|
+
arguments: null,
|
19
|
+
},
|
20
|
+
{
|
21
|
+
kind: "Linked",
|
22
|
+
fieldName: "successor",
|
23
|
+
alias: null,
|
24
|
+
arguments: null,
|
25
|
+
selections: [
|
26
|
+
{
|
27
|
+
kind: "Linked",
|
28
|
+
fieldName: "successor",
|
29
|
+
alias: null,
|
30
|
+
arguments: null,
|
31
|
+
selections: [
|
32
|
+
{
|
33
|
+
kind: "Scalar",
|
34
|
+
fieldName: "name",
|
35
|
+
alias: null,
|
36
|
+
arguments: null,
|
37
|
+
},
|
38
|
+
],
|
39
|
+
},
|
40
|
+
],
|
41
|
+
},
|
42
|
+
],
|
43
|
+
},
|
44
|
+
];
|
45
|
+
|
46
|
+
export type Query__meNameSuccessor__param = {
|
47
|
+
me: {
|
48
|
+
name: string,
|
49
|
+
successor: ({
|
50
|
+
successor: ({
|
51
|
+
name: string,
|
52
|
+
} | null),
|
53
|
+
} | null),
|
54
|
+
},
|
55
|
+
};
|
56
|
+
|
57
|
+
const artifact: ReaderArtifact<
|
58
|
+
Query__meNameSuccessor__param,
|
59
|
+
Query__meNameSuccessor__outputType
|
60
|
+
> = {
|
61
|
+
kind: "ReaderArtifact",
|
62
|
+
resolver: resolver as any,
|
63
|
+
readerAst,
|
64
|
+
variant: { kind: "Eager" },
|
65
|
+
};
|
66
|
+
|
67
|
+
export default artifact;
|
@@ -0,0 +1,42 @@
|
|
1
|
+
import type {IsographEntrypoint, NormalizationAst, RefetchQueryArtifactWrapper} from '@isograph/react';
|
2
|
+
import type {Query__nodeField__param, Query__nodeField__outputType} from './reader';
|
3
|
+
import readerResolver from './reader';
|
4
|
+
const nestedRefetchQueries: RefetchQueryArtifactWrapper[] = [];
|
5
|
+
|
6
|
+
const queryText = 'query nodeField ($id: ID!) {\
|
7
|
+
node____id___v_id: node(id: $id) {\
|
8
|
+
id,\
|
9
|
+
},\
|
10
|
+
}';
|
11
|
+
|
12
|
+
const normalizationAst: NormalizationAst = [
|
13
|
+
{
|
14
|
+
kind: "Linked",
|
15
|
+
fieldName: "node",
|
16
|
+
arguments: [
|
17
|
+
[
|
18
|
+
"id",
|
19
|
+
{ kind: "Variable", name: "id" },
|
20
|
+
],
|
21
|
+
],
|
22
|
+
selections: [
|
23
|
+
{
|
24
|
+
kind: "Scalar",
|
25
|
+
fieldName: "id",
|
26
|
+
arguments: null,
|
27
|
+
},
|
28
|
+
],
|
29
|
+
},
|
30
|
+
];
|
31
|
+
const artifact: IsographEntrypoint<
|
32
|
+
Query__nodeField__param,
|
33
|
+
Query__nodeField__outputType
|
34
|
+
> = {
|
35
|
+
kind: "Entrypoint",
|
36
|
+
queryText,
|
37
|
+
normalizationAst,
|
38
|
+
nestedRefetchQueries,
|
39
|
+
readerArtifact: readerResolver,
|
40
|
+
};
|
41
|
+
|
42
|
+
export default artifact;
|
@@ -0,0 +1,45 @@
|
|
1
|
+
import type {ReaderArtifact, ReaderAst, ExtractSecondParam} from '@isograph/react';
|
2
|
+
import { nodeField as resolver } from '../../../nodeQuery.ts';
|
3
|
+
|
4
|
+
// the type, when read out (either via useLazyReference or via graph)
|
5
|
+
export type Query__nodeField__outputType = ReturnType<typeof resolver>;
|
6
|
+
|
7
|
+
const readerAst: ReaderAst<Query__nodeField__param> = [
|
8
|
+
{
|
9
|
+
kind: "Linked",
|
10
|
+
fieldName: "node",
|
11
|
+
alias: null,
|
12
|
+
arguments: [
|
13
|
+
[
|
14
|
+
"id",
|
15
|
+
{ kind: "Variable", name: "id" },
|
16
|
+
],
|
17
|
+
],
|
18
|
+
selections: [
|
19
|
+
{
|
20
|
+
kind: "Scalar",
|
21
|
+
fieldName: "id",
|
22
|
+
alias: null,
|
23
|
+
arguments: null,
|
24
|
+
},
|
25
|
+
],
|
26
|
+
},
|
27
|
+
];
|
28
|
+
|
29
|
+
export type Query__nodeField__param = {
|
30
|
+
node: ({
|
31
|
+
id: string,
|
32
|
+
} | null),
|
33
|
+
};
|
34
|
+
|
35
|
+
const artifact: ReaderArtifact<
|
36
|
+
Query__nodeField__param,
|
37
|
+
Query__nodeField__outputType
|
38
|
+
> = {
|
39
|
+
kind: "ReaderArtifact",
|
40
|
+
resolver: resolver as any,
|
41
|
+
readerAst,
|
42
|
+
variant: { kind: "Eager" },
|
43
|
+
};
|
44
|
+
|
45
|
+
export default artifact;
|
@@ -0,0 +1,60 @@
|
|
1
|
+
import type {IsographEntrypoint} from '@isograph/react';
|
2
|
+
import { Query__meNameSuccessor__param } from './Query/meNameSuccessor/reader'
|
3
|
+
import { Query__meName__param } from './Query/meName/reader'
|
4
|
+
import { Query__nodeField__param } from './Query/nodeField/reader'
|
5
|
+
import entrypoint_Query__meNameSuccessor from '../__isograph/Query/meNameSuccessor/entrypoint'
|
6
|
+
import entrypoint_Query__meName from '../__isograph/Query/meName/entrypoint'
|
7
|
+
import entrypoint_Query__nodeField from '../__isograph/Query/nodeField/entrypoint'
|
8
|
+
|
9
|
+
type IdentityWithParam<TParam> = <TResolverReturn>(
|
10
|
+
x: (param: TParam) => TResolverReturn
|
11
|
+
) => (param: TParam) => TResolverReturn;
|
12
|
+
type IdentityWithParamComponent<TParam> = <TResolverReturn, TSecondParam = Record<string, never>>(
|
13
|
+
x: (data: TParam, secondParam: TSecondParam) => TResolverReturn
|
14
|
+
) => (data: TParam, secondParam: TSecondParam) => TResolverReturn;
|
15
|
+
|
16
|
+
type WhitespaceCharacter = ' ' | '\t' | '\n';
|
17
|
+
type Whitespace<In> = In extends `${WhitespaceCharacter}${infer In}`
|
18
|
+
? Whitespace<In>
|
19
|
+
: In;
|
20
|
+
|
21
|
+
type MatchesWhitespaceAndString<
|
22
|
+
TString extends string,
|
23
|
+
T
|
24
|
+
> = Whitespace<T> extends `${TString}${string}` ? T : never;
|
25
|
+
|
26
|
+
export function iso<T>(
|
27
|
+
param: T & MatchesWhitespaceAndString<'field Query.meNameSuccessor', T>
|
28
|
+
): IdentityWithParam<Query__meNameSuccessor__param>;
|
29
|
+
|
30
|
+
export function iso<T>(
|
31
|
+
param: T & MatchesWhitespaceAndString<'field Query.meName', T>
|
32
|
+
): IdentityWithParam<Query__meName__param>;
|
33
|
+
|
34
|
+
export function iso<T>(
|
35
|
+
param: T & MatchesWhitespaceAndString<'field Query.nodeField', T>
|
36
|
+
): IdentityWithParam<Query__nodeField__param>;
|
37
|
+
|
38
|
+
export function iso<T>(
|
39
|
+
param: T & MatchesWhitespaceAndString<'entrypoint Query.meNameSuccessor', T>
|
40
|
+
): typeof entrypoint_Query__meNameSuccessor;
|
41
|
+
|
42
|
+
export function iso<T>(
|
43
|
+
param: T & MatchesWhitespaceAndString<'entrypoint Query.meName', T>
|
44
|
+
): typeof entrypoint_Query__meName;
|
45
|
+
|
46
|
+
export function iso<T>(
|
47
|
+
param: T & MatchesWhitespaceAndString<'entrypoint Query.nodeField', T>
|
48
|
+
): typeof entrypoint_Query__nodeField;
|
49
|
+
|
50
|
+
export function iso(_isographLiteralText: string):
|
51
|
+
| IdentityWithParam<any>
|
52
|
+
| IdentityWithParamComponent<any>
|
53
|
+
| IsographEntrypoint<any, any>
|
54
|
+
{
|
55
|
+
return function identity<TResolverReturn>(
|
56
|
+
clientFieldOrEntrypoint: (param: any) => TResolverReturn,
|
57
|
+
): (param: any) => TResolverReturn {
|
58
|
+
return clientFieldOrEntrypoint;
|
59
|
+
};
|
60
|
+
}
|
@@ -0,0 +1,130 @@
|
|
1
|
+
import { describe, test, expect } from 'vitest';
|
2
|
+
import { ROOT_ID, createIsographEnvironment } from '../IsographEnvironment';
|
3
|
+
import { garbageCollectEnvironment, retainQuery } from '../garbageCollection';
|
4
|
+
import { iso } from './__isograph/iso';
|
5
|
+
import { nodeFieldRetainedQuery } from './nodeQuery';
|
6
|
+
|
7
|
+
const getDefaultStore = () => ({
|
8
|
+
[ROOT_ID]: {
|
9
|
+
me: { __link: '0' },
|
10
|
+
you: { __link: '1' },
|
11
|
+
node____id___0: {
|
12
|
+
__link: '0',
|
13
|
+
},
|
14
|
+
},
|
15
|
+
0: {
|
16
|
+
__typename: 'Economist',
|
17
|
+
id: '0',
|
18
|
+
name: 'Jeremy Bentham',
|
19
|
+
successor: { __link: '1' },
|
20
|
+
},
|
21
|
+
1: {
|
22
|
+
__typename: 'Economist',
|
23
|
+
id: '1',
|
24
|
+
name: 'John Stuart Mill',
|
25
|
+
predecessor: { __link: '0' },
|
26
|
+
successor: { __link: '2' },
|
27
|
+
},
|
28
|
+
2: {
|
29
|
+
__typename: 'Economist',
|
30
|
+
id: '2',
|
31
|
+
name: 'Henry Sidgwick',
|
32
|
+
predecessor: { __link: '1' },
|
33
|
+
},
|
34
|
+
});
|
35
|
+
|
36
|
+
export const meNameField = iso(`
|
37
|
+
field Query.meName {
|
38
|
+
me {
|
39
|
+
name
|
40
|
+
}
|
41
|
+
}
|
42
|
+
`)(() => {});
|
43
|
+
import meNameEntrypoint from './__isograph/Query/meName/entrypoint';
|
44
|
+
import { meNameSuccessorRetainedQuery } from './meNameSuccessor';
|
45
|
+
iso(`entrypoint Query.meName`);
|
46
|
+
const meNameRetainedQuery = {
|
47
|
+
normalizationAst: meNameEntrypoint.normalizationAst,
|
48
|
+
variables: {},
|
49
|
+
};
|
50
|
+
|
51
|
+
describe('garbage collection', () => {
|
52
|
+
test('Unreferenced records should be garbage collected', () => {
|
53
|
+
const store = getDefaultStore();
|
54
|
+
const environment = createIsographEnvironment(
|
55
|
+
store,
|
56
|
+
null as any,
|
57
|
+
null as any,
|
58
|
+
);
|
59
|
+
|
60
|
+
expect(store[1]).not.toBe(undefined);
|
61
|
+
|
62
|
+
// TODO enable babel so we don't have to do this
|
63
|
+
retainQuery(environment, meNameRetainedQuery);
|
64
|
+
garbageCollectEnvironment(environment);
|
65
|
+
|
66
|
+
expect(store[1]).toBe(undefined);
|
67
|
+
});
|
68
|
+
|
69
|
+
test('Referenced records should not be garbage collected', () => {
|
70
|
+
const store = getDefaultStore();
|
71
|
+
const environment = createIsographEnvironment(
|
72
|
+
store,
|
73
|
+
null as any,
|
74
|
+
null as any,
|
75
|
+
);
|
76
|
+
|
77
|
+
expect(store[0]).not.toBe(undefined);
|
78
|
+
|
79
|
+
// TODO enable babel so we don't have to do this
|
80
|
+
retainQuery(environment, meNameRetainedQuery);
|
81
|
+
garbageCollectEnvironment(environment);
|
82
|
+
|
83
|
+
expect(store[0]).not.toBe(undefined);
|
84
|
+
});
|
85
|
+
|
86
|
+
test('Referenced records should not be garbage collected, and this should work with variables', () => {
|
87
|
+
const store = getDefaultStore();
|
88
|
+
const environment = createIsographEnvironment(
|
89
|
+
store,
|
90
|
+
null as any,
|
91
|
+
null as any,
|
92
|
+
);
|
93
|
+
|
94
|
+
expect(store[0]).not.toBe(undefined);
|
95
|
+
|
96
|
+
retainQuery(environment, nodeFieldRetainedQuery);
|
97
|
+
garbageCollectEnvironment(environment);
|
98
|
+
|
99
|
+
expect(store[0]).not.toBe(undefined);
|
100
|
+
});
|
101
|
+
|
102
|
+
test('Referenced records should not be garbage collected, and this should work through multiple levels', () => {
|
103
|
+
const store = getDefaultStore();
|
104
|
+
const environment = createIsographEnvironment(
|
105
|
+
store,
|
106
|
+
null as any,
|
107
|
+
null as any,
|
108
|
+
);
|
109
|
+
|
110
|
+
retainQuery(environment, meNameSuccessorRetainedQuery);
|
111
|
+
garbageCollectEnvironment(environment);
|
112
|
+
|
113
|
+
expect(store[0]).not.toBe(undefined);
|
114
|
+
expect(store[1]).not.toBe(undefined);
|
115
|
+
expect(store[2]).not.toBe(undefined);
|
116
|
+
});
|
117
|
+
|
118
|
+
test('ROOT_ID should not be garbage collected, even if there are no retained queries', () => {
|
119
|
+
const store = getDefaultStore();
|
120
|
+
const environment = createIsographEnvironment(
|
121
|
+
store,
|
122
|
+
null as any,
|
123
|
+
null as any,
|
124
|
+
);
|
125
|
+
garbageCollectEnvironment(environment);
|
126
|
+
|
127
|
+
expect(store[ROOT_ID]).not.toBe(undefined);
|
128
|
+
expect(store[0]).toBe(undefined);
|
129
|
+
});
|
130
|
+
});
|
@@ -0,0 +1,20 @@
|
|
1
|
+
import { iso } from './__isograph/iso';
|
2
|
+
|
3
|
+
export const meNameField = iso(`
|
4
|
+
field Query.meNameSuccessor {
|
5
|
+
me {
|
6
|
+
name
|
7
|
+
successor {
|
8
|
+
successor {
|
9
|
+
name
|
10
|
+
}
|
11
|
+
}
|
12
|
+
}
|
13
|
+
}
|
14
|
+
`)(() => {});
|
15
|
+
import meNameSuccessorEntrypoint from './__isograph/Query/meNameSuccessor/entrypoint';
|
16
|
+
iso(`entrypoint Query.meNameSuccessor`);
|
17
|
+
export const meNameSuccessorRetainedQuery = {
|
18
|
+
normalizationAst: meNameSuccessorEntrypoint.normalizationAst,
|
19
|
+
variables: {},
|
20
|
+
};
|
@@ -0,0 +1,17 @@
|
|
1
|
+
import { iso } from './__isograph/iso';
|
2
|
+
|
3
|
+
// TODO investigate why this can't be in garbageCollection.test.ts without
|
4
|
+
// typescript incorrectly thinking it is referenced in its own initializer
|
5
|
+
export const nodeField = iso(`
|
6
|
+
field Query.nodeField($id: ID!) {
|
7
|
+
node(id: $id) {
|
8
|
+
id
|
9
|
+
}
|
10
|
+
}
|
11
|
+
`)(() => {});
|
12
|
+
import nodeFieldEntrypoint from './__isograph/Query/nodeField/entrypoint';
|
13
|
+
iso(`entrypoint Query.nodeField`);
|
14
|
+
export const nodeFieldRetainedQuery = {
|
15
|
+
normalizationAst: nodeFieldEntrypoint.normalizationAst,
|
16
|
+
variables: { id: 0 },
|
17
|
+
};
|
@@ -0,0 +1,21 @@
|
|
1
|
+
{
|
2
|
+
"compilerOptions": {
|
3
|
+
"target": "es5",
|
4
|
+
"lib": ["dom", "dom.iterable", "esnext"],
|
5
|
+
"allowJs": true,
|
6
|
+
"skipLibCheck": true,
|
7
|
+
"strict": true,
|
8
|
+
"noEmit": true,
|
9
|
+
"esModuleInterop": true,
|
10
|
+
"module": "esnext",
|
11
|
+
"moduleResolution": "bundler",
|
12
|
+
"resolveJsonModule": true,
|
13
|
+
"isolatedModules": true,
|
14
|
+
"jsx": "preserve",
|
15
|
+
"incremental": true,
|
16
|
+
"allowImportingTsExtensions": true,
|
17
|
+
"paths": {
|
18
|
+
"@isograph/react": ["../index.ts"],
|
19
|
+
},
|
20
|
+
},
|
21
|
+
}
|
@@ -2,35 +2,26 @@ import {
|
|
2
2
|
UnassignedState,
|
3
3
|
useUpdatableDisposableState,
|
4
4
|
} from '@isograph/react-disposable-state';
|
5
|
-
import {
|
6
|
-
ExtractReadFromStore,
|
7
|
-
ExtractResolverResult,
|
8
|
-
IsographEntrypoint,
|
9
|
-
} from './entrypoint';
|
5
|
+
import { IsographEntrypoint } from './entrypoint';
|
10
6
|
import { FragmentReference } from './FragmentReference';
|
11
7
|
import { useIsographEnvironment } from './IsographEnvironmentProvider';
|
12
8
|
import { makeNetworkRequest } from './cache';
|
13
9
|
import { ROOT_ID } from './IsographEnvironment';
|
14
10
|
|
15
11
|
export function useImperativeReference<
|
16
|
-
|
12
|
+
TReadFromStore extends Object,
|
13
|
+
TClientFieldValue,
|
17
14
|
>(
|
18
|
-
entrypoint:
|
15
|
+
entrypoint: IsographEntrypoint<TReadFromStore, TClientFieldValue>,
|
19
16
|
): {
|
20
17
|
queryReference:
|
21
|
-
| FragmentReference<
|
22
|
-
ExtractReadFromStore<TEntrypoint>,
|
23
|
-
ExtractResolverResult<TEntrypoint>
|
24
|
-
>
|
18
|
+
| FragmentReference<TReadFromStore, TClientFieldValue>
|
25
19
|
| UnassignedState;
|
26
20
|
loadQueryReference: (variables: { [index: string]: string }) => void;
|
27
21
|
} {
|
28
22
|
const { state, setState } =
|
29
23
|
useUpdatableDisposableState<
|
30
|
-
FragmentReference<
|
31
|
-
ExtractReadFromStore<TEntrypoint>,
|
32
|
-
ExtractResolverResult<TEntrypoint>
|
33
|
-
>
|
24
|
+
FragmentReference<TReadFromStore, TClientFieldValue>
|
34
25
|
>();
|
35
26
|
const environment = useIsographEnvironment();
|
36
27
|
return {
|
package/src/useLazyReference.ts
CHANGED
@@ -1,50 +1,25 @@
|
|
1
1
|
import { FragmentReference, Variable } from './FragmentReference';
|
2
2
|
import { useIsographEnvironment } from './IsographEnvironmentProvider';
|
3
3
|
import { ROOT_ID } from './IsographEnvironment';
|
4
|
-
import {
|
5
|
-
ExtractReadFromStore,
|
6
|
-
ExtractResolverResult,
|
7
|
-
assertIsEntrypoint,
|
8
|
-
} from './entrypoint';
|
4
|
+
import { IsographEntrypoint } from './entrypoint';
|
9
5
|
import { getOrCreateCacheForArtifact } from './cache';
|
10
6
|
import { useLazyDisposableState } from '@isograph/react-disposable-state';
|
11
|
-
import { type PromiseWrapper } from './PromiseWrapper';
|
12
7
|
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
entrypoint:
|
19
|
-
| TEntrypoint
|
20
|
-
// Temporarily, we need to allow useLazyReference to take the result of calling
|
21
|
-
// iso(`...`). At runtime, we confirm that the passed-in `iso` literal is actually
|
22
|
-
// an entrypoint.
|
23
|
-
| ((_: any) => any),
|
8
|
+
export function useLazyReference<
|
9
|
+
TReadFromStore extends Object,
|
10
|
+
TClientFieldValue,
|
11
|
+
>(
|
12
|
+
entrypoint: IsographEntrypoint<TReadFromStore, TClientFieldValue>,
|
24
13
|
variables: { [key: string]: Variable },
|
25
14
|
): {
|
26
|
-
queryReference: FragmentReference<
|
27
|
-
ExtractReadFromStore<TEntrypoint>,
|
28
|
-
ExtractResolverResult<TEntrypoint>
|
29
|
-
>;
|
15
|
+
queryReference: FragmentReference<TReadFromStore, TClientFieldValue>;
|
30
16
|
} {
|
31
17
|
const environment = useIsographEnvironment();
|
32
|
-
|
33
|
-
ExtractReadFromStore<TEntrypoint>,
|
34
|
-
ExtractResolverResult<TEntrypoint>
|
35
|
-
>(entrypoint);
|
36
|
-
const cache = getOrCreateCacheForArtifact<ExtractResolverResult<TEntrypoint>>(
|
37
|
-
environment,
|
38
|
-
entrypoint,
|
39
|
-
variables,
|
40
|
-
);
|
18
|
+
const cache = getOrCreateCacheForArtifact(environment, entrypoint, variables);
|
41
19
|
|
42
20
|
// TODO add comment explaining why we never use this value
|
43
|
-
// @ts-ignore
|
44
|
-
const
|
45
|
-
useLazyDisposableState<PromiseWrapper<ExtractResolverResult<TEntrypoint>>>(
|
46
|
-
cache,
|
47
|
-
).state;
|
21
|
+
// @ts-ignore(6133)
|
22
|
+
const _data = useLazyDisposableState(cache).state;
|
48
23
|
|
49
24
|
return {
|
50
25
|
queryReference: {
|