├── .eslintrc.js ├── .gitignore ├── .prettierrc ├── CODE_OF_CONDUCT.md ├── LICENSE ├── README.md ├── dist ├── app.controller.d.ts ├── app.controller.js ├── app.controller.js.map ├── app.module.d.ts ├── app.module.js ├── app.module.js.map ├── app.service.d.ts ├── app.service.js ├── app.service.js.map ├── articles │ ├── articles.controller.d.ts │ ├── articles.controller.js │ ├── articles.controller.js.map │ ├── articles.module.d.ts │ ├── articles.module.js │ ├── articles.module.js.map │ ├── articles.service.d.ts │ ├── articles.service.js │ ├── articles.service.js.map │ └── dto │ │ ├── article.dto.d.ts │ │ ├── article.dto.js │ │ ├── article.dto.js.map │ │ ├── comment.dto.d.ts │ │ ├── comment.dto.js │ │ ├── comment.dto.js.map │ │ ├── index.d.ts │ │ ├── index.js │ │ └── index.js.map ├── auth │ ├── auth.controller.d.ts │ ├── auth.controller.js │ ├── auth.controller.js.map │ ├── auth.module.d.ts │ ├── auth.module.js │ ├── auth.module.js.map │ ├── auth.service.d.ts │ ├── auth.service.js │ ├── auth.service.js.map │ ├── dto │ │ ├── index.d.ts │ │ ├── index.js │ │ ├── index.js.map │ │ ├── user.dto.d.ts │ │ ├── user.dto.js │ │ └── user.dto.js.map │ └── strategy │ │ ├── index.d.ts │ │ ├── index.js │ │ ├── index.js.map │ │ ├── jwt.strategy.d.ts │ │ ├── jwt.strategy.js │ │ └── jwt.strategy.js.map ├── common │ ├── decorator │ │ ├── allow-any.decorator.d.ts │ │ ├── allow-any.decorator.js │ │ ├── allow-any.decorator.js.map │ │ ├── get-user.decorator.d.ts │ │ ├── get-user.decorator.js │ │ ├── get-user.decorator.js.map │ │ ├── index.d.ts │ │ ├── index.js │ │ └── index.js.map │ ├── filters │ │ ├── prisma-exceptions.filter.d.ts │ │ ├── prisma-exceptions.filter.js │ │ └── prisma-exceptions.filter.js.map │ └── guard │ │ ├── index.d.ts │ │ ├── index.js │ │ ├── index.js.map │ │ ├── jwt.guard.d.ts │ │ ├── jwt.guard.js │ │ └── jwt.guard.js.map ├── main.d.ts ├── main.js ├── main.js.map ├── prisma │ ├── prisma.module.d.ts │ ├── prisma.module.js │ ├── prisma.module.js.map │ ├── prisma.service.d.ts │ ├── prisma.service.js │ └── prisma.service.js.map ├── profiles │ ├── dto │ │ ├── index.d.ts │ │ ├── index.js │ │ ├── index.js.map │ │ ├── profile.dto.d.ts │ │ ├── profile.dto.js │ │ └── profile.dto.js.map │ ├── profiles.controller.d.ts │ ├── profiles.controller.js │ ├── profiles.controller.js.map │ ├── profiles.module.d.ts │ ├── profiles.module.js │ ├── profiles.module.js.map │ ├── profiles.service.d.ts │ ├── profiles.service.js │ └── profiles.service.js.map ├── tags │ ├── tags.controller.d.ts │ ├── tags.controller.js │ ├── tags.controller.js.map │ ├── tags.module.d.ts │ ├── tags.module.js │ ├── tags.module.js.map │ ├── tags.service.d.ts │ ├── tags.service.js │ └── tags.service.js.map ├── tsconfig.build.tsbuildinfo └── user │ ├── dto │ ├── index.d.ts │ ├── index.js │ ├── index.js.map │ ├── profile.dto.d.ts │ ├── profile.dto.js │ ├── profile.dto.js.map │ ├── user.dto.d.ts │ ├── user.dto.js │ └── user.dto.js.map │ ├── user.controller.d.ts │ ├── user.controller.js │ ├── user.controller.js.map │ ├── user.module.d.ts │ ├── user.module.js │ ├── user.module.js.map │ ├── user.service.d.ts │ ├── user.service.js │ └── user.service.js.map ├── favicon.ico ├── logo.png ├── nest-cli.json ├── package-lock.json ├── package.json ├── prisma └── schema.prisma ├── src ├── app.controller.spec.ts ├── app.controller.ts ├── app.module.ts ├── app.service.ts ├── articles │ ├── articles.controller.spec.ts │ ├── articles.controller.ts │ ├── articles.module.ts │ ├── articles.service.spec.ts │ ├── articles.service.ts │ └── dto │ │ ├── article.dto.ts │ │ ├── comment.dto.ts │ │ └── index.ts ├── auth │ ├── auth.controller.spec.ts │ ├── auth.controller.ts │ ├── auth.module.ts │ ├── auth.service.spec.ts │ ├── auth.service.ts │ ├── dto │ │ ├── index.ts │ │ └── user.dto.ts │ └── strategy │ │ ├── index.ts │ │ └── jwt.strategy.ts ├── common │ ├── decorator │ │ ├── allow-any.decorator.ts │ │ ├── get-user.decorator.ts │ │ └── index.ts │ ├── filters │ │ └── prisma-exceptions.filter.ts │ └── guard │ │ ├── index.ts │ │ └── jwt.guard.ts ├── main.ts ├── prisma │ ├── prisma.module.ts │ ├── prisma.service.spec.ts │ └── prisma.service.ts ├── profiles │ ├── dto │ │ ├── index.ts │ │ └── profile.dto.ts │ ├── profiles.controller.spec.ts │ ├── profiles.controller.ts │ ├── profiles.module.ts │ ├── profiles.service.spec.ts │ └── profiles.service.ts ├── tags │ ├── tags.controller.spec.ts │ ├── tags.controller.ts │ ├── tags.module.ts │ ├── tags.service.spec.ts │ └── tags.service.ts └── user │ ├── dto │ ├── index.ts │ ├── profile.dto.ts │ └── user.dto.ts │ ├── user.controller.spec.ts │ ├── user.controller.ts │ ├── user.module.ts │ ├── user.service.spec.ts │ └── user.service.ts ├── test ├── app.e2e-spec.ts └── jest-e2e.json ├── tsconfig.build.json └── tsconfig.json /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | parser: '@typescript-eslint/parser', 3 | parserOptions: { 4 | project: 'tsconfig.json', 5 | tsconfigRootDir : __dirname, 6 | sourceType: 'module', 7 | }, 8 | plugins: ['@typescript-eslint/eslint-plugin'], 9 | extends: [ 10 | 'plugin:@typescript-eslint/recommended', 11 | 'plugin:prettier/recommended', 12 | ], 13 | root: true, 14 | env: { 15 | node: true, 16 | jest: true, 17 | }, 18 | ignorePatterns: ['.eslintrc.js'], 19 | rules: { 20 | '@typescript-eslint/interface-name-prefix': 'off', 21 | '@typescript-eslint/explicit-function-return-type': 'off', 22 | '@typescript-eslint/explicit-module-boundary-types': 'off', 23 | '@typescript-eslint/no-explicit-any': 'off', 24 | }, 25 | }; 26 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | # Keep environment variables out of version control 3 | .env 4 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "singleQuote": true, 3 | "trailingComma": "all" 4 | 5 | } 6 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | We as members, contributors, and leaders pledge to make participation in our 6 | community a harassment-free experience for everyone, regardless of age, body 7 | size, visible or invisible disability, ethnicity, sex characteristics, gender 8 | identity and expression, level of experience, education, socio-economic status, 9 | nationality, personal appearance, race, religion, or sexual identity 10 | and orientation. 11 | 12 | We pledge to act and interact in ways that contribute to an open, welcoming, 13 | diverse, inclusive, and healthy community. 14 | 15 | ## Our Standards 16 | 17 | Examples of behavior that contributes to a positive environment for our 18 | community include: 19 | 20 | * Demonstrating empathy and kindness toward other people 21 | * Being respectful of differing opinions, viewpoints, and experiences 22 | * Giving and gracefully accepting constructive feedback 23 | * Accepting responsibility and apologizing to those affected by our mistakes, 24 | and learning from the experience 25 | * Focusing on what is best not just for us as individuals, but for the 26 | overall community 27 | 28 | Examples of unacceptable behavior include: 29 | 30 | * The use of sexualized language or imagery, and sexual attention or 31 | advances of any kind 32 | * Trolling, insulting or derogatory comments, and personal or political attacks 33 | * Public or private harassment 34 | * Publishing others' private information, such as a physical or email 35 | address, without their explicit permission 36 | * Other conduct which could reasonably be considered inappropriate in a 37 | professional setting 38 | 39 | ## Enforcement Responsibilities 40 | 41 | Community leaders are responsible for clarifying and enforcing our standards of 42 | acceptable behavior and will take appropriate and fair corrective action in 43 | response to any behavior that they deem inappropriate, threatening, offensive, 44 | or harmful. 45 | 46 | Community leaders have the right and responsibility to remove, edit, or reject 47 | comments, commits, code, wiki edits, issues, and other contributions that are 48 | not aligned to this Code of Conduct, and will communicate reasons for moderation 49 | decisions when appropriate. 50 | 51 | ## Scope 52 | 53 | This Code of Conduct applies within all community spaces, and also applies when 54 | an individual is officially representing the community in public spaces. 55 | Examples of representing our community include using an official e-mail address, 56 | posting via an official social media account, or acting as an appointed 57 | representative at an online or offline event. 58 | 59 | ## Enforcement 60 | 61 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 62 | reported to the community leaders responsible for enforcement by contacting the maintainer team 63 | . 64 | All complaints will be reviewed and investigated promptly and fairly. 65 | 66 | All community leaders are obligated to respect the privacy and security of the 67 | reporter of any incident. 68 | 69 | ## Enforcement Guidelines 70 | 71 | Community leaders will follow these Community Impact Guidelines in determining 72 | the consequences for any action they deem in violation of this Code of Conduct: 73 | 74 | ### 1. Correction 75 | 76 | **Community Impact**: Use of inappropriate language or other behavior deemed 77 | unprofessional or unwelcome in the community. 78 | 79 | **Consequence**: A private, written warning from community leaders, providing 80 | clarity around the nature of the violation and an explanation of why the 81 | behavior was inappropriate. A public apology may be requested. 82 | 83 | ### 2. Warning 84 | 85 | **Community Impact**: A violation through a single incident or series 86 | of actions. 87 | 88 | **Consequence**: A warning with consequences for continued behavior. No 89 | interaction with the people involved, including unsolicited interaction with 90 | those enforcing the Code of Conduct, for a specified period of time. This 91 | includes avoiding interactions in community spaces as well as external channels 92 | like social media. Violating these terms may lead to a temporary or 93 | permanent ban. 94 | 95 | ### 3. Temporary Ban 96 | 97 | **Community Impact**: A serious violation of community standards, including 98 | sustained inappropriate behavior. 99 | 100 | **Consequence**: A temporary ban from any sort of interaction or public 101 | communication with the community for a specified period of time. No public or 102 | private interaction with the people involved, including unsolicited interaction 103 | with those enforcing the Code of Conduct, is allowed during this period. 104 | Violating these terms may lead to a permanent ban. 105 | 106 | ### 4. Permanent Ban 107 | 108 | **Community Impact**: Demonstrating a pattern of violation of community 109 | standards, including sustained inappropriate behavior, harassment of an 110 | individual, or aggression toward or disparagement of classes of individuals. 111 | 112 | **Consequence**: A permanent ban from any sort of public interaction within 113 | the community. 114 | 115 | ## Attribution 116 | 117 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], 118 | version 2.0, available at 119 | https://www.contributor-covenant.org/version/2/0/code_of_conduct.html. 120 | 121 | Community Impact Guidelines were inspired by [Mozilla's code of conduct 122 | enforcement ladder](https://github.com/mozilla/diversity). 123 | 124 | [homepage]: https://www.contributor-covenant.org 125 | 126 | For answers to common questions about this code of conduct, see the FAQ at 127 | https://www.contributor-covenant.org/faq. Translations are available at 128 | https://www.contributor-covenant.org/translations. 129 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 RealWorld 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ![RealWorld Example App](logo.png) 2 | 3 | > ### Nestjs codebase containing real world examples (CRUD, auth, advanced patterns, etc) that adheres to the [RealWorld](https://github.com/gothinkster/realworld) spec and API. 4 | 5 | 6 | ### [Demo](https://demo.realworld.io/)    [RealWorld](https://github.com/gothinkster/realworld) 7 | 8 | 9 | This codebase was created to demonstrate a fully fledged fullstack application built with Nestjs including CRUD operations, authentication, routing, pagination, and more. 10 | 11 | We've gone to great lengths to adhere to the Nestjscommunity styleguides & best practices. 12 | 13 | For more information on how to this works with other frontends/backends, head over to the [RealWorld](https://github.com/gothinkster/realworld) repo. 14 | 15 | 16 | # How it works 17 | This implementation works with nestjs connected to a mongodb database running as a replica set. The database transactions are carried out with prisma as a orm. 18 | # Getting started 19 | To run locally ensure mongodb is installed on your system and a mongod process is running as a replication set. 20 | To start a mongod process as a replication set look [here](https://docs.mongodb.com/manual/tutorial/convert-standalone-to-replica-set/) 21 | ## Installation 22 | 23 | ```bash 24 | $ npm install 25 | ``` 26 | start the mongod process (if it's not running as a windows service) 27 | ```bash 28 | mongod --replSet rs0 29 | ``` 30 | generate prisma types and push schema to mongod database 31 | ```bash 32 | prisma generate 33 | 34 | prisma db push 35 | ``` 36 | 37 | ## Running the app 38 | start the mongod process (if it's not running as a windows service) 39 | ```bash 40 | mongod --replSet rs0 41 | ``` 42 | In a different console 43 | ```bash 44 | # development 45 | $ npm run start 46 | 47 | # watch mode 48 | $ npm run start:dev 49 | 50 | # production mode 51 | $ npm run start:prod 52 | ``` 53 | 54 | ## Test 55 | 56 | ```bash 57 | # unit tests 58 | $ npm run test 59 | 60 | # e2e tests 61 | $ npm run test:e2e 62 | 63 | # test coverage 64 | $ npm run test:cov 65 | ``` 66 | 67 | -------------------------------------------------------------------------------- /dist/app.controller.d.ts: -------------------------------------------------------------------------------- 1 | import { AppService } from './app.service'; 2 | export declare class AppController { 3 | private readonly appService; 4 | constructor(appService: AppService); 5 | getHello(): string; 6 | } 7 | -------------------------------------------------------------------------------- /dist/app.controller.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { 3 | var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; 4 | if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); 5 | else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; 6 | return c > 3 && r && Object.defineProperty(target, key, r), r; 7 | }; 8 | var __metadata = (this && this.__metadata) || function (k, v) { 9 | if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); 10 | }; 11 | Object.defineProperty(exports, "__esModule", { value: true }); 12 | exports.AppController = void 0; 13 | const common_1 = require("@nestjs/common"); 14 | const app_service_1 = require("./app.service"); 15 | let AppController = class AppController { 16 | constructor(appService) { 17 | this.appService = appService; 18 | } 19 | getHello() { 20 | return this.appService.getHello(); 21 | } 22 | }; 23 | __decorate([ 24 | (0, common_1.Get)(), 25 | __metadata("design:type", Function), 26 | __metadata("design:paramtypes", []), 27 | __metadata("design:returntype", String) 28 | ], AppController.prototype, "getHello", null); 29 | AppController = __decorate([ 30 | (0, common_1.Controller)(), 31 | __metadata("design:paramtypes", [app_service_1.AppService]) 32 | ], AppController); 33 | exports.AppController = AppController; 34 | //# sourceMappingURL=app.controller.js.map -------------------------------------------------------------------------------- /dist/app.controller.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"app.controller.js","sourceRoot":"","sources":["../src/app.controller.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,2CAAiD;AACjD,+CAA2C;AAGpC,IAAM,aAAa,GAAnB,MAAM,aAAa;IACxB,YAA6B,UAAsB;QAAtB,eAAU,GAAV,UAAU,CAAY;IAAG,CAAC;IAGvD,QAAQ;QACN,OAAO,IAAI,CAAC,UAAU,CAAC,QAAQ,EAAE,CAAC;IACpC,CAAC;CACF,CAAA;AAJC;IAAC,IAAA,YAAG,GAAE;;;;6CAGL;AANU,aAAa;IADzB,IAAA,mBAAU,GAAE;qCAE8B,wBAAU;GADxC,aAAa,CAOzB;AAPY,sCAAa"} -------------------------------------------------------------------------------- /dist/app.module.d.ts: -------------------------------------------------------------------------------- 1 | export declare class AppModule { 2 | } 3 | -------------------------------------------------------------------------------- /dist/app.module.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { 3 | var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; 4 | if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); 5 | else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; 6 | return c > 3 && r && Object.defineProperty(target, key, r), r; 7 | }; 8 | Object.defineProperty(exports, "__esModule", { value: true }); 9 | exports.AppModule = void 0; 10 | const common_1 = require("@nestjs/common"); 11 | const prisma_module_1 = require("./prisma/prisma.module"); 12 | const profiles_module_1 = require("./profiles/profiles.module"); 13 | const auth_module_1 = require("./auth/auth.module"); 14 | const tags_module_1 = require("./tags/tags.module"); 15 | const user_module_1 = require("./user/user.module"); 16 | const articles_module_1 = require("./articles/articles.module"); 17 | const config_1 = require("@nestjs/config"); 18 | let AppModule = class AppModule { 19 | }; 20 | AppModule = __decorate([ 21 | (0, common_1.Module)({ 22 | imports: [ 23 | prisma_module_1.PrismaModule, 24 | profiles_module_1.ProfilesModule, 25 | auth_module_1.AuthModule, 26 | tags_module_1.TagsModule, 27 | user_module_1.UserModule, 28 | articles_module_1.ArticlesModule, 29 | config_1.ConfigModule.forRoot({ 30 | isGlobal: true, 31 | }), 32 | ], 33 | }) 34 | ], AppModule); 35 | exports.AppModule = AppModule; 36 | //# sourceMappingURL=app.module.js.map -------------------------------------------------------------------------------- /dist/app.module.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"app.module.js","sourceRoot":"","sources":["../src/app.module.ts"],"names":[],"mappings":";;;;;;;;;AAAA,2CAAwC;AACxC,0DAAsD;AACtD,gEAA4D;AAC5D,oDAAgD;AAChD,oDAAgD;AAChD,oDAAgD;AAChD,gEAA4D;AAC5D,2CAA8C;AAevC,IAAM,SAAS,GAAf,MAAM,SAAS;CAAG,CAAA;AAAZ,SAAS;IAbrB,IAAA,eAAM,EAAC;QACN,OAAO,EAAE;YACP,4BAAY;YACZ,gCAAc;YACd,wBAAU;YACV,wBAAU;YACV,wBAAU;YACV,gCAAc;YACd,qBAAY,CAAC,OAAO,CAAC;gBACnB,QAAQ,EAAE,IAAI;aACf,CAAC;SACH;KACF,CAAC;GACW,SAAS,CAAG;AAAZ,8BAAS"} -------------------------------------------------------------------------------- /dist/app.service.d.ts: -------------------------------------------------------------------------------- 1 | export declare class AppService { 2 | getHello(): string; 3 | } 4 | -------------------------------------------------------------------------------- /dist/app.service.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { 3 | var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; 4 | if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); 5 | else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; 6 | return c > 3 && r && Object.defineProperty(target, key, r), r; 7 | }; 8 | Object.defineProperty(exports, "__esModule", { value: true }); 9 | exports.AppService = void 0; 10 | const common_1 = require("@nestjs/common"); 11 | let AppService = class AppService { 12 | getHello() { 13 | return 'Hello World!'; 14 | } 15 | }; 16 | AppService = __decorate([ 17 | (0, common_1.Injectable)() 18 | ], AppService); 19 | exports.AppService = AppService; 20 | //# sourceMappingURL=app.service.js.map -------------------------------------------------------------------------------- /dist/app.service.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"app.service.js","sourceRoot":"","sources":["../src/app.service.ts"],"names":[],"mappings":";;;;;;;;;AAAA,2CAA4C;AAGrC,IAAM,UAAU,GAAhB,MAAM,UAAU;IACrB,QAAQ;QACN,OAAO,cAAc,CAAC;IACxB,CAAC;CACF,CAAA;AAJY,UAAU;IADtB,IAAA,mBAAU,GAAE;GACA,UAAU,CAItB;AAJY,gCAAU"} -------------------------------------------------------------------------------- /dist/articles/articles.controller.d.ts: -------------------------------------------------------------------------------- 1 | import { User } from '@prisma/client'; 2 | import { ArticlesService } from './articles.service'; 3 | export declare class ArticlesController { 4 | private articleService; 5 | constructor(articleService: ArticlesService); 6 | getAllArticles(user: User, tag?: string, author?: string, favorited?: string, limit?: number, offset?: number): Promise<{ 7 | articles: import("./dto").ArticleDto[]; 8 | articlesCount: number; 9 | }>; 10 | getUserFeed(user: User, limit?: number, offset?: number): Promise<{ 11 | articles: import("./dto").ArticleDto[]; 12 | articlesCount: number; 13 | }>; 14 | getArticle(user: User, slug: string): Promise<{ 15 | article: import("./dto").ArticleDto; 16 | }>; 17 | createArticle(user: User, dto: any): Promise<{ 18 | article: import("./dto").ArticleDto; 19 | }>; 20 | updateArticle(user: User, slug: string, dto: any): Promise<{ 21 | article: import("./dto").ArticleDto; 22 | }>; 23 | deleteArticle(slug: string): Promise; 24 | addCommentToArticle(user: User, slug: string, dto: any): Promise<{ 25 | comment: import("./dto").CommentDto; 26 | }>; 27 | getCommentsForArticle(slug: string): Promise<{ 28 | comments: import("./dto").CommentDto[]; 29 | }>; 30 | deleteComment(slug: string, id: string): Promise; 31 | favoriteArticle(user: User, slug: string): Promise<{ 32 | article: import("./dto").ArticleDto; 33 | }>; 34 | unfavoriteArticle(user: User, slug: string): Promise<{ 35 | article: import("./dto").ArticleDto; 36 | }>; 37 | } 38 | -------------------------------------------------------------------------------- /dist/articles/articles.controller.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { 3 | var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; 4 | if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); 5 | else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; 6 | return c > 3 && r && Object.defineProperty(target, key, r), r; 7 | }; 8 | var __metadata = (this && this.__metadata) || function (k, v) { 9 | if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); 10 | }; 11 | var __param = (this && this.__param) || function (paramIndex, decorator) { 12 | return function (target, key) { decorator(target, key, paramIndex); } 13 | }; 14 | Object.defineProperty(exports, "__esModule", { value: true }); 15 | exports.ArticlesController = void 0; 16 | const common_1 = require("@nestjs/common"); 17 | const decorator_1 = require("../common/decorator"); 18 | const guard_1 = require("../common/guard"); 19 | const articles_service_1 = require("./articles.service"); 20 | let ArticlesController = class ArticlesController { 21 | constructor(articleService) { 22 | this.articleService = articleService; 23 | } 24 | async getAllArticles(user, tag, author, favorited, limit = 10, offset = 0) { 25 | const articles = await this.articleService.findArticles(user, tag, author, favorited, limit, offset); 26 | return { 27 | articles: articles, 28 | articlesCount: articles.length, 29 | }; 30 | } 31 | async getUserFeed(user, limit = 10, offset = 0) { 32 | const articles = await this.articleService.getUserFeed(user, limit, offset); 33 | return { 34 | articles: articles, 35 | articlesCount: articles.length, 36 | }; 37 | } 38 | async getArticle(user, slug) { 39 | return { article: await this.articleService.findArticle(user, slug) }; 40 | } 41 | async createArticle(user, dto) { 42 | return { 43 | article: await this.articleService.createArticle(user, dto), 44 | }; 45 | } 46 | async updateArticle(user, slug, dto) { 47 | return { 48 | article: await this.articleService.updateArticle(user, slug, dto.article), 49 | }; 50 | } 51 | deleteArticle(slug) { 52 | return this.articleService.deleteArticle(slug); 53 | } 54 | async addCommentToArticle(user, slug, dto) { 55 | return { 56 | comment: await this.articleService.addCommentToArticle(user, slug, dto.comment), 57 | }; 58 | } 59 | async getCommentsForArticle(slug) { 60 | return { comments: await this.articleService.getCommentsForArticle(slug) }; 61 | } 62 | deleteComment(slug, id) { 63 | return this.articleService.deleteCommentForArticle(slug, id); 64 | } 65 | async favoriteArticle(user, slug) { 66 | return { article: await this.articleService.favouriteArticle(user, slug) }; 67 | } 68 | async unfavoriteArticle(user, slug) { 69 | return { 70 | article: await this.articleService.unfavouriteArticle(user, slug), 71 | }; 72 | } 73 | }; 74 | __decorate([ 75 | (0, common_1.Get)(), 76 | (0, common_1.UseGuards)(guard_1.JwtGuard), 77 | (0, decorator_1.AllowAny)(), 78 | __param(0, (0, decorator_1.GetUser)()), 79 | __param(1, (0, common_1.Query)('tag')), 80 | __param(2, (0, common_1.Query)('author')), 81 | __param(3, (0, common_1.Query)('favorited')), 82 | __param(4, (0, common_1.Query)('limit')), 83 | __param(5, (0, common_1.Query)('offset')), 84 | __metadata("design:type", Function), 85 | __metadata("design:paramtypes", [Object, String, String, String, Object, Object]), 86 | __metadata("design:returntype", Promise) 87 | ], ArticlesController.prototype, "getAllArticles", null); 88 | __decorate([ 89 | (0, common_1.UseGuards)(guard_1.JwtGuard), 90 | (0, common_1.Get)('feed'), 91 | __param(0, (0, decorator_1.GetUser)()), 92 | __param(1, (0, common_1.Query)('limit')), 93 | __param(2, (0, common_1.Query)('offset')), 94 | __metadata("design:type", Function), 95 | __metadata("design:paramtypes", [Object, Object, Object]), 96 | __metadata("design:returntype", Promise) 97 | ], ArticlesController.prototype, "getUserFeed", null); 98 | __decorate([ 99 | (0, common_1.Get)(':slug'), 100 | __param(0, (0, decorator_1.GetUser)()), 101 | __param(1, (0, common_1.Param)('slug')), 102 | __metadata("design:type", Function), 103 | __metadata("design:paramtypes", [Object, String]), 104 | __metadata("design:returntype", Promise) 105 | ], ArticlesController.prototype, "getArticle", null); 106 | __decorate([ 107 | (0, common_1.UseGuards)(guard_1.JwtGuard), 108 | (0, common_1.Post)(), 109 | __param(0, (0, decorator_1.GetUser)()), 110 | __param(1, (0, common_1.Body)('article')), 111 | __metadata("design:type", Function), 112 | __metadata("design:paramtypes", [Object, Object]), 113 | __metadata("design:returntype", Promise) 114 | ], ArticlesController.prototype, "createArticle", null); 115 | __decorate([ 116 | (0, common_1.UseGuards)(guard_1.JwtGuard), 117 | (0, common_1.Put)(':slug'), 118 | __param(0, (0, decorator_1.GetUser)()), 119 | __param(1, (0, common_1.Param)('slug')), 120 | __param(2, (0, common_1.Body)()), 121 | __metadata("design:type", Function), 122 | __metadata("design:paramtypes", [Object, String, Object]), 123 | __metadata("design:returntype", Promise) 124 | ], ArticlesController.prototype, "updateArticle", null); 125 | __decorate([ 126 | (0, common_1.HttpCode)(common_1.HttpStatus.NO_CONTENT), 127 | (0, common_1.UseGuards)(guard_1.JwtGuard), 128 | (0, common_1.Delete)(':slug'), 129 | __param(0, (0, common_1.Param)('slug')), 130 | __metadata("design:type", Function), 131 | __metadata("design:paramtypes", [String]), 132 | __metadata("design:returntype", void 0) 133 | ], ArticlesController.prototype, "deleteArticle", null); 134 | __decorate([ 135 | (0, common_1.UseGuards)(guard_1.JwtGuard), 136 | (0, common_1.Post)(':slug/comments'), 137 | __param(0, (0, decorator_1.GetUser)()), 138 | __param(1, (0, common_1.Param)('slug')), 139 | __param(2, (0, common_1.Body)()), 140 | __metadata("design:type", Function), 141 | __metadata("design:paramtypes", [Object, String, Object]), 142 | __metadata("design:returntype", Promise) 143 | ], ArticlesController.prototype, "addCommentToArticle", null); 144 | __decorate([ 145 | (0, common_1.Get)(':slug/comments'), 146 | __param(0, (0, common_1.Param)('slug')), 147 | __metadata("design:type", Function), 148 | __metadata("design:paramtypes", [String]), 149 | __metadata("design:returntype", Promise) 150 | ], ArticlesController.prototype, "getCommentsForArticle", null); 151 | __decorate([ 152 | (0, common_1.UseGuards)(guard_1.JwtGuard), 153 | (0, common_1.Delete)(':slug/comments/:id'), 154 | __param(0, (0, common_1.Param)('slug')), 155 | __param(1, (0, common_1.Param)('id')), 156 | __metadata("design:type", Function), 157 | __metadata("design:paramtypes", [String, String]), 158 | __metadata("design:returntype", void 0) 159 | ], ArticlesController.prototype, "deleteComment", null); 160 | __decorate([ 161 | (0, common_1.UseGuards)(guard_1.JwtGuard), 162 | (0, common_1.Post)(':slug/favorite'), 163 | __param(0, (0, decorator_1.GetUser)()), 164 | __param(1, (0, common_1.Param)('slug')), 165 | __metadata("design:type", Function), 166 | __metadata("design:paramtypes", [Object, String]), 167 | __metadata("design:returntype", Promise) 168 | ], ArticlesController.prototype, "favoriteArticle", null); 169 | __decorate([ 170 | (0, common_1.UseGuards)(guard_1.JwtGuard), 171 | (0, common_1.Delete)(':slug/favorite'), 172 | __param(0, (0, decorator_1.GetUser)()), 173 | __param(1, (0, common_1.Param)('slug')), 174 | __metadata("design:type", Function), 175 | __metadata("design:paramtypes", [Object, String]), 176 | __metadata("design:returntype", Promise) 177 | ], ArticlesController.prototype, "unfavoriteArticle", null); 178 | ArticlesController = __decorate([ 179 | (0, common_1.Controller)('articles'), 180 | __metadata("design:paramtypes", [articles_service_1.ArticlesService]) 181 | ], ArticlesController); 182 | exports.ArticlesController = ArticlesController; 183 | //# sourceMappingURL=articles.controller.js.map -------------------------------------------------------------------------------- /dist/articles/articles.controller.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"articles.controller.js","sourceRoot":"","sources":["../../src/articles/articles.controller.ts"],"names":[],"mappings":"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"} -------------------------------------------------------------------------------- /dist/articles/articles.module.d.ts: -------------------------------------------------------------------------------- 1 | export declare class ArticlesModule { 2 | } 3 | -------------------------------------------------------------------------------- /dist/articles/articles.module.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { 3 | var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; 4 | if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); 5 | else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; 6 | return c > 3 && r && Object.defineProperty(target, key, r), r; 7 | }; 8 | Object.defineProperty(exports, "__esModule", { value: true }); 9 | exports.ArticlesModule = void 0; 10 | const common_1 = require("@nestjs/common"); 11 | const articles_controller_1 = require("./articles.controller"); 12 | const articles_service_1 = require("./articles.service"); 13 | let ArticlesModule = class ArticlesModule { 14 | }; 15 | ArticlesModule = __decorate([ 16 | (0, common_1.Module)({ 17 | controllers: [articles_controller_1.ArticlesController], 18 | providers: [articles_service_1.ArticlesService], 19 | }) 20 | ], ArticlesModule); 21 | exports.ArticlesModule = ArticlesModule; 22 | //# sourceMappingURL=articles.module.js.map -------------------------------------------------------------------------------- /dist/articles/articles.module.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"articles.module.js","sourceRoot":"","sources":["../../src/articles/articles.module.ts"],"names":[],"mappings":";;;;;;;;;AAAA,2CAAwC;AACxC,+DAA2D;AAC3D,yDAAqD;AAM9C,IAAM,cAAc,GAApB,MAAM,cAAc;CAAG,CAAA;AAAjB,cAAc;IAJ1B,IAAA,eAAM,EAAC;QACN,WAAW,EAAE,CAAC,wCAAkB,CAAC;QACjC,SAAS,EAAE,CAAC,kCAAe,CAAC;KAC7B,CAAC;GACW,cAAc,CAAG;AAAjB,wCAAc"} -------------------------------------------------------------------------------- /dist/articles/articles.service.d.ts: -------------------------------------------------------------------------------- 1 | import { User } from '@prisma/client'; 2 | import { PrismaService } from '../prisma/prisma.service'; 3 | import { ArticleForCreateDto, ArticleForUpdateDto, CommentForCreateDto } from './dto'; 4 | export declare class ArticlesService { 5 | private prisma; 6 | constructor(prisma: PrismaService); 7 | findArticles(user: User, tag: string, author: string, favorited?: string, limit?: number, offset?: number): Promise; 8 | findArticle(user: User, slug: string): Promise; 9 | getUserFeed(user: User, limit: number, offset: number): Promise; 10 | createArticle(user: User, articletoCreate: ArticleForCreateDto): Promise; 11 | updateArticle(user: User, slug: string, dto: ArticleForUpdateDto): Promise; 12 | deleteArticle(slug: string): Promise; 13 | addCommentToArticle(user: User, slug: string, dto: CommentForCreateDto): Promise; 14 | getCommentsForArticle(slug: string): Promise; 15 | deleteCommentForArticle(slug: string, id: string): Promise; 16 | favouriteArticle(user: User, slug: string): Promise; 17 | unfavouriteArticle(user: User, slug: string): Promise; 18 | } 19 | -------------------------------------------------------------------------------- /dist/articles/articles.service.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { 3 | var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; 4 | if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); 5 | else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; 6 | return c > 3 && r && Object.defineProperty(target, key, r), r; 7 | }; 8 | var __metadata = (this && this.__metadata) || function (k, v) { 9 | if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); 10 | }; 11 | Object.defineProperty(exports, "__esModule", { value: true }); 12 | exports.ArticlesService = void 0; 13 | const common_1 = require("@nestjs/common"); 14 | const runtime_1 = require("@prisma/client/runtime"); 15 | const prisma_service_1 = require("../prisma/prisma.service"); 16 | const dto_1 = require("../profiles/dto"); 17 | const dto_2 = require("./dto"); 18 | let ArticlesService = class ArticlesService { 19 | constructor(prisma) { 20 | this.prisma = prisma; 21 | } 22 | async findArticles(user, tag, author, favorited, limit = 10, offset = 0) { 23 | let articles = await this.prisma.article.findMany({ 24 | where: { 25 | author: { 26 | username: author, 27 | }, 28 | }, 29 | take: limit, 30 | skip: offset, 31 | include: { 32 | author: true, 33 | favouritedUsers: true, 34 | }, 35 | orderBy: { 36 | updatedAt: 'desc', 37 | }, 38 | }); 39 | if (tag) 40 | articles = articles.filter((article) => article.tagList.some((db) => db === tag)); 41 | if (favorited) { 42 | const favouritedUser = await this.prisma.user.findUnique({ 43 | where: { 44 | username: favorited, 45 | }, 46 | }); 47 | if (favouritedUser) 48 | articles = articles.filter((article) => article.favouritedUserIds.includes(favouritedUser.id)); 49 | else 50 | throw new common_1.NotFoundException(`user ${favorited} not found`); 51 | } 52 | if (author) { 53 | articles = articles.filter((article) => article.author.username === author); 54 | } 55 | const articlesDto = articles.map((article) => { 56 | var _a; 57 | const following = ((_a = article.author) === null || _a === void 0 ? void 0 : _a.followersIds.includes((user === null || user === void 0 ? void 0 : user.id) || '')) || false; 58 | let authorProfile; 59 | if (!article.author) 60 | authorProfile = null; 61 | else 62 | authorProfile = (0, dto_1.castToProfile)(article.author, following); 63 | return (0, dto_2.castToArticle)(article, user, article.tagList, authorProfile); 64 | }); 65 | return articlesDto; 66 | } 67 | async findArticle(user, slug) { 68 | var _a, _b; 69 | const article = await this.prisma.article.findUnique({ 70 | where: { 71 | slug: slug, 72 | }, 73 | include: { 74 | author: true, 75 | }, 76 | }); 77 | if (article === null) 78 | throw new common_1.NotFoundException('article not found'); 79 | const following = ((_b = (_a = article.author) === null || _a === void 0 ? void 0 : _a.followersIds) === null || _b === void 0 ? void 0 : _b.includes(user === null || user === void 0 ? void 0 : user.id)) || false; 80 | const authorProfile = (0, dto_1.castToProfile)(article.author, following); 81 | return (0, dto_2.castToArticle)(article, user, article.tagList, authorProfile); 82 | } 83 | async getUserFeed(user, limit, offset) { 84 | let articles = await this.prisma.article.findMany({ 85 | include: { 86 | author: true, 87 | }, 88 | take: limit, 89 | skip: offset, 90 | orderBy: { 91 | updatedAt: 'desc', 92 | }, 93 | }); 94 | articles = articles.filter((article) => { 95 | if (!article.author) 96 | return false; 97 | return article.author.followersIds.includes(user.id) || false; 98 | }); 99 | const articlesDto = articles.map((article) => { 100 | const authorProfile = (0, dto_1.castToProfile)(article.author, true); 101 | return (0, dto_2.castToArticle)(article, user, article.tagList, authorProfile); 102 | }); 103 | return articlesDto; 104 | } 105 | async createArticle(user, articletoCreate) { 106 | const slug = articletoCreate.title.split(' ').join('-'); 107 | try { 108 | const article = await this.prisma.article.create({ 109 | data: Object.assign(Object.assign({}, articletoCreate), { authorId: user.id, slug: slug, favouritedUserIds: user.id, tagList: { 110 | set: articletoCreate.tagList, 111 | } }), 112 | }); 113 | return (0, dto_2.castToArticle)(article, user, article.tagList, (0, dto_1.castToProfile)(user, false)); 114 | } 115 | catch (error) { 116 | if (error instanceof runtime_1.PrismaClientValidationError) { 117 | throw new common_1.BadRequestException('bad request'); 118 | } 119 | } 120 | } 121 | async updateArticle(user, slug, dto) { 122 | try { 123 | const article = await this.prisma.article.update({ 124 | where: { 125 | slug: slug, 126 | }, 127 | data: Object.assign(Object.assign({}, dto), { slug: slug }), 128 | include: { 129 | author: true, 130 | }, 131 | }); 132 | return (0, dto_2.castToArticle)(article, user, article.tagList, (0, dto_1.castToProfile)(article.author, false)); 133 | } 134 | catch (error) { 135 | if (error instanceof runtime_1.PrismaClientKnownRequestError) 136 | if (error.code === 'P2025') 137 | throw new common_1.NotFoundException('article not found'); 138 | } 139 | } 140 | async deleteArticle(slug) { 141 | const article = await this.prisma.article.findUnique({ 142 | where: { slug: slug }, 143 | }); 144 | if (!article) 145 | throw new common_1.NotFoundException('article not found'); 146 | await this.prisma.article.delete({ 147 | where: { 148 | slug: slug, 149 | }, 150 | }); 151 | return; 152 | } 153 | async addCommentToArticle(user, slug, dto) { 154 | const article = await this.prisma.article.findUnique({ 155 | where: { 156 | slug: slug, 157 | }, 158 | }); 159 | if (!article) 160 | throw new common_1.NotFoundException('article not found'); 161 | const comment = await this.prisma.comment.create({ 162 | data: { 163 | articleId: article.id, 164 | body: dto.body, 165 | authorId: user.id, 166 | }, 167 | }); 168 | return (0, dto_2.castToCommentDto)(comment, (0, dto_1.castToProfile)(user, false)); 169 | } 170 | async getCommentsForArticle(slug) { 171 | const article = await this.prisma.article.findUnique({ 172 | where: { 173 | slug: slug, 174 | }, 175 | select: { 176 | comments: { 177 | include: { 178 | author: true, 179 | }, 180 | }, 181 | }, 182 | }); 183 | if (article === null) 184 | throw new common_1.NotFoundException('article not found'); 185 | return article.comments.map((comment) => { 186 | return (0, dto_2.castToCommentDto)(comment, (0, dto_1.castToProfile)(comment.author, false)); 187 | }); 188 | } 189 | async deleteCommentForArticle(slug, id) { 190 | try { 191 | await this.prisma.article.update({ 192 | where: { 193 | slug: slug, 194 | }, 195 | data: { 196 | comments: { 197 | delete: { 198 | id: id, 199 | }, 200 | }, 201 | }, 202 | }); 203 | } 204 | catch (error) { 205 | if (error instanceof runtime_1.PrismaClientKnownRequestError) 206 | if (error.code === 'P2002') 207 | throw new common_1.NotFoundException('article not found'); 208 | } 209 | } 210 | async favouriteArticle(user, slug) { 211 | var _a; 212 | let article = await this.prisma.article.findUnique({ 213 | where: { slug: slug }, 214 | include: { 215 | author: true, 216 | }, 217 | }); 218 | if (!article) 219 | throw new common_1.NotFoundException('article not found'); 220 | if (!article.favouritedUserIds.includes(user.id)) { 221 | article = await this.prisma.article.update({ 222 | where: { 223 | slug: slug, 224 | }, 225 | data: { 226 | favouritedUserIds: { 227 | push: user.id, 228 | }, 229 | }, 230 | include: { 231 | author: true, 232 | }, 233 | }); 234 | } 235 | const following = ((_a = article.author) === null || _a === void 0 ? void 0 : _a.followersIds.includes(user.id)) || false; 236 | return (0, dto_2.castToArticle)(article, user, article.tagList, (0, dto_1.castToProfile)(user, following)); 237 | } 238 | async unfavouriteArticle(user, slug) { 239 | var _a; 240 | const article = await this.prisma.article.findUnique({ 241 | where: { slug: slug }, 242 | }); 243 | if (!article) 244 | throw new common_1.NotFoundException('article not found'); 245 | article.favouritedUserIds = article.favouritedUserIds.filter((id) => id !== user.id); 246 | delete article.id; 247 | const articleUpdated = await this.prisma.article.update({ 248 | where: { slug: slug }, 249 | data: article, 250 | include: { author: true }, 251 | }); 252 | const isfollowing = ((_a = articleUpdated.author) === null || _a === void 0 ? void 0 : _a.followersIds.includes(user.id)) || false; 253 | return (0, dto_2.castToArticle)(article, user, article.tagList, (0, dto_1.castToProfile)(articleUpdated.author, isfollowing)); 254 | } 255 | }; 256 | ArticlesService = __decorate([ 257 | (0, common_1.Injectable)(), 258 | __metadata("design:paramtypes", [prisma_service_1.PrismaService]) 259 | ], ArticlesService); 260 | exports.ArticlesService = ArticlesService; 261 | //# sourceMappingURL=articles.service.js.map -------------------------------------------------------------------------------- /dist/articles/articles.service.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"articles.service.js","sourceRoot":"","sources":["../../src/articles/articles.service.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,2CAIwB;AAExB,oDAGgC;AAChC,6DAAyD;AACzD,yCAA4D;AAC5D,+BAMe;AAGR,IAAM,eAAe,GAArB,MAAM,eAAe;IAC1B,YAAoB,MAAqB;QAArB,WAAM,GAAN,MAAM,CAAe;IAAG,CAAC;IAE7C,KAAK,CAAC,YAAY,CAChB,IAAU,EACV,GAAW,EACX,MAAc,EACd,SAAkB,EAClB,KAAK,GAAG,EAAE,EACV,MAAM,GAAG,CAAC;QAEV,IAAI,QAAQ,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC;YAChD,KAAK,EAAE;gBACL,MAAM,EAAE;oBACN,QAAQ,EAAE,MAAM;iBACjB;aACF;YACD,IAAI,EAAE,KAAK;YACX,IAAI,EAAE,MAAM;YACZ,OAAO,EAAE;gBACP,MAAM,EAAE,IAAI;gBACZ,eAAe,EAAE,IAAI;aACtB;YACD,OAAO,EAAE;gBACP,SAAS,EAAE,MAAM;aAClB;SACF,CAAC,CAAC;QACH,IAAI,GAAG;YACL,QAAQ,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,OAAO,EAAE,EAAE,CACrC,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,KAAK,GAAG,CAAC,CACzC,CAAC;QAEJ,IAAI,SAAS,EAAE;YACb,MAAM,cAAc,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC;gBACvD,KAAK,EAAE;oBACL,QAAQ,EAAE,SAAS;iBACpB;aACF,CAAC,CAAC;YACH,IAAI,cAAc;gBAChB,QAAQ,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,OAAO,EAAE,EAAE,CACrC,OAAO,CAAC,iBAAiB,CAAC,QAAQ,CAAC,cAAc,CAAC,EAAE,CAAC,CACtD,CAAC;;gBACC,MAAM,IAAI,0BAAiB,CAAC,QAAQ,SAAS,YAAY,CAAC,CAAC;SACjE;QAED,IAAI,MAAM,EAAE;YACV,QAAQ,GAAG,QAAQ,CAAC,MAAM,CACxB,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,QAAQ,KAAK,MAAM,CAChD,CAAC;SACH;QAED,MAAM,WAAW,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE;;YAC3C,MAAM,SAAS,GACb,CAAA,MAAA,OAAO,CAAC,MAAM,0CAAE,YAAY,CAAC,QAAQ,CAAC,CAAA,IAAI,aAAJ,IAAI,uBAAJ,IAAI,CAAE,EAAE,KAAI,EAAE,CAAC,KAAI,KAAK,CAAC;YACjE,IAAI,aAAyB,CAAC;YAC9B,IAAI,CAAC,OAAO,CAAC,MAAM;gBAAE,aAAa,GAAG,IAAI,CAAC;;gBACrC,aAAa,GAAG,IAAA,mBAAa,EAAC,OAAO,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;YAC9D,OAAO,IAAA,mBAAa,EAAC,OAAO,EAAE,IAAI,EAAE,OAAO,CAAC,OAAO,EAAE,aAAa,CAAC,CAAC;QACtE,CAAC,CAAC,CAAC;QACH,OAAO,WAAW,CAAC;IACrB,CAAC;IAED,KAAK,CAAC,WAAW,CAAC,IAAU,EAAE,IAAY;;QACxC,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,UAAU,CAAC;YACnD,KAAK,EAAE;gBACL,IAAI,EAAE,IAAI;aACX;YACD,OAAO,EAAE;gBACP,MAAM,EAAE,IAAI;aACb;SACF,CAAC,CAAC;QACH,IAAI,OAAO,KAAK,IAAI;YAAE,MAAM,IAAI,0BAAiB,CAAC,mBAAmB,CAAC,CAAC;QAEvE,MAAM,SAAS,GAAG,CAAA,MAAA,MAAA,OAAO,CAAC,MAAM,0CAAE,YAAY,0CAAE,QAAQ,CAAC,IAAI,aAAJ,IAAI,uBAAJ,IAAI,CAAE,EAAE,CAAC,KAAI,KAAK,CAAC;QAE5E,MAAM,aAAa,GAAG,IAAA,mBAAa,EAAC,OAAO,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;QAC/D,OAAO,IAAA,mBAAa,EAAC,OAAO,EAAE,IAAI,EAAE,OAAO,CAAC,OAAO,EAAE,aAAa,CAAC,CAAC;IACtE,CAAC;IAED,KAAK,CAAC,WAAW,CAAC,IAAU,EAAE,KAAa,EAAE,MAAc;QACzD,IAAI,QAAQ,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC;YAChD,OAAO,EAAE;gBACP,MAAM,EAAE,IAAI;aACb;YACD,IAAI,EAAE,KAAK;YACX,IAAI,EAAE,MAAM;YACZ,OAAO,EAAE;gBACP,SAAS,EAAE,MAAM;aAClB;SACF,CAAC,CAAC;QACH,QAAQ,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,OAAO,EAAE,EAAE;YACrC,IAAI,CAAC,OAAO,CAAC,MAAM;gBAAE,OAAO,KAAK,CAAC;YAClC,OAAO,OAAO,CAAC,MAAM,CAAC,YAAY,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,KAAK,CAAC;QAChE,CAAC,CAAC,CAAC;QAEH,MAAM,WAAW,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE;YAC3C,MAAM,aAAa,GAAG,IAAA,mBAAa,EAAC,OAAO,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;YAC1D,OAAO,IAAA,mBAAa,EAAC,OAAO,EAAE,IAAI,EAAE,OAAO,CAAC,OAAO,EAAE,aAAa,CAAC,CAAC;QACtE,CAAC,CAAC,CAAC;QACH,OAAO,WAAW,CAAC;IACrB,CAAC;IAED,KAAK,CAAC,aAAa,CAAC,IAAU,EAAE,eAAoC;QAClE,MAAM,IAAI,GAAG,eAAe,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACxD,IAAI;YACF,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC;gBAC/C,IAAI,kCACC,eAAe,KAClB,QAAQ,EAAE,IAAI,CAAC,EAAE,EACjB,IAAI,EAAE,IAAI,EACV,iBAAiB,EAAE,IAAI,CAAC,EAAE,EAC1B,OAAO,EAAE;wBACP,GAAG,EAAE,eAAe,CAAC,OAAO;qBAC7B,GACF;aACF,CAAC,CAAC;YACH,OAAO,IAAA,mBAAa,EAClB,OAAO,EACP,IAAI,EACJ,OAAO,CAAC,OAAO,EACf,IAAA,mBAAa,EAAC,IAAI,EAAE,KAAK,CAAC,CAC3B,CAAC;SACH;QAAC,OAAO,KAAK,EAAE;YACd,IAAI,KAAK,YAAY,qCAA2B,EAAE;gBAChD,MAAM,IAAI,4BAAmB,CAAC,aAAa,CAAC,CAAC;aAC9C;SAEF;IACH,CAAC;IAED,KAAK,CAAC,aAAa,CAAC,IAAU,EAAE,IAAY,EAAE,GAAwB;QAEpE,IAAI;YACF,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC;gBAC/C,KAAK,EAAE;oBACL,IAAI,EAAE,IAAI;iBACX;gBACD,IAAI,kCACC,GAAG,KACN,IAAI,EAAE,IAAI,GACX;gBACD,OAAO,EAAE;oBACP,MAAM,EAAE,IAAI;iBACb;aACF,CAAC,CAAC;YACH,OAAO,IAAA,mBAAa,EAClB,OAAO,EACP,IAAI,EACJ,OAAO,CAAC,OAAO,EACf,IAAA,mBAAa,EAAC,OAAO,CAAC,MAAM,EAAE,KAAK,CAAC,CACrC,CAAC;SACH;QAAC,OAAO,KAAK,EAAE;YACd,IAAI,KAAK,YAAY,uCAA6B;gBAChD,IAAI,KAAK,CAAC,IAAI,KAAK,OAAO;oBACxB,MAAM,IAAI,0BAAiB,CAAC,mBAAmB,CAAC,CAAC;SACtD;IACH,CAAC;IAED,KAAK,CAAC,aAAa,CAAC,IAAY;QAC9B,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,UAAU,CAAC;YACnD,KAAK,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE;SACtB,CAAC,CAAC;QACH,IAAI,CAAC,OAAO;YAAE,MAAM,IAAI,0BAAiB,CAAC,mBAAmB,CAAC,CAAC;QAC/D,MAAM,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC;YAC/B,KAAK,EAAE;gBACL,IAAI,EAAE,IAAI;aACX;SACF,CAAC,CAAC;QACH,OAAO;IACT,CAAC;IAED,KAAK,CAAC,mBAAmB,CACvB,IAAU,EACV,IAAY,EACZ,GAAwB;QAExB,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,UAAU,CAAC;YACnD,KAAK,EAAE;gBACL,IAAI,EAAE,IAAI;aACX;SACF,CAAC,CAAC;QACH,IAAI,CAAC,OAAO;YAAE,MAAM,IAAI,0BAAiB,CAAC,mBAAmB,CAAC,CAAC;QAC/D,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC;YAC/C,IAAI,EAAE;gBACJ,SAAS,EAAE,OAAO,CAAC,EAAE;gBACrB,IAAI,EAAE,GAAG,CAAC,IAAI;gBACd,QAAQ,EAAE,IAAI,CAAC,EAAE;aAClB;SACF,CAAC,CAAC;QACH,OAAO,IAAA,sBAAgB,EAAC,OAAO,EAAE,IAAA,mBAAa,EAAC,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC;IAC/D,CAAC;IAED,KAAK,CAAC,qBAAqB,CAAC,IAAY;QACtC,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,UAAU,CAAC;YACnD,KAAK,EAAE;gBACL,IAAI,EAAE,IAAI;aACX;YACD,MAAM,EAAE;gBACN,QAAQ,EAAE;oBACR,OAAO,EAAE;wBACP,MAAM,EAAE,IAAI;qBACb;iBACF;aACF;SACF,CAAC,CAAC;QACH,IAAI,OAAO,KAAK,IAAI;YAAE,MAAM,IAAI,0BAAiB,CAAC,mBAAmB,CAAC,CAAC;QACvE,OAAO,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE;YACtC,OAAO,IAAA,sBAAgB,EAAC,OAAO,EAAE,IAAA,mBAAa,EAAC,OAAO,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC,CAAC;QACzE,CAAC,CAAC,CAAC;IACL,CAAC;IAED,KAAK,CAAC,uBAAuB,CAAC,IAAY,EAAE,EAAU;QACpD,IAAI;YACF,MAAM,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC;gBAC/B,KAAK,EAAE;oBACL,IAAI,EAAE,IAAI;iBACX;gBAED,IAAI,EAAE;oBACJ,QAAQ,EAAE;wBACR,MAAM,EAAE;4BACN,EAAE,EAAE,EAAE;yBACP;qBACF;iBACF;aACF,CAAC,CAAC;SACJ;QAAC,OAAO,KAAK,EAAE;YACd,IAAI,KAAK,YAAY,uCAA6B;gBAChD,IAAI,KAAK,CAAC,IAAI,KAAK,OAAO;oBACxB,MAAM,IAAI,0BAAiB,CAAC,mBAAmB,CAAC,CAAC;SACtD;IACH,CAAC;IAED,KAAK,CAAC,gBAAgB,CAAC,IAAU,EAAE,IAAY;;QAC7C,IAAI,OAAO,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,UAAU,CAAC;YACjD,KAAK,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE;YACrB,OAAO,EAAE;gBACP,MAAM,EAAE,IAAI;aACb;SACF,CAAC,CAAC;QACH,IAAI,CAAC,OAAO;YAAE,MAAM,IAAI,0BAAiB,CAAC,mBAAmB,CAAC,CAAC;QAC/D,IAAI,CAAC,OAAO,CAAC,iBAAiB,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE;YAChD,OAAO,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC;gBACzC,KAAK,EAAE;oBACL,IAAI,EAAE,IAAI;iBACX;gBACD,IAAI,EAAE;oBACJ,iBAAiB,EAAE;wBACjB,IAAI,EAAE,IAAI,CAAC,EAAE;qBACd;iBACF;gBACD,OAAO,EAAE;oBACP,MAAM,EAAE,IAAI;iBACb;aACF,CAAC,CAAC;SACJ;QACD,MAAM,SAAS,GAAG,CAAA,MAAA,OAAO,CAAC,MAAM,0CAAE,YAAY,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,KAAI,KAAK,CAAC;QAC1E,OAAO,IAAA,mBAAa,EAClB,OAAO,EACP,IAAI,EACJ,OAAO,CAAC,OAAO,EACf,IAAA,mBAAa,EAAC,IAAI,EAAE,SAAS,CAAC,CAC/B,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,kBAAkB,CAAC,IAAU,EAAE,IAAY;;QAC/C,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,UAAU,CAAC;YACnD,KAAK,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE;SACtB,CAAC,CAAC;QACH,IAAI,CAAC,OAAO;YAAE,MAAM,IAAI,0BAAiB,CAAC,mBAAmB,CAAC,CAAC;QAC/D,OAAO,CAAC,iBAAiB,GAAG,OAAO,CAAC,iBAAiB,CAAC,MAAM,CAC1D,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,KAAK,IAAI,CAAC,EAAE,CACvB,CAAC;QACF,OAAO,OAAO,CAAC,EAAE,CAAC;QAClB,MAAM,cAAc,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC;YACtD,KAAK,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE;YACrB,IAAI,EAAE,OAAO;YACb,OAAO,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE;SAC1B,CAAC,CAAC;QACH,MAAM,WAAW,GACf,CAAA,MAAA,cAAc,CAAC,MAAM,0CAAE,YAAY,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,KAAI,KAAK,CAAC;QACjE,OAAO,IAAA,mBAAa,EAClB,OAAO,EACP,IAAI,EACJ,OAAO,CAAC,OAAO,EACf,IAAA,mBAAa,EAAC,cAAc,CAAC,MAAM,EAAE,WAAW,CAAC,CAClD,CAAC;IACJ,CAAC;CACF,CAAA;AAhSY,eAAe;IAD3B,IAAA,mBAAU,GAAE;qCAEiB,8BAAa;GAD9B,eAAe,CAgS3B;AAhSY,0CAAe"} -------------------------------------------------------------------------------- /dist/articles/dto/article.dto.d.ts: -------------------------------------------------------------------------------- 1 | import { Article, User } from '@prisma/client'; 2 | import { ProfileDto } from '../../profiles/dto'; 3 | export interface ArticleForCreateDto { 4 | title: string; 5 | description: string; 6 | body: string; 7 | tagList?: string[]; 8 | } 9 | export interface ArticleForUpdateDto { 10 | title?: string; 11 | description?: string; 12 | body?: string; 13 | } 14 | export interface ArticleDto { 15 | slug: string; 16 | title: string; 17 | description: string; 18 | body: string; 19 | tagList?: string[]; 20 | favoritesCount: number; 21 | author: ProfileDto; 22 | favorited: boolean; 23 | createdAt: Date; 24 | updatedAt: Date; 25 | } 26 | export declare function castToArticle(article: Article, user: User, tags: string[], author: ProfileDto): ArticleDto; 27 | -------------------------------------------------------------------------------- /dist/articles/dto/article.dto.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | exports.castToArticle = void 0; 4 | function castToArticle(article, user, tags, author) { 5 | return { 6 | slug: article.slug, 7 | title: article.title, 8 | description: article.description, 9 | body: article.body, 10 | tagList: tags, 11 | createdAt: article.createdAt, 12 | updatedAt: article.updatedAt, 13 | favorited: article.favouritedUserIds.includes(user === null || user === void 0 ? void 0 : user.id) || false, 14 | favoritesCount: article.favouritedUserIds.length, 15 | author: author, 16 | }; 17 | } 18 | exports.castToArticle = castToArticle; 19 | //# sourceMappingURL=article.dto.js.map -------------------------------------------------------------------------------- /dist/articles/dto/article.dto.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"article.dto.js","sourceRoot":"","sources":["../../../src/articles/dto/article.dto.ts"],"names":[],"mappings":";;;AA6BA,SAAgB,aAAa,CAC3B,OAAgB,EAChB,IAAU,EACV,IAAc,EACd,MAAkB;IAElB,OAAO;QACL,IAAI,EAAE,OAAO,CAAC,IAAI;QAClB,KAAK,EAAE,OAAO,CAAC,KAAK;QACpB,WAAW,EAAE,OAAO,CAAC,WAAW;QAChC,IAAI,EAAE,OAAO,CAAC,IAAI;QAClB,OAAO,EAAE,IAAI;QACb,SAAS,EAAE,OAAO,CAAC,SAAS;QAC5B,SAAS,EAAE,OAAO,CAAC,SAAS;QAC5B,SAAS,EAAE,OAAO,CAAC,iBAAiB,CAAC,QAAQ,CAAC,IAAI,aAAJ,IAAI,uBAAJ,IAAI,CAAE,EAAE,CAAC,IAAI,KAAK;QAChE,cAAc,EAAE,OAAO,CAAC,iBAAiB,CAAC,MAAM;QAChD,MAAM,EAAE,MAAM;KACf,CAAC;AACJ,CAAC;AAlBD,sCAkBC"} -------------------------------------------------------------------------------- /dist/articles/dto/comment.dto.d.ts: -------------------------------------------------------------------------------- 1 | import { ProfileDto } from '../../profiles/dto'; 2 | import { Comment } from '@prisma/client'; 3 | export interface CommentForCreateDto { 4 | body: string; 5 | } 6 | export interface CommentDto { 7 | id: string; 8 | createdAt: Date; 9 | updatedAt: Date; 10 | body: string; 11 | author: ProfileDto; 12 | } 13 | export declare function castToCommentDto(comment: Comment, author: ProfileDto): CommentDto; 14 | -------------------------------------------------------------------------------- /dist/articles/dto/comment.dto.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | exports.castToCommentDto = void 0; 4 | function castToCommentDto(comment, author) { 5 | return { 6 | id: comment.id, 7 | createdAt: comment.createdAt, 8 | updatedAt: comment.updatedAt, 9 | body: comment.body, 10 | author: author, 11 | }; 12 | } 13 | exports.castToCommentDto = castToCommentDto; 14 | //# sourceMappingURL=comment.dto.js.map -------------------------------------------------------------------------------- /dist/articles/dto/comment.dto.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"comment.dto.js","sourceRoot":"","sources":["../../../src/articles/dto/comment.dto.ts"],"names":[],"mappings":";;;AAcA,SAAgB,gBAAgB,CAC9B,OAAgB,EAChB,MAAkB;IAElB,OAAO;QACL,EAAE,EAAE,OAAO,CAAC,EAAE;QACd,SAAS,EAAE,OAAO,CAAC,SAAS;QAC5B,SAAS,EAAE,OAAO,CAAC,SAAS;QAC5B,IAAI,EAAE,OAAO,CAAC,IAAI;QAClB,MAAM,EAAE,MAAM;KACf,CAAC;AACJ,CAAC;AAXD,4CAWC"} -------------------------------------------------------------------------------- /dist/articles/dto/index.d.ts: -------------------------------------------------------------------------------- 1 | export * from './article.dto'; 2 | export * from './comment.dto'; 3 | -------------------------------------------------------------------------------- /dist/articles/dto/index.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { 3 | if (k2 === undefined) k2 = k; 4 | var desc = Object.getOwnPropertyDescriptor(m, k); 5 | if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { 6 | desc = { enumerable: true, get: function() { return m[k]; } }; 7 | } 8 | Object.defineProperty(o, k2, desc); 9 | }) : (function(o, m, k, k2) { 10 | if (k2 === undefined) k2 = k; 11 | o[k2] = m[k]; 12 | })); 13 | var __exportStar = (this && this.__exportStar) || function(m, exports) { 14 | for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); 15 | }; 16 | Object.defineProperty(exports, "__esModule", { value: true }); 17 | __exportStar(require("./article.dto"), exports); 18 | __exportStar(require("./comment.dto"), exports); 19 | //# sourceMappingURL=index.js.map -------------------------------------------------------------------------------- /dist/articles/dto/index.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/articles/dto/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,gDAA8B;AAC9B,gDAA8B"} -------------------------------------------------------------------------------- /dist/auth/auth.controller.d.ts: -------------------------------------------------------------------------------- 1 | import { AuthService } from './auth.service'; 2 | import { LoginDto, UserForRegistration } from './dto'; 3 | export declare class AuthController { 4 | private readonly authService; 5 | constructor(authService: AuthService); 6 | loginUser(dto: LoginDto): Promise<{ 7 | user: import("./dto").UserDto; 8 | }>; 9 | registerUser(dto: UserForRegistration): Promise<{ 10 | user: import("./dto").UserDto; 11 | }>; 12 | } 13 | -------------------------------------------------------------------------------- /dist/auth/auth.controller.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { 3 | var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; 4 | if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); 5 | else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; 6 | return c > 3 && r && Object.defineProperty(target, key, r), r; 7 | }; 8 | var __metadata = (this && this.__metadata) || function (k, v) { 9 | if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); 10 | }; 11 | var __param = (this && this.__param) || function (paramIndex, decorator) { 12 | return function (target, key) { decorator(target, key, paramIndex); } 13 | }; 14 | Object.defineProperty(exports, "__esModule", { value: true }); 15 | exports.AuthController = void 0; 16 | const common_1 = require("@nestjs/common"); 17 | const auth_service_1 = require("./auth.service"); 18 | let AuthController = class AuthController { 19 | constructor(authService) { 20 | this.authService = authService; 21 | } 22 | async loginUser(dto) { 23 | const user = await this.authService.verifyUser(dto); 24 | return { user: user }; 25 | } 26 | async registerUser(dto) { 27 | const user = await this.authService.createUser(dto); 28 | return { user: user }; 29 | } 30 | }; 31 | __decorate([ 32 | (0, common_1.Post)('login'), 33 | __param(0, (0, common_1.Body)('user')), 34 | __metadata("design:type", Function), 35 | __metadata("design:paramtypes", [Object]), 36 | __metadata("design:returntype", Promise) 37 | ], AuthController.prototype, "loginUser", null); 38 | __decorate([ 39 | (0, common_1.Post)(), 40 | __param(0, (0, common_1.Body)('user')), 41 | __metadata("design:type", Function), 42 | __metadata("design:paramtypes", [Object]), 43 | __metadata("design:returntype", Promise) 44 | ], AuthController.prototype, "registerUser", null); 45 | AuthController = __decorate([ 46 | (0, common_1.Controller)('users'), 47 | __metadata("design:paramtypes", [auth_service_1.AuthService]) 48 | ], AuthController); 49 | exports.AuthController = AuthController; 50 | //# sourceMappingURL=auth.controller.js.map -------------------------------------------------------------------------------- /dist/auth/auth.controller.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"auth.controller.js","sourceRoot":"","sources":["../../src/auth/auth.controller.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;AAAA,2CAAwD;AACxD,iDAA6C;AAItC,IAAM,cAAc,GAApB,MAAM,cAAc;IACzB,YAA6B,WAAwB;QAAxB,gBAAW,GAAX,WAAW,CAAa;IAAG,CAAC;IAEnD,AAAN,KAAK,CAAC,SAAS,CAAe,GAAa;QACzC,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,WAAW,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC;QACpD,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;IACxB,CAAC;IAGK,AAAN,KAAK,CAAC,YAAY,CAAe,GAAwB;QACvD,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,WAAW,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC;QACpD,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;IACxB,CAAC;CACF,CAAA;AAVO;IADL,IAAA,aAAI,EAAC,OAAO,CAAC;IACG,WAAA,IAAA,aAAI,EAAC,MAAM,CAAC,CAAA;;;;+CAG5B;AAGK;IADL,IAAA,aAAI,GAAE;IACa,WAAA,IAAA,aAAI,EAAC,MAAM,CAAC,CAAA;;;;kDAG/B;AAZU,cAAc;IAD1B,IAAA,mBAAU,EAAC,OAAO,CAAC;qCAEwB,0BAAW;GAD1C,cAAc,CAa1B;AAbY,wCAAc"} -------------------------------------------------------------------------------- /dist/auth/auth.module.d.ts: -------------------------------------------------------------------------------- 1 | export declare class AuthModule { 2 | } 3 | -------------------------------------------------------------------------------- /dist/auth/auth.module.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { 3 | var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; 4 | if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); 5 | else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; 6 | return c > 3 && r && Object.defineProperty(target, key, r), r; 7 | }; 8 | Object.defineProperty(exports, "__esModule", { value: true }); 9 | exports.AuthModule = void 0; 10 | const common_1 = require("@nestjs/common"); 11 | const jwt_1 = require("@nestjs/jwt"); 12 | const auth_controller_1 = require("./auth.controller"); 13 | const auth_service_1 = require("./auth.service"); 14 | const strategy_1 = require("./strategy"); 15 | let AuthModule = class AuthModule { 16 | }; 17 | AuthModule = __decorate([ 18 | (0, common_1.Module)({ 19 | imports: [jwt_1.JwtModule.register({})], 20 | controllers: [auth_controller_1.AuthController], 21 | providers: [auth_service_1.AuthService, strategy_1.JwtStrategy], 22 | }) 23 | ], AuthModule); 24 | exports.AuthModule = AuthModule; 25 | //# sourceMappingURL=auth.module.js.map -------------------------------------------------------------------------------- /dist/auth/auth.module.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"auth.module.js","sourceRoot":"","sources":["../../src/auth/auth.module.ts"],"names":[],"mappings":";;;;;;;;;AAAA,2CAAwC;AACxC,qCAAwC;AACxC,uDAAmD;AACnD,iDAA6C;AAC7C,yCAAyC;AAOlC,IAAM,UAAU,GAAhB,MAAM,UAAU;CAAG,CAAA;AAAb,UAAU;IALtB,IAAA,eAAM,EAAC;QACN,OAAO,EAAE,CAAC,eAAS,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;QACjC,WAAW,EAAE,CAAC,gCAAc,CAAC;QAC7B,SAAS,EAAE,CAAC,0BAAW,EAAE,sBAAW,CAAC;KACtC,CAAC;GACW,UAAU,CAAG;AAAb,gCAAU"} -------------------------------------------------------------------------------- /dist/auth/auth.service.d.ts: -------------------------------------------------------------------------------- 1 | import { PrismaService } from 'src/prisma/prisma.service'; 2 | import { LoginDto, UserDto, UserForRegistration } from './dto'; 3 | import { ConfigService } from '@nestjs/config'; 4 | import { JwtService } from '@nestjs/jwt'; 5 | export declare class AuthService { 6 | private prisma; 7 | private config; 8 | private jwt; 9 | constructor(prisma: PrismaService, config: ConfigService, jwt: JwtService); 10 | createUser(dto: UserForRegistration): Promise; 11 | verifyUser(dto: LoginDto): Promise; 12 | signToken(userId: string, email: string): Promise; 13 | } 14 | -------------------------------------------------------------------------------- /dist/auth/auth.service.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { 3 | var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; 4 | if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); 5 | else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; 6 | return c > 3 && r && Object.defineProperty(target, key, r), r; 7 | }; 8 | var __metadata = (this && this.__metadata) || function (k, v) { 9 | if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); 10 | }; 11 | Object.defineProperty(exports, "__esModule", { value: true }); 12 | exports.AuthService = void 0; 13 | const common_1 = require("@nestjs/common"); 14 | const prisma_service_1 = require("../prisma/prisma.service"); 15 | const argon = require("argon2"); 16 | const config_1 = require("@nestjs/config"); 17 | const jwt_1 = require("@nestjs/jwt"); 18 | const runtime_1 = require("@prisma/client/runtime"); 19 | let AuthService = class AuthService { 20 | constructor(prisma, config, jwt) { 21 | this.prisma = prisma; 22 | this.config = config; 23 | this.jwt = jwt; 24 | } 25 | async createUser(dto) { 26 | const password = await argon.hash(dto.password); 27 | try { 28 | const user = await this.prisma.user.create({ 29 | data: Object.assign(Object.assign({}, dto), { password: password }), 30 | }); 31 | const token = await this.signToken(user.id, user.email); 32 | const userToReturn = { 33 | email: user.email, 34 | token: token, 35 | username: user.username, 36 | bio: user.bio, 37 | image: user.image, 38 | }; 39 | return userToReturn; 40 | } 41 | catch (e) { 42 | if (e instanceof runtime_1.PrismaClientKnownRequestError) { 43 | if (e.code === 'P2002') 44 | throw new common_1.BadRequestException('email is taken'); 45 | } 46 | } 47 | } 48 | async verifyUser(dto) { 49 | const user = await this.prisma.user.findUnique({ 50 | where: { 51 | email: dto.email, 52 | }, 53 | }); 54 | if (!user) 55 | throw new common_1.NotFoundException('user does not exist'); 56 | const matches = await argon.verify(user.password, dto.password); 57 | if (!matches) 58 | throw new common_1.UnauthorizedException('password and email do not match'); 59 | const token = await this.signToken(user.id, user.email); 60 | const userReturned = { 61 | email: user.email, 62 | token: token, 63 | username: user.username, 64 | bio: user.bio, 65 | image: user.image, 66 | }; 67 | return userReturned; 68 | } 69 | async signToken(userId, email) { 70 | const data = { 71 | sub: userId, 72 | email: email, 73 | }; 74 | const SECRET = this.config.get('SECRET'); 75 | const token = await this.jwt.signAsync(data, { 76 | secret: SECRET, 77 | expiresIn: '5h', 78 | }); 79 | return token; 80 | } 81 | }; 82 | AuthService = __decorate([ 83 | (0, common_1.Injectable)(), 84 | __metadata("design:paramtypes", [prisma_service_1.PrismaService, 85 | config_1.ConfigService, 86 | jwt_1.JwtService]) 87 | ], AuthService); 88 | exports.AuthService = AuthService; 89 | //# sourceMappingURL=auth.service.js.map -------------------------------------------------------------------------------- /dist/auth/auth.service.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"auth.service.js","sourceRoot":"","sources":["../../src/auth/auth.service.ts"],"names":[],"mappings":"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"} -------------------------------------------------------------------------------- /dist/auth/dto/index.d.ts: -------------------------------------------------------------------------------- 1 | export * from './user.dto'; 2 | -------------------------------------------------------------------------------- /dist/auth/dto/index.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { 3 | if (k2 === undefined) k2 = k; 4 | var desc = Object.getOwnPropertyDescriptor(m, k); 5 | if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { 6 | desc = { enumerable: true, get: function() { return m[k]; } }; 7 | } 8 | Object.defineProperty(o, k2, desc); 9 | }) : (function(o, m, k, k2) { 10 | if (k2 === undefined) k2 = k; 11 | o[k2] = m[k]; 12 | })); 13 | var __exportStar = (this && this.__exportStar) || function(m, exports) { 14 | for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); 15 | }; 16 | Object.defineProperty(exports, "__esModule", { value: true }); 17 | __exportStar(require("./user.dto"), exports); 18 | //# sourceMappingURL=index.js.map -------------------------------------------------------------------------------- /dist/auth/dto/index.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/auth/dto/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,6CAA2B"} -------------------------------------------------------------------------------- /dist/auth/dto/user.dto.d.ts: -------------------------------------------------------------------------------- 1 | export interface LoginDto { 2 | email: string; 3 | password: string; 4 | } 5 | export interface UserDto { 6 | email: string; 7 | token: string; 8 | username: string; 9 | bio: string; 10 | image?: string; 11 | } 12 | export interface UserForRegistration { 13 | email: string; 14 | password: string; 15 | username: string; 16 | } 17 | export interface UserForUpdate { 18 | email?: string; 19 | username?: string; 20 | bio?: string; 21 | image?: string; 22 | } 23 | -------------------------------------------------------------------------------- /dist/auth/dto/user.dto.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | //# sourceMappingURL=user.dto.js.map -------------------------------------------------------------------------------- /dist/auth/dto/user.dto.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"user.dto.js","sourceRoot":"","sources":["../../../src/auth/dto/user.dto.ts"],"names":[],"mappings":""} -------------------------------------------------------------------------------- /dist/auth/strategy/index.d.ts: -------------------------------------------------------------------------------- 1 | export * from './jwt.strategy'; 2 | -------------------------------------------------------------------------------- /dist/auth/strategy/index.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { 3 | if (k2 === undefined) k2 = k; 4 | var desc = Object.getOwnPropertyDescriptor(m, k); 5 | if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { 6 | desc = { enumerable: true, get: function() { return m[k]; } }; 7 | } 8 | Object.defineProperty(o, k2, desc); 9 | }) : (function(o, m, k, k2) { 10 | if (k2 === undefined) k2 = k; 11 | o[k2] = m[k]; 12 | })); 13 | var __exportStar = (this && this.__exportStar) || function(m, exports) { 14 | for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); 15 | }; 16 | Object.defineProperty(exports, "__esModule", { value: true }); 17 | __exportStar(require("./jwt.strategy"), exports); 18 | //# sourceMappingURL=index.js.map -------------------------------------------------------------------------------- /dist/auth/strategy/index.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/auth/strategy/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,iDAA+B"} -------------------------------------------------------------------------------- /dist/auth/strategy/jwt.strategy.d.ts: -------------------------------------------------------------------------------- 1 | import { Strategy } from 'passport-jwt'; 2 | import { ConfigService } from '@nestjs/config'; 3 | import { PrismaService } from '../../prisma/prisma.service'; 4 | declare const JwtStrategy_base: new (...args: any[]) => Strategy; 5 | export declare class JwtStrategy extends JwtStrategy_base { 6 | private config; 7 | private prisma; 8 | constructor(config: ConfigService, prisma: PrismaService); 9 | validate(payload: { 10 | sub: string; 11 | email: string; 12 | }): Promise<{ 13 | email: string; 14 | username: string; 15 | bio: string; 16 | image: string; 17 | followers: import(".prisma/client").User[]; 18 | id: string; 19 | }>; 20 | } 21 | export {}; 22 | -------------------------------------------------------------------------------- /dist/auth/strategy/jwt.strategy.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { 3 | var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; 4 | if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); 5 | else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; 6 | return c > 3 && r && Object.defineProperty(target, key, r), r; 7 | }; 8 | var __metadata = (this && this.__metadata) || function (k, v) { 9 | if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); 10 | }; 11 | Object.defineProperty(exports, "__esModule", { value: true }); 12 | exports.JwtStrategy = void 0; 13 | const passport_jwt_1 = require("passport-jwt"); 14 | const passport_1 = require("@nestjs/passport"); 15 | const common_1 = require("@nestjs/common"); 16 | const config_1 = require("@nestjs/config"); 17 | const prisma_service_1 = require("../../prisma/prisma.service"); 18 | let JwtStrategy = class JwtStrategy extends (0, passport_1.PassportStrategy)(passport_jwt_1.Strategy) { 19 | constructor(config, prisma) { 20 | super({ 21 | jwtFromRequest: passport_jwt_1.ExtractJwt.fromAuthHeaderAsBearerToken(), 22 | secretOrKey: config.get('SECRET'), 23 | }); 24 | this.config = config; 25 | this.prisma = prisma; 26 | } 27 | async validate(payload) { 28 | const user = await this.prisma.user.findUnique({ 29 | where: { id: payload.sub }, 30 | select: { 31 | id: true, 32 | email: true, 33 | bio: true, 34 | username: true, 35 | followers: true, 36 | image: true, 37 | }, 38 | }); 39 | return user; 40 | } 41 | }; 42 | JwtStrategy = __decorate([ 43 | (0, common_1.Injectable)(), 44 | __metadata("design:paramtypes", [config_1.ConfigService, prisma_service_1.PrismaService]) 45 | ], JwtStrategy); 46 | exports.JwtStrategy = JwtStrategy; 47 | //# sourceMappingURL=jwt.strategy.js.map -------------------------------------------------------------------------------- /dist/auth/strategy/jwt.strategy.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"jwt.strategy.js","sourceRoot":"","sources":["../../../src/auth/strategy/jwt.strategy.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,+CAAoD;AACpD,+CAAoD;AACpD,2CAA4C;AAC5C,2CAA+C;AAC/C,gEAA4D;AAGrD,IAAM,WAAW,GAAjB,MAAM,WAAY,SAAQ,IAAA,2BAAgB,EAAC,uBAAQ,CAAC;IACzD,YAAoB,MAAqB,EAAU,MAAqB;QACtE,KAAK,CAAC;YACJ,cAAc,EAAE,yBAAU,CAAC,2BAA2B,EAAE;YACxD,WAAW,EAAE,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;SAClC,CAAC,CAAC;QAJe,WAAM,GAAN,MAAM,CAAe;QAAU,WAAM,GAAN,MAAM,CAAe;IAKxE,CAAC;IAED,KAAK,CAAC,QAAQ,CAAC,OAAuC;QAGpD,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC;YAC7C,KAAK,EAAE,EAAE,EAAE,EAAE,OAAO,CAAC,GAAG,EAAE;YAC1B,MAAM,EAAE;gBACN,EAAE,EAAE,IAAI;gBACR,KAAK,EAAE,IAAI;gBACX,GAAG,EAAE,IAAI;gBACT,QAAQ,EAAE,IAAI;gBACd,SAAS,EAAE,IAAI;gBACf,KAAK,EAAE,IAAI;aACZ;SACF,CAAC,CAAC;QACH,OAAO,IAAI,CAAC;IACd,CAAC;CACF,CAAA;AAxBY,WAAW;IADvB,IAAA,mBAAU,GAAE;qCAEiB,sBAAa,EAAkB,8BAAa;GAD7D,WAAW,CAwBvB;AAxBY,kCAAW"} -------------------------------------------------------------------------------- /dist/common/decorator/allow-any.decorator.d.ts: -------------------------------------------------------------------------------- 1 | export declare const AllowAny: () => import("@nestjs/common").CustomDecorator; 2 | -------------------------------------------------------------------------------- /dist/common/decorator/allow-any.decorator.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | exports.AllowAny = void 0; 4 | const common_1 = require("@nestjs/common"); 5 | const AllowAny = () => (0, common_1.SetMetadata)('allow-any', true); 6 | exports.AllowAny = AllowAny; 7 | //# sourceMappingURL=allow-any.decorator.js.map -------------------------------------------------------------------------------- /dist/common/decorator/allow-any.decorator.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"allow-any.decorator.js","sourceRoot":"","sources":["../../../src/common/decorator/allow-any.decorator.ts"],"names":[],"mappings":";;;AAAA,2CAA6C;AAEtC,MAAM,QAAQ,GAAG,GAAG,EAAE,CAAC,IAAA,oBAAW,EAAC,WAAW,EAAE,IAAI,CAAC,CAAC;AAAhD,QAAA,QAAQ,YAAwC"} -------------------------------------------------------------------------------- /dist/common/decorator/get-user.decorator.d.ts: -------------------------------------------------------------------------------- 1 | export declare const GetUser: (...dataOrPipes: any[]) => ParameterDecorator; 2 | -------------------------------------------------------------------------------- /dist/common/decorator/get-user.decorator.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | exports.GetUser = void 0; 4 | const common_1 = require("@nestjs/common"); 5 | exports.GetUser = (0, common_1.createParamDecorator)((data, ctx) => { 6 | const request = ctx.switchToHttp().getRequest(); 7 | if (data) 8 | return request.user[data]; 9 | return request.user; 10 | }); 11 | //# sourceMappingURL=get-user.decorator.js.map -------------------------------------------------------------------------------- /dist/common/decorator/get-user.decorator.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"get-user.decorator.js","sourceRoot":"","sources":["../../../src/common/decorator/get-user.decorator.ts"],"names":[],"mappings":";;;AAAA,2CAAwE;AAE3D,QAAA,OAAO,GAAG,IAAA,6BAAoB,EACzC,CAAC,IAAqB,EAAE,GAAqB,EAAE,EAAE;IAC/C,MAAM,OAAO,GAAoB,GAAG,CAAC,YAAY,EAAE,CAAC,UAAU,EAAE,CAAC;IACjE,IAAI,IAAI;QAAE,OAAO,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACpC,OAAO,OAAO,CAAC,IAAI,CAAC;AACtB,CAAC,CACF,CAAC"} -------------------------------------------------------------------------------- /dist/common/decorator/index.d.ts: -------------------------------------------------------------------------------- 1 | export * from './allow-any.decorator'; 2 | export * from './get-user.decorator'; 3 | -------------------------------------------------------------------------------- /dist/common/decorator/index.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { 3 | if (k2 === undefined) k2 = k; 4 | var desc = Object.getOwnPropertyDescriptor(m, k); 5 | if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { 6 | desc = { enumerable: true, get: function() { return m[k]; } }; 7 | } 8 | Object.defineProperty(o, k2, desc); 9 | }) : (function(o, m, k, k2) { 10 | if (k2 === undefined) k2 = k; 11 | o[k2] = m[k]; 12 | })); 13 | var __exportStar = (this && this.__exportStar) || function(m, exports) { 14 | for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); 15 | }; 16 | Object.defineProperty(exports, "__esModule", { value: true }); 17 | __exportStar(require("./allow-any.decorator"), exports); 18 | __exportStar(require("./get-user.decorator"), exports); 19 | //# sourceMappingURL=index.js.map -------------------------------------------------------------------------------- /dist/common/decorator/index.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/common/decorator/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,wDAAsC;AACtC,uDAAqC"} -------------------------------------------------------------------------------- /dist/common/filters/prisma-exceptions.filter.d.ts: -------------------------------------------------------------------------------- 1 | export {}; 2 | -------------------------------------------------------------------------------- /dist/common/filters/prisma-exceptions.filter.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | //# sourceMappingURL=prisma-exceptions.filter.js.map -------------------------------------------------------------------------------- /dist/common/filters/prisma-exceptions.filter.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"prisma-exceptions.filter.js","sourceRoot":"","sources":["../../../src/common/filters/prisma-exceptions.filter.ts"],"names":[],"mappings":""} -------------------------------------------------------------------------------- /dist/common/guard/index.d.ts: -------------------------------------------------------------------------------- 1 | export * from './jwt.guard'; 2 | -------------------------------------------------------------------------------- /dist/common/guard/index.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { 3 | if (k2 === undefined) k2 = k; 4 | var desc = Object.getOwnPropertyDescriptor(m, k); 5 | if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { 6 | desc = { enumerable: true, get: function() { return m[k]; } }; 7 | } 8 | Object.defineProperty(o, k2, desc); 9 | }) : (function(o, m, k, k2) { 10 | if (k2 === undefined) k2 = k; 11 | o[k2] = m[k]; 12 | })); 13 | var __exportStar = (this && this.__exportStar) || function(m, exports) { 14 | for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); 15 | }; 16 | Object.defineProperty(exports, "__esModule", { value: true }); 17 | __exportStar(require("./jwt.guard"), exports); 18 | //# sourceMappingURL=index.js.map -------------------------------------------------------------------------------- /dist/common/guard/index.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/common/guard/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,8CAA4B"} -------------------------------------------------------------------------------- /dist/common/guard/jwt.guard.d.ts: -------------------------------------------------------------------------------- 1 | import { ExecutionContext } from '@nestjs/common'; 2 | import { Reflector } from '@nestjs/core'; 3 | declare const JwtGuard_base: import("@nestjs/passport").Type; 4 | export declare class JwtGuard extends JwtGuard_base { 5 | private reflector; 6 | constructor(reflector: Reflector); 7 | handleRequest(err: any, user: any, info: any, context: ExecutionContext, status?: any): any; 8 | } 9 | export {}; 10 | -------------------------------------------------------------------------------- /dist/common/guard/jwt.guard.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | exports.JwtGuard = void 0; 4 | const common_1 = require("@nestjs/common"); 5 | const core_1 = require("@nestjs/core"); 6 | const passport_1 = require("@nestjs/passport"); 7 | class JwtGuard extends (0, passport_1.AuthGuard)('jwt') { 8 | constructor(reflector) { 9 | super(); 10 | this.reflector = reflector; 11 | } 12 | handleRequest(err, user, info, context, status) { 13 | const request = context.switchToHttp().getRequest(); 14 | this.reflector = new core_1.Reflector(); 15 | const allowAny = this.reflector.get('allow-any', context.getHandler()); 16 | if (user) 17 | return user; 18 | if (allowAny) 19 | return true; 20 | throw new common_1.UnauthorizedException(); 21 | } 22 | } 23 | exports.JwtGuard = JwtGuard; 24 | //# sourceMappingURL=jwt.guard.js.map -------------------------------------------------------------------------------- /dist/common/guard/jwt.guard.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"jwt.guard.js","sourceRoot":"","sources":["../../../src/common/guard/jwt.guard.ts"],"names":[],"mappings":";;;AAAA,2CAAyE;AACzE,uCAAyC;AACzC,+CAA6C;AAE7C,MAAa,QAAS,SAAQ,IAAA,oBAAS,EAAC,KAAK,CAAC;IAC5C,YAAoB,SAAoB;QACtC,KAAK,EAAE,CAAC;QADU,cAAS,GAAT,SAAS,CAAW;IAExC,CAAC;IAED,aAAa,CACX,GAAQ,EACR,IAAS,EACT,IAAS,EACT,OAAyB,EACzB,MAAY;QAEZ,MAAM,OAAO,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC,UAAU,EAAE,CAAC;QAEpD,IAAI,CAAC,SAAS,GAAG,IAAI,gBAAS,EAAE,CAAC;QACjC,MAAM,QAAQ,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CACjC,WAAW,EACX,OAAO,CAAC,UAAU,EAAE,CACrB,CAAC;QACF,IAAI,IAAI;YAAE,OAAO,IAAI,CAAC;QACtB,IAAI,QAAQ;YAAE,OAAO,IAAI,CAAC;QAC1B,MAAM,IAAI,8BAAqB,EAAE,CAAC;IACpC,CAAC;CACF;AAvBD,4BAuBC"} -------------------------------------------------------------------------------- /dist/main.d.ts: -------------------------------------------------------------------------------- 1 | export {}; 2 | -------------------------------------------------------------------------------- /dist/main.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | const core_1 = require("@nestjs/core"); 4 | const app_module_1 = require("./app.module"); 5 | async function bootstrap() { 6 | const app = await core_1.NestFactory.create(app_module_1.AppModule); 7 | app.setGlobalPrefix('api'); 8 | await app.listen(3000); 9 | } 10 | bootstrap(); 11 | //# sourceMappingURL=main.js.map -------------------------------------------------------------------------------- /dist/main.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"main.js","sourceRoot":"","sources":["../src/main.ts"],"names":[],"mappings":";;AAAA,uCAA2C;AAC3C,6CAAyC;AAEzC,KAAK,UAAU,SAAS;IACtB,MAAM,GAAG,GAAG,MAAM,kBAAW,CAAC,MAAM,CAAC,sBAAS,CAAC,CAAC;IAChD,GAAG,CAAC,eAAe,CAAC,KAAK,CAAC,CAAC;IAC3B,MAAM,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;AACzB,CAAC;AACD,SAAS,EAAE,CAAC"} -------------------------------------------------------------------------------- /dist/prisma/prisma.module.d.ts: -------------------------------------------------------------------------------- 1 | export declare class PrismaModule { 2 | } 3 | -------------------------------------------------------------------------------- /dist/prisma/prisma.module.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { 3 | var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; 4 | if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); 5 | else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; 6 | return c > 3 && r && Object.defineProperty(target, key, r), r; 7 | }; 8 | Object.defineProperty(exports, "__esModule", { value: true }); 9 | exports.PrismaModule = void 0; 10 | const common_1 = require("@nestjs/common"); 11 | const prisma_service_1 = require("./prisma.service"); 12 | let PrismaModule = class PrismaModule { 13 | }; 14 | PrismaModule = __decorate([ 15 | (0, common_1.Global)(), 16 | (0, common_1.Module)({ 17 | providers: [prisma_service_1.PrismaService], 18 | exports: [prisma_service_1.PrismaService], 19 | }) 20 | ], PrismaModule); 21 | exports.PrismaModule = PrismaModule; 22 | //# sourceMappingURL=prisma.module.js.map -------------------------------------------------------------------------------- /dist/prisma/prisma.module.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"prisma.module.js","sourceRoot":"","sources":["../../src/prisma/prisma.module.ts"],"names":[],"mappings":";;;;;;;;;AAAA,2CAAgD;AAChD,qDAAiD;AAO1C,IAAM,YAAY,GAAlB,MAAM,YAAY;CAAG,CAAA;AAAf,YAAY;IALxB,IAAA,eAAM,GAAE;IACR,IAAA,eAAM,EAAC;QACN,SAAS,EAAE,CAAC,8BAAa,CAAC;QAC1B,OAAO,EAAE,CAAC,8BAAa,CAAC;KACzB,CAAC;GACW,YAAY,CAAG;AAAf,oCAAY"} -------------------------------------------------------------------------------- /dist/prisma/prisma.service.d.ts: -------------------------------------------------------------------------------- 1 | import { PrismaClient } from '@prisma/client'; 2 | export declare class PrismaService extends PrismaClient { 3 | } 4 | -------------------------------------------------------------------------------- /dist/prisma/prisma.service.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { 3 | var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; 4 | if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); 5 | else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; 6 | return c > 3 && r && Object.defineProperty(target, key, r), r; 7 | }; 8 | Object.defineProperty(exports, "__esModule", { value: true }); 9 | exports.PrismaService = void 0; 10 | const common_1 = require("@nestjs/common"); 11 | const client_1 = require("@prisma/client"); 12 | let PrismaService = class PrismaService extends client_1.PrismaClient { 13 | }; 14 | PrismaService = __decorate([ 15 | (0, common_1.Injectable)() 16 | ], PrismaService); 17 | exports.PrismaService = PrismaService; 18 | //# sourceMappingURL=prisma.service.js.map -------------------------------------------------------------------------------- /dist/prisma/prisma.service.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"prisma.service.js","sourceRoot":"","sources":["../../src/prisma/prisma.service.ts"],"names":[],"mappings":";;;;;;;;;AAAA,2CAA4C;AAC5C,2CAA8C;AAGvC,IAAM,aAAa,GAAnB,MAAM,aAAc,SAAQ,qBAAY;CAAG,CAAA;AAArC,aAAa;IADzB,IAAA,mBAAU,GAAE;GACA,aAAa,CAAwB;AAArC,sCAAa"} -------------------------------------------------------------------------------- /dist/profiles/dto/index.d.ts: -------------------------------------------------------------------------------- 1 | export * from './profile.dto'; 2 | -------------------------------------------------------------------------------- /dist/profiles/dto/index.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { 3 | if (k2 === undefined) k2 = k; 4 | var desc = Object.getOwnPropertyDescriptor(m, k); 5 | if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { 6 | desc = { enumerable: true, get: function() { return m[k]; } }; 7 | } 8 | Object.defineProperty(o, k2, desc); 9 | }) : (function(o, m, k, k2) { 10 | if (k2 === undefined) k2 = k; 11 | o[k2] = m[k]; 12 | })); 13 | var __exportStar = (this && this.__exportStar) || function(m, exports) { 14 | for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); 15 | }; 16 | Object.defineProperty(exports, "__esModule", { value: true }); 17 | __exportStar(require("./profile.dto"), exports); 18 | //# sourceMappingURL=index.js.map -------------------------------------------------------------------------------- /dist/profiles/dto/index.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/profiles/dto/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,gDAA8B"} -------------------------------------------------------------------------------- /dist/profiles/dto/profile.dto.d.ts: -------------------------------------------------------------------------------- 1 | import { User } from '@prisma/client'; 2 | export interface ProfileDto { 3 | username: string; 4 | bio: string; 5 | image: string; 6 | following: boolean; 7 | } 8 | export declare function castToProfile(user: User, isFollowing: boolean): ProfileDto; 9 | -------------------------------------------------------------------------------- /dist/profiles/dto/profile.dto.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | exports.castToProfile = void 0; 4 | function castToProfile(user, isFollowing) { 5 | return { 6 | username: user.username, 7 | bio: user.bio, 8 | image: user.image, 9 | following: isFollowing, 10 | }; 11 | } 12 | exports.castToProfile = castToProfile; 13 | //# sourceMappingURL=profile.dto.js.map -------------------------------------------------------------------------------- /dist/profiles/dto/profile.dto.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"profile.dto.js","sourceRoot":"","sources":["../../../src/profiles/dto/profile.dto.ts"],"names":[],"mappings":";;;AASA,SAAgB,aAAa,CAAC,IAAU,EAAE,WAAoB;IAC5D,OAAO;QACL,QAAQ,EAAE,IAAI,CAAC,QAAQ;QACvB,GAAG,EAAE,IAAI,CAAC,GAAG;QACb,KAAK,EAAE,IAAI,CAAC,KAAK;QACjB,SAAS,EAAE,WAAW;KACvB,CAAC;AACJ,CAAC;AAPD,sCAOC"} -------------------------------------------------------------------------------- /dist/profiles/profiles.controller.d.ts: -------------------------------------------------------------------------------- 1 | import { User } from '@prisma/client'; 2 | import { ProfilesService } from './profiles.service'; 3 | export declare class ProfilesController { 4 | private profileService; 5 | constructor(profileService: ProfilesService); 6 | findUser(user: User, userName: string): Promise<{ 7 | profile: import("./dto").ProfileDto; 8 | }>; 9 | followUser(user: User, userName: string): Promise<{ 10 | profile: import("./dto").ProfileDto; 11 | }>; 12 | unfollowUser(user: User, username: string): Promise<{ 13 | profile: import("./dto").ProfileDto; 14 | }>; 15 | } 16 | -------------------------------------------------------------------------------- /dist/profiles/profiles.controller.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { 3 | var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; 4 | if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); 5 | else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; 6 | return c > 3 && r && Object.defineProperty(target, key, r), r; 7 | }; 8 | var __metadata = (this && this.__metadata) || function (k, v) { 9 | if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); 10 | }; 11 | var __param = (this && this.__param) || function (paramIndex, decorator) { 12 | return function (target, key) { decorator(target, key, paramIndex); } 13 | }; 14 | Object.defineProperty(exports, "__esModule", { value: true }); 15 | exports.ProfilesController = void 0; 16 | const common_1 = require("@nestjs/common"); 17 | const get_user_decorator_1 = require("../common/decorator/get-user.decorator"); 18 | const guard_1 = require("../common/guard"); 19 | const profiles_service_1 = require("./profiles.service"); 20 | let ProfilesController = class ProfilesController { 21 | constructor(profileService) { 22 | this.profileService = profileService; 23 | } 24 | async findUser(user, userName) { 25 | return { profile: await this.profileService.findUser(user, userName) }; 26 | } 27 | async followUser(user, userName) { 28 | return { profile: await this.profileService.followUser(user, userName) }; 29 | } 30 | async unfollowUser(user, username) { 31 | return { profile: await this.profileService.unfollowUser(user, username) }; 32 | } 33 | }; 34 | __decorate([ 35 | (0, common_1.Get)(':username'), 36 | __param(0, (0, get_user_decorator_1.GetUser)()), 37 | __param(1, (0, common_1.Param)('username')), 38 | __metadata("design:type", Function), 39 | __metadata("design:paramtypes", [Object, String]), 40 | __metadata("design:returntype", Promise) 41 | ], ProfilesController.prototype, "findUser", null); 42 | __decorate([ 43 | (0, common_1.HttpCode)(common_1.HttpStatus.OK), 44 | (0, common_1.Post)(':username/follow'), 45 | __param(0, (0, get_user_decorator_1.GetUser)()), 46 | __param(1, (0, common_1.Param)('username')), 47 | __metadata("design:type", Function), 48 | __metadata("design:paramtypes", [Object, String]), 49 | __metadata("design:returntype", Promise) 50 | ], ProfilesController.prototype, "followUser", null); 51 | __decorate([ 52 | (0, common_1.Delete)(':username/follow'), 53 | __param(0, (0, get_user_decorator_1.GetUser)()), 54 | __param(1, (0, common_1.Param)('username')), 55 | __metadata("design:type", Function), 56 | __metadata("design:paramtypes", [Object, String]), 57 | __metadata("design:returntype", Promise) 58 | ], ProfilesController.prototype, "unfollowUser", null); 59 | ProfilesController = __decorate([ 60 | (0, common_1.UseGuards)(guard_1.JwtGuard), 61 | (0, common_1.Controller)('profiles'), 62 | __metadata("design:paramtypes", [profiles_service_1.ProfilesService]) 63 | ], ProfilesController); 64 | exports.ProfilesController = ProfilesController; 65 | //# sourceMappingURL=profiles.controller.js.map -------------------------------------------------------------------------------- /dist/profiles/profiles.controller.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"profiles.controller.js","sourceRoot":"","sources":["../../src/profiles/profiles.controller.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;AAAA,2CASwB;AAExB,+EAAkE;AAClE,2CAA4C;AAC5C,yDAAqD;AAI9C,IAAM,kBAAkB,GAAxB,MAAM,kBAAkB;IAC7B,YAAoB,cAA+B;QAA/B,mBAAc,GAAd,cAAc,CAAiB;IAAG,CAAC;IAEjD,AAAN,KAAK,CAAC,QAAQ,CAAY,IAAU,EAAqB,QAAgB;QACvE,OAAO,EAAE,OAAO,EAAE,MAAM,IAAI,CAAC,cAAc,CAAC,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC,EAAE,CAAC;IACzE,CAAC;IAIK,AAAN,KAAK,CAAC,UAAU,CAAY,IAAU,EAAqB,QAAgB;QACzE,OAAO,EAAE,OAAO,EAAE,MAAM,IAAI,CAAC,cAAc,CAAC,UAAU,CAAC,IAAI,EAAE,QAAQ,CAAC,EAAE,CAAC;IAC3E,CAAC;IAGK,AAAN,KAAK,CAAC,YAAY,CACL,IAAU,EACF,QAAgB;QAEnC,OAAO,EAAE,OAAO,EAAE,MAAM,IAAI,CAAC,cAAc,CAAC,YAAY,CAAC,IAAI,EAAE,QAAQ,CAAC,EAAE,CAAC;IAC7E,CAAC;CACF,CAAA;AAjBO;IADL,IAAA,YAAG,EAAC,WAAW,CAAC;IACD,WAAA,IAAA,4BAAO,GAAE,CAAA;IAAc,WAAA,IAAA,cAAK,EAAC,UAAU,CAAC,CAAA;;;;kDAEvD;AAIK;IAFL,IAAA,iBAAQ,EAAC,mBAAU,CAAC,EAAE,CAAC;IACvB,IAAA,aAAI,EAAC,kBAAkB,CAAC;IACP,WAAA,IAAA,4BAAO,GAAE,CAAA;IAAc,WAAA,IAAA,cAAK,EAAC,UAAU,CAAC,CAAA;;;;oDAEzD;AAGK;IADL,IAAA,eAAM,EAAC,kBAAkB,CAAC;IAExB,WAAA,IAAA,4BAAO,GAAE,CAAA;IACT,WAAA,IAAA,cAAK,EAAC,UAAU,CAAC,CAAA;;;;sDAGnB;AAnBU,kBAAkB;IAF9B,IAAA,kBAAS,EAAC,gBAAQ,CAAC;IACnB,IAAA,mBAAU,EAAC,UAAU,CAAC;qCAEe,kCAAe;GADxC,kBAAkB,CAoB9B;AApBY,gDAAkB"} -------------------------------------------------------------------------------- /dist/profiles/profiles.module.d.ts: -------------------------------------------------------------------------------- 1 | export declare class ProfilesModule { 2 | } 3 | -------------------------------------------------------------------------------- /dist/profiles/profiles.module.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { 3 | var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; 4 | if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); 5 | else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; 6 | return c > 3 && r && Object.defineProperty(target, key, r), r; 7 | }; 8 | Object.defineProperty(exports, "__esModule", { value: true }); 9 | exports.ProfilesModule = void 0; 10 | const common_1 = require("@nestjs/common"); 11 | const profiles_controller_1 = require("./profiles.controller"); 12 | const profiles_service_1 = require("./profiles.service"); 13 | let ProfilesModule = class ProfilesModule { 14 | }; 15 | ProfilesModule = __decorate([ 16 | (0, common_1.Module)({ 17 | controllers: [profiles_controller_1.ProfilesController], 18 | providers: [profiles_service_1.ProfilesService], 19 | }) 20 | ], ProfilesModule); 21 | exports.ProfilesModule = ProfilesModule; 22 | //# sourceMappingURL=profiles.module.js.map -------------------------------------------------------------------------------- /dist/profiles/profiles.module.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"profiles.module.js","sourceRoot":"","sources":["../../src/profiles/profiles.module.ts"],"names":[],"mappings":";;;;;;;;;AAAA,2CAAwC;AACxC,+DAA2D;AAC3D,yDAAqD;AAM9C,IAAM,cAAc,GAApB,MAAM,cAAc;CAAG,CAAA;AAAjB,cAAc;IAJ1B,IAAA,eAAM,EAAC;QACN,WAAW,EAAE,CAAC,wCAAkB,CAAC;QACjC,SAAS,EAAE,CAAC,kCAAe,CAAC;KAC7B,CAAC;GACW,cAAc,CAAG;AAAjB,wCAAc"} -------------------------------------------------------------------------------- /dist/profiles/profiles.service.d.ts: -------------------------------------------------------------------------------- 1 | import { User } from '@prisma/client'; 2 | import { PrismaService } from 'src/prisma/prisma.service'; 3 | import { ProfileDto } from './dto'; 4 | export declare class ProfilesService { 5 | private prisma; 6 | constructor(prisma: PrismaService); 7 | findUser(user: User, userName: string): Promise; 8 | followUser(user: User, userName: string): Promise; 9 | unfollowUser(user: User, username: string): Promise; 10 | } 11 | -------------------------------------------------------------------------------- /dist/profiles/profiles.service.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { 3 | var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; 4 | if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); 5 | else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; 6 | return c > 3 && r && Object.defineProperty(target, key, r), r; 7 | }; 8 | var __metadata = (this && this.__metadata) || function (k, v) { 9 | if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); 10 | }; 11 | Object.defineProperty(exports, "__esModule", { value: true }); 12 | exports.ProfilesService = void 0; 13 | const common_1 = require("@nestjs/common"); 14 | const prisma_service_1 = require("../prisma/prisma.service"); 15 | const dto_1 = require("./dto"); 16 | let ProfilesService = class ProfilesService { 17 | constructor(prisma) { 18 | this.prisma = prisma; 19 | } 20 | async findUser(user, userName) { 21 | const userFromDb = await this.prisma.user.findUnique({ 22 | where: { 23 | username: userName, 24 | }, 25 | }); 26 | if (!userFromDb) 27 | throw new common_1.NotFoundException('user not found'); 28 | const isFollowing = userFromDb.followersIds.includes(user.id); 29 | const profile = (0, dto_1.castToProfile)(userFromDb, isFollowing); 30 | return profile; 31 | } 32 | async followUser(user, userName) { 33 | const userFollowed = await this.prisma.user.update({ 34 | where: { 35 | username: userName, 36 | }, 37 | data: { 38 | followers: { 39 | set: [{ username: user.username }], 40 | }, 41 | }, 42 | }); 43 | const profile = (0, dto_1.castToProfile)(userFollowed, true); 44 | return profile; 45 | } 46 | async unfollowUser(user, username) { 47 | const userFromDb = await this.prisma.user.update({ 48 | where: { 49 | username: username, 50 | }, 51 | data: { 52 | followers: { 53 | disconnect: [{ id: user.id }], 54 | }, 55 | }, 56 | }); 57 | const profile = (0, dto_1.castToProfile)(userFromDb, false); 58 | return profile; 59 | } 60 | }; 61 | ProfilesService = __decorate([ 62 | (0, common_1.Injectable)(), 63 | __metadata("design:paramtypes", [prisma_service_1.PrismaService]) 64 | ], ProfilesService); 65 | exports.ProfilesService = ProfilesService; 66 | //# sourceMappingURL=profiles.service.js.map -------------------------------------------------------------------------------- /dist/profiles/profiles.service.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"profiles.service.js","sourceRoot":"","sources":["../../src/profiles/profiles.service.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,2CAA+D;AAE/D,6DAA0D;AAC1D,+BAAkD;AAG3C,IAAM,eAAe,GAArB,MAAM,eAAe;IAC1B,YAAoB,MAAqB;QAArB,WAAM,GAAN,MAAM,CAAe;IAAG,CAAC;IAE7C,KAAK,CAAC,QAAQ,CAAC,IAAU,EAAE,QAAgB;QACzC,MAAM,UAAU,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC;YACnD,KAAK,EAAE;gBACL,QAAQ,EAAE,QAAQ;aACnB;SACF,CAAC,CAAC;QACH,IAAI,CAAC,UAAU;YAAE,MAAM,IAAI,0BAAiB,CAAC,gBAAgB,CAAC,CAAC;QAE/D,MAAM,WAAW,GAAG,UAAU,CAAC,YAAY,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAC9D,MAAM,OAAO,GAAe,IAAA,mBAAa,EAAC,UAAU,EAAE,WAAW,CAAC,CAAC;QACnE,OAAO,OAAO,CAAC;IACjB,CAAC;IAED,KAAK,CAAC,UAAU,CAAC,IAAU,EAAE,QAAgB;QAC3C,MAAM,YAAY,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC;YACjD,KAAK,EAAE;gBACL,QAAQ,EAAE,QAAQ;aACnB;YACD,IAAI,EAAE;gBACJ,SAAS,EAAE;oBACT,GAAG,EAAE,CAAC,EAAE,QAAQ,EAAE,IAAI,CAAC,QAAQ,EAAE,CAAC;iBACnC;aACF;SACF,CAAC,CAAC;QAEH,MAAM,OAAO,GAAe,IAAA,mBAAa,EAAC,YAAY,EAAE,IAAI,CAAC,CAAC;QAC9D,OAAO,OAAO,CAAC;IACjB,CAAC;IAED,KAAK,CAAC,YAAY,CAAC,IAAU,EAAE,QAAgB;QAC7C,MAAM,UAAU,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC;YAC/C,KAAK,EAAE;gBACL,QAAQ,EAAE,QAAQ;aACnB;YACD,IAAI,EAAE;gBACJ,SAAS,EAAE;oBACT,UAAU,EAAE,CAAC,EAAE,EAAE,EAAE,IAAI,CAAC,EAAE,EAAE,CAAC;iBAC9B;aACF;SACF,CAAC,CAAC;QAEH,MAAM,OAAO,GAAe,IAAA,mBAAa,EAAC,UAAU,EAAE,KAAK,CAAC,CAAC;QAC7D,OAAO,OAAO,CAAC;IACjB,CAAC;CACF,CAAA;AA/CY,eAAe;IAD3B,IAAA,mBAAU,GAAE;qCAEiB,8BAAa;GAD9B,eAAe,CA+C3B;AA/CY,0CAAe"} -------------------------------------------------------------------------------- /dist/tags/tags.controller.d.ts: -------------------------------------------------------------------------------- 1 | import { TagsService } from './tags.service'; 2 | export declare class TagsController { 3 | private tagsService; 4 | constructor(tagsService: TagsService); 5 | getTags(): Promise<{ 6 | tags: string[]; 7 | }>; 8 | } 9 | -------------------------------------------------------------------------------- /dist/tags/tags.controller.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { 3 | var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; 4 | if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); 5 | else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; 6 | return c > 3 && r && Object.defineProperty(target, key, r), r; 7 | }; 8 | var __metadata = (this && this.__metadata) || function (k, v) { 9 | if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); 10 | }; 11 | Object.defineProperty(exports, "__esModule", { value: true }); 12 | exports.TagsController = void 0; 13 | const common_1 = require("@nestjs/common"); 14 | const tags_service_1 = require("./tags.service"); 15 | let TagsController = class TagsController { 16 | constructor(tagsService) { 17 | this.tagsService = tagsService; 18 | } 19 | async getTags() { 20 | return { tags: await this.tagsService.getTags() }; 21 | } 22 | }; 23 | __decorate([ 24 | (0, common_1.Get)(), 25 | __metadata("design:type", Function), 26 | __metadata("design:paramtypes", []), 27 | __metadata("design:returntype", Promise) 28 | ], TagsController.prototype, "getTags", null); 29 | TagsController = __decorate([ 30 | (0, common_1.Controller)('tags'), 31 | __metadata("design:paramtypes", [tags_service_1.TagsService]) 32 | ], TagsController); 33 | exports.TagsController = TagsController; 34 | //# sourceMappingURL=tags.controller.js.map -------------------------------------------------------------------------------- /dist/tags/tags.controller.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"tags.controller.js","sourceRoot":"","sources":["../../src/tags/tags.controller.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,2CAAiD;AACjD,iDAA6C;AAGtC,IAAM,cAAc,GAApB,MAAM,cAAc;IACzB,YAAoB,WAAwB;QAAxB,gBAAW,GAAX,WAAW,CAAa;IAAG,CAAC;IAE1C,AAAN,KAAK,CAAC,OAAO;QACX,OAAO,EAAE,IAAI,EAAE,MAAM,IAAI,CAAC,WAAW,CAAC,OAAO,EAAE,EAAE,CAAC;IACpD,CAAC;CACF,CAAA;AAHO;IADL,IAAA,YAAG,GAAE;;;;6CAGL;AALU,cAAc;IAD1B,IAAA,mBAAU,EAAC,MAAM,CAAC;qCAEgB,0BAAW;GADjC,cAAc,CAM1B;AANY,wCAAc"} -------------------------------------------------------------------------------- /dist/tags/tags.module.d.ts: -------------------------------------------------------------------------------- 1 | export declare class TagsModule { 2 | } 3 | -------------------------------------------------------------------------------- /dist/tags/tags.module.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { 3 | var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; 4 | if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); 5 | else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; 6 | return c > 3 && r && Object.defineProperty(target, key, r), r; 7 | }; 8 | Object.defineProperty(exports, "__esModule", { value: true }); 9 | exports.TagsModule = void 0; 10 | const common_1 = require("@nestjs/common"); 11 | const tags_controller_1 = require("./tags.controller"); 12 | const tags_service_1 = require("./tags.service"); 13 | let TagsModule = class TagsModule { 14 | }; 15 | TagsModule = __decorate([ 16 | (0, common_1.Module)({ 17 | providers: [tags_service_1.TagsService], 18 | controllers: [tags_controller_1.TagsController], 19 | }) 20 | ], TagsModule); 21 | exports.TagsModule = TagsModule; 22 | //# sourceMappingURL=tags.module.js.map -------------------------------------------------------------------------------- /dist/tags/tags.module.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"tags.module.js","sourceRoot":"","sources":["../../src/tags/tags.module.ts"],"names":[],"mappings":";;;;;;;;;AAAA,2CAAwC;AACxC,uDAAmD;AACnD,iDAA6C;AAMtC,IAAM,UAAU,GAAhB,MAAM,UAAU;CAAG,CAAA;AAAb,UAAU;IAJtB,IAAA,eAAM,EAAC;QACN,SAAS,EAAE,CAAC,0BAAW,CAAC;QACxB,WAAW,EAAE,CAAC,gCAAc,CAAC;KAC9B,CAAC;GACW,UAAU,CAAG;AAAb,gCAAU"} -------------------------------------------------------------------------------- /dist/tags/tags.service.d.ts: -------------------------------------------------------------------------------- 1 | import { PrismaService } from 'src/prisma/prisma.service'; 2 | export declare class TagsService { 3 | private prisma; 4 | constructor(prisma: PrismaService); 5 | getTags(): Promise; 6 | } 7 | -------------------------------------------------------------------------------- /dist/tags/tags.service.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { 3 | var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; 4 | if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); 5 | else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; 6 | return c > 3 && r && Object.defineProperty(target, key, r), r; 7 | }; 8 | var __metadata = (this && this.__metadata) || function (k, v) { 9 | if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); 10 | }; 11 | Object.defineProperty(exports, "__esModule", { value: true }); 12 | exports.TagsService = void 0; 13 | const common_1 = require("@nestjs/common"); 14 | const prisma_service_1 = require("../prisma/prisma.service"); 15 | let TagsService = class TagsService { 16 | constructor(prisma) { 17 | this.prisma = prisma; 18 | } 19 | async getTags() { 20 | const tags = await this.prisma.article.findMany({ 21 | select: { 22 | tagList: true, 23 | }, 24 | }); 25 | const flatTags = tags 26 | .map((tagList) => tagList.tagList) 27 | .reduce((a, b) => a.concat(b)); 28 | const returnTags = []; 29 | flatTags.forEach((tag) => { 30 | if (!((returnTags === null || returnTags === void 0 ? void 0 : returnTags.includes(tag)) || false)) 31 | returnTags.push(tag); 32 | }); 33 | return returnTags; 34 | } 35 | }; 36 | TagsService = __decorate([ 37 | (0, common_1.Injectable)(), 38 | __metadata("design:paramtypes", [prisma_service_1.PrismaService]) 39 | ], TagsService); 40 | exports.TagsService = TagsService; 41 | //# sourceMappingURL=tags.service.js.map -------------------------------------------------------------------------------- /dist/tags/tags.service.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"tags.service.js","sourceRoot":"","sources":["../../src/tags/tags.service.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,2CAA4C;AAC5C,6DAA0D;AAGnD,IAAM,WAAW,GAAjB,MAAM,WAAW;IACtB,YAAoB,MAAqB;QAArB,WAAM,GAAN,MAAM,CAAe;IAAG,CAAC;IAE7C,KAAK,CAAC,OAAO;QACX,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC;YAC9C,MAAM,EAAE;gBACN,OAAO,EAAE,IAAI;aACd;SACF,CAAC,CAAC;QACH,MAAM,QAAQ,GAAG,IAAI;aAClB,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,OAAO,CAAC;aACjC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;QACjC,MAAM,UAAU,GAAa,EAAE,CAAC;QAChC,QAAQ,CAAC,OAAO,CAAC,CAAC,GAAG,EAAE,EAAE;YACvB,IAAI,CAAC,CAAC,CAAA,UAAU,aAAV,UAAU,uBAAV,UAAU,CAAE,QAAQ,CAAC,GAAG,CAAC,KAAI,KAAK,CAAC;gBAAE,UAAU,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAClE,CAAC,CAAC,CAAC;QACH,OAAO,UAAU,CAAC;IACpB,CAAC;CACF,CAAA;AAlBY,WAAW;IADvB,IAAA,mBAAU,GAAE;qCAEiB,8BAAa;GAD9B,WAAW,CAkBvB;AAlBY,kCAAW"} -------------------------------------------------------------------------------- /dist/user/dto/index.d.ts: -------------------------------------------------------------------------------- 1 | export * from './user.dto'; 2 | export * from './profile.dto'; 3 | -------------------------------------------------------------------------------- /dist/user/dto/index.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { 3 | if (k2 === undefined) k2 = k; 4 | var desc = Object.getOwnPropertyDescriptor(m, k); 5 | if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { 6 | desc = { enumerable: true, get: function() { return m[k]; } }; 7 | } 8 | Object.defineProperty(o, k2, desc); 9 | }) : (function(o, m, k, k2) { 10 | if (k2 === undefined) k2 = k; 11 | o[k2] = m[k]; 12 | })); 13 | var __exportStar = (this && this.__exportStar) || function(m, exports) { 14 | for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); 15 | }; 16 | Object.defineProperty(exports, "__esModule", { value: true }); 17 | __exportStar(require("./user.dto"), exports); 18 | __exportStar(require("./profile.dto"), exports); 19 | //# sourceMappingURL=index.js.map -------------------------------------------------------------------------------- /dist/user/dto/index.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/user/dto/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,6CAA2B;AAC3B,gDAA8B"} -------------------------------------------------------------------------------- /dist/user/dto/profile.dto.d.ts: -------------------------------------------------------------------------------- 1 | export interface Profile { 2 | username: string; 3 | bio: string; 4 | image: string; 5 | following: boolean; 6 | } 7 | -------------------------------------------------------------------------------- /dist/user/dto/profile.dto.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | //# sourceMappingURL=profile.dto.js.map -------------------------------------------------------------------------------- /dist/user/dto/profile.dto.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"profile.dto.js","sourceRoot":"","sources":["../../../src/user/dto/profile.dto.ts"],"names":[],"mappings":""} -------------------------------------------------------------------------------- /dist/user/dto/user.dto.d.ts: -------------------------------------------------------------------------------- 1 | export interface LoginDto { 2 | email: string; 3 | password: string; 4 | } 5 | export interface UserDto { 6 | email: string; 7 | token: string; 8 | username: string; 9 | bio: string; 10 | image?: string; 11 | } 12 | export interface UserForRegistration { 13 | username: string; 14 | email: string; 15 | passeword: string; 16 | } 17 | export interface UserForUpdate { 18 | email?: string; 19 | username?: string; 20 | bio?: string; 21 | image?: string; 22 | } 23 | -------------------------------------------------------------------------------- /dist/user/dto/user.dto.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | //# sourceMappingURL=user.dto.js.map -------------------------------------------------------------------------------- /dist/user/dto/user.dto.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"user.dto.js","sourceRoot":"","sources":["../../../src/user/dto/user.dto.ts"],"names":[],"mappings":""} -------------------------------------------------------------------------------- /dist/user/user.controller.d.ts: -------------------------------------------------------------------------------- 1 | import { User } from '@prisma/client'; 2 | import { UserForUpdate } from './dto'; 3 | import { UserService } from './user.service'; 4 | export declare class UserController { 5 | private userService; 6 | constructor(userService: UserService); 7 | getCurrentUser(user: User): { 8 | user: User; 9 | }; 10 | updateUser(user: User, dto: UserForUpdate): Promise<{ 11 | user: User; 12 | }>; 13 | } 14 | -------------------------------------------------------------------------------- /dist/user/user.controller.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { 3 | var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; 4 | if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); 5 | else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; 6 | return c > 3 && r && Object.defineProperty(target, key, r), r; 7 | }; 8 | var __metadata = (this && this.__metadata) || function (k, v) { 9 | if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); 10 | }; 11 | var __param = (this && this.__param) || function (paramIndex, decorator) { 12 | return function (target, key) { decorator(target, key, paramIndex); } 13 | }; 14 | Object.defineProperty(exports, "__esModule", { value: true }); 15 | exports.UserController = void 0; 16 | const common_1 = require("@nestjs/common"); 17 | const get_user_decorator_1 = require("../common/decorator/get-user.decorator"); 18 | const guard_1 = require("../common/guard"); 19 | const user_service_1 = require("./user.service"); 20 | let UserController = class UserController { 21 | constructor(userService) { 22 | this.userService = userService; 23 | } 24 | getCurrentUser(user) { 25 | return { user: user }; 26 | } 27 | async updateUser(user, dto) { 28 | return { user: await this.userService.updateUser(user, dto) }; 29 | } 30 | }; 31 | __decorate([ 32 | (0, common_1.Get)(), 33 | __param(0, (0, get_user_decorator_1.GetUser)()), 34 | __metadata("design:type", Function), 35 | __metadata("design:paramtypes", [Object]), 36 | __metadata("design:returntype", void 0) 37 | ], UserController.prototype, "getCurrentUser", null); 38 | __decorate([ 39 | (0, common_1.Put)(), 40 | __param(0, (0, get_user_decorator_1.GetUser)()), 41 | __param(1, (0, common_1.Body)('user')), 42 | __metadata("design:type", Function), 43 | __metadata("design:paramtypes", [Object, Object]), 44 | __metadata("design:returntype", Promise) 45 | ], UserController.prototype, "updateUser", null); 46 | UserController = __decorate([ 47 | (0, common_1.UseGuards)(guard_1.JwtGuard), 48 | (0, common_1.Controller)('user'), 49 | __metadata("design:paramtypes", [user_service_1.UserService]) 50 | ], UserController); 51 | exports.UserController = UserController; 52 | //# sourceMappingURL=user.controller.js.map -------------------------------------------------------------------------------- /dist/user/user.controller.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"user.controller.js","sourceRoot":"","sources":["../../src/user/user.controller.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;AAAA,2CAAuE;AAEvE,+EAAkE;AAClE,2CAA4C;AAE5C,iDAA6C;AAItC,IAAM,cAAc,GAApB,MAAM,cAAc;IACzB,YAAoB,WAAwB;QAAxB,gBAAW,GAAX,WAAW,CAAa;IAAG,CAAC;IAEhD,cAAc,CAAY,IAAU;QAClC,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;IACxB,CAAC;IAGK,AAAN,KAAK,CAAC,UAAU,CAAY,IAAU,EAAgB,GAAkB;QACtE,OAAO,EAAE,IAAI,EAAE,MAAM,IAAI,CAAC,WAAW,CAAC,UAAU,CAAC,IAAI,EAAE,GAAG,CAAC,EAAE,CAAC;IAChE,CAAC;CACF,CAAA;AATC;IAAC,IAAA,YAAG,GAAE;IACU,WAAA,IAAA,4BAAO,GAAE,CAAA;;;;oDAExB;AAGK;IADL,IAAA,YAAG,GAAE;IACY,WAAA,IAAA,4BAAO,GAAE,CAAA;IAAc,WAAA,IAAA,aAAI,EAAC,MAAM,CAAC,CAAA;;;;gDAEpD;AAVU,cAAc;IAF1B,IAAA,kBAAS,EAAC,gBAAQ,CAAC;IACnB,IAAA,mBAAU,EAAC,MAAM,CAAC;qCAEgB,0BAAW;GADjC,cAAc,CAW1B;AAXY,wCAAc"} -------------------------------------------------------------------------------- /dist/user/user.module.d.ts: -------------------------------------------------------------------------------- 1 | export declare class UserModule { 2 | } 3 | -------------------------------------------------------------------------------- /dist/user/user.module.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { 3 | var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; 4 | if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); 5 | else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; 6 | return c > 3 && r && Object.defineProperty(target, key, r), r; 7 | }; 8 | Object.defineProperty(exports, "__esModule", { value: true }); 9 | exports.UserModule = void 0; 10 | const common_1 = require("@nestjs/common"); 11 | const user_controller_1 = require("./user.controller"); 12 | const user_service_1 = require("./user.service"); 13 | let UserModule = class UserModule { 14 | }; 15 | UserModule = __decorate([ 16 | (0, common_1.Module)({ 17 | controllers: [user_controller_1.UserController], 18 | providers: [user_service_1.UserService], 19 | }) 20 | ], UserModule); 21 | exports.UserModule = UserModule; 22 | //# sourceMappingURL=user.module.js.map -------------------------------------------------------------------------------- /dist/user/user.module.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"user.module.js","sourceRoot":"","sources":["../../src/user/user.module.ts"],"names":[],"mappings":";;;;;;;;;AAAA,2CAAwC;AACxC,uDAAmD;AACnD,iDAA6C;AAMtC,IAAM,UAAU,GAAhB,MAAM,UAAU;CAAG,CAAA;AAAb,UAAU;IAJtB,IAAA,eAAM,EAAC;QACN,WAAW,EAAE,CAAC,gCAAc,CAAC;QAC7B,SAAS,EAAE,CAAC,0BAAW,CAAC;KACzB,CAAC;GACW,UAAU,CAAG;AAAb,gCAAU"} -------------------------------------------------------------------------------- /dist/user/user.service.d.ts: -------------------------------------------------------------------------------- 1 | import { User } from '@prisma/client'; 2 | import { PrismaService } from 'src/prisma/prisma.service'; 3 | import { UserForUpdate } from './dto'; 4 | export declare class UserService { 5 | private prisma; 6 | constructor(prisma: PrismaService); 7 | updateUser(user: User, dto: UserForUpdate): Promise; 8 | } 9 | -------------------------------------------------------------------------------- /dist/user/user.service.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { 3 | var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; 4 | if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); 5 | else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; 6 | return c > 3 && r && Object.defineProperty(target, key, r), r; 7 | }; 8 | var __metadata = (this && this.__metadata) || function (k, v) { 9 | if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); 10 | }; 11 | Object.defineProperty(exports, "__esModule", { value: true }); 12 | exports.UserService = void 0; 13 | const common_1 = require("@nestjs/common"); 14 | const runtime_1 = require("@prisma/client/runtime"); 15 | const prisma_service_1 = require("../prisma/prisma.service"); 16 | let UserService = class UserService { 17 | constructor(prisma) { 18 | this.prisma = prisma; 19 | } 20 | async updateUser(user, dto) { 21 | try { 22 | const userUpdated = await this.prisma.user.update({ 23 | where: { 24 | email: user.email, 25 | }, 26 | data: Object.assign({}, dto), 27 | }); 28 | return userUpdated; 29 | } 30 | catch (error) { 31 | if (error instanceof runtime_1.PrismaClientKnownRequestError) { 32 | if (error.code === 'P2002') 33 | throw new common_1.BadRequestException('email or username taken'); 34 | } 35 | } 36 | } 37 | }; 38 | UserService = __decorate([ 39 | (0, common_1.Injectable)(), 40 | __metadata("design:paramtypes", [prisma_service_1.PrismaService]) 41 | ], UserService); 42 | exports.UserService = UserService; 43 | //# sourceMappingURL=user.service.js.map -------------------------------------------------------------------------------- /dist/user/user.service.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"user.service.js","sourceRoot":"","sources":["../../src/user/user.service.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,2CAAiE;AAEjE,oDAAuE;AACvE,6DAA0D;AAInD,IAAM,WAAW,GAAjB,MAAM,WAAW;IACtB,YAAoB,MAAqB;QAArB,WAAM,GAAN,MAAM,CAAe;IAAG,CAAC;IAE7C,KAAK,CAAC,UAAU,CAAC,IAAU,EAAE,GAAkB;QAC7C,IAAI;YACF,MAAM,WAAW,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC;gBAChD,KAAK,EAAE;oBACL,KAAK,EAAE,IAAI,CAAC,KAAK;iBAClB;gBACD,IAAI,oBACC,GAAG,CACP;aACF,CAAC,CAAC;YACH,OAAO,WAAW,CAAC;SACpB;QAAC,OAAO,KAAK,EAAE;YACd,IAAI,KAAK,YAAY,uCAA6B,EAAE;gBAClD,IAAI,KAAK,CAAC,IAAI,KAAK,OAAO;oBACxB,MAAM,IAAI,4BAAmB,CAAC,yBAAyB,CAAC,CAAC;aAC5D;SACF;IACH,CAAC;CACF,CAAA;AArBY,WAAW;IADvB,IAAA,mBAAU,GAAE;qCAEiB,8BAAa;GAD9B,WAAW,CAqBvB;AArBY,kCAAW"} -------------------------------------------------------------------------------- /favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gearhead041/realworld-nestjs-prisma-mongodb/6a9d48d29e187b17cc2707e2d808ff415b28181d/favicon.ico -------------------------------------------------------------------------------- /logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gearhead041/realworld-nestjs-prisma-mongodb/6a9d48d29e187b17cc2707e2d808ff415b28181d/logo.png -------------------------------------------------------------------------------- /nest-cli.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json.schemastore.org/nest-cli", 3 | "collection": "@nestjs/schematics", 4 | "sourceRoot": "src" 5 | } 6 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "conduit-backend", 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": "^9.0.0", 25 | "@nestjs/config": "^2.2.0", 26 | "@nestjs/core": "^9.0.0", 27 | "@nestjs/jwt": "^9.0.0", 28 | "@nestjs/passport": "^9.0.0", 29 | "@nestjs/platform-express": "^9.0.0", 30 | "@prisma/client": "^4.5.0", 31 | "argon2": "^0.30.1", 32 | "class-validator": "^0.13.2", 33 | "passport": "^0.6.0", 34 | "passport-jwt": "^4.0.0", 35 | "reflect-metadata": "^0.1.13", 36 | "rimraf": "^3.0.2", 37 | "rxjs": "^7.2.0" 38 | }, 39 | "devDependencies": { 40 | "@nestjs/cli": "^9.0.0", 41 | "@nestjs/schematics": "^9.0.0", 42 | "@nestjs/testing": "^9.0.0", 43 | "@types/express": "^4.17.13", 44 | "@types/jest": "28.1.8", 45 | "@types/node": "^16.0.0", 46 | "@types/passport-jwt": "^3.0.7", 47 | "@types/supertest": "^2.0.11", 48 | "@typescript-eslint/eslint-plugin": "^5.0.0", 49 | "@typescript-eslint/parser": "^5.0.0", 50 | "eslint": "^8.0.1", 51 | "eslint-config-prettier": "^8.3.0", 52 | "eslint-plugin-prettier": "^4.0.0", 53 | "jest": "28.1.3", 54 | "prettier": "^2.3.2", 55 | "prisma": "^4.5.0", 56 | "source-map-support": "^0.5.20", 57 | "supertest": "^6.1.3", 58 | "ts-jest": "28.0.8", 59 | "ts-loader": "^9.2.3", 60 | "ts-node": "^10.0.0", 61 | "tsconfig-paths": "4.1.0", 62 | "typescript": "^4.7.4" 63 | }, 64 | "jest": { 65 | "moduleFileExtensions": [ 66 | "js", 67 | "json", 68 | "ts" 69 | ], 70 | "rootDir": "src", 71 | "testRegex": ".*\\.spec\\.ts$", 72 | "transform": { 73 | "^.+\\.(t|j)s$": "ts-jest" 74 | }, 75 | "collectCoverageFrom": [ 76 | "**/*.(t|j)s" 77 | ], 78 | "coverageDirectory": "../coverage", 79 | "testEnvironment": "node" 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /prisma/schema.prisma: -------------------------------------------------------------------------------- 1 | // This is your Prisma schema file, 2 | // learn more about it in the docs: https://pris.ly/d/prisma-schema 3 | 4 | generator client { 5 | provider = "prisma-client-js" 6 | } 7 | 8 | datasource db { 9 | provider = "mongodb" 10 | url = env("DATABASE_URL") 11 | } 12 | 13 | model User{ 14 | id String @id @default(auto()) @map("_id") @db.ObjectId 15 | email String @unique 16 | username String @unique 17 | bio String? 18 | image String? 19 | password String 20 | comments Comment[] 21 | articles Article[] 22 | followers User[] @relation("authorFollowers", fields: [followersIds], references: [id]) 23 | followersIds String[] @db.ObjectId 24 | following User[] @relation("authorFollowers", fields: [followingIds], references: [id]) 25 | followingIds String[] @db.ObjectId 26 | articlesLiked Article[] @relation("likedArticles", fields: [articlesLikedIds], references: [id]) 27 | articlesLikedIds String[] @db.ObjectId 28 | } 29 | 30 | model Article { 31 | id String @id @default(auto()) @map("_id") @db.ObjectId 32 | title String 33 | slug String @unique 34 | description String 35 | createdAt DateTime @default(now()) 36 | updatedAt DateTime @updatedAt 37 | body String 38 | tagList String[] @default([]) 39 | favouritedUsers User[] @relation( "likedArticles", fields: [favouritedUserIds], references: [id]) 40 | favouritedUserIds String[] @db.ObjectId 41 | author User @relation(fields: [authorId], references: [id], onDelete: Cascade) 42 | authorId String 43 | comments Comment[] 44 | } 45 | 46 | model Comment { 47 | id String @id @default(auto()) @map("_id") @db.ObjectId 48 | body String 49 | createdAt DateTime @default(now()) 50 | updatedAt DateTime @updatedAt 51 | author User @relation(fields: [authorId], references: [id], onDelete: Cascade) 52 | authorId String 53 | article Article @relation(fields: [articleId], references: [id], onDelete: Cascade) 54 | articleId String 55 | } 56 | 57 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /src/app.controller.ts: -------------------------------------------------------------------------------- 1 | import { Controller, Get } from '@nestjs/common'; 2 | import { AppService } from './app.service'; 3 | 4 | @Controller() 5 | export class AppController { 6 | constructor(private readonly appService: AppService) {} 7 | 8 | @Get() 9 | getHello(): string { 10 | return this.appService.getHello(); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/app.module.ts: -------------------------------------------------------------------------------- 1 | import { Module } from '@nestjs/common'; 2 | import { PrismaModule } from './prisma/prisma.module'; 3 | import { ProfilesModule } from './profiles/profiles.module'; 4 | import { AuthModule } from './auth/auth.module'; 5 | import { TagsModule } from './tags/tags.module'; 6 | import { UserModule } from './user/user.module'; 7 | import { ArticlesModule } from './articles/articles.module'; 8 | import { ConfigModule } from '@nestjs/config'; 9 | 10 | @Module({ 11 | imports: [ 12 | PrismaModule, 13 | ProfilesModule, 14 | AuthModule, 15 | TagsModule, 16 | UserModule, 17 | ArticlesModule, 18 | ConfigModule.forRoot({ 19 | isGlobal: true, 20 | }), 21 | ], 22 | }) 23 | export class AppModule {} 24 | -------------------------------------------------------------------------------- /src/app.service.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from '@nestjs/common'; 2 | 3 | @Injectable() 4 | export class AppService { 5 | getHello(): string { 6 | return 'Hello World!'; 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /src/articles/articles.controller.spec.ts: -------------------------------------------------------------------------------- 1 | import { Test, TestingModule } from '@nestjs/testing'; 2 | import { ArticlesController } from './articles.controller'; 3 | 4 | describe('ArticlesController', () => { 5 | let controller: ArticlesController; 6 | 7 | beforeEach(async () => { 8 | const module: TestingModule = await Test.createTestingModule({ 9 | controllers: [ArticlesController], 10 | }).compile(); 11 | 12 | controller = module.get(ArticlesController); 13 | }); 14 | 15 | it('should be defined', () => { 16 | expect(controller).toBeDefined(); 17 | }); 18 | }); 19 | -------------------------------------------------------------------------------- /src/articles/articles.controller.ts: -------------------------------------------------------------------------------- 1 | import { 2 | Body, 3 | Controller, 4 | Delete, 5 | Get, 6 | HttpCode, 7 | HttpStatus, 8 | Param, 9 | Post, 10 | Put, 11 | Query, 12 | UseGuards, 13 | } from '@nestjs/common'; 14 | import { User } from '@prisma/client'; 15 | import { AllowAny, GetUser } from '../common/decorator'; 16 | import { JwtGuard } from '../common/guard'; 17 | import { ArticlesService } from './articles.service'; 18 | 19 | @Controller('articles') 20 | export class ArticlesController { 21 | constructor(private articleService: ArticlesService) {} 22 | 23 | @Get() 24 | @UseGuards(JwtGuard) 25 | @AllowAny() 26 | async getAllArticles( 27 | @GetUser() user: User, 28 | //filter by tag 29 | @Query('tag') tag?: string, 30 | //filter by author 31 | @Query('author') author?: string, 32 | //favorited by user 33 | @Query('favorited') favorited?: string, 34 | //limit number of articles returned 35 | @Query('limit') limit = 10, 36 | //skip number of articles 37 | @Query('offset') offset = 0, 38 | ) { 39 | const articles = await this.articleService.findArticles( 40 | user, 41 | tag, 42 | author, 43 | favorited, 44 | limit, 45 | offset, 46 | ); 47 | return { 48 | articles: articles, 49 | articlesCount: articles.length, 50 | }; 51 | } 52 | 53 | @UseGuards(JwtGuard) 54 | @Get('feed') 55 | async getUserFeed( 56 | @GetUser() user: User, 57 | @Query('limit') limit = 10, 58 | @Query('offset') offset = 0, 59 | ) { 60 | const articles = await this.articleService.getUserFeed(user, limit, offset); 61 | return { 62 | articles: articles, 63 | articlesCount: articles.length, 64 | }; 65 | } 66 | 67 | @Get(':slug') 68 | async getArticle(@GetUser() user: User, @Param('slug') slug: string) { 69 | return { article: await this.articleService.findArticle(user, slug) }; 70 | } 71 | 72 | @UseGuards(JwtGuard) 73 | @Post() 74 | async createArticle(@GetUser() user: User, @Body('article') dto) { 75 | return { 76 | article: await this.articleService.createArticle(user, dto), 77 | }; 78 | } 79 | 80 | @UseGuards(JwtGuard) 81 | @Put(':slug') 82 | async updateArticle( 83 | @GetUser() user: User, 84 | @Param('slug') slug: string, 85 | @Body() dto, 86 | ) { 87 | return { 88 | article: await this.articleService.updateArticle(user, slug, dto.article), 89 | }; 90 | } 91 | 92 | @HttpCode(HttpStatus.NO_CONTENT) 93 | @UseGuards(JwtGuard) 94 | @Delete(':slug') 95 | deleteArticle(@Param('slug') slug: string) { 96 | return this.articleService.deleteArticle(slug); 97 | } 98 | 99 | @UseGuards(JwtGuard) 100 | @Post(':slug/comments') 101 | async addCommentToArticle( 102 | @GetUser() user: User, 103 | @Param('slug') slug: string, 104 | @Body() dto, 105 | ) { 106 | return { 107 | comment: await this.articleService.addCommentToArticle( 108 | user, 109 | slug, 110 | dto.comment, 111 | ), 112 | }; 113 | } 114 | 115 | @Get(':slug/comments') 116 | async getCommentsForArticle(@Param('slug') slug: string) { 117 | return { comments: await this.articleService.getCommentsForArticle(slug) }; 118 | } 119 | 120 | @UseGuards(JwtGuard) 121 | @Delete(':slug/comments/:id') 122 | deleteComment(@Param('slug') slug: string, @Param('id') id: string) { 123 | return this.articleService.deleteCommentForArticle(slug, id); 124 | } 125 | 126 | @UseGuards(JwtGuard) 127 | @Post(':slug/favorite') 128 | async favoriteArticle(@GetUser() user: User, @Param('slug') slug: string) { 129 | return { article: await this.articleService.favouriteArticle(user, slug) }; 130 | } 131 | 132 | @UseGuards(JwtGuard) 133 | @Delete(':slug/favorite') 134 | async unfavoriteArticle(@GetUser() user: User, @Param('slug') slug: string) { 135 | return { 136 | article: await this.articleService.unfavouriteArticle(user, slug), 137 | }; 138 | } 139 | } 140 | -------------------------------------------------------------------------------- /src/articles/articles.module.ts: -------------------------------------------------------------------------------- 1 | import { Module } from '@nestjs/common'; 2 | import { ArticlesController } from './articles.controller'; 3 | import { ArticlesService } from './articles.service'; 4 | 5 | @Module({ 6 | controllers: [ArticlesController], 7 | providers: [ArticlesService], 8 | }) 9 | export class ArticlesModule {} 10 | -------------------------------------------------------------------------------- /src/articles/articles.service.spec.ts: -------------------------------------------------------------------------------- 1 | import { Test, TestingModule } from '@nestjs/testing'; 2 | import { ArticlesService } from './articles.service'; 3 | 4 | describe('ArticlesService', () => { 5 | let service: ArticlesService; 6 | 7 | beforeEach(async () => { 8 | const module: TestingModule = await Test.createTestingModule({ 9 | providers: [ArticlesService], 10 | }).compile(); 11 | 12 | service = module.get(ArticlesService); 13 | }); 14 | 15 | it('should be defined', () => { 16 | expect(service).toBeDefined(); 17 | }); 18 | }); 19 | -------------------------------------------------------------------------------- /src/articles/articles.service.ts: -------------------------------------------------------------------------------- 1 | import { 2 | BadRequestException, 3 | Injectable, 4 | NotFoundException, 5 | } from '@nestjs/common'; 6 | import { User } from '@prisma/client'; 7 | import { 8 | PrismaClientKnownRequestError, 9 | PrismaClientValidationError, 10 | } from '@prisma/client/runtime'; 11 | import { PrismaService } from '../prisma/prisma.service'; 12 | import { castToProfile, ProfileDto } from '../profiles/dto'; 13 | import { 14 | ArticleForCreateDto, 15 | ArticleForUpdateDto, 16 | castToArticle, 17 | castToCommentDto, 18 | CommentForCreateDto, 19 | } from './dto'; 20 | 21 | @Injectable() 22 | export class ArticlesService { 23 | constructor(private prisma: PrismaService) {} 24 | 25 | async findArticles( 26 | user: User, 27 | tag: string, 28 | author: string, 29 | favorited?: string, 30 | limit = 10, 31 | offset = 0, 32 | ) { 33 | let articles = await this.prisma.article.findMany({ 34 | where: { 35 | author: { 36 | username: author, 37 | }, 38 | }, 39 | take: limit, 40 | skip: offset, 41 | include: { 42 | author: true, 43 | favouritedUsers: true, 44 | }, 45 | orderBy: { 46 | updatedAt: 'desc', 47 | }, 48 | }); 49 | if (tag) 50 | articles = articles.filter((article) => 51 | article.tagList.some((db) => db === tag), 52 | ); 53 | 54 | if (favorited) { 55 | const favouritedUser = await this.prisma.user.findUnique({ 56 | where: { 57 | username: favorited, 58 | }, 59 | }); 60 | if (favouritedUser) 61 | articles = articles.filter((article) => 62 | article.favouritedUserIds.includes(favouritedUser.id), 63 | ); 64 | else throw new NotFoundException(`user ${favorited} not found`); 65 | } 66 | 67 | if (author) { 68 | articles = articles.filter( 69 | (article) => article.author.username === author, 70 | ); 71 | } 72 | 73 | const articlesDto = articles.map((article) => { 74 | const following = 75 | article.author?.followersIds.includes(user?.id || '') || false; 76 | let authorProfile: ProfileDto; 77 | if (!article.author) authorProfile = null; 78 | else authorProfile = castToProfile(article.author, following); 79 | return castToArticle(article, user, article.tagList, authorProfile); 80 | }); 81 | return articlesDto; 82 | } 83 | 84 | async findArticle(user: User, slug: string) { 85 | const article = await this.prisma.article.findUnique({ 86 | where: { 87 | slug: slug, 88 | }, 89 | include: { 90 | author: true, 91 | }, 92 | }); 93 | if (article === null) throw new NotFoundException('article not found'); 94 | 95 | const following = article.author?.followersIds?.includes(user?.id) || false; 96 | 97 | const authorProfile = castToProfile(article.author, following); 98 | return castToArticle(article, user, article.tagList, authorProfile); 99 | } 100 | 101 | async getUserFeed(user: User, limit: number, offset: number) { 102 | let articles = await this.prisma.article.findMany({ 103 | include: { 104 | author: true, 105 | }, 106 | take: limit, 107 | skip: offset, 108 | orderBy: { 109 | updatedAt: 'desc', 110 | }, 111 | }); 112 | articles = articles.filter((article) => { 113 | if (!article.author) return false; 114 | return article.author.followersIds.includes(user.id) || false; 115 | }); 116 | 117 | const articlesDto = articles.map((article) => { 118 | const authorProfile = castToProfile(article.author, true); 119 | return castToArticle(article, user, article.tagList, authorProfile); 120 | }); 121 | return articlesDto; 122 | } 123 | 124 | async createArticle(user: User, articletoCreate: ArticleForCreateDto) { 125 | const slug = articletoCreate.title.split(' ').join('-'); 126 | try { 127 | const article = await this.prisma.article.create({ 128 | data: { 129 | ...articletoCreate, 130 | authorId: user.id, 131 | slug: slug, 132 | favouritedUserIds: user.id, 133 | tagList: { 134 | set: articletoCreate.tagList, 135 | }, 136 | }, 137 | }); 138 | return castToArticle( 139 | article, 140 | user, 141 | article.tagList, 142 | castToProfile(user, false), 143 | ); 144 | } catch (error) { 145 | if (error instanceof PrismaClientValidationError) { 146 | throw new BadRequestException('bad request'); 147 | } 148 | // if (error.code === 'P2002') 149 | } 150 | } 151 | 152 | async updateArticle(user: User, slug: string, dto: ArticleForUpdateDto) { 153 | // const newSlug = slug + '.01'; 154 | try { 155 | const article = await this.prisma.article.update({ 156 | where: { 157 | slug: slug, 158 | }, 159 | data: { 160 | ...dto, 161 | slug: slug, 162 | }, 163 | include: { 164 | author: true, 165 | }, 166 | }); 167 | return castToArticle( 168 | article, 169 | user, 170 | article.tagList, 171 | castToProfile(article.author, false), 172 | ); 173 | } catch (error) { 174 | if (error instanceof PrismaClientKnownRequestError) 175 | if (error.code === 'P2025') 176 | throw new NotFoundException('article not found'); 177 | } 178 | } 179 | 180 | async deleteArticle(slug: string) { 181 | const article = await this.prisma.article.findUnique({ 182 | where: { slug: slug }, 183 | }); 184 | if (!article) throw new NotFoundException('article not found'); 185 | await this.prisma.article.delete({ 186 | where: { 187 | slug: slug, 188 | }, 189 | }); 190 | return; 191 | } 192 | 193 | async addCommentToArticle( 194 | user: User, 195 | slug: string, 196 | dto: CommentForCreateDto, 197 | ) { 198 | const article = await this.prisma.article.findUnique({ 199 | where: { 200 | slug: slug, 201 | }, 202 | }); 203 | if (!article) throw new NotFoundException('article not found'); 204 | const comment = await this.prisma.comment.create({ 205 | data: { 206 | articleId: article.id, 207 | body: dto.body, 208 | authorId: user.id, 209 | }, 210 | }); 211 | return castToCommentDto(comment, castToProfile(user, false)); 212 | } 213 | 214 | async getCommentsForArticle(slug: string) { 215 | const article = await this.prisma.article.findUnique({ 216 | where: { 217 | slug: slug, 218 | }, 219 | select: { 220 | comments: { 221 | include: { 222 | author: true, 223 | }, 224 | }, 225 | }, 226 | }); 227 | if (article === null) throw new NotFoundException('article not found'); 228 | return article.comments.map((comment) => { 229 | return castToCommentDto(comment, castToProfile(comment.author, false)); 230 | }); 231 | } 232 | 233 | async deleteCommentForArticle(slug: string, id: string) { 234 | try { 235 | await this.prisma.article.update({ 236 | where: { 237 | slug: slug, 238 | }, 239 | 240 | data: { 241 | comments: { 242 | delete: { 243 | id: id, 244 | }, 245 | }, 246 | }, 247 | }); 248 | } catch (error) { 249 | if (error instanceof PrismaClientKnownRequestError) 250 | if (error.code === 'P2002') 251 | throw new NotFoundException('article not found'); 252 | } 253 | } 254 | 255 | async favouriteArticle(user: User, slug: string) { 256 | let article = await this.prisma.article.findUnique({ 257 | where: { slug: slug }, 258 | include: { 259 | author: true, 260 | }, 261 | }); 262 | if (!article) throw new NotFoundException('article not found'); 263 | if (!article.favouritedUserIds.includes(user.id)) { 264 | article = await this.prisma.article.update({ 265 | where: { 266 | slug: slug, 267 | }, 268 | data: { 269 | favouritedUserIds: { 270 | push: user.id, 271 | }, 272 | }, 273 | include: { 274 | author: true, 275 | }, 276 | }); 277 | } 278 | const following = article.author?.followersIds.includes(user.id) || false; 279 | return castToArticle( 280 | article, 281 | user, 282 | article.tagList, 283 | castToProfile(user, following), 284 | ); 285 | } 286 | 287 | async unfavouriteArticle(user: User, slug: string) { 288 | const article = await this.prisma.article.findUnique({ 289 | where: { slug: slug }, 290 | }); 291 | if (!article) throw new NotFoundException('article not found'); 292 | article.favouritedUserIds = article.favouritedUserIds.filter( 293 | (id) => id !== user.id, 294 | ); 295 | delete article.id; 296 | const articleUpdated = await this.prisma.article.update({ 297 | where: { slug: slug }, 298 | data: article, 299 | include: { author: true }, 300 | }); 301 | const isfollowing = 302 | articleUpdated.author?.followersIds.includes(user.id) || false; 303 | return castToArticle( 304 | article, 305 | user, 306 | article.tagList, 307 | castToProfile(articleUpdated.author, isfollowing), 308 | ); 309 | } 310 | } 311 | -------------------------------------------------------------------------------- /src/articles/dto/article.dto.ts: -------------------------------------------------------------------------------- 1 | import { Article, User } from '@prisma/client'; 2 | import { ProfileDto } from '../../profiles/dto'; 3 | 4 | export interface ArticleForCreateDto { 5 | title: string; 6 | description: string; 7 | body: string; 8 | tagList?: string[]; 9 | } 10 | 11 | export interface ArticleForUpdateDto { 12 | title?: string; 13 | description?: string; 14 | body?: string; 15 | } 16 | 17 | export interface ArticleDto { 18 | slug: string; 19 | title: string; 20 | description: string; 21 | body: string; 22 | tagList?: string[]; 23 | favoritesCount: number; 24 | author: ProfileDto; 25 | favorited: boolean; 26 | createdAt: Date; 27 | updatedAt: Date; 28 | } 29 | 30 | export function castToArticle( 31 | article: Article, 32 | user: User, 33 | tags: string[], 34 | author: ProfileDto, 35 | ): ArticleDto { 36 | return { 37 | slug: article.slug, 38 | title: article.title, 39 | description: article.description, 40 | body: article.body, 41 | tagList: tags, 42 | createdAt: article.createdAt, 43 | updatedAt: article.updatedAt, 44 | favorited: article.favouritedUserIds.includes(user?.id) || false, 45 | favoritesCount: article.favouritedUserIds.length, 46 | author: author, 47 | }; 48 | } 49 | -------------------------------------------------------------------------------- /src/articles/dto/comment.dto.ts: -------------------------------------------------------------------------------- 1 | import { ProfileDto } from '../../profiles/dto'; 2 | import { Comment } from '@prisma/client'; 3 | export interface CommentForCreateDto { 4 | body: string; 5 | } 6 | 7 | export interface CommentDto { 8 | id: string; 9 | createdAt: Date; 10 | updatedAt: Date; 11 | body: string; 12 | author: ProfileDto; 13 | } 14 | 15 | export function castToCommentDto( 16 | comment: Comment, 17 | author: ProfileDto, 18 | ): CommentDto { 19 | return { 20 | id: comment.id, 21 | createdAt: comment.createdAt, 22 | updatedAt: comment.updatedAt, 23 | body: comment.body, 24 | author: author, 25 | }; 26 | } 27 | -------------------------------------------------------------------------------- /src/articles/dto/index.ts: -------------------------------------------------------------------------------- 1 | export * from './article.dto'; 2 | export * from './comment.dto'; 3 | -------------------------------------------------------------------------------- /src/auth/auth.controller.spec.ts: -------------------------------------------------------------------------------- 1 | import { Test, TestingModule } from '@nestjs/testing'; 2 | import { AuthController } from './auth.controller'; 3 | 4 | describe('AuthController', () => { 5 | let controller: AuthController; 6 | 7 | beforeEach(async () => { 8 | const module: TestingModule = await Test.createTestingModule({ 9 | controllers: [AuthController], 10 | }).compile(); 11 | 12 | controller = module.get(AuthController); 13 | }); 14 | 15 | it('should be defined', () => { 16 | expect(controller).toBeDefined(); 17 | }); 18 | }); 19 | -------------------------------------------------------------------------------- /src/auth/auth.controller.ts: -------------------------------------------------------------------------------- 1 | import { Body, Controller, Post } from '@nestjs/common'; 2 | import { AuthService } from './auth.service'; 3 | import { LoginDto, UserForRegistration } from './dto'; 4 | 5 | @Controller('users') 6 | export class AuthController { 7 | constructor(private readonly authService: AuthService) {} 8 | @Post('login') 9 | async loginUser(@Body('user') dto: LoginDto) { 10 | const user = await this.authService.verifyUser(dto); 11 | return { user: user }; 12 | } 13 | 14 | @Post() 15 | async registerUser(@Body('user') dto: UserForRegistration) { 16 | const user = await this.authService.createUser(dto); 17 | return { user: user }; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/auth/auth.module.ts: -------------------------------------------------------------------------------- 1 | import { Module } from '@nestjs/common'; 2 | import { JwtModule } from '@nestjs/jwt'; 3 | import { AuthController } from './auth.controller'; 4 | import { AuthService } from './auth.service'; 5 | import { JwtStrategy } from './strategy'; 6 | 7 | @Module({ 8 | imports: [JwtModule.register({})], 9 | controllers: [AuthController], 10 | providers: [AuthService, JwtStrategy], 11 | }) 12 | export class AuthModule {} 13 | -------------------------------------------------------------------------------- /src/auth/auth.service.spec.ts: -------------------------------------------------------------------------------- 1 | import { Test, TestingModule } from '@nestjs/testing'; 2 | import { AuthService } from './auth.service'; 3 | 4 | describe('AuthService', () => { 5 | let service: AuthService; 6 | 7 | beforeEach(async () => { 8 | const module: TestingModule = await Test.createTestingModule({ 9 | providers: [AuthService], 10 | }).compile(); 11 | 12 | service = module.get(AuthService); 13 | }); 14 | 15 | it('should be defined', () => { 16 | expect(service).toBeDefined(); 17 | }); 18 | }); 19 | -------------------------------------------------------------------------------- /src/auth/auth.service.ts: -------------------------------------------------------------------------------- 1 | import { 2 | BadRequestException, 3 | Injectable, 4 | NotFoundException, 5 | UnauthorizedException, 6 | } from '@nestjs/common'; 7 | import { PrismaService } from 'src/prisma/prisma.service'; 8 | import { LoginDto, UserDto, UserForRegistration } from './dto'; 9 | import * as argon from 'argon2'; 10 | import { ConfigService } from '@nestjs/config'; 11 | import { JwtService } from '@nestjs/jwt'; 12 | import { PrismaClientKnownRequestError } from '@prisma/client/runtime'; 13 | 14 | @Injectable() 15 | export class AuthService { 16 | constructor( 17 | private prisma: PrismaService, 18 | private config: ConfigService, 19 | private jwt: JwtService, 20 | ) {} 21 | 22 | async createUser(dto: UserForRegistration) { 23 | const password = await argon.hash(dto.password); 24 | try { 25 | const user = await this.prisma.user.create({ 26 | data: { 27 | ...dto, 28 | password: password, 29 | }, 30 | }); 31 | const token = await this.signToken(user.id, user.email); 32 | const userToReturn: UserDto = { 33 | email: user.email, 34 | token: token, 35 | username: user.username, 36 | bio: user.bio, 37 | image: user.image, 38 | }; 39 | 40 | return userToReturn; 41 | } catch (e) { 42 | if (e instanceof PrismaClientKnownRequestError) { 43 | if (e.code === 'P2002') throw new BadRequestException('email is taken'); 44 | } 45 | } 46 | } 47 | 48 | async verifyUser(dto: LoginDto) { 49 | const user = await this.prisma.user.findUnique({ 50 | where: { 51 | email: dto.email, 52 | }, 53 | }); 54 | if (!user) throw new NotFoundException('user does not exist'); 55 | const matches = await argon.verify(user.password, dto.password); 56 | if (!matches) 57 | throw new UnauthorizedException('password and email do not match'); 58 | const token = await this.signToken(user.id, user.email); 59 | const userReturned: UserDto = { 60 | email: user.email, 61 | token: token, 62 | username: user.username, 63 | bio: user.bio, 64 | image: user.image, 65 | }; 66 | return userReturned; 67 | } 68 | 69 | async signToken(userId: string, email: string): Promise { 70 | const data = { 71 | sub: userId, 72 | email: email, 73 | }; 74 | const SECRET = this.config.get('SECRET'); 75 | const token = await this.jwt.signAsync(data, { 76 | secret: SECRET, 77 | expiresIn: '5h', 78 | }); 79 | return token; 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /src/auth/dto/index.ts: -------------------------------------------------------------------------------- 1 | export * from './user.dto'; 2 | -------------------------------------------------------------------------------- /src/auth/dto/user.dto.ts: -------------------------------------------------------------------------------- 1 | export interface LoginDto { 2 | email: string; 3 | password: string; 4 | } 5 | 6 | export interface UserDto { 7 | email: string; 8 | token: string; 9 | username: string; 10 | bio: string; 11 | image?: string; 12 | } 13 | 14 | export interface UserForRegistration { 15 | email: string; 16 | password: string; 17 | username: string; 18 | } 19 | 20 | export interface UserForUpdate { 21 | email?: string; 22 | username?: string; 23 | bio?: string; 24 | image?: string; 25 | } 26 | -------------------------------------------------------------------------------- /src/auth/strategy/index.ts: -------------------------------------------------------------------------------- 1 | export * from './jwt.strategy'; 2 | -------------------------------------------------------------------------------- /src/auth/strategy/jwt.strategy.ts: -------------------------------------------------------------------------------- 1 | import { ExtractJwt, Strategy } from 'passport-jwt'; 2 | import { PassportStrategy } from '@nestjs/passport'; 3 | import { Injectable } from '@nestjs/common'; 4 | import { ConfigService } from '@nestjs/config'; 5 | import { PrismaService } from '../../prisma/prisma.service'; 6 | 7 | @Injectable() 8 | export class JwtStrategy extends PassportStrategy(Strategy) { 9 | constructor(private config: ConfigService, private prisma: PrismaService) { 10 | super({ 11 | jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(), 12 | secretOrKey: config.get('SECRET'), 13 | }); 14 | } 15 | 16 | async validate(payload: { sub: string; email: string }) { 17 | //this value is appended to req.user 18 | //this means we can access it in the controller 19 | const user = await this.prisma.user.findUnique({ 20 | where: { id: payload.sub }, 21 | select: { 22 | id: true, 23 | email: true, 24 | bio: true, 25 | username: true, 26 | followers: true, 27 | image: true, 28 | }, 29 | }); 30 | return user; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/common/decorator/allow-any.decorator.ts: -------------------------------------------------------------------------------- 1 | import { SetMetadata } from '@nestjs/common'; 2 | 3 | export const AllowAny = () => SetMetadata('allow-any', true); 4 | -------------------------------------------------------------------------------- /src/common/decorator/get-user.decorator.ts: -------------------------------------------------------------------------------- 1 | import { createParamDecorator, ExecutionContext } from '@nestjs/common'; 2 | 3 | export const GetUser = createParamDecorator( 4 | (data: any | undefined, ctx: ExecutionContext) => { 5 | const request: Express.Request = ctx.switchToHttp().getRequest(); 6 | if (data) return request.user[data]; 7 | return request.user; 8 | }, 9 | ); 10 | -------------------------------------------------------------------------------- /src/common/decorator/index.ts: -------------------------------------------------------------------------------- 1 | export * from './allow-any.decorator'; 2 | export * from './get-user.decorator'; 3 | -------------------------------------------------------------------------------- /src/common/filters/prisma-exceptions.filter.ts: -------------------------------------------------------------------------------- 1 | import { Catch } from '@nestjs/common'; 2 | import { PrismaClientKnownRequestError } from '@prisma/client/runtime'; 3 | 4 | // @Catch(PrismaClientKnownRequestError) 5 | -------------------------------------------------------------------------------- /src/common/guard/index.ts: -------------------------------------------------------------------------------- 1 | export * from './jwt.guard'; 2 | -------------------------------------------------------------------------------- /src/common/guard/jwt.guard.ts: -------------------------------------------------------------------------------- 1 | import { ExecutionContext, UnauthorizedException } from '@nestjs/common'; 2 | import { Reflector } from '@nestjs/core'; 3 | import { AuthGuard } from '@nestjs/passport'; 4 | 5 | export class JwtGuard extends AuthGuard('jwt') { 6 | constructor(private reflector: Reflector) { 7 | super(); 8 | } 9 | 10 | handleRequest( 11 | err: any, 12 | user: any, 13 | info: any, 14 | context: ExecutionContext, 15 | status?: any, 16 | ) { 17 | const request = context.switchToHttp().getRequest(); 18 | //HACK not recommended though 😅 19 | this.reflector = new Reflector(); 20 | const allowAny = this.reflector.get( 21 | 'allow-any', 22 | context.getHandler(), 23 | ); 24 | if (user) return user; 25 | if (allowAny) return true; 26 | throw new UnauthorizedException(); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /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 | app.setGlobalPrefix('api'); 7 | await app.listen(3000); 8 | } 9 | bootstrap(); 10 | -------------------------------------------------------------------------------- /src/prisma/prisma.module.ts: -------------------------------------------------------------------------------- 1 | import { Global, Module } from '@nestjs/common'; 2 | import { PrismaService } from './prisma.service'; 3 | 4 | @Global() 5 | @Module({ 6 | providers: [PrismaService], 7 | exports: [PrismaService], 8 | }) 9 | export class PrismaModule {} 10 | -------------------------------------------------------------------------------- /src/prisma/prisma.service.spec.ts: -------------------------------------------------------------------------------- 1 | import { Test, TestingModule } from '@nestjs/testing'; 2 | import { PrismaService } from './prisma.service'; 3 | 4 | describe('PrismaService', () => { 5 | let service: PrismaService; 6 | 7 | beforeEach(async () => { 8 | const module: TestingModule = await Test.createTestingModule({ 9 | providers: [PrismaService], 10 | }).compile(); 11 | 12 | service = module.get(PrismaService); 13 | }); 14 | 15 | it('should be defined', () => { 16 | expect(service).toBeDefined(); 17 | }); 18 | }); 19 | -------------------------------------------------------------------------------- /src/prisma/prisma.service.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from '@nestjs/common'; 2 | import { PrismaClient } from '@prisma/client'; 3 | 4 | @Injectable() 5 | export class PrismaService extends PrismaClient {} 6 | -------------------------------------------------------------------------------- /src/profiles/dto/index.ts: -------------------------------------------------------------------------------- 1 | export * from './profile.dto'; 2 | -------------------------------------------------------------------------------- /src/profiles/dto/profile.dto.ts: -------------------------------------------------------------------------------- 1 | import { User } from '@prisma/client'; 2 | 3 | export interface ProfileDto { 4 | username: string; 5 | bio: string; 6 | image: string; 7 | following: boolean; 8 | } 9 | 10 | export function castToProfile(user: User, isFollowing: boolean): ProfileDto { 11 | return { 12 | username: user.username, 13 | bio: user.bio, 14 | image: user.image, 15 | following: isFollowing, 16 | }; 17 | } 18 | -------------------------------------------------------------------------------- /src/profiles/profiles.controller.spec.ts: -------------------------------------------------------------------------------- 1 | import { Test, TestingModule } from '@nestjs/testing'; 2 | import { ProfilesController } from './profiles.controller'; 3 | 4 | describe('ProfilesController', () => { 5 | let controller: ProfilesController; 6 | 7 | beforeEach(async () => { 8 | const module: TestingModule = await Test.createTestingModule({ 9 | controllers: [ProfilesController], 10 | }).compile(); 11 | 12 | controller = module.get(ProfilesController); 13 | }); 14 | 15 | it('should be defined', () => { 16 | expect(controller).toBeDefined(); 17 | }); 18 | }); 19 | -------------------------------------------------------------------------------- /src/profiles/profiles.controller.ts: -------------------------------------------------------------------------------- 1 | import { 2 | Controller, 3 | Delete, 4 | Get, 5 | HttpCode, 6 | HttpStatus, 7 | Param, 8 | Post, 9 | UseGuards, 10 | } from '@nestjs/common'; 11 | import { User } from '@prisma/client'; 12 | import { GetUser } from 'src/common/decorator/get-user.decorator'; 13 | import { JwtGuard } from 'src/common/guard'; 14 | import { ProfilesService } from './profiles.service'; 15 | 16 | @UseGuards(JwtGuard) 17 | @Controller('profiles') 18 | export class ProfilesController { 19 | constructor(private profileService: ProfilesService) {} 20 | @Get(':username') 21 | async findUser(@GetUser() user: User, @Param('username') userName: string) { 22 | return { profile: await this.profileService.findUser(user, userName) }; 23 | } 24 | 25 | @HttpCode(HttpStatus.OK) 26 | @Post(':username/follow') 27 | async followUser(@GetUser() user: User, @Param('username') userName: string) { 28 | return { profile: await this.profileService.followUser(user, userName) }; 29 | } 30 | 31 | @Delete(':username/follow') 32 | async unfollowUser( 33 | @GetUser() user: User, 34 | @Param('username') username: string, 35 | ) { 36 | return { profile: await this.profileService.unfollowUser(user, username) }; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/profiles/profiles.module.ts: -------------------------------------------------------------------------------- 1 | import { Module } from '@nestjs/common'; 2 | import { ProfilesController } from './profiles.controller'; 3 | import { ProfilesService } from './profiles.service'; 4 | 5 | @Module({ 6 | controllers: [ProfilesController], 7 | providers: [ProfilesService], 8 | }) 9 | export class ProfilesModule {} 10 | -------------------------------------------------------------------------------- /src/profiles/profiles.service.spec.ts: -------------------------------------------------------------------------------- 1 | import { Test, TestingModule } from '@nestjs/testing'; 2 | import { ProfilesService } from './profiles.service'; 3 | 4 | describe('ProfilesService', () => { 5 | let service: ProfilesService; 6 | 7 | beforeEach(async () => { 8 | const module: TestingModule = await Test.createTestingModule({ 9 | providers: [ProfilesService], 10 | }).compile(); 11 | 12 | service = module.get(ProfilesService); 13 | }); 14 | 15 | it('should be defined', () => { 16 | expect(service).toBeDefined(); 17 | }); 18 | }); 19 | -------------------------------------------------------------------------------- /src/profiles/profiles.service.ts: -------------------------------------------------------------------------------- 1 | import { Injectable, NotFoundException } from '@nestjs/common'; 2 | import { User } from '@prisma/client'; 3 | import { PrismaService } from 'src/prisma/prisma.service'; 4 | import { castToProfile, ProfileDto } from './dto'; 5 | 6 | @Injectable() 7 | export class ProfilesService { 8 | constructor(private prisma: PrismaService) {} 9 | 10 | async findUser(user: User, userName: string) { 11 | const userFromDb = await this.prisma.user.findUnique({ 12 | where: { 13 | username: userName, 14 | }, 15 | }); 16 | if (!userFromDb) throw new NotFoundException('user not found'); 17 | 18 | const isFollowing = userFromDb.followersIds.includes(user.id); 19 | const profile: ProfileDto = castToProfile(userFromDb, isFollowing); 20 | return profile; 21 | } 22 | 23 | async followUser(user: User, userName: string) { 24 | const userFollowed = await this.prisma.user.update({ 25 | where: { 26 | username: userName, 27 | }, 28 | data: { 29 | followers: { 30 | set: [{ username: user.username }], 31 | }, 32 | }, 33 | }); 34 | 35 | const profile: ProfileDto = castToProfile(userFollowed, true); 36 | return profile; 37 | } 38 | 39 | async unfollowUser(user: User, username: string) { 40 | const userFromDb = await this.prisma.user.update({ 41 | where: { 42 | username: username, 43 | }, 44 | data: { 45 | followers: { 46 | disconnect: [{ id: user.id }], 47 | }, 48 | }, 49 | }); 50 | 51 | const profile: ProfileDto = castToProfile(userFromDb, false); 52 | return profile; 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/tags/tags.controller.spec.ts: -------------------------------------------------------------------------------- 1 | import { Test, TestingModule } from '@nestjs/testing'; 2 | import { TagsController } from './tags.controller'; 3 | 4 | describe('TagsController', () => { 5 | let controller: TagsController; 6 | 7 | beforeEach(async () => { 8 | const module: TestingModule = await Test.createTestingModule({ 9 | controllers: [TagsController], 10 | }).compile(); 11 | 12 | controller = module.get(TagsController); 13 | }); 14 | 15 | it('should be defined', () => { 16 | expect(controller).toBeDefined(); 17 | }); 18 | }); 19 | -------------------------------------------------------------------------------- /src/tags/tags.controller.ts: -------------------------------------------------------------------------------- 1 | import { Controller, Get } from '@nestjs/common'; 2 | import { TagsService } from './tags.service'; 3 | 4 | @Controller('tags') 5 | export class TagsController { 6 | constructor(private tagsService: TagsService) {} 7 | @Get() 8 | async getTags() { 9 | return { tags: await this.tagsService.getTags() }; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/tags/tags.module.ts: -------------------------------------------------------------------------------- 1 | import { Module } from '@nestjs/common'; 2 | import { TagsController } from './tags.controller'; 3 | import { TagsService } from './tags.service'; 4 | 5 | @Module({ 6 | providers: [TagsService], 7 | controllers: [TagsController], 8 | }) 9 | export class TagsModule {} 10 | -------------------------------------------------------------------------------- /src/tags/tags.service.spec.ts: -------------------------------------------------------------------------------- 1 | import { Test, TestingModule } from '@nestjs/testing'; 2 | import { TagsService } from './tags.service'; 3 | 4 | describe('TagsService', () => { 5 | let service: TagsService; 6 | 7 | beforeEach(async () => { 8 | const module: TestingModule = await Test.createTestingModule({ 9 | providers: [TagsService], 10 | }).compile(); 11 | 12 | service = module.get(TagsService); 13 | }); 14 | 15 | it('should be defined', () => { 16 | expect(service).toBeDefined(); 17 | }); 18 | }); 19 | -------------------------------------------------------------------------------- /src/tags/tags.service.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from '@nestjs/common'; 2 | import { PrismaService } from 'src/prisma/prisma.service'; 3 | 4 | @Injectable() 5 | export class TagsService { 6 | constructor(private prisma: PrismaService) {} 7 | 8 | async getTags() { 9 | const tags = await this.prisma.article.findMany({ 10 | select: { 11 | tagList: true, 12 | }, 13 | }); 14 | const flatTags = tags 15 | .map((tagList) => tagList.tagList) 16 | .reduce((a, b) => a.concat(b)); 17 | const returnTags: string[] = []; 18 | flatTags.forEach((tag) => { 19 | if (!(returnTags?.includes(tag) || false)) returnTags.push(tag); 20 | }); 21 | return returnTags; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/user/dto/index.ts: -------------------------------------------------------------------------------- 1 | export * from './user.dto'; 2 | export * from './profile.dto'; 3 | -------------------------------------------------------------------------------- /src/user/dto/profile.dto.ts: -------------------------------------------------------------------------------- 1 | export interface Profile { 2 | username: string; 3 | bio: string; 4 | image: string; 5 | following: boolean; 6 | } 7 | -------------------------------------------------------------------------------- /src/user/dto/user.dto.ts: -------------------------------------------------------------------------------- 1 | export interface LoginDto { 2 | email: string; 3 | password: string; 4 | } 5 | 6 | export interface UserDto { 7 | email: string; 8 | token: string; 9 | username: string; 10 | bio: string; 11 | image?: string; 12 | } 13 | 14 | export interface UserForRegistration { 15 | username: string; 16 | email: string; 17 | passeword: string; 18 | } 19 | 20 | export interface UserForUpdate { 21 | email?: string; 22 | username?: string; 23 | bio?: string; 24 | image?: string; 25 | } 26 | -------------------------------------------------------------------------------- /src/user/user.controller.spec.ts: -------------------------------------------------------------------------------- 1 | import { Test, TestingModule } from '@nestjs/testing'; 2 | import { UserController } from './user.controller'; 3 | 4 | describe('UserController', () => { 5 | let controller: UserController; 6 | 7 | beforeEach(async () => { 8 | const module: TestingModule = await Test.createTestingModule({ 9 | controllers: [UserController], 10 | }).compile(); 11 | 12 | controller = module.get(UserController); 13 | }); 14 | 15 | it('should be defined', () => { 16 | expect(controller).toBeDefined(); 17 | }); 18 | }); 19 | -------------------------------------------------------------------------------- /src/user/user.controller.ts: -------------------------------------------------------------------------------- 1 | import { Body, Controller, Get, Put, UseGuards } from '@nestjs/common'; 2 | import { User } from '@prisma/client'; 3 | import { GetUser } from 'src/common/decorator/get-user.decorator'; 4 | import { JwtGuard } from 'src/common/guard'; 5 | import { UserForUpdate } from './dto'; 6 | import { UserService } from './user.service'; 7 | 8 | @UseGuards(JwtGuard) 9 | @Controller('user') 10 | export class UserController { 11 | constructor(private userService: UserService) {} 12 | @Get() 13 | getCurrentUser(@GetUser() user: User) { 14 | return { user: user }; 15 | } 16 | 17 | @Put() 18 | async updateUser(@GetUser() user: User, @Body('user') dto: UserForUpdate) { 19 | return { user: await this.userService.updateUser(user, dto) }; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/user/user.module.ts: -------------------------------------------------------------------------------- 1 | import { Module } from '@nestjs/common'; 2 | import { UserController } from './user.controller'; 3 | import { UserService } from './user.service'; 4 | 5 | @Module({ 6 | controllers: [UserController], 7 | providers: [UserService], 8 | }) 9 | export class UserModule {} 10 | -------------------------------------------------------------------------------- /src/user/user.service.spec.ts: -------------------------------------------------------------------------------- 1 | import { Test, TestingModule } from '@nestjs/testing'; 2 | import { UserService } from './user.service'; 3 | 4 | describe('UserService', () => { 5 | let service: UserService; 6 | 7 | beforeEach(async () => { 8 | const module: TestingModule = await Test.createTestingModule({ 9 | providers: [UserService], 10 | }).compile(); 11 | 12 | service = module.get(UserService); 13 | }); 14 | 15 | it('should be defined', () => { 16 | expect(service).toBeDefined(); 17 | }); 18 | }); 19 | -------------------------------------------------------------------------------- /src/user/user.service.ts: -------------------------------------------------------------------------------- 1 | import { BadRequestException, Injectable } from '@nestjs/common'; 2 | import { User } from '@prisma/client'; 3 | import { PrismaClientKnownRequestError } from '@prisma/client/runtime'; 4 | import { PrismaService } from 'src/prisma/prisma.service'; 5 | import { UserForUpdate } from './dto'; 6 | 7 | @Injectable() 8 | export class UserService { 9 | constructor(private prisma: PrismaService) {} 10 | 11 | async updateUser(user: User, dto: UserForUpdate) { 12 | try { 13 | const userUpdated = await this.prisma.user.update({ 14 | where: { 15 | email: user.email, 16 | }, 17 | data: { 18 | ...dto, 19 | }, 20 | }); 21 | return userUpdated; 22 | } catch (error) { 23 | if (error instanceof PrismaClientKnownRequestError) { 24 | if (error.code === 'P2002') 25 | throw new BadRequestException('email or username taken'); 26 | } 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /tsconfig.build.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "exclude": ["node_modules", "test", "dist", "**/*spec.ts"] 4 | } 5 | -------------------------------------------------------------------------------- /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 | "strictNullChecks": false, 16 | "noImplicitAny": false, 17 | "strictBindCallApply": false, 18 | "forceConsistentCasingInFileNames": false, 19 | "noFallthroughCasesInSwitch": false 20 | } 21 | } 22 | --------------------------------------------------------------------------------