Repository: kondzerau-ivan/twitter
Pull request #4: 1 implement a basic http rest api server
Author: login: kondzerau-ivan
Created: 2025-04-18T14:39:38Z | Merged: 2025-04-24T19:07:06Z



Diff:
diff --git a/package-lock.json b/package-lock.json
index 92ef068..1d4c541 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -16,24 +16,10 @@
         "express": "^5.1.0",
         "globals": "^16.0.0",
         "husky": "^9.1.7",
-        "ts-node": "^10.9.2",
         "typescript": "^5.8.3",
         "typescript-eslint": "^8.30.1"
       }
     },
-    "node_modules/@cspotcode/source-map-support": {
-      "version": "0.8.1",
-      "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz",
-      "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==",
-      "dev": true,
-      "license": "MIT",
-      "dependencies": {
-        "@jridgewell/trace-mapping": "0.3.9"
-      },
-      "engines": {
-        "node": ">=12"
-      }
-    },
     "node_modules/@eslint-community/eslint-utils": {
       "version": "4.6.1",
       "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.6.1.tgz",
@@ -264,34 +250,6 @@
         "url": "https://github.com/sponsors/nzakas"
       }
     },
-    "node_modules/@jridgewell/resolve-uri": {
-      "version": "3.1.2",
-      "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz",
-      "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==",
-      "dev": true,
-      "license": "MIT",
-      "engines": {
-        "node": ">=6.0.0"
-      }
-    },
-    "node_modules/@jridgewell/sourcemap-codec": {
-      "version": "1.5.0",
-      "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz",
-      "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==",
-      "dev": true,
-      "license": "MIT"
-    },
-    "node_modules/@jridgewell/trace-mapping": {
-      "version": "0.3.9",
-      "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz",
-      "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==",
-      "dev": true,
-      "license": "MIT",
-      "dependencies": {
-        "@jridgewell/resolve-uri": "^3.0.3",
-        "@jridgewell/sourcemap-codec": "^1.4.10"
-      }
-    },
     "node_modules/@nodelib/fs.scandir": {
       "version": "2.1.5",
       "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
@@ -330,34 +288,6 @@
         "node": ">= 8"
       }
     },
-    "node_modules/@tsconfig/node10": {
-      "version": "1.0.11",
-      "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.11.tgz",
-      "integrity": "sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw==",
-      "dev": true,
-      "license": "MIT"
-    },
-    "node_modules/@tsconfig/node12": {
-      "version": "1.0.11",
-      "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz",
-      "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==",
-      "dev": true,
-      "license": "MIT"
-    },
-    "node_modules/@tsconfig/node14": {
-      "version": "1.0.3",
-      "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz",
-      "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==",
-      "dev": true,
-      "license": "MIT"
-    },
-    "node_modules/@tsconfig/node16": {
-      "version": "1.0.4",
-      "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz",
-      "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==",
-      "dev": true,
-      "license": "MIT"
-    },
     "node_modules/@types/body-parser": {
       "version": "1.19.5",
       "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.5.tgz",
@@ -722,19 +652,6 @@
         "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0"
       }
     },
-    "node_modules/acorn-walk": {
-      "version": "8.3.4",
-      "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.4.tgz",
-      "integrity": "sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==",
-      "dev": true,
-      "license": "MIT",
-      "dependencies": {
-        "acorn": "^8.11.0"
-      },
-      "engines": {
-        "node": ">=0.4.0"
-      }
-    },
     "node_modules/ajv": {
       "version": "6.12.6",
       "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
@@ -768,13 +685,6 @@
         "url": "https://github.com/chalk/ansi-styles?sponsor=1"
       }
     },
-    "node_modules/arg": {
-      "version": "4.1.3",
-      "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz",
-      "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==",
-      "dev": true,
-      "license": "MIT"
-    },
     "node_modules/argparse": {
       "version": "2.0.1",
       "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
@@ -972,13 +882,6 @@
         "node": ">=6.6.0"
       }
     },
-    "node_modules/create-require": {
-      "version": "1.1.1",
-      "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz",
-      "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==",
-      "dev": true,
-      "license": "MIT"
-    },
     "node_modules/cross-spawn": {
       "version": "7.0.6",
       "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
@@ -1029,16 +932,6 @@
         "node": ">= 0.8"
       }
     },
-    "node_modules/diff": {
-      "version": "4.0.2",
-      "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz",
-      "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==",
-      "dev": true,
-      "license": "BSD-3-Clause",
-      "engines": {
-        "node": ">=0.3.1"
-      }
-    },
     "node_modules/dunder-proto": {
       "version": "1.0.1",
       "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz",
@@ -1854,13 +1747,6 @@
       "dev": true,
       "license": "MIT"
     },
-    "node_modules/make-error": {
-      "version": "1.3.6",
-      "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz",
-      "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==",
-      "dev": true,
-      "license": "ISC"
-    },
     "node_modules/math-intrinsics": {
       "version": "1.1.0",
       "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz",
@@ -2547,50 +2433,6 @@
         "typescript": ">=4.8.4"
       }
     },
-    "node_modules/ts-node": {
-      "version": "10.9.2",
-      "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz",
-      "integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==",
-      "dev": true,
-      "license": "MIT",
-      "dependencies": {
-        "@cspotcode/source-map-support": "^0.8.0",
-        "@tsconfig/node10": "^1.0.7",
-        "@tsconfig/node12": "^1.0.7",
-        "@tsconfig/node14": "^1.0.0",
-        "@tsconfig/node16": "^1.0.2",
-        "acorn": "^8.4.1",
-        "acorn-walk": "^8.1.1",
-        "arg": "^4.1.0",
-        "create-require": "^1.1.0",
-        "diff": "^4.0.1",
-        "make-error": "^1.1.1",
-        "v8-compile-cache-lib": "^3.0.1",
-        "yn": "3.1.1"
-      },
-      "bin": {
-        "ts-node": "dist/bin.js",
-        "ts-node-cwd": "dist/bin-cwd.js",
-        "ts-node-esm": "dist/bin-esm.js",
-        "ts-node-script": "dist/bin-script.js",
-        "ts-node-transpile-only": "dist/bin-transpile.js",
-        "ts-script": "dist/bin-script-deprecated.js"
-      },
-      "peerDependencies": {
-        "@swc/core": ">=1.2.50",
-        "@swc/wasm": ">=1.2.50",
-        "@types/node": "*",
-        "typescript": ">=2.7"
-      },
-      "peerDependenciesMeta": {
-        "@swc/core": {
-          "optional": true
-        },
-        "@swc/wasm": {
-          "optional": true
-        }
-      }
-    },
     "node_modules/type-check": {
       "version": "0.4.0",
       "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
@@ -2683,13 +2525,6 @@
         "punycode": "^2.1.0"
       }
     },
-    "node_modules/v8-compile-cache-lib": {
-      "version": "3.0.1",
-      "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz",
-      "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==",
-      "dev": true,
-      "license": "MIT"
-    },
     "node_modules/vary": {
       "version": "1.1.2",
       "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
@@ -2733,16 +2568,6 @@
       "dev": true,
       "license": "ISC"
     },
-    "node_modules/yn": {
-      "version": "3.1.1",
-      "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz",
-      "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==",
-      "dev": true,
-      "license": "MIT",
-      "engines": {
-        "node": ">=6"
-      }
-    },
     "node_modules/yocto-queue": {
       "version": "0.1.0",
       "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
diff --git a/package.json b/package.json
index 8e4c82e..262dd86 100644
--- a/package.json
+++ b/package.json
@@ -3,8 +3,10 @@
   "version": "1.0.0",
   "description": "",
   "main": "index.js",
+  "type": "module",
   "scripts": {
-    "test": "echo \"Error: no test specified\" && exit 1",
+    "dev": "node --experimental-transform-types --disable-warning=ExperimentalWarning --trace-warnings --watch ./src/index.ts",
+    "lint": "npx eslint --fix",
     "prepare": "husky"
   },
   "repository": {
@@ -25,7 +27,6 @@
     "express": "^5.1.0",
     "globals": "^16.0.0",
     "husky": "^9.1.7",
-    "ts-node": "^10.9.2",
     "typescript": "^5.8.3",
     "typescript-eslint": "^8.30.1"
   }
diff --git a/src/index.ts b/src/index.ts
index e69de29..4694b8e 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -0,0 +1,19 @@
+import express from 'express';
+import { authRouter } from './interface/routes/auth.ts';
+import { postsRouter } from './interface/routes/posts.ts';
+import { usersRouter } from './interface/routes/users.ts';
+import { commentsRouter } from './interface/routes/comments.ts';
+
+const PORT = 3000;
+const BASE_URL = '/api/v1';
+const app = express();
+
+app.use(express.json());
+app.use(`${BASE_URL}/auth`, authRouter);
+app.use(`${BASE_URL}/users`, usersRouter);
+app.use(`${BASE_URL}/posts`, postsRouter);
+app.use(`${BASE_URL}/comments`, commentsRouter);
+
+app.listen(PORT, () => {
+  console.log(`Server running at http://localhost:${PORT}`);
+});
diff --git a/src/interface/routes/auth.ts b/src/interface/routes/auth.ts
new file mode 100644
index 0000000..a13a8a5
--- /dev/null
+++ b/src/interface/routes/auth.ts
@@ -0,0 +1,12 @@
+import { Router } from 'express';
+import type { Request, Response } from 'express';
+
+export const authRouter = Router();
+
+authRouter.get('/', (req: Request, res: Response) => {
+  res.json({});
+});
+
+authRouter.post('/', (req: Request, res: Response) => {
+  res.json({});
+});
diff --git a/src/interface/routes/comments.ts b/src/interface/routes/comments.ts
new file mode 100644
index 0000000..4078645
--- /dev/null
+++ b/src/interface/routes/comments.ts
@@ -0,0 +1,19 @@
+import { Router } from 'express';
+import type { Request, Response } from 'express';
+import { likesRouter } from './likes.ts';
+
+export const commentsRouter = Router();
+
+commentsRouter.get('/:commentId', (req: Request, res: Response) => {
+  res.json({});
+});
+
+commentsRouter.put('/:commentId', (req: Request, res: Response) => {
+  res.json({});
+});
+
+commentsRouter.delete('/:commentId', (req: Request, res: Response) => {
+  res.json({});
+});
+
+commentsRouter.use('/:commentId/likes', likesRouter);
diff --git a/src/interface/routes/likes.ts b/src/interface/routes/likes.ts
new file mode 100644
index 0000000..6470391
--- /dev/null
+++ b/src/interface/routes/likes.ts
@@ -0,0 +1,16 @@
+import { Router } from 'express';
+import type { Request, Response } from 'express';
+
+export const likesRouter = Router();
+
+likesRouter.get('/', (req: Request, res: Response) => {
+  res.json({});
+});
+
+likesRouter.post('/', (req: Request, res: Response) => {
+  res.json({});
+});
+
+likesRouter.delete('/', (req: Request, res: Response) => {
+  res.json({});
+});
diff --git a/src/interface/routes/posts.ts b/src/interface/routes/posts.ts
new file mode 100644
index 0000000..289fdbb
--- /dev/null
+++ b/src/interface/routes/posts.ts
@@ -0,0 +1,36 @@
+import { Router } from 'express';
+import type { Request, Response } from 'express';
+import { likesRouter } from './likes.ts';
+
+
+export const postsRouter = Router();
+
+postsRouter.get('/', (req: Request, res: Response) => {
+  res.json({});
+});
+
+postsRouter.post('/', (req: Request, res: Response) => {
+  res.json({});
+});
+
+postsRouter.get('/:postId', (req: Request, res: Response) => {
+  res.json({});
+});
+
+postsRouter.put('/:postId', (req: Request, res: Response) => {
+  res.json({});
+});
+
+postsRouter.delete('/:postId', (req: Request, res: Response) => {
+  res.json({});
+});
+
+postsRouter.get('/:postId/comments', (req: Request, res: Response) => {
+  res.json({});
+});
+
+postsRouter.post('/:postId/comments', (req: Request, res: Response) => {
+  res.json({});
+});
+
+postsRouter.use('/:postId/likes', likesRouter);
diff --git a/src/interface/routes/users.ts b/src/interface/routes/users.ts
new file mode 100644
index 0000000..8e23bf5
--- /dev/null
+++ b/src/interface/routes/users.ts
@@ -0,0 +1,28 @@
+import { Router } from 'express';
+import type { Request, Response } from 'express';
+
+export const usersRouter = Router();
+
+usersRouter.get('/:userId', (req: Request, res: Response) => {
+  res.json({});
+});
+
+usersRouter.get('/:userId/posts', (req: Request, res: Response) => {
+  res.json({});
+});
+
+usersRouter.get('/:userId/comments', (req: Request, res: Response) => {
+  res.json({});
+});
+
+usersRouter.get('/:userId/followers', (req: Request, res: Response) => {
+  res.json({});
+});
+
+usersRouter.post('/:userId/followers', (req: Request, res: Response) => {
+  res.json({});
+});
+
+usersRouter.delete('/:userId/followers', (req: Request, res: Response) => {
+  res.json({});
+});
diff --git a/tsconfig.json b/tsconfig.json
index 56227f6..8d4093e 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -11,7 +11,7 @@
     // "disableReferencedProjectLoad": true,             /* Reduce the number of projects loaded automatically by TypeScript. */
 
     /* Language and Environment */
-    "target": "es2017",                                  /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */
+    "target": "ESNext",                                  /* 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. */
     // "libReplacement": true,                           /* Enable lib replacement. */
@@ -26,9 +26,9 @@
     // "moduleDetection": "auto",                        /* Control what method is used to detect module-format JS files. */
 
     /* 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. */
+    "module": "ESNext",                                /* Specify what module code is generated. */
+    "rootDir": "./src",                                  /* Specify the root folder within your source files. */
+    "moduleResolution": "node",                     /* Specify how TypeScript looks up a file from a given module specifier. */
     // "baseUrl": "./",                                  /* Specify the base directory to resolve non-relative module names. */
     // "paths": {},                                      /* 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. */
@@ -36,13 +36,13 @@
     // "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. */
+    "allowImportingTsExtensions": true,               /* Allow imports to include TypeScript file extensions. Requires '--moduleResolution bundler' and either '--noEmit' or '--emitDeclarationOnly' to be set. */
     // "rewriteRelativeImportExtensions": true,          /* Rewrite '.ts', '.tsx', '.mts', and '.cts' file extensions in relative import paths to their JavaScript equivalent in output files. */
     // "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. */
     // "noUncheckedSideEffectImports": true,             /* Check side effect imports. */
-    // "resolveJsonModule": true,                        /* Enable importing .json files. */
+    "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. */
 
@@ -57,7 +57,7 @@
     // "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. */
-    // "noEmit": true,                                   /* Disable emitting files from a compilation. */
+    "noEmit": true,                                   /* Disable emitting files from a compilation. */
     // "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. */
@@ -79,7 +79,7 @@
     // "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. */
     // "isolatedDeclarations": true,                     /* Require sufficient annotation on exports so other tools can trivially generate declaration files. */
     // "erasableSyntaxOnly": true,                       /* Do not allow runtime constructs that are not part of ECMAScript. */
-    // "allowSyntheticDefaultImports": true,             /* Allow 'import x from y' when a module doesn't have a default export. */
+    "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. */


Reviews:
user: login: 3axap4eHko
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-04-18T15:11:38Z
user: login: 3axap4eHko
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-04-18T15:12:54Z
user: login: 3axap4eHko
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-04-18T15:13:57Z
user: login: kondzerau-ivan
body: Внёс правки.
state: COMMENTED
author_association: OWNER
submitted_at: 2025-04-18T16:24:10Z
user: login: 3axap4eHko
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-04-19T20:33:53Z
user: login: 3axap4eHko
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-04-19T20:34:14Z
user: login: 3axap4eHko
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-04-19T20:44:29Z
user: login: 3axap4eHko
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-04-19T20:44:40Z
user: login: 3axap4eHko
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-04-20T00:25:16Z
user: login: 3axap4eHko
state: APPROVED
author_association: COLLABORATOR
submitted_at: 2025-04-24T19:04:47Z

Review comments:
diff_hunk: @@ -0,0 +1,33 @@
+import { Router } from 'express';
+import type { Request, Response } from 'express';
+
+const router = Router();
+
+router.get('/auth', (req: Request, res: Response) => {
+  res.json({
+    authenticated: false,
+    message: "User is not logged in"
+  });
+});
+
+router.post('/auth', (req: Request, res: Response) => {
+  const { email, password } = req.body;
+  if (email === 'batman@gmail.com' && password === 'batman123') {
path: src/interface/routes/auth.ts
user: login: 3axap4eHko
body: Не придумывай ничего, просто `res.json({})` и все
created_at: 2025-04-18T15:11:38Z
author_association: COLLABORATOR
diff_hunk: @@ -0,0 +1,33 @@
+import { Router } from 'express';
+import type { Request, Response } from 'express';
+
+const router = Router();
path: src/interface/routes/auth.ts
user: login: 3axap4eHko
body: export const authRouter = Router();
created_at: 2025-04-18T15:12:54Z
author_association: COLLABORATOR
diff_hunk: @@ -0,0 +1,33 @@
+import { Router } from 'express';
+import type { Request, Response } from 'express';
+
+const router = Router();
+
+router.get('/auth', (req: Request, res: Response) => {
+  res.json({
+    authenticated: false,
+    message: "User is not logged in"
+  });
+});
+
+router.post('/auth', (req: Request, res: Response) => {
+  const { email, password } = req.body;
+  if (email === 'batman@gmail.com' && password === 'batman123') {
+    res.status(200).json({
+      authenticated: true,
+      message: 'Authentication successful',
+      user: {
+        id: 1,
+        email: email,
+      },
+      token: 'fake-jwt-token'
+    })
+  } else {
+    res.status(401).json({
+      authenticated: false,
+      message: 'Invalid email or password'
+    })
+  }
+});
+
+export { router as authRouter };
path: src/interface/routes/auth.ts
user: login: 3axap4eHko
body: зачем переменную называть `router`, затем переименовывать ее на `authRouter`? не делай лишнее
created_at: 2025-04-18T15:13:57Z
author_association: COLLABORATOR
diff_hunk: @@ -0,0 +1,68 @@
+import { Router } from 'express';
+import type { Request, Response } from 'express';
+
+export const postsRouter = Router();
+
+postsRouter.get('/posts', (req: Request, res: Response) => {
+  res.json({});
+});
+
+postsRouter.get('/posts/:postId', (req: Request, res: Response) => {
+  res.json({});
+});
+
+postsRouter.post('/posts', (req: Request, res: Response) => {
+  res.json({});
+});
+
+postsRouter.put('/posts/:postId', (req: Request, res: Response) => {
+  res.json({});
+});
+
+postsRouter.delete('/posts/:postId', (req: Request, res: Response) => {
+  res.json({});
+});
+
+postsRouter.get('/posts/:postId/likes', (req: Request, res: Response) => {
+  res.json({});
+});
+
+postsRouter.post('/posts/:postId/likes', (req: Request, res: Response) => {
+  res.json({});
+});
+
+postsRouter.delete('/posts/:postId/likes', (req: Request, res: Response) => {
+  res.json({});
+});
+
+postsRouter.get('/posts/:postId/comments', (req: Request, res: Response) => {
+  res.json({});
+});
+
+postsRouter.get('/posts/:postId/comments/:commentId', (req: Request, res: Response) => {
+  res.json({});
+});
+
+postsRouter.post('/posts/:postId/comments', (req: Request, res: Response) => {
+  res.json({});
+});
+
+postsRouter.put('/posts/:postId/comments/:commentId', (req: Request, res: Response) => {
+  res.json({});
+});
+
+postsRouter.delete('/posts/:postId/comments/:commentId', (req: Request, res: Response) => {
+  res.json({});
+});
+
+postsRouter.get('/posts/:postId/comments/:commentId/likes', (req: Request, res: Response) => {
+  res.json({});
+});
+
+postsRouter.post('/posts/:postId/comments/:commentId/likes', (req: Request, res: Response) => {
+  res.json({});
+});
+
+postsRouter.delete('/posts/:postId/comments/:commentId/likes', (req: Request, res: Response) => {
+  res.json({});
+});
path: src/interface/routes/posts.ts
user: login: 3axap4eHko
body: Давай коменты тоже сделаем отдельным раутером так как `commentId` у нас уникально идентифицирует комментарий
```ts
postsRouter.get('/:commentId', (req: Request, res: Response) => {
  res.json({});
});

postsRouter.delete('/:commentId', (req: Request, res: Response) => {
  res.json({});
});
postsRouter.put('/:commentId', (req: Request, res: Response) => {
  res.json({});
});

postsRouter.delete('/:commentId', (req: Request, res: Response) => {
  res.json({});
});

postsRouter.get('/:commentId/likes', (req: Request, res: Response) => {
  res.json({});
});

postsRouter.post('/:commentId/likes', (req: Request, res: Response) => {
  res.json({});
});

postsRouter.delete('/:commentId/likes', (req: Request, res: Response) => {
  res.json({});
});
```
created_at: 2025-04-19T20:33:53Z
author_association: COLLABORATOR
diff_hunk: @@ -0,0 +1,68 @@
+import { Router } from 'express';
+import type { Request, Response } from 'express';
+
+export const postsRouter = Router();
+
+postsRouter.get('/posts', (req: Request, res: Response) => {
path: src/interface/routes/posts.ts
user: login: 3axap4eHko
body: Теперь немного организуем пути. Посмотри как често у тебя повторяется `/posts` например в раутере post. Вместо того что бы повторять строку каждый раз, лучше всего монтировать раутер в этот путь `app.use('/router', postsRouter)` , сделай так же для други раутеров
created_at: 2025-04-19T20:34:14Z
author_association: COLLABORATOR
diff_hunk: @@ -0,0 +1,68 @@
+import { Router } from 'express';
+import type { Request, Response } from 'express';
+
+export const postsRouter = Router();
+
+postsRouter.get('/posts', (req: Request, res: Response) => {
+  res.json({});
+});
+
+postsRouter.get('/posts/:postId', (req: Request, res: Response) => {
+  res.json({});
+});
+
+postsRouter.post('/posts', (req: Request, res: Response) => {
+  res.json({});
+});
+
+postsRouter.put('/posts/:postId', (req: Request, res: Response) => {
+  res.json({});
+});
+
+postsRouter.delete('/posts/:postId', (req: Request, res: Response) => {
+  res.json({});
+});
+
+postsRouter.get('/posts/:postId/likes', (req: Request, res: Response) => {
+  res.json({});
+});
+
+postsRouter.post('/posts/:postId/likes', (req: Request, res: Response) => {
+  res.json({});
+});
+
+postsRouter.delete('/posts/:postId/likes', (req: Request, res: Response) => {
+  res.json({});
+});
+
+postsRouter.get('/posts/:postId/comments', (req: Request, res: Response) => {
path: src/interface/routes/posts.ts
user: login: 3axap4eHko
body: оставляем этот
created_at: 2025-04-19T20:44:29Z
author_association: COLLABORATOR
diff_hunk: @@ -0,0 +1,68 @@
+import { Router } from 'express';
+import type { Request, Response } from 'express';
+
+export const postsRouter = Router();
+
+postsRouter.get('/posts', (req: Request, res: Response) => {
+  res.json({});
+});
+
+postsRouter.get('/posts/:postId', (req: Request, res: Response) => {
+  res.json({});
+});
+
+postsRouter.post('/posts', (req: Request, res: Response) => {
+  res.json({});
+});
+
+postsRouter.put('/posts/:postId', (req: Request, res: Response) => {
+  res.json({});
+});
+
+postsRouter.delete('/posts/:postId', (req: Request, res: Response) => {
+  res.json({});
+});
+
+postsRouter.get('/posts/:postId/likes', (req: Request, res: Response) => {
+  res.json({});
+});
+
+postsRouter.post('/posts/:postId/likes', (req: Request, res: Response) => {
+  res.json({});
+});
+
+postsRouter.delete('/posts/:postId/likes', (req: Request, res: Response) => {
+  res.json({});
+});
+
+postsRouter.get('/posts/:postId/comments', (req: Request, res: Response) => {
+  res.json({});
+});
+
+postsRouter.get('/posts/:postId/comments/:commentId', (req: Request, res: Response) => {
+  res.json({});
+});
+
+postsRouter.post('/posts/:postId/comments', (req: Request, res: Response) => {
path: src/interface/routes/posts.ts
user: login: 3axap4eHko
body: и оставляем этот
created_at: 2025-04-19T20:44:40Z
author_association: COLLABORATOR
diff_hunk: @@ -0,0 +1,19 @@
+import express from 'express';
+import { authRouter } from './interface/routes/auth.ts';
+import { postsRouter } from './interface/routes/posts.ts';
+import { usersRouter } from './interface/routes/users.ts';
+import { commentsRouter } from './interface/routes/comments.ts';
+
+const PORT = 3000;
+const BASE_URL = '/api/v1';
+const app = express();
+
+app.use(express.json());
+app.use(BASE_URL, authRouter);
path: src/index.ts
user: login: 3axap4eHko
body: а что тут за исключение?
created_at: 2025-04-20T00:25:16Z
author_association: COLLABORATOR

PR comments:
user: login: kondzerau-ivan
created_at: 2025-04-19T16:08:24Z
body: @3axap4eHko добавил роуты для постов и юзеров.
author_association: OWNER
user: login: 3axap4eHko
created_at: 2025-04-19T17:56:27Z
body: Перечитай https://expressjs.com/en/5x/api.html#app.param у тебя не правильно параметризированы пути. Вместо `/posts:postId` у тебя должно быть `/posts/:postId` и т.д. для все путей
author_association: COLLABORATOR
user: login: kondzerau-ivan
created_at: 2025-04-19T20:21:11Z
body: @3axap4eHko исправил.
author_association: OWNER
user: login: kondzerau-ivan
created_at: 2025-04-19T21:26:27Z
body: @3axap4eHko добавил комменты отдельным раутом. Так же внёс правки в пути раутов.
author_association: OWNER
user: login: 3axap4eHko
created_at: 2025-04-20T00:27:07Z
body: И задачка со звездочкой переиспользовать likes для постов и комментов
author_association: COLLABORATOR
user: login: kondzerau-ivan
created_at: 2025-04-20T04:02:56Z
body: > И задачка со звездочкой переиспользовать likes для постов и комментов

Поясни, пожалуйста, что это значит "переиспользовать likes"?
author_association: OWNER
user: login: kondzerau-ivan
created_at: 2025-04-21T08:43:55Z
body: @3axap4eHko добавил отдельный раут для **likes** и исправил **/auth**.
author_association: OWNER
user: login: kondzerau-ivan
created_at: 2025-04-23T12:13:52Z
body: @3axap4eHko внёс исправления в likes router.
author_association: OWNER