@lenne.tech/nest-server 3.0.0 → 3.1.0
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/config.env.js +14 -1
- package/dist/config.env.js.map +1 -1
- package/dist/core/common/helpers/service.helper.js +2 -0
- package/dist/core/common/helpers/service.helper.js.map +1 -1
- package/dist/core/common/interfaces/mailjet-options.interface.d.ts +4 -0
- package/dist/core/common/interfaces/mailjet-options.interface.js +3 -0
- package/dist/core/common/interfaces/mailjet-options.interface.js.map +1 -0
- package/dist/core/common/interfaces/server-options.interface.d.ts +4 -0
- package/dist/core/common/services/mailjet.service.d.ts +15 -0
- package/dist/core/common/services/mailjet.service.js +64 -0
- package/dist/core/common/services/mailjet.service.js.map +1 -0
- package/dist/core/modules/user/core-user.model.d.ts +3 -0
- package/dist/core/modules/user/core-user.model.js +17 -0
- package/dist/core/modules/user/core-user.model.js.map +1 -1
- package/dist/core/modules/user/core-user.service.js +2 -0
- package/dist/core/modules/user/core-user.service.js.map +1 -1
- package/dist/core.module.js +3 -1
- package/dist/core.module.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/server/modules/user/user.resolver.d.ts +3 -0
- package/dist/server/modules/user/user.resolver.js +31 -0
- package/dist/server/modules/user/user.resolver.js.map +1 -1
- package/dist/server/modules/user/user.service.d.ts +3 -0
- package/dist/server/modules/user/user.service.js +44 -3
- package/dist/server/modules/user/user.service.js.map +1 -1
- package/dist/test/test.helper.js +1 -1
- package/dist/test/test.helper.js.map +1 -1
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/package.json +5 -1
- package/src/config.env.ts +14 -1
- package/src/core/common/helpers/service.helper.ts +6 -0
- package/src/core/common/interfaces/mailjet-options.interface.ts +4 -0
- package/src/core/common/interfaces/server-options.interface.ts +12 -0
- package/src/core/common/services/mailjet.service.ts +84 -0
- package/src/core/modules/user/core-user.model.ts +20 -0
- package/src/core/modules/user/core-user.service.ts +6 -0
- package/src/core.module.ts +3 -1
- package/src/index.ts +1 -0
- package/src/server/modules/user/user.resolver.ts +24 -0
- package/src/server/modules/user/user.service.ts +86 -4
- package/src/templates/password-reset.ejs +3 -0
- package/src/templates/welcome.ejs +3 -2
- package/src/test/test.helper.ts +2 -2
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lenne.tech/nest-server",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.1.0",
|
|
4
4
|
"description": "Modern, fast, powerful Node.js web framework in TypeScript based on Nest with a GraphQL API and a connection to MongoDB (or other databases).",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"node",
|
|
@@ -62,11 +62,13 @@
|
|
|
62
62
|
"@nestjs/passport": "8.1.0",
|
|
63
63
|
"@nestjs/platform-express": "8.2.6",
|
|
64
64
|
"@nestjs/testing": "8.2.6",
|
|
65
|
+
"@shelf/jest-mongodb": "2.2.0",
|
|
65
66
|
"@types/ejs": "3.1.0",
|
|
66
67
|
"@types/jest": "27.4.0",
|
|
67
68
|
"@types/lodash": "4.14.178",
|
|
68
69
|
"@types/multer": "1.4.7",
|
|
69
70
|
"@types/node": "16.11.21",
|
|
71
|
+
"@types/node-mailjet": "3.3.8",
|
|
70
72
|
"@types/nodemailer": "6.4.4",
|
|
71
73
|
"@types/passport": "1.0.7",
|
|
72
74
|
"@types/supertest": "2.0.11",
|
|
@@ -92,8 +94,10 @@
|
|
|
92
94
|
"json-to-graphql-query": "2.2.0",
|
|
93
95
|
"light-my-request": "4.7.0",
|
|
94
96
|
"lodash": "4.17.21",
|
|
97
|
+
"mongodb": "4.3.0",
|
|
95
98
|
"mongoose": "6.1.7",
|
|
96
99
|
"multer": "1.4.4",
|
|
100
|
+
"node-mailjet": "3.3.5",
|
|
97
101
|
"nodemailer": "6.7.2",
|
|
98
102
|
"nodemon": "2.0.15",
|
|
99
103
|
"passport": "0.5.2",
|
package/src/config.env.ts
CHANGED
|
@@ -19,10 +19,16 @@ const config: { [env: string]: IServerOptions } = {
|
|
|
19
19
|
port: 587,
|
|
20
20
|
secure: false,
|
|
21
21
|
},
|
|
22
|
+
mailjet: {
|
|
23
|
+
api_key_public: 'MAILJET_API_KEY_PUBLIC',
|
|
24
|
+
api_key_private: 'MAILJET_API_KEY_PRIVATE',
|
|
25
|
+
},
|
|
22
26
|
defaultSender: {
|
|
23
27
|
email: 'rebeca68@ethereal.email',
|
|
24
28
|
name: 'Rebeca Sixtyeight',
|
|
25
29
|
},
|
|
30
|
+
verificationLink: 'http://localhost:4200/user/verification',
|
|
31
|
+
passwordResetLink: 'http://localhost:4200/user/password-reset',
|
|
26
32
|
},
|
|
27
33
|
env: 'development',
|
|
28
34
|
graphQl: {
|
|
@@ -60,10 +66,16 @@ const config: { [env: string]: IServerOptions } = {
|
|
|
60
66
|
port: 587,
|
|
61
67
|
secure: false,
|
|
62
68
|
},
|
|
69
|
+
mailjet: {
|
|
70
|
+
api_key_public: 'MAILJET_API_KEY_PUBLIC',
|
|
71
|
+
api_key_private: 'MAILJET_API_KEY_PRIVATE',
|
|
72
|
+
},
|
|
63
73
|
defaultSender: {
|
|
64
74
|
email: 'rebeca68@ethereal.email',
|
|
65
75
|
name: 'Rebeca Sixtyeight',
|
|
66
76
|
},
|
|
77
|
+
verificationLink: 'http://localhost:4200/user/verification',
|
|
78
|
+
passwordResetLink: 'http://localhost:4200/user/password-reset',
|
|
67
79
|
},
|
|
68
80
|
env: 'productive',
|
|
69
81
|
graphQl: {
|
|
@@ -93,7 +105,8 @@ const config: { [env: string]: IServerOptions } = {
|
|
|
93
105
|
*
|
|
94
106
|
* default: development
|
|
95
107
|
*/
|
|
96
|
-
const envConfig = config[process.env
|
|
108
|
+
const envConfig = config[process.env['NODE' + '_ENV'] || 'development'] || config.development;
|
|
109
|
+
console.log('Server starts in mode: ', process.env['NODE' + '_ENV'] || 'development');
|
|
97
110
|
|
|
98
111
|
/**
|
|
99
112
|
* Export envConfig as default
|
|
@@ -86,6 +86,12 @@ export class ServiceHelper {
|
|
|
86
86
|
// Remove password if exists
|
|
87
87
|
delete output.password;
|
|
88
88
|
|
|
89
|
+
// Remove verification token if exists
|
|
90
|
+
delete output.verificationToken;
|
|
91
|
+
|
|
92
|
+
// Remove password reset token if exists
|
|
93
|
+
delete output.passwordResetToken;
|
|
94
|
+
|
|
89
95
|
// Return prepared user
|
|
90
96
|
return output;
|
|
91
97
|
}
|
|
@@ -3,6 +3,7 @@ import { JwtModuleOptions } from '@nestjs/jwt';
|
|
|
3
3
|
import { ServeStaticOptions } from '@nestjs/platform-express/interfaces/serve-static-options.interface';
|
|
4
4
|
import * as SMTPTransport from 'nodemailer/lib/smtp-transport';
|
|
5
5
|
import { MongooseModuleOptions } from '@nestjs/mongoose/dist/interfaces/mongoose-options.interface';
|
|
6
|
+
import { MailjetOptions } from './mailjet-options.interface';
|
|
6
7
|
|
|
7
8
|
/**
|
|
8
9
|
* Options for the server
|
|
@@ -101,6 +102,17 @@ export interface IServerOptions {
|
|
|
101
102
|
*/
|
|
102
103
|
smtp?: SMTPTransport | SMTPTransport.Options | string;
|
|
103
104
|
|
|
105
|
+
mailjet?: MailjetOptions;
|
|
106
|
+
/**
|
|
107
|
+
* Verification link for email
|
|
108
|
+
*/
|
|
109
|
+
verificationLink?: string;
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Password reset link for email
|
|
113
|
+
*/
|
|
114
|
+
passwordResetLink?: string;
|
|
115
|
+
|
|
104
116
|
/**
|
|
105
117
|
* Data for default sender
|
|
106
118
|
*/
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { Injectable } from '@nestjs/common';
|
|
2
|
+
import { ConfigService } from './config.service';
|
|
3
|
+
import * as mailjet from 'node-mailjet';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Mailjet service
|
|
7
|
+
*/
|
|
8
|
+
@Injectable()
|
|
9
|
+
export class MailjetService {
|
|
10
|
+
/**
|
|
11
|
+
* Inject services
|
|
12
|
+
*/
|
|
13
|
+
constructor(protected configService: ConfigService) {}
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Send a mail
|
|
17
|
+
*/
|
|
18
|
+
public async sendMail(
|
|
19
|
+
recipients: string | string[],
|
|
20
|
+
subject: string,
|
|
21
|
+
templateId: number,
|
|
22
|
+
config: {
|
|
23
|
+
senderEmail?: string;
|
|
24
|
+
senderName?: string;
|
|
25
|
+
attachments?: mailjet.Email.Attachment[];
|
|
26
|
+
templateData?: { [key: string]: any };
|
|
27
|
+
sandbox?: boolean;
|
|
28
|
+
}
|
|
29
|
+
): Promise<mailjet.Email.PostResponse> {
|
|
30
|
+
// Process config
|
|
31
|
+
const { senderName, senderEmail, templateData, attachments, sandbox } = {
|
|
32
|
+
senderEmail: this.configService.get('email.defaultSender.email'),
|
|
33
|
+
senderName: this.configService.get('email.defaultSender.name'),
|
|
34
|
+
sandbox: false,
|
|
35
|
+
attachments: null,
|
|
36
|
+
templateData: null,
|
|
37
|
+
...config,
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
// Parse recipients
|
|
41
|
+
let to;
|
|
42
|
+
if (Array.isArray(recipients)) {
|
|
43
|
+
to = [];
|
|
44
|
+
for (const recipient of recipients) {
|
|
45
|
+
to.push({ Email: recipient });
|
|
46
|
+
}
|
|
47
|
+
} else {
|
|
48
|
+
to = [{ Email: recipients }];
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// Parse body for mailjet request
|
|
52
|
+
const body: mailjet.Email.SendParams = {
|
|
53
|
+
Messages: [
|
|
54
|
+
{
|
|
55
|
+
From: {
|
|
56
|
+
Email: senderEmail,
|
|
57
|
+
Name: senderName,
|
|
58
|
+
},
|
|
59
|
+
To: to,
|
|
60
|
+
TemplateID: templateId,
|
|
61
|
+
TemplateLanguage: true,
|
|
62
|
+
Variables: templateData,
|
|
63
|
+
Subject: subject,
|
|
64
|
+
Attachments: attachments,
|
|
65
|
+
},
|
|
66
|
+
],
|
|
67
|
+
SandboxMode: sandbox,
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
let connection: mailjet.Email.Client;
|
|
71
|
+
try {
|
|
72
|
+
// Connect to mailjet
|
|
73
|
+
connection = await mailjet.connect(
|
|
74
|
+
this.configService.get('email.mailjet.api_key_public'),
|
|
75
|
+
this.configService.get('email.mailjet.api_key_private')
|
|
76
|
+
);
|
|
77
|
+
} catch (e) {
|
|
78
|
+
throw new Error('Cannot connect to mailjet.');
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// Send mail with mailjet
|
|
82
|
+
return connection.post('send', { version: 'v3.1' }).request(body);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
@@ -59,6 +59,26 @@ export abstract class CoreUserModel extends CorePersistenceModel {
|
|
|
59
59
|
@Prop()
|
|
60
60
|
username: string = undefined;
|
|
61
61
|
|
|
62
|
+
/**
|
|
63
|
+
* Password reset token of the user
|
|
64
|
+
*/
|
|
65
|
+
@IsOptional()
|
|
66
|
+
@Prop()
|
|
67
|
+
passwordResetToken: string = undefined;
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Verification token of the user
|
|
71
|
+
*/
|
|
72
|
+
@IsOptional()
|
|
73
|
+
@Prop()
|
|
74
|
+
verificationToken: string = undefined;
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Verification of the user
|
|
78
|
+
*/
|
|
79
|
+
@Prop({ type: Boolean })
|
|
80
|
+
verified = false;
|
|
81
|
+
|
|
62
82
|
// ===================================================================================================================
|
|
63
83
|
// Methods
|
|
64
84
|
// ===================================================================================================================
|
|
@@ -230,6 +230,12 @@ export abstract class CoreUserService<
|
|
|
230
230
|
// Remove password if exists
|
|
231
231
|
delete (user as any).password;
|
|
232
232
|
|
|
233
|
+
// Remove verification token if exists
|
|
234
|
+
delete (user as any).verificationToken;
|
|
235
|
+
|
|
236
|
+
// Remove password reset token if exists
|
|
237
|
+
delete (user as any).passwordResetToken;
|
|
238
|
+
|
|
233
239
|
// Return prepared user
|
|
234
240
|
return user;
|
|
235
241
|
}
|
package/src/core.module.ts
CHANGED
|
@@ -9,6 +9,7 @@ import { ConfigService } from './core/common/services/config.service';
|
|
|
9
9
|
import { EmailService } from './core/common/services/email.service';
|
|
10
10
|
import { TemplateService } from './core/common/services/template.service';
|
|
11
11
|
import { MongooseModule } from '@nestjs/mongoose';
|
|
12
|
+
import { MailjetService } from './core/common/services/mailjet.service';
|
|
12
13
|
|
|
13
14
|
/**
|
|
14
15
|
* Core module (dynamic)
|
|
@@ -91,6 +92,7 @@ export class CoreModule {
|
|
|
91
92
|
// Core Services
|
|
92
93
|
EmailService,
|
|
93
94
|
TemplateService,
|
|
95
|
+
MailjetService,
|
|
94
96
|
];
|
|
95
97
|
|
|
96
98
|
// Return dynamic module
|
|
@@ -101,7 +103,7 @@ export class CoreModule {
|
|
|
101
103
|
GraphQLModule.forRoot(config.graphQl),
|
|
102
104
|
],
|
|
103
105
|
providers,
|
|
104
|
-
exports: [ConfigService, EmailService, TemplateService],
|
|
106
|
+
exports: [ConfigService, EmailService, TemplateService, MailjetService],
|
|
105
107
|
};
|
|
106
108
|
}
|
|
107
109
|
}
|
package/src/index.ts
CHANGED
|
@@ -41,6 +41,7 @@ export * from './core/common/scalars/json.scalar';
|
|
|
41
41
|
export * from './core/common/services/config.service';
|
|
42
42
|
export * from './core/common/services/email.service';
|
|
43
43
|
export * from './core/common/services/template.service';
|
|
44
|
+
export * from './core/common/services/mailjet.service';
|
|
44
45
|
|
|
45
46
|
// =====================================================================================================================
|
|
46
47
|
// Core - Modules - Auth
|
|
@@ -43,6 +43,30 @@ export class UserResolver {
|
|
|
43
43
|
return await this.usersService.find(args, info);
|
|
44
44
|
}
|
|
45
45
|
|
|
46
|
+
/**
|
|
47
|
+
* Verify user with email
|
|
48
|
+
*/
|
|
49
|
+
@Query((returns) => Boolean, { description: 'Verify user with email' })
|
|
50
|
+
async verifyUser(@Args('token') token: string) {
|
|
51
|
+
return await this.usersService.verify(token);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Request new password for user with email
|
|
56
|
+
*/
|
|
57
|
+
@Query((returns) => Boolean, { description: 'Request new password for user with email' })
|
|
58
|
+
async requestPasswordResetMail(@Args('email') email: string) {
|
|
59
|
+
return await this.usersService.requestPasswordResetMail(email);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Set new password for user with token
|
|
64
|
+
*/
|
|
65
|
+
@Query((returns) => Boolean, { description: 'Set new password for user with token' })
|
|
66
|
+
async resetPassword(@Args('token') token: string, @Args('password') password: string) {
|
|
67
|
+
return await this.usersService.resetPassword(token, password);
|
|
68
|
+
}
|
|
69
|
+
|
|
46
70
|
// ===========================================================================
|
|
47
71
|
// Mutations
|
|
48
72
|
// ===========================================================================
|
|
@@ -1,4 +1,10 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
Inject,
|
|
3
|
+
Injectable,
|
|
4
|
+
NotFoundException,
|
|
5
|
+
UnauthorizedException,
|
|
6
|
+
UnprocessableEntityException,
|
|
7
|
+
} from '@nestjs/common';
|
|
2
8
|
import * as fs from 'fs';
|
|
3
9
|
import { GraphQLResolveInfo } from 'graphql';
|
|
4
10
|
import envConfig from '../../../config.env';
|
|
@@ -15,6 +21,8 @@ import { InjectModel } from '@nestjs/mongoose';
|
|
|
15
21
|
import { Model } from 'mongoose';
|
|
16
22
|
import { ICorePersistenceModel } from '../../../core/common/interfaces/core-persistence-model.interface';
|
|
17
23
|
import { PubSub } from 'graphql-subscriptions';
|
|
24
|
+
import * as crypto from 'crypto';
|
|
25
|
+
import * as bcrypt from 'bcrypt';
|
|
18
26
|
|
|
19
27
|
/**
|
|
20
28
|
* User service
|
|
@@ -55,17 +63,91 @@ export class UserService extends CoreUserService<User, UserInput, UserCreateInpu
|
|
|
55
63
|
*/
|
|
56
64
|
async create(input: UserCreateInput, currentUser?: User, ...args: any[]): Promise<User> {
|
|
57
65
|
const user = await super.create(input, currentUser);
|
|
58
|
-
|
|
66
|
+
|
|
67
|
+
await this.prepareOutput(user, args[0]);
|
|
68
|
+
|
|
59
69
|
await this.pubSub.publish('userCreated', User.map(user));
|
|
70
|
+
|
|
71
|
+
const verificationToken = crypto.randomBytes(32).toString('hex');
|
|
72
|
+
await this.userModel.findByIdAndUpdate(user.id, { $set: { verificationToken } }).exec();
|
|
73
|
+
|
|
60
74
|
await this.emailService.sendMail(user.email, 'Welcome', {
|
|
61
75
|
htmlTemplate: 'welcome',
|
|
62
|
-
templateData: user,
|
|
63
|
-
text,
|
|
76
|
+
templateData: { name: user.username, link: envConfig.email.verificationLink + '/' + verificationToken },
|
|
64
77
|
});
|
|
65
78
|
|
|
66
79
|
return user;
|
|
67
80
|
}
|
|
68
81
|
|
|
82
|
+
/**
|
|
83
|
+
* Verify user with token
|
|
84
|
+
*
|
|
85
|
+
* @param token
|
|
86
|
+
*/
|
|
87
|
+
async verify(token: string): Promise<boolean> {
|
|
88
|
+
const user = await this.userModel.findOne({ verificationToken: token }).exec();
|
|
89
|
+
|
|
90
|
+
if (!user) {
|
|
91
|
+
throw new NotFoundException();
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
if (!user.verificationToken) {
|
|
95
|
+
throw new Error('User has no token');
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
if (user.verified) {
|
|
99
|
+
throw new Error('User already verified');
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
await this.userModel.findByIdAndUpdate(user.id, { $set: { verified: true, verificationToken: null } }).exec();
|
|
103
|
+
|
|
104
|
+
return true;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Set newpassword for user with token
|
|
109
|
+
*
|
|
110
|
+
* @param token
|
|
111
|
+
* @param newPassword
|
|
112
|
+
*/
|
|
113
|
+
async resetPassword(token: string, newPassword: string): Promise<boolean> {
|
|
114
|
+
const user = await this.userModel.findOne({ passwordResetToken: token }).exec();
|
|
115
|
+
|
|
116
|
+
if (!user) {
|
|
117
|
+
throw new NotFoundException();
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
const cryptedPassword = await bcrypt.hash(newPassword, 10);
|
|
121
|
+
await this.userModel
|
|
122
|
+
.findByIdAndUpdate(user.id, { $set: { password: cryptedPassword, passwordResetToken: null } })
|
|
123
|
+
.exec();
|
|
124
|
+
|
|
125
|
+
return true;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* Request email with password reset link
|
|
130
|
+
*
|
|
131
|
+
* @param email
|
|
132
|
+
*/
|
|
133
|
+
async requestPasswordResetMail(email: string): Promise<boolean> {
|
|
134
|
+
const user = await this.userModel.findOne({ email }).exec();
|
|
135
|
+
|
|
136
|
+
if (!user) {
|
|
137
|
+
throw new NotFoundException();
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
const resetToken = crypto.randomBytes(32).toString('hex');
|
|
141
|
+
await this.userModel.findByIdAndUpdate(user.id, { $set: { passwordResetToken: resetToken } }).exec();
|
|
142
|
+
|
|
143
|
+
await this.emailService.sendMail(user.email, 'Password reset', {
|
|
144
|
+
htmlTemplate: 'password-reset',
|
|
145
|
+
templateData: { name: user.username, link: envConfig.email.passwordResetLink + '/' + resetToken },
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
return true;
|
|
149
|
+
}
|
|
150
|
+
|
|
69
151
|
/**
|
|
70
152
|
* Get users via filter
|
|
71
153
|
*/
|
|
@@ -1,2 +1,3 @@
|
|
|
1
|
-
<h1>Welcome <%=
|
|
2
|
-
<p>
|
|
1
|
+
<h1>Welcome <%= name %>,</h1>
|
|
2
|
+
<p>please confirm your email address.</p>
|
|
3
|
+
<a href="<%= link %>">E-Mail bestätigen</a>
|
package/src/test/test.helper.ts
CHANGED
|
@@ -113,7 +113,7 @@ export class TestHelper {
|
|
|
113
113
|
/**
|
|
114
114
|
* GraphQL request
|
|
115
115
|
* @param graphql
|
|
116
|
-
* @param
|
|
116
|
+
* @param options
|
|
117
117
|
*/
|
|
118
118
|
async graphQl(graphql: string | TestGraphQLConfig, options: TestGraphQLOptions = {}): Promise<any> {
|
|
119
119
|
// Default options
|
|
@@ -148,7 +148,7 @@ export class TestHelper {
|
|
|
148
148
|
graphql = Object.assign(
|
|
149
149
|
{
|
|
150
150
|
arguments: null,
|
|
151
|
-
fields: [
|
|
151
|
+
fields: [],
|
|
152
152
|
name: null,
|
|
153
153
|
type: TestGraphQLType.QUERY,
|
|
154
154
|
},
|