/
simple.ts
107 lines (103 loc) · 2.95 KB
/
simple.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
import {
GraphQLSchema,
GraphQLObjectType,
GraphQLString,
GraphQLNonNull,
GraphQLSchemaConfig,
} from 'graphql';
// use for dispatching a `pong` to the `ping` subscription
const pendingPongs: Record<string, number | undefined> = {};
const pongListeners: Record<string, ((done: boolean) => void) | undefined> = {};
export function pong(key = 'global'): void {
if (pongListeners[key]) {
pongListeners[key]?.(false);
} else {
const pending = pendingPongs[key];
pendingPongs[key] = pending ? pending + 1 : 1;
}
}
export const schemaConfig: GraphQLSchemaConfig = {
query: new GraphQLObjectType({
name: 'Query',
fields: {
getValue: {
type: new GraphQLNonNull(GraphQLString),
resolve: () => 'value',
},
},
}),
subscription: new GraphQLObjectType({
name: 'Subscription',
fields: {
greetings: {
type: new GraphQLNonNull(GraphQLString),
subscribe: async function* () {
for (const hi of ['Hi', 'Bonjour', 'Hola', 'Ciao', 'Zdravo']) {
yield { greetings: hi };
}
},
},
ping: {
type: new GraphQLNonNull(GraphQLString),
args: {
key: {
type: GraphQLString,
},
},
subscribe: function (_src, args) {
const key = args.key ? args.key : 'global';
return {
[Symbol.asyncIterator]() {
return this;
},
async next() {
if ((pendingPongs[key] ?? 0) > 0) {
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
pendingPongs[key]!--;
return { value: { ping: 'pong' } };
}
if (
await new Promise((resolve) => (pongListeners[key] = resolve))
)
return { done: true };
return { value: { ping: 'pong' } };
},
async return() {
pongListeners[key]?.(true);
delete pongListeners[key];
return { done: true };
},
async throw() {
throw new Error('Ping no gusta');
},
};
},
},
lateReturn: {
type: new GraphQLNonNull(GraphQLString),
subscribe() {
let completed = () => {
// noop
};
return {
[Symbol.asyncIterator]() {
return this;
},
async next() {
await new Promise<void>((resolve) => (completed = resolve));
return { done: true };
},
return() {
completed();
// resolve return in next tick so that the generator loop breaks first
return new Promise((resolve) =>
setTimeout(() => resolve({ done: true }), 0),
);
},
};
},
},
},
}),
};
export const schema = new GraphQLSchema(schemaConfig);