作者 陈志颖

feat:添加模块

@@ -2197,6 +2197,19 @@ @@ -2197,6 +2197,19 @@
2197 "uuid": "8.3.2" 2197 "uuid": "8.3.2"
2198 } 2198 }
2199 }, 2199 },
  2200 + "@nestjs/config": {
  2201 + "version": "0.6.3",
  2202 + "resolved": "https://registry.npmjs.org/@nestjs/config/-/config-0.6.3.tgz",
  2203 + "integrity": "sha512-JxvvUpmH0/WOrTB+zh8dEkxSUQXhB7V3d/qeQXyCnMiEFjaq89+fNFztpWjz4DlOfdS4/eYTzIEy9PH2uGnfzA==",
  2204 + "requires": {
  2205 + "dotenv": "8.2.0",
  2206 + "dotenv-expand": "5.1.0",
  2207 + "lodash.get": "4.4.2",
  2208 + "lodash.has": "4.5.2",
  2209 + "lodash.set": "4.3.2",
  2210 + "uuid": "8.3.2"
  2211 + }
  2212 + },
2200 "@nestjs/core": { 2213 "@nestjs/core": {
2201 "version": "7.6.12", 2214 "version": "7.6.12",
2202 "resolved": "https://registry.npmjs.org/@nestjs/core/-/core-7.6.12.tgz", 2215 "resolved": "https://registry.npmjs.org/@nestjs/core/-/core-7.6.12.tgz",
@@ -5354,6 +5367,16 @@ @@ -5354,6 +5367,16 @@
5354 } 5367 }
5355 } 5368 }
5356 }, 5369 },
  5370 + "dotenv": {
  5371 + "version": "8.2.0",
  5372 + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-8.2.0.tgz",
  5373 + "integrity": "sha512-8sJ78ElpbDJBHNeBzUbUVLsqKdccaa/BXF1uPTw3GrvQTBgrQrtObr2mUrE38vzYd8cEv+m/JBfDLioYcfXoaw=="
  5374 + },
  5375 + "dotenv-expand": {
  5376 + "version": "5.1.0",
  5377 + "resolved": "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-5.1.0.tgz",
  5378 + "integrity": "sha512-YXQl1DSa4/PQyRfgrv6aoNjhasp/p4qs9FjJ4q4cQk+8m4r6k4ZSiEyytKG8f8W9gi8WsQtIObNmKd+tMzNTmA=="
  5379 + },
5357 "ecc-jsbn": { 5380 "ecc-jsbn": {
5358 "version": "0.1.2", 5381 "version": "0.1.2",
5359 "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", 5382 "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz",
@@ -8041,6 +8064,21 @@ @@ -8041,6 +8064,21 @@
8041 "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz", 8064 "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz",
8042 "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==" 8065 "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA=="
8043 }, 8066 },
  8067 + "lodash.get": {
  8068 + "version": "4.4.2",
  8069 + "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz",
  8070 + "integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk="
  8071 + },
  8072 + "lodash.has": {
  8073 + "version": "4.5.2",
  8074 + "resolved": "https://registry.npmjs.org/lodash.has/-/lodash.has-4.5.2.tgz",
  8075 + "integrity": "sha1-0Z9NwQlQWMzL4rDN9O4P5Ko3yGI="
  8076 + },
  8077 + "lodash.set": {
  8078 + "version": "4.3.2",
  8079 + "resolved": "https://registry.npmjs.org/lodash.set/-/lodash.set-4.3.2.tgz",
  8080 + "integrity": "sha1-2HV7HagH3eJIFrDWqEvqGnYjCyM="
  8081 + },
8044 "lodash.sortby": { 8082 "lodash.sortby": {
8045 "version": "4.7.0", 8083 "version": "4.7.0",
8046 "resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz", 8084 "resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz",
@@ -8480,6 +8518,19 @@ @@ -8480,6 +8518,19 @@
8480 "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", 8518 "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==",
8481 "dev": true 8519 "dev": true
8482 }, 8520 },
  8521 + "nestjs-config": {
  8522 + "version": "1.4.7",
  8523 + "resolved": "https://registry.npmjs.org/nestjs-config/-/nestjs-config-1.4.7.tgz",
  8524 + "integrity": "sha512-lD/tW5UZ3J+awJSUOjjCjJ6QwXVoJBYuigDJONQj4FETxImPLeB30Brxgt6ZyGX8o3BvA5osDdNfYO2iKQUXRQ==",
  8525 + "requires": {
  8526 + "dotenv": "^8.0.0",
  8527 + "glob": "^7.1.2",
  8528 + "lodash.get": "^4.4.2",
  8529 + "lodash.set": "^4.3.2",
  8530 + "reflect-metadata": "^0.1.12",
  8531 + "rxjs": "^6.0.0"
  8532 + }
  8533 + },
