Skip to content

Commit 5702b93

Browse files
committed
Document derived context
1 parent f9b80ae commit 5702b93

12 files changed

+476
-55
lines changed

src/Errors.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -607,3 +607,11 @@ export function noTypesDefined() {
607607
export function tsConfigNotFound(cwd: string) {
608608
return `Grats: Could not find \`tsconfig.json\` searching in ${cwd}.\n\nSee https://www.typescriptlang.org/download/ for instructors on how to add TypeScript to your project. Then run \`npx tsc --init\` to create a \`tsconfig.json\` file.`;
609609
}
610+
611+
export function cyclicDerivedContext() {
612+
return `Cyclic dependency detected in derived context. This derived context value depends upon itself.`;
613+
}
614+
615+
export function invalidDerivedContextArgType() {
616+
return "Invalid type for derived context function argument. Derived context functions may only accept other `@gqlContext` types as arguments.";
617+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
/** @gqlContext */
2+
type RootContext = {
3+
userName: string;
4+
};
5+
6+
type DerivedContext = {
7+
greeting: string;
8+
};
9+
10+
/** @gqlContext */
11+
export function createDerivedContext(
12+
ctx: RootContext,
13+
oops: DerivedContext,
14+
): DerivedContext {
15+
return { greeting: `Hello, ${ctx.userName}!` };
16+
}
17+
18+
/** @gqlType */
19+
type Query = unknown;
20+
21+
/** @gqlField */
22+
export function greeting(_: Query, ctx: DerivedContext): string {
23+
return ctx.greeting;
24+
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
-----------------
2+
INPUT
3+
-----------------
4+
/** @gqlContext */
5+
type RootContext = {
6+
userName: string;
7+
};
8+
9+
type DerivedContext = {
10+
greeting: string;
11+
};
12+
13+
/** @gqlContext */
14+
export function createDerivedContext(
15+
ctx: RootContext,
16+
oops: DerivedContext,
17+
): DerivedContext {
18+
return { greeting: `Hello, ${ctx.userName}!` };
19+
}
20+
21+
/** @gqlType */
22+
type Query = unknown;
23+
24+
/** @gqlField */
25+
export function greeting(_: Query, ctx: DerivedContext): string {
26+
return ctx.greeting;
27+
}
28+
29+
-----------------
30+
OUTPUT
31+
-----------------
32+
src/tests/fixtures/derived_context/cyclicContextDependency.invalid.ts:10:5 - error: Cyclic dependency detected in derived context. This derived context value depends upon itself.
33+
34+
10 /** @gqlContext */
35+
~~~~~~~~~~~~
36+
37+
src/tests/fixtures/derived_context/cyclicContextDependency.invalid.ts:13:3
38+
13 oops: DerivedContext,
39+
~~~~~~~~~~~~~~~~~~~~
40+
This derived context depends on itself
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
/** @gqlContext */
2+
type RootContext = {
3+
userName: string;
4+
};
5+
6+
type A = {
7+
greeting: string;
8+
};
9+
10+
/** @gqlContext */
11+
export function a(ctx: RootContext, b: B): A {
12+
return { greeting: `Hello, ${ctx.userName}!` };
13+
}
14+
15+
type B = {
16+
greeting: string;
17+
};
18+
19+
/** @gqlContext */
20+
export function b(ctx: RootContext, c: C): B {
21+
return { greeting: `Hello, ${ctx.userName}!` };
22+
}
23+
24+
type C = {
25+
greeting: string;
26+
};
27+
28+
/** @gqlContext */
29+
export function c(ctx: RootContext, a: A): C {
30+
return { greeting: `Hello, ${ctx.userName}!` };
31+
}
32+
33+
/** @gqlType */
34+
type Query = unknown;
35+
36+
/** @gqlField */
37+
export function greeting(_: Query, ctx: A): string {
38+
return ctx.greeting;
39+
}
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
-----------------
2+
INPUT
3+
-----------------
4+
/** @gqlContext */
5+
type RootContext = {
6+
userName: string;
7+
};
8+
9+
type A = {
10+
greeting: string;
11+
};
12+
13+
/** @gqlContext */
14+
export function a(ctx: RootContext, b: B): A {
15+
return { greeting: `Hello, ${ctx.userName}!` };
16+
}
17+
18+
type B = {
19+
greeting: string;
20+
};
21+
22+
/** @gqlContext */
23+
export function b(ctx: RootContext, c: C): B {
24+
return { greeting: `Hello, ${ctx.userName}!` };
25+
}
26+
27+
type C = {
28+
greeting: string;
29+
};
30+
31+
/** @gqlContext */
32+
export function c(ctx: RootContext, a: A): C {
33+
return { greeting: `Hello, ${ctx.userName}!` };
34+
}
35+
36+
/** @gqlType */
37+
type Query = unknown;
38+
39+
/** @gqlField */
40+
export function greeting(_: Query, ctx: A): string {
41+
return ctx.greeting;
42+
}
43+
44+
-----------------
45+
OUTPUT
46+
-----------------
47+
src/tests/fixtures/derived_context/cyclicContextDependencyWithChain.invalid.ts:10:5 - error: Cyclic dependency detected in derived context. This derived context value depends upon itself.
48+
49+
10 /** @gqlContext */
50+
~~~~~~~~~~~~
51+
52+
src/tests/fixtures/derived_context/cyclicContextDependencyWithChain.invalid.ts:11:37
53+
11 export function a(ctx: RootContext, b: B): A {
54+
~~~~
55+
This derived context depends on
56+
src/tests/fixtures/derived_context/cyclicContextDependencyWithChain.invalid.ts:20:37
57+
20 export function b(ctx: RootContext, c: C): B {
58+
~~~~
59+
Which in turn depends on
60+
src/tests/fixtures/derived_context/cyclicContextDependencyWithChain.invalid.ts:29:37
61+
29 export function c(ctx: RootContext, a: A): C {
62+
~~~~
63+
Which ultimately creates a cycle back to the initial derived context

src/tests/fixtures/derived_context/derivedContextChain.ts.expected

Lines changed: 34 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -51,38 +51,37 @@ export function consumingMultipleContexts(
5151
-----------------
5252
OUTPUT
5353
-----------------
54-
-- SDL --
55-
type Query {
56-
consumingMultipleContexts: String
57-
greeting: String
58-
}
59-
-- TypeScript --
60-
import { consumingMultipleContexts as queryConsumingMultipleContextsResolver, createDerivedContextA as createDerivedContextA, createDerivedContextB as createDerivedContextB, allTheContexts as allTheContexts, greeting as queryGreetingResolver } from "./derivedContextChain";
61-
import { GraphQLSchema, GraphQLObjectType, GraphQLString } from "graphql";
62-
export function getSchema(): GraphQLSchema {
63-
const QueryType: GraphQLObjectType = new GraphQLObjectType({
64-
name: "Query",
65-
fields() {
66-
return {
67-
consumingMultipleContexts: {
68-
name: "consumingMultipleContexts",
69-
type: GraphQLString,
70-
resolve(source, _args, context) {
71-
return queryConsumingMultipleContextsResolver(source, context, createDerivedContextA(context), createDerivedContextB(createDerivedContextA(context)), allTheContexts(context, createDerivedContextA(context), createDerivedContextB(createDerivedContextA(context))));
72-
}
73-
},
74-
greeting: {
75-
name: "greeting",
76-
type: GraphQLString,
77-
resolve(source) {
78-
return queryGreetingResolver(source, allTheContexts(context, createDerivedContextA(context), createDerivedContextB(createDerivedContextA(context))));
79-
}
80-
}
81-
};
82-
}
83-
});
84-
return new GraphQLSchema({
85-
query: QueryType,
86-
types: [QueryType]
87-
});
88-
}
54+
src/tests/fixtures/derived_context/derivedContextChain.ts:6:5 - error: Cyclic dependency detected in derived context. This derived context value depends upon itself.
55+
56+
6 /** @gqlContext */
57+
~~~~~~~~~~~~
58+
59+
src/tests/fixtures/derived_context/derivedContextChain.ts:23:3
60+
23 a: DerivedContextA,
61+
~~~~~~~~~~~~~~~~~~
62+
This derived context depends on
63+
src/tests/fixtures/derived_context/derivedContextChain.ts:24:3
64+
24 b: DerivedContextB,
65+
~~~~~~~~~~~~~~~~~~
66+
Which in turn depends on
67+
src/tests/fixtures/derived_context/derivedContextChain.ts:14:39
68+
14 export function createDerivedContextB(ctx: DerivedContextA): DerivedContextB {
69+
~~~~~~~~~~~~~~~~~~~~
70+
Which ultimately creates a cycle back to the initial derived context
71+
src/tests/fixtures/derived_context/derivedContextChain.ts:6:5 - error: Cyclic dependency detected in derived context. This derived context value depends upon itself.
72+
73+
6 /** @gqlContext */
74+
~~~~~~~~~~~~
75+
76+
src/tests/fixtures/derived_context/derivedContextChain.ts:23:3
77+
23 a: DerivedContextA,
78+
~~~~~~~~~~~~~~~~~~
79+
This derived context depends on
80+
src/tests/fixtures/derived_context/derivedContextChain.ts:24:3
81+
24 b: DerivedContextB,
82+
~~~~~~~~~~~~~~~~~~
83+
Which in turn depends on
84+
src/tests/fixtures/derived_context/derivedContextChain.ts:14:39
85+
14 export function createDerivedContextB(ctx: DerivedContextA): DerivedContextB {
86+
~~~~~~~~~~~~~~~~~~~~
87+
Which ultimately creates a cycle back to the initial derived context
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
/** @gqlContext */
2+
type RootContext = {
3+
userName: string;
4+
};
5+
6+
type DerivedContext = {
7+
greeting: string;
8+
};
9+
10+
/** @gqlContext */
11+
export function createDerivedContext(): DerivedContext {
12+
return { greeting: `Hello!` };
13+
}
14+
15+
/** @gqlType */
16+
type Query = unknown;
17+
18+
/** @gqlField */
19+
export function greeting(_: Query, ctx: DerivedContext): string {
20+
return ctx.greeting;
21+
}
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
-----------------
2+
INPUT
3+
-----------------
4+
/** @gqlContext */
5+
type RootContext = {
6+
userName: string;
7+
};
8+
9+
type DerivedContext = {
10+
greeting: string;
11+
};
12+
13+
/** @gqlContext */
14+
export function createDerivedContext(): DerivedContext {
15+
return { greeting: `Hello!` };
16+
}
17+
18+
/** @gqlType */
19+
type Query = unknown;
20+
21+
/** @gqlField */
22+
export function greeting(_: Query, ctx: DerivedContext): string {
23+
return ctx.greeting;
24+
}
25+
26+
-----------------
27+
OUTPUT
28+
-----------------
29+
-- SDL --
30+
type Query {
31+
greeting: String
32+
}
33+
-- TypeScript --
34+
import { greeting as queryGreetingResolver, createDerivedContext as createDerivedContext } from "./simpleDerivedContextNoArgs";
35+
import { GraphQLSchema, GraphQLObjectType, GraphQLString } from "graphql";
36+
export function getSchema(): GraphQLSchema {
37+
const QueryType: GraphQLObjectType = new GraphQLObjectType({
38+
name: "Query",
39+
fields() {
40+
return {
41+
greeting: {
42+
name: "greeting",
43+
type: GraphQLString,
44+
resolve(source) {
45+
return queryGreetingResolver(source, createDerivedContext());
46+
}
47+
}
48+
};
49+
}
50+
});
51+
return new GraphQLSchema({
52+
query: QueryType,
53+
types: [QueryType]
54+
});
55+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
/** @gqlContext */
2+
type RootContext = {
3+
userName: string;
4+
};
5+
6+
type DerivedContext = {
7+
greeting: string;
8+
};
9+
10+
/** @gqlContext */
11+
export function createDerivedContext(
12+
ctx: RootContext,
13+
oops: string,
14+
): DerivedContext {
15+
return { greeting: `Hello, ${ctx.userName}!` };
16+
}
17+
18+
/** @gqlType */
19+
type Query = unknown;
20+
21+
/** @gqlField */
22+
export function greeting(_: Query, ctx: DerivedContext): string {
23+
return ctx.greeting;
24+
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
-----------------
2+
INPUT
3+
-----------------
4+
/** @gqlContext */
5+
type RootContext = {
6+
userName: string;
7+
};
8+
9+
type DerivedContext = {
10+
greeting: string;
11+
};
12+
13+
/** @gqlContext */
14+
export function createDerivedContext(
15+
ctx: RootContext,
16+
oops: string,
17+
): DerivedContext {
18+
return { greeting: `Hello, ${ctx.userName}!` };
19+
}
20+
21+
/** @gqlType */
22+
type Query = unknown;
23+
24+
/** @gqlField */
25+
export function greeting(_: Query, ctx: DerivedContext): string {
26+
return ctx.greeting;
27+
}
28+
29+
-----------------
30+
OUTPUT
31+
-----------------
32+
src/tests/fixtures/derived_context/simpleDerivedContextReadsRandomType.invalid.ts:13:3 - error: Invalid type for derived context function argument. Derived context functions may only accept other `@gqlContext` types as arguments.
33+
34+
13 oops: string,
35+
~~~~~~~~~~~~

0 commit comments

Comments
 (0)