Added ESLint and Prettier, added module resolvers, tests not working by now.

This commit is contained in:
Hackntosh 2023-07-31 20:18:07 -03:00
parent fc7ede917c
commit e11771a62b
77 changed files with 1534 additions and 1584 deletions

2
.eslintignore Normal file
View file

@ -0,0 +1,2 @@
node_modules
dist

18
.eslintrc.json Normal file
View file

@ -0,0 +1,18 @@
{
"env": {
"es2021": true,
"node": true
},
"extends": "standard-with-typescript",
"parserOptions": {
"ecmaVersion": "latest",
"sourceType": "module",
"project": [
"./tsconfig.json"
]
},
"rules": {
"@typescript-eslint/no-misused-promises": "off",
"@typescript-eslint/explicit-function-return-type": 1
}
}

8
.prettierrc Normal file
View file

@ -0,0 +1,8 @@
{
"semi": false,
"singleQuote": true,
"arrowParens": "avoid",
"useTabs": false,
"endOfLine": "lf",
"tabWidth": 2
}

31
.swcrc
View file

@ -1,20 +1,17 @@
{
"jsc": {
"parser": {
"syntax": "typescript",
"tsx": false,
"decorators": true,
"dynamicImport": true
},
"target": "es2020",
"baseUrl": "./"
"jsc": {
"parser": {
"syntax": "typescript",
"tsx": false,
"decorators": true,
"dynamicImport": true
},
"exclude": [
"@types/",
"interfaces/"
],
"module": {
"type": "commonjs"
},
"minify": true
"target": "es2020",
"baseUrl": "./"
},
"exclude": ["@types/", "interfaces/"],
"module": {
"type": "commonjs"
},
"minify": true
}

3
.vscode/settings.json vendored Normal file
View file

@ -0,0 +1,3 @@
{
"json.schemaDownload.enable": true
}

View file

@ -1,4 +1,3 @@
# Project Knedita
An open-source social media.
@ -21,7 +20,6 @@ An open-source social media.
- Image compression ✅
- Following/unfollowing features ✅
- Like posts ✅
- Probably pinned posts
- Authentication ✅
- Add more verification (like, if the password is too short) ✅
- Set display name ✅

View file

@ -45,7 +45,7 @@ services:
- .env
volumes:
- localstack:/data
- "/var/run/docker.sock:/var/run/docker.sock"
- '/var/run/docker.sock:/var/run/docker.sock'
redis:
image: redis:alpine

2109
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -4,11 +4,12 @@
"description": "A social media",
"scripts": {
"build": "swc src -d dist",
"dev:start": "ts-node-dev --transpile-only --respawn src/server.ts",
"dev:start": "ts-node-dev -r tsconfig-paths/register --transpile-only --respawn src/server.ts",
"docker": "docker compose up -d",
"docker:build": "docker build -t api . && docker compose up -d",
"docker:db": "docker compose -f docker-compose.db.yml up -d",
"docker:seed": "docker exec -it api npm run prisma:seed",
"lint": "eslint --ignore-path .eslintignore --ext .js,.ts .",
"migrate:dev": "prisma migrate dev",
"migrate:dev:create": "prisma migrate dev --create-only",
"migrate:reset": "prisma migrate reset",
@ -43,16 +44,24 @@
"@types/node": "^20.3.1",
"@types/supertest": "^2.0.12",
"@types/validator": "^13.7.17",
"@typescript-eslint/eslint-plugin": "^5.60.0",
"@typescript-eslint/eslint-plugin": "^5.62.0",
"@typescript-eslint/parser": "^5.62.0",
"eslint": "^8.46.0",
"eslint-config-prettier": "^8.9.0",
"eslint-config-standard-with-typescript": "^37.0.0",
"eslint-plugin-import": "^2.28.0",
"eslint-plugin-n": "^16.0.1",
"eslint-plugin-promise": "^6.1.1",
"jest": "^29.5.0",
"nodemon": "^3.0.1",
"pm2": "^4.2.3",
"prettier": "^3.0.0",
"prisma": "^5.0.0",
"supertest": "^6.3.3",
"ts-jest": "^29.1.0",
"ts-node-dev": "^2.0.0",
"ts-standard": "^12.0.2",
"typescript": "^5.1.3"
"tsconfig-paths": "^4.2.0",
"typescript": "^5.1.6"
},
"dependencies": {
"@prisma/client": "^5.0.0",

View file

@ -45,6 +45,8 @@ model PostLike {
createdAt DateTime @default(now())
}
// I should join these two up? Yeah, but I will not do it since it didn't work on the first time.
model CommentLike {
id String @id @default(uuid())
commentId String

View file

@ -4,6 +4,8 @@ const redisPassword = process.env.REDIS_PASSWORD ?? ''
const redisHost = process.env.REDIS_HOST ?? ''
const redisPort = process.env.REDIS_PORT ?? ''
const redis = new RedisClient(`redis://:${redisPassword}@${redisHost}:${redisPort}/0`)
const redis = new RedisClient(
`redis://:${redisPassword}@${redisHost}:${redisPort}/0`
)
export default redis

View file

@ -1,7 +1,7 @@
import multer from 'multer'
import { Request } from 'express'
import { type Request } from 'express'
import path from 'path'
import s3 from '../clients/s3-client'
import s3 from 'clients/s3-client'
import multerS3 from 'multer-s3'
const tempFolder = path.resolve(__dirname, '..', '..', 'temp', 'uploads')
@ -18,7 +18,7 @@ const storageTypes = {
const fileName: string = `${folder}/${req.user!.id}.webp`
callback(null, fileName)
}
},
}),
s3: multerS3({
@ -37,21 +37,22 @@ const storageTypes = {
const fileName: string = `${folder}/${req.user!.id}.jpg`
callback(null, fileName)
}
})
},
}),
}
const multerConfig = {
dest: tempFolder,
storage: storageTypes.s3,
limits: {
fileSize: 15 * 1024 * 1024 // 1mb
fileSize: 15 * 1024 * 1024, // 1mb
},
fileFilter: (req: Request, file: Express.Multer.File, callback: multer.FileFilterCallback) => {
const allowedMimes = [
'image/jpeg',
'image/png'
]
fileFilter: (
req: Request,
file: Express.Multer.File,
callback: multer.FileFilterCallback,
) => {
const allowedMimes = ['image/jpeg', 'image/png']
if (allowedMimes.includes(file.mimetype)) {
callback(null, true)

View file

@ -1,11 +1,10 @@
/* eslint-disable @typescript-eslint/no-misused-promises */
import { Router } from 'express'
// Controllers
import comments from './comments'
// Middlewares
import authenticated from '../middlewares/authenticated'
import authenticated from 'middlewares/authenticated'
const commentsRouter = Router()

View file

@ -1,23 +1,26 @@
import comment from '../../services/comments'
import comment from 'services/comments'
import type { Request, Response } from 'express'
import { badRequest } from '../../lib/http-errors'
import { badRequest } from 'lib/http-errors'
async function commentCreateController (req: Request, res: Response): Promise<void> {
async function commentCreateController (
req: Request,
res: Response
): Promise<void> {
const { content, postId } = req.body
const id = req.user?.id ?? ''
if (postId === undefined) {
return badRequest(res, 'Expected post id')
badRequest(res, 'Expected post id'); return
}
if (content === undefined) {
return badRequest(res, 'Expected comment content')
badRequest(res, 'Expected comment content'); return
}
const result = await comment.create(postId, content, id)
if (result instanceof Error) {
return badRequest(res, result.message)
badRequest(res, result.message); return
}
res.json(result)

View file

@ -1,19 +1,22 @@
import comment from '../../services/comments'
import comment from 'services/comments'
import type { Request, Response } from 'express'
import { badRequest } from '../../lib/http-errors'
import { badRequest } from 'lib/http-errors'
async function commentDeleteController (req: Request, res: Response): Promise<void> {
async function commentDeleteController (
req: Request,
res: Response
): Promise<void> {
const { commentId } = req.body
const id = req.user?.id ?? ''
if (commentId === undefined) {
return badRequest(res, 'Expected comment id')
badRequest(res, 'Expected comment id'); return
}
const result = await comment.delete(commentId, id)
if (result instanceof Error) {
return badRequest(res, result.message)
badRequest(res, result.message); return
}
res.json(result)

View file

@ -1,18 +1,21 @@
import comment from '../../services/comments'
import comment from 'services/comments'
import type { Request, Response } from 'express'
import { badRequest } from '../../lib/http-errors'
import { badRequest } from 'lib/http-errors'
async function commentFetchController (req: Request, res: Response): Promise<void> {
async function commentFetchController (
req: Request,
res: Response
): Promise<void> {
const commentId = req.query.id as string
if (commentId === undefined) {
return badRequest(res, 'Expected comment id')
badRequest(res, 'Expected comment id'); return
}
const result = await comment.fetch(commentId)
if (result instanceof Error) {
return badRequest(res, result.message)
badRequest(res, result.message); return
}
res.json(result)

View file

@ -1,18 +1,21 @@
import comment from '../../services/comments'
import comment from 'services/comments'
import type { Request, Response } from 'express'
import { badRequest } from '../../lib/http-errors'
import { badRequest } from 'lib/http-errors'
async function commentFetchLikesController (req: Request, res: Response): Promise<void> {
async function commentFetchLikesController (
req: Request,
res: Response
): Promise<void> {
const commentId = req.query.id as string
if (commentId === undefined) {
return badRequest(res, 'Expected comment id')
badRequest(res, 'Expected comment id'); return
}
const result = await comment.fetchLikes(commentId)
if (result instanceof Error) {
return badRequest(res, result.message)
badRequest(res, result.message); return
}
res.json(result)

View file

@ -1,23 +1,26 @@
import comment from '../../services/comments'
import comment from 'services/comments'
import type { Request, Response } from 'express'
import { badRequest } from '../../lib/http-errors'
import { badRequest } from 'lib/http-errors'
async function commentUpdateController (req: Request, res: Response): Promise<void> {
async function commentUpdateController (
req: Request,
res: Response
): Promise<void> {
const { commentId, content } = req.body
const id = req.user?.id ?? ''
if (commentId === undefined) {
return badRequest(res, 'Expected comment content')
badRequest(res, 'Expected comment content'); return
}
if (content === undefined) {
return badRequest(res, 'Expected content to update')
badRequest(res, 'Expected content to update'); return
}
const result = await comment.update(content, id, commentId)
if (result instanceof Error) {
return badRequest(res, result.message)
badRequest(res, result.message); return
}
res.json(result)

View file

@ -1,11 +1,10 @@
/* eslint-disable @typescript-eslint/no-misused-promises */
import { Router } from 'express'
// Controllers
import post from './posts'
// Middlewares
import authenticated from '../middlewares/authenticated'
import authenticated from 'middlewares/authenticated'
const postsRouter = Router()

View file

@ -1,19 +1,22 @@
import post from '../../services/posts'
import post from 'services/posts'
import type { Request, Response } from 'express'
import { badRequest } from '../../lib/http-errors'
import { badRequest } from 'lib/http-errors'
async function postCreateController (req: Request, res: Response): Promise<void> {
async function postCreateController (
req: Request,
res: Response
): Promise<void> {
const { content } = req.body
const id: string = req.user?.id ?? ''
if (content === undefined) {
return badRequest(res, 'Expected post content')
badRequest(res, 'Expected post content'); return
}
const result = await post.create(content, id)
if (result instanceof Error) {
return badRequest(res, result.message)
badRequest(res, result.message); return
}
res.json(result)

View file

@ -1,15 +1,18 @@
import post from '../../services/posts'
import post from 'services/posts'
import type { Request, Response } from 'express'
import { badRequest } from '../../lib/http-errors'
import { badRequest } from 'lib/http-errors'
async function postDeleteController (req: Request, res: Response): Promise<void> {
async function postDeleteController (
req: Request,
res: Response
): Promise<void> {
const userId = req.user?.id ?? ''
const postId = req.body.postId
const result = await post.delete(postId, userId)
if (result instanceof Error) {
return badRequest(res, result.message)
badRequest(res, result.message); return
}
res.json(result)

View file

@ -1,18 +1,21 @@
import post from '../../services/posts'
import post from 'services/posts'
import type { Request, Response } from 'express'
import { badRequest } from '../../lib/http-errors'
import { badRequest } from 'lib/http-errors'
async function postFetchInfoController (req: Request, res: Response): Promise<void> {
async function postFetchInfoController (
req: Request,
res: Response
): Promise<void> {
const id = req.query.id as string
if (id === undefined) {
return badRequest(res, 'Missing post id')
badRequest(res, 'Missing post id'); return
}
const result = await post.fetch(id)
if (result instanceof Error) {
return badRequest(res, result.message)
badRequest(res, result.message); return
}
res.json(result)

View file

@ -1,18 +1,21 @@
import post from '../../services/posts'
import post from 'services/posts'
import type { Request, Response } from 'express'
import { badRequest } from '../../lib/http-errors'
import { badRequest } from 'lib/http-errors'
async function postFetchLikesController (req: Request, res: Response): Promise<void> {
async function postFetchLikesController (
req: Request,
res: Response
): Promise<void> {
const id = req.query.id as string
if (id === undefined) {
return badRequest(res, 'Missing post id')
badRequest(res, 'Missing post id'); return
}
const result = await post.fetchLikes(id)
if (result instanceof Error) {
return badRequest(res, result.message)
badRequest(res, result.message); return
}
res.json(result)

View file

@ -1,15 +1,18 @@
import post from '../../services/posts'
import post from 'services/posts'
import type { Request, Response } from 'express'
import { badRequest } from '../../lib/http-errors'
import { badRequest } from 'lib/http-errors'
async function postUpdateController (req: Request, res: Response): Promise<void> {
async function postUpdateController (
req: Request,
res: Response
): Promise<void> {
const { postId, content } = req.body
const userId = req.user?.id ?? ''
const result = await post.update(postId, content, userId)
if (result instanceof Error) {
return badRequest(res, result.message)
badRequest(res, result.message); return
}
res.json(result)

View file

@ -1,12 +1,11 @@
/* eslint-disable @typescript-eslint/no-misused-promises */
import { Router } from 'express'
// Controllers
import user from './users'
// Middlewares
import authenticated from '../middlewares/authenticated'
import uploadFile from '../middlewares/upload-image'
import authenticated from 'middlewares/authenticated'
import uploadFile from 'middlewares/upload-image'
const usersRouter = Router()
@ -24,7 +23,12 @@ usersRouter.post('/like-post', authenticated, user.likePost)
usersRouter.post('/signup', user.signup)
// PUT
usersRouter.put('/profile-picture/upload', authenticated, uploadFile, user.uploadPicture)
usersRouter.put(
'/profile-picture/upload',
authenticated,
uploadFile,
user.uploadPicture
)
usersRouter.put('/update', authenticated, user.update)
export default usersRouter

View file

@ -1,14 +1,14 @@
import user from '../../services/users'
import user from 'services/users'
import type { Request, Response } from 'express'
import { badRequest } from '../../lib/http-errors'
import { badRequest } from 'lib/http-errors'
async function userAuthController (req: Request, res: Response): Promise<void> {
const { email, password } = req.body
const result = await user.auth(email, password)
const result = await user.auth({ email, password })
if (result instanceof Error) {
return badRequest(res, result.message)
badRequest(res, result.message); return
}
res.json(result)

View file

@ -1,13 +1,16 @@
import user from '../../services/users'
import user from 'services/users'
import type { Request, Response } from 'express'
import { badRequest } from '../../lib/http-errors'
import { badRequest } from 'lib/http-errors'
async function userDeleteController (req: Request, res: Response): Promise<void> {
async function userDeleteController (
req: Request,
res: Response
): Promise<void> {
const userId = req.user?.id ?? ''
const result = await user.delete(userId)
if (result instanceof Error) {
return badRequest(res, result.message)
badRequest(res, result.message); return
}
res.json(result)

View file

@ -1,18 +1,21 @@
import user from '../../services/users'
import user from 'services/users'
import type { Request, Response } from 'express'
import { badRequest } from '../../lib/http-errors'
import { badRequest } from 'lib/http-errors'
async function userFetchInfoController (req: Request, res: Response): Promise<void> {
async function userFetchInfoController (
req: Request,
res: Response
): Promise<void> {
const username = req.query.u as string
if (username === undefined) {
return badRequest(res, 'Missing username')
badRequest(res, 'Missing username'); return
}
const result = await user.fetchInfo(username.toLowerCase())
if (result instanceof Error) {
return badRequest(res, result.message)
badRequest(res, result.message); return
}
res.json(result)

View file

@ -1,12 +1,15 @@
import user from '../../services/users'
import user from 'services/users'
import type { Request, Response } from 'express'
import { badRequest } from '../../lib/http-errors'
import { badRequest } from 'lib/http-errors'
async function userFetchPostsController (req: Request, res: Response): Promise<void> {
async function userFetchPostsController (
req: Request,
res: Response
): Promise<void> {
const username = req.query.u as string
if (username === undefined) {
return badRequest(res, 'Missing username')
badRequest(res, 'Missing username'); return
}
const result = await user.fetchPosts(username)

View file

@ -1,15 +1,18 @@
import user from '../../services/users'
import user from 'services/users'
import type { Request, Response } from 'express'
import { badRequest } from '../../lib/http-errors'
import { badRequest } from 'lib/http-errors'
async function userFollowController (req: Request, res: Response): Promise<void> {
async function userFollowController (
req: Request,
res: Response
): Promise<void> {
const userId = req.user?.id ?? ''
const { userToFollow } = req.body
const result = await user.follow(userId, userToFollow)
if (result instanceof Error) {
return badRequest(res, result.message)
badRequest(res, result.message); return
}
res.json(result)

View file

@ -1,15 +1,18 @@
import user from '../../services/users'
import user from 'services/users'
import type { Request, Response } from 'express'
import { badRequest } from '../../lib/http-errors'
import { badRequest } from 'lib/http-errors'
async function userLikeCommentController (req: Request, res: Response): Promise<void> {
async function userLikeCommentController (
req: Request,
res: Response
): Promise<void> {
const userId = req.user?.id ?? ''
const { commentId, postId } = req.body
const { commentId } = req.body
const result = await user.likeComment(postId, commentId, userId)
const result = await user.likeComment(commentId, userId)
if (result instanceof Error) {
return badRequest(res, result.message)
badRequest(res, result.message); return
}
res.json(result)

View file

@ -1,15 +1,18 @@
import user from '../../services/users'
import user from 'services/users'
import type { Request, Response } from 'express'
import { badRequest } from '../../lib/http-errors'
import { badRequest } from 'lib/http-errors'
async function userLikePostController (req: Request, res: Response): Promise<void> {
async function userLikePostController (
req: Request,
res: Response
): Promise<void> {
const userId = req.user?.id ?? ''
const { postId } = req.body
const result = await user.likePost(postId, userId)
if (result instanceof Error) {
return badRequest(res, result.message)
badRequest(res, result.message); return
}
res.json(result)

View file

@ -1,12 +1,15 @@
import user from '../../services/users'
import { Request, Response } from 'express'
import { badRequest } from '../../lib/http-errors'
import user from 'services/users'
import type { Request, Response } from 'express'
import { badRequest } from 'lib/http-errors'
async function userSearchController (req: Request, res: Response): Promise<void> {
async function userSearchController (
req: Request,
res: Response
): Promise<void> {
const username = req.query.u as string
if (username === undefined) {
return badRequest(res, 'Missing username')
badRequest(res, 'Missing username'); return
}
const result = await user.searchUser(username)

View file

@ -1,14 +1,17 @@
import user from '../../services/users'
import user from 'services/users'
import type { Request, Response } from 'express'
import { badRequest } from '../../lib/http-errors'
import { badRequest } from 'lib/http-errors'
async function userSignupController (req: Request, res: Response): Promise<void> {
async function userSignupController (
req: Request,
res: Response
): Promise<void> {
const { username, email, password } = req.body
const result = await user.signup(username, email, password)
const result = await user.signup({ username, email, password })
if (result instanceof Error) {
return badRequest(res, result.message)
badRequest(res, result.message); return
}
res.json(result)

View file

@ -1,15 +1,18 @@
import user from '../../services/users'
import user from 'services/users'
import type { Request, Response } from 'express'
import { badRequest } from '../../lib/http-errors'
import { badRequest } from 'lib/http-errors'
async function userUpdateController (req: Request, res: Response): Promise<void> {
async function userUpdateController (
req: Request,
res: Response
): Promise<void> {
const { email, displayName, username } = req.body
const id = req.user?.id ?? ''
const result = await user.update({ id, email, displayName, username })
if (result instanceof Error) {
return badRequest(res, result.message)
badRequest(res, result.message); return
}
res.json(result)

View file

@ -1,13 +1,16 @@
/* eslint-disable @typescript-eslint/restrict-template-expressions */
import user from '../../services/users'
import user from 'services/users'
import type { Request, Response } from 'express'
import { badRequest } from '../../lib/http-errors'
import { badRequest } from 'lib/http-errors'
let url
async function userUploadPictureController (req: Request, res: Response): Promise<void> {
async function userUploadPictureController (
req: Request,
res: Response
): Promise<void> {
if (req.file === undefined) {
return badRequest(res, 'Expected a JPG or PNG file')
badRequest(res, 'Expected a JPG or PNG file'); return
}
const userId = req.user?.id ?? ''
@ -23,7 +26,7 @@ async function userUploadPictureController (req: Request, res: Response): Promis
const result = await user.uploadPicture(userId, url)
if (result instanceof Error) {
return badRequest(res, result.message)
badRequest(res, result.message); return
}
res.json(result)

View file

@ -2,8 +2,8 @@ interface userPayload {
id?: string
displayName?: string | null
username?: string
password?: string
email?: string
password?: string
token?: string
}

View file

@ -1,17 +1,26 @@
import sharp from 'sharp'
import s3 from '../clients/s3-client'
import s3 from 'clients/s3-client'
import { GetObjectCommand, PutObjectCommand } from '@aws-sdk/client-s3'
export default async function compressImage (imageName: string): Promise<Error | Object > {
export default async function compressImage (
imageName: string,
isProfilePicture: string
): Promise<Error | Record<never, never>> {
// Get file from s3
const { Body } = await s3.send(new GetObjectCommand({
Bucket: process.env.AWS_BUCKET ?? '',
Key: imageName
}))
const { Body } = await s3.send(
new GetObjectCommand({
Bucket: process.env.AWS_BUCKET ?? '',
Key: imageName
})
)
const imageBuffer = await Body?.transformToByteArray()
const compressedImageBuffer = await sharp(imageBuffer)
.resize(
isProfilePicture === 'true' ? 200 : undefined,
isProfilePicture === 'true' ? 200 : undefined
)
.jpeg({ quality: 65 })
.toBuffer()

View file

@ -0,0 +1,29 @@
import { type NotificationType } from '@prisma/client'
import prisma from 'clients/prisma-client'
export default async function createNotification (
fromUserId: string,
toUserId: string,
content: string,
type: NotificationType
): Promise<Record<never, never> | Error> {
await prisma.notifications.create({
data: {
type,
fromUserId,
toUserId,
content
},
include: {
fromUser: {
select: {
id: true,
displayName: true,
username: true,
profileImage: true
}
}
}
})
return {}
}

View file

@ -1,6 +1,10 @@
import { Response } from 'express'
import { type Response } from 'express'
const sendErrorResponse = (res: Response, status: number, message: string): void => {
const sendErrorResponse = (
res: Response,
status: number,
message: string
): void => {
res.status(status).json({ error: message })
}
@ -16,6 +20,9 @@ export const forbidden = (res: Response, message = 'Forbidden'): void => {
sendErrorResponse(res, 403, message)
}
export const internalServerError = (res: Response, message = 'Internal Server Error'): void => {
export const internalServerError = (
res: Response,
message = 'Internal Server Error'
): void => {
sendErrorResponse(res, 500, message)
}

View file

@ -1,29 +1,38 @@
import { verify } from 'jsonwebtoken'
import prisma from '../clients/prisma-client'
import prisma from 'clients/prisma-client'
import type { Response, Request, NextFunction } from 'express'
import jwtPayload from '../interfaces/jwt'
import { unauthorized } from '../lib/http-errors'
import type jwtPayload from 'interfaces/jwt'
import { unauthorized } from 'lib/http-errors'
async function authenticated (req: Request, res: Response, next: NextFunction): Promise<void> {
if (req.headers.authorization === undefined || req.headers.authorization.length === 0) {
return unauthorized(res, 'Missing token')
async function authenticated (
req: Request,
res: Response,
next: NextFunction
): Promise<void> {
if (
req.headers.authorization === undefined ||
req.headers.authorization.length === 0
) {
unauthorized(res, 'Missing token'); return
}
const token = req.headers.authorization.split(' ')[1]
try {
const decoded = await new Promise<jwtPayload | undefined>((resolve, reject) => {
verify(token, process.env.JWT_ACCESS_SECRET ?? '', (error, decoded) => {
if (error != null) {
reject(error)
} else {
resolve(decoded as jwtPayload)
}
})
})
const decoded = await new Promise<jwtPayload | undefined>(
(resolve, reject) => {
verify(token, process.env.JWT_ACCESS_SECRET ?? '', (error, decoded) => {
if (error != null) {
reject(error)
} else {
resolve(decoded as jwtPayload)
}
})
}
)
if (decoded == null) {
return unauthorized(res, 'Invalid token')
unauthorized(res, 'Invalid token'); return
}
const user = await prisma.user.findFirst({
@ -33,12 +42,12 @@ async function authenticated (req: Request, res: Response, next: NextFunction):
})
if (user == null) {
return unauthorized(res, 'User does not exists')
unauthorized(res, 'User does not exists'); return
}
req.user = decoded
return next()
next()
} catch (error) {
unauthorized(res, `JWT Error: ${(error as Error).message}`)
}

View file

@ -1,6 +1,6 @@
import rateLimit from 'express-rate-limit'
import RedisStore from 'rate-limit-redis'
import redis from '../clients/redis-client'
import redis from 'clients/redis-client'
let maxConnections

View file

@ -1,29 +1,30 @@
/* eslint-disable @typescript-eslint/no-misused-promises */
/* eslint-disable @typescript-eslint/explicit-function-return-type */
import type { Response, Request, NextFunction } from 'express'
import multer from 'multer'
import multerConfig from '../config/multer'
import compressImage from '../lib/compress-image'
import { badRequest } from '../lib/http-errors'
import multerConfig from 'config/multer'
import compressImage from 'lib/compress-image'
import { badRequest } from 'lib/http-errors'
function uploadImage (req: Request, res: Response, next: NextFunction) {
const upload = multer(multerConfig).single('image')
upload(req, res, async (cb: multer.MulterError | Error | any) => {
if (req.user == null) {
return badRequest(res, 'You must be logged in to upload a profile picture')
badRequest(
res,
'You must be logged in to upload a profile picture'
); return
}
if (cb instanceof multer.MulterError || cb instanceof Error) {
return badRequest(res, cb.message)
badRequest(res, cb.message); return
}
if (req.file === undefined) {
return badRequest(res, 'Expected file')
badRequest(res, 'Expected file'); return
}
// @ts-expect-error property `key` does not exists in types
await compressImage(req.file?.key)
await compressImage(req.file?.key, req.body.isProfilePicture)
next()
})

View file

@ -1,6 +1,10 @@
import prisma from '../../clients/prisma-client'
import prisma from 'clients/prisma-client'
async function commentCreateService (postId: string, content: string, authorId: string): Promise<Object | Error> {
async function commentCreateService (
postId: string,
content: string,
authorId: string
): Promise<Record<string, unknown> | Error> {
const post = await prisma.post.findFirst({
where: {
id: postId

View file

@ -1,6 +1,9 @@
import prisma from '../../clients/prisma-client'
import prisma from 'clients/prisma-client'
async function commentDeleteService (commentId: string, authorId: string): Promise<Object | Error> {
async function commentDeleteService (
commentId: string,
authorId: string
): Promise<Record<string, unknown> | Error> {
const user = await prisma.user.findFirst({
where: {
id: authorId

View file

@ -1,6 +1,6 @@
import prisma from '../../clients/prisma-client'
import prisma from 'clients/prisma-client'
async function commentFetchService (commentId: string): Promise<Object | Error> {
async function commentFetchService (commentId: string): Promise<Record<string, unknown> | Error> {
const comment = await prisma.comments.findFirst({
where: {
id: commentId

View file

@ -1,6 +1,6 @@
import prisma from '../../clients/prisma-client'
import prisma from 'clients/prisma-client'
async function commentFetchLikesService (id: string): Promise<Object | Error> {
async function commentFetchLikesService (id: string): Promise<unknown | Error> {
const post = await prisma.commentLike.findMany({
where: {
commentId: id

View file

@ -1,6 +1,10 @@
import prisma from '../../clients/prisma-client'
import prisma from 'clients/prisma-client'
async function commentUpdateService (content: string, authorId: string, commentId: string): Promise<Object | Error> {
async function commentUpdateService (
content: string,
authorId: string,
commentId: string
): Promise<Record<string, unknown> | Error> {
const comment = await prisma.comments.findFirst({
where: {
id: commentId,

View file

@ -1,10 +1,13 @@
import prisma from '../../clients/prisma-client'
import prisma from 'clients/prisma-client'
async function postCreateService (content: string, authorId: string): Promise<Object | Error> {
async function postCreateService (
content: string,
authorId: string
): Promise<Record<string, unknown> | Error> {
const user = await prisma.user.findFirst({ where: { id: authorId } })
if (user === null) {
return new Error('This user doesn\'t exists')
return new Error("This user doesn't exists")
}
const post = await prisma.post.create({

View file

@ -1,13 +1,16 @@
import prisma from '../../clients/prisma-client'
import prisma from 'clients/prisma-client'
async function postDeleteService (postId: string, userId: string): Promise<Object | Error> {
async function postDeleteService (
postId: string,
userId: string
): Promise<Record<string, unknown> | Error> {
const post = await prisma.post.findFirst({ where: { id: postId } })
if (post === null) {
return new Error('Post not found')
}
if (await prisma.user.findFirst({ where: { id: userId } }) === null) {
if ((await prisma.user.findFirst({ where: { id: userId } })) === null) {
return new Error('User not found')
}

View file

@ -1,6 +1,6 @@
import prisma from '../../clients/prisma-client'
import prisma from 'clients/prisma-client'
async function postFetchInfoService (id: string): Promise<Object | Error> {
async function postFetchInfoService (id: string): Promise<Record<string, unknown> | Error> {
const post = await prisma.post.findFirst({
where: {
id

View file

@ -1,6 +1,6 @@
import prisma from '../../clients/prisma-client'
import prisma from 'clients/prisma-client'
async function postFetchLikesService (id: string): Promise<Object | Error> {
async function postFetchLikesService (id: string): Promise<unknown | Error> {
const post = await prisma.postLike.findMany({
where: {
postId: id

View file

@ -1,13 +1,17 @@
import prisma from '../../clients/prisma-client'
import prisma from 'clients/prisma-client'
async function postUpdateService (postId: string, content: string, userId: string): Promise<Object | Error> {
async function postUpdateService (
postId: string,
content: string,
userId: string
): Promise<Record<string, unknown> | Error> {
const post = await prisma.post.findFirst({ where: { id: postId } })
if (post === null) {
return new Error('Post not found')
}
if (await prisma.user.findFirst({ where: { id: userId } }) === null) {
if ((await prisma.user.findFirst({ where: { id: userId } })) === null) {
return new Error('User not found')
}

View file

@ -1,8 +1,12 @@
import * as bcrypt from 'bcrypt'
import jsonwebtoken from 'jsonwebtoken'
import prisma from '../../clients/prisma-client'
import prisma from 'clients/prisma-client'
import type userPayload from 'interfaces/user'
async function userAuthService (email: string, password: string): Promise<Object | Error> {
async function userAuthService ({
email,
password
}: userPayload): Promise<Record<string, unknown> | Error> {
const user = await prisma.user.findFirst({
where: {
email
@ -17,7 +21,10 @@ async function userAuthService (email: string, password: string): Promise<Object
return new Error('Missing fields')
}
const validPassword = await bcrypt.compare(password.replace(/ /g, ''), user.password)
const validPassword = await bcrypt.compare(
password.replace(/ /g, ''),
user.password
)
if (!validPassword) {
return new Error('Invalid email or password')
@ -25,7 +32,11 @@ async function userAuthService (email: string, password: string): Promise<Object
const { id } = user
const bearer = jsonwebtoken.sign({ id }, process.env.JWT_ACCESS_SECRET ?? '', { expiresIn: '1d' })
const bearer = jsonwebtoken.sign(
{ id },
process.env.JWT_ACCESS_SECRET ?? '',
{ expiresIn: '1d' }
)
return {
token: bearer

View file

@ -1,6 +1,6 @@
import prisma from '../../clients/prisma-client'
import prisma from 'clients/prisma-client'
async function userDeleteService (userId: string): Promise<Object | Error> {
async function userDeleteService (userId: string): Promise<Record<string, unknown> | Error> {
const user = await prisma.user.findFirst({ where: { id: userId } })
if (user === null) {

View file

@ -1,6 +1,6 @@
import prisma from '../../clients/prisma-client'
import prisma from 'clients/prisma-client'
async function userFetchInfoService (username: string): Promise<Object | Error> {
async function userFetchInfoService (username: string): Promise<Record<string, unknown> | Error> {
const user = await prisma.user.findFirst({
where: {
username

View file

@ -1,6 +1,8 @@
import prisma from '../../clients/prisma-client'
import prisma from 'clients/prisma-client'
async function userFetchPostsService (username: string): Promise<Object | Error> {
async function userFetchPostsService (
username: string
): Promise<unknown | Error> {
const posts = await prisma.post.findMany({
where: {
author: {

View file

@ -1,6 +1,9 @@
import prisma from '../../clients/prisma-client'
import prisma from 'clients/prisma-client'
async function userFollowService (userId: string, followingUsername: string): Promise<Object | Error> {
async function userFollowService (
userId: string,
followingUsername: string
): Promise<Record<string, unknown> | Error> {
if (userId === undefined || followingUsername === undefined) {
return new Error('Missing fields')
}

View file

@ -1,6 +1,9 @@
import prisma from '../../clients/prisma-client'
import prisma from 'clients/prisma-client'
async function userLikeCommentService (postId: string, commentId: string, userId: string): Promise<Object | Error> {
async function userLikeCommentService (
commentId: string,
userId: string
): Promise<Record<string, unknown> | Error> {
if (commentId === undefined || userId === undefined) {
return new Error('Missing fields')
}

View file

@ -1,6 +1,9 @@
import prisma from '../../clients/prisma-client'
import prisma from 'clients/prisma-client'
async function userLikePostService (postId: string, userId: string): Promise<Object | Error> {
async function userLikePostService (
postId: string,
userId: string
): Promise<Record<string, unknown> | Error> {
if (postId === undefined || userId === undefined) {
return new Error('Missing fields')
}

View file

@ -1,6 +1,6 @@
import prisma from '../../clients/prisma-client'
import prisma from 'clients/prisma-client'
async function userSearchService (username: string): Promise<Object | Error> {
async function userSearchService (username: string): Promise<unknown | Error> {
const users = await prisma.user.findMany({
where: {
username: {

View file

@ -1,17 +1,24 @@
import * as bcrypt from 'bcrypt'
import validator from 'validator'
import prisma from '../../clients/prisma-client'
import prisma from 'clients/prisma-client'
import type userPayload from 'interfaces/user'
const passwordRegex = /^(?=.*[0-9])(?=.*[!@#$%^&*_])[a-zA-Z0-9!@#$%^&*_]{8,}$/
const usernameRegex = /^[a-zA-Z0-9_.]{5,15}$/
async function userSignupService (username: string, email: string, password: string): Promise<Object | Error> {
async function userSignupService ({
username,
email,
password
}: userPayload): Promise<Record<string, unknown> | Error> {
if (username === undefined || email === undefined || password === undefined) {
return new Error('Missing fields')
}
if (!passwordRegex.test(password)) {
return new Error('Password must have at least 8 characters, one number and one special character.')
return new Error(
'Password must have at least 8 characters, one number and one special character.'
)
}
if (password.trim().length < 8) {
@ -19,7 +26,9 @@ async function userSignupService (username: string, email: string, password: str
}
if (!usernameRegex.test(username)) {
return new Error('Username not allowed. Only alphanumerics characters (uppercase and lowercase words), underscore, dots and it must be between 5 and 15 characters')
return new Error(
'Username not allowed. Only alphanumerics characters (uppercase and lowercase words), underscore, dots and it must be between 5 and 15 characters'
)
}
if (!validator.isEmail(email)) {

View file

@ -1,7 +1,12 @@
import userPayload from '../../interfaces/user'
import prisma from '../../clients/prisma-client'
import type userPayload from 'interfaces/user'
import prisma from 'clients/prisma-client'
async function userUpdateService ({ id, email, displayName, username }: userPayload): Promise<Object | Error> {
async function userUpdateService ({
id,
email,
displayName,
username
}: userPayload): Promise<Record<string, unknown> | Error> {
const user = await prisma.user.findFirst({ where: { id } })
if (user === null) {
@ -13,14 +18,14 @@ async function userUpdateService ({ id, email, displayName, username }: userPayl
if (email !== undefined && email.trim() !== user.email) {
const existingUser = await prisma.user.findFirst({ where: { email } })
if ((existingUser != null) && existingUser.email !== user.email) {
if (existingUser != null && existingUser.email !== user.email) {
return new Error('Email already in use')
}
}
if (username !== undefined && username.trim() !== user.username) {
const existingUser = await prisma.user.findFirst({ where: { username } })
if ((existingUser != null) && existingUser.username !== user.username) {
if (existingUser != null && existingUser.username !== user.username) {
return new Error('Username already in use')
}
}

View file

@ -1,6 +1,9 @@
import prisma from '../../clients/prisma-client'
import prisma from 'clients/prisma-client'
async function userUploadPictureService (authorId: string, url: string): Promise<Object | Error> {
async function userUploadPictureService (
authorId: string,
url: string
): Promise<Record<string, unknown> | Error> {
const user = await prisma.user.findFirst({ where: { id: authorId } })
if (user == null) {

View file

@ -2,7 +2,7 @@ import app from '../../app'
import request from 'supertest'
import signUpNewUser from '../utils/create-user'
import deleteUser from '../utils/delete-user'
import userPayload from '../../interfaces/user'
import type userPayload from '../../interfaces/user'
let user: userPayload
@ -16,17 +16,23 @@ describe('POST /post/create', () => {
})
it('should respond with 200 status code if the user send the token and the content', async () => {
const response = await request(app).post('/post/create').send({
content: 'Hello world'
}).set('Authorization', `Bearer ${user.token ?? ''}`).expect(200)
const response = await request(app)
.post('/post/create')
.send({
content: 'Hello world'
})
.set('Authorization', `Bearer ${user.token ?? ''}`)
.expect(200)
expect(response.body).toEqual(expect.objectContaining({
id: expect.any(String),
content: expect.any(String),
authorId: expect.any(String),
createdAt: expect.any(String),
updatedAt: expect.any(String)
}))
expect(response.body).toEqual(
expect.objectContaining({
id: expect.any(String),
content: expect.any(String),
authorId: expect.any(String),
createdAt: expect.any(String),
updatedAt: expect.any(String)
})
)
})
it('should respond with 400 status code if the user send no token', async () => {

View file

@ -2,7 +2,7 @@ import app from '../../app'
import request from 'supertest'
import signUpNewUser from '../utils/create-user'
import deleteUser from '../utils/delete-user'
import userPayload from '../../interfaces/user'
import type userPayload from '../../interfaces/user'
let user: userPayload
@ -21,13 +21,15 @@ describe('DELETE /post/delete', () => {
.send({
content: 'lorem ipsum'
})
.set('Authorization', `Bearer ${user.token ?? ''}`).expect(200)
.set('Authorization', `Bearer ${user.token ?? ''}`)
.expect(200)
await request(app)
.post('/post/delete')
.send({
postId: response.body.id
})
.set('Authorization', `Bearer ${user.token ?? ''}`).expect(200)
.set('Authorization', `Bearer ${user.token ?? ''}`)
.expect(200)
})
})

View file

@ -2,7 +2,7 @@ import app from '../../app'
import request from 'supertest'
import signUpNewUser from '../utils/create-user'
import deleteUser from '../utils/delete-user'
import userPayload from '../../interfaces/user'
import type userPayload from '../../interfaces/user'
let postId: string
@ -14,9 +14,13 @@ describe('POST /post/info', () => {
const token = user.token ?? ''
const post = await request(app).post('/post/create').send({
content: 'Hello world'
}).set('Authorization', `Bearer ${token}`).expect(200)
const post = await request(app)
.post('/post/create')
.send({
content: 'Hello world'
})
.set('Authorization', `Bearer ${token}`)
.expect(200)
postId = post.body.id
})
@ -26,15 +30,19 @@ describe('POST /post/info', () => {
})
it('should respond with 200 status code and return some info about the post', async () => {
const response = await request(app).get(`/post/info?id=${postId}`).expect(200)
const response = await request(app)
.get(`/post/info?id=${postId}`)
.expect(200)
expect(response.body).toEqual(expect.objectContaining({
id: expect.any(String),
content: expect.any(String),
createdAt: expect.any(String),
updatedAt: expect.any(String),
author: expect.any(Object)
}))
expect(response.body).toEqual(
expect.objectContaining({
id: expect.any(String),
content: expect.any(String),
createdAt: expect.any(String),
updatedAt: expect.any(String),
author: expect.any(Object)
})
)
})
it('should respond with 400 status code if the post does not exists', async () => {

View file

@ -2,7 +2,7 @@ import app from '../../app'
import request from 'supertest'
import signUpNewUser from '../utils/create-user'
import deleteUser from '../utils/delete-user'
import userPayload from '../../interfaces/user'
import type userPayload from '../../interfaces/user'
let user: userPayload
@ -16,9 +16,13 @@ describe('PUT /post/update', () => {
})
it('should create a new post and update the content of it', async () => {
const post = await request(app).post('/post/create').send({
content: 'Lorem'
}).set('Authorization', `Bearer ${user.token ?? ''}`).expect(200)
const post = await request(app)
.post('/post/create')
.send({
content: 'Lorem'
})
.set('Authorization', `Bearer ${user.token ?? ''}`)
.expect(200)
expect(post.body).toHaveProperty('id')
@ -30,19 +34,22 @@ describe('PUT /post/update', () => {
const response = await request(app)
.put('/post/update')
.send(fieldsToUpdate)
.set('Authorization', `Bearer ${user.token ?? ''}`).expect(200)
.set('Authorization', `Bearer ${user.token ?? ''}`)
.expect(200)
// Post content should be Lorem Ipsum
if (post.body.content === response.body.content) {
throw new Error('Post didn\'t update')
throw new Error("Post didn't update")
}
expect(response.body).toEqual(expect.objectContaining({
id: expect.any(String),
content: expect.any(String),
createdAt: expect.any(String),
updatedAt: expect.any(String),
author: expect.any(Object)
}))
expect(response.body).toEqual(
expect.objectContaining({
id: expect.any(String),
content: expect.any(String),
createdAt: expect.any(String),
updatedAt: expect.any(String),
author: expect.any(Object)
})
)
})
})

View file

@ -2,7 +2,7 @@ import request from 'supertest'
import app from '../../app'
import deleteUser from '../utils/delete-user'
import signUpNewUser from '../utils/create-user'
import userPayload from '../../interfaces/user'
import type userPayload from '../../interfaces/user'
let user: userPayload
@ -16,14 +16,20 @@ describe('POST /user/auth', () => {
})
it('should respond with a error if the user does not exists', async () => {
const response = await request(app).post('/user/auth').send({ email: 'mm@mm.com', password: 'aa' }).expect(400)
const response = await request(app)
.post('/user/auth')
.send({ email: 'mm@mm.com', password: 'aa' })
.expect(400)
expect(response.body).toHaveProperty('error')
expect(response.body.error).toBe('User does not exists')
})
it('should respond with a error if receive an invalid email or password', async () => {
const response = await request(app).post('/user/auth').send({ email: user.email, password: 'fake_pass' }).expect(400)
const response = await request(app)
.post('/user/auth')
.send({ email: user.email, password: 'fake_pass' })
.expect(400)
expect(response.body).toHaveProperty('error')
expect(response.body.error).toBe('Invalid email or password')

View file

@ -1,7 +1,7 @@
import app from '../../app'
import request from 'supertest'
import signUpNewUser from '../utils/create-user'
import userPayload from '../../interfaces/user'
import type userPayload from '../../interfaces/user'
let user: userPayload
@ -11,7 +11,8 @@ describe('DELETE /user/delete', () => {
})
it('should delete the user successfully', async () => {
await request(app).post('/user/delete')
await request(app)
.post('/user/delete')
.set('Authorization', `Bearer ${user.token ?? ''}`)
.expect(200)
})

View file

@ -2,7 +2,7 @@ import app from '../../app'
import request from 'supertest'
import deleteUser from '../utils/delete-user'
import signUpNewUser from '../utils/create-user'
import userPayload from '../../interfaces/user'
import type userPayload from '../../interfaces/user'
let user: userPayload
@ -16,7 +16,9 @@ describe('POST /user/info', () => {
})
it('should respond with 200 status code and return the user data', async () => {
const response = await request(app).get(`/user/info?u=${user.username ?? ''}`).expect(200)
const response = await request(app)
.get(`/user/info?u=${user.username ?? ''}`)
.expect(200)
expect(response.body).toHaveProperty('profileImage')
expect(response.body).toHaveProperty('displayName')

View file

@ -2,7 +2,7 @@ import request from 'supertest'
import app from '../../app'
import deleteUser from '../utils/delete-user'
import signUpNewUser from '../utils/create-user'
import userPayload from '../../interfaces/user'
import type userPayload from '../../interfaces/user'
let user: userPayload
@ -17,19 +17,25 @@ describe('POST /user/signup', () => {
})
it('should respond with a 400 status code if sent any invalid data', async () => {
await request(app).post('/user/signup').send({
username: 'username12@',
email: user.email,
password: user.password
}).expect(400)
await request(app)
.post('/user/signup')
.send({
username: 'username12@',
email: user.email,
password: user.password
})
.expect(400)
})
it('should respond with a 400 status code for an existing username or email', async () => {
await request(app).post('/user/signup').send({
username: user.username,
email: user.email,
password: user.password
}).expect(400)
await request(app)
.post('/user/signup')
.send({
username: user.username,
email: user.email,
password: user.password
})
.expect(400)
})
it('should respond with a 400 status code if receive an empty body', async () => {

View file

@ -2,7 +2,7 @@ import request from 'supertest'
import app from '../../app'
import signUpNewUser from '../utils/create-user'
import deleteUser from '../utils/delete-user'
import userPayload from '../../interfaces/user'
import type userPayload from '../../interfaces/user'
let user: userPayload
@ -23,12 +23,15 @@ describe('PUT /user/update', () => {
const response = await request(app)
.put('/user/update')
.send(fieldsToUpdate)
.set('Authorization', `Bearer ${user.token ?? ''}`).expect(200)
.set('Authorization', `Bearer ${user.token ?? ''}`)
.expect(200)
expect(response.body).toEqual(expect.objectContaining({
displayName: expect.any(String),
username: expect.any(String),
createdAt: expect.any(String)
}))
expect(response.body).toEqual(
expect.objectContaining({
displayName: expect.any(String),
username: expect.any(String),
createdAt: expect.any(String)
})
)
})
})

View file

@ -1,7 +1,7 @@
import app from '../../app'
import request from 'supertest'
import { faker } from '@faker-js/faker'
import userPayload from '../../interfaces/user'
import type userPayload from '../../interfaces/user'
async function signUpNewUser (): Promise<userPayload> {
// To avoid conflicts with existing usernames or emails
@ -9,18 +9,22 @@ async function signUpNewUser (): Promise<userPayload> {
const email = faker.internet.email()
const password = faker.internet.password() + '@1'
await request(app).post('/user/signup').send({
username,
email,
password
}).expect(200)
await request(app)
.post('/user/signup')
.send({
username,
email,
password
})
.expect(200)
const response = await request(app)
.post('/user/auth')
.send({
email,
password
}).expect(200)
})
.expect(200)
return {
username,

View file

@ -1,4 +1,3 @@
/* eslint-disable @typescript-eslint/explicit-function-return-type */
import prisma from '../../clients/prisma-client'
export default async function deleteUser (username: string) {

View file

@ -1,105 +1,47 @@
{
"compilerOptions": {
/* Visit https://aka.ms/tsconfig to read more about this file */
/* Projects */
// "incremental": true, /* Save .tsbuildinfo files to allow for incremental compilation of projects. */
// "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */
// "tsBuildInfoFile": "./.tsbuildinfo", /* Specify the path to .tsbuildinfo incremental compilation file. */
// "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects. */
// "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */
// "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */
/* Language and Environment */
"target": "es2016", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */
// "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */
// "jsx": "preserve", /* Specify what JSX code is generated. */
// "experimentalDecorators": true, /* Enable experimental support for legacy experimental decorators. */
// "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */
// "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'. */
// "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */
// "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using 'jsx: react-jsx*'. */
// "reactNamespace": "", /* Specify the object invoked for 'createElement'. This only applies when targeting 'react' JSX emit. */
// "noLib": true, /* Disable including any library files, including the default lib.d.ts. */
// "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */
// "moduleDetection": "auto", /* Control what method is used to detect module-format JS files. */
"target": "es2016",
/* Modules */
"module": "commonjs", /* Specify what module code is generated. */
"rootDir": "./", /* Specify the root folder within your source files. */
// "moduleResolution": "node10", /* Specify how TypeScript looks up a file from a given module specifier. */
"baseUrl": "./src", /* Specify the base directory to resolve non-relative module names. */
/* Specify a set of entries that re-map imports to additional lookup locations. */
// "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */
"module": "commonjs",
"rootDir": "./",
"baseUrl": "./src",
"paths": {
"clients/*": [
"clients/*"
],
"config/*": [
"config/*"
],
"controllers/*": [
"controllers/*"
],
"interfaces/*": [
"interfaces/*"
],
"lib/*": [
"lib/*"
],
"middlewares/*": [
"middlewares/*"
],
"services/*": [
"services/*"
]
},
"typeRoots": [
"src/@types/express.d.ts",
"src/@types/global.d.ts",
"node_modules/@types"
], /* Specify multiple folders that act like './node_modules/@types'. */
// "types": [], /* Specify type package names to be included without being referenced in a source file. */
// "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */
// "moduleSuffixes": [], /* List of file name suffixes to search when resolving a module. */
// "allowImportingTsExtensions": true, /* Allow imports to include TypeScript file extensions. Requires '--moduleResolution bundler' and either '--noEmit' or '--emitDeclarationOnly' to be set. */
// "resolvePackageJsonExports": true, /* Use the package.json 'exports' field when resolving package imports. */
// "resolvePackageJsonImports": true, /* Use the package.json 'imports' field when resolving imports. */
// "customConditions": [], /* Conditions to set in addition to the resolver-specific defaults when resolving imports. */
// "resolveJsonModule": true, /* Enable importing .json files. */
// "allowArbitraryExtensions": true, /* Enable importing files with any extension, provided a declaration file is present. */
// "noResolve": true, /* Disallow 'import's, 'require's or '<reference>'s from expanding the number of files TypeScript should add to a project. */
/* JavaScript Support */
// "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */
// "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */
// "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'. */
],
/* Emit */
// "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */
// "declarationMap": true, /* Create sourcemaps for d.ts files. */
// "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */
// "sourceMap": true, /* Create source map files for emitted JavaScript files. */
// "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */
// "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */
"outDir": "./dist", /* Specify an output folder for all emitted files. */
"removeComments": true, /* Disable emitting comments. */
// "noEmit": true, /* Disable emitting files from a compilation. */
// "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */
// "importsNotUsedAsValues": "remove", /* Specify emit/checking behavior for imports that are only used for types. */
// "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */
// "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */
// "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */
// "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */
// "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */
// "newLine": "crlf", /* Set the newline character for emitting files. */
// "stripInternal": true, /* Disable emitting declarations that have '@internal' in their JSDoc comments. */
// "noEmitHelpers": true, /* Disable generating custom helper functions like '__extends' in compiled output. */
// "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */
// "preserveConstEnums": true, /* Disable erasing 'const enum' declarations in generated code. */
// "declarationDir": "./", /* Specify the output directory for generated declaration files. */
// "preserveValueImports": true, /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */
"outDir": "./dist",
"removeComments": true,
/* Interop Constraints */
// "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */
// "verbatimModuleSyntax": true, /* Do not transform or elide any imports or exports not marked as type-only, ensuring they are written in the output file's format based on the 'module' setting. */
// "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */
"esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */
// "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */
"forceConsistentCasingInFileNames": true, /* Ensure that casing is correct in imports. */
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
/* Type Checking */
"strict": true, /* Enable all strict type-checking options. */
// "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied 'any' type. */
// "strictNullChecks": true, /* When type checking, take into account 'null' and 'undefined'. */
// "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */
// "strictBindCallApply": true, /* Check that the arguments for 'bind', 'call', and 'apply' methods match the original function. */
// "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */
// "noImplicitThis": true, /* Enable error reporting when 'this' is given the type 'any'. */
// "useUnknownInCatchVariables": true, /* Default catch clause variables as 'unknown' instead of 'any'. */
// "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */
// "noUnusedLocals": true, /* Enable error reporting when local variables aren't read. */
// "noUnusedParameters": true, /* Raise an error when a function parameter isn't read. */
// "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */
// "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */
// "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */
// "noUncheckedIndexedAccess": true, /* Add 'undefined' to a type when accessed using an index. */
// "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */
// "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type. */
// "allowUnusedLabels": true, /* Disable error reporting for unused labels. */
// "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */
/* Completeness */
// "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */
"skipLibCheck": true, /* Skip type checking all .d.ts files. */
"strict": true,
"skipLibCheck": true
}
}