@graphql-yoga/nestjs 3.0.2 → 3.1.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/CHANGELOG.md +23 -0
- package/__tests__/graphql.spec.ts +79 -1
- package/dist/cjs/index.js +37 -2
- package/dist/esm/index.js +38 -3
- package/dist/package.json +2 -2
- package/dist/typings/index.d.cts +16 -6
- package/dist/typings/index.d.ts +16 -6
- package/package.json +3 -3
- package/src/index.ts +84 -11
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,28 @@
|
|
|
1
1
|
# @graphql-yoga/nestjs
|
|
2
2
|
|
|
3
|
+
## 3.1.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- Updated dependencies
|
|
8
|
+
[[`3ef877a7`](https://github.com/dotansimha/graphql-yoga/commit/3ef877a75c5b19e082121ece08981183422618f0)]:
|
|
9
|
+
- graphql-yoga@5.1.1
|
|
10
|
+
|
|
11
|
+
## 3.1.0
|
|
12
|
+
|
|
13
|
+
### Minor Changes
|
|
14
|
+
|
|
15
|
+
- [#2992](https://github.com/dotansimha/graphql-yoga/pull/2992)
|
|
16
|
+
[`b1f0e3a2`](https://github.com/dotansimha/graphql-yoga/commit/b1f0e3a2986956c6791a251df908e3f8b50ec966)
|
|
17
|
+
Thanks [@magrinj](https://github.com/magrinj)! - Adding support of conditionalSchema option.
|
|
18
|
+
(Currently without support for WebSocket subscriptions)
|
|
19
|
+
|
|
20
|
+
### Patch Changes
|
|
21
|
+
|
|
22
|
+
- Updated dependencies
|
|
23
|
+
[[`b1f0e3a2`](https://github.com/dotansimha/graphql-yoga/commit/b1f0e3a2986956c6791a251df908e3f8b50ec966)]:
|
|
24
|
+
- graphql-yoga@5.1.0
|
|
25
|
+
|
|
3
26
|
## 3.0.2
|
|
4
27
|
|
|
5
28
|
### Patch Changes
|
|
@@ -1,3 +1,11 @@
|
|
|
1
|
+
import {
|
|
2
|
+
GraphQLID,
|
|
3
|
+
GraphQLList,
|
|
4
|
+
GraphQLNonNull,
|
|
5
|
+
GraphQLObjectType,
|
|
6
|
+
GraphQLSchema,
|
|
7
|
+
GraphQLString,
|
|
8
|
+
} from 'graphql';
|
|
1
9
|
import { INestApplication } from '@nestjs/common';
|
|
2
10
|
import { Test } from '@nestjs/testing';
|
|
3
11
|
import { fetch } from '@whatwg-node/fetch';
|
|
@@ -7,7 +15,44 @@ let app: INestApplication, url: string;
|
|
|
7
15
|
|
|
8
16
|
beforeAll(async () => {
|
|
9
17
|
const module = await Test.createTestingModule({
|
|
10
|
-
imports: [
|
|
18
|
+
imports: [
|
|
19
|
+
AppModule.forRoot({
|
|
20
|
+
conditionalSchema: async () => {
|
|
21
|
+
const DogObjectType = new GraphQLObjectType({
|
|
22
|
+
name: 'Dog',
|
|
23
|
+
fields: {
|
|
24
|
+
id: {
|
|
25
|
+
type: new GraphQLNonNull(GraphQLID),
|
|
26
|
+
},
|
|
27
|
+
name: {
|
|
28
|
+
type: new GraphQLNonNull(GraphQLString),
|
|
29
|
+
},
|
|
30
|
+
breed: {
|
|
31
|
+
type: new GraphQLNonNull(GraphQLString),
|
|
32
|
+
},
|
|
33
|
+
},
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
return new GraphQLSchema({
|
|
37
|
+
query: new GraphQLObjectType({
|
|
38
|
+
name: 'Query',
|
|
39
|
+
fields: {
|
|
40
|
+
getDogs: {
|
|
41
|
+
type: new GraphQLList(new GraphQLNonNull(DogObjectType)),
|
|
42
|
+
resolve: () => [
|
|
43
|
+
{
|
|
44
|
+
id: '1',
|
|
45
|
+
name: 'Bingo',
|
|
46
|
+
breed: 'Dalmatian',
|
|
47
|
+
},
|
|
48
|
+
],
|
|
49
|
+
},
|
|
50
|
+
},
|
|
51
|
+
}),
|
|
52
|
+
});
|
|
53
|
+
},
|
|
54
|
+
}),
|
|
55
|
+
],
|
|
11
56
|
}).compile();
|
|
12
57
|
app = module.createNestApplication();
|
|
13
58
|
await app.listen(0);
|
|
@@ -48,3 +93,36 @@ it('should return query result', async () => {
|
|
|
48
93
|
}
|
|
49
94
|
`);
|
|
50
95
|
});
|
|
96
|
+
|
|
97
|
+
it('should return query result for conditional schema', async () => {
|
|
98
|
+
const res = await fetch(url, {
|
|
99
|
+
method: 'POST',
|
|
100
|
+
headers: {
|
|
101
|
+
'content-type': 'application/json',
|
|
102
|
+
},
|
|
103
|
+
body: JSON.stringify({
|
|
104
|
+
query: /* GraphQL */ `
|
|
105
|
+
{
|
|
106
|
+
getDogs {
|
|
107
|
+
id
|
|
108
|
+
name
|
|
109
|
+
breed
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
`,
|
|
113
|
+
}),
|
|
114
|
+
});
|
|
115
|
+
await expect(res.json()).resolves.toMatchInlineSnapshot(`
|
|
116
|
+
{
|
|
117
|
+
"data": {
|
|
118
|
+
"getDogs": [
|
|
119
|
+
{
|
|
120
|
+
"breed": "Dalmatian",
|
|
121
|
+
"id": "1",
|
|
122
|
+
"name": "Bingo",
|
|
123
|
+
},
|
|
124
|
+
],
|
|
125
|
+
},
|
|
126
|
+
}
|
|
127
|
+
`);
|
|
128
|
+
});
|
package/dist/cjs/index.js
CHANGED
|
@@ -28,7 +28,7 @@ class AbstractYogaDriver extends graphql_2.AbstractGraphQLDriver {
|
|
|
28
28
|
async stop() {
|
|
29
29
|
// noop
|
|
30
30
|
}
|
|
31
|
-
registerExpress(options, { preStartHook } = {}) {
|
|
31
|
+
registerExpress({ conditionalSchema, ...options }, { preStartHook } = {}) {
|
|
32
32
|
const app = this.httpAdapterHost.httpAdapter.getInstance();
|
|
33
33
|
preStartHook?.(app);
|
|
34
34
|
// nest's logger doesnt have the info method
|
|
@@ -41,8 +41,10 @@ class AbstractYogaDriver extends graphql_2.AbstractGraphQLDriver {
|
|
|
41
41
|
this.log(message, ...args);
|
|
42
42
|
}
|
|
43
43
|
}
|
|
44
|
+
const schema = this.mergeConditionalSchema(conditionalSchema, options.schema);
|
|
44
45
|
const yoga = (0, graphql_yoga_1.createYoga)({
|
|
45
46
|
...options,
|
|
47
|
+
schema,
|
|
46
48
|
graphqlEndpoint: options.path,
|
|
47
49
|
// disable logging by default
|
|
48
50
|
// however, if `true` use nest logger
|
|
@@ -55,11 +57,13 @@ class AbstractYogaDriver extends graphql_2.AbstractGraphQLDriver {
|
|
|
55
57
|
this.yoga = yoga;
|
|
56
58
|
app.use(yoga.graphqlEndpoint, (req, res) => yoga(req, res, { req, res }));
|
|
57
59
|
}
|
|
58
|
-
registerFastify(options, { preStartHook } = {}) {
|
|
60
|
+
registerFastify({ conditionalSchema, ...options }, { preStartHook } = {}) {
|
|
59
61
|
const app = this.httpAdapterHost.httpAdapter.getInstance();
|
|
60
62
|
preStartHook?.(app);
|
|
63
|
+
const schema = this.mergeConditionalSchema(conditionalSchema, options.schema);
|
|
61
64
|
const yoga = (0, graphql_yoga_1.createYoga)({
|
|
62
65
|
...options,
|
|
66
|
+
schema,
|
|
63
67
|
graphqlEndpoint: options.path,
|
|
64
68
|
// disable logging by default
|
|
65
69
|
// however, if `true` use fastify logger
|
|
@@ -78,6 +82,27 @@ class AbstractYogaDriver extends graphql_2.AbstractGraphQLDriver {
|
|
|
78
82
|
return reply;
|
|
79
83
|
});
|
|
80
84
|
}
|
|
85
|
+
mergeConditionalSchema(conditionalSchema, schema) {
|
|
86
|
+
let mergedSchema = schema;
|
|
87
|
+
if (conditionalSchema) {
|
|
88
|
+
mergedSchema = async (request) => {
|
|
89
|
+
const schemas = [];
|
|
90
|
+
if (schema) {
|
|
91
|
+
schemas.push(schema);
|
|
92
|
+
}
|
|
93
|
+
const conditionalSchemaResult = typeof conditionalSchema === 'function'
|
|
94
|
+
? await conditionalSchema(request)
|
|
95
|
+
: await conditionalSchema;
|
|
96
|
+
if (conditionalSchemaResult) {
|
|
97
|
+
schemas.push(conditionalSchemaResult);
|
|
98
|
+
}
|
|
99
|
+
return (0, graphql_yoga_1.mergeSchemas)({
|
|
100
|
+
schemas,
|
|
101
|
+
});
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
return mergedSchema;
|
|
105
|
+
}
|
|
81
106
|
subscriptionWithFilter(instanceRef, filterFn,
|
|
82
107
|
// disable next error, the original function in @nestjs/graphql is also untyped
|
|
83
108
|
// eslint-disable-next-line @typescript-eslint/ban-types
|
|
@@ -111,6 +136,11 @@ let YogaDriver = exports.YogaDriver = class YogaDriver extends AbstractYogaDrive
|
|
|
111
136
|
: options.subscriptions;
|
|
112
137
|
if (config['graphql-ws']) {
|
|
113
138
|
config['graphql-ws'] = typeof config['graphql-ws'] === 'object' ? config['graphql-ws'] : {};
|
|
139
|
+
if (options.conditionalSchema) {
|
|
140
|
+
throw new Error(`
|
|
141
|
+
Conditional schema is not supported with graphql-ws.
|
|
142
|
+
`);
|
|
143
|
+
}
|
|
114
144
|
config['graphql-ws'].onSubscribe = async (ctx, msg) => {
|
|
115
145
|
const { schema, execute, subscribe, contextFactory, parse, validate } = this.yoga.getEnveloped({
|
|
116
146
|
...ctx,
|
|
@@ -138,6 +168,11 @@ let YogaDriver = exports.YogaDriver = class YogaDriver extends AbstractYogaDrive
|
|
|
138
168
|
typeof config['subscriptions-transport-ws'] === 'object'
|
|
139
169
|
? config['subscriptions-transport-ws']
|
|
140
170
|
: {};
|
|
171
|
+
if (options.conditionalSchema) {
|
|
172
|
+
throw new Error(`
|
|
173
|
+
Conditional schema is not supported with subscriptions-transport-ws.
|
|
174
|
+
`);
|
|
175
|
+
}
|
|
141
176
|
config['subscriptions-transport-ws'].onOperation = async (_msg, params, ws) => {
|
|
142
177
|
const { schema, execute, subscribe, contextFactory, parse, validate } = this.yoga.getEnveloped({
|
|
143
178
|
...params.context,
|
package/dist/esm/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { __decorate } from "tslib";
|
|
2
2
|
import { printSchema } from 'graphql';
|
|
3
|
-
import { createYoga, filter, pipe } from 'graphql-yoga';
|
|
3
|
+
import { createYoga, filter, mergeSchemas, pipe, } from 'graphql-yoga';
|
|
4
4
|
import { Injectable, Logger } from '@nestjs/common';
|
|
5
5
|
import { AbstractGraphQLDriver, GqlSubscriptionService, } from '@nestjs/graphql';
|
|
6
6
|
export class AbstractYogaDriver extends AbstractGraphQLDriver {
|
|
@@ -25,7 +25,7 @@ export class AbstractYogaDriver extends AbstractGraphQLDriver {
|
|
|
25
25
|
async stop() {
|
|
26
26
|
// noop
|
|
27
27
|
}
|
|
28
|
-
registerExpress(options, { preStartHook } = {}) {
|
|
28
|
+
registerExpress({ conditionalSchema, ...options }, { preStartHook } = {}) {
|
|
29
29
|
const app = this.httpAdapterHost.httpAdapter.getInstance();
|
|
30
30
|
preStartHook?.(app);
|
|
31
31
|
// nest's logger doesnt have the info method
|
|
@@ -38,8 +38,10 @@ export class AbstractYogaDriver extends AbstractGraphQLDriver {
|
|
|
38
38
|
this.log(message, ...args);
|
|
39
39
|
}
|
|
40
40
|
}
|
|
41
|
+
const schema = this.mergeConditionalSchema(conditionalSchema, options.schema);
|
|
41
42
|
const yoga = createYoga({
|
|
42
43
|
...options,
|
|
44
|
+
schema,
|
|
43
45
|
graphqlEndpoint: options.path,
|
|
44
46
|
// disable logging by default
|
|
45
47
|
// however, if `true` use nest logger
|
|
@@ -52,11 +54,13 @@ export class AbstractYogaDriver extends AbstractGraphQLDriver {
|
|
|
52
54
|
this.yoga = yoga;
|
|
53
55
|
app.use(yoga.graphqlEndpoint, (req, res) => yoga(req, res, { req, res }));
|
|
54
56
|
}
|
|
55
|
-
registerFastify(options, { preStartHook } = {}) {
|
|
57
|
+
registerFastify({ conditionalSchema, ...options }, { preStartHook } = {}) {
|
|
56
58
|
const app = this.httpAdapterHost.httpAdapter.getInstance();
|
|
57
59
|
preStartHook?.(app);
|
|
60
|
+
const schema = this.mergeConditionalSchema(conditionalSchema, options.schema);
|
|
58
61
|
const yoga = createYoga({
|
|
59
62
|
...options,
|
|
63
|
+
schema,
|
|
60
64
|
graphqlEndpoint: options.path,
|
|
61
65
|
// disable logging by default
|
|
62
66
|
// however, if `true` use fastify logger
|
|
@@ -75,6 +79,27 @@ export class AbstractYogaDriver extends AbstractGraphQLDriver {
|
|
|
75
79
|
return reply;
|
|
76
80
|
});
|
|
77
81
|
}
|
|
82
|
+
mergeConditionalSchema(conditionalSchema, schema) {
|
|
83
|
+
let mergedSchema = schema;
|
|
84
|
+
if (conditionalSchema) {
|
|
85
|
+
mergedSchema = async (request) => {
|
|
86
|
+
const schemas = [];
|
|
87
|
+
if (schema) {
|
|
88
|
+
schemas.push(schema);
|
|
89
|
+
}
|
|
90
|
+
const conditionalSchemaResult = typeof conditionalSchema === 'function'
|
|
91
|
+
? await conditionalSchema(request)
|
|
92
|
+
: await conditionalSchema;
|
|
93
|
+
if (conditionalSchemaResult) {
|
|
94
|
+
schemas.push(conditionalSchemaResult);
|
|
95
|
+
}
|
|
96
|
+
return mergeSchemas({
|
|
97
|
+
schemas,
|
|
98
|
+
});
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
return mergedSchema;
|
|
102
|
+
}
|
|
78
103
|
subscriptionWithFilter(instanceRef, filterFn,
|
|
79
104
|
// disable next error, the original function in @nestjs/graphql is also untyped
|
|
80
105
|
// eslint-disable-next-line @typescript-eslint/ban-types
|
|
@@ -107,6 +132,11 @@ export let YogaDriver = class YogaDriver extends AbstractYogaDriver {
|
|
|
107
132
|
: options.subscriptions;
|
|
108
133
|
if (config['graphql-ws']) {
|
|
109
134
|
config['graphql-ws'] = typeof config['graphql-ws'] === 'object' ? config['graphql-ws'] : {};
|
|
135
|
+
if (options.conditionalSchema) {
|
|
136
|
+
throw new Error(`
|
|
137
|
+
Conditional schema is not supported with graphql-ws.
|
|
138
|
+
`);
|
|
139
|
+
}
|
|
110
140
|
config['graphql-ws'].onSubscribe = async (ctx, msg) => {
|
|
111
141
|
const { schema, execute, subscribe, contextFactory, parse, validate } = this.yoga.getEnveloped({
|
|
112
142
|
...ctx,
|
|
@@ -134,6 +164,11 @@ export let YogaDriver = class YogaDriver extends AbstractYogaDriver {
|
|
|
134
164
|
typeof config['subscriptions-transport-ws'] === 'object'
|
|
135
165
|
? config['subscriptions-transport-ws']
|
|
136
166
|
: {};
|
|
167
|
+
if (options.conditionalSchema) {
|
|
168
|
+
throw new Error(`
|
|
169
|
+
Conditional schema is not supported with subscriptions-transport-ws.
|
|
170
|
+
`);
|
|
171
|
+
}
|
|
137
172
|
config['subscriptions-transport-ws'].onOperation = async (_msg, params, ws) => {
|
|
138
173
|
const { schema, execute, subscribe, contextFactory, parse, validate } = this.yoga.getEnveloped({
|
|
139
174
|
...params.context,
|
package/dist/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@graphql-yoga/nestjs",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.1.1",
|
|
4
4
|
"description": "GraphQL Yoga driver for NestJS GraphQL.",
|
|
5
5
|
"sideEffects": false,
|
|
6
6
|
"peerDependencies": {
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
"@nestjs/core": "^10.0.0",
|
|
9
9
|
"@nestjs/graphql": "^12.0.0",
|
|
10
10
|
"graphql": "^15.0.0 || ^16.0.0",
|
|
11
|
-
"graphql-yoga": "^5.
|
|
11
|
+
"graphql-yoga": "^5.1.1"
|
|
12
12
|
},
|
|
13
13
|
"repository": {
|
|
14
14
|
"type": "git",
|
package/dist/typings/index.d.cts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { Express, Request as ExpressRequest, Response as ExpressResponse } from 'express';
|
|
2
2
|
import type { FastifyInstance, FastifyReply, FastifyRequest } from 'fastify';
|
|
3
|
-
import { YogaServerInstance, YogaServerOptions } from 'graphql-yoga';
|
|
3
|
+
import { YogaSchemaDefinition, YogaServerInstance, YogaServerOptions } from 'graphql-yoga';
|
|
4
4
|
import { AbstractGraphQLDriver, GqlModuleOptions, SubscriptionConfig } from '@nestjs/graphql';
|
|
5
5
|
export type YogaDriverPlatform = 'express' | 'fastify';
|
|
6
6
|
export type YogaDriverServerContext<Platform extends YogaDriverPlatform> = Platform extends 'fastify' ? {
|
|
@@ -10,14 +10,23 @@ export type YogaDriverServerContext<Platform extends YogaDriverPlatform> = Platf
|
|
|
10
10
|
req: ExpressRequest;
|
|
11
11
|
res: ExpressResponse;
|
|
12
12
|
};
|
|
13
|
-
export type YogaDriverServerOptions<Platform extends YogaDriverPlatform> = Omit<YogaServerOptions<YogaDriverServerContext<Platform>, never>, 'context' | 'schema'
|
|
13
|
+
export type YogaDriverServerOptions<Platform extends YogaDriverPlatform> = Omit<YogaServerOptions<YogaDriverServerContext<Platform>, never>, 'context' | 'schema'> & {
|
|
14
|
+
conditionalSchema?: YogaSchemaDefinition<YogaDriverServerContext<Platform>, never> | undefined;
|
|
15
|
+
};
|
|
14
16
|
export type YogaDriverServerInstance<Platform extends YogaDriverPlatform> = YogaServerInstance<YogaDriverServerContext<Platform>, never>;
|
|
15
|
-
export type YogaDriverConfig<Platform extends YogaDriverPlatform = 'express'> = GqlModuleOptions & YogaDriverServerOptions<Platform> & {
|
|
17
|
+
export type YogaDriverConfig<Platform extends YogaDriverPlatform = 'express'> = GqlModuleOptions & YogaDriverServerOptions<Platform> & ({
|
|
16
18
|
/**
|
|
17
19
|
* Subscriptions configuration. Passing `true` will install only `graphql-ws`.
|
|
18
20
|
*/
|
|
19
21
|
subscriptions?: boolean | YogaDriverSubscriptionConfig;
|
|
20
|
-
|
|
22
|
+
conditionalSchema?: never;
|
|
23
|
+
} | {
|
|
24
|
+
/**
|
|
25
|
+
* TODO: Support conditional schema with subscriptions
|
|
26
|
+
*/
|
|
27
|
+
subscriptions?: never;
|
|
28
|
+
conditionalSchema?: YogaSchemaDefinition<YogaDriverServerContext<Platform>, never> | undefined;
|
|
29
|
+
});
|
|
21
30
|
export type YogaDriverSubscriptionConfig = {
|
|
22
31
|
'graphql-ws'?: Omit<SubscriptionConfig['graphql-ws'], 'onSubscribe'>;
|
|
23
32
|
'subscriptions-transport-ws'?: Omit<SubscriptionConfig['subscriptions-transport-ws'], 'onOperation'>;
|
|
@@ -26,12 +35,13 @@ export declare abstract class AbstractYogaDriver<Platform extends YogaDriverPlat
|
|
|
26
35
|
protected yoga: YogaDriverServerInstance<Platform>;
|
|
27
36
|
start(options: YogaDriverConfig<Platform>): Promise<void>;
|
|
28
37
|
stop(): Promise<void>;
|
|
29
|
-
protected registerExpress(options: YogaDriverConfig<'express'>, { preStartHook }?: {
|
|
38
|
+
protected registerExpress({ conditionalSchema, ...options }: YogaDriverConfig<'express'>, { preStartHook }?: {
|
|
30
39
|
preStartHook?: (app: Express) => void;
|
|
31
40
|
}): void;
|
|
32
|
-
protected registerFastify(options: YogaDriverConfig<'fastify'>, { preStartHook }?: {
|
|
41
|
+
protected registerFastify({ conditionalSchema, ...options }: YogaDriverConfig<'fastify'>, { preStartHook }?: {
|
|
33
42
|
preStartHook?: (app: FastifyInstance) => void;
|
|
34
43
|
}): void;
|
|
44
|
+
private mergeConditionalSchema;
|
|
35
45
|
subscriptionWithFilter<TPayload, TVariables, TContext>(instanceRef: unknown, filterFn: (payload: TPayload, variables: TVariables, context: TContext) => boolean | Promise<boolean>, createSubscribeContext: Function): (args_0: TPayload, args_1: TVariables, args_2: TContext) => Promise<import("graphql-yoga").Repeater<TPayload, void, unknown>>;
|
|
36
46
|
}
|
|
37
47
|
export declare class YogaDriver<Platform extends YogaDriverPlatform = 'express'> extends AbstractYogaDriver<Platform> {
|
package/dist/typings/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { Express, Request as ExpressRequest, Response as ExpressResponse } from 'express';
|
|
2
2
|
import type { FastifyInstance, FastifyReply, FastifyRequest } from 'fastify';
|
|
3
|
-
import { YogaServerInstance, YogaServerOptions } from 'graphql-yoga';
|
|
3
|
+
import { YogaSchemaDefinition, YogaServerInstance, YogaServerOptions } from 'graphql-yoga';
|
|
4
4
|
import { AbstractGraphQLDriver, GqlModuleOptions, SubscriptionConfig } from '@nestjs/graphql';
|
|
5
5
|
export type YogaDriverPlatform = 'express' | 'fastify';
|
|
6
6
|
export type YogaDriverServerContext<Platform extends YogaDriverPlatform> = Platform extends 'fastify' ? {
|
|
@@ -10,14 +10,23 @@ export type YogaDriverServerContext<Platform extends YogaDriverPlatform> = Platf
|
|
|
10
10
|
req: ExpressRequest;
|
|
11
11
|
res: ExpressResponse;
|
|
12
12
|
};
|
|
13
|
-
export type YogaDriverServerOptions<Platform extends YogaDriverPlatform> = Omit<YogaServerOptions<YogaDriverServerContext<Platform>, never>, 'context' | 'schema'
|
|
13
|
+
export type YogaDriverServerOptions<Platform extends YogaDriverPlatform> = Omit<YogaServerOptions<YogaDriverServerContext<Platform>, never>, 'context' | 'schema'> & {
|
|
14
|
+
conditionalSchema?: YogaSchemaDefinition<YogaDriverServerContext<Platform>, never> | undefined;
|
|
15
|
+
};
|
|
14
16
|
export type YogaDriverServerInstance<Platform extends YogaDriverPlatform> = YogaServerInstance<YogaDriverServerContext<Platform>, never>;
|
|
15
|
-
export type YogaDriverConfig<Platform extends YogaDriverPlatform = 'express'> = GqlModuleOptions & YogaDriverServerOptions<Platform> & {
|
|
17
|
+
export type YogaDriverConfig<Platform extends YogaDriverPlatform = 'express'> = GqlModuleOptions & YogaDriverServerOptions<Platform> & ({
|
|
16
18
|
/**
|
|
17
19
|
* Subscriptions configuration. Passing `true` will install only `graphql-ws`.
|
|
18
20
|
*/
|
|
19
21
|
subscriptions?: boolean | YogaDriverSubscriptionConfig;
|
|
20
|
-
|
|
22
|
+
conditionalSchema?: never;
|
|
23
|
+
} | {
|
|
24
|
+
/**
|
|
25
|
+
* TODO: Support conditional schema with subscriptions
|
|
26
|
+
*/
|
|
27
|
+
subscriptions?: never;
|
|
28
|
+
conditionalSchema?: YogaSchemaDefinition<YogaDriverServerContext<Platform>, never> | undefined;
|
|
29
|
+
});
|
|
21
30
|
export type YogaDriverSubscriptionConfig = {
|
|
22
31
|
'graphql-ws'?: Omit<SubscriptionConfig['graphql-ws'], 'onSubscribe'>;
|
|
23
32
|
'subscriptions-transport-ws'?: Omit<SubscriptionConfig['subscriptions-transport-ws'], 'onOperation'>;
|
|
@@ -26,12 +35,13 @@ export declare abstract class AbstractYogaDriver<Platform extends YogaDriverPlat
|
|
|
26
35
|
protected yoga: YogaDriverServerInstance<Platform>;
|
|
27
36
|
start(options: YogaDriverConfig<Platform>): Promise<void>;
|
|
28
37
|
stop(): Promise<void>;
|
|
29
|
-
protected registerExpress(options: YogaDriverConfig<'express'>, { preStartHook }?: {
|
|
38
|
+
protected registerExpress({ conditionalSchema, ...options }: YogaDriverConfig<'express'>, { preStartHook }?: {
|
|
30
39
|
preStartHook?: (app: Express) => void;
|
|
31
40
|
}): void;
|
|
32
|
-
protected registerFastify(options: YogaDriverConfig<'fastify'>, { preStartHook }?: {
|
|
41
|
+
protected registerFastify({ conditionalSchema, ...options }: YogaDriverConfig<'fastify'>, { preStartHook }?: {
|
|
33
42
|
preStartHook?: (app: FastifyInstance) => void;
|
|
34
43
|
}): void;
|
|
44
|
+
private mergeConditionalSchema;
|
|
35
45
|
subscriptionWithFilter<TPayload, TVariables, TContext>(instanceRef: unknown, filterFn: (payload: TPayload, variables: TVariables, context: TContext) => boolean | Promise<boolean>, createSubscribeContext: Function): (args_0: TPayload, args_1: TVariables, args_2: TContext) => Promise<import("graphql-yoga").Repeater<TPayload, void, unknown>>;
|
|
36
46
|
}
|
|
37
47
|
export declare class YogaDriver<Platform extends YogaDriverPlatform = 'express'> extends AbstractYogaDriver<Platform> {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@graphql-yoga/nestjs",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.1.1",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "GraphQL Yoga driver for NestJS GraphQL.",
|
|
6
6
|
"repository": {
|
|
@@ -46,7 +46,7 @@
|
|
|
46
46
|
"@nestjs/core": "^10.0.0",
|
|
47
47
|
"@nestjs/graphql": "^12.0.0",
|
|
48
48
|
"graphql": "^15.0.0 || ^16.0.0",
|
|
49
|
-
"graphql-yoga": "^5.
|
|
49
|
+
"graphql-yoga": "^5.1.1"
|
|
50
50
|
},
|
|
51
51
|
"devDependencies": {
|
|
52
52
|
"@nestjs/common": "^10.0.0",
|
|
@@ -66,7 +66,7 @@
|
|
|
66
66
|
"graphql": "^16.6.0",
|
|
67
67
|
"graphql-http": "^1.18.0",
|
|
68
68
|
"graphql-ws": "^5.11.3",
|
|
69
|
-
"graphql-yoga": "^5.
|
|
69
|
+
"graphql-yoga": "^5.1.1",
|
|
70
70
|
"prettier": "^3.0.0",
|
|
71
71
|
"reflect-metadata": "^0.1.13",
|
|
72
72
|
"rxjs": "^7.8.0",
|
package/src/index.ts
CHANGED
|
@@ -1,7 +1,15 @@
|
|
|
1
1
|
import type { Express, Request as ExpressRequest, Response as ExpressResponse } from 'express';
|
|
2
2
|
import type { FastifyInstance, FastifyReply, FastifyRequest } from 'fastify';
|
|
3
|
-
import { printSchema } from 'graphql';
|
|
4
|
-
import {
|
|
3
|
+
import { GraphQLSchema, printSchema } from 'graphql';
|
|
4
|
+
import {
|
|
5
|
+
createYoga,
|
|
6
|
+
filter,
|
|
7
|
+
mergeSchemas,
|
|
8
|
+
pipe,
|
|
9
|
+
YogaSchemaDefinition,
|
|
10
|
+
YogaServerInstance,
|
|
11
|
+
YogaServerOptions,
|
|
12
|
+
} from 'graphql-yoga';
|
|
5
13
|
import type { ExecutionParams } from 'subscriptions-transport-ws';
|
|
6
14
|
import { Injectable, Logger } from '@nestjs/common';
|
|
7
15
|
import {
|
|
@@ -27,7 +35,9 @@ export type YogaDriverServerContext<Platform extends YogaDriverPlatform> =
|
|
|
27
35
|
export type YogaDriverServerOptions<Platform extends YogaDriverPlatform> = Omit<
|
|
28
36
|
YogaServerOptions<YogaDriverServerContext<Platform>, never>,
|
|
29
37
|
'context' | 'schema'
|
|
30
|
-
|
|
38
|
+
> & {
|
|
39
|
+
conditionalSchema?: YogaSchemaDefinition<YogaDriverServerContext<Platform>, never> | undefined;
|
|
40
|
+
};
|
|
31
41
|
|
|
32
42
|
export type YogaDriverServerInstance<Platform extends YogaDriverPlatform> = YogaServerInstance<
|
|
33
43
|
YogaDriverServerContext<Platform>,
|
|
@@ -35,12 +45,25 @@ export type YogaDriverServerInstance<Platform extends YogaDriverPlatform> = Yoga
|
|
|
35
45
|
>;
|
|
36
46
|
|
|
37
47
|
export type YogaDriverConfig<Platform extends YogaDriverPlatform = 'express'> = GqlModuleOptions &
|
|
38
|
-
YogaDriverServerOptions<Platform> &
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
48
|
+
YogaDriverServerOptions<Platform> &
|
|
49
|
+
(
|
|
50
|
+
| {
|
|
51
|
+
/**
|
|
52
|
+
* Subscriptions configuration. Passing `true` will install only `graphql-ws`.
|
|
53
|
+
*/
|
|
54
|
+
subscriptions?: boolean | YogaDriverSubscriptionConfig;
|
|
55
|
+
conditionalSchema?: never;
|
|
56
|
+
}
|
|
57
|
+
| {
|
|
58
|
+
/**
|
|
59
|
+
* TODO: Support conditional schema with subscriptions
|
|
60
|
+
*/
|
|
61
|
+
subscriptions?: never;
|
|
62
|
+
conditionalSchema?:
|
|
63
|
+
| YogaSchemaDefinition<YogaDriverServerContext<Platform>, never>
|
|
64
|
+
| undefined;
|
|
65
|
+
}
|
|
66
|
+
);
|
|
44
67
|
|
|
45
68
|
export type YogaDriverSubscriptionConfig = {
|
|
46
69
|
'graphql-ws'?: Omit<SubscriptionConfig['graphql-ws'], 'onSubscribe'>;
|
|
@@ -78,7 +101,7 @@ export abstract class AbstractYogaDriver<
|
|
|
78
101
|
}
|
|
79
102
|
|
|
80
103
|
protected registerExpress(
|
|
81
|
-
options: YogaDriverConfig<'express'>,
|
|
104
|
+
{ conditionalSchema, ...options }: YogaDriverConfig<'express'>,
|
|
82
105
|
{ preStartHook }: { preStartHook?: (app: Express) => void } = {},
|
|
83
106
|
) {
|
|
84
107
|
const app: Express = this.httpAdapterHost.httpAdapter.getInstance();
|
|
@@ -96,8 +119,11 @@ export abstract class AbstractYogaDriver<
|
|
|
96
119
|
}
|
|
97
120
|
}
|
|
98
121
|
|
|
122
|
+
const schema = this.mergeConditionalSchema<'express'>(conditionalSchema, options.schema);
|
|
123
|
+
|
|
99
124
|
const yoga = createYoga<YogaDriverServerContext<'express'>>({
|
|
100
125
|
...options,
|
|
126
|
+
schema,
|
|
101
127
|
graphqlEndpoint: options.path,
|
|
102
128
|
// disable logging by default
|
|
103
129
|
// however, if `true` use nest logger
|
|
@@ -115,15 +141,18 @@ export abstract class AbstractYogaDriver<
|
|
|
115
141
|
}
|
|
116
142
|
|
|
117
143
|
protected registerFastify(
|
|
118
|
-
options: YogaDriverConfig<'fastify'>,
|
|
144
|
+
{ conditionalSchema, ...options }: YogaDriverConfig<'fastify'>,
|
|
119
145
|
{ preStartHook }: { preStartHook?: (app: FastifyInstance) => void } = {},
|
|
120
146
|
) {
|
|
121
147
|
const app: FastifyInstance = this.httpAdapterHost.httpAdapter.getInstance();
|
|
122
148
|
|
|
123
149
|
preStartHook?.(app);
|
|
124
150
|
|
|
151
|
+
const schema = this.mergeConditionalSchema<'fastify'>(conditionalSchema, options.schema);
|
|
152
|
+
|
|
125
153
|
const yoga = createYoga<YogaDriverServerContext<'fastify'>>({
|
|
126
154
|
...options,
|
|
155
|
+
schema,
|
|
127
156
|
graphqlEndpoint: options.path,
|
|
128
157
|
// disable logging by default
|
|
129
158
|
// however, if `true` use fastify logger
|
|
@@ -144,6 +173,38 @@ export abstract class AbstractYogaDriver<
|
|
|
144
173
|
});
|
|
145
174
|
}
|
|
146
175
|
|
|
176
|
+
private mergeConditionalSchema<T extends YogaDriverPlatform>(
|
|
177
|
+
conditionalSchema: YogaSchemaDefinition<YogaDriverServerContext<T>, never> | undefined,
|
|
178
|
+
schema?: GraphQLSchema,
|
|
179
|
+
) {
|
|
180
|
+
let mergedSchema: YogaSchemaDefinition<YogaDriverServerContext<T>, never> | undefined = schema;
|
|
181
|
+
|
|
182
|
+
if (conditionalSchema) {
|
|
183
|
+
mergedSchema = async request => {
|
|
184
|
+
const schemas: GraphQLSchema[] = [];
|
|
185
|
+
|
|
186
|
+
if (schema) {
|
|
187
|
+
schemas.push(schema);
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
const conditionalSchemaResult =
|
|
191
|
+
typeof conditionalSchema === 'function'
|
|
192
|
+
? await conditionalSchema(request)
|
|
193
|
+
: await conditionalSchema;
|
|
194
|
+
|
|
195
|
+
if (conditionalSchemaResult) {
|
|
196
|
+
schemas.push(conditionalSchemaResult);
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
return mergeSchemas({
|
|
200
|
+
schemas,
|
|
201
|
+
});
|
|
202
|
+
};
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
return mergedSchema;
|
|
206
|
+
}
|
|
207
|
+
|
|
147
208
|
public subscriptionWithFilter<TPayload, TVariables, TContext>(
|
|
148
209
|
instanceRef: unknown,
|
|
149
210
|
filterFn: (
|
|
@@ -198,6 +259,12 @@ export class YogaDriver<
|
|
|
198
259
|
if (config['graphql-ws']) {
|
|
199
260
|
config['graphql-ws'] = typeof config['graphql-ws'] === 'object' ? config['graphql-ws'] : {};
|
|
200
261
|
|
|
262
|
+
if (options.conditionalSchema) {
|
|
263
|
+
throw new Error(`
|
|
264
|
+
Conditional schema is not supported with graphql-ws.
|
|
265
|
+
`);
|
|
266
|
+
}
|
|
267
|
+
|
|
201
268
|
config['graphql-ws'].onSubscribe = async (ctx, msg) => {
|
|
202
269
|
const { schema, execute, subscribe, contextFactory, parse, validate } =
|
|
203
270
|
this.yoga.getEnveloped({
|
|
@@ -229,6 +296,12 @@ export class YogaDriver<
|
|
|
229
296
|
? config['subscriptions-transport-ws']
|
|
230
297
|
: {};
|
|
231
298
|
|
|
299
|
+
if (options.conditionalSchema) {
|
|
300
|
+
throw new Error(`
|
|
301
|
+
Conditional schema is not supported with subscriptions-transport-ws.
|
|
302
|
+
`);
|
|
303
|
+
}
|
|
304
|
+
|
|
232
305
|
config['subscriptions-transport-ws'].onOperation = async (
|
|
233
306
|
_msg: unknown,
|
|
234
307
|
params: ExecutionParams,
|