Commit a5f5cd13 authored by Kulpybaev Ilyas's avatar Kulpybaev Ilyas

урок 82

parent da877c7b
import * as fs from 'fs';
const fileName = 'test.json';
fs.readFile(fileName, (err: NodeJS.ErrnoException | null, data: Buffer) => {
if (err) console.error(err);
else console.log('File contents:', JSON.parse(data.toString()));
});
...@@ -9,12 +9,16 @@ ...@@ -9,12 +9,16 @@
"version": "1.0.0", "version": "1.0.0",
"license": "ISC", "license": "ISC",
"dependencies": { "dependencies": {
"class-transformer": "^0.5.1",
"cors": "^2.8.5",
"express": "^4.18.2", "express": "^4.18.2",
"reflect-metadata": "^0.2.1",
"ts-node": "^10.9.1", "ts-node": "^10.9.1",
"tslib": "^2.6.0", "tslib": "^2.6.0",
"typescript": "^5.1.6" "typescript": "^5.1.6"
}, },
"devDependencies": { "devDependencies": {
"@types/cors": "^2.8.17",
"@types/express": "^4.17.17", "@types/express": "^4.17.17",
"@types/node": "^20.4.2", "@types/node": "^20.4.2",
"@typescript-eslint/eslint-plugin": "^6.0.0", "@typescript-eslint/eslint-plugin": "^6.0.0",
...@@ -288,6 +292,15 @@ ...@@ -288,6 +292,15 @@
"@types/node": "*" "@types/node": "*"
} }
}, },
"node_modules/@types/cors": {
"version": "2.8.17",
"resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.17.tgz",
"integrity": "sha512-8CGDvrBj1zgo2qE+oS3pOCyYNqCPryMWY2bGfwA0dcfopWGgxs+78df0Rs3rc9THP4JkOhLsAa+15VdpAqkcUA==",
"dev": true,
"dependencies": {
"@types/node": "*"
}
},
"node_modules/@types/express": { "node_modules/@types/express": {
"version": "4.17.21", "version": "4.17.21",
"resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.21.tgz", "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.21.tgz",
...@@ -859,6 +872,11 @@ ...@@ -859,6 +872,11 @@
"node": ">= 6" "node": ">= 6"
} }
}, },
"node_modules/class-transformer": {
"version": "0.5.1",
"resolved": "https://registry.npmjs.org/class-transformer/-/class-transformer-0.5.1.tgz",
"integrity": "sha512-SQa1Ws6hUbfC98vKGxZH3KFY0Y1lm5Zm0SY8XX9zbK7FJCyVEac3ATW0RIpwzW+oOfmHE5PMPufDG9hCfoEOMw=="
},
"node_modules/color-convert": { "node_modules/color-convert": {
"version": "2.0.1", "version": "2.0.1",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
...@@ -915,6 +933,18 @@ ...@@ -915,6 +933,18 @@
"resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
"integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ=="
}, },
"node_modules/cors": {
"version": "2.8.5",
"resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz",
"integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==",
"dependencies": {
"object-assign": "^4",
"vary": "^1"
},
"engines": {
"node": ">= 0.10"
}
},
"node_modules/create-require": { "node_modules/create-require": {
"version": "1.1.1", "version": "1.1.1",
"resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz",
...@@ -2171,6 +2201,14 @@ ...@@ -2171,6 +2201,14 @@
"node": ">=0.10.0" "node": ">=0.10.0"
} }
}, },
"node_modules/object-assign": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
"integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/object-inspect": { "node_modules/object-inspect": {
"version": "1.13.1", "version": "1.13.1",
"resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz", "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz",
...@@ -2450,6 +2488,11 @@ ...@@ -2450,6 +2488,11 @@
"node": ">=8.10.0" "node": ">=8.10.0"
} }
}, },
"node_modules/reflect-metadata": {
"version": "0.2.1",
"resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.2.1.tgz",
"integrity": "sha512-i5lLI6iw9AU3Uu4szRNPPEkomnkjRTaVt9hy/bn5g/oSzekBSMeLZblcjP74AW0vBabqERLLIrz+gR8QYR54Tw=="
},
"node_modules/resolve-from": { "node_modules/resolve-from": {
"version": "4.0.0", "version": "4.0.0",
"resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
......
...@@ -13,12 +13,16 @@ ...@@ -13,12 +13,16 @@
"author": "", "author": "",
"license": "ISC", "license": "ISC",
"dependencies": { "dependencies": {
"class-transformer": "^0.5.1",
"cors": "^2.8.5",
"express": "^4.18.2", "express": "^4.18.2",
"reflect-metadata": "^0.2.1",
"ts-node": "^10.9.1", "ts-node": "^10.9.1",
"tslib": "^2.6.0", "tslib": "^2.6.0",
"typescript": "^5.1.6" "typescript": "^5.1.6"
}, },
"devDependencies": { "devDependencies": {
"@types/cors": "^2.8.17",
"@types/express": "^4.17.17", "@types/express": "^4.17.17",
"@types/node": "^20.4.2", "@types/node": "^20.4.2",
"@typescript-eslint/eslint-plugin": "^6.0.0", "@typescript-eslint/eslint-plugin": "^6.0.0",
...@@ -27,7 +31,7 @@ ...@@ -27,7 +31,7 @@
"eslint-config-prettier": "^8.8.0", "eslint-config-prettier": "^8.8.0",
"eslint-plugin-prettier": "^5.0.0", "eslint-plugin-prettier": "^5.0.0",
"nodemon": "^3.0.1", "nodemon": "^3.0.1",
"tsconfig-paths": "^4.2.0", "prettier": "^3.0.0",
"prettier": "^3.0.0" "tsconfig-paths": "^4.2.0"
} }
} }
import express from 'express'; import express from 'express';
import { Application, RequestHandler } from 'express'; import { Application, RequestHandler } from 'express';
import { AppInit } from './interfaces/AppInit.interface'; import { AppInit } from './interfaces/AppInit.interface';
import { IRoute } from './interfaces/IRoute.interface'; import { IRoute } from './interfaces/IRoute.interface';
......
import { RequestHandler } from 'express';
import { ProductService } from '@/services/product.service';
import { plainToInstance } from 'class-transformer';
import { ProductDto } from '@/dto/ProductDto';
export class ProductController {
private service: ProductService;
constructor() {
this.service = new ProductService();
}
getProducts: RequestHandler = (req, res): void => {
const products = this.service.getProducts();
res.send(products);
};
getProduct: RequestHandler = (req, res): void => {
const product = this.service.getProduct(req.params.id);
res.send(product);
};
createProduct: RequestHandler = (req, res): void => {
const productDto = plainToInstance(ProductDto, req.body);
const product = this.service.createProduct(productDto);
res.send(product);
};
}
[
{
"id": "d21c0ed1-ba56-4d2b-8a5f-999fd4615dd9",
"title": "test title",
"price": 10,
"description": "test description"
},
{
"id": "6e2cbadd-0193-46be-9cd6-cea2ca3c1c73",
"title": "Example",
"price": 100500
},
{
"id": "f6e4a14f-20c5-4b97-8ac8-fa4a36b8d92d",
"name": "New product",
"description": "Some new cool perfect super product",
"price": 1600
}
]
\ No newline at end of file
import { Expose } from 'class-transformer';
@Expose()
export class ProductDto {
title!: string;
description!: string;
price!: number;
}
import App from './app'; import App from './app';
import logger from './middlewares/logger'; import logger from './middlewares/logger';
import { ArticleRoute } from './routes/article.route'; import { ArticleRoute } from './routes/article.route';
import { ProductRoute } from '@/routes/product.route';
import cors from 'cors';
const app = new App({ const app = new App({
port: 8000, port: 8000,
middlewares: [logger()], middlewares: [logger(), cors()],
controllers: [new ArticleRoute()], controllers: [new ArticleRoute(), new ProductRoute()],
}); });
app.listen(); app.listen();
export interface IProduct {
id: string;
title: string;
price: number;
description?: string;
}
...@@ -6,7 +6,6 @@ export class ArticleRoute implements IRoute { ...@@ -6,7 +6,6 @@ export class ArticleRoute implements IRoute {
public path = '/articles'; public path = '/articles';
public router = Router(); public router = Router();
private controller: ArticleController; private controller: ArticleController;
constructor() { constructor() {
this.controller = new ArticleController(); this.controller = new ArticleController();
this.init(); this.init();
......
import { Router } from 'express';
import { IRoute } from '@/interfaces/IRoute.interface';
import { ProductController } from '@/controllers/product.controller';
export class ProductRoute implements IRoute {
public path = '/products';
public router = Router();
private controller: ProductController;
constructor() {
this.controller = new ProductController();
this.init();
}
private init() {
this.router.get('/', this.controller.getProducts);
this.router.get('/:id', this.controller.getProduct);
this.router.post('/', this.controller.createProduct);
}
}
import { IProduct } from '@/interfaces/IProduct.interface';
import { ProductDto } from '@/dto/ProductDto';
import * as fs from 'fs';
import path from 'path';
import { randomUUID } from 'crypto';
const filePath = path.join(__dirname, '../data/products.json');
export class ProductService {
private products: IProduct[] = [];
constructor() {
this.init();
}
private init() {
try {
const fileContents = fs.readFileSync(filePath);
this.products = JSON.parse(fileContents.toString());
} catch (e) {
this.products = [];
}
}
private save() {
fs.writeFileSync(filePath, JSON.stringify(this.products, null, 2));
}
public getProducts(): IProduct[] {
return this.products;
}
public getProduct(id: string): IProduct {
const singleProduct = this.products.find((product) => product.id === id);
if (singleProduct) return singleProduct;
else throw new Error('Invalid id');
}
public createProduct(productDto: ProductDto): IProduct {
const product = {
id: randomUUID(),
...productDto,
};
this.products.push(product);
this.save();
return product;
}
}
...@@ -23,7 +23,7 @@ ...@@ -23,7 +23,7 @@
"experimentalDecorators": true, "experimentalDecorators": true,
"emitDecoratorMetadata": true, "emitDecoratorMetadata": true,
"resolveJsonModule": true, "resolveJsonModule": true,
"esModuleInterop": true "esModuleInterop": true,
}, },
"include": ["src/**/*.ts"], "include": ["src/**/*.ts"],
"exclude": ["node_modules"] "exclude": ["node_modules"]
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment