├── LICENSE
├── README.md
├── employee-gql-service-nest8
├── .eslintrc.js
├── .gitignore
├── .prettierrc
├── README.md
├── nest-cli.json
├── package-lock.json
├── package.json
├── src
│ ├── app.module.ts
│ ├── employee
│ │ ├── dto
│ │ │ └── create-employee.input.ts
│ │ ├── employee.module.ts
│ │ ├── employee.resolver.ts
│ │ ├── employee.service.ts
│ │ └── entity
│ │ │ └── employee.entity.ts
│ ├── graphql-schema.gql
│ ├── main.ts
│ └── project
│ │ ├── dto
│ │ ├── create-project.input.ts
│ │ └── update-project.input.ts
│ │ ├── entity
│ │ └── project.entity.ts
│ │ ├── project.module.ts
│ │ ├── project.resolver.ts
│ │ └── project.service.ts
├── test
│ ├── app.e2e-spec.ts
│ └── jest-e2e.json
├── tsconfig.build.json
└── tsconfig.json
└── employee-gql-service
├── .eslintrc.js
├── .gitignore
├── .prettierrc
├── README.md
├── nest-cli.json
├── package-lock.json
├── package.json
├── src
├── app.controller.spec.ts
├── app.module.ts
├── employee
│ ├── dto
│ │ └── create-employee.input.ts
│ ├── employee.module.ts
│ ├── employee.resolver.ts
│ ├── employee.service.ts
│ └── entities
│ │ └── employee.entity.ts
├── graphql-schema.gql
├── main.ts
└── project
│ ├── dto
│ ├── create-project.input.ts
│ └── update-project.input.ts
│ ├── entities
│ └── project.entity.ts
│ ├── project.module.ts
│ ├── project.resolver.ts
│ └── project.service.ts
├── test
├── app.e2e-spec.ts
└── jest-e2e.json
├── tsconfig.build.json
└── tsconfig.json
/LICENSE:
--------------------------------------------------------------------------------
1 | Apache License
2 | Version 2.0, January 2004
3 | http://www.apache.org/licenses/
4 |
5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6 |
7 | 1. Definitions.
8 |
9 | "License" shall mean the terms and conditions for use, reproduction,
10 | and distribution as defined by Sections 1 through 9 of this document.
11 |
12 | "Licensor" shall mean the copyright owner or entity authorized by
13 | the copyright owner that is granting the License.
14 |
15 | "Legal Entity" shall mean the union of the acting entity and all
16 | other entities that control, are controlled by, or are under common
17 | control with that entity. For the purposes of this definition,
18 | "control" means (i) the power, direct or indirect, to cause the
19 | direction or management of such entity, whether by contract or
20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 | outstanding shares, or (iii) beneficial ownership of such entity.
22 |
23 | "You" (or "Your") shall mean an individual or Legal Entity
24 | exercising permissions granted by this License.
25 |
26 | "Source" form shall mean the preferred form for making modifications,
27 | including but not limited to software source code, documentation
28 | source, and configuration files.
29 |
30 | "Object" form shall mean any form resulting from mechanical
31 | transformation or translation of a Source form, including but
32 | not limited to compiled object code, generated documentation,
33 | and conversions to other media types.
34 |
35 | "Work" shall mean the work of authorship, whether in Source or
36 | Object form, made available under the License, as indicated by a
37 | copyright notice that is included in or attached to the work
38 | (an example is provided in the Appendix below).
39 |
40 | "Derivative Works" shall mean any work, whether in Source or Object
41 | form, that is based on (or derived from) the Work and for which the
42 | editorial revisions, annotations, elaborations, or other modifications
43 | represent, as a whole, an original work of authorship. For the purposes
44 | of this License, Derivative Works shall not include works that remain
45 | separable from, or merely link (or bind by name) to the interfaces of,
46 | the Work and Derivative Works thereof.
47 |
48 | "Contribution" shall mean any work of authorship, including
49 | the original version of the Work and any modifications or additions
50 | to that Work or Derivative Works thereof, that is intentionally
51 | submitted to Licensor for inclusion in the Work by the copyright owner
52 | or by an individual or Legal Entity authorized to submit on behalf of
53 | the copyright owner. For the purposes of this definition, "submitted"
54 | means any form of electronic, verbal, or written communication sent
55 | to the Licensor or its representatives, including but not limited to
56 | communication on electronic mailing lists, source code control systems,
57 | and issue tracking systems that are managed by, or on behalf of, the
58 | Licensor for the purpose of discussing and improving the Work, but
59 | excluding communication that is conspicuously marked or otherwise
60 | designated in writing by the copyright owner as "Not a Contribution."
61 |
62 | "Contributor" shall mean Licensor and any individual or Legal Entity
63 | on behalf of whom a Contribution has been received by Licensor and
64 | subsequently incorporated within the Work.
65 |
66 | 2. Grant of Copyright License. Subject to the terms and conditions of
67 | this License, each Contributor hereby grants to You a perpetual,
68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 | copyright license to reproduce, prepare Derivative Works of,
70 | publicly display, publicly perform, sublicense, and distribute the
71 | Work and such Derivative Works in Source or Object form.
72 |
73 | 3. Grant of Patent License. Subject to the terms and conditions of
74 | this License, each Contributor hereby grants to You a perpetual,
75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 | (except as stated in this section) patent license to make, have made,
77 | use, offer to sell, sell, import, and otherwise transfer the Work,
78 | where such license applies only to those patent claims licensable
79 | by such Contributor that are necessarily infringed by their
80 | Contribution(s) alone or by combination of their Contribution(s)
81 | with the Work to which such Contribution(s) was submitted. If You
82 | institute patent litigation against any entity (including a
83 | cross-claim or counterclaim in a lawsuit) alleging that the Work
84 | or a Contribution incorporated within the Work constitutes direct
85 | or contributory patent infringement, then any patent licenses
86 | granted to You under this License for that Work shall terminate
87 | as of the date such litigation is filed.
88 |
89 | 4. Redistribution. You may reproduce and distribute copies of the
90 | Work or Derivative Works thereof in any medium, with or without
91 | modifications, and in Source or Object form, provided that You
92 | meet the following conditions:
93 |
94 | (a) You must give any other recipients of the Work or
95 | Derivative Works a copy of this License; and
96 |
97 | (b) You must cause any modified files to carry prominent notices
98 | stating that You changed the files; and
99 |
100 | (c) You must retain, in the Source form of any Derivative Works
101 | that You distribute, all copyright, patent, trademark, and
102 | attribution notices from the Source form of the Work,
103 | excluding those notices that do not pertain to any part of
104 | the Derivative Works; and
105 |
106 | (d) If the Work includes a "NOTICE" text file as part of its
107 | distribution, then any Derivative Works that You distribute must
108 | include a readable copy of the attribution notices contained
109 | within such NOTICE file, excluding those notices that do not
110 | pertain to any part of the Derivative Works, in at least one
111 | of the following places: within a NOTICE text file distributed
112 | as part of the Derivative Works; within the Source form or
113 | documentation, if provided along with the Derivative Works; or,
114 | within a display generated by the Derivative Works, if and
115 | wherever such third-party notices normally appear. The contents
116 | of the NOTICE file are for informational purposes only and
117 | do not modify the License. You may add Your own attribution
118 | notices within Derivative Works that You distribute, alongside
119 | or as an addendum to the NOTICE text from the Work, provided
120 | that such additional attribution notices cannot be construed
121 | as modifying the License.
122 |
123 | You may add Your own copyright statement to Your modifications and
124 | may provide additional or different license terms and conditions
125 | for use, reproduction, or distribution of Your modifications, or
126 | for any such Derivative Works as a whole, provided Your use,
127 | reproduction, and distribution of the Work otherwise complies with
128 | the conditions stated in this License.
129 |
130 | 5. Submission of Contributions. Unless You explicitly state otherwise,
131 | any Contribution intentionally submitted for inclusion in the Work
132 | by You to the Licensor shall be under the terms and conditions of
133 | this License, without any additional terms or conditions.
134 | Notwithstanding the above, nothing herein shall supersede or modify
135 | the terms of any separate license agreement you may have executed
136 | with Licensor regarding such Contributions.
137 |
138 | 6. Trademarks. This License does not grant permission to use the trade
139 | names, trademarks, service marks, or product names of the Licensor,
140 | except as required for reasonable and customary use in describing the
141 | origin of the Work and reproducing the content of the NOTICE file.
142 |
143 | 7. Disclaimer of Warranty. Unless required by applicable law or
144 | agreed to in writing, Licensor provides the Work (and each
145 | Contributor provides its Contributions) on an "AS IS" BASIS,
146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 | implied, including, without limitation, any warranties or conditions
148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 | PARTICULAR PURPOSE. You are solely responsible for determining the
150 | appropriateness of using or redistributing the Work and assume any
151 | risks associated with Your exercise of permissions under this License.
152 |
153 | 8. Limitation of Liability. In no event and under no legal theory,
154 | whether in tort (including negligence), contract, or otherwise,
155 | unless required by applicable law (such as deliberate and grossly
156 | negligent acts) or agreed to in writing, shall any Contributor be
157 | liable to You for damages, including any direct, indirect, special,
158 | incidental, or consequential damages of any character arising as a
159 | result of this License or out of the use or inability to use the
160 | Work (including but not limited to damages for loss of goodwill,
161 | work stoppage, computer failure or malfunction, or any and all
162 | other commercial damages or losses), even if such Contributor
163 | has been advised of the possibility of such damages.
164 |
165 | 9. Accepting Warranty or Additional Liability. While redistributing
166 | the Work or Derivative Works thereof, You may choose to offer,
167 | and charge a fee for, acceptance of support, warranty, indemnity,
168 | or other liability obligations and/or rights consistent with this
169 | License. However, in accepting such obligations, You may act only
170 | on Your own behalf and on Your sole responsibility, not on behalf
171 | of any other Contributor, and only if You agree to indemnify,
172 | defend, and hold each Contributor harmless for any liability
173 | incurred by, or claims asserted against, such Contributor by reason
174 | of your accepting any such warranty or additional liability.
175 |
176 | END OF TERMS AND CONDITIONS
177 |
178 | APPENDIX: How to apply the Apache License to your work.
179 |
180 | To apply the Apache License to your work, attach the following
181 | boilerplate notice, with the fields enclosed by brackets "[]"
182 | replaced with your own identifying information. (Don't include
183 | the brackets!) The text should be enclosed in the appropriate
184 | comment syntax for the file format. We also recommend that a
185 | file or class name and description of purpose be included on the
186 | same "printed page" as the copyright notice for easier
187 | identification within third-party archives.
188 |
189 | Copyright [yyyy] [name of copyright owner]
190 |
191 | Licensed under the Apache License, Version 2.0 (the "License");
192 | you may not use this file except in compliance with the License.
193 | You may obtain a copy of the License at
194 |
195 | http://www.apache.org/licenses/LICENSE-2.0
196 |
197 | Unless required by applicable law or agreed to in writing, software
198 | distributed under the License is distributed on an "AS IS" BASIS,
199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 | See the License for the specific language governing permissions and
201 | limitations under the License.
202 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # nestjs-graphql-course-youtube
2 | This is source project of this tutorial. https://youtu.be/_PVA98-ooWA
3 |
--------------------------------------------------------------------------------
/employee-gql-service-nest8/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | parser: '@typescript-eslint/parser',
3 | parserOptions: {
4 | project: 'tsconfig.json',
5 | sourceType: 'module',
6 | },
7 | plugins: ['@typescript-eslint/eslint-plugin'],
8 | extends: [
9 | 'plugin:@typescript-eslint/recommended',
10 | 'plugin:prettier/recommended',
11 | ],
12 | root: true,
13 | env: {
14 | node: true,
15 | jest: true,
16 | },
17 | ignorePatterns: ['.eslintrc.js'],
18 | rules: {
19 | '@typescript-eslint/interface-name-prefix': 'off',
20 | '@typescript-eslint/explicit-function-return-type': 'off',
21 | '@typescript-eslint/explicit-module-boundary-types': 'off',
22 | '@typescript-eslint/no-explicit-any': 'off',
23 | },
24 | };
25 |
--------------------------------------------------------------------------------
/employee-gql-service-nest8/.gitignore:
--------------------------------------------------------------------------------
1 | # compiled output
2 | /dist
3 | /node_modules
4 |
5 | # Logs
6 | logs
7 | *.log
8 | npm-debug.log*
9 | yarn-debug.log*
10 | yarn-error.log*
11 | lerna-debug.log*
12 |
13 | # OS
14 | .DS_Store
15 |
16 | # Tests
17 | /coverage
18 | /.nyc_output
19 |
20 | # IDEs and editors
21 | /.idea
22 | .project
23 | .classpath
24 | .c9/
25 | *.launch
26 | .settings/
27 | *.sublime-workspace
28 |
29 | # IDE - VSCode
30 | .vscode/*
31 | !.vscode/settings.json
32 | !.vscode/tasks.json
33 | !.vscode/launch.json
34 | !.vscode/extensions.json
--------------------------------------------------------------------------------
/employee-gql-service-nest8/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "singleQuote": true,
3 | "trailingComma": "all"
4 | }
--------------------------------------------------------------------------------
/employee-gql-service-nest8/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | [circleci-image]: https://img.shields.io/circleci/build/github/nestjs/nest/master?token=abc123def456
6 | [circleci-url]: https://circleci.com/gh/nestjs/nest
7 |
8 | A progressive Node.js framework for building efficient and scalable server-side applications.
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
24 |
25 | ## Description
26 |
27 | [Nest](https://github.com/nestjs/nest) framework TypeScript starter repository.
28 |
29 | ## Installation
30 |
31 | ```bash
32 | $ npm install
33 | ```
34 |
35 | ## Running the app
36 |
37 | ```bash
38 | # development
39 | $ npm run start
40 |
41 | # watch mode
42 | $ npm run start:dev
43 |
44 | # production mode
45 | $ npm run start:prod
46 | ```
47 |
48 | ## Test
49 |
50 | ```bash
51 | # unit tests
52 | $ npm run test
53 |
54 | # e2e tests
55 | $ npm run test:e2e
56 |
57 | # test coverage
58 | $ npm run test:cov
59 | ```
60 |
61 | ## Support
62 |
63 | Nest is an MIT-licensed open source project. It can grow thanks to the sponsors and support by the amazing backers. If you'd like to join them, please [read more here](https://docs.nestjs.com/support).
64 |
65 | ## Stay in touch
66 |
67 | - Author - [Kamil Myśliwiec](https://kamilmysliwiec.com)
68 | - Website - [https://nestjs.com](https://nestjs.com/)
69 | - Twitter - [@nestframework](https://twitter.com/nestframework)
70 |
71 | ## License
72 |
73 | Nest is [MIT licensed](LICENSE).
74 |
--------------------------------------------------------------------------------
/employee-gql-service-nest8/nest-cli.json:
--------------------------------------------------------------------------------
1 | {
2 | "collection": "@nestjs/schematics",
3 | "sourceRoot": "src"
4 | }
5 |
--------------------------------------------------------------------------------
/employee-gql-service-nest8/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "employee-gql-service-nest8",
3 | "version": "0.0.1",
4 | "description": "",
5 | "author": "",
6 | "private": true,
7 | "license": "UNLICENSED",
8 | "scripts": {
9 | "prebuild": "rimraf dist",
10 | "build": "nest build",
11 | "format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\"",
12 | "start": "nest start",
13 | "start:dev": "nest start --watch",
14 | "start:debug": "nest start --debug --watch",
15 | "start:prod": "node dist/main",
16 | "lint": "eslint \"{src,apps,libs,test}/**/*.ts\" --fix",
17 | "test": "jest",
18 | "test:watch": "jest --watch",
19 | "test:cov": "jest --coverage",
20 | "test:debug": "node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand",
21 | "test:e2e": "jest --config ./test/jest-e2e.json"
22 | },
23 | "dependencies": {
24 | "@nestjs/common": "^8.0.0",
25 | "@nestjs/core": "^8.0.0",
26 | "@nestjs/graphql": "^8.0.2",
27 | "@nestjs/platform-express": "^8.0.0",
28 | "@nestjs/typeorm": "^8.0.1",
29 | "apollo-server-express": "^2.25.2",
30 | "graphql": "^15.5.1",
31 | "graphql-tools": "^7.0.5",
32 | "pg": "^8.6.0",
33 | "reflect-metadata": "^0.1.13",
34 | "rimraf": "^3.0.2",
35 | "rxjs": "^7.2.0",
36 | "typeorm": "^0.2.34"
37 | },
38 | "devDependencies": {
39 | "@nestjs/cli": "^8.0.0",
40 | "@nestjs/schematics": "^8.0.0",
41 | "@nestjs/testing": "^8.0.0",
42 | "@types/express": "^4.17.13",
43 | "@types/jest": "^26.0.24",
44 | "@types/node": "^16.0.0",
45 | "@types/supertest": "^2.0.11",
46 | "@typescript-eslint/eslint-plugin": "^4.28.2",
47 | "@typescript-eslint/parser": "^4.28.2",
48 | "eslint": "^7.30.0",
49 | "eslint-config-prettier": "^8.3.0",
50 | "eslint-plugin-prettier": "^3.4.0",
51 | "jest": "27.0.6",
52 | "prettier": "^2.3.2",
53 | "supertest": "^6.1.3",
54 | "ts-jest": "^27.0.3",
55 | "ts-loader": "^9.2.3",
56 | "ts-node": "^10.0.0",
57 | "tsconfig-paths": "^3.10.1",
58 | "typescript": "^4.3.5"
59 | },
60 | "jest": {
61 | "moduleFileExtensions": [
62 | "js",
63 | "json",
64 | "ts"
65 | ],
66 | "rootDir": "src",
67 | "testRegex": ".*\\.spec\\.ts$",
68 | "transform": {
69 | "^.+\\.(t|j)s$": "ts-jest"
70 | },
71 | "collectCoverageFrom": [
72 | "**/*.(t|j)s"
73 | ],
74 | "coverageDirectory": "../coverage",
75 | "testEnvironment": "node"
76 | }
77 | }
78 |
--------------------------------------------------------------------------------
/employee-gql-service-nest8/src/app.module.ts:
--------------------------------------------------------------------------------
1 | import { Module } from '@nestjs/common';
2 | import { EmployeeModule } from './employee/employee.module';
3 | import { ProjectModule } from './project/project.module';
4 | import { GraphQLModule } from '@nestjs/graphql';
5 | import { TypeOrmModule } from '@nestjs/typeorm';
6 | import { join } from 'path';
7 |
8 | @Module({
9 | imports: [EmployeeModule, ProjectModule,GraphQLModule.forRoot(
10 | {
11 | autoSchemaFile: join(process.cwd(), 'src/graphql-schema.gql')
12 | }
13 | ),
14 | TypeOrmModule.forRoot({
15 | type: 'postgres',
16 | host: '192.168.1.6',
17 | port: 5432,
18 | username: 'nairobi',
19 | password: '1qazxsw2#',
20 | database: 'employee',
21 | entities: ["dist/**/*.entity{.ts,.js}"],
22 | synchronize: true,
23 | }),],
24 | controllers: [],
25 | providers: [],
26 | })
27 | export class AppModule {}
28 |
--------------------------------------------------------------------------------
/employee-gql-service-nest8/src/employee/dto/create-employee.input.ts:
--------------------------------------------------------------------------------
1 | import { Field, InputType } from "@nestjs/graphql"
2 |
3 | @InputType()
4 | export class EmployeeCreateDTO {
5 | @Field()
6 | firstName: string
7 | @Field()
8 | lastName: string
9 | @Field()
10 | designation: string
11 | @Field({ nullable: true })
12 | city: string
13 |
14 | @Field()
15 | projectId: string
16 | }
--------------------------------------------------------------------------------
/employee-gql-service-nest8/src/employee/employee.module.ts:
--------------------------------------------------------------------------------
1 | import { Module } from '@nestjs/common';
2 | import { EmployeeService } from './employee.service';
3 | import { EmployeeResolver } from './employee.resolver';
4 | import { TypeOrmModule } from '@nestjs/typeorm';
5 | import { Employee } from './entity/employee.entity';
6 | import { ProjectModule } from 'src/project/project.module';
7 |
8 | @Module({
9 | imports: [TypeOrmModule.forFeature([Employee]), ProjectModule],
10 | providers: [EmployeeService, EmployeeResolver]
11 | })
12 | export class EmployeeModule {}
13 |
--------------------------------------------------------------------------------
/employee-gql-service-nest8/src/employee/employee.resolver.ts:
--------------------------------------------------------------------------------
1 | import { } from '@nestjs/graphql';
2 | import { Resolver, Query, Mutation, Args, ResolveField, Parent } from '@nestjs/graphql';
3 | import { Project } from 'src/project/entity/project.entity';
4 | import { EmployeeCreateDTO } from './dto/create-employee.input';
5 | import { EmployeeService } from './employee.service';
6 | import { Employee } from './entity/employee.entity'
7 | @Resolver(() => Employee)
8 | export class EmployeeResolver {
9 | constructor(private employeeService: EmployeeService) { }
10 |
11 | @Query(() => [Employee], { name: "getAllEmployees" })
12 | findAll() {
13 | return this.employeeService.findAll();
14 | }
15 |
16 | @Mutation(() => Employee, { name: "createEmployee" })
17 | create(@Args('employeeInput') employee: EmployeeCreateDTO) {
18 | return this.employeeService.create(employee)
19 | }
20 | @Query(() => Employee)
21 | findOne(@Args("id") id: string) {
22 | return this.employeeService.findOne(id)
23 | }
24 |
25 |
26 |
27 | @ResolveField(() => Project)
28 | project(@Parent() employee: Employee) {
29 | return this.employeeService.getProject(employee.projectId)
30 |
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/employee-gql-service-nest8/src/employee/employee.service.ts:
--------------------------------------------------------------------------------
1 | import { Injectable } from '@nestjs/common';
2 | import { InjectRepository } from '@nestjs/typeorm';
3 | import { Project } from 'src/project/entity/project.entity';
4 | import { ProjectModule } from 'src/project/project.module';
5 | import { ProjectService } from 'src/project/project.service';
6 | import { Repository } from 'typeorm';
7 | import { EmployeeCreateDTO } from './dto/create-employee.input';
8 | import { Employee } from './entity/employee.entity';
9 |
10 | @Injectable()
11 | export class EmployeeService {
12 |
13 | constructor(@InjectRepository(Employee) private employeeRepository: Repository,
14 | private projectService: ProjectService) {
15 |
16 | }
17 |
18 | async findAll(): Promise {
19 | return this.employeeRepository.find();
20 | }
21 | async findOne(id: string) {
22 | return this.employeeRepository.findOne(id)
23 | }
24 |
25 | async create(employee: EmployeeCreateDTO): Promise {
26 |
27 | let emp = this.employeeRepository.create(employee);
28 | return this.employeeRepository.save(emp)
29 |
30 | }
31 |
32 | async getProject(id: string): Promise {
33 | return this.projectService.findOne(id)
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/employee-gql-service-nest8/src/employee/entity/employee.entity.ts:
--------------------------------------------------------------------------------
1 | import { Field, ObjectType } from "@nestjs/graphql"
2 | import { Project } from "src/project/entity/project.entity"
3 | import { Column, Entity, ManyToOne, PrimaryColumn, PrimaryGeneratedColumn } from "typeorm"
4 |
5 | @ObjectType()
6 | @Entity()
7 | export class Employee {
8 | @Field()
9 | @PrimaryGeneratedColumn('uuid')
10 | id: string
11 | @Field()
12 | @Column()
13 | firstName: string
14 | @Field()
15 | @Column()
16 | lastName: string
17 | @Field()
18 | @Column()
19 | designation: string
20 | @Field({ nullable: true })
21 | @Column({ nullable: true })
22 | city: string
23 |
24 | @ManyToOne(() => Project, project => project.employees)
25 | @Field(() => Project)
26 | project: Project
27 |
28 | @Column()
29 | @Field()
30 | projectId: string
31 |
32 | }
--------------------------------------------------------------------------------
/employee-gql-service-nest8/src/graphql-schema.gql:
--------------------------------------------------------------------------------
1 | # ------------------------------------------------------
2 | # THIS FILE WAS AUTOMATICALLY GENERATED (DO NOT MODIFY)
3 | # ------------------------------------------------------
4 |
5 | type Employee {
6 | id: String!
7 | firstName: String!
8 | lastName: String!
9 | designation: String!
10 | city: String
11 | project: Project!
12 | projectId: String!
13 | }
14 |
15 | type Project {
16 | id: String!
17 | name: String!
18 | code: Int!
19 | employees: [Employee!]
20 | }
21 |
22 | type Query {
23 | getAllEmployees: [Employee!]!
24 | findOne(id: String!): Employee!
25 | getAllProjects: [Project!]!
26 | project(id: String!): Project!
27 | }
28 |
29 | type Mutation {
30 | createEmployee(employeeInput: EmployeeCreateDTO!): Employee!
31 | createProject(project: CreateProjectInput!): Project!
32 | updateProject(project: UpdateProjectInput!): Project!
33 | removeProject(id: String!): Project!
34 | }
35 |
36 | input EmployeeCreateDTO {
37 | firstName: String!
38 | lastName: String!
39 | designation: String!
40 | city: String
41 | projectId: String!
42 | }
43 |
44 | input CreateProjectInput {
45 | name: String!
46 | code: Int!
47 | }
48 |
49 | input UpdateProjectInput {
50 | id: String!
51 | name: String!
52 | code: Int!
53 | }
54 |
--------------------------------------------------------------------------------
/employee-gql-service-nest8/src/main.ts:
--------------------------------------------------------------------------------
1 | import { NestFactory } from '@nestjs/core';
2 | import { AppModule } from './app.module';
3 |
4 | async function bootstrap() {
5 | const app = await NestFactory.create(AppModule);
6 | await app.listen(3000);
7 | }
8 | bootstrap();
9 |
--------------------------------------------------------------------------------
/employee-gql-service-nest8/src/project/dto/create-project.input.ts:
--------------------------------------------------------------------------------
1 | import { InputType, Int, Field } from '@nestjs/graphql';
2 |
3 | @InputType()
4 | export class CreateProjectInput {
5 |
6 |
7 | @Field()
8 | name: string
9 | @Field(() => Int)
10 | code: number
11 | }
--------------------------------------------------------------------------------
/employee-gql-service-nest8/src/project/dto/update-project.input.ts:
--------------------------------------------------------------------------------
1 | import { CreateProjectInput } from './create-project.input';
2 | import { InputType, Field, Int, PartialType } from '@nestjs/graphql';
3 |
4 | @InputType()
5 | export class UpdateProjectInput {
6 |
7 | @Field()
8 | id: string
9 | @Field()
10 | name: string
11 | @Field(() => Int)
12 | code: number
13 |
14 |
15 | }
--------------------------------------------------------------------------------
/employee-gql-service-nest8/src/project/entity/project.entity.ts:
--------------------------------------------------------------------------------
1 | import { ObjectType, Field, Int } from '@nestjs/graphql';
2 | import { Employee } from 'src/employee/entity/employee.entity';
3 | import { Column, Entity, OneToMany, PrimaryGeneratedColumn } from 'typeorm';
4 |
5 | @ObjectType()
6 | @Entity()
7 | export class Project {
8 |
9 | @Field()
10 | @PrimaryGeneratedColumn('uuid')
11 | id: string
12 | @Field()
13 | @Column()
14 | name: string
15 | @Field(() => Int)
16 | @Column()
17 | code: number
18 |
19 | @OneToMany(() => Employee, employee => employee.project)
20 | @Field(() => [Employee], { nullable: true })
21 | employees: Employee[]
22 |
23 | }
--------------------------------------------------------------------------------
/employee-gql-service-nest8/src/project/project.module.ts:
--------------------------------------------------------------------------------
1 | import { Module } from '@nestjs/common';
2 | import { ProjectService } from './project.service';
3 | import { ProjectResolver } from './project.resolver';
4 | import { TypeOrmModule } from '@nestjs/typeorm';
5 | import { Project } from './entity/project.entity';
6 |
7 | @Module({
8 | imports: [TypeOrmModule.forFeature([Project])],
9 | providers: [ProjectResolver, ProjectService],
10 | exports: [ProjectService]
11 | })
12 | export class ProjectModule { }
--------------------------------------------------------------------------------
/employee-gql-service-nest8/src/project/project.resolver.ts:
--------------------------------------------------------------------------------
1 | import { Resolver, Query, Mutation, Args, Int } from '@nestjs/graphql';
2 | import { ProjectService } from './project.service';
3 | import { Project } from './entity/project.entity';
4 | import { CreateProjectInput } from './dto/create-project.input';
5 | import { UpdateProjectInput } from './dto/update-project.input';
6 |
7 | @Resolver(() => Project)
8 | export class ProjectResolver {
9 | constructor(private readonly projectService: ProjectService) { }
10 |
11 | @Mutation(() => Project)
12 | createProject(@Args('project') project: CreateProjectInput) {
13 | return this.projectService.create(project);
14 | }
15 |
16 | @Query(() => [Project], { name: 'getAllProjects' })
17 | findAll() {
18 | return this.projectService.findAll();
19 | }
20 |
21 | @Query(() => Project, { name: 'project' })
22 | findOne(@Args('id') id: string) {
23 | return this.projectService.findOne(id);
24 | }
25 |
26 | @Mutation(() => Project)
27 | updateProject(@Args('project') project: UpdateProjectInput) {
28 | return this.projectService.update(project.id, project);
29 | }
30 |
31 | @Mutation(() => Project)
32 | removeProject(@Args('id') id: string) {
33 | return this.projectService.remove(id);
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/employee-gql-service-nest8/src/project/project.service.ts:
--------------------------------------------------------------------------------
1 | import { Injectable, NotFoundException } from '@nestjs/common';
2 | import { InjectRepository } from '@nestjs/typeorm';
3 | import { Repository } from 'typeorm';
4 | import { CreateProjectInput } from './dto/create-project.input';
5 | import { UpdateProjectInput } from './dto/update-project.input';
6 | import { Project } from './entity/project.entity';
7 |
8 | @Injectable()
9 | export class ProjectService {
10 |
11 | constructor(@InjectRepository(Project) private projectRepository: Repository) { }
12 |
13 | create(project: CreateProjectInput): Promise {
14 | let proj = this.projectRepository.create(project);
15 | return this.projectRepository.save(proj) //you can directly use this without create. depends on DTO. this explained in video
16 |
17 | }
18 |
19 | async findAll(): Promise {
20 | return this.projectRepository.find({
21 | relations: ["employees"]
22 | });
23 | }
24 |
25 | async findOne(id: string): Promise {
26 | return this.projectRepository.findOne(id, { relations: ["employees"] });
27 | }
28 |
29 | update(id: string, updateProjectInput: UpdateProjectInput) {
30 | let project: Project = this.projectRepository.create(updateProjectInput)
31 | project.id = id;
32 | return this.projectRepository.save(project)
33 | }
34 |
35 | async remove(id: string) {
36 | let proj = this.findOne(id)
37 | if (proj) {
38 | let ret = await this.projectRepository.delete(id)
39 | if (ret.affected === 1) {
40 | return proj;
41 | }
42 | }
43 | throw new NotFoundException(`Record cannot find by id ${id}`)
44 | }
45 | }
--------------------------------------------------------------------------------
/employee-gql-service-nest8/test/app.e2e-spec.ts:
--------------------------------------------------------------------------------
1 | import { Test, TestingModule } from '@nestjs/testing';
2 | import { INestApplication } from '@nestjs/common';
3 | import * as request from 'supertest';
4 | import { AppModule } from './../src/app.module';
5 |
6 | describe('AppController (e2e)', () => {
7 | let app: INestApplication;
8 |
9 | beforeEach(async () => {
10 | const moduleFixture: TestingModule = await Test.createTestingModule({
11 | imports: [AppModule],
12 | }).compile();
13 |
14 | app = moduleFixture.createNestApplication();
15 | await app.init();
16 | });
17 |
18 | it('/ (GET)', () => {
19 | return request(app.getHttpServer())
20 | .get('/')
21 | .expect(200)
22 | .expect('Hello World!');
23 | });
24 | });
25 |
--------------------------------------------------------------------------------
/employee-gql-service-nest8/test/jest-e2e.json:
--------------------------------------------------------------------------------
1 | {
2 | "moduleFileExtensions": ["js", "json", "ts"],
3 | "rootDir": ".",
4 | "testEnvironment": "node",
5 | "testRegex": ".e2e-spec.ts$",
6 | "transform": {
7 | "^.+\\.(t|j)s$": "ts-jest"
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/employee-gql-service-nest8/tsconfig.build.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./tsconfig.json",
3 | "exclude": ["node_modules", "test", "dist", "**/*spec.ts"]
4 | }
5 |
--------------------------------------------------------------------------------
/employee-gql-service-nest8/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "module": "commonjs",
4 | "declaration": true,
5 | "removeComments": true,
6 | "emitDecoratorMetadata": true,
7 | "experimentalDecorators": true,
8 | "allowSyntheticDefaultImports": true,
9 | "target": "es2017",
10 | "sourceMap": true,
11 | "outDir": "./dist",
12 | "baseUrl": "./",
13 | "incremental": true,
14 | "skipLibCheck": true
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/employee-gql-service/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | parser: '@typescript-eslint/parser',
3 | parserOptions: {
4 | project: 'tsconfig.json',
5 | sourceType: 'module',
6 | },
7 | plugins: ['@typescript-eslint/eslint-plugin'],
8 | extends: [
9 | 'plugin:@typescript-eslint/recommended',
10 | 'plugin:prettier/recommended',
11 | ],
12 | root: true,
13 | env: {
14 | node: true,
15 | jest: true,
16 | },
17 | ignorePatterns: ['.eslintrc.js'],
18 | rules: {
19 | '@typescript-eslint/interface-name-prefix': 'off',
20 | '@typescript-eslint/explicit-function-return-type': 'off',
21 | '@typescript-eslint/explicit-module-boundary-types': 'off',
22 | '@typescript-eslint/no-explicit-any': 'off',
23 | },
24 | };
25 |
--------------------------------------------------------------------------------
/employee-gql-service/.gitignore:
--------------------------------------------------------------------------------
1 | # compiled output
2 | /dist
3 | /node_modules
4 |
5 | # Logs
6 | logs
7 | *.log
8 | npm-debug.log*
9 | yarn-debug.log*
10 | yarn-error.log*
11 | lerna-debug.log*
12 |
13 | # OS
14 | .DS_Store
15 |
16 | # Tests
17 | /coverage
18 | /.nyc_output
19 |
20 | # IDEs and editors
21 | /.idea
22 | .project
23 | .classpath
24 | .c9/
25 | *.launch
26 | .settings/
27 | *.sublime-workspace
28 |
29 | # IDE - VSCode
30 | .vscode/*
31 | !.vscode/settings.json
32 | !.vscode/tasks.json
33 | !.vscode/launch.json
34 | !.vscode/extensions.json
--------------------------------------------------------------------------------
/employee-gql-service/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "singleQuote": true,
3 | "trailingComma": "all"
4 | }
--------------------------------------------------------------------------------
/employee-gql-service/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | [circleci-image]: https://img.shields.io/circleci/build/github/nestjs/nest/master?token=abc123def456
6 | [circleci-url]: https://circleci.com/gh/nestjs/nest
7 |
8 | A progressive Node.js framework for building efficient and scalable server-side applications.
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
24 |
25 | ## Description
26 |
27 | [Nest](https://github.com/nestjs/nest) framework TypeScript starter repository.
28 |
29 | ## Installation
30 |
31 | ```bash
32 | $ npm install
33 | ```
34 |
35 | ## Running the app
36 |
37 | ```bash
38 | # development
39 | $ npm run start
40 |
41 | # watch mode
42 | $ npm run start:dev
43 |
44 | # production mode
45 | $ npm run start:prod
46 | ```
47 |
48 | ## Test
49 |
50 | ```bash
51 | # unit tests
52 | $ npm run test
53 |
54 | # e2e tests
55 | $ npm run test:e2e
56 |
57 | # test coverage
58 | $ npm run test:cov
59 | ```
60 |
61 | ## Support
62 |
63 | Nest is an MIT-licensed open source project. It can grow thanks to the sponsors and support by the amazing backers. If you'd like to join them, please [read more here](https://docs.nestjs.com/support).
64 |
65 | ## Stay in touch
66 |
67 | - Author - [Kamil Myśliwiec](https://kamilmysliwiec.com)
68 | - Website - [https://nestjs.com](https://nestjs.com/)
69 | - Twitter - [@nestframework](https://twitter.com/nestframework)
70 |
71 | ## License
72 |
73 | Nest is [MIT licensed](LICENSE).
74 |
--------------------------------------------------------------------------------
/employee-gql-service/nest-cli.json:
--------------------------------------------------------------------------------
1 | {
2 | "collection": "@nestjs/schematics",
3 | "sourceRoot": "src"
4 | }
5 |
--------------------------------------------------------------------------------
/employee-gql-service/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "employee-gql-service",
3 | "version": "0.0.1",
4 | "description": "",
5 | "author": "",
6 | "private": true,
7 | "license": "UNLICENSED",
8 | "scripts": {
9 | "prebuild": "rimraf dist",
10 | "build": "nest build",
11 | "format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\"",
12 | "start": "nest start",
13 | "start:dev": "nest start --watch",
14 | "start:debug": "nest start --debug --watch",
15 | "start:prod": "node dist/main",
16 | "lint": "eslint \"{src,apps,libs,test}/**/*.ts\" --fix",
17 | "test": "jest",
18 | "test:watch": "jest --watch",
19 | "test:cov": "jest --coverage",
20 | "test:debug": "node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand",
21 | "test:e2e": "jest --config ./test/jest-e2e.json"
22 | },
23 | "dependencies": {
24 | "@nestjs/common": "^7.6.15",
25 | "@nestjs/core": "^7.6.15",
26 | "@nestjs/graphql": "^7.10.6",
27 | "@nestjs/platform-express": "^7.6.15",
28 | "@nestjs/typeorm": "^7.1.5",
29 | "apollo-server-express": "^2.24.1",
30 | "graphql": "^15.5.0",
31 | "graphql-tools": "^7.0.5",
32 | "pg": "^8.6.0",
33 | "reflect-metadata": "^0.1.13",
34 | "rimraf": "^3.0.2",
35 | "rxjs": "^6.6.6",
36 | "typeorm": "^0.2.32"
37 | },
38 | "devDependencies": {
39 | "@nestjs/cli": "^7.6.0",
40 | "@nestjs/schematics": "^7.3.0",
41 | "@nestjs/testing": "^7.6.15",
42 | "@types/express": "^4.17.11",
43 | "@types/jest": "^26.0.22",
44 | "@types/node": "^14.14.36",
45 | "@types/supertest": "^2.0.10",
46 | "@typescript-eslint/eslint-plugin": "^4.19.0",
47 | "@typescript-eslint/parser": "^4.19.0",
48 | "eslint": "^7.22.0",
49 | "eslint-config-prettier": "^8.1.0",
50 | "eslint-plugin-prettier": "^3.3.1",
51 | "jest": "^26.6.3",
52 | "prettier": "^2.2.1",
53 | "supertest": "^6.1.3",
54 | "ts-jest": "^26.5.4",
55 | "ts-loader": "^8.0.18",
56 | "ts-node": "^9.1.1",
57 | "tsconfig-paths": "^3.9.0",
58 | "typescript": "^4.2.3"
59 | },
60 | "jest": {
61 | "moduleFileExtensions": [
62 | "js",
63 | "json",
64 | "ts"
65 | ],
66 | "rootDir": "src",
67 | "testRegex": ".*\\.spec\\.ts$",
68 | "transform": {
69 | "^.+\\.(t|j)s$": "ts-jest"
70 | },
71 | "collectCoverageFrom": [
72 | "**/*.(t|j)s"
73 | ],
74 | "coverageDirectory": "../coverage",
75 | "testEnvironment": "node"
76 | }
77 | }
78 |
--------------------------------------------------------------------------------
/employee-gql-service/src/app.controller.spec.ts:
--------------------------------------------------------------------------------
1 | import { Test, TestingModule } from '@nestjs/testing';
2 | import { AppController } from './app.controller';
3 | import { AppService } from './app.service';
4 |
5 | describe('AppController', () => {
6 | let appController: AppController;
7 |
8 | beforeEach(async () => {
9 | const app: TestingModule = await Test.createTestingModule({
10 | controllers: [AppController],
11 | providers: [AppService],
12 | }).compile();
13 |
14 | appController = app.get(AppController);
15 | });
16 |
17 | describe('root', () => {
18 | it('should return "Hello World!"', () => {
19 | expect(appController.getHello()).toBe('Hello World!');
20 | });
21 | });
22 | });
23 |
--------------------------------------------------------------------------------
/employee-gql-service/src/app.module.ts:
--------------------------------------------------------------------------------
1 | import { Module } from '@nestjs/common';
2 | import { GraphQLModule } from '@nestjs/graphql';
3 | import { TypeOrmModule } from '@nestjs/typeorm';
4 | import { join } from 'path';
5 | import { EmployeeModule } from './employee/employee.module';
6 | import { ProjectModule } from './project/project.module';
7 |
8 |
9 |
10 | @Module({
11 | imports: [EmployeeModule, GraphQLModule.forRoot(
12 | {
13 | autoSchemaFile: join(process.cwd(), 'src/graphql-schema.gql')
14 | }
15 | ),
16 | TypeOrmModule.forRoot({
17 | type: 'postgres',
18 | host: 'localhost',
19 | port: 5432,
20 | username: 'nairobi',
21 | password: '1qazxsw2#',
22 | database: 'employee',
23 | entities: ["dist/**/*.entity{.ts,.js}"],
24 | synchronize: true,
25 | }),
26 | ProjectModule],
27 | controllers: [],
28 | providers: [],
29 | })
30 | export class AppModule { }
31 |
--------------------------------------------------------------------------------
/employee-gql-service/src/employee/dto/create-employee.input.ts:
--------------------------------------------------------------------------------
1 | import { Field, InputType } from "@nestjs/graphql"
2 |
3 | @InputType()
4 | export class EmployeeCreateDTO {
5 | @Field()
6 | firstName: string
7 | @Field()
8 | lastName: string
9 | @Field()
10 | designation: string
11 | @Field({ nullable: true })
12 | city: string
13 |
14 | @Field()
15 | projectId: string
16 | }
--------------------------------------------------------------------------------
/employee-gql-service/src/employee/employee.module.ts:
--------------------------------------------------------------------------------
1 | import { Module } from '@nestjs/common';
2 | import { EmployeeService } from './employee.service';
3 | import { EmployeeResolver } from './employee.resolver';
4 | import { TypeOrmModule } from '@nestjs/typeorm';
5 | import { Employee } from './entities/employee.entity';
6 | import { ProjectModule } from 'src/project/project.module';
7 |
8 | @Module({
9 | imports: [TypeOrmModule.forFeature([Employee]), ProjectModule],
10 | providers: [EmployeeService, EmployeeResolver]
11 | })
12 | export class EmployeeModule { }
13 |
--------------------------------------------------------------------------------
/employee-gql-service/src/employee/employee.resolver.ts:
--------------------------------------------------------------------------------
1 | import { Resolver, Query, Mutation, Args, ResolveField, Parent } from '@nestjs/graphql';
2 | import { identity } from 'rxjs';
3 | import { Project } from 'src/project/entities/project.entity';
4 | import { EmployeeCreateDTO } from './dto/create-employee.input';
5 | import { EmployeeService } from './employee.service';
6 | import { Employee } from './entities/employee.entity';
7 |
8 | @Resolver(() => Employee)
9 | export class EmployeeResolver {
10 |
11 | constructor(private employeeService: EmployeeService) { }
12 |
13 | @Query(() => [Employee], { name: "getAllEmployees" })
14 | findAll() {
15 | return this.employeeService.findAll();
16 | }
17 |
18 | @Mutation(() => Employee, { name: "createEmployee" })
19 | create(@Args('employeeInput') employee: EmployeeCreateDTO) {
20 | return this.employeeService.create(employee)
21 | }
22 | @Query(() => Employee)
23 | findOne(@Args("id") id: string) {
24 | return this.employeeService.findOne(id)
25 | }
26 |
27 |
28 |
29 | @ResolveField(() => Project)
30 | project(@Parent() employee: Employee) {
31 | return this.employeeService.getProject(employee.projectId)
32 |
33 | }
34 |
35 | }
36 |
--------------------------------------------------------------------------------
/employee-gql-service/src/employee/employee.service.ts:
--------------------------------------------------------------------------------
1 | import { Injectable } from '@nestjs/common';
2 | import { InjectRepository } from '@nestjs/typeorm';
3 | import { Project } from 'src/project/entities/project.entity';
4 | import { ProjectModule } from 'src/project/project.module';
5 | import { ProjectService } from 'src/project/project.service';
6 | import { Repository } from 'typeorm';
7 | import { EmployeeCreateDTO } from './dto/create-employee.input';
8 | import { Employee } from './entities/employee.entity';
9 |
10 | @Injectable()
11 | export class EmployeeService {
12 |
13 |
14 | constructor(@InjectRepository(Employee) private employeeRepository: Repository,
15 | private projectService: ProjectService) {
16 |
17 | }
18 |
19 | async findAll(): Promise {
20 | return this.employeeRepository.find();
21 | }
22 | async findOne(id: string) {
23 | return this.employeeRepository.findOne(id)
24 | }
25 |
26 | async create(employee: EmployeeCreateDTO): Promise {
27 |
28 | let emp = this.employeeRepository.create(employee);
29 | return this.employeeRepository.save(emp)
30 |
31 | }
32 |
33 | async getProject(id: string): Promise {
34 | return this.projectService.findOne(id)
35 | }
36 |
37 | }
38 |
--------------------------------------------------------------------------------
/employee-gql-service/src/employee/entities/employee.entity.ts:
--------------------------------------------------------------------------------
1 | import { Field, ObjectType } from "@nestjs/graphql"
2 | import { Project } from "src/project/entities/project.entity"
3 | import { Column, Entity, ManyToOne, PrimaryColumn, PrimaryGeneratedColumn } from "typeorm"
4 |
5 | @ObjectType()
6 | @Entity()
7 | export class Employee {
8 | @Field()
9 | @PrimaryGeneratedColumn('uuid')
10 | id: string
11 | @Field()
12 | @Column()
13 | firstName: string
14 | @Field()
15 | @Column()
16 | lastName: string
17 | @Field()
18 | @Column()
19 | designation: string
20 | @Field({ nullable: true })
21 | @Column({ nullable: true })
22 | city: string
23 |
24 | @ManyToOne(() => Project, project => project.employees)
25 | @Field(() => Project)
26 | project: Project
27 |
28 | @Column()
29 | @Field()
30 | projectId: string
31 |
32 | }
--------------------------------------------------------------------------------
/employee-gql-service/src/graphql-schema.gql:
--------------------------------------------------------------------------------
1 | # ------------------------------------------------------
2 | # THIS FILE WAS AUTOMATICALLY GENERATED (DO NOT MODIFY)
3 | # ------------------------------------------------------
4 |
5 | type Employee {
6 | id: String!
7 | firstName: String!
8 | lastName: String!
9 | designation: String!
10 | city: String
11 | project: Project!
12 | projectId: String!
13 | }
14 |
15 | type Project {
16 | id: String!
17 | name: String!
18 | code: Int!
19 | employees: [Employee!]
20 | }
21 |
22 | type Query {
23 | getAllEmployees: [Employee!]!
24 | findOne(id: String!): Employee!
25 | getAllProjects: [Project!]!
26 | project(id: String!): Project!
27 | }
28 |
29 | type Mutation {
30 | createEmployee(employeeInput: EmployeeCreateDTO!): Employee!
31 | createProject(project: CreateProjectInput!): Project!
32 | updateProject(project: UpdateProjectInput!): Project!
33 | removeProject(id: String!): Project!
34 | }
35 |
36 | input EmployeeCreateDTO {
37 | firstName: String!
38 | lastName: String!
39 | designation: String!
40 | city: String
41 | projectId: String!
42 | }
43 |
44 | input CreateProjectInput {
45 | name: String!
46 | code: Int!
47 | }
48 |
49 | input UpdateProjectInput {
50 | id: String!
51 | name: String!
52 | code: Int!
53 | }
54 |
--------------------------------------------------------------------------------
/employee-gql-service/src/main.ts:
--------------------------------------------------------------------------------
1 | import { NestFactory } from '@nestjs/core';
2 | import { AppModule } from './app.module';
3 |
4 | async function bootstrap() {
5 | const app = await NestFactory.create(AppModule);
6 | await app.listen(3000);
7 | }
8 | bootstrap();
9 |
--------------------------------------------------------------------------------
/employee-gql-service/src/project/dto/create-project.input.ts:
--------------------------------------------------------------------------------
1 | import { InputType, Int, Field } from '@nestjs/graphql';
2 |
3 | @InputType()
4 | export class CreateProjectInput {
5 |
6 |
7 | @Field()
8 | name: string
9 | @Field(() => Int)
10 | code: number
11 | }
12 |
--------------------------------------------------------------------------------
/employee-gql-service/src/project/dto/update-project.input.ts:
--------------------------------------------------------------------------------
1 | import { CreateProjectInput } from './create-project.input';
2 | import { InputType, Field, Int, PartialType } from '@nestjs/graphql';
3 |
4 | @InputType()
5 | export class UpdateProjectInput {
6 |
7 | @Field()
8 | id: string
9 | @Field()
10 | name: string
11 | @Field(() => Int)
12 | code: number
13 |
14 |
15 | }
16 |
--------------------------------------------------------------------------------
/employee-gql-service/src/project/entities/project.entity.ts:
--------------------------------------------------------------------------------
1 | import { ObjectType, Field, Int } from '@nestjs/graphql';
2 | import { Employee } from 'src/employee/entities/employee.entity';
3 | import { Column, Entity, OneToMany, PrimaryGeneratedColumn } from 'typeorm';
4 |
5 | @ObjectType()
6 | @Entity()
7 | export class Project {
8 |
9 | @Field()
10 | @PrimaryGeneratedColumn('uuid')
11 | id: string
12 | @Field()
13 | @Column()
14 | name: string
15 | @Field(() => Int)
16 | @Column()
17 | code: number
18 |
19 | @OneToMany(() => Employee, employee => employee.project)
20 | @Field(() => [Employee], { nullable: true })
21 | employees: Employee[]
22 |
23 | }
24 |
--------------------------------------------------------------------------------
/employee-gql-service/src/project/project.module.ts:
--------------------------------------------------------------------------------
1 | import { Module } from '@nestjs/common';
2 | import { ProjectService } from './project.service';
3 | import { ProjectResolver } from './project.resolver';
4 | import { TypeOrmModule } from '@nestjs/typeorm';
5 | import { Project } from './entities/project.entity';
6 |
7 | @Module({
8 | imports: [TypeOrmModule.forFeature([Project])],
9 | providers: [ProjectResolver, ProjectService],
10 | exports: [ProjectService]
11 | })
12 | export class ProjectModule { }
13 |
--------------------------------------------------------------------------------
/employee-gql-service/src/project/project.resolver.ts:
--------------------------------------------------------------------------------
1 | import { Resolver, Query, Mutation, Args, Int } from '@nestjs/graphql';
2 | import { ProjectService } from './project.service';
3 | import { Project } from './entities/project.entity';
4 | import { CreateProjectInput } from './dto/create-project.input';
5 | import { UpdateProjectInput } from './dto/update-project.input';
6 |
7 | @Resolver(() => Project)
8 | export class ProjectResolver {
9 | constructor(private readonly projectService: ProjectService) { }
10 |
11 | @Mutation(() => Project)
12 | createProject(@Args('project') project: CreateProjectInput) {
13 | return this.projectService.create(project);
14 | }
15 |
16 | @Query(() => [Project], { name: 'getAllProjects' })
17 | findAll() {
18 | return this.projectService.findAll();
19 | }
20 |
21 | @Query(() => Project, { name: 'project' })
22 | findOne(@Args('id') id: string) {
23 | return this.projectService.findOne(id);
24 | }
25 |
26 | @Mutation(() => Project)
27 | updateProject(@Args('project') project: UpdateProjectInput) {
28 | return this.projectService.update(project.id, project);
29 | }
30 |
31 | @Mutation(() => Project)
32 | removeProject(@Args('id') id: string) {
33 | return this.projectService.remove(id);
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/employee-gql-service/src/project/project.service.ts:
--------------------------------------------------------------------------------
1 | import { Injectable, NotFoundException } from '@nestjs/common';
2 | import { InjectRepository } from '@nestjs/typeorm';
3 | import { Repository } from 'typeorm';
4 | import { CreateProjectInput } from './dto/create-project.input';
5 | import { UpdateProjectInput } from './dto/update-project.input';
6 | import { Project } from './entities/project.entity';
7 |
8 | @Injectable()
9 | export class ProjectService {
10 |
11 | constructor(@InjectRepository(Project) private projectRepository: Repository) { }
12 |
13 | create(project: CreateProjectInput): Promise {
14 | let proj = this.projectRepository.create(project);
15 | return this.projectRepository.save(proj) //you can directly use this without create. depends on DTO. this explained in video
16 |
17 | }
18 |
19 | async findAll(): Promise {
20 | return this.projectRepository.find({
21 | relations: ["employees"]
22 | });
23 | }
24 |
25 | async findOne(id: string): Promise {
26 | return this.projectRepository.findOne(id, { relations: ["employees"] });
27 | }
28 |
29 | update(id: string, updateProjectInput: UpdateProjectInput) {
30 | let project: Project = this.projectRepository.create(updateProjectInput)
31 | project.id = id;
32 | return this.projectRepository.save(project)
33 | }
34 |
35 | async remove(id: string) {
36 | let proj = this.findOne(id)
37 | if (proj) {
38 | let ret = await this.projectRepository.delete(id)
39 | if (ret.affected === 1) {
40 | return proj;
41 | }
42 | }
43 | throw new NotFoundException(`Record cannot find by id ${id}`)
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/employee-gql-service/test/app.e2e-spec.ts:
--------------------------------------------------------------------------------
1 | import { Test, TestingModule } from '@nestjs/testing';
2 | import { INestApplication } from '@nestjs/common';
3 | import * as request from 'supertest';
4 | import { AppModule } from './../src/app.module';
5 |
6 | describe('AppController (e2e)', () => {
7 | let app: INestApplication;
8 |
9 | beforeEach(async () => {
10 | const moduleFixture: TestingModule = await Test.createTestingModule({
11 | imports: [AppModule],
12 | }).compile();
13 |
14 | app = moduleFixture.createNestApplication();
15 | await app.init();
16 | });
17 |
18 | it('/ (GET)', () => {
19 | return request(app.getHttpServer())
20 | .get('/')
21 | .expect(200)
22 | .expect('Hello World!');
23 | });
24 | });
25 |
--------------------------------------------------------------------------------
/employee-gql-service/test/jest-e2e.json:
--------------------------------------------------------------------------------
1 | {
2 | "moduleFileExtensions": ["js", "json", "ts"],
3 | "rootDir": ".",
4 | "testEnvironment": "node",
5 | "testRegex": ".e2e-spec.ts$",
6 | "transform": {
7 | "^.+\\.(t|j)s$": "ts-jest"
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/employee-gql-service/tsconfig.build.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./tsconfig.json",
3 | "exclude": ["node_modules", "test", "dist", "**/*spec.ts"]
4 | }
5 |
--------------------------------------------------------------------------------
/employee-gql-service/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "module": "commonjs",
4 | "declaration": true,
5 | "removeComments": true,
6 | "emitDecoratorMetadata": true,
7 | "experimentalDecorators": true,
8 | "allowSyntheticDefaultImports": true,
9 | "target": "es2017",
10 | "sourceMap": true,
11 | "outDir": "./dist",
12 | "baseUrl": "./",
13 | "incremental": true
14 | }
15 | }
16 |
--------------------------------------------------------------------------------