8483 "nice-try": { 8534 "nice-try": {
8484 "version": "1.0.5", 8535 "version": "1.0.5",
8485 "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", 8536 "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz",
@@ -22,12 +22,14 @@ @@ -22,12 +22,14 @@
22 }, 22 },
23 "dependencies": { 23 "dependencies": {
24 "@nestjs/common": "^7.5.1", 24 "@nestjs/common": "^7.5.1",
  25 + "@nestjs/config": "^0.6.3",
25 "@nestjs/core": "^7.5.1", 26 "@nestjs/core": "^7.5.1",
26 "@nestjs/graphql": "^7.9.9", 27 "@nestjs/graphql": "^7.9.9",
27 "@nestjs/platform-express": "^7.5.1", 28 "@nestjs/platform-express": "^7.5.1",
28 "apollo-server-express": "^2.21.0", 29 "apollo-server-express": "^2.21.0",
29 "graphql": "^15.5.0", 30 "graphql": "^15.5.0",
30 "graphql-tools": "^7.0.4", 31 "graphql-tools": "^7.0.4",
  32 + "nestjs-config": "^1.4.7",
31 "reflect-metadata": "^0.1.13", 33 "reflect-metadata": "^0.1.13",
32 "rimraf": "^3.0.2", 34 "rimraf": "^3.0.2",
33 "rxjs": "^6.6.3" 35 "rxjs": "^6.6.3"
1 import { Module } from '@nestjs/common'; 1 import { Module } from '@nestjs/common';
2 -import { AppController } from './app.controller';  
3 -import { AppService } from './app.service'; 2 +import { GraphQLModule } from '@nestjs/graphql';
  3 +import { ConfigModule, ConfigService } from 'nestjs-config';
  4 +// import { AppController } from './app.controller';
  5 +// import { AppService } from './app.service';
  6 +import * as path from 'path';
4 7
5 @Module({ 8 @Module({
6 - imports: [],  
7 - controllers: [AppController],  
8 - providers: [AppService], 9 + imports: [
  10 + ConfigModule.load(path.resolve(__dirname, 'config', '**/!(*.d).{ts,js}')),
  11 + GraphQLModule.forRootAsync({
  12 + imports: [ConfigModule],
  13 + useFactory: (config: ConfigService) => config.get('graphql'),
  14 + inject: [ConfigService],
  15 + }),
  16 + ],
  17 + // controllers: [AppController],
  18 + // providers: [AppService],
9 }) 19 })
10 -export class AppModule {} 20 +// export class AppModule {}
  21 +export class ApplicationModule {}
  1 +import * as path from 'path';
  2 +
  3 +export default {
  4 + autoSchemaFile: path.join(process.cwd(), 'src/schema.gql'), // 最后生成`Schema 文件,不可修改`
  5 + installSubscriptionHandlers: true, // 启动订阅
  6 +};
  1 +import { ValidationPipe } from '@nestjs/common';
1 import { NestFactory } from '@nestjs/core'; 2 import { NestFactory } from '@nestjs/core';
2 -import { AppModule } from './app.module'; 3 +import { ApplicationModule } from './app.module';
3 4
4 async function bootstrap() { 5 async function bootstrap() {
5 - const app = await NestFactory.create(AppModule); 6 + const app = await NestFactory.create(ApplicationModule);
  7 + app.useGlobalPipes(new ValidationPipe());
  8 +
6 await app.listen(3000); 9 await app.listen(3000);
  10 + console.log(`Application is running on: ${await app.getUrl()}`);
7 } 11 }
8 bootstrap(); 12 bootstrap();
  1 +import { Module } from '@nestjs/common';
  2 +import { AuthorService } from './author.service';
  3 +import { AuthorResolver } from './author.resolver';
  4 +@Module({
  5 + providers: [AuthorService, AuthorResolver],
  6 +})
  7 +export class AuthorModule {}
  1 +import {
  2 + Args,
  3 + Mutation,
  4 + Query,
  5 + Resolver,
  6 + Subscription,
  7 + ResolveField,
  8 + Parent,
  9 + Int,
  10 +} from '@nestjs/graphql';
  11 +import { PubSub } from 'graphql-subscriptions';
  12 +import { Author } from './models/aothor.model';
  13 +import { Post } from './models/post.model';
  14 +import { AuthorService } from './author.service';
  15 +
  16 +const pubSub = new PubSub();
  17 +
  18 +@Resolver(() => Author)
  19 +export class AuthorResolver {
  20 + constructor(private authorsService: AuthorService) {}
  21 + // 根据id查询作者信息
  22 + @Query((returns) => Author, {
  23 + name: 'author',
  24 + description: 'get author info by id',
  25 + nullable: false,
  26 + })
  27 + async getAuthor(
  28 + @Args('id', {
  29 + type: () => Int,
  30 + description: 'author id',
  31 + nullable: false,
  32 + })
  33 + id: number,
  34 + ): Promise<any> {
  35 + return {
  36 + id,
  37 + firstName: 'wu',
  38 + lastName: 'pat',
  39 + };
  40 + }
  41 + // 修改作者信息
  42 + @Mutation((returns) => Author, {
  43 + name: 'changeAuthor',
  44 + description: 'change author info by id',
  45 + nullable: false,
  46 + })
  47 + async changeAuthor(
  48 + @Args('id') id: number,
  49 + @Args('firstName') firstName: string,
  50 + @Args('lastName') lastName: string,
  51 + ): Promise<any> {
  52 + return {
  53 + id,
  54 + firstName,
  55 + lastName,
  56 + };
  57 + }
  58 + // 解析posts字段
  59 + @ResolveField()
  60 + async posts(@Parent() author: Author): Promise<any> {
  61 + const { id } = author;
  62 + return [
  63 + {
  64 + id: 4,
  65 + title: 'hello',
  66 + votes: 2112,
  67 + },
  68 + ];
  69 + }
  70 + // 新增文章
  71 + @Mutation((returns) => Post)
  72 + async addPost() {
  73 + const newPost = {
  74 + id: 1,
  75 + title: '新增文章',
  76 + };
  77 + // 新增成功后,通知更新
  78 + await pubSub.publish('postAdded', { postAdded: newPost });
  79 + return newPost;
  80 + }
  81 +
  82 + // 监听变更
  83 + @Subscription((returns) => Post, {
  84 + name: 'postAdded',
  85 + })
  86 + async postAdded(/*@Args('title') title: string*/) {
  87 + return pubSub.asyncIterator('postAdded');
  88 + }
  89 +}
  1 +import { Injectable } from '@nestjs/common';
  2 +@Injectable()
  3 +export class AuthorService {
  4 + async findOneById() {}
  5 +}
  1 +export class GetAuthorArgs {}
  1 +import { Field, Int, ObjectType } from '@nestjs/graphql';
  2 +import { Post } from './post.model';
  3 +
  4 +@ObjectType({ description: 'Author model' })
  5 +export class Author {
  6 + @Field((type) => Int, {
  7 + description: '作者id',
  8 + })
  9 + id: number;
  10 +
  11 + @Field({
  12 + nullable: true,
  13 + description: '作者姓氏',
  14 + })
  15 + firstName?: string;
  16 +
  17 + @Field({
  18 + nullable: true,
  19 + description: '作者名字',
  20 + })
  21 + lastName?: string;
  22 +
  23 + @Field((type) => [Post], {
  24 + nullable: 'items',
  25 + description: '作者发表的文章',
  26 + })
  27 + posts: Post[];
  28 +}
  1 +import { Field, Int, ObjectType } from '@nestjs/graphql';
  2 +
  3 +@ObjectType()
  4 +export class Post {
  5 + @Field((type) => Int)
  6 + id: number;
  7 +
  8 + @Field() title: string;
  9 +
  10 + @Field((type) => Int, {
  11 + nullable: true,
  12 + })
  13 + votes?: number;
  14 +}